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); |
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 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); |
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); |
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 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
182 ASSERT(!extra.is(receiver)); | 182 ASSERT(!extra.is(receiver)); |
183 ASSERT(!extra.is(name)); | 183 ASSERT(!extra.is(name)); |
184 ASSERT(!extra.is(scratch)); | 184 ASSERT(!extra.is(scratch)); |
185 | 185 |
186 // Check scratch and extra registers are valid, and extra2 is unused. | 186 // Check scratch and extra registers are valid, and extra2 is unused. |
187 ASSERT(!scratch.is(no_reg)); | 187 ASSERT(!scratch.is(no_reg)); |
188 ASSERT(extra2.is(no_reg)); | 188 ASSERT(extra2.is(no_reg)); |
189 | 189 |
190 // Check that the receiver isn't a smi. | 190 // Check that the receiver isn't a smi. |
191 __ test(receiver, Immediate(kSmiTagMask)); | 191 __ test(receiver, Immediate(kSmiTagMask)); |
192 __ j(zero, &miss, not_taken); | 192 __ j(zero, &miss); |
193 | 193 |
194 // Get the map of the receiver and compute the hash. | 194 // Get the map of the receiver and compute the hash. |
195 __ mov(scratch, FieldOperand(name, String::kHashFieldOffset)); | 195 __ mov(scratch, FieldOperand(name, String::kHashFieldOffset)); |
196 __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); | 196 __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); |
197 __ xor_(scratch, flags); | 197 __ xor_(scratch, flags); |
198 __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize); | 198 __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize); |
199 | 199 |
200 // Probe the primary table. | 200 // Probe the primary table. |
201 ProbeTable(isolate, masm, flags, kPrimary, name, scratch, extra); | 201 ProbeTable(isolate, masm, flags, kPrimary, name, scratch, extra); |
202 | 202 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); | 243 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); |
244 } | 244 } |
245 | 245 |
246 | 246 |
247 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, | 247 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, |
248 Register receiver, | 248 Register receiver, |
249 Register scratch, | 249 Register scratch, |
250 Label* miss_label) { | 250 Label* miss_label) { |
251 // Check that the receiver isn't a smi. | 251 // Check that the receiver isn't a smi. |
252 __ test(receiver, Immediate(kSmiTagMask)); | 252 __ test(receiver, Immediate(kSmiTagMask)); |
253 __ j(zero, miss_label, not_taken); | 253 __ j(zero, miss_label); |
254 | 254 |
255 // Check that the object is a JS array. | 255 // Check that the object is a JS array. |
256 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); | 256 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); |
257 __ j(not_equal, miss_label, not_taken); | 257 __ j(not_equal, miss_label); |
258 | 258 |
259 // Load length directly from the JS array. | 259 // Load length directly from the JS array. |
260 __ mov(eax, FieldOperand(receiver, JSArray::kLengthOffset)); | 260 __ mov(eax, FieldOperand(receiver, JSArray::kLengthOffset)); |
261 __ ret(0); | 261 __ ret(0); |
262 } | 262 } |
263 | 263 |
264 | 264 |
265 // 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 |
266 // 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. |
267 static void GenerateStringCheck(MacroAssembler* masm, | 267 static void GenerateStringCheck(MacroAssembler* masm, |
268 Register receiver, | 268 Register receiver, |
269 Register scratch, | 269 Register scratch, |
270 Label* smi, | 270 Label* smi, |
271 Label* non_string_object) { | 271 Label* non_string_object) { |
272 // Check that the object isn't a smi. | 272 // Check that the object isn't a smi. |
273 __ test(receiver, Immediate(kSmiTagMask)); | 273 __ test(receiver, Immediate(kSmiTagMask)); |
274 __ j(zero, smi, not_taken); | 274 __ j(zero, smi); |
275 | 275 |
276 // Check that the object is a string. | 276 // Check that the object is a string. |
277 __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); | 277 __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); |
278 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); | 278 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); |
279 ASSERT(kNotStringTag != 0); | 279 ASSERT(kNotStringTag != 0); |
280 __ test(scratch, Immediate(kNotStringTag)); | 280 __ test(scratch, Immediate(kNotStringTag)); |
281 __ j(not_zero, non_string_object, not_taken); | 281 __ j(not_zero, non_string_object); |
282 } | 282 } |
283 | 283 |
284 | 284 |
285 void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, | 285 void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, |
286 Register receiver, | 286 Register receiver, |
287 Register scratch1, | 287 Register scratch1, |
288 Register scratch2, | 288 Register scratch2, |
289 Label* miss, | 289 Label* miss, |
290 bool support_wrappers) { | 290 bool support_wrappers) { |
291 Label check_wrapper; | 291 Label check_wrapper; |
292 | 292 |
293 // 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 |
294 // scratch register. | 294 // scratch register. |
295 GenerateStringCheck(masm, receiver, scratch1, miss, | 295 GenerateStringCheck(masm, receiver, scratch1, miss, |
296 support_wrappers ? &check_wrapper : miss); | 296 support_wrappers ? &check_wrapper : miss); |
297 | 297 |
298 // Load length from the string and convert to a smi. | 298 // Load length from the string and convert to a smi. |
299 __ mov(eax, FieldOperand(receiver, String::kLengthOffset)); | 299 __ mov(eax, FieldOperand(receiver, String::kLengthOffset)); |
300 __ ret(0); | 300 __ ret(0); |
301 | 301 |
302 if (support_wrappers) { | 302 if (support_wrappers) { |
303 // Check if the object is a JSValue wrapper. | 303 // Check if the object is a JSValue wrapper. |
304 __ bind(&check_wrapper); | 304 __ bind(&check_wrapper); |
305 __ cmp(scratch1, JS_VALUE_TYPE); | 305 __ cmp(scratch1, JS_VALUE_TYPE); |
306 __ j(not_equal, miss, not_taken); | 306 __ j(not_equal, miss); |
307 | 307 |
308 // 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 |
309 // directly if it is. | 309 // directly if it is. |
310 __ mov(scratch2, FieldOperand(receiver, JSValue::kValueOffset)); | 310 __ mov(scratch2, FieldOperand(receiver, JSValue::kValueOffset)); |
311 GenerateStringCheck(masm, scratch2, scratch1, miss, miss); | 311 GenerateStringCheck(masm, scratch2, scratch1, miss, miss); |
312 __ mov(eax, FieldOperand(scratch2, String::kLengthOffset)); | 312 __ mov(eax, FieldOperand(scratch2, String::kLengthOffset)); |
313 __ ret(0); | 313 __ ret(0); |
314 } | 314 } |
315 } | 315 } |
316 | 316 |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
501 Register receiver, | 501 Register receiver, |
502 Register scratch1, | 502 Register scratch1, |
503 Register scratch2, | 503 Register scratch2, |
504 Register scratch3, | 504 Register scratch3, |
505 Label* miss) { | 505 Label* miss) { |
506 ASSERT(holder->HasNamedInterceptor()); | 506 ASSERT(holder->HasNamedInterceptor()); |
507 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); | 507 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); |
508 | 508 |
509 // Check that the receiver isn't a smi. | 509 // Check that the receiver isn't a smi. |
510 __ test(receiver, Immediate(kSmiTagMask)); | 510 __ test(receiver, Immediate(kSmiTagMask)); |
511 __ j(zero, miss, not_taken); | 511 __ j(zero, miss); |
512 | 512 |
513 CallOptimization optimization(lookup); | 513 CallOptimization optimization(lookup); |
514 | 514 |
515 if (optimization.is_constant_call()) { | 515 if (optimization.is_constant_call()) { |
516 return CompileCacheable(masm, | 516 return CompileCacheable(masm, |
517 object, | 517 object, |
518 receiver, | 518 receiver, |
519 scratch1, | 519 scratch1, |
520 scratch2, | 520 scratch2, |
521 scratch3, | 521 scratch3, |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
718 void StubCompiler::GenerateStoreField(MacroAssembler* masm, | 718 void StubCompiler::GenerateStoreField(MacroAssembler* masm, |
719 JSObject* object, | 719 JSObject* object, |
720 int index, | 720 int index, |
721 Map* transition, | 721 Map* transition, |
722 Register receiver_reg, | 722 Register receiver_reg, |
723 Register name_reg, | 723 Register name_reg, |
724 Register scratch, | 724 Register scratch, |
725 Label* miss_label) { | 725 Label* miss_label) { |
726 // Check that the object isn't a smi. | 726 // Check that the object isn't a smi. |
727 __ test(receiver_reg, Immediate(kSmiTagMask)); | 727 __ test(receiver_reg, Immediate(kSmiTagMask)); |
728 __ j(zero, miss_label, not_taken); | 728 __ j(zero, miss_label); |
729 | 729 |
730 // Check that the map of the object hasn't changed. | 730 // Check that the map of the object hasn't changed. |
731 __ cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset), | 731 __ cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset), |
732 Immediate(Handle<Map>(object->map()))); | 732 Immediate(Handle<Map>(object->map()))); |
733 __ j(not_equal, miss_label, not_taken); | 733 __ j(not_equal, miss_label); |
734 | 734 |
735 // Perform global security token check if needed. | 735 // Perform global security token check if needed. |
736 if (object->IsJSGlobalProxy()) { | 736 if (object->IsJSGlobalProxy()) { |
737 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); | 737 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); |
738 } | 738 } |
739 | 739 |
740 // Stub never generated for non-global objects that require access | 740 // Stub never generated for non-global objects that require access |
741 // checks. | 741 // checks. |
742 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 742 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
743 | 743 |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
813 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); | 813 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); |
814 ASSERT(cell->value()->IsTheHole()); | 814 ASSERT(cell->value()->IsTheHole()); |
815 if (Serializer::enabled()) { | 815 if (Serializer::enabled()) { |
816 __ mov(scratch, Immediate(Handle<Object>(cell))); | 816 __ mov(scratch, Immediate(Handle<Object>(cell))); |
817 __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), | 817 __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), |
818 Immediate(masm->isolate()->factory()->the_hole_value())); | 818 Immediate(masm->isolate()->factory()->the_hole_value())); |
819 } else { | 819 } else { |
820 __ cmp(Operand::Cell(Handle<JSGlobalPropertyCell>(cell)), | 820 __ cmp(Operand::Cell(Handle<JSGlobalPropertyCell>(cell)), |
821 Immediate(masm->isolate()->factory()->the_hole_value())); | 821 Immediate(masm->isolate()->factory()->the_hole_value())); |
822 } | 822 } |
823 __ j(not_equal, miss, not_taken); | 823 __ j(not_equal, miss); |
824 return cell; | 824 return cell; |
825 } | 825 } |
826 | 826 |
827 | 827 |
828 // Calls GenerateCheckPropertyCell for each global object in the prototype chain | 828 // Calls GenerateCheckPropertyCell for each global object in the prototype chain |
829 // from object to (but not including) holder. | 829 // from object to (but not including) holder. |
830 MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCells( | 830 MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCells( |
831 MacroAssembler* masm, | 831 MacroAssembler* masm, |
832 JSObject* object, | 832 JSObject* object, |
833 JSObject* holder, | 833 JSObject* holder, |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
918 } | 918 } |
919 | 919 |
920 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 920 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
921 reg = holder_reg; // from now the object is in holder_reg | 921 reg = holder_reg; // from now the object is in holder_reg |
922 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 922 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
923 } else if (heap()->InNewSpace(prototype)) { | 923 } else if (heap()->InNewSpace(prototype)) { |
924 // Get the map of the current object. | 924 // Get the map of the current object. |
925 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 925 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
926 __ cmp(Operand(scratch1), Immediate(Handle<Map>(current->map()))); | 926 __ cmp(Operand(scratch1), Immediate(Handle<Map>(current->map()))); |
927 // Branch on the result of the map check. | 927 // Branch on the result of the map check. |
928 __ j(not_equal, miss, not_taken); | 928 __ j(not_equal, miss); |
929 // Check access rights to the global object. This has to happen | 929 // Check access rights to the global object. This has to happen |
930 // after the map check so that we know that the object is | 930 // after the map check so that we know that the object is |
931 // actually a global object. | 931 // actually a global object. |
932 if (current->IsJSGlobalProxy()) { | 932 if (current->IsJSGlobalProxy()) { |
933 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 933 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
934 | 934 |
935 // Restore scratch register to be the map of the object. | 935 // Restore scratch register to be the map of the object. |
936 // We load the prototype from the map in the scratch register. | 936 // We load the prototype from the map in the scratch register. |
937 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 937 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
938 } | 938 } |
939 // The prototype is in new space; we cannot store a reference | 939 // The prototype is in new space; we cannot store a reference |
940 // to it in the code. Load it from the map. | 940 // to it in the code. Load it from the map. |
941 reg = holder_reg; // from now the object is in holder_reg | 941 reg = holder_reg; // from now the object is in holder_reg |
942 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 942 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
943 } else { | 943 } else { |
944 // Check the map of the current object. | 944 // Check the map of the current object. |
945 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 945 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
946 Immediate(Handle<Map>(current->map()))); | 946 Immediate(Handle<Map>(current->map()))); |
947 // Branch on the result of the map check. | 947 // Branch on the result of the map check. |
948 __ j(not_equal, miss, not_taken); | 948 __ j(not_equal, miss); |
949 // Check access rights to the global object. This has to happen | 949 // Check access rights to the global object. This has to happen |
950 // after the map check so that we know that the object is | 950 // after the map check so that we know that the object is |
951 // actually a global object. | 951 // actually a global object. |
952 if (current->IsJSGlobalProxy()) { | 952 if (current->IsJSGlobalProxy()) { |
953 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 953 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
954 } | 954 } |
955 // The prototype is in old space; load it directly. | 955 // The prototype is in old space; load it directly. |
956 reg = holder_reg; // from now the object is in holder_reg | 956 reg = holder_reg; // from now the object is in holder_reg |
957 __ mov(reg, Handle<JSObject>(prototype)); | 957 __ mov(reg, Handle<JSObject>(prototype)); |
958 } | 958 } |
959 | 959 |
960 if (save_at_depth == depth) { | 960 if (save_at_depth == depth) { |
961 __ mov(Operand(esp, kPointerSize), reg); | 961 __ mov(Operand(esp, kPointerSize), reg); |
962 } | 962 } |
963 | 963 |
964 // Go to the next object in the prototype chain. | 964 // Go to the next object in the prototype chain. |
965 current = prototype; | 965 current = prototype; |
966 } | 966 } |
967 ASSERT(current == holder); | 967 ASSERT(current == holder); |
968 | 968 |
969 // Log the check depth. | 969 // Log the check depth. |
970 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 970 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
971 | 971 |
972 // Check the holder map. | 972 // Check the holder map. |
973 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 973 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
974 Immediate(Handle<Map>(holder->map()))); | 974 Immediate(Handle<Map>(holder->map()))); |
975 __ j(not_equal, miss, not_taken); | 975 __ j(not_equal, miss); |
976 | 976 |
977 // Perform security check for access to the global object. | 977 // Perform security check for access to the global object. |
978 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | 978 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
979 if (holder->IsJSGlobalProxy()) { | 979 if (holder->IsJSGlobalProxy()) { |
980 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 980 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
981 }; | 981 }; |
982 | 982 |
983 // If we've skipped any global objects, it's not enough to verify | 983 // If we've skipped any global objects, it's not enough to verify |
984 // that their maps haven't changed. We also need to check that the | 984 // that their maps haven't changed. We also need to check that the |
985 // property cell for the property is still empty. | 985 // property cell for the property is still empty. |
(...skipping 14 matching lines...) Expand all Loading... |
1000 JSObject* holder, | 1000 JSObject* holder, |
1001 Register receiver, | 1001 Register receiver, |
1002 Register scratch1, | 1002 Register scratch1, |
1003 Register scratch2, | 1003 Register scratch2, |
1004 Register scratch3, | 1004 Register scratch3, |
1005 int index, | 1005 int index, |
1006 String* name, | 1006 String* name, |
1007 Label* miss) { | 1007 Label* miss) { |
1008 // Check that the receiver isn't a smi. | 1008 // Check that the receiver isn't a smi. |
1009 __ test(receiver, Immediate(kSmiTagMask)); | 1009 __ test(receiver, Immediate(kSmiTagMask)); |
1010 __ j(zero, miss, not_taken); | 1010 __ j(zero, miss); |
1011 | 1011 |
1012 // Check the prototype chain. | 1012 // Check the prototype chain. |
1013 Register reg = | 1013 Register reg = |
1014 CheckPrototypes(object, receiver, holder, | 1014 CheckPrototypes(object, receiver, holder, |
1015 scratch1, scratch2, scratch3, name, miss); | 1015 scratch1, scratch2, scratch3, name, miss); |
1016 | 1016 |
1017 // Get the value from the properties. | 1017 // Get the value from the properties. |
1018 GenerateFastPropertyLoad(masm(), eax, reg, holder, index); | 1018 GenerateFastPropertyLoad(masm(), eax, reg, holder, index); |
1019 __ ret(0); | 1019 __ ret(0); |
1020 } | 1020 } |
1021 | 1021 |
1022 | 1022 |
1023 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object, | 1023 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object, |
1024 JSObject* holder, | 1024 JSObject* holder, |
1025 Register receiver, | 1025 Register receiver, |
1026 Register name_reg, | 1026 Register name_reg, |
1027 Register scratch1, | 1027 Register scratch1, |
1028 Register scratch2, | 1028 Register scratch2, |
1029 Register scratch3, | 1029 Register scratch3, |
1030 AccessorInfo* callback, | 1030 AccessorInfo* callback, |
1031 String* name, | 1031 String* name, |
1032 Label* miss) { | 1032 Label* miss) { |
1033 // Check that the receiver isn't a smi. | 1033 // Check that the receiver isn't a smi. |
1034 __ test(receiver, Immediate(kSmiTagMask)); | 1034 __ test(receiver, Immediate(kSmiTagMask)); |
1035 __ j(zero, miss, not_taken); | 1035 __ j(zero, miss); |
1036 | 1036 |
1037 // Check that the maps haven't changed. | 1037 // Check that the maps haven't changed. |
1038 Register reg = | 1038 Register reg = |
1039 CheckPrototypes(object, receiver, holder, scratch1, | 1039 CheckPrototypes(object, receiver, holder, scratch1, |
1040 scratch2, scratch3, name, miss); | 1040 scratch2, scratch3, name, miss); |
1041 | 1041 |
1042 Handle<AccessorInfo> callback_handle(callback); | 1042 Handle<AccessorInfo> callback_handle(callback); |
1043 | 1043 |
1044 // Insert additional parameters into the stack frame above return address. | 1044 // Insert additional parameters into the stack frame above return address. |
1045 ASSERT(!scratch3.is(reg)); | 1045 ASSERT(!scratch3.is(reg)); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1092 JSObject* holder, | 1092 JSObject* holder, |
1093 Register receiver, | 1093 Register receiver, |
1094 Register scratch1, | 1094 Register scratch1, |
1095 Register scratch2, | 1095 Register scratch2, |
1096 Register scratch3, | 1096 Register scratch3, |
1097 Object* value, | 1097 Object* value, |
1098 String* name, | 1098 String* name, |
1099 Label* miss) { | 1099 Label* miss) { |
1100 // Check that the receiver isn't a smi. | 1100 // Check that the receiver isn't a smi. |
1101 __ test(receiver, Immediate(kSmiTagMask)); | 1101 __ test(receiver, Immediate(kSmiTagMask)); |
1102 __ j(zero, miss, not_taken); | 1102 __ j(zero, miss); |
1103 | 1103 |
1104 // Check that the maps haven't changed. | 1104 // Check that the maps haven't changed. |
1105 CheckPrototypes(object, receiver, holder, | 1105 CheckPrototypes(object, receiver, holder, |
1106 scratch1, scratch2, scratch3, name, miss); | 1106 scratch1, scratch2, scratch3, name, miss); |
1107 | 1107 |
1108 // Return the constant value. | 1108 // Return the constant value. |
1109 __ mov(eax, Handle<Object>(value)); | 1109 __ mov(eax, Handle<Object>(value)); |
1110 __ ret(0); | 1110 __ ret(0); |
1111 } | 1111 } |
1112 | 1112 |
1113 | 1113 |
1114 void StubCompiler::GenerateLoadInterceptor(JSObject* object, | 1114 void StubCompiler::GenerateLoadInterceptor(JSObject* object, |
1115 JSObject* interceptor_holder, | 1115 JSObject* interceptor_holder, |
1116 LookupResult* lookup, | 1116 LookupResult* lookup, |
1117 Register receiver, | 1117 Register receiver, |
1118 Register name_reg, | 1118 Register name_reg, |
1119 Register scratch1, | 1119 Register scratch1, |
1120 Register scratch2, | 1120 Register scratch2, |
1121 Register scratch3, | 1121 Register scratch3, |
1122 String* name, | 1122 String* name, |
1123 Label* miss) { | 1123 Label* miss) { |
1124 ASSERT(interceptor_holder->HasNamedInterceptor()); | 1124 ASSERT(interceptor_holder->HasNamedInterceptor()); |
1125 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 1125 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); |
1126 | 1126 |
1127 // Check that the receiver isn't a smi. | 1127 // Check that the receiver isn't a smi. |
1128 __ test(receiver, Immediate(kSmiTagMask)); | 1128 __ test(receiver, Immediate(kSmiTagMask)); |
1129 __ j(zero, miss, not_taken); | 1129 __ j(zero, miss); |
1130 | 1130 |
1131 // So far the most popular follow ups for interceptor loads are FIELD | 1131 // So far the most popular follow ups for interceptor loads are FIELD |
1132 // and CALLBACKS, so inline only them, other cases may be added | 1132 // and CALLBACKS, so inline only them, other cases may be added |
1133 // later. | 1133 // later. |
1134 bool compile_followup_inline = false; | 1134 bool compile_followup_inline = false; |
1135 if (lookup->IsProperty() && lookup->IsCacheable()) { | 1135 if (lookup->IsProperty() && lookup->IsCacheable()) { |
1136 if (lookup->type() == FIELD) { | 1136 if (lookup->type() == FIELD) { |
1137 compile_followup_inline = true; | 1137 compile_followup_inline = true; |
1138 } else if (lookup->type() == CALLBACKS && | 1138 } else if (lookup->type() == CALLBACKS && |
1139 lookup->GetCallbackObject()->IsAccessorInfo() && | 1139 lookup->GetCallbackObject()->IsAccessorInfo() && |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1248 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), | 1248 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), |
1249 isolate()); | 1249 isolate()); |
1250 __ TailCallExternalReference(ref, 5, 1); | 1250 __ TailCallExternalReference(ref, 5, 1); |
1251 } | 1251 } |
1252 } | 1252 } |
1253 | 1253 |
1254 | 1254 |
1255 void CallStubCompiler::GenerateNameCheck(String* name, Label* miss) { | 1255 void CallStubCompiler::GenerateNameCheck(String* name, Label* miss) { |
1256 if (kind_ == Code::KEYED_CALL_IC) { | 1256 if (kind_ == Code::KEYED_CALL_IC) { |
1257 __ cmp(Operand(ecx), Immediate(Handle<String>(name))); | 1257 __ cmp(Operand(ecx), Immediate(Handle<String>(name))); |
1258 __ j(not_equal, miss, not_taken); | 1258 __ j(not_equal, miss); |
1259 } | 1259 } |
1260 } | 1260 } |
1261 | 1261 |
1262 | 1262 |
1263 void CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object, | 1263 void CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object, |
1264 JSObject* holder, | 1264 JSObject* holder, |
1265 String* name, | 1265 String* name, |
1266 Label* miss) { | 1266 Label* miss) { |
1267 ASSERT(holder->IsGlobalObject()); | 1267 ASSERT(holder->IsGlobalObject()); |
1268 | 1268 |
1269 // Get the number of arguments. | 1269 // Get the number of arguments. |
1270 const int argc = arguments().immediate(); | 1270 const int argc = arguments().immediate(); |
1271 | 1271 |
1272 // Get the receiver from the stack. | 1272 // Get the receiver from the stack. |
1273 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1273 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
1274 | 1274 |
1275 // If the object is the holder then we know that it's a global | 1275 // If the object is the holder then we know that it's a global |
1276 // object which can only happen for contextual calls. In this case, | 1276 // object which can only happen for contextual calls. In this case, |
1277 // the receiver cannot be a smi. | 1277 // the receiver cannot be a smi. |
1278 if (object != holder) { | 1278 if (object != holder) { |
1279 __ test(edx, Immediate(kSmiTagMask)); | 1279 __ test(edx, Immediate(kSmiTagMask)); |
1280 __ j(zero, miss, not_taken); | 1280 __ j(zero, miss); |
1281 } | 1281 } |
1282 | 1282 |
1283 // Check that the maps haven't changed. | 1283 // Check that the maps haven't changed. |
1284 CheckPrototypes(object, edx, holder, ebx, eax, edi, name, miss); | 1284 CheckPrototypes(object, edx, holder, ebx, eax, edi, name, miss); |
1285 } | 1285 } |
1286 | 1286 |
1287 | 1287 |
1288 void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell, | 1288 void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell, |
1289 JSFunction* function, | 1289 JSFunction* function, |
1290 Label* miss) { | 1290 Label* miss) { |
1291 // Get the value from the cell. | 1291 // Get the value from the cell. |
1292 if (Serializer::enabled()) { | 1292 if (Serializer::enabled()) { |
1293 __ mov(edi, Immediate(Handle<JSGlobalPropertyCell>(cell))); | 1293 __ mov(edi, Immediate(Handle<JSGlobalPropertyCell>(cell))); |
1294 __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset)); | 1294 __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset)); |
1295 } else { | 1295 } else { |
1296 __ mov(edi, Operand::Cell(Handle<JSGlobalPropertyCell>(cell))); | 1296 __ mov(edi, Operand::Cell(Handle<JSGlobalPropertyCell>(cell))); |
1297 } | 1297 } |
1298 | 1298 |
1299 // Check that the cell contains the same function. | 1299 // Check that the cell contains the same function. |
1300 if (isolate()->heap()->InNewSpace(function)) { | 1300 if (isolate()->heap()->InNewSpace(function)) { |
1301 // We can't embed a pointer to a function in new space so we have | 1301 // We can't embed a pointer to a function in new space so we have |
1302 // to verify that the shared function info is unchanged. This has | 1302 // to verify that the shared function info is unchanged. This has |
1303 // the nice side effect that multiple closures based on the same | 1303 // the nice side effect that multiple closures based on the same |
1304 // function can all use this call IC. Before we load through the | 1304 // function can all use this call IC. Before we load through the |
1305 // function, we have to verify that it still is a function. | 1305 // function, we have to verify that it still is a function. |
1306 __ test(edi, Immediate(kSmiTagMask)); | 1306 __ test(edi, Immediate(kSmiTagMask)); |
1307 __ j(zero, miss, not_taken); | 1307 __ j(zero, miss); |
1308 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); | 1308 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); |
1309 __ j(not_equal, miss, not_taken); | 1309 __ j(not_equal, miss); |
1310 | 1310 |
1311 // Check the shared function info. Make sure it hasn't changed. | 1311 // Check the shared function info. Make sure it hasn't changed. |
1312 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), | 1312 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), |
1313 Immediate(Handle<SharedFunctionInfo>(function->shared()))); | 1313 Immediate(Handle<SharedFunctionInfo>(function->shared()))); |
1314 __ j(not_equal, miss, not_taken); | 1314 __ j(not_equal, miss); |
1315 } else { | 1315 } else { |
1316 __ cmp(Operand(edi), Immediate(Handle<JSFunction>(function))); | 1316 __ cmp(Operand(edi), Immediate(Handle<JSFunction>(function))); |
1317 __ j(not_equal, miss, not_taken); | 1317 __ j(not_equal, miss); |
1318 } | 1318 } |
1319 } | 1319 } |
1320 | 1320 |
1321 | 1321 |
1322 MaybeObject* CallStubCompiler::GenerateMissBranch() { | 1322 MaybeObject* CallStubCompiler::GenerateMissBranch() { |
1323 MaybeObject* maybe_obj = | 1323 MaybeObject* maybe_obj = |
1324 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), | 1324 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), |
1325 kind_); | 1325 kind_); |
1326 Object* obj; | 1326 Object* obj; |
1327 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1327 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
(...skipping 17 matching lines...) Expand all Loading... |
1345 Label miss; | 1345 Label miss; |
1346 | 1346 |
1347 GenerateNameCheck(name, &miss); | 1347 GenerateNameCheck(name, &miss); |
1348 | 1348 |
1349 // Get the receiver from the stack. | 1349 // Get the receiver from the stack. |
1350 const int argc = arguments().immediate(); | 1350 const int argc = arguments().immediate(); |
1351 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1351 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
1352 | 1352 |
1353 // Check that the receiver isn't a smi. | 1353 // Check that the receiver isn't a smi. |
1354 __ test(edx, Immediate(kSmiTagMask)); | 1354 __ test(edx, Immediate(kSmiTagMask)); |
1355 __ j(zero, &miss, not_taken); | 1355 __ j(zero, &miss); |
1356 | 1356 |
1357 // Do the right check and compute the holder register. | 1357 // Do the right check and compute the holder register. |
1358 Register reg = CheckPrototypes(object, edx, holder, ebx, eax, edi, | 1358 Register reg = CheckPrototypes(object, edx, holder, ebx, eax, edi, |
1359 name, &miss); | 1359 name, &miss); |
1360 | 1360 |
1361 GenerateFastPropertyLoad(masm(), edi, reg, holder, index); | 1361 GenerateFastPropertyLoad(masm(), edi, reg, holder, index); |
1362 | 1362 |
1363 // Check that the function really is a function. | 1363 // Check that the function really is a function. |
1364 __ test(edi, Immediate(kSmiTagMask)); | 1364 __ test(edi, Immediate(kSmiTagMask)); |
1365 __ j(zero, &miss, not_taken); | 1365 __ j(zero, &miss); |
1366 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); | 1366 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); |
1367 __ j(not_equal, &miss, not_taken); | 1367 __ j(not_equal, &miss); |
1368 | 1368 |
1369 // Patch the receiver on the stack with the global proxy if | 1369 // Patch the receiver on the stack with the global proxy if |
1370 // necessary. | 1370 // necessary. |
1371 if (object->IsGlobalObject()) { | 1371 if (object->IsGlobalObject()) { |
1372 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 1372 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
1373 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 1373 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
1374 } | 1374 } |
1375 | 1375 |
1376 // Invoke the function. | 1376 // Invoke the function. |
1377 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION); | 1377 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION); |
(...skipping 744 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2122 Label miss, miss_before_stack_reserved; | 2122 Label miss, miss_before_stack_reserved; |
2123 | 2123 |
2124 GenerateNameCheck(name, &miss_before_stack_reserved); | 2124 GenerateNameCheck(name, &miss_before_stack_reserved); |
2125 | 2125 |
2126 // Get the receiver from the stack. | 2126 // Get the receiver from the stack. |
2127 const int argc = arguments().immediate(); | 2127 const int argc = arguments().immediate(); |
2128 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2128 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
2129 | 2129 |
2130 // Check that the receiver isn't a smi. | 2130 // Check that the receiver isn't a smi. |
2131 __ test(edx, Immediate(kSmiTagMask)); | 2131 __ test(edx, Immediate(kSmiTagMask)); |
2132 __ j(zero, &miss_before_stack_reserved, not_taken); | 2132 __ j(zero, &miss_before_stack_reserved); |
2133 | 2133 |
2134 Counters* counters = isolate()->counters(); | 2134 Counters* counters = isolate()->counters(); |
2135 __ IncrementCounter(counters->call_const(), 1); | 2135 __ IncrementCounter(counters->call_const(), 1); |
2136 __ IncrementCounter(counters->call_const_fast_api(), 1); | 2136 __ IncrementCounter(counters->call_const_fast_api(), 1); |
2137 | 2137 |
2138 // Allocate space for v8::Arguments implicit values. Must be initialized | 2138 // Allocate space for v8::Arguments implicit values. Must be initialized |
2139 // before calling any runtime function. | 2139 // before calling any runtime function. |
2140 __ sub(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize)); | 2140 __ sub(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize)); |
2141 | 2141 |
2142 // Check that the maps haven't changed and find a Holder as a side effect. | 2142 // 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... |
2190 | 2190 |
2191 GenerateNameCheck(name, &miss); | 2191 GenerateNameCheck(name, &miss); |
2192 | 2192 |
2193 // Get the receiver from the stack. | 2193 // Get the receiver from the stack. |
2194 const int argc = arguments().immediate(); | 2194 const int argc = arguments().immediate(); |
2195 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2195 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
2196 | 2196 |
2197 // Check that the receiver isn't a smi. | 2197 // Check that the receiver isn't a smi. |
2198 if (check != NUMBER_CHECK) { | 2198 if (check != NUMBER_CHECK) { |
2199 __ test(edx, Immediate(kSmiTagMask)); | 2199 __ test(edx, Immediate(kSmiTagMask)); |
2200 __ j(zero, &miss, not_taken); | 2200 __ j(zero, &miss); |
2201 } | 2201 } |
2202 | 2202 |
2203 // Make sure that it's okay not to patch the on stack receiver | 2203 // Make sure that it's okay not to patch the on stack receiver |
2204 // unless we're doing a receiver map check. | 2204 // unless we're doing a receiver map check. |
2205 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 2205 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
2206 | 2206 |
2207 SharedFunctionInfo* function_info = function->shared(); | 2207 SharedFunctionInfo* function_info = function->shared(); |
2208 switch (check) { | 2208 switch (check) { |
2209 case RECEIVER_MAP_CHECK: | 2209 case RECEIVER_MAP_CHECK: |
2210 __ IncrementCounter(isolate()->counters()->call_const(), 1); | 2210 __ IncrementCounter(isolate()->counters()->call_const(), 1); |
(...skipping 11 matching lines...) Expand all Loading... |
2222 break; | 2222 break; |
2223 | 2223 |
2224 case STRING_CHECK: | 2224 case STRING_CHECK: |
2225 if (!function->IsBuiltin() && !function_info->strict_mode()) { | 2225 if (!function->IsBuiltin() && !function_info->strict_mode()) { |
2226 // Calling non-strict non-builtins with a value as the receiver | 2226 // Calling non-strict non-builtins with a value as the receiver |
2227 // requires boxing. | 2227 // requires boxing. |
2228 __ jmp(&miss); | 2228 __ jmp(&miss); |
2229 } else { | 2229 } else { |
2230 // Check that the object is a string or a symbol. | 2230 // Check that the object is a string or a symbol. |
2231 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, eax); | 2231 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, eax); |
2232 __ j(above_equal, &miss, not_taken); | 2232 __ j(above_equal, &miss); |
2233 // Check that the maps starting from the prototype haven't changed. | 2233 // Check that the maps starting from the prototype haven't changed. |
2234 GenerateDirectLoadGlobalFunctionPrototype( | 2234 GenerateDirectLoadGlobalFunctionPrototype( |
2235 masm(), Context::STRING_FUNCTION_INDEX, eax, &miss); | 2235 masm(), Context::STRING_FUNCTION_INDEX, eax, &miss); |
2236 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 2236 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
2237 ebx, edx, edi, name, &miss); | 2237 ebx, edx, edi, name, &miss); |
2238 } | 2238 } |
2239 break; | 2239 break; |
2240 | 2240 |
2241 case NUMBER_CHECK: { | 2241 case NUMBER_CHECK: { |
2242 if (!function->IsBuiltin() && !function_info->strict_mode()) { | 2242 if (!function->IsBuiltin() && !function_info->strict_mode()) { |
2243 // Calling non-strict non-builtins with a value as the receiver | 2243 // Calling non-strict non-builtins with a value as the receiver |
2244 // requires boxing. | 2244 // requires boxing. |
2245 __ jmp(&miss); | 2245 __ jmp(&miss); |
2246 } else { | 2246 } else { |
2247 Label fast; | 2247 Label fast; |
2248 // Check that the object is a smi or a heap number. | 2248 // Check that the object is a smi or a heap number. |
2249 __ test(edx, Immediate(kSmiTagMask)); | 2249 __ test(edx, Immediate(kSmiTagMask)); |
2250 __ j(zero, &fast, taken); | 2250 __ j(zero, &fast); |
2251 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax); | 2251 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax); |
2252 __ j(not_equal, &miss, not_taken); | 2252 __ j(not_equal, &miss); |
2253 __ bind(&fast); | 2253 __ bind(&fast); |
2254 // Check that the maps starting from the prototype haven't changed. | 2254 // Check that the maps starting from the prototype haven't changed. |
2255 GenerateDirectLoadGlobalFunctionPrototype( | 2255 GenerateDirectLoadGlobalFunctionPrototype( |
2256 masm(), Context::NUMBER_FUNCTION_INDEX, eax, &miss); | 2256 masm(), Context::NUMBER_FUNCTION_INDEX, eax, &miss); |
2257 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 2257 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
2258 ebx, edx, edi, name, &miss); | 2258 ebx, edx, edi, name, &miss); |
2259 } | 2259 } |
2260 break; | 2260 break; |
2261 } | 2261 } |
2262 | 2262 |
2263 case BOOLEAN_CHECK: { | 2263 case BOOLEAN_CHECK: { |
2264 if (!function->IsBuiltin() && !function_info->strict_mode()) { | 2264 if (!function->IsBuiltin() && !function_info->strict_mode()) { |
2265 // Calling non-strict non-builtins with a value as the receiver | 2265 // Calling non-strict non-builtins with a value as the receiver |
2266 // requires boxing. | 2266 // requires boxing. |
2267 __ jmp(&miss); | 2267 __ jmp(&miss); |
2268 } else { | 2268 } else { |
2269 Label fast; | 2269 Label fast; |
2270 // Check that the object is a boolean. | 2270 // Check that the object is a boolean. |
2271 __ cmp(edx, factory()->true_value()); | 2271 __ cmp(edx, factory()->true_value()); |
2272 __ j(equal, &fast, taken); | 2272 __ j(equal, &fast); |
2273 __ cmp(edx, factory()->false_value()); | 2273 __ cmp(edx, factory()->false_value()); |
2274 __ j(not_equal, &miss, not_taken); | 2274 __ j(not_equal, &miss); |
2275 __ bind(&fast); | 2275 __ bind(&fast); |
2276 // Check that the maps starting from the prototype haven't changed. | 2276 // Check that the maps starting from the prototype haven't changed. |
2277 GenerateDirectLoadGlobalFunctionPrototype( | 2277 GenerateDirectLoadGlobalFunctionPrototype( |
2278 masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss); | 2278 masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss); |
2279 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 2279 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
2280 ebx, edx, edi, name, &miss); | 2280 ebx, edx, edi, name, &miss); |
2281 } | 2281 } |
2282 break; | 2282 break; |
2283 } | 2283 } |
2284 | 2284 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2332 edi, | 2332 edi, |
2333 eax, | 2333 eax, |
2334 &miss); | 2334 &miss); |
2335 if (result->IsFailure()) return result; | 2335 if (result->IsFailure()) return result; |
2336 | 2336 |
2337 // Restore receiver. | 2337 // Restore receiver. |
2338 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2338 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
2339 | 2339 |
2340 // Check that the function really is a function. | 2340 // Check that the function really is a function. |
2341 __ test(eax, Immediate(kSmiTagMask)); | 2341 __ test(eax, Immediate(kSmiTagMask)); |
2342 __ j(zero, &miss, not_taken); | 2342 __ j(zero, &miss); |
2343 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); | 2343 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); |
2344 __ j(not_equal, &miss, not_taken); | 2344 __ j(not_equal, &miss); |
2345 | 2345 |
2346 // Patch the receiver on the stack with the global proxy if | 2346 // Patch the receiver on the stack with the global proxy if |
2347 // necessary. | 2347 // necessary. |
2348 if (object->IsGlobalObject()) { | 2348 if (object->IsGlobalObject()) { |
2349 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 2349 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
2350 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 2350 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
2351 } | 2351 } |
2352 | 2352 |
2353 // Invoke the function. | 2353 // Invoke the function. |
2354 __ mov(edi, eax); | 2354 __ mov(edi, eax); |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2471 // ----------- S t a t e ------------- | 2471 // ----------- S t a t e ------------- |
2472 // -- eax : value | 2472 // -- eax : value |
2473 // -- ecx : name | 2473 // -- ecx : name |
2474 // -- edx : receiver | 2474 // -- edx : receiver |
2475 // -- esp[0] : return address | 2475 // -- esp[0] : return address |
2476 // ----------------------------------- | 2476 // ----------------------------------- |
2477 Label miss; | 2477 Label miss; |
2478 | 2478 |
2479 // Check that the object isn't a smi. | 2479 // Check that the object isn't a smi. |
2480 __ test(edx, Immediate(kSmiTagMask)); | 2480 __ test(edx, Immediate(kSmiTagMask)); |
2481 __ j(zero, &miss, not_taken); | 2481 __ j(zero, &miss); |
2482 | 2482 |
2483 // Check that the map of the object hasn't changed. | 2483 // Check that the map of the object hasn't changed. |
2484 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 2484 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
2485 Immediate(Handle<Map>(object->map()))); | 2485 Immediate(Handle<Map>(object->map()))); |
2486 __ j(not_equal, &miss, not_taken); | 2486 __ j(not_equal, &miss); |
2487 | 2487 |
2488 // Perform global security token check if needed. | 2488 // Perform global security token check if needed. |
2489 if (object->IsJSGlobalProxy()) { | 2489 if (object->IsJSGlobalProxy()) { |
2490 __ CheckAccessGlobalProxy(edx, ebx, &miss); | 2490 __ CheckAccessGlobalProxy(edx, ebx, &miss); |
2491 } | 2491 } |
2492 | 2492 |
2493 // Stub never generated for non-global objects that require access | 2493 // Stub never generated for non-global objects that require access |
2494 // checks. | 2494 // checks. |
2495 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 2495 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
2496 | 2496 |
(...skipping 24 matching lines...) Expand all Loading... |
2521 // ----------- S t a t e ------------- | 2521 // ----------- S t a t e ------------- |
2522 // -- eax : value | 2522 // -- eax : value |
2523 // -- ecx : name | 2523 // -- ecx : name |
2524 // -- edx : receiver | 2524 // -- edx : receiver |
2525 // -- esp[0] : return address | 2525 // -- esp[0] : return address |
2526 // ----------------------------------- | 2526 // ----------------------------------- |
2527 Label miss; | 2527 Label miss; |
2528 | 2528 |
2529 // Check that the object isn't a smi. | 2529 // Check that the object isn't a smi. |
2530 __ test(edx, Immediate(kSmiTagMask)); | 2530 __ test(edx, Immediate(kSmiTagMask)); |
2531 __ j(zero, &miss, not_taken); | 2531 __ j(zero, &miss); |
2532 | 2532 |
2533 // Check that the map of the object hasn't changed. | 2533 // Check that the map of the object hasn't changed. |
2534 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 2534 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
2535 Immediate(Handle<Map>(receiver->map()))); | 2535 Immediate(Handle<Map>(receiver->map()))); |
2536 __ j(not_equal, &miss, not_taken); | 2536 __ j(not_equal, &miss); |
2537 | 2537 |
2538 // Perform global security token check if needed. | 2538 // Perform global security token check if needed. |
2539 if (receiver->IsJSGlobalProxy()) { | 2539 if (receiver->IsJSGlobalProxy()) { |
2540 __ CheckAccessGlobalProxy(edx, ebx, &miss); | 2540 __ CheckAccessGlobalProxy(edx, ebx, &miss); |
2541 } | 2541 } |
2542 | 2542 |
2543 // Stub never generated for non-global objects that require access | 2543 // Stub never generated for non-global objects that require access |
2544 // checks. | 2544 // checks. |
2545 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); | 2545 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); |
2546 | 2546 |
(...skipping 26 matching lines...) Expand all Loading... |
2573 // -- eax : value | 2573 // -- eax : value |
2574 // -- ecx : name | 2574 // -- ecx : name |
2575 // -- edx : receiver | 2575 // -- edx : receiver |
2576 // -- esp[0] : return address | 2576 // -- esp[0] : return address |
2577 // ----------------------------------- | 2577 // ----------------------------------- |
2578 Label miss; | 2578 Label miss; |
2579 | 2579 |
2580 // Check that the map of the global has not changed. | 2580 // Check that the map of the global has not changed. |
2581 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 2581 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
2582 Immediate(Handle<Map>(object->map()))); | 2582 Immediate(Handle<Map>(object->map()))); |
2583 __ j(not_equal, &miss, not_taken); | 2583 __ j(not_equal, &miss); |
2584 | 2584 |
2585 | 2585 |
2586 // Compute the cell operand to use. | 2586 // Compute the cell operand to use. |
2587 Operand cell_operand = Operand::Cell(Handle<JSGlobalPropertyCell>(cell)); | 2587 Operand cell_operand = Operand::Cell(Handle<JSGlobalPropertyCell>(cell)); |
2588 if (Serializer::enabled()) { | 2588 if (Serializer::enabled()) { |
2589 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); | 2589 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); |
2590 cell_operand = FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset); | 2590 cell_operand = FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset); |
2591 } | 2591 } |
2592 | 2592 |
2593 // Check that the value in the cell is not the hole. If it is, this | 2593 // 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... |
2626 // -- edx : receiver | 2626 // -- edx : receiver |
2627 // -- esp[0] : return address | 2627 // -- esp[0] : return address |
2628 // ----------------------------------- | 2628 // ----------------------------------- |
2629 Label miss; | 2629 Label miss; |
2630 | 2630 |
2631 Counters* counters = isolate()->counters(); | 2631 Counters* counters = isolate()->counters(); |
2632 __ IncrementCounter(counters->keyed_store_field(), 1); | 2632 __ IncrementCounter(counters->keyed_store_field(), 1); |
2633 | 2633 |
2634 // Check that the name has not changed. | 2634 // Check that the name has not changed. |
2635 __ cmp(Operand(ecx), Immediate(Handle<String>(name))); | 2635 __ cmp(Operand(ecx), Immediate(Handle<String>(name))); |
2636 __ j(not_equal, &miss, not_taken); | 2636 __ j(not_equal, &miss); |
2637 | 2637 |
2638 // Generate store field code. Trashes the name register. | 2638 // Generate store field code. Trashes the name register. |
2639 GenerateStoreField(masm(), | 2639 GenerateStoreField(masm(), |
2640 object, | 2640 object, |
2641 index, | 2641 index, |
2642 transition, | 2642 transition, |
2643 edx, ecx, ebx, | 2643 edx, ecx, ebx, |
2644 &miss); | 2644 &miss); |
2645 | 2645 |
2646 // Handle store cache miss. | 2646 // Handle store cache miss. |
(...skipping 12 matching lines...) Expand all Loading... |
2659 // ----------- S t a t e ------------- | 2659 // ----------- S t a t e ------------- |
2660 // -- eax : value | 2660 // -- eax : value |
2661 // -- ecx : key | 2661 // -- ecx : key |
2662 // -- edx : receiver | 2662 // -- edx : receiver |
2663 // -- esp[0] : return address | 2663 // -- esp[0] : return address |
2664 // ----------------------------------- | 2664 // ----------------------------------- |
2665 Label miss; | 2665 Label miss; |
2666 | 2666 |
2667 // Check that the receiver isn't a smi. | 2667 // Check that the receiver isn't a smi. |
2668 __ test(edx, Immediate(kSmiTagMask)); | 2668 __ test(edx, Immediate(kSmiTagMask)); |
2669 __ j(zero, &miss, not_taken); | 2669 __ j(zero, &miss); |
2670 | 2670 |
2671 // Check that the map matches. | 2671 // Check that the map matches. |
2672 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 2672 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
2673 Immediate(Handle<Map>(receiver->map()))); | 2673 Immediate(Handle<Map>(receiver->map()))); |
2674 __ j(not_equal, &miss, not_taken); | 2674 __ j(not_equal, &miss); |
2675 | 2675 |
2676 // Check that the key is a smi. | 2676 // Check that the key is a smi. |
2677 __ test(ecx, Immediate(kSmiTagMask)); | 2677 __ test(ecx, Immediate(kSmiTagMask)); |
2678 __ j(not_zero, &miss, not_taken); | 2678 __ j(not_zero, &miss); |
2679 | 2679 |
2680 // Get the elements array and make sure it is a fast element array, not 'cow'. | 2680 // Get the elements array and make sure it is a fast element array, not 'cow'. |
2681 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); | 2681 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
2682 __ cmp(FieldOperand(edi, HeapObject::kMapOffset), | 2682 __ cmp(FieldOperand(edi, HeapObject::kMapOffset), |
2683 Immediate(factory()->fixed_array_map())); | 2683 Immediate(factory()->fixed_array_map())); |
2684 __ j(not_equal, &miss, not_taken); | 2684 __ j(not_equal, &miss); |
2685 | 2685 |
2686 // Check that the key is within bounds. | 2686 // Check that the key is within bounds. |
2687 if (receiver->IsJSArray()) { | 2687 if (receiver->IsJSArray()) { |
2688 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis. | 2688 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis. |
2689 __ j(above_equal, &miss, not_taken); | 2689 __ j(above_equal, &miss); |
2690 } else { | 2690 } else { |
2691 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // Compare smis. | 2691 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // Compare smis. |
2692 __ j(above_equal, &miss, not_taken); | 2692 __ j(above_equal, &miss); |
2693 } | 2693 } |
2694 | 2694 |
2695 // Do the store and update the write barrier. Make sure to preserve | 2695 // Do the store and update the write barrier. Make sure to preserve |
2696 // the value in register eax. | 2696 // the value in register eax. |
2697 __ mov(edx, Operand(eax)); | 2697 __ mov(edx, Operand(eax)); |
2698 __ mov(FieldOperand(edi, ecx, times_2, FixedArray::kHeaderSize), eax); | 2698 __ mov(FieldOperand(edi, ecx, times_2, FixedArray::kHeaderSize), eax); |
2699 __ RecordWrite(edi, 0, edx, ecx); | 2699 __ RecordWrite(edi, 0, edx, ecx); |
2700 | 2700 |
2701 // Done. | 2701 // Done. |
2702 __ ret(0); | 2702 __ ret(0); |
(...skipping 13 matching lines...) Expand all Loading... |
2716 JSObject* last) { | 2716 JSObject* last) { |
2717 // ----------- S t a t e ------------- | 2717 // ----------- S t a t e ------------- |
2718 // -- eax : receiver | 2718 // -- eax : receiver |
2719 // -- ecx : name | 2719 // -- ecx : name |
2720 // -- esp[0] : return address | 2720 // -- esp[0] : return address |
2721 // ----------------------------------- | 2721 // ----------------------------------- |
2722 Label miss; | 2722 Label miss; |
2723 | 2723 |
2724 // Check that the receiver isn't a smi. | 2724 // Check that the receiver isn't a smi. |
2725 __ test(eax, Immediate(kSmiTagMask)); | 2725 __ test(eax, Immediate(kSmiTagMask)); |
2726 __ j(zero, &miss, not_taken); | 2726 __ j(zero, &miss); |
2727 | 2727 |
2728 ASSERT(last->IsGlobalObject() || last->HasFastProperties()); | 2728 ASSERT(last->IsGlobalObject() || last->HasFastProperties()); |
2729 | 2729 |
2730 // Check the maps of the full prototype chain. Also check that | 2730 // Check the maps of the full prototype chain. Also check that |
2731 // global property cells up to (but not including) the last object | 2731 // global property cells up to (but not including) the last object |
2732 // in the prototype chain are empty. | 2732 // in the prototype chain are empty. |
2733 CheckPrototypes(object, eax, last, ebx, edx, edi, name, &miss); | 2733 CheckPrototypes(object, eax, last, ebx, edx, edi, name, &miss); |
2734 | 2734 |
2735 // If the last object in the prototype chain is a global object, | 2735 // If the last object in the prototype chain is a global object, |
2736 // check that the global property cell is empty. | 2736 // check that the global property cell is empty. |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2869 // -- ecx : name | 2869 // -- ecx : name |
2870 // -- esp[0] : return address | 2870 // -- esp[0] : return address |
2871 // ----------------------------------- | 2871 // ----------------------------------- |
2872 Label miss; | 2872 Label miss; |
2873 | 2873 |
2874 // If the object is the holder then we know that it's a global | 2874 // If the object is the holder then we know that it's a global |
2875 // object which can only happen for contextual loads. In this case, | 2875 // object which can only happen for contextual loads. In this case, |
2876 // the receiver cannot be a smi. | 2876 // the receiver cannot be a smi. |
2877 if (object != holder) { | 2877 if (object != holder) { |
2878 __ test(eax, Immediate(kSmiTagMask)); | 2878 __ test(eax, Immediate(kSmiTagMask)); |
2879 __ j(zero, &miss, not_taken); | 2879 __ j(zero, &miss); |
2880 } | 2880 } |
2881 | 2881 |
2882 // Check that the maps haven't changed. | 2882 // Check that the maps haven't changed. |
2883 CheckPrototypes(object, eax, holder, ebx, edx, edi, name, &miss); | 2883 CheckPrototypes(object, eax, holder, ebx, edx, edi, name, &miss); |
2884 | 2884 |
2885 // Get the value from the cell. | 2885 // Get the value from the cell. |
2886 if (Serializer::enabled()) { | 2886 if (Serializer::enabled()) { |
2887 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); | 2887 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); |
2888 __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset)); | 2888 __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset)); |
2889 } else { | 2889 } else { |
2890 __ mov(ebx, Operand::Cell(Handle<JSGlobalPropertyCell>(cell))); | 2890 __ mov(ebx, Operand::Cell(Handle<JSGlobalPropertyCell>(cell))); |
2891 } | 2891 } |
2892 | 2892 |
2893 // Check for deleted property if property can actually be deleted. | 2893 // Check for deleted property if property can actually be deleted. |
2894 if (!is_dont_delete) { | 2894 if (!is_dont_delete) { |
2895 __ cmp(ebx, factory()->the_hole_value()); | 2895 __ cmp(ebx, factory()->the_hole_value()); |
2896 __ j(equal, &miss, not_taken); | 2896 __ j(equal, &miss); |
2897 } else if (FLAG_debug_code) { | 2897 } else if (FLAG_debug_code) { |
2898 __ cmp(ebx, factory()->the_hole_value()); | 2898 __ cmp(ebx, factory()->the_hole_value()); |
2899 __ Check(not_equal, "DontDelete cells can't contain the hole"); | 2899 __ Check(not_equal, "DontDelete cells can't contain the hole"); |
2900 } | 2900 } |
2901 | 2901 |
2902 Counters* counters = isolate()->counters(); | 2902 Counters* counters = isolate()->counters(); |
2903 __ IncrementCounter(counters->named_load_global_stub(), 1); | 2903 __ IncrementCounter(counters->named_load_global_stub(), 1); |
2904 __ mov(eax, ebx); | 2904 __ mov(eax, ebx); |
2905 __ ret(0); | 2905 __ ret(0); |
2906 | 2906 |
(...skipping 15 matching lines...) Expand all Loading... |
2922 // -- edx : receiver | 2922 // -- edx : receiver |
2923 // -- esp[0] : return address | 2923 // -- esp[0] : return address |
2924 // ----------------------------------- | 2924 // ----------------------------------- |
2925 Label miss; | 2925 Label miss; |
2926 | 2926 |
2927 Counters* counters = isolate()->counters(); | 2927 Counters* counters = isolate()->counters(); |
2928 __ IncrementCounter(counters->keyed_load_field(), 1); | 2928 __ IncrementCounter(counters->keyed_load_field(), 1); |
2929 | 2929 |
2930 // Check that the name has not changed. | 2930 // Check that the name has not changed. |
2931 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 2931 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
2932 __ j(not_equal, &miss, not_taken); | 2932 __ j(not_equal, &miss); |
2933 | 2933 |
2934 GenerateLoadField(receiver, holder, edx, ebx, ecx, edi, index, name, &miss); | 2934 GenerateLoadField(receiver, holder, edx, ebx, ecx, edi, index, name, &miss); |
2935 | 2935 |
2936 __ bind(&miss); | 2936 __ bind(&miss); |
2937 __ DecrementCounter(counters->keyed_load_field(), 1); | 2937 __ DecrementCounter(counters->keyed_load_field(), 1); |
2938 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2938 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
2939 | 2939 |
2940 // Return the generated code. | 2940 // Return the generated code. |
2941 return GetCode(FIELD, name); | 2941 return GetCode(FIELD, name); |
2942 } | 2942 } |
2943 | 2943 |
2944 | 2944 |
2945 MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback( | 2945 MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback( |
2946 String* name, | 2946 String* name, |
2947 JSObject* receiver, | 2947 JSObject* receiver, |
2948 JSObject* holder, | 2948 JSObject* holder, |
2949 AccessorInfo* callback) { | 2949 AccessorInfo* callback) { |
2950 // ----------- S t a t e ------------- | 2950 // ----------- S t a t e ------------- |
2951 // -- eax : key | 2951 // -- eax : key |
2952 // -- edx : receiver | 2952 // -- edx : receiver |
2953 // -- esp[0] : return address | 2953 // -- esp[0] : return address |
2954 // ----------------------------------- | 2954 // ----------------------------------- |
2955 Label miss; | 2955 Label miss; |
2956 | 2956 |
2957 Counters* counters = isolate()->counters(); | 2957 Counters* counters = isolate()->counters(); |
2958 __ IncrementCounter(counters->keyed_load_callback(), 1); | 2958 __ IncrementCounter(counters->keyed_load_callback(), 1); |
2959 | 2959 |
2960 // Check that the name has not changed. | 2960 // Check that the name has not changed. |
2961 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 2961 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
2962 __ j(not_equal, &miss, not_taken); | 2962 __ j(not_equal, &miss); |
2963 | 2963 |
2964 MaybeObject* result = GenerateLoadCallback(receiver, holder, edx, eax, ebx, | 2964 MaybeObject* result = GenerateLoadCallback(receiver, holder, edx, eax, ebx, |
2965 ecx, edi, callback, name, &miss); | 2965 ecx, edi, callback, name, &miss); |
2966 if (result->IsFailure()) { | 2966 if (result->IsFailure()) { |
2967 miss.Unuse(); | 2967 miss.Unuse(); |
2968 return result; | 2968 return result; |
2969 } | 2969 } |
2970 | 2970 |
2971 __ bind(&miss); | 2971 __ bind(&miss); |
2972 | 2972 |
(...skipping 14 matching lines...) Expand all Loading... |
2987 // -- edx : receiver | 2987 // -- edx : receiver |
2988 // -- esp[0] : return address | 2988 // -- esp[0] : return address |
2989 // ----------------------------------- | 2989 // ----------------------------------- |
2990 Label miss; | 2990 Label miss; |
2991 | 2991 |
2992 Counters* counters = isolate()->counters(); | 2992 Counters* counters = isolate()->counters(); |
2993 __ IncrementCounter(counters->keyed_load_constant_function(), 1); | 2993 __ IncrementCounter(counters->keyed_load_constant_function(), 1); |
2994 | 2994 |
2995 // Check that the name has not changed. | 2995 // Check that the name has not changed. |
2996 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 2996 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
2997 __ j(not_equal, &miss, not_taken); | 2997 __ j(not_equal, &miss); |
2998 | 2998 |
2999 GenerateLoadConstant(receiver, holder, edx, ebx, ecx, edi, | 2999 GenerateLoadConstant(receiver, holder, edx, ebx, ecx, edi, |
3000 value, name, &miss); | 3000 value, name, &miss); |
3001 __ bind(&miss); | 3001 __ bind(&miss); |
3002 __ DecrementCounter(counters->keyed_load_constant_function(), 1); | 3002 __ DecrementCounter(counters->keyed_load_constant_function(), 1); |
3003 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3003 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3004 | 3004 |
3005 // Return the generated code. | 3005 // Return the generated code. |
3006 return GetCode(CONSTANT_FUNCTION, name); | 3006 return GetCode(CONSTANT_FUNCTION, name); |
3007 } | 3007 } |
3008 | 3008 |
3009 | 3009 |
3010 MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, | 3010 MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, |
3011 JSObject* holder, | 3011 JSObject* holder, |
3012 String* name) { | 3012 String* name) { |
3013 // ----------- S t a t e ------------- | 3013 // ----------- S t a t e ------------- |
3014 // -- eax : key | 3014 // -- eax : key |
3015 // -- edx : receiver | 3015 // -- edx : receiver |
3016 // -- esp[0] : return address | 3016 // -- esp[0] : return address |
3017 // ----------------------------------- | 3017 // ----------------------------------- |
3018 Label miss; | 3018 Label miss; |
3019 | 3019 |
3020 Counters* counters = isolate()->counters(); | 3020 Counters* counters = isolate()->counters(); |
3021 __ IncrementCounter(counters->keyed_load_interceptor(), 1); | 3021 __ IncrementCounter(counters->keyed_load_interceptor(), 1); |
3022 | 3022 |
3023 // Check that the name has not changed. | 3023 // Check that the name has not changed. |
3024 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 3024 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
3025 __ j(not_equal, &miss, not_taken); | 3025 __ j(not_equal, &miss); |
3026 | 3026 |
3027 LookupResult lookup; | 3027 LookupResult lookup; |
3028 LookupPostInterceptor(holder, name, &lookup); | 3028 LookupPostInterceptor(holder, name, &lookup); |
3029 GenerateLoadInterceptor(receiver, | 3029 GenerateLoadInterceptor(receiver, |
3030 holder, | 3030 holder, |
3031 &lookup, | 3031 &lookup, |
3032 edx, | 3032 edx, |
3033 eax, | 3033 eax, |
3034 ecx, | 3034 ecx, |
3035 ebx, | 3035 ebx, |
(...skipping 15 matching lines...) Expand all Loading... |
3051 // -- edx : receiver | 3051 // -- edx : receiver |
3052 // -- esp[0] : return address | 3052 // -- esp[0] : return address |
3053 // ----------------------------------- | 3053 // ----------------------------------- |
3054 Label miss; | 3054 Label miss; |
3055 | 3055 |
3056 Counters* counters = isolate()->counters(); | 3056 Counters* counters = isolate()->counters(); |
3057 __ IncrementCounter(counters->keyed_load_array_length(), 1); | 3057 __ IncrementCounter(counters->keyed_load_array_length(), 1); |
3058 | 3058 |
3059 // Check that the name has not changed. | 3059 // Check that the name has not changed. |
3060 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 3060 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
3061 __ j(not_equal, &miss, not_taken); | 3061 __ j(not_equal, &miss); |
3062 | 3062 |
3063 GenerateLoadArrayLength(masm(), edx, ecx, &miss); | 3063 GenerateLoadArrayLength(masm(), edx, ecx, &miss); |
3064 __ bind(&miss); | 3064 __ bind(&miss); |
3065 __ DecrementCounter(counters->keyed_load_array_length(), 1); | 3065 __ DecrementCounter(counters->keyed_load_array_length(), 1); |
3066 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3066 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3067 | 3067 |
3068 // Return the generated code. | 3068 // Return the generated code. |
3069 return GetCode(CALLBACKS, name); | 3069 return GetCode(CALLBACKS, name); |
3070 } | 3070 } |
3071 | 3071 |
3072 | 3072 |
3073 MaybeObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) { | 3073 MaybeObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) { |
3074 // ----------- S t a t e ------------- | 3074 // ----------- S t a t e ------------- |
3075 // -- eax : key | 3075 // -- eax : key |
3076 // -- edx : receiver | 3076 // -- edx : receiver |
3077 // -- esp[0] : return address | 3077 // -- esp[0] : return address |
3078 // ----------------------------------- | 3078 // ----------------------------------- |
3079 Label miss; | 3079 Label miss; |
3080 | 3080 |
3081 Counters* counters = isolate()->counters(); | 3081 Counters* counters = isolate()->counters(); |
3082 __ IncrementCounter(counters->keyed_load_string_length(), 1); | 3082 __ IncrementCounter(counters->keyed_load_string_length(), 1); |
3083 | 3083 |
3084 // Check that the name has not changed. | 3084 // Check that the name has not changed. |
3085 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 3085 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
3086 __ j(not_equal, &miss, not_taken); | 3086 __ j(not_equal, &miss); |
3087 | 3087 |
3088 GenerateLoadStringLength(masm(), edx, ecx, ebx, &miss, true); | 3088 GenerateLoadStringLength(masm(), edx, ecx, ebx, &miss, true); |
3089 __ bind(&miss); | 3089 __ bind(&miss); |
3090 __ DecrementCounter(counters->keyed_load_string_length(), 1); | 3090 __ DecrementCounter(counters->keyed_load_string_length(), 1); |
3091 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3091 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3092 | 3092 |
3093 // Return the generated code. | 3093 // Return the generated code. |
3094 return GetCode(CALLBACKS, name); | 3094 return GetCode(CALLBACKS, name); |
3095 } | 3095 } |
3096 | 3096 |
3097 | 3097 |
3098 MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { | 3098 MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { |
3099 // ----------- S t a t e ------------- | 3099 // ----------- S t a t e ------------- |
3100 // -- eax : key | 3100 // -- eax : key |
3101 // -- edx : receiver | 3101 // -- edx : receiver |
3102 // -- esp[0] : return address | 3102 // -- esp[0] : return address |
3103 // ----------------------------------- | 3103 // ----------------------------------- |
3104 Label miss; | 3104 Label miss; |
3105 | 3105 |
3106 Counters* counters = isolate()->counters(); | 3106 Counters* counters = isolate()->counters(); |
3107 __ IncrementCounter(counters->keyed_load_function_prototype(), 1); | 3107 __ IncrementCounter(counters->keyed_load_function_prototype(), 1); |
3108 | 3108 |
3109 // Check that the name has not changed. | 3109 // Check that the name has not changed. |
3110 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 3110 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
3111 __ j(not_equal, &miss, not_taken); | 3111 __ j(not_equal, &miss); |
3112 | 3112 |
3113 GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss); | 3113 GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss); |
3114 __ bind(&miss); | 3114 __ bind(&miss); |
3115 __ DecrementCounter(counters->keyed_load_function_prototype(), 1); | 3115 __ DecrementCounter(counters->keyed_load_function_prototype(), 1); |
3116 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3116 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3117 | 3117 |
3118 // Return the generated code. | 3118 // Return the generated code. |
3119 return GetCode(CALLBACKS, name); | 3119 return GetCode(CALLBACKS, name); |
3120 } | 3120 } |
3121 | 3121 |
3122 | 3122 |
3123 MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) { | 3123 MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) { |
3124 // ----------- S t a t e ------------- | 3124 // ----------- S t a t e ------------- |
3125 // -- eax : key | 3125 // -- eax : key |
3126 // -- edx : receiver | 3126 // -- edx : receiver |
3127 // -- esp[0] : return address | 3127 // -- esp[0] : return address |
3128 // ----------------------------------- | 3128 // ----------------------------------- |
3129 Label miss; | 3129 Label miss; |
3130 | 3130 |
3131 // Check that the receiver isn't a smi. | 3131 // Check that the receiver isn't a smi. |
3132 __ test(edx, Immediate(kSmiTagMask)); | 3132 __ test(edx, Immediate(kSmiTagMask)); |
3133 __ j(zero, &miss, not_taken); | 3133 __ j(zero, &miss); |
3134 | 3134 |
3135 // Check that the map matches. | 3135 // Check that the map matches. |
3136 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 3136 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
3137 Immediate(Handle<Map>(receiver->map()))); | 3137 Immediate(Handle<Map>(receiver->map()))); |
3138 __ j(not_equal, &miss, not_taken); | 3138 __ j(not_equal, &miss); |
3139 | 3139 |
3140 // Check that the key is a smi. | 3140 // Check that the key is a smi. |
3141 __ test(eax, Immediate(kSmiTagMask)); | 3141 __ test(eax, Immediate(kSmiTagMask)); |
3142 __ j(not_zero, &miss, not_taken); | 3142 __ j(not_zero, &miss); |
3143 | 3143 |
3144 // Get the elements array. | 3144 // Get the elements array. |
3145 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); | 3145 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); |
3146 __ AssertFastElements(ecx); | 3146 __ AssertFastElements(ecx); |
3147 | 3147 |
3148 // Check that the key is within bounds. | 3148 // Check that the key is within bounds. |
3149 __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset)); | 3149 __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset)); |
3150 __ j(above_equal, &miss, not_taken); | 3150 __ j(above_equal, &miss); |
3151 | 3151 |
3152 // Load the result and make sure it's not the hole. | 3152 // Load the result and make sure it's not the hole. |
3153 __ mov(ebx, Operand(ecx, eax, times_2, | 3153 __ mov(ebx, Operand(ecx, eax, times_2, |
3154 FixedArray::kHeaderSize - kHeapObjectTag)); | 3154 FixedArray::kHeaderSize - kHeapObjectTag)); |
3155 __ cmp(ebx, factory()->the_hole_value()); | 3155 __ cmp(ebx, factory()->the_hole_value()); |
3156 __ j(equal, &miss, not_taken); | 3156 __ j(equal, &miss); |
3157 __ mov(eax, ebx); | 3157 __ mov(eax, ebx); |
3158 __ ret(0); | 3158 __ ret(0); |
3159 | 3159 |
3160 __ bind(&miss); | 3160 __ bind(&miss); |
3161 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3161 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3162 | 3162 |
3163 // Return the generated code. | 3163 // Return the generated code. |
3164 return GetCode(NORMAL, NULL); | 3164 return GetCode(NORMAL, NULL); |
3165 } | 3165 } |
3166 | 3166 |
3167 | 3167 |
3168 // Specialized stub for constructing objects from functions which only have only | 3168 // Specialized stub for constructing objects from functions which only have only |
3169 // simple assignments of the form this.x = ...; in their body. | 3169 // simple assignments of the form this.x = ...; in their body. |
3170 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { | 3170 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { |
3171 // ----------- S t a t e ------------- | 3171 // ----------- S t a t e ------------- |
3172 // -- eax : argc | 3172 // -- eax : argc |
3173 // -- edi : constructor | 3173 // -- edi : constructor |
3174 // -- esp[0] : return address | 3174 // -- esp[0] : return address |
3175 // -- esp[4] : last argument | 3175 // -- esp[4] : last argument |
3176 // ----------------------------------- | 3176 // ----------------------------------- |
3177 Label generic_stub_call; | 3177 Label generic_stub_call; |
3178 #ifdef ENABLE_DEBUGGER_SUPPORT | 3178 #ifdef ENABLE_DEBUGGER_SUPPORT |
3179 // Check to see whether there are any break points in the function code. If | 3179 // Check to see whether there are any break points in the function code. If |
3180 // there are jump to the generic constructor stub which calls the actual | 3180 // there are jump to the generic constructor stub which calls the actual |
3181 // code for the function thereby hitting the break points. | 3181 // code for the function thereby hitting the break points. |
3182 __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 3182 __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
3183 __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kDebugInfoOffset)); | 3183 __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kDebugInfoOffset)); |
3184 __ cmp(ebx, factory()->undefined_value()); | 3184 __ cmp(ebx, factory()->undefined_value()); |
3185 __ j(not_equal, &generic_stub_call, not_taken); | 3185 __ j(not_equal, &generic_stub_call); |
3186 #endif | 3186 #endif |
3187 | 3187 |
3188 // Load the initial map and verify that it is in fact a map. | 3188 // Load the initial map and verify that it is in fact a map. |
3189 __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); | 3189 __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); |
3190 // Will both indicate a NULL and a Smi. | 3190 // Will both indicate a NULL and a Smi. |
3191 __ test(ebx, Immediate(kSmiTagMask)); | 3191 __ test(ebx, Immediate(kSmiTagMask)); |
3192 __ j(zero, &generic_stub_call); | 3192 __ j(zero, &generic_stub_call); |
3193 __ CmpObjectType(ebx, MAP_TYPE, ecx); | 3193 __ CmpObjectType(ebx, MAP_TYPE, ecx); |
3194 __ j(not_equal, &generic_stub_call); | 3194 __ j(not_equal, &generic_stub_call); |
3195 | 3195 |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3308 JSObject*receiver, ExternalArrayType array_type, Code::Flags flags) { | 3308 JSObject*receiver, ExternalArrayType array_type, Code::Flags flags) { |
3309 // ----------- S t a t e ------------- | 3309 // ----------- S t a t e ------------- |
3310 // -- eax : key | 3310 // -- eax : key |
3311 // -- edx : receiver | 3311 // -- edx : receiver |
3312 // -- esp[0] : return address | 3312 // -- esp[0] : return address |
3313 // ----------------------------------- | 3313 // ----------------------------------- |
3314 Label slow, failed_allocation; | 3314 Label slow, failed_allocation; |
3315 | 3315 |
3316 // Check that the object isn't a smi. | 3316 // Check that the object isn't a smi. |
3317 __ test(edx, Immediate(kSmiTagMask)); | 3317 __ test(edx, Immediate(kSmiTagMask)); |
3318 __ j(zero, &slow, not_taken); | 3318 __ j(zero, &slow); |
3319 | 3319 |
3320 // Check that the key is a smi. | 3320 // Check that the key is a smi. |
3321 __ test(eax, Immediate(kSmiTagMask)); | 3321 __ test(eax, Immediate(kSmiTagMask)); |
3322 __ j(not_zero, &slow, not_taken); | 3322 __ j(not_zero, &slow); |
3323 | 3323 |
3324 // Check that the map matches. | 3324 // Check that the map matches. |
3325 __ CheckMap(edx, Handle<Map>(receiver->map()), &slow, false); | 3325 __ CheckMap(edx, Handle<Map>(receiver->map()), &slow, false); |
3326 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); | 3326 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); |
3327 | 3327 |
3328 // eax: key, known to be a smi. | 3328 // eax: key, known to be a smi. |
3329 // edx: receiver, known to be a JSObject. | 3329 // edx: receiver, known to be a JSObject. |
3330 // ebx: elements object, known to be an external array. | 3330 // ebx: elements object, known to be an external array. |
3331 // Check that the index is in range. | 3331 // Check that the index is in range. |
3332 __ mov(ecx, eax); | 3332 __ mov(ecx, eax); |
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3675 | 3675 |
3676 return GetCode(flags); | 3676 return GetCode(flags); |
3677 } | 3677 } |
3678 | 3678 |
3679 | 3679 |
3680 #undef __ | 3680 #undef __ |
3681 | 3681 |
3682 } } // namespace v8::internal | 3682 } } // namespace v8::internal |
3683 | 3683 |
3684 #endif // V8_TARGET_ARCH_IA32 | 3684 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |