Line data Source code
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/. */
6 :
7 : #include "vm/RegExpStatics.h"
8 :
9 : #include "vm/RegExpStaticsObject.h"
10 :
11 : #include "vm/NativeObject-inl.h"
12 :
13 : using namespace js;
14 :
15 : /*
16 : * RegExpStatics allocates memory -- in order to keep the statics stored
17 : * per-global and not leak, we create a js::Class to wrap the C++ instance and
18 : * provide an appropriate finalizer. We lazily create and store an instance of
19 : * that js::Class in a global reserved slot.
20 : */
21 :
22 : static void
23 0 : resc_finalize(FreeOp* fop, JSObject* obj)
24 : {
25 0 : MOZ_ASSERT(fop->onActiveCooperatingThread());
26 0 : RegExpStatics* res = static_cast<RegExpStatics*>(obj->as<RegExpStaticsObject>().getPrivate());
27 0 : fop->delete_(res);
28 0 : }
29 :
30 : static void
31 0 : resc_trace(JSTracer* trc, JSObject* obj)
32 : {
33 0 : void* pdata = obj->as<RegExpStaticsObject>().getPrivate();
34 0 : if (pdata)
35 0 : static_cast<RegExpStatics*>(pdata)->trace(trc);
36 0 : }
37 :
38 : static const ClassOps RegExpStaticsObjectClassOps = {
39 : nullptr, /* addProperty */
40 : nullptr, /* delProperty */
41 : nullptr, /* getProperty */
42 : nullptr, /* setProperty */
43 : nullptr, /* enumerate */
44 : nullptr, /* newEnumerate */
45 : nullptr, /* resolve */
46 : nullptr, /* mayResolve */
47 : resc_finalize,
48 : nullptr, /* call */
49 : nullptr, /* hasInstance */
50 : nullptr, /* construct */
51 : resc_trace
52 : };
53 :
54 : const Class RegExpStaticsObject::class_ = {
55 : "RegExpStatics",
56 : JSCLASS_HAS_PRIVATE |
57 : JSCLASS_FOREGROUND_FINALIZE,
58 : &RegExpStaticsObjectClassOps
59 : };
60 :
61 : RegExpStaticsObject*
62 13 : RegExpStatics::create(JSContext* cx, Handle<GlobalObject*> parent)
63 : {
64 13 : RegExpStaticsObject* obj = NewObjectWithGivenProto<RegExpStaticsObject>(cx, nullptr);
65 13 : if (!obj)
66 0 : return nullptr;
67 13 : RegExpStatics* res = cx->new_<RegExpStatics>();
68 13 : if (!res)
69 0 : return nullptr;
70 13 : obj->setPrivate(static_cast<void*>(res));
71 13 : return obj;
72 : }
73 :
74 : bool
75 6 : RegExpStatics::executeLazy(JSContext* cx)
76 : {
77 6 : if (!pendingLazyEvaluation)
78 0 : return true;
79 :
80 6 : MOZ_ASSERT(lazySource);
81 6 : MOZ_ASSERT(matchesInput);
82 6 : MOZ_ASSERT(lazyIndex != size_t(-1));
83 :
84 : /* Retrieve or create the RegExpShared in this zone. */
85 12 : RootedAtom source(cx, lazySource);
86 12 : RootedRegExpShared shared(cx, cx->zone()->regExps.get(cx, source, lazyFlags));
87 6 : if (!shared)
88 0 : return false;
89 :
90 : /*
91 : * It is not necessary to call aboutToWrite(): evaluation of
92 : * implicit copies is safe.
93 : */
94 :
95 : /* Execute the full regular expression. */
96 12 : RootedLinearString input(cx, matchesInput);
97 12 : RegExpRunStatus status = RegExpShared::execute(cx, &shared, input, lazyIndex, &this->matches,
98 6 : nullptr);
99 6 : if (status == RegExpRunStatus_Error)
100 0 : return false;
101 :
102 : /*
103 : * RegExpStatics are only updated on successful (matching) execution.
104 : * Re-running the same expression must therefore produce a matching result.
105 : */
106 6 : MOZ_ASSERT(status == RegExpRunStatus_Success);
107 :
108 : /* Unset lazy state and remove rooted values that now have no use. */
109 6 : pendingLazyEvaluation = false;
110 6 : lazySource = nullptr;
111 6 : lazyIndex = size_t(-1);
112 :
113 6 : return true;
114 : }
|