1 /* 2 * Copyright (C) 2009 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 * THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 #include "bindings/v8/V8StringResource.h" 28 29 #include "bindings/v8/V8Binding.h" 30 #include "core/inspector/BindingVisitors.h" 31 #include "wtf/MainThread.h" 32 33 namespace WebCore { 34 35 WebCoreStringResourceBase* WebCoreStringResourceBase::toWebCoreStringResourceBase(v8::Handle<v8::String> string) 36 { 37 v8::String::Encoding encoding; 38 v8::String::ExternalStringResourceBase* resource = string->GetExternalStringResourceBase(&encoding); 39 if (!resource) 40 return 0; 41 if (encoding == v8::String::ONE_BYTE_ENCODING) 42 return static_cast<WebCoreStringResource8*>(resource); 43 return static_cast<WebCoreStringResource16*>(resource); 44 } 45 46 void WebCoreStringResourceBase::visitStrings(ExternalStringVisitor* visitor) 47 { 48 visitor->visitJSExternalString(m_plainString.impl()); 49 if (m_plainString.impl() != m_atomicString.impl() && !m_atomicString.isNull()) 50 visitor->visitJSExternalString(m_atomicString.impl()); 51 } 52 53 template<class StringClass> struct StringTraits { 54 static const StringClass& fromStringResource(WebCoreStringResourceBase*); 55 template<bool oneByte> 56 static StringClass fromV8String(v8::Handle<v8::String>, int); 57 }; 58 59 template<> 60 struct StringTraits<String> { 61 static const String& fromStringResource(WebCoreStringResourceBase* resource) 62 { 63 return resource->webcoreString(); 64 } 65 template<bool oneByte> 66 static String fromV8String(v8::Handle<v8::String>, int); 67 }; 68 69 template<> 70 struct StringTraits<AtomicString> { 71 static const AtomicString& fromStringResource(WebCoreStringResourceBase* resource) 72 { 73 return resource->atomicString(); 74 } 75 template<bool oneByte> 76 static AtomicString fromV8String(v8::Handle<v8::String>, int); 77 }; 78 79 template<> 80 String StringTraits<String>::fromV8String<false>(v8::Handle<v8::String> v8String, int length) 81 { 82 ASSERT(v8String->Length() == length); 83 UChar* buffer; 84 String result = String::createUninitialized(length, buffer); 85 v8String->Write(reinterpret_cast<uint16_t*>(buffer), 0, length); 86 return result; 87 } 88 89 template<> 90 AtomicString StringTraits<AtomicString>::fromV8String<false>(v8::Handle<v8::String> v8String, int length) 91 { 92 ASSERT(v8String->Length() == length); 93 static const int inlineBufferSize = 16; 94 if (length <= inlineBufferSize) { 95 UChar inlineBuffer[inlineBufferSize]; 96 v8String->Write(reinterpret_cast<uint16_t*>(inlineBuffer), 0, length); 97 return AtomicString(inlineBuffer, length); 98 } 99 UChar* buffer; 100 String result = String::createUninitialized(length, buffer); 101 v8String->Write(reinterpret_cast<uint16_t*>(buffer), 0, length); 102 return AtomicString(result); 103 } 104 105 template<> 106 String StringTraits<String>::fromV8String<true>(v8::Handle<v8::String> v8String, int length) 107 { 108 ASSERT(v8String->Length() == length); 109 LChar* buffer; 110 String result = String::createUninitialized(length, buffer); 111 v8String->WriteOneByte(buffer, 0, length); 112 return result; 113 } 114 115 template<> 116 AtomicString StringTraits<AtomicString>::fromV8String<true>(v8::Handle<v8::String> v8String, int length) 117 { 118 ASSERT(v8String->Length() == length); 119 static const int inlineBufferSize = 32; 120 if (length <= inlineBufferSize) { 121 LChar inlineBuffer[inlineBufferSize]; 122 v8String->WriteOneByte(inlineBuffer, 0, length); 123 return AtomicString(inlineBuffer, length); 124 } 125 LChar* buffer; 126 String string = String::createUninitialized(length, buffer); 127 v8String->WriteOneByte(buffer, 0, length); 128 return AtomicString(string); 129 } 130 131 template<typename StringType> 132 StringType v8StringToWebCoreString(v8::Handle<v8::String> v8String, ExternalMode external) 133 { 134 { 135 // A lot of WebCoreStringResourceBase::toWebCoreStringResourceBase is copied here by hand for performance reasons. 136 // This portion of this function is very hot in certain Dromeao benchmarks. 137 v8::String::Encoding encoding; 138 v8::String::ExternalStringResourceBase* resource = v8String->GetExternalStringResourceBase(&encoding); 139 if (LIKELY(!!resource)) { 140 WebCoreStringResourceBase* base; 141 if (encoding == v8::String::ONE_BYTE_ENCODING) 142 base = static_cast<WebCoreStringResource8*>(resource); 143 else 144 base = static_cast<WebCoreStringResource16*>(resource); 145 return StringTraits<StringType>::fromStringResource(base); 146 } 147 } 148 149 int length = v8String->Length(); 150 if (UNLIKELY(!length)) 151 return StringType(""); 152 153 bool oneByte = v8String->ContainsOnlyOneByte(); 154 StringType result(oneByte ? StringTraits<StringType>::template fromV8String<true>(v8String, length) : StringTraits<StringType>::template fromV8String<false>(v8String, length)); 155 156 if (external != Externalize || !v8String->CanMakeExternal()) 157 return result; 158 159 if (result.is8Bit()) { 160 WebCoreStringResource8* stringResource = new WebCoreStringResource8(result); 161 if (UNLIKELY(!v8String->MakeExternal(stringResource))) 162 delete stringResource; 163 } else { 164 WebCoreStringResource16* stringResource = new WebCoreStringResource16(result); 165 if (UNLIKELY(!v8String->MakeExternal(stringResource))) 166 delete stringResource; 167 } 168 return result; 169 } 170 171 // Explicitly instantiate the above template with the expected parameterizations, 172 // to ensure the compiler generates the code; otherwise link errors can result in GCC 4.4. 173 template String v8StringToWebCoreString<String>(v8::Handle<v8::String>, ExternalMode); 174 template AtomicString v8StringToWebCoreString<AtomicString>(v8::Handle<v8::String>, ExternalMode); 175 176 // Fast but non thread-safe version. 177 String int32ToWebCoreStringFast(int value) 178 { 179 // Caching of small strings below is not thread safe: newly constructed AtomicString 180 // are not safely published. 181 ASSERT(isMainThread()); 182 183 // Most numbers used are <= 100. Even if they aren't used there's very little cost in using the space. 184 const int kLowNumbers = 100; 185 DEFINE_STATIC_LOCAL(Vector<AtomicString>, lowNumbers, (kLowNumbers + 1)); 186 String webCoreString; 187 if (0 <= value && value <= kLowNumbers) { 188 webCoreString = lowNumbers[value]; 189 if (!webCoreString) { 190 AtomicString valueString = AtomicString::number(value); 191 lowNumbers[value] = valueString; 192 webCoreString = valueString; 193 } 194 } else 195 webCoreString = String::number(value); 196 return webCoreString; 197 } 198 199 String int32ToWebCoreString(int value) 200 { 201 // If we are on the main thread (this should always true for non-workers), call the faster one. 202 if (isMainThread()) 203 return int32ToWebCoreStringFast(value); 204 return String::number(value); 205 } 206 207 } // namespace WebCore 208