js/src/vm/String-inl.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     2  * vim: set ts=8 sts=4 et sw=4 tw=99:
     3  * This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #ifndef vm_String_inl_h
     8 #define vm_String_inl_h
    10 #include "vm/String.h"
    12 #include "mozilla/PodOperations.h"
    14 #include "jscntxt.h"
    16 #include "gc/Marking.h"
    18 #include "jsgcinlines.h"
    20 namespace js {
    22 template <AllowGC allowGC>
    23 static MOZ_ALWAYS_INLINE JSInlineString *
    24 NewFatInlineString(ThreadSafeContext *cx, JS::Latin1Chars chars)
    25 {
    26     size_t len = chars.length();
    27     JS_ASSERT(JSFatInlineString::lengthFits(len));
    28     JSInlineString *str = JSInlineString::lengthFits(len)
    29                           ? JSInlineString::new_<allowGC>(cx)
    30                           : JSFatInlineString::new_<allowGC>(cx);
    31     if (!str)
    32         return nullptr;
    34     jschar *p = str->init(len);
    35     for (size_t i = 0; i < len; ++i)
    36         p[i] = static_cast<jschar>(chars[i]);
    37     p[len] = '\0';
    38     return str;
    39 }
    41 template <AllowGC allowGC>
    42 static MOZ_ALWAYS_INLINE JSInlineString *
    43 NewFatInlineString(ExclusiveContext *cx, JS::TwoByteChars chars)
    44 {
    45     size_t len = chars.length();
    47     /*
    48      * Don't bother trying to find a static atom; measurement shows that not
    49      * many get here (for one, Atomize is catching them).
    50      */
    51     JS_ASSERT(JSFatInlineString::lengthFits(len));
    52     JSInlineString *str = JSInlineString::lengthFits(len)
    53                           ? JSInlineString::new_<allowGC>(cx)
    54                           : JSFatInlineString::new_<allowGC>(cx);
    55     if (!str)
    56         return nullptr;
    58     jschar *storage = str->init(len);
    59     mozilla::PodCopy(storage, chars.start().get(), len);
    60     storage[len] = 0;
    61     return str;
    62 }
    64 static inline void
    65 StringWriteBarrierPost(js::ThreadSafeContext *maybecx, JSString **strp)
    66 {
    67 }
    69 static inline void
    70 StringWriteBarrierPostRemove(js::ThreadSafeContext *maybecx, JSString **strp)
    71 {
    72 }
    74 } /* namespace js */
    76 MOZ_ALWAYS_INLINE bool
    77 JSString::validateLength(js::ThreadSafeContext *maybecx, size_t length)
    78 {
    79     if (MOZ_UNLIKELY(length > JSString::MAX_LENGTH)) {
    80         js_ReportAllocationOverflow(maybecx);
    81         return false;
    82     }
    84     return true;
    85 }
    87 MOZ_ALWAYS_INLINE void
    88 JSRope::init(js::ThreadSafeContext *cx, JSString *left, JSString *right, size_t length)
    89 {
    90     d.lengthAndFlags = buildLengthAndFlags(length, ROPE_FLAGS);
    91     d.u1.left = left;
    92     d.s.u2.right = right;
    93     js::StringWriteBarrierPost(cx, &d.u1.left);
    94     js::StringWriteBarrierPost(cx, &d.s.u2.right);
    95 }
    97 template <js::AllowGC allowGC>
    98 MOZ_ALWAYS_INLINE JSRope *
    99 JSRope::new_(js::ThreadSafeContext *cx,
   100              typename js::MaybeRooted<JSString*, allowGC>::HandleType left,
   101              typename js::MaybeRooted<JSString*, allowGC>::HandleType right,
   102              size_t length)
   103 {
   104     if (!validateLength(cx, length))
   105         return nullptr;
   106     JSRope *str = (JSRope *) js_NewGCString<allowGC>(cx);
   107     if (!str)
   108         return nullptr;
   109     str->init(cx, left, right, length);
   110     return str;
   111 }
   113 inline void
   114 JSRope::markChildren(JSTracer *trc)
   115 {
   116     js::gc::MarkStringUnbarriered(trc, &d.u1.left, "left child");
   117     js::gc::MarkStringUnbarriered(trc, &d.s.u2.right, "right child");
   118 }
   120 MOZ_ALWAYS_INLINE void
   121 JSDependentString::init(js::ThreadSafeContext *cx, JSLinearString *base, const jschar *chars,
   122                         size_t length)
   123 {
   124     JS_ASSERT(!js::IsPoisonedPtr(base));
   125     d.lengthAndFlags = buildLengthAndFlags(length, DEPENDENT_FLAGS);
   126     d.u1.chars = chars;
   127     d.s.u2.base = base;
   128     js::StringWriteBarrierPost(cx, reinterpret_cast<JSString **>(&d.s.u2.base));
   129 }
   131 MOZ_ALWAYS_INLINE JSLinearString *
   132 JSDependentString::new_(js::ExclusiveContext *cx,
   133                         JSLinearString *baseArg, const jschar *chars, size_t length)
   134 {
   135     /* Try to avoid long chains of dependent strings. */
   136     while (baseArg->isDependent())
   137         baseArg = baseArg->asDependent().base();
   139     JS_ASSERT(baseArg->isFlat());
   141     /*
   142      * The chars we are pointing into must be owned by something in the chain
   143      * of dependent or undepended strings kept alive by our base pointer.
   144      */
   145 #ifdef DEBUG
   146     for (JSLinearString *b = baseArg; ; b = b->base()) {
   147         if (chars >= b->chars() && chars < b->chars() + b->length() &&
   148             length <= b->length() - (chars - b->chars()))
   149         {
   150             break;
   151         }
   152     }
   153 #endif
   155     /*
   156      * Do not create a string dependent on inline chars from another string,
   157      * both to avoid the awkward moving-GC hazard this introduces and because it
   158      * is more efficient to immediately undepend here.
   159      */
   160     if (JSFatInlineString::lengthFits(length))
   161         return js::NewFatInlineString<js::CanGC>(cx, JS::TwoByteChars(chars, length));
   163     JSDependentString *str = (JSDependentString *)js_NewGCString<js::NoGC>(cx);
   164     if (str) {
   165         str->init(cx, baseArg, chars, length);
   166         return str;
   167     }
   169     JS::Rooted<JSLinearString*> base(cx, baseArg);
   171     str = (JSDependentString *)js_NewGCString<js::CanGC>(cx);
   172     if (!str)
   173         return nullptr;
   174     str->init(cx, base, chars, length);
   175     return str;
   176 }
   178 inline void
   179 JSString::markBase(JSTracer *trc)
   180 {
   181     JS_ASSERT(hasBase());
   182     js::gc::MarkStringUnbarriered(trc, &d.s.u2.base, "base");
   183 }
   185 MOZ_ALWAYS_INLINE void
   186 JSFlatString::init(const jschar *chars, size_t length)
   187 {
   188     d.lengthAndFlags = buildLengthAndFlags(length, FIXED_FLAGS);
   189     d.u1.chars = chars;
   190 }
   192 template <js::AllowGC allowGC>
   193 MOZ_ALWAYS_INLINE JSFlatString *
   194 JSFlatString::new_(js::ThreadSafeContext *cx, const jschar *chars, size_t length)
   195 {
   196     JS_ASSERT(chars[length] == jschar(0));
   198     if (!validateLength(cx, length))
   199         return nullptr;
   200     JSFlatString *str = (JSFlatString *)js_NewGCString<allowGC>(cx);
   201     if (!str)
   202         return nullptr;
   203     str->init(chars, length);
   204     return str;
   205 }
   207 inline js::PropertyName *
   208 JSFlatString::toPropertyName(JSContext *cx)
   209 {
   210 #ifdef DEBUG
   211     uint32_t dummy;
   212     JS_ASSERT(!isIndex(&dummy));
   213 #endif
   214     if (isAtom())
   215         return asAtom().asPropertyName();
   216     JSAtom *atom = js::AtomizeString(cx, this);
   217     if (!atom)
   218         return nullptr;
   219     return atom->asPropertyName();
   220 }
   222 template <js::AllowGC allowGC>
   223 MOZ_ALWAYS_INLINE JSInlineString *
   224 JSInlineString::new_(js::ThreadSafeContext *cx)
   225 {
   226     return (JSInlineString *)js_NewGCString<allowGC>(cx);
   227 }
   229 MOZ_ALWAYS_INLINE jschar *
   230 JSInlineString::init(size_t length)
   231 {
   232     d.lengthAndFlags = buildLengthAndFlags(length, FIXED_FLAGS);
   233     d.u1.chars = d.inlineStorage;
   234     JS_ASSERT(lengthFits(length) || (isFatInline() && JSFatInlineString::lengthFits(length)));
   235     return d.inlineStorage;
   236 }
   238 MOZ_ALWAYS_INLINE void
   239 JSInlineString::resetLength(size_t length)
   240 {
   241     d.lengthAndFlags = buildLengthAndFlags(length, FIXED_FLAGS);
   242     JS_ASSERT(lengthFits(length) || (isFatInline() && JSFatInlineString::lengthFits(length)));
   243 }
   245 template <js::AllowGC allowGC>
   246 MOZ_ALWAYS_INLINE JSFatInlineString *
   247 JSFatInlineString::new_(js::ThreadSafeContext *cx)
   248 {
   249     return js_NewGCFatInlineString<allowGC>(cx);
   250 }
   252 MOZ_ALWAYS_INLINE void
   253 JSExternalString::init(const jschar *chars, size_t length, const JSStringFinalizer *fin)
   254 {
   255     JS_ASSERT(fin);
   256     JS_ASSERT(fin->finalize);
   257     d.lengthAndFlags = buildLengthAndFlags(length, FIXED_FLAGS);
   258     d.u1.chars = chars;
   259     d.s.u2.externalFinalizer = fin;
   260 }
   262 MOZ_ALWAYS_INLINE JSExternalString *
   263 JSExternalString::new_(JSContext *cx, const jschar *chars, size_t length,
   264                        const JSStringFinalizer *fin)
   265 {
   266     JS_ASSERT(chars[length] == 0);
   268     if (!validateLength(cx, length))
   269         return nullptr;
   270     JSExternalString *str = js_NewGCExternalString(cx);
   271     if (!str)
   272         return nullptr;
   273     str->init(chars, length, fin);
   274     cx->runtime()->updateMallocCounter(cx->zone(), (length + 1) * sizeof(jschar));
   275     return str;
   276 }
   278 inline JSLinearString *
   279 js::StaticStrings::getUnitStringForElement(JSContext *cx, JSString *str, size_t index)
   280 {
   281     JS_ASSERT(index < str->length());
   283     jschar c;
   284     if (!str->getChar(cx, index, &c))
   285         return nullptr;
   286     if (c < UNIT_STATIC_LIMIT)
   287         return getUnit(c);
   288     return js_NewDependentString(cx, str, index, 1);
   289 }
   291 inline JSAtom *
   292 js::StaticStrings::getLength2(jschar c1, jschar c2)
   293 {
   294     JS_ASSERT(fitsInSmallChar(c1));
   295     JS_ASSERT(fitsInSmallChar(c2));
   296     size_t index = (((size_t)toSmallChar[c1]) << 6) + toSmallChar[c2];
   297     return length2StaticTable[index];
   298 }
   300 MOZ_ALWAYS_INLINE void
   301 JSString::finalize(js::FreeOp *fop)
   302 {
   303     /* FatInline strings are in a different arena. */
   304     JS_ASSERT(getAllocKind() != js::gc::FINALIZE_FAT_INLINE_STRING);
   306     if (isFlat())
   307         asFlat().finalize(fop);
   308     else
   309         JS_ASSERT(isDependent() || isRope());
   310 }
   312 inline void
   313 JSFlatString::finalize(js::FreeOp *fop)
   314 {
   315     JS_ASSERT(getAllocKind() != js::gc::FINALIZE_FAT_INLINE_STRING);
   317     if (chars() != d.inlineStorage)
   318         fop->free_(const_cast<jschar *>(chars()));
   319 }
   321 inline void
   322 JSFatInlineString::finalize(js::FreeOp *fop)
   323 {
   324     JS_ASSERT(getAllocKind() == js::gc::FINALIZE_FAT_INLINE_STRING);
   326     if (chars() != d.inlineStorage)
   327         fop->free_(const_cast<jschar *>(chars()));
   328 }
   330 inline void
   331 JSAtom::finalize(js::FreeOp *fop)
   332 {
   333     JS_ASSERT(JSString::isAtom());
   334     JS_ASSERT(JSString::isFlat());
   336     if (chars() != d.inlineStorage)
   337         fop->free_(const_cast<jschar *>(chars()));
   338 }
   340 inline void
   341 JSExternalString::finalize(js::FreeOp *fop)
   342 {
   343     const JSStringFinalizer *fin = externalFinalizer();
   344     fin->finalize(fin, const_cast<jschar *>(chars()));
   345 }
   347 #endif /* vm_String_inl_h */

mercurial