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

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: ia32 ready to go 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 (args == NULL || !array->HasFastSmiOnlyElements()) { 428 if (args == NULL || !array->HasFastSmiElements()) {
416 return elms; 429 return elms;
417 } 430 }
418 } else if (map == heap->fixed_cow_array_map()) { 431 } else if (map == heap->fixed_cow_array_map()) {
419 MaybeObject* maybe_writable_result = array->EnsureWritableFastElements(); 432 MaybeObject* maybe_writable_result = array->EnsureWritableFastElements();
420 if (args == NULL || !array->HasFastSmiOnlyElements() || 433 if (args == NULL || !array->HasFastSmiElements() ||
421 maybe_writable_result->IsFailure()) { 434 maybe_writable_result->IsFailure()) {
422 return maybe_writable_result; 435 return maybe_writable_result;
423 } 436 }
424 } else { 437 } else {
425 return NULL; 438 return NULL;
426 } 439 }
427 440
428 // Need to ensure that the arguments passed in args can be contained in 441 // Need to ensure that the arguments passed in args can be contained in
429 // the array. 442 // the array.
430 int args_length = args->length(); 443 int args_length = args->length();
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
504 517
505 if (new_length > elms->length()) { 518 if (new_length > elms->length()) {
506 // New backing storage is needed. 519 // New backing storage is needed.
507 int capacity = new_length + (new_length >> 1) + 16; 520 int capacity = new_length + (new_length >> 1) + 16;
508 Object* obj; 521 Object* obj;
509 { MaybeObject* maybe_obj = heap->AllocateUninitializedFixedArray(capacity); 522 { MaybeObject* maybe_obj = heap->AllocateUninitializedFixedArray(capacity);
510 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 523 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
511 } 524 }
512 FixedArray* new_elms = FixedArray::cast(obj); 525 FixedArray* new_elms = FixedArray::cast(obj);
513 526
514 CopyObjectToObjectElements(elms, FAST_ELEMENTS, 0, 527 ElementsKind kind = array->GetElementsKind();
515 new_elms, FAST_ELEMENTS, 0, len); 528 CopyObjectToObjectElements(elms, kind, 0, new_elms, kind, 0, len);
516 FillWithHoles(heap, new_elms, new_length, capacity); 529 FillWithHoles(heap, new_elms, new_length, capacity);
517 530
518 elms = new_elms; 531 elms = new_elms;
519 } 532 }
520 533
521 // Add the provided values. 534 // Add the provided values.
522 AssertNoAllocation no_gc; 535 AssertNoAllocation no_gc;
523 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); 536 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
524 for (int index = 0; index < to_add; index++) { 537 for (int index = 0; index < to_add; index++) {
525 elms->set(index + len, args[index + 1], mode); 538 elms->set(index + len, args[index + 1], mode);
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
576 EnsureJSArrayWithWritableFastElements(heap, receiver, NULL, 0); 589 EnsureJSArrayWithWritableFastElements(heap, receiver, NULL, 0);
577 if (maybe_elms_obj == NULL) 590 if (maybe_elms_obj == NULL)
578 return CallJsBuiltin(isolate, "ArrayShift", args); 591 return CallJsBuiltin(isolate, "ArrayShift", args);
579 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; 592 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
580 } 593 }
581 if (!IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(receiver))) { 594 if (!IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(receiver))) {
582 return CallJsBuiltin(isolate, "ArrayShift", args); 595 return CallJsBuiltin(isolate, "ArrayShift", args);
583 } 596 }
584 FixedArray* elms = FixedArray::cast(elms_obj); 597 FixedArray* elms = FixedArray::cast(elms_obj);
585 JSArray* array = JSArray::cast(receiver); 598 JSArray* array = JSArray::cast(receiver);
586 ASSERT(array->HasFastTypeElements()); 599 ASSERT(array->HasFastSmiOrObjectElements());
587 600
588 int len = Smi::cast(array->length())->value(); 601 int len = Smi::cast(array->length())->value();
589 if (len == 0) return heap->undefined_value(); 602 if (len == 0) return heap->undefined_value();
590 603
591 // Get first element 604 // Get first element
592 Object* first = elms->get(0); 605 Object* first = elms->get(0);
593 if (first->IsTheHole()) { 606 if (first->IsTheHole()) {
594 first = heap->undefined_value(); 607 first = heap->undefined_value();
595 } 608 }
596 609
(...skipping 21 matching lines...) Expand all
618 EnsureJSArrayWithWritableFastElements(heap, receiver, NULL, 0); 631 EnsureJSArrayWithWritableFastElements(heap, receiver, NULL, 0);
619 if (maybe_elms_obj == NULL) 632 if (maybe_elms_obj == NULL)
620 return CallJsBuiltin(isolate, "ArrayUnshift", args); 633 return CallJsBuiltin(isolate, "ArrayUnshift", args);
621 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; 634 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
622 } 635 }
623 if (!IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(receiver))) { 636 if (!IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(receiver))) {
624 return CallJsBuiltin(isolate, "ArrayUnshift", args); 637 return CallJsBuiltin(isolate, "ArrayUnshift", args);
625 } 638 }
626 FixedArray* elms = FixedArray::cast(elms_obj); 639 FixedArray* elms = FixedArray::cast(elms_obj);
627 JSArray* array = JSArray::cast(receiver); 640 JSArray* array = JSArray::cast(receiver);
628 ASSERT(array->HasFastTypeElements()); 641 ASSERT(array->HasFastSmiOrObjectElements());
629 642
630 int len = Smi::cast(array->length())->value(); 643 int len = Smi::cast(array->length())->value();
631 int to_add = args.length() - 1; 644 int to_add = args.length() - 1;
632 int new_length = len + to_add; 645 int new_length = len + to_add;
633 // Currently fixed arrays cannot grow too big, so 646 // Currently fixed arrays cannot grow too big, so
634 // we should never hit this case. 647 // we should never hit this case.
635 ASSERT(to_add <= (Smi::kMaxValue - len)); 648 ASSERT(to_add <= (Smi::kMaxValue - len));
636 649
637 MaybeObject* maybe_object = 650 MaybeObject* maybe_object =
638 array->EnsureCanContainElements(&args, 1, to_add, 651 array->EnsureCanContainElements(&args, 1, to_add,
639 DONT_ALLOW_DOUBLE_ELEMENTS); 652 DONT_ALLOW_DOUBLE_ELEMENTS);
640 if (maybe_object->IsFailure()) return maybe_object; 653 if (maybe_object->IsFailure()) return maybe_object;
641 654
642 if (new_length > elms->length()) { 655 if (new_length > elms->length()) {
643 // New backing storage is needed. 656 // New backing storage is needed.
644 int capacity = new_length + (new_length >> 1) + 16; 657 int capacity = new_length + (new_length >> 1) + 16;
645 Object* obj; 658 Object* obj;
646 { MaybeObject* maybe_obj = heap->AllocateUninitializedFixedArray(capacity); 659 { MaybeObject* maybe_obj = heap->AllocateUninitializedFixedArray(capacity);
647 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 660 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
648 } 661 }
649 FixedArray* new_elms = FixedArray::cast(obj); 662 FixedArray* new_elms = FixedArray::cast(obj);
650 CopyObjectToObjectElements(elms, FAST_ELEMENTS, 0, 663 ElementsKind kind = array->GetElementsKind();
651 new_elms, FAST_ELEMENTS, to_add, len); 664 CopyObjectToObjectElements(elms, kind, 0, new_elms, kind, to_add, len);
652 FillWithHoles(heap, new_elms, new_length, capacity); 665 FillWithHoles(heap, new_elms, new_length, capacity);
653 elms = new_elms; 666 elms = new_elms;
654 array->set_elements(elms); 667 array->set_elements(elms);
655 } else { 668 } else {
656 AssertNoAllocation no_gc; 669 AssertNoAllocation no_gc;
657 MoveElements(heap, &no_gc, elms, to_add, elms, 0, len); 670 MoveElements(heap, &no_gc, elms, to_add, elms, 0, len);
658 } 671 }
659 672
660 // Add the provided values. 673 // Add the provided values.
661 AssertNoAllocation no_gc; 674 AssertNoAllocation no_gc;
662 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); 675 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
663 for (int i = 0; i < to_add; i++) { 676 for (int i = 0; i < to_add; i++) {
664 elms->set(i, args[i + 1], mode); 677 elms->set(i, args[i + 1], mode);
665 } 678 }
666 679
667 // Set the length. 680 // Set the length.
668 array->set_length(Smi::FromInt(new_length)); 681 array->set_length(Smi::FromInt(new_length));
669 return Smi::FromInt(new_length); 682 return Smi::FromInt(new_length);
670 } 683 }
671 684
672 685
673 BUILTIN(ArraySlice) { 686 BUILTIN(ArraySlice) {
674 Heap* heap = isolate->heap(); 687 Heap* heap = isolate->heap();
675 Object* receiver = *args.receiver(); 688 Object* receiver = *args.receiver();
676 FixedArray* elms; 689 FixedArray* elms;
677 int len = -1; 690 int len = -1;
678 if (receiver->IsJSArray()) { 691 if (receiver->IsJSArray()) {
679 JSArray* array = JSArray::cast(receiver); 692 JSArray* array = JSArray::cast(receiver);
680 if (!array->HasFastTypeElements() || 693 if (!array->HasFastSmiOrObjectElements() ||
681 !IsJSArrayFastElementMovingAllowed(heap, array)) { 694 !IsJSArrayFastElementMovingAllowed(heap, array)) {
682 return CallJsBuiltin(isolate, "ArraySlice", args); 695 return CallJsBuiltin(isolate, "ArraySlice", args);
683 } 696 }
684 697
685 elms = FixedArray::cast(array->elements()); 698 elms = FixedArray::cast(array->elements());
686 len = Smi::cast(array->length())->value(); 699 len = Smi::cast(array->length())->value();
687 } else { 700 } else {
688 // Array.slice(arguments, ...) is quite a common idiom (notably more 701 // Array.slice(arguments, ...) is quite a common idiom (notably more
689 // than 50% of invocations in Web apps). Treat it in C++ as well. 702 // than 50% of invocations in Web apps). Treat it in C++ as well.
690 Map* arguments_map = 703 Map* arguments_map =
691 isolate->context()->global_context()->arguments_boilerplate()->map(); 704 isolate->context()->global_context()->arguments_boilerplate()->map();
692 705
693 bool is_arguments_object_with_fast_elements = 706 bool is_arguments_object_with_fast_elements =
694 receiver->IsJSObject() 707 receiver->IsJSObject()
695 && JSObject::cast(receiver)->map() == arguments_map 708 && JSObject::cast(receiver)->map() == arguments_map
696 && JSObject::cast(receiver)->HasFastTypeElements(); 709 && JSObject::cast(receiver)->HasFastSmiOrObjectElements();
697 if (!is_arguments_object_with_fast_elements) { 710 if (!is_arguments_object_with_fast_elements) {
698 return CallJsBuiltin(isolate, "ArraySlice", args); 711 return CallJsBuiltin(isolate, "ArraySlice", args);
699 } 712 }
700 elms = FixedArray::cast(JSObject::cast(receiver)->elements()); 713 elms = FixedArray::cast(JSObject::cast(receiver)->elements());
701 Object* len_obj = JSObject::cast(receiver) 714 Object* len_obj = JSObject::cast(receiver)
702 ->InObjectPropertyAt(Heap::kArgumentsLengthIndex); 715 ->InObjectPropertyAt(Heap::kArgumentsLengthIndex);
703 if (!len_obj->IsSmi()) { 716 if (!len_obj->IsSmi()) {
704 return CallJsBuiltin(isolate, "ArraySlice", args); 717 return CallJsBuiltin(isolate, "ArraySlice", args);
705 } 718 }
706 len = Smi::cast(len_obj)->value(); 719 len = Smi::cast(len_obj)->value();
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
751 // Calculate the length of result array. 764 // Calculate the length of result array.
752 int result_len = Max(final - k, 0); 765 int result_len = Max(final - k, 0);
753 766
754 MaybeObject* maybe_array = 767 MaybeObject* maybe_array =
755 heap->AllocateJSArrayAndStorage(elements_kind, 768 heap->AllocateJSArrayAndStorage(elements_kind,
756 result_len, 769 result_len,
757 result_len); 770 result_len);
758 JSArray* result_array; 771 JSArray* result_array;
759 if (!maybe_array->To(&result_array)) return maybe_array; 772 if (!maybe_array->To(&result_array)) return maybe_array;
760 773
761 CopyObjectToObjectElements(elms, FAST_ELEMENTS, k, 774 CopyObjectToObjectElements(elms, elements_kind, k,
762 FixedArray::cast(result_array->elements()), 775 FixedArray::cast(result_array->elements()),
763 FAST_ELEMENTS, 0, result_len); 776 elements_kind, 0, result_len);
764 777
765 return result_array; 778 return result_array;
766 } 779 }
767 780
768 781
769 BUILTIN(ArraySplice) { 782 BUILTIN(ArraySplice) {
770 Heap* heap = isolate->heap(); 783 Heap* heap = isolate->heap();
771 Object* receiver = *args.receiver(); 784 Object* receiver = *args.receiver();
772 Object* elms_obj; 785 Object* elms_obj;
773 { MaybeObject* maybe_elms_obj = 786 { MaybeObject* maybe_elms_obj =
774 EnsureJSArrayWithWritableFastElements(heap, receiver, &args, 3); 787 EnsureJSArrayWithWritableFastElements(heap, receiver, &args, 3);
775 if (maybe_elms_obj == NULL) 788 if (maybe_elms_obj == NULL)
776 return CallJsBuiltin(isolate, "ArraySplice", args); 789 return CallJsBuiltin(isolate, "ArraySplice", args);
777 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; 790 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
778 } 791 }
779 if (!IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(receiver))) { 792 if (!IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(receiver))) {
780 return CallJsBuiltin(isolate, "ArraySplice", args); 793 return CallJsBuiltin(isolate, "ArraySplice", args);
781 } 794 }
782 FixedArray* elms = FixedArray::cast(elms_obj); 795 FixedArray* elms = FixedArray::cast(elms_obj);
783 JSArray* array = JSArray::cast(receiver); 796 JSArray* array = JSArray::cast(receiver);
784 ASSERT(array->HasFastTypeElements()); 797 ASSERT(array->HasFastSmiOrObjectElements());
785 798
786 int len = Smi::cast(array->length())->value(); 799 int len = Smi::cast(array->length())->value();
787 800
788 int n_arguments = args.length() - 1; 801 int n_arguments = args.length() - 1;
789 802
790 int relative_start = 0; 803 int relative_start = 0;
791 if (n_arguments > 0) { 804 if (n_arguments > 0) {
792 Object* arg1 = args[1]; 805 Object* arg1 = args[1];
793 if (arg1->IsSmi()) { 806 if (arg1->IsSmi()) {
794 relative_start = Smi::cast(arg1)->value(); 807 relative_start = Smi::cast(arg1)->value();
(...skipping 30 matching lines...) Expand all
825 ElementsKind elements_kind = 838 ElementsKind elements_kind =
826 JSObject::cast(receiver)->GetElementsKind(); 839 JSObject::cast(receiver)->GetElementsKind();
827 MaybeObject* maybe_array = 840 MaybeObject* maybe_array =
828 heap->AllocateJSArrayAndStorage(elements_kind, 841 heap->AllocateJSArrayAndStorage(elements_kind,
829 actual_delete_count, 842 actual_delete_count,
830 actual_delete_count); 843 actual_delete_count);
831 if (!maybe_array->To(&result_array)) return maybe_array; 844 if (!maybe_array->To(&result_array)) return maybe_array;
832 845
833 { 846 {
834 // Fill newly created array. 847 // Fill newly created array.
835 CopyObjectToObjectElements(elms, FAST_ELEMENTS, actual_start, 848 CopyObjectToObjectElements(elms, elements_kind, actual_start,
836 FixedArray::cast(result_array->elements()), 849 FixedArray::cast(result_array->elements()),
837 FAST_ELEMENTS, 0, actual_delete_count); 850 elements_kind, 0, actual_delete_count);
838 } 851 }
839 852
840 int item_count = (n_arguments > 1) ? (n_arguments - 2) : 0; 853 int item_count = (n_arguments > 1) ? (n_arguments - 2) : 0;
841 int new_length = len - actual_delete_count + item_count; 854 int new_length = len - actual_delete_count + item_count;
842 855
843 bool elms_changed = false; 856 bool elms_changed = false;
844 if (item_count < actual_delete_count) { 857 if (item_count < actual_delete_count) {
845 // Shrink the array. 858 // Shrink the array.
846 const bool trim_array = !heap->lo_space()->Contains(elms) && 859 const bool trim_array = !heap->lo_space()->Contains(elms) &&
847 ((actual_start + item_count) < 860 ((actual_start + item_count) <
(...skipping 28 matching lines...) Expand all
876 int capacity = new_length + (new_length >> 1) + 16; 889 int capacity = new_length + (new_length >> 1) + 16;
877 Object* obj; 890 Object* obj;
878 { MaybeObject* maybe_obj = 891 { MaybeObject* maybe_obj =
879 heap->AllocateUninitializedFixedArray(capacity); 892 heap->AllocateUninitializedFixedArray(capacity);
880 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 893 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
881 } 894 }
882 FixedArray* new_elms = FixedArray::cast(obj); 895 FixedArray* new_elms = FixedArray::cast(obj);
883 896
884 { 897 {
885 // Copy the part before actual_start as is. 898 // Copy the part before actual_start as is.
886 CopyObjectToObjectElements(elms, FAST_ELEMENTS, 0, 899 ElementsKind kind = array->GetElementsKind();
887 new_elms, FAST_ELEMENTS, 0, actual_start); 900 CopyObjectToObjectElements(elms, kind, 0,
901 new_elms, kind, 0, actual_start);
888 const int to_copy = len - actual_delete_count - actual_start; 902 const int to_copy = len - actual_delete_count - actual_start;
889 CopyObjectToObjectElements(elms, FAST_ELEMENTS, 903 CopyObjectToObjectElements(elms, kind,
890 actual_start + actual_delete_count, 904 actual_start + actual_delete_count,
891 new_elms, FAST_ELEMENTS, 905 new_elms, kind,
892 actual_start + item_count, to_copy); 906 actual_start + item_count, to_copy);
893 } 907 }
894 908
895 FillWithHoles(heap, new_elms, new_length, capacity); 909 FillWithHoles(heap, new_elms, new_length, capacity);
896 910
897 elms = new_elms; 911 elms = new_elms;
898 elms_changed = true; 912 elms_changed = true;
899 } else { 913 } else {
900 AssertNoAllocation no_gc; 914 AssertNoAllocation no_gc;
901 MoveElements(heap, &no_gc, 915 MoveElements(heap, &no_gc,
(...skipping 26 matching lines...) Expand all
928 JSObject* array_proto = 942 JSObject* array_proto =
929 JSObject::cast(global_context->array_function()->prototype()); 943 JSObject::cast(global_context->array_function()->prototype());
930 if (!ArrayPrototypeHasNoElements(heap, global_context, array_proto)) { 944 if (!ArrayPrototypeHasNoElements(heap, global_context, array_proto)) {
931 return CallJsBuiltin(isolate, "ArrayConcat", args); 945 return CallJsBuiltin(isolate, "ArrayConcat", args);
932 } 946 }
933 947
934 // Iterate through all the arguments performing checks 948 // Iterate through all the arguments performing checks
935 // and calculating total length. 949 // and calculating total length.
936 int n_arguments = args.length(); 950 int n_arguments = args.length();
937 int result_len = 0; 951 int result_len = 0;
938 ElementsKind elements_kind = FAST_SMI_ONLY_ELEMENTS; 952 ElementsKind elements_kind = GetInitialFastElementsKind();
939 for (int i = 0; i < n_arguments; i++) { 953 for (int i = 0; i < n_arguments; i++) {
940 Object* arg = args[i]; 954 Object* arg = args[i];
941 if (!arg->IsJSArray() || !JSArray::cast(arg)->HasFastTypeElements() 955 if (!arg->IsJSArray() ||
942 || JSArray::cast(arg)->GetPrototype() != array_proto) { 956 !JSArray::cast(arg)->HasFastSmiOrObjectElements() ||
957 JSArray::cast(arg)->GetPrototype() != array_proto) {
943 return CallJsBuiltin(isolate, "ArrayConcat", args); 958 return CallJsBuiltin(isolate, "ArrayConcat", args);
944 } 959 }
945 960
946 int len = Smi::cast(JSArray::cast(arg)->length())->value(); 961 int len = Smi::cast(JSArray::cast(arg)->length())->value();
947 962
948 // We shouldn't overflow when adding another len. 963 // We shouldn't overflow when adding another len.
949 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2); 964 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2);
950 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt); 965 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt);
951 USE(kHalfOfMaxInt); 966 USE(kHalfOfMaxInt);
952 result_len += len; 967 result_len += len;
953 ASSERT(result_len >= 0); 968 ASSERT(result_len >= 0);
954 969
955 if (result_len > FixedArray::kMaxLength) { 970 if (result_len > FixedArray::kMaxLength) {
956 return CallJsBuiltin(isolate, "ArrayConcat", args); 971 return CallJsBuiltin(isolate, "ArrayConcat", args);
957 } 972 }
958 973
959 if (!JSArray::cast(arg)->HasFastSmiOnlyElements()) { 974 if (!JSArray::cast(arg)->HasFastSmiElements()) {
960 elements_kind = FAST_ELEMENTS; 975 if (IsFastSmiElementsKind(elements_kind)) {
976 if (IsFastHoleyElementsKind(elements_kind)) {
977 elements_kind = FAST_HOLEY_ELEMENTS;
978 } else {
979 elements_kind = FAST_ELEMENTS;
980 }
981 }
982 }
983
984 if (JSArray::cast(arg)->HasFastHoleyElements()) {
985 elements_kind = GetHoleyElementsKind(elements_kind);
961 } 986 }
962 } 987 }
963 988
964 // Allocate result. 989 // Allocate result.
965 JSArray* result_array; 990 JSArray* result_array;
966 MaybeObject* maybe_array = 991 MaybeObject* maybe_array =
967 heap->AllocateJSArrayAndStorage(elements_kind, 992 heap->AllocateJSArrayAndStorage(elements_kind,
968 result_len, 993 result_len,
969 result_len); 994 result_len);
970 if (!maybe_array->To(&result_array)) return maybe_array; 995 if (!maybe_array->To(&result_array)) return maybe_array;
971 if (result_len == 0) return result_array; 996 if (result_len == 0) return result_array;
972 997
973 // Copy data. 998 // Copy data.
974 int start_pos = 0; 999 int start_pos = 0;
975 FixedArray* result_elms(FixedArray::cast(result_array->elements())); 1000 FixedArray* result_elms(FixedArray::cast(result_array->elements()));
976 for (int i = 0; i < n_arguments; i++) { 1001 for (int i = 0; i < n_arguments; i++) {
977 JSArray* array = JSArray::cast(args[i]); 1002 JSArray* array = JSArray::cast(args[i]);
978 int len = Smi::cast(array->length())->value(); 1003 int len = Smi::cast(array->length())->value();
979 FixedArray* elms = FixedArray::cast(array->elements()); 1004 FixedArray* elms = FixedArray::cast(array->elements());
980 CopyObjectToObjectElements(elms, FAST_ELEMENTS, 0, 1005 CopyObjectToObjectElements(elms, elements_kind, 0,
981 result_elms, FAST_ELEMENTS, 1006 result_elms, elements_kind,
982 start_pos, len); 1007 start_pos, len);
983 start_pos += len; 1008 start_pos += len;
984 } 1009 }
985 ASSERT(start_pos == result_len); 1010 ASSERT(start_pos == result_len);
986 1011
987 return result_array; 1012 return result_array;
988 } 1013 }
989 1014
990 1015
991 // ----------------------------------------------------------------------------- 1016 // -----------------------------------------------------------------------------
(...skipping 681 matching lines...) Expand 10 before | Expand all | Expand 10 after
1673 return Handle<Code>(code_address); \ 1698 return Handle<Code>(code_address); \
1674 } 1699 }
1675 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) 1700 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C)
1676 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) 1701 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A)
1677 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) 1702 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A)
1678 #undef DEFINE_BUILTIN_ACCESSOR_C 1703 #undef DEFINE_BUILTIN_ACCESSOR_C
1679 #undef DEFINE_BUILTIN_ACCESSOR_A 1704 #undef DEFINE_BUILTIN_ACCESSOR_A
1680 1705
1681 1706
1682 } } // namespace v8::internal 1707 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/bootstrapper.cc ('k') | src/code-stubs.cc » ('j') | src/elements.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698