Example #1
0
bool
js::XDRAtom(XDRState<mode> *xdr, MutableHandleAtom atomp)
{
    AssertCanGC();
    if (mode == XDR_ENCODE) {
        uint32_t nchars = atomp->length();
        if (!xdr->codeUint32(&nchars))
            return false;

        jschar *chars = const_cast<jschar *>(atomp->getChars(xdr->cx()));
        if (!chars)
            return false;

        return xdr->codeChars(chars, nchars);
    }

    /* Avoid JSString allocation for already existing atoms. See bug 321985. */
    uint32_t nchars;
    if (!xdr->codeUint32(&nchars))
        return false;

    JSContext *cx = xdr->cx();
    JSAtom *atom;
#if IS_LITTLE_ENDIAN
    /* Directly access the little endian chars in the XDR buffer. */
    const jschar *chars = reinterpret_cast<const jschar *>(xdr->buf.read(nchars * sizeof(jschar)));
    atom = AtomizeChars<CanGC>(cx, chars, nchars);
#else
    /*
     * We must copy chars to a temporary buffer to convert between little and
     * big endian data.
     */
    jschar *chars;
    jschar stackChars[256];
    if (nchars <= ArrayLength(stackChars)) {
        chars = stackChars;
    } else {
        /*
         * This is very uncommon. Don't use the tempLifoAlloc arena for this as
         * most allocations here will be bigger than tempLifoAlloc's default
         * chunk size.
         */
        chars = cx->runtime->pod_malloc<jschar>(nchars);
        if (!chars)
            return false;
    }

    JS_ALWAYS_TRUE(xdr->codeChars(chars, nchars));
    atom = AtomizeChars<CanGC>(cx, chars, nchars);
    if (chars != stackChars)
        js_free(chars);
#endif /* !IS_LITTLE_ENDIAN */

    if (!atom)
        return false;
    atomp.set(atom);
    return true;
}
Example #2
0
bool
js::XDRAtom(XDRState<mode> *xdr, MutableHandleAtom atomp)
{
    if (mode == XDR_ENCODE) {
        static_assert(JSString::MAX_LENGTH <= INT32_MAX, "String length must fit in 31 bits");
        uint32_t length = atomp->length();
        uint32_t lengthAndEncoding = (length << 1) | uint32_t(atomp->hasLatin1Chars());
        if (!xdr->codeUint32(&lengthAndEncoding))
            return false;

        JS::AutoCheckCannotGC nogc;
        return atomp->hasLatin1Chars()
               ? xdr->codeChars(atomp->latin1Chars(nogc), length)
               : xdr->codeChars(const_cast<char16_t*>(atomp->twoByteChars(nogc)), length);
    }

    /* Avoid JSString allocation for already existing atoms. See bug 321985. */
    uint32_t lengthAndEncoding;
    if (!xdr->codeUint32(&lengthAndEncoding))
        return false;

    uint32_t length = lengthAndEncoding >> 1;
    bool latin1 = lengthAndEncoding & 0x1;

    JSContext *cx = xdr->cx();
    JSAtom *atom;
    if (latin1) {
        const Latin1Char *chars = reinterpret_cast<const Latin1Char *>(xdr->buf.read(length));
        atom = AtomizeChars(cx, chars, length);
    } else {
#if IS_LITTLE_ENDIAN
        /* Directly access the little endian chars in the XDR buffer. */
        const char16_t *chars = reinterpret_cast<const char16_t *>(xdr->buf.read(length * sizeof(char16_t)));
        atom = AtomizeChars(cx, chars, length);
#else
        /*
         * We must copy chars to a temporary buffer to convert between little and
         * big endian data.
         */
        char16_t *chars;
        char16_t stackChars[256];
        if (length <= ArrayLength(stackChars)) {
            chars = stackChars;
        } else {
            /*
             * This is very uncommon. Don't use the tempLifoAlloc arena for this as
             * most allocations here will be bigger than tempLifoAlloc's default
             * chunk size.
             */
            chars = cx->runtime()->pod_malloc<char16_t>(length);
            if (!chars)
                return false;
        }

        JS_ALWAYS_TRUE(xdr->codeChars(chars, length));
        atom = AtomizeChars(cx, chars, length);
        if (chars != stackChars)
            js_free(chars);
#endif /* !IS_LITTLE_ENDIAN */
    }

    if (!atom)
        return false;
    atomp.set(atom);
    return true;
}