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/arm/ic-arm.cc

Issue 1332003: Port number dictionary probing in generated code to ARM.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 9 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 | « no previous file | src/ia32/ic-ia32.cc » ('j') | src/x64/ic-x64.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 // r3 - used as temporary and to hold the capacity of the property 58 // r3 - used as temporary and to hold the capacity of the property
59 // dictionary. 59 // dictionary.
60 // 60 //
61 // r2 - holds the name of the property and is unchanged. 61 // r2 - holds the name of the property and is unchanged.
62 62
63 Label done; 63 Label done;
64 64
65 // Check for the absence of an interceptor. 65 // Check for the absence of an interceptor.
66 // Load the map into t0. 66 // Load the map into t0.
67 __ ldr(t0, FieldMemOperand(t1, JSObject::kMapOffset)); 67 __ ldr(t0, FieldMemOperand(t1, JSObject::kMapOffset));
68 // Test the has_named_interceptor bit in the map. 68
69 __ ldr(r3, FieldMemOperand(t0, Map::kInstanceAttributesOffset)); 69 // Bail out if the receiver has a named interceptor.
70 __ tst(r3, Operand(1 << (Map::kHasNamedInterceptor + (3 * 8)))); 70 __ ldrb(r3, FieldMemOperand(t0, Map::kBitFieldOffset));
71 // Jump to miss if the interceptor bit is set. 71 __ tst(r3, Operand(1 << Map::kHasNamedInterceptor));
72 __ b(ne, miss); 72 __ b(nz, miss);
73 73
74 // Bail out if we have a JS global proxy object. 74 // Bail out if we have a JS global proxy object.
75 __ ldrb(r3, FieldMemOperand(t0, Map::kInstanceTypeOffset)); 75 __ ldrb(r3, FieldMemOperand(t0, Map::kInstanceTypeOffset));
76 __ cmp(r3, Operand(JS_GLOBAL_PROXY_TYPE)); 76 __ cmp(r3, Operand(JS_GLOBAL_PROXY_TYPE));
77 __ b(eq, miss); 77 __ b(eq, miss);
78 78
79 // Possible work-around for http://crbug.com/16276. 79 // Possible work-around for http://crbug.com/16276.
80 // See also: http://codereview.chromium.org/155418. 80 // See also: http://codereview.chromium.org/155418.
81 __ cmp(r3, Operand(JS_GLOBAL_OBJECT_TYPE)); 81 __ cmp(r3, Operand(JS_GLOBAL_OBJECT_TYPE));
82 __ b(eq, miss); 82 __ b(eq, miss);
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 __ bind(&done); // t1 == t0 + 4*index 137 __ bind(&done); // t1 == t0 + 4*index
138 __ ldr(r3, FieldMemOperand(t1, kElementsStartOffset + 2 * kPointerSize)); 138 __ ldr(r3, FieldMemOperand(t1, kElementsStartOffset + 2 * kPointerSize));
139 __ tst(r3, Operand(PropertyDetails::TypeField::mask() << kSmiTagSize)); 139 __ tst(r3, Operand(PropertyDetails::TypeField::mask() << kSmiTagSize));
140 __ b(ne, miss); 140 __ b(ne, miss);
141 141
142 // Get the value at the masked, scaled index and return. 142 // Get the value at the masked, scaled index and return.
143 __ ldr(t1, FieldMemOperand(t1, kElementsStartOffset + 1 * kPointerSize)); 143 __ ldr(t1, FieldMemOperand(t1, kElementsStartOffset + 1 * kPointerSize));
144 } 144 }
145 145
146 146
147 static void GenerateNumberDictionaryLoad(MacroAssembler* masm,
148 Label* miss,
149 Register elements,
150 Register key,
151 Register t0,
152 Register t1,
153 Register t2) {
154 // Register use:
155 //
156 // elements - holds the slow-case elements of the receiver and is unchanged.
157 //
158 // key - holds the smi key on entry and is unchanged if a branch is
159 // performed to the miss label.
160 //
161 // Scratch registers:
162 //
163 // t0 - holds the untagged key on entry and holds the hash once computed.
164 // Holds the result on exit if the load succeeded.
165 //
166 // t1 - used to hold the capacity mask of the dictionary
167 //
168 // t2 - used for the index into the dictionary.
169 Label done;
170
171 // Compute the hash code from the untagged key. This must be kept in sync
172 // with ComputeIntegerHash in utils.h.
173 //
174 // hash = ~hash + (hash << 15);
175 __ mvn(t1, Operand(t0));
176 __ add(t0, t1, Operand(t0, LSL, 15));
177 // hash = hash ^ (hash >> 12);
178 __ eor(t0, t0, Operand(t0, LSR, 12));
179 // hash = hash + (hash << 2);
180 __ add(t0, t0, Operand(t0, LSL, 2));
181 // hash = hash ^ (hash >> 4);
182 __ eor(t0, t0, Operand(t0, LSR, 4));
183 // hash = hash * 2057;
184 __ mov(t1, Operand(2057));
185 __ mul(t0, t0, t1);
186 // hash = hash ^ (hash >> 16);
187 __ eor(t0, t0, Operand(t0, LSR, 16));
188
189 // Compute the capacity mask.
190 __ ldr(t1, FieldMemOperand(elements, NumberDictionary::kCapacityOffset));
191 __ mov(t1, Operand(t1, ASR, kSmiTagSize)); // convert smi to int
192 __ sub(t1, t1, Operand(1));
193
194 // Generate an unrolled loop that performs a few probes before giving up.
195 static const int kProbes = 4;
196 for (int i = 0; i < kProbes; i++) {
197 // Use t2 for index calculations and keep the hash intact in t0.
198 __ mov(t2, t0);
199 // Compute the masked index: (hash + i + i * i) & mask.
200 if (i > 0) {
201 __ add(t2, t2, Operand(NumberDictionary::GetProbeOffset(i)));
202 }
203 __ and_(t2, t2, Operand(t1));
204
205 // Scale the index by multiplying by the element size.
206 ASSERT(NumberDictionary::kEntrySize == 3);
207 __ add(t2, t2, Operand(t2, LSL, 1)); // t2 = t2 * 3
208
209 // Check if the key is identical to the name.
210 __ add(t2, elements, Operand(t2, LSL, kPointerSizeLog2));
211 __ ldr(ip, FieldMemOperand(t2, NumberDictionary::kElementsStartOffset));
212 __ cmp(key, Operand(ip));
213 if (i != kProbes - 1) {
214 __ b(eq, &done);
215 } else {
216 __ b(ne, miss);
217 }
218 }
219
220 __ bind(&done);
221 // Check that the value is a normal property.
222 // t2: elements + (index * kPointerSize)
223 const int kDetailsOffset =
224 NumberDictionary::kElementsStartOffset + 2 * kPointerSize;
225 __ ldr(t1, FieldMemOperand(t2, kDetailsOffset));
226 __ tst(t1, Operand(Smi::FromInt(PropertyDetails::TypeField::mask())));
227 __ b(ne, miss);
228
229 // Get the value at the masked, scaled index and return.
230 const int kValueOffset =
231 NumberDictionary::kElementsStartOffset + kPointerSize;
232 __ ldr(t0, FieldMemOperand(t2, kValueOffset));
233 }
234
235
147 void LoadIC::GenerateArrayLength(MacroAssembler* masm) { 236 void LoadIC::GenerateArrayLength(MacroAssembler* masm) {
148 // ----------- S t a t e ------------- 237 // ----------- S t a t e -------------
149 // -- r2 : name 238 // -- r2 : name
150 // -- lr : return address 239 // -- lr : return address
151 // -- [sp] : receiver 240 // -- [sp] : receiver
152 // ----------------------------------- 241 // -----------------------------------
153 Label miss; 242 Label miss;
154 243
155 __ ldr(r0, MemOperand(sp, 0)); 244 __ ldr(r0, MemOperand(sp, 0));
156 245
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after
523 __ TailCallRuntime(Runtime::kGetProperty, 2, 1); 612 __ TailCallRuntime(Runtime::kGetProperty, 2, 1);
524 } 613 }
525 614
526 615
527 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { 616 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
528 // ---------- S t a t e -------------- 617 // ---------- S t a t e --------------
529 // -- lr : return address 618 // -- lr : return address
530 // -- sp[0] : key 619 // -- sp[0] : key
531 // -- sp[4] : receiver 620 // -- sp[4] : receiver
532 // ----------------------------------- 621 // -----------------------------------
533 Label slow, fast, check_pixel_array; 622 Label slow, fast, check_pixel_array, check_number_dictionary;
534 623
535 // Get the key and receiver object from the stack. 624 // Get the key and receiver object from the stack.
536 __ ldm(ia, sp, r0.bit() | r1.bit()); 625 __ ldm(ia, sp, r0.bit() | r1.bit());
537 626
538 // Check that the object isn't a smi. 627 // Check that the object isn't a smi.
539 __ BranchOnSmi(r1, &slow); 628 __ BranchOnSmi(r1, &slow);
540 // Get the map of the receiver. 629 // Get the map of the receiver.
541 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); 630 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
542 // Check bit field. 631 // Check bit field.
543 __ ldrb(r3, FieldMemOperand(r2, Map::kBitFieldOffset)); 632 __ ldrb(r3, FieldMemOperand(r2, Map::kBitFieldOffset));
544 __ tst(r3, Operand(kSlowCaseBitFieldMask)); 633 __ tst(r3, Operand(kSlowCaseBitFieldMask));
545 __ b(ne, &slow); 634 __ b(ne, &slow);
546 // Check that the object is some kind of JS object EXCEPT JS Value type. 635 // Check that the object is some kind of JS object EXCEPT JS Value type.
547 // In the case that the object is a value-wrapper object, 636 // In the case that the object is a value-wrapper object,
548 // we enter the runtime system to make sure that indexing into string 637 // we enter the runtime system to make sure that indexing into string
549 // objects work as intended. 638 // objects work as intended.
550 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); 639 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
551 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset)); 640 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
552 __ cmp(r2, Operand(JS_OBJECT_TYPE)); 641 __ cmp(r2, Operand(JS_OBJECT_TYPE));
553 __ b(lt, &slow); 642 __ b(lt, &slow);
554 643
555 // Check that the key is a smi. 644 // Check that the key is a smi.
556 __ BranchOnNotSmi(r0, &slow); 645 __ BranchOnNotSmi(r0, &slow);
646 // Save key in r2 in case we want it for the number dictionary case.
647 __ mov(r2, r0);
557 __ mov(r0, Operand(r0, ASR, kSmiTagSize)); 648 __ mov(r0, Operand(r0, ASR, kSmiTagSize));
558 649
559 // Get the elements array of the object. 650 // Get the elements array of the object.
560 __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset)); 651 __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset));
561 // Check that the object is in fast mode (not dictionary). 652 // Check that the object is in fast mode (not dictionary).
562 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); 653 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
563 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); 654 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
564 __ cmp(r3, ip); 655 __ cmp(r3, ip);
565 __ b(ne, &slow); 656 __ b(ne, &check_pixel_array);
566 // Check that the key (index) is within bounds. 657 // Check that the key (index) is within bounds.
567 __ ldr(r3, FieldMemOperand(r1, Array::kLengthOffset)); 658 __ ldr(r3, FieldMemOperand(r1, Array::kLengthOffset));
568 __ cmp(r0, Operand(r3)); 659 __ cmp(r0, Operand(r3));
569 __ b(lo, &fast); 660 __ b(ge, &slow);
661 // Fast case: Do the load.
662 __ add(r3, r1, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
663 __ ldr(r0, MemOperand(r3, r0, LSL, kPointerSizeLog2));
664 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
665 __ cmp(r0, ip);
666 // In case the loaded value is the_hole we have to consult GetProperty
667 // to ensure the prototype chain is searched.
668 __ b(eq, &slow);
669 __ Ret();
570 670
571 // Check whether the elements is a pixel array. 671 // Check whether the elements is a pixel array.
572 __ bind(&check_pixel_array); 672 __ bind(&check_pixel_array);
573 __ LoadRoot(ip, Heap::kPixelArrayMapRootIndex); 673 __ LoadRoot(ip, Heap::kPixelArrayMapRootIndex);
574 __ cmp(r3, ip); 674 __ cmp(r3, ip);
575 __ b(ne, &slow); 675 __ b(ne, &check_number_dictionary);
576 __ ldr(ip, FieldMemOperand(r1, PixelArray::kLengthOffset)); 676 __ ldr(ip, FieldMemOperand(r1, PixelArray::kLengthOffset));
577 __ cmp(r0, ip); 677 __ cmp(r0, ip);
578 __ b(hs, &slow); 678 __ b(hs, &slow);
579 __ ldr(ip, FieldMemOperand(r1, PixelArray::kExternalPointerOffset)); 679 __ ldr(ip, FieldMemOperand(r1, PixelArray::kExternalPointerOffset));
580 __ ldrb(r0, MemOperand(ip, r0)); 680 __ ldrb(r0, MemOperand(ip, r0));
581 __ mov(r0, Operand(r0, LSL, kSmiTagSize)); // Tag result as smi. 681 __ mov(r0, Operand(r0, LSL, kSmiTagSize)); // Tag result as smi.
582 __ Ret(); 682 __ Ret();
583 683
684 __ bind(&check_number_dictionary);
685 // Check whether the elements is a number dictionary.
686 // r0: untagged index
687 // r1: elements
688 // r2: key
689 __ LoadRoot(ip, Heap::kHashTableMapRootIndex);
690 __ cmp(r3, ip);
691 __ b(ne, &slow);
692 GenerateNumberDictionaryLoad(masm, &slow, r1, r2, r0, r3, r4);
693 __ Ret();
694
584 // Slow case: Push extra copies of the arguments (2). 695 // Slow case: Push extra copies of the arguments (2).
585 __ bind(&slow); 696 __ bind(&slow);
586 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1, r0, r1); 697 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1, r0, r1);
587 GenerateRuntimeGetProperty(masm); 698 GenerateRuntimeGetProperty(masm);
588
589 // Fast case: Do the load.
590 __ bind(&fast);
591 __ add(r3, r1, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
592 __ ldr(r0, MemOperand(r3, r0, LSL, kPointerSizeLog2));
593 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
594 __ cmp(r0, ip);
595 // In case the loaded value is the_hole we have to consult GetProperty
596 // to ensure the prototype chain is searched.
597 __ b(eq, &slow);
598
599 __ Ret();
600 } 699 }
601 700
602 701
603 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { 702 void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
604 // ---------- S t a t e -------------- 703 // ---------- S t a t e --------------
605 // -- lr : return address 704 // -- lr : return address
606 // -- sp[0] : key 705 // -- sp[0] : key
607 // -- sp[4] : receiver 706 // -- sp[4] : receiver
608 // ----------------------------------- 707 // -----------------------------------
609 708
(...skipping 953 matching lines...) Expand 10 before | Expand all | Expand 10 after
1563 __ bind(&miss); 1662 __ bind(&miss);
1564 1663
1565 GenerateMiss(masm); 1664 GenerateMiss(masm);
1566 } 1665 }
1567 1666
1568 1667
1569 #undef __ 1668 #undef __
1570 1669
1571 1670
1572 } } // namespace v8::internal 1671 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | src/ia32/ic-ia32.cc » ('j') | src/x64/ic-x64.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698