Changeset 200272 in webkit


Ignore:
Timestamp:
Apr 29, 2016 5:34:01 PM (8 years ago)
Author:
mark.lam@apple.com
Message:

Make RegExp.prototype.test spec compliant.
https://bugs.webkit.org/show_bug.cgi?id=155862

Reviewed by Saam Barati.

Source/JavaScriptCore:

  • builtins/RegExpPrototype.js:

(intrinsic.RegExpTestIntrinsic.test):

  • create_hash_table:
  • Delete obsoleted code.
  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::addToGraph):
(JSC::DFG::ByteCodeParser::handleIntrinsicCall):

  • We now have 2 intrinsics for RegExp.prototype.test: RegExpTestIntrinsic and RegExpTestFastIntrinsic.

RegExpTestIntrinsic maps to the entry at the top of the builtin ES6
RegExp.prototype.test.
RegExpTestFastIntrinsic maps to the fast path in the builtin ES6
RegExp.prototype.test.

Both will end up using the RegExpTest DFG node to implement the fast path
of RegExp.prototype.test. RegExpTestIntrinsic will have some additional checks
before the RegExpTest node. Those checks are for speculating that it is ok for
us to take the fast path.

  • runtime/CommonIdentifiers.h:
  • runtime/Intrinsic.h:
  • runtime/JSGlobalObject.cpp:

(JSC::JSGlobalObject::init):

  • Added the regExpTestFast function.
  • Also fixed the parameter length on 2 other functions that were erroneous.
  • runtime/RegExpPrototype.cpp:

(JSC::RegExpPrototype::finishCreation):
(JSC::regExpProtoFuncTestFast):
(JSC::regExpProtoFuncTest): Deleted.

  • runtime/RegExpPrototype.h:
  • tests/es6.yaml:

LayoutTests:

  • js/regress/regexp-prototype-test-observable-side-effects-expected.txt: Added.
  • js/regress/regexp-prototype-test-observable-side-effects.html: Added.
  • js/regress/regexp-prototype-test-observable-side-effects2-expected.txt: Added.
  • js/regress/regexp-prototype-test-observable-side-effects2.html: Added.
  • js/regress/script-tests/regexp-prototype-test-observable-side-effects.js: Added.
  • js/regress/script-tests/simple-regexp-test-folding-fail-with-hoisted-regexp.js: Added.
  • js/regress/script-tests/simple-regexp-test-folding-with-hoisted-regexp.js: Added.
  • js/regress/simple-regexp-test-folding-fail-with-hoisted-regexp-expected.txt: Added.
  • js/regress/simple-regexp-test-folding-fail-with-hoisted-regexp.html: Added.
  • js/regress/simple-regexp-test-folding-with-hoisted-regexp-expected.txt: Added.
  • js/regress/simple-regexp-test-folding-with-hoisted-regexp.html: Added.
Location:
trunk
Files:
12 added
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r200269 r200272  
     12016-04-29  Mark Lam  <mark.lam@apple.com>
     2
     3        Make RegExp.prototype.test spec compliant.
     4        https://bugs.webkit.org/show_bug.cgi?id=155862
     5
     6        Reviewed by Saam Barati.
     7
     8        * js/regress/regexp-prototype-test-observable-side-effects-expected.txt: Added.
     9        * js/regress/regexp-prototype-test-observable-side-effects.html: Added.
     10        * js/regress/regexp-prototype-test-observable-side-effects2-expected.txt: Added.
     11        * js/regress/regexp-prototype-test-observable-side-effects2.html: Added.
     12        * js/regress/script-tests/regexp-prototype-test-observable-side-effects.js: Added.
     13        * js/regress/script-tests/simple-regexp-test-folding-fail-with-hoisted-regexp.js: Added.
     14        * js/regress/script-tests/simple-regexp-test-folding-with-hoisted-regexp.js: Added.
     15        * js/regress/simple-regexp-test-folding-fail-with-hoisted-regexp-expected.txt: Added.
     16        * js/regress/simple-regexp-test-folding-fail-with-hoisted-regexp.html: Added.
     17        * js/regress/simple-regexp-test-folding-with-hoisted-regexp-expected.txt: Added.
     18        * js/regress/simple-regexp-test-folding-with-hoisted-regexp.html: Added.
     19
    1202016-04-29  Commit Queue  <commit-queue@webkit.org>
    221
  • trunk/Source/JavaScriptCore/ChangeLog

    r200263 r200272  
     12016-04-29  Mark Lam  <mark.lam@apple.com>
     2
     3        Make RegExp.prototype.test spec compliant.
     4        https://bugs.webkit.org/show_bug.cgi?id=155862
     5
     6        Reviewed by Saam Barati.
     7
     8        * builtins/RegExpPrototype.js:
     9        (intrinsic.RegExpTestIntrinsic.test):
     10
     11        * create_hash_table:
     12        - Delete obsoleted code.
     13
     14        * dfg/DFGByteCodeParser.cpp:
     15        (JSC::DFG::ByteCodeParser::addToGraph):
     16        (JSC::DFG::ByteCodeParser::handleIntrinsicCall):
     17        - We now have 2 intrinsics for RegExp.prototype.test:
     18          RegExpTestIntrinsic and RegExpTestFastIntrinsic.
     19
     20          RegExpTestIntrinsic maps to the entry at the top of the builtin ES6
     21          RegExp.prototype.test.
     22          RegExpTestFastIntrinsic maps to the fast path in the builtin ES6
     23          RegExp.prototype.test.
     24
     25          Both will end up using the RegExpTest DFG node to implement the fast path
     26          of RegExp.prototype.test.  RegExpTestIntrinsic will have some additional checks
     27          before the RegExpTest node.  Those checks are for speculating that it is ok for
     28          us to take the fast path.
     29
     30        * runtime/CommonIdentifiers.h:
     31        * runtime/Intrinsic.h:
     32
     33        * runtime/JSGlobalObject.cpp:
     34        (JSC::JSGlobalObject::init):
     35        - Added the regExpTestFast function.
     36        - Also fixed the parameter length on 2 other functions that were erroneous.
     37
     38        * runtime/RegExpPrototype.cpp:
     39        (JSC::RegExpPrototype::finishCreation):
     40        (JSC::regExpProtoFuncTestFast):
     41        (JSC::regExpProtoFuncTest): Deleted.
     42        * runtime/RegExpPrototype.h:
     43        * tests/es6.yaml:
     44
    1452016-04-29  Benjamin Poulain  <benjamin@webkit.org>
    246
  • trunk/Source/JavaScriptCore/builtins/RegExpPrototype.js

    r200239 r200272  
    488488    return result;
    489489}
     490
     491// ES 21.2.5.13 RegExp.prototype.test(string)
     492[intrinsic=RegExpTestIntrinsic] function test(strArg)
     493{
     494    "use strict";
     495
     496    let regexp = this;
     497
     498    // Check for observable side effects and call the fast path if there aren't any.
     499    if (@isRegExpObject(regexp) && @tryGetById(regexp, "exec") === @regExpBuiltinExec)
     500        return @regExpTestFast.@call(regexp, strArg);
     501
     502    // 1. Let R be the this value.
     503    // 2. If Type(R) is not Object, throw a TypeError exception.
     504    if (!@isObject(regexp))
     505        throw new @TypeError("RegExp.prototype.test requires that |this| be an Object");
     506
     507    // 3. Let string be ? ToString(S).
     508    let str = @toString(strArg);
     509
     510    // 4. Let match be ? RegExpExec(R, string).
     511    let match = @regExpExec(regexp, str);
     512
     513    // 5. If match is not null, return true; else return false.
     514    if (match !== null)
     515        return true;
     516    return false;
     517}
  • trunk/Source/JavaScriptCore/create_hash_table

    r193900 r200272  
    307307            $intrinsic = "ArrayPopIntrinsic" if ($key eq "pop");
    308308        }
    309         if ($name eq "regExpPrototypeTable") {
    310             $intrinsic = "RegExpExecIntrinsic" if ($key eq "exec");
    311             $intrinsic = "RegExpTestIntrinsic" if ($key eq "test");
    312         }
    313309
    314310        if ($values[$i]{"type"} eq "Function" && $firstValue eq "JSBuiltin")  {
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r200149 r200272  
    4949#include "PutByIdFlags.h"
    5050#include "PutByIdStatus.h"
    51 #include <RegExpPrototype.h>
     51#include "RegExpPrototype.h"
    5252#include "StackAlignment.h"
    5353#include "StringConstructor.h"
     
    722722        return addToGraph(result);
    723723    }
     724    Node* addToGraph(NodeType op, OpInfo info, Edge child1, Edge child2 = Edge(), Edge child3 = Edge())
     725    {
     726        Node* result = m_graph.addNode(SpecNone, op, currentNodeOrigin(), info, child1, child2, child3);
     727        return addToGraph(result);
     728    }
    724729    Node* addToGraph(NodeType op, OpInfo info1, OpInfo info2, Node* child1 = 0, Node* child2 = 0, Node* child3 = 0)
    725730    {
     
    727732            SpecNone, op, currentNodeOrigin(), info1, info2,
    728733            Edge(child1), Edge(child2), Edge(child3));
     734        return addToGraph(result);
     735    }
     736    Node* addToGraph(NodeType op, OpInfo info1, OpInfo info2, Edge child1, Edge child2 = Edge(), Edge child3 = Edge())
     737    {
     738        Node* result = m_graph.addNode(
     739            SpecNone, op, currentNodeOrigin(), info1, info2, child1, child2, child3);
    729740        return addToGraph(result);
    730741    }
     
    22062217    }
    22072218       
    2208     case RegExpTestIntrinsic: {
     2219    case RegExpTestIntrinsic:
     2220    case RegExpTestFastIntrinsic: {
    22092221        if (argumentCountIncludingThis != 2)
    22102222            return false;
    2211        
     2223
     2224        if (intrinsic == RegExpTestIntrinsic) {
     2225            // Don't inline intrinsic if we exited due to one of the primordial RegExp checks failing.
     2226            if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCell))
     2227                return false;
     2228
     2229            JSGlobalObject* globalObject = m_inlineStackTop->m_codeBlock->globalObject();
     2230            Structure* regExpStructure = globalObject->regExpStructure();
     2231            m_graph.registerStructure(regExpStructure);
     2232            ASSERT(regExpStructure->storedPrototype().isObject());
     2233            ASSERT(regExpStructure->storedPrototype().asCell()->classInfo() == RegExpPrototype::info());
     2234
     2235            FrozenValue* regExpPrototypeObjectValue = m_graph.freeze(regExpStructure->storedPrototype());
     2236            Structure* regExpPrototypeStructure = regExpPrototypeObjectValue->structure();
     2237
     2238            auto isRegExpPropertySame = [&] (JSValue primordialProperty, UniquedStringImpl* propertyUID) {
     2239                JSValue currentProperty;
     2240                if (!m_graph.getRegExpPrototypeProperty(regExpStructure->storedPrototypeObject(), regExpPrototypeStructure, propertyUID, currentProperty))
     2241                    return false;
     2242               
     2243                return currentProperty == primordialProperty;
     2244            };
     2245
     2246            // Check that RegExp.exec is still the primordial RegExp.prototype.exec
     2247            if (!isRegExpPropertySame(globalObject->regExpProtoExecFunction(), m_vm->propertyNames->exec.impl()))
     2248                return false;
     2249
     2250            // Check that regExpObject is actually a RegExp object.
     2251            Node* regExpObject = get(virtualRegisterForArgument(0, registerOffset));
     2252            addToGraph(Check, Edge(regExpObject, RegExpObjectUse));
     2253
     2254            // Check that regExpObject's exec is actually the primodial RegExp.prototype.exec.
     2255            UniquedStringImpl* execPropertyID = m_vm->propertyNames->exec.impl();
     2256            unsigned execIndex = m_graph.identifiers().ensure(execPropertyID);
     2257            Node* actualProperty = addToGraph(TryGetById, OpInfo(execIndex), OpInfo(SpecFunction), Edge(regExpObject, CellUse));
     2258            FrozenValue* regExpPrototypeExec = m_graph.freeze(globalObject->regExpProtoExecFunction());
     2259            addToGraph(CheckCell, OpInfo(regExpPrototypeExec), Edge(actualProperty, CellUse));
     2260        }
     2261
    22122262        insertChecks();
    2213         Node* regExpExec = addToGraph(RegExpTest, OpInfo(0), OpInfo(prediction), addToGraph(GetGlobalObject, callee), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)));
     2263        Node* regExpObject = get(virtualRegisterForArgument(0, registerOffset));
     2264        Node* regExpExec = addToGraph(RegExpTest, OpInfo(0), OpInfo(prediction), addToGraph(GetGlobalObject, callee), regExpObject, get(virtualRegisterForArgument(1, registerOffset)));
    22142265        set(VirtualRegister(resultOperand), regExpExec);
    22152266       
  • trunk/Source/JavaScriptCore/runtime/CommonIdentifiers.h

    r200252 r200272  
    437437    macro(regExpProtoStickyGetter) \
    438438    macro(regExpProtoUnicodeGetter) \
     439    macro(regExpPrototypeSymbolReplace) \
    439440    macro(regExpReplaceFast) \
    440441    macro(regExpSearchFast) \
    441442    macro(regExpSplitFast) \
    442     macro(regExpPrototypeSymbolReplace) \
     443    macro(regExpTestFast) \
    443444    macro(stringIncludesInternal) \
    444445    macro(stringSplitFast) \
  • trunk/Source/JavaScriptCore/runtime/Intrinsic.h

    r200149 r200272  
    5252    RegExpExecIntrinsic,
    5353    RegExpTestIntrinsic,
     54    RegExpTestFastIntrinsic,
    5455    StringPrototypeValueOfIntrinsic,
    5556    StringPrototypeReplaceIntrinsic,
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp

    r200218 r200272  
    653653        GlobalPropertyInfo(vm.propertyNames->builtinNames().advanceStringIndexPrivateName(), JSFunction::createBuiltinFunction(vm, regExpPrototypeAdvanceStringIndexCodeGenerator(vm), this), DontEnum | DontDelete | ReadOnly),
    654654        GlobalPropertyInfo(vm.propertyNames->builtinNames().regExpExecPrivateName(), JSFunction::createBuiltinFunction(vm, regExpPrototypeRegExpExecCodeGenerator(vm), this), DontEnum | DontDelete | ReadOnly),
    655         GlobalPropertyInfo(vm.propertyNames->regExpMatchFastPrivateName, JSFunction::create(vm, this, 2, String(), regExpProtoFuncMatchFast), DontEnum | DontDelete | ReadOnly),
    656         GlobalPropertyInfo(vm.propertyNames->regExpSearchFastPrivateName, JSFunction::create(vm, this, 2, String(), regExpProtoFuncSearchFast), DontEnum | DontDelete | ReadOnly),
     655        GlobalPropertyInfo(vm.propertyNames->regExpMatchFastPrivateName, JSFunction::create(vm, this, 1, String(), regExpProtoFuncMatchFast), DontEnum | DontDelete | ReadOnly),
     656        GlobalPropertyInfo(vm.propertyNames->regExpSearchFastPrivateName, JSFunction::create(vm, this, 1, String(), regExpProtoFuncSearchFast), DontEnum | DontDelete | ReadOnly),
    657657        GlobalPropertyInfo(vm.propertyNames->regExpSplitFastPrivateName, JSFunction::create(vm, this, 2, String(), regExpProtoFuncSplitFast), DontEnum | DontDelete | ReadOnly),
    658658        GlobalPropertyInfo(vm.propertyNames->regExpPrototypeSymbolReplacePrivateName, m_regExpPrototype->getDirect(vm, vm.propertyNames->replaceSymbol), DontEnum | DontDelete | ReadOnly),
     659        GlobalPropertyInfo(vm.propertyNames->regExpTestFastPrivateName, JSFunction::create(vm, this, 1, String(), regExpProtoFuncTestFast, RegExpTestFastIntrinsic), DontEnum | DontDelete | ReadOnly),
    659660
    660661        // String.prototype helpers.
  • trunk/Source/JavaScriptCore/runtime/RegExpPrototype.cpp

    r200117 r200272  
    4545namespace JSC {
    4646
    47 static EncodedJSValue JSC_HOST_CALL regExpProtoFuncTest(ExecState*);
    4847static EncodedJSValue JSC_HOST_CALL regExpProtoFuncExec(ExecState*);
    4948static EncodedJSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState*);
     
    7069    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->compile, regExpProtoFuncCompile, DontEnum, 2);
    7170    JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->exec, regExpProtoFuncExec, DontEnum, 1, RegExpExecIntrinsic);
    72     JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->test, regExpProtoFuncTest, DontEnum, 1, RegExpTestIntrinsic);
    7371    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->toString, regExpProtoFuncToString, DontEnum, 0);
    7472    JSC_NATIVE_GETTER(vm.propertyNames->global, regExpProtoGetterGlobal, DontEnum | Accessor);
     
    8381    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->searchSymbol, regExpPrototypeSearchCodeGenerator, DontEnum);
    8482    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->splitSymbol, regExpPrototypeSplitCodeGenerator, DontEnum);
     83    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->test, regExpPrototypeTestCodeGenerator, DontEnum);
    8584
    8685    m_emptyRegExp.set(vm, this, RegExp::create(vm, "", NoFlags));
     
    9897// ------------------------------ Functions ---------------------------
    9998
    100 EncodedJSValue JSC_HOST_CALL regExpProtoFuncTest(ExecState* exec)
     99EncodedJSValue JSC_HOST_CALL regExpProtoFuncTestFast(ExecState* exec)
    101100{
    102101    JSValue thisValue = exec->thisValue();
  • trunk/Source/JavaScriptCore/runtime/RegExpPrototype.h

    r199812 r200272  
    6262EncodedJSValue JSC_HOST_CALL regExpProtoFuncSearchFast(ExecState*);
    6363EncodedJSValue JSC_HOST_CALL regExpProtoFuncSplitFast(ExecState*);
     64EncodedJSValue JSC_HOST_CALL regExpProtoFuncTestFast(ExecState*);
    6465
    6566} // namespace JSC
  • trunk/Source/JavaScriptCore/tests/es6.yaml

    r200149 r200272  
    998998  cmd: runES6 :normal
    999999- path: es6/Proxy_internal_get_calls_RegExp.prototype.test.js
    1000   cmd: runES6 :fail
     1000  cmd: runES6 :normal
    10011001- path: es6/Proxy_internal_get_calls_RegExp.prototype.toString.js
    10021002  cmd: runES6 :normal
Note: See TracChangeset for help on using the changeset viewer.