Bug 620327: Spruce up js_regexp_ToString. (r=Waldo)
authorChris Leary <cdleary@mozilla.com>
Wed, 12 Jan 2011 15:29:03 -0800
changeset 60572 99c9ed53df99bd42bac723cbd34f8c73be84c6d0
parent 60571 7e5853562debba1c7b905cc1ce73a41695dbc748
child 60573 5100377484bae5a68303ec977b6a226ceada0542
push id18037
push usercleary@mozilla.com
push dateFri, 14 Jan 2011 17:42:55 +0000
treeherdermozilla-central@4e0501a0c5e5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersWaldo
bugs620327
milestone2.0b10pre
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 620327: Spruce up js_regexp_ToString. (r=Waldo)
js/src/jsregexp.cpp
js/src/jsregexpinlines.h
--- a/js/src/jsregexp.cpp
+++ b/js/src/jsregexp.cpp
@@ -154,20 +154,23 @@ js_CloneRegExpObject(JSContext *cx, JSOb
         uint32 origFlags = re->getFlags();
         uint32 staticsFlags = res->getFlags();
         if ((origFlags & staticsFlags) != staticsFlags) {
             /*
              * This regex is lacking flags from the statics, so we must recompile with the new
              * flags instead of increffing.
              */
             re = RegExp::create(cx, re->getSource(), origFlags | staticsFlags);
+            if (!re)
+                return NULL;
         } else {
             re->incref(cx);
         }
     }
+    JS_ASSERT(re);
     clone->setPrivate(re);
     clone->zeroRegExpLastIndex();
     return clone;
 }
 
 #ifdef JS_TRACER
 JS_DEFINE_CALLINFO_3(extern, OBJECT, js_CloneRegExpObject, CONTEXT, OBJECT, OBJECT, 0,
                      ACCSET_STORE_ANY)
@@ -568,62 +571,49 @@ js::Class js_RegExpClass = {
 
 /*
  * RegExp instance methods.
  */
 
 JSBool
 js_regexp_toString(JSContext *cx, JSObject *obj, Value *vp)
 {
-    static const jschar empty_regexp_ucstr[] = {'(', '?', ':', ')', 0};
     if (!InstanceOf(cx, obj, &js_RegExpClass, vp + 2))
         return false;
+
     RegExp *re = RegExp::extractFrom(obj);
     if (!re) {
         *vp = StringValue(cx->runtime->emptyString);
         return true;
     }
 
     JSLinearString *src = re->getSource();
-    size_t length = src->length();
-    const jschar *source = src->getChars(cx);
-    if (!source)
+    StringBuffer sb(cx);
+    if (size_t len = src->length()) {
+        if (!sb.reserve(len + 2))
+            return false;
+        JS_ALWAYS_TRUE(sb.append('/'));
+        JS_ALWAYS_TRUE(sb.append(src->chars(), len));
+        JS_ALWAYS_TRUE(sb.append('/'));
+    } else {
+        if (!sb.append("/(?:)/"))
+            return false;
+    }
+    if (re->global() && !sb.append('g'))
+        return false;
+    if (re->ignoreCase() && !sb.append('i'))
+        return false;
+    if (re->multiline() && !sb.append('m'))
+        return false;
+    if (re->sticky() && !sb.append('y'))
         return false;
 
-    if (length == 0) {
-        source = empty_regexp_ucstr;
-        length = JS_ARRAY_LENGTH(empty_regexp_ucstr) - 1;
-    }
-    length += 2;
-    uint32 nflags = re->flagCount();
-    jschar *chars = (jschar*) cx->malloc((length + nflags + 1) * sizeof(jschar));
-    if (!chars) {
+    JSFlatString *str = sb.finishString();
+    if (!str)
         return false;
-    }
-
-    chars[0] = '/';
-    js_strncpy(&chars[1], source, length - 2);
-    chars[length - 1] = '/';
-    if (nflags) {
-        if (re->global())
-            chars[length++] = 'g';
-        if (re->ignoreCase())
-            chars[length++] = 'i';
-        if (re->multiline())
-            chars[length++] = 'm';
-        if (re->sticky())
-            chars[length++] = 'y';
-    }
-    chars[length] = 0;
-
-    JSString *str = js_NewString(cx, chars, length);
-    if (!str) {
-        cx->free(chars);
-        return false;
-    }
     *vp = StringValue(str);
     return true;
 }
 
 static JSBool
 regexp_toString(JSContext *cx, uintN argc, Value *vp)
 {
     JSObject *obj = JS_THIS_OBJECT(cx, Jsvalify(vp));
--- a/js/src/jsregexpinlines.h
+++ b/js/src/jsregexpinlines.h
@@ -191,18 +191,16 @@ class RegExp
     bool global() const { return flags & JSREG_GLOB; }
     bool multiline() const { return flags & JSREG_MULTILINE; }
     bool sticky() const { return flags & JSREG_STICKY; }
 
     const uint32 &getFlags() const {
         JS_ASSERT((flags & allFlags) == flags);
         return flags;
     }
-
-    uint32 flagCount() const;
 };
 
 class RegExpMatchBuilder
 {
     JSContext   * const cx;
     JSObject    * const array;
 
   public:
@@ -540,25 +538,16 @@ RegExp::hasMetaChars(const jschar *chars
 {
     for (size_t i = 0; i < length; ++i) {
         if (isMetaChar(chars[i]))
             return true;
     }
     return false;
 }
 
-inline uint32
-RegExp::flagCount() const
-{
-    uint32 nflags = 0;
-    for (uint32 tmpFlags = flags; tmpFlags != 0; tmpFlags &= tmpFlags - 1)
-        nflags++;
-    return nflags;
-}
-
 inline void
 RegExp::incref(JSContext *cx)
 {
 #ifdef DEBUG
     assertSameCompartment(cx, compartment);
 #endif
     ++refCount;
 }