Bug 589735 - Allow static JS strings to be turned off; turn off on ia64 (r=igor)
authorLuke Wagner <luke@mozilla.com>
Wed, 24 Aug 2011 14:28:28 -0700
changeset 75902 00be7279f6ad8c6d2fb94abb1a536b0642c87434
parent 75901 72459db22a34a168fdb794da36764a16815e3653
child 75903 d4003f345b2418211b0327d757c6ac1268162115
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
reviewersigor
bugs589735
milestone9.0a1
Bug 589735 - Allow static JS strings to be turned off; turn off on ia64 (r=igor)
js/src/jsgcinlines.h
js/src/jsnum.cpp
js/src/jsstr.cpp
js/src/jstracer.cpp
js/src/jstracer.h
js/src/tracejit/Writer.cpp
js/src/vm/String-inl.h
js/src/vm/String.h
--- a/js/src/jsgcinlines.h
+++ b/js/src/jsgcinlines.h
@@ -47,50 +47,62 @@
 #include "jsxml.h"
 
 #include "jslock.h"
 #include "jstl.h"
 
 inline bool
 JSAtom::isUnitString(const void *ptr)
 {
+#ifdef JS_HAS_STATIC_STRINGS
     jsuword delta = reinterpret_cast<jsuword>(ptr) -
                     reinterpret_cast<jsuword>(unitStaticTable);
     if (delta >= UNIT_STATIC_LIMIT * sizeof(JSString))
         return false;
 
     /* If ptr points inside the static array, it must be well-aligned. */
     JS_ASSERT(delta % sizeof(JSString) == 0);
     return true;
+#else
+    return false;
+#endif
 }
 
 inline bool
 JSAtom::isLength2String(const void *ptr)
 {
+#ifdef JS_HAS_STATIC_STRINGS
     jsuword delta = reinterpret_cast<jsuword>(ptr) -
                     reinterpret_cast<jsuword>(length2StaticTable);
     if (delta >= NUM_SMALL_CHARS * NUM_SMALL_CHARS * sizeof(JSString))
         return false;
 
     /* If ptr points inside the static array, it must be well-aligned. */
     JS_ASSERT(delta % sizeof(JSString) == 0);
     return true;
+#else
+    return false;
+#endif
 }
 
 inline bool
 JSAtom::isHundredString(const void *ptr)
 {
+#ifdef JS_HAS_STATIC_STRINGS
     jsuword delta = reinterpret_cast<jsuword>(ptr) -
                     reinterpret_cast<jsuword>(hundredStaticTable);
     if (delta >= NUM_HUNDRED_STATICS * sizeof(JSString))
         return false;
 
     /* If ptr points inside the static array, it must be well-aligned. */
     JS_ASSERT(delta % sizeof(JSString) == 0);
     return true;
+#else
+    return false;
+#endif
 }
 
 inline bool
 JSAtom::isStatic(const void *ptr)
 {
     return isUnitString(ptr) || isLength2String(ptr) || isHundredString(ptr);
 }
 
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -1198,23 +1198,25 @@ js_NumberToStringWithBase(JSContext *cx,
         return NULL;
 
     JSCompartment *c = cx->compartment;
 
     int32_t i;
     if (JSDOUBLE_IS_INT32(d, &i)) {
         if (base == 10 && JSAtom::hasIntStatic(i))
             return &JSAtom::intStatic(i);
+#ifdef JS_HAS_STATIC_STRINGS
         if (jsuint(i) < jsuint(base)) {
             if (i < 10)
                 return &JSAtom::intStatic(i);
             jschar c = 'a' + i - 10;
             JS_ASSERT(JSAtom::hasUnitStatic(c));
             return &JSAtom::unitStatic(c);
         }
+#endif
 
         if (JSFlatString *str = c->dtoaCache.lookup(base, d))
             return str;
 
         numStr = IntToCString(&cbuf, i, base);
         JS_ASSERT(!cbuf.dbuf && numStr >= cbuf.sbuf && numStr < cbuf.sbuf + cbuf.sbufSize);
     } else {
         if (JSFlatString *str = c->dtoaCache.lookup(base, d))
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -2879,16 +2879,18 @@ static JSFunctionSpec string_methods[] =
     JS_FN("blink",             str_blink,             0,0),
     JS_FN("sup",               str_sup,               0,0),
     JS_FN("sub",               str_sub,               0,0),
 #endif
 
     JS_FS_END
 };
 
+#ifdef JS_HAS_STATIC_STRINGS
+
 /*
  * Set up some tools to make it easier to generate large tables. After constant
  * folding, for each n, Rn(0) is the comma-separated list R(0), R(1), ..., R(2^n-1).
  * Similary, Rn(k) (for any k and n) generates the list R(k), R(k+1), ..., R(k+2^n-1).
  * To use this, define R appropriately, then use Rn(0) (for some value of n), then
  * undefine R.
  */
 #define R2(n)  R(n),   R((n) + (1 << 0)),    R((n) + (2 << 0)),    R((n) + (3 << 0))
@@ -3073,16 +3075,18 @@ const JSString::Data *const JSAtom::intS
 #undef R6
 #undef R8
 #undef R10
 #undef R12
 
 #undef R3
 #undef R7
 
+#endif  /* defined(JS_HAS_STATIC_STRINGS) */
+
 JSBool
 js_String(JSContext *cx, uintN argc, Value *vp)
 {
     Value *argv = vp + 2;
 
     JSString *str;
     if (argc > 0) {
         str = js_ValueToString(cx, argv[0]);
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -11470,30 +11470,33 @@ TraceRecorder::callNative(uintN argc, JS
                     LIns* abs_ins = w.name(w.cmovi(isNeg_ins, neg_ins, a), "abs");
                     set(&vp[0], w.i2d(abs_ins));
                     pendingSpecializedNative = IGNORE_NATIVE_CALL_COMPLETE_CALLBACK;
                     return RECORD_CONTINUE;
                 }
             }
             if (vp[1].isString()) {
                 JSString *str = vp[1].toString();
+#ifdef JS_HAS_STATIC_STRINGS
                 if (native == js_str_charAt) {
                     jsdouble i = vp[2].toNumber();
                     if (JSDOUBLE_IS_NaN(i))
                       i = 0;
                     if (i < 0 || i >= str->length())
                         RETURN_STOP("charAt out of bounds");
                     LIns* str_ins = get(&vp[1]);
                     LIns* idx_ins = get(&vp[2]);
                     LIns* char_ins;
                     CHECK_STATUS(getCharAt(str, str_ins, idx_ins, mode, &char_ins));
                     set(&vp[0], char_ins);
                     pendingSpecializedNative = IGNORE_NATIVE_CALL_COMPLETE_CALLBACK;
                     return RECORD_CONTINUE;
-                } else if (native == js_str_charCodeAt) {
+                } else
+#endif
+                if (native == js_str_charCodeAt) {
                     jsdouble i = vp[2].toNumber();
                     if (JSDOUBLE_IS_NaN(i))
                       i = 0;
                     if (i < 0 || i >= str->length())
                         RETURN_STOP("charCodeAt out of bounds");
                     LIns* str_ins = get(&vp[1]);
                     LIns* idx_ins = get(&vp[2]);
                     LIns* charCode_ins;
@@ -12838,16 +12841,17 @@ TraceRecorder::getCharCodeAt(JSString *s
           snapshot(MISMATCH_EXIT));
     *out = w.i2d(w.getStringChar(str_ins, idx_ins));
     return RECORD_CONTINUE;
 }
 
 JS_STATIC_ASSERT(sizeof(JSString) == 16 || sizeof(JSString) == 32);
 
 
+#ifdef JS_HAS_STATIC_STRINGS
 JS_REQUIRES_STACK LIns*
 TraceRecorder::getUnitString(LIns* str_ins, LIns* idx_ins)
 {
     LIns *ch_ins = w.getStringChar(str_ins, idx_ins);
     guard(true, w.ltuiN(ch_ins, JSAtom::UNIT_STATIC_LIMIT), MISMATCH_EXIT);
     JS_STATIC_ASSERT(sizeof(JSString) == 16 || sizeof(JSString) == 32);
     return w.addp(w.nameImmpNonGC(JSAtom::unitStaticTable),
                   w.lshpN(w.ui2p(ch_ins), (sizeof(JSString) == 16) ? 4 : 5));
@@ -12882,16 +12886,17 @@ TraceRecorder::getCharAt(JSString *str, 
             LIns *unitstr_ins = getUnitString(str_ins, idx_ins);
             w.stAlloc(unitstr_ins, phi_ins);
             w.label(mbr);
         }
         *out = w.ldpAlloc(phi_ins);
     }
     return RECORD_CONTINUE;
 }
+#endif
 
 // Typed array tracing depends on EXPANDED_LOADSTORE and F2I
 #if NJ_EXPANDED_LOADSTORE_SUPPORTED && NJ_F2I_SUPPORTED
 static bool OkToTraceTypedArrays = true;
 #else
 static bool OkToTraceTypedArrays = false;
 #endif
 
@@ -12916,28 +12921,30 @@ TraceRecorder::record_JSOP_GETELEM()
     bool call = *cx->regs().pc == JSOP_CALLELEM;
 
     Value& idx = stackval(-1);
     Value& lval = stackval(-2);
 
     LIns* obj_ins = get(&lval);
     LIns* idx_ins = get(&idx);
 
+#ifdef JS_HAS_STATIC_STRINGS
     // Special case for array-like access of strings.
     if (lval.isString() && hasInt32Repr(idx)) {
         if (call)
             RETURN_STOP_A("JSOP_CALLELEM on a string");
         int i = asInt32(idx);
         if (size_t(i) >= lval.toString()->length())
             RETURN_STOP_A("Invalid string index in JSOP_GETELEM");
         LIns* char_ins;
         CHECK_STATUS_A(getCharAt(lval.toString(), obj_ins, idx_ins, JSOP_GETELEM, &char_ins));
         set(&lval, char_ins);
         return ARECORD_CONTINUE;
     }
+#endif
 
     if (lval.isPrimitive())
         RETURN_STOP_A("JSOP_GETLEM on a primitive");
     RETURN_IF_XML_A(lval);
 
     JSObject* obj = &lval.toObject();
     if (obj == globalObj)
         RETURN_STOP_A("JSOP_GETELEM on global");
--- a/js/src/jstracer.h
+++ b/js/src/jstracer.h
@@ -1393,20 +1393,22 @@ class TraceRecorder
                                                                   Value* outp);
     JS_REQUIRES_STACK RecordingStatus getPropertyWithScriptGetter(JSObject *obj,
                                                                   nanojit::LIns* obj_ins,
                                                                   const js::Shape* shape);
 
     JS_REQUIRES_STACK RecordingStatus getCharCodeAt(JSString *str,
                                                     nanojit::LIns* str_ins, nanojit::LIns* idx_ins,
                                                     nanojit::LIns** out_ins);
+#ifdef JS_HAS_STATIC_STRINGS
     JS_REQUIRES_STACK nanojit::LIns* getUnitString(nanojit::LIns* str_ins, nanojit::LIns* idx_ins);
     JS_REQUIRES_STACK RecordingStatus getCharAt(JSString *str,
                                                 nanojit::LIns* str_ins, nanojit::LIns* idx_ins,
                                                 JSOp mode, nanojit::LIns** out_ins);
+#endif
 
     JS_REQUIRES_STACK RecordingStatus initOrSetPropertyByName(nanojit::LIns* obj_ins,
                                                               Value* idvalp, Value* rvalp,
                                                               bool init);
     JS_REQUIRES_STACK RecordingStatus initOrSetPropertyByIndex(nanojit::LIns* obj_ins,
                                                                nanojit::LIns* index_ins,
                                                                Value* rvalp, bool init);
     JS_REQUIRES_STACK AbortableRecordingStatus setElem(int lval_spindex, int idx_spindex,
--- a/js/src/tracejit/Writer.cpp
+++ b/js/src/tracejit/Writer.cpp
@@ -245,28 +245,31 @@ couldBeObjectOrString(LIns *ins)
                ins->oprnd2()->isImmQ() &&
                uintptr_t(ins->oprnd2()->immQ()) == JSVAL_PAYLOAD_MASK)
     {
         // ins_oprnd1 = ldq ...
         // ins_oprnd2 = immq JSVAL_PAYLOAD_MASK
         // ins = andq ins_oprnd1, ins_oprnd2
         ret = true;
 #endif
-    } else if (ins->isop(LIR_addp) &&
+    }
+#ifdef JS_HAS_STATIC_STRINGS
+    else if (ins->isop(LIR_addp) &&
                ((ins->oprnd1()->isImmP() &&
                  (void *)ins->oprnd1()->immP() == JSAtom::unitStaticTable) ||
                 (ins->oprnd2()->isImmP() &&
                  (void *)ins->oprnd2()->immP() == JSAtom::unitStaticTable)))
     {
         // (String only)
         // ins = addp ..., JSString::unitStringTable
         //   OR
         // ins = addp JSString::unitStringTable, ...
         ret = true;
     }
+#endif
 
     return ret;
 }
 
 static bool
 isConstPrivatePtr(LIns *ins, unsigned slot)
 {
 #if JS_BITS_PER_WORD == 32
--- a/js/src/vm/String-inl.h
+++ b/js/src/vm/String-inl.h
@@ -188,16 +188,17 @@ JSExternalString::new_(JSContext *cx, co
     JSExternalString *str = js_NewGCExternalString(cx);
     if (!str)
         return NULL;
     str->init(chars, length, type, closure);
     cx->runtime->updateMallocCounter((length + 1) * sizeof(jschar));
     return str;
 }
 
+#ifdef JS_HAS_STATIC_STRINGS
 inline bool
 JSAtom::fitsInSmallChar(jschar c)
 {
     return c < SMALL_CHAR_LIMIT && toSmallChar[c] != INVALID_SMALL_CHAR;
 }
 
 inline bool
 JSAtom::hasUnitStatic(jschar c)
@@ -299,16 +300,92 @@ JSAtom::lookupStatic(const jschar *chars
                 return &intStatic(i);
         }
         return NULL;
     }
 
     return NULL;
 }
 
+#else  /* defined(JS_HAS_STATIC_STRINGS) */
+
+inline bool
+JSAtom::fitsInSmallChar(jschar c)
+{
+    return false;
+}
+
+inline bool
+JSAtom::hasUnitStatic(jschar c)
+{
+    return false;
+}
+
+inline JSStaticAtom &
+JSAtom::unitStatic(jschar c)
+{
+    JS_NOT_REACHED("no static strings");
+    return *(JSStaticAtom *)NULL;
+}
+
+inline bool
+JSAtom::hasUintStatic(uint32 u)
+{
+    return false;
+}
+
+inline JSStaticAtom &
+JSAtom::uintStatic(uint32 u)
+{
+    JS_NOT_REACHED("no static strings");
+    return *(JSStaticAtom *)NULL;
+}
+
+inline bool
+JSAtom::hasIntStatic(int32 i)
+{
+    return false;
+}
+
+inline JSStaticAtom &
+JSAtom::intStatic(jsint i)
+{
+    JS_NOT_REACHED("no static strings");
+    return *(JSStaticAtom *)NULL;
+}
+
+inline JSLinearString *
+JSAtom::getUnitStringForElement(JSContext *cx, JSString *str, size_t index)
+{
+    JS_ASSERT(index < str->length());
+    return js_NewDependentString(cx, str, index, 1);
+}
+
+inline JSStaticAtom &
+JSAtom::length2Static(jschar c1, jschar c2)
+{
+    JS_NOT_REACHED("no static strings");
+    return *(JSStaticAtom *)NULL;
+}
+
+inline JSStaticAtom &
+JSAtom::length2Static(uint32 i)
+{
+    JS_NOT_REACHED("no static strings");
+    return *(JSStaticAtom *)NULL;
+}
+
+/* Get a static atomized string for chars if possible. */
+inline JSStaticAtom *
+JSAtom::lookupStatic(const jschar *chars, size_t length)
+{
+    return NULL;
+}
+#endif /* defined(JS_HAS_STATIC_STRINGS) */
+
 JS_ALWAYS_INLINE void
 JSString::finalize(JSContext *cx)
 {
     /* Statics are not GC-things and shorts are in a different arena. */
     JS_ASSERT(!isStaticAtom() && !isShort());
 
     if (isFlat())
         asFlat().finalize(cx->runtime);
--- a/js/src/vm/String.h
+++ b/js/src/vm/String.h
@@ -650,34 +650,45 @@ class JSExternalString : public JSFixedS
     /* Only called by the GC for strings with the FINALIZE_EXTERNAL_STRING kind. */
 
     void finalize(JSContext *cx);
     void finalize();
 };
 
 JS_STATIC_ASSERT(sizeof(JSExternalString) == sizeof(JSString));
 
+#if !defined(__ia64__)
+/*
+ * Don't use static strings on ia64 since the compiler may put the static
+ * memory out of the acceptable 47-bit jsval pointer range.
+ */
+# define JS_HAS_STATIC_STRINGS
+#endif
+
 class JSAtom : public JSFixedString
 {
   public:
     /* Exposed only for jits. */
 
+#ifdef JS_HAS_STATIC_STRINGS
     static const size_t UNIT_STATIC_LIMIT   = 256U;
     static const size_t SMALL_CHAR_LIMIT    = 128U; /* Bigger chars cannot be in a length-2 string. */
     static const size_t NUM_SMALL_CHARS     = 64U;
     static const size_t INT_STATIC_LIMIT    = 256U;
     static const size_t NUM_HUNDRED_STATICS = 156U;
 
-#ifdef __SUNPRO_CC
-# pragma align 8 (__1cGJSAtomPunitStaticTable_, __1cGJSAtomSlength2StaticTable_, __1cGJSAtomShundredStaticTable_)
-#endif
+# ifdef __SUNPRO_CC
+#  pragma align 8 (__1cGJSAtomPunitStaticTable_, __1cGJSAtomSlength2StaticTable_, __1cGJSAtomShundredStaticTable_)
+# endif
+
     static const JSString::Data unitStaticTable[];
     static const JSString::Data length2StaticTable[];
     static const JSString::Data hundredStaticTable[];
     static const JSString::Data *const intStaticTable[];
+#endif
 
   private:
     /* Defined in jsgcinlines.h */
     static inline bool isUnitString(const void *ptr);
     static inline bool isLength2String(const void *ptr);
     static inline bool isHundredString(const void *ptr);
 
     typedef uint8 SmallChar;