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

Side by Side Diff: src/x64/ic-x64.cc

Issue 3144002: Copy-on-write arrays. (Closed)
Patch Set: Review fixes. Created 10 years, 4 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
« no previous file with comments | « src/x64/full-codegen-x64.cc ('k') | src/x64/macro-assembler-x64.h » ('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 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 469 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 480
481 // Check bit field. 481 // Check bit field.
482 __ testb(FieldOperand(map, Map::kBitFieldOffset), 482 __ testb(FieldOperand(map, Map::kBitFieldOffset),
483 Immediate((1 << Map::kIsAccessCheckNeeded) | 483 Immediate((1 << Map::kIsAccessCheckNeeded) |
484 (1 << interceptor_bit))); 484 (1 << interceptor_bit)));
485 __ j(not_zero, slow); 485 __ j(not_zero, slow);
486 } 486 }
487 487
488 488
489 // Loads an indexed element from a fast case array. 489 // Loads an indexed element from a fast case array.
490 // If not_fast_array is NULL, doesn't perform the elements map check.
490 static void GenerateFastArrayLoad(MacroAssembler* masm, 491 static void GenerateFastArrayLoad(MacroAssembler* masm,
491 Register receiver, 492 Register receiver,
492 Register key, 493 Register key,
493 Register elements, 494 Register elements,
494 Register scratch, 495 Register scratch,
495 Register result, 496 Register result,
496 Label* not_fast_array, 497 Label* not_fast_array,
497 Label* out_of_range) { 498 Label* out_of_range) {
498 // Register use: 499 // Register use:
499 // 500 //
500 // receiver - holds the receiver on entry. 501 // receiver - holds the receiver on entry.
501 // Unchanged unless 'result' is the same register. 502 // Unchanged unless 'result' is the same register.
502 // 503 //
503 // key - holds the smi key on entry. 504 // key - holds the smi key on entry.
504 // Unchanged unless 'result' is the same register. 505 // Unchanged unless 'result' is the same register.
505 // 506 //
506 // elements - holds the elements of the receiver on exit. 507 // elements - holds the elements of the receiver on exit.
507 // 508 //
508 // result - holds the result on exit if the load succeeded. 509 // result - holds the result on exit if the load succeeded.
509 // Allowed to be the the same as 'receiver' or 'key'. 510 // Allowed to be the the same as 'receiver' or 'key'.
510 // Unchanged on bailout so 'receiver' and 'key' can be safely 511 // Unchanged on bailout so 'receiver' and 'key' can be safely
511 // used by further computation. 512 // used by further computation.
512 // 513 //
513 // Scratch registers: 514 // Scratch registers:
514 // 515 //
515 // scratch - used to hold elements of the receiver and the loaded value. 516 // scratch - used to hold elements of the receiver and the loaded value.
516 517
517 __ movq(elements, FieldOperand(receiver, JSObject::kElementsOffset)); 518 __ movq(elements, FieldOperand(receiver, JSObject::kElementsOffset));
518 // Check that the object is in fast mode (not dictionary). 519 if (not_fast_array != NULL) {
519 __ CompareRoot(FieldOperand(elements, HeapObject::kMapOffset), 520 // Check that the object is in fast mode and writable.
520 Heap::kFixedArrayMapRootIndex); 521 __ CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
521 __ j(not_equal, not_fast_array); 522 Heap::kFixedArrayMapRootIndex);
523 __ j(not_equal, not_fast_array);
524 } else {
525 __ AssertFastElements(elements);
526 }
522 // Check that the key (index) is within bounds. 527 // Check that the key (index) is within bounds.
523 __ SmiCompare(key, FieldOperand(elements, FixedArray::kLengthOffset)); 528 __ SmiCompare(key, FieldOperand(elements, FixedArray::kLengthOffset));
524 // Unsigned comparison rejects negative indices. 529 // Unsigned comparison rejects negative indices.
525 __ j(above_equal, out_of_range); 530 __ j(above_equal, out_of_range);
526 // Fast case: Do the load. 531 // Fast case: Do the load.
527 SmiIndex index = masm->SmiToIndex(scratch, key, kPointerSizeLog2); 532 SmiIndex index = masm->SmiToIndex(scratch, key, kPointerSizeLog2);
528 __ movq(scratch, FieldOperand(elements, 533 __ movq(scratch, FieldOperand(elements,
529 index.reg, 534 index.reg,
530 index.scale, 535 index.scale,
531 FixedArray::kHeaderSize)); 536 FixedArray::kHeaderSize));
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
604 609
605 // Check that the key is a smi. 610 // Check that the key is a smi.
606 __ JumpIfNotSmi(rax, &check_string); 611 __ JumpIfNotSmi(rax, &check_string);
607 __ bind(&index_smi); 612 __ bind(&index_smi);
608 // Now the key is known to be a smi. This place is also jumped to from below 613 // Now the key is known to be a smi. This place is also jumped to from below
609 // where a numeric string is converted to a smi. 614 // where a numeric string is converted to a smi.
610 615
611 GenerateKeyedLoadReceiverCheck( 616 GenerateKeyedLoadReceiverCheck(
612 masm, rdx, rcx, Map::kHasIndexedInterceptor, &slow); 617 masm, rdx, rcx, Map::kHasIndexedInterceptor, &slow);
613 618
619 // Check the "has fast elements" bit in the receiver's map which is
620 // now in rcx.
621 __ testb(FieldOperand(rcx, Map::kBitField2Offset),
622 Immediate(1 << Map::kHasFastElements));
623 __ j(zero, &check_pixel_array);
624
614 GenerateFastArrayLoad(masm, 625 GenerateFastArrayLoad(masm,
615 rdx, 626 rdx,
616 rax, 627 rax,
617 rcx, 628 rcx,
618 rbx, 629 rbx,
619 rax, 630 rax,
620 &check_pixel_array, 631 NULL,
621 &slow); 632 &slow);
622 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); 633 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1);
623 __ ret(0); 634 __ ret(0);
624 635
625 __ bind(&check_pixel_array); 636 __ bind(&check_pixel_array);
626 // Check whether the elements object is a pixel array. 637 // Check whether the elements object is a pixel array.
627 // rdx: receiver 638 // rdx: receiver
628 // rax: key 639 // rax: key
629 // rcx: elements array 640 __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
630 __ SmiToInteger32(rbx, rax); // Used on both directions of next branch. 641 __ SmiToInteger32(rbx, rax); // Used on both directions of next branch.
631 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), 642 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset),
632 Heap::kPixelArrayMapRootIndex); 643 Heap::kPixelArrayMapRootIndex);
633 __ j(not_equal, &check_number_dictionary); 644 __ j(not_equal, &check_number_dictionary);
634 __ cmpl(rbx, FieldOperand(rcx, PixelArray::kLengthOffset)); 645 __ cmpl(rbx, FieldOperand(rcx, PixelArray::kLengthOffset));
635 __ j(above_equal, &slow); 646 __ j(above_equal, &slow);
636 __ movq(rax, FieldOperand(rcx, PixelArray::kExternalPointerOffset)); 647 __ movq(rax, FieldOperand(rcx, PixelArray::kExternalPointerOffset));
637 __ movzxbq(rax, Operand(rax, rbx, times_1, 0)); 648 __ movzxbq(rax, Operand(rax, rbx, times_1, 0));
638 __ Integer32ToSmi(rax, rax); 649 __ Integer32ToSmi(rax, rax);
639 __ ret(0); 650 __ ret(0);
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after
1005 __ j(equal, &array); 1016 __ j(equal, &array);
1006 // Check that the object is some kind of JS object. 1017 // Check that the object is some kind of JS object.
1007 __ CmpInstanceType(rbx, FIRST_JS_OBJECT_TYPE); 1018 __ CmpInstanceType(rbx, FIRST_JS_OBJECT_TYPE);
1008 __ j(below, &slow); 1019 __ j(below, &slow);
1009 1020
1010 // Object case: Check key against length in the elements array. 1021 // Object case: Check key against length in the elements array.
1011 // rax: value 1022 // rax: value
1012 // rdx: JSObject 1023 // rdx: JSObject
1013 // rcx: index 1024 // rcx: index
1014 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); 1025 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
1015 // Check that the object is in fast mode (not dictionary). 1026 // Check that the object is in fast mode and writable.
1016 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), 1027 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
1017 Heap::kFixedArrayMapRootIndex); 1028 Heap::kFixedArrayMapRootIndex);
1018 __ j(not_equal, &check_pixel_array); 1029 __ j(not_equal, &check_pixel_array);
1019 __ SmiCompareInteger32(FieldOperand(rbx, FixedArray::kLengthOffset), rcx); 1030 __ SmiCompareInteger32(FieldOperand(rbx, FixedArray::kLengthOffset), rcx);
1020 // rax: value 1031 // rax: value
1021 // rbx: FixedArray 1032 // rbx: FixedArray
1022 // rcx: index 1033 // rcx: index
1023 __ j(above, &fast); 1034 __ j(above, &fast);
1024 1035
1025 // Slow case: call runtime. 1036 // Slow case: call runtime.
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1068 // flags: smicompare (rdx.length(), rbx) 1079 // flags: smicompare (rdx.length(), rbx)
1069 __ j(not_equal, &slow); // do not leave holes in the array 1080 __ j(not_equal, &slow); // do not leave holes in the array
1070 __ SmiCompareInteger32(FieldOperand(rbx, FixedArray::kLengthOffset), rcx); 1081 __ SmiCompareInteger32(FieldOperand(rbx, FixedArray::kLengthOffset), rcx);
1071 __ j(below_equal, &slow); 1082 __ j(below_equal, &slow);
1072 // Increment index to get new length. 1083 // Increment index to get new length.
1073 __ leal(rdi, Operand(rcx, 1)); 1084 __ leal(rdi, Operand(rcx, 1));
1074 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rdi); 1085 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rdi);
1075 __ jmp(&fast); 1086 __ jmp(&fast);
1076 1087
1077 // Array case: Get the length and the elements array from the JS 1088 // Array case: Get the length and the elements array from the JS
1078 // array. Check that the array is in fast mode; if it is the 1089 // array. Check that the array is in fast mode (and writable); if it
1079 // length is always a smi. 1090 // is the length is always a smi.
1080 __ bind(&array); 1091 __ bind(&array);
1081 // rax: value 1092 // rax: value
1082 // rdx: receiver (a JSArray) 1093 // rdx: receiver (a JSArray)
1083 // rcx: index 1094 // rcx: index
1084 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); 1095 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
1085 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), 1096 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
1086 Heap::kFixedArrayMapRootIndex); 1097 Heap::kFixedArrayMapRootIndex);
1087 __ j(not_equal, &slow); 1098 __ j(not_equal, &slow);
1088 1099
1089 // Check the key against the length in the array, compute the 1100 // Check the key against the length in the array, compute the
(...skipping 765 matching lines...) Expand 10 before | Expand all | Expand 10 after
1855 Register scratch = rbx; 1866 Register scratch = rbx;
1856 1867
1857 // Check that the receiver isn't a smi. 1868 // Check that the receiver isn't a smi.
1858 __ JumpIfSmi(receiver, &miss); 1869 __ JumpIfSmi(receiver, &miss);
1859 1870
1860 // Check that the object is a JS array. 1871 // Check that the object is a JS array.
1861 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); 1872 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch);
1862 __ j(not_equal, &miss); 1873 __ j(not_equal, &miss);
1863 1874
1864 // Check that elements are FixedArray. 1875 // Check that elements are FixedArray.
1876 // We rely on StoreIC_ArrayLength below to deal with all types of
1877 // fast elements (including COW).
1865 __ movq(scratch, FieldOperand(receiver, JSArray::kElementsOffset)); 1878 __ movq(scratch, FieldOperand(receiver, JSArray::kElementsOffset));
1866 __ CmpObjectType(scratch, FIXED_ARRAY_TYPE, scratch); 1879 __ CmpObjectType(scratch, FIXED_ARRAY_TYPE, scratch);
1867 __ j(not_equal, &miss); 1880 __ j(not_equal, &miss);
1868 1881
1869 // Check that value is a smi. 1882 // Check that value is a smi.
1870 __ JumpIfNotSmi(value, &miss); 1883 __ JumpIfNotSmi(value, &miss);
1871 1884
1872 // Prepare tail call to StoreIC_ArrayLength. 1885 // Prepare tail call to StoreIC_ArrayLength.
1873 __ pop(scratch); 1886 __ pop(scratch);
1874 __ push(receiver); 1887 __ push(receiver);
(...skipping 30 matching lines...) Expand all
1905 GenerateMiss(masm); 1918 GenerateMiss(masm);
1906 } 1919 }
1907 1920
1908 1921
1909 #undef __ 1922 #undef __
1910 1923
1911 1924
1912 } } // namespace v8::internal 1925 } } // namespace v8::internal
1913 1926
1914 #endif // V8_TARGET_ARCH_X64 1927 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/full-codegen-x64.cc ('k') | src/x64/macro-assembler-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698