diff options
Diffstat (limited to 'Source/JavaScriptCore/runtime/JSStringJoiner.h')
| -rw-r--r-- | Source/JavaScriptCore/runtime/JSStringJoiner.h | 122 |
1 files changed, 25 insertions, 97 deletions
diff --git a/Source/JavaScriptCore/runtime/JSStringJoiner.h b/Source/JavaScriptCore/runtime/JSStringJoiner.h index 255fd3e11..73950c6d7 100644 --- a/Source/JavaScriptCore/runtime/JSStringJoiner.h +++ b/Source/JavaScriptCore/runtime/JSStringJoiner.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2015 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2013 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,121 +26,49 @@ #ifndef JSStringJoiner_h #define JSStringJoiner_h -#include "ExceptionHelpers.h" #include "JSCJSValue.h" +#include <wtf/Vector.h> +#include <wtf/text/WTFString.h> namespace JSC { +class ExecState; + + class JSStringJoiner { public: - JSStringJoiner(ExecState&, LChar separator, unsigned stringCount); - JSStringJoiner(ExecState&, StringView separator, unsigned stringCount); + JSStringJoiner(const String& separator, size_t stringCount); - void append(ExecState&, JSValue); - bool appendWithoutSideEffects(ExecState&, JSValue); - void appendEmptyString(); - - JSValue join(ExecState&); + void append(const String&); + JSValue join(ExecState*); private: - void append(StringViewWithUnderlyingString&&); - void append8Bit(const String&); - void appendLiteral(const Identifier&); - unsigned joinedLength(ExecState&) const; + String m_separator; + Vector<String> m_strings; - LChar m_singleCharacterSeparator; - StringView m_separator; - Vector<StringViewWithUnderlyingString> m_strings; Checked<unsigned, RecordOverflow> m_accumulatedStringsLength; - bool m_isAll8Bit { true }; + bool m_isValid; + bool m_is8Bits; }; -inline JSStringJoiner::JSStringJoiner(ExecState& state, StringView separator, unsigned stringCount) +inline JSStringJoiner::JSStringJoiner(const String& separator, size_t stringCount) : m_separator(separator) - , m_isAll8Bit(m_separator.is8Bit()) -{ - if (!m_strings.tryReserveCapacity(stringCount)) - throwOutOfMemoryError(&state); -} - -inline JSStringJoiner::JSStringJoiner(ExecState& state, LChar separator, unsigned stringCount) - : m_singleCharacterSeparator(separator) - , m_separator { &m_singleCharacterSeparator, 1 } -{ - if (!m_strings.tryReserveCapacity(stringCount)) - throwOutOfMemoryError(&state); -} - -ALWAYS_INLINE void JSStringJoiner::append(StringViewWithUnderlyingString&& string) -{ - m_accumulatedStringsLength += string.view.length(); - m_isAll8Bit = m_isAll8Bit && string.view.is8Bit(); - m_strings.uncheckedAppend(WTFMove(string)); -} - -ALWAYS_INLINE void JSStringJoiner::append8Bit(const String& string) -{ - ASSERT(string.is8Bit()); - m_accumulatedStringsLength += string.length(); - m_strings.uncheckedAppend({ string, string }); -} - -ALWAYS_INLINE void JSStringJoiner::appendLiteral(const Identifier& literal) -{ - m_accumulatedStringsLength += literal.length(); - ASSERT(literal.string().is8Bit()); - m_strings.uncheckedAppend({ literal.string(), { } }); -} - -ALWAYS_INLINE void JSStringJoiner::appendEmptyString() + , m_isValid(true) + , m_is8Bits(m_separator.is8Bit()) { - m_strings.uncheckedAppend({ { }, { } }); + ASSERT(!m_separator.isNull()); + m_isValid = m_strings.tryReserveCapacity(stringCount); } -ALWAYS_INLINE bool JSStringJoiner::appendWithoutSideEffects(ExecState& state, JSValue value) +inline void JSStringJoiner::append(const String& str) { - // The following code differs from using the result of JSValue::toString in the following ways: - // 1) It's inlined more than JSValue::toString is. - // 2) It includes conversion to WTF::String in a way that avoids allocating copies of substrings. - // 3) It doesn't create a JSString for numbers, true, or false. - // 4) It turns undefined and null into the empty string instead of "undefined" and "null". - // 5) It uses optimized code paths for all the cases known to be 8-bit and for the empty string. - // If we might make an effectful calls, return false. Otherwise return true. - - if (value.isCell()) { - if (!value.asCell()->isString()) - return false; - - append(asString(value)->viewWithUnderlyingString(state)); - return true; - } + if (!m_isValid) + return; - if (value.isInt32()) { - append8Bit(state.vm().numericStrings.add(value.asInt32())); - return true; - } - if (value.isDouble()) { - append8Bit(state.vm().numericStrings.add(value.asDouble())); - return true; - } - if (value.isTrue()) { - append8Bit(state.vm().propertyNames->trueKeyword.string()); - return true; - } - if (value.isFalse()) { - append8Bit(state.vm().propertyNames->falseKeyword.string()); - return true; - } - ASSERT(value.isUndefinedOrNull()); - appendEmptyString(); - return true; -} - -ALWAYS_INLINE void JSStringJoiner::append(ExecState& state, JSValue value) -{ - if (!appendWithoutSideEffects(state, value)) { - JSString* jsString = value.toString(&state); - append(jsString->viewWithUnderlyingString(state)); + m_strings.append(str); + if (!str.isNull()) { + m_accumulatedStringsLength += str.length(); + m_is8Bits = m_is8Bits && str.is8Bit(); } } |
