Bug 726429 - Handle GC during string table initialization (r=luke)
authorBill McCloskey <wmccloskey@mozilla.com>
Thu, 23 Feb 2012 14:34:06 -0800
changeset 87583 168d1528a2da87f9cfd4c7e2760dee40975a75e1
parent 87582 a7f0048a58d34321ff2e3b35672f9c021d9ac668
child 87584 24dd2472229fb4abbb516b3887de55ca58913b03
push id22133
push usermak77@bonardo.net
push dateFri, 24 Feb 2012 10:23:30 +0000
treeherdermozilla-central@fbcdc2c87df8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs726429
milestone13.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 726429 - Handle GC during string table initialization (r=luke)
js/src/jsapi-tests/Makefile.in
js/src/jsapi-tests/testOOM.cpp
js/src/vm/String.cpp
js/src/vm/String.h
--- a/js/src/jsapi-tests/Makefile.in
+++ b/js/src/jsapi-tests/Makefile.in
@@ -62,16 +62,17 @@ CPPSRCS = \
   testDeepFreeze.cpp \
   testDefineGetterSetterNonEnumerable.cpp \
   testDefineProperty.cpp \
   testExtendedEq.cpp \
   testExternalStrings.cpp \
   testFuncCallback.cpp \
   testFunctionProperties.cpp \
   testGCOutOfMemory.cpp \
+  testOOM.cpp \
   testGetPropertyDefault.cpp \
   testIndexToString.cpp \
   testIntString.cpp \
   testIntTypesABI.cpp \
   testIntern.cpp \
   testLookup.cpp \
   testLooselyEqual.cpp \
   testNewObject.cpp \
new file mode 100644
--- /dev/null
+++ b/js/src/jsapi-tests/testOOM.cpp
@@ -0,0 +1,19 @@
+#include "tests.h"
+
+BEGIN_TEST(testOOM)
+{
+    JSString *jsstr = JS_ValueToString(cx, INT_TO_JSVAL(9));
+    jsval tmp = STRING_TO_JSVAL(jsstr);
+    JS_SetProperty(cx, global, "rootme", &tmp);
+    const jschar *s = JS_GetStringCharsZ(cx, jsstr);
+    JS_ASSERT(s[0] == '9' && s[1] == '\0');
+    return true;
+}
+
+virtual JSRuntime * createRuntime()
+{
+    JSRuntime *rt = JS_NewRuntime(0);
+    JS_SetGCParameter(rt, JSGC_MAX_BYTES, (uint32_t)-1);
+    return rt;
+}
+END_TEST(testOOM)
--- a/js/src/vm/String.cpp
+++ b/js/src/vm/String.cpp
@@ -486,37 +486,39 @@ StaticStrings::init(JSContext *cx)
             jschar buffer[] = { (i / 100) + '0', ((i / 10) % 10) + '0', (i % 10) + '0', 0x00 };
             JSFixedString *s = js_NewStringCopyN(cx, buffer, 3);
             if (!s)
                 return false;
             intStaticTable[i] = s->morphAtomizedStringIntoAtom();
         }
     }
 
-    initialized = true;
     return true;
 }
 
 void
 StaticStrings::trace(JSTracer *trc)
 {
-    if (!initialized)
-        return;
-
     /* These strings never change, so barriers are not needed. */
 
-    for (uint32_t i = 0; i < UNIT_STATIC_LIMIT; i++)
-        MarkStringUnbarriered(trc, unitStaticTable[i], "unit-static-string");
+    for (uint32_t i = 0; i < UNIT_STATIC_LIMIT; i++) {
+        if (JSAtom *atom = unitStaticTable[i])
+            MarkStringUnbarriered(trc, atom, "unit-static-string");
+    }
 
-    for (uint32_t i = 0; i < NUM_SMALL_CHARS * NUM_SMALL_CHARS; i++)
-        MarkStringUnbarriered(trc, length2StaticTable[i], "length2-static-string");
+    for (uint32_t i = 0; i < NUM_SMALL_CHARS * NUM_SMALL_CHARS; i++) {
+        if (JSAtom *atom = length2StaticTable[i])
+            MarkStringUnbarriered(trc, atom, "length2-static-string");
+    }
 
     /* This may mark some strings more than once, but so be it. */
-    for (uint32_t i = 0; i < INT_STATIC_LIMIT; i++)
-        MarkStringUnbarriered(trc, intStaticTable[i], "int-static-string");
+    for (uint32_t i = 0; i < INT_STATIC_LIMIT; i++) {
+        if (JSAtom *atom = intStaticTable[i])
+            MarkStringUnbarriered(trc, atom, "int-static-string");
+    }
 }
 
 bool
 StaticStrings::isStatic(JSAtom *atom)
 {
     const jschar *chars = atom->chars();
     switch (atom->length()) {
       case 1:
--- a/js/src/vm/String.h
+++ b/js/src/vm/String.h
@@ -691,33 +691,35 @@ class JSShortAtom : public JSShortString
 
 JS_STATIC_ASSERT(sizeof(JSShortAtom) == sizeof(JSShortString));
 
 namespace js {
 
 class StaticStrings
 {
   private:
-    bool initialized;
-
     /* Bigger chars cannot be in a length-2 string. */
     static const size_t SMALL_CHAR_LIMIT    = 128U;
     static const size_t NUM_SMALL_CHARS     = 64U;
 
     static const size_t INT_STATIC_LIMIT    = 256U;
 
     JSAtom *length2StaticTable[NUM_SMALL_CHARS * NUM_SMALL_CHARS];
     JSAtom *intStaticTable[INT_STATIC_LIMIT];
 
   public:
     /* We keep these public for the methodjit. */
     static const size_t UNIT_STATIC_LIMIT   = 256U;
     JSAtom *unitStaticTable[UNIT_STATIC_LIMIT];
 
-    StaticStrings() : initialized(false) {}
+    StaticStrings() {
+        PodArrayZero(unitStaticTable);
+        PodArrayZero(length2StaticTable);
+        PodArrayZero(intStaticTable);
+    }
 
     bool init(JSContext *cx);
     void trace(JSTracer *trc);
 
     static inline bool hasUint(uint32_t u);
     inline JSAtom *getUint(uint32_t u);
 
     static inline bool hasInt(int32_t i);