OLD | NEW |
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 Loading... |
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, Label::kFar, not_taken); |
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, Label::kFar, not_taken); |
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 29 matching lines...) Expand all Loading... |
119 __ IncrementCounter(counters->negative_lookups_miss(), 1); | 119 __ IncrementCounter(counters->negative_lookups_miss(), 1); |
120 | 120 |
121 __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset)); | 121 __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset)); |
122 | 122 |
123 const int kInterceptorOrAccessCheckNeededMask = | 123 const int kInterceptorOrAccessCheckNeededMask = |
124 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); | 124 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); |
125 | 125 |
126 // 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. |
127 __ test_b(FieldOperand(r0, Map::kBitFieldOffset), | 127 __ test_b(FieldOperand(r0, Map::kBitFieldOffset), |
128 kInterceptorOrAccessCheckNeededMask); | 128 kInterceptorOrAccessCheckNeededMask); |
129 __ j(not_zero, miss_label, not_taken); | 129 __ j(not_zero, miss_label, Label::kFar, not_taken); |
130 | 130 |
131 // Check that receiver is a JSObject. | 131 // Check that receiver is a JSObject. |
132 __ CmpInstanceType(r0, FIRST_JS_OBJECT_TYPE); | 132 __ CmpInstanceType(r0, FIRST_JS_OBJECT_TYPE); |
133 __ j(below, miss_label, not_taken); | 133 __ j(below, miss_label, Label::kFar, not_taken); |
134 | 134 |
135 // Load properties array. | 135 // Load properties array. |
136 Register properties = r0; | 136 Register properties = r0; |
137 __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); | 137 __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); |
138 | 138 |
139 // Check that the properties array is a dictionary. | 139 // Check that the properties array is a dictionary. |
140 __ cmp(FieldOperand(properties, HeapObject::kMapOffset), | 140 __ cmp(FieldOperand(properties, HeapObject::kMapOffset), |
141 Immediate(masm->isolate()->factory()->hash_table_map())); | 141 Immediate(masm->isolate()->factory()->hash_table_map())); |
142 __ j(not_equal, miss_label); | 142 __ j(not_equal, miss_label); |
143 | 143 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
177 ASSERT(!extra.is(receiver)); | 177 ASSERT(!extra.is(receiver)); |
178 ASSERT(!extra.is(name)); | 178 ASSERT(!extra.is(name)); |
179 ASSERT(!extra.is(scratch)); | 179 ASSERT(!extra.is(scratch)); |
180 | 180 |
181 // Check scratch and extra registers are valid, and extra2 is unused. | 181 // Check scratch and extra registers are valid, and extra2 is unused. |
182 ASSERT(!scratch.is(no_reg)); | 182 ASSERT(!scratch.is(no_reg)); |
183 ASSERT(extra2.is(no_reg)); | 183 ASSERT(extra2.is(no_reg)); |
184 | 184 |
185 // Check that the receiver isn't a smi. | 185 // Check that the receiver isn't a smi. |
186 __ test(receiver, Immediate(kSmiTagMask)); | 186 __ test(receiver, Immediate(kSmiTagMask)); |
187 __ j(zero, &miss, not_taken); | 187 __ j(zero, &miss, Label::kFar, not_taken); |
188 | 188 |
189 // Get the map of the receiver and compute the hash. | 189 // Get the map of the receiver and compute the hash. |
190 __ mov(scratch, FieldOperand(name, String::kHashFieldOffset)); | 190 __ mov(scratch, FieldOperand(name, String::kHashFieldOffset)); |
191 __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); | 191 __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); |
192 __ xor_(scratch, flags); | 192 __ xor_(scratch, flags); |
193 __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize); | 193 __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize); |
194 | 194 |
195 // Probe the primary table. | 195 // Probe the primary table. |
196 ProbeTable(isolate, masm, flags, kPrimary, name, scratch, extra); | 196 ProbeTable(isolate, masm, flags, kPrimary, name, scratch, extra); |
197 | 197 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
238 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); | 238 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); |
239 } | 239 } |
240 | 240 |
241 | 241 |
242 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, | 242 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, |
243 Register receiver, | 243 Register receiver, |
244 Register scratch, | 244 Register scratch, |
245 Label* miss_label) { | 245 Label* miss_label) { |
246 // Check that the receiver isn't a smi. | 246 // Check that the receiver isn't a smi. |
247 __ test(receiver, Immediate(kSmiTagMask)); | 247 __ test(receiver, Immediate(kSmiTagMask)); |
248 __ j(zero, miss_label, not_taken); | 248 __ j(zero, miss_label, Label::kFar, not_taken); |
249 | 249 |
250 // Check that the object is a JS array. | 250 // Check that the object is a JS array. |
251 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); | 251 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); |
252 __ j(not_equal, miss_label, not_taken); | 252 __ j(not_equal, miss_label, Label::kFar, not_taken); |
253 | 253 |
254 // Load length directly from the JS array. | 254 // Load length directly from the JS array. |
255 __ mov(eax, FieldOperand(receiver, JSArray::kLengthOffset)); | 255 __ mov(eax, FieldOperand(receiver, JSArray::kLengthOffset)); |
256 __ ret(0); | 256 __ ret(0); |
257 } | 257 } |
258 | 258 |
259 | 259 |
260 // Generate code to check if an object is a string. If the object is | 260 // Generate code to check if an object is a string. If the object is |
261 // a string, the map's instance type is left in the scratch register. | 261 // a string, the map's instance type is left in the scratch register. |
262 static void GenerateStringCheck(MacroAssembler* masm, | 262 static void GenerateStringCheck(MacroAssembler* masm, |
263 Register receiver, | 263 Register receiver, |
264 Register scratch, | 264 Register scratch, |
265 Label* smi, | 265 Label* smi, |
266 Label* non_string_object) { | 266 Label* non_string_object) { |
267 // Check that the object isn't a smi. | 267 // Check that the object isn't a smi. |
268 __ test(receiver, Immediate(kSmiTagMask)); | 268 __ test(receiver, Immediate(kSmiTagMask)); |
269 __ j(zero, smi, not_taken); | 269 __ j(zero, smi, Label::kFar, not_taken); |
270 | 270 |
271 // Check that the object is a string. | 271 // Check that the object is a string. |
272 __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); | 272 __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); |
273 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); | 273 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); |
274 ASSERT(kNotStringTag != 0); | 274 ASSERT(kNotStringTag != 0); |
275 __ test(scratch, Immediate(kNotStringTag)); | 275 __ test(scratch, Immediate(kNotStringTag)); |
276 __ j(not_zero, non_string_object, not_taken); | 276 __ j(not_zero, non_string_object, Label::kFar, not_taken); |
277 } | 277 } |
278 | 278 |
279 | 279 |
280 void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, | 280 void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, |
281 Register receiver, | 281 Register receiver, |
282 Register scratch1, | 282 Register scratch1, |
283 Register scratch2, | 283 Register scratch2, |
284 Label* miss, | 284 Label* miss, |
285 bool support_wrappers) { | 285 bool support_wrappers) { |
286 Label check_wrapper; | 286 Label check_wrapper; |
287 | 287 |
288 // Check if the object is a string leaving the instance type in the | 288 // Check if the object is a string leaving the instance type in the |
289 // scratch register. | 289 // scratch register. |
290 GenerateStringCheck(masm, receiver, scratch1, miss, | 290 GenerateStringCheck(masm, receiver, scratch1, miss, |
291 support_wrappers ? &check_wrapper : miss); | 291 support_wrappers ? &check_wrapper : miss); |
292 | 292 |
293 // Load length from the string and convert to a smi. | 293 // Load length from the string and convert to a smi. |
294 __ mov(eax, FieldOperand(receiver, String::kLengthOffset)); | 294 __ mov(eax, FieldOperand(receiver, String::kLengthOffset)); |
295 __ ret(0); | 295 __ ret(0); |
296 | 296 |
297 if (support_wrappers) { | 297 if (support_wrappers) { |
298 // Check if the object is a JSValue wrapper. | 298 // Check if the object is a JSValue wrapper. |
299 __ bind(&check_wrapper); | 299 __ bind(&check_wrapper); |
300 __ cmp(scratch1, JS_VALUE_TYPE); | 300 __ cmp(scratch1, JS_VALUE_TYPE); |
301 __ j(not_equal, miss, not_taken); | 301 __ j(not_equal, miss, Label::kFar, not_taken); |
302 | 302 |
303 // Check if the wrapped value is a string and load the length | 303 // Check if the wrapped value is a string and load the length |
304 // directly if it is. | 304 // directly if it is. |
305 __ mov(scratch2, FieldOperand(receiver, JSValue::kValueOffset)); | 305 __ mov(scratch2, FieldOperand(receiver, JSValue::kValueOffset)); |
306 GenerateStringCheck(masm, scratch2, scratch1, miss, miss); | 306 GenerateStringCheck(masm, scratch2, scratch1, miss, miss); |
307 __ mov(eax, FieldOperand(scratch2, String::kLengthOffset)); | 307 __ mov(eax, FieldOperand(scratch2, String::kLengthOffset)); |
308 __ ret(0); | 308 __ ret(0); |
309 } | 309 } |
310 } | 310 } |
311 | 311 |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
496 Register receiver, | 496 Register receiver, |
497 Register scratch1, | 497 Register scratch1, |
498 Register scratch2, | 498 Register scratch2, |
499 Register scratch3, | 499 Register scratch3, |
500 Label* miss) { | 500 Label* miss) { |
501 ASSERT(holder->HasNamedInterceptor()); | 501 ASSERT(holder->HasNamedInterceptor()); |
502 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); | 502 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); |
503 | 503 |
504 // Check that the receiver isn't a smi. | 504 // Check that the receiver isn't a smi. |
505 __ test(receiver, Immediate(kSmiTagMask)); | 505 __ test(receiver, Immediate(kSmiTagMask)); |
506 __ j(zero, miss, not_taken); | 506 __ j(zero, miss, Label::kFar, not_taken); |
507 | 507 |
508 CallOptimization optimization(lookup); | 508 CallOptimization optimization(lookup); |
509 | 509 |
510 if (optimization.is_constant_call()) { | 510 if (optimization.is_constant_call()) { |
511 return CompileCacheable(masm, | 511 return CompileCacheable(masm, |
512 object, | 512 object, |
513 receiver, | 513 receiver, |
514 scratch1, | 514 scratch1, |
515 scratch2, | 515 scratch2, |
516 scratch3, | 516 scratch3, |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
713 void StubCompiler::GenerateStoreField(MacroAssembler* masm, | 713 void StubCompiler::GenerateStoreField(MacroAssembler* masm, |
714 JSObject* object, | 714 JSObject* object, |
715 int index, | 715 int index, |
716 Map* transition, | 716 Map* transition, |
717 Register receiver_reg, | 717 Register receiver_reg, |
718 Register name_reg, | 718 Register name_reg, |
719 Register scratch, | 719 Register scratch, |
720 Label* miss_label) { | 720 Label* miss_label) { |
721 // Check that the object isn't a smi. | 721 // Check that the object isn't a smi. |
722 __ test(receiver_reg, Immediate(kSmiTagMask)); | 722 __ test(receiver_reg, Immediate(kSmiTagMask)); |
723 __ j(zero, miss_label, not_taken); | 723 __ j(zero, miss_label, Label::kFar, not_taken); |
724 | 724 |
725 // Check that the map of the object hasn't changed. | 725 // Check that the map of the object hasn't changed. |
726 __ cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset), | 726 __ cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset), |
727 Immediate(Handle<Map>(object->map()))); | 727 Immediate(Handle<Map>(object->map()))); |
728 __ j(not_equal, miss_label, not_taken); | 728 __ j(not_equal, miss_label, Label::kFar, not_taken); |
729 | 729 |
730 // Perform global security token check if needed. | 730 // Perform global security token check if needed. |
731 if (object->IsJSGlobalProxy()) { | 731 if (object->IsJSGlobalProxy()) { |
732 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); | 732 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); |
733 } | 733 } |
734 | 734 |
735 // Stub never generated for non-global objects that require access | 735 // Stub never generated for non-global objects that require access |
736 // checks. | 736 // checks. |
737 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 737 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
738 | 738 |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
808 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); | 808 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); |
809 ASSERT(cell->value()->IsTheHole()); | 809 ASSERT(cell->value()->IsTheHole()); |
810 if (Serializer::enabled()) { | 810 if (Serializer::enabled()) { |
811 __ mov(scratch, Immediate(Handle<Object>(cell))); | 811 __ mov(scratch, Immediate(Handle<Object>(cell))); |
812 __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), | 812 __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), |
813 Immediate(masm->isolate()->factory()->the_hole_value())); | 813 Immediate(masm->isolate()->factory()->the_hole_value())); |
814 } else { | 814 } else { |
815 __ cmp(Operand::Cell(Handle<JSGlobalPropertyCell>(cell)), | 815 __ cmp(Operand::Cell(Handle<JSGlobalPropertyCell>(cell)), |
816 Immediate(masm->isolate()->factory()->the_hole_value())); | 816 Immediate(masm->isolate()->factory()->the_hole_value())); |
817 } | 817 } |
818 __ j(not_equal, miss, not_taken); | 818 __ j(not_equal, miss, Label::kFar, not_taken); |
819 return cell; | 819 return cell; |
820 } | 820 } |
821 | 821 |
822 | 822 |
823 // Calls GenerateCheckPropertyCell for each global object in the prototype chain | 823 // Calls GenerateCheckPropertyCell for each global object in the prototype chain |
824 // from object to (but not including) holder. | 824 // from object to (but not including) holder. |
825 MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCells( | 825 MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCells( |
826 MacroAssembler* masm, | 826 MacroAssembler* masm, |
827 JSObject* object, | 827 JSObject* object, |
828 JSObject* holder, | 828 JSObject* holder, |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
908 scratch1, | 908 scratch1, |
909 scratch2); | 909 scratch2); |
910 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 910 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
911 reg = holder_reg; // from now the object is in holder_reg | 911 reg = holder_reg; // from now the object is in holder_reg |
912 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 912 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
913 } else if (heap()->InNewSpace(prototype)) { | 913 } else if (heap()->InNewSpace(prototype)) { |
914 // Get the map of the current object. | 914 // Get the map of the current object. |
915 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 915 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
916 __ cmp(Operand(scratch1), Immediate(Handle<Map>(current->map()))); | 916 __ cmp(Operand(scratch1), Immediate(Handle<Map>(current->map()))); |
917 // Branch on the result of the map check. | 917 // Branch on the result of the map check. |
918 __ j(not_equal, miss, not_taken); | 918 __ j(not_equal, miss, Label::kFar, not_taken); |
919 // Check access rights to the global object. This has to happen | 919 // Check access rights to the global object. This has to happen |
920 // after the map check so that we know that the object is | 920 // after the map check so that we know that the object is |
921 // actually a global object. | 921 // actually a global object. |
922 if (current->IsJSGlobalProxy()) { | 922 if (current->IsJSGlobalProxy()) { |
923 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 923 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
924 | 924 |
925 // Restore scratch register to be the map of the object. | 925 // Restore scratch register to be the map of the object. |
926 // We load the prototype from the map in the scratch register. | 926 // We load the prototype from the map in the scratch register. |
927 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 927 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
928 } | 928 } |
929 // The prototype is in new space; we cannot store a reference | 929 // The prototype is in new space; we cannot store a reference |
930 // to it in the code. Load it from the map. | 930 // to it in the code. Load it from the map. |
931 reg = holder_reg; // from now the object is in holder_reg | 931 reg = holder_reg; // from now the object is in holder_reg |
932 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 932 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
933 } else { | 933 } else { |
934 // Check the map of the current object. | 934 // Check the map of the current object. |
935 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 935 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
936 Immediate(Handle<Map>(current->map()))); | 936 Immediate(Handle<Map>(current->map()))); |
937 // Branch on the result of the map check. | 937 // Branch on the result of the map check. |
938 __ j(not_equal, miss, not_taken); | 938 __ j(not_equal, miss, Label::kFar, not_taken); |
939 // Check access rights to the global object. This has to happen | 939 // Check access rights to the global object. This has to happen |
940 // after the map check so that we know that the object is | 940 // after the map check so that we know that the object is |
941 // actually a global object. | 941 // actually a global object. |
942 if (current->IsJSGlobalProxy()) { | 942 if (current->IsJSGlobalProxy()) { |
943 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 943 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
944 } | 944 } |
945 // The prototype is in old space; load it directly. | 945 // The prototype is in old space; load it directly. |
946 reg = holder_reg; // from now the object is in holder_reg | 946 reg = holder_reg; // from now the object is in holder_reg |
947 __ mov(reg, Handle<JSObject>(prototype)); | 947 __ mov(reg, Handle<JSObject>(prototype)); |
948 } | 948 } |
949 | 949 |
950 if (save_at_depth == depth) { | 950 if (save_at_depth == depth) { |
951 __ mov(Operand(esp, kPointerSize), reg); | 951 __ mov(Operand(esp, kPointerSize), reg); |
952 } | 952 } |
953 | 953 |
954 // Go to the next object in the prototype chain. | 954 // Go to the next object in the prototype chain. |
955 current = prototype; | 955 current = prototype; |
956 } | 956 } |
957 ASSERT(current == holder); | 957 ASSERT(current == holder); |
958 | 958 |
959 // Log the check depth. | 959 // Log the check depth. |
960 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 960 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
961 | 961 |
962 // Check the holder map. | 962 // Check the holder map. |
963 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 963 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
964 Immediate(Handle<Map>(holder->map()))); | 964 Immediate(Handle<Map>(holder->map()))); |
965 __ j(not_equal, miss, not_taken); | 965 __ j(not_equal, miss, Label::kFar, not_taken); |
966 | 966 |
967 // Perform security check for access to the global object. | 967 // Perform security check for access to the global object. |
968 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | 968 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
969 if (holder->IsJSGlobalProxy()) { | 969 if (holder->IsJSGlobalProxy()) { |
970 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 970 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
971 }; | 971 }; |
972 | 972 |
973 // If we've skipped any global objects, it's not enough to verify | 973 // If we've skipped any global objects, it's not enough to verify |
974 // that their maps haven't changed. We also need to check that the | 974 // that their maps haven't changed. We also need to check that the |
975 // property cell for the property is still empty. | 975 // property cell for the property is still empty. |
(...skipping 14 matching lines...) Expand all Loading... |
990 JSObject* holder, | 990 JSObject* holder, |
991 Register receiver, | 991 Register receiver, |
992 Register scratch1, | 992 Register scratch1, |
993 Register scratch2, | 993 Register scratch2, |
994 Register scratch3, | 994 Register scratch3, |
995 int index, | 995 int index, |
996 String* name, | 996 String* name, |
997 Label* miss) { | 997 Label* miss) { |
998 // Check that the receiver isn't a smi. | 998 // Check that the receiver isn't a smi. |
999 __ test(receiver, Immediate(kSmiTagMask)); | 999 __ test(receiver, Immediate(kSmiTagMask)); |
1000 __ j(zero, miss, not_taken); | 1000 __ j(zero, miss, Label::kFar, not_taken); |
1001 | 1001 |
1002 // Check the prototype chain. | 1002 // Check the prototype chain. |
1003 Register reg = | 1003 Register reg = |
1004 CheckPrototypes(object, receiver, holder, | 1004 CheckPrototypes(object, receiver, holder, |
1005 scratch1, scratch2, scratch3, name, miss); | 1005 scratch1, scratch2, scratch3, name, miss); |
1006 | 1006 |
1007 // Get the value from the properties. | 1007 // Get the value from the properties. |
1008 GenerateFastPropertyLoad(masm(), eax, reg, holder, index); | 1008 GenerateFastPropertyLoad(masm(), eax, reg, holder, index); |
1009 __ ret(0); | 1009 __ ret(0); |
1010 } | 1010 } |
1011 | 1011 |
1012 | 1012 |
1013 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object, | 1013 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object, |
1014 JSObject* holder, | 1014 JSObject* holder, |
1015 Register receiver, | 1015 Register receiver, |
1016 Register name_reg, | 1016 Register name_reg, |
1017 Register scratch1, | 1017 Register scratch1, |
1018 Register scratch2, | 1018 Register scratch2, |
1019 Register scratch3, | 1019 Register scratch3, |
1020 AccessorInfo* callback, | 1020 AccessorInfo* callback, |
1021 String* name, | 1021 String* name, |
1022 Label* miss) { | 1022 Label* miss) { |
1023 // Check that the receiver isn't a smi. | 1023 // Check that the receiver isn't a smi. |
1024 __ test(receiver, Immediate(kSmiTagMask)); | 1024 __ test(receiver, Immediate(kSmiTagMask)); |
1025 __ j(zero, miss, not_taken); | 1025 __ j(zero, miss, Label::kFar, not_taken); |
1026 | 1026 |
1027 // Check that the maps haven't changed. | 1027 // Check that the maps haven't changed. |
1028 Register reg = | 1028 Register reg = |
1029 CheckPrototypes(object, receiver, holder, scratch1, | 1029 CheckPrototypes(object, receiver, holder, scratch1, |
1030 scratch2, scratch3, name, miss); | 1030 scratch2, scratch3, name, miss); |
1031 | 1031 |
1032 Handle<AccessorInfo> callback_handle(callback); | 1032 Handle<AccessorInfo> callback_handle(callback); |
1033 | 1033 |
1034 // Insert additional parameters into the stack frame above return address. | 1034 // Insert additional parameters into the stack frame above return address. |
1035 ASSERT(!scratch3.is(reg)); | 1035 ASSERT(!scratch3.is(reg)); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1082 JSObject* holder, | 1082 JSObject* holder, |
1083 Register receiver, | 1083 Register receiver, |
1084 Register scratch1, | 1084 Register scratch1, |
1085 Register scratch2, | 1085 Register scratch2, |
1086 Register scratch3, | 1086 Register scratch3, |
1087 Object* value, | 1087 Object* value, |
1088 String* name, | 1088 String* name, |
1089 Label* miss) { | 1089 Label* miss) { |
1090 // Check that the receiver isn't a smi. | 1090 // Check that the receiver isn't a smi. |
1091 __ test(receiver, Immediate(kSmiTagMask)); | 1091 __ test(receiver, Immediate(kSmiTagMask)); |
1092 __ j(zero, miss, not_taken); | 1092 __ j(zero, miss, Label::kFar, not_taken); |
1093 | 1093 |
1094 // Check that the maps haven't changed. | 1094 // Check that the maps haven't changed. |
1095 CheckPrototypes(object, receiver, holder, | 1095 CheckPrototypes(object, receiver, holder, |
1096 scratch1, scratch2, scratch3, name, miss); | 1096 scratch1, scratch2, scratch3, name, miss); |
1097 | 1097 |
1098 // Return the constant value. | 1098 // Return the constant value. |
1099 __ mov(eax, Handle<Object>(value)); | 1099 __ mov(eax, Handle<Object>(value)); |
1100 __ ret(0); | 1100 __ ret(0); |
1101 } | 1101 } |
1102 | 1102 |
1103 | 1103 |
1104 void StubCompiler::GenerateLoadInterceptor(JSObject* object, | 1104 void StubCompiler::GenerateLoadInterceptor(JSObject* object, |
1105 JSObject* interceptor_holder, | 1105 JSObject* interceptor_holder, |
1106 LookupResult* lookup, | 1106 LookupResult* lookup, |
1107 Register receiver, | 1107 Register receiver, |
1108 Register name_reg, | 1108 Register name_reg, |
1109 Register scratch1, | 1109 Register scratch1, |
1110 Register scratch2, | 1110 Register scratch2, |
1111 Register scratch3, | 1111 Register scratch3, |
1112 String* name, | 1112 String* name, |
1113 Label* miss) { | 1113 Label* miss) { |
1114 ASSERT(interceptor_holder->HasNamedInterceptor()); | 1114 ASSERT(interceptor_holder->HasNamedInterceptor()); |
1115 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 1115 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); |
1116 | 1116 |
1117 // Check that the receiver isn't a smi. | 1117 // Check that the receiver isn't a smi. |
1118 __ test(receiver, Immediate(kSmiTagMask)); | 1118 __ test(receiver, Immediate(kSmiTagMask)); |
1119 __ j(zero, miss, not_taken); | 1119 __ j(zero, miss, Label::kFar, not_taken); |
1120 | 1120 |
1121 // So far the most popular follow ups for interceptor loads are FIELD | 1121 // So far the most popular follow ups for interceptor loads are FIELD |
1122 // and CALLBACKS, so inline only them, other cases may be added | 1122 // and CALLBACKS, so inline only them, other cases may be added |
1123 // later. | 1123 // later. |
1124 bool compile_followup_inline = false; | 1124 bool compile_followup_inline = false; |
1125 if (lookup->IsProperty() && lookup->IsCacheable()) { | 1125 if (lookup->IsProperty() && lookup->IsCacheable()) { |
1126 if (lookup->type() == FIELD) { | 1126 if (lookup->type() == FIELD) { |
1127 compile_followup_inline = true; | 1127 compile_followup_inline = true; |
1128 } else if (lookup->type() == CALLBACKS && | 1128 } else if (lookup->type() == CALLBACKS && |
1129 lookup->GetCallbackObject()->IsAccessorInfo() && | 1129 lookup->GetCallbackObject()->IsAccessorInfo() && |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1238 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), | 1238 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), |
1239 isolate()); | 1239 isolate()); |
1240 __ TailCallExternalReference(ref, 5, 1); | 1240 __ TailCallExternalReference(ref, 5, 1); |
1241 } | 1241 } |
1242 } | 1242 } |
1243 | 1243 |
1244 | 1244 |
1245 void CallStubCompiler::GenerateNameCheck(String* name, Label* miss) { | 1245 void CallStubCompiler::GenerateNameCheck(String* name, Label* miss) { |
1246 if (kind_ == Code::KEYED_CALL_IC) { | 1246 if (kind_ == Code::KEYED_CALL_IC) { |
1247 __ cmp(Operand(ecx), Immediate(Handle<String>(name))); | 1247 __ cmp(Operand(ecx), Immediate(Handle<String>(name))); |
1248 __ j(not_equal, miss, not_taken); | 1248 __ j(not_equal, miss, Label::kFar, not_taken); |
1249 } | 1249 } |
1250 } | 1250 } |
1251 | 1251 |
1252 | 1252 |
1253 void CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object, | 1253 void CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object, |
1254 JSObject* holder, | 1254 JSObject* holder, |
1255 String* name, | 1255 String* name, |
1256 Label* miss) { | 1256 Label* miss) { |
1257 ASSERT(holder->IsGlobalObject()); | 1257 ASSERT(holder->IsGlobalObject()); |
1258 | 1258 |
1259 // Get the number of arguments. | 1259 // Get the number of arguments. |
1260 const int argc = arguments().immediate(); | 1260 const int argc = arguments().immediate(); |
1261 | 1261 |
1262 // Get the receiver from the stack. | 1262 // Get the receiver from the stack. |
1263 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1263 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
1264 | 1264 |
1265 // If the object is the holder then we know that it's a global | 1265 // If the object is the holder then we know that it's a global |
1266 // object which can only happen for contextual calls. In this case, | 1266 // object which can only happen for contextual calls. In this case, |
1267 // the receiver cannot be a smi. | 1267 // the receiver cannot be a smi. |
1268 if (object != holder) { | 1268 if (object != holder) { |
1269 __ test(edx, Immediate(kSmiTagMask)); | 1269 __ test(edx, Immediate(kSmiTagMask)); |
1270 __ j(zero, miss, not_taken); | 1270 __ j(zero, miss, Label::kFar, not_taken); |
1271 } | 1271 } |
1272 | 1272 |
1273 // Check that the maps haven't changed. | 1273 // Check that the maps haven't changed. |
1274 CheckPrototypes(object, edx, holder, ebx, eax, edi, name, miss); | 1274 CheckPrototypes(object, edx, holder, ebx, eax, edi, name, miss); |
1275 } | 1275 } |
1276 | 1276 |
1277 | 1277 |
1278 void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell, | 1278 void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell, |
1279 JSFunction* function, | 1279 JSFunction* function, |
1280 Label* miss) { | 1280 Label* miss) { |
1281 // Get the value from the cell. | 1281 // Get the value from the cell. |
1282 if (Serializer::enabled()) { | 1282 if (Serializer::enabled()) { |
1283 __ mov(edi, Immediate(Handle<JSGlobalPropertyCell>(cell))); | 1283 __ mov(edi, Immediate(Handle<JSGlobalPropertyCell>(cell))); |
1284 __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset)); | 1284 __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset)); |
1285 } else { | 1285 } else { |
1286 __ mov(edi, Operand::Cell(Handle<JSGlobalPropertyCell>(cell))); | 1286 __ mov(edi, Operand::Cell(Handle<JSGlobalPropertyCell>(cell))); |
1287 } | 1287 } |
1288 | 1288 |
1289 // Check that the cell contains the same function. | 1289 // Check that the cell contains the same function. |
1290 if (isolate()->heap()->InNewSpace(function)) { | 1290 if (isolate()->heap()->InNewSpace(function)) { |
1291 // We can't embed a pointer to a function in new space so we have | 1291 // We can't embed a pointer to a function in new space so we have |
1292 // to verify that the shared function info is unchanged. This has | 1292 // to verify that the shared function info is unchanged. This has |
1293 // the nice side effect that multiple closures based on the same | 1293 // the nice side effect that multiple closures based on the same |
1294 // function can all use this call IC. Before we load through the | 1294 // function can all use this call IC. Before we load through the |
1295 // function, we have to verify that it still is a function. | 1295 // function, we have to verify that it still is a function. |
1296 __ test(edi, Immediate(kSmiTagMask)); | 1296 __ test(edi, Immediate(kSmiTagMask)); |
1297 __ j(zero, miss, not_taken); | 1297 __ j(zero, miss, Label::kFar, not_taken); |
1298 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); | 1298 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); |
1299 __ j(not_equal, miss, not_taken); | 1299 __ j(not_equal, miss, Label::kFar, not_taken); |
1300 | 1300 |
1301 // Check the shared function info. Make sure it hasn't changed. | 1301 // Check the shared function info. Make sure it hasn't changed. |
1302 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), | 1302 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), |
1303 Immediate(Handle<SharedFunctionInfo>(function->shared()))); | 1303 Immediate(Handle<SharedFunctionInfo>(function->shared()))); |
1304 __ j(not_equal, miss, not_taken); | 1304 __ j(not_equal, miss, Label::kFar, not_taken); |
1305 } else { | 1305 } else { |
1306 __ cmp(Operand(edi), Immediate(Handle<JSFunction>(function))); | 1306 __ cmp(Operand(edi), Immediate(Handle<JSFunction>(function))); |
1307 __ j(not_equal, miss, not_taken); | 1307 __ j(not_equal, miss, Label::kFar, not_taken); |
1308 } | 1308 } |
1309 } | 1309 } |
1310 | 1310 |
1311 | 1311 |
1312 MaybeObject* CallStubCompiler::GenerateMissBranch() { | 1312 MaybeObject* CallStubCompiler::GenerateMissBranch() { |
1313 MaybeObject* maybe_obj = | 1313 MaybeObject* maybe_obj = |
1314 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), | 1314 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), |
1315 kind_); | 1315 kind_); |
1316 Object* obj; | 1316 Object* obj; |
1317 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1317 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
(...skipping 17 matching lines...) Expand all Loading... |
1335 Label miss; | 1335 Label miss; |
1336 | 1336 |
1337 GenerateNameCheck(name, &miss); | 1337 GenerateNameCheck(name, &miss); |
1338 | 1338 |
1339 // Get the receiver from the stack. | 1339 // Get the receiver from the stack. |
1340 const int argc = arguments().immediate(); | 1340 const int argc = arguments().immediate(); |
1341 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1341 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
1342 | 1342 |
1343 // Check that the receiver isn't a smi. | 1343 // Check that the receiver isn't a smi. |
1344 __ test(edx, Immediate(kSmiTagMask)); | 1344 __ test(edx, Immediate(kSmiTagMask)); |
1345 __ j(zero, &miss, not_taken); | 1345 __ j(zero, &miss, Label::kFar, not_taken); |
1346 | 1346 |
1347 // Do the right check and compute the holder register. | 1347 // Do the right check and compute the holder register. |
1348 Register reg = CheckPrototypes(object, edx, holder, ebx, eax, edi, | 1348 Register reg = CheckPrototypes(object, edx, holder, ebx, eax, edi, |
1349 name, &miss); | 1349 name, &miss); |
1350 | 1350 |
1351 GenerateFastPropertyLoad(masm(), edi, reg, holder, index); | 1351 GenerateFastPropertyLoad(masm(), edi, reg, holder, index); |
1352 | 1352 |
1353 // Check that the function really is a function. | 1353 // Check that the function really is a function. |
1354 __ test(edi, Immediate(kSmiTagMask)); | 1354 __ test(edi, Immediate(kSmiTagMask)); |
1355 __ j(zero, &miss, not_taken); | 1355 __ j(zero, &miss, Label::kFar, not_taken); |
1356 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); | 1356 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); |
1357 __ j(not_equal, &miss, not_taken); | 1357 __ j(not_equal, &miss, Label::kFar, not_taken); |
1358 | 1358 |
1359 // Patch the receiver on the stack with the global proxy if | 1359 // Patch the receiver on the stack with the global proxy if |
1360 // necessary. | 1360 // necessary. |
1361 if (object->IsGlobalObject()) { | 1361 if (object->IsGlobalObject()) { |
1362 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 1362 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
1363 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 1363 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
1364 } | 1364 } |
1365 | 1365 |
1366 // Invoke the function. | 1366 // Invoke the function. |
1367 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION); | 1367 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION); |
(...skipping 744 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2112 Label miss, miss_before_stack_reserved; | 2112 Label miss, miss_before_stack_reserved; |
2113 | 2113 |
2114 GenerateNameCheck(name, &miss_before_stack_reserved); | 2114 GenerateNameCheck(name, &miss_before_stack_reserved); |
2115 | 2115 |
2116 // Get the receiver from the stack. | 2116 // Get the receiver from the stack. |
2117 const int argc = arguments().immediate(); | 2117 const int argc = arguments().immediate(); |
2118 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2118 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
2119 | 2119 |
2120 // Check that the receiver isn't a smi. | 2120 // Check that the receiver isn't a smi. |
2121 __ test(edx, Immediate(kSmiTagMask)); | 2121 __ test(edx, Immediate(kSmiTagMask)); |
2122 __ j(zero, &miss_before_stack_reserved, not_taken); | 2122 __ j(zero, &miss_before_stack_reserved, Label::kFar, not_taken); |
2123 | 2123 |
2124 Counters* counters = isolate()->counters(); | 2124 Counters* counters = isolate()->counters(); |
2125 __ IncrementCounter(counters->call_const(), 1); | 2125 __ IncrementCounter(counters->call_const(), 1); |
2126 __ IncrementCounter(counters->call_const_fast_api(), 1); | 2126 __ IncrementCounter(counters->call_const_fast_api(), 1); |
2127 | 2127 |
2128 // Allocate space for v8::Arguments implicit values. Must be initialized | 2128 // Allocate space for v8::Arguments implicit values. Must be initialized |
2129 // before calling any runtime function. | 2129 // before calling any runtime function. |
2130 __ sub(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize)); | 2130 __ sub(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize)); |
2131 | 2131 |
2132 // Check that the maps haven't changed and find a Holder as a side effect. | 2132 // 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 Loading... |
2180 | 2180 |
2181 GenerateNameCheck(name, &miss); | 2181 GenerateNameCheck(name, &miss); |
2182 | 2182 |
2183 // Get the receiver from the stack. | 2183 // Get the receiver from the stack. |
2184 const int argc = arguments().immediate(); | 2184 const int argc = arguments().immediate(); |
2185 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2185 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
2186 | 2186 |
2187 // Check that the receiver isn't a smi. | 2187 // Check that the receiver isn't a smi. |
2188 if (check != NUMBER_CHECK) { | 2188 if (check != NUMBER_CHECK) { |
2189 __ test(edx, Immediate(kSmiTagMask)); | 2189 __ test(edx, Immediate(kSmiTagMask)); |
2190 __ j(zero, &miss, not_taken); | 2190 __ j(zero, &miss, Label::kFar, not_taken); |
2191 } | 2191 } |
2192 | 2192 |
2193 // Make sure that it's okay not to patch the on stack receiver | 2193 // Make sure that it's okay not to patch the on stack receiver |
2194 // unless we're doing a receiver map check. | 2194 // unless we're doing a receiver map check. |
2195 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 2195 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
2196 | 2196 |
2197 SharedFunctionInfo* function_info = function->shared(); | 2197 SharedFunctionInfo* function_info = function->shared(); |
2198 switch (check) { | 2198 switch (check) { |
2199 case RECEIVER_MAP_CHECK: | 2199 case RECEIVER_MAP_CHECK: |
2200 __ IncrementCounter(isolate()->counters()->call_const(), 1); | 2200 __ IncrementCounter(isolate()->counters()->call_const(), 1); |
(...skipping 11 matching lines...) Expand all Loading... |
2212 break; | 2212 break; |
2213 | 2213 |
2214 case STRING_CHECK: | 2214 case STRING_CHECK: |
2215 if (!function->IsBuiltin() && !function_info->strict_mode()) { | 2215 if (!function->IsBuiltin() && !function_info->strict_mode()) { |
2216 // Calling non-strict non-builtins with a value as the receiver | 2216 // Calling non-strict non-builtins with a value as the receiver |
2217 // requires boxing. | 2217 // requires boxing. |
2218 __ jmp(&miss); | 2218 __ jmp(&miss); |
2219 } else { | 2219 } else { |
2220 // Check that the object is a string or a symbol. | 2220 // Check that the object is a string or a symbol. |
2221 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, eax); | 2221 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, eax); |
2222 __ j(above_equal, &miss, not_taken); | 2222 __ j(above_equal, &miss, Label::kFar, not_taken); |
2223 // Check that the maps starting from the prototype haven't changed. | 2223 // Check that the maps starting from the prototype haven't changed. |
2224 GenerateDirectLoadGlobalFunctionPrototype( | 2224 GenerateDirectLoadGlobalFunctionPrototype( |
2225 masm(), Context::STRING_FUNCTION_INDEX, eax, &miss); | 2225 masm(), Context::STRING_FUNCTION_INDEX, eax, &miss); |
2226 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 2226 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
2227 ebx, edx, edi, name, &miss); | 2227 ebx, edx, edi, name, &miss); |
2228 } | 2228 } |
2229 break; | 2229 break; |
2230 | 2230 |
2231 case NUMBER_CHECK: { | 2231 case NUMBER_CHECK: { |
2232 if (!function->IsBuiltin() && !function_info->strict_mode()) { | 2232 if (!function->IsBuiltin() && !function_info->strict_mode()) { |
2233 // Calling non-strict non-builtins with a value as the receiver | 2233 // Calling non-strict non-builtins with a value as the receiver |
2234 // requires boxing. | 2234 // requires boxing. |
2235 __ jmp(&miss); | 2235 __ jmp(&miss); |
2236 } else { | 2236 } else { |
2237 Label fast; | 2237 Label fast; |
2238 // Check that the object is a smi or a heap number. | 2238 // Check that the object is a smi or a heap number. |
2239 __ test(edx, Immediate(kSmiTagMask)); | 2239 __ test(edx, Immediate(kSmiTagMask)); |
2240 __ j(zero, &fast, taken); | 2240 __ j(zero, &fast, Label::kFar, taken); |
2241 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax); | 2241 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax); |
2242 __ j(not_equal, &miss, not_taken); | 2242 __ j(not_equal, &miss, Label::kFar, not_taken); |
2243 __ bind(&fast); | 2243 __ bind(&fast); |
2244 // Check that the maps starting from the prototype haven't changed. | 2244 // Check that the maps starting from the prototype haven't changed. |
2245 GenerateDirectLoadGlobalFunctionPrototype( | 2245 GenerateDirectLoadGlobalFunctionPrototype( |
2246 masm(), Context::NUMBER_FUNCTION_INDEX, eax, &miss); | 2246 masm(), Context::NUMBER_FUNCTION_INDEX, eax, &miss); |
2247 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 2247 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
2248 ebx, edx, edi, name, &miss); | 2248 ebx, edx, edi, name, &miss); |
2249 } | 2249 } |
2250 break; | 2250 break; |
2251 } | 2251 } |
2252 | 2252 |
2253 case BOOLEAN_CHECK: { | 2253 case BOOLEAN_CHECK: { |
2254 if (!function->IsBuiltin() && !function_info->strict_mode()) { | 2254 if (!function->IsBuiltin() && !function_info->strict_mode()) { |
2255 // Calling non-strict non-builtins with a value as the receiver | 2255 // Calling non-strict non-builtins with a value as the receiver |
2256 // requires boxing. | 2256 // requires boxing. |
2257 __ jmp(&miss); | 2257 __ jmp(&miss); |
2258 } else { | 2258 } else { |
2259 Label fast; | 2259 Label fast; |
2260 // Check that the object is a boolean. | 2260 // Check that the object is a boolean. |
2261 __ cmp(edx, factory()->true_value()); | 2261 __ cmp(edx, factory()->true_value()); |
2262 __ j(equal, &fast, taken); | 2262 __ j(equal, &fast, Label::kFar, taken); |
2263 __ cmp(edx, factory()->false_value()); | 2263 __ cmp(edx, factory()->false_value()); |
2264 __ j(not_equal, &miss, not_taken); | 2264 __ j(not_equal, &miss, Label::kFar, not_taken); |
2265 __ bind(&fast); | 2265 __ bind(&fast); |
2266 // Check that the maps starting from the prototype haven't changed. | 2266 // Check that the maps starting from the prototype haven't changed. |
2267 GenerateDirectLoadGlobalFunctionPrototype( | 2267 GenerateDirectLoadGlobalFunctionPrototype( |
2268 masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss); | 2268 masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss); |
2269 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 2269 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
2270 ebx, edx, edi, name, &miss); | 2270 ebx, edx, edi, name, &miss); |
2271 } | 2271 } |
2272 break; | 2272 break; |
2273 } | 2273 } |
2274 | 2274 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2322 edi, | 2322 edi, |
2323 eax, | 2323 eax, |
2324 &miss); | 2324 &miss); |
2325 if (result->IsFailure()) return result; | 2325 if (result->IsFailure()) return result; |
2326 | 2326 |
2327 // Restore receiver. | 2327 // Restore receiver. |
2328 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2328 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
2329 | 2329 |
2330 // Check that the function really is a function. | 2330 // Check that the function really is a function. |
2331 __ test(eax, Immediate(kSmiTagMask)); | 2331 __ test(eax, Immediate(kSmiTagMask)); |
2332 __ j(zero, &miss, not_taken); | 2332 __ j(zero, &miss, Label::kFar, not_taken); |
2333 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); | 2333 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); |
2334 __ j(not_equal, &miss, not_taken); | 2334 __ j(not_equal, &miss, Label::kFar, not_taken); |
2335 | 2335 |
2336 // Patch the receiver on the stack with the global proxy if | 2336 // Patch the receiver on the stack with the global proxy if |
2337 // necessary. | 2337 // necessary. |
2338 if (object->IsGlobalObject()) { | 2338 if (object->IsGlobalObject()) { |
2339 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 2339 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
2340 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 2340 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
2341 } | 2341 } |
2342 | 2342 |
2343 // Invoke the function. | 2343 // Invoke the function. |
2344 __ mov(edi, eax); | 2344 __ mov(edi, eax); |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2461 // ----------- S t a t e ------------- | 2461 // ----------- S t a t e ------------- |
2462 // -- eax : value | 2462 // -- eax : value |
2463 // -- ecx : name | 2463 // -- ecx : name |
2464 // -- edx : receiver | 2464 // -- edx : receiver |
2465 // -- esp[0] : return address | 2465 // -- esp[0] : return address |
2466 // ----------------------------------- | 2466 // ----------------------------------- |
2467 Label miss; | 2467 Label miss; |
2468 | 2468 |
2469 // Check that the object isn't a smi. | 2469 // Check that the object isn't a smi. |
2470 __ test(edx, Immediate(kSmiTagMask)); | 2470 __ test(edx, Immediate(kSmiTagMask)); |
2471 __ j(zero, &miss, not_taken); | 2471 __ j(zero, &miss, Label::kFar, not_taken); |
2472 | 2472 |
2473 // Check that the map of the object hasn't changed. | 2473 // Check that the map of the object hasn't changed. |
2474 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 2474 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
2475 Immediate(Handle<Map>(object->map()))); | 2475 Immediate(Handle<Map>(object->map()))); |
2476 __ j(not_equal, &miss, not_taken); | 2476 __ j(not_equal, &miss, Label::kFar, not_taken); |
2477 | 2477 |
2478 // Perform global security token check if needed. | 2478 // Perform global security token check if needed. |
2479 if (object->IsJSGlobalProxy()) { | 2479 if (object->IsJSGlobalProxy()) { |
2480 __ CheckAccessGlobalProxy(edx, ebx, &miss); | 2480 __ CheckAccessGlobalProxy(edx, ebx, &miss); |
2481 } | 2481 } |
2482 | 2482 |
2483 // Stub never generated for non-global objects that require access | 2483 // Stub never generated for non-global objects that require access |
2484 // checks. | 2484 // checks. |
2485 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 2485 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
2486 | 2486 |
(...skipping 24 matching lines...) Expand all Loading... |
2511 // ----------- S t a t e ------------- | 2511 // ----------- S t a t e ------------- |
2512 // -- eax : value | 2512 // -- eax : value |
2513 // -- ecx : name | 2513 // -- ecx : name |
2514 // -- edx : receiver | 2514 // -- edx : receiver |
2515 // -- esp[0] : return address | 2515 // -- esp[0] : return address |
2516 // ----------------------------------- | 2516 // ----------------------------------- |
2517 Label miss; | 2517 Label miss; |
2518 | 2518 |
2519 // Check that the object isn't a smi. | 2519 // Check that the object isn't a smi. |
2520 __ test(edx, Immediate(kSmiTagMask)); | 2520 __ test(edx, Immediate(kSmiTagMask)); |
2521 __ j(zero, &miss, not_taken); | 2521 __ j(zero, &miss, Label::kFar, not_taken); |
2522 | 2522 |
2523 // Check that the map of the object hasn't changed. | 2523 // Check that the map of the object hasn't changed. |
2524 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 2524 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
2525 Immediate(Handle<Map>(receiver->map()))); | 2525 Immediate(Handle<Map>(receiver->map()))); |
2526 __ j(not_equal, &miss, not_taken); | 2526 __ j(not_equal, &miss, Label::kFar, not_taken); |
2527 | 2527 |
2528 // Perform global security token check if needed. | 2528 // Perform global security token check if needed. |
2529 if (receiver->IsJSGlobalProxy()) { | 2529 if (receiver->IsJSGlobalProxy()) { |
2530 __ CheckAccessGlobalProxy(edx, ebx, &miss); | 2530 __ CheckAccessGlobalProxy(edx, ebx, &miss); |
2531 } | 2531 } |
2532 | 2532 |
2533 // Stub never generated for non-global objects that require access | 2533 // Stub never generated for non-global objects that require access |
2534 // checks. | 2534 // checks. |
2535 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); | 2535 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); |
2536 | 2536 |
(...skipping 26 matching lines...) Expand all Loading... |
2563 // -- eax : value | 2563 // -- eax : value |
2564 // -- ecx : name | 2564 // -- ecx : name |
2565 // -- edx : receiver | 2565 // -- edx : receiver |
2566 // -- esp[0] : return address | 2566 // -- esp[0] : return address |
2567 // ----------------------------------- | 2567 // ----------------------------------- |
2568 Label miss; | 2568 Label miss; |
2569 | 2569 |
2570 // Check that the map of the global has not changed. | 2570 // Check that the map of the global has not changed. |
2571 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 2571 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
2572 Immediate(Handle<Map>(object->map()))); | 2572 Immediate(Handle<Map>(object->map()))); |
2573 __ j(not_equal, &miss, not_taken); | 2573 __ j(not_equal, &miss, Label::kFar, not_taken); |
2574 | 2574 |
2575 | 2575 |
2576 // Compute the cell operand to use. | 2576 // Compute the cell operand to use. |
2577 Operand cell_operand = Operand::Cell(Handle<JSGlobalPropertyCell>(cell)); | 2577 Operand cell_operand = Operand::Cell(Handle<JSGlobalPropertyCell>(cell)); |
2578 if (Serializer::enabled()) { | 2578 if (Serializer::enabled()) { |
2579 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); | 2579 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); |
2580 cell_operand = FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset); | 2580 cell_operand = FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset); |
2581 } | 2581 } |
2582 | 2582 |
2583 // Check that the value in the cell is not the hole. If it is, this | 2583 // Check that the value in the cell is not the hole. If it is, this |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2616 // -- edx : receiver | 2616 // -- edx : receiver |
2617 // -- esp[0] : return address | 2617 // -- esp[0] : return address |
2618 // ----------------------------------- | 2618 // ----------------------------------- |
2619 Label miss; | 2619 Label miss; |
2620 | 2620 |
2621 Counters* counters = isolate()->counters(); | 2621 Counters* counters = isolate()->counters(); |
2622 __ IncrementCounter(counters->keyed_store_field(), 1); | 2622 __ IncrementCounter(counters->keyed_store_field(), 1); |
2623 | 2623 |
2624 // Check that the name has not changed. | 2624 // Check that the name has not changed. |
2625 __ cmp(Operand(ecx), Immediate(Handle<String>(name))); | 2625 __ cmp(Operand(ecx), Immediate(Handle<String>(name))); |
2626 __ j(not_equal, &miss, not_taken); | 2626 __ j(not_equal, &miss, Label::kFar, not_taken); |
2627 | 2627 |
2628 // Generate store field code. Trashes the name register. | 2628 // Generate store field code. Trashes the name register. |
2629 GenerateStoreField(masm(), | 2629 GenerateStoreField(masm(), |
2630 object, | 2630 object, |
2631 index, | 2631 index, |
2632 transition, | 2632 transition, |
2633 edx, ecx, ebx, | 2633 edx, ecx, ebx, |
2634 &miss); | 2634 &miss); |
2635 | 2635 |
2636 // Handle store cache miss. | 2636 // Handle store cache miss. |
(...skipping 12 matching lines...) Expand all Loading... |
2649 // ----------- S t a t e ------------- | 2649 // ----------- S t a t e ------------- |
2650 // -- eax : value | 2650 // -- eax : value |
2651 // -- ecx : key | 2651 // -- ecx : key |
2652 // -- edx : receiver | 2652 // -- edx : receiver |
2653 // -- esp[0] : return address | 2653 // -- esp[0] : return address |
2654 // ----------------------------------- | 2654 // ----------------------------------- |
2655 Label miss; | 2655 Label miss; |
2656 | 2656 |
2657 // Check that the receiver isn't a smi. | 2657 // Check that the receiver isn't a smi. |
2658 __ test(edx, Immediate(kSmiTagMask)); | 2658 __ test(edx, Immediate(kSmiTagMask)); |
2659 __ j(zero, &miss, not_taken); | 2659 __ j(zero, &miss, Label::kFar, not_taken); |
2660 | 2660 |
2661 // Check that the map matches. | 2661 // Check that the map matches. |
2662 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 2662 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
2663 Immediate(Handle<Map>(receiver->map()))); | 2663 Immediate(Handle<Map>(receiver->map()))); |
2664 __ j(not_equal, &miss, not_taken); | 2664 __ j(not_equal, &miss, Label::kFar, not_taken); |
2665 | 2665 |
2666 // Check that the key is a smi. | 2666 // Check that the key is a smi. |
2667 __ test(ecx, Immediate(kSmiTagMask)); | 2667 __ test(ecx, Immediate(kSmiTagMask)); |
2668 __ j(not_zero, &miss, not_taken); | 2668 __ j(not_zero, &miss, Label::kFar, not_taken); |
2669 | 2669 |
2670 // Get the elements array and make sure it is a fast element array, not 'cow'. | 2670 // Get the elements array and make sure it is a fast element array, not 'cow'. |
2671 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); | 2671 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
2672 __ cmp(FieldOperand(edi, HeapObject::kMapOffset), | 2672 __ cmp(FieldOperand(edi, HeapObject::kMapOffset), |
2673 Immediate(factory()->fixed_array_map())); | 2673 Immediate(factory()->fixed_array_map())); |
2674 __ j(not_equal, &miss, not_taken); | 2674 __ j(not_equal, &miss, Label::kFar, not_taken); |
2675 | 2675 |
2676 // Check that the key is within bounds. | 2676 // Check that the key is within bounds. |
2677 if (receiver->IsJSArray()) { | 2677 if (receiver->IsJSArray()) { |
2678 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis. | 2678 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis. |
2679 __ j(above_equal, &miss, not_taken); | 2679 __ j(above_equal, &miss, Label::kFar, not_taken); |
2680 } else { | 2680 } else { |
2681 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // Compare smis. | 2681 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // Compare smis. |
2682 __ j(above_equal, &miss, not_taken); | 2682 __ j(above_equal, &miss, Label::kFar, not_taken); |
2683 } | 2683 } |
2684 | 2684 |
2685 // Do the store and update the write barrier. Make sure to preserve | 2685 // Do the store and update the write barrier. Make sure to preserve |
2686 // the value in register eax. | 2686 // the value in register eax. |
2687 __ mov(edx, Operand(eax)); | 2687 __ mov(edx, Operand(eax)); |
2688 __ mov(FieldOperand(edi, ecx, times_2, FixedArray::kHeaderSize), eax); | 2688 __ mov(FieldOperand(edi, ecx, times_2, FixedArray::kHeaderSize), eax); |
2689 __ RecordWrite(edi, 0, edx, ecx); | 2689 __ RecordWrite(edi, 0, edx, ecx); |
2690 | 2690 |
2691 // Done. | 2691 // Done. |
2692 __ ret(0); | 2692 __ ret(0); |
(...skipping 13 matching lines...) Expand all Loading... |
2706 JSObject* last) { | 2706 JSObject* last) { |
2707 // ----------- S t a t e ------------- | 2707 // ----------- S t a t e ------------- |
2708 // -- eax : receiver | 2708 // -- eax : receiver |
2709 // -- ecx : name | 2709 // -- ecx : name |
2710 // -- esp[0] : return address | 2710 // -- esp[0] : return address |
2711 // ----------------------------------- | 2711 // ----------------------------------- |
2712 Label miss; | 2712 Label miss; |
2713 | 2713 |
2714 // Check that the receiver isn't a smi. | 2714 // Check that the receiver isn't a smi. |
2715 __ test(eax, Immediate(kSmiTagMask)); | 2715 __ test(eax, Immediate(kSmiTagMask)); |
2716 __ j(zero, &miss, not_taken); | 2716 __ j(zero, &miss, Label::kFar, not_taken); |
2717 | 2717 |
2718 ASSERT(last->IsGlobalObject() || last->HasFastProperties()); | 2718 ASSERT(last->IsGlobalObject() || last->HasFastProperties()); |
2719 | 2719 |
2720 // Check the maps of the full prototype chain. Also check that | 2720 // Check the maps of the full prototype chain. Also check that |
2721 // global property cells up to (but not including) the last object | 2721 // global property cells up to (but not including) the last object |
2722 // in the prototype chain are empty. | 2722 // in the prototype chain are empty. |
2723 CheckPrototypes(object, eax, last, ebx, edx, edi, name, &miss); | 2723 CheckPrototypes(object, eax, last, ebx, edx, edi, name, &miss); |
2724 | 2724 |
2725 // If the last object in the prototype chain is a global object, | 2725 // If the last object in the prototype chain is a global object, |
2726 // check that the global property cell is empty. | 2726 // check that the global property cell is empty. |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2859 // -- ecx : name | 2859 // -- ecx : name |
2860 // -- esp[0] : return address | 2860 // -- esp[0] : return address |
2861 // ----------------------------------- | 2861 // ----------------------------------- |
2862 Label miss; | 2862 Label miss; |
2863 | 2863 |
2864 // If the object is the holder then we know that it's a global | 2864 // If the object is the holder then we know that it's a global |
2865 // object which can only happen for contextual loads. In this case, | 2865 // object which can only happen for contextual loads. In this case, |
2866 // the receiver cannot be a smi. | 2866 // the receiver cannot be a smi. |
2867 if (object != holder) { | 2867 if (object != holder) { |
2868 __ test(eax, Immediate(kSmiTagMask)); | 2868 __ test(eax, Immediate(kSmiTagMask)); |
2869 __ j(zero, &miss, not_taken); | 2869 __ j(zero, &miss, Label::kFar, not_taken); |
2870 } | 2870 } |
2871 | 2871 |
2872 // Check that the maps haven't changed. | 2872 // Check that the maps haven't changed. |
2873 CheckPrototypes(object, eax, holder, ebx, edx, edi, name, &miss); | 2873 CheckPrototypes(object, eax, holder, ebx, edx, edi, name, &miss); |
2874 | 2874 |
2875 // Get the value from the cell. | 2875 // Get the value from the cell. |
2876 if (Serializer::enabled()) { | 2876 if (Serializer::enabled()) { |
2877 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); | 2877 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); |
2878 __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset)); | 2878 __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset)); |
2879 } else { | 2879 } else { |
2880 __ mov(ebx, Operand::Cell(Handle<JSGlobalPropertyCell>(cell))); | 2880 __ mov(ebx, Operand::Cell(Handle<JSGlobalPropertyCell>(cell))); |
2881 } | 2881 } |
2882 | 2882 |
2883 // Check for deleted property if property can actually be deleted. | 2883 // Check for deleted property if property can actually be deleted. |
2884 if (!is_dont_delete) { | 2884 if (!is_dont_delete) { |
2885 __ cmp(ebx, factory()->the_hole_value()); | 2885 __ cmp(ebx, factory()->the_hole_value()); |
2886 __ j(equal, &miss, not_taken); | 2886 __ j(equal, &miss, Label::kFar, not_taken); |
2887 } else if (FLAG_debug_code) { | 2887 } else if (FLAG_debug_code) { |
2888 __ cmp(ebx, factory()->the_hole_value()); | 2888 __ cmp(ebx, factory()->the_hole_value()); |
2889 __ Check(not_equal, "DontDelete cells can't contain the hole"); | 2889 __ Check(not_equal, "DontDelete cells can't contain the hole"); |
2890 } | 2890 } |
2891 | 2891 |
2892 Counters* counters = isolate()->counters(); | 2892 Counters* counters = isolate()->counters(); |
2893 __ IncrementCounter(counters->named_load_global_stub(), 1); | 2893 __ IncrementCounter(counters->named_load_global_stub(), 1); |
2894 __ mov(eax, ebx); | 2894 __ mov(eax, ebx); |
2895 __ ret(0); | 2895 __ ret(0); |
2896 | 2896 |
(...skipping 15 matching lines...) Expand all Loading... |
2912 // -- edx : receiver | 2912 // -- edx : receiver |
2913 // -- esp[0] : return address | 2913 // -- esp[0] : return address |
2914 // ----------------------------------- | 2914 // ----------------------------------- |
2915 Label miss; | 2915 Label miss; |
2916 | 2916 |
2917 Counters* counters = isolate()->counters(); | 2917 Counters* counters = isolate()->counters(); |
2918 __ IncrementCounter(counters->keyed_load_field(), 1); | 2918 __ IncrementCounter(counters->keyed_load_field(), 1); |
2919 | 2919 |
2920 // Check that the name has not changed. | 2920 // Check that the name has not changed. |
2921 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 2921 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
2922 __ j(not_equal, &miss, not_taken); | 2922 __ j(not_equal, &miss, Label::kFar, not_taken); |
2923 | 2923 |
2924 GenerateLoadField(receiver, holder, edx, ebx, ecx, edi, index, name, &miss); | 2924 GenerateLoadField(receiver, holder, edx, ebx, ecx, edi, index, name, &miss); |
2925 | 2925 |
2926 __ bind(&miss); | 2926 __ bind(&miss); |
2927 __ DecrementCounter(counters->keyed_load_field(), 1); | 2927 __ DecrementCounter(counters->keyed_load_field(), 1); |
2928 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2928 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
2929 | 2929 |
2930 // Return the generated code. | 2930 // Return the generated code. |
2931 return GetCode(FIELD, name); | 2931 return GetCode(FIELD, name); |
2932 } | 2932 } |
2933 | 2933 |
2934 | 2934 |
2935 MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback( | 2935 MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback( |
2936 String* name, | 2936 String* name, |
2937 JSObject* receiver, | 2937 JSObject* receiver, |
2938 JSObject* holder, | 2938 JSObject* holder, |
2939 AccessorInfo* callback) { | 2939 AccessorInfo* callback) { |
2940 // ----------- S t a t e ------------- | 2940 // ----------- S t a t e ------------- |
2941 // -- eax : key | 2941 // -- eax : key |
2942 // -- edx : receiver | 2942 // -- edx : receiver |
2943 // -- esp[0] : return address | 2943 // -- esp[0] : return address |
2944 // ----------------------------------- | 2944 // ----------------------------------- |
2945 Label miss; | 2945 Label miss; |
2946 | 2946 |
2947 Counters* counters = isolate()->counters(); | 2947 Counters* counters = isolate()->counters(); |
2948 __ IncrementCounter(counters->keyed_load_callback(), 1); | 2948 __ IncrementCounter(counters->keyed_load_callback(), 1); |
2949 | 2949 |
2950 // Check that the name has not changed. | 2950 // Check that the name has not changed. |
2951 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 2951 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
2952 __ j(not_equal, &miss, not_taken); | 2952 __ j(not_equal, &miss, Label::kFar, not_taken); |
2953 | 2953 |
2954 MaybeObject* result = GenerateLoadCallback(receiver, holder, edx, eax, ebx, | 2954 MaybeObject* result = GenerateLoadCallback(receiver, holder, edx, eax, ebx, |
2955 ecx, edi, callback, name, &miss); | 2955 ecx, edi, callback, name, &miss); |
2956 if (result->IsFailure()) { | 2956 if (result->IsFailure()) { |
2957 miss.Unuse(); | 2957 miss.Unuse(); |
2958 return result; | 2958 return result; |
2959 } | 2959 } |
2960 | 2960 |
2961 __ bind(&miss); | 2961 __ bind(&miss); |
2962 | 2962 |
(...skipping 14 matching lines...) Expand all Loading... |
2977 // -- edx : receiver | 2977 // -- edx : receiver |
2978 // -- esp[0] : return address | 2978 // -- esp[0] : return address |
2979 // ----------------------------------- | 2979 // ----------------------------------- |
2980 Label miss; | 2980 Label miss; |
2981 | 2981 |
2982 Counters* counters = isolate()->counters(); | 2982 Counters* counters = isolate()->counters(); |
2983 __ IncrementCounter(counters->keyed_load_constant_function(), 1); | 2983 __ IncrementCounter(counters->keyed_load_constant_function(), 1); |
2984 | 2984 |
2985 // Check that the name has not changed. | 2985 // Check that the name has not changed. |
2986 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 2986 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
2987 __ j(not_equal, &miss, not_taken); | 2987 __ j(not_equal, &miss, Label::kFar, not_taken); |
2988 | 2988 |
2989 GenerateLoadConstant(receiver, holder, edx, ebx, ecx, edi, | 2989 GenerateLoadConstant(receiver, holder, edx, ebx, ecx, edi, |
2990 value, name, &miss); | 2990 value, name, &miss); |
2991 __ bind(&miss); | 2991 __ bind(&miss); |
2992 __ DecrementCounter(counters->keyed_load_constant_function(), 1); | 2992 __ DecrementCounter(counters->keyed_load_constant_function(), 1); |
2993 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2993 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
2994 | 2994 |
2995 // Return the generated code. | 2995 // Return the generated code. |
2996 return GetCode(CONSTANT_FUNCTION, name); | 2996 return GetCode(CONSTANT_FUNCTION, name); |
2997 } | 2997 } |
2998 | 2998 |
2999 | 2999 |
3000 MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, | 3000 MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, |
3001 JSObject* holder, | 3001 JSObject* holder, |
3002 String* name) { | 3002 String* name) { |
3003 // ----------- S t a t e ------------- | 3003 // ----------- S t a t e ------------- |
3004 // -- eax : key | 3004 // -- eax : key |
3005 // -- edx : receiver | 3005 // -- edx : receiver |
3006 // -- esp[0] : return address | 3006 // -- esp[0] : return address |
3007 // ----------------------------------- | 3007 // ----------------------------------- |
3008 Label miss; | 3008 Label miss; |
3009 | 3009 |
3010 Counters* counters = isolate()->counters(); | 3010 Counters* counters = isolate()->counters(); |
3011 __ IncrementCounter(counters->keyed_load_interceptor(), 1); | 3011 __ IncrementCounter(counters->keyed_load_interceptor(), 1); |
3012 | 3012 |
3013 // Check that the name has not changed. | 3013 // Check that the name has not changed. |
3014 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 3014 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
3015 __ j(not_equal, &miss, not_taken); | 3015 __ j(not_equal, &miss, Label::kFar, not_taken); |
3016 | 3016 |
3017 LookupResult lookup; | 3017 LookupResult lookup; |
3018 LookupPostInterceptor(holder, name, &lookup); | 3018 LookupPostInterceptor(holder, name, &lookup); |
3019 GenerateLoadInterceptor(receiver, | 3019 GenerateLoadInterceptor(receiver, |
3020 holder, | 3020 holder, |
3021 &lookup, | 3021 &lookup, |
3022 edx, | 3022 edx, |
3023 eax, | 3023 eax, |
3024 ecx, | 3024 ecx, |
3025 ebx, | 3025 ebx, |
(...skipping 15 matching lines...) Expand all Loading... |
3041 // -- edx : receiver | 3041 // -- edx : receiver |
3042 // -- esp[0] : return address | 3042 // -- esp[0] : return address |
3043 // ----------------------------------- | 3043 // ----------------------------------- |
3044 Label miss; | 3044 Label miss; |
3045 | 3045 |
3046 Counters* counters = isolate()->counters(); | 3046 Counters* counters = isolate()->counters(); |
3047 __ IncrementCounter(counters->keyed_load_array_length(), 1); | 3047 __ IncrementCounter(counters->keyed_load_array_length(), 1); |
3048 | 3048 |
3049 // Check that the name has not changed. | 3049 // Check that the name has not changed. |
3050 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 3050 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
3051 __ j(not_equal, &miss, not_taken); | 3051 __ j(not_equal, &miss, Label::kFar, not_taken); |
3052 | 3052 |
3053 GenerateLoadArrayLength(masm(), edx, ecx, &miss); | 3053 GenerateLoadArrayLength(masm(), edx, ecx, &miss); |
3054 __ bind(&miss); | 3054 __ bind(&miss); |
3055 __ DecrementCounter(counters->keyed_load_array_length(), 1); | 3055 __ DecrementCounter(counters->keyed_load_array_length(), 1); |
3056 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3056 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3057 | 3057 |
3058 // Return the generated code. | 3058 // Return the generated code. |
3059 return GetCode(CALLBACKS, name); | 3059 return GetCode(CALLBACKS, name); |
3060 } | 3060 } |
3061 | 3061 |
3062 | 3062 |
3063 MaybeObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) { | 3063 MaybeObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) { |
3064 // ----------- S t a t e ------------- | 3064 // ----------- S t a t e ------------- |
3065 // -- eax : key | 3065 // -- eax : key |
3066 // -- edx : receiver | 3066 // -- edx : receiver |
3067 // -- esp[0] : return address | 3067 // -- esp[0] : return address |
3068 // ----------------------------------- | 3068 // ----------------------------------- |
3069 Label miss; | 3069 Label miss; |
3070 | 3070 |
3071 Counters* counters = isolate()->counters(); | 3071 Counters* counters = isolate()->counters(); |
3072 __ IncrementCounter(counters->keyed_load_string_length(), 1); | 3072 __ IncrementCounter(counters->keyed_load_string_length(), 1); |
3073 | 3073 |
3074 // Check that the name has not changed. | 3074 // Check that the name has not changed. |
3075 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 3075 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
3076 __ j(not_equal, &miss, not_taken); | 3076 __ j(not_equal, &miss, Label::kFar, not_taken); |
3077 | 3077 |
3078 GenerateLoadStringLength(masm(), edx, ecx, ebx, &miss, true); | 3078 GenerateLoadStringLength(masm(), edx, ecx, ebx, &miss, true); |
3079 __ bind(&miss); | 3079 __ bind(&miss); |
3080 __ DecrementCounter(counters->keyed_load_string_length(), 1); | 3080 __ DecrementCounter(counters->keyed_load_string_length(), 1); |
3081 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3081 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3082 | 3082 |
3083 // Return the generated code. | 3083 // Return the generated code. |
3084 return GetCode(CALLBACKS, name); | 3084 return GetCode(CALLBACKS, name); |
3085 } | 3085 } |
3086 | 3086 |
3087 | 3087 |
3088 MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { | 3088 MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { |
3089 // ----------- S t a t e ------------- | 3089 // ----------- S t a t e ------------- |
3090 // -- eax : key | 3090 // -- eax : key |
3091 // -- edx : receiver | 3091 // -- edx : receiver |
3092 // -- esp[0] : return address | 3092 // -- esp[0] : return address |
3093 // ----------------------------------- | 3093 // ----------------------------------- |
3094 Label miss; | 3094 Label miss; |
3095 | 3095 |
3096 Counters* counters = isolate()->counters(); | 3096 Counters* counters = isolate()->counters(); |
3097 __ IncrementCounter(counters->keyed_load_function_prototype(), 1); | 3097 __ IncrementCounter(counters->keyed_load_function_prototype(), 1); |
3098 | 3098 |
3099 // Check that the name has not changed. | 3099 // Check that the name has not changed. |
3100 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 3100 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
3101 __ j(not_equal, &miss, not_taken); | 3101 __ j(not_equal, &miss, Label::kFar, not_taken); |
3102 | 3102 |
3103 GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss); | 3103 GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss); |
3104 __ bind(&miss); | 3104 __ bind(&miss); |
3105 __ DecrementCounter(counters->keyed_load_function_prototype(), 1); | 3105 __ DecrementCounter(counters->keyed_load_function_prototype(), 1); |
3106 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3106 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3107 | 3107 |
3108 // Return the generated code. | 3108 // Return the generated code. |
3109 return GetCode(CALLBACKS, name); | 3109 return GetCode(CALLBACKS, name); |
3110 } | 3110 } |
3111 | 3111 |
3112 | 3112 |
3113 MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) { | 3113 MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) { |
3114 // ----------- S t a t e ------------- | 3114 // ----------- S t a t e ------------- |
3115 // -- eax : key | 3115 // -- eax : key |
3116 // -- edx : receiver | 3116 // -- edx : receiver |
3117 // -- esp[0] : return address | 3117 // -- esp[0] : return address |
3118 // ----------------------------------- | 3118 // ----------------------------------- |
3119 Label miss; | 3119 Label miss; |
3120 | 3120 |
3121 // Check that the receiver isn't a smi. | 3121 // Check that the receiver isn't a smi. |
3122 __ test(edx, Immediate(kSmiTagMask)); | 3122 __ test(edx, Immediate(kSmiTagMask)); |
3123 __ j(zero, &miss, not_taken); | 3123 __ j(zero, &miss, Label::kFar, not_taken); |
3124 | 3124 |
3125 // Check that the map matches. | 3125 // Check that the map matches. |
3126 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 3126 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
3127 Immediate(Handle<Map>(receiver->map()))); | 3127 Immediate(Handle<Map>(receiver->map()))); |
3128 __ j(not_equal, &miss, not_taken); | 3128 __ j(not_equal, &miss, Label::kFar, not_taken); |
3129 | 3129 |
3130 // Check that the key is a smi. | 3130 // Check that the key is a smi. |
3131 __ test(eax, Immediate(kSmiTagMask)); | 3131 __ test(eax, Immediate(kSmiTagMask)); |
3132 __ j(not_zero, &miss, not_taken); | 3132 __ j(not_zero, &miss, Label::kFar, not_taken); |
3133 | 3133 |
3134 // Get the elements array. | 3134 // Get the elements array. |
3135 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); | 3135 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); |
3136 __ AssertFastElements(ecx); | 3136 __ AssertFastElements(ecx); |
3137 | 3137 |
3138 // Check that the key is within bounds. | 3138 // Check that the key is within bounds. |
3139 __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset)); | 3139 __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset)); |
3140 __ j(above_equal, &miss, not_taken); | 3140 __ j(above_equal, &miss, Label::kFar, not_taken); |
3141 | 3141 |
3142 // Load the result and make sure it's not the hole. | 3142 // Load the result and make sure it's not the hole. |
3143 __ mov(ebx, Operand(ecx, eax, times_2, | 3143 __ mov(ebx, Operand(ecx, eax, times_2, |
3144 FixedArray::kHeaderSize - kHeapObjectTag)); | 3144 FixedArray::kHeaderSize - kHeapObjectTag)); |
3145 __ cmp(ebx, factory()->the_hole_value()); | 3145 __ cmp(ebx, factory()->the_hole_value()); |
3146 __ j(equal, &miss, not_taken); | 3146 __ j(equal, &miss, Label::kFar, not_taken); |
3147 __ mov(eax, ebx); | 3147 __ mov(eax, ebx); |
3148 __ ret(0); | 3148 __ ret(0); |
3149 | 3149 |
3150 __ bind(&miss); | 3150 __ bind(&miss); |
3151 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3151 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3152 | 3152 |
3153 // Return the generated code. | 3153 // Return the generated code. |
3154 return GetCode(NORMAL, NULL); | 3154 return GetCode(NORMAL, NULL); |
3155 } | 3155 } |
3156 | 3156 |
3157 | 3157 |
3158 // Specialized stub for constructing objects from functions which only have only | 3158 // Specialized stub for constructing objects from functions which only have only |
3159 // simple assignments of the form this.x = ...; in their body. | 3159 // simple assignments of the form this.x = ...; in their body. |
3160 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { | 3160 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { |
3161 // ----------- S t a t e ------------- | 3161 // ----------- S t a t e ------------- |
3162 // -- eax : argc | 3162 // -- eax : argc |
3163 // -- edi : constructor | 3163 // -- edi : constructor |
3164 // -- esp[0] : return address | 3164 // -- esp[0] : return address |
3165 // -- esp[4] : last argument | 3165 // -- esp[4] : last argument |
3166 // ----------------------------------- | 3166 // ----------------------------------- |
3167 Label generic_stub_call; | 3167 Label generic_stub_call; |
3168 #ifdef ENABLE_DEBUGGER_SUPPORT | 3168 #ifdef ENABLE_DEBUGGER_SUPPORT |
3169 // Check to see whether there are any break points in the function code. If | 3169 // Check to see whether there are any break points in the function code. If |
3170 // there are jump to the generic constructor stub which calls the actual | 3170 // there are jump to the generic constructor stub which calls the actual |
3171 // code for the function thereby hitting the break points. | 3171 // code for the function thereby hitting the break points. |
3172 __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 3172 __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
3173 __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kDebugInfoOffset)); | 3173 __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kDebugInfoOffset)); |
3174 __ cmp(ebx, factory()->undefined_value()); | 3174 __ cmp(ebx, factory()->undefined_value()); |
3175 __ j(not_equal, &generic_stub_call, not_taken); | 3175 __ j(not_equal, &generic_stub_call, Label::kFar, not_taken); |
3176 #endif | 3176 #endif |
3177 | 3177 |
3178 // Load the initial map and verify that it is in fact a map. | 3178 // Load the initial map and verify that it is in fact a map. |
3179 __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); | 3179 __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); |
3180 // Will both indicate a NULL and a Smi. | 3180 // Will both indicate a NULL and a Smi. |
3181 __ test(ebx, Immediate(kSmiTagMask)); | 3181 __ test(ebx, Immediate(kSmiTagMask)); |
3182 __ j(zero, &generic_stub_call); | 3182 __ j(zero, &generic_stub_call); |
3183 __ CmpObjectType(ebx, MAP_TYPE, ecx); | 3183 __ CmpObjectType(ebx, MAP_TYPE, ecx); |
3184 __ j(not_equal, &generic_stub_call); | 3184 __ j(not_equal, &generic_stub_call); |
3185 | 3185 |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3298 JSObject*receiver, ExternalArrayType array_type, Code::Flags flags) { | 3298 JSObject*receiver, ExternalArrayType array_type, Code::Flags flags) { |
3299 // ----------- S t a t e ------------- | 3299 // ----------- S t a t e ------------- |
3300 // -- eax : key | 3300 // -- eax : key |
3301 // -- edx : receiver | 3301 // -- edx : receiver |
3302 // -- esp[0] : return address | 3302 // -- esp[0] : return address |
3303 // ----------------------------------- | 3303 // ----------------------------------- |
3304 Label slow, failed_allocation; | 3304 Label slow, failed_allocation; |
3305 | 3305 |
3306 // Check that the object isn't a smi. | 3306 // Check that the object isn't a smi. |
3307 __ test(edx, Immediate(kSmiTagMask)); | 3307 __ test(edx, Immediate(kSmiTagMask)); |
3308 __ j(zero, &slow, not_taken); | 3308 __ j(zero, &slow, Label::kFar, not_taken); |
3309 | 3309 |
3310 // Check that the key is a smi. | 3310 // Check that the key is a smi. |
3311 __ test(eax, Immediate(kSmiTagMask)); | 3311 __ test(eax, Immediate(kSmiTagMask)); |
3312 __ j(not_zero, &slow, not_taken); | 3312 __ j(not_zero, &slow, Label::kFar, not_taken); |
3313 | 3313 |
3314 // Check that the map matches. | 3314 // Check that the map matches. |
3315 __ CheckMap(edx, Handle<Map>(receiver->map()), &slow, false); | 3315 __ CheckMap(edx, Handle<Map>(receiver->map()), &slow, false); |
3316 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); | 3316 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); |
3317 | 3317 |
3318 // eax: key, known to be a smi. | 3318 // eax: key, known to be a smi. |
3319 // edx: receiver, known to be a JSObject. | 3319 // edx: receiver, known to be a JSObject. |
3320 // ebx: elements object, known to be an external array. | 3320 // ebx: elements object, known to be an external array. |
3321 // Check that the index is in range. | 3321 // Check that the index is in range. |
3322 __ mov(ecx, eax); | 3322 __ mov(ecx, eax); |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3494 __ j(not_equal, &check_heap_number); | 3494 __ j(not_equal, &check_heap_number); |
3495 | 3495 |
3496 // smi case | 3496 // smi case |
3497 __ mov(ecx, eax); // Preserve the value in eax. Key is no longer needed. | 3497 __ mov(ecx, eax); // Preserve the value in eax. Key is no longer needed. |
3498 __ SmiUntag(ecx); | 3498 __ SmiUntag(ecx); |
3499 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); | 3499 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); |
3500 // ecx: base pointer of external storage | 3500 // ecx: base pointer of external storage |
3501 switch (array_type) { | 3501 switch (array_type) { |
3502 case kExternalPixelArray: | 3502 case kExternalPixelArray: |
3503 { // Clamp the value to [0..255]. | 3503 { // Clamp the value to [0..255]. |
3504 NearLabel done; | 3504 Label done; |
3505 __ test(ecx, Immediate(0xFFFFFF00)); | 3505 __ test(ecx, Immediate(0xFFFFFF00)); |
3506 __ j(zero, &done); | 3506 __ j(zero, &done, Label::kNear); |
3507 __ setcc(negative, ecx); // 1 if negative, 0 if positive. | 3507 __ setcc(negative, ecx); // 1 if negative, 0 if positive. |
3508 __ dec_b(ecx); // 0 if negative, 255 if positive. | 3508 __ dec_b(ecx); // 0 if negative, 255 if positive. |
3509 __ bind(&done); | 3509 __ bind(&done); |
3510 } | 3510 } |
3511 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); | 3511 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); |
3512 break; | 3512 break; |
3513 case kExternalByteArray: | 3513 case kExternalByteArray: |
3514 case kExternalUnsignedByteArray: | 3514 case kExternalUnsignedByteArray: |
3515 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); | 3515 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); |
3516 break; | 3516 break; |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3577 if (CpuFeatures::IsSupported(SSE2)) { | 3577 if (CpuFeatures::IsSupported(SSE2)) { |
3578 if (array_type != kExternalIntArray && | 3578 if (array_type != kExternalIntArray && |
3579 array_type != kExternalUnsignedIntArray) { | 3579 array_type != kExternalUnsignedIntArray) { |
3580 ASSERT(CpuFeatures::IsSupported(SSE2)); | 3580 ASSERT(CpuFeatures::IsSupported(SSE2)); |
3581 CpuFeatures::Scope scope(SSE2); | 3581 CpuFeatures::Scope scope(SSE2); |
3582 __ cvttsd2si(ecx, FieldOperand(eax, HeapNumber::kValueOffset)); | 3582 __ cvttsd2si(ecx, FieldOperand(eax, HeapNumber::kValueOffset)); |
3583 // ecx: untagged integer value | 3583 // ecx: untagged integer value |
3584 switch (array_type) { | 3584 switch (array_type) { |
3585 case kExternalPixelArray: | 3585 case kExternalPixelArray: |
3586 { // Clamp the value to [0..255]. | 3586 { // Clamp the value to [0..255]. |
3587 NearLabel done; | 3587 Label done; |
3588 __ test(ecx, Immediate(0xFFFFFF00)); | 3588 __ test(ecx, Immediate(0xFFFFFF00)); |
3589 __ j(zero, &done); | 3589 __ j(zero, &done, Label::kNear); |
3590 __ setcc(negative, ecx); // 1 if negative, 0 if positive. | 3590 __ setcc(negative, ecx); // 1 if negative, 0 if positive. |
3591 __ dec_b(ecx); // 0 if negative, 255 if positive. | 3591 __ dec_b(ecx); // 0 if negative, 255 if positive. |
3592 __ bind(&done); | 3592 __ bind(&done); |
3593 } | 3593 } |
3594 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); | 3594 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); |
3595 break; | 3595 break; |
3596 case kExternalByteArray: | 3596 case kExternalByteArray: |
3597 case kExternalUnsignedByteArray: | 3597 case kExternalUnsignedByteArray: |
3598 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); | 3598 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); |
3599 break; | 3599 break; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3665 | 3665 |
3666 return GetCode(flags); | 3666 return GetCode(flags); |
3667 } | 3667 } |
3668 | 3668 |
3669 | 3669 |
3670 #undef __ | 3670 #undef __ |
3671 | 3671 |
3672 } } // namespace v8::internal | 3672 } } // namespace v8::internal |
3673 | 3673 |
3674 #endif // V8_TARGET_ARCH_IA32 | 3674 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |