/[jscoverage]/trunk/js/jsstr.cpp
ViewVC logotype

Diff of /trunk/js/jsstr.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 332 by siliconforks, Thu Oct 23 19:03:33 2008 UTC revision 460 by siliconforks, Sat Sep 26 23:15:22 2009 UTC
# Line 1  Line 1 
1  /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-  /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2   * vim: set ts=8 sw=4 et tw=80:   * vim: set ts=8 sw=4 et tw=99:
3   *   *
4   * ***** BEGIN LICENSE BLOCK *****   * ***** BEGIN LICENSE BLOCK *****
5   * Version: MPL 1.1/GPL 2.0/LGPL 2.1   * Version: MPL 1.1/GPL 2.0/LGPL 2.1
# Line 59  Line 59 
59  #include "jsarray.h"  #include "jsarray.h"
60  #include "jsatom.h"  #include "jsatom.h"
61  #include "jsbool.h"  #include "jsbool.h"
62    #include "jsbuiltins.h"
63  #include "jscntxt.h"  #include "jscntxt.h"
64  #include "jsversion.h"  #include "jsversion.h"
65  #include "jsgc.h"  #include "jsgc.h"
# Line 69  Line 70 
70  #include "jsopcode.h"  #include "jsopcode.h"
71  #include "jsregexp.h"  #include "jsregexp.h"
72  #include "jsscope.h"  #include "jsscope.h"
73    #include "jsstaticcheck.h"
74  #include "jsstr.h"  #include "jsstr.h"
75  #include "jsbit.h"  #include "jsbit.h"
76    
# Line 97  Line 99 
99              JSPREFIX_SET_BASE(str, base);              JSPREFIX_SET_BASE(str, base);
100          } else if (start <= JSSTRDEP_START_MASK) {          } else if (start <= JSSTRDEP_START_MASK) {
101              length = JSSTRDEP_LENGTH(str);              length = JSSTRDEP_LENGTH(str);
102              JSSTRDEP_INIT(str, base, start, length);              JSSTRDEP_REINIT(str, base, start, length);
103          }          }
104      }      }
105      *basep = base;      *basep = base;
# Line 164  Line 166 
166      js_strncpy(s + ln, rs, rn);      js_strncpy(s + ln, rs, rn);
167      n = ln + rn;      n = ln + rn;
168      s[n] = 0;      s[n] = 0;
169    
170      str = js_NewString(cx, s, n);      str = js_NewString(cx, s, n);
171      if (!str) {      if (!str) {
172          /* Out of memory: clean up any space we (re-)allocated. */          /* Out of memory: clean up any space we (re-)allocated. */
# Line 179  Line 182 
182    
183          /* Morph left into a dependent prefix if we realloc'd its buffer. */          /* Morph left into a dependent prefix if we realloc'd its buffer. */
184          if (ldep) {          if (ldep) {
185              JSPREFIX_INIT(ldep, str, ln);              JSPREFIX_REINIT(ldep, str, ln);
186  #ifdef DEBUG  #ifdef DEBUG
187            {            {
188              JSRuntime *rt = cx->runtime;              JSRuntime *rt = cx->runtime;
# Line 211  Line 214 
214    
215          js_strncpy(s, JSSTRDEP_CHARS(str), n);          js_strncpy(s, JSSTRDEP_CHARS(str), n);
216          s[n] = 0;          s[n] = 0;
217          JSFLATSTR_INIT(str, s, n);          JSFLATSTR_REINIT(str, s, n);
218    
219  #ifdef DEBUG  #ifdef DEBUG
220          {          {
# Line 535  Line 538 
538  jschar      js_empty_ucstr[]  = {0};  jschar      js_empty_ucstr[]  = {0};
539  JSSubString js_EmptySubString = {0, js_empty_ucstr};  JSSubString js_EmptySubString = {0, js_empty_ucstr};
540    
 enum string_tinyid {  
     STRING_LENGTH = -1  
 };  
   
 static JSPropertySpec string_props[] = {  
     {js_length_str,     STRING_LENGTH,  
                         JSPROP_READONLY|JSPROP_PERMANENT|JSPROP_SHARED, 0,0},  
     {0,0,0,0,0}  
 };  
   
541  static JSBool  static JSBool
542  str_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)  str_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
543  {  {
544      jsval v;      jsval v;
545      JSString *str;      JSString *str;
     jsint slot;  
   
     if (!JSVAL_IS_INT(id))  
         return JS_TRUE;  
546    
547      slot = JSVAL_TO_INT(id);      if (id == ATOM_KEY(cx->runtime->atomState.lengthAtom)) {
     if (slot == STRING_LENGTH) {  
548          if (OBJ_GET_CLASS(cx, obj) == &js_StringClass) {          if (OBJ_GET_CLASS(cx, obj) == &js_StringClass) {
549              /* Follow ECMA-262 by fetching intrinsic length of our string. */              /* Follow ECMA-262 by fetching intrinsic length of our string. */
550              v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);              v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
# Line 571  Line 559 
559    
560          *vp = INT_TO_JSVAL((jsint) JSSTRING_LENGTH(str));          *vp = INT_TO_JSVAL((jsint) JSSTRING_LENGTH(str));
561      }      }
562    
563      return JS_TRUE;      return JS_TRUE;
564  }  }
565    
# Line 732  Line 721 
721  /*  /*
722   * Java-like string native methods.   * Java-like string native methods.
723   */   */
724  JSBool  
725  js_str_substring(JSContext *cx, uintN argc, jsval *vp)  static JSString *
726    SubstringTail(JSContext *cx, JSString *str, jsdouble length, jsdouble begin, jsdouble end)
727    {
728        if (begin < 0)
729            begin = 0;
730        else if (begin > length)
731            begin = length;
732    
733        if (end < 0)
734            end = 0;
735        else if (end > length)
736            end = length;
737        if (end < begin) {
738            /* ECMA emulates old JDK1.0 java.lang.String.substring. */
739            jsdouble tmp = begin;
740            begin = end;
741            end = tmp;
742        }
743    
744        return js_NewDependentString(cx, str, (size_t)begin, (size_t)(end - begin));
745    }
746    
747    static JSBool
748    str_substring(JSContext *cx, uintN argc, jsval *vp)
749  {  {
750      JSString *str;      JSString *str;
751      jsdouble d;      jsdouble d;
# Line 746  Line 758 
758              return JS_FALSE;              return JS_FALSE;
759          length = JSSTRING_LENGTH(str);          length = JSSTRING_LENGTH(str);
760          begin = js_DoubleToInteger(d);          begin = js_DoubleToInteger(d);
         if (begin < 0)  
             begin = 0;  
         else if (begin > length)  
             begin = length;  
   
761          if (argc == 1) {          if (argc == 1) {
762              end = length;              end = length;
763          } else {          } else {
# Line 758  Line 765 
765              if (JSVAL_IS_NULL(vp[3]))              if (JSVAL_IS_NULL(vp[3]))
766                  return JS_FALSE;                  return JS_FALSE;
767              end = js_DoubleToInteger(d);              end = js_DoubleToInteger(d);
             if (end < 0)  
                 end = 0;  
             else if (end > length)  
                 end = length;  
             if (end < begin) {  
                 /* ECMA emulates old JDK1.0 java.lang.String.substring. */  
                 jsdouble tmp = begin;  
                 begin = end;  
                 end = tmp;  
             }  
768          }          }
769    
770          str = js_NewDependentString(cx, str, (size_t)begin,          str = SubstringTail(cx, str, length, begin, end);
                                     (size_t)(end - begin));  
771          if (!str)          if (!str)
772              return JS_FALSE;              return JS_FALSE;
773      }      }
# Line 779  Line 775 
775      return JS_TRUE;      return JS_TRUE;
776  }  }
777    
778    #ifdef JS_TRACER
779    static JSString* FASTCALL
780    String_p_toString(JSContext* cx, JSObject* obj)
781    {
782        if (!JS_InstanceOf(cx, obj, &js_StringClass, NULL))
783            return NULL;
784        jsval v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
785        JS_ASSERT(JSVAL_IS_STRING(v));
786        return JSVAL_TO_STRING(v);
787    }
788    #endif
789    
790  JSString* JS_FASTCALL  JSString* JS_FASTCALL
791  js_toLowerCase(JSContext *cx, JSString *str)  js_toLowerCase(JSContext *cx, JSString *str)
792  {  {
# Line 800  Line 808 
808      return str;      return str;
809  }  }
810    
811  JSBool  static JSBool
812  js_str_toLowerCase(JSContext *cx, uintN argc, jsval *vp)  str_toLowerCase(JSContext *cx, uintN argc, jsval *vp)
813  {  {
814      JSString *str;      JSString *str;
815    
# Line 826  Line 834 
834          NORMALIZE_THIS(cx, vp, str);          NORMALIZE_THIS(cx, vp, str);
835          return cx->localeCallbacks->localeToLowerCase(cx, str, vp);          return cx->localeCallbacks->localeToLowerCase(cx, str, vp);
836      }      }
837      return js_str_toLowerCase(cx, 0, vp);      return str_toLowerCase(cx, 0, vp);
838  }  }
839    
840  JSString* JS_FASTCALL  JSString* JS_FASTCALL
# Line 850  Line 858 
858      return str;      return str;
859  }  }
860    
861  JSBool  static JSBool
862  js_str_toUpperCase(JSContext *cx, uintN argc, jsval *vp)  str_toUpperCase(JSContext *cx, uintN argc, jsval *vp)
863  {  {
864      JSString *str;      JSString *str;
865    
# Line 876  Line 884 
884          NORMALIZE_THIS(cx, vp, str);          NORMALIZE_THIS(cx, vp, str);
885          return cx->localeCallbacks->localeToUpperCase(cx, str, vp);          return cx->localeCallbacks->localeToUpperCase(cx, str, vp);
886      }      }
887      return js_str_toUpperCase(cx, 0, vp);      return str_toUpperCase(cx, 0, vp);
888  }  }
889    
890  static JSBool  static JSBool
# Line 900  Line 908 
908      return JS_TRUE;      return JS_TRUE;
909  }  }
910    
911  JSBool  static JSBool
912  js_str_charAt(JSContext *cx, uintN argc, jsval *vp)  str_charAt(JSContext *cx, uintN argc, jsval *vp)
913  {  {
914      jsval t;      jsval t;
915      JSString *str;      JSString *str;
# Line 944  Line 952 
952      return JS_TRUE;      return JS_TRUE;
953  }  }
954    
955  JSBool  static JSBool
956  js_str_charCodeAt(JSContext *cx, uintN argc, jsval *vp)  str_charCodeAt(JSContext *cx, uintN argc, jsval *vp)
957  {  {
958      jsval t;      jsval t;
959      JSString *str;      JSString *str;
# Line 985  Line 993 
993      return JS_TRUE;      return JS_TRUE;
994  }  }
995    
996    #ifdef JS_TRACER
997    extern jsdouble js_NaN;
998    
999    jsdouble FASTCALL
1000    js_String_p_charCodeAt(JSString* str, jsdouble d)
1001    {
1002        d = js_DoubleToInteger(d);
1003        if (d < 0 || (int32)JSSTRING_LENGTH(str) <= d)
1004            return js_NaN;
1005        return jsdouble(JSSTRING_CHARS(str)[jsuint(d)]);
1006    }
1007    
1008    int32 FASTCALL
1009    js_String_p_charCodeAt_int(JSString* str, jsint i)
1010    {
1011        if (i < 0 || (int32)JSSTRING_LENGTH(str) <= i)
1012            return 0;
1013        return JSSTRING_CHARS(str)[i];
1014    }
1015    
1016    jsdouble FASTCALL
1017    js_String_p_charCodeAt0(JSString* str)
1018    {
1019        if ((int32)JSSTRING_LENGTH(str) == 0)
1020            return js_NaN;
1021        return jsdouble(JSSTRING_CHARS(str)[0]);
1022    }
1023    
1024    int32 FASTCALL
1025    js_String_p_charCodeAt0_int(JSString* str)
1026    {
1027        if ((int32)JSSTRING_LENGTH(str) == 0)
1028            return 0;
1029        return JSSTRING_CHARS(str)[0];
1030    }
1031    
1032    /*
1033     * The FuncFilter replaces the generic double version of charCodeAt with the
1034     * integer fast path if appropriate.
1035     */
1036    JS_DEFINE_CALLINFO_1(extern, INT32, js_String_p_charCodeAt0_int, STRING,        1, 1)
1037    JS_DEFINE_CALLINFO_2(extern, INT32, js_String_p_charCodeAt_int,  STRING, INT32, 1, 1)
1038    #endif
1039    
1040  jsint  jsint
1041  js_BoyerMooreHorspool(const jschar *text, jsint textlen,  js_BoyerMooreHorspool(const jschar *text, jsint textlen,
1042                        const jschar *pat, jsint patlen,                        const jschar *pat, jsint patlen,
# Line 1102  Line 1154 
1154      text = JSSTRING_CHARS(str);      text = JSSTRING_CHARS(str);
1155      textlen = (jsint) JSSTRING_LENGTH(str);      textlen = (jsint) JSSTRING_LENGTH(str);
1156    
1157      str2 = ArgToRootedString(cx, argc, vp, 0);      if (argc != 0 && JSVAL_IS_STRING(vp[2])) {
1158      if (!str2)          str2 = JSVAL_TO_STRING(vp[2]);
1159          return JS_FALSE;      } else {
1160            str2 = ArgToRootedString(cx, argc, vp, 0);
1161            if (!str2)
1162                return JS_FALSE;
1163        }
1164      pat = JSSTRING_CHARS(str2);      pat = JSSTRING_CHARS(str2);
1165      patlen = (jsint) JSSTRING_LENGTH(str2);      patlen = (jsint) JSSTRING_LENGTH(str2);
1166    
1167        i = textlen - patlen; // Start searching here
1168        if (i < 0) {
1169            *vp = INT_TO_JSVAL(-1);
1170            return JS_TRUE;
1171        }
1172    
1173      if (argc > 1) {      if (argc > 1) {
1174          d = js_ValueToNumber(cx, &vp[3]);          if (JSVAL_IS_INT(vp[3])) {
1175          if (JSVAL_IS_NULL(vp[3]))              j = JSVAL_TO_INT(vp[3]);
1176              return JS_FALSE;              if (j <= 0)
         if (JSDOUBLE_IS_NaN(d)) {  
             i = textlen;  
         } else {  
             d = js_DoubleToInteger(d);  
             if (d < 0)  
1177                  i = 0;                  i = 0;
1178              else if (d > textlen)              else if (j < i)
1179                  i = textlen;                  i = j;
1180              else          } else {
1181                  i = (jsint)d;              d = js_ValueToNumber(cx, &vp[3]);
1182                if (JSVAL_IS_NULL(vp[3]))
1183                    return JS_FALSE;
1184                if (!JSDOUBLE_IS_NaN(d)) {
1185                    d = js_DoubleToInteger(d);
1186                    if (d <= 0)
1187                        i = 0;
1188                    else if (d < i)
1189                        i = (jsint)d;
1190                }
1191          }          }
     } else {  
         i = textlen;  
1192      }      }
1193    
1194      if (patlen == 0) {      if (patlen == 0) {
# Line 1134  Line 1198 
1198    
1199      j = 0;      j = 0;
1200      while (i >= 0) {      while (i >= 0) {
1201          /* Don't assume that text is NUL-terminated: it could be dependent. */          /* This is always safe because i <= textlen - patlen and j < patlen */
1202          if (i + j < textlen && text[i + j] == pat[j]) {          if (text[i + j] == pat[j]) {
1203              if (++j == patlen)              if (++j == patlen)
1204                  break;                  break;
1205          } else {          } else {
# Line 1299  Line 1363 
1363              test = JS_TRUE;              test = JS_TRUE;
1364          } else {          } else {
1365              /*              /*
1366               * MODE_MATCH implies js_str_match is being called from a script or               * MODE_MATCH implies str_match is being called from a script or a
1367               * a scripted function.  If the caller cares only about testing null               * scripted function.  If the caller cares only about testing null
1368               * vs. non-null return value, optimize away the array object that               * vs. non-null return value, optimize away the array object that
1369               * would normally be returned in *vp.               * would normally be returned in *vp.
1370               *               *
# Line 1354  Line 1418 
1418      mdata = (MatchData *)data;      mdata = (MatchData *)data;
1419      arrayobj = JSVAL_TO_OBJECT(*mdata->arrayval);      arrayobj = JSVAL_TO_OBJECT(*mdata->arrayval);
1420      if (!arrayobj) {      if (!arrayobj) {
1421          arrayobj = js_ConstructObject(cx, &js_ArrayClass, NULL, NULL, 0, NULL);          arrayobj = js_NewArrayObject(cx, 0, NULL);
1422          if (!arrayobj)          if (!arrayobj)
1423              return JS_FALSE;              return JS_FALSE;
1424          *mdata->arrayval = OBJECT_TO_JSVAL(arrayobj);          *mdata->arrayval = OBJECT_TO_JSVAL(arrayobj);
# Line 1365  Line 1429 
1429          return JS_FALSE;          return JS_FALSE;
1430      v = STRING_TO_JSVAL(matchstr);      v = STRING_TO_JSVAL(matchstr);
1431      JS_ASSERT(count <= JSVAL_INT_MAX);      JS_ASSERT(count <= JSVAL_INT_MAX);
1432    
1433        JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_ASSIGNING);
1434      return OBJ_SET_PROPERTY(cx, arrayobj, INT_TO_JSID(count), &v);      return OBJ_SET_PROPERTY(cx, arrayobj, INT_TO_JSID(count), &v);
1435  }  }
1436    
1437  JSBool  static JSBool
1438  js_StringMatchHelper(JSContext *cx, uintN argc, jsval *vp, jsbytecode *pc)  StringMatchHelper(JSContext *cx, uintN argc, jsval *vp, jsbytecode *pc)
1439  {  {
1440      JSTempValueRooter tvr;      JSTempValueRooter tvr;
1441      MatchData mdata;      MatchData mdata;
# Line 1387  Line 1453 
1453      return ok;      return ok;
1454  }  }
1455    
1456  JSBool  static JSBool
1457  js_str_match(JSContext *cx, uintN argc, jsval *vp)  str_match(JSContext *cx, uintN argc, jsval *vp)
1458  {  {
1459      JSStackFrame *fp;      return StringMatchHelper(cx, argc, vp, js_GetCurrentBytecodePC(cx));
   
     for (fp = cx->fp; fp && !fp->regs; fp = fp->down)  
         JS_ASSERT(!fp->script);  
     return js_StringMatchHelper(cx, argc, vp, fp ? fp->regs->pc : NULL);  
1460  }  }
1461    
1462  static JSBool  static JSBool
# Line 1478  Line 1540 
1540      return NULL;      return NULL;
1541  }  }
1542    
1543  static JSBool  static JS_REQUIRES_STACK JSBool
1544  find_replen(JSContext *cx, ReplaceData *rdata, size_t *sizep)  find_replen(JSContext *cx, ReplaceData *rdata, size_t *sizep)
1545  {  {
1546      JSString *repstr;      JSString *repstr;
# Line 1498  Line 1560 
1560           * Save the regExpStatics from the current regexp, since they may be           * Save the regExpStatics from the current regexp, since they may be
1561           * clobbered by a RegExp usage in the lambda function.  Note that all           * clobbered by a RegExp usage in the lambda function.  Note that all
1562           * members of JSRegExpStatics are JSSubStrings, so not GC roots, save           * members of JSRegExpStatics are JSSubStrings, so not GC roots, save
1563           * input, which is rooted otherwise via vp[1] in js_str_replace.           * input, which is rooted otherwise via vp[1] in str_replace.
1564           */           */
1565          JSRegExpStatics save = cx->regExpStatics;          JSRegExpStatics save = cx->regExpStatics;
1566          JSBool freeMoreParens = JS_FALSE;          JSBool freeMoreParens = JS_FALSE;
# Line 1642  Line 1704 
1704      rdata->chars = NULL;      rdata->chars = NULL;
1705  }  }
1706    
1707  static JSBool  static JS_REQUIRES_STACK JSBool
1708  replace_glob(JSContext *cx, jsint count, GlobData *data)  replace_glob(JSContext *cx, jsint count, GlobData *data)
1709  {  {
1710      ReplaceData *rdata;      ReplaceData *rdata;
# Line 1678  Line 1740 
1740      return JS_TRUE;      return JS_TRUE;
1741  }  }
1742    
1743  JSBool  static JS_REQUIRES_STACK JSBool
1744  js_str_replace(JSContext *cx, uintN argc, jsval *vp)  str_replace(JSContext *cx, uintN argc, jsval *vp)
1745  {  {
1746      JSObject *lambda;      JSObject *lambda;
1747      JSString *repstr;      JSString *repstr;
# Line 1697  Line 1759 
1759      return js_StringReplaceHelper(cx, argc, lambda, repstr, vp);      return js_StringReplaceHelper(cx, argc, lambda, repstr, vp);
1760  }  }
1761    
1762  JSBool  JSBool JS_REQUIRES_STACK
1763  js_StringReplaceHelper(JSContext *cx, uintN argc, JSObject *lambda,  js_StringReplaceHelper(JSContext *cx, uintN argc, JSObject *lambda,
1764                         JSString *repstr, jsval *vp)                         JSString *repstr, jsval *vp)
1765  {  {
# Line 1718  Line 1780 
1780      rdata.lambda = lambda;      rdata.lambda = lambda;
1781      rdata.repstr = repstr;      rdata.repstr = repstr;
1782      if (repstr) {      if (repstr) {
1783            if (!js_MakeStringImmutable(cx, repstr))
1784                return JS_FALSE;
1785          rdata.dollarEnd = JSSTRING_CHARS(repstr) + JSSTRING_LENGTH(repstr);          rdata.dollarEnd = JSSTRING_CHARS(repstr) + JSSTRING_LENGTH(repstr);
1786          rdata.dollar = js_strchr_limit(JSSTRING_CHARS(repstr), '$',          rdata.dollar = js_strchr_limit(JSSTRING_CHARS(repstr), '$',
1787                                         rdata.dollarEnd);                                         rdata.dollarEnd);
# Line 1785  Line 1849 
1849  }  }
1850    
1851  /*  /*
1852   * Subroutine used by js_str_split to find the next split point in str, starting   * Subroutine used by str_split to find the next split point in str, starting
1853   * at offset *ip and looking either for the separator substring given by sep, or   * at offset *ip and looking either for the separator substring given by sep, or
1854   * for the next re match.  In the re case, return the matched separator in *sep,   * for the next re match.  In the re case, return the matched separator in *sep,
1855   * and the possibly updated offset in *ip.   * and the possibly updated offset in *ip.
# Line 1810  Line 1874 
1874       *       *
1875       * and the resulting array converts back to the string "ab," for symmetry.       * and the resulting array converts back to the string "ab," for symmetry.
1876       * However, we ape Perl and do this only if there is a sufficiently large       * However, we ape Perl and do this only if there is a sufficiently large
1877       * limit argument (see js_str_split).       * limit argument (see str_split).
1878       */       */
1879      i = *ip;      i = *ip;
1880      length = JSSTRING_LENGTH(str);      length = JSSTRING_LENGTH(str);
# Line 1896  Line 1960 
1960      return k;      return k;
1961  }  }
1962    
1963  JSBool  static JSBool
1964  js_str_split(JSContext *cx, uintN argc, jsval *vp)  str_split(JSContext *cx, uintN argc, jsval *vp)
1965  {  {
1966      JSString *str, *sub;      JSString *str, *sub;
1967      JSObject *arrayobj;      JSObject *arrayobj;
# Line 1911  Line 1975 
1975    
1976      NORMALIZE_THIS(cx, vp, str);      NORMALIZE_THIS(cx, vp, str);
1977    
1978      arrayobj = js_ConstructObject(cx, &js_ArrayClass, NULL, NULL, 0, NULL);      arrayobj = js_NewArrayObject(cx, 0, NULL);
1979      if (!arrayobj)      if (!arrayobj)
1980          return JS_FALSE;          return JS_FALSE;
1981      *vp = OBJECT_TO_JSVAL(arrayobj);      *vp = OBJECT_TO_JSVAL(arrayobj);
# Line 2049  Line 2113 
2113  /*  /*
2114   * Python-esque sequence operations.   * Python-esque sequence operations.
2115   */   */
2116  JSBool  static JSBool
2117  js_str_concat(JSContext *cx, uintN argc, jsval *vp)  str_concat(JSContext *cx, uintN argc, jsval *vp)
2118  {  {
2119      JSString *str, *str2;      JSString *str, *str2;
2120      jsval *argv;      jsval *argv;
# Line 2058  Line 2122 
2122    
2123      NORMALIZE_THIS(cx, vp, str);      NORMALIZE_THIS(cx, vp, str);
2124    
2125        /* Set vp (aka rval) early to handle the argc == 0 case. */
2126        *vp = STRING_TO_JSVAL(str);
2127    
2128      for (i = 0, argv = vp + 2; i < argc; i++) {      for (i = 0, argv = vp + 2; i < argc; i++) {
2129          str2 = js_ValueToString(cx, argv[i]);          str2 = js_ValueToString(cx, argv[i]);
2130          if (!str2)          if (!str2)
# Line 2067  Line 2134 
2134          str = js_ConcatStrings(cx, str, str2);          str = js_ConcatStrings(cx, str, str2);
2135          if (!str)          if (!str)
2136              return JS_FALSE;              return JS_FALSE;
2137            *vp = STRING_TO_JSVAL(str);
2138      }      }
2139    
     *vp = STRING_TO_JSVAL(str);  
2140      return JS_TRUE;      return JS_TRUE;
2141  }  }
2142    
# Line 2308  Line 2375 
2375  }  }
2376  #endif /* JS_HAS_STR_HTML_HELPERS */  #endif /* JS_HAS_STR_HTML_HELPERS */
2377    
2378    #ifdef JS_TRACER
2379    JSString* FASTCALL
2380    js_String_getelem(JSContext* cx, JSString* str, int32 i)
2381    {
2382        if ((size_t)i >= JSSTRING_LENGTH(str))
2383            return NULL;
2384        return js_GetUnitString(cx, str, (size_t)i);
2385    }
2386    #endif
2387    
2388    JS_DEFINE_CALLINFO_2(extern, BOOL,   js_EqualStrings, STRING, STRING,                       1, 1)
2389    JS_DEFINE_CALLINFO_2(extern, INT32,  js_CompareStrings, STRING, STRING,                     1, 1)
2390    
2391    JS_DEFINE_TRCINFO_1(str_toString,
2392        (2, (extern, STRING_RETRY,      String_p_toString, CONTEXT, THIS,                        1, 1)))
2393    JS_DEFINE_TRCINFO_1(str_charAt,
2394        (3, (extern, STRING_RETRY,      js_String_getelem, CONTEXT, THIS_STRING, INT32,           1, 1)))
2395    JS_DEFINE_TRCINFO_2(str_charCodeAt,
2396        (1, (extern, DOUBLE,            js_String_p_charCodeAt0, THIS_STRING,                     1, 1)),
2397        (2, (extern, DOUBLE,            js_String_p_charCodeAt, THIS_STRING, DOUBLE,              1, 1)))
2398    JS_DEFINE_TRCINFO_1(str_concat,
2399        (3, (extern, STRING_RETRY,      js_ConcatStrings, CONTEXT, THIS_STRING, STRING,           1, 1)))
2400    
2401  #define GENERIC           JSFUN_GENERIC_NATIVE  #define GENERIC           JSFUN_GENERIC_NATIVE
2402  #define PRIMITIVE         JSFUN_THISP_PRIMITIVE  #define PRIMITIVE         JSFUN_THISP_PRIMITIVE
2403  #define GENERIC_PRIMITIVE (GENERIC | PRIMITIVE)  #define GENERIC_PRIMITIVE (GENERIC | PRIMITIVE)
# Line 2319  Line 2409 
2409  #endif  #endif
2410    
2411      /* Java-like methods. */      /* Java-like methods. */
2412      JS_FN(js_toString_str,     str_toString,          0,JSFUN_THISP_STRING),      JS_TN(js_toString_str,     str_toString,          0,JSFUN_THISP_STRING, str_toString_trcinfo),
2413      JS_FN(js_valueOf_str,      str_toString,          0,JSFUN_THISP_STRING),      JS_FN(js_valueOf_str,      str_toString,          0,JSFUN_THISP_STRING),
2414      JS_FN("substring",         js_str_substring,      2,GENERIC_PRIMITIVE),      JS_FN(js_toJSON_str,       str_toString,          0,JSFUN_THISP_STRING),
2415      JS_FN("toLowerCase",       js_str_toLowerCase,    0,GENERIC_PRIMITIVE),      JS_FN("substring",         str_substring,         2,GENERIC_PRIMITIVE),
2416      JS_FN("toUpperCase",       js_str_toUpperCase,    0,GENERIC_PRIMITIVE),      JS_FN("toLowerCase",       str_toLowerCase,       0,GENERIC_PRIMITIVE),
2417      JS_FN("charAt",            js_str_charAt,         1,GENERIC_PRIMITIVE),      JS_FN("toUpperCase",       str_toUpperCase,       0,GENERIC_PRIMITIVE),
2418      JS_FN("charCodeAt",        js_str_charCodeAt,     1,GENERIC_PRIMITIVE),      JS_TN("charAt",            str_charAt,            1,GENERIC_PRIMITIVE, str_charAt_trcinfo),
2419        JS_TN("charCodeAt",        str_charCodeAt,        1,GENERIC_PRIMITIVE, str_charCodeAt_trcinfo),
2420      JS_FN("indexOf",           str_indexOf,           1,GENERIC_PRIMITIVE),      JS_FN("indexOf",           str_indexOf,           1,GENERIC_PRIMITIVE),
2421      JS_FN("lastIndexOf",       str_lastIndexOf,       1,GENERIC_PRIMITIVE),      JS_FN("lastIndexOf",       str_lastIndexOf,       1,GENERIC_PRIMITIVE),
2422      JS_FN("trim",              str_trim,              0,GENERIC_PRIMITIVE),      JS_FN("trim",              str_trim,              0,GENERIC_PRIMITIVE),
# Line 2336  Line 2427 
2427      JS_FN("localeCompare",     str_localeCompare,     1,GENERIC_PRIMITIVE),      JS_FN("localeCompare",     str_localeCompare,     1,GENERIC_PRIMITIVE),
2428    
2429      /* Perl-ish methods (search is actually Python-esque). */      /* Perl-ish methods (search is actually Python-esque). */
2430      JS_FN("match",             js_str_match,          1,GENERIC_PRIMITIVE),      JS_FN("match",             str_match,             1,GENERIC_PRIMITIVE),
2431      JS_FN("search",            str_search,            1,GENERIC_PRIMITIVE),      JS_FN("search",            str_search,            1,GENERIC_PRIMITIVE),
2432      JS_FN("replace",           js_str_replace,        2,GENERIC_PRIMITIVE),      JS_FN("replace",           str_replace,           2,GENERIC_PRIMITIVE),
2433      JS_FN("split",             js_str_split,          2,GENERIC_PRIMITIVE),      JS_FN("split",             str_split,             2,GENERIC_PRIMITIVE),
2434  #if JS_HAS_PERL_SUBSTR  #if JS_HAS_PERL_SUBSTR
2435      JS_FN("substr",            str_substr,            2,GENERIC_PRIMITIVE),      JS_FN("substr",            str_substr,            2,GENERIC_PRIMITIVE),
2436  #endif  #endif
2437    
2438      /* Python-esque sequence methods. */      /* Python-esque sequence methods. */
2439      JS_FN("concat",            js_str_concat,         1,GENERIC_PRIMITIVE),      JS_TN("concat",            str_concat,            1,GENERIC_PRIMITIVE, str_concat_trcinfo),
2440      JS_FN("slice",             str_slice,             2,GENERIC_PRIMITIVE),      JS_FN("slice",             str_slice,             2,GENERIC_PRIMITIVE),
2441    
2442      /* HTML string methods. */      /* HTML string methods. */
# Line 2368  Line 2459 
2459      JS_FS_END      JS_FS_END
2460  };  };
2461    
2462  static JSBool  JSBool
2463  String(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)  js_String(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2464  {  {
2465      JSString *str;      JSString *str;
2466    
# Line 2381  Line 2472 
2472      } else {      } else {
2473          str = cx->runtime->emptyString;          str = cx->runtime->emptyString;
2474      }      }
2475      if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {      if (!JS_IsConstructing(cx)) {
2476          *rval = STRING_TO_JSVAL(str);          *rval = STRING_TO_JSVAL(str);
2477          return JS_TRUE;          return JS_TRUE;
2478      }      }
2479      STOBJ_SET_SLOT(obj, JSSLOT_PRIVATE, STRING_TO_JSVAL(str));      obj->fslots[JSSLOT_PRIVATE] = STRING_TO_JSVAL(str);
2480      return JS_TRUE;      return JS_TRUE;
2481  }  }
2482    
2483  JSBool  #ifdef JS_TRACER
2484  js_str_fromCharCode(JSContext *cx, uintN argc, jsval *vp)  
2485    JSObject* FASTCALL
2486    js_String_tn(JSContext* cx, JSObject* proto, JSString* str)
2487    {
2488        JS_ASSERT(JS_ON_TRACE(cx));
2489        JSObject* obj = js_NewNativeObject(cx, &js_StringClass, proto, JSSLOT_PRIVATE + 1);
2490        if (!obj)
2491            return NULL;
2492    
2493        obj->fslots[JSSLOT_PRIVATE] = STRING_TO_JSVAL(str);
2494        return obj;
2495    }
2496    
2497    JS_DEFINE_CALLINFO_3(extern, OBJECT, js_String_tn, CONTEXT, CALLEE_PROTOTYPE, STRING, 0, 0)
2498    
2499    #endif /* !JS_TRACER */
2500    
2501    static JSBool
2502    str_fromCharCode(JSContext *cx, uintN argc, jsval *vp)
2503  {  {
2504      jsval *argv;      jsval *argv;
2505      uintN i;      uintN i;
# Line 2429  Line 2538 
2538      return JS_TRUE;      return JS_TRUE;
2539  }  }
2540    
2541    #ifdef JS_TRACER
2542    static JSString* FASTCALL
2543    String_fromCharCode(JSContext* cx, int32 i)
2544    {
2545        JS_ASSERT(JS_ON_TRACE(cx));
2546        jschar c = (jschar)i;
2547        if (c < UNIT_STRING_LIMIT)
2548            return js_GetUnitStringForChar(cx, c);
2549        return js_NewStringCopyN(cx, &c, 1);
2550    }
2551    #endif
2552    
2553    JS_DEFINE_TRCINFO_1(str_fromCharCode,
2554        (2, (static, STRING_RETRY, String_fromCharCode, CONTEXT, INT32, 1, 1)))
2555    
2556  static JSFunctionSpec string_static_methods[] = {  static JSFunctionSpec string_static_methods[] = {
2557      JS_FN("fromCharCode",    js_str_fromCharCode,    1,0),      JS_TN("fromCharCode", str_fromCharCode, 1, 0, str_fromCharCode_trcinfo),
2558      JS_FS_END      JS_FS_END
2559  };  };
2560    
# Line 2522  Line 2646 
2646          JS_LOCK_GC(rt);          JS_LOCK_GC(rt);
2647          if (!rt->unitStrings[c])          if (!rt->unitStrings[c])
2648              rt->unitStrings[c] = str;              rt->unitStrings[c] = str;
2649    #ifdef DEBUG
2650            else
2651                JSFLATSTR_INIT(str, NULL, 0);  /* avoid later assertion (bug 479381) */
2652    #endif
2653          JS_UNLOCK_GC(rt);          JS_UNLOCK_GC(rt);
2654      }      }
2655      return rt->unitStrings[c];      return rt->unitStrings[c];
# Line 2576  Line 2704 
2704      if (!JS_DefineFunctions(cx, obj, string_functions))      if (!JS_DefineFunctions(cx, obj, string_functions))
2705          return NULL;          return NULL;
2706    
2707      proto = JS_InitClass(cx, obj, NULL, &js_StringClass, String, 1,      proto = JS_InitClass(cx, obj, NULL, &js_StringClass, js_String, 1,
2708                           string_props, string_methods,                           NULL, string_methods,
2709                           NULL, string_static_methods);                           NULL, string_static_methods);
2710      if (!proto)      if (!proto)
2711          return NULL;          return NULL;
2712      STOBJ_SET_SLOT(proto, JSSLOT_PRIVATE,      proto->fslots[JSSLOT_PRIVATE] = STRING_TO_JSVAL(cx->runtime->emptyString);
2713                     STRING_TO_JSVAL(cx->runtime->emptyString));      if (!js_DefineNativeProperty(cx, proto, ATOM_TO_JSID(cx->runtime->atomState.lengthAtom),
2714                                     JSVAL_VOID, NULL, NULL,
2715                                     JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0,
2716                                     NULL)) {
2717            return JS_FALSE;
2718        }
2719    
2720      return proto;      return proto;
2721  }  }
2722    
# Line 2592  Line 2726 
2726      JSString *str;      JSString *str;
2727    
2728      if (length > JSSTRING_LENGTH_MASK) {      if (length > JSSTRING_LENGTH_MASK) {
2729            if (JS_ON_TRACE(cx)) {
2730                /*
2731                 * If we can't leave the trace, signal OOM condition, otherwise
2732                 * exit from trace and proceed with GC.
2733                 */
2734                if (!js_CanLeaveTrace(cx))
2735                    return NULL;
2736    
2737                js_LeaveTrace(cx);
2738            }
2739          js_ReportAllocationOverflow(cx);          js_ReportAllocationOverflow(cx);
2740          return NULL;          return NULL;
2741      }      }
# Line 2793  Line 2937 
2937              }              }
2938          }          }
2939      }      }
2940      if (valid)      if (valid && JSSTRING_IS_DEFLATED(str))
2941          js_PurgeDeflatedStringCache(rt, str);          js_PurgeDeflatedStringCache(rt, str);
2942  }  }
2943    
# Line 2920  Line 3064 
3064      return JS_TRUE;      return JS_TRUE;
3065  }  }
3066    
3067  jsint JS_FASTCALL  int32 JS_FASTCALL
3068  js_CompareStrings(JSString *str1, JSString *str2)  js_CompareStrings(JSString *str1, JSString *str2)
3069  {  {
3070      size_t l1, l2, n, i;      size_t l1, l2, n, i;
# Line 3308  Line 3452 
3452      hep = JS_HashTableRawLookup(cache, hash, str);      hep = JS_HashTableRawLookup(cache, hash, str);
3453      JS_ASSERT(*hep == NULL);      JS_ASSERT(*hep == NULL);
3454      ok = JS_HashTableRawAdd(cache, hep, hash, str, bytes) != NULL;      ok = JS_HashTableRawAdd(cache, hep, hash, str, bytes) != NULL;
3455        if (ok) {
3456            JSSTRING_SET_DEFLATED(str);
3457  #ifdef DEBUG  #ifdef DEBUG
     if (ok)  
3458          rt->deflatedStringCacheBytes += length;          rt->deflatedStringCacheBytes += length;
3459  #endif  #endif
3460        }
3461    
3462      JS_RELEASE_LOCK(rt->deflatedStringCacheLock);      JS_RELEASE_LOCK(rt->deflatedStringCacheLock);
3463      return ok;      return ok;
# Line 3366  Line 3512 
3512  #ifdef DEBUG  #ifdef DEBUG
3513                  rt->deflatedStringCacheBytes += JSSTRING_LENGTH(str);                  rt->deflatedStringCacheBytes += JSSTRING_LENGTH(str);
3514  #endif  #endif
3515                    JSSTRING_SET_DEFLATED(str);
3516              } else {              } else {
3517                  if (cx)                  if (cx)
3518                      JS_free(cx, bytes);                      JS_free(cx, bytes);

Legend:
Removed from v.332  
changed lines
  Added in v.460

  ViewVC Help
Powered by ViewVC 1.1.24