Modified: trunk/Source/_javascript_Core/runtime/StringPrototype.cpp (207860 => 207861)
--- trunk/Source/_javascript_Core/runtime/StringPrototype.cpp 2016-10-26 01:15:36 UTC (rev 207860)
+++ trunk/Source/_javascript_Core/runtime/StringPrototype.cpp 2016-10-26 01:15:49 UTC (rev 207861)
@@ -433,8 +433,15 @@
return jsString(exec, WTFMove(impl));
}
+#define OUT_OF_MEMORY(exec__, scope__) \
+ do { \
+ throwOutOfMemoryError(exec__, scope__); \
+ return encodedJSValue(); \
+ } while (false)
+
static ALWAYS_INLINE EncodedJSValue removeUsingRegExpSearch(VM& vm, ExecState* exec, JSString* string, const String& source, RegExp* regExp)
{
+ auto scope = DECLARE_THROW_SCOPE(vm);
SuperSamplerScope superSamplerScope(false);
size_t lastIndex = 0;
@@ -449,9 +456,10 @@
if (!result)
break;
- if (lastIndex < result.start)
- sourceRanges.constructAndAppend(lastIndex, result.start - lastIndex);
-
+ if (lastIndex < result.start) {
+ if (UNLIKELY(!sourceRanges.tryConstructAndAppend(lastIndex, result.start - lastIndex)))
+ OUT_OF_MEMORY(exec, scope);
+ }
lastIndex = result.end;
startPosition = lastIndex;
@@ -466,9 +474,11 @@
if (!lastIndex)
return JSValue::encode(string);
- if (static_cast<unsigned>(lastIndex) < sourceLen)
- sourceRanges.constructAndAppend(lastIndex, sourceLen - lastIndex);
-
+ if (static_cast<unsigned>(lastIndex) < sourceLen) {
+ if (UNLIKELY(!sourceRanges.tryConstructAndAppend(lastIndex, sourceLen - lastIndex)))
+ OUT_OF_MEMORY(exec, scope);
+ }
+ scope.release();
return JSValue::encode(jsSpliceSubstrings(exec, string, source, sourceRanges.data(), sourceRanges.size()));
}
@@ -490,8 +500,10 @@
regExpObject->setLastIndex(exec, 0);
RETURN_IF_EXCEPTION(scope, encodedJSValue());
- if (callType == CallType::None && !replacementString.length())
+ if (callType == CallType::None && !replacementString.length()) {
+ scope.release();
return removeUsingRegExpSearch(vm, exec, string, source, regExp);
+ }
}
// FIXME: This is wrong because we may be called directly from the FTL.
@@ -518,7 +530,8 @@
if (!result)
break;
- sourceRanges.constructAndAppend(lastIndex, result.start - lastIndex);
+ if (UNLIKELY(!sourceRanges.tryConstructAndAppend(lastIndex, result.start - lastIndex)))
+ OUT_OF_MEMORY(exec, scope);
unsigned i = 0;
for (; i < regExp->numSubpatterns() + 1; ++i) {
@@ -556,7 +569,8 @@
if (!result)
break;
- sourceRanges.constructAndAppend(lastIndex, result.start - lastIndex);
+ if (UNLIKELY(!sourceRanges.tryConstructAndAppend(lastIndex, result.start - lastIndex)))
+ OUT_OF_MEMORY(exec, scope);
unsigned i = 0;
for (; i < regExp->numSubpatterns() + 1; ++i) {
@@ -596,7 +610,8 @@
break;
if (callType != CallType::None) {
- sourceRanges.constructAndAppend(lastIndex, result.start - lastIndex);
+ if (UNLIKELY(!sourceRanges.tryConstructAndAppend(lastIndex, result.start - lastIndex)))
+ OUT_OF_MEMORY(exec, scope);
MarkedArgumentBuffer args;
@@ -620,7 +635,8 @@
} else {
int replLen = replacementString.length();
if (lastIndex < result.start || replLen) {
- sourceRanges.constructAndAppend(lastIndex, result.start - lastIndex);
+ if (UNLIKELY(!sourceRanges.tryConstructAndAppend(lastIndex, result.start - lastIndex)))
+ OUT_OF_MEMORY(exec, scope);
if (replLen)
replacements.append(substituteBackreferences(replacementString, source, ovector, regExp));
@@ -644,9 +660,10 @@
if (!lastIndex && replacements.isEmpty())
return JSValue::encode(string);
- if (static_cast<unsigned>(lastIndex) < sourceLen)
- sourceRanges.constructAndAppend(lastIndex, sourceLen - lastIndex);
-
+ if (static_cast<unsigned>(lastIndex) < sourceLen) {
+ if (UNLIKELY(!sourceRanges.tryConstructAndAppend(lastIndex, sourceLen - lastIndex)))
+ OUT_OF_MEMORY(exec, scope);
+ }
return JSValue::encode(jsSpliceSubstringsWithSeparators(exec, string, source, sourceRanges.data(), sourceRanges.size(), replacements.data(), replacements.size()));
}
@@ -662,11 +679,13 @@
// ES5.1 15.5.4.10 step 8.a.
searchValue->setLastIndex(exec, 0);
RETURN_IF_EXCEPTION(scope, encodedJSValue());
+ scope.release();
return removeUsingRegExpSearch(vm, exec, thisValue, thisValue->value(exec), regExp);
}
CallData callData;
String replacementString = emptyString();
+ scope.release();
return replaceUsingRegExpSearch(
vm, exec, thisValue, searchValue, callData, CallType::None, replacementString, JSValue());
}
@@ -695,6 +714,7 @@
RETURN_IF_EXCEPTION(scope, encodedJSValue());
}
+ scope.release();
return replaceUsingRegExpSearch(
vm, exec, string, searchValue, callData, callType, replacementString, replaceValue);
}
@@ -832,6 +852,7 @@
if (!searchValue.inherits(RegExpObject::info()))
return JSValue::encode(jsUndefined());
+ scope.release();
return replaceUsingRegExpSearch(exec->vm(), exec, string, searchValue, exec->argument(1));
}
Modified: trunk/Source/WTF/wtf/Vector.h (207860 => 207861)
--- trunk/Source/WTF/wtf/Vector.h 2016-10-26 01:15:36 UTC (rev 207860)
+++ trunk/Source/WTF/wtf/Vector.h 2016-10-26 01:15:49 UTC (rev 207861)
@@ -722,6 +722,7 @@
void append(ValueType&& value) { append<ValueType>(std::forward<ValueType>(value)); }
template<typename U> void append(U&&);
template<typename... Args> void constructAndAppend(Args&&...);
+ template<typename... Args> bool tryConstructAndAppend(Args&&...);
void uncheckedAppend(ValueType&& value) { uncheckedAppend<ValueType>(std::forward<ValueType>(value)); }
template<typename U> void uncheckedAppend(U&&);
@@ -785,6 +786,7 @@
template<typename U> U* expandCapacity(size_t newMinCapacity, U*);
template<typename U> void appendSlowCase(U&&);
template<typename... Args> void constructAndAppendSlowCase(Args&&...);
+ template<typename... Args> bool tryConstructAndAppendSlowCase(Args&&...);
void asanSetInitialBufferSizeTo(size_t);
void asanSetBufferSizeToFullCapacity();
@@ -1225,6 +1227,19 @@
constructAndAppendSlowCase(std::forward<Args>(args)...);
}
+template<typename T, size_t inlineCapacity, typename OverflowHandler, size_t minCapacity> template<typename... Args>
+ALWAYS_INLINE bool Vector<T, inlineCapacity, OverflowHandler, minCapacity>::tryConstructAndAppend(Args&&... args)
+{
+ if (size() != capacity()) {
+ asanBufferSizeWillChangeTo(m_size + 1);
+ new (NotNull, end()) T(std::forward<Args>(args)...);
+ ++m_size;
+ return true;
+ }
+
+ return tryConstructAndAppendSlowCase(std::forward<Args>(args)...);
+}
+
template<typename T, size_t inlineCapacity, typename OverflowHandler, size_t minCapacity> template<typename U>
void Vector<T, inlineCapacity, OverflowHandler, minCapacity>::appendSlowCase(U&& value)
{
@@ -1252,6 +1267,21 @@
++m_size;
}
+template<typename T, size_t inlineCapacity, typename OverflowHandler, size_t minCapacity> template<typename... Args>
+bool Vector<T, inlineCapacity, OverflowHandler, minCapacity>::tryConstructAndAppendSlowCase(Args&&... args)
+{
+ ASSERT(size() == capacity());
+
+ if (UNLIKELY(!tryExpandCapacity(size() + 1)))
+ return false;
+ ASSERT(begin());
+
+ asanBufferSizeWillChangeTo(m_size + 1);
+ new (NotNull, end()) T(std::forward<Args>(args)...);
+ ++m_size;
+ return true;
+}
+
// This version of append saves a branch in the case where you know that the
// vector's capacity is large enough for the append to succeed.