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

Side by Side Diff: src/x64/stub-cache-x64.cc

Issue 7060010: Merge bleeding edge into the GC branch up to 7948. The asserts (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: Created 9 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/x64/simulator-x64.h ('k') | src/zone.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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 75
76 __ bind(&miss); 76 __ bind(&miss);
77 } 77 }
78 78
79 79
80 // Helper function used to check that the dictionary doesn't contain 80 // Helper function used to check that the dictionary doesn't contain
81 // the property. This function may return false negatives, so miss_label 81 // the property. This function may return false negatives, so miss_label
82 // must always call a backup property check that is complete. 82 // must always call a backup property check that is complete.
83 // This function is safe to call if the receiver has fast properties. 83 // This function is safe to call if the receiver has fast properties.
84 // Name must be a symbol and receiver must be a heap object. 84 // Name must be a symbol and receiver must be a heap object.
85 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm, 85 MUST_USE_RESULT static MaybeObject* GenerateDictionaryNegativeLookup(
86 Label* miss_label, 86 MacroAssembler* masm,
87 Register receiver, 87 Label* miss_label,
88 String* name, 88 Register receiver,
89 Register r0, 89 String* name,
90 Register r1) { 90 Register r0,
91 Register r1) {
91 ASSERT(name->IsSymbol()); 92 ASSERT(name->IsSymbol());
92 Counters* counters = masm->isolate()->counters(); 93 Counters* counters = masm->isolate()->counters();
93 __ IncrementCounter(counters->negative_lookups(), 1); 94 __ IncrementCounter(counters->negative_lookups(), 1);
94 __ IncrementCounter(counters->negative_lookups_miss(), 1); 95 __ IncrementCounter(counters->negative_lookups_miss(), 1);
95 96
96 Label done;
97 __ movq(r0, FieldOperand(receiver, HeapObject::kMapOffset)); 97 __ movq(r0, FieldOperand(receiver, HeapObject::kMapOffset));
98 98
99 const int kInterceptorOrAccessCheckNeededMask = 99 const int kInterceptorOrAccessCheckNeededMask =
100 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); 100 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded);
101 101
102 // Bail out if the receiver has a named interceptor or requires access checks. 102 // Bail out if the receiver has a named interceptor or requires access checks.
103 __ testb(FieldOperand(r0, Map::kBitFieldOffset), 103 __ testb(FieldOperand(r0, Map::kBitFieldOffset),
104 Immediate(kInterceptorOrAccessCheckNeededMask)); 104 Immediate(kInterceptorOrAccessCheckNeededMask));
105 __ j(not_zero, miss_label); 105 __ j(not_zero, miss_label);
106 106
107 // Check that receiver is a JSObject. 107 // Check that receiver is a JSObject.
108 __ CmpInstanceType(r0, FIRST_JS_OBJECT_TYPE); 108 __ CmpInstanceType(r0, FIRST_JS_OBJECT_TYPE);
109 __ j(below, miss_label); 109 __ j(below, miss_label);
110 110
111 // Load properties array. 111 // Load properties array.
112 Register properties = r0; 112 Register properties = r0;
113 __ movq(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); 113 __ movq(properties, FieldOperand(receiver, JSObject::kPropertiesOffset));
114 114
115 // Check that the properties array is a dictionary. 115 // Check that the properties array is a dictionary.
116 __ CompareRoot(FieldOperand(properties, HeapObject::kMapOffset), 116 __ CompareRoot(FieldOperand(properties, HeapObject::kMapOffset),
117 Heap::kHashTableMapRootIndex); 117 Heap::kHashTableMapRootIndex);
118 __ j(not_equal, miss_label); 118 __ j(not_equal, miss_label);
119 119
120 // Compute the capacity mask. 120 Label done;
121 const int kCapacityOffset = 121 MaybeObject* result = StringDictionaryLookupStub::GenerateNegativeLookup(
122 StringDictionary::kHeaderSize + 122 masm,
123 StringDictionary::kCapacityIndex * kPointerSize; 123 miss_label,
124 124 &done,
125 // Generate an unrolled loop that performs a few probes before 125 properties,
126 // giving up. 126 name,
127 static const int kProbes = 4; 127 r1);
128 const int kElementsStartOffset = 128 if (result->IsFailure()) return result;
129 StringDictionary::kHeaderSize +
130 StringDictionary::kElementsStartIndex * kPointerSize;
131
132 // If names of slots in range from 1 to kProbes - 1 for the hash value are
133 // not equal to the name and kProbes-th slot is not used (its name is the
134 // undefined value), it guarantees the hash table doesn't contain the
135 // property. It's true even if some slots represent deleted properties
136 // (their names are the null value).
137 for (int i = 0; i < kProbes; i++) {
138 // r0 points to properties hash.
139 // Compute the masked index: (hash + i + i * i) & mask.
140 Register index = r1;
141 // Capacity is smi 2^n.
142 __ SmiToInteger32(index, FieldOperand(properties, kCapacityOffset));
143 __ decl(index);
144 __ and_(index,
145 Immediate(name->Hash() + StringDictionary::GetProbeOffset(i)));
146
147 // Scale the index by multiplying by the entry size.
148 ASSERT(StringDictionary::kEntrySize == 3);
149 __ lea(index, Operand(index, index, times_2, 0)); // index *= 3.
150
151 Register entity_name = r1;
152 // Having undefined at this place means the name is not contained.
153 ASSERT_EQ(kSmiTagSize, 1);
154 __ movq(entity_name, Operand(properties, index, times_pointer_size,
155 kElementsStartOffset - kHeapObjectTag));
156 __ Cmp(entity_name, masm->isolate()->factory()->undefined_value());
157 // __ jmp(miss_label);
158 if (i != kProbes - 1) {
159 __ j(equal, &done);
160
161 // Stop if found the property.
162 __ Cmp(entity_name, Handle<String>(name));
163 __ j(equal, miss_label);
164
165 // Check if the entry name is not a symbol.
166 __ movq(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset));
167 __ testb(FieldOperand(entity_name, Map::kInstanceTypeOffset),
168 Immediate(kIsSymbolMask));
169 __ j(zero, miss_label);
170 } else {
171 // Give up probing if still not found the undefined value.
172 __ j(not_equal, miss_label);
173 }
174 }
175 129
176 __ bind(&done); 130 __ bind(&done);
177 __ DecrementCounter(counters->negative_lookups_miss(), 1); 131 __ DecrementCounter(counters->negative_lookups_miss(), 1);
132
133 return result;
178 } 134 }
179 135
180 136
181 void StubCache::GenerateProbe(MacroAssembler* masm, 137 void StubCache::GenerateProbe(MacroAssembler* masm,
182 Code::Flags flags, 138 Code::Flags flags,
183 Register receiver, 139 Register receiver,
184 Register name, 140 Register name,
185 Register scratch, 141 Register scratch,
186 Register extra, 142 Register extra,
187 Register extra2) { 143 Register extra2) {
(...skipping 552 matching lines...) Expand 10 before | Expand all | Expand 10 after
740 code = masm->isolate()->builtins()->builtin(Builtins::kLoadIC_Miss); 696 code = masm->isolate()->builtins()->builtin(Builtins::kLoadIC_Miss);
741 } else { 697 } else {
742 code = masm->isolate()->builtins()->builtin(Builtins::kKeyedLoadIC_Miss); 698 code = masm->isolate()->builtins()->builtin(Builtins::kKeyedLoadIC_Miss);
743 } 699 }
744 700
745 Handle<Code> ic(code); 701 Handle<Code> ic(code);
746 __ Jump(ic, RelocInfo::CODE_TARGET); 702 __ Jump(ic, RelocInfo::CODE_TARGET);
747 } 703 }
748 704
749 705
706 void StubCompiler::GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm) {
707 Code* code = masm->isolate()->builtins()->builtin(
708 Builtins::kKeyedLoadIC_MissForceGeneric);
709 Handle<Code> ic(code);
710 __ Jump(ic, RelocInfo::CODE_TARGET);
711 }
712
713
750 // Both name_reg and receiver_reg are preserved on jumps to miss_label, 714 // Both name_reg and receiver_reg are preserved on jumps to miss_label,
751 // but may be destroyed if store is successful. 715 // but may be destroyed if store is successful.
752 void StubCompiler::GenerateStoreField(MacroAssembler* masm, 716 void StubCompiler::GenerateStoreField(MacroAssembler* masm,
753 JSObject* object, 717 JSObject* object,
754 int index, 718 int index,
755 Map* transition, 719 Map* transition,
756 Register receiver_reg, 720 Register receiver_reg,
757 Register name_reg, 721 Register name_reg,
758 Register scratch, 722 Register scratch,
759 Label* miss_label) { 723 Label* miss_label) {
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
900 if (lookup_result->IsFailure()) { 864 if (lookup_result->IsFailure()) {
901 set_failure(Failure::cast(lookup_result)); 865 set_failure(Failure::cast(lookup_result));
902 return reg; 866 return reg;
903 } else { 867 } else {
904 name = String::cast(lookup_result->ToObjectUnchecked()); 868 name = String::cast(lookup_result->ToObjectUnchecked());
905 } 869 }
906 } 870 }
907 ASSERT(current->property_dictionary()->FindEntry(name) == 871 ASSERT(current->property_dictionary()->FindEntry(name) ==
908 StringDictionary::kNotFound); 872 StringDictionary::kNotFound);
909 873
910 GenerateDictionaryNegativeLookup(masm(), 874 MaybeObject* negative_lookup = GenerateDictionaryNegativeLookup(masm(),
911 miss, 875 miss,
912 reg, 876 reg,
913 name, 877 name,
914 scratch1, 878 scratch1,
915 scratch2); 879 scratch2);
880 if (negative_lookup->IsFailure()) {
881 set_failure(Failure::cast(negative_lookup));
882 return reg;
883 }
884
916 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); 885 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
917 reg = holder_reg; // from now the object is in holder_reg 886 reg = holder_reg; // from now the object is in holder_reg
918 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); 887 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
919 } else if (heap()->InNewSpace(prototype)) { 888 } else if (heap()->InNewSpace(prototype)) {
920 // Get the map of the current object. 889 // Get the map of the current object.
921 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); 890 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
922 __ Cmp(scratch1, Handle<Map>(current->map())); 891 __ Cmp(scratch1, Handle<Map>(current->map()));
923 // Branch on the result of the map check. 892 // Branch on the result of the map check.
924 __ j(not_equal, miss); 893 __ j(not_equal, miss);
925 // Check access rights to the global object. This has to happen 894 // Check access rights to the global object. This has to happen
(...skipping 1011 matching lines...) Expand 10 before | Expand all | Expand 10 after
1937 // This only happens for the most negative smi. 1906 // This only happens for the most negative smi.
1938 Label slow; 1907 Label slow;
1939 __ j(negative, &slow); 1908 __ j(negative, &slow);
1940 1909
1941 // Smi case done. 1910 // Smi case done.
1942 __ Integer32ToSmi(rax, rax); 1911 __ Integer32ToSmi(rax, rax);
1943 __ ret(2 * kPointerSize); 1912 __ ret(2 * kPointerSize);
1944 1913
1945 // Check if the argument is a heap number and load its value. 1914 // Check if the argument is a heap number and load its value.
1946 __ bind(&not_smi); 1915 __ bind(&not_smi);
1947 __ CheckMap(rax, factory()->heap_number_map(), &slow, true); 1916 __ CheckMap(rax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK);
1948 __ movq(rbx, FieldOperand(rax, HeapNumber::kValueOffset)); 1917 __ movq(rbx, FieldOperand(rax, HeapNumber::kValueOffset));
1949 1918
1950 // Check the sign of the argument. If the argument is positive, 1919 // Check the sign of the argument. If the argument is positive,
1951 // just return it. 1920 // just return it.
1952 Label negative_sign; 1921 Label negative_sign;
1953 const int sign_mask_shift = 1922 const int sign_mask_shift =
1954 (HeapNumber::kExponentOffset - HeapNumber::kValueOffset) * kBitsPerByte; 1923 (HeapNumber::kExponentOffset - HeapNumber::kValueOffset) * kBitsPerByte;
1955 __ movq(rdi, static_cast<int64_t>(HeapNumber::kSignMask) << sign_mask_shift, 1924 __ movq(rdi, static_cast<int64_t>(HeapNumber::kSignMask) << sign_mask_shift,
1956 RelocInfo::NONE); 1925 RelocInfo::NONE);
1957 __ testq(rbx, rdi); 1926 __ testq(rbx, rdi);
(...skipping 28 matching lines...) Expand all
1986 Object* object, 1955 Object* object,
1987 JSObject* holder, 1956 JSObject* holder,
1988 JSGlobalPropertyCell* cell, 1957 JSGlobalPropertyCell* cell,
1989 JSFunction* function, 1958 JSFunction* function,
1990 String* name) { 1959 String* name) {
1991 ASSERT(optimization.is_simple_api_call()); 1960 ASSERT(optimization.is_simple_api_call());
1992 // Bail out if object is a global object as we don't want to 1961 // Bail out if object is a global object as we don't want to
1993 // repatch it to global receiver. 1962 // repatch it to global receiver.
1994 if (object->IsGlobalObject()) return heap()->undefined_value(); 1963 if (object->IsGlobalObject()) return heap()->undefined_value();
1995 if (cell != NULL) return heap()->undefined_value(); 1964 if (cell != NULL) return heap()->undefined_value();
1965 if (!object->IsJSObject()) return heap()->undefined_value();
1996 int depth = optimization.GetPrototypeDepthOfExpectedType( 1966 int depth = optimization.GetPrototypeDepthOfExpectedType(
1997 JSObject::cast(object), holder); 1967 JSObject::cast(object), holder);
1998 if (depth == kInvalidProtoDepth) return heap()->undefined_value(); 1968 if (depth == kInvalidProtoDepth) return heap()->undefined_value();
1999 1969
2000 Label miss, miss_before_stack_reserved; 1970 Label miss, miss_before_stack_reserved;
2001 1971
2002 GenerateNameCheck(name, &miss_before_stack_reserved); 1972 GenerateNameCheck(name, &miss_before_stack_reserved);
2003 1973
2004 // Get the receiver from the stack. 1974 // Get the receiver from the stack.
2005 const int argc = arguments().immediate(); 1975 const int argc = arguments().immediate();
(...skipping 510 matching lines...) Expand 10 before | Expand all | Expand 10 after
2516 __ bind(&miss); 2486 __ bind(&miss);
2517 __ DecrementCounter(counters->keyed_store_field(), 1); 2487 __ DecrementCounter(counters->keyed_store_field(), 1);
2518 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); 2488 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2519 __ Jump(ic, RelocInfo::CODE_TARGET); 2489 __ Jump(ic, RelocInfo::CODE_TARGET);
2520 2490
2521 // Return the generated code. 2491 // Return the generated code.
2522 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); 2492 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
2523 } 2493 }
2524 2494
2525 2495
2526 MaybeObject* KeyedStoreStubCompiler::CompileStoreSpecialized( 2496 MaybeObject* KeyedStoreStubCompiler::CompileStoreFastElement(
2527 JSObject* receiver) { 2497 Map* receiver_map) {
2528 // ----------- S t a t e ------------- 2498 // ----------- S t a t e -------------
2529 // -- rax : value 2499 // -- rax : value
2530 // -- rcx : key 2500 // -- rcx : key
2531 // -- rdx : receiver 2501 // -- rdx : receiver
2532 // -- rsp[0] : return address 2502 // -- rsp[0] : return address
2533 // ----------------------------------- 2503 // -----------------------------------
2534 Label miss; 2504 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
2505 MaybeObject* maybe_stub =
2506 KeyedStoreFastElementStub(is_js_array).TryGetCode();
2507 Code* stub;
2508 if (!maybe_stub->To(&stub)) return maybe_stub;
2509 __ DispatchMap(rdx,
2510 Handle<Map>(receiver_map),
2511 Handle<Code>(stub),
2512 DO_SMI_CHECK);
2535 2513
2536 // Check that the receiver isn't a smi.
2537 __ JumpIfSmi(rdx, &miss);
2538
2539 // Check that the map matches.
2540 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
2541 Handle<Map>(receiver->map()));
2542 __ j(not_equal, &miss);
2543
2544 // Check that the key is a smi.
2545 __ JumpIfNotSmi(rcx, &miss);
2546
2547 // Get the elements array and make sure it is a fast element array, not 'cow'.
2548 __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset));
2549 __ Cmp(FieldOperand(rdi, HeapObject::kMapOffset),
2550 factory()->fixed_array_map());
2551 __ j(not_equal, &miss);
2552
2553 // Check that the key is within bounds.
2554 if (receiver->IsJSArray()) {
2555 __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset));
2556 __ j(above_equal, &miss);
2557 } else {
2558 __ SmiCompare(rcx, FieldOperand(rdi, FixedArray::kLengthOffset));
2559 __ j(above_equal, &miss);
2560 }
2561
2562 // Do the store and update the write barrier. Make sure to preserve
2563 // the value in register eax.
2564 __ movq(rdx, rax);
2565 __ SmiToInteger32(rcx, rcx);
2566 __ movq(FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize),
2567 rax);
2568 __ RecordWrite(rdi, 0, rdx, rcx, kDontSaveFPRegs);
2569
2570 // Done.
2571 __ ret(0);
2572
2573 // Handle store cache miss.
2574 __ bind(&miss);
2575 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); 2514 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2576 __ jmp(ic, RelocInfo::CODE_TARGET); 2515 __ jmp(ic, RelocInfo::CODE_TARGET);
2577 2516
2578 // Return the generated code. 2517 // Return the generated code.
2579 return GetCode(NORMAL, NULL); 2518 return GetCode(NORMAL, NULL);
2580 } 2519 }
2581 2520
2582 2521
2522 MaybeObject* KeyedStoreStubCompiler::CompileStoreMegamorphic(
2523 MapList* receiver_maps,
2524 CodeList* handler_ics) {
2525 // ----------- S t a t e -------------
2526 // -- rax : value
2527 // -- rcx : key
2528 // -- rdx : receiver
2529 // -- rsp[0] : return address
2530 // -----------------------------------
2531 Label miss;
2532 __ JumpIfSmi(rdx, &miss);
2533
2534 Register map_reg = rbx;
2535 __ movq(map_reg, FieldOperand(rdx, HeapObject::kMapOffset));
2536 int receiver_count = receiver_maps->length();
2537 for (int current = 0; current < receiver_count; ++current) {
2538 // Check map and tail call if there's a match
2539 Handle<Map> map(receiver_maps->at(current));
2540 __ Cmp(map_reg, map);
2541 __ j(equal,
2542 Handle<Code>(handler_ics->at(current)),
2543 RelocInfo::CODE_TARGET);
2544 }
2545
2546 __ bind(&miss);
2547 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2548 __ jmp(ic, RelocInfo::CODE_TARGET);
2549
2550 // Return the generated code.
2551 return GetCode(NORMAL, NULL, MEGAMORPHIC);
2552 }
2553
2554
2583 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, 2555 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name,
2584 JSObject* object, 2556 JSObject* object,
2585 JSObject* last) { 2557 JSObject* last) {
2586 // ----------- S t a t e ------------- 2558 // ----------- S t a t e -------------
2587 // -- rax : receiver 2559 // -- rax : receiver
2588 // -- rcx : name 2560 // -- rcx : name
2589 // -- rsp[0] : return address 2561 // -- rsp[0] : return address
2590 // ----------------------------------- 2562 // -----------------------------------
2591 Label miss; 2563 Label miss;
2592 2564
2593 // Chech that receiver is not a smi. 2565 // Check that receiver is not a smi.
2594 __ JumpIfSmi(rax, &miss); 2566 __ JumpIfSmi(rax, &miss);
2595 2567
2596 // Check the maps of the full prototype chain. Also check that 2568 // Check the maps of the full prototype chain. Also check that
2597 // global property cells up to (but not including) the last object 2569 // global property cells up to (but not including) the last object
2598 // in the prototype chain are empty. 2570 // in the prototype chain are empty.
2599 CheckPrototypes(object, rax, last, rbx, rdx, rdi, name, &miss); 2571 CheckPrototypes(object, rax, last, rbx, rdx, rdi, name, &miss);
2600 2572
2601 // If the last object in the prototype chain is a global object, 2573 // If the last object in the prototype chain is a global object,
2602 // check that the global property cell is empty. 2574 // check that the global property cell is empty.
2603 if (last->IsGlobalObject()) { 2575 if (last->IsGlobalObject()) {
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after
2974 GenerateLoadFunctionPrototype(masm(), rdx, rcx, rbx, &miss); 2946 GenerateLoadFunctionPrototype(masm(), rdx, rcx, rbx, &miss);
2975 __ bind(&miss); 2947 __ bind(&miss);
2976 __ DecrementCounter(counters->keyed_load_function_prototype(), 1); 2948 __ DecrementCounter(counters->keyed_load_function_prototype(), 1);
2977 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2949 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2978 2950
2979 // Return the generated code. 2951 // Return the generated code.
2980 return GetCode(CALLBACKS, name); 2952 return GetCode(CALLBACKS, name);
2981 } 2953 }
2982 2954
2983 2955
2984 MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) { 2956 MaybeObject* KeyedLoadStubCompiler::CompileLoadFastElement(Map* receiver_map) {
2957 // ----------- S t a t e -------------
2958 // -- rax : key
2959 // -- rdx : receiver
2960 // -- rsp[0] : return address
2961 // -----------------------------------
2962 MaybeObject* maybe_stub = KeyedLoadFastElementStub().TryGetCode();
2963 Code* stub;
2964 if (!maybe_stub->To(&stub)) return maybe_stub;
2965 __ DispatchMap(rdx,
2966 Handle<Map>(receiver_map),
2967 Handle<Code>(stub),
2968 DO_SMI_CHECK);
2969
2970 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
2971 __ jmp(ic, RelocInfo::CODE_TARGET);
2972
2973 // Return the generated code.
2974 return GetCode(NORMAL, NULL);
2975 }
2976
2977
2978 MaybeObject* KeyedLoadStubCompiler::CompileLoadMegamorphic(
2979 MapList* receiver_maps,
2980 CodeList* handler_ics) {
2985 // ----------- S t a t e ------------- 2981 // ----------- S t a t e -------------
2986 // -- rax : key 2982 // -- rax : key
2987 // -- rdx : receiver 2983 // -- rdx : receiver
2988 // -- rsp[0] : return address 2984 // -- rsp[0] : return address
2989 // ----------------------------------- 2985 // -----------------------------------
2990 Label miss; 2986 Label miss;
2991
2992 // Check that the receiver isn't a smi.
2993 __ JumpIfSmi(rdx, &miss); 2987 __ JumpIfSmi(rdx, &miss);
2994 2988
2995 // Check that the map matches. 2989 Register map_reg = rbx;
2996 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), 2990 __ movq(map_reg, FieldOperand(rdx, HeapObject::kMapOffset));
2997 Handle<Map>(receiver->map())); 2991 int receiver_count = receiver_maps->length();
2998 __ j(not_equal, &miss); 2992 for (int current = 0; current < receiver_count; ++current) {
2993 // Check map and tail call if there's a match
2994 Handle<Map> map(receiver_maps->at(current));
2995 __ Cmp(map_reg, map);
2996 __ j(equal,
2997 Handle<Code>(handler_ics->at(current)),
2998 RelocInfo::CODE_TARGET);
2999 }
2999 3000
3000 // Check that the key is a smi. 3001 __ bind(&miss);
3001 __ JumpIfNotSmi(rax, &miss);
3002
3003 // Get the elements array.
3004 __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
3005 __ AssertFastElements(rcx);
3006
3007 // Check that the key is within bounds.
3008 __ SmiCompare(rax, FieldOperand(rcx, FixedArray::kLengthOffset));
3009 __ j(above_equal, &miss);
3010
3011 // Load the result and make sure it's not the hole.
3012 SmiIndex index = masm()->SmiToIndex(rbx, rax, kPointerSizeLog2);
3013 __ movq(rbx, FieldOperand(rcx,
3014 index.reg,
3015 index.scale,
3016 FixedArray::kHeaderSize));
3017 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
3018 __ j(equal, &miss);
3019 __ movq(rax, rbx);
3020 __ ret(0);
3021
3022 __ bind(&miss);
3023 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3002 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3024 3003
3025 // Return the generated code. 3004 // Return the generated code.
3026 return GetCode(NORMAL, NULL); 3005 return GetCode(NORMAL, NULL, MEGAMORPHIC);
3027 } 3006 }
3028 3007
3029 3008
3030 // Specialized stub for constructing objects from functions which only have only 3009 // Specialized stub for constructing objects from functions which only have only
3031 // simple assignments of the form this.x = ...; in their body. 3010 // simple assignments of the form this.x = ...; in their body.
3032 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { 3011 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
3033 // ----------- S t a t e ------------- 3012 // ----------- S t a t e -------------
3034 // -- rax : argc 3013 // -- rax : argc
3035 // -- rdi : constructor 3014 // -- rdi : constructor
3036 // -- rsp[0] : return address 3015 // -- rsp[0] : return address
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
3153 Code* code = 3132 Code* code =
3154 isolate()->builtins()->builtin(Builtins::kJSConstructStubGeneric); 3133 isolate()->builtins()->builtin(Builtins::kJSConstructStubGeneric);
3155 Handle<Code> generic_construct_stub(code); 3134 Handle<Code> generic_construct_stub(code);
3156 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); 3135 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET);
3157 3136
3158 // Return the generated code. 3137 // Return the generated code.
3159 return GetCode(); 3138 return GetCode();
3160 } 3139 }
3161 3140
3162 3141
3163 MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( 3142 MaybeObject* ExternalArrayLoadStubCompiler::CompileLoad(
3164 JSObject* receiver, ExternalArrayType array_type, Code::Flags flags) { 3143 JSObject*receiver, ExternalArrayType array_type) {
3165 // ----------- S t a t e ------------- 3144 // ----------- S t a t e -------------
3166 // -- rax : key 3145 // -- rax : key
3167 // -- rdx : receiver 3146 // -- rdx : receiver
3168 // -- rsp[0] : return address 3147 // -- rsp[0] : return address
3169 // ----------------------------------- 3148 // -----------------------------------
3170 Label slow; 3149 MaybeObject* maybe_stub =
3150 KeyedLoadExternalArrayStub(array_type).TryGetCode();
3151 Code* stub;
3152 if (!maybe_stub->To(&stub)) return maybe_stub;
3153 __ DispatchMap(rdx,
3154 Handle<Map>(receiver->map()),
3155 Handle<Code>(stub),
3156 DO_SMI_CHECK);
3171 3157
3172 // Check that the object isn't a smi. 3158 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
3173 __ JumpIfSmi(rdx, &slow); 3159 __ jmp(ic, RelocInfo::CODE_TARGET);
3160
3161 // Return the generated code.
3162 return GetCode();
3163 }
3164
3165 MaybeObject* ExternalArrayStoreStubCompiler::CompileStore(
3166 JSObject* receiver, ExternalArrayType array_type) {
3167 // ----------- S t a t e -------------
3168 // -- rax : value
3169 // -- rcx : key
3170 // -- rdx : receiver
3171 // -- rsp[0] : return address
3172 // -----------------------------------
3173 MaybeObject* maybe_stub =
3174 KeyedStoreExternalArrayStub(array_type).TryGetCode();
3175 Code* stub;
3176 if (!maybe_stub->To(&stub)) return maybe_stub;
3177 __ DispatchMap(rdx,
3178 Handle<Map>(receiver->map()),
3179 Handle<Code>(stub),
3180 DO_SMI_CHECK);
3181
3182 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
3183 __ jmp(ic, RelocInfo::CODE_TARGET);
3184
3185 return GetCode();
3186 }
3187
3188
3189 #undef __
3190 #define __ ACCESS_MASM(masm)
3191
3192
3193 void KeyedLoadStubCompiler::GenerateLoadExternalArray(
3194 MacroAssembler* masm,
3195 ExternalArrayType array_type) {
3196 // ----------- S t a t e -------------
3197 // -- rax : key
3198 // -- rdx : receiver
3199 // -- rsp[0] : return address
3200 // -----------------------------------
3201 Label slow, miss_force_generic;
3202
3203 // This stub is meant to be tail-jumped to, the receiver must already
3204 // have been verified by the caller to not be a smi.
3174 3205
3175 // Check that the key is a smi. 3206 // Check that the key is a smi.
3176 __ JumpIfNotSmi(rax, &slow); 3207 __ JumpIfNotSmi(rax, &miss_force_generic);
3177
3178 // Check that the map matches.
3179 __ CheckMap(rdx, Handle<Map>(receiver->map()), &slow, false);
3180 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
3181 3208
3182 // Check that the index is in range. 3209 // Check that the index is in range.
3210 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
3183 __ SmiToInteger32(rcx, rax); 3211 __ SmiToInteger32(rcx, rax);
3184 __ cmpl(rcx, FieldOperand(rbx, ExternalArray::kLengthOffset)); 3212 __ cmpl(rcx, FieldOperand(rbx, ExternalArray::kLengthOffset));
3185 // Unsigned comparison catches both negative and too-large values. 3213 // Unsigned comparison catches both negative and too-large values.
3186 __ j(above_equal, &slow); 3214 __ j(above_equal, &miss_force_generic);
3187 3215
3188 // rax: index (as a smi) 3216 // rax: index (as a smi)
3189 // rdx: receiver (JSObject) 3217 // rdx: receiver (JSObject)
3190 // rcx: untagged index 3218 // rcx: untagged index
3191 // rbx: elements array 3219 // rbx: elements array
3192 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset)); 3220 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
3193 // rbx: base pointer of external storage 3221 // rbx: base pointer of external storage
3194 switch (array_type) { 3222 switch (array_type) {
3195 case kExternalByteArray: 3223 case kExternalByteArray:
3196 __ movsxbq(rcx, Operand(rbx, rcx, times_1, 0)); 3224 __ movsxbq(rcx, Operand(rbx, rcx, times_1, 0));
(...skipping 30 matching lines...) Expand all
3227 // For integer array types: 3255 // For integer array types:
3228 // rcx: value 3256 // rcx: value
3229 // For floating-point array type: 3257 // For floating-point array type:
3230 // xmm0: value as double. 3258 // xmm0: value as double.
3231 3259
3232 ASSERT(kSmiValueSize == 32); 3260 ASSERT(kSmiValueSize == 32);
3233 if (array_type == kExternalUnsignedIntArray) { 3261 if (array_type == kExternalUnsignedIntArray) {
3234 // For the UnsignedInt array type, we need to see whether 3262 // For the UnsignedInt array type, we need to see whether
3235 // the value can be represented in a Smi. If not, we need to convert 3263 // the value can be represented in a Smi. If not, we need to convert
3236 // it to a HeapNumber. 3264 // it to a HeapNumber.
3237 NearLabel box_int; 3265 Label box_int;
3238 3266
3239 __ JumpIfUIntNotValidSmiValue(rcx, &box_int); 3267 __ JumpIfUIntNotValidSmiValue(rcx, &box_int, Label::kNear);
3240 3268
3241 __ Integer32ToSmi(rax, rcx); 3269 __ Integer32ToSmi(rax, rcx);
3242 __ ret(0); 3270 __ ret(0);
3243 3271
3244 __ bind(&box_int); 3272 __ bind(&box_int);
3245 3273
3246 // Allocate a HeapNumber for the int and perform int-to-double 3274 // Allocate a HeapNumber for the int and perform int-to-double
3247 // conversion. 3275 // conversion.
3248 // The value is zero-extended since we loaded the value from memory 3276 // The value is zero-extended since we loaded the value from memory
3249 // with movl. 3277 // with movl.
(...skipping 13 matching lines...) Expand all
3263 __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0); 3291 __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0);
3264 __ movq(rax, rcx); 3292 __ movq(rax, rcx);
3265 __ ret(0); 3293 __ ret(0);
3266 } else { 3294 } else {
3267 __ Integer32ToSmi(rax, rcx); 3295 __ Integer32ToSmi(rax, rcx);
3268 __ ret(0); 3296 __ ret(0);
3269 } 3297 }
3270 3298
3271 // Slow case: Jump to runtime. 3299 // Slow case: Jump to runtime.
3272 __ bind(&slow); 3300 __ bind(&slow);
3273 Counters* counters = isolate()->counters(); 3301 Counters* counters = masm->isolate()->counters();
3274 __ IncrementCounter(counters->keyed_load_external_array_slow(), 1); 3302 __ IncrementCounter(counters->keyed_load_external_array_slow(), 1);
3275 3303
3276 // ----------- S t a t e ------------- 3304 // ----------- S t a t e -------------
3277 // -- rax : key 3305 // -- rax : key
3278 // -- rdx : receiver 3306 // -- rdx : receiver
3279 // -- rsp[0] : return address 3307 // -- rsp[0] : return address
3280 // ----------------------------------- 3308 // -----------------------------------
3281 3309
3282 __ pop(rbx); 3310 Handle<Code> ic = masm->isolate()->builtins()->KeyedLoadIC_Slow();
3283 __ push(rdx); // receiver 3311 __ jmp(ic, RelocInfo::CODE_TARGET);
3284 __ push(rax); // name
3285 __ push(rbx); // return address
3286 3312
3287 // Perform tail call to the entry. 3313 // Miss case: Jump to runtime.
3288 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); 3314 __ bind(&miss_force_generic);
3289 3315
3290 // Return the generated code. 3316 // ----------- S t a t e -------------
3291 return GetCode(flags); 3317 // -- rax : key
3318 // -- rdx : receiver
3319 // -- rsp[0] : return address
3320 // -----------------------------------
3321 Handle<Code> miss_ic =
3322 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
3323 __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3292 } 3324 }
3293 3325
3294 3326
3295 MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub( 3327 void KeyedStoreStubCompiler::GenerateStoreExternalArray(
3296 JSObject* receiver, ExternalArrayType array_type, Code::Flags flags) { 3328 MacroAssembler* masm,
3329 ExternalArrayType array_type) {
3297 // ----------- S t a t e ------------- 3330 // ----------- S t a t e -------------
3298 // -- rax : value 3331 // -- rax : value
3299 // -- rcx : key 3332 // -- rcx : key
3300 // -- rdx : receiver 3333 // -- rdx : receiver
3301 // -- rsp[0] : return address 3334 // -- rsp[0] : return address
3302 // ----------------------------------- 3335 // -----------------------------------
3303 Label slow; 3336 Label slow, miss_force_generic;
3304 3337
3305 // Check that the object isn't a smi. 3338 // This stub is meant to be tail-jumped to, the receiver must already
3306 __ JumpIfSmi(rdx, &slow); 3339 // have been verified by the caller to not be a smi.
3307
3308 // Check that the map matches.
3309 __ CheckMap(rdx, Handle<Map>(receiver->map()), &slow, false);
3310 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
3311 3340
3312 // Check that the key is a smi. 3341 // Check that the key is a smi.
3313 __ JumpIfNotSmi(rcx, &slow); 3342 __ JumpIfNotSmi(rcx, &miss_force_generic);
3314 3343
3315 // Check that the index is in range. 3344 // Check that the index is in range.
3345 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
3316 __ SmiToInteger32(rdi, rcx); // Untag the index. 3346 __ SmiToInteger32(rdi, rcx); // Untag the index.
3317 __ cmpl(rdi, FieldOperand(rbx, ExternalArray::kLengthOffset)); 3347 __ cmpl(rdi, FieldOperand(rbx, ExternalArray::kLengthOffset));
3318 // Unsigned comparison catches both negative and too-large values. 3348 // Unsigned comparison catches both negative and too-large values.
3319 __ j(above_equal, &slow); 3349 __ j(above_equal, &miss_force_generic);
3320 3350
3321 // Handle both smis and HeapNumbers in the fast path. Go to the 3351 // Handle both smis and HeapNumbers in the fast path. Go to the
3322 // runtime for all other kinds of values. 3352 // runtime for all other kinds of values.
3323 // rax: value 3353 // rax: value
3324 // rcx: key (a smi) 3354 // rcx: key (a smi)
3325 // rdx: receiver (a JSObject) 3355 // rdx: receiver (a JSObject)
3326 // rbx: elements array 3356 // rbx: elements array
3327 // rdi: untagged key 3357 // rdi: untagged key
3328 NearLabel check_heap_number; 3358 Label check_heap_number;
3329 if (array_type == kExternalPixelArray) { 3359 if (array_type == kExternalPixelArray) {
3330 // Float to pixel conversion is only implemented in the runtime for now. 3360 // Float to pixel conversion is only implemented in the runtime for now.
3331 __ JumpIfNotSmi(rax, &slow); 3361 __ JumpIfNotSmi(rax, &slow);
3332 } else { 3362 } else {
3333 __ JumpIfNotSmi(rax, &check_heap_number); 3363 __ JumpIfNotSmi(rax, &check_heap_number, Label::kNear);
3334 } 3364 }
3335 // No more branches to slow case on this path. Key and receiver not needed. 3365 // No more branches to slow case on this path. Key and receiver not needed.
3336 __ SmiToInteger32(rdx, rax); 3366 __ SmiToInteger32(rdx, rax);
3337 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset)); 3367 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
3338 // rbx: base pointer of external storage 3368 // rbx: base pointer of external storage
3339 switch (array_type) { 3369 switch (array_type) {
3340 case kExternalPixelArray: 3370 case kExternalPixelArray:
3341 { // Clamp the value to [0..255]. 3371 { // Clamp the value to [0..255].
3342 NearLabel done; 3372 Label done;
3343 __ testl(rdx, Immediate(0xFFFFFF00)); 3373 __ testl(rdx, Immediate(0xFFFFFF00));
3344 __ j(zero, &done); 3374 __ j(zero, &done, Label::kNear);
3345 __ setcc(negative, rdx); // 1 if negative, 0 if positive. 3375 __ setcc(negative, rdx); // 1 if negative, 0 if positive.
3346 __ decb(rdx); // 0 if negative, 255 if positive. 3376 __ decb(rdx); // 0 if negative, 255 if positive.
3347 __ bind(&done); 3377 __ bind(&done);
3348 } 3378 }
3349 __ movb(Operand(rbx, rdi, times_1, 0), rdx); 3379 __ movb(Operand(rbx, rdi, times_1, 0), rdx);
3350 break; 3380 break;
3351 case kExternalByteArray: 3381 case kExternalByteArray:
3352 case kExternalUnsignedByteArray: 3382 case kExternalUnsignedByteArray:
3353 __ movb(Operand(rbx, rdi, times_1, 0), rdx); 3383 __ movb(Operand(rbx, rdi, times_1, 0), rdx);
3354 break; 3384 break;
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
3443 // Slow case: call runtime. 3473 // Slow case: call runtime.
3444 __ bind(&slow); 3474 __ bind(&slow);
3445 3475
3446 // ----------- S t a t e ------------- 3476 // ----------- S t a t e -------------
3447 // -- rax : value 3477 // -- rax : value
3448 // -- rcx : key 3478 // -- rcx : key
3449 // -- rdx : receiver 3479 // -- rdx : receiver
3450 // -- rsp[0] : return address 3480 // -- rsp[0] : return address
3451 // ----------------------------------- 3481 // -----------------------------------
3452 3482
3453 __ pop(rbx); 3483 Handle<Code> ic = masm->isolate()->builtins()->KeyedStoreIC_Slow();
3454 __ push(rdx); // receiver 3484 __ jmp(ic, RelocInfo::CODE_TARGET);
3455 __ push(rcx); // key
3456 __ push(rax); // value
3457 __ Push(Smi::FromInt(NONE)); // PropertyAttributes
3458 __ Push(Smi::FromInt(
3459 Code::ExtractExtraICStateFromFlags(flags) & kStrictMode));
3460 __ push(rbx); // return address
3461 3485
3462 // Do tail-call to runtime routine. 3486 // Miss case: call runtime.
3463 __ TailCallRuntime(Runtime::kSetProperty, 5, 1); 3487 __ bind(&miss_force_generic);
3464 3488
3465 return GetCode(flags); 3489 // ----------- S t a t e -------------
3490 // -- rax : value
3491 // -- rcx : key
3492 // -- rdx : receiver
3493 // -- rsp[0] : return address
3494 // -----------------------------------
3495
3496 Handle<Code> miss_ic =
3497 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
3498 __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3466 } 3499 }
3467 3500
3501
3502 void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
3503 // ----------- S t a t e -------------
3504 // -- rax : key
3505 // -- rdx : receiver
3506 // -- rsp[0] : return address
3507 // -----------------------------------
3508 Label miss_force_generic;
3509
3510 // This stub is meant to be tail-jumped to, the receiver must already
3511 // have been verified by the caller to not be a smi.
3512
3513 // Check that the key is a smi.
3514 __ JumpIfNotSmi(rax, &miss_force_generic);
3515
3516 // Get the elements array.
3517 __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
3518 __ AssertFastElements(rcx);
3519
3520 // Check that the key is within bounds.
3521 __ SmiCompare(rax, FieldOperand(rcx, FixedArray::kLengthOffset));
3522 __ j(above_equal, &miss_force_generic);
3523
3524 // Load the result and make sure it's not the hole.
3525 SmiIndex index = masm->SmiToIndex(rbx, rax, kPointerSizeLog2);
3526 __ movq(rbx, FieldOperand(rcx,
3527 index.reg,
3528 index.scale,
3529 FixedArray::kHeaderSize));
3530 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
3531 __ j(equal, &miss_force_generic);
3532 __ movq(rax, rbx);
3533 __ ret(0);
3534
3535 __ bind(&miss_force_generic);
3536 Code* code = masm->isolate()->builtins()->builtin(
3537 Builtins::kKeyedLoadIC_MissForceGeneric);
3538 Handle<Code> ic(code);
3539 __ jmp(ic, RelocInfo::CODE_TARGET);
3540 }
3541
3542
3543 void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
3544 bool is_js_array) {
3545 // ----------- S t a t e -------------
3546 // -- rax : value
3547 // -- rcx : key
3548 // -- rdx : receiver
3549 // -- rsp[0] : return address
3550 // -----------------------------------
3551 Label miss_force_generic;
3552
3553 // This stub is meant to be tail-jumped to, the receiver must already
3554 // have been verified by the caller to not be a smi.
3555
3556 // Check that the key is a smi.
3557 __ JumpIfNotSmi(rcx, &miss_force_generic);
3558
3559 // Get the elements array and make sure it is a fast element array, not 'cow'.
3560 __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset));
3561 __ CompareRoot(FieldOperand(rdi, HeapObject::kMapOffset),
3562 Heap::kFixedArrayMapRootIndex);
3563 __ j(not_equal, &miss_force_generic);
3564
3565 // Check that the key is within bounds.
3566 if (is_js_array) {
3567 __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset));
3568 __ j(above_equal, &miss_force_generic);
3569 } else {
3570 __ SmiCompare(rcx, FieldOperand(rdi, FixedArray::kLengthOffset));
3571 __ j(above_equal, &miss_force_generic);
3572 }
3573
3574 // Do the store and update the write barrier.
3575 __ SmiToInteger32(rcx, rcx);
3576 __ lea(rcx,
3577 FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize));
3578 __ movq(Operand(rcx, 0), rax);
3579 // Make sure to preserve the value in register rax.
3580 __ movq(rdx, rax);
3581 __ RecordWrite(rdi, rcx, rdx, kDontSaveFPRegs);
3582
3583 // Done.
3584 __ ret(0);
3585
3586 // Handle store cache miss.
3587 __ bind(&miss_force_generic);
3588 Handle<Code> ic_force_generic =
3589 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
3590 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
3591 }
3592
3593
3468 #undef __ 3594 #undef __
3469 3595
3470 } } // namespace v8::internal 3596 } } // namespace v8::internal
3471 3597
3472 #endif // V8_TARGET_ARCH_X64 3598 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/simulator-x64.h ('k') | src/zone.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698