Title: [199812] trunk/Source/_javascript_Core
Revision
199812
Author
msab...@apple.com
Date
2016-04-21 03:57:45 -0700 (Thu, 21 Apr 2016)

Log Message

Align RegExp[@@match] with other @@ methods
https://bugs.webkit.org/show_bug.cgi?id=156832

Reviewed by Mark Lam.

Various changes to align the RegExp[@@match] with [@@search] and [@@split].

Made RegExp.prototype.@exec a hidden property on the global object and
called it @regExpBuiltinExec to match the name it has in the standard.
Changed all places that used the old name to use the new one.

Made the match fast path function, which used to be call @match, to be called
@regExpMatchFast and put it on the global object.  Changed it to also handle
expressions both with and without the global flag.  Refactored the builtin
@match accordingly.

Added the builtin function @hasObservableSideEffectsForRegExpMatch() that
checks to see if we can use the fast path of if we need the explicit version.

Put the main RegExp functions @match, @search and @split in alphabetical
order in RegExpPrototype.js.  Did the same for @match, @repeat, @search and 
@split in StringPrototype.js.
        
* builtins/RegExpPrototype.js:
(regExpExec):
(hasObservableSideEffectsForRegExpMatch): New.
(match):
(search):
(hasObservableSideEffectsForRegExpSplit):
Reordered in the file and updated to use @regExpBuiltinExec.

* builtins/StringPrototype.js:
(match):
(repeatSlowPath):
(repeat):
(search):
(split):
Reordered functions in the file.

* runtime/CommonIdentifiers.h:
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::setGlobalThis):
(JSC::getById):
(JSC::getGetterById):
(JSC::JSGlobalObject::init):
* runtime/RegExpPrototype.cpp:
(JSC::RegExpPrototype::finishCreation):
(JSC::regExpProtoFuncExec):
(JSC::regExpProtoFuncMatchFast):
(JSC::regExpProtoFuncMatchPrivate): Deleted.
* runtime/RegExpPrototype.h:

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (199811 => 199812)


--- trunk/Source/_javascript_Core/ChangeLog	2016-04-21 10:53:51 UTC (rev 199811)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-04-21 10:57:45 UTC (rev 199812)
@@ -1,3 +1,57 @@
+2016-04-21  Michael Saboff  <msab...@apple.com>
+
+        Align RegExp[@@match] with other @@ methods
+        https://bugs.webkit.org/show_bug.cgi?id=156832
+
+        Reviewed by Mark Lam.
+
+        Various changes to align the RegExp[@@match] with [@@search] and [@@split].
+
+        Made RegExp.prototype.@exec a hidden property on the global object and
+        called it @regExpBuiltinExec to match the name it has in the standard.
+        Changed all places that used the old name to use the new one.
+
+        Made the match fast path function, which used to be call @match, to be called
+        @regExpMatchFast and put it on the global object.  Changed it to also handle
+        expressions both with and without the global flag.  Refactored the builtin
+        @match accordingly.
+
+        Added the builtin function @hasObservableSideEffectsForRegExpMatch() that
+        checks to see if we can use the fast path of if we need the explicit version.
+
+        Put the main RegExp functions @match, @search and @split in alphabetical
+        order in RegExpPrototype.js.  Did the same for @match, @repeat, @search and 
+        @split in StringPrototype.js.
+        
+        * builtins/RegExpPrototype.js:
+        (regExpExec):
+        (hasObservableSideEffectsForRegExpMatch): New.
+        (match):
+        (search):
+        (hasObservableSideEffectsForRegExpSplit):
+        Reordered in the file and updated to use @regExpBuiltinExec.
+
+        * builtins/StringPrototype.js:
+        (match):
+        (repeatSlowPath):
+        (repeat):
+        (search):
+        (split):
+        Reordered functions in the file.
+
+        * runtime/CommonIdentifiers.h:
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::setGlobalThis):
+        (JSC::getById):
+        (JSC::getGetterById):
+        (JSC::JSGlobalObject::init):
+        * runtime/RegExpPrototype.cpp:
+        (JSC::RegExpPrototype::finishCreation):
+        (JSC::regExpProtoFuncExec):
+        (JSC::regExpProtoFuncMatchFast):
+        (JSC::regExpProtoFuncMatchPrivate): Deleted.
+        * runtime/RegExpPrototype.h:
+
 2016-04-20  Geoffrey Garen  <gga...@apple.com>
 
         _javascript_Core garbage collection is missing an autorelease pool

Modified: trunk/Source/_javascript_Core/builtins/RegExpPrototype.js (199811 => 199812)


--- trunk/Source/_javascript_Core/builtins/RegExpPrototype.js	2016-04-21 10:53:51 UTC (rev 199811)
+++ trunk/Source/_javascript_Core/builtins/RegExpPrototype.js	2016-04-21 10:57:45 UTC (rev 199812)
@@ -45,69 +45,81 @@
     return index + 2;
 }
 
-function match(str)
+function regExpExec(regexp, str)
 {
     "use strict";
 
+    let exec = regexp.exec;
+    let builtinExec = @regExpBuiltinExec;
+    if (exec !== builtinExec && typeof exec === "function") {
+        let result = exec.@call(regexp, str);
+        if (result !== null && !@isObject(result))
+            throw new @TypeError("The result of a RegExp exec must be null or an object");
+        return result;
+    }
+    return builtinExec.@call(regexp, str);
+}
+
+function hasObservableSideEffectsForRegExpMatch(regexp) {
+    // This is accessed by the RegExpExec internal function.
+    let regexpExec = @tryGetById(regexp, "exec");
+    if (regexpExec !== @regExpBuiltinExec)
+        return true;
+
+    let regexpGlobal = @tryGetById(regexp, "global");
+    if (regexpGlobal !== @regExpProtoGlobalGetter)
+        return true;
+    let regexpUnicode = @tryGetById(regexp, "unicode");
+    if (regexpUnicode !== @regExpProtoUnicodeGetter)
+        return true;
+
+    return !@isRegExpObject(regexp);
+}
+
+function match(strArg)
+{
+    "use strict";
+
     if (!@isObject(this))
         throw new @TypeError("RegExp.prototype.@@match requires that |this| be an Object");
 
     let regexp = this;
-    let stringArg = @toString(str);
 
+    // Check for observable side effects and call the fast path if there aren't any.
+    if (!@hasObservableSideEffectsForRegExpMatch(regexp))
+        return @regExpMatchFast.@call(regexp, strArg);
+
+    let str = @toString(strArg);
+
     if (!regexp.global)
-        return regexp.exec(stringArg);
-
+        return @regExpExec(regexp, str);
+    
     let unicode = regexp.unicode;
     regexp.lastIndex = 0;
     let resultList = [];
-    let execFunc = regexp.exec;
+    let stringLength = str.length;
 
-    if (execFunc !== @RegExp.prototype.@exec && typeof execFunc === "function") {
-        // Match using the overridden exec.
-        let stringLength = stringArg.length;
+    while (true) {
+        let result = @regExpExec(regexp, str);
+        
+        if (result === null) {
+            if (resultList.length === 0)
+                return null;
+            return resultList;
+        }
 
-        while (true) {
-            let result = execFunc(stringArg);
-            
-            if (result === null) {
-                if (resultList.length === 0)
-                    return null;
-                return resultList;
-            }
+        if (!@isObject(result))
+            throw new @TypeError("RegExp.prototype.@@match call to RegExp.exec didn't return null or an object");
 
-            if (!@isObject(result))
-                throw new @TypeError("RegExp.prototype.@@match call to RegExp.exec didn't return null or an object");
+        let resultString = @toString(result[0]);
 
-            let resultString = @toString(result[0]);
+        if (!resultString.length)
+            regexp.lastIndex = @advanceStringIndex(str, regexp.lastIndex, unicode);
 
-            if (!resultString.length)
-                regexp.lastIndex = @advanceStringIndex(stringArg, regexp.lastIndex, unicode);
-
-            resultList.@push(resultString);
-
-            execFunc = regexp.exec;
-        }
+        resultList.@push(resultString);
     }
-
-    return regexp.@match(stringArg);
 }
 
-function regExpExec(regexp, str)
-{
-    "use strict";
-
-    let exec = regexp.exec;
-    let builtinExec = @RegExp.prototype.@exec;
-    if (exec !== builtinExec && typeof exec === "function") {
-        let result = exec.@call(regexp, str);
-        if (result !== null && !@isObject(result))
-            throw new @TypeError("The result of a RegExp exec must be null or an object");
-        return result;
-    }
-    return builtinExec.@call(regexp, str);
-}
-
 // 21.2.5.9 RegExp.prototype[@@search] (string)
 function search(strArg)
 {
@@ -116,7 +128,7 @@
     let regexp = this;
 
     // Check for observable side effects and call the fast path if there aren't any.
-    if (@isRegExpObject(regexp) && @tryGetById(regexp, "exec") === @RegExp.prototype.@exec)
+    if (@isRegExpObject(regexp) && @tryGetById(regexp, "exec") === @regExpBuiltinExec)
         return @regExpSearchFast.@call(regexp, strArg);
 
     // 1. Let rx be the this value.
@@ -145,7 +157,7 @@
 function hasObservableSideEffectsForRegExpSplit(regexp) {
     // This is accessed by the RegExpExec internal function.
     let regexpExec = @tryGetById(regexp, "exec");
-    if (regexpExec !== @RegExp.prototype.@exec)
+    if (regexpExec !== @regExpBuiltinExec)
         return true;
     
     // This is accessed by step 5 below.

Modified: trunk/Source/_javascript_Core/builtins/StringPrototype.js (199811 => 199812)


--- trunk/Source/_javascript_Core/builtins/StringPrototype.js	2016-04-21 10:53:51 UTC (rev 199811)
+++ trunk/Source/_javascript_Core/builtins/StringPrototype.js	2016-04-21 10:57:45 UTC (rev 199812)
@@ -46,27 +46,6 @@
     return createdRegExp[@symbolMatch](thisString);
 }
 
-function search(regexp)
-{
-    "use strict";
-
-    if (this == null) {
-        if (this === null)
-            throw new @TypeError("String.prototype.search requires that |this| not be null");
-        throw new @TypeError("String.prototype.search requires that |this| not be undefined");
-    }
-
-    if (regexp != null) {
-        var searcher = regexp[@symbolSearch];
-        if (searcher != @undefined)
-            return searcher.@call(regexp, this);
-    }
-
-    var thisString = @toString(this);
-    var createdRegExp = @regExpCreate(regexp, @undefined);
-    return createdRegExp[@symbolSearch](thisString);
-}
-
 function repeatSlowPath(string, count)
 {
     "use strict";
@@ -126,6 +105,27 @@
     return @repeatSlowPath(string, count);
 }
 
+function search(regexp)
+{
+    "use strict";
+
+    if (this == null) {
+        if (this === null)
+            throw new @TypeError("String.prototype.search requires that |this| not be null");
+        throw new @TypeError("String.prototype.search requires that |this| not be undefined");
+    }
+
+    if (regexp != null) {
+        var searcher = regexp[@symbolSearch];
+        if (searcher != @undefined)
+            return searcher.@call(regexp, this);
+    }
+
+    var thisString = @toString(this);
+    var createdRegExp = @regExpCreate(regexp, @undefined);
+    return createdRegExp[@symbolSearch](thisString);
+}
+
 function split(separator, limit)
 {
     "use strict";

Modified: trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h (199811 => 199812)


--- trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h	2016-04-21 10:53:51 UTC (rev 199811)
+++ trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h	2016-04-21 10:57:45 UTC (rev 199812)
@@ -427,6 +427,8 @@
     macro(setIteratorNext) \
     macro(MapIterator) \
     macro(mapIteratorNext) \
+    macro(regExpBuiltinExec) \
+    macro(regExpMatchFast) \
     macro(regExpProtoFlagsGetter) \
     macro(regExpProtoGlobalGetter) \
     macro(regExpProtoIgnoreCaseGetter) \

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (199811 => 199812)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2016-04-21 10:53:51 UTC (rev 199811)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2016-04-21 10:57:45 UTC (rev 199812)
@@ -257,7 +257,6 @@
     m_globalThis.set(vm, this, globalThis);
 }
 
-
 static JSObject* getGetterById(ExecState* exec, JSObject* base, const Identifier& ident)
 {
     JSValue baseValue = JSValue(base);
@@ -646,10 +645,13 @@
         GlobalPropertyInfo(vm.propertyNames->regExpProtoUnicodeGetterPrivateName, regExpProtoUnicodeGetterObject, DontEnum | DontDelete | ReadOnly),
 
         // RegExp.prototype helpers.
+        GlobalPropertyInfo(vm.propertyNames->regExpBuiltinExecPrivateName, m_regExpPrototype->getDirect(vm, vm.propertyNames->exec), DontEnum | DontDelete | ReadOnly),
         GlobalPropertyInfo(vm.propertyNames->regExpCreatePrivateName, JSFunction::create(vm, this, 2, String(), esSpecRegExpCreate, NoIntrinsic), DontEnum | DontDelete | ReadOnly),
+        GlobalPropertyInfo(vm.propertyNames->builtinNames().hasObservableSideEffectsForRegExpMatchPrivateName(), JSFunction::createBuiltinFunction(vm, regExpPrototypeHasObservableSideEffectsForRegExpMatchCodeGenerator(vm), this), DontEnum | DontDelete | ReadOnly),
         GlobalPropertyInfo(vm.propertyNames->builtinNames().hasObservableSideEffectsForRegExpSplitPrivateName(), JSFunction::createBuiltinFunction(vm, regExpPrototypeHasObservableSideEffectsForRegExpSplitCodeGenerator(vm), this), DontEnum | DontDelete | ReadOnly),
         GlobalPropertyInfo(vm.propertyNames->builtinNames().advanceStringIndexPrivateName(), JSFunction::createBuiltinFunction(vm, regExpPrototypeAdvanceStringIndexCodeGenerator(vm), this), DontEnum | DontDelete | ReadOnly),
         GlobalPropertyInfo(vm.propertyNames->builtinNames().regExpExecPrivateName(), JSFunction::createBuiltinFunction(vm, regExpPrototypeRegExpExecCodeGenerator(vm), this), DontEnum | DontDelete | ReadOnly),
+        GlobalPropertyInfo(vm.propertyNames->regExpMatchFastPrivateName, JSFunction::create(vm, this, 2, String(), regExpProtoFuncMatchFast), DontEnum | DontDelete | ReadOnly),
         GlobalPropertyInfo(vm.propertyNames->regExpSearchFastPrivateName, JSFunction::create(vm, this, 2, String(), regExpProtoFuncSearchFast), DontEnum | DontDelete | ReadOnly),
         GlobalPropertyInfo(vm.propertyNames->regExpSplitFastPrivateName, JSFunction::create(vm, this, 2, String(), regExpProtoFuncSplitFast), DontEnum | DontDelete | ReadOnly),
 

Modified: trunk/Source/_javascript_Core/runtime/RegExpPrototype.cpp (199811 => 199812)


--- trunk/Source/_javascript_Core/runtime/RegExpPrototype.cpp	2016-04-21 10:53:51 UTC (rev 199811)
+++ trunk/Source/_javascript_Core/runtime/RegExpPrototype.cpp	2016-04-21 10:57:45 UTC (rev 199812)
@@ -46,7 +46,6 @@
 
 static EncodedJSValue JSC_HOST_CALL regExpProtoFuncTest(ExecState*);
 static EncodedJSValue JSC_HOST_CALL regExpProtoFuncExec(ExecState*);
-static EncodedJSValue JSC_HOST_CALL regExpProtoFuncMatchPrivate(ExecState*);
 static EncodedJSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState*);
 static EncodedJSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState*);
 static EncodedJSValue JSC_HOST_CALL regExpProtoGetterGlobal(ExecState*);
@@ -69,6 +68,7 @@
     Base::finishCreation(vm);
     ASSERT(inherits(info()));
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->compile, regExpProtoFuncCompile, DontEnum, 2);
+    JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->exec, regExpProtoFuncExec, DontEnum, 1, RegExpExecIntrinsic);
     JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->test, regExpProtoFuncTest, DontEnum, 1, RegExpTestIntrinsic);
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->toString, regExpProtoFuncToString, DontEnum, 0);
     JSC_NATIVE_GETTER(vm.propertyNames->global, regExpProtoGetterGlobal, DontEnum | Accessor);
@@ -78,15 +78,10 @@
     JSC_NATIVE_GETTER(vm.propertyNames->unicode, regExpProtoGetterUnicode, DontEnum | Accessor);
     JSC_NATIVE_GETTER(vm.propertyNames->source, regExpProtoGetterSource, DontEnum | Accessor);
     JSC_NATIVE_GETTER(vm.propertyNames->flags, regExpProtoGetterFlags, DontEnum | Accessor);
-    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().matchPrivateName(), regExpProtoFuncMatchPrivate, DontEnum | DontDelete | ReadOnly, 1);
     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->matchSymbol, regExpPrototypeMatchCodeGenerator, DontEnum);
     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->searchSymbol, regExpPrototypeSearchCodeGenerator, DontEnum);
     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->splitSymbol, regExpPrototypeSplitCodeGenerator, DontEnum);
 
-    JSFunction* execFunction = JSFunction::create(vm, globalObject, 1, vm.propertyNames->exec.string(), regExpProtoFuncExec, RegExpExecIntrinsic);
-    putDirectWithoutTransition(vm, vm.propertyNames->execPrivateName, execFunction, DontEnum | DontDelete | ReadOnly);
-    putDirectWithoutTransition(vm, vm.propertyNames->exec, execFunction, DontEnum);
-
     m_emptyRegExp.set(vm, this, RegExp::create(vm, "", NoFlags));
 }
 
@@ -123,7 +118,7 @@
     return JSValue::encode(asRegExpObject(thisValue)->exec(exec, exec->lexicalGlobalObject(), string));
 }
 
-EncodedJSValue JSC_HOST_CALL regExpProtoFuncMatchPrivate(ExecState* exec)
+EncodedJSValue JSC_HOST_CALL regExpProtoFuncMatchFast(ExecState* exec)
 {
     JSValue thisValue = exec->thisValue();
     if (!thisValue.inherits(RegExpObject::info()))
@@ -131,6 +126,8 @@
     JSString* string = exec->argument(0).toStringOrNull(exec);
     if (!string)
         return JSValue::encode(jsUndefined());
+    if (!asRegExpObject(thisValue)->regExp()->global())
+        return JSValue::encode(asRegExpObject(thisValue)->exec(exec, exec->lexicalGlobalObject(), string));
     return JSValue::encode(asRegExpObject(thisValue)->matchGlobal(exec, exec->lexicalGlobalObject(), string));
 }
 

Modified: trunk/Source/_javascript_Core/runtime/RegExpPrototype.h (199811 => 199812)


--- trunk/Source/_javascript_Core/runtime/RegExpPrototype.h	2016-04-21 10:53:51 UTC (rev 199811)
+++ trunk/Source/_javascript_Core/runtime/RegExpPrototype.h	2016-04-21 10:57:45 UTC (rev 199812)
@@ -58,6 +58,7 @@
     WriteBarrier<RegExp> m_emptyRegExp;
 };
 
+EncodedJSValue JSC_HOST_CALL regExpProtoFuncMatchFast(ExecState*);
 EncodedJSValue JSC_HOST_CALL regExpProtoFuncSearchFast(ExecState*);
 EncodedJSValue JSC_HOST_CALL regExpProtoFuncSplitFast(ExecState*);
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to