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/core/v8/V8StringResource.h" 28 29 #include "bindings/core/v8/V8Binding.h" 30 #include "core/inspector/BindingVisitors.h" 31 #include "wtf/MainThread.h" 32 33 namespace blink { 34 35 template<class StringClass> struct StringTraits { 36 static const StringClass& fromStringResource(WebCoreStringResourceBase*); 37 template <typename V8StringTrait> 38 static StringClass fromV8String(v8::Handle<v8::String>, int); 39 }; 40 41 template<> 42 struct StringTraits<String> { 43 static const String& fromStringResource(WebCoreStringResourceBase* resource) 44 { 45 return resource->webcoreString(); 46 } 47 template <typename V8StringTrait> 48 static String fromV8String(v8::Handle<v8::String>, int); 49 }; 50 51 template<> 52 struct StringTraits<AtomicString> { 53 static const AtomicString& fromStringResource(WebCoreStringResourceBase* resource) 54 { 55 return resource->atomicString(); 56 } 57 template <typename V8StringTrait> 58 static AtomicString fromV8String(v8::Handle<v8::String>, int); 59 }; 60 61 struct V8StringTwoBytesTrait { 62 typedef UChar CharType; 63 ALWAYS_INLINE static void write(v8::Handle<v8::String> v8String, CharType* buffer, int length) 64 { 65 v8String->Write(reinterpret_cast<uint16_t*>(buffer), 0, length); 66 } 67 }; 68 69 struct V8StringOneByteTrait { 70 typedef LChar CharType; 71 ALWAYS_INLINE static void write(v8::Handle<v8::String> v8String, CharType* buffer, int length) 72 { 73 v8String->WriteOneByte(buffer, 0, length); 74 } 75 }; 76 77 template <typename V8StringTrait> 78 String StringTraits<String>::fromV8String(v8::Handle<v8::String> v8String, int length) 79 { 80 ASSERT(v8String->Length() == length); 81 typename V8StringTrait::CharType* buffer; 82 String result = String::createUninitialized(length, buffer); 83 V8StringTrait::write(v8String, buffer, length); 84 return result; 85 } 86 87 template <typename V8StringTrait> 88 AtomicString StringTraits<AtomicString>::fromV8String(v8::Handle<v8::String> v8String, int length) 89 { 90 ASSERT(v8String->Length() == length); 91 static const int inlineBufferSize = 32 / sizeof(typename V8StringTrait::CharType); 92 if (length <= inlineBufferSize) { 93 typename V8StringTrait::CharType inlineBuffer[inlineBufferSize]; 94 V8StringTrait::write(v8String, inlineBuffer, length); 95 return AtomicString(inlineBuffer, length); 96 } 97 typename V8StringTrait::CharType* buffer; 98 String string = String::createUninitialized(length, buffer); 99 V8StringTrait::write(v8String, buffer, length); 100 return AtomicString(string); 101 } 102 103 template<typename StringType> 104 StringType v8StringToWebCoreString(v8::Handle<v8::String> v8String, ExternalMode external) 105 { 106 { 107 // This portion of this function is very hot in certain Dromeao benchmarks. 108 v8::String::Encoding encoding; 109 v8::String::ExternalStringResourceBase* resource = v8String->GetExternalStringResourceBase(&encoding); 110 if (LIKELY(!!resource)) { 111 WebCoreStringResourceBase* base; 112 if (encoding == v8::String::ONE_BYTE_ENCODING) 113 base = static_cast<WebCoreStringResource8*>(resource); 114 else 115 base = static_cast<WebCoreStringResource16*>(resource); 116 return StringTraits<StringType>::fromStringResource(base); 117 } 118 } 119 120 int length = v8String->Length(); 121 if (UNLIKELY(!length)) 122 return StringType(""); 123 124 bool oneByte = v8String->ContainsOnlyOneByte(); 125 StringType result(oneByte ? StringTraits<StringType>::template fromV8String<V8StringOneByteTrait>(v8String, length) : StringTraits<StringType>::template fromV8String<V8StringTwoBytesTrait>(v8String, length)); 126 127 if (external != Externalize || !v8String->CanMakeExternal()) 128 return result; 129 130 if (result.is8Bit()) { 131 WebCoreStringResource8* stringResource = new WebCoreStringResource8(result); 132 if (UNLIKELY(!v8String->MakeExternal(stringResource))) 133 delete stringResource; 134 } else { 135 WebCoreStringResource16* stringResource = new WebCoreStringResource16(result); 136 if (UNLIKELY(!v8String->MakeExternal(stringResource))) 137 delete stringResource; 138 } 139 return result; 140 } 141 142 // Explicitly instantiate the above template with the expected parameterizations, 143 // to ensure the compiler generates the code; otherwise link errors can result in GCC 4.4. 144 template String v8StringToWebCoreString<String>(v8::Handle<v8::String>, ExternalMode); 145 template AtomicString v8StringToWebCoreString<AtomicString>(v8::Handle<v8::String>, ExternalMode); 146 147 // Fast but non thread-safe version. 148 String int32ToWebCoreStringFast(int value) 149 { 150 // Caching of small strings below is not thread safe: newly constructed AtomicString 151 // are not safely published. 152 ASSERT(isMainThread()); 153 154 // Most numbers used are <= 100. Even if they aren't used there's very little cost in using the space. 155 const int kLowNumbers = 100; 156 DEFINE_STATIC_LOCAL(Vector<AtomicString>, lowNumbers, (kLowNumbers + 1)); 157 String webCoreString; 158 if (0 <= value && value <= kLowNumbers) { 159 webCoreString = lowNumbers[value]; 160 if (!webCoreString) { 161 AtomicString valueString = AtomicString::number(value); 162 lowNumbers[value] = valueString; 163 webCoreString = valueString; 164 } 165 } else { 166 webCoreString = String::number(value); 167 } 168 return webCoreString; 169 } 170 171 String int32ToWebCoreString(int value) 172 { 173 // If we are on the main thread (this should always true for non-workers), call the faster one. 174 if (isMainThread()) 175 return int32ToWebCoreStringFast(value); 176 return String::number(value); 177 } 178 179 } // namespace blink 180