| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 295 MUST_USE_RESULT | 295 MUST_USE_RESULT |
| 296 static inline Handle<FixedArrayBase> EnsureJSArrayWithWritableFastElements( | 296 static inline Handle<FixedArrayBase> EnsureJSArrayWithWritableFastElements( |
| 297 Isolate* isolate, | 297 Isolate* isolate, |
| 298 Handle<Object> receiver, | 298 Handle<Object> receiver, |
| 299 Arguments* args, | 299 Arguments* args, |
| 300 int first_added_arg) { | 300 int first_added_arg) { |
| 301 if (!receiver->IsJSArray()) return Handle<FixedArrayBase>::null(); | 301 if (!receiver->IsJSArray()) return Handle<FixedArrayBase>::null(); |
| 302 Handle<JSArray> array = Handle<JSArray>::cast(receiver); | 302 Handle<JSArray> array = Handle<JSArray>::cast(receiver); |
| 303 if (array->map()->is_observed()) return Handle<FixedArrayBase>::null(); | 303 if (array->map()->is_observed()) return Handle<FixedArrayBase>::null(); |
| 304 if (!array->map()->is_extensible()) return Handle<FixedArrayBase>::null(); | 304 if (!array->map()->is_extensible()) return Handle<FixedArrayBase>::null(); |
| 305 Handle<FixedArrayBase> elms(array->elements()); | 305 Handle<FixedArrayBase> elms(array->elements(), isolate); |
| 306 Heap* heap = isolate->heap(); | 306 Heap* heap = isolate->heap(); |
| 307 Map* map = elms->map(); | 307 Map* map = elms->map(); |
| 308 if (map == heap->fixed_array_map()) { | 308 if (map == heap->fixed_array_map()) { |
| 309 if (args == NULL || array->HasFastObjectElements()) return elms; | 309 if (args == NULL || array->HasFastObjectElements()) return elms; |
| 310 } else if (map == heap->fixed_cow_array_map()) { | 310 } else if (map == heap->fixed_cow_array_map()) { |
| 311 elms = JSObject::EnsureWritableFastElements(array); | 311 elms = JSObject::EnsureWritableFastElements(array); |
| 312 if (args == NULL || array->HasFastObjectElements()) return elms; | 312 if (args == NULL || array->HasFastObjectElements()) return elms; |
| 313 } else if (map == heap->fixed_double_array_map()) { | 313 } else if (map == heap->fixed_double_array_map()) { |
| 314 if (args == NULL) return elms; | 314 if (args == NULL) return elms; |
| 315 } else { | 315 } else { |
| 316 return Handle<FixedArrayBase>::null(); | 316 return Handle<FixedArrayBase>::null(); |
| 317 } | 317 } |
| 318 | 318 |
| 319 // Need to ensure that the arguments passed in args can be contained in | 319 // Need to ensure that the arguments passed in args can be contained in |
| 320 // the array. | 320 // the array. |
| 321 int args_length = args->length(); | 321 int args_length = args->length(); |
| 322 if (first_added_arg >= args_length) return handle(array->elements()); | 322 if (first_added_arg >= args_length) return handle(array->elements(), isolate); |
| 323 | 323 |
| 324 ElementsKind origin_kind = array->map()->elements_kind(); | 324 ElementsKind origin_kind = array->map()->elements_kind(); |
| 325 ASSERT(!IsFastObjectElementsKind(origin_kind)); | 325 ASSERT(!IsFastObjectElementsKind(origin_kind)); |
| 326 ElementsKind target_kind = origin_kind; | 326 ElementsKind target_kind = origin_kind; |
| 327 int arg_count = args->length() - first_added_arg; | 327 int arg_count = args->length() - first_added_arg; |
| 328 Object** arguments = args->arguments() - first_added_arg - (arg_count - 1); | 328 Object** arguments = args->arguments() - first_added_arg - (arg_count - 1); |
| 329 for (int i = 0; i < arg_count; i++) { | 329 for (int i = 0; i < arg_count; i++) { |
| 330 Object* arg = arguments[i]; | 330 Object* arg = arguments[i]; |
| 331 if (arg->IsHeapObject()) { | 331 if (arg->IsHeapObject()) { |
| 332 if (arg->IsHeapNumber()) { | 332 if (arg->IsHeapNumber()) { |
| 333 target_kind = FAST_DOUBLE_ELEMENTS; | 333 target_kind = FAST_DOUBLE_ELEMENTS; |
| 334 } else { | 334 } else { |
| 335 target_kind = FAST_ELEMENTS; | 335 target_kind = FAST_ELEMENTS; |
| 336 break; | 336 break; |
| 337 } | 337 } |
| 338 } | 338 } |
| 339 } | 339 } |
| 340 if (target_kind != origin_kind) { | 340 if (target_kind != origin_kind) { |
| 341 JSObject::TransitionElementsKind(array, target_kind); | 341 JSObject::TransitionElementsKind(array, target_kind); |
| 342 return handle(array->elements()); | 342 return handle(array->elements(), isolate); |
| 343 } | 343 } |
| 344 return elms; | 344 return elms; |
| 345 } | 345 } |
| 346 | 346 |
| 347 | 347 |
| 348 // TODO(ishell): Handlify when all Array* builtins are handlified. | 348 // TODO(ishell): Handlify when all Array* builtins are handlified. |
| 349 static inline bool IsJSArrayFastElementMovingAllowed(Heap* heap, | 349 static inline bool IsJSArrayFastElementMovingAllowed(Heap* heap, |
| 350 JSArray* receiver) { | 350 JSArray* receiver) { |
| 351 if (!FLAG_clever_optimizations) return false; | 351 if (!FLAG_clever_optimizations) return false; |
| 352 Context* native_context = heap->isolate()->context()->native_context(); | 352 Context* native_context = heap->isolate()->context()->native_context(); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 411 int new_length = len + to_add; | 411 int new_length = len + to_add; |
| 412 | 412 |
| 413 if (new_length > elms->length()) { | 413 if (new_length > elms->length()) { |
| 414 // New backing storage is needed. | 414 // New backing storage is needed. |
| 415 int capacity = new_length + (new_length >> 1) + 16; | 415 int capacity = new_length + (new_length >> 1) + 16; |
| 416 Handle<FixedArray> new_elms = | 416 Handle<FixedArray> new_elms = |
| 417 isolate->factory()->NewUninitializedFixedArray(capacity); | 417 isolate->factory()->NewUninitializedFixedArray(capacity); |
| 418 | 418 |
| 419 ElementsAccessor* accessor = array->GetElementsAccessor(); | 419 ElementsAccessor* accessor = array->GetElementsAccessor(); |
| 420 accessor->CopyElements( | 420 accessor->CopyElements( |
| 421 Handle<JSObject>::null(), 0, kind, new_elms, 0, | 421 elms_obj, 0, kind, new_elms, 0, |
| 422 ElementsAccessor::kCopyToEndAndInitializeToHole, elms_obj); | 422 ElementsAccessor::kCopyToEndAndInitializeToHole); |
| 423 | 423 |
| 424 elms = new_elms; | 424 elms = new_elms; |
| 425 } | 425 } |
| 426 | 426 |
| 427 // Add the provided values. | 427 // Add the provided values. |
| 428 DisallowHeapAllocation no_gc; | 428 DisallowHeapAllocation no_gc; |
| 429 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); | 429 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); |
| 430 for (int index = 0; index < to_add; index++) { | 430 for (int index = 0; index < to_add; index++) { |
| 431 elms->set(index + len, args[index + 1], mode); | 431 elms->set(index + len, args[index + 1], mode); |
| 432 } | 432 } |
| (...skipping 21 matching lines...) Expand all Loading... |
| 454 | 454 |
| 455 Handle<FixedDoubleArray> new_elms; | 455 Handle<FixedDoubleArray> new_elms; |
| 456 | 456 |
| 457 if (new_length > elms_len) { | 457 if (new_length > elms_len) { |
| 458 // New backing storage is needed. | 458 // New backing storage is needed. |
| 459 int capacity = new_length + (new_length >> 1) + 16; | 459 int capacity = new_length + (new_length >> 1) + 16; |
| 460 new_elms = isolate->factory()->NewFixedDoubleArray(capacity); | 460 new_elms = isolate->factory()->NewFixedDoubleArray(capacity); |
| 461 | 461 |
| 462 ElementsAccessor* accessor = array->GetElementsAccessor(); | 462 ElementsAccessor* accessor = array->GetElementsAccessor(); |
| 463 accessor->CopyElements( | 463 accessor->CopyElements( |
| 464 Handle<JSObject>::null(), 0, kind, new_elms, 0, | 464 elms_obj, 0, kind, new_elms, 0, |
| 465 ElementsAccessor::kCopyToEndAndInitializeToHole, elms_obj); | 465 ElementsAccessor::kCopyToEndAndInitializeToHole); |
| 466 | 466 |
| 467 } else { | 467 } else { |
| 468 // to_add is > 0 and new_length <= elms_len, so elms_obj cannot be the | 468 // to_add is > 0 and new_length <= elms_len, so elms_obj cannot be the |
| 469 // empty_fixed_array. | 469 // empty_fixed_array. |
| 470 new_elms = Handle<FixedDoubleArray>::cast(elms_obj); | 470 new_elms = Handle<FixedDoubleArray>::cast(elms_obj); |
| 471 } | 471 } |
| 472 | 472 |
| 473 // Add the provided values. | 473 // Add the provided values. |
| 474 DisallowHeapAllocation no_gc; | 474 DisallowHeapAllocation no_gc; |
| 475 int index; | 475 int index; |
| 476 for (index = 0; index < to_add; index++) { | 476 for (index = 0; index < to_add; index++) { |
| 477 Object* arg = args[index + 1]; | 477 Object* arg = args[index + 1]; |
| 478 new_elms->set(index + len, arg->Number()); | 478 new_elms->set(index + len, arg->Number()); |
| 479 } | 479 } |
| 480 | 480 |
| 481 if (*new_elms != array->elements()) { | 481 if (*new_elms != array->elements()) { |
| 482 array->set_elements(*new_elms); | 482 array->set_elements(*new_elms); |
| 483 } | 483 } |
| 484 | 484 |
| 485 // Set the length. | 485 // Set the length. |
| 486 array->set_length(Smi::FromInt(new_length)); | 486 array->set_length(Smi::FromInt(new_length)); |
| 487 return Smi::FromInt(new_length); | 487 return Smi::FromInt(new_length); |
| 488 } | 488 } |
| 489 } | 489 } |
| 490 | 490 |
| 491 | 491 |
| 492 // TODO(ishell): Temporary wrapper until handlified. | |
| 493 static bool ElementsAccessorHasElementWrapper( | |
| 494 ElementsAccessor* accessor, | |
| 495 Handle<Object> receiver, | |
| 496 Handle<JSObject> holder, | |
| 497 uint32_t key, | |
| 498 Handle<FixedArrayBase> backing_store = Handle<FixedArrayBase>::null()) { | |
| 499 return accessor->HasElement(*receiver, *holder, key, | |
| 500 backing_store.is_null() ? NULL : *backing_store); | |
| 501 } | |
| 502 | |
| 503 | |
| 504 BUILTIN(ArrayPop) { | 492 BUILTIN(ArrayPop) { |
| 505 HandleScope scope(isolate); | 493 HandleScope scope(isolate); |
| 506 Handle<Object> receiver = args.receiver(); | 494 Handle<Object> receiver = args.receiver(); |
| 507 Handle<FixedArrayBase> elms_obj = | 495 Handle<FixedArrayBase> elms_obj = |
| 508 EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0); | 496 EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0); |
| 509 if (elms_obj.is_null()) return CallJsBuiltin(isolate, "ArrayPop", args); | 497 if (elms_obj.is_null()) return CallJsBuiltin(isolate, "ArrayPop", args); |
| 510 | 498 |
| 511 Handle<JSArray> array = Handle<JSArray>::cast(receiver); | 499 Handle<JSArray> array = Handle<JSArray>::cast(receiver); |
| 512 ASSERT(!array->map()->is_observed()); | 500 ASSERT(!array->map()->is_observed()); |
| 513 | 501 |
| 514 int len = Smi::cast(array->length())->value(); | 502 int len = Smi::cast(array->length())->value(); |
| 515 if (len == 0) return isolate->heap()->undefined_value(); | 503 if (len == 0) return isolate->heap()->undefined_value(); |
| 516 | 504 |
| 517 ElementsAccessor* accessor = array->GetElementsAccessor(); | 505 ElementsAccessor* accessor = array->GetElementsAccessor(); |
| 518 int new_length = len - 1; | 506 int new_length = len - 1; |
| 519 Handle<Object> element; | 507 Handle<Object> element; |
| 520 if (ElementsAccessorHasElementWrapper( | 508 if (accessor->HasElement(*array, *array, new_length, *elms_obj)) { |
| 521 accessor, array, array, new_length, elms_obj)) { | |
| 522 element = accessor->Get( | 509 element = accessor->Get( |
| 523 array, array, new_length, elms_obj); | 510 array, array, new_length, elms_obj); |
| 524 } else { | 511 } else { |
| 525 Handle<Object> proto(array->GetPrototype(), isolate); | 512 Handle<Object> proto(array->GetPrototype(), isolate); |
| 526 element = Object::GetElement(isolate, proto, len - 1); | 513 element = Object::GetElement(isolate, proto, len - 1); |
| 527 } | 514 } |
| 528 RETURN_IF_EMPTY_HANDLE(isolate, element); | 515 RETURN_IF_EMPTY_HANDLE(isolate, element); |
| 529 RETURN_IF_EMPTY_HANDLE(isolate, | 516 RETURN_IF_EMPTY_HANDLE(isolate, |
| 530 accessor->SetLength( | 517 accessor->SetLength( |
| 531 array, handle(Smi::FromInt(new_length), isolate))); | 518 array, handle(Smi::FromInt(new_length), isolate))); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 611 | 598 |
| 612 if (new_length > elms->length()) { | 599 if (new_length > elms->length()) { |
| 613 // New backing storage is needed. | 600 // New backing storage is needed. |
| 614 int capacity = new_length + (new_length >> 1) + 16; | 601 int capacity = new_length + (new_length >> 1) + 16; |
| 615 Handle<FixedArray> new_elms = | 602 Handle<FixedArray> new_elms = |
| 616 isolate->factory()->NewUninitializedFixedArray(capacity); | 603 isolate->factory()->NewUninitializedFixedArray(capacity); |
| 617 | 604 |
| 618 ElementsKind kind = array->GetElementsKind(); | 605 ElementsKind kind = array->GetElementsKind(); |
| 619 ElementsAccessor* accessor = array->GetElementsAccessor(); | 606 ElementsAccessor* accessor = array->GetElementsAccessor(); |
| 620 accessor->CopyElements( | 607 accessor->CopyElements( |
| 621 Handle<JSObject>::null(), 0, kind, new_elms, to_add, | 608 elms, 0, kind, new_elms, to_add, |
| 622 ElementsAccessor::kCopyToEndAndInitializeToHole, elms); | 609 ElementsAccessor::kCopyToEndAndInitializeToHole); |
| 623 | 610 |
| 624 elms = new_elms; | 611 elms = new_elms; |
| 625 array->set_elements(*elms); | 612 array->set_elements(*elms); |
| 626 } else { | 613 } else { |
| 627 DisallowHeapAllocation no_gc; | 614 DisallowHeapAllocation no_gc; |
| 628 heap->MoveElements(*elms, to_add, 0, len); | 615 heap->MoveElements(*elms, to_add, 0, len); |
| 629 } | 616 } |
| 630 | 617 |
| 631 // Add the provided values. | 618 // Add the provided values. |
| 632 DisallowHeapAllocation no_gc; | 619 DisallowHeapAllocation no_gc; |
| 633 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); | 620 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); |
| 634 for (int i = 0; i < to_add; i++) { | 621 for (int i = 0; i < to_add; i++) { |
| 635 elms->set(i, args[i + 1], mode); | 622 elms->set(i, args[i + 1], mode); |
| 636 } | 623 } |
| 637 | 624 |
| 638 // Set the length. | 625 // Set the length. |
| 639 array->set_length(Smi::FromInt(new_length)); | 626 array->set_length(Smi::FromInt(new_length)); |
| 640 return Smi::FromInt(new_length); | 627 return Smi::FromInt(new_length); |
| 641 } | 628 } |
| 642 | 629 |
| 643 | 630 |
| 644 BUILTIN(ArraySlice) { | 631 BUILTIN(ArraySlice) { |
| 645 HandleScope scope(isolate); | 632 HandleScope scope(isolate); |
| 646 Heap* heap = isolate->heap(); | 633 Heap* heap = isolate->heap(); |
| 647 Handle<Object> receiver = args.receiver(); | 634 Handle<Object> receiver = args.receiver(); |
| 648 Handle<FixedArrayBase> elms; | |
| 649 int len = -1; | 635 int len = -1; |
| 650 if (receiver->IsJSArray()) { | 636 int relative_start = 0; |
| 651 Handle<JSArray> array = Handle<JSArray>::cast(receiver); | 637 int relative_end = 0; |
| 652 if (!IsJSArrayFastElementMovingAllowed(heap, *array)) { | 638 { |
| 653 return CallJsBuiltin(isolate, "ArraySlice", args); | 639 DisallowHeapAllocation no_gc; |
| 640 if (receiver->IsJSArray()) { |
| 641 JSArray* array = JSArray::cast(*receiver); |
| 642 if (!IsJSArrayFastElementMovingAllowed(heap, array)) { |
| 643 AllowHeapAllocation allow_allocation; |
| 644 return CallJsBuiltin(isolate, "ArraySlice", args); |
| 645 } |
| 646 |
| 647 if (!array->HasFastElements()) { |
| 648 AllowHeapAllocation allow_allocation; |
| 649 return CallJsBuiltin(isolate, "ArraySlice", args); |
| 650 } |
| 651 |
| 652 len = Smi::cast(array->length())->value(); |
| 653 } else { |
| 654 // Array.slice(arguments, ...) is quite a common idiom (notably more |
| 655 // than 50% of invocations in Web apps). Treat it in C++ as well. |
| 656 Map* arguments_map = isolate->context()->native_context()-> |
| 657 sloppy_arguments_boilerplate()->map(); |
| 658 |
| 659 bool is_arguments_object_with_fast_elements = |
| 660 receiver->IsJSObject() && |
| 661 JSObject::cast(*receiver)->map() == arguments_map; |
| 662 if (!is_arguments_object_with_fast_elements) { |
| 663 AllowHeapAllocation allow_allocation; |
| 664 return CallJsBuiltin(isolate, "ArraySlice", args); |
| 665 } |
| 666 JSObject* object = JSObject::cast(*receiver); |
| 667 |
| 668 if (!object->HasFastElements()) { |
| 669 AllowHeapAllocation allow_allocation; |
| 670 return CallJsBuiltin(isolate, "ArraySlice", args); |
| 671 } |
| 672 |
| 673 Object* len_obj = object->InObjectPropertyAt(Heap::kArgumentsLengthIndex); |
| 674 if (!len_obj->IsSmi()) { |
| 675 AllowHeapAllocation allow_allocation; |
| 676 return CallJsBuiltin(isolate, "ArraySlice", args); |
| 677 } |
| 678 len = Smi::cast(len_obj)->value(); |
| 679 if (len > object->elements()->length()) { |
| 680 AllowHeapAllocation allow_allocation; |
| 681 return CallJsBuiltin(isolate, "ArraySlice", args); |
| 682 } |
| 654 } | 683 } |
| 655 | 684 |
| 656 if (array->HasFastElements()) { | 685 ASSERT(len >= 0); |
| 657 elms = handle(array->elements()); | 686 int n_arguments = args.length() - 1; |
| 658 } else { | |
| 659 return CallJsBuiltin(isolate, "ArraySlice", args); | |
| 660 } | |
| 661 | 687 |
| 662 len = Smi::cast(array->length())->value(); | 688 // Note carefully choosen defaults---if argument is missing, |
| 663 } else { | 689 // it's undefined which gets converted to 0 for relative_start |
| 664 // Array.slice(arguments, ...) is quite a common idiom (notably more | 690 // and to len for relative_end. |
| 665 // than 50% of invocations in Web apps). Treat it in C++ as well. | 691 relative_start = 0; |
| 666 Handle<Map> arguments_map(isolate->context()->native_context()-> | 692 relative_end = len; |
| 667 sloppy_arguments_boilerplate()->map()); | 693 if (n_arguments > 0) { |
| 668 | 694 Object* arg1 = args[1]; |
| 669 bool is_arguments_object_with_fast_elements = | 695 if (arg1->IsSmi()) { |
| 670 receiver->IsJSObject() && | 696 relative_start = Smi::cast(arg1)->value(); |
| 671 Handle<JSObject>::cast(receiver)->map() == *arguments_map; | 697 } else if (arg1->IsHeapNumber()) { |
| 672 if (!is_arguments_object_with_fast_elements) { | 698 double start = HeapNumber::cast(arg1)->value(); |
| 673 return CallJsBuiltin(isolate, "ArraySlice", args); | 699 if (start < kMinInt || start > kMaxInt) { |
| 674 } | 700 AllowHeapAllocation allow_allocation; |
| 675 Handle<JSObject> object = Handle<JSObject>::cast(receiver); | 701 return CallJsBuiltin(isolate, "ArraySlice", args); |
| 676 | 702 } |
| 677 if (object->HasFastElements()) { | 703 relative_start = std::isnan(start) ? 0 : static_cast<int>(start); |
| 678 elms = handle(object->elements()); | 704 } else if (!arg1->IsUndefined()) { |
| 679 } else { | 705 AllowHeapAllocation allow_allocation; |
| 680 return CallJsBuiltin(isolate, "ArraySlice", args); | |
| 681 } | |
| 682 Handle<Object> len_obj( | |
| 683 object->InObjectPropertyAt(Heap::kArgumentsLengthIndex), isolate); | |
| 684 if (!len_obj->IsSmi()) { | |
| 685 return CallJsBuiltin(isolate, "ArraySlice", args); | |
| 686 } | |
| 687 len = Handle<Smi>::cast(len_obj)->value(); | |
| 688 if (len > elms->length()) { | |
| 689 return CallJsBuiltin(isolate, "ArraySlice", args); | |
| 690 } | |
| 691 } | |
| 692 | |
| 693 Handle<JSObject> object = Handle<JSObject>::cast(receiver); | |
| 694 | |
| 695 ASSERT(len >= 0); | |
| 696 int n_arguments = args.length() - 1; | |
| 697 | |
| 698 // Note carefully choosen defaults---if argument is missing, | |
| 699 // it's undefined which gets converted to 0 for relative_start | |
| 700 // and to len for relative_end. | |
| 701 int relative_start = 0; | |
| 702 int relative_end = len; | |
| 703 if (n_arguments > 0) { | |
| 704 Handle<Object> arg1 = args.at<Object>(1); | |
| 705 if (arg1->IsSmi()) { | |
| 706 relative_start = Handle<Smi>::cast(arg1)->value(); | |
| 707 } else if (arg1->IsHeapNumber()) { | |
| 708 double start = Handle<HeapNumber>::cast(arg1)->value(); | |
| 709 if (start < kMinInt || start > kMaxInt) { | |
| 710 return CallJsBuiltin(isolate, "ArraySlice", args); | 706 return CallJsBuiltin(isolate, "ArraySlice", args); |
| 711 } | 707 } |
| 712 relative_start = std::isnan(start) ? 0 : static_cast<int>(start); | 708 if (n_arguments > 1) { |
| 713 } else if (!arg1->IsUndefined()) { | 709 Object* arg2 = args[2]; |
| 714 return CallJsBuiltin(isolate, "ArraySlice", args); | 710 if (arg2->IsSmi()) { |
| 715 } | 711 relative_end = Smi::cast(arg2)->value(); |
| 716 if (n_arguments > 1) { | 712 } else if (arg2->IsHeapNumber()) { |
| 717 Handle<Object> arg2 = args.at<Object>(2); | 713 double end = HeapNumber::cast(arg2)->value(); |
| 718 if (arg2->IsSmi()) { | 714 if (end < kMinInt || end > kMaxInt) { |
| 719 relative_end = Handle<Smi>::cast(arg2)->value(); | 715 AllowHeapAllocation allow_allocation; |
| 720 } else if (arg2->IsHeapNumber()) { | 716 return CallJsBuiltin(isolate, "ArraySlice", args); |
| 721 double end = Handle<HeapNumber>::cast(arg2)->value(); | 717 } |
| 722 if (end < kMinInt || end > kMaxInt) { | 718 relative_end = std::isnan(end) ? 0 : static_cast<int>(end); |
| 719 } else if (!arg2->IsUndefined()) { |
| 720 AllowHeapAllocation allow_allocation; |
| 723 return CallJsBuiltin(isolate, "ArraySlice", args); | 721 return CallJsBuiltin(isolate, "ArraySlice", args); |
| 724 } | 722 } |
| 725 relative_end = std::isnan(end) ? 0 : static_cast<int>(end); | |
| 726 } else if (!arg2->IsUndefined()) { | |
| 727 return CallJsBuiltin(isolate, "ArraySlice", args); | |
| 728 } | 723 } |
| 729 } | 724 } |
| 730 } | 725 } |
| 731 | 726 |
| 732 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 6. | 727 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 6. |
| 733 int k = (relative_start < 0) ? Max(len + relative_start, 0) | 728 int k = (relative_start < 0) ? Max(len + relative_start, 0) |
| 734 : Min(relative_start, len); | 729 : Min(relative_start, len); |
| 735 | 730 |
| 736 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 8. | 731 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 8. |
| 737 int final = (relative_end < 0) ? Max(len + relative_end, 0) | 732 int final = (relative_end < 0) ? Max(len + relative_end, 0) |
| 738 : Min(relative_end, len); | 733 : Min(relative_end, len); |
| 739 | 734 |
| 740 // Calculate the length of result array. | 735 // Calculate the length of result array. |
| 741 int result_len = Max(final - k, 0); | 736 int result_len = Max(final - k, 0); |
| 742 | 737 |
| 738 Handle<JSObject> object = Handle<JSObject>::cast(receiver); |
| 739 Handle<FixedArrayBase> elms(object->elements(), isolate); |
| 740 |
| 743 ElementsKind kind = object->GetElementsKind(); | 741 ElementsKind kind = object->GetElementsKind(); |
| 744 if (IsHoleyElementsKind(kind)) { | 742 if (IsHoleyElementsKind(kind)) { |
| 743 DisallowHeapAllocation no_gc; |
| 745 bool packed = true; | 744 bool packed = true; |
| 746 ElementsAccessor* accessor = ElementsAccessor::ForKind(kind); | 745 ElementsAccessor* accessor = ElementsAccessor::ForKind(kind); |
| 747 for (int i = k; i < final; i++) { | 746 for (int i = k; i < final; i++) { |
| 748 if (!ElementsAccessorHasElementWrapper( | 747 if (!accessor->HasElement(*object, *object, i, *elms)) { |
| 749 accessor, object, object, i, elms)) { | |
| 750 packed = false; | 748 packed = false; |
| 751 break; | 749 break; |
| 752 } | 750 } |
| 753 } | 751 } |
| 754 if (packed) { | 752 if (packed) { |
| 755 kind = GetPackedElementsKind(kind); | 753 kind = GetPackedElementsKind(kind); |
| 756 } else if (!receiver->IsJSArray()) { | 754 } else if (!receiver->IsJSArray()) { |
| 755 AllowHeapAllocation allow_allocation; |
| 757 return CallJsBuiltin(isolate, "ArraySlice", args); | 756 return CallJsBuiltin(isolate, "ArraySlice", args); |
| 758 } | 757 } |
| 759 } | 758 } |
| 760 | 759 |
| 761 Handle<JSArray> result_array = | 760 Handle<JSArray> result_array = |
| 762 isolate->factory()->NewJSArray(kind, result_len, result_len); | 761 isolate->factory()->NewJSArray(kind, result_len, result_len); |
| 763 | 762 |
| 764 DisallowHeapAllocation no_gc; | 763 DisallowHeapAllocation no_gc; |
| 765 if (result_len == 0) return *result_array; | 764 if (result_len == 0) return *result_array; |
| 766 | 765 |
| 767 ElementsAccessor* accessor = object->GetElementsAccessor(); | 766 ElementsAccessor* accessor = object->GetElementsAccessor(); |
| 768 accessor->CopyElements(Handle<JSObject>::null(), k, kind, | 767 accessor->CopyElements( |
| 769 handle(result_array->elements()), 0, result_len, elms); | 768 elms, k, kind, handle(result_array->elements(), isolate), 0, result_len); |
| 770 return *result_array; | 769 return *result_array; |
| 771 } | 770 } |
| 772 | 771 |
| 773 | 772 |
| 774 BUILTIN(ArraySplice) { | 773 BUILTIN(ArraySplice) { |
| 775 HandleScope scope(isolate); | 774 HandleScope scope(isolate); |
| 776 Heap* heap = isolate->heap(); | 775 Heap* heap = isolate->heap(); |
| 777 Handle<Object> receiver = args.receiver(); | 776 Handle<Object> receiver = args.receiver(); |
| 778 Handle<FixedArrayBase> elms_obj = | 777 Handle<FixedArrayBase> elms_obj = |
| 779 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 3); | 778 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 3); |
| 780 if (elms_obj.is_null() || | 779 if (elms_obj.is_null() || |
| 781 !IsJSArrayFastElementMovingAllowed(heap, | 780 !IsJSArrayFastElementMovingAllowed(heap, |
| 782 *Handle<JSArray>::cast(receiver))) { | 781 *Handle<JSArray>::cast(receiver))) { |
| 783 return CallJsBuiltin(isolate, "ArraySplice", args); | 782 return CallJsBuiltin(isolate, "ArraySplice", args); |
| 784 } | 783 } |
| 785 Handle<JSArray> array = Handle<JSArray>::cast(receiver); | 784 Handle<JSArray> array = Handle<JSArray>::cast(receiver); |
| 786 ASSERT(!array->map()->is_observed()); | 785 ASSERT(!array->map()->is_observed()); |
| 787 | 786 |
| 788 int len = Smi::cast(array->length())->value(); | 787 int len = Smi::cast(array->length())->value(); |
| 789 | 788 |
| 790 int n_arguments = args.length() - 1; | 789 int n_arguments = args.length() - 1; |
| 791 | 790 |
| 792 int relative_start = 0; | 791 int relative_start = 0; |
| 793 if (n_arguments > 0) { | 792 if (n_arguments > 0) { |
| 794 Handle<Object> arg1 = args.at<Object>(1); | 793 DisallowHeapAllocation no_gc; |
| 794 Object* arg1 = args[1]; |
| 795 if (arg1->IsSmi()) { | 795 if (arg1->IsSmi()) { |
| 796 relative_start = Handle<Smi>::cast(arg1)->value(); | 796 relative_start = Smi::cast(arg1)->value(); |
| 797 } else if (arg1->IsHeapNumber()) { | 797 } else if (arg1->IsHeapNumber()) { |
| 798 double start = Handle<HeapNumber>::cast(arg1)->value(); | 798 double start = HeapNumber::cast(arg1)->value(); |
| 799 if (start < kMinInt || start > kMaxInt) { | 799 if (start < kMinInt || start > kMaxInt) { |
| 800 AllowHeapAllocation allow_allocation; |
| 800 return CallJsBuiltin(isolate, "ArraySplice", args); | 801 return CallJsBuiltin(isolate, "ArraySplice", args); |
| 801 } | 802 } |
| 802 relative_start = std::isnan(start) ? 0 : static_cast<int>(start); | 803 relative_start = std::isnan(start) ? 0 : static_cast<int>(start); |
| 803 } else if (!arg1->IsUndefined()) { | 804 } else if (!arg1->IsUndefined()) { |
| 805 AllowHeapAllocation allow_allocation; |
| 804 return CallJsBuiltin(isolate, "ArraySplice", args); | 806 return CallJsBuiltin(isolate, "ArraySplice", args); |
| 805 } | 807 } |
| 806 } | 808 } |
| 807 int actual_start = (relative_start < 0) ? Max(len + relative_start, 0) | 809 int actual_start = (relative_start < 0) ? Max(len + relative_start, 0) |
| 808 : Min(relative_start, len); | 810 : Min(relative_start, len); |
| 809 | 811 |
| 810 // SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is | 812 // SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is |
| 811 // given as a request to delete all the elements from the start. | 813 // given as a request to delete all the elements from the start. |
| 812 // And it differs from the case of undefined delete count. | 814 // And it differs from the case of undefined delete count. |
| 813 // This does not follow ECMA-262, but we do the same for | 815 // This does not follow ECMA-262, but we do the same for |
| 814 // compatibility. | 816 // compatibility. |
| 815 int actual_delete_count; | 817 int actual_delete_count; |
| 816 if (n_arguments == 1) { | 818 if (n_arguments == 1) { |
| 817 ASSERT(len - actual_start >= 0); | 819 ASSERT(len - actual_start >= 0); |
| 818 actual_delete_count = len - actual_start; | 820 actual_delete_count = len - actual_start; |
| 819 } else { | 821 } else { |
| 820 int value = 0; // ToInteger(undefined) == 0 | 822 int value = 0; // ToInteger(undefined) == 0 |
| 821 if (n_arguments > 1) { | 823 if (n_arguments > 1) { |
| 824 DisallowHeapAllocation no_gc; |
| 822 Object* arg2 = args[2]; | 825 Object* arg2 = args[2]; |
| 823 if (arg2->IsSmi()) { | 826 if (arg2->IsSmi()) { |
| 824 value = Smi::cast(arg2)->value(); | 827 value = Smi::cast(arg2)->value(); |
| 825 } else { | 828 } else { |
| 829 AllowHeapAllocation allow_allocation; |
| 826 return CallJsBuiltin(isolate, "ArraySplice", args); | 830 return CallJsBuiltin(isolate, "ArraySplice", args); |
| 827 } | 831 } |
| 828 } | 832 } |
| 829 actual_delete_count = Min(Max(value, 0), len - actual_start); | 833 actual_delete_count = Min(Max(value, 0), len - actual_start); |
| 830 } | 834 } |
| 831 | 835 |
| 832 ElementsKind elements_kind = array->GetElementsKind(); | 836 ElementsKind elements_kind = array->GetElementsKind(); |
| 833 | 837 |
| 834 int item_count = (n_arguments > 1) ? (n_arguments - 2) : 0; | 838 int item_count = (n_arguments > 1) ? (n_arguments - 2) : 0; |
| 835 int new_length = len - actual_delete_count + item_count; | 839 int new_length = len - actual_delete_count + item_count; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 849 | 853 |
| 850 Handle<JSArray> result_array = | 854 Handle<JSArray> result_array = |
| 851 isolate->factory()->NewJSArray(elements_kind, | 855 isolate->factory()->NewJSArray(elements_kind, |
| 852 actual_delete_count, | 856 actual_delete_count, |
| 853 actual_delete_count); | 857 actual_delete_count); |
| 854 | 858 |
| 855 if (actual_delete_count > 0) { | 859 if (actual_delete_count > 0) { |
| 856 DisallowHeapAllocation no_gc; | 860 DisallowHeapAllocation no_gc; |
| 857 ElementsAccessor* accessor = array->GetElementsAccessor(); | 861 ElementsAccessor* accessor = array->GetElementsAccessor(); |
| 858 accessor->CopyElements( | 862 accessor->CopyElements( |
| 859 Handle<JSObject>::null(), actual_start, elements_kind, | 863 elms_obj, actual_start, elements_kind, |
| 860 handle(result_array->elements()), 0, actual_delete_count, elms_obj); | 864 handle(result_array->elements(), isolate), 0, actual_delete_count); |
| 861 } | 865 } |
| 862 | 866 |
| 863 bool elms_changed = false; | 867 bool elms_changed = false; |
| 864 if (item_count < actual_delete_count) { | 868 if (item_count < actual_delete_count) { |
| 865 // Shrink the array. | 869 // Shrink the array. |
| 866 const bool trim_array = !heap->lo_space()->Contains(*elms_obj) && | 870 const bool trim_array = !heap->lo_space()->Contains(*elms_obj) && |
| 867 ((actual_start + item_count) < | 871 ((actual_start + item_count) < |
| 868 (len - actual_delete_count - actual_start)); | 872 (len - actual_delete_count - actual_start)); |
| 869 if (trim_array) { | 873 if (trim_array) { |
| 870 const int delta = actual_delete_count - item_count; | 874 const int delta = actual_delete_count - item_count; |
| 871 | 875 |
| 872 if (elms_obj->IsFixedDoubleArray()) { | 876 if (elms_obj->IsFixedDoubleArray()) { |
| 873 Handle<FixedDoubleArray> elms = | 877 Handle<FixedDoubleArray> elms = |
| 874 Handle<FixedDoubleArray>::cast(elms_obj); | 878 Handle<FixedDoubleArray>::cast(elms_obj); |
| 875 MoveDoubleElements(*elms, delta, *elms, 0, actual_start); | 879 MoveDoubleElements(*elms, delta, *elms, 0, actual_start); |
| 876 } else { | 880 } else { |
| 877 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj); | 881 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj); |
| 878 DisallowHeapAllocation no_gc; | 882 DisallowHeapAllocation no_gc; |
| 879 heap->MoveElements(*elms, delta, 0, actual_start); | 883 heap->MoveElements(*elms, delta, 0, actual_start); |
| 880 } | 884 } |
| 881 | 885 |
| 882 if (heap->CanMoveObjectStart(*elms_obj)) { | 886 if (heap->CanMoveObjectStart(*elms_obj)) { |
| 883 // On the fast path we move the start of the object in memory. | 887 // On the fast path we move the start of the object in memory. |
| 884 elms_obj = handle(LeftTrimFixedArray(heap, *elms_obj, delta)); | 888 elms_obj = handle(LeftTrimFixedArray(heap, *elms_obj, delta), isolate); |
| 885 } else { | 889 } else { |
| 886 // This is the slow path. We are going to move the elements to the left | 890 // This is the slow path. We are going to move the elements to the left |
| 887 // by copying them. For trimmed values we store the hole. | 891 // by copying them. For trimmed values we store the hole. |
| 888 if (elms_obj->IsFixedDoubleArray()) { | 892 if (elms_obj->IsFixedDoubleArray()) { |
| 889 Handle<FixedDoubleArray> elms = | 893 Handle<FixedDoubleArray> elms = |
| 890 Handle<FixedDoubleArray>::cast(elms_obj); | 894 Handle<FixedDoubleArray>::cast(elms_obj); |
| 891 MoveDoubleElements(*elms, 0, *elms, delta, len - delta); | 895 MoveDoubleElements(*elms, 0, *elms, delta, len - delta); |
| 892 elms->FillWithHoles(len - delta, len); | 896 elms->FillWithHoles(len - delta, len); |
| 893 } else { | 897 } else { |
| 894 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj); | 898 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 928 Handle<FixedArray> new_elms = | 932 Handle<FixedArray> new_elms = |
| 929 isolate->factory()->NewUninitializedFixedArray(capacity); | 933 isolate->factory()->NewUninitializedFixedArray(capacity); |
| 930 | 934 |
| 931 DisallowHeapAllocation no_gc; | 935 DisallowHeapAllocation no_gc; |
| 932 | 936 |
| 933 ElementsKind kind = array->GetElementsKind(); | 937 ElementsKind kind = array->GetElementsKind(); |
| 934 ElementsAccessor* accessor = array->GetElementsAccessor(); | 938 ElementsAccessor* accessor = array->GetElementsAccessor(); |
| 935 if (actual_start > 0) { | 939 if (actual_start > 0) { |
| 936 // Copy the part before actual_start as is. | 940 // Copy the part before actual_start as is. |
| 937 accessor->CopyElements( | 941 accessor->CopyElements( |
| 938 Handle<JSObject>::null(), 0, kind, new_elms, 0, actual_start, elms); | 942 elms, 0, kind, new_elms, 0, actual_start); |
| 939 } | 943 } |
| 940 accessor->CopyElements( | 944 accessor->CopyElements( |
| 941 Handle<JSObject>::null(), actual_start + actual_delete_count, kind, | 945 elms, actual_start + actual_delete_count, kind, |
| 942 new_elms, actual_start + item_count, | 946 new_elms, actual_start + item_count, |
| 943 ElementsAccessor::kCopyToEndAndInitializeToHole, elms); | 947 ElementsAccessor::kCopyToEndAndInitializeToHole); |
| 944 | 948 |
| 945 elms_obj = new_elms; | 949 elms_obj = new_elms; |
| 946 elms_changed = true; | 950 elms_changed = true; |
| 947 } else { | 951 } else { |
| 948 DisallowHeapAllocation no_gc; | 952 DisallowHeapAllocation no_gc; |
| 949 heap->MoveElements(*elms, actual_start + item_count, | 953 heap->MoveElements(*elms, actual_start + item_count, |
| 950 actual_start + actual_delete_count, | 954 actual_start + actual_delete_count, |
| 951 (len - actual_delete_count - actual_start)); | 955 (len - actual_delete_count - actual_start)); |
| 952 } | 956 } |
| 953 } | 957 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 977 // Set the length. | 981 // Set the length. |
| 978 array->set_length(Smi::FromInt(new_length)); | 982 array->set_length(Smi::FromInt(new_length)); |
| 979 | 983 |
| 980 return *result_array; | 984 return *result_array; |
| 981 } | 985 } |
| 982 | 986 |
| 983 | 987 |
| 984 BUILTIN(ArrayConcat) { | 988 BUILTIN(ArrayConcat) { |
| 985 HandleScope scope(isolate); | 989 HandleScope scope(isolate); |
| 986 Heap* heap = isolate->heap(); | 990 Heap* heap = isolate->heap(); |
| 987 Handle<Context> native_context(isolate->context()->native_context()); | 991 Handle<Context> native_context(isolate->context()->native_context(), isolate); |
| 988 Handle<JSObject> array_proto( | 992 Handle<JSObject> array_proto( |
| 989 JSObject::cast(native_context->array_function()->prototype())); | 993 JSObject::cast(native_context->array_function()->prototype()), isolate); |
| 990 if (!ArrayPrototypeHasNoElements(heap, *native_context, *array_proto)) { | 994 if (!ArrayPrototypeHasNoElements(heap, *native_context, *array_proto)) { |
| 991 return CallJsBuiltin(isolate, "ArrayConcat", args); | 995 return CallJsBuiltin(isolate, "ArrayConcat", args); |
| 992 } | 996 } |
| 993 | 997 |
| 994 // Iterate through all the arguments performing checks | 998 // Iterate through all the arguments performing checks |
| 995 // and calculating total length. | 999 // and calculating total length. |
| 996 int n_arguments = args.length(); | 1000 int n_arguments = args.length(); |
| 997 int result_len = 0; | 1001 int result_len = 0; |
| 998 ElementsKind elements_kind = GetInitialFastElementsKind(); | 1002 ElementsKind elements_kind = GetInitialFastElementsKind(); |
| 999 bool has_double = false; | 1003 bool has_double = false; |
| 1000 bool is_holey = false; | 1004 bool is_holey = false; |
| 1001 for (int i = 0; i < n_arguments; i++) { | 1005 for (int i = 0; i < n_arguments; i++) { |
| 1002 Handle<Object> arg = args.at<Object>(i); | 1006 DisallowHeapAllocation no_gc; |
| 1007 Object* arg = args[i]; |
| 1003 if (!arg->IsJSArray() || | 1008 if (!arg->IsJSArray() || |
| 1004 !Handle<JSArray>::cast(arg)->HasFastElements() || | 1009 !JSArray::cast(arg)->HasFastElements() || |
| 1005 Handle<JSArray>::cast(arg)->GetPrototype() != *array_proto) { | 1010 JSArray::cast(arg)->GetPrototype() != *array_proto) { |
| 1011 AllowHeapAllocation allow_allocation; |
| 1006 return CallJsBuiltin(isolate, "ArrayConcat", args); | 1012 return CallJsBuiltin(isolate, "ArrayConcat", args); |
| 1007 } | 1013 } |
| 1008 int len = Smi::cast(Handle<JSArray>::cast(arg)->length())->value(); | 1014 int len = Smi::cast(JSArray::cast(arg)->length())->value(); |
| 1009 | 1015 |
| 1010 // We shouldn't overflow when adding another len. | 1016 // We shouldn't overflow when adding another len. |
| 1011 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2); | 1017 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2); |
| 1012 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt); | 1018 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt); |
| 1013 USE(kHalfOfMaxInt); | 1019 USE(kHalfOfMaxInt); |
| 1014 result_len += len; | 1020 result_len += len; |
| 1015 ASSERT(result_len >= 0); | 1021 ASSERT(result_len >= 0); |
| 1016 | 1022 |
| 1017 if (result_len > FixedDoubleArray::kMaxLength) { | 1023 if (result_len > FixedDoubleArray::kMaxLength) { |
| 1024 AllowHeapAllocation allow_allocation; |
| 1018 return CallJsBuiltin(isolate, "ArrayConcat", args); | 1025 return CallJsBuiltin(isolate, "ArrayConcat", args); |
| 1019 } | 1026 } |
| 1020 | 1027 |
| 1021 ElementsKind arg_kind = Handle<JSArray>::cast(arg)->map()->elements_kind(); | 1028 ElementsKind arg_kind = JSArray::cast(arg)->map()->elements_kind(); |
| 1022 has_double = has_double || IsFastDoubleElementsKind(arg_kind); | 1029 has_double = has_double || IsFastDoubleElementsKind(arg_kind); |
| 1023 is_holey = is_holey || IsFastHoleyElementsKind(arg_kind); | 1030 is_holey = is_holey || IsFastHoleyElementsKind(arg_kind); |
| 1024 if (IsMoreGeneralElementsKindTransition(elements_kind, arg_kind)) { | 1031 if (IsMoreGeneralElementsKindTransition(elements_kind, arg_kind)) { |
| 1025 elements_kind = arg_kind; | 1032 elements_kind = arg_kind; |
| 1026 } | 1033 } |
| 1027 } | 1034 } |
| 1028 | 1035 |
| 1029 if (is_holey) elements_kind = GetHoleyElementsKind(elements_kind); | 1036 if (is_holey) elements_kind = GetHoleyElementsKind(elements_kind); |
| 1030 | 1037 |
| 1031 // If a double array is concatted into a fast elements array, the fast | 1038 // If a double array is concatted into a fast elements array, the fast |
| 1032 // elements array needs to be initialized to contain proper holes, since | 1039 // elements array needs to be initialized to contain proper holes, since |
| 1033 // boxing doubles may cause incremental marking. | 1040 // boxing doubles may cause incremental marking. |
| 1034 ArrayStorageAllocationMode mode = | 1041 ArrayStorageAllocationMode mode = |
| 1035 has_double && IsFastObjectElementsKind(elements_kind) | 1042 has_double && IsFastObjectElementsKind(elements_kind) |
| 1036 ? INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE : DONT_INITIALIZE_ARRAY_ELEMENTS; | 1043 ? INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE : DONT_INITIALIZE_ARRAY_ELEMENTS; |
| 1037 Handle<JSArray> result_array = | 1044 Handle<JSArray> result_array = |
| 1038 isolate->factory()->NewJSArray(elements_kind, | 1045 isolate->factory()->NewJSArray(elements_kind, |
| 1039 result_len, | 1046 result_len, |
| 1040 result_len, | 1047 result_len, |
| 1041 mode); | 1048 mode); |
| 1042 if (result_len == 0) return *result_array; | 1049 if (result_len == 0) return *result_array; |
| 1043 | 1050 |
| 1044 int j = 0; | 1051 int j = 0; |
| 1045 Handle<FixedArrayBase> storage(result_array->elements()); | 1052 Handle<FixedArrayBase> storage(result_array->elements(), isolate); |
| 1046 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); | 1053 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); |
| 1047 for (int i = 0; i < n_arguments; i++) { | 1054 for (int i = 0; i < n_arguments; i++) { |
| 1048 Handle<JSArray> array = args.at<JSArray>(i); | 1055 // TODO(ishell): It is crucial to keep |array| as a raw pointer to avoid |
| 1056 // performance degradation. Revisit this later. |
| 1057 JSArray* array = JSArray::cast(args[i]); |
| 1049 int len = Smi::cast(array->length())->value(); | 1058 int len = Smi::cast(array->length())->value(); |
| 1050 ElementsKind from_kind = array->GetElementsKind(); | 1059 ElementsKind from_kind = array->GetElementsKind(); |
| 1051 if (len > 0) { | 1060 if (len > 0) { |
| 1052 accessor->CopyElements(array, 0, from_kind, storage, j, len); | 1061 accessor->CopyElements(array, 0, from_kind, storage, j, len); |
| 1053 j += len; | 1062 j += len; |
| 1054 } | 1063 } |
| 1055 } | 1064 } |
| 1056 | 1065 |
| 1057 ASSERT(j == result_len); | 1066 ASSERT(j == result_len); |
| 1058 | 1067 |
| (...skipping 660 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1719 } | 1728 } |
| 1720 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) | 1729 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) |
| 1721 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) | 1730 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) |
| 1722 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) | 1731 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) |
| 1723 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) | 1732 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) |
| 1724 #undef DEFINE_BUILTIN_ACCESSOR_C | 1733 #undef DEFINE_BUILTIN_ACCESSOR_C |
| 1725 #undef DEFINE_BUILTIN_ACCESSOR_A | 1734 #undef DEFINE_BUILTIN_ACCESSOR_A |
| 1726 | 1735 |
| 1727 | 1736 |
| 1728 } } // namespace v8::internal | 1737 } } // namespace v8::internal |
| OLD | NEW |