summaryrefslogtreecommitdiff
path: root/src/third_party/mozjs-45
diff options
context:
space:
mode:
authorMark Benvenuto <mark.benvenuto@mongodb.com>2017-03-23 15:12:36 -0400
committerMark Benvenuto <mark.benvenuto@mongodb.com>2017-04-07 11:46:46 -0400
commite024dc2e0014ef8e70ba5463cf206a05f7afc6ac (patch)
tree711f9b54df8cba0542a53dd4770c6b616754c2a8 /src/third_party/mozjs-45
parentc48f2983e1a525394449fd2f2f1323b964bc8968 (diff)
downloadmongo-e024dc2e0014ef8e70ba5463cf206a05f7afc6ac.tar.gz
SERVER-28400 Firefox ESR 45.8.0
Diffstat (limited to 'src/third_party/mozjs-45')
-rw-r--r--src/third_party/mozjs-45/SConscript8
-rw-r--r--src/third_party/mozjs-45/extract.sh3
-rw-r--r--src/third_party/mozjs-45/extract/js/public/GCAPI.h2
-rw-r--r--src/third_party/mozjs-45/extract/js/src/NamespaceImports.h7
-rw-r--r--src/third_party/mozjs-45/extract/js/src/asmjs/AsmJSModule.cpp14
-rw-r--r--src/third_party/mozjs-45/extract/js/src/builtin/MapObject.cpp52
-rw-r--r--src/third_party/mozjs-45/extract/js/src/builtin/MapObject.h6
-rw-r--r--src/third_party/mozjs-45/extract/js/src/ds/OrderedHashTable.h28
-rw-r--r--src/third_party/mozjs-45/extract/js/src/gc/Allocator.cpp11
-rw-r--r--src/third_party/mozjs-45/extract/js/src/gc/GCRuntime.h2
-rw-r--r--src/third_party/mozjs-45/extract/js/src/gc/Heap.h4
-rw-r--r--src/third_party/mozjs-45/extract/js/src/gc/Marking.cpp88
-rw-r--r--src/third_party/mozjs-45/extract/js/src/gc/Marking.h14
-rw-r--r--src/third_party/mozjs-45/extract/js/src/gc/Zone.cpp1
-rw-r--r--src/third_party/mozjs-45/extract/js/src/irregexp/RegExpEngine.cpp7
-rw-r--r--src/third_party/mozjs-45/extract/js/src/jit/BaselineIC.cpp14
-rw-r--r--src/third_party/mozjs-45/extract/js/src/jit/BaselineJIT.cpp11
-rw-r--r--src/third_party/mozjs-45/extract/js/src/jit/ExecutableAllocator.cpp47
-rw-r--r--src/third_party/mozjs-45/extract/js/src/jit/ExecutableAllocator.h40
-rw-r--r--src/third_party/mozjs-45/extract/js/src/jit/ExecutableAllocatorPosix.cpp108
-rw-r--r--src/third_party/mozjs-45/extract/js/src/jit/ExecutableAllocatorWin.cpp289
-rw-r--r--src/third_party/mozjs-45/extract/js/src/jit/Ion.cpp12
-rw-r--r--src/third_party/mozjs-45/extract/js/src/jit/IonAnalysis.cpp6
-rw-r--r--src/third_party/mozjs-45/extract/js/src/jit/IonBuilder.cpp11
-rw-r--r--src/third_party/mozjs-45/extract/js/src/jit/IonCaches.cpp20
-rw-r--r--src/third_party/mozjs-45/extract/js/src/jit/IonCode.h2
-rw-r--r--src/third_party/mozjs-45/extract/js/src/jit/JitcodeMap.cpp37
-rw-r--r--src/third_party/mozjs-45/extract/js/src/jit/JitcodeMap.h12
-rw-r--r--src/third_party/mozjs-45/extract/js/src/jit/Lowering.cpp4
-rw-r--r--src/third_party/mozjs-45/extract/js/src/jit/ProcessExecutableMemory.cpp614
-rw-r--r--src/third_party/mozjs-45/extract/js/src/jit/ProcessExecutableMemory.h46
-rw-r--r--src/third_party/mozjs-45/extract/js/src/jit/SharedIC.cpp8
-rw-r--r--src/third_party/mozjs-45/extract/js/src/jit/VMFunctions.cpp14
-rw-r--r--src/third_party/mozjs-45/extract/js/src/jsarray.cpp10
-rw-r--r--src/third_party/mozjs-45/extract/js/src/jsatom.cpp3
-rw-r--r--src/third_party/mozjs-45/extract/js/src/jsatom.h19
-rw-r--r--src/third_party/mozjs-45/extract/js/src/jsatominlines.h7
-rw-r--r--src/third_party/mozjs-45/extract/js/src/jscntxt.h1
-rw-r--r--src/third_party/mozjs-45/extract/js/src/jscompartment.cpp22
-rw-r--r--src/third_party/mozjs-45/extract/js/src/jscompartment.h18
-rw-r--r--src/third_party/mozjs-45/extract/js/src/jsgc.cpp49
-rw-r--r--src/third_party/mozjs-45/extract/js/src/jsgc.h6
-rw-r--r--src/third_party/mozjs-45/extract/js/src/jsgcinlines.h36
-rw-r--r--src/third_party/mozjs-45/extract/js/src/jsiter.cpp12
-rw-r--r--src/third_party/mozjs-45/extract/js/src/jsmath.cpp10
-rw-r--r--src/third_party/mozjs-45/extract/js/src/jsmath.h3
-rw-r--r--src/third_party/mozjs-45/extract/js/src/jswatchpoint.cpp5
-rw-r--r--src/third_party/mozjs-45/extract/js/src/jsweakmap.cpp2
-rw-r--r--src/third_party/mozjs-45/extract/js/src/jsweakmap.h18
-rw-r--r--src/third_party/mozjs-45/extract/js/src/moz.build8
-rw-r--r--src/third_party/mozjs-45/extract/js/src/proxy/Wrapper.cpp5
-rw-r--r--src/third_party/mozjs-45/extract/js/src/vm/Debugger.cpp14
-rw-r--r--src/third_party/mozjs-45/extract/js/src/vm/Debugger.h2
-rw-r--r--src/third_party/mozjs-45/extract/js/src/vm/Initialization.cpp7
-rw-r--r--src/third_party/mozjs-45/extract/js/src/vm/ObjectGroup.cpp66
-rw-r--r--src/third_party/mozjs-45/extract/js/src/vm/RegExpObject.cpp2
-rw-r--r--src/third_party/mozjs-45/extract/js/src/vm/Runtime.cpp27
-rw-r--r--src/third_party/mozjs-45/extract/js/src/vm/Runtime.h9
-rw-r--r--src/third_party/mozjs-45/extract/js/src/vm/Shape.h28
-rw-r--r--src/third_party/mozjs-45/extract/js/src/vm/String-inl.h17
-rw-r--r--src/third_party/mozjs-45/extract/js/src/vm/String.cpp17
-rw-r--r--src/third_party/mozjs-45/extract/js/src/vm/String.h105
-rw-r--r--src/third_party/mozjs-45/extract/js/src/vm/Symbol.cpp8
-rw-r--r--src/third_party/mozjs-45/extract/js/src/vm/Symbol.h26
-rw-r--r--src/third_party/mozjs-45/extract/js/src/vm/TypeInference.cpp10
-rw-r--r--src/third_party/mozjs-45/extract/js/src/vm/TypeInference.h2
-rw-r--r--src/third_party/mozjs-45/extract/js/src/vm/TypedArrayObject.cpp43
-rw-r--r--src/third_party/mozjs-45/extract/js/src/vm/UnboxedObject.cpp4
-rw-r--r--src/third_party/mozjs-45/extract/mfbt/HashFunctions.h85
-rw-r--r--src/third_party/mozjs-45/get-sources.sh2
-rw-r--r--src/third_party/mozjs-45/include/js/GCAPI.h2
-rw-r--r--src/third_party/mozjs-45/include/mozilla/HashFunctions.h85
-rw-r--r--src/third_party/mozjs-45/mongo_patches/SERVER-28400-Solaris_MAP_NORESERVE.patch18
-rw-r--r--src/third_party/mozjs-45/platform/aarch64/linux/build/js-confdefs.h6
-rw-r--r--src/third_party/mozjs-45/platform/aarch64/linux/include/js-config.h2
-rw-r--r--src/third_party/mozjs-45/platform/ppc64le/linux/build/js-confdefs.h6
-rw-r--r--src/third_party/mozjs-45/platform/ppc64le/linux/include/js-config.h2
-rw-r--r--src/third_party/mozjs-45/platform/s390x/linux/build/js-confdefs.h6
-rw-r--r--src/third_party/mozjs-45/platform/s390x/linux/include/js-config.h2
-rw-r--r--src/third_party/mozjs-45/platform/x86_64/freebsd/build/js-confdefs.h6
-rw-r--r--src/third_party/mozjs-45/platform/x86_64/freebsd/include/js-config.h2
-rw-r--r--src/third_party/mozjs-45/platform/x86_64/linux/build/js-confdefs.h6
-rw-r--r--src/third_party/mozjs-45/platform/x86_64/linux/include/js-config.h2
-rw-r--r--src/third_party/mozjs-45/platform/x86_64/macOS/build/js-confdefs.h6
-rw-r--r--src/third_party/mozjs-45/platform/x86_64/macOS/include/js-config.h2
-rw-r--r--src/third_party/mozjs-45/platform/x86_64/openbsd/build/js-confdefs.h6
-rw-r--r--src/third_party/mozjs-45/platform/x86_64/openbsd/include/js-config.h2
-rw-r--r--src/third_party/mozjs-45/platform/x86_64/solaris/build/js-confdefs.h6
-rw-r--r--src/third_party/mozjs-45/platform/x86_64/solaris/include/js-config.h2
-rw-r--r--src/third_party/mozjs-45/platform/x86_64/windows/build/js-confdefs.h6
-rw-r--r--src/third_party/mozjs-45/platform/x86_64/windows/include/js-config.h2
91 files changed, 1615 insertions, 812 deletions
diff --git a/src/third_party/mozjs-45/SConscript b/src/third_party/mozjs-45/SConscript
index dae5ab61ccb..4e9a8b07f9c 100644
--- a/src/third_party/mozjs-45/SConscript
+++ b/src/third_party/mozjs-45/SConscript
@@ -91,6 +91,7 @@ env.Prepend(CPPPATH=[
sources = [
"extract/js/src/builtin/RegExp.cpp",
"extract/js/src/frontend/Parser.cpp",
+ "extract/js/src/jit/ProcessExecutableMemory.cpp",
"extract/js/src/jsarray.cpp",
"extract/js/src/jsatom.cpp",
"extract/js/src/jsmath.cpp",
@@ -112,13 +113,6 @@ if env.TargetOSIs('windows'):
env.Prepend(CPPDEFINES=[
("_CRT_RAND_S", "1")
])
- sources.extend([
- "extract/js/src/jit/ExecutableAllocatorWin.cpp",
- ])
-else:
- sources.extend([
- "extract/js/src/jit/ExecutableAllocatorPosix.cpp",
- ])
sources.extend(Glob('platform/' + env["TARGET_ARCH"] + "/" + env["TARGET_OS"] + "/build/*.cpp")),
diff --git a/src/third_party/mozjs-45/extract.sh b/src/third_party/mozjs-45/extract.sh
index 589661b4ff9..18c51f7eaee 100644
--- a/src/third_party/mozjs-45/extract.sh
+++ b/src/third_party/mozjs-45/extract.sh
@@ -229,4 +229,5 @@ cp extract/mfbt/XorShift128PlusRNG.h include/mozilla
git apply \
mongo_patches/SERVER-23358.patch \
mongo_patches/SERVER-24400.patch \
- mongo_patches/SERVER-22927-x86_64.patch
+ mongo_patches/SERVER-22927-x86_64.patch \
+ mongo_patches/SERVER-28400-Solaris_MAP_NORESERVE.patch
diff --git a/src/third_party/mozjs-45/extract/js/public/GCAPI.h b/src/third_party/mozjs-45/extract/js/public/GCAPI.h
index 90f8e4eba3f..84b6150c36f 100644
--- a/src/third_party/mozjs-45/extract/js/public/GCAPI.h
+++ b/src/third_party/mozjs-45/extract/js/public/GCAPI.h
@@ -566,8 +566,6 @@ namespace gc {
static MOZ_ALWAYS_INLINE void
ExposeGCThingToActiveJS(JS::GCCellPtr thing)
{
- MOZ_ASSERT(thing.kind() != JS::TraceKind::Shape);
-
/*
* GC things residing in the nursery cannot be gray: they have no mark bits.
* All live objects in the nursery are moved to tenured at the beginning of
diff --git a/src/third_party/mozjs-45/extract/js/src/NamespaceImports.h b/src/third_party/mozjs-45/extract/js/src/NamespaceImports.h
index 05a0e5dcf51..929263e69f4 100644
--- a/src/third_party/mozjs-45/extract/js/src/NamespaceImports.h
+++ b/src/third_party/mozjs-45/extract/js/src/NamespaceImports.h
@@ -49,6 +49,10 @@ class MOZ_STACK_CLASS SourceBufferHolder;
class HandleValueArray;
class ObjectOpResult;
+
+class Symbol;
+enum class SymbolCode: uint32_t;
+
} // namespace JS
// Do the importing.
@@ -148,6 +152,9 @@ using JS::ObjectOpResult;
using JS::Zone;
+using JS::Symbol;
+using JS::SymbolCode;
+
} /* namespace js */
#endif /* NamespaceImports_h */
diff --git a/src/third_party/mozjs-45/extract/js/src/asmjs/AsmJSModule.cpp b/src/third_party/mozjs-45/extract/js/src/asmjs/AsmJSModule.cpp
index 350827042ee..9e707d06d0e 100644
--- a/src/third_party/mozjs-45/extract/js/src/asmjs/AsmJSModule.cpp
+++ b/src/third_party/mozjs-45/extract/js/src/asmjs/AsmJSModule.cpp
@@ -64,12 +64,11 @@ using JS::GenericNaN;
static uint8_t*
AllocateExecutableMemory(ExclusiveContext* cx, size_t bytes)
{
- // On most platforms, this will allocate RWX memory. On iOS, or when
- // --non-writable-jitcode is used, this will allocate RW memory. In this
- // case, DynamicallyLinkModule will reprotect the code as RX.
- unsigned permissions =
- ExecutableAllocator::initialProtectionFlags(ExecutableAllocator::Writable);
- void* p = AllocateExecutableMemory(nullptr, bytes, permissions, "asm-js-code", AsmJSPageSize);
+ // bytes is a multiple of the system's page size, but not necessarily
+ // a multiple of ExecutableCodePageSize.
+ bytes = JS_ROUNDUP(bytes, ExecutableCodePageSize);
+
+ void* p = AllocateExecutableMemory(bytes, ProtectionSetting::Writable);
if (!p)
ReportOutOfMemory(cx);
return (uint8_t*)p;
@@ -122,7 +121,8 @@ AsmJSModule::~AsmJSModule()
exitDatum.baselineScript->removeDependentAsmJSModule(exit);
}
- DeallocateExecutableMemory(code_, pod.totalBytes_, AsmJSPageSize);
+ uint32_t size = JS_ROUNDUP(pod.totalBytes_, ExecutableCodePageSize);
+ DeallocateExecutableMemory(code_, size);
}
if (prevLinked_)
diff --git a/src/third_party/mozjs-45/extract/js/src/builtin/MapObject.cpp b/src/third_party/mozjs-45/extract/js/src/builtin/MapObject.cpp
index 94b97f434a5..8d474aefb50 100644
--- a/src/third_party/mozjs-45/extract/js/src/builtin/MapObject.cpp
+++ b/src/third_party/mozjs-45/extract/js/src/builtin/MapObject.cpp
@@ -15,6 +15,7 @@
#include "js/Utility.h"
#include "vm/GlobalObject.h"
#include "vm/Interpreter.h"
+#include "vm/Symbol.h"
#include "jsobjinlines.h"
@@ -63,13 +64,33 @@ HashableValue::setValue(JSContext* cx, HandleValue v)
return true;
}
-HashNumber
-HashableValue::hash() const
+static HashNumber
+HashValue(const Value& v, const mozilla::HashCodeScrambler& hcs)
{
// HashableValue::setValue normalizes values so that the SameValue relation
// on HashableValues is the same as the == relationship on
- // value.data.asBits.
- return value.asRawBits();
+ // value.asRawBits(). So why not just return that? Security.
+ //
+ // To avoid revealing GC of atoms, string-based hash codes are computed
+ // from the string contents rather than any pointer; to avoid revealing
+ // addresses, pointer-based hash codes are computed using the
+ // HashCodeScrambler.
+
+ if (v.isString())
+ return v.toString()->asAtom().hash();
+ if (v.isSymbol())
+ return v.toSymbol()->hash();
+ if (v.isObject())
+ return hcs.scramble(v.asRawBits());
+
+ MOZ_ASSERT(v.isNull() || !v.isGCThing(), "do not reveal pointers via hash codes");
+ return v.asRawBits();
+}
+
+HashNumber
+HashableValue::hash(const mozilla::HashCodeScrambler& hcs) const
+{
+ return HashValue(value, hcs);
}
bool
@@ -325,13 +346,15 @@ MapObject::mark(JSTracer* trc, JSObject* obj)
struct UnbarrieredHashPolicy {
typedef Value Lookup;
- static HashNumber hash(const Lookup& v) { return v.asRawBits(); }
+ static HashNumber hash(const Lookup& v, const mozilla::HashCodeScrambler& hcs) {
+ return HashValue(v, hcs);
+ }
static bool match(const Value& k, const Lookup& l) { return k == l; }
static bool isEmpty(const Value& v) { return v.isMagic(JS_HASH_KEY_EMPTY); }
static void makeEmpty(Value* vp) { vp->setMagic(JS_HASH_KEY_EMPTY); }
};
-template <typename TableType>
+template <typename RealTableType, typename TableType>
class OrderedHashTableRef : public gc::BufferableRef
{
TableType* table;
@@ -341,8 +364,9 @@ class OrderedHashTableRef : public gc::BufferableRef
explicit OrderedHashTableRef(TableType* t, const Value& k) : table(t), key(k) {}
void trace(JSTracer* trc) override {
- MOZ_ASSERT(UnbarrieredHashPolicy::hash(key) ==
- HashableValue::Hasher::hash(*reinterpret_cast<HashableValue*>(&key)));
+ MOZ_ASSERT(reinterpret_cast<RealTableType*>(table)
+ ->hash(*reinterpret_cast<HashableValue*>(&key)) ==
+ table->hash(key));
Value prior = key;
TraceManuallyBarrieredEdge(trc, &key, "ordered hash table key");
table->rekeyOneEntry(prior, key);
@@ -354,7 +378,7 @@ WriteBarrierPost(JSRuntime* rt, ValueMap* map, const Value& key)
{
typedef OrderedHashMap<Value, Value, UnbarrieredHashPolicy, RuntimeAllocPolicy> UnbarrieredMap;
if (MOZ_UNLIKELY(key.isObject() && IsInsideNursery(&key.toObject()))) {
- rt->gc.storeBuffer.putGeneric(OrderedHashTableRef<UnbarrieredMap>(
+ rt->gc.storeBuffer.putGeneric(OrderedHashTableRef<ValueMap, UnbarrieredMap>(
reinterpret_cast<UnbarrieredMap*>(map), key));
}
}
@@ -364,7 +388,7 @@ WriteBarrierPost(JSRuntime* rt, ValueSet* set, const Value& key)
{
typedef OrderedHashSet<Value, UnbarrieredHashPolicy, RuntimeAllocPolicy> UnbarrieredSet;
if (MOZ_UNLIKELY(key.isObject() && IsInsideNursery(&key.toObject()))) {
- rt->gc.storeBuffer.putGeneric(OrderedHashTableRef<UnbarrieredSet>(
+ rt->gc.storeBuffer.putGeneric(OrderedHashTableRef<ValueSet, UnbarrieredSet>(
reinterpret_cast<UnbarrieredSet*>(set), key));
}
}
@@ -411,7 +435,8 @@ MapObject::set(JSContext* cx, HandleObject obj, HandleValue k, HandleValue v)
MapObject*
MapObject::create(JSContext* cx, HandleObject proto /* = nullptr */)
{
- auto map = cx->make_unique<ValueMap>(cx->runtime());
+ auto map = cx->make_unique<ValueMap>(cx->runtime(),
+ cx->compartment()->randomHashCodeScrambler());
if (!map || !map->init()) {
ReportOutOfMemory(cx);
return nullptr;
@@ -535,7 +560,7 @@ MapObject::is(HandleObject o)
}
#define ARG0_KEY(cx, args, key) \
- Rooted<HashableValue> key(cx); \
+ Rooted<HashableValue> key(cx); \
if (args.length() > 0 && !key.setValue(cx, args[0])) \
return false
@@ -1064,7 +1089,8 @@ SetObject::add(JSContext* cx, HandleObject obj, HandleValue k)
SetObject*
SetObject::create(JSContext* cx, HandleObject proto /* = nullptr */)
{
- auto set = cx->make_unique<ValueSet>(cx->runtime());
+ auto set = cx->make_unique<ValueSet>(cx->runtime(),
+ cx->compartment()->randomHashCodeScrambler());
if (!set || !set->init()) {
ReportOutOfMemory(cx);
return nullptr;
diff --git a/src/third_party/mozjs-45/extract/js/src/builtin/MapObject.h b/src/third_party/mozjs-45/extract/js/src/builtin/MapObject.h
index 1118675f873..9af58fc21cd 100644
--- a/src/third_party/mozjs-45/extract/js/src/builtin/MapObject.h
+++ b/src/third_party/mozjs-45/extract/js/src/builtin/MapObject.h
@@ -29,7 +29,9 @@ class HashableValue : public JS::Traceable
public:
struct Hasher {
typedef HashableValue Lookup;
- static HashNumber hash(const Lookup& v) { return v.hash(); }
+ static HashNumber hash(const Lookup& v, const mozilla::HashCodeScrambler& hcs) {
+ return v.hash(hcs);
+ }
static bool match(const HashableValue& k, const Lookup& l) { return k == l; }
static bool isEmpty(const HashableValue& v) { return v.value.isMagic(JS_HASH_KEY_EMPTY); }
static void makeEmpty(HashableValue* vp) { vp->value = MagicValue(JS_HASH_KEY_EMPTY); }
@@ -38,7 +40,7 @@ class HashableValue : public JS::Traceable
HashableValue() : value(UndefinedValue()) {}
bool setValue(JSContext* cx, HandleValue v);
- HashNumber hash() const;
+ HashNumber hash(const mozilla::HashCodeScrambler& hcs) const;
bool operator==(const HashableValue& other) const;
HashableValue mark(JSTracer* trc) const;
Value get() const { return value.get(); }
diff --git a/src/third_party/mozjs-45/extract/js/src/ds/OrderedHashTable.h b/src/third_party/mozjs-45/extract/js/src/ds/OrderedHashTable.h
index c9927212976..cb58ac2f735 100644
--- a/src/third_party/mozjs-45/extract/js/src/ds/OrderedHashTable.h
+++ b/src/third_party/mozjs-45/extract/js/src/ds/OrderedHashTable.h
@@ -29,12 +29,15 @@
*
* See the comment about "Hash policy" in HashTable.h for general features that
* hash policy classes must provide. Hash policies for OrderedHashMaps and Sets
- * must additionally provide a distinguished "empty" key value and the
+ * differ in that the hash() method takes an extra argument:
+ * static js::HashNumber hash(Lookup, const HashCodeScrambler&);
+ * They must additionally provide a distinguished "empty" key value and the
* following static member functions:
* bool isEmpty(const Key&);
* void makeEmpty(Key*);
*/
+#include "mozilla/HashFunctions.h"
#include "mozilla/Move.h"
using mozilla::Forward;
@@ -78,10 +81,11 @@ class OrderedHashTable
uint32_t hashShift; // multiplicative hash shift
Range* ranges; // list of all live Ranges on this table
AllocPolicy alloc;
+ mozilla::HashCodeScrambler hcs; // don't reveal pointer hash codes
public:
- explicit OrderedHashTable(AllocPolicy& ap)
- : hashTable(nullptr), data(nullptr), dataLength(0), ranges(nullptr), alloc(ap) {}
+ OrderedHashTable(AllocPolicy& ap, mozilla::HashCodeScrambler hcs)
+ : hashTable(nullptr), data(nullptr), dataLength(0), ranges(nullptr), alloc(ap), hcs(hcs) {}
bool init() {
MOZ_ASSERT(!hashTable, "init must be called at most once");
@@ -430,8 +434,8 @@ class OrderedHashTable
void rekeyFront(const Key& k) {
MOZ_ASSERT(valid());
Data& entry = ht.data[i];
- HashNumber oldHash = prepareHash(Ops::getKey(entry.element)) >> ht.hashShift;
- HashNumber newHash = prepareHash(k) >> ht.hashShift;
+ HashNumber oldHash = ht.prepareHash(Ops::getKey(entry.element)) >> ht.hashShift;
+ HashNumber newHash = ht.prepareHash(k) >> ht.hashShift;
Ops::setKey(entry.element, k);
if (newHash != oldHash) {
// Remove this entry from its old hash chain. (If this crashes
@@ -527,10 +531,12 @@ class OrderedHashTable
*/
static double minDataFill() { return 0.25; }
- static HashNumber prepareHash(const Lookup& l) {
- return ScrambleHashCode(Ops::hash(l));
+ public:
+ HashNumber prepareHash(const Lookup& l) const {
+ return ScrambleHashCode(Ops::hash(l, hcs));
}
+ private:
/* The size of hashTable, in elements. Always a power of two. */
uint32_t hashBuckets() const {
return 1 << (HashNumberSizeBits - hashShift);
@@ -701,7 +707,7 @@ class OrderedHashMap
public:
typedef typename Impl::Range Range;
- explicit OrderedHashMap(AllocPolicy ap = AllocPolicy()) : impl(ap) {}
+ OrderedHashMap(AllocPolicy ap, mozilla::HashCodeScrambler hcs) : impl(ap, hcs) {}
bool init() { return impl.init(); }
uint32_t count() const { return impl.count(); }
bool has(const Key& key) const { return impl.has(key); }
@@ -713,6 +719,8 @@ class OrderedHashMap
bool remove(const Key& key, bool* foundp) { return impl.remove(key, foundp); }
bool clear() { return impl.clear(); }
+ HashNumber hash(const Key& key) const { return impl.prepareHash(key); }
+
void rekeyOneEntry(const Key& current, const Key& newKey) {
const Entry* e = get(current);
if (!e)
@@ -738,7 +746,7 @@ class OrderedHashSet
public:
typedef typename Impl::Range Range;
- explicit OrderedHashSet(AllocPolicy ap = AllocPolicy()) : impl(ap) {}
+ explicit OrderedHashSet(AllocPolicy ap, mozilla::HashCodeScrambler hcs) : impl(ap, hcs) {}
bool init() { return impl.init(); }
uint32_t count() const { return impl.count(); }
bool has(const T& value) const { return impl.has(value); }
@@ -747,6 +755,8 @@ class OrderedHashSet
bool remove(const T& value, bool* foundp) { return impl.remove(value, foundp); }
bool clear() { return impl.clear(); }
+ HashNumber hash(const T& value) const { return impl.prepareHash(value); }
+
void rekeyOneEntry(const T& current, const T& newKey) {
return impl.rekeyOneEntry(current, newKey, newKey);
}
diff --git a/src/third_party/mozjs-45/extract/js/src/gc/Allocator.cpp b/src/third_party/mozjs-45/extract/js/src/gc/Allocator.cpp
index b409dfa4a1f..bdc17bdc8db 100644
--- a/src/third_party/mozjs-45/extract/js/src/gc/Allocator.cpp
+++ b/src/third_party/mozjs-45/extract/js/src/gc/Allocator.cpp
@@ -57,11 +57,14 @@ GCRuntime::checkAllocatorState(JSContext* cx, AllocKind kind)
}
#if defined(JS_GC_ZEAL) || defined(DEBUG)
- MOZ_ASSERT_IF(rt->isAtomsCompartment(cx->compartment()),
- kind == AllocKind::STRING ||
- kind == AllocKind::FAT_INLINE_STRING ||
+ MOZ_ASSERT_IF(cx->compartment()->isAtomsCompartment(),
+ kind == AllocKind::ATOM ||
+ kind == AllocKind::FAT_INLINE_ATOM ||
kind == AllocKind::SYMBOL ||
kind == AllocKind::JITCODE);
+ MOZ_ASSERT_IF(!cx->compartment()->isAtomsCompartment(),
+ kind != AllocKind::ATOM &&
+ kind != AllocKind::FAT_INLINE_ATOM);
MOZ_ASSERT(!rt->isHeapBusy());
MOZ_ASSERT(isAllocAllowed());
#endif
@@ -221,6 +224,8 @@ js::Allocate(ExclusiveContext* cx)
macro(JSFatInlineString) \
macro(JSScript) \
macro(JSString) \
+ macro(js::NormalAtom) \
+ macro(js::FatInlineAtom) \
macro(js::AccessorShape) \
macro(js::BaseShape) \
macro(js::LazyScript) \
diff --git a/src/third_party/mozjs-45/extract/js/src/gc/GCRuntime.h b/src/third_party/mozjs-45/extract/js/src/gc/GCRuntime.h
index d2b45473862..e0ad996150d 100644
--- a/src/third_party/mozjs-45/extract/js/src/gc/GCRuntime.h
+++ b/src/third_party/mozjs-45/extract/js/src/gc/GCRuntime.h
@@ -923,7 +923,7 @@ class GCRuntime
void purgeRuntime();
bool beginMarkPhase(JS::gcreason::Reason reason);
bool shouldPreserveJITCode(JSCompartment* comp, int64_t currentTime,
- JS::gcreason::Reason reason);
+ JS::gcreason::Reason reason, bool canAllocateMoreCode);
void bufferGrayRoots();
void markCompartments();
IncrementalProgress drainMarkStack(SliceBudget& sliceBudget, gcstats::Phase phase);
diff --git a/src/third_party/mozjs-45/extract/js/src/gc/Heap.h b/src/third_party/mozjs-45/extract/js/src/gc/Heap.h
index 1ff1d9fa498..783da19a388 100644
--- a/src/third_party/mozjs-45/extract/js/src/gc/Heap.h
+++ b/src/third_party/mozjs-45/extract/js/src/gc/Heap.h
@@ -106,6 +106,8 @@ enum class AllocKind {
FAT_INLINE_STRING,
STRING,
EXTERNAL_STRING,
+ FAT_INLINE_ATOM,
+ ATOM,
SYMBOL,
JITCODE,
LIMIT,
@@ -197,6 +199,8 @@ MapAllocToTraceKind(AllocKind kind)
JS::TraceKind::String, /* AllocKind::FAT_INLINE_STRING */
JS::TraceKind::String, /* AllocKind::STRING */
JS::TraceKind::String, /* AllocKind::EXTERNAL_STRING */
+ JS::TraceKind::String, /* AllocKind::FAT_INLINE_ATOM */
+ JS::TraceKind::String, /* AllocKind::ATOM */
JS::TraceKind::Symbol, /* AllocKind::SYMBOL */
JS::TraceKind::JitCode, /* AllocKind::JITCODE */
};
diff --git a/src/third_party/mozjs-45/extract/js/src/gc/Marking.cpp b/src/third_party/mozjs-45/extract/js/src/gc/Marking.cpp
index f52ab393f71..4e10b20b36c 100644
--- a/src/third_party/mozjs-45/extract/js/src/gc/Marking.cpp
+++ b/src/third_party/mozjs-45/extract/js/src/gc/Marking.cpp
@@ -171,6 +171,17 @@ template <> bool ThingIsPermanentAtomOrWellKnownSymbol<JS::Symbol>(JS::Symbol* s
return sym->isWellKnownSymbol();
}
+template <typename T>
+static inline bool
+IsOwnedByOtherRuntime(JSRuntime* rt, T thing)
+{
+ bool other = thing->runtimeFromAnyThread() != rt;
+ MOZ_ASSERT_IF(other,
+ ThingIsPermanentAtomOrWellKnownSymbol(thing) ||
+ thing->zoneFromAnyThread()->isSelfHostingZone());
+ return other;
+}
+
template<typename T>
void
js::CheckTracedThing(JSTracer* trc, T* thing)
@@ -188,10 +199,10 @@ js::CheckTracedThing(JSTracer* trc, T* thing)
MOZ_ASSERT_IF(!IsMovingTracer(trc) && !trc->isTenuringTracer(), !IsForwarded(thing));
/*
- * Permanent atoms are not associated with this runtime, but will be
- * ignored during marking.
+ * Permanent atoms and things in the self-hosting zone are not associated
+ * with this runtime, but will be ignored during marking.
*/
- if (ThingIsPermanentAtomOrWellKnownSymbol(thing))
+ if (IsOwnedByOtherRuntime(trc->runtime(), thing))
return;
Zone* zone = thing->zoneFromAnyThread();
@@ -675,16 +686,24 @@ GCMarker::markImplicitEdges(T* thing)
template <typename T>
static inline bool
-MustSkipMarking(T thing)
+MustSkipMarking(GCMarker* gcmarker, T thing)
{
+ // Don't trace things that are owned by another runtime.
+ if (IsOwnedByOtherRuntime(gcmarker->runtime(), thing))
+ return true;
+
// Don't mark things outside a zone if we are in a per-zone GC.
return !thing->zone()->isGCMarking();
}
template <>
bool
-MustSkipMarking<JSObject*>(JSObject* obj)
+MustSkipMarking<JSObject*>(GCMarker* gcmarker, JSObject* obj)
{
+ // Don't trace things that are owned by another runtime.
+ if (IsOwnedByOtherRuntime(gcmarker->runtime(), obj))
+ return true;
+
// We may mark a Nursery thing outside the context of the
// MinorCollectionTracer because of a pre-barrier. The pre-barrier is not
// needed in this case because we perform a minor collection before each
@@ -698,34 +717,12 @@ MustSkipMarking<JSObject*>(JSObject* obj)
return !TenuredCell::fromPointer(obj)->zone()->isGCMarking();
}
-template <>
-bool
-MustSkipMarking<JSString*>(JSString* str)
-{
- // Don't mark permanent atoms, as they may be associated with another
- // runtime. Note that traverse() also checks this, but we need to not
- // run the isGCMarking test from off-main-thread, so have to check it here
- // too.
- return str->isPermanentAtom() ||
- !str->zone()->isGCMarking();
-}
-
-template <>
-bool
-MustSkipMarking<JS::Symbol*>(JS::Symbol* sym)
-{
- // As for JSString, don't touch a globally owned well-known symbol from
- // off-main-thread.
- return sym->isWellKnownSymbol() ||
- !sym->zone()->isGCMarking();
-}
-
template <typename T>
void
DoMarking(GCMarker* gcmarker, T* thing)
{
// Do per-type marking precondition checks.
- if (MustSkipMarking(thing))
+ if (MustSkipMarking(gcmarker, thing))
return;
CheckTracedThing(gcmarker, thing);
@@ -752,13 +749,13 @@ void
NoteWeakEdge(GCMarker* gcmarker, T** thingp)
{
// Do per-type marking precondition checks.
- if (MustSkipMarking(*thingp))
+ if (MustSkipMarking(gcmarker, *thingp))
return;
CheckTracedThing(gcmarker, *thingp);
// If the target is already marked, there's no need to store the edge.
- if (IsMarkedUnbarriered(thingp))
+ if (IsMarkedUnbarriered(gcmarker->runtime(), thingp))
return;
gcmarker->noteWeakEdge(thingp);
@@ -2329,17 +2326,22 @@ IsMarkedInternalCommon(T* thingp)
template <typename T>
static bool
-IsMarkedInternal(T** thingp)
+IsMarkedInternal(JSRuntime* rt, T** thingp)
{
+ if (IsOwnedByOtherRuntime(rt, *thingp))
+ return true;
+
return IsMarkedInternalCommon(thingp);
}
template <>
/* static */ bool
-IsMarkedInternal(JSObject** thingp)
+IsMarkedInternal(JSRuntime* rt, JSObject** thingp)
{
+ if (IsOwnedByOtherRuntime(rt, *thingp))
+ return true;
+
if (IsInsideNursery(*thingp)) {
- JSRuntime* rt = (*thingp)->runtimeFromAnyThread();
MOZ_ASSERT(CurrentThreadCanAccessRuntime(rt));
return rt->gc.nursery.getForwardedPointer(thingp);
}
@@ -2348,18 +2350,18 @@ IsMarkedInternal(JSObject** thingp)
template <typename S>
struct IsMarkedFunctor : public IdentityDefaultAdaptor<S> {
- template <typename T> S operator()(T* t, bool* rv) {
- *rv = IsMarkedInternal(&t);
+ template <typename T> S operator()(T* t, JSRuntime* rt, bool* rv) {
+ *rv = IsMarkedInternal(rt, &t);
return js::gc::RewrapTaggedPointer<S, T*>::wrap(t);
}
};
template <typename T>
static bool
-IsMarkedInternal(T* thingp)
+IsMarkedInternal(JSRuntime* rt, T* thingp)
{
bool rv = true;
- *thingp = DispatchTyped(IsMarkedFunctor<T>(), *thingp, &rv);
+ *thingp = DispatchTyped(IsMarkedFunctor<T>(), *thingp, rt, &rv);
return rv;
}
@@ -2427,16 +2429,16 @@ namespace gc {
template <typename T>
bool
-IsMarkedUnbarriered(T* thingp)
+IsMarkedUnbarriered(JSRuntime* rt, T* thingp)
{
- return IsMarkedInternal(ConvertToBase(thingp));
+ return IsMarkedInternal(rt, ConvertToBase(thingp));
}
template <typename T>
bool
-IsMarked(WriteBarrieredBase<T>* thingp)
+IsMarked(JSRuntime* rt, WriteBarrieredBase<T>* thingp)
{
- return IsMarkedInternal(ConvertToBase(thingp->unsafeUnbarrieredForTracing()));
+ return IsMarkedInternal(rt, ConvertToBase(thingp->unsafeUnbarrieredForTracing()));
}
template <typename T>
@@ -2469,8 +2471,8 @@ EdgeNeedsSweep(JS::Heap<T>* thingp)
// Instantiate a copy of the Tracing templates for each derived type.
#define INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS(type) \
- template bool IsMarkedUnbarriered<type>(type*); \
- template bool IsMarked<type>(WriteBarrieredBase<type>*); \
+ template bool IsMarkedUnbarriered<type>(JSRuntime*, type*); \
+ template bool IsMarked<type>(JSRuntime*, WriteBarrieredBase<type>*); \
template bool IsAboutToBeFinalizedUnbarriered<type>(type*); \
template bool IsAboutToBeFinalized<type>(WriteBarrieredBase<type>*); \
template bool IsAboutToBeFinalized<type>(ReadBarrieredBase<type>*); \
diff --git a/src/third_party/mozjs-45/extract/js/src/gc/Marking.h b/src/third_party/mozjs-45/extract/js/src/gc/Marking.h
index 5c69cd1fdb6..5e237c2154b 100644
--- a/src/third_party/mozjs-45/extract/js/src/gc/Marking.h
+++ b/src/third_party/mozjs-45/extract/js/src/gc/Marking.h
@@ -142,7 +142,9 @@ namespace gc {
struct WeakKeyTableHashPolicy {
typedef JS::GCCellPtr Lookup;
- static HashNumber hash(const Lookup& v) { return mozilla::HashGeneric(v.asCell()); }
+ static HashNumber hash(const Lookup& v, const mozilla::HashCodeScrambler&) {
+ return mozilla::HashGeneric(v.asCell());
+ }
static bool match(const JS::GCCellPtr& k, const Lookup& l) { return k == l; }
static bool isEmpty(const JS::GCCellPtr& v) { return !v; }
static void makeEmpty(JS::GCCellPtr* vp) { *vp = nullptr; }
@@ -368,13 +370,19 @@ PushArena(GCMarker* gcmarker, ArenaHeader* aheader);
/*** Liveness ***/
+// Report whether a thing has been marked. Things which are in zones that are
+// not currently being collected or are owned by another runtime are always
+// reported as being marked.
template <typename T>
bool
-IsMarkedUnbarriered(T* thingp);
+IsMarkedUnbarriered(JSRuntime* rt, T* thingp);
+// Report whether a thing has been marked. Things which are in zones that are
+// not currently being collected or are owned by another runtime are always
+// reported as being marked.
template <typename T>
bool
-IsMarked(WriteBarrieredBase<T>* thingp);
+IsMarked(JSRuntime* rt, WriteBarrieredBase<T>* thingp);
template <typename T>
bool
diff --git a/src/third_party/mozjs-45/extract/js/src/gc/Zone.cpp b/src/third_party/mozjs-45/extract/js/src/gc/Zone.cpp
index 260f06dbe47..b001ecff9e6 100644
--- a/src/third_party/mozjs-45/extract/js/src/gc/Zone.cpp
+++ b/src/third_party/mozjs-45/extract/js/src/gc/Zone.cpp
@@ -29,6 +29,7 @@ JS::Zone::Zone(JSRuntime* rt)
types(this),
compartments(),
gcGrayRoots(),
+ gcWeakKeys(SystemAllocPolicy(), rt->randomHashCodeScrambler()),
gcMallocBytes(0),
gcMallocGCTriggered(false),
usage(&rt->gc.usage),
diff --git a/src/third_party/mozjs-45/extract/js/src/irregexp/RegExpEngine.cpp b/src/third_party/mozjs-45/extract/js/src/irregexp/RegExpEngine.cpp
index ba30fc7a72d..84dab0c8adf 100644
--- a/src/third_party/mozjs-45/extract/js/src/irregexp/RegExpEngine.cpp
+++ b/src/third_party/mozjs-45/extract/js/src/irregexp/RegExpEngine.cpp
@@ -32,6 +32,7 @@
#include "irregexp/NativeRegExpMacroAssembler.h"
#include "irregexp/RegExpMacroAssembler.h"
+#include "jit/ExecutableAllocator.h"
#include "jit/JitCommon.h"
using namespace js;
@@ -1730,7 +1731,11 @@ irregexp::CompilePattern(JSContext* cx, RegExpShared* shared, RegExpCompileData*
Maybe<InterpretedRegExpMacroAssembler> interpreted_assembler;
RegExpMacroAssembler* assembler;
- if (IsNativeRegExpEnabled(cx) && !force_bytecode) {
+ if (IsNativeRegExpEnabled(cx) &&
+ !force_bytecode &&
+ jit::CanLikelyAllocateMoreExecutableMemory() &&
+ shared->getSource()->length() < 32 * 1024)
+ {
NativeRegExpMacroAssembler::Mode mode =
is_ascii ? NativeRegExpMacroAssembler::ASCII
: NativeRegExpMacroAssembler::CHAR16;
diff --git a/src/third_party/mozjs-45/extract/js/src/jit/BaselineIC.cpp b/src/third_party/mozjs-45/extract/js/src/jit/BaselineIC.cpp
index 03236cff6cc..69c402bc1a9 100644
--- a/src/third_party/mozjs-45/extract/js/src/jit/BaselineIC.cpp
+++ b/src/third_party/mozjs-45/extract/js/src/jit/BaselineIC.cpp
@@ -1061,6 +1061,14 @@ IsCacheableSetPropCall(JSContext* cx, JSObject* obj, JSObject* holder, Shape* sh
JSFunction* func = &shape->setterObject()->as<JSFunction>();
+ if (IsWindow(obj)) {
+ if (!func->isNative())
+ return false;
+
+ if (!func->jitInfo() || func->jitInfo()->needsOuterizedThisObject())
+ return false;
+ }
+
if (func->isNative()) {
*isScripted = false;
return true;
@@ -6398,6 +6406,12 @@ ICCallStubCompiler::guardFunApply(MacroAssembler& masm, AllocatableGeneralRegist
Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFlags()),
Imm32(BaselineFrame::HAS_ARGS_OBJ),
failure);
+
+ // Limit the length to something reasonable.
+ masm.branch32(Assembler::Above,
+ Address(BaselineFrameReg, BaselineFrame::offsetOfNumActualArgs()),
+ Imm32(ICCall_ScriptedApplyArray::MAX_ARGS_ARRAY_LENGTH),
+ failure);
} else {
MOZ_ASSERT(applyThing == FunApply_Array);
diff --git a/src/third_party/mozjs-45/extract/js/src/jit/BaselineJIT.cpp b/src/third_party/mozjs-45/extract/js/src/jit/BaselineJIT.cpp
index f0dc2655e83..293868a741f 100644
--- a/src/third_party/mozjs-45/extract/js/src/jit/BaselineJIT.cpp
+++ b/src/third_party/mozjs-45/extract/js/src/jit/BaselineJIT.cpp
@@ -314,12 +314,17 @@ CanEnterBaselineJIT(JSContext* cx, HandleScript script, InterpreterFrame* osrFra
if (script->nslots() > BaselineScript::MAX_JSSCRIPT_SLOTS)
return Method_CantCompile;
- if (!cx->compartment()->ensureJitCompartmentExists(cx))
- return Method_Error;
-
if (script->hasBaselineScript())
return Method_Compiled;
+ // Check this before calling ensureJitCompartmentExists, so we're less
+ // likely to report OOM in JSRuntime::createJitRuntime.
+ if (!CanLikelyAllocateMoreExecutableMemory())
+ return Method_Skipped;
+
+ if (!cx->compartment()->ensureJitCompartmentExists(cx))
+ return Method_Error;
+
// Check script warm-up counter.
if (script->incWarmUpCounter() <= JitOptions.baselineWarmUpThreshold)
return Method_Skipped;
diff --git a/src/third_party/mozjs-45/extract/js/src/jit/ExecutableAllocator.cpp b/src/third_party/mozjs-45/extract/js/src/jit/ExecutableAllocator.cpp
index 55ad6b6d69c..aa24216c3a5 100644
--- a/src/third_party/mozjs-45/extract/js/src/jit/ExecutableAllocator.cpp
+++ b/src/third_party/mozjs-45/extract/js/src/jit/ExecutableAllocator.cpp
@@ -29,15 +29,8 @@
#include "js/MemoryMetrics.h"
-#ifdef __APPLE__
-#include <TargetConditionals.h>
-#endif
-
using namespace js::jit;
-size_t ExecutableAllocator::pageSize = 0;
-size_t ExecutableAllocator::largeAllocSize = 0;
-
ExecutablePool::~ExecutablePool()
{
MOZ_ASSERT(m_ionCodeBytes == 0);
@@ -48,28 +41,6 @@ ExecutablePool::~ExecutablePool()
m_allocator->releasePoolPages(this);
}
-/* static */ void
-ExecutableAllocator::initStatic()
-{
- if (!pageSize) {
- pageSize = determinePageSize();
- // On Windows, VirtualAlloc effectively allocates in 64K chunks.
- // (Technically, it allocates in page chunks, but the starting
- // address is always a multiple of 64K, so each allocation uses up
- // 64K of address space.) So a size less than that would be
- // pointless. But it turns out that 64KB is a reasonable size for
- // all platforms. (This assumes 4KB pages.) On 64-bit windows,
- // AllocateExecutableMemory prepends an extra page for structured
- // exception handling data (see comments in function) onto whatever
- // is passed in, so subtract one page here.
-#if defined(JS_CPU_X64) && defined(XP_WIN)
- largeAllocSize = pageSize * 15;
-#else
- largeAllocSize = pageSize * 16;
-#endif
- }
-}
-
void
ExecutableAllocator::addSizeOfCode(JS::CodeSizes* sizes) const
{
@@ -88,8 +59,16 @@ ExecutableAllocator::addSizeOfCode(JS::CodeSizes* sizes) const
}
}
-#if TARGET_OS_IPHONE
-bool ExecutableAllocator::nonWritableJitCode = true;
-#else
-bool ExecutableAllocator::nonWritableJitCode = false;
-#endif
+ExecutablePool::Allocation
+ExecutableAllocator::systemAlloc(size_t n)
+{
+ void* allocation = AllocateExecutableMemory(n, ProtectionSetting::Executable);
+ ExecutablePool::Allocation alloc = { reinterpret_cast<char*>(allocation), n };
+ return alloc;
+}
+
+void
+ExecutableAllocator::systemRelease(const ExecutablePool::Allocation& alloc)
+{
+ DeallocateExecutableMemory(alloc.pages, alloc.size);
+}
diff --git a/src/third_party/mozjs-45/extract/js/src/jit/ExecutableAllocator.h b/src/third_party/mozjs-45/extract/js/src/jit/ExecutableAllocator.h
index 874f6b7314f..cc0ad2b66ea 100644
--- a/src/third_party/mozjs-45/extract/js/src/jit/ExecutableAllocator.h
+++ b/src/third_party/mozjs-45/extract/js/src/jit/ExecutableAllocator.h
@@ -39,6 +39,7 @@
#include "jit/arm/Simulator-arm.h"
#include "jit/mips32/Simulator-mips32.h"
#include "jit/mips64/Simulator-mips64.h"
+#include "jit/ProcessExecutableMemory.h"
#include "js/GCAPI.h"
#include "js/HashTable.h"
#include "js/Vector.h"
@@ -186,13 +187,7 @@ class ExecutableAllocator
typedef void (*DestroyCallback)(void* addr, size_t size);
DestroyCallback destroyCallback;
-#ifdef XP_WIN
- mozilla::Maybe<mozilla::non_crypto::XorShift128PlusRNG> randomNumberGenerator;
-#endif
-
public:
- enum ProtectionSetting { Writable, Executable };
-
ExecutableAllocator()
: destroyCallback(nullptr)
{
@@ -263,14 +258,7 @@ class ExecutableAllocator
this->destroyCallback = destroyCallback;
}
- static void initStatic();
-
- static bool nonWritableJitCode;
-
private:
- static size_t pageSize;
- static size_t largeAllocSize;
-
static const size_t OVERSIZE_ALLOCATION = size_t(-1);
static size_t roundUpAllocationSize(size_t request, size_t granularity)
@@ -294,11 +282,10 @@ class ExecutableAllocator
// On OOM, this will return an Allocation where pages is nullptr.
ExecutablePool::Allocation systemAlloc(size_t n);
static void systemRelease(const ExecutablePool::Allocation& alloc);
- void* computeRandomAllocationAddress();
ExecutablePool* createPool(size_t n)
{
- size_t allocSize = roundUpAllocationSize(n, pageSize);
+ size_t allocSize = roundUpAllocationSize(n, ExecutableCodePageSize);
if (allocSize == OVERSIZE_ALLOCATION)
return nullptr;
@@ -316,8 +303,8 @@ class ExecutableAllocator
}
if (!m_pools.put(pool)) {
+ // Note: this will call |systemRelease(a)|.
js_delete(pool);
- systemRelease(a);
return nullptr;
}
@@ -344,11 +331,11 @@ class ExecutableAllocator
}
// If the request is large, we just provide a unshared allocator
- if (n > largeAllocSize)
+ if (n > ExecutableCodePageSize)
return createPool(n);
// Create a new allocator
- ExecutablePool* pool = createPool(largeAllocSize);
+ ExecutablePool* pool = createPool(ExecutableCodePageSize);
if (!pool)
return nullptr;
// At this point, local |pool| is the owner.
@@ -385,18 +372,12 @@ class ExecutableAllocator
static void makeWritable(void* start, size_t size)
{
- if (nonWritableJitCode)
- reprotectRegion(start, size, Writable);
}
static void makeExecutable(void* start, size_t size)
{
- if (nonWritableJitCode)
- reprotectRegion(start, size, Executable);
}
- static unsigned initialProtectionFlags(ProtectionSetting protection);
-
#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
static void cacheFlush(void*, size_t)
{
@@ -469,8 +450,6 @@ class ExecutableAllocator
ExecutableAllocator(const ExecutableAllocator&) = delete;
void operator=(const ExecutableAllocator&) = delete;
- static void reprotectRegion(void*, size_t, ProtectionSetting);
-
// These are strong references; they keep pools alive.
static const size_t maxSmallPools = 4;
typedef js::Vector<ExecutablePool*, maxSmallPools, js::SystemAllocPolicy> SmallExecPoolVector;
@@ -482,17 +461,8 @@ class ExecutableAllocator
typedef js::HashSet<ExecutablePool*, js::DefaultHasher<ExecutablePool*>, js::SystemAllocPolicy>
ExecPoolHashSet;
ExecPoolHashSet m_pools; // All pools, just for stats purposes.
-
- static size_t determinePageSize();
};
-extern void*
-AllocateExecutableMemory(void* addr, size_t bytes, unsigned permissions, const char* tag,
- size_t pageSize);
-
-extern void
-DeallocateExecutableMemory(void* addr, size_t bytes, size_t pageSize);
-
} // namespace jit
} // namespace js
diff --git a/src/third_party/mozjs-45/extract/js/src/jit/ExecutableAllocatorPosix.cpp b/src/third_party/mozjs-45/extract/js/src/jit/ExecutableAllocatorPosix.cpp
deleted file mode 100644
index d6d791174d6..00000000000
--- a/src/third_party/mozjs-45/extract/js/src/jit/ExecutableAllocatorPosix.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=99:
- *
- * Copyright (C) 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "mozilla/DebugOnly.h"
-#include "mozilla/TaggedAnonymousMemory.h"
-
-#include <errno.h>
-#include <sys/mman.h>
-#include <unistd.h>
-
-#include "jit/ExecutableAllocator.h"
-#include "js/Utility.h"
-
-using namespace js::jit;
-
-size_t
-ExecutableAllocator::determinePageSize()
-{
- return getpagesize();
-}
-
-void*
-js::jit::AllocateExecutableMemory(void* addr, size_t bytes, unsigned permissions, const char* tag,
- size_t pageSize)
-{
- MOZ_ASSERT(bytes % pageSize == 0);
- void* p = MozTaggedAnonymousMmap(addr, bytes, permissions, MAP_PRIVATE | MAP_ANON, -1, 0, tag);
- return p == MAP_FAILED ? nullptr : p;
-}
-
-void
-js::jit::DeallocateExecutableMemory(void* addr, size_t bytes, size_t pageSize)
-{
- MOZ_ASSERT(bytes % pageSize == 0);
- mozilla::DebugOnly<int> result = munmap(addr, bytes);
- MOZ_ASSERT(!result || errno == ENOMEM);
-}
-
-ExecutablePool::Allocation
-ExecutableAllocator::systemAlloc(size_t n)
-{
- void* allocation = AllocateExecutableMemory(nullptr, n, initialProtectionFlags(Executable),
- "js-jit-code", pageSize);
- ExecutablePool::Allocation alloc = { reinterpret_cast<char*>(allocation), n };
- return alloc;
-}
-
-void
-ExecutableAllocator::systemRelease(const ExecutablePool::Allocation& alloc)
-{
- DeallocateExecutableMemory(alloc.pages, alloc.size, pageSize);
-}
-
-static const unsigned FLAGS_RW = PROT_READ | PROT_WRITE;
-static const unsigned FLAGS_RX = PROT_READ | PROT_EXEC;
-
-void
-ExecutableAllocator::reprotectRegion(void* start, size_t size, ProtectionSetting setting)
-{
- MOZ_ASSERT(nonWritableJitCode);
- MOZ_ASSERT(pageSize);
-
- // Calculate the start of the page containing this region,
- // and account for this extra memory within size.
- intptr_t startPtr = reinterpret_cast<intptr_t>(start);
- intptr_t pageStartPtr = startPtr & ~(pageSize - 1);
- void* pageStart = reinterpret_cast<void*>(pageStartPtr);
- size += (startPtr - pageStartPtr);
-
- // Round size up
- size += (pageSize - 1);
- size &= ~(pageSize - 1);
-
- mprotect(pageStart, size, (setting == Writable) ? FLAGS_RW : FLAGS_RX);
-}
-
-/* static */ unsigned
-ExecutableAllocator::initialProtectionFlags(ProtectionSetting protection)
-{
- if (!nonWritableJitCode)
- return FLAGS_RW | FLAGS_RX;
-
- return (protection == Writable) ? FLAGS_RW : FLAGS_RX;
-}
diff --git a/src/third_party/mozjs-45/extract/js/src/jit/ExecutableAllocatorWin.cpp b/src/third_party/mozjs-45/extract/js/src/jit/ExecutableAllocatorWin.cpp
deleted file mode 100644
index fe068b90814..00000000000
--- a/src/third_party/mozjs-45/extract/js/src/jit/ExecutableAllocatorWin.cpp
+++ /dev/null
@@ -1,289 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=99:
- *
- * Copyright (C) 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "mozilla/WindowsVersion.h"
-
-#include "jsfriendapi.h"
-#include "jsmath.h"
-#include "jswin.h"
-
-#include "jit/ExecutableAllocator.h"
-
-using namespace js::jit;
-
-size_t
-ExecutableAllocator::determinePageSize()
-{
- SYSTEM_INFO system_info;
- GetSystemInfo(&system_info);
- return system_info.dwPageSize;
-}
-
-void*
-ExecutableAllocator::computeRandomAllocationAddress()
-{
- /*
- * Inspiration is V8's OS::Allocate in platform-win32.cc.
- *
- * VirtualAlloc takes 64K chunks out of the virtual address space, so we
- * keep 16b alignment.
- *
- * x86: V8 comments say that keeping addresses in the [64MiB, 1GiB) range
- * tries to avoid system default DLL mapping space. In the end, we get 13
- * bits of randomness in our selection.
- * x64: [2GiB, 4TiB), with 25 bits of randomness.
- */
-#ifdef JS_CPU_X64
- static const uintptr_t base = 0x0000000080000000;
- static const uintptr_t mask = 0x000003ffffff0000;
-#elif defined(JS_CPU_X86)
- static const uintptr_t base = 0x04000000;
- static const uintptr_t mask = 0x3fff0000;
-#else
-# error "Unsupported architecture"
-#endif
-
- if (randomNumberGenerator.isNothing()) {
- mozilla::Array<uint64_t, 2> seed;
- js::GenerateXorShift128PlusSeed(seed);
- randomNumberGenerator.emplace(seed[0], seed[1]);
- }
-
- uint64_t rand = randomNumberGenerator.ref().next();
- return (void*) (base | (rand & mask));
-}
-
-static bool
-RandomizeIsBrokenImpl()
-{
- // We disable everything before Vista, for now.
- return !mozilla::IsVistaOrLater();
-}
-
-static bool
-RandomizeIsBroken()
-{
- // Use the compiler's intrinsic guards for |static type value = expr| to avoid some potential
- // races if runtimes are created from multiple threads.
- static int result = RandomizeIsBrokenImpl();
- return !!result;
-}
-
-#ifdef JS_CPU_X64
-static js::JitExceptionHandler sJitExceptionHandler;
-
-JS_FRIEND_API(void)
-js::SetJitExceptionHandler(JitExceptionHandler handler)
-{
- MOZ_ASSERT(!sJitExceptionHandler);
- sJitExceptionHandler = handler;
-}
-
-// From documentation for UNWIND_INFO on
-// http://msdn.microsoft.com/en-us/library/ddssxxy8.aspx
-struct UnwindInfo
-{
- uint8_t version : 3;
- uint8_t flags : 5;
- uint8_t sizeOfPrologue;
- uint8_t countOfUnwindCodes;
- uint8_t frameRegister : 4;
- uint8_t frameOffset : 4;
- ULONG exceptionHandler;
-};
-
-static const unsigned ThunkLength = 12;
-
-struct ExceptionHandlerRecord
-{
- RUNTIME_FUNCTION runtimeFunction;
- UnwindInfo unwindInfo;
- uint8_t thunk[ThunkLength];
-};
-
-// This function must match the function pointer type PEXCEPTION_HANDLER
-// mentioned in:
-// http://msdn.microsoft.com/en-us/library/ssa62fwe.aspx.
-// This type is rather elusive in documentation; Wine is the best I've found:
-// http://source.winehq.org/source/include/winnt.h
-static DWORD
-ExceptionHandler(PEXCEPTION_RECORD exceptionRecord, _EXCEPTION_REGISTRATION_RECORD*,
- PCONTEXT context, _EXCEPTION_REGISTRATION_RECORD**)
-{
- return sJitExceptionHandler(exceptionRecord, context);
-}
-
-// For an explanation of the problem being solved here, see
-// SetJitExceptionFilter in jsfriendapi.h.
-static bool
-RegisterExecutableMemory(void* p, size_t bytes, size_t pageSize)
-{
- ExceptionHandlerRecord* r = reinterpret_cast<ExceptionHandlerRecord*>(p);
-
- // All these fields are specified to be offsets from the base of the
- // executable code (which is 'p'), even if they have 'Address' in their
- // names. In particular, exceptionHandler is a ULONG offset which is a
- // 32-bit integer. Since 'p' can be farther than INT32_MAX away from
- // sJitExceptionHandler, we must generate a little thunk inside the
- // record. The record is put on its own page so that we can take away write
- // access to protect against accidental clobbering.
-
- r->runtimeFunction.BeginAddress = pageSize;
- r->runtimeFunction.EndAddress = (DWORD)bytes;
- r->runtimeFunction.UnwindData = offsetof(ExceptionHandlerRecord, unwindInfo);
-
- r->unwindInfo.version = 1;
- r->unwindInfo.flags = UNW_FLAG_EHANDLER;
- r->unwindInfo.sizeOfPrologue = 0;
- r->unwindInfo.countOfUnwindCodes = 0;
- r->unwindInfo.frameRegister = 0;
- r->unwindInfo.frameOffset = 0;
- r->unwindInfo.exceptionHandler = offsetof(ExceptionHandlerRecord, thunk);
-
- // mov imm64, rax
- r->thunk[0] = 0x48;
- r->thunk[1] = 0xb8;
- void* handler = JS_FUNC_TO_DATA_PTR(void*, ExceptionHandler);
- memcpy(&r->thunk[2], &handler, 8);
-
- // jmp rax
- r->thunk[10] = 0xff;
- r->thunk[11] = 0xe0;
-
- DWORD oldProtect;
- if (!VirtualProtect(p, pageSize, PAGE_EXECUTE_READ, &oldProtect))
- return false;
-
- return RtlAddFunctionTable(&r->runtimeFunction, 1, reinterpret_cast<DWORD64>(p));
-}
-
-static void
-UnregisterExecutableMemory(void* p, size_t bytes, size_t pageSize)
-{
- ExceptionHandlerRecord* r = reinterpret_cast<ExceptionHandlerRecord*>(p);
- RtlDeleteFunctionTable(&r->runtimeFunction);
-}
-#endif
-
-void*
-js::jit::AllocateExecutableMemory(void* addr, size_t bytes, unsigned permissions, const char* tag,
- size_t pageSize)
-{
- MOZ_ASSERT(bytes % pageSize == 0);
-
-#ifdef JS_CPU_X64
- if (sJitExceptionHandler)
- bytes += pageSize;
-#endif
-
- void* p = VirtualAlloc(addr, bytes, MEM_COMMIT | MEM_RESERVE, permissions);
- if (!p)
- return nullptr;
-
-#ifdef JS_CPU_X64
- if (sJitExceptionHandler) {
- if (!RegisterExecutableMemory(p, bytes, pageSize)) {
- VirtualFree(p, 0, MEM_RELEASE);
- return nullptr;
- }
-
- p = (uint8_t*)p + pageSize;
- }
-#endif
-
- return p;
-}
-
-void
-js::jit::DeallocateExecutableMemory(void* addr, size_t bytes, size_t pageSize)
-{
- MOZ_ASSERT(bytes % pageSize == 0);
-
-#ifdef JS_CPU_X64
- if (sJitExceptionHandler) {
- addr = (uint8_t*)addr - pageSize;
- UnregisterExecutableMemory(addr, bytes, pageSize);
- }
-#endif
-
- VirtualFree(addr, 0, MEM_RELEASE);
-}
-
-ExecutablePool::Allocation
-ExecutableAllocator::systemAlloc(size_t n)
-{
- void* allocation = nullptr;
- if (!RandomizeIsBroken()) {
- void* randomAddress = computeRandomAllocationAddress();
- allocation = AllocateExecutableMemory(randomAddress, n, initialProtectionFlags(Executable),
- "js-jit-code", pageSize);
- }
- if (!allocation) {
- allocation = AllocateExecutableMemory(nullptr, n, initialProtectionFlags(Executable),
- "js-jit-code", pageSize);
- }
- ExecutablePool::Allocation alloc = { reinterpret_cast<char*>(allocation), n };
- return alloc;
-}
-
-void
-ExecutableAllocator::systemRelease(const ExecutablePool::Allocation& alloc)
-{
- DeallocateExecutableMemory(alloc.pages, alloc.size, pageSize);
-}
-
-void
-ExecutableAllocator::reprotectRegion(void* start, size_t size, ProtectionSetting setting)
-{
- MOZ_ASSERT(nonWritableJitCode);
- MOZ_ASSERT(pageSize);
-
- // Calculate the start of the page containing this region,
- // and account for this extra memory within size.
- intptr_t startPtr = reinterpret_cast<intptr_t>(start);
- intptr_t pageStartPtr = startPtr & ~(pageSize - 1);
- void* pageStart = reinterpret_cast<void*>(pageStartPtr);
- size += (startPtr - pageStartPtr);
-
- // Round size up
- size += (pageSize - 1);
- size &= ~(pageSize - 1);
-
- DWORD oldProtect;
- int flags = (setting == Writable) ? PAGE_READWRITE : PAGE_EXECUTE_READ;
- if (!VirtualProtect(pageStart, size, flags, &oldProtect))
- MOZ_CRASH();
-}
-
-/* static */ unsigned
-ExecutableAllocator::initialProtectionFlags(ProtectionSetting protection)
-{
- if (!nonWritableJitCode)
- return PAGE_EXECUTE_READWRITE;
-
- return (protection == Writable) ? PAGE_READWRITE : PAGE_EXECUTE_READ;
-}
diff --git a/src/third_party/mozjs-45/extract/js/src/jit/Ion.cpp b/src/third_party/mozjs-45/extract/js/src/jit/Ion.cpp
index 93d96c257c0..f47a413fc68 100644
--- a/src/third_party/mozjs-45/extract/js/src/jit/Ion.cpp
+++ b/src/third_party/mozjs-45/extract/js/src/jit/Ion.cpp
@@ -722,13 +722,14 @@ JitCompartment::sweep(FreeOp* fop, JSCompartment* compartment)
if (!stubCodes_->lookup(ICSetProp_Fallback::Compiler::BASELINE_KEY))
baselineSetPropReturnAddr_ = nullptr;
- if (stringConcatStub_ && !IsMarkedUnbarriered(&stringConcatStub_))
+ JSRuntime* rt = fop->runtime();
+ if (stringConcatStub_ && !IsMarkedUnbarriered(rt, &stringConcatStub_))
stringConcatStub_ = nullptr;
- if (regExpExecStub_ && !IsMarkedUnbarriered(&regExpExecStub_))
+ if (regExpExecStub_ && !IsMarkedUnbarriered(rt, &regExpExecStub_))
regExpExecStub_ = nullptr;
- if (regExpTestStub_ && !IsMarkedUnbarriered(&regExpTestStub_))
+ if (regExpTestStub_ && !IsMarkedUnbarriered(rt, &regExpTestStub_))
regExpTestStub_ = nullptr;
for (size_t i = 0; i <= SimdTypeDescr::LAST_TYPE; i++) {
@@ -2413,6 +2414,11 @@ Compile(JSContext* cx, HandleScript script, BaselineFrame* osrFrame, jsbytecode*
if (optimizationLevel == Optimization_DontCompile)
return Method_Skipped;
+ if (!CanLikelyAllocateMoreExecutableMemory()) {
+ script->resetWarmUpCounter();
+ return Method_Skipped;
+ }
+
if (script->hasIonScript()) {
IonScript* scriptIon = script->ionScript();
if (!scriptIon->method())
diff --git a/src/third_party/mozjs-45/extract/js/src/jit/IonAnalysis.cpp b/src/third_party/mozjs-45/extract/js/src/jit/IonAnalysis.cpp
index 0dd337c2ecb..8a41afc51eb 100644
--- a/src/third_party/mozjs-45/extract/js/src/jit/IonAnalysis.cpp
+++ b/src/third_party/mozjs-45/extract/js/src/jit/IonAnalysis.cpp
@@ -3673,6 +3673,9 @@ jit::AnalyzeNewScriptDefiniteProperties(JSContext* cx, JSFunction* fun,
TempAllocator temp(&alloc);
JitContext jctx(cx, &temp);
+ if (!jit::CanLikelyAllocateMoreExecutableMemory())
+ return true;
+
if (!cx->compartment()->ensureJitCompartmentExists(cx))
return false;
@@ -3902,6 +3905,9 @@ jit::AnalyzeArgumentsUsage(JSContext* cx, JSScript* scriptArg)
TempAllocator temp(&alloc);
JitContext jctx(cx, &temp);
+ if (!jit::CanLikelyAllocateMoreExecutableMemory())
+ return true;
+
if (!cx->compartment()->ensureJitCompartmentExists(cx))
return false;
diff --git a/src/third_party/mozjs-45/extract/js/src/jit/IonBuilder.cpp b/src/third_party/mozjs-45/extract/js/src/jit/IonBuilder.cpp
index 3efc6bb0c11..9e70e244889 100644
--- a/src/third_party/mozjs-45/extract/js/src/jit/IonBuilder.cpp
+++ b/src/third_party/mozjs-45/extract/js/src/jit/IonBuilder.cpp
@@ -1235,9 +1235,11 @@ IonBuilder::initScopeChain(MDefinition* callee)
current->add(scope);
// This reproduce what is done in CallObject::createForFunction. Skip
- // this for analyses, as the script might not have a baseline script
- // with template objects yet.
- if (fun->needsCallObject() && !info().isAnalysis()) {
+ // this for the arguments analysis, as the script might not have a
+ // baseline script with template objects yet.
+ if (fun->needsCallObject() &&
+ info().analysisMode() != Analysis_ArgumentsUsage)
+ {
if (fun->isNamedLambda()) {
scope = createDeclEnvObject(callee, scope);
if (!scope)
@@ -6135,6 +6137,9 @@ IonBuilder::getSingletonPrototype(JSFunction* target)
MDefinition*
IonBuilder::createThisScriptedSingleton(JSFunction* target, MDefinition* callee)
{
+ if (!target->hasScript())
+ return nullptr;
+
// Get the singleton prototype (if exists)
JSObject* proto = getSingletonPrototype(target);
if (!proto)
diff --git a/src/third_party/mozjs-45/extract/js/src/jit/IonCaches.cpp b/src/third_party/mozjs-45/extract/js/src/jit/IonCaches.cpp
index b5fe6dec072..56437abf613 100644
--- a/src/third_party/mozjs-45/extract/js/src/jit/IonCaches.cpp
+++ b/src/third_party/mozjs-45/extract/js/src/jit/IonCaches.cpp
@@ -2418,9 +2418,20 @@ IsCacheableSetPropCallNative(HandleObject obj, HandleObject holder, HandleShape
if (!shape || !IsCacheableProtoChainForIon(obj, holder))
return false;
- return shape->hasSetterValue() && shape->setterObject() &&
- shape->setterObject()->is<JSFunction>() &&
- shape->setterObject()->as<JSFunction>().isNative();
+ if (!shape->hasSetterValue())
+ return false;
+
+ if (!shape->setterObject() || !shape->setterObject()->is<JSFunction>())
+ return false;
+
+ JSFunction& setter = shape->setterObject()->as<JSFunction>();
+ if (!setter.isNative())
+ return false;
+
+ if (setter.jitInfo() && !setter.jitInfo()->needsOuterizedThisObject())
+ return true;
+
+ return !IsWindow(obj);
}
static bool
@@ -2429,6 +2440,9 @@ IsCacheableSetPropCallScripted(HandleObject obj, HandleObject holder, HandleShap
if (!shape || !IsCacheableProtoChainForIon(obj, holder))
return false;
+ if (IsWindow(obj))
+ return false;
+
return shape->hasSetterValue() && shape->setterObject() &&
shape->setterObject()->is<JSFunction>() &&
shape->setterObject()->as<JSFunction>().hasJITCode();
diff --git a/src/third_party/mozjs-45/extract/js/src/jit/IonCode.h b/src/third_party/mozjs-45/extract/js/src/jit/IonCode.h
index 085a9076c33..8156b9cb8f6 100644
--- a/src/third_party/mozjs-45/extract/js/src/jit/IonCode.h
+++ b/src/third_party/mozjs-45/extract/js/src/jit/IonCode.h
@@ -767,7 +767,7 @@ struct AutoFlushICache
namespace gc {
inline bool
-IsMarked(const jit::VMFunction*)
+IsMarked(JSRuntime* rt, const jit::VMFunction*)
{
// VMFunction are only static objects which are used by WeakMaps as keys.
// It is considered as a root object which is always marked.
diff --git a/src/third_party/mozjs-45/extract/js/src/jit/JitcodeMap.cpp b/src/third_party/mozjs-45/extract/js/src/jit/JitcodeMap.cpp
index 7f6a06120d2..e8cba8e63a4 100644
--- a/src/third_party/mozjs-45/extract/js/src/jit/JitcodeMap.cpp
+++ b/src/third_party/mozjs-45/extract/js/src/jit/JitcodeMap.cpp
@@ -756,7 +756,7 @@ JitcodeGlobalTable::setAllEntriesAsExpired(JSRuntime* rt)
struct Unconditionally
{
template <typename T>
- static bool ShouldMark(T* thingp) { return true; }
+ static bool ShouldMark(JSRuntime* rt, T* thingp) { return true; }
};
void
@@ -775,13 +775,13 @@ JitcodeGlobalTable::markUnconditionally(JSTracer* trc)
struct IfUnmarked
{
template <typename T>
- static bool ShouldMark(T* thingp) { return !IsMarkedUnbarriered(thingp); }
+ static bool ShouldMark(JSRuntime* rt, T* thingp) { return !IsMarkedUnbarriered(rt, thingp); }
};
template <>
-bool IfUnmarked::ShouldMark<TypeSet::Type>(TypeSet::Type* type)
+bool IfUnmarked::ShouldMark<TypeSet::Type>(JSRuntime* rt, TypeSet::Type* type)
{
- return !TypeSet::IsTypeMarked(type);
+ return !TypeSet::IsTypeMarked(rt, type);
}
bool
@@ -832,7 +832,7 @@ JitcodeGlobalTable::markIteratively(JSTracer* trc)
// mapping, alive as well.
if (!entry->isSampled(gen, lapCount)) {
entry->setAsExpired();
- if (!entry->baseEntry().isJitcodeMarkedFromAnyThread())
+ if (!entry->baseEntry().isJitcodeMarkedFromAnyThread(trc->runtime()))
continue;
}
@@ -868,7 +868,7 @@ template <class ShouldMarkProvider>
bool
JitcodeGlobalEntry::BaseEntry::markJitcode(JSTracer* trc)
{
- if (ShouldMarkProvider::ShouldMark(&jitcode_)) {
+ if (ShouldMarkProvider::ShouldMark(trc->runtime(), &jitcode_)) {
TraceManuallyBarrieredEdge(trc, &jitcode_, "jitcodglobaltable-baseentry-jitcode");
return true;
}
@@ -876,9 +876,9 @@ JitcodeGlobalEntry::BaseEntry::markJitcode(JSTracer* trc)
}
bool
-JitcodeGlobalEntry::BaseEntry::isJitcodeMarkedFromAnyThread()
+JitcodeGlobalEntry::BaseEntry::isJitcodeMarkedFromAnyThread(JSRuntime* rt)
{
- return IsMarkedUnbarriered(&jitcode_) ||
+ return IsMarkedUnbarriered(rt, &jitcode_) ||
jitcode_->arenaHeader()->allocatedDuringIncremental;
}
@@ -892,7 +892,7 @@ template <class ShouldMarkProvider>
bool
JitcodeGlobalEntry::BaselineEntry::mark(JSTracer* trc)
{
- if (ShouldMarkProvider::ShouldMark(&script_)) {
+ if (ShouldMarkProvider::ShouldMark(trc->runtime(), &script_)) {
TraceManuallyBarrieredEdge(trc, &script_, "jitcodeglobaltable-baselineentry-script");
return true;
}
@@ -906,9 +906,9 @@ JitcodeGlobalEntry::BaselineEntry::sweepChildren()
}
bool
-JitcodeGlobalEntry::BaselineEntry::isMarkedFromAnyThread()
+JitcodeGlobalEntry::BaselineEntry::isMarkedFromAnyThread(JSRuntime* rt)
{
- return IsMarkedUnbarriered(&script_) ||
+ return IsMarkedUnbarriered(rt, &script_) ||
script_->arenaHeader()->allocatedDuringIncremental;
}
@@ -918,8 +918,9 @@ JitcodeGlobalEntry::IonEntry::mark(JSTracer* trc)
{
bool markedAny = false;
+ JSRuntime* rt = trc->runtime();
for (unsigned i = 0; i < numScripts(); i++) {
- if (ShouldMarkProvider::ShouldMark(&sizedScriptList()->pairs[i].script)) {
+ if (ShouldMarkProvider::ShouldMark(rt, &sizedScriptList()->pairs[i].script)) {
TraceManuallyBarrieredEdge(trc, &sizedScriptList()->pairs[i].script,
"jitcodeglobaltable-ionentry-script");
markedAny = true;
@@ -932,15 +933,15 @@ JitcodeGlobalEntry::IonEntry::mark(JSTracer* trc)
for (IonTrackedTypeWithAddendum* iter = optsAllTypes_->begin();
iter != optsAllTypes_->end(); iter++)
{
- if (ShouldMarkProvider::ShouldMark(&iter->type)) {
+ if (ShouldMarkProvider::ShouldMark(rt, &iter->type)) {
TypeSet::MarkTypeUnbarriered(trc, &iter->type, "jitcodeglobaltable-ionentry-type");
markedAny = true;
}
- if (iter->hasAllocationSite() && ShouldMarkProvider::ShouldMark(&iter->script)) {
+ if (iter->hasAllocationSite() && ShouldMarkProvider::ShouldMark(rt, &iter->script)) {
TraceManuallyBarrieredEdge(trc, &iter->script,
"jitcodeglobaltable-ionentry-type-addendum-script");
markedAny = true;
- } else if (iter->hasConstructor() && ShouldMarkProvider::ShouldMark(&iter->constructor)) {
+ } else if (iter->hasConstructor() && ShouldMarkProvider::ShouldMark(rt, &iter->constructor)) {
TraceManuallyBarrieredEdge(trc, &iter->constructor,
"jitcodeglobaltable-ionentry-type-addendum-constructor");
markedAny = true;
@@ -973,10 +974,10 @@ JitcodeGlobalEntry::IonEntry::sweepChildren()
}
bool
-JitcodeGlobalEntry::IonEntry::isMarkedFromAnyThread()
+JitcodeGlobalEntry::IonEntry::isMarkedFromAnyThread(JSRuntime* rt)
{
for (unsigned i = 0; i < numScripts(); i++) {
- if (!IsMarkedUnbarriered(&sizedScriptList()->pairs[i].script) &&
+ if (!IsMarkedUnbarriered(rt, &sizedScriptList()->pairs[i].script) &&
!sizedScriptList()->pairs[i].script->arenaHeader()->allocatedDuringIncremental)
{
return false;
@@ -989,7 +990,7 @@ JitcodeGlobalEntry::IonEntry::isMarkedFromAnyThread()
for (IonTrackedTypeWithAddendum* iter = optsAllTypes_->begin();
iter != optsAllTypes_->end(); iter++)
{
- if (!TypeSet::IsTypeMarked(&iter->type) &&
+ if (!TypeSet::IsTypeMarked(rt, &iter->type) &&
!TypeSet::IsTypeAllocatedDuringIncremental(iter->type))
{
return false;
diff --git a/src/third_party/mozjs-45/extract/js/src/jit/JitcodeMap.h b/src/third_party/mozjs-45/extract/js/src/jit/JitcodeMap.h
index 01c475adecb..e11126321d3 100644
--- a/src/third_party/mozjs-45/extract/js/src/jit/JitcodeMap.h
+++ b/src/third_party/mozjs-45/extract/js/src/jit/JitcodeMap.h
@@ -208,7 +208,7 @@ class JitcodeGlobalEntry
}
template <class ShouldMarkProvider> bool markJitcode(JSTracer* trc);
- bool isJitcodeMarkedFromAnyThread();
+ bool isJitcodeMarkedFromAnyThread(JSRuntime* rt);
bool isJitcodeAboutToBeFinalized();
};
@@ -370,7 +370,7 @@ class JitcodeGlobalEntry
template <class ShouldMarkProvider> bool mark(JSTracer* trc);
void sweepChildren();
- bool isMarkedFromAnyThread();
+ bool isMarkedFromAnyThread(JSRuntime* rt);
};
struct BaselineEntry : public BaseEntry
@@ -428,7 +428,7 @@ class JitcodeGlobalEntry
template <class ShouldMarkProvider> bool mark(JSTracer* trc);
void sweepChildren();
- bool isMarkedFromAnyThread();
+ bool isMarkedFromAnyThread(JSRuntime* rt);
};
struct IonCacheEntry : public BaseEntry
@@ -949,13 +949,13 @@ class JitcodeGlobalEntry
}
bool isMarkedFromAnyThread(JSRuntime* rt) {
- if (!baseEntry().isJitcodeMarkedFromAnyThread())
+ if (!baseEntry().isJitcodeMarkedFromAnyThread(rt))
return false;
switch (kind()) {
case Ion:
- return ionEntry().isMarkedFromAnyThread();
+ return ionEntry().isMarkedFromAnyThread(rt);
case Baseline:
- return baselineEntry().isMarkedFromAnyThread();
+ return baselineEntry().isMarkedFromAnyThread(rt);
case IonCache:
return ionCacheEntry().isMarkedFromAnyThread(rt);
case Dummy:
diff --git a/src/third_party/mozjs-45/extract/js/src/jit/Lowering.cpp b/src/third_party/mozjs-45/extract/js/src/jit/Lowering.cpp
index 64f86f38f22..f1fc578f207 100644
--- a/src/third_party/mozjs-45/extract/js/src/jit/Lowering.cpp
+++ b/src/third_party/mozjs-45/extract/js/src/jit/Lowering.cpp
@@ -2310,9 +2310,7 @@ LIRGenerator::visitInterruptCheck(MInterruptCheck* ins)
// is complicated because there could be another AutoWritableJitCode on the
// stack.
LInstructionHelper<0, 0, 0>* lir;
- if (GetJitContext()->runtime->canUseSignalHandlers() &&
- !ExecutableAllocator::nonWritableJitCode)
- {
+ if (GetJitContext()->runtime->canUseSignalHandlers()) {
lir = new(alloc()) LInterruptCheckImplicit();
} else {
lir = new(alloc()) LInterruptCheck();
diff --git a/src/third_party/mozjs-45/extract/js/src/jit/ProcessExecutableMemory.cpp b/src/third_party/mozjs-45/extract/js/src/jit/ProcessExecutableMemory.cpp
new file mode 100644
index 00000000000..7e05dfc84f1
--- /dev/null
+++ b/src/third_party/mozjs-45/extract/js/src/jit/ProcessExecutableMemory.cpp
@@ -0,0 +1,614 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "jit/ProcessExecutableMemory.h"
+
+#include "mozilla/Array.h"
+#include "mozilla/Atomics.h"
+#include "mozilla/DebugOnly.h"
+#include "mozilla/Maybe.h"
+#include "mozilla/TaggedAnonymousMemory.h"
+#include "mozilla/XorShift128PlusRNG.h"
+
+#include "jsfriendapi.h"
+#include "jslock.h"
+#include "jsmath.h"
+#include "jsutil.h"
+#include "jswin.h"
+
+#include <errno.h>
+
+#include "gc/Memory.h"
+
+#ifdef XP_WIN
+# include "mozilla/WindowsVersion.h"
+#else
+# include <sys/mman.h>
+# include <unistd.h>
+#endif
+
+using namespace js;
+using namespace js::jit;
+
+#ifdef XP_WIN
+static void*
+ComputeRandomAllocationAddress()
+{
+ /*
+ * Inspiration is V8's OS::Allocate in platform-win32.cc.
+ *
+ * VirtualAlloc takes 64K chunks out of the virtual address space, so we
+ * keep 16b alignment.
+ *
+ * x86: V8 comments say that keeping addresses in the [64MiB, 1GiB) range
+ * tries to avoid system default DLL mapping space. In the end, we get 13
+ * bits of randomness in our selection.
+ * x64: [2GiB, 4TiB), with 25 bits of randomness.
+ */
+# ifdef HAVE_64BIT_BUILD
+ static const uintptr_t base = 0x0000000080000000;
+ static const uintptr_t mask = 0x000003ffffff0000;
+# elif defined(_M_IX86) || defined(__i386__)
+ static const uintptr_t base = 0x04000000;
+ static const uintptr_t mask = 0x3fff0000;
+# else
+# error "Unsupported architecture"
+# endif
+
+ uint64_t rand = js::GenerateRandomSeed();
+ return (void*) (base | (rand & mask));
+}
+
+# ifdef HAVE_64BIT_BUILD
+static js::JitExceptionHandler sJitExceptionHandler;
+
+JS_FRIEND_API(void)
+js::SetJitExceptionHandler(JitExceptionHandler handler)
+{
+ MOZ_ASSERT(!sJitExceptionHandler);
+ sJitExceptionHandler = handler;
+}
+
+// From documentation for UNWIND_INFO on
+// http://msdn.microsoft.com/en-us/library/ddssxxy8.aspx
+struct UnwindInfo
+{
+ uint8_t version : 3;
+ uint8_t flags : 5;
+ uint8_t sizeOfPrologue;
+ uint8_t countOfUnwindCodes;
+ uint8_t frameRegister : 4;
+ uint8_t frameOffset : 4;
+ ULONG exceptionHandler;
+};
+
+static const unsigned ThunkLength = 12;
+
+struct ExceptionHandlerRecord
+{
+ RUNTIME_FUNCTION runtimeFunction;
+ UnwindInfo unwindInfo;
+ uint8_t thunk[ThunkLength];
+};
+
+// This function must match the function pointer type PEXCEPTION_HANDLER
+// mentioned in:
+// http://msdn.microsoft.com/en-us/library/ssa62fwe.aspx.
+// This type is rather elusive in documentation; Wine is the best I've found:
+// http://source.winehq.org/source/include/winnt.h
+static DWORD
+ExceptionHandler(PEXCEPTION_RECORD exceptionRecord, _EXCEPTION_REGISTRATION_RECORD*,
+ PCONTEXT context, _EXCEPTION_REGISTRATION_RECORD**)
+{
+ return sJitExceptionHandler(exceptionRecord, context);
+}
+
+// For an explanation of the problem being solved here, see
+// SetJitExceptionFilter in jsfriendapi.h.
+static bool
+RegisterExecutableMemory(void* p, size_t bytes, size_t pageSize)
+{
+ if (!VirtualAlloc(p, pageSize, MEM_COMMIT, PAGE_READWRITE))
+ MOZ_CRASH();
+
+ ExceptionHandlerRecord* r = reinterpret_cast<ExceptionHandlerRecord*>(p);
+
+ // All these fields are specified to be offsets from the base of the
+ // executable code (which is 'p'), even if they have 'Address' in their
+ // names. In particular, exceptionHandler is a ULONG offset which is a
+ // 32-bit integer. Since 'p' can be farther than INT32_MAX away from
+ // sJitExceptionHandler, we must generate a little thunk inside the
+ // record. The record is put on its own page so that we can take away write
+ // access to protect against accidental clobbering.
+
+ r->runtimeFunction.BeginAddress = pageSize;
+ r->runtimeFunction.EndAddress = (DWORD)bytes;
+ r->runtimeFunction.UnwindData = offsetof(ExceptionHandlerRecord, unwindInfo);
+
+ r->unwindInfo.version = 1;
+ r->unwindInfo.flags = UNW_FLAG_EHANDLER;
+ r->unwindInfo.sizeOfPrologue = 0;
+ r->unwindInfo.countOfUnwindCodes = 0;
+ r->unwindInfo.frameRegister = 0;
+ r->unwindInfo.frameOffset = 0;
+ r->unwindInfo.exceptionHandler = offsetof(ExceptionHandlerRecord, thunk);
+
+ // mov imm64, rax
+ r->thunk[0] = 0x48;
+ r->thunk[1] = 0xb8;
+ void* handler = JS_FUNC_TO_DATA_PTR(void*, ExceptionHandler);
+ memcpy(&r->thunk[2], &handler, 8);
+
+ // jmp rax
+ r->thunk[10] = 0xff;
+ r->thunk[11] = 0xe0;
+
+ DWORD oldProtect;
+ if (!VirtualProtect(p, pageSize, PAGE_EXECUTE_READ, &oldProtect))
+ MOZ_CRASH();
+
+ bool success = RtlAddFunctionTable(&r->runtimeFunction, 1, reinterpret_cast<DWORD64>(p));
+
+ return success;
+}
+
+static void
+UnregisterExecutableMemory(void* p, size_t bytes, size_t pageSize)
+{
+ ExceptionHandlerRecord* r = reinterpret_cast<ExceptionHandlerRecord*>(p);
+
+ RtlDeleteFunctionTable(&r->runtimeFunction);
+}
+# endif
+
+static void*
+ReserveProcessExecutableMemory(size_t bytes)
+{
+# ifdef HAVE_64BIT_BUILD
+ size_t pageSize = gc::SystemPageSize();
+ if (sJitExceptionHandler)
+ bytes += pageSize;
+# endif
+
+ void* p = nullptr;
+ for (size_t i = 0; i < 10; i++) {
+ void* randomAddr = ComputeRandomAllocationAddress();
+ p = VirtualAlloc(randomAddr, bytes, MEM_RESERVE, PAGE_NOACCESS);
+ if (p)
+ break;
+ }
+
+ if (!p) {
+ // Try again without randomization.
+ p = VirtualAlloc(nullptr, bytes, MEM_RESERVE, PAGE_NOACCESS);
+ if (!p)
+ return nullptr;
+ }
+
+# ifdef HAVE_64BIT_BUILD
+ if (sJitExceptionHandler) {
+ if (!RegisterExecutableMemory(p, bytes, pageSize)) {
+ VirtualFree(p, 0, MEM_RELEASE);
+ return nullptr;
+ }
+
+ p = (uint8_t*)p + pageSize;
+ }
+# endif
+
+ return p;
+}
+
+static void
+DeallocateProcessExecutableMemory(void* addr, size_t bytes)
+{
+# ifdef HAVE_64BIT_BUILD
+ if (sJitExceptionHandler) {
+ size_t pageSize = gc::SystemPageSize();
+ addr = (uint8_t*)addr - pageSize;
+ UnregisterExecutableMemory(addr, bytes, pageSize);
+ }
+# endif
+
+ VirtualFree(addr, 0, MEM_RELEASE);
+}
+
+static DWORD
+ProtectionSettingToFlags(ProtectionSetting protection)
+{
+ return PAGE_EXECUTE_READWRITE;
+}
+
+static void
+CommitPages(void* addr, size_t bytes, ProtectionSetting protection)
+{
+ if (!VirtualAlloc(addr, bytes, MEM_COMMIT, ProtectionSettingToFlags(protection)))
+ MOZ_CRASH("CommitPages failed");
+}
+
+static void
+DecommitPages(void* addr, size_t bytes)
+{
+ if (!VirtualFree(addr, bytes, MEM_DECOMMIT))
+ MOZ_CRASH("DecommitPages failed");
+}
+#else // !XP_WIN
+static void*
+ComputeRandomAllocationAddress()
+{
+ uint64_t rand = js::GenerateRandomSeed();
+
+# ifdef HAVE_64BIT_BUILD
+ // x64 CPUs have a 48-bit address space and on some platforms the OS will
+ // give us access to 47 bits, so to be safe we right shift by 18 to leave
+ // 46 bits.
+ rand >>= 18;
+# else
+ // On 32-bit, right shift by 34 to leave 30 bits, range [0, 1GiB). Then add
+ // 512MiB to get range [512MiB, 1.5GiB), or [0x20000000, 0x60000000). This
+ // is based on V8 comments in platform-posix.cc saying this range is
+ // relatively unpopulated across a variety of kernels.
+ rand >>= 34;
+ rand += 512 * 1024 * 1024;
+# endif
+
+ // Ensure page alignment.
+ uintptr_t mask = ~uintptr_t(gc::SystemPageSize() - 1);
+ return (void*) uintptr_t(rand & mask);
+}
+
+static void*
+ReserveProcessExecutableMemory(size_t bytes)
+{
+ // Note that randomAddr is just a hint: if the address is not available
+ // mmap will pick a different address.
+ void* randomAddr = ComputeRandomAllocationAddress();
+#ifdef SOLARIS
+ // Do not reserve swap space for the entire allocation. Regardless of what mmap(2) says,
+ // Solaris reserves swap space even though this allocation is not marked as writable.
+ void* p = MozTaggedAnonymousMmap(randomAddr, bytes, PROT_NONE, MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
+ -1, 0, "js-executable-memory");
+#else
+ void* p = MozTaggedAnonymousMmap(randomAddr, bytes, PROT_NONE, MAP_PRIVATE | MAP_ANON,
+ -1, 0, "js-executable-memory");
+#endif
+ if (p == MAP_FAILED)
+ return nullptr;
+ return p;
+}
+
+static void
+DeallocateProcessExecutableMemory(void* addr, size_t bytes)
+{
+ mozilla::DebugOnly<int> result = munmap(addr, bytes);
+ MOZ_ASSERT(!result || errno == ENOMEM);
+}
+
+static unsigned
+ProtectionSettingToFlags(ProtectionSetting protection)
+{
+ return PROT_READ | PROT_WRITE | PROT_EXEC;
+}
+
+static void
+CommitPages(void* addr, size_t bytes, ProtectionSetting protection)
+{
+ void* p = MozTaggedAnonymousMmap(addr, bytes, ProtectionSettingToFlags(protection),
+ MAP_FIXED | MAP_PRIVATE | MAP_ANON,
+ -1, 0, "js-executable-memory");
+ MOZ_RELEASE_ASSERT(addr == p);
+}
+
+static void
+DecommitPages(void* addr, size_t bytes)
+{
+ // Use mmap with MAP_FIXED and PROT_NONE. Inspired by jemalloc's
+ // pages_decommit.
+ void* p = MozTaggedAnonymousMmap(addr, bytes, PROT_NONE,
+ MAP_FIXED | MAP_PRIVATE | MAP_ANON,
+ -1, 0, "js-executable-memory");
+ MOZ_RELEASE_ASSERT(addr == p);
+}
+#endif
+
+template <size_t NumBits>
+class PageBitSet
+{
+ using WordType = uint32_t;
+ static const size_t BitsPerWord = sizeof(WordType) * 8;
+
+ static_assert((NumBits % BitsPerWord) == 0,
+ "NumBits must be a multiple of BitsPerWord");
+ static const size_t NumWords = NumBits / BitsPerWord;
+
+ mozilla::Array<WordType, NumWords> words_;
+
+ uint32_t indexToWord(uint32_t index) const {
+ MOZ_ASSERT(index < NumBits);
+ return index / BitsPerWord;
+ }
+ WordType indexToBit(uint32_t index) const {
+ MOZ_ASSERT(index < NumBits);
+ return WordType(1) << (index % BitsPerWord);
+ }
+
+ public:
+ void init() {
+ mozilla::PodArrayZero(words_);
+ }
+ bool contains(size_t index) const {
+ uint32_t word = indexToWord(index);
+ return words_[word] & indexToBit(index);
+ }
+ void insert(size_t index) {
+ MOZ_ASSERT(!contains(index));
+ uint32_t word = indexToWord(index);
+ words_[word] |= indexToBit(index);
+ }
+ void remove(size_t index) {
+ MOZ_ASSERT(contains(index));
+ uint32_t word = indexToWord(index);
+ words_[word] &= ~indexToBit(index);
+ }
+
+#ifdef DEBUG
+ bool empty() const {
+ for (size_t i = 0; i < NumWords; i++) {
+ if (words_[i] != 0)
+ return false;
+ }
+ return true;
+ }
+#endif
+};
+
+// Limit on the number of bytes of executable memory to prevent JIT spraying
+// attacks.
+#if JS_BITS_PER_WORD == 32
+static const size_t MaxCodeBytesPerProcess = 128 * 1024 * 1024;
+#else
+static const size_t MaxCodeBytesPerProcess = 640 * 1024 * 1024;
+#endif
+
+// Per-process executable memory allocator. It reserves a block of memory of
+// MaxCodeBytesPerProcess bytes, then allocates/deallocates pages from that.
+//
+// This has a number of benefits compared to raw mmap/VirtualAlloc:
+//
+// * More resillient against certain attacks.
+//
+// * Behaves more consistently across platforms: it avoids the 64K granularity
+// issues on Windows, for instance.
+//
+// * On x64, near jumps can be used for jumps to other JIT pages.
+//
+// * On Win64, we have to register the exception handler only once (at process
+// startup). This saves some memory and avoids RtlAddFunctionTable profiler
+// deadlocks.
+class ProcessExecutableMemory
+{
+ static_assert((MaxCodeBytesPerProcess % ExecutableCodePageSize) == 0,
+ "MaxCodeBytesPerProcess must be a multiple of ExecutableCodePageSize");
+ static const size_t MaxCodePages = MaxCodeBytesPerProcess / ExecutableCodePageSize;
+
+ // Start of the MaxCodeBytesPerProcess memory block or nullptr if
+ // uninitialized. Note that this is NOT guaranteed to be aligned to
+ // ExecutableCodePageSize.
+ uint8_t* base_;
+
+ // The fields below should only be accessed while we hold the lock.
+ PRLock* lock_;
+
+ // pagesAllocated_ is an Atomic so that bytesAllocated does not have to
+ // take the lock.
+ mozilla::Atomic<size_t, mozilla::ReleaseAcquire> pagesAllocated_;
+
+ // Page where we should try to allocate next.
+ size_t cursor_;
+
+ mozilla::Maybe<mozilla::non_crypto::XorShift128PlusRNG> rng_;
+ PageBitSet<MaxCodePages> pages_;
+
+ public:
+ ProcessExecutableMemory()
+ : base_(nullptr),
+ lock_(nullptr),
+ pagesAllocated_(0),
+ cursor_(0),
+ rng_(),
+ pages_()
+ {}
+
+ MOZ_MUST_USE bool init() {
+ pages_.init();
+
+ MOZ_RELEASE_ASSERT(!initialized());
+ MOZ_RELEASE_ASSERT(gc::SystemPageSize() <= ExecutableCodePageSize);
+
+ lock_ = PR_NewLock();
+ if (!lock_)
+ return false;
+
+ void* p = ReserveProcessExecutableMemory(MaxCodeBytesPerProcess);
+ if (!p)
+ return false;
+
+ base_ = static_cast<uint8_t*>(p);
+
+ mozilla::Array<uint64_t, 2> seed;
+ GenerateXorShift128PlusSeed(seed);
+ rng_.emplace(seed[0], seed[1]);
+ return true;
+ }
+
+ bool initialized() const {
+ return base_ != nullptr;
+ }
+
+ size_t bytesAllocated() const {
+ MOZ_ASSERT(pagesAllocated_ <= MaxCodePages);
+ return pagesAllocated_ * ExecutableCodePageSize;
+ }
+
+ void release() {
+ MOZ_ASSERT(initialized());
+ MOZ_ASSERT(pages_.empty());
+ MOZ_ASSERT(pagesAllocated_ == 0);
+ DeallocateProcessExecutableMemory(base_, MaxCodeBytesPerProcess);
+ base_ = nullptr;
+ rng_.reset();
+ MOZ_ASSERT(lock_);
+ PR_DestroyLock(lock_);
+ lock_ = nullptr;
+ MOZ_ASSERT(!initialized());
+ }
+
+ void assertValidAddress(void* p, size_t bytes) const {
+ MOZ_RELEASE_ASSERT(p >= base_ &&
+ uintptr_t(p) + bytes <= uintptr_t(base_) + MaxCodeBytesPerProcess);
+ }
+
+ void* allocate(size_t bytes, ProtectionSetting protection);
+ void deallocate(void* addr, size_t bytes);
+};
+
+void*
+ProcessExecutableMemory::allocate(size_t bytes, ProtectionSetting protection)
+{
+ MOZ_ASSERT(initialized());
+ MOZ_ASSERT(bytes > 0);
+ MOZ_ASSERT((bytes % ExecutableCodePageSize) == 0);
+
+ size_t numPages = bytes / ExecutableCodePageSize;
+
+ // Take the lock and try to allocate.
+ void* p = nullptr;
+ {
+ PR_Lock(lock_);
+ MOZ_ASSERT(pagesAllocated_ <= MaxCodePages);
+
+ // Check if we have enough pages available.
+ if (pagesAllocated_ + numPages >= MaxCodePages) {
+ PR_Unlock(lock_);
+ return nullptr;
+ }
+
+ MOZ_ASSERT(bytes <= MaxCodeBytesPerProcess);
+
+ // Maybe skip a page to make allocations less predictable.
+ size_t page = cursor_ + (rng_.ref().next() % 2);
+
+ for (size_t i = 0; i < MaxCodePages; i++) {
+ // Make sure page + numPages - 1 is a valid index.
+ if (page + numPages > MaxCodePages)
+ page = 0;
+
+ bool available = true;
+ for (size_t j = 0; j < numPages; j++) {
+ if (pages_.contains(page + j)) {
+ available = false;
+ break;
+ }
+ }
+ if (!available) {
+ page++;
+ continue;
+ }
+
+ // Mark the pages as unavailable.
+ for (size_t j = 0; j < numPages; j++)
+ pages_.insert(page + j);
+
+ pagesAllocated_ += numPages;
+ MOZ_ASSERT(pagesAllocated_ <= MaxCodePages);
+
+ // If we allocated a small number of pages, move cursor_ to the
+ // next page. We don't do this for larger allocations to avoid
+ // skipping a large number of small holes.
+ if (numPages <= 2)
+ cursor_ = page + numPages;
+
+ p = base_ + page * ExecutableCodePageSize;
+ break;
+ }
+ PR_Unlock(lock_);
+ if (!p)
+ return nullptr;
+ }
+
+ // Commit the pages after releasing the lock.
+ CommitPages(p, bytes, protection);
+ return p;
+}
+
+void
+ProcessExecutableMemory::deallocate(void* addr, size_t bytes)
+{
+ MOZ_ASSERT(initialized());
+ MOZ_ASSERT(addr);
+ MOZ_ASSERT((uintptr_t(addr) % gc::SystemPageSize()) == 0);
+ MOZ_ASSERT(bytes > 0);
+ MOZ_ASSERT((bytes % ExecutableCodePageSize) == 0);
+
+ assertValidAddress(addr, bytes);
+
+ size_t firstPage = (static_cast<uint8_t*>(addr) - base_) / ExecutableCodePageSize;
+ size_t numPages = bytes / ExecutableCodePageSize;
+
+ // Decommit before taking the lock.
+ DecommitPages(addr, bytes);
+
+ PR_Lock(lock_);
+ MOZ_ASSERT(numPages <= pagesAllocated_);
+ pagesAllocated_ -= numPages;
+
+ for (size_t i = 0; i < numPages; i++)
+ pages_.remove(firstPage + i);
+
+ // Move the cursor back so we can reuse pages instead of fragmenting the
+ // whole region.
+ if (firstPage < cursor_)
+ cursor_ = firstPage;
+
+ PR_Unlock(lock_);
+}
+
+static ProcessExecutableMemory execMemory;
+
+void*
+js::jit::AllocateExecutableMemory(size_t bytes, ProtectionSetting protection)
+{
+ return execMemory.allocate(bytes, protection);
+}
+
+void
+js::jit::DeallocateExecutableMemory(void* addr, size_t bytes)
+{
+ execMemory.deallocate(addr, bytes);
+}
+
+bool
+js::jit::InitProcessExecutableMemory()
+{
+ return execMemory.init();
+}
+
+void
+js::jit::ReleaseProcessExecutableMemory()
+{
+ execMemory.release();
+}
+
+bool
+js::jit::CanLikelyAllocateMoreExecutableMemory()
+{
+ // Use a 16 MB buffer.
+ static const size_t BufferSize = 16 * 1024 * 1024;
+
+ MOZ_ASSERT(execMemory.bytesAllocated() <= MaxCodeBytesPerProcess);
+
+ return execMemory.bytesAllocated() + BufferSize <= MaxCodeBytesPerProcess;
+}
diff --git a/src/third_party/mozjs-45/extract/js/src/jit/ProcessExecutableMemory.h b/src/third_party/mozjs-45/extract/js/src/jit/ProcessExecutableMemory.h
new file mode 100644
index 00000000000..7884706e3bd
--- /dev/null
+++ b/src/third_party/mozjs-45/extract/js/src/jit/ProcessExecutableMemory.h
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef jit_ProcessExecutableMemory_h
+#define jit_ProcessExecutableMemory_h
+
+#include "mozilla/Attributes.h"
+
+namespace js {
+namespace jit {
+
+// Executable code is allocated in 64K chunks. ExecutableAllocator uses pools
+// that are at least this big. Code we allocate does not necessarily have 64K
+// alignment though.
+static const size_t ExecutableCodePageSize = 64 * 1024;
+
+enum class ProtectionSetting {
+ Protected, // Not readable, writable, or executable.
+ Writable,
+ Executable,
+};
+
+// Functions called at process start-up/shutdown to initialize/release the
+// executable memory region.
+extern MOZ_MUST_USE bool InitProcessExecutableMemory();
+extern void ReleaseProcessExecutableMemory();
+
+// Allocate/deallocate executable pages.
+extern void* AllocateExecutableMemory(size_t bytes, ProtectionSetting protection);
+extern void DeallocateExecutableMemory(void* addr, size_t bytes);
+
+// Returns true if we can allocate a few more MB of executable code without
+// hitting our code limit. This function can be used to stop compiling things
+// that are optional (like Baseline and Ion code) when we're about to reach the
+// limit, so we are less likely to OOM or crash. Note that the limit is
+// per-process, so other threads can also allocate code after we call this
+// function.
+extern bool CanLikelyAllocateMoreExecutableMemory();
+
+} // namespace jit
+} // namespace js
+
+#endif // jit_ProcessExecutableMemory_h
diff --git a/src/third_party/mozjs-45/extract/js/src/jit/SharedIC.cpp b/src/third_party/mozjs-45/extract/js/src/jit/SharedIC.cpp
index 2867776f0af..3d3a30f4813 100644
--- a/src/third_party/mozjs-45/extract/js/src/jit/SharedIC.cpp
+++ b/src/third_party/mozjs-45/extract/js/src/jit/SharedIC.cpp
@@ -2448,6 +2448,14 @@ IsCacheableGetPropCall(JSContext* cx, JSObject* obj, JSObject* holder, Shape* sh
return false;
JSFunction* func = &shape->getterObject()->as<JSFunction>();
+ if (IsWindow(obj)) {
+ if (!func->isNative())
+ return false;
+
+ if (!func->jitInfo() || func->jitInfo()->needsOuterizedThisObject())
+ return false;
+ }
+
if (func->isNative()) {
*isScripted = false;
return true;
diff --git a/src/third_party/mozjs-45/extract/js/src/jit/VMFunctions.cpp b/src/third_party/mozjs-45/extract/js/src/jit/VMFunctions.cpp
index 6eda48e0a5f..1296b52fec5 100644
--- a/src/third_party/mozjs-45/extract/js/src/jit/VMFunctions.cpp
+++ b/src/third_party/mozjs-45/extract/js/src/jit/VMFunctions.cpp
@@ -1208,14 +1208,18 @@ AssertValidStringPtr(JSContext* cx, JSString* str)
MOZ_ASSERT(str->length() <= JSString::MAX_LENGTH);
gc::AllocKind kind = str->getAllocKind();
- if (str->isFatInline())
- MOZ_ASSERT(kind == gc::AllocKind::FAT_INLINE_STRING);
- else if (str->isExternal())
+ if (str->isFatInline()) {
+ MOZ_ASSERT(kind == gc::AllocKind::FAT_INLINE_STRING ||
+ kind == gc::AllocKind::FAT_INLINE_ATOM);
+ } else if (str->isExternal()) {
MOZ_ASSERT(kind == gc::AllocKind::EXTERNAL_STRING);
- else if (str->isAtom() || str->isFlat())
+ } else if (str->isAtom()) {
+ MOZ_ASSERT(kind == gc::AllocKind::ATOM);
+ } else if (str->isFlat()) {
MOZ_ASSERT(kind == gc::AllocKind::STRING || kind == gc::AllocKind::FAT_INLINE_STRING);
- else
+ } else {
MOZ_ASSERT(kind == gc::AllocKind::STRING);
+ }
#endif
}
diff --git a/src/third_party/mozjs-45/extract/js/src/jsarray.cpp b/src/third_party/mozjs-45/extract/js/src/jsarray.cpp
index 59384b3fd4b..1131720cb72 100644
--- a/src/third_party/mozjs-45/extract/js/src/jsarray.cpp
+++ b/src/third_party/mozjs-45/extract/js/src/jsarray.cpp
@@ -1882,6 +1882,7 @@ js::array_sort(JSContext* cx, unsigned argc, Value* vp)
undefs = 0;
bool allStrings = true;
bool allInts = true;
+ bool extraIndexed = ObjectMayHaveExtraIndexedProperties(obj);
RootedValue v(cx);
for (uint32_t i = 0; i < len; i++) {
if (!CheckForInterrupt(cx))
@@ -1914,7 +1915,10 @@ js::array_sort(JSContext* cx, unsigned argc, Value* vp)
}
/* Here len == n + undefs + number_of_holes. */
+ bool defaultOrMatch;
if (fval.isNull()) {
+ defaultOrMatch = true;
+
/*
* Sort using the default comparator converting all elements to
* strings.
@@ -1938,6 +1942,7 @@ js::array_sort(JSContext* cx, unsigned argc, Value* vp)
if (comp == Match_Failure)
return false;
+ defaultOrMatch = comp != Match_None;
if (comp != Match_None) {
if (allInts) {
JS_ALWAYS_TRUE(vec.resize(n * 2));
@@ -1958,7 +1963,10 @@ js::array_sort(JSContext* cx, unsigned argc, Value* vp)
}
}
- if (!InitArrayElements(cx, obj, 0, uint32_t(n), vec.begin(), ShouldUpdateTypes::DontUpdate))
+ ShouldUpdateTypes updateTypes = !extraIndexed && (allStrings || allInts) && defaultOrMatch
+ ? ShouldUpdateTypes::DontUpdate
+ : ShouldUpdateTypes::Update;
+ if (!InitArrayElements(cx, obj, 0, uint32_t(n), vec.begin(), updateTypes))
return false;
}
diff --git a/src/third_party/mozjs-45/extract/js/src/jsatom.cpp b/src/third_party/mozjs-45/extract/js/src/jsatom.cpp
index 3d3c0e4d821..65f1deffbf9 100644
--- a/src/third_party/mozjs-45/extract/js/src/jsatom.cpp
+++ b/src/third_party/mozjs-45/extract/js/src/jsatom.cpp
@@ -340,7 +340,8 @@ AtomizeAndCopyChars(ExclusiveContext* cx, const CharT* tbchars, size_t length, P
return nullptr;
}
- JSAtom* atom = flat->morphAtomizedStringIntoAtom();
+ JSAtom* atom = flat->morphAtomizedStringIntoAtom(lookup.hash);
+ MOZ_ASSERT(atom->hash() == lookup.hash);
// We have held the lock since looking up p, and the operations we've done
// since then can't GC; therefore the atoms table has not been modified and
diff --git a/src/third_party/mozjs-45/extract/js/src/jsatom.h b/src/third_party/mozjs-45/extract/js/src/jsatom.h
index ed1a6c9adf8..48d3c0ef9cf 100644
--- a/src/third_party/mozjs-45/extract/js/src/jsatom.h
+++ b/src/third_party/mozjs-45/extract/js/src/jsatom.h
@@ -23,25 +23,6 @@ class JSAutoByteString;
namespace js {
-JS_STATIC_ASSERT(sizeof(HashNumber) == 4);
-
-static MOZ_ALWAYS_INLINE js::HashNumber
-HashId(jsid id)
-{
- return mozilla::HashGeneric(JSID_BITS(id));
-}
-
-struct JsidHasher
-{
- typedef jsid Lookup;
- static HashNumber hash(const Lookup& l) {
- return HashNumber(JSID_BITS(l));
- }
- static bool match(const jsid& id, const Lookup& l) {
- return id == l;
- }
-};
-
/*
* Return a printable, lossless char[] representation of a string-type atom.
* The lifetime of the result matches the lifetime of bytes.
diff --git a/src/third_party/mozjs-45/extract/js/src/jsatominlines.h b/src/third_party/mozjs-45/extract/js/src/jsatominlines.h
index 2fb7d35aa0a..216a91071e2 100644
--- a/src/third_party/mozjs-45/extract/js/src/jsatominlines.h
+++ b/src/third_party/mozjs-45/extract/js/src/jsatominlines.h
@@ -156,12 +156,13 @@ inline
AtomHasher::Lookup::Lookup(const JSAtom* atom)
: isLatin1(atom->hasLatin1Chars()), length(atom->length()), atom(atom)
{
+ hash = atom->hash();
if (isLatin1) {
latin1Chars = atom->latin1Chars(nogc);
- hash = mozilla::HashString(latin1Chars, length);
+ MOZ_ASSERT(mozilla::HashString(latin1Chars, length) == hash);
} else {
twoByteChars = atom->twoByteChars(nogc);
- hash = mozilla::HashString(twoByteChars, length);
+ MOZ_ASSERT(mozilla::HashString(twoByteChars, length) == hash);
}
}
@@ -171,7 +172,7 @@ AtomHasher::match(const AtomStateEntry& entry, const Lookup& lookup)
JSAtom* key = entry.asPtr();
if (lookup.atom)
return lookup.atom == key;
- if (key->length() != lookup.length)
+ if (key->length() != lookup.length || key->hash() != lookup.hash)
return false;
if (key->hasLatin1Chars()) {
diff --git a/src/third_party/mozjs-45/extract/js/src/jscntxt.h b/src/third_party/mozjs-45/extract/js/src/jscntxt.h
index 0f70509d67f..89bf2863503 100644
--- a/src/third_party/mozjs-45/extract/js/src/jscntxt.h
+++ b/src/third_party/mozjs-45/extract/js/src/jscntxt.h
@@ -12,6 +12,7 @@
#include "mozilla/MemoryReporting.h"
#include "js/TraceableVector.h"
+#include "js/Utility.h"
#include "js/Vector.h"
#include "vm/Runtime.h"
diff --git a/src/third_party/mozjs-45/extract/js/src/jscompartment.cpp b/src/third_party/mozjs-45/extract/js/src/jscompartment.cpp
index c0d41ce8037..0d72551ef4b 100644
--- a/src/third_party/mozjs-45/extract/js/src/jscompartment.cpp
+++ b/src/third_party/mozjs-45/extract/js/src/jscompartment.cpp
@@ -46,6 +46,7 @@ JSCompartment::JSCompartment(Zone* zone, const JS::CompartmentOptions& options =
runtime_(zone->runtimeFromMainThread()),
principals_(nullptr),
isSystem_(false),
+ isAtomsCompartment_(false),
isSelfHosting(false),
marked(true),
warnedAboutFlagsArgument(false),
@@ -72,6 +73,7 @@ JSCompartment::JSCompartment(Zone* zone, const JS::CompartmentOptions& options =
gcIncomingGrayPointers(nullptr),
gcPreserveJitCode(options.preserveJitCode()),
debugModeBits(0),
+ randomKeyGenerator_(runtime_->forkRandomKeyGenerator()),
watchpointMap(nullptr),
scriptCountsMap(nullptr),
debugScriptMap(nullptr),
@@ -157,6 +159,12 @@ JSRuntime::createJitRuntime(JSContext* cx)
MOZ_ASSERT(!jitRuntime_);
+ if (!CanLikelyAllocateMoreExecutableMemory()) {
+ // Report OOM instead of potentially hitting the MOZ_CRASH below.
+ ReportOutOfMemory(cx);
+ return nullptr;
+ }
+
jit::JitRuntime* jrt = cx->new_<jit::JitRuntime>();
if (!jrt)
return nullptr;
@@ -1168,6 +1176,20 @@ JSCompartment::addTelemetry(const char* filename, DeprecatedLanguageExtension e)
sawDeprecatedLanguageExtension[e] = true;
}
+HashNumber
+JSCompartment::randomHashCode()
+{
+ ensureRandomNumberGenerator();
+ return HashNumber(randomNumberGenerator.ref().next());
+}
+
+mozilla::HashCodeScrambler
+JSCompartment::randomHashCodeScrambler()
+{
+ return mozilla::HashCodeScrambler(randomKeyGenerator_.next(),
+ randomKeyGenerator_.next());
+}
+
AutoSetNewObjectMetadata::AutoSetNewObjectMetadata(ExclusiveContext* ecx
MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
: CustomAutoRooter(ecx)
diff --git a/src/third_party/mozjs-45/extract/js/src/jscompartment.h b/src/third_party/mozjs-45/extract/js/src/jscompartment.h
index 96938211507..de5592fd65a 100644
--- a/src/third_party/mozjs-45/extract/js/src/jscompartment.h
+++ b/src/third_party/mozjs-45/extract/js/src/jscompartment.h
@@ -270,9 +270,19 @@ struct JSCompartment
performanceMonitoring.unlink();
isSystem_ = isSystem;
}
+
+ bool isAtomsCompartment() const {
+ return isAtomsCompartment_;
+ }
+ void setIsAtomsCompartment() {
+ isAtomsCompartment_ = true;
+ }
+
private:
JSPrincipals* principals_;
bool isSystem_;
+ bool isAtomsCompartment_;
+
public:
bool isSelfHosting;
bool marked;
@@ -601,6 +611,14 @@ struct JSCompartment
void ensureRandomNumberGenerator();
private:
+ mozilla::non_crypto::XorShift128PlusRNG randomKeyGenerator_;
+
+ public:
+ js::HashNumber randomHashCode();
+
+ mozilla::HashCodeScrambler randomHashCodeScrambler();
+
+ private:
JSCompartment* thisForCtor() { return this; }
public:
diff --git a/src/third_party/mozjs-45/extract/js/src/jsgc.cpp b/src/third_party/mozjs-45/extract/js/src/jsgc.cpp
index 610fd78b0b6..776ebef6563 100644
--- a/src/third_party/mozjs-45/extract/js/src/jsgc.cpp
+++ b/src/third_party/mozjs-45/extract/js/src/jsgc.cpp
@@ -238,6 +238,7 @@ using namespace js;
using namespace js::gc;
using mozilla::ArrayLength;
+using mozilla::HashCodeScrambler;
using mozilla::Maybe;
using mozilla::Swap;
@@ -291,6 +292,8 @@ const uint32_t Arena::ThingSizes[] = CHECK_MIN_THING_SIZE(
sizeof(JSFatInlineString), /* AllocKind::FAT_INLINE_STRING */
sizeof(JSString), /* AllocKind::STRING */
sizeof(JSExternalString), /* AllocKind::EXTERNAL_STRING */
+ sizeof(js::FatInlineAtom), /* AllocKind::FAT_INLINE_ATOM */
+ sizeof(js::NormalAtom), /* AllocKind::ATOM */
sizeof(JS::Symbol), /* AllocKind::SYMBOL */
sizeof(jit::JitCode), /* AllocKind::JITCODE */
);
@@ -324,6 +327,8 @@ const uint32_t Arena::FirstThingOffsets[] = {
OFFSET(JSFatInlineString), /* AllocKind::FAT_INLINE_STRING */
OFFSET(JSString), /* AllocKind::STRING */
OFFSET(JSExternalString), /* AllocKind::EXTERNAL_STRING */
+ OFFSET(js::FatInlineAtom), /* AllocKind::FAT_INLINE_ATOM */
+ OFFSET(js::NormalAtom), /* AllocKind::ATOM */
OFFSET(JS::Symbol), /* AllocKind::SYMBOL */
OFFSET(jit::JitCode), /* AllocKind::JITCODE */
};
@@ -380,6 +385,8 @@ static const AllocKind BackgroundPhaseObjects[] = {
static const AllocKind BackgroundPhaseStringsAndSymbols[] = {
AllocKind::FAT_INLINE_STRING,
AllocKind::STRING,
+ AllocKind::FAT_INLINE_ATOM,
+ AllocKind::ATOM,
AllocKind::SYMBOL
};
@@ -633,6 +640,10 @@ FinalizeArenas(FreeOp* fop,
return FinalizeTypedArenas<JSFatInlineString>(fop, src, dest, thingKind, budget, keepArenas);
case AllocKind::EXTERNAL_STRING:
return FinalizeTypedArenas<JSExternalString>(fop, src, dest, thingKind, budget, keepArenas);
+ case AllocKind::FAT_INLINE_ATOM:
+ return FinalizeTypedArenas<js::FatInlineAtom>(fop, src, dest, thingKind, budget, keepArenas);
+ case AllocKind::ATOM:
+ return FinalizeTypedArenas<js::NormalAtom>(fop, src, dest, thingKind, budget, keepArenas);
case AllocKind::SYMBOL:
return FinalizeTypedArenas<JS::Symbol>(fop, src, dest, thingKind, budget, keepArenas);
case AllocKind::JITCODE:
@@ -2323,8 +2334,9 @@ GCRuntime::relocateArenas(Zone* zone, JS::gcreason::Reason reason, ArenaHeader*&
void
MovingTracer::onObjectEdge(JSObject** objp)
{
- if (IsForwarded(*objp))
- *objp = Forwarded(*objp);
+ JSObject* obj = *objp;
+ if (obj->runtimeFromAnyThread() == runtime() && IsForwarded(obj))
+ *objp = Forwarded(obj);
}
void
@@ -2477,6 +2489,8 @@ bool ArenasToUpdate::shouldProcessKind(AllocKind kind)
if (kind == AllocKind::FAT_INLINE_STRING ||
kind == AllocKind::STRING ||
kind == AllocKind::EXTERNAL_STRING ||
+ kind == AllocKind::FAT_INLINE_ATOM ||
+ kind == AllocKind::ATOM ||
kind == AllocKind::SYMBOL)
{
return false;
@@ -3782,10 +3796,12 @@ GCRuntime::purgeRuntime()
bool
GCRuntime::shouldPreserveJITCode(JSCompartment* comp, int64_t currentTime,
- JS::gcreason::Reason reason)
+ JS::gcreason::Reason reason, bool canAllocateMoreCode)
{
if (cleanUpEverything)
return false;
+ if (!canAllocateMoreCode)
+ return false;
if (alwaysPreserveCode)
return true;
@@ -3932,15 +3948,19 @@ GCRuntime::beginMarkPhase(JS::gcreason::Reason reason)
zone->setPreservingCode(false);
}
+ // Discard JIT code more aggressively if the process is approaching its
+ // executable code limit.
+ bool canAllocateMoreCode = jit::CanLikelyAllocateMoreExecutableMemory();
+
for (CompartmentsIter c(rt, WithAtoms); !c.done(); c.next()) {
c->marked = false;
c->scheduledForDestruction = false;
c->maybeAlive = false;
- if (shouldPreserveJITCode(c, currentTime, reason))
+ if (shouldPreserveJITCode(c, currentTime, reason, canAllocateMoreCode))
c->zone()->setPreservingCode(true);
}
- if (!rt->gc.cleanUpEverything) {
+ if (!rt->gc.cleanUpEverything && canAllocateMoreCode) {
if (JSCompartment* comp = jit::TopmostIonActivationCompartment(rt))
comp->zone()->setPreservingCode(true);
}
@@ -4298,7 +4318,7 @@ js::gc::MarkingValidator::nonIncrementalMark()
* For saving, smush all of the keys into one big table and split them back
* up into per-zone tables when restoring.
*/
- gc::WeakKeyTable savedWeakKeys;
+ gc::WeakKeyTable savedWeakKeys(SystemAllocPolicy(), runtime->randomHashCodeScrambler());
if (!savedWeakKeys.init())
return;
@@ -4571,7 +4591,6 @@ Zone::findOutgoingEdges(ComponentFinder<JS::Zone>& finder)
if (r.front()->isGCMarking())
finder.addEdgeTo(r.front());
}
- gcZoneGroupEdges.clear();
Debugger::findZoneEdges(this, finder);
}
@@ -4600,6 +4619,11 @@ GCRuntime::findZoneEdgesForWeakMaps()
void
GCRuntime::findZoneGroups()
{
+#ifdef DEBUG
+ for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next())
+ MOZ_ASSERT(zone->gcZoneGroupEdges.empty());
+#endif
+
ComponentFinder<Zone> finder(rt->mainThread.nativeStackLimit[StackForSystemCode]);
if (!isIncremental || !findZoneEdgesForWeakMaps())
finder.useOneComponent();
@@ -4612,12 +4636,19 @@ GCRuntime::findZoneGroups()
currentZoneGroup = zoneGroups;
zoneGroupIndex = 0;
+ for (GCZonesIter zone(rt); !zone.done(); zone.next())
+ zone->gcZoneGroupEdges.clear();
+
+#ifdef DEBUG
for (Zone* head = currentZoneGroup; head; head = head->nextGroup()) {
for (Zone* zone = head; zone; zone = zone->nextNodeInGroup())
MOZ_ASSERT(zone->isGCMarking());
}
MOZ_ASSERT_IF(!isIncremental, !currentZoneGroup->nextGroup());
+ for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next())
+ MOZ_ASSERT(zone->gcZoneGroupEdges.empty());
+#endif
}
static void
@@ -4787,11 +4818,11 @@ MarkIncomingCrossCompartmentPointers(JSRuntime* rt, const uint32_t color)
MOZ_ASSERT(dst->compartment() == c);
if (color == GRAY) {
- if (IsMarkedUnbarriered(&src) && src->asTenured().isMarked(GRAY))
+ if (IsMarkedUnbarriered(rt, &src) && src->asTenured().isMarked(GRAY))
TraceManuallyBarrieredEdge(&rt->gc.marker, &dst,
"cross-compartment gray pointer");
} else {
- if (IsMarkedUnbarriered(&src) && !src->asTenured().isMarked(GRAY))
+ if (IsMarkedUnbarriered(rt, &src) && !src->asTenured().isMarked(GRAY))
TraceManuallyBarrieredEdge(&rt->gc.marker, &dst,
"cross-compartment black pointer");
}
diff --git a/src/third_party/mozjs-45/extract/js/src/jsgc.h b/src/third_party/mozjs-45/extract/js/src/jsgc.h
index a254a0b3ae9..d4cfc9960b8 100644
--- a/src/third_party/mozjs-45/extract/js/src/jsgc.h
+++ b/src/third_party/mozjs-45/extract/js/src/jsgc.h
@@ -103,6 +103,8 @@ template <> struct MapTypeToFinalizeKind<ObjectGroup> { static const Alloc
template <> struct MapTypeToFinalizeKind<JSFatInlineString> { static const AllocKind kind = AllocKind::FAT_INLINE_STRING; };
template <> struct MapTypeToFinalizeKind<JSString> { static const AllocKind kind = AllocKind::STRING; };
template <> struct MapTypeToFinalizeKind<JSExternalString> { static const AllocKind kind = AllocKind::EXTERNAL_STRING; };
+template <> struct MapTypeToFinalizeKind<js::FatInlineAtom> { static const AllocKind kind = AllocKind::FAT_INLINE_ATOM; };
+template <> struct MapTypeToFinalizeKind<js::NormalAtom> { static const AllocKind kind = AllocKind::ATOM; };
template <> struct MapTypeToFinalizeKind<JS::Symbol> { static const AllocKind kind = AllocKind::SYMBOL; };
template <> struct MapTypeToFinalizeKind<jit::JitCode> { static const AllocKind kind = AllocKind::JITCODE; };
@@ -140,6 +142,8 @@ IsNurseryAllocable(AllocKind kind)
false, /* AllocKind::FAT_INLINE_STRING */
false, /* AllocKind::STRING */
false, /* AllocKind::EXTERNAL_STRING */
+ false, /* AllocKind::FAT_INLINE_ATOM */
+ false, /* AllocKind::ATOM */
false, /* AllocKind::SYMBOL */
false, /* AllocKind::JITCODE */
};
@@ -175,6 +179,8 @@ IsBackgroundFinalized(AllocKind kind)
true, /* AllocKind::FAT_INLINE_STRING */
true, /* AllocKind::STRING */
false, /* AllocKind::EXTERNAL_STRING */
+ true, /* AllocKind::FAT_INLINE_ATOM */
+ true, /* AllocKind::ATOM */
true, /* AllocKind::SYMBOL */
false, /* AllocKind::JITCODE */
};
diff --git a/src/third_party/mozjs-45/extract/js/src/jsgcinlines.h b/src/third_party/mozjs-45/extract/js/src/jsgcinlines.h
index 6ca8804cd8f..0cc2b051cb4 100644
--- a/src/third_party/mozjs-45/extract/js/src/jsgcinlines.h
+++ b/src/third_party/mozjs-45/extract/js/src/jsgcinlines.h
@@ -89,11 +89,19 @@ class ArenaIter
}
};
+enum CellIterNeedsBarrier : uint8_t
+{
+ CellIterDoesntNeedBarrier = 0,
+ CellIterMayNeedBarrier = 1
+};
+
class ArenaCellIterImpl
{
- // These three are set in initUnsynchronized().
+ // These are set in initUnsynchronized().
size_t firstThingOffset;
size_t thingSize;
+ JS::TraceKind traceKind;
+ bool needsBarrier;
#ifdef DEBUG
bool isInited;
#endif
@@ -122,26 +130,30 @@ class ArenaCellIterImpl
ArenaCellIterImpl()
: firstThingOffset(0) // Squelch
, thingSize(0) // warnings
+ , traceKind(JS::TraceKind::Null)
+ , needsBarrier(false)
, limit(0)
{
}
- void initUnsynchronized(ArenaHeader* aheader) {
+ void initUnsynchronized(ArenaHeader* aheader, CellIterNeedsBarrier mayNeedBarrier) {
AllocKind kind = aheader->getAllocKind();
#ifdef DEBUG
isInited = true;
#endif
firstThingOffset = Arena::firstThingOffset(kind);
thingSize = Arena::thingSize(kind);
+ traceKind = MapAllocToTraceKind(kind);
+ needsBarrier = mayNeedBarrier && !aheader->zone->runtimeFromMainThread()->isHeapCollecting();
reset(aheader);
}
- void init(ArenaHeader* aheader) {
+ void init(ArenaHeader* aheader, CellIterNeedsBarrier mayNeedBarrier) {
#ifdef DEBUG
AllocKind kind = aheader->getAllocKind();
MOZ_ASSERT(aheader->zone->arenas.isSynchronizedFreeList(kind));
#endif
- initUnsynchronized(aheader);
+ initUnsynchronized(aheader, mayNeedBarrier);
}
// Use this to move from an Arena of a particular kind to another Arena of
@@ -161,7 +173,15 @@ class ArenaCellIterImpl
TenuredCell* getCell() const {
MOZ_ASSERT(!done());
- return reinterpret_cast<TenuredCell*>(thing);
+ TenuredCell* cell = reinterpret_cast<TenuredCell*>(thing);
+
+ // This can result in a a new reference being created to an object that
+ // an ongoing incremental GC may find to be unreachable, so we may need
+ // a barrier here.
+ if (needsBarrier)
+ ExposeGCThingToActiveJS(JS::GCCellPtr(cell, traceKind));
+
+ return cell;
}
template<typename T> T* get() const {
@@ -186,7 +206,7 @@ class ArenaCellIterUnderGC : public ArenaCellIterImpl
public:
explicit ArenaCellIterUnderGC(ArenaHeader* aheader) {
MOZ_ASSERT(aheader->zone->runtimeFromAnyThread()->isHeapBusy());
- init(aheader);
+ init(aheader, CellIterDoesntNeedBarrier);
}
};
@@ -194,7 +214,7 @@ class ArenaCellIterUnderFinalize : public ArenaCellIterImpl
{
public:
explicit ArenaCellIterUnderFinalize(ArenaHeader* aheader) {
- initUnsynchronized(aheader);
+ initUnsynchronized(aheader, CellIterDoesntNeedBarrier);
}
};
@@ -210,7 +230,7 @@ class ZoneCellIterImpl
MOZ_ASSERT(zone->arenas.isSynchronizedFreeList(kind));
arenaIter.init(zone, kind);
if (!arenaIter.done())
- cellIter.init(arenaIter.get());
+ cellIter.init(arenaIter.get(), CellIterMayNeedBarrier);
}
public:
diff --git a/src/third_party/mozjs-45/extract/js/src/jsiter.cpp b/src/third_party/mozjs-45/extract/js/src/jsiter.cpp
index 9b27317683b..9cbff88bfb1 100644
--- a/src/third_party/mozjs-45/extract/js/src/jsiter.cpp
+++ b/src/third_party/mozjs-45/extract/js/src/jsiter.cpp
@@ -69,17 +69,7 @@ NativeIterator::mark(JSTracer* trc)
TraceManuallyBarrieredEdge(trc, &iterObj_, "iterObj");
}
-struct IdHashPolicy {
- typedef jsid Lookup;
- static HashNumber hash(jsid id) {
- return JSID_BITS(id);
- }
- static bool match(jsid id1, jsid id2) {
- return id1 == id2;
- }
-};
-
-typedef HashSet<jsid, IdHashPolicy> IdSet;
+typedef HashSet<jsid, JsidHasher> IdSet;
static inline bool
NewKeyValuePair(JSContext* cx, jsid id, const Value& val, MutableHandleValue rval)
diff --git a/src/third_party/mozjs-45/extract/js/src/jsmath.cpp b/src/third_party/mozjs-45/extract/js/src/jsmath.cpp
index 040269f63d9..e381b42a846 100644
--- a/src/third_party/mozjs-45/extract/js/src/jsmath.cpp
+++ b/src/third_party/mozjs-45/extract/js/src/jsmath.cpp
@@ -747,8 +747,8 @@ js::math_pow(JSContext* cx, unsigned argc, Value* vp)
return math_pow_handle(cx, args.get(0), args.get(1), args.rval());
}
-static uint64_t
-GenerateSeed()
+uint64_t
+js::GenerateRandomSeed()
{
uint64_t seed = 0;
@@ -763,7 +763,7 @@ GenerateSeed()
close(fd);
}
#else
-# error "Platform needs to implement GenerateSeed()"
+# error "Platform needs to implement GenerateRandomSeed()"
#endif
// Also mix in PRMJ_Now() in case we couldn't read random bits from the OS.
@@ -775,8 +775,8 @@ js::GenerateXorShift128PlusSeed(mozilla::Array<uint64_t, 2>& seed)
{
// XorShift128PlusRNG must be initialized with a non-zero seed.
do {
- seed[0] = GenerateSeed();
- seed[1] = GenerateSeed();
+ seed[0] = GenerateRandomSeed();
+ seed[1] = GenerateRandomSeed();
} while (seed[0] == 0 && seed[1] == 0);
}
diff --git a/src/third_party/mozjs-45/extract/js/src/jsmath.h b/src/third_party/mozjs-45/extract/js/src/jsmath.h
index e703c703c62..a1d1aaedfb3 100644
--- a/src/third_party/mozjs-45/extract/js/src/jsmath.h
+++ b/src/third_party/mozjs-45/extract/js/src/jsmath.h
@@ -86,6 +86,9 @@ class MathCache
extern JSObject*
InitMathClass(JSContext* cx, HandleObject obj);
+extern uint64_t
+GenerateRandomSeed();
+
// Fill |seed[0]| and |seed[1]| with random bits, suitable for
// seeding a XorShift128+ random number generator.
extern void
diff --git a/src/third_party/mozjs-45/extract/js/src/jswatchpoint.cpp b/src/third_party/mozjs-45/extract/js/src/jswatchpoint.cpp
index 9713ebe5990..53418e36fc4 100644
--- a/src/third_party/mozjs-45/extract/js/src/jswatchpoint.cpp
+++ b/src/third_party/mozjs-45/extract/js/src/jswatchpoint.cpp
@@ -11,6 +11,7 @@
#include "jsfriendapi.h"
#include "gc/Marking.h"
+#include "vm/Shape.h"
#include "jsgcinlines.h"
@@ -153,7 +154,7 @@ WatchpointMap::markIteratively(JSTracer* trc)
JSObject* priorKeyObj = entry.key().object;
jsid priorKeyId(entry.key().id.get());
bool objectIsLive =
- IsMarked(const_cast<PreBarrieredObject*>(&entry.key().object));
+ IsMarked(trc->runtime(), const_cast<PreBarrieredObject*>(&entry.key().object));
if (objectIsLive || entry.value().held) {
if (!objectIsLive) {
TraceEdge(trc, const_cast<PreBarrieredObject*>(&entry.key().object),
@@ -166,7 +167,7 @@ WatchpointMap::markIteratively(JSTracer* trc)
JSID_IS_SYMBOL(priorKeyId));
TraceEdge(trc, const_cast<PreBarrieredId*>(&entry.key().id), "WatchKey::id");
- if (entry.value().closure && !IsMarked(&entry.value().closure)) {
+ if (entry.value().closure && !IsMarked(trc->runtime(), &entry.value().closure)) {
TraceEdge(trc, &entry.value().closure, "Watchpoint::closure");
marked = true;
}
diff --git a/src/third_party/mozjs-45/extract/js/src/jsweakmap.cpp b/src/third_party/mozjs-45/extract/js/src/jsweakmap.cpp
index 2249f46f71c..70a119601c7 100644
--- a/src/third_party/mozjs-45/extract/js/src/jsweakmap.cpp
+++ b/src/third_party/mozjs-45/extract/js/src/jsweakmap.cpp
@@ -150,7 +150,7 @@ ObjectValueMap::findZoneEdges()
if (!delegate)
continue;
Zone* delegateZone = delegate->zone();
- if (delegateZone == zone)
+ if (delegateZone == zone || !delegateZone->isGCMarking())
continue;
if (!delegateZone->gcZoneGroupEdges.put(key->zone()))
return false;
diff --git a/src/third_party/mozjs-45/extract/js/src/jsweakmap.h b/src/third_party/mozjs-45/extract/js/src/jsweakmap.h
index 3c17c78d415..020f51e9733 100644
--- a/src/third_party/mozjs-45/extract/js/src/jsweakmap.h
+++ b/src/third_party/mozjs-45/extract/js/src/jsweakmap.h
@@ -184,7 +184,7 @@ class WeakMap : public HashMap<Key, Value, HashPolicy, RuntimeAllocPolicy>,
Key key(p->key());
MOZ_ASSERT((markedCell == extractUnbarriered(key)) || (markedCell == getDelegate(key)));
- if (gc::IsMarked(&key)) {
+ if (gc::IsMarked(trc->runtime(), &key)) {
TraceEdge(trc, &p->value(), "ephemeron value");
} else if (keyNeedsMark(key)) {
TraceEdge(trc, &p->value(), "WeakMap ephemeron value");
@@ -249,7 +249,7 @@ class WeakMap : public HashMap<Key, Value, HashPolicy, RuntimeAllocPolicy>,
for (Enum e(*this); !e.empty(); e.popFront()) {
// If the entry is live, ensure its key and value are marked.
- bool keyIsMarked = gc::IsMarked(&e.front().mutableKey());
+ bool keyIsMarked = gc::IsMarked(trc->runtime(), &e.front().mutableKey());
if (!keyIsMarked && keyNeedsMark(e.front().key())) {
TraceEdge(trc, &e.front().mutableKey(), "proxy-preserved WeakMap entry key");
keyIsMarked = true;
@@ -257,7 +257,7 @@ class WeakMap : public HashMap<Key, Value, HashPolicy, RuntimeAllocPolicy>,
}
if (keyIsMarked) {
- if (!gc::IsMarked(&e.front().value())) {
+ if (!gc::IsMarked(trc->runtime(), &e.front().value())) {
TraceEdge(trc, &e.front().value(), "WeakMap entry value");
markedAny = true;
}
@@ -283,7 +283,15 @@ class WeakMap : public HashMap<Key, Value, HashPolicy, RuntimeAllocPolicy>,
JSObject* getDelegate(JSObject* key) const {
JSWeakmapKeyDelegateOp op = key->getClass()->ext.weakmapKeyDelegateOp;
- return op ? op(key) : nullptr;
+ if (!op)
+ return nullptr;
+
+ JSObject* obj = op(key);
+ if (!obj)
+ return nullptr;
+
+ MOZ_ASSERT(obj->runtimeFromMainThread() == zone->runtimeFromMainThread());
+ return obj;
}
JSObject* getDelegate(gc::Cell* cell) const {
@@ -296,7 +304,7 @@ class WeakMap : public HashMap<Key, Value, HashPolicy, RuntimeAllocPolicy>,
* Check if the delegate is marked with any color to properly handle
* gray marking when the key's delegate is black and the map is gray.
*/
- return delegate && gc::IsMarkedUnbarriered(&delegate);
+ return delegate && gc::IsMarkedUnbarriered(zone->runtimeFromMainThread(), &delegate);
}
bool keyNeedsMark(gc::Cell* cell) const {
diff --git a/src/third_party/mozjs-45/extract/js/src/moz.build b/src/third_party/mozjs-45/extract/js/src/moz.build
index 591d7a6a3ee..123c9f3bcb5 100644
--- a/src/third_party/mozjs-45/extract/js/src/moz.build
+++ b/src/third_party/mozjs-45/extract/js/src/moz.build
@@ -236,6 +236,7 @@ UNIFIED_SOURCES += [
'jit/MoveResolver.cpp',
'jit/OptimizationTracking.cpp',
'jit/PerfSpewer.cpp',
+ 'jit/ProcessExecutableMemory.cpp',
'jit/RangeAnalysis.cpp',
'jit/Recover.cpp',
'jit/RegisterAllocator.cpp',
@@ -530,15 +531,8 @@ elif CONFIG['JS_CODEGEN_MIPS32'] or CONFIG['JS_CODEGEN_MIPS64']:
]
if CONFIG['OS_ARCH'] == 'WINNT':
- SOURCES += [
- 'jit/ExecutableAllocatorWin.cpp',
- ]
# _CRT_RAND_S must be #defined before #including stdlib.h to get rand_s()
DEFINES['_CRT_RAND_S'] = True
-else:
- SOURCES += [
- 'jit/ExecutableAllocatorPosix.cpp',
- ]
if CONFIG['JS_HAS_CTYPES']:
SOURCES += [
diff --git a/src/third_party/mozjs-45/extract/js/src/proxy/Wrapper.cpp b/src/third_party/mozjs-45/extract/js/src/proxy/Wrapper.cpp
index e80113ce362..6a60746904d 100644
--- a/src/third_party/mozjs-45/extract/js/src/proxy/Wrapper.cpp
+++ b/src/third_party/mozjs-45/extract/js/src/proxy/Wrapper.cpp
@@ -42,7 +42,10 @@ JSObject*
Wrapper::wrappedObject(JSObject* wrapper)
{
MOZ_ASSERT(wrapper->is<WrapperObject>());
- return wrapper->as<ProxyObject>().target();
+ JSObject* target = wrapper->as<ProxyObject>().target();
+ if (target)
+ JS::ExposeObjectToActiveJS(target);
+ return target;
}
bool
diff --git a/src/third_party/mozjs-45/extract/js/src/vm/Debugger.cpp b/src/third_party/mozjs-45/extract/js/src/vm/Debugger.cpp
index 12de1145276..d583c9c52e9 100644
--- a/src/third_party/mozjs-45/extract/js/src/vm/Debugger.cpp
+++ b/src/third_party/mozjs-45/extract/js/src/vm/Debugger.cpp
@@ -517,7 +517,7 @@ Debugger::getHook(Hook hook) const
}
bool
-Debugger::hasAnyLiveHooks() const
+Debugger::hasAnyLiveHooks(JSRuntime* rt) const
{
if (!enabled)
return false;
@@ -532,7 +532,7 @@ Debugger::hasAnyLiveHooks() const
/* If any breakpoints are in live scripts, return true. */
for (Breakpoint* bp = firstBreakpoint(); bp; bp = bp->nextInDebugger()) {
- if (IsMarkedUnbarriered(&bp->site->script))
+ if (IsMarkedUnbarriered(rt, &bp->site->script))
return true;
}
@@ -2520,7 +2520,7 @@ Debugger::markAllIteratively(GCMarker* trc)
for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) {
if (c->isDebuggee()) {
GlobalObject* global = c->unsafeUnbarrieredMaybeGlobal();
- if (!IsMarkedUnbarriered(&global))
+ if (!IsMarkedUnbarriered(rt, &global))
continue;
/*
@@ -2542,8 +2542,8 @@ Debugger::markAllIteratively(GCMarker* trc)
if (!dbgobj->zone()->isGCMarking())
continue;
- bool dbgMarked = IsMarked(&dbgobj);
- if (!dbgMarked && dbg->hasAnyLiveHooks()) {
+ bool dbgMarked = IsMarked(rt, &dbgobj);
+ if (!dbgMarked && dbg->hasAnyLiveHooks(rt)) {
/*
* obj could be reachable only via its live, enabled
* debugger hooks, which may yet be called.
@@ -2556,12 +2556,12 @@ Debugger::markAllIteratively(GCMarker* trc)
if (dbgMarked) {
/* Search for breakpoints to mark. */
for (Breakpoint* bp = dbg->firstBreakpoint(); bp; bp = bp->nextInDebugger()) {
- if (IsMarkedUnbarriered(&bp->site->script)) {
+ if (IsMarkedUnbarriered(rt, &bp->site->script)) {
/*
* The debugger and the script are both live.
* Therefore the breakpoint handler is live.
*/
- if (!IsMarked(&bp->getHandlerRef())) {
+ if (!IsMarked(rt, &bp->getHandlerRef())) {
TraceEdge(trc, &bp->getHandlerRef(), "breakpoint handler");
markedAny = true;
}
diff --git a/src/third_party/mozjs-45/extract/js/src/vm/Debugger.h b/src/third_party/mozjs-45/extract/js/src/vm/Debugger.h
index ef7b94bc24f..49744a7d00d 100644
--- a/src/third_party/mozjs-45/extract/js/src/vm/Debugger.h
+++ b/src/third_party/mozjs-45/extract/js/src/vm/Debugger.h
@@ -607,7 +607,7 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
void updateObservesAsmJSOnDebuggees(IsObserving observing);
JSObject* getHook(Hook hook) const;
- bool hasAnyLiveHooks() const;
+ bool hasAnyLiveHooks(JSRuntime* rt) const;
static JSTrapStatus slowPathOnEnterFrame(JSContext* cx, AbstractFramePtr frame);
static bool slowPathOnLeaveFrame(JSContext* cx, AbstractFramePtr frame, bool ok);
diff --git a/src/third_party/mozjs-45/extract/js/src/vm/Initialization.cpp b/src/third_party/mozjs-45/extract/js/src/vm/Initialization.cpp
index cf5d21aa230..fcef4b22b44 100644
--- a/src/third_party/mozjs-45/extract/js/src/vm/Initialization.cpp
+++ b/src/third_party/mozjs-45/extract/js/src/vm/Initialization.cpp
@@ -83,7 +83,9 @@ JS_Init(void)
js::oom::SetThreadType(js::oom::THREAD_TYPE_MAIN);
#endif
- js::jit::ExecutableAllocator::initStatic();
+ js::gc::InitMemorySubsystem(); // Ensure gc::SystemPageSize() works.
+ if (!js::jit::InitProcessExecutableMemory())
+ return false;
if (!js::jit::InitializeIon())
return false;
@@ -146,6 +148,9 @@ JS_ShutDown(void)
u_cleanup();
#endif // EXPOSE_INTL_API
+ if (!JSRuntime::hasLiveRuntimes())
+ js::jit::ReleaseProcessExecutableMemory();
+
libraryInitState = InitState::ShutDown;
}
diff --git a/src/third_party/mozjs-45/extract/js/src/vm/ObjectGroup.cpp b/src/third_party/mozjs-45/extract/js/src/vm/ObjectGroup.cpp
index 6ef50de88c3..ad002b4a05e 100644
--- a/src/third_party/mozjs-45/extract/js/src/vm/ObjectGroup.cpp
+++ b/src/third_party/mozjs-45/extract/js/src/vm/ObjectGroup.cpp
@@ -12,6 +12,7 @@
#include "gc/StoreBuffer.h"
#include "gc/Zone.h"
#include "vm/ArrayObject.h"
+#include "vm/Shape.h"
#include "vm/UnboxedObject.h"
#include "jsobjinlines.h"
@@ -554,45 +555,38 @@ ObjectGroup::defaultNewGroup(ExclusiveContext* cx, const Class* clasp,
ObjectGroupCompartment::newTablePostBarrier(cx, table, clasp, proto, associated);
- if (proto.isObject()) {
- RootedObject obj(cx, proto.toObject());
-
- if (associated) {
- if (associated->is<JSFunction>()) {
- if (!TypeNewScript::make(cx->asJSContext(), group, &associated->as<JSFunction>()))
- return nullptr;
- } else {
- group->setTypeDescr(&associated->as<TypeDescr>());
- }
+ if (associated) {
+ if (associated->is<JSFunction>()) {
+ if (!TypeNewScript::make(cx->asJSContext(), group, &associated->as<JSFunction>()))
+ return nullptr;
+ } else {
+ group->setTypeDescr(&associated->as<TypeDescr>());
}
+ }
- /*
- * Some builtin objects have slotful native properties baked in at
- * creation via the Shape::{insert,get}initialShape mechanism. Since
- * these properties are never explicitly defined on new objects, update
- * the type information for them here.
- */
-
- const JSAtomState& names = cx->names();
-
- if (obj->is<RegExpObject>()) {
- AddTypePropertyId(cx, group, nullptr, NameToId(names.source), TypeSet::StringType());
- AddTypePropertyId(cx, group, nullptr, NameToId(names.global), TypeSet::BooleanType());
- AddTypePropertyId(cx, group, nullptr, NameToId(names.ignoreCase), TypeSet::BooleanType());
- AddTypePropertyId(cx, group, nullptr, NameToId(names.multiline), TypeSet::BooleanType());
- AddTypePropertyId(cx, group, nullptr, NameToId(names.sticky), TypeSet::BooleanType());
- AddTypePropertyId(cx, group, nullptr, NameToId(names.lastIndex), TypeSet::Int32Type());
- }
+ /*
+ * Some builtin objects have slotful native properties baked in at
+ * creation via the Shape::{insert,get}initialShape mechanism. Since
+ * these properties are never explicitly defined on new objects, update
+ * the type information for them here.
+ */
- if (obj->is<StringObject>())
- AddTypePropertyId(cx, group, nullptr, NameToId(names.length), TypeSet::Int32Type());
+ const JSAtomState& names = cx->names();
- if (obj->is<ErrorObject>()) {
- AddTypePropertyId(cx, group, nullptr, NameToId(names.fileName), TypeSet::StringType());
- AddTypePropertyId(cx, group, nullptr, NameToId(names.lineNumber), TypeSet::Int32Type());
- AddTypePropertyId(cx, group, nullptr, NameToId(names.columnNumber), TypeSet::Int32Type());
- AddTypePropertyId(cx, group, nullptr, NameToId(names.stack), TypeSet::StringType());
- }
+ if (clasp == &RegExpObject::class_) {
+ AddTypePropertyId(cx, group, nullptr, NameToId(names.source), TypeSet::StringType());
+ AddTypePropertyId(cx, group, nullptr, NameToId(names.global), TypeSet::BooleanType());
+ AddTypePropertyId(cx, group, nullptr, NameToId(names.ignoreCase), TypeSet::BooleanType());
+ AddTypePropertyId(cx, group, nullptr, NameToId(names.multiline), TypeSet::BooleanType());
+ AddTypePropertyId(cx, group, nullptr, NameToId(names.sticky), TypeSet::BooleanType());
+ AddTypePropertyId(cx, group, nullptr, NameToId(names.lastIndex), TypeSet::Int32Type());
+ } else if (clasp == &StringObject::class_) {
+ AddTypePropertyId(cx, group, nullptr, NameToId(names.length), TypeSet::Int32Type());
+ } else if (ErrorObject::isErrorClass(clasp)) {
+ AddTypePropertyId(cx, group, nullptr, NameToId(names.fileName), TypeSet::StringType());
+ AddTypePropertyId(cx, group, nullptr, NameToId(names.lineNumber), TypeSet::Int32Type());
+ AddTypePropertyId(cx, group, nullptr, NameToId(names.columnNumber), TypeSet::Int32Type());
+ AddTypePropertyId(cx, group, nullptr, NameToId(names.stack), TypeSet::StringType());
}
return group;
@@ -1116,7 +1110,7 @@ struct ObjectGroupCompartment::PlainObjectKey
};
static inline HashNumber hash(const Lookup& lookup) {
- return (HashNumber) (JSID_BITS(lookup.properties[lookup.nproperties - 1].id) ^
+ return (HashNumber) (HashId(lookup.properties[lookup.nproperties - 1].id) ^
lookup.nproperties);
}
diff --git a/src/third_party/mozjs-45/extract/js/src/vm/RegExpObject.cpp b/src/third_party/mozjs-45/extract/js/src/vm/RegExpObject.cpp
index fec090d3f19..9d0dd97d037 100644
--- a/src/third_party/mozjs-45/extract/js/src/vm/RegExpObject.cpp
+++ b/src/third_party/mozjs-45/extract/js/src/vm/RegExpObject.cpp
@@ -793,7 +793,7 @@ RegExpCompartment::sweep(JSRuntime* rt)
// the RegExpShared if it was accidentally marked earlier but wasn't
// marked by the current trace.
bool keep = shared->marked() &&
- IsMarked(&shared->source);
+ IsMarked(rt, &shared->source);
for (size_t i = 0; i < ArrayLength(shared->compilationArray); i++) {
RegExpShared::RegExpCompilation& compilation = shared->compilationArray[i];
if (compilation.jitCode &&
diff --git a/src/third_party/mozjs-45/extract/js/src/vm/Runtime.cpp b/src/third_party/mozjs-45/extract/js/src/vm/Runtime.cpp
index 94909a2ed47..a3a3fda4158 100644
--- a/src/third_party/mozjs-45/extract/js/src/vm/Runtime.cpp
+++ b/src/third_party/mozjs-45/extract/js/src/vm/Runtime.cpp
@@ -311,6 +311,7 @@ JSRuntime::init(uint32_t maxbytes, uint32_t maxNurseryBytes)
return false;
atomsCompartment->setIsSystem(true);
+ atomsCompartment->setIsAtomsCompartment();
atomsZone.forget();
this->atomsCompartment_ = atomsCompartment.forget();
@@ -745,6 +746,32 @@ JSRuntime::triggerActivityCallback(bool active)
activityCallback(activityCallbackArg, active);
}
+mozilla::non_crypto::XorShift128PlusRNG&
+JSRuntime::randomKeyGenerator()
+{
+ MOZ_ASSERT(CurrentThreadCanAccessRuntime(this));
+ if (randomKeyGenerator_.isNothing()) {
+ mozilla::Array<uint64_t, 2> seed;
+ GenerateXorShift128PlusSeed(seed);
+ randomKeyGenerator_.emplace(seed[0], seed[1]);
+ }
+ return randomKeyGenerator_.ref();
+}
+
+mozilla::HashCodeScrambler
+JSRuntime::randomHashCodeScrambler()
+{
+ auto& rng = randomKeyGenerator();
+ return mozilla::HashCodeScrambler(rng.next(), rng.next());
+}
+
+mozilla::non_crypto::XorShift128PlusRNG
+JSRuntime::forkRandomKeyGenerator()
+{
+ auto& rng = randomKeyGenerator();
+ return mozilla::non_crypto::XorShift128PlusRNG(rng.next(), rng.next());
+}
+
void
JSRuntime::updateMallocCounter(size_t nbytes)
{
diff --git a/src/third_party/mozjs-45/extract/js/src/vm/Runtime.h b/src/third_party/mozjs-45/extract/js/src/vm/Runtime.h
index 51734df147a..9df53087c03 100644
--- a/src/third_party/mozjs-45/extract/js/src/vm/Runtime.h
+++ b/src/third_party/mozjs-45/extract/js/src/vm/Runtime.h
@@ -949,6 +949,15 @@ struct JSRuntime : public JS::shadow::Runtime,
return interpreterStack_;
}
+ private:
+ // Used to generate random keys for hash tables.
+ mozilla::Maybe<mozilla::non_crypto::XorShift128PlusRNG> randomKeyGenerator_;
+ mozilla::non_crypto::XorShift128PlusRNG& randomKeyGenerator();
+
+ public:
+ mozilla::HashCodeScrambler randomHashCodeScrambler();
+ mozilla::non_crypto::XorShift128PlusRNG forkRandomKeyGenerator();
+
//-------------------------------------------------------------------------
// Self-hosting support
//-------------------------------------------------------------------------
diff --git a/src/third_party/mozjs-45/extract/js/src/vm/Shape.h b/src/third_party/mozjs-45/extract/js/src/vm/Shape.h
index 51185898d80..1c2c99a1feb 100644
--- a/src/third_party/mozjs-45/extract/js/src/vm/Shape.h
+++ b/src/third_party/mozjs-45/extract/js/src/vm/Shape.h
@@ -29,6 +29,8 @@
#include "js/RootingAPI.h"
#include "js/UbiNode.h"
#include "vm/ObjectGroup.h"
+#include "vm/String.h"
+#include "vm/Symbol.h"
#ifdef _MSC_VER
#pragma warning(push)
@@ -516,11 +518,33 @@ struct StackBaseShape : public DefaultHasher<ReadBarriered<UnownedBaseShape*>>
static inline bool match(ReadBarriered<UnownedBaseShape*> key, const Lookup& lookup);
};
+static MOZ_ALWAYS_INLINE js::HashNumber
+HashId(jsid id)
+{
+ // HashGeneric alone would work, but bits of atom and symbol addresses
+ // could then be recovered from the hash code. See bug 1330769.
+ if (MOZ_LIKELY(JSID_IS_ATOM(id)))
+ return JSID_TO_ATOM(id)->hash();
+ if (JSID_IS_SYMBOL(id))
+ return JSID_TO_SYMBOL(id)->hash();
+ return mozilla::HashGeneric(JSID_BITS(id));
+}
+
+struct JsidHasher
+{
+ typedef jsid Lookup;
+ static HashNumber hash(jsid id) {
+ return HashId(id);
+ }
+ static bool match(jsid id1, jsid id2) {
+ return id1 == id2;
+ }
+};
+
typedef HashSet<ReadBarriered<UnownedBaseShape*>,
StackBaseShape,
SystemAllocPolicy> BaseShapeSet;
-
class Shape : public gc::TenuredCell
{
friend class ::JSObject;
@@ -1172,7 +1196,7 @@ struct StackShape : public JS::Traceable
/* Accumulate from least to most random so the low bits are most random. */
hash = mozilla::RotateLeft(hash, 4) ^ attrs;
hash = mozilla::RotateLeft(hash, 4) ^ slot_;
- hash = mozilla::RotateLeft(hash, 4) ^ JSID_BITS(propid);
+ hash = mozilla::RotateLeft(hash, 4) ^ HashId(propid);
hash = mozilla::RotateLeft(hash, 4) ^ uintptr_t(rawGetter);
hash = mozilla::RotateLeft(hash, 4) ^ uintptr_t(rawSetter);
return hash;
diff --git a/src/third_party/mozjs-45/extract/js/src/vm/String-inl.h b/src/third_party/mozjs-45/extract/js/src/vm/String-inl.h
index b4676d344d0..0e95063f21a 100644
--- a/src/third_party/mozjs-45/extract/js/src/vm/String-inl.h
+++ b/src/third_party/mozjs-45/extract/js/src/vm/String-inl.h
@@ -13,6 +13,7 @@
#include "mozilla/Range.h"
#include "jscntxt.h"
+#include "jscompartment.h"
#include "gc/Allocator.h"
#include "gc/Marking.h"
@@ -220,7 +221,11 @@ JSFlatString::new_(js::ExclusiveContext* cx, const CharT* chars, size_t length)
if (!validateLength(cx, length))
return nullptr;
- JSFlatString* str = static_cast<JSFlatString*>(js::Allocate<JSString, allowGC>(cx));
+ JSFlatString* str;
+ if (cx->compartment()->isAtomsCompartment())
+ str = js::Allocate<js::NormalAtom, allowGC>(cx);
+ else
+ str = static_cast<JSFlatString*>(js::Allocate<JSString, allowGC>(cx));
if (!str)
return nullptr;
@@ -247,6 +252,9 @@ template <js::AllowGC allowGC>
MOZ_ALWAYS_INLINE JSThinInlineString*
JSThinInlineString::new_(js::ExclusiveContext* cx)
{
+ if (cx->compartment()->isAtomsCompartment())
+ return (JSThinInlineString*)(js::Allocate<js::NormalAtom, allowGC>(cx));
+
return static_cast<JSThinInlineString*>(js::Allocate<JSString, allowGC>(cx));
}
@@ -254,6 +262,9 @@ template <js::AllowGC allowGC>
MOZ_ALWAYS_INLINE JSFatInlineString*
JSFatInlineString::new_(js::ExclusiveContext* cx)
{
+ if (cx->compartment()->isAtomsCompartment())
+ return (JSFatInlineString*)(js::Allocate<js::FatInlineAtom, allowGC>(cx));
+
return js::Allocate<JSFatInlineString, allowGC>(cx);
}
@@ -351,6 +362,7 @@ JSString::finalize(js::FreeOp* fop)
{
/* FatInline strings are in a different arena. */
MOZ_ASSERT(getAllocKind() != js::gc::AllocKind::FAT_INLINE_STRING);
+ MOZ_ASSERT(getAllocKind() != js::gc::AllocKind::FAT_INLINE_ATOM);
if (isFlat())
asFlat().finalize(fop);
@@ -362,6 +374,7 @@ inline void
JSFlatString::finalize(js::FreeOp* fop)
{
MOZ_ASSERT(getAllocKind() != js::gc::AllocKind::FAT_INLINE_STRING);
+ MOZ_ASSERT(getAllocKind() != js::gc::AllocKind::FAT_INLINE_ATOM);
if (!isInline())
fop->free_(nonInlineCharsRaw());
@@ -381,6 +394,8 @@ JSAtom::finalize(js::FreeOp* fop)
{
MOZ_ASSERT(JSString::isAtom());
MOZ_ASSERT(JSString::isFlat());
+ MOZ_ASSERT(getAllocKind() == js::gc::AllocKind::ATOM ||
+ getAllocKind() == js::gc::AllocKind::FAT_INLINE_ATOM);
if (!isInline())
fop->free_(nonInlineCharsRaw());
diff --git a/src/third_party/mozjs-45/extract/js/src/vm/String.cpp b/src/third_party/mozjs-45/extract/js/src/vm/String.cpp
index e5a315fbfc3..1bbe151c015 100644
--- a/src/third_party/mozjs-45/extract/js/src/vm/String.cpp
+++ b/src/third_party/mozjs-45/extract/js/src/vm/String.cpp
@@ -71,8 +71,12 @@ JSString::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)
JS::ubi::Node::Size
JS::ubi::Concrete<JSString>::size(mozilla::MallocSizeOf mallocSizeOf) const
{
- JSString &str = get();
- size_t size = str.isFatInline() ? sizeof(JSFatInlineString) : sizeof(JSString);
+ JSString& str = get();
+ size_t size;
+ if (str.isAtom())
+ size = str.isFatInline() ? sizeof(js::FatInlineAtom) : sizeof(js::NormalAtom);
+ else
+ size = str.isFatInline() ? sizeof(JSFatInlineString) : sizeof(JSString);
// We can't use mallocSizeof on things in the nursery. At the moment,
// strings are never in the nursery, but that may change.
@@ -789,7 +793,8 @@ StaticStrings::init(JSContext* cx)
JSFlatString* s = NewStringCopyN<NoGC>(cx, buffer, 1);
if (!s)
return false;
- unitStaticTable[i] = s->morphAtomizedStringIntoPermanentAtom();
+ HashNumber hash = mozilla::HashString(buffer, 1);
+ unitStaticTable[i] = s->morphAtomizedStringIntoPermanentAtom(hash);
}
for (uint32_t i = 0; i < NUM_SMALL_CHARS * NUM_SMALL_CHARS; i++) {
@@ -797,7 +802,8 @@ StaticStrings::init(JSContext* cx)
JSFlatString* s = NewStringCopyN<NoGC>(cx, buffer, 2);
if (!s)
return false;
- length2StaticTable[i] = s->morphAtomizedStringIntoPermanentAtom();
+ HashNumber hash = mozilla::HashString(buffer, 2);
+ length2StaticTable[i] = s->morphAtomizedStringIntoPermanentAtom(hash);
}
for (uint32_t i = 0; i < INT_STATIC_LIMIT; i++) {
@@ -815,7 +821,8 @@ StaticStrings::init(JSContext* cx)
JSFlatString* s = NewStringCopyN<NoGC>(cx, buffer, 3);
if (!s)
return false;
- intStaticTable[i] = s->morphAtomizedStringIntoPermanentAtom();
+ HashNumber hash = mozilla::HashString(buffer, 3);
+ intStaticTable[i] = s->morphAtomizedStringIntoPermanentAtom(hash);
}
}
diff --git a/src/third_party/mozjs-45/extract/js/src/vm/String.h b/src/third_party/mozjs-45/extract/js/src/vm/String.h
index e788aadbe14..80466681507 100644
--- a/src/third_party/mozjs-45/extract/js/src/vm/String.h
+++ b/src/third_party/mozjs-45/extract/js/src/vm/String.h
@@ -123,7 +123,11 @@ static const size_t UINT32_CHAR_BUFFER_LENGTH = sizeof("4294967295") - 1;
* | |
* | +-- JSFatInlineString - / header is fat
* |
- * JSAtom - / string equality === pointer equality
+ * JSAtom (abstract) - / string equality === pointer equality
+ * | |
+ * | +-- js::NormalAtom - JSFlatString + atom hash code
+ * | |
+ * | +-- js::FatInlineAtom - JSFatInlineString + atom hash code
* |
* js::PropertyName - / chars don't contain an index (uint32_t)
*
@@ -135,10 +139,9 @@ static const size_t UINT32_CHAR_BUFFER_LENGTH = sizeof("4294967295") - 1;
* Atoms can additionally be permanent, i.e. unable to be collected, and can
* be combined with other string types to create additional most-derived types
* that satisfy the invariants of more than one of the abovementioned
- * most-derived types:
- * - InlineAtom = JSInlineString + JSAtom (atom with inline chars, abstract)
- * - ThinInlineAtom = JSThinInlineString + JSAtom (atom with inline chars)
- * - FatInlineAtom = JSFatInlineString + JSAtom (atom with (more) inline chars)
+ * most-derived types. Furthermore, each atom stores a hash number (based on its
+ * chars). This hash number is used as key in the atoms table and when the atom
+ * is used as key in a JS Map/Set.
*
* Derived string types can be queried from ancestor types via isX() and
* retrieved with asX() debug-only-checked casts.
@@ -765,14 +768,8 @@ class JSFlatString : public JSLinearString
* Once a JSFlatString sub-class has been added to the atom state, this
* operation changes the string to the JSAtom type, in place.
*/
- MOZ_ALWAYS_INLINE JSAtom* morphAtomizedStringIntoAtom() {
- d.u1.flags |= ATOM_BIT;
- return &asAtom();
- }
- MOZ_ALWAYS_INLINE JSAtom* morphAtomizedStringIntoPermanentAtom() {
- d.u1.flags |= PERMANENT_ATOM_MASK;
- return &asAtom();
- }
+ MOZ_ALWAYS_INLINE JSAtom* morphAtomizedStringIntoAtom(js::HashNumber hash);
+ MOZ_ALWAYS_INLINE JSAtom* morphAtomizedStringIntoPermanentAtom(js::HashNumber hash);
inline void finalize(js::FreeOp* fop);
@@ -984,6 +981,9 @@ class JSAtom : public JSFlatString
d.u1.flags |= PERMANENT_ATOM_MASK;
}
+ inline js::HashNumber hash() const;
+ inline void initHash(js::HashNumber hash);
+
#ifdef DEBUG
void dump();
#endif
@@ -994,6 +994,83 @@ static_assert(sizeof(JSAtom) == sizeof(JSString),
namespace js {
+class NormalAtom : public JSAtom
+{
+ protected: // Silence Clang unused-field warning.
+ HashNumber hash_;
+ uint32_t padding_; // Ensure the size is a multiple of gc::CellSize.
+
+ public:
+ HashNumber hash() const {
+ return hash_;
+ }
+ void initHash(HashNumber hash) {
+ hash_ = hash;
+ }
+};
+
+static_assert(sizeof(NormalAtom) == sizeof(JSString) + sizeof(uint64_t),
+ "NormalAtom must have size of a string + HashNumber, "
+ "aligned to gc::CellSize");
+
+class FatInlineAtom : public JSAtom
+{
+ protected: // Silence Clang unused-field warning.
+ char inlineStorage_[sizeof(JSFatInlineString) - sizeof(JSString)];
+ HashNumber hash_;
+ uint32_t padding_; // Ensure the size is a multiple of gc::CellSize.
+
+ public:
+ HashNumber hash() const {
+ return hash_;
+ }
+ void initHash(HashNumber hash) {
+ hash_ = hash;
+ }
+};
+
+static_assert(sizeof(FatInlineAtom) == sizeof(JSFatInlineString) + sizeof(uint64_t),
+ "FatInlineAtom must have size of a fat inline string + HashNumber, "
+ "aligned to gc::CellSize");
+
+} // namespace js
+
+inline js::HashNumber
+JSAtom::hash() const
+{
+ if (isFatInline())
+ return static_cast<const js::FatInlineAtom*>(this)->hash();
+ return static_cast<const js::NormalAtom*>(this)->hash();
+}
+
+inline void
+JSAtom::initHash(js::HashNumber hash)
+{
+ if (isFatInline())
+ return static_cast<js::FatInlineAtom*>(this)->initHash(hash);
+ return static_cast<js::NormalAtom*>(this)->initHash(hash);
+}
+
+MOZ_ALWAYS_INLINE JSAtom*
+JSFlatString::morphAtomizedStringIntoAtom(js::HashNumber hash)
+{
+ d.u1.flags |= ATOM_BIT;
+ JSAtom* atom = &asAtom();
+ atom->initHash(hash);
+ return atom;
+}
+
+MOZ_ALWAYS_INLINE JSAtom*
+JSFlatString::morphAtomizedStringIntoPermanentAtom(js::HashNumber hash)
+{
+ d.u1.flags |= PERMANENT_ATOM_MASK;
+ JSAtom* atom = &asAtom();
+ atom->initHash(hash);
+ return atom;
+}
+
+namespace js {
+
class StaticStrings
{
private:
@@ -1187,6 +1264,8 @@ NewStringCopyZ(js::ExclusiveContext* cx, const char* s)
return NewStringCopyN<allowGC>(cx, s, strlen(s));
}
+JS_STATIC_ASSERT(sizeof(HashNumber) == 4);
+
} /* namespace js */
// Addon IDs are interned atoms which are never destroyed. This detail is
diff --git a/src/third_party/mozjs-45/extract/js/src/vm/Symbol.cpp b/src/third_party/mozjs-45/extract/js/src/vm/Symbol.cpp
index dfe6278d140..c1ec8892bf0 100644
--- a/src/third_party/mozjs-45/extract/js/src/vm/Symbol.cpp
+++ b/src/third_party/mozjs-45/extract/js/src/vm/Symbol.cpp
@@ -20,7 +20,7 @@ using JS::Symbol;
using namespace js;
Symbol*
-Symbol::newInternal(ExclusiveContext* cx, JS::SymbolCode code, JSAtom* description)
+Symbol::newInternal(ExclusiveContext* cx, JS::SymbolCode code, uint32_t hash, JSAtom* description)
{
MOZ_ASSERT(cx->compartment() == cx->atomsCompartment());
MOZ_ASSERT(cx->atomsCompartment()->runtimeFromAnyThread()->currentThreadHasExclusiveAccess());
@@ -31,7 +31,7 @@ Symbol::newInternal(ExclusiveContext* cx, JS::SymbolCode code, JSAtom* descripti
ReportOutOfMemory(cx);
return nullptr;
}
- return new (p) Symbol(code, description);
+ return new (p) Symbol(code, hash, description);
}
Symbol*
@@ -48,7 +48,7 @@ Symbol::new_(ExclusiveContext* cx, JS::SymbolCode code, JSString* description)
// probably be replaced with an assertion that we're on the main thread.
AutoLockForExclusiveAccess lock(cx);
AutoCompartment ac(cx, cx->atomsCompartment());
- return newInternal(cx, code, atom);
+ return newInternal(cx, code, cx->compartment()->randomHashCode(), atom);
}
Symbol*
@@ -66,7 +66,7 @@ Symbol::for_(js::ExclusiveContext* cx, HandleString description)
return *p;
AutoCompartment ac(cx, cx->atomsCompartment());
- Symbol* sym = newInternal(cx, SymbolCode::InSymbolRegistry, atom);
+ Symbol* sym = newInternal(cx, SymbolCode::InSymbolRegistry, atom->hash(), atom);
if (!sym)
return nullptr;
diff --git a/src/third_party/mozjs-45/extract/js/src/vm/Symbol.h b/src/third_party/mozjs-45/extract/js/src/vm/Symbol.h
index c201ed127c5..e39a490662f 100644
--- a/src/third_party/mozjs-45/extract/js/src/vm/Symbol.h
+++ b/src/third_party/mozjs-45/extract/js/src/vm/Symbol.h
@@ -16,10 +16,11 @@
#include "gc/Barrier.h"
#include "gc/Marking.h"
-
#include "js/GCHashTable.h"
#include "js/RootingAPI.h"
#include "js/TypeDecls.h"
+#include "js/Utility.h"
+#include "vm/String.h"
namespace JS {
@@ -27,25 +28,31 @@ class Symbol : public js::gc::TenuredCell
{
private:
SymbolCode code_;
+
+ // Each Symbol gets its own hash code so that we don't have to use
+ // addresses as hash codes (a security hazard).
+ js::HashNumber hash_;
+
JSAtom* description_;
// The minimum allocation size is sizeof(JSString): 16 bytes on 32-bit
- // architectures and 24 bytes on 64-bit. 8 bytes of padding makes Symbol
+ // architectures and 24 bytes on 64-bit. A size_t of padding makes Symbol
// the minimum size on both.
- uint64_t unused2_;
+ size_t unused_;
- Symbol(SymbolCode code, JSAtom* desc)
- : code_(code), description_(desc)
+ Symbol(SymbolCode code, js::HashNumber hash, JSAtom* desc)
+ : code_(code), hash_(hash), description_(desc)
{
- // Silence warnings about unused2 being... unused.
- (void)unused2_;
+ // Silence warnings about unused_ being... unused.
+ (void)unused_;
}
Symbol(const Symbol&) = delete;
void operator=(const Symbol&) = delete;
static Symbol*
- newInternal(js::ExclusiveContext* cx, SymbolCode code, JSAtom* description);
+ newInternal(js::ExclusiveContext* cx, SymbolCode code, js::HashNumber hash,
+ JSAtom* description);
public:
static Symbol* new_(js::ExclusiveContext* cx, SymbolCode code, JSString* description);
@@ -53,6 +60,7 @@ class Symbol : public js::gc::TenuredCell
JSAtom* description() const { return description_; }
SymbolCode code() const { return code_; }
+ js::HashNumber hash() const { return hash_; }
bool isWellKnownSymbol() const { return uint32_t(code_) < WellKnownSymbolLimit; }
@@ -88,7 +96,7 @@ struct HashSymbolsByDescription
typedef JSAtom* Lookup;
static HashNumber hash(Lookup l) {
- return HashNumber(reinterpret_cast<uintptr_t>(l));
+ return HashNumber(l->hash());
}
static bool match(Key sym, Lookup l) {
return sym->description() == l;
diff --git a/src/third_party/mozjs-45/extract/js/src/vm/TypeInference.cpp b/src/third_party/mozjs-45/extract/js/src/vm/TypeInference.cpp
index b289cfd62a7..2738145960c 100644
--- a/src/third_party/mozjs-45/extract/js/src/vm/TypeInference.cpp
+++ b/src/third_party/mozjs-45/extract/js/src/vm/TypeInference.cpp
@@ -749,16 +749,16 @@ TypeSet::readBarrier(const TypeSet* types)
}
/* static */ bool
-TypeSet::IsTypeMarked(TypeSet::Type* v)
+TypeSet::IsTypeMarked(JSRuntime* rt, TypeSet::Type* v)
{
bool rv;
if (v->isSingletonUnchecked()) {
JSObject* obj = v->singletonNoBarrier();
- rv = IsMarkedUnbarriered(&obj);
+ rv = IsMarkedUnbarriered(rt, &obj);
*v = TypeSet::ObjectType(obj);
} else if (v->isGroupUnchecked()) {
ObjectGroup* group = v->groupNoBarrier();
- rv = IsMarkedUnbarriered(&group);
+ rv = IsMarkedUnbarriered(rt, &group);
*v = TypeSet::ObjectType(group);
} else {
rv = true;
@@ -4192,6 +4192,10 @@ ObjectGroup::sweep(AutoClearTypeInferenceStateOnOOM* oom)
if (unboxedLayout().newScript())
unboxedLayout().newScript()->sweep();
+
+ // Discard constructor code to avoid holding onto ExecutablePools.
+ if (zone()->isGCCompacting())
+ unboxedLayout().setConstructorCode(nullptr);
}
if (maybePreliminaryObjects())
diff --git a/src/third_party/mozjs-45/extract/js/src/vm/TypeInference.h b/src/third_party/mozjs-45/extract/js/src/vm/TypeInference.h
index 7e647c0fe25..2f85f8620a7 100644
--- a/src/third_party/mozjs-45/extract/js/src/vm/TypeInference.h
+++ b/src/third_party/mozjs-45/extract/js/src/vm/TypeInference.h
@@ -532,7 +532,7 @@ class TypeSet
static void MarkTypeRoot(JSTracer* trc, Type* v, const char* name);
static void MarkTypeUnbarriered(JSTracer* trc, Type* v, const char* name);
- static bool IsTypeMarked(Type* v);
+ static bool IsTypeMarked(JSRuntime* rt, Type* v);
static bool IsTypeAllocatedDuringIncremental(Type v);
static bool IsTypeAboutToBeFinalized(Type* v);
};
diff --git a/src/third_party/mozjs-45/extract/js/src/vm/TypedArrayObject.cpp b/src/third_party/mozjs-45/extract/js/src/vm/TypedArrayObject.cpp
index a3c8a902581..7f92aab6da9 100644
--- a/src/third_party/mozjs-45/extract/js/src/vm/TypedArrayObject.cpp
+++ b/src/third_party/mozjs-45/extract/js/src/vm/TypedArrayObject.cpp
@@ -1032,6 +1032,11 @@ DataViewObject*
DataViewObject::create(JSContext* cx, uint32_t byteOffset, uint32_t byteLength,
Handle<ArrayBufferObject*> arrayBuffer, JSObject* protoArg)
{
+ if (arrayBuffer->isNeutered()) {
+ JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_DETACHED);
+ return nullptr;
+ }
+
MOZ_ASSERT(byteOffset <= INT32_MAX);
MOZ_ASSERT(byteLength <= INT32_MAX);
MOZ_ASSERT(byteOffset + byteLength < UINT32_MAX);
@@ -2264,36 +2269,50 @@ js::DefineTypedArrayElement(JSContext* cx, HandleObject obj, uint64_t index,
{
MOZ_ASSERT(IsAnyTypedArray(obj));
- // These are all substeps of 3.c.
- // Steps i-vi.
+ // These are all substeps of 3.b.
+
+ // Steps i-iii are handled by the caller.
+
+ // Steps iv-v.
// We (wrongly) ignore out of range defines with a value.
- if (index >= AnyTypedArrayLength(obj))
+ uint32_t length = AnyTypedArrayLength(obj);
+ if (index >= length)
return result.succeed();
- // Step vii.
+ // Step vi.
if (desc.isAccessorDescriptor())
return result.fail(JSMSG_CANT_REDEFINE_PROP);
- // Step viii.
+ // Step vii.
if (desc.hasConfigurable() && desc.configurable())
return result.fail(JSMSG_CANT_REDEFINE_PROP);
- // Step ix.
+ // Step viii.
if (desc.hasEnumerable() && !desc.enumerable())
return result.fail(JSMSG_CANT_REDEFINE_PROP);
- // Step x.
+ // Step ix.
if (desc.hasWritable() && !desc.writable())
return result.fail(JSMSG_CANT_REDEFINE_PROP);
- // Step xi.
+ // Step x.
if (desc.hasValue()) {
- double d;
- if (!ToNumber(cx, desc.value(), &d))
+ // The following step numbers refer to 9.4.5.9
+ // IntegerIndexedElementSet.
+
+ // Steps 1-2 are enforced by the caller.
+
+ // Step 3.
+ double numValue;
+ if (!ToNumber(cx, desc.value(), &numValue))
return false;
- if (obj->is<TypedArrayObject>())
- TypedArrayObject::setElement(obj->as<TypedArrayObject>(), index, d);
+ // Steps 4-5, 8-9.
+ if (AnyTypedArrayIsDetached(obj))
+ return result.fail(JSMSG_TYPED_ARRAY_DETACHED);
+
+ // Steps 10-16.
+ TypedArrayObject::setElement(obj->as<TypedArrayObject>(), index, numValue);
}
// Step xii.
diff --git a/src/third_party/mozjs-45/extract/js/src/vm/UnboxedObject.cpp b/src/third_party/mozjs-45/extract/js/src/vm/UnboxedObject.cpp
index 504a5c418c4..f1b377d57b4 100644
--- a/src/third_party/mozjs-45/extract/js/src/vm/UnboxedObject.cpp
+++ b/src/third_party/mozjs-45/extract/js/src/vm/UnboxedObject.cpp
@@ -7,6 +7,7 @@
#include "vm/UnboxedObject-inl.h"
#include "jit/BaselineIC.h"
+#include "jit/ExecutableAllocator.h"
#include "jit/JitCommon.h"
#include "jit/Linker.h"
@@ -698,7 +699,8 @@ UnboxedPlainObject::createWithProperties(ExclusiveContext* cx, HandleObjectGroup
#ifndef JS_CODEGEN_NONE
if (cx->isJSContext() &&
!layout.constructorCode() &&
- cx->asJSContext()->runtime()->jitSupportsFloatingPoint)
+ cx->asJSContext()->runtime()->jitSupportsFloatingPoint &&
+ jit::CanLikelyAllocateMoreExecutableMemory())
{
if (!UnboxedLayout::makeConstructorCode(cx->asJSContext(), group))
return nullptr;
diff --git a/src/third_party/mozjs-45/extract/mfbt/HashFunctions.h b/src/third_party/mozjs-45/extract/mfbt/HashFunctions.h
index f490a28fee4..8eb83a3737c 100644
--- a/src/third_party/mozjs-45/extract/mfbt/HashFunctions.h
+++ b/src/third_party/mozjs-45/extract/mfbt/HashFunctions.h
@@ -50,6 +50,7 @@
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/Char16.h"
+#include "mozilla/MathAlgorithms.h"
#include "mozilla/Types.h"
#include <stdint.h>
@@ -312,6 +313,90 @@ HashString(const wchar_t* aStr, size_t aLength)
MOZ_WARN_UNUSED_RESULT extern MFBT_API uint32_t
HashBytes(const void* bytes, size_t aLength);
+/**
+ * A pseudorandom function mapping 32-bit integers to 32-bit integers.
+ *
+ * This is for when you're feeding private data (like pointer values or credit
+ * card numbers) to a non-crypto hash function (like HashBytes) and then using
+ * the hash code for something that untrusted parties could observe (like a JS
+ * Map). Plug in a HashCodeScrambler before that last step to avoid leaking the
+ * private data.
+ *
+ * By itself, this does not prevent hash-flooding DoS attacks, because an
+ * attacker can still generate many values with exactly equal hash codes by
+ * attacking the non-crypto hash function alone. Equal hash codes will, of
+ * course, still be equal however much you scramble them.
+ *
+ * The algorithm is SipHash-1-3. See <https://131002.net/siphash/>.
+ */
+class HashCodeScrambler
+{
+ struct SipHasher;
+
+ uint64_t mK0, mK1;
+
+public:
+ /** Creates a new scrambler with the given 128-bit key. */
+ HashCodeScrambler(uint64_t aK0, uint64_t aK1) : mK0(aK0), mK1(aK1) {}
+
+ /**
+ * Scramble a hash code. Always produces the same result for the same
+ * combination of key and hash code.
+ */
+ uint32_t scramble(uint32_t aHashCode) const
+ {
+ SipHasher hasher(mK0, mK1);
+ return uint32_t(hasher.sipHash(aHashCode));
+ }
+
+private:
+ struct SipHasher
+ {
+ SipHasher(uint64_t aK0, uint64_t aK1)
+ {
+ // 1. Initialization.
+ mV0 = aK0 ^ UINT64_C(0x736f6d6570736575);
+ mV1 = aK1 ^ UINT64_C(0x646f72616e646f6d);
+ mV2 = aK0 ^ UINT64_C(0x6c7967656e657261);
+ mV3 = aK1 ^ UINT64_C(0x7465646279746573);
+ }
+
+ uint64_t sipHash(uint64_t aM)
+ {
+ // 2. Compression.
+ mV3 ^= aM;
+ sipRound();
+ mV0 ^= aM;
+
+ // 3. Finalization.
+ mV2 ^= 0xff;
+ for (int i = 0; i < 3; i++)
+ sipRound();
+ return mV0 ^ mV1 ^ mV2 ^ mV3;
+ }
+
+ void sipRound()
+ {
+ mV0 += mV1;
+ mV1 = RotateLeft(mV1, 13);
+ mV1 ^= mV0;
+ mV0 = RotateLeft(mV0, 32);
+ mV2 += mV3;
+ mV3 = RotateLeft(mV3, 16);
+ mV3 ^= mV2;
+ mV0 += mV3;
+ mV3 = RotateLeft(mV3, 21);
+ mV3 ^= mV0;
+ mV2 += mV1;
+ mV1 = RotateLeft(mV1, 17);
+ mV1 ^= mV2;
+ mV2 = RotateLeft(mV2, 32);
+ }
+
+ uint64_t mV0, mV1, mV2, mV3;
+ };
+};
+
} /* namespace mozilla */
#endif /* __cplusplus */
diff --git a/src/third_party/mozjs-45/get-sources.sh b/src/third_party/mozjs-45/get-sources.sh
index 39acace54e5..089a52d2793 100644
--- a/src/third_party/mozjs-45/get-sources.sh
+++ b/src/third_party/mozjs-45/get-sources.sh
@@ -2,7 +2,7 @@
# how we got the last firefox sources
-VERSION=45.5.0esr
+VERSION=45.8.0esr
TARBALL=firefox-$VERSION.source.tar.xz
if [ ! -f $TARBALL ]; then
wget "https://ftp.mozilla.org/pub/mozilla.org/firefox/releases/$VERSION/source/$TARBALL"
diff --git a/src/third_party/mozjs-45/include/js/GCAPI.h b/src/third_party/mozjs-45/include/js/GCAPI.h
index 90f8e4eba3f..84b6150c36f 100644
--- a/src/third_party/mozjs-45/include/js/GCAPI.h
+++ b/src/third_party/mozjs-45/include/js/GCAPI.h
@@ -566,8 +566,6 @@ namespace gc {
static MOZ_ALWAYS_INLINE void
ExposeGCThingToActiveJS(JS::GCCellPtr thing)
{
- MOZ_ASSERT(thing.kind() != JS::TraceKind::Shape);
-
/*
* GC things residing in the nursery cannot be gray: they have no mark bits.
* All live objects in the nursery are moved to tenured at the beginning of
diff --git a/src/third_party/mozjs-45/include/mozilla/HashFunctions.h b/src/third_party/mozjs-45/include/mozilla/HashFunctions.h
index f490a28fee4..8eb83a3737c 100644
--- a/src/third_party/mozjs-45/include/mozilla/HashFunctions.h
+++ b/src/third_party/mozjs-45/include/mozilla/HashFunctions.h
@@ -50,6 +50,7 @@
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/Char16.h"
+#include "mozilla/MathAlgorithms.h"
#include "mozilla/Types.h"
#include <stdint.h>
@@ -312,6 +313,90 @@ HashString(const wchar_t* aStr, size_t aLength)
MOZ_WARN_UNUSED_RESULT extern MFBT_API uint32_t
HashBytes(const void* bytes, size_t aLength);
+/**
+ * A pseudorandom function mapping 32-bit integers to 32-bit integers.
+ *
+ * This is for when you're feeding private data (like pointer values or credit
+ * card numbers) to a non-crypto hash function (like HashBytes) and then using
+ * the hash code for something that untrusted parties could observe (like a JS
+ * Map). Plug in a HashCodeScrambler before that last step to avoid leaking the
+ * private data.
+ *
+ * By itself, this does not prevent hash-flooding DoS attacks, because an
+ * attacker can still generate many values with exactly equal hash codes by
+ * attacking the non-crypto hash function alone. Equal hash codes will, of
+ * course, still be equal however much you scramble them.
+ *
+ * The algorithm is SipHash-1-3. See <https://131002.net/siphash/>.
+ */
+class HashCodeScrambler
+{
+ struct SipHasher;
+
+ uint64_t mK0, mK1;
+
+public:
+ /** Creates a new scrambler with the given 128-bit key. */
+ HashCodeScrambler(uint64_t aK0, uint64_t aK1) : mK0(aK0), mK1(aK1) {}
+
+ /**
+ * Scramble a hash code. Always produces the same result for the same
+ * combination of key and hash code.
+ */
+ uint32_t scramble(uint32_t aHashCode) const
+ {
+ SipHasher hasher(mK0, mK1);
+ return uint32_t(hasher.sipHash(aHashCode));
+ }
+
+private:
+ struct SipHasher
+ {
+ SipHasher(uint64_t aK0, uint64_t aK1)
+ {
+ // 1. Initialization.
+ mV0 = aK0 ^ UINT64_C(0x736f6d6570736575);
+ mV1 = aK1 ^ UINT64_C(0x646f72616e646f6d);
+ mV2 = aK0 ^ UINT64_C(0x6c7967656e657261);
+ mV3 = aK1 ^ UINT64_C(0x7465646279746573);
+ }
+
+ uint64_t sipHash(uint64_t aM)
+ {
+ // 2. Compression.
+ mV3 ^= aM;
+ sipRound();
+ mV0 ^= aM;
+
+ // 3. Finalization.
+ mV2 ^= 0xff;
+ for (int i = 0; i < 3; i++)
+ sipRound();
+ return mV0 ^ mV1 ^ mV2 ^ mV3;
+ }
+
+ void sipRound()
+ {
+ mV0 += mV1;
+ mV1 = RotateLeft(mV1, 13);
+ mV1 ^= mV0;
+ mV0 = RotateLeft(mV0, 32);
+ mV2 += mV3;
+ mV3 = RotateLeft(mV3, 16);
+ mV3 ^= mV2;
+ mV0 += mV3;
+ mV3 = RotateLeft(mV3, 21);
+ mV3 ^= mV0;
+ mV2 += mV1;
+ mV1 = RotateLeft(mV1, 17);
+ mV1 ^= mV2;
+ mV2 = RotateLeft(mV2, 32);
+ }
+
+ uint64_t mV0, mV1, mV2, mV3;
+ };
+};
+
} /* namespace mozilla */
#endif /* __cplusplus */
diff --git a/src/third_party/mozjs-45/mongo_patches/SERVER-28400-Solaris_MAP_NORESERVE.patch b/src/third_party/mozjs-45/mongo_patches/SERVER-28400-Solaris_MAP_NORESERVE.patch
new file mode 100644
index 00000000000..99ef9ad9d5c
--- /dev/null
+++ b/src/third_party/mozjs-45/mongo_patches/SERVER-28400-Solaris_MAP_NORESERVE.patch
@@ -0,0 +1,18 @@
+--- a/src/third_party/mozjs-45/extract/js/src/jit/ProcessExecutableMemory.cpp
++++ b/src/third_party/mozjs-45/extract/js/src/jit/ProcessExecutableMemory.cpp
+@@ -266,8 +266,15 @@ ReserveProcessExecutableMemory(size_t bytes)
+ // Note that randomAddr is just a hint: if the address is not available
+ // mmap will pick a different address.
+ void* randomAddr = ComputeRandomAllocationAddress();
++#ifdef SOLARIS
++ // Do not reserve swap space for the entire allocation. Regardless of what mmap(2) says,
++ // Solaris reserves swap space even though this allocation is not marked as writable.
++ void* p = MozTaggedAnonymousMmap(randomAddr, bytes, PROT_NONE, MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
++ -1, 0, "js-executable-memory");
++#else
+ void* p = MozTaggedAnonymousMmap(randomAddr, bytes, PROT_NONE, MAP_PRIVATE | MAP_ANON,
+ -1, 0, "js-executable-memory");
++#endif
+ if (p == MAP_FAILED)
+ return nullptr;
+ return p;
diff --git a/src/third_party/mozjs-45/platform/aarch64/linux/build/js-confdefs.h b/src/third_party/mozjs-45/platform/aarch64/linux/build/js-confdefs.h
index debbcfb5052..2b1a51d09f7 100644
--- a/src/third_party/mozjs-45/platform/aarch64/linux/build/js-confdefs.h
+++ b/src/third_party/mozjs-45/platform/aarch64/linux/build/js-confdefs.h
@@ -74,10 +74,10 @@
#define MALLOC_H <malloc.h>
#define MALLOC_USABLE_SIZE_CONST_PTR
#define MOZILLA_UAVERSION "45.0"
-#define MOZILLA_VERSION "45.5.0"
-#define MOZILLA_VERSION_U 45.5.0
+#define MOZILLA_VERSION "45.8.0"
+#define MOZILLA_VERSION_U 45.8.0
#define MOZJS_MAJOR_VERSION 45
-#define MOZJS_MINOR_VERSION 5
+#define MOZJS_MINOR_VERSION 8
#define MOZ_DEBUG_SYMBOLS 1
#define MOZ_DLL_SUFFIX ".so"
#define MOZ_GLUE_IN_PROGRAM 1
diff --git a/src/third_party/mozjs-45/platform/aarch64/linux/include/js-config.h b/src/third_party/mozjs-45/platform/aarch64/linux/include/js-config.h
index 49bb6d59d70..e4dcddbe680 100644
--- a/src/third_party/mozjs-45/platform/aarch64/linux/include/js-config.h
+++ b/src/third_party/mozjs-45/platform/aarch64/linux/include/js-config.h
@@ -54,6 +54,6 @@
/* MOZILLA JSAPI version number components */
#define MOZJS_MAJOR_VERSION 45
-#define MOZJS_MINOR_VERSION 5
+#define MOZJS_MINOR_VERSION 8
#endif /* js_config_h */
diff --git a/src/third_party/mozjs-45/platform/ppc64le/linux/build/js-confdefs.h b/src/third_party/mozjs-45/platform/ppc64le/linux/build/js-confdefs.h
index debbcfb5052..2b1a51d09f7 100644
--- a/src/third_party/mozjs-45/platform/ppc64le/linux/build/js-confdefs.h
+++ b/src/third_party/mozjs-45/platform/ppc64le/linux/build/js-confdefs.h
@@ -74,10 +74,10 @@
#define MALLOC_H <malloc.h>
#define MALLOC_USABLE_SIZE_CONST_PTR
#define MOZILLA_UAVERSION "45.0"
-#define MOZILLA_VERSION "45.5.0"
-#define MOZILLA_VERSION_U 45.5.0
+#define MOZILLA_VERSION "45.8.0"
+#define MOZILLA_VERSION_U 45.8.0
#define MOZJS_MAJOR_VERSION 45
-#define MOZJS_MINOR_VERSION 5
+#define MOZJS_MINOR_VERSION 8
#define MOZ_DEBUG_SYMBOLS 1
#define MOZ_DLL_SUFFIX ".so"
#define MOZ_GLUE_IN_PROGRAM 1
diff --git a/src/third_party/mozjs-45/platform/ppc64le/linux/include/js-config.h b/src/third_party/mozjs-45/platform/ppc64le/linux/include/js-config.h
index 49bb6d59d70..e4dcddbe680 100644
--- a/src/third_party/mozjs-45/platform/ppc64le/linux/include/js-config.h
+++ b/src/third_party/mozjs-45/platform/ppc64le/linux/include/js-config.h
@@ -54,6 +54,6 @@
/* MOZILLA JSAPI version number components */
#define MOZJS_MAJOR_VERSION 45
-#define MOZJS_MINOR_VERSION 5
+#define MOZJS_MINOR_VERSION 8
#endif /* js_config_h */
diff --git a/src/third_party/mozjs-45/platform/s390x/linux/build/js-confdefs.h b/src/third_party/mozjs-45/platform/s390x/linux/build/js-confdefs.h
index b4a6a864fc0..c94367cff3f 100644
--- a/src/third_party/mozjs-45/platform/s390x/linux/build/js-confdefs.h
+++ b/src/third_party/mozjs-45/platform/s390x/linux/build/js-confdefs.h
@@ -75,10 +75,10 @@
#define MALLOC_H <malloc.h>
#define MALLOC_USABLE_SIZE_CONST_PTR
#define MOZILLA_UAVERSION "45.0"
-#define MOZILLA_VERSION "45.5.0"
-#define MOZILLA_VERSION_U 45.5.0
+#define MOZILLA_VERSION "45.8.0"
+#define MOZILLA_VERSION_U 45.8.0
#define MOZJS_MAJOR_VERSION 45
-#define MOZJS_MINOR_VERSION 5
+#define MOZJS_MINOR_VERSION 8
#define MOZ_DEBUG_SYMBOLS 1
#define MOZ_DLL_SUFFIX ".so"
#define MOZ_GLUE_IN_PROGRAM 1
diff --git a/src/third_party/mozjs-45/platform/s390x/linux/include/js-config.h b/src/third_party/mozjs-45/platform/s390x/linux/include/js-config.h
index 49bb6d59d70..e4dcddbe680 100644
--- a/src/third_party/mozjs-45/platform/s390x/linux/include/js-config.h
+++ b/src/third_party/mozjs-45/platform/s390x/linux/include/js-config.h
@@ -54,6 +54,6 @@
/* MOZILLA JSAPI version number components */
#define MOZJS_MAJOR_VERSION 45
-#define MOZJS_MINOR_VERSION 5
+#define MOZJS_MINOR_VERSION 8
#endif /* js_config_h */
diff --git a/src/third_party/mozjs-45/platform/x86_64/freebsd/build/js-confdefs.h b/src/third_party/mozjs-45/platform/x86_64/freebsd/build/js-confdefs.h
index c99865cff0d..c36f3704f05 100644
--- a/src/third_party/mozjs-45/platform/x86_64/freebsd/build/js-confdefs.h
+++ b/src/third_party/mozjs-45/platform/x86_64/freebsd/build/js-confdefs.h
@@ -69,10 +69,10 @@
#define MALLOC_H <malloc_np.h>
#define MALLOC_USABLE_SIZE_CONST_PTR const
#define MOZILLA_UAVERSION "45.0"
-#define MOZILLA_VERSION "45.5.0"
-#define MOZILLA_VERSION_U 45.5.0
+#define MOZILLA_VERSION "45.8.0"
+#define MOZILLA_VERSION_U 45.8.0
#define MOZJS_MAJOR_VERSION 45
-#define MOZJS_MINOR_VERSION 5
+#define MOZJS_MINOR_VERSION 8
#define MOZ_DEBUG_SYMBOLS 1
#define MOZ_DLL_SUFFIX ".so"
#define MOZ_GLUE_IN_PROGRAM 1
diff --git a/src/third_party/mozjs-45/platform/x86_64/freebsd/include/js-config.h b/src/third_party/mozjs-45/platform/x86_64/freebsd/include/js-config.h
index e4175f7d74d..dcc2617a294 100644
--- a/src/third_party/mozjs-45/platform/x86_64/freebsd/include/js-config.h
+++ b/src/third_party/mozjs-45/platform/x86_64/freebsd/include/js-config.h
@@ -54,6 +54,6 @@
/* MOZILLA JSAPI version number components */
#define MOZJS_MAJOR_VERSION 45
-#define MOZJS_MINOR_VERSION 5
+#define MOZJS_MINOR_VERSION 8
#endif /* js_config_h */
diff --git a/src/third_party/mozjs-45/platform/x86_64/linux/build/js-confdefs.h b/src/third_party/mozjs-45/platform/x86_64/linux/build/js-confdefs.h
index d3a0aac8ae9..9b3d5f6ca7b 100644
--- a/src/third_party/mozjs-45/platform/x86_64/linux/build/js-confdefs.h
+++ b/src/third_party/mozjs-45/platform/x86_64/linux/build/js-confdefs.h
@@ -79,10 +79,10 @@
#define MALLOC_H <malloc.h>
#define MALLOC_USABLE_SIZE_CONST_PTR
#define MOZILLA_UAVERSION "45.0"
-#define MOZILLA_VERSION "45.5.0"
-#define MOZILLA_VERSION_U 45.5.0
+#define MOZILLA_VERSION "45.8.0"
+#define MOZILLA_VERSION_U 45.8.0
#define MOZJS_MAJOR_VERSION 45
-#define MOZJS_MINOR_VERSION 5
+#define MOZJS_MINOR_VERSION 8
#define MOZ_DEBUG_SYMBOLS 1
#define MOZ_DLL_SUFFIX ".so"
#define MOZ_GLUE_IN_PROGRAM 1
diff --git a/src/third_party/mozjs-45/platform/x86_64/linux/include/js-config.h b/src/third_party/mozjs-45/platform/x86_64/linux/include/js-config.h
index 49bb6d59d70..e4dcddbe680 100644
--- a/src/third_party/mozjs-45/platform/x86_64/linux/include/js-config.h
+++ b/src/third_party/mozjs-45/platform/x86_64/linux/include/js-config.h
@@ -54,6 +54,6 @@
/* MOZILLA JSAPI version number components */
#define MOZJS_MAJOR_VERSION 45
-#define MOZJS_MINOR_VERSION 5
+#define MOZJS_MINOR_VERSION 8
#endif /* js_config_h */
diff --git a/src/third_party/mozjs-45/platform/x86_64/macOS/build/js-confdefs.h b/src/third_party/mozjs-45/platform/x86_64/macOS/build/js-confdefs.h
index c4ff9c6d80b..48623cf2b8b 100644
--- a/src/third_party/mozjs-45/platform/x86_64/macOS/build/js-confdefs.h
+++ b/src/third_party/mozjs-45/platform/x86_64/macOS/build/js-confdefs.h
@@ -62,10 +62,10 @@
#define MALLOC_H <malloc/malloc.h>
#define MALLOC_USABLE_SIZE_CONST_PTR const
#define MOZILLA_UAVERSION "45.0"
-#define MOZILLA_VERSION "45.5.0"
-#define MOZILLA_VERSION_U 45.5.0
+#define MOZILLA_VERSION "45.8.0"
+#define MOZILLA_VERSION_U 45.8.0
#define MOZJS_MAJOR_VERSION 45
-#define MOZJS_MINOR_VERSION 5
+#define MOZJS_MINOR_VERSION 8
#define MOZ_DEBUG_SYMBOLS 1
#define MOZ_DLL_SUFFIX ".dylib"
#define MOZ_MEMORY 1
diff --git a/src/third_party/mozjs-45/platform/x86_64/macOS/include/js-config.h b/src/third_party/mozjs-45/platform/x86_64/macOS/include/js-config.h
index e4175f7d74d..dcc2617a294 100644
--- a/src/third_party/mozjs-45/platform/x86_64/macOS/include/js-config.h
+++ b/src/third_party/mozjs-45/platform/x86_64/macOS/include/js-config.h
@@ -54,6 +54,6 @@
/* MOZILLA JSAPI version number components */
#define MOZJS_MAJOR_VERSION 45
-#define MOZJS_MINOR_VERSION 5
+#define MOZJS_MINOR_VERSION 8
#endif /* js_config_h */
diff --git a/src/third_party/mozjs-45/platform/x86_64/openbsd/build/js-confdefs.h b/src/third_party/mozjs-45/platform/x86_64/openbsd/build/js-confdefs.h
index 8b25ee0b17b..d4ccca388b9 100644
--- a/src/third_party/mozjs-45/platform/x86_64/openbsd/build/js-confdefs.h
+++ b/src/third_party/mozjs-45/platform/x86_64/openbsd/build/js-confdefs.h
@@ -67,10 +67,10 @@
#define MALLOC_H <malloc.h>
#define MALLOC_USABLE_SIZE_CONST_PTR const
#define MOZILLA_UAVERSION "45.0"
-#define MOZILLA_VERSION "45.5.0"
-#define MOZILLA_VERSION_U 45.5.0
+#define MOZILLA_VERSION "45.8.0"
+#define MOZILLA_VERSION_U 45.8.0
#define MOZJS_MAJOR_VERSION 45
-#define MOZJS_MINOR_VERSION 5
+#define MOZJS_MINOR_VERSION 8
#define MOZ_DEBUG_SYMBOLS 1
#define MOZ_DLL_SUFFIX ".so.1.0"
#define MOZ_GLUE_IN_PROGRAM 1
diff --git a/src/third_party/mozjs-45/platform/x86_64/openbsd/include/js-config.h b/src/third_party/mozjs-45/platform/x86_64/openbsd/include/js-config.h
index ac52cef4d93..071a002314c 100644
--- a/src/third_party/mozjs-45/platform/x86_64/openbsd/include/js-config.h
+++ b/src/third_party/mozjs-45/platform/x86_64/openbsd/include/js-config.h
@@ -54,6 +54,6 @@
/* MOZILLA JSAPI version number components */
#define MOZJS_MAJOR_VERSION 45
-#define MOZJS_MINOR_VERSION 5
+#define MOZJS_MINOR_VERSION 8
#endif /* js_config_h */
diff --git a/src/third_party/mozjs-45/platform/x86_64/solaris/build/js-confdefs.h b/src/third_party/mozjs-45/platform/x86_64/solaris/build/js-confdefs.h
index bd7f2dc1cba..24af9ec84b2 100644
--- a/src/third_party/mozjs-45/platform/x86_64/solaris/build/js-confdefs.h
+++ b/src/third_party/mozjs-45/platform/x86_64/solaris/build/js-confdefs.h
@@ -69,10 +69,10 @@
#define MALLOC_H <malloc.h>
#define MALLOC_USABLE_SIZE_CONST_PTR const
#define MOZILLA_UAVERSION "45.0"
-#define MOZILLA_VERSION "45.5.0"
-#define MOZILLA_VERSION_U 45.5.0
+#define MOZILLA_VERSION "45.8.0"
+#define MOZILLA_VERSION_U 45.8.0
#define MOZJS_MAJOR_VERSION 45
-#define MOZJS_MINOR_VERSION 5
+#define MOZJS_MINOR_VERSION 8
#define MOZ_DEBUG_SYMBOLS 1
#define MOZ_DLL_SUFFIX ".so"
#define MOZ_GLUE_IN_PROGRAM 1
diff --git a/src/third_party/mozjs-45/platform/x86_64/solaris/include/js-config.h b/src/third_party/mozjs-45/platform/x86_64/solaris/include/js-config.h
index d916ed709c4..8dd55eebb3f 100644
--- a/src/third_party/mozjs-45/platform/x86_64/solaris/include/js-config.h
+++ b/src/third_party/mozjs-45/platform/x86_64/solaris/include/js-config.h
@@ -54,6 +54,6 @@
/* MOZILLA JSAPI version number components */
#define MOZJS_MAJOR_VERSION 45
-#define MOZJS_MINOR_VERSION 5
+#define MOZJS_MINOR_VERSION 8
#endif /* js_config_h */
diff --git a/src/third_party/mozjs-45/platform/x86_64/windows/build/js-confdefs.h b/src/third_party/mozjs-45/platform/x86_64/windows/build/js-confdefs.h
index 4bcf6372758..2be82e81ea4 100644
--- a/src/third_party/mozjs-45/platform/x86_64/windows/build/js-confdefs.h
+++ b/src/third_party/mozjs-45/platform/x86_64/windows/build/js-confdefs.h
@@ -30,10 +30,10 @@
#define MALLOC_H <malloc.h>
#define MALLOC_USABLE_SIZE_CONST_PTR const
#define MOZILLA_UAVERSION "45.0"
-#define MOZILLA_VERSION "45.5.0"
-#define MOZILLA_VERSION_U 45.5.0
+#define MOZILLA_VERSION "45.8.0"
+#define MOZILLA_VERSION_U 45.8.0
#define MOZJS_MAJOR_VERSION 45
-#define MOZJS_MINOR_VERSION 5
+#define MOZJS_MINOR_VERSION 8
#define MOZ_DEBUG_SYMBOLS 1
#define MOZ_DLL_SUFFIX ".dll"
#define MOZ_MEMORY 1
diff --git a/src/third_party/mozjs-45/platform/x86_64/windows/include/js-config.h b/src/third_party/mozjs-45/platform/x86_64/windows/include/js-config.h
index 01fcaf17001..1ea25b51001 100644
--- a/src/third_party/mozjs-45/platform/x86_64/windows/include/js-config.h
+++ b/src/third_party/mozjs-45/platform/x86_64/windows/include/js-config.h
@@ -54,6 +54,6 @@
/* MOZILLA JSAPI version number components */
#define MOZJS_MAJOR_VERSION 45
-#define MOZJS_MINOR_VERSION 5
+#define MOZJS_MINOR_VERSION 8
#endif /* js_config_h */