blob: 7a4e55d54e1eb769aeab8405a551ce9171e3325b [file] [log] [blame]
/*
* Copyright (C) 2009 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "bindings/core/v8/V8StringResource.h"
#include "bindings/core/v8/V8Binding.h"
namespace blink {
template <class StringClass>
struct StringTraits {
static const StringClass& fromStringResource(WebCoreStringResourceBase*);
template <typename V8StringTrait>
static StringClass fromV8String(v8::Local<v8::String>, int);
};
template <>
struct StringTraits<String> {
static const String& fromStringResource(WebCoreStringResourceBase* resource) {
return resource->webcoreString();
}
template <typename V8StringTrait>
static String fromV8String(v8::Local<v8::String>, int);
};
template <>
struct StringTraits<AtomicString> {
static const AtomicString& fromStringResource(
WebCoreStringResourceBase* resource) {
return resource->getAtomicString();
}
template <typename V8StringTrait>
static AtomicString fromV8String(v8::Local<v8::String>, int);
};
struct V8StringTwoBytesTrait {
typedef UChar CharType;
ALWAYS_INLINE static void write(v8::Local<v8::String> v8String,
CharType* buffer,
int length) {
v8String->Write(reinterpret_cast<uint16_t*>(buffer), 0, length);
}
};
struct V8StringOneByteTrait {
typedef LChar CharType;
ALWAYS_INLINE static void write(v8::Local<v8::String> v8String,
CharType* buffer,
int length) {
v8String->WriteOneByte(buffer, 0, length);
}
};
template <typename V8StringTrait>
String StringTraits<String>::fromV8String(v8::Local<v8::String> v8String,
int length) {
ASSERT(v8String->Length() == length);
typename V8StringTrait::CharType* buffer;
String result = String::createUninitialized(length, buffer);
V8StringTrait::write(v8String, buffer, length);
return result;
}
template <typename V8StringTrait>
AtomicString StringTraits<AtomicString>::fromV8String(
v8::Local<v8::String> v8String,
int length) {
ASSERT(v8String->Length() == length);
static const int inlineBufferSize =
32 / sizeof(typename V8StringTrait::CharType);
if (length <= inlineBufferSize) {
typename V8StringTrait::CharType inlineBuffer[inlineBufferSize];
V8StringTrait::write(v8String, inlineBuffer, length);
return AtomicString(inlineBuffer, length);
}
typename V8StringTrait::CharType* buffer;
String string = String::createUninitialized(length, buffer);
V8StringTrait::write(v8String, buffer, length);
return AtomicString(string);
}
template <typename StringType>
StringType v8StringToWebCoreString(v8::Local<v8::String> v8String,
ExternalMode external) {
{
// This portion of this function is very hot in certain Dromeao benchmarks.
v8::String::Encoding encoding;
v8::String::ExternalStringResourceBase* resource =
v8String->GetExternalStringResourceBase(&encoding);
if (LIKELY(!!resource)) {
WebCoreStringResourceBase* base;
if (encoding == v8::String::ONE_BYTE_ENCODING)
base = static_cast<WebCoreStringResource8*>(resource);
else
base = static_cast<WebCoreStringResource16*>(resource);
return StringTraits<StringType>::fromStringResource(base);
}
}
int length = v8String->Length();
if (UNLIKELY(!length))
return StringType("");
bool oneByte = v8String->ContainsOnlyOneByte();
StringType result(oneByte ? StringTraits<StringType>::template fromV8String<
V8StringOneByteTrait>(v8String, length)
: StringTraits<StringType>::template fromV8String<
V8StringTwoBytesTrait>(v8String, length));
if (external != Externalize || !v8String->CanMakeExternal())
return result;
if (result.is8Bit()) {
WebCoreStringResource8* stringResource = new WebCoreStringResource8(result);
if (UNLIKELY(!v8String->MakeExternal(stringResource)))
delete stringResource;
} else {
WebCoreStringResource16* stringResource =
new WebCoreStringResource16(result);
if (UNLIKELY(!v8String->MakeExternal(stringResource)))
delete stringResource;
}
return result;
}
// Explicitly instantiate the above template with the expected
// parameterizations, to ensure the compiler generates the code; otherwise link
// errors can result in GCC 4.4.
template String v8StringToWebCoreString<String>(v8::Local<v8::String>,
ExternalMode);
template AtomicString v8StringToWebCoreString<AtomicString>(
v8::Local<v8::String>,
ExternalMode);
// Fast but non thread-safe version.
String int32ToWebCoreStringFast(int value) {
// Caching of small strings below is not thread safe: newly constructed
// AtomicString are not safely published.
ASSERT(isMainThread());
// Most numbers used are <= 100. Even if they aren't used there's very little
// cost in using the space.
const int kLowNumbers = 100;
DEFINE_STATIC_LOCAL(Vector<AtomicString>, lowNumbers, (kLowNumbers + 1));
String webCoreString;
if (0 <= value && value <= kLowNumbers) {
webCoreString = lowNumbers[value];
if (!webCoreString) {
AtomicString valueString = AtomicString::number(value);
lowNumbers[value] = valueString;
webCoreString = valueString;
}
} else {
webCoreString = String::number(value);
}
return webCoreString;
}
String int32ToWebCoreString(int value) {
// If we are on the main thread (this should always true for non-workers),
// call the faster one.
if (isMainThread())
return int32ToWebCoreStringFast(value);
return String::number(value);
}
} // namespace blink