js/src/vm/RegExpStatics.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/js/src/vm/RegExpStatics.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,122 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99:
     1.6 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#include "vm/RegExpStatics.h"
    1.11 +
    1.12 +#include "vm/RegExpStaticsObject.h"
    1.13 +
    1.14 +#include "jsobjinlines.h"
    1.15 +
    1.16 +using namespace js;
    1.17 +
    1.18 +/*
    1.19 + * RegExpStatics allocates memory -- in order to keep the statics stored
    1.20 + * per-global and not leak, we create a js::Class to wrap the C++ instance and
    1.21 + * provide an appropriate finalizer. We store an instance of that js::Class in
    1.22 + * a global reserved slot.
    1.23 + */
    1.24 +
    1.25 +static void
    1.26 +resc_finalize(FreeOp *fop, JSObject *obj)
    1.27 +{
    1.28 +    RegExpStatics *res = static_cast<RegExpStatics *>(obj->getPrivate());
    1.29 +    fop->delete_(res);
    1.30 +}
    1.31 +
    1.32 +static void
    1.33 +resc_trace(JSTracer *trc, JSObject *obj)
    1.34 +{
    1.35 +    void *pdata = obj->getPrivate();
    1.36 +    JS_ASSERT(pdata);
    1.37 +    RegExpStatics *res = static_cast<RegExpStatics *>(pdata);
    1.38 +    res->mark(trc);
    1.39 +}
    1.40 +
    1.41 +const Class RegExpStaticsObject::class_ = {
    1.42 +    "RegExpStatics",
    1.43 +    JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS,
    1.44 +    JS_PropertyStub,         /* addProperty */
    1.45 +    JS_DeletePropertyStub,   /* delProperty */
    1.46 +    JS_PropertyStub,         /* getProperty */
    1.47 +    JS_StrictPropertyStub,   /* setProperty */
    1.48 +    JS_EnumerateStub,
    1.49 +    JS_ResolveStub,
    1.50 +    JS_ConvertStub,
    1.51 +    resc_finalize,
    1.52 +    nullptr,                 /* call        */
    1.53 +    nullptr,                 /* hasInstance */
    1.54 +    nullptr,                 /* construct   */
    1.55 +    resc_trace
    1.56 +};
    1.57 +
    1.58 +JSObject *
    1.59 +RegExpStatics::create(JSContext *cx, GlobalObject *parent)
    1.60 +{
    1.61 +    JSObject *obj = NewObjectWithGivenProto(cx, &RegExpStaticsObject::class_, nullptr, parent);
    1.62 +    if (!obj)
    1.63 +        return nullptr;
    1.64 +    RegExpStatics *res = cx->new_<RegExpStatics>();
    1.65 +    if (!res)
    1.66 +        return nullptr;
    1.67 +    obj->setPrivate(static_cast<void *>(res));
    1.68 +    return obj;
    1.69 +}
    1.70 +
    1.71 +void
    1.72 +RegExpStatics::markFlagsSet(JSContext *cx)
    1.73 +{
    1.74 +    // Flags set on the RegExp function get propagated to constructed RegExp
    1.75 +    // objects, which interferes with optimizations that inline RegExp cloning
    1.76 +    // or avoid cloning entirely. Scripts making this assumption listen to
    1.77 +    // type changes on RegExp.prototype, so mark a state change to trigger
    1.78 +    // recompilation of all such code (when recompiling, a stub call will
    1.79 +    // always be performed).
    1.80 +    JS_ASSERT(this == cx->global()->getRegExpStatics());
    1.81 +
    1.82 +    types::MarkTypeObjectFlags(cx, cx->global(), types::OBJECT_FLAG_REGEXP_FLAGS_SET);
    1.83 +}
    1.84 +
    1.85 +bool
    1.86 +RegExpStatics::executeLazy(JSContext *cx)
    1.87 +{
    1.88 +    if (!pendingLazyEvaluation)
    1.89 +        return true;
    1.90 +
    1.91 +    JS_ASSERT(lazySource);
    1.92 +    JS_ASSERT(matchesInput);
    1.93 +    JS_ASSERT(lazyIndex != size_t(-1));
    1.94 +
    1.95 +    /* Retrieve or create the RegExpShared in this compartment. */
    1.96 +    RegExpGuard g(cx);
    1.97 +    if (!cx->compartment()->regExps.get(cx, lazySource, lazyFlags, &g))
    1.98 +        return false;
    1.99 +
   1.100 +    /*
   1.101 +     * It is not necessary to call aboutToWrite(): evaluation of
   1.102 +     * implicit copies is safe.
   1.103 +     */
   1.104 +
   1.105 +    size_t length = matchesInput->length();
   1.106 +    const jschar *chars = matchesInput->chars();
   1.107 +
   1.108 +    /* Execute the full regular expression. */
   1.109 +    RegExpRunStatus status = g->execute(cx, chars, length, &this->lazyIndex, this->matches);
   1.110 +    if (status == RegExpRunStatus_Error)
   1.111 +        return false;
   1.112 +
   1.113 +    /*
   1.114 +     * RegExpStatics are only updated on successful (matching) execution.
   1.115 +     * Re-running the same expression must therefore produce a matching result.
   1.116 +     */
   1.117 +    JS_ASSERT(status == RegExpRunStatus_Success);
   1.118 +
   1.119 +    /* Unset lazy state and remove rooted values that now have no use. */
   1.120 +    pendingLazyEvaluation = false;
   1.121 +    lazySource = nullptr;
   1.122 +    lazyIndex = size_t(-1);
   1.123 +
   1.124 +    return true;
   1.125 +}

mercurial