OLD | NEW |
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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
57 __ b(eq, global_object); | 57 __ b(eq, global_object); |
58 __ cmp(type, Operand(JS_BUILTINS_OBJECT_TYPE)); | 58 __ cmp(type, Operand(JS_BUILTINS_OBJECT_TYPE)); |
59 __ b(eq, global_object); | 59 __ b(eq, global_object); |
60 __ cmp(type, Operand(JS_GLOBAL_PROXY_TYPE)); | 60 __ cmp(type, Operand(JS_GLOBAL_PROXY_TYPE)); |
61 __ b(eq, global_object); | 61 __ b(eq, global_object); |
62 } | 62 } |
63 | 63 |
64 | 64 |
65 // Generated code falls through if the receiver is a regular non-global | 65 // Generated code falls through if the receiver is a regular non-global |
66 // JS object with slow properties and no interceptors. | 66 // JS object with slow properties and no interceptors. |
67 static void GenerateStringDictionaryReceiverCheck(MacroAssembler* masm, | 67 static void GenerateNameDictionaryReceiverCheck(MacroAssembler* masm, |
68 Register receiver, | 68 Register receiver, |
69 Register elements, | 69 Register elements, |
70 Register t0, | 70 Register t0, |
71 Register t1, | 71 Register t1, |
72 Label* miss) { | 72 Label* miss) { |
73 // Register usage: | 73 // Register usage: |
74 // receiver: holds the receiver on entry and is unchanged. | 74 // receiver: holds the receiver on entry and is unchanged. |
75 // elements: holds the property dictionary on fall through. | 75 // elements: holds the property dictionary on fall through. |
76 // Scratch registers: | 76 // Scratch registers: |
77 // t0: used to holds the receiver map. | 77 // t0: used to holds the receiver map. |
78 // t1: used to holds the receiver instance type, receiver bit mask and | 78 // t1: used to holds the receiver instance type, receiver bit mask and |
79 // elements map. | 79 // elements map. |
80 | 80 |
81 // Check that the receiver isn't a smi. | 81 // Check that the receiver isn't a smi. |
82 __ JumpIfSmi(receiver, miss); | 82 __ JumpIfSmi(receiver, miss); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 Register result, | 124 Register result, |
125 Register scratch1, | 125 Register scratch1, |
126 Register scratch2) { | 126 Register scratch2) { |
127 // Main use of the scratch registers. | 127 // Main use of the scratch registers. |
128 // scratch1: Used as temporary and to hold the capacity of the property | 128 // scratch1: Used as temporary and to hold the capacity of the property |
129 // dictionary. | 129 // dictionary. |
130 // scratch2: Used as temporary. | 130 // scratch2: Used as temporary. |
131 Label done; | 131 Label done; |
132 | 132 |
133 // Probe the dictionary. | 133 // Probe the dictionary. |
134 StringDictionaryLookupStub::GeneratePositiveLookup(masm, | 134 NameDictionaryLookupStub::GeneratePositiveLookup(masm, |
135 miss, | 135 miss, |
136 &done, | 136 &done, |
137 elements, | 137 elements, |
138 name, | 138 name, |
139 scratch1, | 139 scratch1, |
140 scratch2); | 140 scratch2); |
141 | 141 |
142 // If probing finds an entry check that the value is a normal | 142 // If probing finds an entry check that the value is a normal |
143 // property. | 143 // property. |
144 __ bind(&done); // scratch2 == elements + 4 * index | 144 __ bind(&done); // scratch2 == elements + 4 * index |
145 const int kElementsStartOffset = StringDictionary::kHeaderSize + | 145 const int kElementsStartOffset = NameDictionary::kHeaderSize + |
146 StringDictionary::kElementsStartIndex * kPointerSize; | 146 NameDictionary::kElementsStartIndex * kPointerSize; |
147 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; | 147 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; |
148 __ ldr(scratch1, FieldMemOperand(scratch2, kDetailsOffset)); | 148 __ ldr(scratch1, FieldMemOperand(scratch2, kDetailsOffset)); |
149 __ tst(scratch1, Operand(PropertyDetails::TypeField::kMask << kSmiTagSize)); | 149 __ tst(scratch1, Operand(PropertyDetails::TypeField::kMask << kSmiTagSize)); |
150 __ b(ne, miss); | 150 __ b(ne, miss); |
151 | 151 |
152 // Get the value at the masked, scaled index and return. | 152 // Get the value at the masked, scaled index and return. |
153 __ ldr(result, | 153 __ ldr(result, |
154 FieldMemOperand(scratch2, kElementsStartOffset + 1 * kPointerSize)); | 154 FieldMemOperand(scratch2, kElementsStartOffset + 1 * kPointerSize)); |
155 } | 155 } |
156 | 156 |
(...skipping 16 matching lines...) Expand all Loading... |
173 Register value, | 173 Register value, |
174 Register scratch1, | 174 Register scratch1, |
175 Register scratch2) { | 175 Register scratch2) { |
176 // Main use of the scratch registers. | 176 // Main use of the scratch registers. |
177 // scratch1: Used as temporary and to hold the capacity of the property | 177 // scratch1: Used as temporary and to hold the capacity of the property |
178 // dictionary. | 178 // dictionary. |
179 // scratch2: Used as temporary. | 179 // scratch2: Used as temporary. |
180 Label done; | 180 Label done; |
181 | 181 |
182 // Probe the dictionary. | 182 // Probe the dictionary. |
183 StringDictionaryLookupStub::GeneratePositiveLookup(masm, | 183 NameDictionaryLookupStub::GeneratePositiveLookup(masm, |
184 miss, | 184 miss, |
185 &done, | 185 &done, |
186 elements, | 186 elements, |
187 name, | 187 name, |
188 scratch1, | 188 scratch1, |
189 scratch2); | 189 scratch2); |
190 | 190 |
191 // If probing finds an entry in the dictionary check that the value | 191 // If probing finds an entry in the dictionary check that the value |
192 // is a normal property that is not read only. | 192 // is a normal property that is not read only. |
193 __ bind(&done); // scratch2 == elements + 4 * index | 193 __ bind(&done); // scratch2 == elements + 4 * index |
194 const int kElementsStartOffset = StringDictionary::kHeaderSize + | 194 const int kElementsStartOffset = NameDictionary::kHeaderSize + |
195 StringDictionary::kElementsStartIndex * kPointerSize; | 195 NameDictionary::kElementsStartIndex * kPointerSize; |
196 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; | 196 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; |
197 const int kTypeAndReadOnlyMask = | 197 const int kTypeAndReadOnlyMask = |
198 (PropertyDetails::TypeField::kMask | | 198 (PropertyDetails::TypeField::kMask | |
199 PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize; | 199 PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize; |
200 __ ldr(scratch1, FieldMemOperand(scratch2, kDetailsOffset)); | 200 __ ldr(scratch1, FieldMemOperand(scratch2, kDetailsOffset)); |
201 __ tst(scratch1, Operand(kTypeAndReadOnlyMask)); | 201 __ tst(scratch1, Operand(kTypeAndReadOnlyMask)); |
202 __ b(ne, miss); | 202 __ b(ne, miss); |
203 | 203 |
204 // Store the value at the masked, scaled index and return. | 204 // Store the value at the masked, scaled index and return. |
205 const int kValueOffset = kElementsStartOffset + kPointerSize; | 205 const int kValueOffset = kElementsStartOffset + kPointerSize; |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
296 MemOperand(scratch1, key, LSL, kPointerSizeLog2 - kSmiTagSize)); | 296 MemOperand(scratch1, key, LSL, kPointerSizeLog2 - kSmiTagSize)); |
297 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 297 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
298 __ cmp(scratch2, ip); | 298 __ cmp(scratch2, ip); |
299 // In case the loaded value is the_hole we have to consult GetProperty | 299 // In case the loaded value is the_hole we have to consult GetProperty |
300 // to ensure the prototype chain is searched. | 300 // to ensure the prototype chain is searched. |
301 __ b(eq, out_of_range); | 301 __ b(eq, out_of_range); |
302 __ mov(result, scratch2); | 302 __ mov(result, scratch2); |
303 } | 303 } |
304 | 304 |
305 | 305 |
306 // Checks whether a key is an array index string or an internalized string. | 306 // Checks whether a key is an array index string or a unique name. |
307 // Falls through if a key is an internalized string. | 307 // Falls through if a key is a unique name. |
308 static void GenerateKeyStringCheck(MacroAssembler* masm, | 308 static void GenerateKeyNameCheck(MacroAssembler* masm, |
309 Register key, | 309 Register key, |
310 Register map, | 310 Register map, |
311 Register hash, | 311 Register hash, |
312 Label* index_string, | 312 Label* index_string, |
313 Label* not_internalized) { | 313 Label* not_unique) { |
314 // The key is not a smi. | 314 // The key is not a smi. |
315 // Is it a string? | 315 Label unique; |
316 __ CompareObjectType(key, map, hash, FIRST_NONSTRING_TYPE); | 316 // Is it a name? |
317 __ b(ge, not_internalized); | 317 __ CompareObjectType(key, map, hash, LAST_UNIQUE_NAME_TYPE); |
| 318 __ b(hi, not_unique); |
| 319 STATIC_ASSERT(LAST_UNIQUE_NAME_TYPE == FIRST_NONSTRING_TYPE); |
| 320 __ b(eq, &unique); |
318 | 321 |
319 // Is the string an array index, with cached numeric value? | 322 // Is the string an array index, with cached numeric value? |
320 __ ldr(hash, FieldMemOperand(key, String::kHashFieldOffset)); | 323 __ ldr(hash, FieldMemOperand(key, Name::kHashFieldOffset)); |
321 __ tst(hash, Operand(String::kContainsCachedArrayIndexMask)); | 324 __ tst(hash, Operand(Name::kContainsCachedArrayIndexMask)); |
322 __ b(eq, index_string); | 325 __ b(eq, index_string); |
323 | 326 |
324 // Is the string internalized? | 327 // Is the string internalized? |
325 // map: key map | 328 // map: key map |
326 __ ldrb(hash, FieldMemOperand(map, Map::kInstanceTypeOffset)); | 329 __ ldrb(hash, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
327 STATIC_ASSERT(kInternalizedTag != 0); | 330 STATIC_ASSERT(kInternalizedTag != 0); |
328 __ tst(hash, Operand(kIsInternalizedMask)); | 331 __ tst(hash, Operand(kIsInternalizedMask)); |
329 __ b(eq, not_internalized); | 332 __ b(eq, not_unique); |
| 333 |
| 334 __ bind(&unique); |
330 } | 335 } |
331 | 336 |
332 | 337 |
333 // Defined in ic.cc. | 338 // Defined in ic.cc. |
334 Object* CallIC_Miss(Arguments args); | 339 Object* CallIC_Miss(Arguments args); |
335 | 340 |
336 // The generated code does not accept smi keys. | 341 // The generated code does not accept smi keys. |
337 // The generated code falls through if both probes miss. | 342 // The generated code falls through if both probes miss. |
338 void CallICBase::GenerateMonomorphicCacheProbe(MacroAssembler* masm, | 343 void CallICBase::GenerateMonomorphicCacheProbe(MacroAssembler* masm, |
339 int argc, | 344 int argc, |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
420 void CallICBase::GenerateNormal(MacroAssembler* masm, int argc) { | 425 void CallICBase::GenerateNormal(MacroAssembler* masm, int argc) { |
421 // ----------- S t a t e ------------- | 426 // ----------- S t a t e ------------- |
422 // -- r2 : name | 427 // -- r2 : name |
423 // -- lr : return address | 428 // -- lr : return address |
424 // ----------------------------------- | 429 // ----------------------------------- |
425 Label miss; | 430 Label miss; |
426 | 431 |
427 // Get the receiver of the function from the stack into r1. | 432 // Get the receiver of the function from the stack into r1. |
428 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | 433 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); |
429 | 434 |
430 GenerateStringDictionaryReceiverCheck(masm, r1, r0, r3, r4, &miss); | 435 GenerateNameDictionaryReceiverCheck(masm, r1, r0, r3, r4, &miss); |
431 | 436 |
432 // r0: elements | 437 // r0: elements |
433 // Search the dictionary - put result in register r1. | 438 // Search the dictionary - put result in register r1. |
434 GenerateDictionaryLoad(masm, &miss, r0, r2, r1, r3, r4); | 439 GenerateDictionaryLoad(masm, &miss, r0, r2, r1, r3, r4); |
435 | 440 |
436 GenerateFunctionTailCall(masm, argc, &miss, r4); | 441 GenerateFunctionTailCall(masm, argc, &miss, r4); |
437 | 442 |
438 __ bind(&miss); | 443 __ bind(&miss); |
439 } | 444 } |
440 | 445 |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
524 void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { | 529 void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { |
525 // ----------- S t a t e ------------- | 530 // ----------- S t a t e ------------- |
526 // -- r2 : name | 531 // -- r2 : name |
527 // -- lr : return address | 532 // -- lr : return address |
528 // ----------------------------------- | 533 // ----------------------------------- |
529 | 534 |
530 // Get the receiver of the function from the stack into r1. | 535 // Get the receiver of the function from the stack into r1. |
531 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | 536 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); |
532 | 537 |
533 Label do_call, slow_call, slow_load, slow_reload_receiver; | 538 Label do_call, slow_call, slow_load, slow_reload_receiver; |
534 Label check_number_dictionary, check_string, lookup_monomorphic_cache; | 539 Label check_number_dictionary, check_name, lookup_monomorphic_cache; |
535 Label index_smi, index_string; | 540 Label index_smi, index_name; |
536 | 541 |
537 // Check that the key is a smi. | 542 // Check that the key is a smi. |
538 __ JumpIfNotSmi(r2, &check_string); | 543 __ JumpIfNotSmi(r2, &check_name); |
539 __ bind(&index_smi); | 544 __ bind(&index_smi); |
540 // Now the key is known to be a smi. This place is also jumped to from below | 545 // Now the key is known to be a smi. This place is also jumped to from below |
541 // where a numeric string is converted to a smi. | 546 // where a numeric string is converted to a smi. |
542 | 547 |
543 GenerateKeyedLoadReceiverCheck( | 548 GenerateKeyedLoadReceiverCheck( |
544 masm, r1, r0, r3, Map::kHasIndexedInterceptor, &slow_call); | 549 masm, r1, r0, r3, Map::kHasIndexedInterceptor, &slow_call); |
545 | 550 |
546 GenerateFastArrayLoad( | 551 GenerateFastArrayLoad( |
547 masm, r1, r2, r4, r3, r0, r1, &check_number_dictionary, &slow_load); | 552 masm, r1, r2, r4, r3, r0, r1, &check_number_dictionary, &slow_load); |
548 Counters* counters = masm->isolate()->counters(); | 553 Counters* counters = masm->isolate()->counters(); |
(...skipping 26 matching lines...) Expand all Loading... |
575 { | 580 { |
576 FrameScope scope(masm, StackFrame::INTERNAL); | 581 FrameScope scope(masm, StackFrame::INTERNAL); |
577 __ push(r2); // save the key | 582 __ push(r2); // save the key |
578 __ Push(r1, r2); // pass the receiver and the key | 583 __ Push(r1, r2); // pass the receiver and the key |
579 __ CallRuntime(Runtime::kKeyedGetProperty, 2); | 584 __ CallRuntime(Runtime::kKeyedGetProperty, 2); |
580 __ pop(r2); // restore the key | 585 __ pop(r2); // restore the key |
581 } | 586 } |
582 __ mov(r1, r0); | 587 __ mov(r1, r0); |
583 __ jmp(&do_call); | 588 __ jmp(&do_call); |
584 | 589 |
585 __ bind(&check_string); | 590 __ bind(&check_name); |
586 GenerateKeyStringCheck(masm, r2, r0, r3, &index_string, &slow_call); | 591 GenerateKeyNameCheck(masm, r2, r0, r3, &index_name, &slow_call); |
587 | 592 |
588 // The key is known to be internalized. | 593 // The key is known to be a uniquq name. |
589 // If the receiver is a regular JS object with slow properties then do | 594 // If the receiver is a regular JS object with slow properties then do |
590 // a quick inline probe of the receiver's dictionary. | 595 // a quick inline probe of the receiver's dictionary. |
591 // Otherwise do the monomorphic cache probe. | 596 // Otherwise do the monomorphic cache probe. |
592 GenerateKeyedLoadReceiverCheck( | 597 GenerateKeyedLoadReceiverCheck( |
593 masm, r1, r0, r3, Map::kHasNamedInterceptor, &lookup_monomorphic_cache); | 598 masm, r1, r0, r3, Map::kHasNamedInterceptor, &lookup_monomorphic_cache); |
594 | 599 |
595 __ ldr(r0, FieldMemOperand(r1, JSObject::kPropertiesOffset)); | 600 __ ldr(r0, FieldMemOperand(r1, JSObject::kPropertiesOffset)); |
596 __ ldr(r3, FieldMemOperand(r0, HeapObject::kMapOffset)); | 601 __ ldr(r3, FieldMemOperand(r0, HeapObject::kMapOffset)); |
597 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); | 602 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); |
598 __ cmp(r3, ip); | 603 __ cmp(r3, ip); |
599 __ b(ne, &lookup_monomorphic_cache); | 604 __ b(ne, &lookup_monomorphic_cache); |
600 | 605 |
601 GenerateDictionaryLoad(masm, &slow_load, r0, r2, r1, r3, r4); | 606 GenerateDictionaryLoad(masm, &slow_load, r0, r2, r1, r3, r4); |
602 __ IncrementCounter(counters->keyed_call_generic_lookup_dict(), 1, r0, r3); | 607 __ IncrementCounter(counters->keyed_call_generic_lookup_dict(), 1, r0, r3); |
603 __ jmp(&do_call); | 608 __ jmp(&do_call); |
604 | 609 |
605 __ bind(&lookup_monomorphic_cache); | 610 __ bind(&lookup_monomorphic_cache); |
606 __ IncrementCounter(counters->keyed_call_generic_lookup_cache(), 1, r0, r3); | 611 __ IncrementCounter(counters->keyed_call_generic_lookup_cache(), 1, r0, r3); |
607 GenerateMonomorphicCacheProbe(masm, | 612 GenerateMonomorphicCacheProbe(masm, |
608 argc, | 613 argc, |
609 Code::KEYED_CALL_IC, | 614 Code::KEYED_CALL_IC, |
610 Code::kNoExtraICState); | 615 Code::kNoExtraICState); |
611 // Fall through on miss. | 616 // Fall through on miss. |
612 | 617 |
613 __ bind(&slow_call); | 618 __ bind(&slow_call); |
614 // This branch is taken if: | 619 // This branch is taken if: |
615 // - the receiver requires boxing or access check, | 620 // - the receiver requires boxing or access check, |
616 // - the key is neither smi nor an internalized string, | 621 // - the key is neither smi nor a unique name, |
617 // - the value loaded is not a function, | 622 // - the value loaded is not a function, |
618 // - there is hope that the runtime will create a monomorphic call stub | 623 // - there is hope that the runtime will create a monomorphic call stub |
619 // that will get fetched next time. | 624 // that will get fetched next time. |
620 __ IncrementCounter(counters->keyed_call_generic_slow(), 1, r0, r3); | 625 __ IncrementCounter(counters->keyed_call_generic_slow(), 1, r0, r3); |
621 GenerateMiss(masm, argc); | 626 GenerateMiss(masm, argc); |
622 | 627 |
623 __ bind(&index_string); | 628 __ bind(&index_name); |
624 __ IndexFromHash(r3, r2); | 629 __ IndexFromHash(r3, r2); |
625 // Now jump to the place where smi keys are handled. | 630 // Now jump to the place where smi keys are handled. |
626 __ jmp(&index_smi); | 631 __ jmp(&index_smi); |
627 } | 632 } |
628 | 633 |
629 | 634 |
630 void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { | 635 void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { |
631 // ----------- S t a t e ------------- | 636 // ----------- S t a t e ------------- |
632 // -- r2 : name | 637 // -- r2 : name |
633 // -- lr : return address | 638 // -- lr : return address |
634 // ----------------------------------- | 639 // ----------------------------------- |
635 | 640 |
636 // Check if the name is a string. | 641 // Check if the name is really a name. |
637 Label miss; | 642 Label miss; |
638 __ JumpIfSmi(r2, &miss); | 643 __ JumpIfSmi(r2, &miss); |
639 __ IsObjectJSStringType(r2, r0, &miss); | 644 __ IsObjectNameType(r2, r0, &miss); |
640 | 645 |
641 CallICBase::GenerateNormal(masm, argc); | 646 CallICBase::GenerateNormal(masm, argc); |
642 __ bind(&miss); | 647 __ bind(&miss); |
643 GenerateMiss(masm, argc); | 648 GenerateMiss(masm, argc); |
644 } | 649 } |
645 | 650 |
646 | 651 |
647 // Defined in ic.cc. | 652 // Defined in ic.cc. |
648 Object* LoadIC_Miss(Arguments args); | 653 Object* LoadIC_Miss(Arguments args); |
649 | 654 |
(...skipping 18 matching lines...) Expand all Loading... |
668 | 673 |
669 void LoadIC::GenerateNormal(MacroAssembler* masm) { | 674 void LoadIC::GenerateNormal(MacroAssembler* masm) { |
670 // ----------- S t a t e ------------- | 675 // ----------- S t a t e ------------- |
671 // -- r2 : name | 676 // -- r2 : name |
672 // -- lr : return address | 677 // -- lr : return address |
673 // -- r0 : receiver | 678 // -- r0 : receiver |
674 // -- sp[0] : receiver | 679 // -- sp[0] : receiver |
675 // ----------------------------------- | 680 // ----------------------------------- |
676 Label miss; | 681 Label miss; |
677 | 682 |
678 GenerateStringDictionaryReceiverCheck(masm, r0, r1, r3, r4, &miss); | 683 GenerateNameDictionaryReceiverCheck(masm, r0, r1, r3, r4, &miss); |
679 | 684 |
680 // r1: elements | 685 // r1: elements |
681 GenerateDictionaryLoad(masm, &miss, r1, r2, r0, r3, r4); | 686 GenerateDictionaryLoad(masm, &miss, r1, r2, r0, r3, r4); |
682 __ Ret(); | 687 __ Ret(); |
683 | 688 |
684 // Cache miss: Jump to runtime. | 689 // Cache miss: Jump to runtime. |
685 __ bind(&miss); | 690 __ bind(&miss); |
686 GenerateMiss(masm); | 691 GenerateMiss(masm); |
687 } | 692 } |
688 | 693 |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
911 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); | 916 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); |
912 } | 917 } |
913 | 918 |
914 | 919 |
915 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { | 920 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { |
916 // ---------- S t a t e -------------- | 921 // ---------- S t a t e -------------- |
917 // -- lr : return address | 922 // -- lr : return address |
918 // -- r0 : key | 923 // -- r0 : key |
919 // -- r1 : receiver | 924 // -- r1 : receiver |
920 // ----------------------------------- | 925 // ----------------------------------- |
921 Label slow, check_string, index_smi, index_string, property_array_property; | 926 Label slow, check_name, index_smi, index_name, property_array_property; |
922 Label probe_dictionary, check_number_dictionary; | 927 Label probe_dictionary, check_number_dictionary; |
923 | 928 |
924 Register key = r0; | 929 Register key = r0; |
925 Register receiver = r1; | 930 Register receiver = r1; |
926 | 931 |
927 Isolate* isolate = masm->isolate(); | 932 Isolate* isolate = masm->isolate(); |
928 | 933 |
929 // Check that the key is a smi. | 934 // Check that the key is a smi. |
930 __ JumpIfNotSmi(key, &check_string); | 935 __ JumpIfNotSmi(key, &check_name); |
931 __ bind(&index_smi); | 936 __ bind(&index_smi); |
932 // Now the key is known to be a smi. This place is also jumped to from below | 937 // Now the key is known to be a smi. This place is also jumped to from below |
933 // where a numeric string is converted to a smi. | 938 // where a numeric string is converted to a smi. |
934 | 939 |
935 GenerateKeyedLoadReceiverCheck( | 940 GenerateKeyedLoadReceiverCheck( |
936 masm, receiver, r2, r3, Map::kHasIndexedInterceptor, &slow); | 941 masm, receiver, r2, r3, Map::kHasIndexedInterceptor, &slow); |
937 | 942 |
938 // Check the receiver's map to see if it has fast elements. | 943 // Check the receiver's map to see if it has fast elements. |
939 __ CheckFastElements(r2, r3, &check_number_dictionary); | 944 __ CheckFastElements(r2, r3, &check_number_dictionary); |
940 | 945 |
(...skipping 16 matching lines...) Expand all Loading... |
957 __ mov(r2, Operand(r0, ASR, kSmiTagSize)); | 962 __ mov(r2, Operand(r0, ASR, kSmiTagSize)); |
958 __ LoadFromNumberDictionary(&slow, r4, r0, r0, r2, r3, r5); | 963 __ LoadFromNumberDictionary(&slow, r4, r0, r0, r2, r3, r5); |
959 __ Ret(); | 964 __ Ret(); |
960 | 965 |
961 // Slow case, key and receiver still in r0 and r1. | 966 // Slow case, key and receiver still in r0 and r1. |
962 __ bind(&slow); | 967 __ bind(&slow); |
963 __ IncrementCounter(isolate->counters()->keyed_load_generic_slow(), | 968 __ IncrementCounter(isolate->counters()->keyed_load_generic_slow(), |
964 1, r2, r3); | 969 1, r2, r3); |
965 GenerateRuntimeGetProperty(masm); | 970 GenerateRuntimeGetProperty(masm); |
966 | 971 |
967 __ bind(&check_string); | 972 __ bind(&check_name); |
968 GenerateKeyStringCheck(masm, key, r2, r3, &index_string, &slow); | 973 GenerateKeyNameCheck(masm, key, r2, r3, &index_name, &slow); |
969 | 974 |
970 GenerateKeyedLoadReceiverCheck( | 975 GenerateKeyedLoadReceiverCheck( |
971 masm, receiver, r2, r3, Map::kHasNamedInterceptor, &slow); | 976 masm, receiver, r2, r3, Map::kHasNamedInterceptor, &slow); |
972 | 977 |
973 // If the receiver is a fast-case object, check the keyed lookup | 978 // If the receiver is a fast-case object, check the keyed lookup |
974 // cache. Otherwise probe the dictionary. | 979 // cache. Otherwise probe the dictionary. |
975 __ ldr(r3, FieldMemOperand(r1, JSObject::kPropertiesOffset)); | 980 __ ldr(r3, FieldMemOperand(r1, JSObject::kPropertiesOffset)); |
976 __ ldr(r4, FieldMemOperand(r3, HeapObject::kMapOffset)); | 981 __ ldr(r4, FieldMemOperand(r3, HeapObject::kMapOffset)); |
977 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); | 982 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); |
978 __ cmp(r4, ip); | 983 __ cmp(r4, ip); |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1069 // r3: elements | 1074 // r3: elements |
1070 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); | 1075 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); |
1071 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset)); | 1076 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset)); |
1072 GenerateGlobalInstanceTypeCheck(masm, r2, &slow); | 1077 GenerateGlobalInstanceTypeCheck(masm, r2, &slow); |
1073 // Load the property to r0. | 1078 // Load the property to r0. |
1074 GenerateDictionaryLoad(masm, &slow, r3, r0, r0, r2, r4); | 1079 GenerateDictionaryLoad(masm, &slow, r3, r0, r0, r2, r4); |
1075 __ IncrementCounter( | 1080 __ IncrementCounter( |
1076 isolate->counters()->keyed_load_generic_symbol(), 1, r2, r3); | 1081 isolate->counters()->keyed_load_generic_symbol(), 1, r2, r3); |
1077 __ Ret(); | 1082 __ Ret(); |
1078 | 1083 |
1079 __ bind(&index_string); | 1084 __ bind(&index_name); |
1080 __ IndexFromHash(r3, key); | 1085 __ IndexFromHash(r3, key); |
1081 // Now jump to the place where smi keys are handled. | 1086 // Now jump to the place where smi keys are handled. |
1082 __ jmp(&index_smi); | 1087 __ jmp(&index_smi); |
1083 } | 1088 } |
1084 | 1089 |
1085 | 1090 |
1086 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { | 1091 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { |
1087 // ---------- S t a t e -------------- | 1092 // ---------- S t a t e -------------- |
1088 // -- lr : return address | 1093 // -- lr : return address |
1089 // -- r0 : key (index) | 1094 // -- r0 : key (index) |
(...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1540 | 1545 |
1541 void StoreIC::GenerateNormal(MacroAssembler* masm) { | 1546 void StoreIC::GenerateNormal(MacroAssembler* masm) { |
1542 // ----------- S t a t e ------------- | 1547 // ----------- S t a t e ------------- |
1543 // -- r0 : value | 1548 // -- r0 : value |
1544 // -- r1 : receiver | 1549 // -- r1 : receiver |
1545 // -- r2 : name | 1550 // -- r2 : name |
1546 // -- lr : return address | 1551 // -- lr : return address |
1547 // ----------------------------------- | 1552 // ----------------------------------- |
1548 Label miss; | 1553 Label miss; |
1549 | 1554 |
1550 GenerateStringDictionaryReceiverCheck(masm, r1, r3, r4, r5, &miss); | 1555 GenerateNameDictionaryReceiverCheck(masm, r1, r3, r4, r5, &miss); |
1551 | 1556 |
1552 GenerateDictionaryStore(masm, &miss, r3, r2, r0, r4, r5); | 1557 GenerateDictionaryStore(masm, &miss, r3, r2, r0, r4, r5); |
1553 Counters* counters = masm->isolate()->counters(); | 1558 Counters* counters = masm->isolate()->counters(); |
1554 __ IncrementCounter(counters->store_normal_hit(), | 1559 __ IncrementCounter(counters->store_normal_hit(), |
1555 1, r4, r5); | 1560 1, r4, r5); |
1556 __ Ret(); | 1561 __ Ret(); |
1557 | 1562 |
1558 __ bind(&miss); | 1563 __ bind(&miss); |
1559 __ IncrementCounter(counters->store_normal_miss(), 1, r4, r5); | 1564 __ IncrementCounter(counters->store_normal_miss(), 1, r4, r5); |
1560 GenerateMiss(masm); | 1565 GenerateMiss(masm); |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1676 } else { | 1681 } else { |
1677 ASSERT(Assembler::GetCondition(branch_instr) == ne); | 1682 ASSERT(Assembler::GetCondition(branch_instr) == ne); |
1678 patcher.EmitCondition(eq); | 1683 patcher.EmitCondition(eq); |
1679 } | 1684 } |
1680 } | 1685 } |
1681 | 1686 |
1682 | 1687 |
1683 } } // namespace v8::internal | 1688 } } // namespace v8::internal |
1684 | 1689 |
1685 #endif // V8_TARGET_ARCH_ARM | 1690 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |