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

Side by Side 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 unified diff | Download patch
« no previous file with comments | « src/builtins.h ('k') | test/mjsunit/array-unshift.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 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 array->set_length(len); 239 array->set_length(len);
240 240
241 return array; 241 return array;
242 } 242 }
243 243
244 244
245 BUILTIN(ArrayPush) { 245 BUILTIN(ArrayPush) {
246 JSArray* array = JSArray::cast(*args.receiver()); 246 JSArray* array = JSArray::cast(*args.receiver());
247 ASSERT(array->HasFastElements()); 247 ASSERT(array->HasFastElements());
248 248
249 // Make sure we have space for the elements.
250 int len = Smi::cast(array->length())->value(); 249 int len = Smi::cast(array->length())->value();
250 int to_add = args.length() - 1;
251 if (to_add == 0) {
252 return Smi::FromInt(len);
253 }
251 254
252 // Set new length. 255 int new_length = len + to_add;
253 int new_length = len + args.length() - 1;
254 FixedArray* elms = FixedArray::cast(array->elements()); 256 FixedArray* elms = FixedArray::cast(array->elements());
255 257
256 if (new_length <= elms->length()) { 258 if (new_length > elms->length()) {
257 // Backing storage has extra space for the provided values.
258 for (int index = 0; index < args.length() - 1; index++) {
259 elms->set(index + len, args[index+1]);
260 }
261 } else {
262 // New backing storage is needed. 259 // New backing storage is needed.
263 int capacity = new_length + (new_length >> 1) + 16; 260 int capacity = new_length + (new_length >> 1) + 16;
264 Object* obj = Heap::AllocateFixedArrayWithHoles(capacity); 261 Object* obj = Heap::AllocateFixedArrayWithHoles(capacity);
265 if (obj->IsFailure()) return obj; 262 if (obj->IsFailure()) return obj;
266 263
267 AssertNoAllocation no_gc; 264 AssertNoAllocation no_gc;
268 FixedArray* new_elms = FixedArray::cast(obj); 265 FixedArray* new_elms = FixedArray::cast(obj);
269 WriteBarrierMode mode = new_elms->GetWriteBarrierMode(no_gc); 266 WriteBarrierMode mode = new_elms->GetWriteBarrierMode(no_gc);
270 // Fill out the new array with old elements. 267 // Fill out the new array with old elements.
271 for (int i = 0; i < len; i++) new_elms->set(i, elms->get(i), mode); 268 for (int i = 0; i < len; i++) new_elms->set(i, elms->get(i), mode);
272 // Add the provided values. 269 elms = new_elms;
273 for (int index = 0; index < args.length() - 1; index++) { 270 array->set_elements(elms);
274 new_elms->set(index + len, args[index+1], mode);
275 }
276 // Set the new backing storage.
277 array->set_elements(new_elms);
278 } 271 }
272
273 AssertNoAllocation no_gc;
274 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
275
276 // Add the provided values.
277 for (int index = 0; index < to_add; index++) {
278 elms->set(index + len, args[index + 1], mode);
279 }
280
279 // Set the length. 281 // Set the length.
280 array->set_length(Smi::FromInt(new_length)); 282 array->set_length(Smi::FromInt(new_length));
281 return array->length(); 283 return Smi::FromInt(new_length);
282 } 284 }
283 285
284 286
285 BUILTIN(ArrayPop) { 287 BUILTIN(ArrayPop) {
286 JSArray* array = JSArray::cast(*args.receiver()); 288 JSArray* array = JSArray::cast(*args.receiver());
287 ASSERT(array->HasFastElements()); 289 ASSERT(array->HasFastElements());
288 Object* undefined = Heap::undefined_value(); 290 Object* undefined = Heap::undefined_value();
289 291
290 int len = Smi::cast(array->length())->value(); 292 int len = Smi::cast(array->length())->value();
291 if (len == 0) return undefined; 293 if (len == 0) return undefined;
(...skipping 14 matching lines...) Expand all
306 // Remember to check the prototype chain. 308 // Remember to check the prototype chain.
307 JSFunction* array_function = 309 JSFunction* array_function =
308 Top::context()->global_context()->array_function(); 310 Top::context()->global_context()->array_function();
309 JSObject* prototype = JSObject::cast(array_function->prototype()); 311 JSObject* prototype = JSObject::cast(array_function->prototype());
310 top = prototype->GetElement(len - 1); 312 top = prototype->GetElement(len - 1);
311 313
312 return top; 314 return top;
313 } 315 }
314 316
315 317
318 static Object* GetElementToMove(uint32_t index,
319 FixedArray* elms,
320 JSObject* prototype) {
321 Object* e = elms->get(index);
322 if (e->IsTheHole() && prototype->HasElement(index)) {
323 e = prototype->GetElement(index);
324 }
325 return e;
326 }
327
328
316 BUILTIN(ArrayShift) { 329 BUILTIN(ArrayShift) {
317 JSArray* array = JSArray::cast(*args.receiver()); 330 JSArray* array = JSArray::cast(*args.receiver());
318 ASSERT(array->HasFastElements()); 331 ASSERT(array->HasFastElements());
319 332
320 int len = Smi::cast(array->length())->value(); 333 int len = Smi::cast(array->length())->value();
321 if (len == 0) return Heap::undefined_value(); 334 if (len == 0) return Heap::undefined_value();
322 335
323 // Fetch the prototype. 336 // Fetch the prototype.
324 JSFunction* array_function = 337 JSFunction* array_function =
325 Top::context()->global_context()->array_function(); 338 Top::context()->global_context()->array_function();
326 JSObject* prototype = JSObject::cast(array_function->prototype()); 339 JSObject* prototype = JSObject::cast(array_function->prototype());
327 340
341 FixedArray* elms = FixedArray::cast(array->elements());
342
328 // Get first element 343 // Get first element
329 FixedArray* elms = FixedArray::cast(array->elements());
330 Object* first = elms->get(0); 344 Object* first = elms->get(0);
331
332 if (first->IsTheHole()) { 345 if (first->IsTheHole()) {
333 first = prototype->GetElement(0); 346 first = prototype->GetElement(0);
334 } 347 }
335 348
336 // Shift the elements. 349 // Shift the elements.
337 for (int i = 0; i < len - 1; i++) { 350 for (int i = 0; i < len - 1; i++) {
338 Object* e = elms->get(i + 1); 351 elms->set(i, GetElementToMove(i + 1, elms, prototype));
339 if (e->IsTheHole() && prototype->HasElement(i + 1)) {
340 e = prototype->GetElement(i + 1);
341 }
342 elms->set(i, e);
343 } 352 }
344 elms->set(len - 1, Heap::the_hole_value()); 353 elms->set(len - 1, Heap::the_hole_value());
345 354
346 // Set the length. 355 // Set the length.
347 array->set_length(Smi::FromInt(len - 1)); 356 array->set_length(Smi::FromInt(len - 1));
348 357
349 return first; 358 return first;
350 } 359 }
351 360
352 361
362 BUILTIN(ArrayUnshift) {
363 JSArray* array = JSArray::cast(*args.receiver());
364 ASSERT(array->HasFastElements());
365
366 int len = Smi::cast(array->length())->value();
367 int to_add = args.length() - 1;
368 // Note that we cannot quit early if to_add == 0 as
369 // values should be lifted from prototype into
370 // the array.
371
372 int new_length = len + to_add;
373 FixedArray* elms = FixedArray::cast(array->elements());
374
375 // Fetch the prototype.
376 JSFunction* array_function =
377 Top::context()->global_context()->array_function();
378 JSObject* prototype = JSObject::cast(array_function->prototype());
379
380 if (new_length > elms->length()) {
381 // New backing storage is needed.
382 int capacity = new_length + (new_length >> 1) + 16;
383 Object* obj = Heap::AllocateFixedArrayWithHoles(capacity);
384 if (obj->IsFailure()) return obj;
385
386 AssertNoAllocation no_gc;
387 FixedArray* new_elms = FixedArray::cast(obj);
388 WriteBarrierMode mode = new_elms->GetWriteBarrierMode(no_gc);
389 // Fill out the new array with old elements.
390 for (int i = 0; i < len; i++)
391 new_elms->set(to_add + i,
392 GetElementToMove(i, elms, prototype),
393 mode);
394
395 elms = new_elms;
396 array->set_elements(elms);
397 } else {
398 AssertNoAllocation no_gc;
399 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
400
401 // Move elements to the right
402 for (int i = 0; i < len; i++) {
403 elms->set(new_length - i - 1,
404 GetElementToMove(len - i - 1, elms, prototype),
405 mode);
406 }
407 }
408
409 // Add the provided values.
410 AssertNoAllocation no_gc;
411 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
412 for (int i = 0; i < to_add; i++) {
413 elms->set(i, args[i + 1], mode);
414 }
415
416 // Set the length.
417 array->set_length(Smi::FromInt(new_length));
418 return Smi::FromInt(new_length);
419 }
420
421
353 // ----------------------------------------------------------------------------- 422 // -----------------------------------------------------------------------------
354 // 423 //
355 424
356 425
357 // Returns the holder JSObject if the function can legally be called 426 // Returns the holder JSObject if the function can legally be called
358 // with this receiver. Returns Heap::null_value() if the call is 427 // with this receiver. Returns Heap::null_value() if the call is
359 // illegal. Any arguments that don't fit the expected type is 428 // illegal. Any arguments that don't fit the expected type is
360 // overwritten with undefined. Arguments that do fit the expected 429 // overwritten with undefined. Arguments that do fit the expected
361 // type is overwritten with the object in the prototype chain that 430 // type is overwritten with the object in the prototype chain that
362 // actually has that type. 431 // actually has that type.
(...skipping 626 matching lines...) Expand 10 before | Expand all | Expand 10 after
989 if (entry->contains(pc)) { 1058 if (entry->contains(pc)) {
990 return names_[i]; 1059 return names_[i];
991 } 1060 }
992 } 1061 }
993 } 1062 }
994 return NULL; 1063 return NULL;
995 } 1064 }
996 1065
997 1066
998 } } // namespace v8::internal 1067 } } // namespace v8::internal
OLDNEW
« 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