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 +}