| Index: src/js/regexp.js | 
| diff --git a/src/js/regexp.js b/src/js/regexp.js | 
| index e51a6d227a8d40ef2308cfeb1eed557c44656f4f..ecf3289b61ca3392cdfe59946fb4d78bab869ac9 100644 | 
| --- a/src/js/regexp.js | 
| +++ b/src/js/regexp.js | 
| @@ -17,7 +17,6 @@ | 
| var InternalPackedArray = utils.InternalPackedArray; | 
| var MaxSimple; | 
| var MinSimple; | 
| -var lastMatchInfoSymbol = utils.ImportNow("regexp_last_match_info_symbol"); | 
| var matchSymbol = utils.ImportNow("match_symbol"); | 
| var replaceSymbol = utils.ImportNow("replace_symbol"); | 
| var searchSymbol = utils.ImportNow("search_symbol"); | 
| @@ -924,7 +923,179 @@ | 
| %FunctionRemovePrototype(RegExpSubclassSearch); | 
|  | 
|  | 
| +// Getters for the static properties lastMatch, lastParen, leftContext, and | 
| +// rightContext of the RegExp constructor.  The properties are computed based | 
| +// on the captures array of the last successful match and the subject string | 
| +// of the last successful match. | 
| +function RegExpGetLastMatch() { | 
| +  var regExpSubject = LAST_SUBJECT(RegExpLastMatchInfo); | 
| +  return %_SubString(regExpSubject, | 
| +                     RegExpLastMatchInfo[CAPTURE0], | 
| +                     RegExpLastMatchInfo[CAPTURE1]); | 
| +} | 
| + | 
| + | 
| +function RegExpGetLastParen() { | 
| +  var length = NUMBER_OF_CAPTURES(RegExpLastMatchInfo); | 
| +  if (length <= 2) return '';  // There were no captures. | 
| +  // We match the SpiderMonkey behavior: return the substring defined by the | 
| +  // last pair (after the first pair) of elements of the capture array even if | 
| +  // it is empty. | 
| +  var regExpSubject = LAST_SUBJECT(RegExpLastMatchInfo); | 
| +  var start = RegExpLastMatchInfo[CAPTURE(length - 2)]; | 
| +  var end = RegExpLastMatchInfo[CAPTURE(length - 1)]; | 
| +  if (start != -1 && end != -1) { | 
| +    return %_SubString(regExpSubject, start, end); | 
| +  } | 
| +  return ""; | 
| +} | 
| + | 
| + | 
| +function RegExpGetLeftContext() { | 
| +  var start_index; | 
| +  var subject; | 
| +  start_index = RegExpLastMatchInfo[CAPTURE0]; | 
| +  subject = LAST_SUBJECT(RegExpLastMatchInfo); | 
| +  return %_SubString(subject, 0, start_index); | 
| +} | 
| + | 
| + | 
| +function RegExpGetRightContext() { | 
| +  var start_index; | 
| +  var subject; | 
| +  start_index = RegExpLastMatchInfo[CAPTURE1]; | 
| +  subject = LAST_SUBJECT(RegExpLastMatchInfo); | 
| +  return %_SubString(subject, start_index, subject.length); | 
| +} | 
| + | 
| + | 
| +// The properties $1..$9 are the first nine capturing substrings of the last | 
| +// successful match, or ''.  The function RegExpMakeCaptureGetter will be | 
| +// called with indices from 1 to 9. | 
| +function RegExpMakeCaptureGetter(n) { | 
| +  return function foo() { | 
| +    var index = n * 2; | 
| +    if (index >= NUMBER_OF_CAPTURES(RegExpLastMatchInfo)) return ''; | 
| +    var matchStart = RegExpLastMatchInfo[CAPTURE(index)]; | 
| +    var matchEnd = RegExpLastMatchInfo[CAPTURE(index + 1)]; | 
| +    if (matchStart == -1 || matchEnd == -1) return ''; | 
| +    return %_SubString(LAST_SUBJECT(RegExpLastMatchInfo), matchStart, matchEnd); | 
| +  }; | 
| +} | 
| + | 
| + | 
| +// ES6 21.2.5.3. | 
| +function RegExpGetFlags() { | 
| +  if (!IS_RECEIVER(this)) { | 
| +    throw %make_type_error( | 
| +        kRegExpNonObject, "RegExp.prototype.flags", TO_STRING(this)); | 
| +  } | 
| +  var result = ''; | 
| +  if (this.global) result += 'g'; | 
| +  if (this.ignoreCase) result += 'i'; | 
| +  if (this.multiline) result += 'm'; | 
| +  if (this.unicode) result += 'u'; | 
| +  if (this.sticky) result += 'y'; | 
| +  return result; | 
| +} | 
| + | 
| + | 
| +// ES6 21.2.5.4. | 
| +function RegExpGetGlobal() { | 
| +  if (!IS_REGEXP(this)) { | 
| +    // TODO(littledan): Remove this RegExp compat workaround | 
| +    if (this === GlobalRegExp.prototype) { | 
| +      %IncrementUseCounter(kRegExpPrototypeOldFlagGetter); | 
| +      return UNDEFINED; | 
| +    } | 
| +    throw %make_type_error(kRegExpNonRegExp, "RegExp.prototype.global"); | 
| +  } | 
| +  return TO_BOOLEAN(REGEXP_GLOBAL(this)); | 
| +} | 
| +%SetForceInlineFlag(RegExpGetGlobal); | 
| + | 
| + | 
| +// ES6 21.2.5.5. | 
| +function RegExpGetIgnoreCase() { | 
| +  if (!IS_REGEXP(this)) { | 
| +    // TODO(littledan): Remove this RegExp compat workaround | 
| +    if (this === GlobalRegExp.prototype) { | 
| +      %IncrementUseCounter(kRegExpPrototypeOldFlagGetter); | 
| +      return UNDEFINED; | 
| +    } | 
| +    throw %make_type_error(kRegExpNonRegExp, "RegExp.prototype.ignoreCase"); | 
| +  } | 
| +  return TO_BOOLEAN(REGEXP_IGNORE_CASE(this)); | 
| +} | 
| + | 
| + | 
| +// ES6 21.2.5.7. | 
| +function RegExpGetMultiline() { | 
| +  if (!IS_REGEXP(this)) { | 
| +    // TODO(littledan): Remove this RegExp compat workaround | 
| +    if (this === GlobalRegExp.prototype) { | 
| +      %IncrementUseCounter(kRegExpPrototypeOldFlagGetter); | 
| +      return UNDEFINED; | 
| +    } | 
| +    throw %make_type_error(kRegExpNonRegExp, "RegExp.prototype.multiline"); | 
| +  } | 
| +  return TO_BOOLEAN(REGEXP_MULTILINE(this)); | 
| +} | 
| + | 
| + | 
| +// ES6 21.2.5.10. | 
| +function RegExpGetSource() { | 
| +  if (!IS_REGEXP(this)) { | 
| +    // TODO(littledan): Remove this RegExp compat workaround | 
| +    if (this === GlobalRegExp.prototype) { | 
| +      %IncrementUseCounter(kRegExpPrototypeSourceGetter); | 
| +      return "(?:)"; | 
| +    } | 
| +    throw %make_type_error(kRegExpNonRegExp, "RegExp.prototype.source"); | 
| +  } | 
| +  return REGEXP_SOURCE(this); | 
| +} | 
| + | 
| + | 
| +// ES6 21.2.5.12. | 
| +function RegExpGetSticky() { | 
| +  if (!IS_REGEXP(this)) { | 
| +    // Compat fix: RegExp.prototype.sticky == undefined; UseCounter tracks it | 
| +    // TODO(littledan): Remove this workaround or standardize it | 
| +    if (this === GlobalRegExp.prototype) { | 
| +      %IncrementUseCounter(kRegExpPrototypeStickyGetter); | 
| +      return UNDEFINED; | 
| +    } | 
| +    throw %make_type_error(kRegExpNonRegExp, "RegExp.prototype.sticky"); | 
| +  } | 
| +  return TO_BOOLEAN(REGEXP_STICKY(this)); | 
| +} | 
| +%SetForceInlineFlag(RegExpGetSticky); | 
| + | 
| + | 
| +// ES6 21.2.5.15. | 
| +function RegExpGetUnicode() { | 
| +  if (!IS_REGEXP(this)) { | 
| +    // TODO(littledan): Remove this RegExp compat workaround | 
| +    if (this === GlobalRegExp.prototype) { | 
| +      %IncrementUseCounter(kRegExpPrototypeUnicodeGetter); | 
| +      return UNDEFINED; | 
| +    } | 
| +    throw %make_type_error(kRegExpNonRegExp, "RegExp.prototype.unicode"); | 
| +  } | 
| +  return TO_BOOLEAN(REGEXP_UNICODE(this)); | 
| +} | 
| +%SetForceInlineFlag(RegExpGetUnicode); | 
| + | 
| + | 
| +function RegExpSpecies() { | 
| +  return this; | 
| +} | 
| + | 
| + | 
| // ------------------------------------------------------------------- | 
| + | 
| +utils.InstallGetter(GlobalRegExp, speciesSymbol, RegExpSpecies); | 
|  | 
| utils.InstallFunctions(GlobalRegExp.prototype, DONT_ENUM, [ | 
| "exec", RegExpSubclassExecJS, | 
| @@ -937,8 +1108,58 @@ | 
| splitSymbol, RegExpSubclassSplit, | 
| ]); | 
|  | 
| -// Temporary until all RegExpLastMatchInfo accesses are ported to C++. | 
| -SET_PRIVATE(GlobalRegExp, lastMatchInfoSymbol, RegExpLastMatchInfo); | 
| +utils.InstallGetter(GlobalRegExp.prototype, 'flags', RegExpGetFlags); | 
| +utils.InstallGetter(GlobalRegExp.prototype, 'global', RegExpGetGlobal); | 
| +utils.InstallGetter(GlobalRegExp.prototype, 'ignoreCase', RegExpGetIgnoreCase); | 
| +utils.InstallGetter(GlobalRegExp.prototype, 'multiline', RegExpGetMultiline); | 
| +utils.InstallGetter(GlobalRegExp.prototype, 'source', RegExpGetSource); | 
| +utils.InstallGetter(GlobalRegExp.prototype, 'sticky', RegExpGetSticky); | 
| +utils.InstallGetter(GlobalRegExp.prototype, 'unicode', RegExpGetUnicode); | 
| + | 
| +// The properties `input` and `$_` are aliases for each other.  When this | 
| +// value is set the value it is set to is coerced to a string. | 
| +// Getter and setter for the input. | 
| +var RegExpGetInput = function() { | 
| +  var regExpInput = LAST_INPUT(RegExpLastMatchInfo); | 
| +  return IS_UNDEFINED(regExpInput) ? "" : regExpInput; | 
| +}; | 
| +var RegExpSetInput = function(string) { | 
| +  LAST_INPUT(RegExpLastMatchInfo) = TO_STRING(string); | 
| +}; | 
| + | 
| +%OptimizeObjectForAddingMultipleProperties(GlobalRegExp, 22); | 
| +utils.InstallGetterSetter(GlobalRegExp, 'input', RegExpGetInput, RegExpSetInput, | 
| +                          DONT_DELETE); | 
| +utils.InstallGetterSetter(GlobalRegExp, '$_', RegExpGetInput, RegExpSetInput, | 
| +                          DONT_ENUM | DONT_DELETE); | 
| + | 
| + | 
| +var NoOpSetter = function(ignored) {}; | 
| + | 
| + | 
| +// Static properties set by a successful match. | 
| +utils.InstallGetterSetter(GlobalRegExp, 'lastMatch', RegExpGetLastMatch, | 
| +                          NoOpSetter, DONT_DELETE); | 
| +utils.InstallGetterSetter(GlobalRegExp, '$&', RegExpGetLastMatch, NoOpSetter, | 
| +                          DONT_ENUM | DONT_DELETE); | 
| +utils.InstallGetterSetter(GlobalRegExp, 'lastParen', RegExpGetLastParen, | 
| +                          NoOpSetter, DONT_DELETE); | 
| +utils.InstallGetterSetter(GlobalRegExp, '$+', RegExpGetLastParen, NoOpSetter, | 
| +                          DONT_ENUM | DONT_DELETE); | 
| +utils.InstallGetterSetter(GlobalRegExp, 'leftContext', RegExpGetLeftContext, | 
| +                          NoOpSetter, DONT_DELETE); | 
| +utils.InstallGetterSetter(GlobalRegExp, '$`', RegExpGetLeftContext, NoOpSetter, | 
| +                          DONT_ENUM | DONT_DELETE); | 
| +utils.InstallGetterSetter(GlobalRegExp, 'rightContext', RegExpGetRightContext, | 
| +                          NoOpSetter, DONT_DELETE); | 
| +utils.InstallGetterSetter(GlobalRegExp, "$'", RegExpGetRightContext, NoOpSetter, | 
| +                          DONT_ENUM | DONT_DELETE); | 
| + | 
| +for (var i = 1; i < 10; ++i) { | 
| +  utils.InstallGetterSetter(GlobalRegExp, '$' + i, RegExpMakeCaptureGetter(i), | 
| +                            NoOpSetter, DONT_DELETE); | 
| +} | 
| +%ToFastProperties(GlobalRegExp); | 
|  | 
| // ------------------------------------------------------------------- | 
| // Internal | 
|  |