OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |