Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(50)

Side by Side Diff: src/objects.cc

Issue 12041084: Object.observe: change array truncation logic to efficiently handle large sparse arrays (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Better handling of non-sparse arrays Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | test/mjsunit/harmony/object-observe.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 9333 matching lines...) Expand 10 before | Expand all | Expand 10 after
9344 return this; 9344 return this;
9345 } 9345 }
9346 9346
9347 9347
9348 void JSArray::Expand(int required_size) { 9348 void JSArray::Expand(int required_size) {
9349 GetIsolate()->factory()->SetElementsCapacityAndLength( 9349 GetIsolate()->factory()->SetElementsCapacityAndLength(
9350 Handle<JSArray>(this), required_size, required_size); 9350 Handle<JSArray>(this), required_size, required_size);
9351 } 9351 }
9352 9352
9353 9353
9354 // Returns false if the passed-in index is marked non-configurable,
9355 // which will cause the ES5 truncation operation to halt, and thus
9356 // no further old values need be collected.
9357 static bool GetOldValue(Isolate* isolate,
9358 Handle<JSObject> object,
9359 uint32_t index,
9360 List<Handle<Object> >* old_values,
9361 List<Handle<String> >* indices) {
9362 PropertyAttributes attributes = object->GetLocalElementAttribute(index);
9363 ASSERT(attributes != ABSENT);
9364 if (attributes == DONT_DELETE) return false;
9365 old_values->Add(object->GetLocalElementAccessorPair(index) == NULL
9366 ? Object::GetElement(object, index)
9367 : Handle<Object>::cast(isolate->factory()->the_hole_value()));
9368 indices->Add(isolate->factory()->Uint32ToString(index));
9369 return true;
9370 }
9371
9372
9354 MaybeObject* JSArray::SetElementsLength(Object* len) { 9373 MaybeObject* JSArray::SetElementsLength(Object* len) {
9355 // We should never end in here with a pixel or external array. 9374 // We should never end in here with a pixel or external array.
9356 ASSERT(AllowsSetElementsLength()); 9375 ASSERT(AllowsSetElementsLength());
9357 if (!(FLAG_harmony_observation && map()->is_observed())) 9376 if (!(FLAG_harmony_observation && map()->is_observed()))
9358 return GetElementsAccessor()->SetLength(this, len); 9377 return GetElementsAccessor()->SetLength(this, len);
9359 9378
9360 Isolate* isolate = GetIsolate(); 9379 Isolate* isolate = GetIsolate();
9361 HandleScope scope(isolate); 9380 HandleScope scope(isolate);
9362 Handle<JSArray> self(this); 9381 Handle<JSArray> self(this);
9363 List<Handle<String> > indices; 9382 List<Handle<String> > indices;
9364 List<Handle<Object> > old_values; 9383 List<Handle<Object> > old_values;
9365 Handle<Object> old_length_handle(self->length()); 9384 Handle<Object> old_length_handle(self->length());
9366 Handle<Object> new_length_handle(len); 9385 Handle<Object> new_length_handle(len);
9367 uint32_t old_length = 0; 9386 uint32_t old_length = 0;
9368 CHECK(old_length_handle->ToArrayIndex(&old_length)); 9387 CHECK(old_length_handle->ToArrayIndex(&old_length));
9369 uint32_t new_length = 0; 9388 uint32_t new_length = 0;
9370 if (!new_length_handle->ToArrayIndex(&new_length)) 9389 if (!new_length_handle->ToArrayIndex(&new_length))
9371 return Failure::InternalError(); 9390 return Failure::InternalError();
9372 9391
9373 // TODO(adamk): This loop can be very slow for arrays in dictionary mode. 9392 // Observed arrays should always be in dictionary mode;
9374 // Find another way to iterate over arrays with dictionary elements. 9393 // if they were in fast mode, the below is slower than necessary
9375 for (uint32_t i = old_length - 1; i + 1 > new_length; --i) { 9394 // as it iterates over the array backing store multiple times.
9376 PropertyAttributes attributes = self->GetLocalElementAttribute(i); 9395 ASSERT(self->HasDictionaryElements());
9377 if (attributes == ABSENT) continue; 9396 static const PropertyAttributes kNoAttrFilter = NONE;
9378 // A non-configurable property will cause the truncation operation to 9397 int num_elements = self->NumberOfLocalElements(kNoAttrFilter);
9379 // stop at this index. 9398 if (num_elements > 0) {
9380 if (attributes == DONT_DELETE) break; 9399 if (old_length == static_cast<uint32_t>(num_elements)) {
9381 old_values.Add( 9400 // Simple case for arrays without holes.
9382 self->GetLocalElementAccessorPair(i) == NULL 9401 for (uint32_t i = old_length - 1; i + 1 > new_length; --i) {
9383 ? Object::GetElement(self, i) 9402 if (!GetOldValue(isolate, self, i, &old_values, &indices)) break;
9384 : Handle<Object>::cast(isolate->factory()->the_hole_value())); 9403 }
9385 indices.Add(isolate->factory()->Uint32ToString(i)); 9404 } else {
9405 // For sparse arrays, only iterate over existing elements.
9406 Handle<FixedArray> keys = isolate->factory()->NewFixedArray(num_elements);
9407 self->GetLocalElementKeys(*keys, kNoAttrFilter);
9408 while (num_elements-- > 0) {
9409 uint32_t index = NumberToUint32(keys->get(num_elements));
9410 if (index < new_length) break;
9411 if (!GetOldValue(isolate, self, index, &old_values, &indices)) break;
9412 }
9413 }
9386 } 9414 }
9387 9415
9388 MaybeObject* result = 9416 MaybeObject* result =
9389 self->GetElementsAccessor()->SetLength(*self, *new_length_handle); 9417 self->GetElementsAccessor()->SetLength(*self, *new_length_handle);
9390 Handle<Object> hresult; 9418 Handle<Object> hresult;
9391 if (!result->ToHandle(&hresult, isolate)) return result; 9419 if (!result->ToHandle(&hresult, isolate)) return result;
9392 9420
9393 CHECK(self->length()->ToArrayIndex(&new_length)); 9421 CHECK(self->length()->ToArrayIndex(&new_length));
9394 if (old_length != new_length) { 9422 if (old_length != new_length) {
9395 for (int i = 0; i < indices.length(); ++i) { 9423 for (int i = 0; i < indices.length(); ++i) {
(...skipping 4459 matching lines...) Expand 10 before | Expand all | Expand 10 after
13855 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); 13883 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
13856 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); 13884 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
13857 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); 13885 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
13858 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); 13886 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
13859 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); 13887 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
13860 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); 13888 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
13861 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); 13889 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
13862 } 13890 }
13863 13891
13864 } } // namespace v8::internal 13892 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | test/mjsunit/harmony/object-observe.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698