Index: src/builtins.cc |
diff --git a/src/builtins.cc b/src/builtins.cc |
index 90a8d3e1b843caa04ec42c00cc04457c13364c5c..4bb451cadedf6c8a0f9274e60b07610908697911 100644 |
--- a/src/builtins.cc |
+++ b/src/builtins.cc |
@@ -1,4 +1,4 @@ |
-// Copyright 2011 the V8 project authors. All rights reserved. |
+// Copyright 2012 the V8 project authors. All rights reserved. |
// Redistribution and use in source and binary forms, with or without |
// modification, are permitted provided that the following conditions are |
// met: |
@@ -193,13 +193,21 @@ static MaybeObject* ArrayCodeGenericCommon(Arguments* args, |
JSArray* array; |
if (CalledAsConstructor(isolate)) { |
array = JSArray::cast((*args)[0]); |
+ // Initialize elements and length in case later allocations fail so that the |
+ // array object is initialized in a valid state. |
+ array->set_length(Smi::FromInt(0)); |
+ array->set_elements(heap->empty_fixed_array()); |
+ if (!FLAG_smi_only_arrays) { |
+ if (array->GetElementsKind() == FAST_SMI_ONLY_ELEMENTS) { |
+ Context* global_context = isolate->context()->global_context(); |
+ array->set_map(Map::cast(global_context->object_js_array_map())); |
+ } |
+ } |
} else { |
// Allocate the JS Array |
- Object* obj; |
- { MaybeObject* maybe_obj = heap->AllocateJSObject(constructor); |
- if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
- } |
- array = JSArray::cast(obj); |
+ MaybeObject* maybe_obj = |
+ heap->AllocateEmptyJSArray(FAST_SMI_ONLY_ELEMENTS); |
+ if (!maybe_obj->To(&array)) return maybe_obj; |
} |
// Optimize the case where there is one argument and the argument is a |
@@ -301,29 +309,6 @@ BUILTIN(ArrayCodeGeneric) { |
} |
-MUST_USE_RESULT static MaybeObject* AllocateJSArray(Heap* heap) { |
- JSFunction* array_function = |
- heap->isolate()->context()->global_context()->array_function(); |
- Object* result; |
- { MaybeObject* maybe_result = heap->AllocateJSObject(array_function); |
- if (!maybe_result->ToObject(&result)) return maybe_result; |
- } |
- return result; |
-} |
- |
- |
-MUST_USE_RESULT static MaybeObject* AllocateEmptyJSArray(Heap* heap) { |
- Object* result; |
- { MaybeObject* maybe_result = AllocateJSArray(heap); |
- if (!maybe_result->ToObject(&result)) return maybe_result; |
- } |
- JSArray* result_array = JSArray::cast(result); |
- result_array->set_length(Smi::FromInt(0)); |
- result_array->set_elements(heap->empty_fixed_array()); |
- return result_array; |
-} |
- |
- |
static void CopyElements(Heap* heap, |
AssertNoAllocation* no_gc, |
FixedArray* dst, |
@@ -331,6 +316,7 @@ static void CopyElements(Heap* heap, |
FixedArray* src, |
int src_index, |
int len) { |
+ if (len == 0) return; |
ASSERT(dst != src); // Use MoveElements instead. |
ASSERT(dst->map() != HEAP->fixed_cow_array_map()); |
ASSERT(len > 0); |
@@ -352,6 +338,7 @@ static void MoveElements(Heap* heap, |
FixedArray* src, |
int src_index, |
int len) { |
+ if (len == 0) return; |
ASSERT(dst->map() != HEAP->fixed_cow_array_map()); |
memmove(dst->data_start() + dst_index, |
src->data_start() + src_index, |
@@ -543,9 +530,7 @@ BUILTIN(ArrayPush) { |
FixedArray* new_elms = FixedArray::cast(obj); |
AssertNoAllocation no_gc; |
- if (len > 0) { |
- CopyElements(heap, &no_gc, new_elms, 0, elms, 0, len); |
- } |
+ CopyElements(heap, &no_gc, new_elms, 0, elms, 0, len); |
FillWithHoles(heap, new_elms, new_length, capacity); |
elms = new_elms; |
@@ -681,9 +666,7 @@ BUILTIN(ArrayUnshift) { |
} |
FixedArray* new_elms = FixedArray::cast(obj); |
AssertNoAllocation no_gc; |
- if (len > 0) { |
- CopyElements(heap, &no_gc, new_elms, to_add, elms, 0, len); |
- } |
+ CopyElements(heap, &no_gc, new_elms, to_add, elms, 0, len); |
FillWithHoles(heap, new_elms, new_length, capacity); |
elms = new_elms; |
array->set_elements(elms); |
@@ -781,45 +764,22 @@ BUILTIN(ArraySlice) { |
int final = (relative_end < 0) ? Max(len + relative_end, 0) |
: Min(relative_end, len); |
- // Calculate the length of result array. |
- int result_len = final - k; |
- if (result_len <= 0) { |
- return AllocateEmptyJSArray(heap); |
- } |
- |
- Object* result; |
- { MaybeObject* maybe_result = AllocateJSArray(heap); |
- if (!maybe_result->ToObject(&result)) return maybe_result; |
- } |
- JSArray* result_array = JSArray::cast(result); |
+ ElementsKind elements_kind = JSObject::cast(receiver)->GetElementsKind(); |
- { MaybeObject* maybe_result = |
- heap->AllocateUninitializedFixedArray(result_len); |
- if (!maybe_result->ToObject(&result)) return maybe_result; |
- } |
- FixedArray* result_elms = FixedArray::cast(result); |
+ // Calculate the length of result array. |
+ int result_len = Max(final - k, 0); |
- MaybeObject* maybe_object = |
- result_array->EnsureCanContainElements(result_elms, |
- DONT_ALLOW_DOUBLE_ELEMENTS); |
- if (maybe_object->IsFailure()) return maybe_object; |
+ MaybeObject* maybe_array = |
+ heap->AllocateJSArrayAndStorage(elements_kind, |
+ result_len, |
+ result_len); |
+ JSArray* result_array; |
+ if (!maybe_array->To(&result_array)) return maybe_array; |
AssertNoAllocation no_gc; |
- CopyElements(heap, &no_gc, result_elms, 0, elms, k, result_len); |
- |
- // Set elements. |
- result_array->set_elements(result_elms); |
- |
- // Set the length. |
- result_array->set_length(Smi::FromInt(result_len)); |
+ CopyElements(heap, &no_gc, FixedArray::cast(result_array->elements()), 0, |
+ elms, k, result_len); |
- // Set the ElementsKind. |
- ElementsKind elements_kind = JSObject::cast(receiver)->GetElementsKind(); |
- if (IsMoreGeneralElementsKindTransition(result_array->GetElementsKind(), |
- elements_kind)) { |
- MaybeObject* maybe = result_array->TransitionElementsKind(elements_kind); |
- if (maybe->IsFailure()) return maybe; |
- } |
return result_array; |
} |
@@ -880,47 +840,22 @@ BUILTIN(ArraySplice) { |
} |
JSArray* result_array = NULL; |
- if (actual_delete_count == 0) { |
- Object* result; |
- { MaybeObject* maybe_result = AllocateEmptyJSArray(heap); |
- if (!maybe_result->ToObject(&result)) return maybe_result; |
- } |
- result_array = JSArray::cast(result); |
- } else { |
- // Allocate result array. |
- Object* result; |
- { MaybeObject* maybe_result = AllocateJSArray(heap); |
- if (!maybe_result->ToObject(&result)) return maybe_result; |
- } |
- result_array = JSArray::cast(result); |
- |
- { MaybeObject* maybe_result = |
- heap->AllocateUninitializedFixedArray(actual_delete_count); |
- if (!maybe_result->ToObject(&result)) return maybe_result; |
- } |
- FixedArray* result_elms = FixedArray::cast(result); |
+ ElementsKind elements_kind = |
+ JSObject::cast(receiver)->GetElementsKind(); |
+ MaybeObject* maybe_array = |
+ heap->AllocateJSArrayAndStorage(elements_kind, |
+ actual_delete_count, |
+ actual_delete_count); |
+ if (!maybe_array->To(&result_array)) return maybe_array; |
+ { |
AssertNoAllocation no_gc; |
// Fill newly created array. |
CopyElements(heap, |
&no_gc, |
- result_elms, 0, |
+ FixedArray::cast(result_array->elements()), 0, |
elms, actual_start, |
actual_delete_count); |
- |
- // Set elements. |
- result_array->set_elements(result_elms); |
- |
- // Set the length. |
- result_array->set_length(Smi::FromInt(actual_delete_count)); |
- |
- // Set the ElementsKind. |
- ElementsKind elements_kind = array->GetElementsKind(); |
- if (IsMoreGeneralElementsKindTransition(result_array->GetElementsKind(), |
- elements_kind)) { |
- MaybeObject* maybe = result_array->TransitionElementsKind(elements_kind); |
- if (maybe->IsFailure()) return maybe; |
- } |
} |
int item_count = (n_arguments > 1) ? (n_arguments - 2) : 0; |
@@ -935,7 +870,7 @@ BUILTIN(ArraySplice) { |
if (trim_array) { |
const int delta = actual_delete_count - item_count; |
- if (actual_start > 0) { |
+ { |
AssertNoAllocation no_gc; |
MoveElements(heap, &no_gc, elms, delta, elms, 0, actual_start); |
} |
@@ -967,18 +902,17 @@ BUILTIN(ArraySplice) { |
} |
FixedArray* new_elms = FixedArray::cast(obj); |
- AssertNoAllocation no_gc; |
- // Copy the part before actual_start as is. |
- if (actual_start > 0) { |
+ { |
+ AssertNoAllocation no_gc; |
+ // Copy the part before actual_start as is. |
CopyElements(heap, &no_gc, new_elms, 0, elms, 0, actual_start); |
- } |
- const int to_copy = len - actual_delete_count - actual_start; |
- if (to_copy > 0) { |
+ const int to_copy = len - actual_delete_count - actual_start; |
CopyElements(heap, &no_gc, |
new_elms, actual_start + item_count, |
elms, actual_start + actual_delete_count, |
to_copy); |
} |
+ |
FillWithHoles(heap, new_elms, new_length, capacity); |
elms = new_elms; |
@@ -1022,6 +956,7 @@ BUILTIN(ArrayConcat) { |
// and calculating total length. |
int n_arguments = args.length(); |
int result_len = 0; |
+ ElementsKind elements_kind = FAST_SMI_ONLY_ELEMENTS; |
for (int i = 0; i < n_arguments; i++) { |
Object* arg = args[i]; |
if (!arg->IsJSArray() || !JSArray::cast(arg)->HasFastTypeElements() |
@@ -1041,54 +976,34 @@ BUILTIN(ArrayConcat) { |
if (result_len > FixedArray::kMaxLength) { |
return CallJsBuiltin(isolate, "ArrayConcat", args); |
} |
- } |
- if (result_len == 0) { |
- return AllocateEmptyJSArray(heap); |
+ if (!JSArray::cast(arg)->HasFastElements()) { |
+ elements_kind = FAST_ELEMENTS; |
+ } |
} |
// Allocate result. |
- Object* result; |
- { MaybeObject* maybe_result = AllocateJSArray(heap); |
- if (!maybe_result->ToObject(&result)) return maybe_result; |
- } |
- JSArray* result_array = JSArray::cast(result); |
- |
- { MaybeObject* maybe_result = |
- heap->AllocateUninitializedFixedArray(result_len); |
- if (!maybe_result->ToObject(&result)) return maybe_result; |
- } |
- FixedArray* result_elms = FixedArray::cast(result); |
- |
- // Ensure element type transitions happen before copying elements in. |
- if (result_array->HasFastSmiOnlyElements()) { |
- for (int i = 0; i < n_arguments; i++) { |
- JSArray* array = JSArray::cast(args[i]); |
- if (!array->HasFastSmiOnlyElements()) { |
- result_array->EnsureCanContainHeapObjectElements(); |
- break; |
- } |
- } |
- } |
+ JSArray* result_array; |
+ MaybeObject* maybe_array = |
+ heap->AllocateJSArrayAndStorage(elements_kind, |
+ result_len, |
+ result_len); |
+ if (!maybe_array->To(&result_array)) return maybe_array; |
+ if (result_len == 0) return result_array; |
// Copy data. |
AssertNoAllocation no_gc; |
int start_pos = 0; |
+ FixedArray* result_elms(FixedArray::cast(result_array->elements())); |
for (int i = 0; i < n_arguments; i++) { |
JSArray* array = JSArray::cast(args[i]); |
int len = Smi::cast(array->length())->value(); |
- if (len > 0) { |
- FixedArray* elms = FixedArray::cast(array->elements()); |
- CopyElements(heap, &no_gc, result_elms, start_pos, elms, 0, len); |
- start_pos += len; |
- } |
+ FixedArray* elms = FixedArray::cast(array->elements()); |
+ CopyElements(heap, &no_gc, result_elms, start_pos, elms, 0, len); |
+ start_pos += len; |
} |
ASSERT(start_pos == result_len); |
- // Set the length and elements. |
- result_array->set_length(Smi::FromInt(result_len)); |
- result_array->set_elements(result_elms); |
- |
return result_array; |
} |