Add runtime function for string to array conversion.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4022 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
vitalyr@chromium.org 2010-03-04 14:03:08 +00:00
parent 8c086c50dd
commit 05a74e8131
8 changed files with 101 additions and 21 deletions

View File

@ -242,16 +242,6 @@ BUILTIN(ArrayCodeGeneric) {
}
static Object* AllocateUninitializedFixedArray(int len) {
Object* obj = Heap::AllocateRawFixedArray(len);
if (obj->IsFailure()) return obj;
reinterpret_cast<FixedArray*>(obj)->set_map(Heap::fixed_array_map());
FixedArray::cast(obj)->set_length(len);
return obj;
}
static Object* AllocateJSArray() {
JSFunction* array_function =
Top::context()->global_context()->array_function();
@ -363,7 +353,7 @@ BUILTIN(ArrayPush) {
if (new_length > elms->length()) {
// New backing storage is needed.
int capacity = new_length + (new_length >> 1) + 16;
Object* obj = AllocateUninitializedFixedArray(capacity);
Object* obj = Heap::AllocateUninitializedFixedArray(capacity);
if (obj->IsFailure()) return obj;
FixedArray* new_elms = FixedArray::cast(obj);
@ -473,7 +463,7 @@ BUILTIN(ArrayUnshift) {
if (new_length > elms->length()) {
// New backing storage is needed.
int capacity = new_length + (new_length >> 1) + 16;
Object* obj = AllocateUninitializedFixedArray(capacity);
Object* obj = Heap::AllocateUninitializedFixedArray(capacity);
if (obj->IsFailure()) return obj;
FixedArray* new_elms = FixedArray::cast(obj);
@ -553,7 +543,7 @@ BUILTIN(ArraySlice) {
if (result->IsFailure()) return result;
JSArray* result_array = JSArray::cast(result);
result = AllocateUninitializedFixedArray(result_len);
result = Heap::AllocateUninitializedFixedArray(result_len);
if (result->IsFailure()) return result;
FixedArray* result_elms = FixedArray::cast(result);
@ -622,7 +612,7 @@ BUILTIN(ArraySplice) {
if (result->IsFailure()) return result;
JSArray* result_array = JSArray::cast(result);
result = AllocateUninitializedFixedArray(actualDeleteCount);
result = Heap::AllocateUninitializedFixedArray(actualDeleteCount);
if (result->IsFailure()) return result;
FixedArray* result_elms = FixedArray::cast(result);
@ -660,7 +650,7 @@ BUILTIN(ArraySplice) {
if (new_length > elms->length()) {
// New backing storage is needed.
int capacity = new_length + (new_length >> 1) + 16;
Object* obj = AllocateUninitializedFixedArray(capacity);
Object* obj = Heap::AllocateUninitializedFixedArray(capacity);
if (obj->IsFailure()) return obj;
FixedArray* new_elms = FixedArray::cast(obj);

View File

@ -43,6 +43,12 @@ Handle<FixedArray> Factory::NewFixedArray(int size, PretenureFlag pretenure) {
}
Handle<FixedArray> Factory::NewUninitializedFixedArray(int size) {
ASSERT(0 <= size);
CALL_HEAP_FUNCTION(Heap::AllocateUninitializedFixedArray(size), FixedArray);
}
Handle<FixedArray> Factory::NewFixedArrayWithHoles(int size) {
ASSERT(0 <= size);
CALL_HEAP_FUNCTION(Heap::AllocateFixedArrayWithHoles(size), FixedArray);

View File

@ -45,6 +45,10 @@ class Factory : public AllStatic {
int size,
PretenureFlag pretenure = NOT_TENURED);
// Allocate a new uninitialized fixed array. It must be filled by
// the caller.
static Handle<FixedArray> NewUninitializedFixedArray(int size);
// Allocate a new fixed array with non-existing entries (the hole).
static Handle<FixedArray> NewFixedArrayWithHoles(int size);

View File

@ -2967,6 +2967,18 @@ Object* Heap::AllocateFixedArray(int length, PretenureFlag pretenure) {
}
Object* Heap::AllocateUninitializedFixedArray(int length) {
if (length == 0) return empty_fixed_array();
Object* obj = AllocateRawFixedArray(length);
if (obj->IsFailure()) return obj;
reinterpret_cast<FixedArray*>(obj)->set_map(fixed_array_map());
FixedArray::cast(obj)->set_length(length);
return obj;
}
Object* Heap::AllocateFixedArrayWithHoles(int length) {
if (length == 0) return empty_fixed_array();
Object* result = AllocateRawFixedArray(length);

View File

@ -450,9 +450,16 @@ class Heap : public AllStatic {
// failed.
// Please note this does not perform a garbage collection.
static Object* AllocateFixedArray(int length, PretenureFlag pretenure);
// Allocate uninitialized, non-tenured fixed array with length elements.
// Allocates a fixed array initialized with undefined values
static Object* AllocateFixedArray(int length);
// Allocates an uninitialized fixed array. It must be filled by the caller.
//
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed.
// Please note this does not perform a garbage collection.
static Object* AllocateUninitializedFixedArray(int length);
// Make a copy of src and return it. Returns
// Failure::RetryAfterGC(requested_bytes, space) if the allocation failed.
static Object* CopyFixedArray(FixedArray* src);

View File

@ -4213,6 +4213,70 @@ static Object* Runtime_StringTrim(Arguments args) {
return s->SubString(left, right);
}
// Copies ascii characters to the given fixed array looking up
// one-char strings in the cache. Gives up on the first char that is
// not in the cache. Returns the length of the successfully copied
// prefix.
static int CopyCachedAsciiCharsToArray(const char* chars,
FixedArray* elements,
int length) {
AssertNoAllocation nogc;
FixedArray* ascii_cache = Heap::single_character_string_cache();
Object* undefined = Heap::undefined_value();
for (int i = 0; i < length; ++i) {
Object* value = ascii_cache->get(chars[i]);
if (value == undefined) return i;
ASSERT(!Heap::InNewSpace(value));
elements->set(i, value, SKIP_WRITE_BARRIER);
}
return length;
}
// Converts a String to JSArray.
// For example, "foo" => ["f", "o", "o"].
static Object* Runtime_StringToArray(Arguments args) {
HandleScope scope;
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(String, s, 0);
s->TryFlatten();
const int length = s->length();
Handle<FixedArray> elements = Factory::NewUninitializedFixedArray(length);
if (s->IsFlat()) {
if (s->IsAsciiRepresentation()) {
Vector<const char> chars = s->ToAsciiVector();
int num_copied_from_cache = CopyCachedAsciiCharsToArray(chars.start(),
*elements,
length);
for (int i = num_copied_from_cache; i < length; ++i) {
elements->set(i, *LookupSingleCharacterStringFromCode(chars[i]));
}
} else {
ASSERT(s->IsTwoByteRepresentation());
Vector<const uc16> chars = s->ToUC16Vector();
for (int i = 0; i < length; ++i) {
elements->set(i, *LookupSingleCharacterStringFromCode(chars[i]));
}
}
} else {
for (int i = 0; i < length; ++i) {
elements->set(i, *LookupSingleCharacterStringFromCode(s->Get(i)));
}
}
#ifdef DEBUG
for (int i = 0; i < length; ++i) {
ASSERT(String::cast(elements->get(i))->length() == 1);
}
#endif
return *Factory::NewJSArrayWithElements(elements);
}
bool Runtime::IsUpperCaseChar(uint16_t ch) {
unibrow::uchar chars[unibrow::ToUppercase::kMaxWidth];
int char_length = to_upper_mapping.get(ch, 0, chars);

View File

@ -163,6 +163,7 @@ namespace internal {
F(StringReplaceRegExpWithString, 4, 1) \
F(StringMatch, 3, 1) \
F(StringTrim, 3, 1) \
F(StringToArray, 1, 1) \
\
/* Numbers */ \
F(NumberToRadixString, 2, 1) \

View File

@ -530,11 +530,7 @@ function StringSplit(separator, limit) {
var separator_length = separator.length;
// If the separator string is empty then return the elements in the subject.
if (separator_length === 0) {
var result = $Array(length);
for (var i = 0; i < length; i++) result[i] = subject[i];
return result;
}
if (separator_length === 0) return %StringToArray(subject);
var result = [];
var start_index = 0;