Bug 1334744 - Add a faster API for working with external strings. r=luke
authorJan de Mooij <jdemooij@mozilla.com>
Mon, 30 Jan 2017 19:07:54 +0100
changeset 331708 bf223949220cb242645dfff27a7fe2fb8330c320
parent 331707 468f75ba2034e33ae82dcd349425e51b6bbf7a48
child 331709 075a7c9527673428ec30f7db62845738adb51d3c
push id31281
push userkwierso@gmail.com
push dateMon, 30 Jan 2017 23:45:09 +0000
treeherdermozilla-central@1fe66bd0efba [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs1334744
milestone54.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 1334744 - Add a faster API for working with external strings. r=luke
js/src/jsfriendapi.h
js/src/vm/String.h
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -562,25 +562,27 @@ struct Function {
     void* _1;
 };
 
 struct String
 {
     static const uint32_t INLINE_CHARS_BIT = JS_BIT(2);
     static const uint32_t LATIN1_CHARS_BIT = JS_BIT(6);
     static const uint32_t ROPE_FLAGS       = 0;
+    static const uint32_t EXTERNAL_FLAGS   = JS_BIT(5);
     static const uint32_t TYPE_FLAGS_MASK  = JS_BIT(6) - 1;
     uint32_t flags;
     uint32_t length;
     union {
         const JS::Latin1Char* nonInlineCharsLatin1;
         const char16_t* nonInlineCharsTwoByte;
         JS::Latin1Char inlineStorageLatin1[1];
         char16_t inlineStorageTwoByte[1];
     };
+    const JSStringFinalizer* externalFinalizer;
 };
 
 } /* namespace shadow */
 
 // This is equal to |&JSObject::class_|.  Use it in places where you don't want
 // to #include jsobj.h.
 extern JS_FRIEND_DATA(const js::Class* const) ObjectClassPtr;
 
@@ -825,16 +827,31 @@ GetLatin1AtomChars(const JS::AutoCheckCa
 }
 
 MOZ_ALWAYS_INLINE const char16_t*
 GetTwoByteAtomChars(const JS::AutoCheckCannotGC& nogc, JSAtom* atom)
 {
     return GetTwoByteLinearStringChars(nogc, AtomToLinearString(atom));
 }
 
+MOZ_ALWAYS_INLINE bool
+IsExternalString(JSString* str, const JSStringFinalizer** fin, const char16_t** chars)
+{
+    using shadow::String;
+    String* s = reinterpret_cast<String*>(str);
+
+    if ((s->flags & String::TYPE_FLAGS_MASK) != String::EXTERNAL_FLAGS)
+        return false;
+
+    MOZ_ASSERT(JS_IsExternalString(str));
+    *fin = s->externalFinalizer;
+    *chars = s->nonInlineCharsTwoByte;
+    return true;
+}
+
 JS_FRIEND_API(JSLinearString*)
 StringToLinearStringSlow(JSContext* cx, JSString* str);
 
 MOZ_ALWAYS_INLINE JSLinearString*
 StringToLinearString(JSContext* cx, JSString* str)
 {
     using shadow::String;
     String* s = reinterpret_cast<String*>(str);
--- a/js/src/vm/String.h
+++ b/js/src/vm/String.h
@@ -297,28 +297,32 @@ class JSString : public js::gc::TenuredC
         static_assert(offsetof(JSString, d.u1.length) == offsetof(String, length),
                       "shadow::String length offset must match JSString");
         static_assert(offsetof(JSString, d.u1.flags) == offsetof(String, flags),
                       "shadow::String flags offset must match JSString");
         static_assert(offsetof(JSString, d.s.u2.nonInlineCharsLatin1) == offsetof(String, nonInlineCharsLatin1),
                       "shadow::String nonInlineChars offset must match JSString");
         static_assert(offsetof(JSString, d.s.u2.nonInlineCharsTwoByte) == offsetof(String, nonInlineCharsTwoByte),
                       "shadow::String nonInlineChars offset must match JSString");
+        static_assert(offsetof(JSString, d.s.u3.externalFinalizer) == offsetof(String, externalFinalizer),
+                      "shadow::String externalFinalizer offset must match JSString");
         static_assert(offsetof(JSString, d.inlineStorageLatin1) == offsetof(String, inlineStorageLatin1),
                       "shadow::String inlineStorage offset must match JSString");
         static_assert(offsetof(JSString, d.inlineStorageTwoByte) == offsetof(String, inlineStorageTwoByte),
                       "shadow::String inlineStorage offset must match JSString");
         static_assert(INLINE_CHARS_BIT == String::INLINE_CHARS_BIT,
                       "shadow::String::INLINE_CHARS_BIT must match JSString::INLINE_CHARS_BIT");
         static_assert(LATIN1_CHARS_BIT == String::LATIN1_CHARS_BIT,
                       "shadow::String::LATIN1_CHARS_BIT must match JSString::LATIN1_CHARS_BIT");
         static_assert(TYPE_FLAGS_MASK == String::TYPE_FLAGS_MASK,
                       "shadow::String::TYPE_FLAGS_MASK must match JSString::TYPE_FLAGS_MASK");
         static_assert(ROPE_FLAGS == String::ROPE_FLAGS,
                       "shadow::String::ROPE_FLAGS must match JSString::ROPE_FLAGS");
+        static_assert(EXTERNAL_FLAGS == String::EXTERNAL_FLAGS,
+                      "shadow::String::EXTERNAL_FLAGS must match JSString::EXTERNAL_FLAGS");
     }
 
     /* Avoid lame compile errors in JSRope::flatten */
     friend class JSRope;
 
     friend class js::gc::RelocationOverlay;
 
   protected: