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

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

Powered by Google App Engine
This is Rietveld 408576698