| 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 |