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

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

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

Powered by Google App Engine
This is Rietveld 408576698