LCOV - code coverage report
Current view: directory - js/src/vm - RegExpStatics-inl.h (source / functions) Found Hit Coverage
Test: app.info Lines: 151 103 68.2 %
Date: 2012-06-02 Functions: 25 20 80.0 %

       1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2                 :  * vim: set ts=8 sw=4 et tw=99 ft=cpp:
       3                 :  *
       4                 :  * ***** BEGIN LICENSE BLOCK *****
       5                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       6                 :  *
       7                 :  * The contents of this file are subject to the Mozilla Public License Version
       8                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       9                 :  * the License. You may obtain a copy of the License at
      10                 :  * http://www.mozilla.org/MPL/
      11                 :  *
      12                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      13                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      14                 :  * for the specific language governing rights and limitations under the
      15                 :  * License.
      16                 :  *
      17                 :  * The Original Code is Mozilla SpiderMonkey JavaScript code.
      18                 :  *
      19                 :  * The Initial Developer of the Original Code is
      20                 :  * the Mozilla Foundation.
      21                 :  * Portions created by the Initial Developer are Copyright (C) 2011
      22                 :  * the Initial Developer. All Rights Reserved.
      23                 :  *
      24                 :  * Contributor(s):
      25                 :  *  Chris Leary <cdleary@mozilla.com>
      26                 :  *
      27                 :  * Alternatively, the contents of this file may be used under the terms of
      28                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      29                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      30                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      31                 :  * of those above. If you wish to allow use of your version of this file only
      32                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      33                 :  * use your version of this file under the terms of the MPL, indicate your
      34                 :  * decision by deleting the provisions above and replace them with the notice
      35                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      36                 :  * the provisions above, a recipient may use your version of this file under
      37                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      38                 :  *
      39                 :  * ***** END LICENSE BLOCK ***** */
      40                 : 
      41                 : #ifndef RegExpStatics_inl_h__
      42                 : #define RegExpStatics_inl_h__
      43                 : 
      44                 : #include "RegExpStatics.h"
      45                 : 
      46                 : #include "vm/String-inl.h"
      47                 : 
      48                 : namespace js {
      49                 : 
      50                 : inline js::RegExpStatics *
      51         2389101 : js::GlobalObject::getRegExpStatics() const
      52                 : {
      53         2389101 :     JSObject &resObj = getSlot(REGEXP_STATICS).toObject();
      54         2389101 :     return static_cast<RegExpStatics *>(resObj.getPrivate());
      55                 : }
      56                 : 
      57                 : inline size_t
      58              59 : SizeOfRegExpStaticsData(const JSObject *obj, JSMallocSizeOfFun mallocSizeOf)
      59                 : {
      60              59 :     return mallocSizeOf(obj->getPrivate());
      61                 : }
      62                 : 
      63                 : inline
      64           38635 : RegExpStatics::RegExpStatics()
      65                 :   : bufferLink(NULL),
      66           38635 :     copied(false)
      67                 : {
      68           38635 :     clear();
      69           38635 : }
      70                 : 
      71                 : inline bool
      72          787770 : RegExpStatics::createDependent(JSContext *cx, size_t start, size_t end, Value *out) const 
      73                 : {
      74          787770 :     JS_ASSERT(start <= end);
      75          787770 :     JS_ASSERT(end <= matchPairsInput->length());
      76          787770 :     JSString *str = js_NewDependentString(cx, matchPairsInput, start, end - start);
      77          787770 :     if (!str)
      78               0 :         return false;
      79          787770 :     *out = StringValue(str);
      80          787770 :     return true;
      81                 : }
      82                 : 
      83                 : inline bool
      84               0 : RegExpStatics::createPendingInput(JSContext *cx, Value *out) const
      85                 : {
      86               0 :     out->setString(pendingInput ? pendingInput.get() : cx->runtime->emptyString);
      87               0 :     return true;
      88                 : }
      89                 : 
      90                 : inline bool
      91          787752 : RegExpStatics::makeMatch(JSContext *cx, size_t checkValidIndex, size_t pairNum, Value *out) const
      92                 : {
      93          787752 :     if (checkValidIndex / 2 >= pairCount() || matchPairs[checkValidIndex] < 0) {
      94               0 :         out->setString(cx->runtime->emptyString);
      95               0 :         return true;
      96                 :     }
      97          787752 :     return createDependent(cx, get(pairNum, 0), get(pairNum, 1), out);
      98                 : }
      99                 : 
     100                 : inline bool
     101               9 : RegExpStatics::createLastParen(JSContext *cx, Value *out) const
     102                 : {
     103               9 :     if (pairCount() <= 1) {
     104               0 :         out->setString(cx->runtime->emptyString);
     105               0 :         return true;
     106                 :     }
     107               9 :     size_t num = pairCount() - 1;
     108               9 :     int start = get(num, 0);
     109               9 :     int end = get(num, 1);
     110               9 :     if (start == -1) {
     111               0 :         out->setString(cx->runtime->emptyString);
     112               0 :         return true;
     113                 :     }
     114               9 :     JS_ASSERT(start >= 0 && end >= 0);
     115               9 :     JS_ASSERT(end >= start);
     116               9 :     return createDependent(cx, start, end, out);
     117                 : }
     118                 : 
     119                 : inline bool
     120               0 : RegExpStatics::createLeftContext(JSContext *cx, Value *out) const
     121                 : {
     122               0 :     if (!pairCount()) {
     123               0 :         out->setString(cx->runtime->emptyString);
     124               0 :         return true;
     125                 :     }
     126               0 :     if (matchPairs[0] < 0) {
     127               0 :         *out = UndefinedValue();
     128               0 :         return true;
     129                 :     }
     130               0 :     return createDependent(cx, 0, matchPairs[0], out);
     131                 : }
     132                 : 
     133                 : inline bool
     134               9 : RegExpStatics::createRightContext(JSContext *cx, Value *out) const
     135                 : {
     136               9 :     if (!pairCount()) {
     137               0 :         out->setString(cx->runtime->emptyString);
     138               0 :         return true;
     139                 :     }
     140               9 :     if (matchPairs[1] < 0) {
     141               0 :         *out = UndefinedValue();
     142               0 :         return true;
     143                 :     }
     144               9 :     return createDependent(cx, matchPairs[1], matchPairsInput->length(), out);
     145                 : }
     146                 : 
     147                 : inline void
     148            8966 : RegExpStatics::getParen(size_t pairNum, JSSubString *out) const
     149                 : {
     150            8966 :     checkParenNum(pairNum);
     151            8966 :     if (!pairIsPresent(pairNum)) {
     152              18 :         *out = js_EmptySubString;
     153              18 :         return;
     154                 :     }
     155            8948 :     out->chars = matchPairsInput->chars() + get(pairNum, 0);
     156            8948 :     out->length = getParenLength(pairNum);
     157                 : }
     158                 : 
     159                 : inline void
     160           48666 : RegExpStatics::getLastMatch(JSSubString *out) const
     161                 : {
     162           48666 :     if (!pairCount()) {
     163               0 :         *out = js_EmptySubString;
     164               0 :         return;
     165                 :     }
     166           48666 :     JS_ASSERT(matchPairsInput);
     167           48666 :     out->chars = matchPairsInput->chars() + get(0, 0);
     168           48666 :     JS_ASSERT(get(0, 1) >= get(0, 0));
     169           48666 :     out->length = get(0, 1) - get(0, 0);
     170                 : }
     171                 : 
     172                 : inline void
     173               0 : RegExpStatics::getLastParen(JSSubString *out) const
     174                 : {
     175               0 :     size_t pc = pairCount();
     176                 :     /* Note: the first pair is the whole match. */
     177               0 :     if (pc <= 1) {
     178               0 :         *out = js_EmptySubString;
     179               0 :         return;
     180                 :     }
     181               0 :     getParen(pc - 1, out);
     182                 : }
     183                 : 
     184                 : inline void
     185               0 : RegExpStatics::getLeftContext(JSSubString *out) const
     186                 : {
     187               0 :     if (!pairCount()) {
     188               0 :         *out = js_EmptySubString;
     189               0 :         return;
     190                 :     }
     191               0 :     out->chars = matchPairsInput->chars();
     192               0 :     out->length = get(0, 0);
     193                 : }
     194                 : 
     195                 : inline void
     196          209975 : RegExpStatics::getRightContext(JSSubString *out) const
     197                 : {
     198          209975 :     if (!pairCount()) {
     199               0 :         *out = js_EmptySubString;
     200               0 :         return;
     201                 :     }
     202          209975 :     out->chars = matchPairsInput->chars() + get(0, 1);
     203          209975 :     JS_ASSERT(get(0, 1) <= int(matchPairsInput->length()));
     204          209975 :     out->length = matchPairsInput->length() - get(0, 1);
     205                 : }
     206                 : 
     207                 : inline void
     208              76 : RegExpStatics::copyTo(RegExpStatics &dst)
     209                 : {
     210              76 :     dst.matchPairs.clear();
     211                 :     /* 'save' has already reserved space in matchPairs */
     212              76 :     dst.matchPairs.infallibleAppend(matchPairs);
     213              76 :     dst.matchPairsInput = matchPairsInput;
     214              76 :     dst.pendingInput = pendingInput;
     215              76 :     dst.flags = flags;
     216              76 : }
     217                 : 
     218                 : inline void
     219         2618684 : RegExpStatics::aboutToWrite()
     220                 : {
     221         2618684 :     if (bufferLink && !bufferLink->copied) {
     222              38 :         copyTo(*bufferLink);
     223              38 :         bufferLink->copied = true;
     224                 :     }
     225         2618684 : }
     226                 : 
     227                 : inline void
     228           28361 : RegExpStatics::restore()
     229                 : {
     230           28361 :     if (bufferLink->copied)
     231              38 :         bufferLink->copyTo(*this);
     232           28361 :     bufferLink = bufferLink->bufferLink;
     233           28361 : }
     234                 : 
     235                 : inline bool
     236         2566819 : RegExpStatics::updateFromMatchPairs(JSContext *cx, JSLinearString *input, MatchPairs *newPairs)
     237                 : {
     238         2566819 :     JS_ASSERT(input);
     239         2566819 :     aboutToWrite();
     240                 :     BarrieredSetPair<JSString, JSLinearString>(cx->compartment,
     241                 :                                                pendingInput, input,
     242         2566819 :                                                matchPairsInput, input);
     243                 : 
     244         2566819 :     if (!matchPairs.resizeUninitialized(2 * newPairs->pairCount())) {
     245               0 :         js_ReportOutOfMemory(cx);
     246               0 :         return false;
     247                 :     }
     248                 : 
     249         6984902 :     for (size_t i = 0; i < newPairs->pairCount(); ++i) {
     250         4418083 :         matchPairs[2 * i] = newPairs->pair(i).start;
     251         4418083 :         matchPairs[2 * i + 1] = newPairs->pair(i).limit;
     252                 :     }
     253                 : 
     254         2566819 :     return true;
     255                 : }
     256                 : 
     257                 : inline void
     258           51847 : RegExpStatics::clear()
     259                 : {
     260           51847 :     aboutToWrite();
     261           51847 :     flags = RegExpFlag(0);
     262           51847 :     pendingInput = NULL;
     263           51847 :     matchPairsInput = NULL;
     264           51847 :     matchPairs.clear();
     265           51847 : }
     266                 : 
     267                 : inline void
     268               9 : RegExpStatics::setPendingInput(JSString *newInput)
     269                 : {
     270               9 :     aboutToWrite();
     271               9 :     pendingInput = newInput;
     272               9 : }
     273                 : 
     274           56722 : PreserveRegExpStatics::~PreserveRegExpStatics()
     275                 : {
     276           28361 :     original->restore();
     277           28361 : }
     278                 : 
     279                 : inline void
     280               9 : RegExpStatics::setMultiline(JSContext *cx, bool enabled)
     281                 : {
     282               9 :     aboutToWrite();
     283               9 :     if (enabled) {
     284               9 :         flags = RegExpFlag(flags | MultilineFlag);
     285               9 :         markFlagsSet(cx);
     286                 :     } else {
     287               0 :         flags = RegExpFlag(flags & ~MultilineFlag);
     288                 :     }
     289               9 : }
     290                 : 
     291                 : inline void
     292               9 : RegExpStatics::markFlagsSet(JSContext *cx)
     293                 : {
     294                 :     /*
     295                 :      * Flags set on the RegExp function get propagated to constructed RegExp
     296                 :      * objects, which interferes with optimizations that inline RegExp cloning
     297                 :      * or avoid cloning entirely. Scripts making this assumption listen to
     298                 :      * type changes on RegExp.prototype, so mark a state change to trigger
     299                 :      * recompilation of all such code (when recompiling, a stub call will
     300                 :      * always be performed).
     301                 :      */
     302               9 :     GlobalObject *global = GetGlobalForScopeChain(cx);
     303               9 :     JS_ASSERT(this == global->getRegExpStatics());
     304                 : 
     305               9 :     types::MarkTypeObjectFlags(cx, global, types::OBJECT_FLAG_REGEXP_FLAGS_SET);
     306               9 : }
     307                 : 
     308                 : inline void
     309               0 : RegExpStatics::reset(JSContext *cx, JSString *newInput, bool newMultiline)
     310                 : {
     311               0 :     aboutToWrite();
     312               0 :     clear();
     313               0 :     pendingInput = newInput;
     314               0 :     setMultiline(cx, newMultiline);
     315               0 :     checkInvariants();
     316               0 : }
     317                 : 
     318                 : } /* namespace js */
     319                 : 
     320                 : inline js::RegExpStatics *
     321         2369599 : JSContext::regExpStatics()
     322                 : {
     323         2369599 :     return js::GetGlobalForScopeChain(this)->getRegExpStatics();
     324                 : }
     325                 : 
     326                 : #endif

Generated by: LCOV version 1.7