Commit 67bcc7f6 authored by jgruber's avatar jgruber Committed by Commit bot

[regexp] Port RegExpCompile and RegExpToString

Again, fast paths could be added for unmodified JSRegExp instances.

BUG=v8:5339

Review-Url: https://codereview.chromium.org/2392463005
Cr-Commit-Position: refs/heads/master@{#40119}
parent 407b479d
......@@ -1719,6 +1719,13 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
Builtins::kRegExpPrototypeStickyGetter, true);
SimpleInstallGetter(prototype, factory->unicode_string(),
Builtins::kRegExpPrototypeUnicodeGetter, true);
SimpleInstallFunction(prototype, "compile",
Builtins::kRegExpPrototypeCompile, 2, false,
DONT_ENUM);
SimpleInstallFunction(prototype, factory->toString_string(),
Builtins::kRegExpPrototypeToString, 0, false,
DONT_ENUM);
}
{
......
......@@ -7,6 +7,7 @@
#include "src/code-factory.h"
#include "src/regexp/jsregexp.h"
#include "src/string-builder.h"
namespace v8 {
namespace internal {
......@@ -158,6 +159,36 @@ BUILTIN(RegExpConstructor) {
RegExpInitialize(isolate, regexp, pattern, flags));
}
BUILTIN(RegExpPrototypeCompile) {
HandleScope scope(isolate);
CHECK_RECEIVER(JSRegExp, regexp, "RegExp.prototype.compile");
Handle<Object> pattern = args.atOrUndefined(isolate, 1);
Handle<Object> flags = args.atOrUndefined(isolate, 2);
if (pattern->IsJSRegExp()) {
Handle<JSRegExp> pattern_regexp = Handle<JSRegExp>::cast(pattern);
if (!flags->IsUndefined(isolate)) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kRegExpFlags));
}
flags = PatternFlags(isolate, pattern_regexp);
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, pattern,
Object::GetProperty(pattern, isolate->factory()->source_string()));
}
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, regexp, RegExpInitialize(isolate, regexp, pattern, flags));
// Return undefined for compatibility with JSC.
// See http://crbug.com/585775 for web compat details.
return isolate->heap()->undefined_value();
}
namespace {
compiler::Node* LoadLastIndex(CodeStubAssembler* a, compiler::Node* context,
......@@ -656,6 +687,43 @@ BUILTIN(RegExpPrototypeSourceGetter) {
return regexp->source();
}
BUILTIN(RegExpPrototypeToString) {
HandleScope scope(isolate);
CHECK_RECEIVER(JSReceiver, recv, "RegExp.prototype.toString");
if (*recv == isolate->regexp_function()->prototype()) {
isolate->CountUsage(v8::Isolate::kRegExpPrototypeToString);
}
IncrementalStringBuilder builder(isolate);
builder.AppendCharacter('/');
{
Handle<Object> source;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, source,
JSReceiver::GetProperty(recv, isolate->factory()->source_string()));
Handle<String> source_str;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, source_str,
Object::ToString(isolate, source));
builder.AppendString(source_str);
}
builder.AppendCharacter('/');
{
Handle<Object> flags;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, flags,
JSReceiver::GetProperty(recv, isolate->factory()->flags_string()));
Handle<String> flags_str;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, flags_str,
Object::ToString(isolate, flags));
builder.AppendString(flags_str);
}
RETURN_RESULT_OR_FAILURE(isolate, builder.Finish());
}
// ES6 21.2.4.2.
BUILTIN(RegExpPrototypeSpeciesGetter) {
HandleScope scope(isolate);
......
......@@ -578,6 +578,7 @@ namespace internal {
CPP(RegExpLastMatchGetter) \
CPP(RegExpLastParenGetter) \
CPP(RegExpLeftContextGetter) \
CPP(RegExpPrototypeCompile) \
TFJ(RegExpPrototypeExec, 2) \
TFJ(RegExpPrototypeFlagsGetter, 1) \
TFJ(RegExpPrototypeGlobalGetter, 1) \
......@@ -586,6 +587,7 @@ namespace internal {
CPP(RegExpPrototypeSourceGetter) \
CPP(RegExpPrototypeSpeciesGetter) \
TFJ(RegExpPrototypeStickyGetter, 1) \
CPP(RegExpPrototypeToString) \
TFJ(RegExpPrototypeUnicodeGetter, 1) \
CPP(RegExpRightContextGetter) \
\
......
......@@ -72,36 +72,6 @@ function RegExpInitialize(object, pattern, flags) {
}
function PatternFlags(pattern) {
return (REGEXP_GLOBAL(pattern) ? 'g' : '') +
(REGEXP_IGNORE_CASE(pattern) ? 'i' : '') +
(REGEXP_MULTILINE(pattern) ? 'm' : '') +
(REGEXP_UNICODE(pattern) ? 'u' : '') +
(REGEXP_STICKY(pattern) ? 'y' : '');
}
// ES#sec-regexp.prototype.compile RegExp.prototype.compile (pattern, flags)
function RegExpCompileJS(pattern, flags) {
if (!IS_REGEXP(this)) {
throw %make_type_error(kIncompatibleMethodReceiver,
"RegExp.prototype.compile", this);
}
if (IS_REGEXP(pattern)) {
if (!IS_UNDEFINED(flags)) throw %make_type_error(kRegExpFlags);
flags = PatternFlags(pattern);
pattern = REGEXP_SOURCE(pattern);
}
RegExpInitialize(this, pattern, flags);
// Return undefined for compatibility with JSC.
// See http://crbug.com/585775 for web compat details.
}
function DoRegExpExec(regexp, string, index) {
return %_RegExpExec(regexp, string, index, RegExpLastMatchInfo);
}
......@@ -166,18 +136,6 @@ function RegExpSubclassTest(string) {
%FunctionRemovePrototype(RegExpSubclassTest);
function RegExpToString() {
if (!IS_RECEIVER(this)) {
throw %make_type_error(
kIncompatibleMethodReceiver, 'RegExp.prototype.toString', this);
}
if (this === GlobalRegExpPrototype) {
%IncrementUseCounter(kRegExpPrototypeToString);
}
return '/' + TO_STRING(this.source) + '/' + TO_STRING(this.flags);
}
function AtSurrogatePair(subject, index) {
if (index + 1 >= subject.length) return false;
var first = %_StringCharCodeAt(subject, index);
......@@ -781,8 +739,6 @@ function RegExpSubclassSearch(string) {
utils.InstallFunctions(GlobalRegExp.prototype, DONT_ENUM, [
"test", RegExpSubclassTest,
"toString", RegExpToString,
"compile", RegExpCompileJS,
matchSymbol, RegExpSubclassMatch,
replaceSymbol, RegExpSubclassReplace,
searchSymbol, RegExpSubclassSearch,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment