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

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

Issue 7348008: Merge up to 8597 to experimental/gc from the bleeding edge. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: '' Created 9 years, 5 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/arm/full-codegen-arm.cc ('k') | src/arm/lithium-arm.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 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 __ tst(receiver, Operand(kSmiTagMask)); 82 __ JumpIfSmi(receiver, miss);
83 __ b(eq, miss);
84 83
85 // Check that the receiver is a valid JS object. 84 // Check that the receiver is a valid JS object.
86 __ CompareObjectType(receiver, t0, t1, FIRST_JS_OBJECT_TYPE); 85 __ CompareObjectType(receiver, t0, t1, FIRST_SPEC_OBJECT_TYPE);
87 __ b(lt, miss); 86 __ b(lt, miss);
88 87
89 // If this assert fails, we have to check upper bound too. 88 // If this assert fails, we have to check upper bound too.
90 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 89 STATIC_ASSERT(LAST_TYPE == LAST_SPEC_OBJECT_TYPE);
91 90
92 GenerateGlobalInstanceTypeCheck(masm, t1, miss); 91 GenerateGlobalInstanceTypeCheck(masm, t1, miss);
93 92
94 // Check that the global object does not require access checks. 93 // Check that the global object does not require access checks.
95 __ ldrb(t1, FieldMemOperand(t0, Map::kBitFieldOffset)); 94 __ ldrb(t1, FieldMemOperand(t0, Map::kBitFieldOffset));
96 __ tst(t1, Operand((1 << Map::kIsAccessCheckNeeded) | 95 __ tst(t1, Operand((1 << Map::kIsAccessCheckNeeded) |
97 (1 << Map::kHasNamedInterceptor))); 96 (1 << Map::kHasNamedInterceptor)));
98 __ b(ne, miss); 97 __ b(ne, miss);
99 98
100 __ ldr(elements, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 99 __ ldr(elements, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 __ add(scratch2, scratch2, Operand(kValueOffset - kHeapObjectTag)); 206 __ add(scratch2, scratch2, Operand(kValueOffset - kHeapObjectTag));
208 __ str(value, MemOperand(scratch2)); 207 __ str(value, MemOperand(scratch2));
209 208
210 // Update the write barrier. Make sure not to clobber the value. 209 // Update the write barrier. Make sure not to clobber the value.
211 __ mov(scratch1, value); 210 __ mov(scratch1, value);
212 __ RecordWrite( 211 __ RecordWrite(
213 elements, scratch2, scratch1, kLRHasNotBeenSaved, kDontSaveFPRegs); 212 elements, scratch2, scratch1, kLRHasNotBeenSaved, kDontSaveFPRegs);
214 } 213 }
215 214
216 215
217 static void GenerateNumberDictionaryLoad(MacroAssembler* masm,
218 Label* miss,
219 Register elements,
220 Register key,
221 Register result,
222 Register t0,
223 Register t1,
224 Register t2) {
225 // Register use:
226 //
227 // elements - holds the slow-case elements of the receiver on entry.
228 // Unchanged unless 'result' is the same register.
229 //
230 // key - holds the smi key on entry.
231 // Unchanged unless 'result' is the same register.
232 //
233 // result - holds the result on exit if the load succeeded.
234 // Allowed to be the same as 'key' or 'result'.
235 // Unchanged on bailout so 'key' or 'result' can be used
236 // in further computation.
237 //
238 // Scratch registers:
239 //
240 // t0 - holds the untagged key on entry and holds the hash once computed.
241 //
242 // t1 - used to hold the capacity mask of the dictionary
243 //
244 // t2 - used for the index into the dictionary.
245 Label done;
246
247 // Compute the hash code from the untagged key. This must be kept in sync
248 // with ComputeIntegerHash in utils.h.
249 //
250 // hash = ~hash + (hash << 15);
251 __ mvn(t1, Operand(t0));
252 __ add(t0, t1, Operand(t0, LSL, 15));
253 // hash = hash ^ (hash >> 12);
254 __ eor(t0, t0, Operand(t0, LSR, 12));
255 // hash = hash + (hash << 2);
256 __ add(t0, t0, Operand(t0, LSL, 2));
257 // hash = hash ^ (hash >> 4);
258 __ eor(t0, t0, Operand(t0, LSR, 4));
259 // hash = hash * 2057;
260 __ mov(t1, Operand(2057));
261 __ mul(t0, t0, t1);
262 // hash = hash ^ (hash >> 16);
263 __ eor(t0, t0, Operand(t0, LSR, 16));
264
265 // Compute the capacity mask.
266 __ ldr(t1, FieldMemOperand(elements, NumberDictionary::kCapacityOffset));
267 __ mov(t1, Operand(t1, ASR, kSmiTagSize)); // convert smi to int
268 __ sub(t1, t1, Operand(1));
269
270 // Generate an unrolled loop that performs a few probes before giving up.
271 static const int kProbes = 4;
272 for (int i = 0; i < kProbes; i++) {
273 // Use t2 for index calculations and keep the hash intact in t0.
274 __ mov(t2, t0);
275 // Compute the masked index: (hash + i + i * i) & mask.
276 if (i > 0) {
277 __ add(t2, t2, Operand(NumberDictionary::GetProbeOffset(i)));
278 }
279 __ and_(t2, t2, Operand(t1));
280
281 // Scale the index by multiplying by the element size.
282 ASSERT(NumberDictionary::kEntrySize == 3);
283 __ add(t2, t2, Operand(t2, LSL, 1)); // t2 = t2 * 3
284
285 // Check if the key is identical to the name.
286 __ add(t2, elements, Operand(t2, LSL, kPointerSizeLog2));
287 __ ldr(ip, FieldMemOperand(t2, NumberDictionary::kElementsStartOffset));
288 __ cmp(key, Operand(ip));
289 if (i != kProbes - 1) {
290 __ b(eq, &done);
291 } else {
292 __ b(ne, miss);
293 }
294 }
295
296 __ bind(&done);
297 // Check that the value is a normal property.
298 // t2: elements + (index * kPointerSize)
299 const int kDetailsOffset =
300 NumberDictionary::kElementsStartOffset + 2 * kPointerSize;
301 __ ldr(t1, FieldMemOperand(t2, kDetailsOffset));
302 __ tst(t1, Operand(Smi::FromInt(PropertyDetails::TypeField::mask())));
303 __ b(ne, miss);
304
305 // Get the value at the masked, scaled index and return.
306 const int kValueOffset =
307 NumberDictionary::kElementsStartOffset + kPointerSize;
308 __ ldr(result, FieldMemOperand(t2, kValueOffset));
309 }
310
311
312 void LoadIC::GenerateArrayLength(MacroAssembler* masm) { 216 void LoadIC::GenerateArrayLength(MacroAssembler* masm) {
313 // ----------- S t a t e ------------- 217 // ----------- S t a t e -------------
314 // -- r2 : name 218 // -- r2 : name
315 // -- lr : return address 219 // -- lr : return address
316 // -- r0 : receiver 220 // -- r0 : receiver
317 // -- sp[0] : receiver 221 // -- sp[0] : receiver
318 // ----------------------------------- 222 // -----------------------------------
319 Label miss; 223 Label miss;
320 224
321 StubCompiler::GenerateLoadArrayLength(masm, r0, r3, &miss); 225 StubCompiler::GenerateLoadArrayLength(masm, r0, r3, &miss);
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
497 argc); 401 argc);
498 Isolate::Current()->stub_cache()->GenerateProbe( 402 Isolate::Current()->stub_cache()->GenerateProbe(
499 masm, flags, r1, r2, r3, r4, r5); 403 masm, flags, r1, r2, r3, r4, r5);
500 404
501 // If the stub cache probing failed, the receiver might be a value. 405 // If the stub cache probing failed, the receiver might be a value.
502 // For value objects, we use the map of the prototype objects for 406 // For value objects, we use the map of the prototype objects for
503 // the corresponding JSValue for the cache and that is what we need 407 // the corresponding JSValue for the cache and that is what we need
504 // to probe. 408 // to probe.
505 // 409 //
506 // Check for number. 410 // Check for number.
507 __ tst(r1, Operand(kSmiTagMask)); 411 __ JumpIfSmi(r1, &number);
508 __ b(eq, &number);
509 __ CompareObjectType(r1, r3, r3, HEAP_NUMBER_TYPE); 412 __ CompareObjectType(r1, r3, r3, HEAP_NUMBER_TYPE);
510 __ b(ne, &non_number); 413 __ b(ne, &non_number);
511 __ bind(&number); 414 __ bind(&number);
512 StubCompiler::GenerateLoadGlobalFunctionPrototype( 415 StubCompiler::GenerateLoadGlobalFunctionPrototype(
513 masm, Context::NUMBER_FUNCTION_INDEX, r1); 416 masm, Context::NUMBER_FUNCTION_INDEX, r1);
514 __ b(&probe); 417 __ b(&probe);
515 418
516 // Check for string. 419 // Check for string.
517 __ bind(&non_number); 420 __ bind(&non_number);
518 __ cmp(r3, Operand(FIRST_NONSTRING_TYPE)); 421 __ cmp(r3, Operand(FIRST_NONSTRING_TYPE));
(...skipping 23 matching lines...) Expand all
542 } 445 }
543 446
544 447
545 static void GenerateFunctionTailCall(MacroAssembler* masm, 448 static void GenerateFunctionTailCall(MacroAssembler* masm,
546 int argc, 449 int argc,
547 Label* miss, 450 Label* miss,
548 Register scratch) { 451 Register scratch) {
549 // r1: function 452 // r1: function
550 453
551 // Check that the value isn't a smi. 454 // Check that the value isn't a smi.
552 __ tst(r1, Operand(kSmiTagMask)); 455 __ JumpIfSmi(r1, miss);
553 __ b(eq, miss);
554 456
555 // Check that the value is a JSFunction. 457 // Check that the value is a JSFunction.
556 __ CompareObjectType(r1, scratch, scratch, JS_FUNCTION_TYPE); 458 __ CompareObjectType(r1, scratch, scratch, JS_FUNCTION_TYPE);
557 __ b(ne, miss); 459 __ b(ne, miss);
558 460
559 // Invoke the function. 461 // Invoke the function.
560 ParameterCount actual(argc); 462 ParameterCount actual(argc);
561 __ InvokeFunction(r1, actual, JUMP_FUNCTION); 463 __ InvokeFunction(r1, actual, JUMP_FUNCTION,
464 NullCallWrapper(), CALL_AS_METHOD);
562 } 465 }
563 466
564 467
565 static void GenerateCallNormal(MacroAssembler* masm, int argc) { 468 static void GenerateCallNormal(MacroAssembler* masm, int argc) {
566 // ----------- S t a t e ------------- 469 // ----------- S t a t e -------------
567 // -- r2 : name 470 // -- r2 : name
568 // -- lr : return address 471 // -- lr : return address
569 // ----------------------------------- 472 // -----------------------------------
570 Label miss; 473 Label miss;
571 474
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
617 520
618 // Move result to r1 and leave the internal frame. 521 // Move result to r1 and leave the internal frame.
619 __ mov(r1, Operand(r0)); 522 __ mov(r1, Operand(r0));
620 __ LeaveInternalFrame(); 523 __ LeaveInternalFrame();
621 524
622 // Check if the receiver is a global object of some sort. 525 // Check if the receiver is a global object of some sort.
623 // This can happen only for regular CallIC but not KeyedCallIC. 526 // This can happen only for regular CallIC but not KeyedCallIC.
624 if (id == IC::kCallIC_Miss) { 527 if (id == IC::kCallIC_Miss) {
625 Label invoke, global; 528 Label invoke, global;
626 __ ldr(r2, MemOperand(sp, argc * kPointerSize)); // receiver 529 __ ldr(r2, MemOperand(sp, argc * kPointerSize)); // receiver
627 __ tst(r2, Operand(kSmiTagMask)); 530 __ JumpIfSmi(r2, &invoke);
628 __ b(eq, &invoke);
629 __ CompareObjectType(r2, r3, r3, JS_GLOBAL_OBJECT_TYPE); 531 __ CompareObjectType(r2, r3, r3, JS_GLOBAL_OBJECT_TYPE);
630 __ b(eq, &global); 532 __ b(eq, &global);
631 __ cmp(r3, Operand(JS_BUILTINS_OBJECT_TYPE)); 533 __ cmp(r3, Operand(JS_BUILTINS_OBJECT_TYPE));
632 __ b(ne, &invoke); 534 __ b(ne, &invoke);
633 535
634 // Patch the receiver on the stack. 536 // Patch the receiver on the stack.
635 __ bind(&global); 537 __ bind(&global);
636 __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset)); 538 __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset));
637 __ str(r2, MemOperand(sp, argc * kPointerSize)); 539 __ str(r2, MemOperand(sp, argc * kPointerSize));
638 __ bind(&invoke); 540 __ bind(&invoke);
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
735 __ bind(&check_number_dictionary); 637 __ bind(&check_number_dictionary);
736 // r2: key 638 // r2: key
737 // r3: elements map 639 // r3: elements map
738 // r4: elements 640 // r4: elements
739 // Check whether the elements is a number dictionary. 641 // Check whether the elements is a number dictionary.
740 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); 642 __ LoadRoot(ip, Heap::kHashTableMapRootIndex);
741 __ cmp(r3, ip); 643 __ cmp(r3, ip);
742 __ b(ne, &slow_load); 644 __ b(ne, &slow_load);
743 __ mov(r0, Operand(r2, ASR, kSmiTagSize)); 645 __ mov(r0, Operand(r2, ASR, kSmiTagSize));
744 // r0: untagged index 646 // r0: untagged index
745 GenerateNumberDictionaryLoad(masm, &slow_load, r4, r2, r1, r0, r3, r5); 647 __ LoadFromNumberDictionary(&slow_load, r4, r2, r1, r0, r3, r5);
746 __ IncrementCounter(counters->keyed_call_generic_smi_dict(), 1, r0, r3); 648 __ IncrementCounter(counters->keyed_call_generic_smi_dict(), 1, r0, r3);
747 __ jmp(&do_call); 649 __ jmp(&do_call);
748 650
749 __ bind(&slow_load); 651 __ bind(&slow_load);
750 // This branch is taken when calling KeyedCallIC_Miss is neither required 652 // This branch is taken when calling KeyedCallIC_Miss is neither required
751 // nor beneficial. 653 // nor beneficial.
752 __ IncrementCounter(counters->keyed_call_generic_slow_load(), 1, r0, r3); 654 __ IncrementCounter(counters->keyed_call_generic_slow_load(), 1, r0, r3);
753 __ EnterInternalFrame(); 655 __ EnterInternalFrame();
754 __ push(r2); // save the key 656 __ push(r2); // save the key
755 __ Push(r1, r2); // pass the receiver and the key 657 __ Push(r1, r2); // pass the receiver and the key
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
805 707
806 708
807 void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { 709 void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) {
808 // ----------- S t a t e ------------- 710 // ----------- S t a t e -------------
809 // -- r2 : name 711 // -- r2 : name
810 // -- lr : return address 712 // -- lr : return address
811 // ----------------------------------- 713 // -----------------------------------
812 714
813 // Check if the name is a string. 715 // Check if the name is a string.
814 Label miss; 716 Label miss;
815 __ tst(r2, Operand(kSmiTagMask)); 717 __ JumpIfSmi(r2, &miss);
816 __ b(eq, &miss);
817 __ IsObjectJSStringType(r2, r0, &miss); 718 __ IsObjectJSStringType(r2, r0, &miss);
818 719
819 GenerateCallNormal(masm, argc); 720 GenerateCallNormal(masm, argc);
820 __ bind(&miss); 721 __ bind(&miss);
821 GenerateMiss(masm, argc); 722 GenerateMiss(masm, argc);
822 } 723 }
823 724
824 725
825 // Defined in ic.cc. 726 // Defined in ic.cc.
826 Object* LoadIC_Miss(Arguments args); 727 Object* LoadIC_Miss(Arguments args);
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
880 __ mov(r3, r0); 781 __ mov(r3, r0);
881 __ Push(r3, r2); 782 __ Push(r3, r2);
882 783
883 // Perform tail call to the entry. 784 // Perform tail call to the entry.
884 ExternalReference ref = 785 ExternalReference ref =
885 ExternalReference(IC_Utility(kLoadIC_Miss), isolate); 786 ExternalReference(IC_Utility(kLoadIC_Miss), isolate);
886 __ TailCallExternalReference(ref, 2, 1); 787 __ TailCallExternalReference(ref, 2, 1);
887 } 788 }
888 789
889 790
791 static MemOperand GenerateMappedArgumentsLookup(MacroAssembler* masm,
792 Register object,
793 Register key,
794 Register scratch1,
795 Register scratch2,
796 Register scratch3,
797 Label* unmapped_case,
798 Label* slow_case) {
799 Heap* heap = masm->isolate()->heap();
800
801 // Check that the receiver is a JSObject. Because of the map check
802 // later, we do not need to check for interceptors or whether it
803 // requires access checks.
804 __ JumpIfSmi(object, slow_case);
805 // Check that the object is some kind of JSObject.
806 __ CompareObjectType(object, scratch1, scratch2, FIRST_JS_RECEIVER_TYPE);
807 __ b(lt, slow_case);
808
809 // Check that the key is a positive smi.
810 __ tst(key, Operand(0x8000001));
811 __ b(ne, slow_case);
812
813 // Load the elements into scratch1 and check its map.
814 Handle<Map> arguments_map(heap->non_strict_arguments_elements_map());
815 __ ldr(scratch1, FieldMemOperand(object, JSObject::kElementsOffset));
816 __ CheckMap(scratch1, scratch2, arguments_map, slow_case, DONT_DO_SMI_CHECK);
817
818 // Check if element is in the range of mapped arguments. If not, jump
819 // to the unmapped lookup with the parameter map in scratch1.
820 __ ldr(scratch2, FieldMemOperand(scratch1, FixedArray::kLengthOffset));
821 __ sub(scratch2, scratch2, Operand(Smi::FromInt(2)));
822 __ cmp(key, Operand(scratch2));
823 __ b(cs, unmapped_case);
824
825 // Load element index and check whether it is the hole.
826 const int kOffset =
827 FixedArray::kHeaderSize + 2 * kPointerSize - kHeapObjectTag;
828
829 __ mov(scratch3, Operand(kPointerSize >> 1));
830 __ mul(scratch3, key, scratch3);
831 __ add(scratch3, scratch3, Operand(kOffset));
832
833 __ ldr(scratch2, MemOperand(scratch1, scratch3));
834 __ LoadRoot(scratch3, Heap::kTheHoleValueRootIndex);
835 __ cmp(scratch2, scratch3);
836 __ b(eq, unmapped_case);
837
838 // Load value from context and return it. We can reuse scratch1 because
839 // we do not jump to the unmapped lookup (which requires the parameter
840 // map in scratch1).
841 __ ldr(scratch1, FieldMemOperand(scratch1, FixedArray::kHeaderSize));
842 __ mov(scratch3, Operand(kPointerSize >> 1));
843 __ mul(scratch3, scratch2, scratch3);
844 __ add(scratch3, scratch3, Operand(Context::kHeaderSize - kHeapObjectTag));
845 return MemOperand(scratch1, scratch3);
846 }
847
848
849 static MemOperand GenerateUnmappedArgumentsLookup(MacroAssembler* masm,
850 Register key,
851 Register parameter_map,
852 Register scratch,
853 Label* slow_case) {
854 // Element is in arguments backing store, which is referenced by the
855 // second element of the parameter_map. The parameter_map register
856 // must be loaded with the parameter map of the arguments object and is
857 // overwritten.
858 const int kBackingStoreOffset = FixedArray::kHeaderSize + kPointerSize;
859 Register backing_store = parameter_map;
860 __ ldr(backing_store, FieldMemOperand(parameter_map, kBackingStoreOffset));
861 Handle<Map> fixed_array_map(masm->isolate()->heap()->fixed_array_map());
862 __ CheckMap(backing_store, scratch, fixed_array_map, slow_case,
863 DONT_DO_SMI_CHECK);
864 __ ldr(scratch, FieldMemOperand(backing_store, FixedArray::kLengthOffset));
865 __ cmp(key, Operand(scratch));
866 __ b(cs, slow_case);
867 __ mov(scratch, Operand(kPointerSize >> 1));
868 __ mul(scratch, key, scratch);
869 __ add(scratch,
870 scratch,
871 Operand(FixedArray::kHeaderSize - kHeapObjectTag));
872 return MemOperand(backing_store, scratch);
873 }
874
875
876 void KeyedLoadIC::GenerateNonStrictArguments(MacroAssembler* masm) {
877 // ---------- S t a t e --------------
878 // -- lr : return address
879 // -- r0 : key
880 // -- r1 : receiver
881 // -----------------------------------
882 Label slow, notin;
883 MemOperand mapped_location =
884 GenerateMappedArgumentsLookup(masm, r1, r0, r2, r3, r4, &notin, &slow);
885 __ ldr(r0, mapped_location);
886 __ Ret();
887 __ bind(&notin);
888 // The unmapped lookup expects that the parameter map is in r2.
889 MemOperand unmapped_location =
890 GenerateUnmappedArgumentsLookup(masm, r0, r2, r3, &slow);
891 __ ldr(r2, unmapped_location);
892 __ LoadRoot(r3, Heap::kTheHoleValueRootIndex);
893 __ cmp(r2, r3);
894 __ b(eq, &slow);
895 __ mov(r0, r2);
896 __ Ret();
897 __ bind(&slow);
898 GenerateMiss(masm, false);
899 }
900
901
902 void KeyedStoreIC::GenerateNonStrictArguments(MacroAssembler* masm) {
903 // ---------- S t a t e --------------
904 // -- r0 : value
905 // -- r1 : key
906 // -- r2 : receiver
907 // -- lr : return address
908 // -----------------------------------
909 Label slow, notin;
910 MemOperand mapped_location =
911 GenerateMappedArgumentsLookup(masm, r2, r1, r3, r4, r5, &notin, &slow);
912 __ str(r0, mapped_location);
913 __ add(r6, r3, r5);
914 __ mov(r9, r0);
915 __ RecordWrite(r3, r6, r9, kLRHasNotBeenSaved, kDontSaveFPRegs);
916 __ Ret();
917 __ bind(&notin);
918 // The unmapped lookup expects that the parameter map is in r3.
919 MemOperand unmapped_location =
920 GenerateUnmappedArgumentsLookup(masm, r1, r3, r4, &slow);
921 __ str(r0, unmapped_location);
922 __ add(r6, r3, r4);
923 __ mov(r9, r0);
924 __ RecordWrite(r3, r6, r9, kLRHasNotBeenSaved, kDontSaveFPRegs);
925 __ Ret();
926 __ bind(&slow);
927 GenerateMiss(masm, false);
928 }
929
930
931 void KeyedCallIC::GenerateNonStrictArguments(MacroAssembler* masm,
932 int argc) {
933 // ----------- S t a t e -------------
934 // -- r2 : name
935 // -- lr : return address
936 // -----------------------------------
937 Label slow, notin;
938 // Load receiver.
939 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
940 MemOperand mapped_location =
941 GenerateMappedArgumentsLookup(masm, r1, r2, r3, r4, r5, &notin, &slow);
942 __ ldr(r1, mapped_location);
943 GenerateFunctionTailCall(masm, argc, &slow, r3);
944 __ bind(&notin);
945 // The unmapped lookup expects that the parameter map is in r3.
946 MemOperand unmapped_location =
947 GenerateUnmappedArgumentsLookup(masm, r2, r3, r4, &slow);
948 __ ldr(r1, unmapped_location);
949 __ LoadRoot(r3, Heap::kTheHoleValueRootIndex);
950 __ cmp(r1, r3);
951 __ b(eq, &slow);
952 GenerateFunctionTailCall(masm, argc, &slow, r3);
953 __ bind(&slow);
954 GenerateMiss(masm, argc);
955 }
956
957
958 Object* KeyedLoadIC_Miss(Arguments args);
959
960
890 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm, bool force_generic) { 961 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm, bool force_generic) {
891 // ---------- S t a t e -------------- 962 // ---------- S t a t e --------------
892 // -- lr : return address 963 // -- lr : return address
893 // -- r0 : key 964 // -- r0 : key
894 // -- r1 : receiver 965 // -- r1 : receiver
895 // ----------------------------------- 966 // -----------------------------------
896 Isolate* isolate = masm->isolate(); 967 Isolate* isolate = masm->isolate();
897 968
898 __ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, r3, r4); 969 __ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, r3, r4);
899 970
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
937 1008
938 // Check that the key is a smi. 1009 // Check that the key is a smi.
939 __ JumpIfNotSmi(key, &check_string); 1010 __ JumpIfNotSmi(key, &check_string);
940 __ bind(&index_smi); 1011 __ bind(&index_smi);
941 // Now the key is known to be a smi. This place is also jumped to from below 1012 // Now the key is known to be a smi. This place is also jumped to from below
942 // where a numeric string is converted to a smi. 1013 // where a numeric string is converted to a smi.
943 1014
944 GenerateKeyedLoadReceiverCheck( 1015 GenerateKeyedLoadReceiverCheck(
945 masm, receiver, r2, r3, Map::kHasIndexedInterceptor, &slow); 1016 masm, receiver, r2, r3, Map::kHasIndexedInterceptor, &slow);
946 1017
947 // Check the "has fast elements" bit in the receiver's map which is 1018 // Check the receiver's map to see if it has fast elements.
948 // now in r2. 1019 __ CheckFastElements(r2, r3, &check_number_dictionary);
949 __ ldrb(r3, FieldMemOperand(r2, Map::kBitField2Offset));
950 __ tst(r3, Operand(1 << Map::kHasFastElements));
951 __ b(eq, &check_number_dictionary);
952 1020
953 GenerateFastArrayLoad( 1021 GenerateFastArrayLoad(
954 masm, receiver, key, r4, r3, r2, r0, NULL, &slow); 1022 masm, receiver, key, r4, r3, r2, r0, NULL, &slow);
955 __ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, r2, r3); 1023 __ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, r2, r3);
956 __ Ret(); 1024 __ Ret();
957 1025
958 __ bind(&check_number_dictionary); 1026 __ bind(&check_number_dictionary);
959 __ ldr(r4, FieldMemOperand(receiver, JSObject::kElementsOffset)); 1027 __ ldr(r4, FieldMemOperand(receiver, JSObject::kElementsOffset));
960 __ ldr(r3, FieldMemOperand(r4, JSObject::kMapOffset)); 1028 __ ldr(r3, FieldMemOperand(r4, JSObject::kMapOffset));
961 1029
962 // Check whether the elements is a number dictionary. 1030 // Check whether the elements is a number dictionary.
963 // r0: key 1031 // r0: key
964 // r3: elements map 1032 // r3: elements map
965 // r4: elements 1033 // r4: elements
966 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); 1034 __ LoadRoot(ip, Heap::kHashTableMapRootIndex);
967 __ cmp(r3, ip); 1035 __ cmp(r3, ip);
968 __ b(ne, &slow); 1036 __ b(ne, &slow);
969 __ mov(r2, Operand(r0, ASR, kSmiTagSize)); 1037 __ mov(r2, Operand(r0, ASR, kSmiTagSize));
970 GenerateNumberDictionaryLoad(masm, &slow, r4, r0, r0, r2, r3, r5); 1038 __ LoadFromNumberDictionary(&slow, r4, r0, r0, r2, r3, r5);
971 __ Ret(); 1039 __ Ret();
972 1040
973 // Slow case, key and receiver still in r0 and r1. 1041 // Slow case, key and receiver still in r0 and r1.
974 __ bind(&slow); 1042 __ bind(&slow);
975 __ IncrementCounter(isolate->counters()->keyed_load_generic_slow(), 1043 __ IncrementCounter(isolate->counters()->keyed_load_generic_slow(),
976 1, r2, r3); 1044 1, r2, r3);
977 GenerateRuntimeGetProperty(masm); 1045 GenerateRuntimeGetProperty(masm);
978 1046
979 __ bind(&check_string); 1047 __ bind(&check_string);
980 GenerateKeyStringCheck(masm, key, r2, r3, &index_string, &slow); 1048 GenerateKeyStringCheck(masm, key, r2, r3, &index_string, &slow);
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
1207 Label slow, fast, array, extra; 1275 Label slow, fast, array, extra;
1208 1276
1209 // Register usage. 1277 // Register usage.
1210 Register value = r0; 1278 Register value = r0;
1211 Register key = r1; 1279 Register key = r1;
1212 Register receiver = r2; 1280 Register receiver = r2;
1213 Register elements = r3; // Elements array of the receiver. 1281 Register elements = r3; // Elements array of the receiver.
1214 // r4 and r5 are used as general scratch registers. 1282 // r4 and r5 are used as general scratch registers.
1215 1283
1216 // Check that the key is a smi. 1284 // Check that the key is a smi.
1217 __ tst(key, Operand(kSmiTagMask)); 1285 __ JumpIfNotSmi(key, &slow);
1218 __ b(ne, &slow);
1219 // Check that the object isn't a smi. 1286 // Check that the object isn't a smi.
1220 __ tst(receiver, Operand(kSmiTagMask)); 1287 __ JumpIfSmi(receiver, &slow);
1221 __ b(eq, &slow);
1222 // Get the map of the object. 1288 // Get the map of the object.
1223 __ ldr(r4, FieldMemOperand(receiver, HeapObject::kMapOffset)); 1289 __ ldr(r4, FieldMemOperand(receiver, HeapObject::kMapOffset));
1224 // Check that the receiver does not require access checks. We need 1290 // Check that the receiver does not require access checks. We need
1225 // to do this because this generic stub does not perform map checks. 1291 // to do this because this generic stub does not perform map checks.
1226 __ ldrb(ip, FieldMemOperand(r4, Map::kBitFieldOffset)); 1292 __ ldrb(ip, FieldMemOperand(r4, Map::kBitFieldOffset));
1227 __ tst(ip, Operand(1 << Map::kIsAccessCheckNeeded)); 1293 __ tst(ip, Operand(1 << Map::kIsAccessCheckNeeded));
1228 __ b(ne, &slow); 1294 __ b(ne, &slow);
1229 // Check if the object is a JS array or not. 1295 // Check if the object is a JS array or not.
1230 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); 1296 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset));
1231 __ cmp(r4, Operand(JS_ARRAY_TYPE)); 1297 __ cmp(r4, Operand(JS_ARRAY_TYPE));
1232 __ b(eq, &array); 1298 __ b(eq, &array);
1233 // Check that the object is some kind of JS object. 1299 // Check that the object is some kind of JSObject.
1234 __ cmp(r4, Operand(FIRST_JS_OBJECT_TYPE)); 1300 __ cmp(r4, Operand(FIRST_JS_RECEIVER_TYPE));
1235 __ b(lt, &slow); 1301 __ b(lt, &slow);
1302 __ cmp(r4, Operand(JS_PROXY_TYPE));
1303 __ b(eq, &slow);
1304 __ cmp(r4, Operand(JS_FUNCTION_PROXY_TYPE));
1305 __ b(eq, &slow);
1236 1306
1237 // Object case: Check key against length in the elements array. 1307 // Object case: Check key against length in the elements array.
1238 __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); 1308 __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
1239 // Check that the object is in fast mode and writable. 1309 // Check that the object is in fast mode and writable.
1240 __ ldr(r4, FieldMemOperand(elements, HeapObject::kMapOffset)); 1310 __ ldr(r4, FieldMemOperand(elements, HeapObject::kMapOffset));
1241 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); 1311 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
1242 __ cmp(r4, ip); 1312 __ cmp(r4, ip);
1243 __ b(ne, &slow); 1313 __ b(ne, &slow);
1244 // Check array bounds. Both the key and the length of FixedArray are smis. 1314 // Check array bounds. Both the key and the length of FixedArray are smis.
1245 __ ldr(ip, FieldMemOperand(elements, FixedArray::kLengthOffset)); 1315 __ ldr(ip, FieldMemOperand(elements, FixedArray::kLengthOffset));
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
1563 Register reg = Assembler::GetRn(instr_at_patch); 1633 Register reg = Assembler::GetRn(instr_at_patch);
1564 patcher.masm()->tst(reg, Operand(kSmiTagMask)); 1634 patcher.masm()->tst(reg, Operand(kSmiTagMask));
1565 patcher.EmitCondition(eq); 1635 patcher.EmitCondition(eq);
1566 } 1636 }
1567 } 1637 }
1568 1638
1569 1639
1570 } } // namespace v8::internal 1640 } } // namespace v8::internal
1571 1641
1572 #endif // V8_TARGET_ARCH_ARM 1642 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/full-codegen-arm.cc ('k') | src/arm/lithium-arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698