/* * Copyright (C) 2012, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef RegExpCachedResult_h #define RegExpCachedResult_h #include "RegExpObject.h" #include "SuperSampler.h" namespace JSC { class JSArray; class JSString; // RegExpCachedResult is used to track the cached results of the last // match, stores on the RegExp constructor (e.g. $&, $_, $1, $2 ...). // These values will be lazily generated on demand, so the cached result // may be in a lazy or reified state. A lazy state is indicated by a // value of m_result indicating a successful match, and a reified state // is indicated by setting m_result to MatchResult::failed(). // Following a successful match, m_result, m_lastInput and m_lastRegExp // can be used to reify the results from the match, following reification // m_reifiedResult and m_reifiedInput hold the cached results. class RegExpCachedResult { public: RegExpCachedResult(VM& vm, JSObject* owner, RegExp* emptyRegExp) : m_result(0, 0) , m_reified(false) { m_lastInput.set(vm, owner, jsEmptyString(&vm)); m_lastRegExp.set(vm, owner, emptyRegExp); } ALWAYS_INLINE void record(VM& vm, JSObject* owner, RegExp* regExp, JSString* input, MatchResult result) { vm.heap.writeBarrier(owner); m_lastRegExp.setWithoutWriteBarrier(regExp); m_lastInput.setWithoutWriteBarrier(input); m_result = result; m_reified = false; } JSArray* lastResult(ExecState*, JSObject* owner); void setInput(ExecState*, JSObject* owner, JSString*); JSString* leftContext(ExecState*, JSObject* owner); JSString* rightContext(ExecState*, JSObject* owner); JSString* input() { return m_reified ? m_reifiedInput.get() : m_lastInput.get(); } void visitChildren(SlotVisitor&); static ptrdiff_t offsetOfLastRegExp() { return OBJECT_OFFSETOF(RegExpCachedResult, m_lastRegExp); } static ptrdiff_t offsetOfLastInput() { return OBJECT_OFFSETOF(RegExpCachedResult, m_lastInput); } static ptrdiff_t offsetOfResult() { return OBJECT_OFFSETOF(RegExpCachedResult, m_result); } static ptrdiff_t offsetOfReified() { return OBJECT_OFFSETOF(RegExpCachedResult, m_reified); } private: MatchResult m_result; bool m_reified; WriteBarrier m_lastInput; WriteBarrier m_lastRegExp; WriteBarrier m_reifiedResult; WriteBarrier m_reifiedInput; WriteBarrier m_reifiedLeftContext; WriteBarrier m_reifiedRightContext; }; } // namespace JSC #endif // RegExpCachedResult_h