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

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

Issue 7001025: Remove support for branch hints from the IA32 and X64 assembler. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/regexp-macro-assembler-ia32.cc ('k') | src/x64/assembler-x64.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
50 ExternalReference value_offset(isolate->stub_cache()->value_reference(table)); 50 ExternalReference value_offset(isolate->stub_cache()->value_reference(table));
51 51
52 Label miss; 52 Label miss;
53 53
54 if (extra.is_valid()) { 54 if (extra.is_valid()) {
55 // Get the code entry from the cache. 55 // Get the code entry from the cache.
56 __ mov(extra, Operand::StaticArray(offset, times_2, value_offset)); 56 __ mov(extra, Operand::StaticArray(offset, times_2, value_offset));
57 57
58 // Check that the key in the entry matches the name. 58 // Check that the key in the entry matches the name.
59 __ cmp(name, Operand::StaticArray(offset, times_2, key_offset)); 59 __ cmp(name, Operand::StaticArray(offset, times_2, key_offset));
60 __ j(not_equal, &miss, not_taken); 60 __ j(not_equal, &miss);
61 61
62 // Check that the flags match what we're looking for. 62 // Check that the flags match what we're looking for.
63 __ mov(offset, FieldOperand(extra, Code::kFlagsOffset)); 63 __ mov(offset, FieldOperand(extra, Code::kFlagsOffset));
64 __ and_(offset, ~Code::kFlagsNotUsedInLookup); 64 __ and_(offset, ~Code::kFlagsNotUsedInLookup);
65 __ cmp(offset, flags); 65 __ cmp(offset, flags);
66 __ j(not_equal, &miss); 66 __ j(not_equal, &miss);
67 67
68 // Jump to the first instruction in the code stub. 68 // Jump to the first instruction in the code stub.
69 __ add(Operand(extra), Immediate(Code::kHeaderSize - kHeapObjectTag)); 69 __ add(Operand(extra), Immediate(Code::kHeaderSize - kHeapObjectTag));
70 __ jmp(Operand(extra)); 70 __ jmp(Operand(extra));
71 71
72 __ bind(&miss); 72 __ bind(&miss);
73 } else { 73 } else {
74 // Save the offset on the stack. 74 // Save the offset on the stack.
75 __ push(offset); 75 __ push(offset);
76 76
77 // Check that the key in the entry matches the name. 77 // Check that the key in the entry matches the name.
78 __ cmp(name, Operand::StaticArray(offset, times_2, key_offset)); 78 __ cmp(name, Operand::StaticArray(offset, times_2, key_offset));
79 __ j(not_equal, &miss, not_taken); 79 __ j(not_equal, &miss);
80 80
81 // Get the code entry from the cache. 81 // Get the code entry from the cache.
82 __ mov(offset, Operand::StaticArray(offset, times_2, value_offset)); 82 __ mov(offset, Operand::StaticArray(offset, times_2, value_offset));
83 83
84 // Check that the flags match what we're looking for. 84 // Check that the flags match what we're looking for.
85 __ mov(offset, FieldOperand(offset, Code::kFlagsOffset)); 85 __ mov(offset, FieldOperand(offset, Code::kFlagsOffset));
86 __ and_(offset, ~Code::kFlagsNotUsedInLookup); 86 __ and_(offset, ~Code::kFlagsNotUsedInLookup);
87 __ cmp(offset, flags); 87 __ cmp(offset, flags);
88 __ j(not_equal, &miss); 88 __ j(not_equal, &miss);
89 89
(...skipping 29 matching lines...) Expand all
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/ia32/regexp-macro-assembler-ia32.cc ('k') | src/x64/assembler-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698