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

Side by Side Diff: src/builtins.cc

Issue 660245: Faster moving FixedArray elements around. (Closed)
Patch Set: Next round Created 10 years, 9 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/array.js ('k') | src/heap.h » ('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 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
235 } 235 }
236 236
237 // Set length and elements on the array. 237 // Set length and elements on the array.
238 array->set_elements(FixedArray::cast(obj)); 238 array->set_elements(FixedArray::cast(obj));
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 static Object* AllocateUninitializedFixedArray(int len) {
246 Object* obj = Heap::AllocateRawFixedArray(len);
247 if (obj->IsFailure()) return obj;
248
249 reinterpret_cast<FixedArray*>(obj)->set_map(Heap::fixed_array_map());
250 FixedArray::cast(obj)->set_length(len);
251 return obj;
252 }
253
254
255 static Object* AllocateJSArray() {
256 JSFunction* array_function =
257 Top::context()->global_context()->array_function();
258 Object* result = Heap::AllocateJSObject(array_function);
259 if (result->IsFailure()) return result;
260 return result;
261 }
262
263
264 static void CopyElements(AssertNoAllocation* no_gc,
265 FixedArray* dst,
266 int dst_index,
267 FixedArray* src,
268 int src_index,
269 int len) {
270 ASSERT(dst != src); // Use MoveElements instead.
271 memcpy(dst->data_start() + dst_index,
272 src->data_start() + src_index,
273 len * kPointerSize);
274 WriteBarrierMode mode = dst->GetWriteBarrierMode(*no_gc);
275 if (mode == UPDATE_WRITE_BARRIER) {
276 Heap::RecordWrites(dst->address(), dst->OffsetOfElementAt(dst_index), len);
277 }
278 }
279
280
281 static void MoveElements(AssertNoAllocation* no_gc,
282 FixedArray* dst,
283 int dst_index,
284 FixedArray* src,
285 int src_index,
286 int len) {
287 memmove(dst->data_start() + dst_index,
288 src->data_start() + src_index,
289 len * kPointerSize);
290 WriteBarrierMode mode = dst->GetWriteBarrierMode(*no_gc);
291 if (mode == UPDATE_WRITE_BARRIER) {
292 Heap::RecordWrites(dst->address(), dst->OffsetOfElementAt(dst_index), len);
293 }
294 }
295
296
297 static void FillWithHoles(FixedArray* dst, int from, int to) {
298 MemsetPointer(dst->data_start() + from, Heap::the_hole_value(), to - from);
299 }
300
301
302 static bool ArrayPrototypeHasNoElements() {
303 // This method depends on non writability of Object and Array prototype
304 // fields.
305 Context* global_context = Top::context()->global_context();
306 // Array.prototype
307 JSObject* proto =
308 JSObject::cast(global_context->array_function()->prototype());
309 if (proto->elements() != Heap::empty_fixed_array()) return false;
310 // Hidden prototype
311 proto = JSObject::cast(proto->GetPrototype());
312 ASSERT(proto->elements() == Heap::empty_fixed_array());
313 // Object.prototype
314 proto = JSObject::cast(proto->GetPrototype());
315 if (proto != global_context->initial_object_prototype()) return false;
316 if (proto->elements() != Heap::empty_fixed_array()) return false;
317 ASSERT(proto->GetPrototype()->IsNull());
318 return true;
319 }
320
321
322 static Object* CallJsBuiltin(const char* name,
323 BuiltinArguments<NO_EXTRA_ARGUMENTS> args) {
324 HandleScope handleScope;
325
326 Handle<Object> js_builtin =
327 GetProperty(Handle<JSObject>(Top::global_context()->builtins()),
328 name);
329 ASSERT(js_builtin->IsJSFunction());
330 Handle<JSFunction> function(Handle<JSFunction>::cast(js_builtin));
331 Vector<Object**> argv(Vector<Object**>::New(args.length() - 1));
332 int n_args = args.length() - 1;
333 for (int i = 0; i < n_args; i++) {
334 argv[i] = &args[i + 1];
335 }
336 bool pending_exception = false;
337 Handle<Object> result = Execution::Call(function,
338 args.receiver(),
339 n_args,
340 argv.start(),
341 &pending_exception);
342 if (pending_exception) return Failure::Exception();
343 return *result;
344 }
345
346
245 BUILTIN(ArrayPush) { 347 BUILTIN(ArrayPush) {
246 JSArray* array = JSArray::cast(*args.receiver()); 348 JSArray* array = JSArray::cast(*args.receiver());
247 ASSERT(array->HasFastElements()); 349 ASSERT(array->HasFastElements());
248 350
249 int len = Smi::cast(array->length())->value(); 351 int len = Smi::cast(array->length())->value();
250 int to_add = args.length() - 1; 352 int to_add = args.length() - 1;
251 if (to_add == 0) { 353 if (to_add == 0) {
252 return Smi::FromInt(len); 354 return Smi::FromInt(len);
253 } 355 }
254 // Currently fixed arrays cannot grow too big, so 356 // Currently fixed arrays cannot grow too big, so
255 // we should never hit this case. 357 // we should never hit this case.
256 ASSERT(to_add <= (Smi::kMaxValue - len)); 358 ASSERT(to_add <= (Smi::kMaxValue - len));
257 359
258 int new_length = len + to_add; 360 int new_length = len + to_add;
259 FixedArray* elms = FixedArray::cast(array->elements()); 361 FixedArray* elms = FixedArray::cast(array->elements());
260 362
261 if (new_length > elms->length()) { 363 if (new_length > elms->length()) {
262 // New backing storage is needed. 364 // New backing storage is needed.
263 int capacity = new_length + (new_length >> 1) + 16; 365 int capacity = new_length + (new_length >> 1) + 16;
264 Object* obj = Heap::AllocateFixedArrayWithHoles(capacity); 366 Object* obj = AllocateUninitializedFixedArray(capacity);
265 if (obj->IsFailure()) return obj; 367 if (obj->IsFailure()) return obj;
368 FixedArray* new_elms = FixedArray::cast(obj);
266 369
267 AssertNoAllocation no_gc; 370 AssertNoAllocation no_gc;
268 FixedArray* new_elms = FixedArray::cast(obj); 371 CopyElements(&no_gc, new_elms, 0, elms, 0, len);
269 WriteBarrierMode mode = new_elms->GetWriteBarrierMode(no_gc); 372 FillWithHoles(new_elms, new_length, capacity);
270 // Fill out the new array with old elements. 373
271 for (int i = 0; i < len; i++) new_elms->set(i, elms->get(i), mode);
272 elms = new_elms; 374 elms = new_elms;
273 array->set_elements(elms); 375 array->set_elements(elms);
274 } 376 }
275 377
378 // Add the provided values.
276 AssertNoAllocation no_gc; 379 AssertNoAllocation no_gc;
277 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); 380 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
278
279 // Add the provided values.
280 for (int index = 0; index < to_add; index++) { 381 for (int index = 0; index < to_add; index++) {
281 elms->set(index + len, args[index + 1], mode); 382 elms->set(index + len, args[index + 1], mode);
282 } 383 }
283 384
284 // Set the length. 385 // Set the length.
285 array->set_length(Smi::FromInt(new_length)); 386 array->set_length(Smi::FromInt(new_length));
286 return Smi::FromInt(new_length); 387 return Smi::FromInt(new_length);
287 } 388 }
288 389
289 390
290 BUILTIN(ArrayPop) { 391 BUILTIN(ArrayPop) {
291 JSArray* array = JSArray::cast(*args.receiver()); 392 JSArray* array = JSArray::cast(*args.receiver());
292 ASSERT(array->HasFastElements()); 393 ASSERT(array->HasFastElements());
293 Object* undefined = Heap::undefined_value();
294 394
295 int len = Smi::cast(array->length())->value(); 395 int len = Smi::cast(array->length())->value();
296 if (len == 0) return undefined; 396 if (len == 0) return Heap::undefined_value();
297 397
298 // Get top element 398 // Get top element
299 FixedArray* elms = FixedArray::cast(array->elements()); 399 FixedArray* elms = FixedArray::cast(array->elements());
300 Object* top = elms->get(len - 1); 400 Object* top = elms->get(len - 1);
301 401
302 // Set the length. 402 // Set the length.
303 array->set_length(Smi::FromInt(len - 1)); 403 array->set_length(Smi::FromInt(len - 1));
304 404
305 if (!top->IsTheHole()) { 405 if (!top->IsTheHole()) {
306 // Delete the top element. 406 // Delete the top element.
307 elms->set_the_hole(len - 1); 407 elms->set_the_hole(len - 1);
308 return top; 408 return top;
309 } 409 }
310 410
311 // Remember to check the prototype chain. 411 // Remember to check the prototype chain.
312 JSFunction* array_function = 412 JSFunction* array_function =
313 Top::context()->global_context()->array_function(); 413 Top::context()->global_context()->array_function();
314 JSObject* prototype = JSObject::cast(array_function->prototype()); 414 JSObject* prototype = JSObject::cast(array_function->prototype());
315 top = prototype->GetElement(len - 1); 415 top = prototype->GetElement(len - 1);
316 416
317 return top; 417 return top;
318 } 418 }
319 419
320 420
321 static Object* GetElementToMove(uint32_t index,
322 FixedArray* elms,
323 JSObject* prototype) {
324 Object* e = elms->get(index);
325 if (e->IsTheHole() && prototype->HasElement(index)) {
326 e = prototype->GetElement(index);
327 }
328 return e;
329 }
330
331
332 BUILTIN(ArrayShift) { 421 BUILTIN(ArrayShift) {
422 if (!ArrayPrototypeHasNoElements()) {
423 return CallJsBuiltin("ArrayShift", args);
424 }
425
333 JSArray* array = JSArray::cast(*args.receiver()); 426 JSArray* array = JSArray::cast(*args.receiver());
334 ASSERT(array->HasFastElements()); 427 ASSERT(array->HasFastElements());
335 428
336 int len = Smi::cast(array->length())->value(); 429 int len = Smi::cast(array->length())->value();
337 if (len == 0) return Heap::undefined_value(); 430 if (len == 0) return Heap::undefined_value();
338 431
339 // Fetch the prototype.
340 JSFunction* array_function =
341 Top::context()->global_context()->array_function();
342 JSObject* prototype = JSObject::cast(array_function->prototype());
343
344 FixedArray* elms = FixedArray::cast(array->elements()); 432 FixedArray* elms = FixedArray::cast(array->elements());
345 433
346 // Get first element 434 // Get first element
347 Object* first = elms->get(0); 435 Object* first = elms->get(0);
348 if (first->IsTheHole()) { 436 if (first->IsTheHole()) {
349 first = prototype->GetElement(0); 437 first = Heap::undefined_value();
350 } 438 }
351 439
352 // Shift the elements. 440 // Shift the elements.
353 for (int i = 0; i < len - 1; i++) { 441 AssertNoAllocation no_gc;
354 elms->set(i, GetElementToMove(i + 1, elms, prototype)); 442 MoveElements(&no_gc, elms, 0, elms, 1, len - 1);
355 }
356 elms->set(len - 1, Heap::the_hole_value()); 443 elms->set(len - 1, Heap::the_hole_value());
357 444
358 // Set the length. 445 // Set the length.
359 array->set_length(Smi::FromInt(len - 1)); 446 array->set_length(Smi::FromInt(len - 1));
360 447
361 return first; 448 return first;
362 } 449 }
363 450
364 451
365 BUILTIN(ArrayUnshift) { 452 BUILTIN(ArrayUnshift) {
453 if (!ArrayPrototypeHasNoElements()) {
454 return CallJsBuiltin("ArrayUnshift", args);
455 }
456
366 JSArray* array = JSArray::cast(*args.receiver()); 457 JSArray* array = JSArray::cast(*args.receiver());
367 ASSERT(array->HasFastElements()); 458 ASSERT(array->HasFastElements());
368 459
369 int len = Smi::cast(array->length())->value(); 460 int len = Smi::cast(array->length())->value();
370 int to_add = args.length() - 1; 461 int to_add = args.length() - 1;
371 // Note that we cannot quit early if to_add == 0 as 462 // Note that we cannot quit early if to_add == 0 as
372 // values should be lifted from prototype into 463 // values should be lifted from prototype into
373 // the array. 464 // the array.
374 465
375 int new_length = len + to_add; 466 int new_length = len + to_add;
376 // Currently fixed arrays cannot grow too big, so 467 // Currently fixed arrays cannot grow too big, so
377 // we should never hit this case. 468 // we should never hit this case.
378 ASSERT(to_add <= (Smi::kMaxValue - len)); 469 ASSERT(to_add <= (Smi::kMaxValue - len));
379 470
380 FixedArray* elms = FixedArray::cast(array->elements()); 471 FixedArray* elms = FixedArray::cast(array->elements());
381 472
382 // Fetch the prototype.
383 JSFunction* array_function =
384 Top::context()->global_context()->array_function();
385 JSObject* prototype = JSObject::cast(array_function->prototype());
386
387 if (new_length > elms->length()) { 473 if (new_length > elms->length()) {
388 // New backing storage is needed. 474 // New backing storage is needed.
389 int capacity = new_length + (new_length >> 1) + 16; 475 int capacity = new_length + (new_length >> 1) + 16;
390 Object* obj = Heap::AllocateFixedArrayWithHoles(capacity); 476 Object* obj = AllocateUninitializedFixedArray(capacity);
391 if (obj->IsFailure()) return obj; 477 if (obj->IsFailure()) return obj;
478 FixedArray* new_elms = FixedArray::cast(obj);
392 479
393 AssertNoAllocation no_gc; 480 AssertNoAllocation no_gc;
394 FixedArray* new_elms = FixedArray::cast(obj); 481 CopyElements(&no_gc, new_elms, to_add, elms, 0, len);
395 WriteBarrierMode mode = new_elms->GetWriteBarrierMode(no_gc); 482 FillWithHoles(new_elms, new_length, capacity);
396 // Fill out the new array with old elements.
397 for (int i = 0; i < len; i++)
398 new_elms->set(to_add + i,
399 GetElementToMove(i, elms, prototype),
400 mode);
401 483
402 elms = new_elms; 484 elms = new_elms;
403 array->set_elements(elms); 485 array->set_elements(elms);
404 } else { 486 } else {
405 AssertNoAllocation no_gc; 487 AssertNoAllocation no_gc;
406 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); 488 MoveElements(&no_gc, elms, to_add, elms, 0, len);
407
408 // Move elements to the right
409 for (int i = 0; i < len; i++) {
410 elms->set(new_length - i - 1,
411 GetElementToMove(len - i - 1, elms, prototype),
412 mode);
413 }
414 } 489 }
415 490
416 // Add the provided values. 491 // Add the provided values.
417 AssertNoAllocation no_gc; 492 AssertNoAllocation no_gc;
418 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); 493 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
419 for (int i = 0; i < to_add; i++) { 494 for (int i = 0; i < to_add; i++) {
420 elms->set(i, args[i + 1], mode); 495 elms->set(i, args[i + 1], mode);
421 } 496 }
422 497
423 // Set the length. 498 // Set the length.
424 array->set_length(Smi::FromInt(new_length)); 499 array->set_length(Smi::FromInt(new_length));
425 return Smi::FromInt(new_length); 500 return Smi::FromInt(new_length);
426 } 501 }
427 502
428 503
429 static Object* CallJsBuiltin(const char* name,
430 BuiltinArguments<NO_EXTRA_ARGUMENTS> args) {
431 HandleScope handleScope;
432
433 Handle<Object> js_builtin =
434 GetProperty(Handle<JSObject>(Top::global_context()->builtins()),
435 name);
436 ASSERT(js_builtin->IsJSFunction());
437 Handle<JSFunction> function(Handle<JSFunction>::cast(js_builtin));
438 Vector<Object**> argv(Vector<Object**>::New(args.length() - 1));
439 int n_args = args.length() - 1;
440 for (int i = 0; i < n_args; i++) {
441 argv[i] = &args[i + 1];
442 }
443 bool pending_exception = false;
444 Handle<Object> result = Execution::Call(function,
445 args.receiver(),
446 n_args,
447 argv.start(),
448 &pending_exception);
449 if (pending_exception) return Failure::Exception();
450 return *result;
451 }
452
453
454 BUILTIN(ArraySlice) { 504 BUILTIN(ArraySlice) {
505 if (!ArrayPrototypeHasNoElements()) {
506 return CallJsBuiltin("ArraySlice", args);
507 }
508
455 JSArray* array = JSArray::cast(*args.receiver()); 509 JSArray* array = JSArray::cast(*args.receiver());
456 ASSERT(array->HasFastElements()); 510 ASSERT(array->HasFastElements());
457 511
458 int len = Smi::cast(array->length())->value(); 512 int len = Smi::cast(array->length())->value();
459 513
460 int n_arguments = args.length() - 1; 514 int n_arguments = args.length() - 1;
461 515
462 // Note carefully choosen defaults---if argument is missing, 516 // Note carefully choosen defaults---if argument is missing,
463 // it's undefined which gets converted to 0 for relativeStart 517 // it's undefined which gets converted to 0 for relativeStart
464 // and to len for relativeEnd. 518 // and to len for relativeEnd.
(...skipping 23 matching lines...) Expand all
488 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 8. 542 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 8.
489 int final = (relativeEnd < 0) ? Max(len + relativeEnd, 0) 543 int final = (relativeEnd < 0) ? Max(len + relativeEnd, 0)
490 : Min(relativeEnd, len); 544 : Min(relativeEnd, len);
491 545
492 // Calculate the length of result array. 546 // Calculate the length of result array.
493 int result_len = final - k; 547 int result_len = final - k;
494 if (result_len < 0) { 548 if (result_len < 0) {
495 result_len = 0; 549 result_len = 0;
496 } 550 }
497 551
498 JSFunction* array_function = 552 Object* result = AllocateJSArray();
499 Top::context()->global_context()->array_function();
500 Object* result = Heap::AllocateJSObject(array_function);
501 if (result->IsFailure()) return result; 553 if (result->IsFailure()) return result;
502 JSArray* result_array = JSArray::cast(result); 554 JSArray* result_array = JSArray::cast(result);
503 555
504 result = Heap::AllocateFixedArrayWithHoles(result_len); 556 result = AllocateUninitializedFixedArray(result_len);
505 if (result->IsFailure()) return result; 557 if (result->IsFailure()) return result;
506 FixedArray* result_elms = FixedArray::cast(result); 558 FixedArray* result_elms = FixedArray::cast(result);
507 559
508 FixedArray* elms = FixedArray::cast(array->elements()); 560 FixedArray* elms = FixedArray::cast(array->elements());
509 561
510 // Fetch the prototype.
511 JSObject* prototype = JSObject::cast(array_function->prototype());
512
513 AssertNoAllocation no_gc; 562 AssertNoAllocation no_gc;
514 WriteBarrierMode mode = result_elms->GetWriteBarrierMode(no_gc); 563 CopyElements(&no_gc, result_elms, 0, elms, k, result_len);
515
516 // Fill newly created array.
517 for (int i = 0; i < result_len; i++) {
518 result_elms->set(i,
519 GetElementToMove(k + i, elms, prototype),
520 mode);
521 }
522 564
523 // Set elements. 565 // Set elements.
524 result_array->set_elements(result_elms); 566 result_array->set_elements(result_elms);
525 567
526 // Set the length. 568 // Set the length.
527 result_array->set_length(Smi::FromInt(result_len)); 569 result_array->set_length(Smi::FromInt(result_len));
528 return result_array; 570 return result_array;
529 } 571 }
530 572
531 573
532 BUILTIN(ArraySplice) { 574 BUILTIN(ArraySplice) {
575 if (!ArrayPrototypeHasNoElements()) {
576 return CallJsBuiltin("ArraySplice", args);
577 }
578
533 JSArray* array = JSArray::cast(*args.receiver()); 579 JSArray* array = JSArray::cast(*args.receiver());
534 ASSERT(array->HasFastElements()); 580 ASSERT(array->HasFastElements());
535 581
536 int len = Smi::cast(array->length())->value(); 582 int len = Smi::cast(array->length())->value();
537 583
538 int n_arguments = args.length() - 1; 584 int n_arguments = args.length() - 1;
539 585
540 // SpiderMonkey and JSC return undefined in the case where no 586 // SpiderMonkey and JSC return undefined in the case where no
541 // arguments are given instead of using the implicit undefined 587 // arguments are given instead of using the implicit undefined
542 // arguments. This does not follow ECMA-262, but we do the same for 588 // arguments. This does not follow ECMA-262, but we do the same for
(...skipping 21 matching lines...) Expand all
564 if (n_arguments > 1) { 610 if (n_arguments > 1) {
565 Object* arg2 = args[2]; 611 Object* arg2 = args[2];
566 if (arg2->IsSmi()) { 612 if (arg2->IsSmi()) {
567 deleteCount = Smi::cast(arg2)->value(); 613 deleteCount = Smi::cast(arg2)->value();
568 } else { 614 } else {
569 return CallJsBuiltin("ArraySplice", args); 615 return CallJsBuiltin("ArraySplice", args);
570 } 616 }
571 } 617 }
572 int actualDeleteCount = Min(Max(deleteCount, 0), len - actualStart); 618 int actualDeleteCount = Min(Max(deleteCount, 0), len - actualStart);
573 619
574 JSFunction* array_function =
575 Top::context()->global_context()->array_function();
576
577 // Allocate result array. 620 // Allocate result array.
578 Object* result = Heap::AllocateJSObject(array_function); 621 Object* result = AllocateJSArray();
579 if (result->IsFailure()) return result; 622 if (result->IsFailure()) return result;
580 JSArray* result_array = JSArray::cast(result); 623 JSArray* result_array = JSArray::cast(result);
581 624
582 result = Heap::AllocateFixedArrayWithHoles(actualDeleteCount); 625 result = AllocateUninitializedFixedArray(actualDeleteCount);
583 if (result->IsFailure()) return result; 626 if (result->IsFailure()) return result;
584 FixedArray* result_elms = FixedArray::cast(result); 627 FixedArray* result_elms = FixedArray::cast(result);
585 628
586 FixedArray* elms = FixedArray::cast(array->elements()); 629 FixedArray* elms = FixedArray::cast(array->elements());
587 630
588 // Fetch the prototype.
589 JSObject* prototype = JSObject::cast(array_function->prototype());
590
591 AssertNoAllocation no_gc; 631 AssertNoAllocation no_gc;
592 WriteBarrierMode mode = result_elms->GetWriteBarrierMode(no_gc);
593
594 // Fill newly created array. 632 // Fill newly created array.
595 for (int k = 0; k < actualDeleteCount; k++) { 633 CopyElements(&no_gc, result_elms, 0, elms, actualStart, actualDeleteCount);
596 result_elms->set(k,
597 GetElementToMove(actualStart + k, elms, prototype),
598 mode);
599 }
600 634
601 // Set elements. 635 // Set elements.
602 result_array->set_elements(result_elms); 636 result_array->set_elements(result_elms);
603 637
604 // Set the length. 638 // Set the length.
605 result_array->set_length(Smi::FromInt(actualDeleteCount)); 639 result_array->set_length(Smi::FromInt(actualDeleteCount));
606 640
607 int itemCount = (n_arguments > 1) ? (n_arguments - 2) : 0; 641 int itemCount = (n_arguments > 1) ? (n_arguments - 2) : 0;
608 642
609 int new_length = len - actualDeleteCount + itemCount; 643 int new_length = len - actualDeleteCount + itemCount;
610 644
611 mode = elms->GetWriteBarrierMode(no_gc);
612 if (itemCount < actualDeleteCount) { 645 if (itemCount < actualDeleteCount) {
613 // Shrink the array. 646 // Shrink the array.
614 for (int k = actualStart; k < (len - actualDeleteCount); k++) { 647 MoveElements(&no_gc,
615 elms->set(k + itemCount, 648 elms, actualStart + itemCount,
616 GetElementToMove(k + actualDeleteCount, elms, prototype), 649 elms, actualStart + actualDeleteCount,
617 mode); 650 (len - actualDeleteCount - actualStart));
618 } 651 FillWithHoles(elms, new_length, len);
619
620 for (int k = len; k > new_length; k--) {
621 elms->set(k - 1, Heap::the_hole_value());
622 }
623 } else if (itemCount > actualDeleteCount) { 652 } else if (itemCount > actualDeleteCount) {
624 // Currently fixed arrays cannot grow too big, so 653 // Currently fixed arrays cannot grow too big, so
625 // we should never hit this case. 654 // we should never hit this case.
626 ASSERT((itemCount - actualDeleteCount) <= (Smi::kMaxValue - len)); 655 ASSERT((itemCount - actualDeleteCount) <= (Smi::kMaxValue - len));
627 656
628 FixedArray* source_elms = elms; 657 FixedArray* source_elms = elms;
629 658
630 // Check if array need to grow. 659 // Check if array need to grow.
631 if (new_length > elms->length()) { 660 if (new_length > elms->length()) {
632 // New backing storage is needed. 661 // New backing storage is needed.
633 int capacity = new_length + (new_length >> 1) + 16; 662 int capacity = new_length + (new_length >> 1) + 16;
634 Object* obj = Heap::AllocateFixedArrayWithHoles(capacity); 663 Object* obj = AllocateUninitializedFixedArray(capacity);
635 if (obj->IsFailure()) return obj; 664 if (obj->IsFailure()) return obj;
636
637 FixedArray* new_elms = FixedArray::cast(obj); 665 FixedArray* new_elms = FixedArray::cast(obj);
638 mode = new_elms->GetWriteBarrierMode(no_gc);
639 666
640 // Copy the part before actualStart as is. 667 // Copy the part before actualStart as is.
641 for (int k = 0; k < actualStart; k++) { 668 CopyElements(&no_gc, new_elms, 0, elms, 0, actualStart);
642 new_elms->set(k, elms->get(k), mode); 669 FillWithHoles(new_elms, new_length, capacity);
643 }
644 670
645 source_elms = elms; 671 source_elms = elms;
646 elms = new_elms; 672 elms = new_elms;
647 array->set_elements(elms); 673 array->set_elements(elms);
648 } 674 }
649 675
650 for (int k = len - actualDeleteCount; k > actualStart; k--) { 676 MoveElements(&no_gc,
651 elms->set(k + itemCount - 1, 677 elms, actualStart + itemCount,
652 GetElementToMove(k + actualDeleteCount - 1, 678 source_elms, actualStart + actualDeleteCount,
653 source_elms, 679 (len - actualDeleteCount - actualStart));
654 prototype),
655 mode);
656 }
657 } 680 }
658 681
682 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
659 for (int k = actualStart; k < actualStart + itemCount; k++) { 683 for (int k = actualStart; k < actualStart + itemCount; k++) {
660 elms->set(k, args[3 + k - actualStart], mode); 684 elms->set(k, args[3 + k - actualStart], mode);
661 } 685 }
662 686
663 // Set the length. 687 // Set the length.
664 array->set_length(Smi::FromInt(new_length)); 688 array->set_length(Smi::FromInt(new_length));
665 689
666 return result_array; 690 return result_array;
667 } 691 }
668 692
(...skipping 642 matching lines...) Expand 10 before | Expand all | Expand 10 after
1311 if (entry->contains(pc)) { 1335 if (entry->contains(pc)) {
1312 return names_[i]; 1336 return names_[i];
1313 } 1337 }
1314 } 1338 }
1315 } 1339 }
1316 return NULL; 1340 return NULL;
1317 } 1341 }
1318 1342
1319 1343
1320 } } // namespace v8::internal 1344 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/array.js ('k') | src/heap.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698