Changeset 273086 in webkit
- Timestamp:
- Feb 18, 2021 11:14:34 AM (3 years ago)
- Location:
- trunk
- Files:
-
- 24 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r272933 r273086 1 2021-02-18 Michael Saboff <msaboff@apple.com> 2 3 [JSC] Implement RegExp Match Indices proposal 4 https://bugs.webkit.org/show_bug.cgi?id=202475 5 6 Reviewed by Yusuke Suzuki. 7 8 Updated tests. 9 10 * es6/Proxy_internal_get_calls_RegExp.prototype.flags.js: 11 * stress/static-getter-in-names.js: 12 * test262/config.yaml: 13 1 14 2021-02-16 Yusuke Suzuki <ysuzuki@apple.com> and Sergey Rubanov <chi187@gmail.com> 2 15 -
trunk/JSTests/es6/Proxy_internal_get_calls_RegExp.prototype.flags.js
r221160 r273086 5 5 var p = new Proxy({}, { get: function(o, k) { get.push(k); return o[k]; }}); 6 6 Object.getOwnPropertyDescriptor(RegExp.prototype, 'flags').get.call(p); 7 return get + '' === " global,ignoreCase,multiline,dotAll,unicode,sticky";7 return get + '' === "hasIndices,global,ignoreCase,multiline,dotAll,unicode,sticky"; 8 8 9 9 } -
trunk/JSTests/stress/static-getter-in-names.js
r221160 r273086 4 4 } 5 5 6 shouldBe(JSON.stringify(Object.getOwnPropertyNames(RegExp.prototype).sort()), '["compile","constructor","dotAll","exec","flags","global"," ignoreCase","multiline","source","sticky","test","toString","unicode"]');6 shouldBe(JSON.stringify(Object.getOwnPropertyNames(RegExp.prototype).sort()), '["compile","constructor","dotAll","exec","flags","global","hasIndices","ignoreCase","multiline","source","sticky","test","toString","unicode"]'); 7 7 shouldBe(JSON.stringify(Object.getOwnPropertyNames(/Cocoa/).sort()), '["lastIndex"]'); -
trunk/JSTests/test262/config.yaml
r272883 r273086 25 25 - host-gc-required 26 26 # https://bugs.webkit.org/show_bug.cgi?id=202475 27 - regexp-match-indices28 27 - top-level-await 29 28 paths: -
trunk/LayoutTests/ChangeLog
r273080 r273086 1 2021-02-18 Michael Saboff <msaboff@apple.com> 2 3 [JSC] Implement RegExp Match Indices proposal 4 https://bugs.webkit.org/show_bug.cgi?id=202475 5 6 Reviewed by Yusuke Suzuki. 7 8 Updated tests. 9 10 * js/Object-getOwnPropertyNames-expected.txt: 11 * js/regexp-named-capture-groups-expected.txt: 12 * js/script-tests/Object-getOwnPropertyNames.js: 13 * js/script-tests/regexp-named-capture-groups.js: 14 1 15 2021-02-18 Kimmo Kinnunen <kkinnunen@apple.com> 2 16 -
trunk/LayoutTests/js/Object-getOwnPropertyNames-expected.txt
r270550 r273086 58 58 PASS getSortedOwnPropertyNames(Date.prototype) is ['constructor', 'getDate', 'getDay', 'getFullYear', 'getHours', 'getMilliseconds', 'getMinutes', 'getMonth', 'getSeconds', 'getTime', 'getTimezoneOffset', 'getUTCDate', 'getUTCDay', 'getUTCFullYear', 'getUTCHours', 'getUTCMilliseconds', 'getUTCMinutes', 'getUTCMonth', 'getUTCSeconds', 'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds', 'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear', 'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds', 'setYear', 'toDateString', 'toGMTString', 'toISOString', 'toJSON', 'toLocaleDateString', 'toLocaleString', 'toLocaleTimeString', 'toString', 'toTimeString', 'toUTCString', 'valueOf'] 59 59 PASS getSortedOwnPropertyNames(RegExp) is ['$&', "$'", '$*', '$+', '$1', '$2', '$3', '$4', '$5', '$6', '$7', '$8', '$9', '$_', '$`', 'input', 'lastMatch', 'lastParen', 'leftContext', 'length', 'multiline', 'name', 'prototype', 'rightContext'] 60 PASS getSortedOwnPropertyNames(RegExp.prototype) is ['compile', 'constructor', 'dotAll', 'exec', 'flags', 'global', ' ignoreCase', 'multiline', 'source', 'sticky', 'test', 'toString', 'unicode']60 PASS getSortedOwnPropertyNames(RegExp.prototype) is ['compile', 'constructor', 'dotAll', 'exec', 'flags', 'global', 'hasIndices', 'ignoreCase', 'multiline', 'source', 'sticky', 'test', 'toString', 'unicode'] 61 61 PASS getSortedOwnPropertyNames(Error) is ['length', 'name', 'prototype', 'stackTraceLimit'] 62 62 PASS getSortedOwnPropertyNames(Error.prototype) is ['constructor', 'message', 'name', 'toString'] -
trunk/LayoutTests/js/regexp-named-capture-groups-expected.txt
r259262 r273086 15 15 PASS matchResult1.groups.day is "02" 16 16 PASS matchResult1.groups.year is "2001" 17 PASS Object.getOwnPropertyNames(matchResult1).sort() is ["0","1","2","3","groups","index","input","length"] 17 PASS matchResult1.indices.groups.month is [0,2] 18 PASS matchResult1.indices.groups.day is [3,5] 19 PASS matchResult1.indices.groups.year is [6,10] 20 PASS Object.getOwnPropertyNames(matchResult1).sort() is ["0","1","2","3","groups","index","indices","input","length"] 18 21 PASS Object.getOwnPropertyNames(matchResult1.groups).sort() is ["day","month","year"] 22 PASS Object.getOwnPropertyNames(matchResult1.indices.groups).sort() is ["day","month","year"] 19 23 PASS matchResult2a[0] is "John W. Smith" 20 24 PASS matchResult2a[1] is "John" 21 25 PASS matchResult2a[2] is "W." 22 26 PASS matchResult2a[3] is "Smith" 27 PASS matchResult2a.indices[1] is [0,4] 28 PASS matchResult2a.indices[2] is [5,7] 29 PASS matchResult2a.indices[3] is [8,13] 23 30 PASS matchResult2a[1] is matchResult2a.groups.first_name 24 31 PASS matchResult2a[2] is matchResult2a.groups.middle_initial 25 32 PASS matchResult2a[3] is matchResult2a.groups.last_name 26 PASS Object.getOwnPropertyNames(matchResult1).sort() is ["0","1","2","3","groups","index","in put","length"]33 PASS Object.getOwnPropertyNames(matchResult1).sort() is ["0","1","2","3","groups","index","indices","input","length"] 27 34 PASS matchResult2b[0] is "Sally Brown" 28 35 PASS matchResult2b[1] is "Sally" 29 36 PASS matchResult2b[2] is undefined. 30 37 PASS matchResult2b[3] is "Brown" 38 PASS matchResult2b.indices[1] is [0,5] 39 PASS matchResult2b.indices[2] is undefined. 40 PASS matchResult2b.indices[3] is [6,11] 31 41 PASS matchResult2b[1] is matchResult2b.groups.first_name 32 42 PASS matchResult2b[2] is matchResult2b.groups.middle_initial 33 43 PASS matchResult2b[3] is matchResult2b.groups.last_name 34 PASS Object.getOwnPropertyNames(matchResult1).sort() is ["0","1","2","3","groups","index","in put","length"]44 PASS Object.getOwnPropertyNames(matchResult1).sort() is ["0","1","2","3","groups","index","indices","input","length"] 35 45 PASS re3.toString() is "\/^(?<part1>.*):(?<part2>.*):\\k<part2>:\\k<part1>$\/" 36 46 PASS re3.test("a:b:b:a") is true -
trunk/LayoutTests/js/script-tests/Object-getOwnPropertyNames.js
r270550 r273086 67 67 "Date.prototype": "['constructor', 'getDate', 'getDay', 'getFullYear', 'getHours', 'getMilliseconds', 'getMinutes', 'getMonth', 'getSeconds', 'getTime', 'getTimezoneOffset', 'getUTCDate', 'getUTCDay', 'getUTCFullYear', 'getUTCHours', 'getUTCMilliseconds', 'getUTCMinutes', 'getUTCMonth', 'getUTCSeconds', 'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds', 'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear', 'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds', 'setYear', 'toDateString', 'toGMTString', 'toISOString', 'toJSON', 'toLocaleDateString', 'toLocaleString', 'toLocaleTimeString', 'toString', 'toTimeString', 'toUTCString', 'valueOf']", 68 68 "RegExp": "['$&', \"$'\", '$*', '$+', '$1', '$2', '$3', '$4', '$5', '$6', '$7', '$8', '$9', '$_', '$`', 'input', 'lastMatch', 'lastParen', 'leftContext', 'length', 'multiline', 'name', 'prototype', 'rightContext']", 69 "RegExp.prototype": "['compile', 'constructor', 'dotAll', 'exec', 'flags', 'global', ' ignoreCase', 'multiline', 'source', 'sticky', 'test', 'toString', 'unicode']",69 "RegExp.prototype": "['compile', 'constructor', 'dotAll', 'exec', 'flags', 'global', 'hasIndices', 'ignoreCase', 'multiline', 'source', 'sticky', 'test', 'toString', 'unicode']", 70 70 "Error": "['length', 'name', 'prototype', 'stackTraceLimit']", 71 71 "Error.prototype": "['constructor', 'message', 'name', 'toString']", -
trunk/LayoutTests/js/script-tests/regexp-named-capture-groups.js
r259262 r273086 16 16 shouldBe('Object.getOwnPropertyNames(execResult1.groups).sort()', '["day","month","year"]'); 17 17 18 var matchResult1 = src1.match( re1);18 var matchResult1 = src1.match(new RegExp(re1, 'd')); 19 19 shouldBe('matchResult1[0]', '"01/02/2001"'); 20 20 shouldBe('matchResult1.groups.month', '"01"'); 21 21 shouldBe('matchResult1.groups.day', '"02"'); 22 22 shouldBe('matchResult1.groups.year', '"2001"'); 23 shouldBe('Object.getOwnPropertyNames(matchResult1).sort()', '["0","1","2","3","groups","index","input","length"]'); 23 shouldBe('matchResult1.indices.groups.month', '[0,2]'); 24 shouldBe('matchResult1.indices.groups.day', '[3,5]'); 25 shouldBe('matchResult1.indices.groups.year', '[6,10]'); 26 shouldBe('Object.getOwnPropertyNames(matchResult1).sort()', '["0","1","2","3","groups","index","indices","input","length"]'); 24 27 shouldBe('Object.getOwnPropertyNames(matchResult1.groups).sort()', '["day","month","year"]'); 28 shouldBe('Object.getOwnPropertyNames(matchResult1.indices.groups).sort()', '["day","month","year"]'); 25 29 26 var re2 = /(?<first_name>\w+)\s(?:(?<middle_initial>\w\.)\s)?(?<last_name>\w+)/ ;30 var re2 = /(?<first_name>\w+)\s(?:(?<middle_initial>\w\.)\s)?(?<last_name>\w+)/d; 27 31 var matchResult2a = "John W. Smith".match(re2); 28 32 … … 31 35 shouldBe('matchResult2a[2]', '"W."'); 32 36 shouldBe('matchResult2a[3]', '"Smith"'); 37 shouldBe('matchResult2a.indices[1]', '[0,4]'); 38 shouldBe('matchResult2a.indices[2]', '[5,7]'); 39 shouldBe('matchResult2a.indices[3]', '[8,13]'); 33 40 shouldBe('matchResult2a[1]', 'matchResult2a.groups.first_name'); 34 41 shouldBe('matchResult2a[2]', 'matchResult2a.groups.middle_initial'); 35 42 shouldBe('matchResult2a[3]', 'matchResult2a.groups.last_name'); 36 shouldBe('Object.getOwnPropertyNames(matchResult1).sort()', '["0","1","2","3","groups","index","in put","length"]');43 shouldBe('Object.getOwnPropertyNames(matchResult1).sort()', '["0","1","2","3","groups","index","indices","input","length"]'); 37 44 38 45 // Verify that named groups that aren't matched are undefined. … … 43 50 shouldBeUndefined('matchResult2b[2]'); 44 51 shouldBe('matchResult2b[3]', '"Brown"'); 52 shouldBe('matchResult2b.indices[1]', '[0,5]'); 53 shouldBeUndefined('matchResult2b.indices[2]'); 54 shouldBe('matchResult2b.indices[3]', '[6,11]'); 45 55 shouldBe('matchResult2b[1]', 'matchResult2b.groups.first_name'); 46 56 shouldBe('matchResult2b[2]', 'matchResult2b.groups.middle_initial'); 47 57 shouldBe('matchResult2b[3]', 'matchResult2b.groups.last_name'); 48 shouldBe('Object.getOwnPropertyNames(matchResult1).sort()', '["0","1","2","3","groups","index","in put","length"]');58 shouldBe('Object.getOwnPropertyNames(matchResult1).sort()', '["0","1","2","3","groups","index","indices","input","length"]'); 49 59 50 60 // Verify that named backreferences work. -
trunk/Source/JavaScriptCore/ChangeLog
r273034 r273086 1 2021-02-18 Michael Saboff <msaboff@apple.com> 2 3 [JSC] Implement RegExp Match Indices proposal 4 https://bugs.webkit.org/show_bug.cgi?id=202475 5 6 Reviewed by Yusuke Suzuki. 7 8 This implements the latest version of the RegExp match indices proposal (https://github.com/tc39/proposal-regexp-match-indices). 9 It includes a new 'd' flag to RegExp's to trigger the population of the 'indices' property tree in a Matches result from 10 RegExp.exec() and related methods. This change is performance neutral on JetStream2. 11 12 * dfg/DFGAbstractInterpreterInlines.h: 13 (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): 14 * dfg/DFGStrengthReductionPhase.cpp: 15 (JSC::DFG::StrengthReductionPhase::handleNode): 16 * runtime/CommonIdentifiers.h: 17 * runtime/JSGlobalObject.cpp: 18 (JSC::JSGlobalObject::init): 19 (JSC::JSGlobalObject::fireWatchpointAndMakeAllArrayStructuresSlowPut): 20 (JSC::JSGlobalObject::visitChildren): 21 * runtime/JSGlobalObject.h: 22 (JSC::JSGlobalObject::regExpMatchesArrayWithIndicesStructure const): 23 (JSC::JSGlobalObject::regExpMatchesIndicesArrayStructure const): 24 * runtime/RegExp.cpp: 25 (JSC::RegExpFunctionalTestCollector::outputOneTest): 26 (JSC::regexpToSourceString): 27 * runtime/RegExp.h: 28 * runtime/RegExpMatchesArray.cpp: 29 (JSC::createEmptyRegExpMatchesArray): 30 (JSC::createStructureWithIndicesImpl): 31 (JSC::createIndicesStructureImpl): 32 (JSC::createRegExpMatchesArrayWithIndicesStructure): 33 (JSC::createRegExpMatchesIndicesArrayStructure): 34 (JSC::createRegExpMatchesArrayWithIndicesSlowPutStructure): 35 (JSC::createRegExpMatchesIndicesArraySlowPutStructure): 36 * runtime/RegExpMatchesArray.h: 37 (JSC::createRegExpMatchesArray): 38 * runtime/RegExpPrototype.cpp: 39 (JSC::RegExpPrototype::finishCreation): 40 (JSC::flagsString): 41 (JSC::JSC_DEFINE_HOST_FUNCTION): 42 * yarr/YarrFlags.cpp: 43 (JSC::Yarr::parseFlags): 44 * yarr/YarrFlags.h: 45 * yarr/YarrInterpreter.h: 46 (JSC::Yarr::BytecodePattern::hasIndices const): 47 * yarr/YarrPattern.h: 48 (JSC::Yarr::YarrPattern::hasIndices const): 49 1 50 2021-02-17 Yusuke Suzuki <ysuzuki@apple.com> 2 51 -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
r272580 r273086 49 49 #include "NumberConstructor.h" 50 50 #include "PutByIdStatus.h" 51 #include "RegExpObject.h" 51 52 #include "SetPrivateBrandStatus.h" 52 53 #include "StringObject.h" … … 2608 2609 if (!globalObject->isHavingABadTime()) { 2609 2610 m_graph.watchpoints().addLazily(globalObject->havingABadTimeWatchpoint()); 2611 2612 RegExp* regExp = nullptr; 2613 if (node->op() == RegExpExec) { 2614 if (Node* regExpObjectNode = node->child2().node()) { 2615 if (RegExpObject* regExpObject = regExpObjectNode->dynamicCastConstant<RegExpObject*>(m_vm)) 2616 regExp = regExpObject->regExp(); 2617 else if (regExpObjectNode->op() == NewRegexp) 2618 regExp = regExpObjectNode->castOperand<RegExp*>(); 2619 } 2620 } else if (node->op() == RegExpExecNonGlobalOrSticky) 2621 regExp = node->castOperand<RegExp*>(); 2622 2610 2623 RegisteredStructureSet structureSet; 2611 structureSet.add(m_graph.registerStructure(globalObject->regExpMatchesArrayStructure())); 2624 // If regExp is unknown, we need to put both regExp MatchesArray structure variants in our set. 2625 if (!regExp || !regExp->hasIndices()) 2626 structureSet.add(m_graph.registerStructure(globalObject->regExpMatchesArrayStructure())); 2627 if (!regExp || regExp->hasIndices()) 2628 structureSet.add(m_graph.registerStructure(globalObject->regExpMatchesArrayWithIndicesStructure())); 2612 2629 setForNode(node, structureSet); 2613 2630 forNode(node).merge(SpecOther); -
trunk/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp
r271987 r273086 596 596 } 597 597 598 if ((m_node->op() == RegExpExec || m_node->op() == RegExpExecNonGlobalOrSticky) && regExp->hasNamedCaptures()) { 599 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=176464 600 // Implement strength reduction optimization for named capture groups. 601 if (verbose) 602 dataLog("Giving up because of named capture groups.\n"); 603 return false; 598 if ((m_node->op() == RegExpExec || m_node->op() == RegExpExecNonGlobalOrSticky)) { 599 if (regExp->hasNamedCaptures()) { 600 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=176464 601 // Implement strength reduction optimization for named capture groups. 602 if (verbose) 603 dataLog("Giving up because of named capture groups.\n"); 604 return false; 605 } 606 607 if (regExp->hasIndices()) { 608 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=220930 609 // Implement strength reduction optimization for RegExp with match indices. 610 if (verbose) 611 dataLog("Giving up because of match indices.\n"); 612 return false; 613 } 604 614 } 605 615 -
trunk/Source/JavaScriptCore/runtime/CommonIdentifiers.h
r269531 r273086 129 129 macro(groups) \ 130 130 macro(has) \ 131 macro(hasIndices) \ 131 132 macro(hasOwnProperty) \ 132 133 macro(hash) \ … … 139 140 macro(ignorePunctuation) \ 140 141 macro(index) \ 142 macro(indices) \ 141 143 macro(inferredName) \ 142 144 macro(input) \ -
trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
r272885 r273086 805 805 m_regExpStructure.set(vm, this, RegExpObject::createStructure(vm, this, m_regExpPrototype.get())); 806 806 m_regExpMatchesArrayStructure.set(vm, this, createRegExpMatchesArrayStructure(vm, this)); 807 m_regExpMatchesArrayWithIndicesStructure.set(vm, this, createRegExpMatchesArrayWithIndicesStructure(vm, this)); 808 m_regExpMatchesIndicesArrayStructure.set(vm, this, createRegExpMatchesIndicesArrayStructure(vm, this)); 807 809 808 810 m_moduleRecordStructure.initLater( … … 1749 1751 slowPutStructure = createRegExpMatchesArraySlowPutStructure(vm, this); 1750 1752 m_regExpMatchesArrayStructure.set(vm, this, slowPutStructure); 1753 slowPutStructure = createRegExpMatchesArrayWithIndicesSlowPutStructure(vm, this); 1754 m_regExpMatchesArrayWithIndicesStructure.set(vm, this, slowPutStructure); 1755 slowPutStructure = createRegExpMatchesIndicesArraySlowPutStructure(vm, this); 1756 m_regExpMatchesIndicesArrayStructure.set(vm, this, slowPutStructure); 1751 1757 slowPutStructure = ClonedArguments::createSlowPutStructure(vm, this, m_objectPrototype.get()); 1752 1758 m_clonedArgumentsStructure.set(vm, this, slowPutStructure); … … 2026 2032 thisObject->m_accessorPropertyDescriptorObjectStructure.visit(visitor); 2027 2033 visitor.append(thisObject->m_regExpMatchesArrayStructure); 2034 visitor.append(thisObject->m_regExpMatchesArrayWithIndicesStructure); 2035 visitor.append(thisObject->m_regExpMatchesIndicesArrayStructure); 2028 2036 thisObject->m_moduleRecordStructure.visit(visitor); 2029 2037 thisObject->m_moduleNamespaceObjectStructure.visit(visitor); -
trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h
r272885 r273086 418 418 LazyProperty<JSGlobalObject, Structure> m_accessorPropertyDescriptorObjectStructure; 419 419 WriteBarrier<Structure> m_regExpMatchesArrayStructure; 420 WriteBarrier<Structure> m_regExpMatchesArrayWithIndicesStructure; 421 WriteBarrier<Structure> m_regExpMatchesIndicesArrayStructure; 420 422 LazyProperty<JSGlobalObject, Structure> m_moduleRecordStructure; 421 423 LazyProperty<JSGlobalObject, Structure> m_moduleNamespaceObjectStructure; … … 827 829 Structure* accessorPropertyDescriptorObjectStructure() const { return m_accessorPropertyDescriptorObjectStructure.get(this); } 828 830 Structure* regExpMatchesArrayStructure() const { return m_regExpMatchesArrayStructure.get(); } 831 Structure* regExpMatchesArrayWithIndicesStructure() const { return m_regExpMatchesArrayWithIndicesStructure.get(); } 832 Structure* regExpMatchesIndicesArrayStructure() const { return m_regExpMatchesIndicesArrayStructure.get(); } 829 833 Structure* moduleRecordStructure() const { return m_moduleRecordStructure.get(this); } 830 834 Structure* moduleNamespaceObjectStructure() const { return m_moduleNamespaceObjectStructure.get(this); } -
trunk/Source/JavaScriptCore/runtime/RegExp.cpp
r263117 r273086 56 56 if (regExp->ignoreCase()) 57 57 fputc('i', m_file); 58 if (regExp->hasIndices()) 59 fputc('d', m_file); 58 60 if (regExp->multiline()) 59 61 fputc('m', m_file); … … 489 491 if (regExp->ignoreCase()) 490 492 postfix[index++] = 'i'; 493 if (regExp->hasIndices()) 494 postfix[index] = 'd'; 491 495 if (regExp->multiline()) 492 496 postfix[index] = 'm'; -
trunk/Source/JavaScriptCore/runtime/RegExp.h
r260415 r273086 65 65 bool unicode() const { return m_flags.contains(Yarr::Flags::Unicode); } 66 66 bool dotAll() const { return m_flags.contains(Yarr::Flags::DotAll); } 67 bool hasIndices() const { return m_flags.contains(Yarr::Flags::HasIndices); } 67 68 68 69 const String& pattern() const { return m_patternString; } -
trunk/Source/JavaScriptCore/runtime/RegExpMatchesArray.cpp
r252514 r273086 41 41 42 42 if (UNLIKELY(globalObject->isHavingABadTime())) { 43 array = JSArray::tryCreateUninitializedRestricted(scope, &deferralContext, globalObject->regExpMatchesArrayStructure(), regExp->numSubpatterns() + 1); 43 array = JSArray::tryCreateUninitializedRestricted(scope, &deferralContext, 44 regExp->hasIndices() ? globalObject->regExpMatchesArrayWithIndicesStructure() : globalObject->regExpMatchesArrayStructure(), regExp->numSubpatterns() + 1); 44 45 // FIXME: we should probably throw an out of memory error here, but 45 46 // when making this change we should check that all clients of this … … 55 56 } 56 57 } else { 57 array = tryCreateUninitializedRegExpMatchesArray(scope, &deferralContext, globalObject->regExpMatchesArrayStructure(), regExp->numSubpatterns() + 1); 58 array = tryCreateUninitializedRegExpMatchesArray(scope, &deferralContext, 59 regExp->hasIndices() ? globalObject->regExpMatchesArrayWithIndicesStructure() : globalObject->regExpMatchesArrayStructure(), regExp->numSubpatterns() + 1); 58 60 RELEASE_ASSERT(array); 59 61 … … 69 71 array->putDirectWithoutBarrier(RegExpMatchesArrayInputPropertyOffset, input); 70 72 array->putDirectWithoutBarrier(RegExpMatchesArrayGroupsPropertyOffset, jsUndefined()); 73 if (regExp->hasIndices()) 74 array->putDirectWithoutBarrier(RegExpMatchesArrayIndicesPropertyOffset, jsUndefined()); 71 75 return array; 72 76 } … … 85 89 } 86 90 91 static Structure* createStructureWithIndicesImpl(VM& vm, JSGlobalObject* globalObject, IndexingType indexingType) 92 { 93 Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType); 94 PropertyOffset offset; 95 structure = Structure::addPropertyTransition(vm, structure, vm.propertyNames->index, 0, offset); 96 ASSERT(offset == RegExpMatchesArrayIndexPropertyOffset); 97 structure = Structure::addPropertyTransition(vm, structure, vm.propertyNames->input, 0, offset); 98 ASSERT(offset == RegExpMatchesArrayInputPropertyOffset); 99 structure = Structure::addPropertyTransition(vm, structure, vm.propertyNames->groups, 0, offset); 100 ASSERT(offset == RegExpMatchesArrayGroupsPropertyOffset); 101 structure = Structure::addPropertyTransition(vm, structure, vm.propertyNames->indices, 0, offset); 102 ASSERT(offset == RegExpMatchesArrayIndicesPropertyOffset); 103 return structure; 104 } 105 106 static Structure* createIndicesStructureImpl(VM& vm, JSGlobalObject* globalObject, IndexingType indexingType) 107 { 108 Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType); 109 PropertyOffset offset; 110 structure = Structure::addPropertyTransition(vm, structure, vm.propertyNames->groups, 0, offset); 111 ASSERT(offset == RegExpMatchesIndicesGroupsPropertyOffset); 112 return structure; 113 } 114 87 115 Structure* createRegExpMatchesArrayStructure(VM& vm, JSGlobalObject* globalObject) 88 116 { 89 117 return createStructureImpl(vm, globalObject, ArrayWithContiguous); 118 } 119 120 Structure* createRegExpMatchesArrayWithIndicesStructure(VM& vm, JSGlobalObject* globalObject) 121 { 122 return createStructureWithIndicesImpl(vm, globalObject, ArrayWithContiguous); 123 } 124 125 Structure* createRegExpMatchesIndicesArrayStructure(VM& vm, JSGlobalObject* globalObject) 126 { 127 return createIndicesStructureImpl(vm, globalObject, ArrayWithContiguous); 90 128 } 91 129 … … 95 133 } 96 134 135 Structure* createRegExpMatchesArrayWithIndicesSlowPutStructure(VM& vm, JSGlobalObject* globalObject) 136 { 137 return createStructureWithIndicesImpl(vm, globalObject, ArrayWithSlowPutArrayStorage); 138 } 139 140 Structure* createRegExpMatchesIndicesArraySlowPutStructure(VM& vm, JSGlobalObject* globalObject) 141 { 142 return createIndicesStructureImpl(vm, globalObject, ArrayWithSlowPutArrayStorage); 143 } 144 97 145 } // namespace JSC -
trunk/Source/JavaScriptCore/runtime/RegExpMatchesArray.h
r264688 r273086 34 34 static const PropertyOffset RegExpMatchesArrayInputPropertyOffset = 101; 35 35 static const PropertyOffset RegExpMatchesArrayGroupsPropertyOffset = 102; 36 static const PropertyOffset RegExpMatchesArrayIndicesPropertyOffset = 103; 37 static const PropertyOffset RegExpMatchesIndicesGroupsPropertyOffset = 100; 36 38 37 39 ALWAYS_INLINE JSArray* tryCreateUninitializedRegExpMatchesArray(ObjectInitializationScope& scope, GCDeferralContext* deferralContext, Structure* structure, unsigned initialLength) … … 77 79 78 80 JSArray* array; 81 JSArray* indicesArray = nullptr; 79 82 80 83 // FIXME: This should handle array allocation errors gracefully. … … 83 86 unsigned numSubpatterns = regExp->numSubpatterns(); 84 87 bool hasNamedCaptures = regExp->hasNamedCaptures(); 88 bool createIndices = regExp->hasIndices(); 85 89 JSObject* groups = hasNamedCaptures ? constructEmptyObject(vm, globalObject->nullPrototypeObjectStructure()) : nullptr; 86 Structure* matchStructure = globalObject->regExpMatchesArrayStructure(); 90 Structure* matchStructure = createIndices ? globalObject->regExpMatchesArrayWithIndicesStructure() : globalObject->regExpMatchesArrayStructure(); 91 92 JSObject* indicesGroups = createIndices && hasNamedCaptures ? constructEmptyObject(vm, globalObject->nullPrototypeObjectStructure()) : nullptr; 87 93 88 94 auto setProperties = [&] () { … … 95 101 auto size = matchStructure->outOfLineSize(); 96 102 gcSafeZeroMemory(static_cast<JSValue*>(array->butterfly()->base(0, capacity)), (capacity - size) * sizeof(JSValue)); 103 104 if (createIndices) { 105 array->putDirect(vm, RegExpMatchesArrayIndicesPropertyOffset, indicesArray); 106 107 Structure* indicesStructure = globalObject->regExpMatchesIndicesArrayStructure(); 108 109 indicesArray->putDirect(vm, RegExpMatchesIndicesGroupsPropertyOffset, indicesGroups); 110 111 ASSERT(!indicesArray->butterfly()->indexingHeader()->preCapacity(indicesStructure)); 112 auto indicesCapacity = indicesStructure->outOfLineCapacity(); 113 auto indicesSize = indicesStructure->outOfLineSize(); 114 gcSafeZeroMemory(static_cast<JSValue*>(indicesArray->butterfly()->base(0, indicesCapacity)), (indicesCapacity - indicesSize) * sizeof(JSValue)); 115 } 116 }; 117 118 auto createIndexArray = [&] (GCDeferralContext& deferralContext, int start, int end) { 119 ObjectInitializationScope scope(vm); 120 121 JSArray* result = JSArray::tryCreateUninitializedRestricted(scope, &deferralContext, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous), 2); 122 result->initializeIndexWithoutBarrier(scope, 0, jsNumber(start)); 123 result->initializeIndexWithoutBarrier(scope, 1, jsNumber(end)); 124 125 return result; 97 126 }; 98 127 99 128 if (UNLIKELY(globalObject->isHavingABadTime())) { 100 129 GCDeferralContext deferralContext(vm.heap); 101 ObjectInitializationScope scope(vm); 102 array = JSArray::tryCreateUninitializedRestricted(scope, &deferralContext, matchStructure, numSubpatterns + 1); 130 ObjectInitializationScope matchesArrayScope(vm); 131 ObjectInitializationScope indicesArrayScope(vm); 132 array = JSArray::tryCreateUninitializedRestricted(matchesArrayScope, &deferralContext, matchStructure, numSubpatterns + 1); 133 134 if (createIndices) 135 indicesArray = JSArray::tryCreateUninitializedRestricted(indicesArrayScope, &deferralContext, globalObject->regExpMatchesIndicesArrayStructure(), numSubpatterns + 1); 103 136 104 137 // FIXME: we should probably throw an out of memory error here, but … … 110 143 setProperties(); 111 144 112 array->initializeIndexWithoutBarrier( scope, 0, jsSubstringOfResolved(vm, &deferralContext, input, result.start, result.end - result.start));113 145 array->initializeIndexWithoutBarrier(matchesArrayScope, 0, jsSubstringOfResolved(vm, &deferralContext, input, result.start, result.end - result.start)); 146 114 147 for (unsigned i = 1; i <= numSubpatterns; ++i) { 115 148 int start = subpatternResults[2 * i]; … … 119 152 else 120 153 value = jsUndefined(); 121 array->initializeIndexWithoutBarrier(scope, i, value); 154 array->initializeIndexWithoutBarrier(matchesArrayScope, i, value); 155 } 156 157 if (createIndices) { 158 for (unsigned i = 0; i <= numSubpatterns; ++i) { 159 int start = subpatternResults[2 * i]; 160 JSValue value; 161 if (start >= 0) 162 indicesArray->initializeIndexWithoutBarrier(indicesArrayScope, i, createIndexArray(deferralContext, start, subpatternResults[2 * i + 1])); 163 else 164 indicesArray->initializeIndexWithoutBarrier(indicesArrayScope, i, jsUndefined()); 165 } 122 166 } 123 167 } else { 124 168 GCDeferralContext deferralContext(vm.heap); 125 ObjectInitializationScope scope(vm); 126 array = tryCreateUninitializedRegExpMatchesArray(scope, &deferralContext, matchStructure, numSubpatterns + 1); 169 ObjectInitializationScope matchesArrayScope(vm); 170 ObjectInitializationScope indicesArrayScope(vm); 171 array = tryCreateUninitializedRegExpMatchesArray(matchesArrayScope, &deferralContext, matchStructure, numSubpatterns + 1); 172 173 if (createIndices) 174 indicesArray = tryCreateUninitializedRegExpMatchesArray(indicesArrayScope, &deferralContext, globalObject->regExpMatchesIndicesArrayStructure(), numSubpatterns + 1); 127 175 128 176 // FIXME: we should probably throw an out of memory error here, but … … 134 182 setProperties(); 135 183 136 array->initializeIndexWithoutBarrier( scope, 0, jsSubstringOfResolved(vm, &deferralContext, input, result.start, result.end - result.start), ArrayWithContiguous);184 array->initializeIndexWithoutBarrier(matchesArrayScope, 0, jsSubstringOfResolved(vm, &deferralContext, input, result.start, result.end - result.start), ArrayWithContiguous); 137 185 138 186 for (unsigned i = 1; i <= numSubpatterns; ++i) { … … 143 191 else 144 192 value = jsUndefined(); 145 array->initializeIndexWithoutBarrier(scope, i, value, ArrayWithContiguous); 193 array->initializeIndexWithoutBarrier(matchesArrayScope, i, value, ArrayWithContiguous); 194 } 195 196 if (createIndices) { 197 for (unsigned i = 0; i <= numSubpatterns; ++i) { 198 int start = subpatternResults[2 * i]; 199 JSValue value; 200 if (start >= 0) 201 indicesArray->initializeIndexWithoutBarrier(indicesArrayScope, i, createIndexArray(deferralContext, start, subpatternResults[2 * i + 1])); 202 else 203 indicesArray->initializeIndexWithoutBarrier(indicesArrayScope, i, jsUndefined()); 204 } 146 205 } 147 206 } … … 149 208 // Now the object is safe to scan by GC. 150 209 151 // We initialize the groups object late as itcould allocate, which with the current API could cause210 // We initialize the groups and indices objects late as they could allocate, which with the current API could cause 152 211 // allocations. 153 212 if (hasNamedCaptures) { 154 213 for (unsigned i = 1; i <= numSubpatterns; ++i) { 155 214 String groupName = regExp->getCaptureGroupName(i); 156 if (!groupName.isEmpty()) 215 if (!groupName.isEmpty()) { 157 216 groups->putDirect(vm, Identifier::fromString(vm, groupName), array->getIndexQuickly(i)); 217 if (createIndices) 218 indicesGroups->putDirect(vm, Identifier::fromString(vm, groupName), indicesArray->getIndexQuickly(i)); 219 } 158 220 } 159 221 } 222 160 223 return array; 161 224 } … … 174 237 JSArray* createEmptyRegExpMatchesArray(JSGlobalObject*, JSString*, RegExp*); 175 238 Structure* createRegExpMatchesArrayStructure(VM&, JSGlobalObject*); 239 Structure* createRegExpMatchesArrayWithIndicesStructure(VM&, JSGlobalObject*); 240 Structure* createRegExpMatchesIndicesArrayStructure(VM&, JSGlobalObject*); 176 241 Structure* createRegExpMatchesArraySlowPutStructure(VM&, JSGlobalObject*); 242 Structure* createRegExpMatchesArrayWithIndicesSlowPutStructure(VM&, JSGlobalObject*); 243 Structure* createRegExpMatchesIndicesArraySlowPutStructure(VM&, JSGlobalObject*); 177 244 178 245 } // namespace JSC -
trunk/Source/JavaScriptCore/runtime/RegExpPrototype.cpp
r267594 r273086 41 41 static JSC_DECLARE_HOST_FUNCTION(regExpProtoFuncToString); 42 42 static JSC_DECLARE_HOST_FUNCTION(regExpProtoGetterGlobal); 43 static JSC_DECLARE_HOST_FUNCTION(regExpProtoGetterHasIndices); 43 44 static JSC_DECLARE_HOST_FUNCTION(regExpProtoGetterIgnoreCase); 44 45 static JSC_DECLARE_HOST_FUNCTION(regExpProtoGetterMultiline); … … 65 66 JSC_NATIVE_GETTER_WITHOUT_TRANSITION(vm.propertyNames->global, regExpProtoGetterGlobal, PropertyAttribute::DontEnum | PropertyAttribute::Accessor); 66 67 JSC_NATIVE_GETTER_WITHOUT_TRANSITION(vm.propertyNames->dotAll, regExpProtoGetterDotAll, PropertyAttribute::DontEnum | PropertyAttribute::Accessor); 68 JSC_NATIVE_GETTER_WITHOUT_TRANSITION(vm.propertyNames->hasIndices, regExpProtoGetterHasIndices, PropertyAttribute::DontEnum | PropertyAttribute::Accessor); 67 69 JSC_NATIVE_GETTER_WITHOUT_TRANSITION(vm.propertyNames->ignoreCase, regExpProtoGetterIgnoreCase, PropertyAttribute::DontEnum | PropertyAttribute::Accessor); 68 70 JSC_NATIVE_GETTER_WITHOUT_TRANSITION(vm.propertyNames->multiline, regExpProtoGetterMultiline, PropertyAttribute::DontEnum | PropertyAttribute::Accessor); … … 171 173 auto scope = DECLARE_THROW_SCOPE(vm); 172 174 175 JSValue indicesValue = regexp->get(globalObject, vm.propertyNames->hasIndices); 176 RETURN_IF_EXCEPTION(scope, string); 173 177 JSValue globalValue = regexp->get(globalObject, vm.propertyNames->global); 174 178 RETURN_IF_EXCEPTION(scope, string); … … 185 189 186 190 unsigned index = 0; 191 if (indicesValue.toBoolean(globalObject)) 192 string[index++] = 'd'; 187 193 if (globalValue.toBoolean(globalObject)) 188 194 string[index++] = 'g'; … … 246 252 247 253 return JSValue::encode(jsBoolean(regexp->regExp()->global())); 254 } 255 256 JSC_DEFINE_HOST_FUNCTION(regExpProtoGetterHasIndices, (JSGlobalObject* globalObject, CallFrame* callFrame)) 257 { 258 VM& vm = globalObject->vm(); 259 auto scope = DECLARE_THROW_SCOPE(vm); 260 261 JSValue thisValue = callFrame->thisValue(); 262 auto* regexp = jsDynamicCast<RegExpObject*>(vm, thisValue); 263 if (UNLIKELY(!regexp)) { 264 if (thisValue == globalObject->regExpPrototype()) 265 return JSValue::encode(jsUndefined()); 266 return throwVMTypeError(globalObject, scope, "The RegExp.prototype.hasIndices getter can only be called on a RegExp object"_s); 267 } 268 269 return JSValue::encode(jsBoolean(regexp->regExp()->hasIndices())); 248 270 } 249 271 -
trunk/Source/JavaScriptCore/yarr/YarrFlags.cpp
r242776 r273086 38 38 for (auto character : string.codeUnits()) { 39 39 switch (character) { 40 case 'd': 41 if (flags.contains(Flags::HasIndices)) 42 return WTF::nullopt; 43 flags.add(Flags::HasIndices); 44 break; 45 40 46 case 'g': 41 47 if (flags.contains(Flags::Global)) -
trunk/Source/JavaScriptCore/yarr/YarrFlags.h
r242776 r273086 37 37 Unicode = 1 << 4, 38 38 DotAll = 1 << 5, 39 DeletedValue = 1 << 6 39 HasIndices = 1 << 6, 40 DeletedValue = 1 << 7 40 41 }; 41 42 -
trunk/Source/JavaScriptCore/yarr/YarrInterpreter.h
r246408 r273086 372 372 bool ignoreCase() const { return m_flags.contains(Flags::IgnoreCase); } 373 373 bool multiline() const { return m_flags.contains(Flags::Multiline); } 374 bool hasIndices() const { return m_flags.contains(Flags::HasIndices); } 374 375 bool sticky() const { return m_flags.contains(Flags::Sticky); } 375 376 bool unicode() const { return m_flags.contains(Flags::Unicode); } -
trunk/Source/JavaScriptCore/yarr/YarrPattern.h
r261464 r273086 525 525 bool ignoreCase() const { return m_flags.contains(Flags::IgnoreCase); } 526 526 bool multiline() const { return m_flags.contains(Flags::Multiline); } 527 bool hasIndices() const { return m_flags.contains(Flags::HasIndices); } 527 528 bool sticky() const { return m_flags.contains(Flags::Sticky); } 528 529 bool unicode() const { return m_flags.contains(Flags::Unicode); }
Note: See TracChangeset
for help on using the changeset viewer.