js/src/vm/RegExpStatics.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
michael@0 2 * vim: set ts=8 sts=4 et sw=4 tw=99:
michael@0 3 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #include "vm/RegExpStatics.h"
michael@0 8
michael@0 9 #include "vm/RegExpStaticsObject.h"
michael@0 10
michael@0 11 #include "jsobjinlines.h"
michael@0 12
michael@0 13 using namespace js;
michael@0 14
michael@0 15 /*
michael@0 16 * RegExpStatics allocates memory -- in order to keep the statics stored
michael@0 17 * per-global and not leak, we create a js::Class to wrap the C++ instance and
michael@0 18 * provide an appropriate finalizer. We store an instance of that js::Class in
michael@0 19 * a global reserved slot.
michael@0 20 */
michael@0 21
michael@0 22 static void
michael@0 23 resc_finalize(FreeOp *fop, JSObject *obj)
michael@0 24 {
michael@0 25 RegExpStatics *res = static_cast<RegExpStatics *>(obj->getPrivate());
michael@0 26 fop->delete_(res);
michael@0 27 }
michael@0 28
michael@0 29 static void
michael@0 30 resc_trace(JSTracer *trc, JSObject *obj)
michael@0 31 {
michael@0 32 void *pdata = obj->getPrivate();
michael@0 33 JS_ASSERT(pdata);
michael@0 34 RegExpStatics *res = static_cast<RegExpStatics *>(pdata);
michael@0 35 res->mark(trc);
michael@0 36 }
michael@0 37
michael@0 38 const Class RegExpStaticsObject::class_ = {
michael@0 39 "RegExpStatics",
michael@0 40 JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS,
michael@0 41 JS_PropertyStub, /* addProperty */
michael@0 42 JS_DeletePropertyStub, /* delProperty */
michael@0 43 JS_PropertyStub, /* getProperty */
michael@0 44 JS_StrictPropertyStub, /* setProperty */
michael@0 45 JS_EnumerateStub,
michael@0 46 JS_ResolveStub,
michael@0 47 JS_ConvertStub,
michael@0 48 resc_finalize,
michael@0 49 nullptr, /* call */
michael@0 50 nullptr, /* hasInstance */
michael@0 51 nullptr, /* construct */
michael@0 52 resc_trace
michael@0 53 };
michael@0 54
michael@0 55 JSObject *
michael@0 56 RegExpStatics::create(JSContext *cx, GlobalObject *parent)
michael@0 57 {
michael@0 58 JSObject *obj = NewObjectWithGivenProto(cx, &RegExpStaticsObject::class_, nullptr, parent);
michael@0 59 if (!obj)
michael@0 60 return nullptr;
michael@0 61 RegExpStatics *res = cx->new_<RegExpStatics>();
michael@0 62 if (!res)
michael@0 63 return nullptr;
michael@0 64 obj->setPrivate(static_cast<void *>(res));
michael@0 65 return obj;
michael@0 66 }
michael@0 67
michael@0 68 void
michael@0 69 RegExpStatics::markFlagsSet(JSContext *cx)
michael@0 70 {
michael@0 71 // Flags set on the RegExp function get propagated to constructed RegExp
michael@0 72 // objects, which interferes with optimizations that inline RegExp cloning
michael@0 73 // or avoid cloning entirely. Scripts making this assumption listen to
michael@0 74 // type changes on RegExp.prototype, so mark a state change to trigger
michael@0 75 // recompilation of all such code (when recompiling, a stub call will
michael@0 76 // always be performed).
michael@0 77 JS_ASSERT(this == cx->global()->getRegExpStatics());
michael@0 78
michael@0 79 types::MarkTypeObjectFlags(cx, cx->global(), types::OBJECT_FLAG_REGEXP_FLAGS_SET);
michael@0 80 }
michael@0 81
michael@0 82 bool
michael@0 83 RegExpStatics::executeLazy(JSContext *cx)
michael@0 84 {
michael@0 85 if (!pendingLazyEvaluation)
michael@0 86 return true;
michael@0 87
michael@0 88 JS_ASSERT(lazySource);
michael@0 89 JS_ASSERT(matchesInput);
michael@0 90 JS_ASSERT(lazyIndex != size_t(-1));
michael@0 91
michael@0 92 /* Retrieve or create the RegExpShared in this compartment. */
michael@0 93 RegExpGuard g(cx);
michael@0 94 if (!cx->compartment()->regExps.get(cx, lazySource, lazyFlags, &g))
michael@0 95 return false;
michael@0 96
michael@0 97 /*
michael@0 98 * It is not necessary to call aboutToWrite(): evaluation of
michael@0 99 * implicit copies is safe.
michael@0 100 */
michael@0 101
michael@0 102 size_t length = matchesInput->length();
michael@0 103 const jschar *chars = matchesInput->chars();
michael@0 104
michael@0 105 /* Execute the full regular expression. */
michael@0 106 RegExpRunStatus status = g->execute(cx, chars, length, &this->lazyIndex, this->matches);
michael@0 107 if (status == RegExpRunStatus_Error)
michael@0 108 return false;
michael@0 109
michael@0 110 /*
michael@0 111 * RegExpStatics are only updated on successful (matching) execution.
michael@0 112 * Re-running the same expression must therefore produce a matching result.
michael@0 113 */
michael@0 114 JS_ASSERT(status == RegExpRunStatus_Success);
michael@0 115
michael@0 116 /* Unset lazy state and remove rooted values that now have no use. */
michael@0 117 pendingLazyEvaluation = false;
michael@0 118 lazySource = nullptr;
michael@0 119 lazyIndex = size_t(-1);
michael@0 120
michael@0 121 return true;
michael@0 122 }

mercurial