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

Side by Side Diff: src/builtins.cc

Issue 10170030: Implement tracking and optimizations of packed arrays (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Platforms ports and review feedback Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 193
194 JSArray* array; 194 JSArray* array;
195 if (CalledAsConstructor(isolate)) { 195 if (CalledAsConstructor(isolate)) {
196 array = JSArray::cast((*args)[0]); 196 array = JSArray::cast((*args)[0]);
197 // Initialize elements and length in case later allocations fail so that the 197 // Initialize elements and length in case later allocations fail so that the
198 // array object is initialized in a valid state. 198 // array object is initialized in a valid state.
199 array->set_length(Smi::FromInt(0)); 199 array->set_length(Smi::FromInt(0));
200 array->set_elements(heap->empty_fixed_array()); 200 array->set_elements(heap->empty_fixed_array());
201 if (!FLAG_smi_only_arrays) { 201 if (!FLAG_smi_only_arrays) {
202 Context* global_context = isolate->context()->global_context(); 202 Context* global_context = isolate->context()->global_context();
203 if (array->GetElementsKind() == FAST_SMI_ONLY_ELEMENTS && 203 if (array->GetElementsKind() == GetInitialFastElementsKind() &&
204 !global_context->object_js_array_map()->IsUndefined()) { 204 !global_context->js_array_maps()->IsUndefined()) {
205 array->set_map(Map::cast(global_context->object_js_array_map())); 205 FixedArray* map_array =
206 FixedArray::cast(global_context->js_array_maps());
207 array->set_map(Map::cast(map_array->
208 get(TERMINAL_FAST_ELEMENTS_KIND)));
206 } 209 }
207 } 210 }
208 } else { 211 } else {
209 // Allocate the JS Array 212 // Allocate the JS Array
210 MaybeObject* maybe_obj = heap->AllocateJSObject(constructor); 213 MaybeObject* maybe_obj = heap->AllocateJSObject(constructor);
211 if (!maybe_obj->To(&array)) return maybe_obj; 214 if (!maybe_obj->To(&array)) return maybe_obj;
212 } 215 }
213 216
214 // Optimize the case where there is one argument and the argument is a 217 // Optimize the case where there is one argument and the argument is a
215 // small smi. 218 // small smi.
216 if (args->length() == 2) { 219 if (args->length() == 2) {
217 Object* obj = (*args)[1]; 220 Object* obj = (*args)[1];
218 if (obj->IsSmi()) { 221 if (obj->IsSmi()) {
219 int len = Smi::cast(obj)->value(); 222 int len = Smi::cast(obj)->value();
220 if (len >= 0 && len < JSObject::kInitialMaxFastElementArray) { 223 if (len >= 0 && len < JSObject::kInitialMaxFastElementArray) {
221 Object* fixed_array; 224 Object* fixed_array;
222 { MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(len); 225 { MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(len);
223 if (!maybe_obj->ToObject(&fixed_array)) return maybe_obj; 226 if (!maybe_obj->ToObject(&fixed_array)) return maybe_obj;
224 } 227 }
228 ElementsKind elements_kind = array->GetElementsKind();
229 if (!IsFastHoleyElementsKind(elements_kind)) {
230 elements_kind = GetHoleyElementsKind(elements_kind);
231 MaybeObject* maybe_array =
232 array->TransitionElementsKind(elements_kind);
233 if (maybe_array->IsFailure()) return maybe_array;
234 }
225 // We do not use SetContent to skip the unnecessary elements type check. 235 // We do not use SetContent to skip the unnecessary elements type check.
226 array->set_elements(FixedArray::cast(fixed_array)); 236 array->set_elements(FixedArray::cast(fixed_array));
227 array->set_length(Smi::cast(obj)); 237 array->set_length(Smi::cast(obj));
228 return array; 238 return array;
229 } 239 }
230 } 240 }
231 // Take the argument as the length. 241 // Take the argument as the length.
232 { MaybeObject* maybe_obj = array->Initialize(0); 242 { MaybeObject* maybe_obj = array->Initialize(0);
233 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 243 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
234 } 244 }
235 return array->SetElementsLength((*args)[1]); 245 return array->SetElementsLength((*args)[1]);
236 } 246 }
237 247
238 // Optimize the case where there are no parameters passed. 248 // Optimize the case where there are no parameters passed.
239 if (args->length() == 1) { 249 if (args->length() == 1) {
240 return array->Initialize(JSArray::kPreallocatedArrayElements); 250 return array->Initialize(JSArray::kPreallocatedArrayElements);
241 } 251 }
242 252
243 // Set length and elements on the array. 253 // Set length and elements on the array.
244 int number_of_elements = args->length() - 1; 254 int number_of_elements = args->length() - 1;
245 MaybeObject* maybe_object = 255 MaybeObject* maybe_object =
246 array->EnsureCanContainElements(args, 1, number_of_elements, 256 array->EnsureCanContainElements(args, 1, number_of_elements,
247 ALLOW_CONVERTED_DOUBLE_ELEMENTS); 257 ALLOW_CONVERTED_DOUBLE_ELEMENTS);
248 if (maybe_object->IsFailure()) return maybe_object; 258 if (maybe_object->IsFailure()) return maybe_object;
249 259
250 // Allocate an appropriately typed elements array. 260 // Allocate an appropriately typed elements array.
251 MaybeObject* maybe_elms; 261 MaybeObject* maybe_elms;
252 ElementsKind elements_kind = array->GetElementsKind(); 262 ElementsKind elements_kind = array->GetElementsKind();
253 if (elements_kind == FAST_DOUBLE_ELEMENTS) { 263 if (IsFastDoubleElementsKind(elements_kind)) {
254 maybe_elms = heap->AllocateUninitializedFixedDoubleArray( 264 maybe_elms = heap->AllocateUninitializedFixedDoubleArray(
255 number_of_elements); 265 number_of_elements);
256 } else { 266 } else {
257 maybe_elms = heap->AllocateFixedArrayWithHoles(number_of_elements); 267 maybe_elms = heap->AllocateFixedArrayWithHoles(number_of_elements);
258 } 268 }
259 FixedArrayBase* elms; 269 FixedArrayBase* elms;
260 if (!maybe_elms->To<FixedArrayBase>(&elms)) return maybe_elms; 270 if (!maybe_elms->To<FixedArrayBase>(&elms)) return maybe_elms;
261 271
262 // Fill in the content 272 // Fill in the content
263 switch (array->GetElementsKind()) { 273 switch (array->GetElementsKind()) {
264 case FAST_SMI_ONLY_ELEMENTS: { 274 case FAST_HOLEY_SMI_ELEMENTS:
275 case FAST_SMI_ELEMENTS: {
265 FixedArray* smi_elms = FixedArray::cast(elms); 276 FixedArray* smi_elms = FixedArray::cast(elms);
266 for (int index = 0; index < number_of_elements; index++) { 277 for (int index = 0; index < number_of_elements; index++) {
267 smi_elms->set(index, (*args)[index+1], SKIP_WRITE_BARRIER); 278 smi_elms->set(index, (*args)[index+1], SKIP_WRITE_BARRIER);
268 } 279 }
269 break; 280 break;
270 } 281 }
282 case FAST_HOLEY_ELEMENTS:
271 case FAST_ELEMENTS: { 283 case FAST_ELEMENTS: {
272 AssertNoAllocation no_gc; 284 AssertNoAllocation no_gc;
273 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); 285 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
274 FixedArray* object_elms = FixedArray::cast(elms); 286 FixedArray* object_elms = FixedArray::cast(elms);
275 for (int index = 0; index < number_of_elements; index++) { 287 for (int index = 0; index < number_of_elements; index++) {
276 object_elms->set(index, (*args)[index+1], mode); 288 object_elms->set(index, (*args)[index+1], mode);
277 } 289 }
278 break; 290 break;
279 } 291 }
292 case FAST_HOLEY_DOUBLE_ELEMENTS:
280 case FAST_DOUBLE_ELEMENTS: { 293 case FAST_DOUBLE_ELEMENTS: {
281 FixedDoubleArray* double_elms = FixedDoubleArray::cast(elms); 294 FixedDoubleArray* double_elms = FixedDoubleArray::cast(elms);
282 for (int index = 0; index < number_of_elements; index++) { 295 for (int index = 0; index < number_of_elements; index++) {
283 double_elms->set(index, (*args)[index+1]->Number()); 296 double_elms->set(index, (*args)[index+1]->Number());
284 } 297 }
285 break; 298 break;
286 } 299 }
287 default: 300 default:
288 UNREACHABLE(); 301 UNREACHABLE();
289 break; 302 break;
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
405 418
406 419
407 MUST_USE_RESULT 420 MUST_USE_RESULT
408 static inline MaybeObject* EnsureJSArrayWithWritableFastElements( 421 static inline MaybeObject* EnsureJSArrayWithWritableFastElements(
409 Heap* heap, Object* receiver, Arguments* args, int first_added_arg) { 422 Heap* heap, Object* receiver, Arguments* args, int first_added_arg) {
410 if (!receiver->IsJSArray()) return NULL; 423 if (!receiver->IsJSArray()) return NULL;
411 JSArray* array = JSArray::cast(receiver); 424 JSArray* array = JSArray::cast(receiver);
412 HeapObject* elms = array->elements(); 425 HeapObject* elms = array->elements();
413 Map* map = elms->map(); 426 Map* map = elms->map();
414 if (map == heap->fixed_array_map()) { 427 if (map == heap->fixed_array_map()) {
415 if (array->HasFastElements()) return elms; 428 if (array->HasFastObjectElements()) return elms;
429 if (array->HasFastDoubleElements()) {
430 ASSERT(elms == heap->empty_fixed_array());
431 MaybeObject* maybe_transition =
432 array->TransitionElementsKind(FAST_ELEMENTS);
433 if (maybe_transition->IsFailure()) return maybe_transition;
434 return elms;
435 }
416 if (args == NULL) { 436 if (args == NULL) {
417 if (array->HasFastDoubleElements()) {
418 ASSERT(elms == heap->empty_fixed_array());
419 MaybeObject* maybe_transition =
420 array->TransitionElementsKind(FAST_ELEMENTS);
421 if (maybe_transition->IsFailure()) return maybe_transition;
422 }
423 return elms; 437 return elms;
424 } 438 }
425 } else if (map == heap->fixed_cow_array_map()) { 439 } else if (map == heap->fixed_cow_array_map()) {
426 MaybeObject* maybe_writable_result = array->EnsureWritableFastElements(); 440 MaybeObject* maybe_writable_result = array->EnsureWritableFastElements();
427 if (args == NULL || array->HasFastElements() || 441 if (args == NULL || array->HasFastObjectElements() ||
428 maybe_writable_result->IsFailure()) { 442 maybe_writable_result->IsFailure()) {
429 return maybe_writable_result; 443 return maybe_writable_result;
430 } 444 }
431 } else { 445 } else {
432 return NULL; 446 return NULL;
433 } 447 }
434 448
435 // Need to ensure that the arguments passed in args can be contained in 449 // Need to ensure that the arguments passed in args can be contained in
436 // the array. 450 // the array.
437 int args_length = args->length(); 451 int args_length = args->length();
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
511 525
512 if (new_length > elms->length()) { 526 if (new_length > elms->length()) {
513 // New backing storage is needed. 527 // New backing storage is needed.
514 int capacity = new_length + (new_length >> 1) + 16; 528 int capacity = new_length + (new_length >> 1) + 16;
515 Object* obj; 529 Object* obj;
516 { MaybeObject* maybe_obj = heap->AllocateUninitializedFixedArray(capacity); 530 { MaybeObject* maybe_obj = heap->AllocateUninitializedFixedArray(capacity);
517 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 531 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
518 } 532 }
519 FixedArray* new_elms = FixedArray::cast(obj); 533 FixedArray* new_elms = FixedArray::cast(obj);
520 534
521 CopyObjectToObjectElements(elms, FAST_ELEMENTS, 0, 535 ElementsKind kind = array->GetElementsKind();
522 new_elms, FAST_ELEMENTS, 0, len); 536 CopyObjectToObjectElements(elms, kind, 0, new_elms, kind, 0, len);
523 FillWithHoles(heap, new_elms, new_length, capacity); 537 FillWithHoles(heap, new_elms, new_length, capacity);
524 538
525 elms = new_elms; 539 elms = new_elms;
526 } 540 }
527 541
528 // Add the provided values. 542 // Add the provided values.
529 AssertNoAllocation no_gc; 543 AssertNoAllocation no_gc;
530 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); 544 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
531 for (int index = 0; index < to_add; index++) { 545 for (int index = 0; index < to_add; index++) {
532 elms->set(index + len, args[index + 1], mode); 546 elms->set(index + len, args[index + 1], mode);
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
583 EnsureJSArrayWithWritableFastElements(heap, receiver, NULL, 0); 597 EnsureJSArrayWithWritableFastElements(heap, receiver, NULL, 0);
584 if (maybe_elms_obj == NULL) 598 if (maybe_elms_obj == NULL)
585 return CallJsBuiltin(isolate, "ArrayShift", args); 599 return CallJsBuiltin(isolate, "ArrayShift", args);
586 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; 600 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
587 } 601 }
588 if (!IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(receiver))) { 602 if (!IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(receiver))) {
589 return CallJsBuiltin(isolate, "ArrayShift", args); 603 return CallJsBuiltin(isolate, "ArrayShift", args);
590 } 604 }
591 FixedArray* elms = FixedArray::cast(elms_obj); 605 FixedArray* elms = FixedArray::cast(elms_obj);
592 JSArray* array = JSArray::cast(receiver); 606 JSArray* array = JSArray::cast(receiver);
593 ASSERT(array->HasFastTypeElements()); 607 ASSERT(array->HasFastSmiOrObjectElements());
594 608
595 int len = Smi::cast(array->length())->value(); 609 int len = Smi::cast(array->length())->value();
596 if (len == 0) return heap->undefined_value(); 610 if (len == 0) return heap->undefined_value();
597 611
598 // Get first element 612 // Get first element
599 Object* first = elms->get(0); 613 Object* first = elms->get(0);
600 if (first->IsTheHole()) { 614 if (first->IsTheHole()) {
601 first = heap->undefined_value(); 615 first = heap->undefined_value();
602 } 616 }
603 617
(...skipping 21 matching lines...) Expand all
625 EnsureJSArrayWithWritableFastElements(heap, receiver, NULL, 0); 639 EnsureJSArrayWithWritableFastElements(heap, receiver, NULL, 0);
626 if (maybe_elms_obj == NULL) 640 if (maybe_elms_obj == NULL)
627 return CallJsBuiltin(isolate, "ArrayUnshift", args); 641 return CallJsBuiltin(isolate, "ArrayUnshift", args);
628 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; 642 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
629 } 643 }
630 if (!IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(receiver))) { 644 if (!IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(receiver))) {
631 return CallJsBuiltin(isolate, "ArrayUnshift", args); 645 return CallJsBuiltin(isolate, "ArrayUnshift", args);
632 } 646 }
633 FixedArray* elms = FixedArray::cast(elms_obj); 647 FixedArray* elms = FixedArray::cast(elms_obj);
634 JSArray* array = JSArray::cast(receiver); 648 JSArray* array = JSArray::cast(receiver);
635 ASSERT(array->HasFastTypeElements()); 649 ASSERT(array->HasFastSmiOrObjectElements());
636 650
637 int len = Smi::cast(array->length())->value(); 651 int len = Smi::cast(array->length())->value();
638 int to_add = args.length() - 1; 652 int to_add = args.length() - 1;
639 int new_length = len + to_add; 653 int new_length = len + to_add;
640 // Currently fixed arrays cannot grow too big, so 654 // Currently fixed arrays cannot grow too big, so
641 // we should never hit this case. 655 // we should never hit this case.
642 ASSERT(to_add <= (Smi::kMaxValue - len)); 656 ASSERT(to_add <= (Smi::kMaxValue - len));
643 657
644 MaybeObject* maybe_object = 658 MaybeObject* maybe_object =
645 array->EnsureCanContainElements(&args, 1, to_add, 659 array->EnsureCanContainElements(&args, 1, to_add,
646 DONT_ALLOW_DOUBLE_ELEMENTS); 660 DONT_ALLOW_DOUBLE_ELEMENTS);
647 if (maybe_object->IsFailure()) return maybe_object; 661 if (maybe_object->IsFailure()) return maybe_object;
648 662
649 if (new_length > elms->length()) { 663 if (new_length > elms->length()) {
650 // New backing storage is needed. 664 // New backing storage is needed.
651 int capacity = new_length + (new_length >> 1) + 16; 665 int capacity = new_length + (new_length >> 1) + 16;
652 Object* obj; 666 Object* obj;
653 { MaybeObject* maybe_obj = heap->AllocateUninitializedFixedArray(capacity); 667 { MaybeObject* maybe_obj = heap->AllocateUninitializedFixedArray(capacity);
654 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 668 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
655 } 669 }
656 FixedArray* new_elms = FixedArray::cast(obj); 670 FixedArray* new_elms = FixedArray::cast(obj);
657 CopyObjectToObjectElements(elms, FAST_ELEMENTS, 0, 671 ElementsKind kind = array->GetElementsKind();
658 new_elms, FAST_ELEMENTS, to_add, len); 672 CopyObjectToObjectElements(elms, kind, 0, new_elms, kind, to_add, len);
659 FillWithHoles(heap, new_elms, new_length, capacity); 673 FillWithHoles(heap, new_elms, new_length, capacity);
660 elms = new_elms; 674 elms = new_elms;
661 array->set_elements(elms); 675 array->set_elements(elms);
662 } else { 676 } else {
663 AssertNoAllocation no_gc; 677 AssertNoAllocation no_gc;
664 MoveElements(heap, &no_gc, elms, to_add, elms, 0, len); 678 MoveElements(heap, &no_gc, elms, to_add, elms, 0, len);
665 } 679 }
666 680
667 // Add the provided values. 681 // Add the provided values.
668 AssertNoAllocation no_gc; 682 AssertNoAllocation no_gc;
669 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); 683 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
670 for (int i = 0; i < to_add; i++) { 684 for (int i = 0; i < to_add; i++) {
671 elms->set(i, args[i + 1], mode); 685 elms->set(i, args[i + 1], mode);
672 } 686 }
673 687
674 // Set the length. 688 // Set the length.
675 array->set_length(Smi::FromInt(new_length)); 689 array->set_length(Smi::FromInt(new_length));
676 return Smi::FromInt(new_length); 690 return Smi::FromInt(new_length);
677 } 691 }
678 692
679 693
680 BUILTIN(ArraySlice) { 694 BUILTIN(ArraySlice) {
681 Heap* heap = isolate->heap(); 695 Heap* heap = isolate->heap();
682 Object* receiver = *args.receiver(); 696 Object* receiver = *args.receiver();
683 FixedArray* elms; 697 FixedArray* elms;
684 int len = -1; 698 int len = -1;
685 if (receiver->IsJSArray()) { 699 if (receiver->IsJSArray()) {
686 JSArray* array = JSArray::cast(receiver); 700 JSArray* array = JSArray::cast(receiver);
687 if (!array->HasFastTypeElements() || 701 if (!array->HasFastSmiOrObjectElements() ||
688 !IsJSArrayFastElementMovingAllowed(heap, array)) { 702 !IsJSArrayFastElementMovingAllowed(heap, array)) {
689 return CallJsBuiltin(isolate, "ArraySlice", args); 703 return CallJsBuiltin(isolate, "ArraySlice", args);
690 } 704 }
691 705
692 elms = FixedArray::cast(array->elements()); 706 elms = FixedArray::cast(array->elements());
693 len = Smi::cast(array->length())->value(); 707 len = Smi::cast(array->length())->value();
694 } else { 708 } else {
695 // Array.slice(arguments, ...) is quite a common idiom (notably more 709 // Array.slice(arguments, ...) is quite a common idiom (notably more
696 // than 50% of invocations in Web apps). Treat it in C++ as well. 710 // than 50% of invocations in Web apps). Treat it in C++ as well.
697 Map* arguments_map = 711 Map* arguments_map =
698 isolate->context()->global_context()->arguments_boilerplate()->map(); 712 isolate->context()->global_context()->arguments_boilerplate()->map();
699 713
700 bool is_arguments_object_with_fast_elements = 714 bool is_arguments_object_with_fast_elements =
701 receiver->IsJSObject() 715 receiver->IsJSObject()
702 && JSObject::cast(receiver)->map() == arguments_map 716 && JSObject::cast(receiver)->map() == arguments_map
703 && JSObject::cast(receiver)->HasFastTypeElements(); 717 && JSObject::cast(receiver)->HasFastSmiOrObjectElements();
704 if (!is_arguments_object_with_fast_elements) { 718 if (!is_arguments_object_with_fast_elements) {
705 return CallJsBuiltin(isolate, "ArraySlice", args); 719 return CallJsBuiltin(isolate, "ArraySlice", args);
706 } 720 }
707 elms = FixedArray::cast(JSObject::cast(receiver)->elements()); 721 elms = FixedArray::cast(JSObject::cast(receiver)->elements());
708 Object* len_obj = JSObject::cast(receiver) 722 Object* len_obj = JSObject::cast(receiver)
709 ->InObjectPropertyAt(Heap::kArgumentsLengthIndex); 723 ->InObjectPropertyAt(Heap::kArgumentsLengthIndex);
710 if (!len_obj->IsSmi()) { 724 if (!len_obj->IsSmi()) {
711 return CallJsBuiltin(isolate, "ArraySlice", args); 725 return CallJsBuiltin(isolate, "ArraySlice", args);
712 } 726 }
713 len = Smi::cast(len_obj)->value(); 727 len = Smi::cast(len_obj)->value();
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
758 // Calculate the length of result array. 772 // Calculate the length of result array.
759 int result_len = Max(final - k, 0); 773 int result_len = Max(final - k, 0);
760 774
761 MaybeObject* maybe_array = 775 MaybeObject* maybe_array =
762 heap->AllocateJSArrayAndStorage(elements_kind, 776 heap->AllocateJSArrayAndStorage(elements_kind,
763 result_len, 777 result_len,
764 result_len); 778 result_len);
765 JSArray* result_array; 779 JSArray* result_array;
766 if (!maybe_array->To(&result_array)) return maybe_array; 780 if (!maybe_array->To(&result_array)) return maybe_array;
767 781
768 CopyObjectToObjectElements(elms, FAST_ELEMENTS, k, 782 CopyObjectToObjectElements(elms, elements_kind, k,
769 FixedArray::cast(result_array->elements()), 783 FixedArray::cast(result_array->elements()),
770 FAST_ELEMENTS, 0, result_len); 784 elements_kind, 0, result_len);
771 785
772 return result_array; 786 return result_array;
773 } 787 }
774 788
775 789
776 BUILTIN(ArraySplice) { 790 BUILTIN(ArraySplice) {
777 Heap* heap = isolate->heap(); 791 Heap* heap = isolate->heap();
778 Object* receiver = *args.receiver(); 792 Object* receiver = *args.receiver();
779 Object* elms_obj; 793 Object* elms_obj;
780 { MaybeObject* maybe_elms_obj = 794 { MaybeObject* maybe_elms_obj =
781 EnsureJSArrayWithWritableFastElements(heap, receiver, &args, 3); 795 EnsureJSArrayWithWritableFastElements(heap, receiver, &args, 3);
782 if (maybe_elms_obj == NULL) 796 if (maybe_elms_obj == NULL)
783 return CallJsBuiltin(isolate, "ArraySplice", args); 797 return CallJsBuiltin(isolate, "ArraySplice", args);
784 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; 798 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
785 } 799 }
786 if (!IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(receiver))) { 800 if (!IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(receiver))) {
787 return CallJsBuiltin(isolate, "ArraySplice", args); 801 return CallJsBuiltin(isolate, "ArraySplice", args);
788 } 802 }
789 FixedArray* elms = FixedArray::cast(elms_obj); 803 FixedArray* elms = FixedArray::cast(elms_obj);
790 JSArray* array = JSArray::cast(receiver); 804 JSArray* array = JSArray::cast(receiver);
791 ASSERT(array->HasFastTypeElements()); 805 ASSERT(array->HasFastSmiOrObjectElements());
792 806
793 int len = Smi::cast(array->length())->value(); 807 int len = Smi::cast(array->length())->value();
794 808
795 int n_arguments = args.length() - 1; 809 int n_arguments = args.length() - 1;
796 810
797 int relative_start = 0; 811 int relative_start = 0;
798 if (n_arguments > 0) { 812 if (n_arguments > 0) {
799 Object* arg1 = args[1]; 813 Object* arg1 = args[1];
800 if (arg1->IsSmi()) { 814 if (arg1->IsSmi()) {
801 relative_start = Smi::cast(arg1)->value(); 815 relative_start = Smi::cast(arg1)->value();
(...skipping 30 matching lines...) Expand all
832 ElementsKind elements_kind = 846 ElementsKind elements_kind =
833 JSObject::cast(receiver)->GetElementsKind(); 847 JSObject::cast(receiver)->GetElementsKind();
834 MaybeObject* maybe_array = 848 MaybeObject* maybe_array =
835 heap->AllocateJSArrayAndStorage(elements_kind, 849 heap->AllocateJSArrayAndStorage(elements_kind,
836 actual_delete_count, 850 actual_delete_count,
837 actual_delete_count); 851 actual_delete_count);
838 if (!maybe_array->To(&result_array)) return maybe_array; 852 if (!maybe_array->To(&result_array)) return maybe_array;
839 853
840 { 854 {
841 // Fill newly created array. 855 // Fill newly created array.
842 CopyObjectToObjectElements(elms, FAST_ELEMENTS, actual_start, 856 CopyObjectToObjectElements(elms, elements_kind, actual_start,
843 FixedArray::cast(result_array->elements()), 857 FixedArray::cast(result_array->elements()),
844 FAST_ELEMENTS, 0, actual_delete_count); 858 elements_kind, 0, actual_delete_count);
845 } 859 }
846 860
847 int item_count = (n_arguments > 1) ? (n_arguments - 2) : 0; 861 int item_count = (n_arguments > 1) ? (n_arguments - 2) : 0;
848 int new_length = len - actual_delete_count + item_count; 862 int new_length = len - actual_delete_count + item_count;
849 863
850 bool elms_changed = false; 864 bool elms_changed = false;
851 if (item_count < actual_delete_count) { 865 if (item_count < actual_delete_count) {
852 // Shrink the array. 866 // Shrink the array.
853 const bool trim_array = !heap->lo_space()->Contains(elms) && 867 const bool trim_array = !heap->lo_space()->Contains(elms) &&
854 ((actual_start + item_count) < 868 ((actual_start + item_count) <
(...skipping 28 matching lines...) Expand all
883 int capacity = new_length + (new_length >> 1) + 16; 897 int capacity = new_length + (new_length >> 1) + 16;
884 Object* obj; 898 Object* obj;
885 { MaybeObject* maybe_obj = 899 { MaybeObject* maybe_obj =
886 heap->AllocateUninitializedFixedArray(capacity); 900 heap->AllocateUninitializedFixedArray(capacity);
887 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 901 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
888 } 902 }
889 FixedArray* new_elms = FixedArray::cast(obj); 903 FixedArray* new_elms = FixedArray::cast(obj);
890 904
891 { 905 {
892 // Copy the part before actual_start as is. 906 // Copy the part before actual_start as is.
893 CopyObjectToObjectElements(elms, FAST_ELEMENTS, 0, 907 ElementsKind kind = array->GetElementsKind();
894 new_elms, FAST_ELEMENTS, 0, actual_start); 908 CopyObjectToObjectElements(elms, kind, 0,
909 new_elms, kind, 0, actual_start);
895 const int to_copy = len - actual_delete_count - actual_start; 910 const int to_copy = len - actual_delete_count - actual_start;
896 CopyObjectToObjectElements(elms, FAST_ELEMENTS, 911 CopyObjectToObjectElements(elms, kind,
897 actual_start + actual_delete_count, 912 actual_start + actual_delete_count,
898 new_elms, FAST_ELEMENTS, 913 new_elms, kind,
899 actual_start + item_count, to_copy); 914 actual_start + item_count, to_copy);
900 } 915 }
901 916
902 FillWithHoles(heap, new_elms, new_length, capacity); 917 FillWithHoles(heap, new_elms, new_length, capacity);
903 918
904 elms = new_elms; 919 elms = new_elms;
905 elms_changed = true; 920 elms_changed = true;
906 } else { 921 } else {
907 AssertNoAllocation no_gc; 922 AssertNoAllocation no_gc;
908 MoveElements(heap, &no_gc, 923 MoveElements(heap, &no_gc,
(...skipping 26 matching lines...) Expand all
935 JSObject* array_proto = 950 JSObject* array_proto =
936 JSObject::cast(global_context->array_function()->prototype()); 951 JSObject::cast(global_context->array_function()->prototype());
937 if (!ArrayPrototypeHasNoElements(heap, global_context, array_proto)) { 952 if (!ArrayPrototypeHasNoElements(heap, global_context, array_proto)) {
938 return CallJsBuiltin(isolate, "ArrayConcat", args); 953 return CallJsBuiltin(isolate, "ArrayConcat", args);
939 } 954 }
940 955
941 // Iterate through all the arguments performing checks 956 // Iterate through all the arguments performing checks
942 // and calculating total length. 957 // and calculating total length.
943 int n_arguments = args.length(); 958 int n_arguments = args.length();
944 int result_len = 0; 959 int result_len = 0;
945 ElementsKind elements_kind = FAST_SMI_ONLY_ELEMENTS; 960 ElementsKind elements_kind = GetInitialFastElementsKind();
946 for (int i = 0; i < n_arguments; i++) { 961 for (int i = 0; i < n_arguments; i++) {
947 Object* arg = args[i]; 962 Object* arg = args[i];
948 if (!arg->IsJSArray() || !JSArray::cast(arg)->HasFastTypeElements() 963 if (!arg->IsJSArray() ||
949 || JSArray::cast(arg)->GetPrototype() != array_proto) { 964 !JSArray::cast(arg)->HasFastSmiOrObjectElements() ||
965 JSArray::cast(arg)->GetPrototype() != array_proto) {
950 return CallJsBuiltin(isolate, "ArrayConcat", args); 966 return CallJsBuiltin(isolate, "ArrayConcat", args);
951 } 967 }
952 968
953 int len = Smi::cast(JSArray::cast(arg)->length())->value(); 969 int len = Smi::cast(JSArray::cast(arg)->length())->value();
954 970
955 // We shouldn't overflow when adding another len. 971 // We shouldn't overflow when adding another len.
956 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2); 972 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2);
957 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt); 973 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt);
958 USE(kHalfOfMaxInt); 974 USE(kHalfOfMaxInt);
959 result_len += len; 975 result_len += len;
960 ASSERT(result_len >= 0); 976 ASSERT(result_len >= 0);
961 977
962 if (result_len > FixedArray::kMaxLength) { 978 if (result_len > FixedArray::kMaxLength) {
963 return CallJsBuiltin(isolate, "ArrayConcat", args); 979 return CallJsBuiltin(isolate, "ArrayConcat", args);
964 } 980 }
965 981
966 if (!JSArray::cast(arg)->HasFastSmiOnlyElements()) { 982 if (!JSArray::cast(arg)->HasFastSmiElements()) {
967 elements_kind = FAST_ELEMENTS; 983 if (IsFastSmiElementsKind(elements_kind)) {
984 if (IsFastHoleyElementsKind(elements_kind)) {
985 elements_kind = FAST_HOLEY_ELEMENTS;
986 } else {
987 elements_kind = FAST_ELEMENTS;
988 }
989 }
990 }
991
992 if (JSArray::cast(arg)->HasFastHoleyElements()) {
993 elements_kind = GetHoleyElementsKind(elements_kind);
968 } 994 }
969 } 995 }
970 996
971 // Allocate result. 997 // Allocate result.
972 JSArray* result_array; 998 JSArray* result_array;
973 MaybeObject* maybe_array = 999 MaybeObject* maybe_array =
974 heap->AllocateJSArrayAndStorage(elements_kind, 1000 heap->AllocateJSArrayAndStorage(elements_kind,
975 result_len, 1001 result_len,
976 result_len); 1002 result_len);
977 if (!maybe_array->To(&result_array)) return maybe_array; 1003 if (!maybe_array->To(&result_array)) return maybe_array;
978 if (result_len == 0) return result_array; 1004 if (result_len == 0) return result_array;
979 1005
980 // Copy data. 1006 // Copy data.
981 int start_pos = 0; 1007 int start_pos = 0;
982 FixedArray* result_elms(FixedArray::cast(result_array->elements())); 1008 FixedArray* result_elms(FixedArray::cast(result_array->elements()));
983 for (int i = 0; i < n_arguments; i++) { 1009 for (int i = 0; i < n_arguments; i++) {
984 JSArray* array = JSArray::cast(args[i]); 1010 JSArray* array = JSArray::cast(args[i]);
985 int len = Smi::cast(array->length())->value(); 1011 int len = Smi::cast(array->length())->value();
986 FixedArray* elms = FixedArray::cast(array->elements()); 1012 FixedArray* elms = FixedArray::cast(array->elements());
987 CopyObjectToObjectElements(elms, FAST_ELEMENTS, 0, 1013 CopyObjectToObjectElements(elms, elements_kind, 0,
988 result_elms, FAST_ELEMENTS, 1014 result_elms, elements_kind,
989 start_pos, len); 1015 start_pos, len);
990 start_pos += len; 1016 start_pos += len;
991 } 1017 }
992 ASSERT(start_pos == result_len); 1018 ASSERT(start_pos == result_len);
993 1019
994 return result_array; 1020 return result_array;
995 } 1021 }
996 1022
997 1023
998 // ----------------------------------------------------------------------------- 1024 // -----------------------------------------------------------------------------
(...skipping 681 matching lines...) Expand 10 before | Expand all | Expand 10 after
1680 return Handle<Code>(code_address); \ 1706 return Handle<Code>(code_address); \
1681 } 1707 }
1682 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) 1708 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C)
1683 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) 1709 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A)
1684 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) 1710 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A)
1685 #undef DEFINE_BUILTIN_ACCESSOR_C 1711 #undef DEFINE_BUILTIN_ACCESSOR_C
1686 #undef DEFINE_BUILTIN_ACCESSOR_A 1712 #undef DEFINE_BUILTIN_ACCESSOR_A
1687 1713
1688 1714
1689 } } // namespace v8::internal 1715 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698