Commit 6e32048e authored by vitalyr@chromium.org's avatar vitalyr@chromium.org

Fast case conversion for ascii strings.

Review URL: http://codereview.chromium.org/660455

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4011 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 1334adbd
......@@ -4084,18 +4084,83 @@ static Object* ConvertCaseHelper(String* s,
}
template <class Converter>
static Object* ConvertCase(Arguments args,
unibrow::Mapping<Converter, 128>* mapping) {
NoHandleAllocation ha;
static inline SeqAsciiString* TryGetSeqAsciiString(String* s) {
if (!s->IsFlat() || !s->IsAsciiRepresentation()) return NULL;
if (s->IsConsString()) {
ASSERT(ConsString::cast(s)->second()->length() == 0);
return SeqAsciiString::cast(ConsString::cast(s)->first());
}
return SeqAsciiString::cast(s);
}
namespace {
struct ToLowerTraits {
typedef unibrow::ToLowercase UnibrowConverter;
static bool ConvertAscii(char* dst, char* src, int length) {
bool changed = false;
for (int i = 0; i < length; ++i) {
char c = src[i];
if ('A' <= c && c <= 'Z') {
c += ('a' - 'A');
changed = true;
}
dst[i] = c;
}
return changed;
}
};
struct ToUpperTraits {
typedef unibrow::ToUppercase UnibrowConverter;
static bool ConvertAscii(char* dst, char* src, int length) {
bool changed = false;
for (int i = 0; i < length; ++i) {
char c = src[i];
if ('a' <= c && c <= 'z') {
c -= ('a' - 'A');
changed = true;
}
dst[i] = c;
}
return changed;
}
};
} // namespace
template <typename ConvertTraits>
static Object* ConvertCase(
Arguments args,
unibrow::Mapping<typename ConvertTraits::UnibrowConverter, 128>* mapping) {
NoHandleAllocation ha;
CONVERT_CHECKED(String, s, args[0]);
s->TryFlatten();
int input_string_length = s->length();
const int length = s->length();
// Assume that the string is not empty; we need this assumption later
if (input_string_length == 0) return s;
int length = input_string_length;
if (length == 0) return s;
// Simpler handling of ascii strings.
//
// NOTE: This assumes that the upper/lower case of an ascii
// character is also ascii. This is currently the case, but it
// might break in the future if we implement more context and locale
// dependent upper/lower conversions.
SeqAsciiString* seq_ascii = TryGetSeqAsciiString(s);
if (seq_ascii != NULL) {
Object* o = Heap::AllocateRawAsciiString(length);
if (o->IsFailure()) return o;
SeqAsciiString* result = SeqAsciiString::cast(o);
bool has_changed_character = ConvertTraits::ConvertAscii(
result->GetChars(), seq_ascii->GetChars(), length);
return has_changed_character ? result : s;
}
Object* answer = ConvertCaseHelper(s, length, length, mapping);
if (answer->IsSmi()) {
......@@ -4107,18 +4172,20 @@ static Object* ConvertCase(Arguments args,
static Object* Runtime_StringToLowerCase(Arguments args) {
return ConvertCase<unibrow::ToLowercase>(args, &to_lower_mapping);
return ConvertCase<ToLowerTraits>(args, &to_lower_mapping);
}
static Object* Runtime_StringToUpperCase(Arguments args) {
return ConvertCase<unibrow::ToUppercase>(args, &to_upper_mapping);
return ConvertCase<ToUpperTraits>(args, &to_upper_mapping);
}
static inline bool IsTrimWhiteSpace(unibrow::uchar c) {
return unibrow::WhiteSpace::Is(c) || c == 0x200b;
}
static Object* Runtime_StringTrim(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 3);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment