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

Unified Diff: src/builtins.cc

Issue 600124: Introduce builtin for Array.unshift function. (Closed)
Patch Set: Adding a test and fixing a bug with no args unshift. Plus Mads' comments Created 10 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/builtins.h ('k') | test/mjsunit/array-unshift.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/builtins.cc
diff --git a/src/builtins.cc b/src/builtins.cc
index 1159a213dce7b3961b8f58117371b34f42a28243..c68de9ac794adc7b37fa23530fc822ca5bf70d8e 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -246,19 +246,16 @@ BUILTIN(ArrayPush) {
JSArray* array = JSArray::cast(*args.receiver());
ASSERT(array->HasFastElements());
- // Make sure we have space for the elements.
int len = Smi::cast(array->length())->value();
+ int to_add = args.length() - 1;
+ if (to_add == 0) {
+ return Smi::FromInt(len);
+ }
- // Set new length.
- int new_length = len + args.length() - 1;
+ int new_length = len + to_add;
FixedArray* elms = FixedArray::cast(array->elements());
- if (new_length <= elms->length()) {
- // Backing storage has extra space for the provided values.
- for (int index = 0; index < args.length() - 1; index++) {
- elms->set(index + len, args[index+1]);
- }
- } else {
+ if (new_length > elms->length()) {
// New backing storage is needed.
int capacity = new_length + (new_length >> 1) + 16;
Object* obj = Heap::AllocateFixedArrayWithHoles(capacity);
@@ -269,16 +266,21 @@ BUILTIN(ArrayPush) {
WriteBarrierMode mode = new_elms->GetWriteBarrierMode(no_gc);
// Fill out the new array with old elements.
for (int i = 0; i < len; i++) new_elms->set(i, elms->get(i), mode);
- // Add the provided values.
- for (int index = 0; index < args.length() - 1; index++) {
- new_elms->set(index + len, args[index+1], mode);
- }
- // Set the new backing storage.
- array->set_elements(new_elms);
+ elms = new_elms;
+ array->set_elements(elms);
+ }
+
+ AssertNoAllocation no_gc;
+ WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
+
+ // Add the provided values.
+ for (int index = 0; index < to_add; index++) {
+ elms->set(index + len, args[index + 1], mode);
}
+
// Set the length.
array->set_length(Smi::FromInt(new_length));
- return array->length();
+ return Smi::FromInt(new_length);
}
@@ -313,6 +315,17 @@ BUILTIN(ArrayPop) {
}
+static Object* GetElementToMove(uint32_t index,
+ FixedArray* elms,
+ JSObject* prototype) {
+ Object* e = elms->get(index);
+ if (e->IsTheHole() && prototype->HasElement(index)) {
+ e = prototype->GetElement(index);
+ }
+ return e;
+}
+
+
BUILTIN(ArrayShift) {
JSArray* array = JSArray::cast(*args.receiver());
ASSERT(array->HasFastElements());
@@ -325,21 +338,17 @@ BUILTIN(ArrayShift) {
Top::context()->global_context()->array_function();
JSObject* prototype = JSObject::cast(array_function->prototype());
- // Get first element
FixedArray* elms = FixedArray::cast(array->elements());
- Object* first = elms->get(0);
+ // Get first element
+ Object* first = elms->get(0);
if (first->IsTheHole()) {
first = prototype->GetElement(0);
}
// Shift the elements.
for (int i = 0; i < len - 1; i++) {
- Object* e = elms->get(i + 1);
- if (e->IsTheHole() && prototype->HasElement(i + 1)) {
- e = prototype->GetElement(i + 1);
- }
- elms->set(i, e);
+ elms->set(i, GetElementToMove(i + 1, elms, prototype));
}
elms->set(len - 1, Heap::the_hole_value());
@@ -350,6 +359,66 @@ BUILTIN(ArrayShift) {
}
+BUILTIN(ArrayUnshift) {
+ JSArray* array = JSArray::cast(*args.receiver());
+ ASSERT(array->HasFastElements());
+
+ int len = Smi::cast(array->length())->value();
+ int to_add = args.length() - 1;
+ // Note that we cannot quit early if to_add == 0 as
+ // values should be lifted from prototype into
+ // the array.
+
+ int new_length = len + to_add;
+ FixedArray* elms = FixedArray::cast(array->elements());
+
+ // Fetch the prototype.
+ JSFunction* array_function =
+ Top::context()->global_context()->array_function();
+ JSObject* prototype = JSObject::cast(array_function->prototype());
+
+ if (new_length > elms->length()) {
+ // New backing storage is needed.
+ int capacity = new_length + (new_length >> 1) + 16;
+ Object* obj = Heap::AllocateFixedArrayWithHoles(capacity);
+ if (obj->IsFailure()) return obj;
+
+ AssertNoAllocation no_gc;
+ FixedArray* new_elms = FixedArray::cast(obj);
+ WriteBarrierMode mode = new_elms->GetWriteBarrierMode(no_gc);
+ // Fill out the new array with old elements.
+ for (int i = 0; i < len; i++)
+ new_elms->set(to_add + i,
+ GetElementToMove(i, elms, prototype),
+ mode);
+
+ elms = new_elms;
+ array->set_elements(elms);
+ } else {
+ AssertNoAllocation no_gc;
+ WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
+
+ // Move elements to the right
+ for (int i = 0; i < len; i++) {
+ elms->set(new_length - i - 1,
+ GetElementToMove(len - i - 1, elms, prototype),
+ mode);
+ }
+ }
+
+ // Add the provided values.
+ AssertNoAllocation no_gc;
+ WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
+ for (int i = 0; i < to_add; i++) {
+ elms->set(i, args[i + 1], mode);
+ }
+
+ // Set the length.
+ array->set_length(Smi::FromInt(new_length));
+ return Smi::FromInt(new_length);
+}
+
+
// -----------------------------------------------------------------------------
//
« no previous file with comments | « src/builtins.h ('k') | test/mjsunit/array-unshift.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698