| Index: src/runtime.cc
|
| diff --git a/src/runtime.cc b/src/runtime.cc
|
| index e473f3718903283c150c873e45a0142398a8996d..66c477fa46d82701834cccdd95246e0c140b314b 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,6 +436,7 @@ static Handle<Object> CreateArrayLiteralBoilerplate(
|
| is_cow ? elements : isolate->factory()->CopyFixedArray(elements);
|
|
|
| Handle<FixedArray> content = Handle<FixedArray>::cast(copied_elements);
|
| + bool has_non_constant_subexpression = true;
|
| if (is_cow) {
|
| #ifdef DEBUG
|
| // Copy-on-write arrays must be shallow (and simple).
|
| @@ -449,12 +454,21 @@ static Handle<Object> CreateArrayLiteralBoilerplate(
|
| CreateLiteralBoilerplate(isolate, literals, fa);
|
| if (result.is_null()) return result;
|
| content->set(i, *result);
|
| + } else {
|
| + has_non_constant_subexpression = true;
|
| }
|
| }
|
| }
|
|
|
| // Set the elements.
|
| - Handle<JSArray>::cast(object)->SetContent(*content);
|
| + Handle<JSArray> js_object(Handle<JSArray>::cast(object));
|
| + isolate->factory()->SetContent(js_object, content);
|
| +
|
| + // To simplify the code that fills in non-constant expressions, assume that
|
| + // any array literal that has non-constant expressions has non smi elements.
|
| + if (has_non_constant_subexpression && js_object->HasFastSmiOnlyElements()) {
|
| + isolate->factory()->EnsureCanContainNonSmiElements(js_object);
|
| + }
|
| return object;
|
| }
|
|
|
| @@ -2287,7 +2301,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);
|
| @@ -2295,7 +2310,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);
|
| @@ -2323,12 +2339,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_++;
|
| @@ -2353,7 +2372,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;
|
| }
|
| @@ -2361,6 +2380,7 @@ class FixedArrayBuilder {
|
| private:
|
| Handle<FixedArray> array_;
|
| int length_;
|
| + bool has_non_smi_elements_;
|
| };
|
|
|
|
|
| @@ -6190,6 +6210,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());
|
| @@ -6564,6 +6586,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());
|
| @@ -6791,7 +6816,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
|
| @@ -9047,6 +9073,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;
|
| @@ -9347,7 +9377,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++) {
|
| @@ -9578,6 +9608,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());
|
| @@ -9697,6 +9728,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.
|
| @@ -10020,7 +10052,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));
|
| @@ -11922,7 +11956,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;
|
| }
|
|
|
| @@ -12039,12 +12073,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);
|
| }
|
|
|
|
|
| @@ -12112,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);
|
| }
|
|
|
|
|
| @@ -13068,6 +13099,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)
|
|
|