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

Side by Side Diff: src/ia32/stub-cache-ia32.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/ia32/simulator-ia32.h ('k') | src/ic.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 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
50 ExternalReference value_offset(isolate->stub_cache()->value_reference(table)); 50 ExternalReference value_offset(isolate->stub_cache()->value_reference(table));
51 51
52 Label miss; 52 Label miss;
53 53
54 if (extra.is_valid()) { 54 if (extra.is_valid()) {
55 // Get the code entry from the cache. 55 // Get the code entry from the cache.
56 __ mov(extra, Operand::StaticArray(offset, times_2, value_offset)); 56 __ mov(extra, Operand::StaticArray(offset, times_2, value_offset));
57 57
58 // Check that the key in the entry matches the name. 58 // Check that the key in the entry matches the name.
59 __ cmp(name, Operand::StaticArray(offset, times_2, key_offset)); 59 __ cmp(name, Operand::StaticArray(offset, times_2, key_offset));
60 __ j(not_equal, &miss, not_taken); 60 __ j(not_equal, &miss);
61 61
62 // Check that the flags match what we're looking for. 62 // Check that the flags match what we're looking for.
63 __ mov(offset, FieldOperand(extra, Code::kFlagsOffset)); 63 __ mov(offset, FieldOperand(extra, Code::kFlagsOffset));
64 __ and_(offset, ~Code::kFlagsNotUsedInLookup); 64 __ and_(offset, ~Code::kFlagsNotUsedInLookup);
65 __ cmp(offset, flags); 65 __ cmp(offset, flags);
66 __ j(not_equal, &miss); 66 __ j(not_equal, &miss);
67 67
68 // Jump to the first instruction in the code stub. 68 // Jump to the first instruction in the code stub.
69 __ add(Operand(extra), Immediate(Code::kHeaderSize - kHeapObjectTag)); 69 __ add(Operand(extra), Immediate(Code::kHeaderSize - kHeapObjectTag));
70 __ jmp(Operand(extra)); 70 __ jmp(Operand(extra));
71 71
72 __ bind(&miss); 72 __ bind(&miss);
73 } else { 73 } else {
74 // Save the offset on the stack. 74 // Save the offset on the stack.
75 __ push(offset); 75 __ push(offset);
76 76
77 // Check that the key in the entry matches the name. 77 // Check that the key in the entry matches the name.
78 __ cmp(name, Operand::StaticArray(offset, times_2, key_offset)); 78 __ cmp(name, Operand::StaticArray(offset, times_2, key_offset));
79 __ j(not_equal, &miss, not_taken); 79 __ j(not_equal, &miss);
80 80
81 // Get the code entry from the cache. 81 // Get the code entry from the cache.
82 __ mov(offset, Operand::StaticArray(offset, times_2, value_offset)); 82 __ mov(offset, Operand::StaticArray(offset, times_2, value_offset));
83 83
84 // Check that the flags match what we're looking for. 84 // Check that the flags match what we're looking for.
85 __ mov(offset, FieldOperand(offset, Code::kFlagsOffset)); 85 __ mov(offset, FieldOperand(offset, Code::kFlagsOffset));
86 __ and_(offset, ~Code::kFlagsNotUsedInLookup); 86 __ and_(offset, ~Code::kFlagsNotUsedInLookup);
87 __ cmp(offset, flags); 87 __ cmp(offset, flags);
88 __ j(not_equal, &miss); 88 __ j(not_equal, &miss);
89 89
(...skipping 10 matching lines...) Expand all
100 __ pop(offset); 100 __ pop(offset);
101 } 101 }
102 } 102 }
103 103
104 104
105 // Helper function used to check that the dictionary doesn't contain 105 // Helper function used to check that the dictionary doesn't contain
106 // the property. This function may return false negatives, so miss_label 106 // the property. This function may return false negatives, so miss_label
107 // must always call a backup property check that is complete. 107 // must always call a backup property check that is complete.
108 // This function is safe to call if the receiver has fast properties. 108 // This function is safe to call if the receiver has fast properties.
109 // Name must be a symbol and receiver must be a heap object. 109 // Name must be a symbol and receiver must be a heap object.
110 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm, 110 static MaybeObject* GenerateDictionaryNegativeLookup(MacroAssembler* masm,
111 Label* miss_label, 111 Label* miss_label,
112 Register receiver, 112 Register receiver,
113 String* name, 113 String* name,
114 Register r0, 114 Register r0,
115 Register r1) { 115 Register r1) {
116 ASSERT(name->IsSymbol()); 116 ASSERT(name->IsSymbol());
117 Counters* counters = masm->isolate()->counters(); 117 Counters* counters = masm->isolate()->counters();
118 __ IncrementCounter(counters->negative_lookups(), 1); 118 __ IncrementCounter(counters->negative_lookups(), 1);
119 __ IncrementCounter(counters->negative_lookups_miss(), 1); 119 __ IncrementCounter(counters->negative_lookups_miss(), 1);
120 120
121 Label done;
122 __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset)); 121 __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset));
123 122
124 const int kInterceptorOrAccessCheckNeededMask = 123 const int kInterceptorOrAccessCheckNeededMask =
125 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); 124 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded);
126 125
127 // Bail out if the receiver has a named interceptor or requires access checks. 126 // Bail out if the receiver has a named interceptor or requires access checks.
128 __ test_b(FieldOperand(r0, Map::kBitFieldOffset), 127 __ test_b(FieldOperand(r0, Map::kBitFieldOffset),
129 kInterceptorOrAccessCheckNeededMask); 128 kInterceptorOrAccessCheckNeededMask);
130 __ j(not_zero, miss_label, not_taken); 129 __ j(not_zero, miss_label);
131 130
132 // Check that receiver is a JSObject. 131 // Check that receiver is a JSObject.
133 __ CmpInstanceType(r0, FIRST_JS_OBJECT_TYPE); 132 __ CmpInstanceType(r0, FIRST_JS_OBJECT_TYPE);
134 __ j(below, miss_label, not_taken); 133 __ j(below, miss_label);
135 134
136 // Load properties array. 135 // Load properties array.
137 Register properties = r0; 136 Register properties = r0;
138 __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); 137 __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset));
139 138
140 // Check that the properties array is a dictionary. 139 // Check that the properties array is a dictionary.
141 __ cmp(FieldOperand(properties, HeapObject::kMapOffset), 140 __ cmp(FieldOperand(properties, HeapObject::kMapOffset),
142 Immediate(masm->isolate()->factory()->hash_table_map())); 141 Immediate(masm->isolate()->factory()->hash_table_map()));
143 __ j(not_equal, miss_label); 142 __ j(not_equal, miss_label);
144 143
145 // Compute the capacity mask. 144 Label done;
146 const int kCapacityOffset = 145 MaybeObject* result =
147 StringDictionary::kHeaderSize + 146 StringDictionaryLookupStub::GenerateNegativeLookup(masm,
148 StringDictionary::kCapacityIndex * kPointerSize; 147 miss_label,
149 148 &done,
150 // Generate an unrolled loop that performs a few probes before 149 properties,
151 // giving up. 150 name,
152 static const int kProbes = 4; 151 r1);
153 const int kElementsStartOffset = 152 if (result->IsFailure()) return result;
154 StringDictionary::kHeaderSize +
155 StringDictionary::kElementsStartIndex * kPointerSize;
156
157 // If names of slots in range from 1 to kProbes - 1 for the hash value are
158 // not equal to the name and kProbes-th slot is not used (its name is the
159 // undefined value), it guarantees the hash table doesn't contain the
160 // property. It's true even if some slots represent deleted properties
161 // (their names are the null value).
162 for (int i = 0; i < kProbes; i++) {
163 // r0 points to properties hash.
164 // Compute the masked index: (hash + i + i * i) & mask.
165 Register index = r1;
166 // Capacity is smi 2^n.
167 __ mov(index, FieldOperand(properties, kCapacityOffset));
168 __ dec(index);
169 __ and_(Operand(index),
170 Immediate(Smi::FromInt(name->Hash() +
171 StringDictionary::GetProbeOffset(i))));
172
173 // Scale the index by multiplying by the entry size.
174 ASSERT(StringDictionary::kEntrySize == 3);
175 __ lea(index, Operand(index, index, times_2, 0)); // index *= 3.
176
177 Register entity_name = r1;
178 // Having undefined at this place means the name is not contained.
179 ASSERT_EQ(kSmiTagSize, 1);
180 __ mov(entity_name, Operand(properties, index, times_half_pointer_size,
181 kElementsStartOffset - kHeapObjectTag));
182 __ cmp(entity_name, masm->isolate()->factory()->undefined_value());
183 if (i != kProbes - 1) {
184 __ j(equal, &done, taken);
185
186 // Stop if found the property.
187 __ cmp(entity_name, Handle<String>(name));
188 __ j(equal, miss_label, not_taken);
189
190 // Check if the entry name is not a symbol.
191 __ mov(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset));
192 __ test_b(FieldOperand(entity_name, Map::kInstanceTypeOffset),
193 kIsSymbolMask);
194 __ j(zero, miss_label, not_taken);
195 } else {
196 // Give up probing if still not found the undefined value.
197 __ j(not_equal, miss_label, not_taken);
198 }
199 }
200 153
201 __ bind(&done); 154 __ bind(&done);
202 __ DecrementCounter(counters->negative_lookups_miss(), 1); 155 __ DecrementCounter(counters->negative_lookups_miss(), 1);
156
157 return result;
203 } 158 }
204 159
205 160
206 void StubCache::GenerateProbe(MacroAssembler* masm, 161 void StubCache::GenerateProbe(MacroAssembler* masm,
207 Code::Flags flags, 162 Code::Flags flags,
208 Register receiver, 163 Register receiver,
209 Register name, 164 Register name,
210 Register scratch, 165 Register scratch,
211 Register extra, 166 Register extra,
212 Register extra2) { 167 Register extra2) {
(...skipping 14 matching lines...) Expand all
227 ASSERT(!extra.is(receiver)); 182 ASSERT(!extra.is(receiver));
228 ASSERT(!extra.is(name)); 183 ASSERT(!extra.is(name));
229 ASSERT(!extra.is(scratch)); 184 ASSERT(!extra.is(scratch));
230 185
231 // Check scratch and extra registers are valid, and extra2 is unused. 186 // Check scratch and extra registers are valid, and extra2 is unused.
232 ASSERT(!scratch.is(no_reg)); 187 ASSERT(!scratch.is(no_reg));
233 ASSERT(extra2.is(no_reg)); 188 ASSERT(extra2.is(no_reg));
234 189
235 // Check that the receiver isn't a smi. 190 // Check that the receiver isn't a smi.
236 __ test(receiver, Immediate(kSmiTagMask)); 191 __ test(receiver, Immediate(kSmiTagMask));
237 __ j(zero, &miss, not_taken); 192 __ j(zero, &miss);
238 193
239 // Get the map of the receiver and compute the hash. 194 // Get the map of the receiver and compute the hash.
240 __ mov(scratch, FieldOperand(name, String::kHashFieldOffset)); 195 __ mov(scratch, FieldOperand(name, String::kHashFieldOffset));
241 __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); 196 __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
242 __ xor_(scratch, flags); 197 __ xor_(scratch, flags);
243 __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize); 198 __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize);
244 199
245 // Probe the primary table. 200 // Probe the primary table.
246 ProbeTable(isolate, masm, flags, kPrimary, name, scratch, extra); 201 ProbeTable(isolate, masm, flags, kPrimary, name, scratch, extra);
247 202
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); 243 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
289 } 244 }
290 245
291 246
292 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, 247 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
293 Register receiver, 248 Register receiver,
294 Register scratch, 249 Register scratch,
295 Label* miss_label) { 250 Label* miss_label) {
296 // Check that the receiver isn't a smi. 251 // Check that the receiver isn't a smi.
297 __ test(receiver, Immediate(kSmiTagMask)); 252 __ test(receiver, Immediate(kSmiTagMask));
298 __ j(zero, miss_label, not_taken); 253 __ j(zero, miss_label);
299 254
300 // Check that the object is a JS array. 255 // Check that the object is a JS array.
301 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); 256 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch);
302 __ j(not_equal, miss_label, not_taken); 257 __ j(not_equal, miss_label);
303 258
304 // Load length directly from the JS array. 259 // Load length directly from the JS array.
305 __ mov(eax, FieldOperand(receiver, JSArray::kLengthOffset)); 260 __ mov(eax, FieldOperand(receiver, JSArray::kLengthOffset));
306 __ ret(0); 261 __ ret(0);
307 } 262 }
308 263
309 264
310 // Generate code to check if an object is a string. If the object is 265 // Generate code to check if an object is a string. If the object is
311 // a string, the map's instance type is left in the scratch register. 266 // a string, the map's instance type is left in the scratch register.
312 static void GenerateStringCheck(MacroAssembler* masm, 267 static void GenerateStringCheck(MacroAssembler* masm,
313 Register receiver, 268 Register receiver,
314 Register scratch, 269 Register scratch,
315 Label* smi, 270 Label* smi,
316 Label* non_string_object) { 271 Label* non_string_object) {
317 // Check that the object isn't a smi. 272 // Check that the object isn't a smi.
318 __ test(receiver, Immediate(kSmiTagMask)); 273 __ test(receiver, Immediate(kSmiTagMask));
319 __ j(zero, smi, not_taken); 274 __ j(zero, smi);
320 275
321 // Check that the object is a string. 276 // Check that the object is a string.
322 __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); 277 __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
323 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); 278 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
324 ASSERT(kNotStringTag != 0); 279 ASSERT(kNotStringTag != 0);
325 __ test(scratch, Immediate(kNotStringTag)); 280 __ test(scratch, Immediate(kNotStringTag));
326 __ j(not_zero, non_string_object, not_taken); 281 __ j(not_zero, non_string_object);
327 } 282 }
328 283
329 284
330 void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, 285 void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm,
331 Register receiver, 286 Register receiver,
332 Register scratch1, 287 Register scratch1,
333 Register scratch2, 288 Register scratch2,
334 Label* miss, 289 Label* miss,
335 bool support_wrappers) { 290 bool support_wrappers) {
336 Label check_wrapper; 291 Label check_wrapper;
337 292
338 // Check if the object is a string leaving the instance type in the 293 // Check if the object is a string leaving the instance type in the
339 // scratch register. 294 // scratch register.
340 GenerateStringCheck(masm, receiver, scratch1, miss, 295 GenerateStringCheck(masm, receiver, scratch1, miss,
341 support_wrappers ? &check_wrapper : miss); 296 support_wrappers ? &check_wrapper : miss);
342 297
343 // Load length from the string and convert to a smi. 298 // Load length from the string and convert to a smi.
344 __ mov(eax, FieldOperand(receiver, String::kLengthOffset)); 299 __ mov(eax, FieldOperand(receiver, String::kLengthOffset));
345 __ ret(0); 300 __ ret(0);
346 301
347 if (support_wrappers) { 302 if (support_wrappers) {
348 // Check if the object is a JSValue wrapper. 303 // Check if the object is a JSValue wrapper.
349 __ bind(&check_wrapper); 304 __ bind(&check_wrapper);
350 __ cmp(scratch1, JS_VALUE_TYPE); 305 __ cmp(scratch1, JS_VALUE_TYPE);
351 __ j(not_equal, miss, not_taken); 306 __ j(not_equal, miss);
352 307
353 // Check if the wrapped value is a string and load the length 308 // Check if the wrapped value is a string and load the length
354 // directly if it is. 309 // directly if it is.
355 __ mov(scratch2, FieldOperand(receiver, JSValue::kValueOffset)); 310 __ mov(scratch2, FieldOperand(receiver, JSValue::kValueOffset));
356 GenerateStringCheck(masm, scratch2, scratch1, miss, miss); 311 GenerateStringCheck(masm, scratch2, scratch1, miss, miss);
357 __ mov(eax, FieldOperand(scratch2, String::kLengthOffset)); 312 __ mov(eax, FieldOperand(scratch2, String::kLengthOffset));
358 __ ret(0); 313 __ ret(0);
359 } 314 }
360 } 315 }
361 316
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
546 Register receiver, 501 Register receiver,
547 Register scratch1, 502 Register scratch1,
548 Register scratch2, 503 Register scratch2,
549 Register scratch3, 504 Register scratch3,
550 Label* miss) { 505 Label* miss) {
551 ASSERT(holder->HasNamedInterceptor()); 506 ASSERT(holder->HasNamedInterceptor());
552 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); 507 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
553 508
554 // Check that the receiver isn't a smi. 509 // Check that the receiver isn't a smi.
555 __ test(receiver, Immediate(kSmiTagMask)); 510 __ test(receiver, Immediate(kSmiTagMask));
556 __ j(zero, miss, not_taken); 511 __ j(zero, miss);
557 512
558 CallOptimization optimization(lookup); 513 CallOptimization optimization(lookup);
559 514
560 if (optimization.is_constant_call()) { 515 if (optimization.is_constant_call()) {
561 return CompileCacheable(masm, 516 return CompileCacheable(masm,
562 object, 517 object,
563 receiver, 518 receiver,
564 scratch1, 519 scratch1,
565 scratch2, 520 scratch2,
566 scratch3, 521 scratch3,
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
751 code = masm->isolate()->builtins()->builtin(Builtins::kLoadIC_Miss); 706 code = masm->isolate()->builtins()->builtin(Builtins::kLoadIC_Miss);
752 } else { 707 } else {
753 code = masm->isolate()->builtins()->builtin(Builtins::kKeyedLoadIC_Miss); 708 code = masm->isolate()->builtins()->builtin(Builtins::kKeyedLoadIC_Miss);
754 } 709 }
755 710
756 Handle<Code> ic(code); 711 Handle<Code> ic(code);
757 __ jmp(ic, RelocInfo::CODE_TARGET); 712 __ jmp(ic, RelocInfo::CODE_TARGET);
758 } 713 }
759 714
760 715
716 void StubCompiler::GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm) {
717 Code* code = masm->isolate()->builtins()->builtin(
718 Builtins::kKeyedLoadIC_MissForceGeneric);
719 Handle<Code> ic(code);
720 __ jmp(ic, RelocInfo::CODE_TARGET);
721 }
722
723
761 // Both name_reg and receiver_reg are preserved on jumps to miss_label, 724 // Both name_reg and receiver_reg are preserved on jumps to miss_label,
762 // but may be destroyed if store is successful. 725 // but may be destroyed if store is successful.
763 void StubCompiler::GenerateStoreField(MacroAssembler* masm, 726 void StubCompiler::GenerateStoreField(MacroAssembler* masm,
764 JSObject* object, 727 JSObject* object,
765 int index, 728 int index,
766 Map* transition, 729 Map* transition,
767 Register receiver_reg, 730 Register receiver_reg,
768 Register name_reg, 731 Register name_reg,
769 Register scratch, 732 Register scratch,
770 Label* miss_label) { 733 Label* miss_label) {
771 // Check that the object isn't a smi. 734 // Check that the object isn't a smi.
772 __ test(receiver_reg, Immediate(kSmiTagMask)); 735 __ test(receiver_reg, Immediate(kSmiTagMask));
773 __ j(zero, miss_label, not_taken); 736 __ j(zero, miss_label);
774 737
775 // Check that the map of the object hasn't changed. 738 // Check that the map of the object hasn't changed.
776 __ cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset), 739 __ cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset),
777 Immediate(Handle<Map>(object->map()))); 740 Immediate(Handle<Map>(object->map())));
778 __ j(not_equal, miss_label, not_taken); 741 __ j(not_equal, miss_label);
779 742
780 // Perform global security token check if needed. 743 // Perform global security token check if needed.
781 if (object->IsJSGlobalProxy()) { 744 if (object->IsJSGlobalProxy()) {
782 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); 745 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label);
783 } 746 }
784 747
785 // Stub never generated for non-global objects that require access 748 // Stub never generated for non-global objects that require access
786 // checks. 749 // checks.
787 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 750 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
788 751
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
866 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); 829 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe);
867 ASSERT(cell->value()->IsTheHole()); 830 ASSERT(cell->value()->IsTheHole());
868 if (Serializer::enabled()) { 831 if (Serializer::enabled()) {
869 __ mov(scratch, Immediate(Handle<Object>(cell))); 832 __ mov(scratch, Immediate(Handle<Object>(cell)));
870 __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), 833 __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset),
871 Immediate(masm->isolate()->factory()->the_hole_value())); 834 Immediate(masm->isolate()->factory()->the_hole_value()));
872 } else { 835 } else {
873 __ cmp(Operand::Cell(Handle<JSGlobalPropertyCell>(cell)), 836 __ cmp(Operand::Cell(Handle<JSGlobalPropertyCell>(cell)),
874 Immediate(masm->isolate()->factory()->the_hole_value())); 837 Immediate(masm->isolate()->factory()->the_hole_value()));
875 } 838 }
876 __ j(not_equal, miss, not_taken); 839 __ j(not_equal, miss);
877 return cell; 840 return cell;
878 } 841 }
879 842
880 843
881 // Calls GenerateCheckPropertyCell for each global object in the prototype chain 844 // Calls GenerateCheckPropertyCell for each global object in the prototype chain
882 // from object to (but not including) holder. 845 // from object to (but not including) holder.
883 MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCells( 846 MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCells(
884 MacroAssembler* masm, 847 MacroAssembler* masm,
885 JSObject* object, 848 JSObject* object,
886 JSObject* holder, 849 JSObject* holder,
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
952 Object* lookup_result = NULL; // Initialization to please compiler. 915 Object* lookup_result = NULL; // Initialization to please compiler.
953 if (!maybe_lookup_result->ToObject(&lookup_result)) { 916 if (!maybe_lookup_result->ToObject(&lookup_result)) {
954 set_failure(Failure::cast(maybe_lookup_result)); 917 set_failure(Failure::cast(maybe_lookup_result));
955 return reg; 918 return reg;
956 } 919 }
957 name = String::cast(lookup_result); 920 name = String::cast(lookup_result);
958 } 921 }
959 ASSERT(current->property_dictionary()->FindEntry(name) == 922 ASSERT(current->property_dictionary()->FindEntry(name) ==
960 StringDictionary::kNotFound); 923 StringDictionary::kNotFound);
961 924
962 GenerateDictionaryNegativeLookup(masm(), 925 MaybeObject* negative_lookup = GenerateDictionaryNegativeLookup(masm(),
963 miss, 926 miss,
964 reg, 927 reg,
965 name, 928 name,
966 scratch1, 929 scratch1,
967 scratch2); 930 scratch2);
931 if (negative_lookup->IsFailure()) {
932 set_failure(Failure::cast(negative_lookup));
933 return reg;
934 }
935
968 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); 936 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
969 reg = holder_reg; // from now the object is in holder_reg 937 reg = holder_reg; // from now the object is in holder_reg
970 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); 938 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
971 } else if (heap()->InNewSpace(prototype)) { 939 } else if (heap()->InNewSpace(prototype)) {
972 // Get the map of the current object. 940 // Get the map of the current object.
973 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); 941 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
974 __ cmp(Operand(scratch1), Immediate(Handle<Map>(current->map()))); 942 __ cmp(Operand(scratch1), Immediate(Handle<Map>(current->map())));
975 // Branch on the result of the map check. 943 // Branch on the result of the map check.
976 __ j(not_equal, miss, not_taken); 944 __ j(not_equal, miss);
977 // Check access rights to the global object. This has to happen 945 // Check access rights to the global object. This has to happen
978 // after the map check so that we know that the object is 946 // after the map check so that we know that the object is
979 // actually a global object. 947 // actually a global object.
980 if (current->IsJSGlobalProxy()) { 948 if (current->IsJSGlobalProxy()) {
981 __ CheckAccessGlobalProxy(reg, scratch1, miss); 949 __ CheckAccessGlobalProxy(reg, scratch1, miss);
982 950
983 // Restore scratch register to be the map of the object. 951 // Restore scratch register to be the map of the object.
984 // We load the prototype from the map in the scratch register. 952 // We load the prototype from the map in the scratch register.
985 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); 953 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
986 } 954 }
987 // The prototype is in new space; we cannot store a reference 955 // The prototype is in new space; we cannot store a reference
988 // to it in the code. Load it from the map. 956 // to it in the code. Load it from the map.
989 reg = holder_reg; // from now the object is in holder_reg 957 reg = holder_reg; // from now the object is in holder_reg
990 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); 958 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
991 } else { 959 } else {
992 // Check the map of the current object. 960 // Check the map of the current object.
993 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), 961 __ cmp(FieldOperand(reg, HeapObject::kMapOffset),
994 Immediate(Handle<Map>(current->map()))); 962 Immediate(Handle<Map>(current->map())));
995 // Branch on the result of the map check. 963 // Branch on the result of the map check.
996 __ j(not_equal, miss, not_taken); 964 __ j(not_equal, miss);
997 // Check access rights to the global object. This has to happen 965 // Check access rights to the global object. This has to happen
998 // after the map check so that we know that the object is 966 // after the map check so that we know that the object is
999 // actually a global object. 967 // actually a global object.
1000 if (current->IsJSGlobalProxy()) { 968 if (current->IsJSGlobalProxy()) {
1001 __ CheckAccessGlobalProxy(reg, scratch1, miss); 969 __ CheckAccessGlobalProxy(reg, scratch1, miss);
1002 } 970 }
1003 // The prototype is in old space; load it directly. 971 // The prototype is in old space; load it directly.
1004 reg = holder_reg; // from now the object is in holder_reg 972 reg = holder_reg; // from now the object is in holder_reg
1005 __ mov(reg, Handle<JSObject>(prototype)); 973 __ mov(reg, Handle<JSObject>(prototype));
1006 } 974 }
1007 975
1008 if (save_at_depth == depth) { 976 if (save_at_depth == depth) {
1009 __ mov(Operand(esp, kPointerSize), reg); 977 __ mov(Operand(esp, kPointerSize), reg);
1010 } 978 }
1011 979
1012 // Go to the next object in the prototype chain. 980 // Go to the next object in the prototype chain.
1013 current = prototype; 981 current = prototype;
1014 } 982 }
1015 ASSERT(current == holder); 983 ASSERT(current == holder);
1016 984
1017 // Log the check depth. 985 // Log the check depth.
1018 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); 986 LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
1019 987
1020 // Check the holder map. 988 // Check the holder map.
1021 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), 989 __ cmp(FieldOperand(reg, HeapObject::kMapOffset),
1022 Immediate(Handle<Map>(holder->map()))); 990 Immediate(Handle<Map>(holder->map())));
1023 __ j(not_equal, miss, not_taken); 991 __ j(not_equal, miss);
1024 992
1025 // Perform security check for access to the global object. 993 // Perform security check for access to the global object.
1026 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); 994 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
1027 if (holder->IsJSGlobalProxy()) { 995 if (holder->IsJSGlobalProxy()) {
1028 __ CheckAccessGlobalProxy(reg, scratch1, miss); 996 __ CheckAccessGlobalProxy(reg, scratch1, miss);
1029 }; 997 };
1030 998
1031 // If we've skipped any global objects, it's not enough to verify 999 // If we've skipped any global objects, it's not enough to verify
1032 // that their maps haven't changed. We also need to check that the 1000 // that their maps haven't changed. We also need to check that the
1033 // property cell for the property is still empty. 1001 // property cell for the property is still empty.
(...skipping 14 matching lines...) Expand all
1048 JSObject* holder, 1016 JSObject* holder,
1049 Register receiver, 1017 Register receiver,
1050 Register scratch1, 1018 Register scratch1,
1051 Register scratch2, 1019 Register scratch2,
1052 Register scratch3, 1020 Register scratch3,
1053 int index, 1021 int index,
1054 String* name, 1022 String* name,
1055 Label* miss) { 1023 Label* miss) {
1056 // Check that the receiver isn't a smi. 1024 // Check that the receiver isn't a smi.
1057 __ test(receiver, Immediate(kSmiTagMask)); 1025 __ test(receiver, Immediate(kSmiTagMask));
1058 __ j(zero, miss, not_taken); 1026 __ j(zero, miss);
1059 1027
1060 // Check the prototype chain. 1028 // Check the prototype chain.
1061 Register reg = 1029 Register reg =
1062 CheckPrototypes(object, receiver, holder, 1030 CheckPrototypes(object, receiver, holder,
1063 scratch1, scratch2, scratch3, name, miss); 1031 scratch1, scratch2, scratch3, name, miss);
1064 1032
1065 // Get the value from the properties. 1033 // Get the value from the properties.
1066 GenerateFastPropertyLoad(masm(), eax, reg, holder, index); 1034 GenerateFastPropertyLoad(masm(), eax, reg, holder, index);
1067 __ ret(0); 1035 __ ret(0);
1068 } 1036 }
1069 1037
1070 1038
1071 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object, 1039 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object,
1072 JSObject* holder, 1040 JSObject* holder,
1073 Register receiver, 1041 Register receiver,
1074 Register name_reg, 1042 Register name_reg,
1075 Register scratch1, 1043 Register scratch1,
1076 Register scratch2, 1044 Register scratch2,
1077 Register scratch3, 1045 Register scratch3,
1078 AccessorInfo* callback, 1046 AccessorInfo* callback,
1079 String* name, 1047 String* name,
1080 Label* miss) { 1048 Label* miss) {
1081 // Check that the receiver isn't a smi. 1049 // Check that the receiver isn't a smi.
1082 __ test(receiver, Immediate(kSmiTagMask)); 1050 __ test(receiver, Immediate(kSmiTagMask));
1083 __ j(zero, miss, not_taken); 1051 __ j(zero, miss);
1084 1052
1085 // Check that the maps haven't changed. 1053 // Check that the maps haven't changed.
1086 Register reg = 1054 Register reg =
1087 CheckPrototypes(object, receiver, holder, scratch1, 1055 CheckPrototypes(object, receiver, holder, scratch1,
1088 scratch2, scratch3, name, miss); 1056 scratch2, scratch3, name, miss);
1089 1057
1090 Handle<AccessorInfo> callback_handle(callback); 1058 Handle<AccessorInfo> callback_handle(callback);
1091 1059
1092 // Insert additional parameters into the stack frame above return address. 1060 // Insert additional parameters into the stack frame above return address.
1093 ASSERT(!scratch3.is(reg)); 1061 ASSERT(!scratch3.is(reg));
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1140 JSObject* holder, 1108 JSObject* holder,
1141 Register receiver, 1109 Register receiver,
1142 Register scratch1, 1110 Register scratch1,
1143 Register scratch2, 1111 Register scratch2,
1144 Register scratch3, 1112 Register scratch3,
1145 Object* value, 1113 Object* value,
1146 String* name, 1114 String* name,
1147 Label* miss) { 1115 Label* miss) {
1148 // Check that the receiver isn't a smi. 1116 // Check that the receiver isn't a smi.
1149 __ test(receiver, Immediate(kSmiTagMask)); 1117 __ test(receiver, Immediate(kSmiTagMask));
1150 __ j(zero, miss, not_taken); 1118 __ j(zero, miss);
1151 1119
1152 // Check that the maps haven't changed. 1120 // Check that the maps haven't changed.
1153 CheckPrototypes(object, receiver, holder, 1121 CheckPrototypes(object, receiver, holder,
1154 scratch1, scratch2, scratch3, name, miss); 1122 scratch1, scratch2, scratch3, name, miss);
1155 1123
1156 // Return the constant value. 1124 // Return the constant value.
1157 __ mov(eax, Handle<Object>(value)); 1125 __ mov(eax, Handle<Object>(value));
1158 __ ret(0); 1126 __ ret(0);
1159 } 1127 }
1160 1128
1161 1129
1162 void StubCompiler::GenerateLoadInterceptor(JSObject* object, 1130 void StubCompiler::GenerateLoadInterceptor(JSObject* object,
1163 JSObject* interceptor_holder, 1131 JSObject* interceptor_holder,
1164 LookupResult* lookup, 1132 LookupResult* lookup,
1165 Register receiver, 1133 Register receiver,
1166 Register name_reg, 1134 Register name_reg,
1167 Register scratch1, 1135 Register scratch1,
1168 Register scratch2, 1136 Register scratch2,
1169 Register scratch3, 1137 Register scratch3,
1170 String* name, 1138 String* name,
1171 Label* miss) { 1139 Label* miss) {
1172 ASSERT(interceptor_holder->HasNamedInterceptor()); 1140 ASSERT(interceptor_holder->HasNamedInterceptor());
1173 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); 1141 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
1174 1142
1175 // Check that the receiver isn't a smi. 1143 // Check that the receiver isn't a smi.
1176 __ test(receiver, Immediate(kSmiTagMask)); 1144 __ test(receiver, Immediate(kSmiTagMask));
1177 __ j(zero, miss, not_taken); 1145 __ j(zero, miss);
1178 1146
1179 // So far the most popular follow ups for interceptor loads are FIELD 1147 // So far the most popular follow ups for interceptor loads are FIELD
1180 // and CALLBACKS, so inline only them, other cases may be added 1148 // and CALLBACKS, so inline only them, other cases may be added
1181 // later. 1149 // later.
1182 bool compile_followup_inline = false; 1150 bool compile_followup_inline = false;
1183 if (lookup->IsProperty() && lookup->IsCacheable()) { 1151 if (lookup->IsProperty() && lookup->IsCacheable()) {
1184 if (lookup->type() == FIELD) { 1152 if (lookup->type() == FIELD) {
1185 compile_followup_inline = true; 1153 compile_followup_inline = true;
1186 } else if (lookup->type() == CALLBACKS && 1154 } else if (lookup->type() == CALLBACKS &&
1187 lookup->GetCallbackObject()->IsAccessorInfo() && 1155 lookup->GetCallbackObject()->IsAccessorInfo() &&
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
1296 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), 1264 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad),
1297 isolate()); 1265 isolate());
1298 __ TailCallExternalReference(ref, 5, 1); 1266 __ TailCallExternalReference(ref, 5, 1);
1299 } 1267 }
1300 } 1268 }
1301 1269
1302 1270
1303 void CallStubCompiler::GenerateNameCheck(String* name, Label* miss) { 1271 void CallStubCompiler::GenerateNameCheck(String* name, Label* miss) {
1304 if (kind_ == Code::KEYED_CALL_IC) { 1272 if (kind_ == Code::KEYED_CALL_IC) {
1305 __ cmp(Operand(ecx), Immediate(Handle<String>(name))); 1273 __ cmp(Operand(ecx), Immediate(Handle<String>(name)));
1306 __ j(not_equal, miss, not_taken); 1274 __ j(not_equal, miss);
1307 } 1275 }
1308 } 1276 }
1309 1277
1310 1278
1311 void CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object, 1279 void CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object,
1312 JSObject* holder, 1280 JSObject* holder,
1313 String* name, 1281 String* name,
1314 Label* miss) { 1282 Label* miss) {
1315 ASSERT(holder->IsGlobalObject()); 1283 ASSERT(holder->IsGlobalObject());
1316 1284
1317 // Get the number of arguments. 1285 // Get the number of arguments.
1318 const int argc = arguments().immediate(); 1286 const int argc = arguments().immediate();
1319 1287
1320 // Get the receiver from the stack. 1288 // Get the receiver from the stack.
1321 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1289 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1322 1290
1323 // If the object is the holder then we know that it's a global 1291 // If the object is the holder then we know that it's a global
1324 // object which can only happen for contextual calls. In this case, 1292 // object which can only happen for contextual calls. In this case,
1325 // the receiver cannot be a smi. 1293 // the receiver cannot be a smi.
1326 if (object != holder) { 1294 if (object != holder) {
1327 __ test(edx, Immediate(kSmiTagMask)); 1295 __ test(edx, Immediate(kSmiTagMask));
1328 __ j(zero, miss, not_taken); 1296 __ j(zero, miss);
1329 } 1297 }
1330 1298
1331 // Check that the maps haven't changed. 1299 // Check that the maps haven't changed.
1332 CheckPrototypes(object, edx, holder, ebx, eax, edi, name, miss); 1300 CheckPrototypes(object, edx, holder, ebx, eax, edi, name, miss);
1333 } 1301 }
1334 1302
1335 1303
1336 void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell, 1304 void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell,
1337 JSFunction* function, 1305 JSFunction* function,
1338 Label* miss) { 1306 Label* miss) {
1339 // Get the value from the cell. 1307 // Get the value from the cell.
1340 if (Serializer::enabled()) { 1308 if (Serializer::enabled()) {
1341 __ mov(edi, Immediate(Handle<JSGlobalPropertyCell>(cell))); 1309 __ mov(edi, Immediate(Handle<JSGlobalPropertyCell>(cell)));
1342 __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset)); 1310 __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset));
1343 } else { 1311 } else {
1344 __ mov(edi, Operand::Cell(Handle<JSGlobalPropertyCell>(cell))); 1312 __ mov(edi, Operand::Cell(Handle<JSGlobalPropertyCell>(cell)));
1345 } 1313 }
1346 1314
1347 // Check that the cell contains the same function. 1315 // Check that the cell contains the same function.
1348 if (isolate()->heap()->InNewSpace(function)) { 1316 if (isolate()->heap()->InNewSpace(function)) {
1349 // We can't embed a pointer to a function in new space so we have 1317 // We can't embed a pointer to a function in new space so we have
1350 // to verify that the shared function info is unchanged. This has 1318 // to verify that the shared function info is unchanged. This has
1351 // the nice side effect that multiple closures based on the same 1319 // the nice side effect that multiple closures based on the same
1352 // function can all use this call IC. Before we load through the 1320 // function can all use this call IC. Before we load through the
1353 // function, we have to verify that it still is a function. 1321 // function, we have to verify that it still is a function.
1354 __ test(edi, Immediate(kSmiTagMask)); 1322 __ test(edi, Immediate(kSmiTagMask));
1355 __ j(zero, miss, not_taken); 1323 __ j(zero, miss);
1356 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); 1324 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx);
1357 __ j(not_equal, miss, not_taken); 1325 __ j(not_equal, miss);
1358 1326
1359 // Check the shared function info. Make sure it hasn't changed. 1327 // Check the shared function info. Make sure it hasn't changed.
1360 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), 1328 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset),
1361 Immediate(Handle<SharedFunctionInfo>(function->shared()))); 1329 Immediate(Handle<SharedFunctionInfo>(function->shared())));
1362 __ j(not_equal, miss, not_taken); 1330 __ j(not_equal, miss);
1363 } else { 1331 } else {
1364 __ cmp(Operand(edi), Immediate(Handle<JSFunction>(function))); 1332 __ cmp(Operand(edi), Immediate(Handle<JSFunction>(function)));
1365 __ j(not_equal, miss, not_taken); 1333 __ j(not_equal, miss);
1366 } 1334 }
1367 } 1335 }
1368 1336
1369 1337
1370 MaybeObject* CallStubCompiler::GenerateMissBranch() { 1338 MaybeObject* CallStubCompiler::GenerateMissBranch() {
1371 MaybeObject* maybe_obj = 1339 MaybeObject* maybe_obj =
1372 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), 1340 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(),
1373 kind_); 1341 kind_);
1374 Object* obj; 1342 Object* obj;
1375 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 1343 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
(...skipping 17 matching lines...) Expand all
1393 Label miss; 1361 Label miss;
1394 1362
1395 GenerateNameCheck(name, &miss); 1363 GenerateNameCheck(name, &miss);
1396 1364
1397 // Get the receiver from the stack. 1365 // Get the receiver from the stack.
1398 const int argc = arguments().immediate(); 1366 const int argc = arguments().immediate();
1399 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1367 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1400 1368
1401 // Check that the receiver isn't a smi. 1369 // Check that the receiver isn't a smi.
1402 __ test(edx, Immediate(kSmiTagMask)); 1370 __ test(edx, Immediate(kSmiTagMask));
1403 __ j(zero, &miss, not_taken); 1371 __ j(zero, &miss);
1404 1372
1405 // Do the right check and compute the holder register. 1373 // Do the right check and compute the holder register.
1406 Register reg = CheckPrototypes(object, edx, holder, ebx, eax, edi, 1374 Register reg = CheckPrototypes(object, edx, holder, ebx, eax, edi,
1407 name, &miss); 1375 name, &miss);
1408 1376
1409 GenerateFastPropertyLoad(masm(), edi, reg, holder, index); 1377 GenerateFastPropertyLoad(masm(), edi, reg, holder, index);
1410 1378
1411 // Check that the function really is a function. 1379 // Check that the function really is a function.
1412 __ test(edi, Immediate(kSmiTagMask)); 1380 __ test(edi, Immediate(kSmiTagMask));
1413 __ j(zero, &miss, not_taken); 1381 __ j(zero, &miss);
1414 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); 1382 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx);
1415 __ j(not_equal, &miss, not_taken); 1383 __ j(not_equal, &miss);
1416 1384
1417 // Patch the receiver on the stack with the global proxy if 1385 // Patch the receiver on the stack with the global proxy if
1418 // necessary. 1386 // necessary.
1419 if (object->IsGlobalObject()) { 1387 if (object->IsGlobalObject()) {
1420 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 1388 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
1421 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 1389 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
1422 } 1390 }
1423 1391
1424 // Invoke the function. 1392 // Invoke the function.
1425 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION); 1393 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION);
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1477 1445
1478 // Get the elements array of the object. 1446 // Get the elements array of the object.
1479 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); 1447 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset));
1480 1448
1481 // Check that the elements are in fast mode and writable. 1449 // Check that the elements are in fast mode and writable.
1482 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), 1450 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
1483 Immediate(factory()->fixed_array_map())); 1451 Immediate(factory()->fixed_array_map()));
1484 __ j(not_equal, &call_builtin); 1452 __ j(not_equal, &call_builtin);
1485 1453
1486 if (argc == 1) { // Otherwise fall through to call builtin. 1454 if (argc == 1) { // Otherwise fall through to call builtin.
1487 Label exit, attempt_to_grow_elements; 1455 Label exit, attempt_to_grow_elements, with_write_barrier;
1488 NearLabel with_write_barrier;
1489 1456
1490 // Get the array's length into eax and calculate new length. 1457 // Get the array's length into eax and calculate new length.
1491 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); 1458 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset));
1492 STATIC_ASSERT(kSmiTagSize == 1); 1459 STATIC_ASSERT(kSmiTagSize == 1);
1493 STATIC_ASSERT(kSmiTag == 0); 1460 STATIC_ASSERT(kSmiTag == 0);
1494 __ add(Operand(eax), Immediate(Smi::FromInt(argc))); 1461 __ add(Operand(eax), Immediate(Smi::FromInt(argc)));
1495 1462
1496 // Get the element's length into ecx. 1463 // Get the element's length into ecx.
1497 __ mov(ecx, FieldOperand(ebx, FixedArray::kLengthOffset)); 1464 __ mov(ecx, FieldOperand(ebx, FixedArray::kLengthOffset));
1498 1465
1499 // Check if we could survive without allocation. 1466 // Check if we could survive without allocation.
1500 __ cmp(eax, Operand(ecx)); 1467 __ cmp(eax, Operand(ecx));
1501 __ j(greater, &attempt_to_grow_elements); 1468 __ j(greater, &attempt_to_grow_elements);
1502 1469
1503 // Save new length. 1470 // Save new length.
1504 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); 1471 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax);
1505 1472
1506 // Push the element. 1473 // Push the element.
1507 __ lea(edx, FieldOperand(ebx, 1474 __ lea(edx, FieldOperand(ebx,
1508 eax, times_half_pointer_size, 1475 eax, times_half_pointer_size,
1509 FixedArray::kHeaderSize - argc * kPointerSize)); 1476 FixedArray::kHeaderSize - argc * kPointerSize));
1510 __ mov(ecx, Operand(esp, argc * kPointerSize)); 1477 __ mov(ecx, Operand(esp, argc * kPointerSize));
1511 __ mov(Operand(edx, 0), ecx); 1478 __ mov(Operand(edx, 0), ecx);
1512 1479
1513 // Check if value is a smi. 1480 // Check if value is a smi.
1514 __ test(ecx, Immediate(kSmiTagMask)); 1481 __ test(ecx, Immediate(kSmiTagMask));
1515 __ j(not_zero, &with_write_barrier); 1482 __ j(not_zero, &with_write_barrier, Label::kNear);
1516 1483
1517 __ bind(&exit); 1484 __ bind(&exit);
1518 __ ret((argc + 1) * kPointerSize); 1485 __ ret((argc + 1) * kPointerSize);
1519 1486
1520 __ bind(&with_write_barrier); 1487 __ bind(&with_write_barrier);
1521 1488
1522 __ RecordWrite( 1489 __ RecordWrite(
1523 ebx, edx, ecx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); 1490 ebx, edx, ecx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
1524 1491
1525 __ ret((argc + 1) * kPointerSize); 1492 __ ret((argc + 1) * kPointerSize);
(...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after
1977 __ mov(eax, Operand(esp, 1 * kPointerSize)); 1944 __ mov(eax, Operand(esp, 1 * kPointerSize));
1978 1945
1979 // Check if the argument is a smi. 1946 // Check if the argument is a smi.
1980 Label smi; 1947 Label smi;
1981 STATIC_ASSERT(kSmiTag == 0); 1948 STATIC_ASSERT(kSmiTag == 0);
1982 __ test(eax, Immediate(kSmiTagMask)); 1949 __ test(eax, Immediate(kSmiTagMask));
1983 __ j(zero, &smi); 1950 __ j(zero, &smi);
1984 1951
1985 // Check if the argument is a heap number and load its value into xmm0. 1952 // Check if the argument is a heap number and load its value into xmm0.
1986 Label slow; 1953 Label slow;
1987 __ CheckMap(eax, factory()->heap_number_map(), &slow, true); 1954 __ CheckMap(eax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK);
1988 __ movdbl(xmm0, FieldOperand(eax, HeapNumber::kValueOffset)); 1955 __ movdbl(xmm0, FieldOperand(eax, HeapNumber::kValueOffset));
1989 1956
1990 // Check if the argument is strictly positive. Note this also 1957 // Check if the argument is strictly positive. Note this also
1991 // discards NaN. 1958 // discards NaN.
1992 __ xorpd(xmm1, xmm1); 1959 __ xorpd(xmm1, xmm1);
1993 __ ucomisd(xmm0, xmm1); 1960 __ ucomisd(xmm0, xmm1);
1994 __ j(below_equal, &slow); 1961 __ j(below_equal, &slow);
1995 1962
1996 // Do a truncating conversion. 1963 // Do a truncating conversion.
1997 __ cvttsd2si(eax, Operand(xmm0)); 1964 __ cvttsd2si(eax, Operand(xmm0));
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
2121 // This only happens for the most negative smi. 2088 // This only happens for the most negative smi.
2122 Label slow; 2089 Label slow;
2123 __ j(negative, &slow); 2090 __ j(negative, &slow);
2124 2091
2125 // Smi case done. 2092 // Smi case done.
2126 __ ret(2 * kPointerSize); 2093 __ ret(2 * kPointerSize);
2127 2094
2128 // Check if the argument is a heap number and load its exponent and 2095 // Check if the argument is a heap number and load its exponent and
2129 // sign into ebx. 2096 // sign into ebx.
2130 __ bind(&not_smi); 2097 __ bind(&not_smi);
2131 __ CheckMap(eax, factory()->heap_number_map(), &slow, true); 2098 __ CheckMap(eax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK);
2132 __ mov(ebx, FieldOperand(eax, HeapNumber::kExponentOffset)); 2099 __ mov(ebx, FieldOperand(eax, HeapNumber::kExponentOffset));
2133 2100
2134 // Check the sign of the argument. If the argument is positive, 2101 // Check the sign of the argument. If the argument is positive,
2135 // just return it. 2102 // just return it.
2136 Label negative_sign; 2103 Label negative_sign;
2137 __ test(ebx, Immediate(HeapNumber::kSignMask)); 2104 __ test(ebx, Immediate(HeapNumber::kSignMask));
2138 __ j(not_zero, &negative_sign); 2105 __ j(not_zero, &negative_sign);
2139 __ ret(2 * kPointerSize); 2106 __ ret(2 * kPointerSize);
2140 2107
2141 // If the argument is negative, clear the sign, and return a new 2108 // If the argument is negative, clear the sign, and return a new
(...skipping 26 matching lines...) Expand all
2168 Object* object, 2135 Object* object,
2169 JSObject* holder, 2136 JSObject* holder,
2170 JSGlobalPropertyCell* cell, 2137 JSGlobalPropertyCell* cell,
2171 JSFunction* function, 2138 JSFunction* function,
2172 String* name) { 2139 String* name) {
2173 ASSERT(optimization.is_simple_api_call()); 2140 ASSERT(optimization.is_simple_api_call());
2174 // Bail out if object is a global object as we don't want to 2141 // Bail out if object is a global object as we don't want to
2175 // repatch it to global receiver. 2142 // repatch it to global receiver.
2176 if (object->IsGlobalObject()) return heap()->undefined_value(); 2143 if (object->IsGlobalObject()) return heap()->undefined_value();
2177 if (cell != NULL) return heap()->undefined_value(); 2144 if (cell != NULL) return heap()->undefined_value();
2145 if (!object->IsJSObject()) return heap()->undefined_value();
2178 int depth = optimization.GetPrototypeDepthOfExpectedType( 2146 int depth = optimization.GetPrototypeDepthOfExpectedType(
2179 JSObject::cast(object), holder); 2147 JSObject::cast(object), holder);
2180 if (depth == kInvalidProtoDepth) return heap()->undefined_value(); 2148 if (depth == kInvalidProtoDepth) return heap()->undefined_value();
2181 2149
2182 Label miss, miss_before_stack_reserved; 2150 Label miss, miss_before_stack_reserved;
2183 2151
2184 GenerateNameCheck(name, &miss_before_stack_reserved); 2152 GenerateNameCheck(name, &miss_before_stack_reserved);
2185 2153
2186 // Get the receiver from the stack. 2154 // Get the receiver from the stack.
2187 const int argc = arguments().immediate(); 2155 const int argc = arguments().immediate();
2188 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 2156 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
2189 2157
2190 // Check that the receiver isn't a smi. 2158 // Check that the receiver isn't a smi.
2191 __ test(edx, Immediate(kSmiTagMask)); 2159 __ test(edx, Immediate(kSmiTagMask));
2192 __ j(zero, &miss_before_stack_reserved, not_taken); 2160 __ j(zero, &miss_before_stack_reserved);
2193 2161
2194 Counters* counters = isolate()->counters(); 2162 Counters* counters = isolate()->counters();
2195 __ IncrementCounter(counters->call_const(), 1); 2163 __ IncrementCounter(counters->call_const(), 1);
2196 __ IncrementCounter(counters->call_const_fast_api(), 1); 2164 __ IncrementCounter(counters->call_const_fast_api(), 1);
2197 2165
2198 // Allocate space for v8::Arguments implicit values. Must be initialized 2166 // Allocate space for v8::Arguments implicit values. Must be initialized
2199 // before calling any runtime function. 2167 // before calling any runtime function.
2200 __ sub(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize)); 2168 __ sub(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize));
2201 2169
2202 // Check that the maps haven't changed and find a Holder as a side effect. 2170 // Check that the maps haven't changed and find a Holder as a side effect.
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
2250 2218
2251 GenerateNameCheck(name, &miss); 2219 GenerateNameCheck(name, &miss);
2252 2220
2253 // Get the receiver from the stack. 2221 // Get the receiver from the stack.
2254 const int argc = arguments().immediate(); 2222 const int argc = arguments().immediate();
2255 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 2223 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
2256 2224
2257 // Check that the receiver isn't a smi. 2225 // Check that the receiver isn't a smi.
2258 if (check != NUMBER_CHECK) { 2226 if (check != NUMBER_CHECK) {
2259 __ test(edx, Immediate(kSmiTagMask)); 2227 __ test(edx, Immediate(kSmiTagMask));
2260 __ j(zero, &miss, not_taken); 2228 __ j(zero, &miss);
2261 } 2229 }
2262 2230
2263 // Make sure that it's okay not to patch the on stack receiver 2231 // Make sure that it's okay not to patch the on stack receiver
2264 // unless we're doing a receiver map check. 2232 // unless we're doing a receiver map check.
2265 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); 2233 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
2266 2234
2267 SharedFunctionInfo* function_info = function->shared(); 2235 SharedFunctionInfo* function_info = function->shared();
2268 switch (check) { 2236 switch (check) {
2269 case RECEIVER_MAP_CHECK: 2237 case RECEIVER_MAP_CHECK:
2270 __ IncrementCounter(isolate()->counters()->call_const(), 1); 2238 __ IncrementCounter(isolate()->counters()->call_const(), 1);
(...skipping 11 matching lines...) Expand all
2282 break; 2250 break;
2283 2251
2284 case STRING_CHECK: 2252 case STRING_CHECK:
2285 if (!function->IsBuiltin() && !function_info->strict_mode()) { 2253 if (!function->IsBuiltin() && !function_info->strict_mode()) {
2286 // Calling non-strict non-builtins with a value as the receiver 2254 // Calling non-strict non-builtins with a value as the receiver
2287 // requires boxing. 2255 // requires boxing.
2288 __ jmp(&miss); 2256 __ jmp(&miss);
2289 } else { 2257 } else {
2290 // Check that the object is a string or a symbol. 2258 // Check that the object is a string or a symbol.
2291 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, eax); 2259 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, eax);
2292 __ j(above_equal, &miss, not_taken); 2260 __ j(above_equal, &miss);
2293 // Check that the maps starting from the prototype haven't changed. 2261 // Check that the maps starting from the prototype haven't changed.
2294 GenerateDirectLoadGlobalFunctionPrototype( 2262 GenerateDirectLoadGlobalFunctionPrototype(
2295 masm(), Context::STRING_FUNCTION_INDEX, eax, &miss); 2263 masm(), Context::STRING_FUNCTION_INDEX, eax, &miss);
2296 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, 2264 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder,
2297 ebx, edx, edi, name, &miss); 2265 ebx, edx, edi, name, &miss);
2298 } 2266 }
2299 break; 2267 break;
2300 2268
2301 case NUMBER_CHECK: { 2269 case NUMBER_CHECK: {
2302 if (!function->IsBuiltin() && !function_info->strict_mode()) { 2270 if (!function->IsBuiltin() && !function_info->strict_mode()) {
2303 // Calling non-strict non-builtins with a value as the receiver 2271 // Calling non-strict non-builtins with a value as the receiver
2304 // requires boxing. 2272 // requires boxing.
2305 __ jmp(&miss); 2273 __ jmp(&miss);
2306 } else { 2274 } else {
2307 Label fast; 2275 Label fast;
2308 // Check that the object is a smi or a heap number. 2276 // Check that the object is a smi or a heap number.
2309 __ test(edx, Immediate(kSmiTagMask)); 2277 __ test(edx, Immediate(kSmiTagMask));
2310 __ j(zero, &fast, taken); 2278 __ j(zero, &fast);
2311 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax); 2279 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax);
2312 __ j(not_equal, &miss, not_taken); 2280 __ j(not_equal, &miss);
2313 __ bind(&fast); 2281 __ bind(&fast);
2314 // Check that the maps starting from the prototype haven't changed. 2282 // Check that the maps starting from the prototype haven't changed.
2315 GenerateDirectLoadGlobalFunctionPrototype( 2283 GenerateDirectLoadGlobalFunctionPrototype(
2316 masm(), Context::NUMBER_FUNCTION_INDEX, eax, &miss); 2284 masm(), Context::NUMBER_FUNCTION_INDEX, eax, &miss);
2317 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, 2285 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder,
2318 ebx, edx, edi, name, &miss); 2286 ebx, edx, edi, name, &miss);
2319 } 2287 }
2320 break; 2288 break;
2321 } 2289 }
2322 2290
2323 case BOOLEAN_CHECK: { 2291 case BOOLEAN_CHECK: {
2324 if (!function->IsBuiltin() && !function_info->strict_mode()) { 2292 if (!function->IsBuiltin() && !function_info->strict_mode()) {
2325 // Calling non-strict non-builtins with a value as the receiver 2293 // Calling non-strict non-builtins with a value as the receiver
2326 // requires boxing. 2294 // requires boxing.
2327 __ jmp(&miss); 2295 __ jmp(&miss);
2328 } else { 2296 } else {
2329 Label fast; 2297 Label fast;
2330 // Check that the object is a boolean. 2298 // Check that the object is a boolean.
2331 __ cmp(edx, factory()->true_value()); 2299 __ cmp(edx, factory()->true_value());
2332 __ j(equal, &fast, taken); 2300 __ j(equal, &fast);
2333 __ cmp(edx, factory()->false_value()); 2301 __ cmp(edx, factory()->false_value());
2334 __ j(not_equal, &miss, not_taken); 2302 __ j(not_equal, &miss);
2335 __ bind(&fast); 2303 __ bind(&fast);
2336 // Check that the maps starting from the prototype haven't changed. 2304 // Check that the maps starting from the prototype haven't changed.
2337 GenerateDirectLoadGlobalFunctionPrototype( 2305 GenerateDirectLoadGlobalFunctionPrototype(
2338 masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss); 2306 masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss);
2339 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, 2307 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder,
2340 ebx, edx, edi, name, &miss); 2308 ebx, edx, edi, name, &miss);
2341 } 2309 }
2342 break; 2310 break;
2343 } 2311 }
2344 2312
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
2392 edi, 2360 edi,
2393 eax, 2361 eax,
2394 &miss); 2362 &miss);
2395 if (result->IsFailure()) return result; 2363 if (result->IsFailure()) return result;
2396 2364
2397 // Restore receiver. 2365 // Restore receiver.
2398 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 2366 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
2399 2367
2400 // Check that the function really is a function. 2368 // Check that the function really is a function.
2401 __ test(eax, Immediate(kSmiTagMask)); 2369 __ test(eax, Immediate(kSmiTagMask));
2402 __ j(zero, &miss, not_taken); 2370 __ j(zero, &miss);
2403 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); 2371 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
2404 __ j(not_equal, &miss, not_taken); 2372 __ j(not_equal, &miss);
2405 2373
2406 // Patch the receiver on the stack with the global proxy if 2374 // Patch the receiver on the stack with the global proxy if
2407 // necessary. 2375 // necessary.
2408 if (object->IsGlobalObject()) { 2376 if (object->IsGlobalObject()) {
2409 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 2377 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
2410 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 2378 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
2411 } 2379 }
2412 2380
2413 // Invoke the function. 2381 // Invoke the function.
2414 __ mov(edi, eax); 2382 __ mov(edi, eax);
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
2531 // ----------- S t a t e ------------- 2499 // ----------- S t a t e -------------
2532 // -- eax : value 2500 // -- eax : value
2533 // -- ecx : name 2501 // -- ecx : name
2534 // -- edx : receiver 2502 // -- edx : receiver
2535 // -- esp[0] : return address 2503 // -- esp[0] : return address
2536 // ----------------------------------- 2504 // -----------------------------------
2537 Label miss; 2505 Label miss;
2538 2506
2539 // Check that the object isn't a smi. 2507 // Check that the object isn't a smi.
2540 __ test(edx, Immediate(kSmiTagMask)); 2508 __ test(edx, Immediate(kSmiTagMask));
2541 __ j(zero, &miss, not_taken); 2509 __ j(zero, &miss);
2542 2510
2543 // Check that the map of the object hasn't changed. 2511 // Check that the map of the object hasn't changed.
2544 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), 2512 __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
2545 Immediate(Handle<Map>(object->map()))); 2513 Immediate(Handle<Map>(object->map())));
2546 __ j(not_equal, &miss, not_taken); 2514 __ j(not_equal, &miss);
2547 2515
2548 // Perform global security token check if needed. 2516 // Perform global security token check if needed.
2549 if (object->IsJSGlobalProxy()) { 2517 if (object->IsJSGlobalProxy()) {
2550 __ CheckAccessGlobalProxy(edx, ebx, &miss); 2518 __ CheckAccessGlobalProxy(edx, ebx, &miss);
2551 } 2519 }
2552 2520
2553 // Stub never generated for non-global objects that require access 2521 // Stub never generated for non-global objects that require access
2554 // checks. 2522 // checks.
2555 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 2523 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
2556 2524
(...skipping 24 matching lines...) Expand all
2581 // ----------- S t a t e ------------- 2549 // ----------- S t a t e -------------
2582 // -- eax : value 2550 // -- eax : value
2583 // -- ecx : name 2551 // -- ecx : name
2584 // -- edx : receiver 2552 // -- edx : receiver
2585 // -- esp[0] : return address 2553 // -- esp[0] : return address
2586 // ----------------------------------- 2554 // -----------------------------------
2587 Label miss; 2555 Label miss;
2588 2556
2589 // Check that the object isn't a smi. 2557 // Check that the object isn't a smi.
2590 __ test(edx, Immediate(kSmiTagMask)); 2558 __ test(edx, Immediate(kSmiTagMask));
2591 __ j(zero, &miss, not_taken); 2559 __ j(zero, &miss);
2592 2560
2593 // Check that the map of the object hasn't changed. 2561 // Check that the map of the object hasn't changed.
2594 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), 2562 __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
2595 Immediate(Handle<Map>(receiver->map()))); 2563 Immediate(Handle<Map>(receiver->map())));
2596 __ j(not_equal, &miss, not_taken); 2564 __ j(not_equal, &miss);
2597 2565
2598 // Perform global security token check if needed. 2566 // Perform global security token check if needed.
2599 if (receiver->IsJSGlobalProxy()) { 2567 if (receiver->IsJSGlobalProxy()) {
2600 __ CheckAccessGlobalProxy(edx, ebx, &miss); 2568 __ CheckAccessGlobalProxy(edx, ebx, &miss);
2601 } 2569 }
2602 2570
2603 // Stub never generated for non-global objects that require access 2571 // Stub never generated for non-global objects that require access
2604 // checks. 2572 // checks.
2605 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); 2573 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
2606 2574
(...skipping 26 matching lines...) Expand all
2633 // -- eax : value 2601 // -- eax : value
2634 // -- ecx : name 2602 // -- ecx : name
2635 // -- edx : receiver 2603 // -- edx : receiver
2636 // -- esp[0] : return address 2604 // -- esp[0] : return address
2637 // ----------------------------------- 2605 // -----------------------------------
2638 Label miss; 2606 Label miss;
2639 2607
2640 // Check that the map of the global has not changed. 2608 // Check that the map of the global has not changed.
2641 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), 2609 __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
2642 Immediate(Handle<Map>(object->map()))); 2610 Immediate(Handle<Map>(object->map())));
2643 __ j(not_equal, &miss, not_taken); 2611 __ j(not_equal, &miss);
2644 2612
2645 // Compute the cell operand to use. 2613 // Compute the cell operand to use.
2646 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); 2614 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell)));
2647 Operand cell_operand = FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset); 2615 Operand cell_operand = FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset);
2648 2616
2649 // Check that the value in the cell is not the hole. If it is, this 2617 // Check that the value in the cell is not the hole. If it is, this
2650 // cell could have been deleted and reintroducing the global needs 2618 // cell could have been deleted and reintroducing the global needs
2651 // to update the property details in the property dictionary of the 2619 // to update the property details in the property dictionary of the
2652 // global object. We bail out to the runtime system to do that. 2620 // global object. We bail out to the runtime system to do that.
2653 __ cmp(cell_operand, factory()->the_hole_value()); 2621 __ cmp(cell_operand, factory()->the_hole_value());
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
2697 // -- edx : receiver 2665 // -- edx : receiver
2698 // -- esp[0] : return address 2666 // -- esp[0] : return address
2699 // ----------------------------------- 2667 // -----------------------------------
2700 Label miss; 2668 Label miss;
2701 2669
2702 Counters* counters = isolate()->counters(); 2670 Counters* counters = isolate()->counters();
2703 __ IncrementCounter(counters->keyed_store_field(), 1); 2671 __ IncrementCounter(counters->keyed_store_field(), 1);
2704 2672
2705 // Check that the name has not changed. 2673 // Check that the name has not changed.
2706 __ cmp(Operand(ecx), Immediate(Handle<String>(name))); 2674 __ cmp(Operand(ecx), Immediate(Handle<String>(name)));
2707 __ j(not_equal, &miss, not_taken); 2675 __ j(not_equal, &miss);
2708 2676
2709 // Generate store field code. Trashes the name register. 2677 // Generate store field code. Trashes the name register.
2710 GenerateStoreField(masm(), 2678 GenerateStoreField(masm(),
2711 object, 2679 object,
2712 index, 2680 index,
2713 transition, 2681 transition,
2714 edx, ecx, ebx, 2682 edx, ecx, ebx,
2715 &miss); 2683 &miss);
2716 2684
2717 // Handle store cache miss. 2685 // Handle store cache miss.
2718 __ bind(&miss); 2686 __ bind(&miss);
2719 __ DecrementCounter(counters->keyed_store_field(), 1); 2687 __ DecrementCounter(counters->keyed_store_field(), 1);
2720 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); 2688 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2721 __ jmp(ic, RelocInfo::CODE_TARGET); 2689 __ jmp(ic, RelocInfo::CODE_TARGET);
2722 2690
2723 // Return the generated code. 2691 // Return the generated code.
2724 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); 2692 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
2725 } 2693 }
2726 2694
2727 2695
2728 MaybeObject* KeyedStoreStubCompiler::CompileStoreSpecialized( 2696 MaybeObject* KeyedStoreStubCompiler::CompileStoreFastElement(
2729 JSObject* receiver) { 2697 Map* receiver_map) {
2730 // ----------- S t a t e ------------- 2698 // ----------- S t a t e -------------
2731 // -- eax : value 2699 // -- eax : value
2732 // -- ecx : key 2700 // -- ecx : key
2733 // -- edx : receiver 2701 // -- edx : receiver
2734 // -- esp[0] : return address 2702 // -- esp[0] : return address
2735 // ----------------------------------- 2703 // -----------------------------------
2736 Label miss; 2704 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
2705 MaybeObject* maybe_stub =
2706 KeyedStoreFastElementStub(is_js_array).TryGetCode();
2707 Code* stub;
2708 if (!maybe_stub->To(&stub)) return maybe_stub;
2709 __ DispatchMap(edx,
2710 Handle<Map>(receiver_map),
2711 Handle<Code>(stub),
2712 DO_SMI_CHECK);
2737 2713
2738 // Check that the receiver isn't a smi.
2739 __ test(edx, Immediate(kSmiTagMask));
2740 __ j(zero, &miss, not_taken);
2741
2742 // Check that the map matches.
2743 __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
2744 Immediate(Handle<Map>(receiver->map())));
2745 __ j(not_equal, &miss, not_taken);
2746
2747 // Check that the key is a smi.
2748 __ test(ecx, Immediate(kSmiTagMask));
2749 __ j(not_zero, &miss, not_taken);
2750
2751 // Get the elements array and make sure it is a fast element array, not 'cow'.
2752 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
2753 __ cmp(FieldOperand(edi, HeapObject::kMapOffset),
2754 Immediate(factory()->fixed_array_map()));
2755 __ j(not_equal, &miss, not_taken);
2756
2757 // Check that the key is within bounds.
2758 if (receiver->IsJSArray()) {
2759 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis.
2760 __ j(above_equal, &miss, not_taken);
2761 } else {
2762 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // Compare smis.
2763 __ j(above_equal, &miss, not_taken);
2764 }
2765
2766 // Do the store and update the write barrier. Make sure to preserve
2767 // the value in register eax.
2768 __ mov(edx, Operand(eax));
2769 __ mov(FieldOperand(edi, ecx, times_2, FixedArray::kHeaderSize), eax);
2770 __ RecordWriteArray(edi, edx, ecx, kDontSaveFPRegs);
2771
2772 // Done.
2773 __ ret(0);
2774
2775 // Handle store cache miss.
2776 __ bind(&miss);
2777 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); 2714 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2778 __ jmp(ic, RelocInfo::CODE_TARGET); 2715 __ jmp(ic, RelocInfo::CODE_TARGET);
2779 2716
2780 // Return the generated code. 2717 // Return the generated code.
2781 return GetCode(NORMAL, NULL); 2718 return GetCode(NORMAL, NULL);
2782 } 2719 }
2783 2720
2784 2721
2722 MaybeObject* KeyedStoreStubCompiler::CompileStoreMegamorphic(
2723 MapList* receiver_maps,
2724 CodeList* handler_ics) {
2725 // ----------- S t a t e -------------
2726 // -- eax : value
2727 // -- ecx : key
2728 // -- edx : receiver
2729 // -- esp[0] : return address
2730 // -----------------------------------
2731 Label miss;
2732 __ JumpIfSmi(edx, &miss);
2733
2734 Register map_reg = ebx;
2735 __ mov(map_reg, FieldOperand(edx, HeapObject::kMapOffset));
2736 int receiver_count = receiver_maps->length();
2737 for (int current = 0; current < receiver_count; ++current) {
2738 Handle<Map> map(receiver_maps->at(current));
2739 __ cmp(map_reg, map);
2740 __ j(equal, Handle<Code>(handler_ics->at(current)));
2741 }
2742 __ bind(&miss);
2743 Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss();
2744 __ jmp(miss_ic, RelocInfo::CODE_TARGET);
2745
2746 // Return the generated code.
2747 return GetCode(NORMAL, NULL, MEGAMORPHIC);
2748 }
2749
2750
2785 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, 2751 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name,
2786 JSObject* object, 2752 JSObject* object,
2787 JSObject* last) { 2753 JSObject* last) {
2788 // ----------- S t a t e ------------- 2754 // ----------- S t a t e -------------
2789 // -- eax : receiver 2755 // -- eax : receiver
2790 // -- ecx : name 2756 // -- ecx : name
2791 // -- esp[0] : return address 2757 // -- esp[0] : return address
2792 // ----------------------------------- 2758 // -----------------------------------
2793 Label miss; 2759 Label miss;
2794 2760
2795 // Check that the receiver isn't a smi. 2761 // Check that the receiver isn't a smi.
2796 __ test(eax, Immediate(kSmiTagMask)); 2762 __ test(eax, Immediate(kSmiTagMask));
2797 __ j(zero, &miss, not_taken); 2763 __ j(zero, &miss);
2798 2764
2799 ASSERT(last->IsGlobalObject() || last->HasFastProperties()); 2765 ASSERT(last->IsGlobalObject() || last->HasFastProperties());
2800 2766
2801 // Check the maps of the full prototype chain. Also check that 2767 // Check the maps of the full prototype chain. Also check that
2802 // global property cells up to (but not including) the last object 2768 // global property cells up to (but not including) the last object
2803 // in the prototype chain are empty. 2769 // in the prototype chain are empty.
2804 CheckPrototypes(object, eax, last, ebx, edx, edi, name, &miss); 2770 CheckPrototypes(object, eax, last, ebx, edx, edi, name, &miss);
2805 2771
2806 // If the last object in the prototype chain is a global object, 2772 // If the last object in the prototype chain is a global object,
2807 // check that the global property cell is empty. 2773 // check that the global property cell is empty.
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
2940 // -- ecx : name 2906 // -- ecx : name
2941 // -- esp[0] : return address 2907 // -- esp[0] : return address
2942 // ----------------------------------- 2908 // -----------------------------------
2943 Label miss; 2909 Label miss;
2944 2910
2945 // If the object is the holder then we know that it's a global 2911 // If the object is the holder then we know that it's a global
2946 // object which can only happen for contextual loads. In this case, 2912 // object which can only happen for contextual loads. In this case,
2947 // the receiver cannot be a smi. 2913 // the receiver cannot be a smi.
2948 if (object != holder) { 2914 if (object != holder) {
2949 __ test(eax, Immediate(kSmiTagMask)); 2915 __ test(eax, Immediate(kSmiTagMask));
2950 __ j(zero, &miss, not_taken); 2916 __ j(zero, &miss);
2951 } 2917 }
2952 2918
2953 // Check that the maps haven't changed. 2919 // Check that the maps haven't changed.
2954 CheckPrototypes(object, eax, holder, ebx, edx, edi, name, &miss); 2920 CheckPrototypes(object, eax, holder, ebx, edx, edi, name, &miss);
2955 2921
2956 // Get the value from the cell. 2922 // Get the value from the cell.
2957 if (Serializer::enabled()) { 2923 if (Serializer::enabled()) {
2958 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); 2924 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell)));
2959 __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset)); 2925 __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset));
2960 } else { 2926 } else {
2961 __ mov(ebx, Operand::Cell(Handle<JSGlobalPropertyCell>(cell))); 2927 __ mov(ebx, Operand::Cell(Handle<JSGlobalPropertyCell>(cell)));
2962 } 2928 }
2963 2929
2964 // Check for deleted property if property can actually be deleted. 2930 // Check for deleted property if property can actually be deleted.
2965 if (!is_dont_delete) { 2931 if (!is_dont_delete) {
2966 __ cmp(ebx, factory()->the_hole_value()); 2932 __ cmp(ebx, factory()->the_hole_value());
2967 __ j(equal, &miss, not_taken); 2933 __ j(equal, &miss);
2968 } else if (FLAG_debug_code) { 2934 } else if (FLAG_debug_code) {
2969 __ cmp(ebx, factory()->the_hole_value()); 2935 __ cmp(ebx, factory()->the_hole_value());
2970 __ Check(not_equal, "DontDelete cells can't contain the hole"); 2936 __ Check(not_equal, "DontDelete cells can't contain the hole");
2971 } 2937 }
2972 2938
2973 Counters* counters = isolate()->counters(); 2939 Counters* counters = isolate()->counters();
2974 __ IncrementCounter(counters->named_load_global_stub(), 1); 2940 __ IncrementCounter(counters->named_load_global_stub(), 1);
2975 __ mov(eax, ebx); 2941 __ mov(eax, ebx);
2976 __ ret(0); 2942 __ ret(0);
2977 2943
(...skipping 15 matching lines...) Expand all
2993 // -- edx : receiver 2959 // -- edx : receiver
2994 // -- esp[0] : return address 2960 // -- esp[0] : return address
2995 // ----------------------------------- 2961 // -----------------------------------
2996 Label miss; 2962 Label miss;
2997 2963
2998 Counters* counters = isolate()->counters(); 2964 Counters* counters = isolate()->counters();
2999 __ IncrementCounter(counters->keyed_load_field(), 1); 2965 __ IncrementCounter(counters->keyed_load_field(), 1);
3000 2966
3001 // Check that the name has not changed. 2967 // Check that the name has not changed.
3002 __ cmp(Operand(eax), Immediate(Handle<String>(name))); 2968 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
3003 __ j(not_equal, &miss, not_taken); 2969 __ j(not_equal, &miss);
3004 2970
3005 GenerateLoadField(receiver, holder, edx, ebx, ecx, edi, index, name, &miss); 2971 GenerateLoadField(receiver, holder, edx, ebx, ecx, edi, index, name, &miss);
3006 2972
3007 __ bind(&miss); 2973 __ bind(&miss);
3008 __ DecrementCounter(counters->keyed_load_field(), 1); 2974 __ DecrementCounter(counters->keyed_load_field(), 1);
3009 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2975 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3010 2976
3011 // Return the generated code. 2977 // Return the generated code.
3012 return GetCode(FIELD, name); 2978 return GetCode(FIELD, name);
3013 } 2979 }
3014 2980
3015 2981
3016 MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback( 2982 MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback(
3017 String* name, 2983 String* name,
3018 JSObject* receiver, 2984 JSObject* receiver,
3019 JSObject* holder, 2985 JSObject* holder,
3020 AccessorInfo* callback) { 2986 AccessorInfo* callback) {
3021 // ----------- S t a t e ------------- 2987 // ----------- S t a t e -------------
3022 // -- eax : key 2988 // -- eax : key
3023 // -- edx : receiver 2989 // -- edx : receiver
3024 // -- esp[0] : return address 2990 // -- esp[0] : return address
3025 // ----------------------------------- 2991 // -----------------------------------
3026 Label miss; 2992 Label miss;
3027 2993
3028 Counters* counters = isolate()->counters(); 2994 Counters* counters = isolate()->counters();
3029 __ IncrementCounter(counters->keyed_load_callback(), 1); 2995 __ IncrementCounter(counters->keyed_load_callback(), 1);
3030 2996
3031 // Check that the name has not changed. 2997 // Check that the name has not changed.
3032 __ cmp(Operand(eax), Immediate(Handle<String>(name))); 2998 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
3033 __ j(not_equal, &miss, not_taken); 2999 __ j(not_equal, &miss);
3034 3000
3035 MaybeObject* result = GenerateLoadCallback(receiver, holder, edx, eax, ebx, 3001 MaybeObject* result = GenerateLoadCallback(receiver, holder, edx, eax, ebx,
3036 ecx, edi, callback, name, &miss); 3002 ecx, edi, callback, name, &miss);
3037 if (result->IsFailure()) { 3003 if (result->IsFailure()) {
3038 miss.Unuse(); 3004 miss.Unuse();
3039 return result; 3005 return result;
3040 } 3006 }
3041 3007
3042 __ bind(&miss); 3008 __ bind(&miss);
3043 3009
(...skipping 14 matching lines...) Expand all
3058 // -- edx : receiver 3024 // -- edx : receiver
3059 // -- esp[0] : return address 3025 // -- esp[0] : return address
3060 // ----------------------------------- 3026 // -----------------------------------
3061 Label miss; 3027 Label miss;
3062 3028
3063 Counters* counters = isolate()->counters(); 3029 Counters* counters = isolate()->counters();
3064 __ IncrementCounter(counters->keyed_load_constant_function(), 1); 3030 __ IncrementCounter(counters->keyed_load_constant_function(), 1);
3065 3031
3066 // Check that the name has not changed. 3032 // Check that the name has not changed.
3067 __ cmp(Operand(eax), Immediate(Handle<String>(name))); 3033 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
3068 __ j(not_equal, &miss, not_taken); 3034 __ j(not_equal, &miss);
3069 3035
3070 GenerateLoadConstant(receiver, holder, edx, ebx, ecx, edi, 3036 GenerateLoadConstant(receiver, holder, edx, ebx, ecx, edi,
3071 value, name, &miss); 3037 value, name, &miss);
3072 __ bind(&miss); 3038 __ bind(&miss);
3073 __ DecrementCounter(counters->keyed_load_constant_function(), 1); 3039 __ DecrementCounter(counters->keyed_load_constant_function(), 1);
3074 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3040 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3075 3041
3076 // Return the generated code. 3042 // Return the generated code.
3077 return GetCode(CONSTANT_FUNCTION, name); 3043 return GetCode(CONSTANT_FUNCTION, name);
3078 } 3044 }
3079 3045
3080 3046
3081 MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, 3047 MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
3082 JSObject* holder, 3048 JSObject* holder,
3083 String* name) { 3049 String* name) {
3084 // ----------- S t a t e ------------- 3050 // ----------- S t a t e -------------
3085 // -- eax : key 3051 // -- eax : key
3086 // -- edx : receiver 3052 // -- edx : receiver
3087 // -- esp[0] : return address 3053 // -- esp[0] : return address
3088 // ----------------------------------- 3054 // -----------------------------------
3089 Label miss; 3055 Label miss;
3090 3056
3091 Counters* counters = isolate()->counters(); 3057 Counters* counters = isolate()->counters();
3092 __ IncrementCounter(counters->keyed_load_interceptor(), 1); 3058 __ IncrementCounter(counters->keyed_load_interceptor(), 1);
3093 3059
3094 // Check that the name has not changed. 3060 // Check that the name has not changed.
3095 __ cmp(Operand(eax), Immediate(Handle<String>(name))); 3061 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
3096 __ j(not_equal, &miss, not_taken); 3062 __ j(not_equal, &miss);
3097 3063
3098 LookupResult lookup; 3064 LookupResult lookup;
3099 LookupPostInterceptor(holder, name, &lookup); 3065 LookupPostInterceptor(holder, name, &lookup);
3100 GenerateLoadInterceptor(receiver, 3066 GenerateLoadInterceptor(receiver,
3101 holder, 3067 holder,
3102 &lookup, 3068 &lookup,
3103 edx, 3069 edx,
3104 eax, 3070 eax,
3105 ecx, 3071 ecx,
3106 ebx, 3072 ebx,
(...skipping 15 matching lines...) Expand all
3122 // -- edx : receiver 3088 // -- edx : receiver
3123 // -- esp[0] : return address 3089 // -- esp[0] : return address
3124 // ----------------------------------- 3090 // -----------------------------------
3125 Label miss; 3091 Label miss;
3126 3092
3127 Counters* counters = isolate()->counters(); 3093 Counters* counters = isolate()->counters();
3128 __ IncrementCounter(counters->keyed_load_array_length(), 1); 3094 __ IncrementCounter(counters->keyed_load_array_length(), 1);
3129 3095
3130 // Check that the name has not changed. 3096 // Check that the name has not changed.
3131 __ cmp(Operand(eax), Immediate(Handle<String>(name))); 3097 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
3132 __ j(not_equal, &miss, not_taken); 3098 __ j(not_equal, &miss);
3133 3099
3134 GenerateLoadArrayLength(masm(), edx, ecx, &miss); 3100 GenerateLoadArrayLength(masm(), edx, ecx, &miss);
3135 __ bind(&miss); 3101 __ bind(&miss);
3136 __ DecrementCounter(counters->keyed_load_array_length(), 1); 3102 __ DecrementCounter(counters->keyed_load_array_length(), 1);
3137 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3103 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3138 3104
3139 // Return the generated code. 3105 // Return the generated code.
3140 return GetCode(CALLBACKS, name); 3106 return GetCode(CALLBACKS, name);
3141 } 3107 }
3142 3108
3143 3109
3144 MaybeObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) { 3110 MaybeObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
3145 // ----------- S t a t e ------------- 3111 // ----------- S t a t e -------------
3146 // -- eax : key 3112 // -- eax : key
3147 // -- edx : receiver 3113 // -- edx : receiver
3148 // -- esp[0] : return address 3114 // -- esp[0] : return address
3149 // ----------------------------------- 3115 // -----------------------------------
3150 Label miss; 3116 Label miss;
3151 3117
3152 Counters* counters = isolate()->counters(); 3118 Counters* counters = isolate()->counters();
3153 __ IncrementCounter(counters->keyed_load_string_length(), 1); 3119 __ IncrementCounter(counters->keyed_load_string_length(), 1);
3154 3120
3155 // Check that the name has not changed. 3121 // Check that the name has not changed.
3156 __ cmp(Operand(eax), Immediate(Handle<String>(name))); 3122 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
3157 __ j(not_equal, &miss, not_taken); 3123 __ j(not_equal, &miss);
3158 3124
3159 GenerateLoadStringLength(masm(), edx, ecx, ebx, &miss, true); 3125 GenerateLoadStringLength(masm(), edx, ecx, ebx, &miss, true);
3160 __ bind(&miss); 3126 __ bind(&miss);
3161 __ DecrementCounter(counters->keyed_load_string_length(), 1); 3127 __ DecrementCounter(counters->keyed_load_string_length(), 1);
3162 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3128 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3163 3129
3164 // Return the generated code. 3130 // Return the generated code.
3165 return GetCode(CALLBACKS, name); 3131 return GetCode(CALLBACKS, name);
3166 } 3132 }
3167 3133
3168 3134
3169 MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { 3135 MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
3170 // ----------- S t a t e ------------- 3136 // ----------- S t a t e -------------
3171 // -- eax : key 3137 // -- eax : key
3172 // -- edx : receiver 3138 // -- edx : receiver
3173 // -- esp[0] : return address 3139 // -- esp[0] : return address
3174 // ----------------------------------- 3140 // -----------------------------------
3175 Label miss; 3141 Label miss;
3176 3142
3177 Counters* counters = isolate()->counters(); 3143 Counters* counters = isolate()->counters();
3178 __ IncrementCounter(counters->keyed_load_function_prototype(), 1); 3144 __ IncrementCounter(counters->keyed_load_function_prototype(), 1);
3179 3145
3180 // Check that the name has not changed. 3146 // Check that the name has not changed.
3181 __ cmp(Operand(eax), Immediate(Handle<String>(name))); 3147 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
3182 __ j(not_equal, &miss, not_taken); 3148 __ j(not_equal, &miss);
3183 3149
3184 GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss); 3150 GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss);
3185 __ bind(&miss); 3151 __ bind(&miss);
3186 __ DecrementCounter(counters->keyed_load_function_prototype(), 1); 3152 __ DecrementCounter(counters->keyed_load_function_prototype(), 1);
3187 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3153 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3188 3154
3189 // Return the generated code. 3155 // Return the generated code.
3190 return GetCode(CALLBACKS, name); 3156 return GetCode(CALLBACKS, name);
3191 } 3157 }
3192 3158
3193 3159
3194 MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) { 3160 MaybeObject* KeyedLoadStubCompiler::CompileLoadFastElement(Map* receiver_map) {
3195 // ----------- S t a t e ------------- 3161 // ----------- S t a t e -------------
3196 // -- eax : key 3162 // -- eax : key
3197 // -- edx : receiver 3163 // -- edx : receiver
3198 // -- esp[0] : return address 3164 // -- esp[0] : return address
3199 // ----------------------------------- 3165 // -----------------------------------
3200 Label miss; 3166 MaybeObject* maybe_stub = KeyedLoadFastElementStub().TryGetCode();
3167 Code* stub;
3168 if (!maybe_stub->To(&stub)) return maybe_stub;
3169 __ DispatchMap(edx,
3170 Handle<Map>(receiver_map),
3171 Handle<Code>(stub),
3172 DO_SMI_CHECK);
3201 3173
3202 // Check that the receiver isn't a smi.
3203 __ test(edx, Immediate(kSmiTagMask));
3204 __ j(zero, &miss, not_taken);
3205
3206 // Check that the map matches.
3207 __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
3208 Immediate(Handle<Map>(receiver->map())));
3209 __ j(not_equal, &miss, not_taken);
3210
3211 // Check that the key is a smi.
3212 __ test(eax, Immediate(kSmiTagMask));
3213 __ j(not_zero, &miss, not_taken);
3214
3215 // Get the elements array.
3216 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
3217 __ AssertFastElements(ecx);
3218
3219 // Check that the key is within bounds.
3220 __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset));
3221 __ j(above_equal, &miss, not_taken);
3222
3223 // Load the result and make sure it's not the hole.
3224 __ mov(ebx, Operand(ecx, eax, times_2,
3225 FixedArray::kHeaderSize - kHeapObjectTag));
3226 __ cmp(ebx, factory()->the_hole_value());
3227 __ j(equal, &miss, not_taken);
3228 __ mov(eax, ebx);
3229 __ ret(0);
3230
3231 __ bind(&miss);
3232 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3174 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3233 3175
3234 // Return the generated code. 3176 // Return the generated code.
3235 return GetCode(NORMAL, NULL); 3177 return GetCode(NORMAL, NULL);
3236 } 3178 }
3237 3179
3238 3180
3181 MaybeObject* KeyedLoadStubCompiler::CompileLoadMegamorphic(
3182 MapList* receiver_maps,
3183 CodeList* handler_ics) {
3184 // ----------- S t a t e -------------
3185 // -- eax : key
3186 // -- edx : receiver
3187 // -- esp[0] : return address
3188 // -----------------------------------
3189 Label miss;
3190 __ JumpIfSmi(edx, &miss);
3191
3192 Register map_reg = ebx;
3193 __ mov(map_reg, FieldOperand(edx, HeapObject::kMapOffset));
3194 int receiver_count = receiver_maps->length();
3195 for (int current = 0; current < receiver_count; ++current) {
3196 Handle<Map> map(receiver_maps->at(current));
3197 __ cmp(map_reg, map);
3198 __ j(equal, Handle<Code>(handler_ics->at(current)));
3199 }
3200
3201 __ bind(&miss);
3202 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3203
3204 // Return the generated code.
3205 return GetCode(NORMAL, NULL, MEGAMORPHIC);
3206 }
3207
3208
3239 // Specialized stub for constructing objects from functions which only have only 3209 // Specialized stub for constructing objects from functions which only have only
3240 // simple assignments of the form this.x = ...; in their body. 3210 // simple assignments of the form this.x = ...; in their body.
3241 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { 3211 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
3242 // ----------- S t a t e ------------- 3212 // ----------- S t a t e -------------
3243 // -- eax : argc 3213 // -- eax : argc
3244 // -- edi : constructor 3214 // -- edi : constructor
3245 // -- esp[0] : return address 3215 // -- esp[0] : return address
3246 // -- esp[4] : last argument 3216 // -- esp[4] : last argument
3247 // ----------------------------------- 3217 // -----------------------------------
3248 Label generic_stub_call; 3218 Label generic_stub_call;
3249 #ifdef ENABLE_DEBUGGER_SUPPORT 3219 #ifdef ENABLE_DEBUGGER_SUPPORT
3250 // Check to see whether there are any break points in the function code. If 3220 // Check to see whether there are any break points in the function code. If
3251 // there are jump to the generic constructor stub which calls the actual 3221 // there are jump to the generic constructor stub which calls the actual
3252 // code for the function thereby hitting the break points. 3222 // code for the function thereby hitting the break points.
3253 __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 3223 __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
3254 __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kDebugInfoOffset)); 3224 __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kDebugInfoOffset));
3255 __ cmp(ebx, factory()->undefined_value()); 3225 __ cmp(ebx, factory()->undefined_value());
3256 __ j(not_equal, &generic_stub_call, not_taken); 3226 __ j(not_equal, &generic_stub_call);
3257 #endif 3227 #endif
3258 3228
3259 // Load the initial map and verify that it is in fact a map. 3229 // Load the initial map and verify that it is in fact a map.
3260 __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); 3230 __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
3261 // Will both indicate a NULL and a Smi. 3231 // Will both indicate a NULL and a Smi.
3262 __ test(ebx, Immediate(kSmiTagMask)); 3232 __ test(ebx, Immediate(kSmiTagMask));
3263 __ j(zero, &generic_stub_call); 3233 __ j(zero, &generic_stub_call);
3264 __ CmpObjectType(ebx, MAP_TYPE, ecx); 3234 __ CmpObjectType(ebx, MAP_TYPE, ecx);
3265 __ j(not_equal, &generic_stub_call); 3235 __ j(not_equal, &generic_stub_call);
3266 3236
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
3368 __ bind(&generic_stub_call); 3338 __ bind(&generic_stub_call);
3369 Handle<Code> generic_construct_stub = 3339 Handle<Code> generic_construct_stub =
3370 isolate()->builtins()->JSConstructStubGeneric(); 3340 isolate()->builtins()->JSConstructStubGeneric();
3371 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); 3341 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET);
3372 3342
3373 // Return the generated code. 3343 // Return the generated code.
3374 return GetCode(); 3344 return GetCode();
3375 } 3345 }
3376 3346
3377 3347
3378 MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( 3348 MaybeObject* ExternalArrayLoadStubCompiler::CompileLoad(
3379 JSObject*receiver, ExternalArrayType array_type, Code::Flags flags) { 3349 JSObject*receiver, ExternalArrayType array_type) {
3380 // ----------- S t a t e ------------- 3350 // ----------- S t a t e -------------
3381 // -- eax : key 3351 // -- eax : key
3382 // -- edx : receiver 3352 // -- edx : receiver
3383 // -- esp[0] : return address 3353 // -- esp[0] : return address
3384 // ----------------------------------- 3354 // -----------------------------------
3385 Label slow, failed_allocation; 3355 MaybeObject* maybe_stub =
3356 KeyedLoadExternalArrayStub(array_type).TryGetCode();
3357 Code* stub;
3358 if (!maybe_stub->To(&stub)) return maybe_stub;
3359 __ DispatchMap(edx,
3360 Handle<Map>(receiver->map()),
3361 Handle<Code>(stub),
3362 DO_SMI_CHECK);
3386 3363
3387 // Check that the object isn't a smi. 3364 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
3388 __ test(edx, Immediate(kSmiTagMask)); 3365 __ jmp(ic, RelocInfo::CODE_TARGET);
3389 __ j(zero, &slow, not_taken); 3366
3367 // Return the generated code.
3368 return GetCode();
3369 }
3370
3371
3372 MaybeObject* ExternalArrayStoreStubCompiler::CompileStore(
3373 JSObject* receiver, ExternalArrayType array_type) {
3374 // ----------- S t a t e -------------
3375 // -- eax : value
3376 // -- ecx : key
3377 // -- edx : receiver
3378 // -- esp[0] : return address
3379 // -----------------------------------
3380 MaybeObject* maybe_stub =
3381 KeyedStoreExternalArrayStub(array_type).TryGetCode();
3382 Code* stub;
3383 if (!maybe_stub->To(&stub)) return maybe_stub;
3384 __ DispatchMap(edx,
3385 Handle<Map>(receiver->map()),
3386 Handle<Code>(stub),
3387 DO_SMI_CHECK);
3388
3389 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
3390 __ jmp(ic, RelocInfo::CODE_TARGET);
3391
3392 return GetCode();
3393 }
3394
3395
3396 #undef __
3397 #define __ ACCESS_MASM(masm)
3398
3399
3400 void KeyedLoadStubCompiler::GenerateLoadExternalArray(
3401 MacroAssembler* masm,
3402 ExternalArrayType array_type) {
3403 // ----------- S t a t e -------------
3404 // -- eax : key
3405 // -- edx : receiver
3406 // -- esp[0] : return address
3407 // -----------------------------------
3408 Label miss_force_generic, failed_allocation, slow;
3409
3410 // This stub is meant to be tail-jumped to, the receiver must already
3411 // have been verified by the caller to not be a smi.
3390 3412
3391 // Check that the key is a smi. 3413 // Check that the key is a smi.
3392 __ test(eax, Immediate(kSmiTagMask)); 3414 __ test(eax, Immediate(kSmiTagMask));
3393 __ j(not_zero, &slow, not_taken); 3415 __ j(not_zero, &miss_force_generic);
3394 3416
3395 // Check that the map matches.
3396 __ CheckMap(edx, Handle<Map>(receiver->map()), &slow, false);
3397 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
3398
3399 // eax: key, known to be a smi.
3400 // edx: receiver, known to be a JSObject.
3401 // ebx: elements object, known to be an external array.
3402 // Check that the index is in range. 3417 // Check that the index is in range.
3403 __ mov(ecx, eax); 3418 __ mov(ecx, eax);
3404 __ SmiUntag(ecx); // Untag the index. 3419 __ SmiUntag(ecx); // Untag the index.
3420 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
3405 __ cmp(ecx, FieldOperand(ebx, ExternalArray::kLengthOffset)); 3421 __ cmp(ecx, FieldOperand(ebx, ExternalArray::kLengthOffset));
3406 // Unsigned comparison catches both negative and too-large values. 3422 // Unsigned comparison catches both negative and too-large values.
3407 __ j(above_equal, &slow); 3423 __ j(above_equal, &miss_force_generic);
3408 __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset)); 3424 __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset));
3409 // ebx: base pointer of external storage 3425 // ebx: base pointer of external storage
3410 switch (array_type) { 3426 switch (array_type) {
3411 case kExternalByteArray: 3427 case kExternalByteArray:
3412 __ movsx_b(eax, Operand(ebx, ecx, times_1, 0)); 3428 __ movsx_b(eax, Operand(ebx, ecx, times_1, 0));
3413 break; 3429 break;
3414 case kExternalUnsignedByteArray: 3430 case kExternalUnsignedByteArray:
3415 case kExternalPixelArray: 3431 case kExternalPixelArray:
3416 __ movzx_b(eax, Operand(ebx, ecx, times_1, 0)); 3432 __ movzx_b(eax, Operand(ebx, ecx, times_1, 0));
3417 break; 3433 break;
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
3504 3520
3505 // If we fail allocation of the HeapNumber, we still have a value on 3521 // If we fail allocation of the HeapNumber, we still have a value on
3506 // top of the FPU stack. Remove it. 3522 // top of the FPU stack. Remove it.
3507 __ bind(&failed_allocation); 3523 __ bind(&failed_allocation);
3508 __ ffree(); 3524 __ ffree();
3509 __ fincstp(); 3525 __ fincstp();
3510 // Fall through to slow case. 3526 // Fall through to slow case.
3511 3527
3512 // Slow case: Jump to runtime. 3528 // Slow case: Jump to runtime.
3513 __ bind(&slow); 3529 __ bind(&slow);
3514 Counters* counters = isolate()->counters(); 3530 Counters* counters = masm->isolate()->counters();
3515 __ IncrementCounter(counters->keyed_load_external_array_slow(), 1); 3531 __ IncrementCounter(counters->keyed_load_external_array_slow(), 1);
3532
3516 // ----------- S t a t e ------------- 3533 // ----------- S t a t e -------------
3517 // -- eax : key 3534 // -- eax : key
3518 // -- edx : receiver 3535 // -- edx : receiver
3519 // -- esp[0] : return address 3536 // -- esp[0] : return address
3520 // ----------------------------------- 3537 // -----------------------------------
3521 3538
3522 __ pop(ebx); 3539 Handle<Code> ic = masm->isolate()->builtins()->KeyedLoadIC_Slow();
3523 __ push(edx); // receiver 3540 __ jmp(ic, RelocInfo::CODE_TARGET);
3524 __ push(eax); // name
3525 __ push(ebx); // return address
3526 3541
3527 // Perform tail call to the entry. 3542 // ----------- S t a t e -------------
3528 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); 3543 // -- eax : key
3544 // -- edx : receiver
3545 // -- esp[0] : return address
3546 // -----------------------------------
3529 3547
3530 // Return the generated code. 3548 // Miss case: Jump to runtime.
3531 return GetCode(flags); 3549 __ bind(&miss_force_generic);
3550 Handle<Code> miss_ic =
3551 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
3552 __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3532 } 3553 }
3533 3554
3534 3555
3535 MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub( 3556 void KeyedStoreStubCompiler::GenerateStoreExternalArray(
3536 JSObject* receiver, ExternalArrayType array_type, Code::Flags flags) { 3557 MacroAssembler* masm,
3558 ExternalArrayType array_type) {
3537 // ----------- S t a t e ------------- 3559 // ----------- S t a t e -------------
3538 // -- eax : value 3560 // -- eax : key
3539 // -- ecx : key
3540 // -- edx : receiver 3561 // -- edx : receiver
3541 // -- esp[0] : return address 3562 // -- esp[0] : return address
3542 // ----------------------------------- 3563 // -----------------------------------
3543 Label slow, check_heap_number; 3564 Label miss_force_generic, slow, check_heap_number;
3544 3565
3545 // Check that the object isn't a smi. 3566 // This stub is meant to be tail-jumped to, the receiver must already
3546 __ test(edx, Immediate(kSmiTagMask)); 3567 // have been verified by the caller to not be a smi.
3547 __ j(zero, &slow);
3548
3549 // Check that the map matches.
3550 __ CheckMap(edx, Handle<Map>(receiver->map()), &slow, false);
3551 3568
3552 // Check that the key is a smi. 3569 // Check that the key is a smi.
3553 __ test(ecx, Immediate(kSmiTagMask)); 3570 __ test(ecx, Immediate(kSmiTagMask));
3554 __ j(not_zero, &slow); 3571 __ j(not_zero, &miss_force_generic);
3555 3572
3556 // Check that the index is in range. 3573 // Check that the index is in range.
3557 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 3574 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
3558 __ mov(ebx, ecx); 3575 __ mov(ebx, ecx);
3559 __ SmiUntag(ebx); 3576 __ SmiUntag(ebx);
3560 __ cmp(ebx, FieldOperand(edi, ExternalArray::kLengthOffset)); 3577 __ cmp(ebx, FieldOperand(edi, ExternalArray::kLengthOffset));
3561 // Unsigned comparison catches both negative and too-large values. 3578 // Unsigned comparison catches both negative and too-large values.
3562 __ j(above_equal, &slow); 3579 __ j(above_equal, &slow);
3563 3580
3564 // Handle both smis and HeapNumbers in the fast path. Go to the 3581 // Handle both smis and HeapNumbers in the fast path. Go to the
(...skipping 10 matching lines...) Expand all
3575 __ j(not_equal, &check_heap_number); 3592 __ j(not_equal, &check_heap_number);
3576 3593
3577 // smi case 3594 // smi case
3578 __ mov(ecx, eax); // Preserve the value in eax. Key is no longer needed. 3595 __ mov(ecx, eax); // Preserve the value in eax. Key is no longer needed.
3579 __ SmiUntag(ecx); 3596 __ SmiUntag(ecx);
3580 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); 3597 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset));
3581 // ecx: base pointer of external storage 3598 // ecx: base pointer of external storage
3582 switch (array_type) { 3599 switch (array_type) {
3583 case kExternalPixelArray: 3600 case kExternalPixelArray:
3584 { // Clamp the value to [0..255]. 3601 { // Clamp the value to [0..255].
3585 NearLabel done; 3602 Label done;
3586 __ test(ecx, Immediate(0xFFFFFF00)); 3603 __ test(ecx, Immediate(0xFFFFFF00));
3587 __ j(zero, &done); 3604 __ j(zero, &done, Label::kNear);
3588 __ setcc(negative, ecx); // 1 if negative, 0 if positive. 3605 __ setcc(negative, ecx); // 1 if negative, 0 if positive.
3589 __ dec_b(ecx); // 0 if negative, 255 if positive. 3606 __ dec_b(ecx); // 0 if negative, 255 if positive.
3590 __ bind(&done); 3607 __ bind(&done);
3591 } 3608 }
3592 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); 3609 __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
3593 break; 3610 break;
3594 case kExternalByteArray: 3611 case kExternalByteArray:
3595 case kExternalUnsignedByteArray: 3612 case kExternalUnsignedByteArray:
3596 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); 3613 __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
3597 break; 3614 break;
(...skipping 25 matching lines...) Expand all
3623 3640
3624 // TODO(danno): handle heap number -> pixel array conversion 3641 // TODO(danno): handle heap number -> pixel array conversion
3625 if (array_type != kExternalPixelArray) { 3642 if (array_type != kExternalPixelArray) {
3626 __ bind(&check_heap_number); 3643 __ bind(&check_heap_number);
3627 // eax: value 3644 // eax: value
3628 // edx: receiver 3645 // edx: receiver
3629 // ecx: key 3646 // ecx: key
3630 // edi: elements array 3647 // edi: elements array
3631 // ebx: untagged index 3648 // ebx: untagged index
3632 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), 3649 __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
3633 Immediate(factory()->heap_number_map())); 3650 Immediate(masm->isolate()->factory()->heap_number_map()));
3634 __ j(not_equal, &slow); 3651 __ j(not_equal, &slow);
3635 3652
3636 // The WebGL specification leaves the behavior of storing NaN and 3653 // The WebGL specification leaves the behavior of storing NaN and
3637 // +/-Infinity into integer arrays basically undefined. For more 3654 // +/-Infinity into integer arrays basically undefined. For more
3638 // reproducible behavior, convert these to zero. 3655 // reproducible behavior, convert these to zero.
3639 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); 3656 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset));
3640 // ebx: untagged index 3657 // ebx: untagged index
3641 // edi: base pointer of external storage 3658 // edi: base pointer of external storage
3642 if (array_type == kExternalFloatArray) { 3659 if (array_type == kExternalFloatArray) {
3643 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); 3660 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
(...skipping 14 matching lines...) Expand all
3658 if (CpuFeatures::IsSupported(SSE2)) { 3675 if (CpuFeatures::IsSupported(SSE2)) {
3659 if (array_type != kExternalIntArray && 3676 if (array_type != kExternalIntArray &&
3660 array_type != kExternalUnsignedIntArray) { 3677 array_type != kExternalUnsignedIntArray) {
3661 ASSERT(CpuFeatures::IsSupported(SSE2)); 3678 ASSERT(CpuFeatures::IsSupported(SSE2));
3662 CpuFeatures::Scope scope(SSE2); 3679 CpuFeatures::Scope scope(SSE2);
3663 __ cvttsd2si(ecx, FieldOperand(eax, HeapNumber::kValueOffset)); 3680 __ cvttsd2si(ecx, FieldOperand(eax, HeapNumber::kValueOffset));
3664 // ecx: untagged integer value 3681 // ecx: untagged integer value
3665 switch (array_type) { 3682 switch (array_type) {
3666 case kExternalPixelArray: 3683 case kExternalPixelArray:
3667 { // Clamp the value to [0..255]. 3684 { // Clamp the value to [0..255].
3668 NearLabel done; 3685 Label done;
3669 __ test(ecx, Immediate(0xFFFFFF00)); 3686 __ test(ecx, Immediate(0xFFFFFF00));
3670 __ j(zero, &done); 3687 __ j(zero, &done, Label::kNear);
3671 __ setcc(negative, ecx); // 1 if negative, 0 if positive. 3688 __ setcc(negative, ecx); // 1 if negative, 0 if positive.
3672 __ dec_b(ecx); // 0 if negative, 255 if positive. 3689 __ dec_b(ecx); // 0 if negative, 255 if positive.
3673 __ bind(&done); 3690 __ bind(&done);
3674 } 3691 }
3675 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); 3692 __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
3676 break; 3693 break;
3677 case kExternalByteArray: 3694 case kExternalByteArray:
3678 case kExternalUnsignedByteArray: 3695 case kExternalUnsignedByteArray:
3679 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); 3696 __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
3680 break; 3697 break;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
3718 // ecx: untagged integer value 3735 // ecx: untagged integer value
3719 __ mov(Operand(edi, ebx, times_4, 0), ecx); 3736 __ mov(Operand(edi, ebx, times_4, 0), ecx);
3720 } 3737 }
3721 __ ret(0); // Return original value. 3738 __ ret(0); // Return original value.
3722 } 3739 }
3723 } 3740 }
3724 } 3741 }
3725 3742
3726 // Slow case: call runtime. 3743 // Slow case: call runtime.
3727 __ bind(&slow); 3744 __ bind(&slow);
3745 Counters* counters = masm->isolate()->counters();
3746 __ IncrementCounter(counters->keyed_store_external_array_slow(), 1);
3747
3728 // ----------- S t a t e ------------- 3748 // ----------- S t a t e -------------
3729 // -- eax : value 3749 // -- eax : value
3730 // -- ecx : key 3750 // -- ecx : key
3731 // -- edx : receiver 3751 // -- edx : receiver
3732 // -- esp[0] : return address 3752 // -- esp[0] : return address
3733 // ----------------------------------- 3753 // -----------------------------------
3734 3754
3735 __ pop(ebx); 3755 Handle<Code> ic = masm->isolate()->builtins()->KeyedStoreIC_Slow();
3736 __ push(edx); 3756 __ jmp(ic, RelocInfo::CODE_TARGET);
3737 __ push(ecx);
3738 __ push(eax);
3739 __ push(Immediate(Smi::FromInt(NONE))); // PropertyAttributes
3740 __ push(Immediate(Smi::FromInt(
3741 Code::ExtractExtraICStateFromFlags(flags) & kStrictMode)));
3742 __ push(ebx); // return address
3743 3757
3744 // Do tail-call to runtime routine. 3758 // ----------- S t a t e -------------
3745 __ TailCallRuntime(Runtime::kSetProperty, 5, 1); 3759 // -- eax : value
3760 // -- ecx : key
3761 // -- edx : receiver
3762 // -- esp[0] : return address
3763 // -----------------------------------
3746 3764
3747 return GetCode(flags); 3765 __ bind(&miss_force_generic);
3766 Handle<Code> miss_ic =
3767 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
3768 __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3769 }
3770
3771
3772
3773
3774 void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
3775 // ----------- S t a t e -------------
3776 // -- eax : key
3777 // -- edx : receiver
3778 // -- esp[0] : return address
3779 // -----------------------------------
3780 Label miss_force_generic;
3781
3782 // This stub is meant to be tail-jumped to, the receiver must already
3783 // have been verified by the caller to not be a smi.
3784
3785 // Check that the key is a smi.
3786 __ test(eax, Immediate(kSmiTagMask));
3787 __ j(not_zero, &miss_force_generic);
3788
3789 // Get the elements array.
3790 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
3791 __ AssertFastElements(ecx);
3792
3793 // Check that the key is within bounds.
3794 __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset));
3795 __ j(above_equal, &miss_force_generic);
3796
3797 // Load the result and make sure it's not the hole.
3798 __ mov(ebx, Operand(ecx, eax, times_2,
3799 FixedArray::kHeaderSize - kHeapObjectTag));
3800 __ cmp(ebx, masm->isolate()->factory()->the_hole_value());
3801 __ j(equal, &miss_force_generic);
3802 __ mov(eax, ebx);
3803 __ ret(0);
3804
3805 __ bind(&miss_force_generic);
3806 Handle<Code> miss_ic =
3807 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
3808 __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3809 }
3810
3811
3812 void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
3813 bool is_js_array) {
3814 // ----------- S t a t e -------------
3815 // -- eax : key
3816 // -- edx : receiver
3817 // -- esp[0] : return address
3818 // -----------------------------------
3819 Label miss_force_generic;
3820
3821 // This stub is meant to be tail-jumped to, the receiver must already
3822 // have been verified by the caller to not be a smi.
3823
3824 // Check that the key is a smi.
3825 __ test(ecx, Immediate(kSmiTagMask));
3826 __ j(not_zero, &miss_force_generic);
3827
3828 // Get the elements array and make sure it is a fast element array, not 'cow'.
3829 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
3830 __ cmp(FieldOperand(edi, HeapObject::kMapOffset),
3831 Immediate(masm->isolate()->factory()->fixed_array_map()));
3832 __ j(not_equal, &miss_force_generic);
3833
3834 if (is_js_array) {
3835 // Check that the key is within bounds.
3836 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // smis.
3837 __ j(above_equal, &miss_force_generic);
3838 } else {
3839 // Check that the key is within bounds.
3840 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // smis.
3841 __ j(above_equal, &miss_force_generic);
3842 }
3843
3844 // Do the store and update the write barrier.
3845 __ lea(ecx, FieldOperand(edi, ecx, times_2, FixedArray::kHeaderSize));
3846 __ mov(Operand(ecx, 0), eax);
3847 // Make sure to preserve the value in register eax.
3848 __ mov(edx, Operand(eax));
3849 __ RecordWrite(edi, ecx, edx, kDontSaveFPRegs);
3850
3851 // Done.
3852 __ ret(0);
3853
3854 // Handle store cache miss, replacing the ic with the generic stub.
3855 __ bind(&miss_force_generic);
3856 Handle<Code> ic_force_generic =
3857 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
3858 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
3748 } 3859 }
3749 3860
3750 3861
3751 #undef __ 3862 #undef __
3752 3863
3753 } } // namespace v8::internal 3864 } } // namespace v8::internal
3754 3865
3755 #endif // V8_TARGET_ARCH_IA32 3866 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/simulator-ia32.h ('k') | src/ic.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698