Index: src/runtime.cc |
diff --git a/src/runtime.cc b/src/runtime.cc |
index a51fcd35429917418bfc75b926f10f75d880dacf..cb6307250fa80a984911bfd5d8afb130b8baac54 100644 |
--- a/src/runtime.cc |
+++ b/src/runtime.cc |
@@ -177,6 +177,7 @@ MUST_USE_RESULT static MaybeObject* DeepCopyBoilerplate(Isolate* isolate, |
// Pixel elements cannot be created using an object literal. |
ASSERT(!copy->HasExternalArrayElements()); |
switch (copy->GetElementsKind()) { |
+ case FAST_SMI_ONLY_ELEMENTS: |
case FAST_ELEMENTS: { |
FixedArray* elements = FixedArray::cast(copy->elements()); |
if (elements->map() == heap->fixed_cow_array_map()) { |
@@ -189,6 +190,9 @@ MUST_USE_RESULT static MaybeObject* DeepCopyBoilerplate(Isolate* isolate, |
} else { |
for (int i = 0; i < elements->length(); i++) { |
Object* value = elements->get(i); |
+ ASSERT(value->IsSmi() || |
+ value->IsTheHole() || |
+ (copy->GetElementsKind() == FAST_ELEMENTS)); |
if (value->IsJSObject()) { |
JSObject* js_object = JSObject::cast(value); |
{ MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, |
@@ -432,16 +436,28 @@ static Handle<Object> CreateArrayLiteralBoilerplate( |
is_cow ? elements : isolate->factory()->CopyFixedArray(elements); |
Handle<FixedArray> content = Handle<FixedArray>::cast(copied_elements); |
+ bool has_non_smi = false; |
if (is_cow) { |
-#ifdef DEBUG |
// Copy-on-write arrays must be shallow (and simple). |
- for (int i = 0; i < content->length(); i++) { |
- ASSERT(!content->get(i)->IsFixedArray()); |
- } |
+ if (FLAG_smi_only_arrays) { |
+ for (int i = 0; i < content->length(); i++) { |
+ Object* current = content->get(i); |
+ ASSERT(!current->IsFixedArray()); |
+ if (!current->IsSmi()) { |
+ has_non_smi = true; |
+ } |
+ } |
+ } else { |
+#if DEBUG |
+ for (int i = 0; i < content->length(); i++) { |
+ ASSERT(!content->get(i)->IsFixedArray()); |
+ } |
#endif |
+ } |
} else { |
for (int i = 0; i < content->length(); i++) { |
- if (content->get(i)->IsFixedArray()) { |
+ Object* current = content->get(i); |
+ if (current->IsFixedArray()) { |
// The value contains the constant_properties of a |
// simple object or array literal. |
Handle<FixedArray> fa(FixedArray::cast(content->get(i))); |
@@ -449,12 +465,25 @@ static Handle<Object> CreateArrayLiteralBoilerplate( |
CreateLiteralBoilerplate(isolate, literals, fa); |
if (result.is_null()) return result; |
content->set(i, *result); |
+ has_non_smi = true; |
+ } else { |
+ if (!current->IsSmi()) { |
+ has_non_smi = true; |
+ } |
} |
} |
} |
// Set the elements. |
- Handle<JSArray>::cast(object)->SetContent(*content); |
+ Handle<JSArray> js_object(Handle<JSArray>::cast(object)); |
+ isolate->factory()->SetContent(js_object, content); |
+ |
+ if (FLAG_smi_only_arrays) { |
+ if (has_non_smi && js_object->HasFastSmiOnlyElements()) { |
+ isolate->factory()->EnsureCanContainNonSmiElements(js_object); |
+ } |
+ } |
+ |
return object; |
} |
@@ -1631,6 +1660,19 @@ RUNTIME_FUNCTION(MaybeObject*, |
} |
+RUNTIME_FUNCTION(MaybeObject*, Runtime_NonSmiElementStored) { |
+ ASSERT(args.length() == 1); |
+ CONVERT_ARG_CHECKED(JSObject, object, 0); |
+ if (FLAG_smi_only_arrays && object->HasFastSmiOnlyElements()) { |
+ MaybeObject* maybe_map = object->GetElementsTransitionMap(FAST_ELEMENTS); |
+ Map* map; |
+ if (!maybe_map->To<Map>(&map)) return maybe_map; |
+ object->set_map(Map::cast(map)); |
+ } |
+ return *object; |
+} |
+ |
+ |
RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExec) { |
HandleScope scope(isolate); |
ASSERT(args.length() == 4); |
@@ -2214,7 +2256,8 @@ class FixedArrayBuilder { |
public: |
explicit FixedArrayBuilder(Isolate* isolate, int initial_capacity) |
: array_(isolate->factory()->NewFixedArrayWithHoles(initial_capacity)), |
- length_(0) { |
+ length_(0), |
+ has_non_smi_elements_(false) { |
// Require a non-zero initial size. Ensures that doubling the size to |
// extend the array will work. |
ASSERT(initial_capacity > 0); |
@@ -2222,7 +2265,8 @@ class FixedArrayBuilder { |
explicit FixedArrayBuilder(Handle<FixedArray> backing_store) |
: array_(backing_store), |
- length_(0) { |
+ length_(0), |
+ has_non_smi_elements_(false) { |
// Require a non-zero initial size. Ensures that doubling the size to |
// extend the array will work. |
ASSERT(backing_store->length() > 0); |
@@ -2250,12 +2294,15 @@ class FixedArrayBuilder { |
} |
void Add(Object* value) { |
+ ASSERT(!value->IsSmi()); |
ASSERT(length_ < capacity()); |
array_->set(length_, value); |
length_++; |
+ has_non_smi_elements_ = true; |
} |
void Add(Smi* value) { |
+ ASSERT(value->IsSmi()); |
ASSERT(length_ < capacity()); |
array_->set(length_, value); |
length_++; |
@@ -2280,7 +2327,7 @@ class FixedArrayBuilder { |
} |
Handle<JSArray> ToJSArray(Handle<JSArray> target_array) { |
- target_array->set_elements(*array_); |
+ FACTORY->SetContent(target_array, array_); |
target_array->set_length(Smi::FromInt(length_)); |
return target_array; |
} |
@@ -2288,6 +2335,7 @@ class FixedArrayBuilder { |
private: |
Handle<FixedArray> array_; |
int length_; |
+ bool has_non_smi_elements_; |
}; |
@@ -6121,6 +6169,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringSplit) { |
int part_count = indices.length(); |
Handle<JSArray> result = isolate->factory()->NewJSArray(part_count); |
+ MaybeObject* maybe_result = result->EnsureCanContainNonSmiElements(); |
+ if (maybe_result->IsFailure()) return maybe_result; |
result->set_length(Smi::FromInt(part_count)); |
ASSERT(result->HasFastElements()); |
@@ -6495,6 +6545,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) { |
// This assumption is used by the slice encoding in one or two smis. |
ASSERT(Smi::kMaxValue >= String::kMaxLength); |
+ MaybeObject* maybe_result = array->EnsureCanContainNonSmiElements(); |
+ if (maybe_result->IsFailure()) return maybe_result; |
+ |
int special_length = special->length(); |
if (!array->HasFastElements()) { |
return isolate->Throw(isolate->heap()->illegal_argument_symbol()); |
@@ -6722,7 +6775,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SparseJoinWithSeparator) { |
NoHandleAllocation ha; |
ASSERT(args.length() == 3); |
CONVERT_CHECKED(JSArray, elements_array, args[0]); |
- RUNTIME_ASSERT(elements_array->HasFastElements()); |
+ RUNTIME_ASSERT(elements_array->HasFastElements() || |
+ elements_array->HasFastSmiOnlyElements()); |
CONVERT_NUMBER_CHECKED(uint32_t, array_length, Uint32, args[1]); |
CONVERT_CHECKED(String, separator, args[2]); |
// elements_array is fast-mode JSarray of alternating positions |
@@ -7889,7 +7943,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObjectFromBound) { |
int bound_argc = 0; |
if (!args[1]->IsNull()) { |
CONVERT_ARG_CHECKED(JSArray, params, 1); |
- RUNTIME_ASSERT(params->HasFastElements()); |
+ RUNTIME_ASSERT(params->HasFastTypeElements()); |
bound_args = Handle<FixedArray>(FixedArray::cast(params->elements())); |
bound_argc = Smi::cast(params->length())->value(); |
} |
@@ -8984,6 +9038,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DateParseString) { |
FlattenString(str); |
CONVERT_ARG_CHECKED(JSArray, output, 1); |
+ |
+ MaybeObject* maybe_result_array = |
+ output->EnsureCanContainNonSmiElements(); |
+ if (maybe_result_array->IsFailure()) return maybe_result_array; |
RUNTIME_ASSERT(output->HasFastElements()); |
AssertNoAllocation no_allocation; |
@@ -9287,7 +9345,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_PushIfAbsent) { |
ASSERT(args.length() == 2); |
CONVERT_CHECKED(JSArray, array, args[0]); |
CONVERT_CHECKED(JSObject, element, args[1]); |
- RUNTIME_ASSERT(array->HasFastElements()); |
+ RUNTIME_ASSERT(array->HasFastElements() || array->HasFastSmiOnlyElements()); |
int length = Smi::cast(array->length())->value(); |
FixedArray* elements = FixedArray::cast(array->elements()); |
for (int i = 0; i < length; i++) { |
@@ -9518,6 +9576,7 @@ static void CollectElementIndices(Handle<JSObject> object, |
List<uint32_t>* indices) { |
ElementsKind kind = object->GetElementsKind(); |
switch (kind) { |
+ case FAST_SMI_ONLY_ELEMENTS: |
case FAST_ELEMENTS: { |
Handle<FixedArray> elements(FixedArray::cast(object->elements())); |
uint32_t length = static_cast<uint32_t>(elements->length()); |
@@ -9637,6 +9696,7 @@ static bool IterateElements(Isolate* isolate, |
ArrayConcatVisitor* visitor) { |
uint32_t length = static_cast<uint32_t>(receiver->length()->Number()); |
switch (receiver->GetElementsKind()) { |
+ case FAST_SMI_ONLY_ELEMENTS: |
case FAST_ELEMENTS: { |
// Run through the elements FixedArray and use HasElement and GetElement |
// to check the prototype for missing elements. |
@@ -9960,7 +10020,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArrayKeys) { |
} |
return *isolate->factory()->NewJSArrayWithElements(keys); |
} else { |
- ASSERT(array->HasFastElements() || array->HasFastDoubleElements()); |
+ ASSERT(array->HasFastElements() || |
+ array->HasFastSmiOnlyElements() || |
+ array->HasFastDoubleElements()); |
Handle<FixedArray> single_interval = isolate->factory()->NewFixedArray(2); |
// -1 means start of array. |
single_interval->set(0, Smi::FromInt(-1)); |
@@ -11870,7 +11932,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetLoadedScripts) { |
// Return result as a JS array. |
Handle<JSObject> result = |
isolate->factory()->NewJSObject(isolate->array_function()); |
- Handle<JSArray>::cast(result)->SetContent(*instances); |
+ isolate->factory()->SetContent(Handle<JSArray>::cast(result), instances); |
return *result; |
} |
@@ -11998,12 +12060,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugReferencedBy) { |
// Return result as JS array. |
Object* result; |
- { MaybeObject* maybe_result = isolate->heap()->AllocateJSObject( |
+ MaybeObject* maybe_result = isolate->heap()->AllocateJSObject( |
isolate->context()->global_context()->array_function()); |
- if (!maybe_result->ToObject(&result)) return maybe_result; |
- } |
- JSArray::cast(result)->SetContent(instances); |
- return result; |
+ if (!maybe_result->ToObject(&result)) return maybe_result; |
+ return JSArray::cast(result)->SetContent(instances); |
} |
@@ -12084,8 +12144,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugConstructedBy) { |
isolate->context()->global_context()->array_function()); |
if (!maybe_result->ToObject(&result)) return maybe_result; |
} |
- JSArray::cast(result)->SetContent(instances); |
- return result; |
+ return JSArray::cast(result)->SetContent(instances); |
} |
@@ -13057,6 +13116,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_IS_VAR) { |
return isolate->heap()->ToBoolean(obj->Has##Name()); \ |
} |
+ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiOnlyElements) |
ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastElements) |
ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastDoubleElements) |
ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements) |