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

Side by Side Diff: src/builtins.cc

Issue 1067523003: Wrap array implementation in a function. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 8 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/messages.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 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/api.h" 7 #include "src/api.h"
8 #include "src/api-natives.h" 8 #include "src/api-natives.h"
9 #include "src/arguments.h" 9 #include "src/arguments.h"
10 #include "src/base/once.h" 10 #include "src/base/once.h"
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after
294 } 294 }
295 295
296 296
297 BUILTIN(ArrayPush) { 297 BUILTIN(ArrayPush) {
298 HandleScope scope(isolate); 298 HandleScope scope(isolate);
299 Handle<Object> receiver = args.receiver(); 299 Handle<Object> receiver = args.receiver();
300 MaybeHandle<FixedArrayBase> maybe_elms_obj = 300 MaybeHandle<FixedArrayBase> maybe_elms_obj =
301 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1); 301 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1);
302 Handle<FixedArrayBase> elms_obj; 302 Handle<FixedArrayBase> elms_obj;
303 if (!maybe_elms_obj.ToHandle(&elms_obj)) { 303 if (!maybe_elms_obj.ToHandle(&elms_obj)) {
304 return CallJsBuiltin(isolate, "ArrayPush", args); 304 return CallJsBuiltin(isolate, "$arrayPush", args);
305 } 305 }
306 306
307 Handle<JSArray> array = Handle<JSArray>::cast(receiver); 307 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
308 int len = Smi::cast(array->length())->value(); 308 int len = Smi::cast(array->length())->value();
309 int to_add = args.length() - 1; 309 int to_add = args.length() - 1;
310 if (to_add > 0 && JSArray::WouldChangeReadOnlyLength(array, len + to_add)) { 310 if (to_add > 0 && JSArray::WouldChangeReadOnlyLength(array, len + to_add)) {
311 return CallJsBuiltin(isolate, "ArrayPush", args); 311 return CallJsBuiltin(isolate, "$arrayPush", args);
312 } 312 }
313 DCHECK(!array->map()->is_observed()); 313 DCHECK(!array->map()->is_observed());
314 314
315 ElementsKind kind = array->GetElementsKind(); 315 ElementsKind kind = array->GetElementsKind();
316 316
317 if (IsFastSmiOrObjectElementsKind(kind)) { 317 if (IsFastSmiOrObjectElementsKind(kind)) {
318 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj); 318 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
319 if (to_add == 0) { 319 if (to_add == 0) {
320 return Smi::FromInt(len); 320 return Smi::FromInt(len);
321 } 321 }
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
404 } 404 }
405 405
406 406
407 BUILTIN(ArrayPop) { 407 BUILTIN(ArrayPop) {
408 HandleScope scope(isolate); 408 HandleScope scope(isolate);
409 Handle<Object> receiver = args.receiver(); 409 Handle<Object> receiver = args.receiver();
410 MaybeHandle<FixedArrayBase> maybe_elms_obj = 410 MaybeHandle<FixedArrayBase> maybe_elms_obj =
411 EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0); 411 EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0);
412 Handle<FixedArrayBase> elms_obj; 412 Handle<FixedArrayBase> elms_obj;
413 if (!maybe_elms_obj.ToHandle(&elms_obj)) { 413 if (!maybe_elms_obj.ToHandle(&elms_obj)) {
414 return CallJsBuiltin(isolate, "ArrayPop", args); 414 return CallJsBuiltin(isolate, "$arrayPop", args);
415 } 415 }
416 416
417 Handle<JSArray> array = Handle<JSArray>::cast(receiver); 417 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
418 DCHECK(!array->map()->is_observed()); 418 DCHECK(!array->map()->is_observed());
419 419
420 int len = Smi::cast(array->length())->value(); 420 int len = Smi::cast(array->length())->value();
421 if (len == 0) return isolate->heap()->undefined_value(); 421 if (len == 0) return isolate->heap()->undefined_value();
422 422
423 if (JSArray::HasReadOnlyLength(array)) { 423 if (JSArray::HasReadOnlyLength(array)) {
424 return CallJsBuiltin(isolate, "ArrayPop", args); 424 return CallJsBuiltin(isolate, "$arrayPop", args);
425 } 425 }
426 426
427 ElementsAccessor* accessor = array->GetElementsAccessor(); 427 ElementsAccessor* accessor = array->GetElementsAccessor();
428 int new_length = len - 1; 428 int new_length = len - 1;
429 Handle<Object> element = 429 Handle<Object> element =
430 accessor->Get(array, array, new_length, elms_obj).ToHandleChecked(); 430 accessor->Get(array, array, new_length, elms_obj).ToHandleChecked();
431 if (element->IsTheHole()) { 431 if (element->IsTheHole()) {
432 return CallJsBuiltin(isolate, "ArrayPop", args); 432 return CallJsBuiltin(isolate, "$arrayPop", args);
433 } 433 }
434 RETURN_FAILURE_ON_EXCEPTION( 434 RETURN_FAILURE_ON_EXCEPTION(
435 isolate, 435 isolate,
436 accessor->SetLength(array, handle(Smi::FromInt(new_length), isolate))); 436 accessor->SetLength(array, handle(Smi::FromInt(new_length), isolate)));
437 return *element; 437 return *element;
438 } 438 }
439 439
440 440
441 BUILTIN(ArrayShift) { 441 BUILTIN(ArrayShift) {
442 HandleScope scope(isolate); 442 HandleScope scope(isolate);
443 Heap* heap = isolate->heap(); 443 Heap* heap = isolate->heap();
444 Handle<Object> receiver = args.receiver(); 444 Handle<Object> receiver = args.receiver();
445 MaybeHandle<FixedArrayBase> maybe_elms_obj = 445 MaybeHandle<FixedArrayBase> maybe_elms_obj =
446 EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0); 446 EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0);
447 Handle<FixedArrayBase> elms_obj; 447 Handle<FixedArrayBase> elms_obj;
448 if (!maybe_elms_obj.ToHandle(&elms_obj) || 448 if (!maybe_elms_obj.ToHandle(&elms_obj) ||
449 !IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(*receiver))) { 449 !IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(*receiver))) {
450 return CallJsBuiltin(isolate, "ArrayShift", args); 450 return CallJsBuiltin(isolate, "$arrayShift", args);
451 } 451 }
452 Handle<JSArray> array = Handle<JSArray>::cast(receiver); 452 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
453 DCHECK(!array->map()->is_observed()); 453 DCHECK(!array->map()->is_observed());
454 454
455 int len = Smi::cast(array->length())->value(); 455 int len = Smi::cast(array->length())->value();
456 if (len == 0) return heap->undefined_value(); 456 if (len == 0) return heap->undefined_value();
457 457
458 if (JSArray::HasReadOnlyLength(array)) { 458 if (JSArray::HasReadOnlyLength(array)) {
459 return CallJsBuiltin(isolate, "ArrayShift", args); 459 return CallJsBuiltin(isolate, "$arrayShift", args);
460 } 460 }
461 461
462 // Get first element 462 // Get first element
463 ElementsAccessor* accessor = array->GetElementsAccessor(); 463 ElementsAccessor* accessor = array->GetElementsAccessor();
464 Handle<Object> first = 464 Handle<Object> first =
465 accessor->Get(array, array, 0, elms_obj).ToHandleChecked(); 465 accessor->Get(array, array, 0, elms_obj).ToHandleChecked();
466 if (first->IsTheHole()) { 466 if (first->IsTheHole()) {
467 return CallJsBuiltin(isolate, "ArrayShift", args); 467 return CallJsBuiltin(isolate, "$arrayShift", args);
468 } 468 }
469 469
470 if (heap->CanMoveObjectStart(*elms_obj)) { 470 if (heap->CanMoveObjectStart(*elms_obj)) {
471 array->set_elements(heap->LeftTrimFixedArray(*elms_obj, 1)); 471 array->set_elements(heap->LeftTrimFixedArray(*elms_obj, 1));
472 } else { 472 } else {
473 // Shift the elements. 473 // Shift the elements.
474 if (elms_obj->IsFixedArray()) { 474 if (elms_obj->IsFixedArray()) {
475 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj); 475 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
476 DisallowHeapAllocation no_gc; 476 DisallowHeapAllocation no_gc;
477 heap->MoveElements(*elms, 0, 1, len - 1); 477 heap->MoveElements(*elms, 0, 1, len - 1);
(...skipping 13 matching lines...) Expand all
491 491
492 492
493 BUILTIN(ArrayUnshift) { 493 BUILTIN(ArrayUnshift) {
494 HandleScope scope(isolate); 494 HandleScope scope(isolate);
495 Heap* heap = isolate->heap(); 495 Heap* heap = isolate->heap();
496 Handle<Object> receiver = args.receiver(); 496 Handle<Object> receiver = args.receiver();
497 MaybeHandle<FixedArrayBase> maybe_elms_obj = 497 MaybeHandle<FixedArrayBase> maybe_elms_obj =
498 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1); 498 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1);
499 Handle<FixedArrayBase> elms_obj; 499 Handle<FixedArrayBase> elms_obj;
500 if (!maybe_elms_obj.ToHandle(&elms_obj)) { 500 if (!maybe_elms_obj.ToHandle(&elms_obj)) {
501 return CallJsBuiltin(isolate, "ArrayUnshift", args); 501 return CallJsBuiltin(isolate, "$arrayUnshift", args);
502 } 502 }
503 Handle<JSArray> array = Handle<JSArray>::cast(receiver); 503 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
504 DCHECK(!array->map()->is_observed()); 504 DCHECK(!array->map()->is_observed());
505 if (!array->HasFastSmiOrObjectElements()) { 505 if (!array->HasFastSmiOrObjectElements()) {
506 return CallJsBuiltin(isolate, "ArrayUnshift", args); 506 return CallJsBuiltin(isolate, "$arrayUnshift", args);
507 } 507 }
508 int len = Smi::cast(array->length())->value(); 508 int len = Smi::cast(array->length())->value();
509 int to_add = args.length() - 1; 509 int to_add = args.length() - 1;
510 int new_length = len + to_add; 510 int new_length = len + to_add;
511 // Currently fixed arrays cannot grow too big, so 511 // Currently fixed arrays cannot grow too big, so
512 // we should never hit this case. 512 // we should never hit this case.
513 DCHECK(to_add <= (Smi::kMaxValue - len)); 513 DCHECK(to_add <= (Smi::kMaxValue - len));
514 514
515 if (to_add > 0 && JSArray::WouldChangeReadOnlyLength(array, len + to_add)) { 515 if (to_add > 0 && JSArray::WouldChangeReadOnlyLength(array, len + to_add)) {
516 return CallJsBuiltin(isolate, "ArrayUnshift", args); 516 return CallJsBuiltin(isolate, "$arrayUnshift", args);
517 } 517 }
518 518
519 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj); 519 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
520 520
521 if (new_length > elms->length()) { 521 if (new_length > elms->length()) {
522 // New backing storage is needed. 522 // New backing storage is needed.
523 int capacity = new_length + (new_length >> 1) + 16; 523 int capacity = new_length + (new_length >> 1) + 16;
524 Handle<FixedArray> new_elms = 524 Handle<FixedArray> new_elms =
525 isolate->factory()->NewUninitializedFixedArray(capacity); 525 isolate->factory()->NewUninitializedFixedArray(capacity);
526 526
(...skipping 29 matching lines...) Expand all
556 Handle<Object> receiver = args.receiver(); 556 Handle<Object> receiver = args.receiver();
557 int len = -1; 557 int len = -1;
558 int relative_start = 0; 558 int relative_start = 0;
559 int relative_end = 0; 559 int relative_end = 0;
560 { 560 {
561 DisallowHeapAllocation no_gc; 561 DisallowHeapAllocation no_gc;
562 if (receiver->IsJSArray()) { 562 if (receiver->IsJSArray()) {
563 JSArray* array = JSArray::cast(*receiver); 563 JSArray* array = JSArray::cast(*receiver);
564 if (!IsJSArrayFastElementMovingAllowed(heap, array)) { 564 if (!IsJSArrayFastElementMovingAllowed(heap, array)) {
565 AllowHeapAllocation allow_allocation; 565 AllowHeapAllocation allow_allocation;
566 return CallJsBuiltin(isolate, "ArraySlice", args); 566 return CallJsBuiltin(isolate, "$arraySlice", args);
567 } 567 }
568 568
569 if (!array->HasFastElements()) { 569 if (!array->HasFastElements()) {
570 AllowHeapAllocation allow_allocation; 570 AllowHeapAllocation allow_allocation;
571 return CallJsBuiltin(isolate, "ArraySlice", args); 571 return CallJsBuiltin(isolate, "$arraySlice", args);
572 } 572 }
573 573
574 len = Smi::cast(array->length())->value(); 574 len = Smi::cast(array->length())->value();
575 } else { 575 } else {
576 // Array.slice(arguments, ...) is quite a common idiom (notably more 576 // Array.slice(arguments, ...) is quite a common idiom (notably more
577 // than 50% of invocations in Web apps). Treat it in C++ as well. 577 // than 50% of invocations in Web apps). Treat it in C++ as well.
578 Map* arguments_map = 578 Map* arguments_map =
579 isolate->context()->native_context()->sloppy_arguments_map(); 579 isolate->context()->native_context()->sloppy_arguments_map();
580 580
581 bool is_arguments_object_with_fast_elements = 581 bool is_arguments_object_with_fast_elements =
582 receiver->IsJSObject() && 582 receiver->IsJSObject() &&
583 JSObject::cast(*receiver)->map() == arguments_map; 583 JSObject::cast(*receiver)->map() == arguments_map;
584 if (!is_arguments_object_with_fast_elements) { 584 if (!is_arguments_object_with_fast_elements) {
585 AllowHeapAllocation allow_allocation; 585 AllowHeapAllocation allow_allocation;
586 return CallJsBuiltin(isolate, "ArraySlice", args); 586 return CallJsBuiltin(isolate, "$arraySlice", args);
587 } 587 }
588 JSObject* object = JSObject::cast(*receiver); 588 JSObject* object = JSObject::cast(*receiver);
589 589
590 if (!object->HasFastElements()) { 590 if (!object->HasFastElements()) {
591 AllowHeapAllocation allow_allocation; 591 AllowHeapAllocation allow_allocation;
592 return CallJsBuiltin(isolate, "ArraySlice", args); 592 return CallJsBuiltin(isolate, "$arraySlice", args);
593 } 593 }
594 594
595 Object* len_obj = object->InObjectPropertyAt(Heap::kArgumentsLengthIndex); 595 Object* len_obj = object->InObjectPropertyAt(Heap::kArgumentsLengthIndex);
596 if (!len_obj->IsSmi()) { 596 if (!len_obj->IsSmi()) {
597 AllowHeapAllocation allow_allocation; 597 AllowHeapAllocation allow_allocation;
598 return CallJsBuiltin(isolate, "ArraySlice", args); 598 return CallJsBuiltin(isolate, "$arraySlice", args);
599 } 599 }
600 len = Smi::cast(len_obj)->value(); 600 len = Smi::cast(len_obj)->value();
601 if (len > object->elements()->length()) { 601 if (len > object->elements()->length()) {
602 AllowHeapAllocation allow_allocation; 602 AllowHeapAllocation allow_allocation;
603 return CallJsBuiltin(isolate, "ArraySlice", args); 603 return CallJsBuiltin(isolate, "$arraySlice", args);
604 } 604 }
605 } 605 }
606 606
607 DCHECK(len >= 0); 607 DCHECK(len >= 0);
608 int n_arguments = args.length() - 1; 608 int n_arguments = args.length() - 1;
609 609
610 // Note carefully choosen defaults---if argument is missing, 610 // Note carefully choosen defaults---if argument is missing,
611 // it's undefined which gets converted to 0 for relative_start 611 // it's undefined which gets converted to 0 for relative_start
612 // and to len for relative_end. 612 // and to len for relative_end.
613 relative_start = 0; 613 relative_start = 0;
614 relative_end = len; 614 relative_end = len;
615 if (n_arguments > 0) { 615 if (n_arguments > 0) {
616 Object* arg1 = args[1]; 616 Object* arg1 = args[1];
617 if (arg1->IsSmi()) { 617 if (arg1->IsSmi()) {
618 relative_start = Smi::cast(arg1)->value(); 618 relative_start = Smi::cast(arg1)->value();
619 } else if (arg1->IsHeapNumber()) { 619 } else if (arg1->IsHeapNumber()) {
620 double start = HeapNumber::cast(arg1)->value(); 620 double start = HeapNumber::cast(arg1)->value();
621 if (start < kMinInt || start > kMaxInt) { 621 if (start < kMinInt || start > kMaxInt) {
622 AllowHeapAllocation allow_allocation; 622 AllowHeapAllocation allow_allocation;
623 return CallJsBuiltin(isolate, "ArraySlice", args); 623 return CallJsBuiltin(isolate, "$arraySlice", args);
624 } 624 }
625 relative_start = std::isnan(start) ? 0 : static_cast<int>(start); 625 relative_start = std::isnan(start) ? 0 : static_cast<int>(start);
626 } else if (!arg1->IsUndefined()) { 626 } else if (!arg1->IsUndefined()) {
627 AllowHeapAllocation allow_allocation; 627 AllowHeapAllocation allow_allocation;
628 return CallJsBuiltin(isolate, "ArraySlice", args); 628 return CallJsBuiltin(isolate, "$arraySlice", args);
629 } 629 }
630 if (n_arguments > 1) { 630 if (n_arguments > 1) {
631 Object* arg2 = args[2]; 631 Object* arg2 = args[2];
632 if (arg2->IsSmi()) { 632 if (arg2->IsSmi()) {
633 relative_end = Smi::cast(arg2)->value(); 633 relative_end = Smi::cast(arg2)->value();
634 } else if (arg2->IsHeapNumber()) { 634 } else if (arg2->IsHeapNumber()) {
635 double end = HeapNumber::cast(arg2)->value(); 635 double end = HeapNumber::cast(arg2)->value();
636 if (end < kMinInt || end > kMaxInt) { 636 if (end < kMinInt || end > kMaxInt) {
637 AllowHeapAllocation allow_allocation; 637 AllowHeapAllocation allow_allocation;
638 return CallJsBuiltin(isolate, "ArraySlice", args); 638 return CallJsBuiltin(isolate, "$arraySlice", args);
639 } 639 }
640 relative_end = std::isnan(end) ? 0 : static_cast<int>(end); 640 relative_end = std::isnan(end) ? 0 : static_cast<int>(end);
641 } else if (!arg2->IsUndefined()) { 641 } else if (!arg2->IsUndefined()) {
642 AllowHeapAllocation allow_allocation; 642 AllowHeapAllocation allow_allocation;
643 return CallJsBuiltin(isolate, "ArraySlice", args); 643 return CallJsBuiltin(isolate, "$arraySlice", args);
644 } 644 }
645 } 645 }
646 } 646 }
647 } 647 }
648 648
649 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 6. 649 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 6.
650 int k = (relative_start < 0) ? Max(len + relative_start, 0) 650 int k = (relative_start < 0) ? Max(len + relative_start, 0)
651 : Min(relative_start, len); 651 : Min(relative_start, len);
652 652
653 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 8. 653 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 8.
(...skipping 14 matching lines...) Expand all
668 for (int i = k; i < final; i++) { 668 for (int i = k; i < final; i++) {
669 if (!accessor->HasElement(object, i, elms)) { 669 if (!accessor->HasElement(object, i, elms)) {
670 packed = false; 670 packed = false;
671 break; 671 break;
672 } 672 }
673 } 673 }
674 if (packed) { 674 if (packed) {
675 kind = GetPackedElementsKind(kind); 675 kind = GetPackedElementsKind(kind);
676 } else if (!receiver->IsJSArray()) { 676 } else if (!receiver->IsJSArray()) {
677 AllowHeapAllocation allow_allocation; 677 AllowHeapAllocation allow_allocation;
678 return CallJsBuiltin(isolate, "ArraySlice", args); 678 return CallJsBuiltin(isolate, "$arraySlice", args);
679 } 679 }
680 } 680 }
681 681
682 Handle<JSArray> result_array = 682 Handle<JSArray> result_array =
683 isolate->factory()->NewJSArray(kind, result_len, result_len); 683 isolate->factory()->NewJSArray(kind, result_len, result_len);
684 684
685 DisallowHeapAllocation no_gc; 685 DisallowHeapAllocation no_gc;
686 if (result_len == 0) return *result_array; 686 if (result_len == 0) return *result_array;
687 687
688 ElementsAccessor* accessor = object->GetElementsAccessor(); 688 ElementsAccessor* accessor = object->GetElementsAccessor();
689 accessor->CopyElements( 689 accessor->CopyElements(
690 elms, k, kind, handle(result_array->elements(), isolate), 0, result_len); 690 elms, k, kind, handle(result_array->elements(), isolate), 0, result_len);
691 return *result_array; 691 return *result_array;
692 } 692 }
693 693
694 694
695 BUILTIN(ArraySplice) { 695 BUILTIN(ArraySplice) {
696 HandleScope scope(isolate); 696 HandleScope scope(isolate);
697 Heap* heap = isolate->heap(); 697 Heap* heap = isolate->heap();
698 Handle<Object> receiver = args.receiver(); 698 Handle<Object> receiver = args.receiver();
699 MaybeHandle<FixedArrayBase> maybe_elms_obj = 699 MaybeHandle<FixedArrayBase> maybe_elms_obj =
700 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 3); 700 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 3);
701 Handle<FixedArrayBase> elms_obj; 701 Handle<FixedArrayBase> elms_obj;
702 if (!maybe_elms_obj.ToHandle(&elms_obj)) { 702 if (!maybe_elms_obj.ToHandle(&elms_obj)) {
703 return CallJsBuiltin(isolate, "ArraySplice", args); 703 return CallJsBuiltin(isolate, "$arraySplice", args);
704 } 704 }
705 Handle<JSArray> array = Handle<JSArray>::cast(receiver); 705 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
706 DCHECK(!array->map()->is_observed()); 706 DCHECK(!array->map()->is_observed());
707 707
708 int len = Smi::cast(array->length())->value(); 708 int len = Smi::cast(array->length())->value();
709 709
710 int n_arguments = args.length() - 1; 710 int n_arguments = args.length() - 1;
711 711
712 int relative_start = 0; 712 int relative_start = 0;
713 if (n_arguments > 0) { 713 if (n_arguments > 0) {
714 DisallowHeapAllocation no_gc; 714 DisallowHeapAllocation no_gc;
715 Object* arg1 = args[1]; 715 Object* arg1 = args[1];
716 if (arg1->IsSmi()) { 716 if (arg1->IsSmi()) {
717 relative_start = Smi::cast(arg1)->value(); 717 relative_start = Smi::cast(arg1)->value();
718 } else if (arg1->IsHeapNumber()) { 718 } else if (arg1->IsHeapNumber()) {
719 double start = HeapNumber::cast(arg1)->value(); 719 double start = HeapNumber::cast(arg1)->value();
720 if (start < kMinInt || start > kMaxInt) { 720 if (start < kMinInt || start > kMaxInt) {
721 AllowHeapAllocation allow_allocation; 721 AllowHeapAllocation allow_allocation;
722 return CallJsBuiltin(isolate, "ArraySplice", args); 722 return CallJsBuiltin(isolate, "$arraySplice", args);
723 } 723 }
724 relative_start = std::isnan(start) ? 0 : static_cast<int>(start); 724 relative_start = std::isnan(start) ? 0 : static_cast<int>(start);
725 } else if (!arg1->IsUndefined()) { 725 } else if (!arg1->IsUndefined()) {
726 AllowHeapAllocation allow_allocation; 726 AllowHeapAllocation allow_allocation;
727 return CallJsBuiltin(isolate, "ArraySplice", args); 727 return CallJsBuiltin(isolate, "$arraySplice", args);
728 } 728 }
729 } 729 }
730 int actual_start = (relative_start < 0) ? Max(len + relative_start, 0) 730 int actual_start = (relative_start < 0) ? Max(len + relative_start, 0)
731 : Min(relative_start, len); 731 : Min(relative_start, len);
732 732
733 // SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is 733 // SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is
734 // given as a request to delete all the elements from the start. 734 // given as a request to delete all the elements from the start.
735 // And it differs from the case of undefined delete count. 735 // And it differs from the case of undefined delete count.
736 // This does not follow ECMA-262, but we do the same for 736 // This does not follow ECMA-262, but we do the same for
737 // compatibility. 737 // compatibility.
738 int actual_delete_count; 738 int actual_delete_count;
739 if (n_arguments == 1) { 739 if (n_arguments == 1) {
740 DCHECK(len - actual_start >= 0); 740 DCHECK(len - actual_start >= 0);
741 actual_delete_count = len - actual_start; 741 actual_delete_count = len - actual_start;
742 } else { 742 } else {
743 int value = 0; // ToInteger(undefined) == 0 743 int value = 0; // ToInteger(undefined) == 0
744 if (n_arguments > 1) { 744 if (n_arguments > 1) {
745 DisallowHeapAllocation no_gc; 745 DisallowHeapAllocation no_gc;
746 Object* arg2 = args[2]; 746 Object* arg2 = args[2];
747 if (arg2->IsSmi()) { 747 if (arg2->IsSmi()) {
748 value = Smi::cast(arg2)->value(); 748 value = Smi::cast(arg2)->value();
749 } else { 749 } else {
750 AllowHeapAllocation allow_allocation; 750 AllowHeapAllocation allow_allocation;
751 return CallJsBuiltin(isolate, "ArraySplice", args); 751 return CallJsBuiltin(isolate, "$arraySplice", args);
752 } 752 }
753 } 753 }
754 actual_delete_count = Min(Max(value, 0), len - actual_start); 754 actual_delete_count = Min(Max(value, 0), len - actual_start);
755 } 755 }
756 756
757 ElementsKind elements_kind = array->GetElementsKind(); 757 ElementsKind elements_kind = array->GetElementsKind();
758 758
759 int item_count = (n_arguments > 1) ? (n_arguments - 2) : 0; 759 int item_count = (n_arguments > 1) ? (n_arguments - 2) : 0;
760 int new_length = len - actual_delete_count + item_count; 760 int new_length = len - actual_delete_count + item_count;
761 761
762 // For double mode we do not support changing the length. 762 // For double mode we do not support changing the length.
763 if (new_length > len && IsFastDoubleElementsKind(elements_kind)) { 763 if (new_length > len && IsFastDoubleElementsKind(elements_kind)) {
764 return CallJsBuiltin(isolate, "ArraySplice", args); 764 return CallJsBuiltin(isolate, "$arraySplice", args);
765 } 765 }
766 766
767 if (new_length != len && JSArray::HasReadOnlyLength(array)) { 767 if (new_length != len && JSArray::HasReadOnlyLength(array)) {
768 AllowHeapAllocation allow_allocation; 768 AllowHeapAllocation allow_allocation;
769 return CallJsBuiltin(isolate, "ArraySplice", args); 769 return CallJsBuiltin(isolate, "$arraySplice", args);
770 } 770 }
771 771
772 if (new_length == 0) { 772 if (new_length == 0) {
773 Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements( 773 Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(
774 elms_obj, elements_kind, actual_delete_count); 774 elms_obj, elements_kind, actual_delete_count);
775 array->set_elements(heap->empty_fixed_array()); 775 array->set_elements(heap->empty_fixed_array());
776 array->set_length(Smi::FromInt(0)); 776 array->set_length(Smi::FromInt(0));
777 return *result; 777 return *result;
778 } 778 }
779 779
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
920 bool has_double = false; 920 bool has_double = false;
921 { 921 {
922 DisallowHeapAllocation no_gc; 922 DisallowHeapAllocation no_gc;
923 Heap* heap = isolate->heap(); 923 Heap* heap = isolate->heap();
924 Context* native_context = isolate->context()->native_context(); 924 Context* native_context = isolate->context()->native_context();
925 Object* array_proto = native_context->array_function()->prototype(); 925 Object* array_proto = native_context->array_function()->prototype();
926 PrototypeIterator iter(isolate, array_proto, 926 PrototypeIterator iter(isolate, array_proto,
927 PrototypeIterator::START_AT_RECEIVER); 927 PrototypeIterator::START_AT_RECEIVER);
928 if (!ArrayPrototypeHasNoElements(heap, &iter)) { 928 if (!ArrayPrototypeHasNoElements(heap, &iter)) {
929 AllowHeapAllocation allow_allocation; 929 AllowHeapAllocation allow_allocation;
930 return CallJsBuiltin(isolate, "ArrayConcatJS", args); 930 return CallJsBuiltin(isolate, "$arrayConcat", args);
931 } 931 }
932 932
933 // Iterate through all the arguments performing checks 933 // Iterate through all the arguments performing checks
934 // and calculating total length. 934 // and calculating total length.
935 bool is_holey = false; 935 bool is_holey = false;
936 for (int i = 0; i < n_arguments; i++) { 936 for (int i = 0; i < n_arguments; i++) {
937 Object* arg = args[i]; 937 Object* arg = args[i];
938 PrototypeIterator iter(isolate, arg); 938 PrototypeIterator iter(isolate, arg);
939 if (!arg->IsJSArray() || !JSArray::cast(arg)->HasFastElements() || 939 if (!arg->IsJSArray() || !JSArray::cast(arg)->HasFastElements() ||
940 iter.GetCurrent() != array_proto) { 940 iter.GetCurrent() != array_proto) {
941 AllowHeapAllocation allow_allocation; 941 AllowHeapAllocation allow_allocation;
942 return CallJsBuiltin(isolate, "ArrayConcatJS", args); 942 return CallJsBuiltin(isolate, "$arrayConcat", args);
943 } 943 }
944 int len = Smi::cast(JSArray::cast(arg)->length())->value(); 944 int len = Smi::cast(JSArray::cast(arg)->length())->value();
945 945
946 // We shouldn't overflow when adding another len. 946 // We shouldn't overflow when adding another len.
947 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2); 947 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2);
948 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt); 948 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt);
949 USE(kHalfOfMaxInt); 949 USE(kHalfOfMaxInt);
950 result_len += len; 950 result_len += len;
951 DCHECK(result_len >= 0); 951 DCHECK(result_len >= 0);
952 952
953 if (result_len > FixedDoubleArray::kMaxLength) { 953 if (result_len > FixedDoubleArray::kMaxLength) {
954 AllowHeapAllocation allow_allocation; 954 AllowHeapAllocation allow_allocation;
955 return CallJsBuiltin(isolate, "ArrayConcatJS", args); 955 return CallJsBuiltin(isolate, "$arrayConcat", args);
956 } 956 }
957 957
958 ElementsKind arg_kind = JSArray::cast(arg)->map()->elements_kind(); 958 ElementsKind arg_kind = JSArray::cast(arg)->map()->elements_kind();
959 has_double = has_double || IsFastDoubleElementsKind(arg_kind); 959 has_double = has_double || IsFastDoubleElementsKind(arg_kind);
960 is_holey = is_holey || IsFastHoleyElementsKind(arg_kind); 960 is_holey = is_holey || IsFastHoleyElementsKind(arg_kind);
961 if (IsMoreGeneralElementsKindTransition(elements_kind, arg_kind)) { 961 if (IsMoreGeneralElementsKindTransition(elements_kind, arg_kind)) {
962 elements_kind = arg_kind; 962 elements_kind = arg_kind;
963 } 963 }
964 } 964 }
965 if (is_holey) elements_kind = GetHoleyElementsKind(elements_kind); 965 if (is_holey) elements_kind = GetHoleyElementsKind(elements_kind);
(...skipping 686 matching lines...) Expand 10 before | Expand all | Expand 10 after
1652 } 1652 }
1653 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) 1653 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C)
1654 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) 1654 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A)
1655 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) 1655 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H)
1656 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) 1656 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A)
1657 #undef DEFINE_BUILTIN_ACCESSOR_C 1657 #undef DEFINE_BUILTIN_ACCESSOR_C
1658 #undef DEFINE_BUILTIN_ACCESSOR_A 1658 #undef DEFINE_BUILTIN_ACCESSOR_A
1659 1659
1660 1660
1661 } } // namespace v8::internal 1661 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/array.js ('k') | src/messages.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698