Bug 893184 - Call constructors for HeapPtrAtoms allocated as part of shared script data. r=till, a=lsblakk
authorJon Coppeard <jcoppeard@mozilla.com>
Tue, 20 Aug 2013 16:40:27 +0100
changeset 149193 abbdc26298fa24d7e3404fe0dac41e8979b58843
parent 149192 6a9878e0ae7b18524de74d1d9a5a0a8b80b7f749
child 149194 c258a05097e097ad02b576d80787bda151903e26
push id4190
push userryanvm@gmail.com
push dateWed, 28 Aug 2013 22:20:33 +0000
treeherdermozilla-aurora@7a34dc5f66db [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstill, lsblakk
bugs893184
milestone25.0a2
Bug 893184 - Call constructors for HeapPtrAtoms allocated as part of shared script data. r=till, a=lsblakk
js/src/jsscript.cpp
js/src/jsscript.h
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -627,17 +627,17 @@ js::XDRScript(XDRState<mode> *xdr, Handl
     SharedScriptData *ssd;
     if (mode == XDR_DECODE) {
         ssd = SharedScriptData::new_(cx, length, nsrcnotes, natoms);
         if (!ssd)
             return false;
         code = ssd->data;
         if (natoms != 0) {
             script->natoms = natoms;
-            script->atoms = ssd->atoms(length, nsrcnotes);
+            script->atoms = ssd->atoms();
         }
     }
 
     if (!xdr->codeBytes(code, length) || !xdr->codeBytes(code + length, nsrcnotes)) {
         if (mode == XDR_DECODE)
             js_free(ssd);
         return false;
     }
@@ -1504,28 +1504,45 @@ ScriptSource::sourceMap()
 /*
  * Shared script data management.
  */
 
 SharedScriptData *
 js::SharedScriptData::new_(ExclusiveContext *cx, uint32_t codeLength,
                            uint32_t srcnotesLength, uint32_t natoms)
 {
+    /*
+     * Ensure the atoms are aligned, as some architectures don't allow unaligned
+     * access.
+     */
+    const uint32_t pointerSize = sizeof(JSAtom *);
+    const uint32_t pointerMask = pointerSize - 1;
+    const uint32_t dataOffset = offsetof(SharedScriptData, data);
     uint32_t baseLength = codeLength + srcnotesLength;
-    uint32_t padding = sizeof(JSAtom *) - baseLength % sizeof(JSAtom *);
-    uint32_t length = baseLength + padding + sizeof(JSAtom *) * natoms;
-
-    SharedScriptData *entry = (SharedScriptData *)cx->malloc_(length +
-                                                              offsetof(SharedScriptData, data));
-
+    uint32_t padding = (pointerSize - ((baseLength + dataOffset) & pointerMask)) & pointerMask;
+    uint32_t length = baseLength + padding + pointerSize * natoms;
+
+    SharedScriptData *entry = (SharedScriptData *)cx->malloc_(length + dataOffset);
     if (!entry)
         return NULL;
-    entry->marked = false;
+
     entry->length = length;
+    entry->natoms = natoms;
+    entry->marked = false;
     memset(entry->data + baseLength, 0, padding);
+
+    /*
+     * Call constructors to initialize the storage that will be accessed as a
+     * HeapPtrAtom array via atoms().
+     */
+    HeapPtrAtom *atoms = entry->atoms();
+    JS_ASSERT(reinterpret_cast<uintptr_t>(atoms) % sizeof(JSAtom *) == 0);
+    for (unsigned i = 0; i < natoms; ++i)
+        new (&atoms[i]) HeapPtrAtom();
+
     return entry;
 }
 
 /*
  * Takes ownership of its *ssd parameter and either adds it into the runtime's
  * ScriptDataTable or frees it if a matching entry already exists.
  *
  * Sets the |code| and |atoms| fields on the given JSScript.
@@ -1542,16 +1559,18 @@ SaveSharedScriptData(ExclusiveContext *c
     ScriptBytecodeHasher::Lookup l(ssd);
 
     ScriptDataTable::AddPtr p = cx->scriptDataTable().lookupForAdd(l);
     if (p) {
         js_free(ssd);
         ssd = *p;
     } else {
         if (!cx->scriptDataTable().add(p, ssd)) {
+            script->code = NULL;
+            script->atoms = NULL;
             js_free(ssd);
             js_ReportOutOfMemory(cx);
             return false;
         }
     }
 
 #ifdef JSGC_INCREMENTAL
     /*
@@ -1563,17 +1582,17 @@ SaveSharedScriptData(ExclusiveContext *c
     if (cx->isJSContext()) {
         JSRuntime *rt = cx->asJSContext()->runtime();
         if (JS::IsIncrementalGCInProgress(rt) && rt->gcIsFull)
             ssd->marked = true;
     }
 #endif
 
     script->code = ssd->data;
-    script->atoms = ssd->atoms(script->length, nsrcnotes);
+    script->atoms = ssd->atoms();
     return true;
 }
 
 static inline void
 MarkScriptData(JSRuntime *rt, const jsbytecode *bytecode)
 {
     /*
      * As an invariant, a ScriptBytecodeEntry should not be 'marked' outside of
@@ -1907,17 +1926,17 @@ JSScript::fullyInitFromEmitter(Exclusive
     if (!ssd)
         return false;
 
     jsbytecode *code = ssd->data;
     PodCopy<jsbytecode>(code, bce->prolog.code.begin(), prologLength);
     PodCopy<jsbytecode>(code + prologLength, bce->code().begin(), mainLength);
     if (!FinishTakingSrcNotes(cx, bce, (jssrcnote *)(code + script->length)))
         return false;
-    InitAtomMap(bce->atomIndices.getMap(), ssd->atoms(script->length, nsrcnotes));
+    InitAtomMap(bce->atomIndices.getMap(), ssd->atoms());
 
     if (!SaveSharedScriptData(cx, script, ssd, nsrcnotes))
         return false;
 
     uint32_t nfixed = bce->sc->isFunctionBox() ? script->bindings.numVars() : 0;
     JS_ASSERT(nfixed < SLOTNO_LIMIT);
     script->nfixed = uint16_t(nfixed);
     if (script->nfixed + bce->maxStackDepth >= JS_BIT(16)) {
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -1382,32 +1382,37 @@ struct SourceCompressionToken
 extern void
 CallNewScriptHook(JSContext *cx, JS::HandleScript script, JS::HandleFunction fun);
 
 extern void
 CallDestroyScriptHook(FreeOp *fop, JSScript *script);
 
 struct SharedScriptData
 {
+    uint32_t length;
+    uint32_t natoms;
     bool marked;
-    uint32_t length;
     jsbytecode data[1];
 
     static SharedScriptData *new_(ExclusiveContext *cx, uint32_t codeLength,
                                   uint32_t srcnotesLength, uint32_t natoms);
 
-    HeapPtrAtom *atoms(uint32_t codeLength, uint32_t srcnotesLength) {
-        uint32_t length = codeLength + srcnotesLength;
-        return reinterpret_cast<HeapPtrAtom *>(data + length + sizeof(JSAtom *) -
-                                               length % sizeof(JSAtom *));
+    HeapPtrAtom *atoms() {
+        if (!natoms)
+            return NULL;
+        return reinterpret_cast<HeapPtrAtom *>(data + length - sizeof(JSAtom *) * natoms);
     }
 
     static SharedScriptData *fromBytecode(const jsbytecode *bytecode) {
         return (SharedScriptData *)(bytecode - offsetof(SharedScriptData, data));
     }
+
+  private:
+    SharedScriptData() MOZ_DELETE;
+    SharedScriptData(const SharedScriptData&) MOZ_DELETE;
 };
 
 struct ScriptBytecodeHasher
 {
     struct Lookup
     {
         jsbytecode          *code;
         uint32_t            length;