Changeset 175365 in webkit
- Timestamp:
- Oct 29, 2014, 8:54:23 PM (12 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 11 edited
-
ChangeLog (modified) (1 diff)
-
jit/Repatch.cpp (modified) (2 diffs)
-
runtime/JSArray.h (modified) (1 diff)
-
runtime/JSGlobalObject.cpp (modified) (1 diff)
-
runtime/RegExpCachedResult.cpp (modified) (1 diff)
-
runtime/RegExpCachedResult.h (modified) (4 diffs)
-
runtime/RegExpConstructor.cpp (modified) (3 diffs)
-
runtime/RegExpMatchesArray.cpp (modified) (2 diffs)
-
runtime/RegExpMatchesArray.h (modified) (1 diff)
-
runtime/RegExpObject.cpp (modified) (1 diff)
-
runtime/StringPrototype.cpp (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r175362 r175365 1 2014-10-29 Andreas Kling <akling@apple.com> 2 3 Use plain JSArray for RegExp matches instead of a lazily populated custom object. 4 <https://webkit.org/b/138191> 5 6 Reviewed by Geoffrey Garen. 7 8 We're already offering two RegExp matching APIs, one that collects subpattern 9 matches (exec), and one that simply tests for a match (test). 10 Given that, it was pretty overkill to lazily populate the resulting array of 11 matches, since the user could simply use test() if they didn't need them. 12 13 This allows the JIT to generate better code for RegExp match arrays, and also 14 enables some fast paths in the JSC runtime that check if an object isJSArray(). 15 16 Looks like ~1.5% improvement on Octane/regexp according to run-jsc-benchmarks. 17 18 * jit/Repatch.cpp: 19 (JSC::tryCacheGetByID): 20 * runtime/JSArray.h: 21 (JSC::createArrayButterflyWithExactLength): Deleted. 22 * runtime/JSGlobalObject.cpp: 23 (JSC::JSGlobalObject::init): 24 * runtime/RegExpCachedResult.cpp: 25 (JSC::RegExpCachedResult::visitChildren): 26 (JSC::RegExpCachedResult::lastResult): 27 (JSC::RegExpCachedResult::leftContext): 28 (JSC::RegExpCachedResult::rightContext): 29 * runtime/RegExpCachedResult.h: 30 (JSC::RegExpCachedResult::RegExpCachedResult): 31 (JSC::RegExpCachedResult::record): 32 (JSC::RegExpCachedResult::input): 33 * runtime/RegExpConstructor.cpp: 34 (JSC::RegExpConstructor::getBackref): 35 (JSC::RegExpConstructor::getLastParen): 36 (JSC::RegExpConstructor::getLeftContext): 37 (JSC::RegExpConstructor::getRightContext): 38 * runtime/RegExpMatchesArray.cpp: 39 (JSC::createRegExpMatchesArray): 40 (JSC::RegExpMatchesArray::RegExpMatchesArray): Deleted. 41 (JSC::RegExpMatchesArray::create): Deleted. 42 (JSC::RegExpMatchesArray::finishCreation): Deleted. 43 (JSC::RegExpMatchesArray::visitChildren): Deleted. 44 (JSC::RegExpMatchesArray::reifyAllProperties): Deleted. 45 (JSC::RegExpMatchesArray::reifyMatchProperty): Deleted. 46 (JSC::RegExpMatchesArray::leftContext): Deleted. 47 (JSC::RegExpMatchesArray::rightContext): Deleted. 48 * runtime/RegExpMatchesArray.h: 49 (JSC::RegExpMatchesArray::createStructure): Deleted. 50 (JSC::RegExpMatchesArray::reifyAllPropertiesIfNecessary): Deleted. 51 (JSC::RegExpMatchesArray::reifyMatchPropertyIfNecessary): Deleted. 52 (JSC::RegExpMatchesArray::getOwnPropertySlot): Deleted. 53 (JSC::RegExpMatchesArray::getOwnPropertySlotByIndex): Deleted. 54 (JSC::RegExpMatchesArray::put): Deleted. 55 (JSC::RegExpMatchesArray::putByIndex): Deleted. 56 (JSC::RegExpMatchesArray::deleteProperty): Deleted. 57 (JSC::RegExpMatchesArray::deletePropertyByIndex): Deleted. 58 (JSC::RegExpMatchesArray::getOwnPropertyNames): Deleted. 59 (JSC::RegExpMatchesArray::defineOwnProperty): Deleted. 60 (JSC::isRegExpMatchesArray): Deleted. 61 * runtime/RegExpObject.cpp: 62 (JSC::RegExpObject::exec): 63 * runtime/StringPrototype.cpp: 64 (JSC::stringProtoFuncMatch): 65 1 66 2014-10-29 Joseph Pecoraro <pecoraro@apple.com> 2 67 -
trunk/Source/JavaScriptCore/jit/Repatch.cpp
r172176 r175365 639 639 VM* vm = &exec->vm(); 640 640 641 if ((isJSArray(baseValue) || is RegExpMatchesArray(baseValue) || isJSString(baseValue)) && propertyName == exec->propertyNames().length) {641 if ((isJSArray(baseValue) || isJSString(baseValue)) && propertyName == exec->propertyNames().length) { 642 642 GPRReg baseGPR = static_cast<GPRReg>(stubInfo.patch.baseGPR); 643 643 #if USE(JSVALUE32_64) … … 648 648 MacroAssembler stubJit; 649 649 650 if (isJSArray(baseValue) || isRegExpMatchesArray(baseValue)) {650 if (isJSArray(baseValue)) { 651 651 GPRReg scratchGPR = TempRegisterSet(stubInfo.patch.usedRegisters).getFreeGPR(); 652 652 bool needToRestoreScratch = false; -
trunk/Source/JavaScriptCore/runtime/JSArray.h
r172618 r175365 189 189 vm, intendedOwner, 0, 0, true, header, vectorLength * sizeof(EncodedJSValue)); 190 190 return result; 191 }192 193 inline Butterfly* createArrayButterflyWithExactLength(VM& vm, JSCell* intendedOwner, unsigned initialLength)194 {195 Butterfly* butterfly = Butterfly::create(196 vm, intendedOwner, 0, 0, true, indexingHeaderForArray(initialLength, initialLength),197 ArrayStorage::sizeFor(initialLength));198 ArrayStorage* storage = butterfly->arrayStorage();199 storage->m_indexBias = 0;200 storage->m_sparseMap.clear();201 storage->m_numValuesInVector = 0;202 return butterfly;203 191 } 204 192 -
trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
r173706 r175365 289 289 for (unsigned i = 0; i < NumberOfIndexingShapes; ++i) 290 290 m_arrayStructureForIndexingShapeDuringAllocation[i] = m_originalArrayStructureForIndexingShape[i]; 291 292 m_regExpMatchesArrayStructure.set(vm, this, RegExpMatchesArray::createStructure(vm, this, m_arrayPrototype.get()));291 292 m_regExpMatchesArrayStructure.set(vm, this, Structure::create(vm, this, m_arrayPrototype.get(), TypeInfo(ObjectType, StructureFlags), JSArray::info(), ArrayWithSlowPutArrayStorage)); 293 293 294 294 RegExp* emptyRegex = RegExp::create(vm, "", NoFlags); -
trunk/Source/JavaScriptCore/runtime/RegExpCachedResult.cpp
r163844 r175365 38 38 visitor.append(&m_reifiedInput); 39 39 visitor.append(&m_reifiedResult); 40 visitor.append(&m_reifiedLeftContext); 41 visitor.append(&m_reifiedRightContext); 40 42 } 41 43 42 RegExpMatchesArray* RegExpCachedResult::lastResult(ExecState* exec, JSObject* owner)44 JSArray* RegExpCachedResult::lastResult(ExecState* exec, JSObject* owner) 43 45 { 44 if ( m_result) {46 if (!m_reified) { 45 47 m_reifiedInput.set(exec->vm(), owner, m_lastInput.get()); 46 m_reifiedResult.set(exec->vm(), owner, RegExpMatchesArray::create(exec, m_lastInput.get(), m_lastRegExp.get(), m_result));47 m_re sult = MatchResult::failed();48 m_reifiedResult.set(exec->vm(), owner, createRegExpMatchesArray(exec, m_lastInput.get(), m_lastRegExp.get(), m_result)); 49 m_reified = true; 48 50 } 49 51 return m_reifiedResult.get(); 52 } 53 54 JSString* RegExpCachedResult::leftContext(ExecState* exec, JSObject* owner) 55 { 56 // Make sure we're reified. 57 lastResult(exec, owner); 58 if (!m_reifiedLeftContext) 59 m_reifiedLeftContext.set(exec->vm(), owner, m_result.start ? jsSubstring(exec, m_reifiedInput.get(), 0, m_result.start) : jsEmptyString(exec)); 60 return m_reifiedLeftContext.get(); 61 } 62 63 JSString* RegExpCachedResult::rightContext(ExecState* exec, JSObject* owner) 64 { 65 // Make sure we're reified. 66 lastResult(exec, owner); 67 if (!m_reifiedRightContext) { 68 unsigned length = m_reifiedInput->length(); 69 m_reifiedRightContext.set(exec->vm(), owner, m_result.end != length ? jsSubstring(exec, m_reifiedInput.get(), m_result.end, length - m_result.end) : jsEmptyString(exec)); 70 } 71 return m_reifiedRightContext.get(); 50 72 } 51 73 -
trunk/Source/JavaScriptCore/runtime/RegExpCachedResult.h
r173269 r175365 31 31 namespace JSC { 32 32 33 class JSArray; 33 34 class JSString; 34 class RegExpMatchesArray;35 35 36 36 // RegExpCachedResult is used to track the cached results of the last … … 47 47 RegExpCachedResult(VM& vm, JSObject* owner, RegExp* emptyRegExp) 48 48 : m_result(0, 0) 49 , m_reified(false) 49 50 { 50 51 m_lastInput.set(vm, owner, jsEmptyString(&vm)); … … 56 57 m_lastRegExp.set(vm, owner, regExp); 57 58 m_lastInput.set(vm, owner, input); 59 m_reifiedLeftContext.clear(); 60 m_reifiedRightContext.clear(); 58 61 m_result = result; 62 m_reified = false; 59 63 } 60 64 61 RegExpMatchesArray* lastResult(ExecState*, JSObject* owner);65 JSArray* lastResult(ExecState*, JSObject* owner); 62 66 void setInput(ExecState*, JSObject* owner, JSString*); 67 68 JSString* leftContext(ExecState*, JSObject* owner); 69 JSString* rightContext(ExecState*, JSObject* owner); 63 70 64 71 JSString* input() 65 72 { 66 // If m_result showas a match then we're in a lazy state, so m_lastInput 67 // is the most recent value of the input property. If not then we have 68 // reified, in which case m_reifiedInput will contain the correct value. 69 return m_result ? m_lastInput.get() : m_reifiedInput.get(); 73 return m_reified ? m_reifiedInput.get() : m_lastInput.get(); 70 74 } 71 75 … … 74 78 private: 75 79 MatchResult m_result; 80 bool m_reified; 76 81 WriteBarrier<JSString> m_lastInput; 77 82 WriteBarrier<RegExp> m_lastRegExp; 78 WriteBarrier< RegExpMatchesArray> m_reifiedResult;83 WriteBarrier<JSArray> m_reifiedResult; 79 84 WriteBarrier<JSString> m_reifiedInput; 85 WriteBarrier<JSString> m_reifiedLeftContext; 86 WriteBarrier<JSString> m_reifiedRightContext; 80 87 }; 81 88 -
trunk/Source/JavaScriptCore/runtime/RegExpConstructor.cpp
r171939 r175365 117 117 JSValue RegExpConstructor::getBackref(ExecState* exec, unsigned i) 118 118 { 119 RegExpMatchesArray* array = m_cachedResult.lastResult(exec, this);119 JSArray* array = m_cachedResult.lastResult(exec, this); 120 120 121 121 if (i < array->length()) { … … 130 130 JSValue RegExpConstructor::getLastParen(ExecState* exec) 131 131 { 132 RegExpMatchesArray* array = m_cachedResult.lastResult(exec, this);132 JSArray* array = m_cachedResult.lastResult(exec, this); 133 133 unsigned length = array->length(); 134 134 if (length > 1) { … … 143 143 JSValue RegExpConstructor::getLeftContext(ExecState* exec) 144 144 { 145 return m_cachedResult.l astResult(exec, this)->leftContext(exec);145 return m_cachedResult.leftContext(exec, this); 146 146 } 147 147 148 148 JSValue RegExpConstructor::getRightContext(ExecState* exec) 149 149 { 150 return m_cachedResult. lastResult(exec, this)->rightContext(exec);150 return m_cachedResult.rightContext(exec, this); 151 151 } 152 152 -
trunk/Source/JavaScriptCore/runtime/RegExpMatchesArray.cpp
r172618 r175365 1 1 /* 2 * Copyright (C) 2012 Apple Inc. All rights reserved.2 * Copyright (C) 2012-2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 32 32 namespace JSC { 33 33 34 const ClassInfo RegExpMatchesArray::s_info = {"Array", &JSArray::s_info, 0, CREATE_METHOD_TABLE(RegExpMatchesArray)}; 35 36 RegExpMatchesArray::RegExpMatchesArray(VM& vm, Butterfly* butterfly, JSGlobalObject* globalObject, JSString* input, RegExp* regExp, MatchResult result) 37 : JSArray(vm, globalObject->regExpMatchesArrayStructure(), butterfly) 38 , m_result(result) 39 , m_state(ReifiedNone) 40 { 41 m_input.set(vm, this, input); 42 m_regExp.set(vm, this, regExp); 43 } 44 45 RegExpMatchesArray* RegExpMatchesArray::create(ExecState* exec, JSString* input, RegExp* regExp, MatchResult result) 34 JSArray* createRegExpMatchesArray(ExecState* exec, JSString* input, RegExp* regExp, MatchResult result) 46 35 { 47 36 ASSERT(result); 48 37 VM& vm = exec->vm(); 49 Butterfly* butterfly = createArrayButterflyWithExactLength(vm, 0, regExp->numSubpatterns() + 1); 50 RegExpMatchesArray* array = new (NotNull, allocateCell<RegExpMatchesArray>(vm.heap)) RegExpMatchesArray(vm, butterfly, exec->lexicalGlobalObject(), input, regExp, result); 51 array->finishCreation(vm); 52 return array; 53 } 38 JSArray* array = JSArray::tryCreateUninitialized(vm, exec->lexicalGlobalObject()->regExpMatchesArrayStructure(), regExp->numSubpatterns() + 1); 39 RELEASE_ASSERT(array); 54 40 55 void RegExpMatchesArray::finishCreation(VM& vm) 56 { 57 Base::finishCreation(vm); 58 } 41 SamplingRegion samplingRegion("Reifying substring properties"); 59 42 60 void RegExpMatchesArray::visitChildren(JSCell* cell, SlotVisitor& visitor) 61 { 62 RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell); 63 ASSERT_GC_OBJECT_INHERITS(thisObject, info()); 64 Base::visitChildren(thisObject, visitor); 65 visitor.append(&thisObject->m_input); 66 visitor.append(&thisObject->m_regExp); 67 } 43 array->putDirectIndex(exec, 0, jsSubstring(exec, input, result.start, result.end - result.start)); 68 44 69 void RegExpMatchesArray::reifyAllProperties(ExecState* exec) 70 { 71 ASSERT(m_state != ReifiedAll); 72 ASSERT(m_result); 73 74 SamplingRegion samplingRegion("Reifying substring properties"); 75 76 reifyMatchPropertyIfNecessary(exec); 77 78 if (unsigned numSubpatterns = m_regExp->numSubpatterns()) { 45 if (unsigned numSubpatterns = regExp->numSubpatterns()) { 79 46 Vector<int, 32> subpatternResults; 80 int position = m_regExp->match(exec->vm(), m_input->value(exec), m_result.start, subpatternResults);81 ASSERT_UNUSED(position, position >= 0 && static_cast<size_t>(position) == m_result.start);82 ASSERT( m_result.start == static_cast<size_t>(subpatternResults[0]));83 ASSERT( m_result.end == static_cast<size_t>(subpatternResults[1]));47 int position = regExp->match(exec->vm(), input->value(exec), result.start, subpatternResults); 48 ASSERT_UNUSED(position, position >= 0 && static_cast<size_t>(position) == result.start); 49 ASSERT(result.start == static_cast<size_t>(subpatternResults[0])); 50 ASSERT(result.end == static_cast<size_t>(subpatternResults[1])); 84 51 85 52 for (unsigned i = 1; i <= numSubpatterns; ++i) { 86 53 int start = subpatternResults[2 * i]; 87 54 if (start >= 0) 88 putDirectIndex(exec, i, jsSubstring(exec, m_input.get(), start, subpatternResults[2 * i + 1] - start));55 array->putDirectIndex(exec, i, jsSubstring(exec, input, start, subpatternResults[2 * i + 1] - start)); 89 56 else 90 putDirectIndex(exec, i, jsUndefined());57 array->putDirectIndex(exec, i, jsUndefined()); 91 58 } 92 59 } 93 60 94 putDirect(exec->vm(), exec->propertyNames().index, jsNumber(m_result.start));95 putDirect(exec->vm(), exec->propertyNames().input, m_input.get());61 array->putDirect(exec->vm(), exec->propertyNames().index, jsNumber(result.start)); 62 array->putDirect(exec->vm(), exec->propertyNames().input, input); 96 63 97 m_state = ReifiedAll; 98 } 99 100 void RegExpMatchesArray::reifyMatchProperty(ExecState* exec) 101 { 102 ASSERT(m_state == ReifiedNone); 103 ASSERT(m_result); 104 putDirectIndex(exec, 0, jsSubstring(exec, m_input.get(), m_result.start, m_result.end - m_result.start)); 105 m_state = ReifiedMatch; 106 } 107 108 JSString* RegExpMatchesArray::leftContext(ExecState* exec) 109 { 110 if (!m_result.start) 111 return jsEmptyString(exec); 112 return jsSubstring(exec, m_input.get(), 0, m_result.start); 113 } 114 115 JSString* RegExpMatchesArray::rightContext(ExecState* exec) 116 { 117 unsigned length = m_input->length(); 118 if (m_result.end == length) 119 return jsEmptyString(exec); 120 return jsSubstring(exec, m_input.get(), m_result.end, length - m_result.end); 64 return array; 121 65 } 122 66 -
trunk/Source/JavaScriptCore/runtime/RegExpMatchesArray.h
r173269 r175365 27 27 namespace JSC { 28 28 29 class RegExpMatchesArray : public JSArray { 30 private: 31 RegExpMatchesArray(VM&, Butterfly*, JSGlobalObject*, JSString*, RegExp*, MatchResult); 32 33 enum ReifiedState { ReifiedNone, ReifiedMatch, ReifiedAll }; 34 35 public: 36 typedef JSArray Base; 37 38 static RegExpMatchesArray* create(ExecState*, JSString*, RegExp*, MatchResult); 39 40 JSString* leftContext(ExecState*); 41 JSString* rightContext(ExecState*); 42 43 DECLARE_INFO; 44 45 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) 46 { 47 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info(), ArrayWithSlowPutArrayStorage); 48 } 49 50 static void visitChildren(JSCell*, SlotVisitor&); 51 52 protected: 53 void finishCreation(VM&); 54 55 static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | Base::StructureFlags; 56 57 private: 58 ALWAYS_INLINE void reifyAllPropertiesIfNecessary(ExecState* exec) 59 { 60 if (m_state != ReifiedAll) 61 reifyAllProperties(exec); 62 } 63 64 ALWAYS_INLINE void reifyMatchPropertyIfNecessary(ExecState* exec) 65 { 66 if (m_state == ReifiedNone) 67 reifyMatchProperty(exec); 68 } 69 70 static bool getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot) 71 { 72 RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(object); 73 thisObject->reifyAllPropertiesIfNecessary(exec); 74 return JSArray::getOwnPropertySlot(thisObject, exec, propertyName, slot); 75 } 76 77 static bool getOwnPropertySlotByIndex(JSObject* object, ExecState* exec, unsigned propertyName, PropertySlot& slot) 78 { 79 RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(object); 80 if (propertyName) 81 thisObject->reifyAllPropertiesIfNecessary(exec); 82 else 83 thisObject->reifyMatchPropertyIfNecessary(exec); 84 return JSArray::getOwnPropertySlotByIndex(thisObject, exec, propertyName, slot); 85 } 86 87 static void put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue v, PutPropertySlot& slot) 88 { 89 RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell); 90 thisObject->reifyAllPropertiesIfNecessary(exec); 91 JSArray::put(thisObject, exec, propertyName, v, slot); 92 } 93 94 static void putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, JSValue v, bool shouldThrow) 95 { 96 RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell); 97 thisObject->reifyAllPropertiesIfNecessary(exec); 98 JSArray::putByIndex(thisObject, exec, propertyName, v, shouldThrow); 99 } 100 101 static bool deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName) 102 { 103 RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell); 104 thisObject->reifyAllPropertiesIfNecessary(exec); 105 return JSArray::deleteProperty(thisObject, exec, propertyName); 106 } 107 108 static bool deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned propertyName) 109 { 110 RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell); 111 thisObject->reifyAllPropertiesIfNecessary(exec); 112 return JSArray::deletePropertyByIndex(thisObject, exec, propertyName); 113 } 114 115 static void getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& arr, EnumerationMode mode = ExcludeDontEnumProperties) 116 { 117 RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(object); 118 thisObject->reifyAllPropertiesIfNecessary(exec); 119 JSArray::getOwnPropertyNames(thisObject, exec, arr, mode); 120 } 121 122 static bool defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool shouldThrow) 123 { 124 RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(object); 125 thisObject->reifyAllPropertiesIfNecessary(exec); 126 return JSArray::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow); 127 } 128 129 void reifyAllProperties(ExecState*); 130 void reifyMatchProperty(ExecState*); 131 132 WriteBarrier<JSString> m_input; 133 WriteBarrier<RegExp> m_regExp; 134 MatchResult m_result; 135 ReifiedState m_state; 136 }; 137 138 inline bool isRegExpMatchesArray(JSValue value) 139 { 140 return value.isCell() && value.asCell()->classInfo() == RegExpMatchesArray::info(); 141 } 29 JSArray* createRegExpMatchesArray(ExecState*, JSString*, RegExp*, MatchResult); 142 30 143 31 } -
trunk/Source/JavaScriptCore/runtime/RegExpObject.cpp
r172176 r175365 303 303 { 304 304 if (MatchResult result = match(exec, string)) 305 return RegExpMatchesArray::create(exec, string, regExp(), result);305 return createRegExpMatchesArray(exec, string, regExp(), result); 306 306 return jsNull(); 307 307 } -
trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp
r173761 r175365 865 865 // case without 'g' flag is handled like RegExp.prototype.exec 866 866 if (!global) 867 return JSValue::encode(result ? RegExpMatchesArray::create(exec, string, regExp, result) : jsNull());867 return JSValue::encode(result ? createRegExpMatchesArray(exec, string, regExp, result) : jsNull()); 868 868 869 869 // return array of matches
Note:
See TracChangeset
for help on using the changeset viewer.