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

Side by Side Diff: src/x64/ic-x64.cc

Issue 2801007: Remove redundant checks in and around GenerateDictionaryLoad.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 6 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/v8-counters.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 27 matching lines...) Expand all
38 namespace v8 { 38 namespace v8 {
39 namespace internal { 39 namespace internal {
40 40
41 // ---------------------------------------------------------------------------- 41 // ----------------------------------------------------------------------------
42 // Static IC stub generators. 42 // Static IC stub generators.
43 // 43 //
44 44
45 #define __ ACCESS_MASM(masm) 45 #define __ ACCESS_MASM(masm)
46 46
47 47
48 static void GenerateGlobalInstanceTypeCheck(MacroAssembler* masm,
49 Register type,
50 Label* global_object) {
51 // Register usage:
52 // type: holds the receiver instance type on entry.
53 __ cmpb(type, Immediate(JS_GLOBAL_OBJECT_TYPE));
54 __ j(equal, global_object);
55 __ cmpb(type, Immediate(JS_BUILTINS_OBJECT_TYPE));
56 __ j(equal, global_object);
57 __ cmpb(type, Immediate(JS_GLOBAL_PROXY_TYPE));
58 __ j(equal, global_object);
59 }
60
61
62 // Generated code falls through if the receiver is a regular non-global
63 // JS object with slow properties and no interceptors.
64 static void GenerateDictionaryLoadReceiverCheck(MacroAssembler* masm,
65 Register receiver,
66 Register r0,
67 Register r1,
68 Label* miss) {
69 // Register usage:
70 // receiver: holds the receiver on entry and is unchanged.
71 // r0: used to hold receiver instance type.
72 // Holds the property dictionary on fall through.
73 // r1: used to hold receivers map.
74
75 __ JumpIfSmi(receiver, miss);
76
77 // Check that the receiver is a valid JS object.
78 __ movq(r1, FieldOperand(receiver, HeapObject::kMapOffset));
79 __ movb(r0, FieldOperand(r1, Map::kInstanceTypeOffset));
80 __ cmpb(r0, Immediate(FIRST_JS_OBJECT_TYPE));
81 __ j(below, miss);
82
83 // If this assert fails, we have to check upper bound too.
84 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
85
86 GenerateGlobalInstanceTypeCheck(masm, r0, miss);
87
88 // Check for non-global object that requires access check.
89 __ testb(FieldOperand(r1, Map::kBitFieldOffset),
90 Immediate((1 << Map::kIsAccessCheckNeeded) |
91 (1 << Map::kHasNamedInterceptor)));
92 __ j(not_zero, miss);
93
94 __ movq(r0, FieldOperand(receiver, JSObject::kPropertiesOffset));
95 __ CompareRoot(FieldOperand(r0, HeapObject::kMapOffset),
96 Heap::kHashTableMapRootIndex);
97 __ j(not_equal, miss);
98 }
99
100
48 // Helper function used to load a property from a dictionary backing storage. 101 // Helper function used to load a property from a dictionary backing storage.
49 // This function may return false negatives, so miss_label 102 // This function may return false negatives, so miss_label
50 // must always call a backup property load that is complete. 103 // must always call a backup property load that is complete.
51 // This function is safe to call if the receiver has fast properties, 104 // This function is safe to call if name is not a symbol, and will jump to
52 // or if name is not a symbol, and will jump to the miss_label in that case. 105 // the miss_label in that case.
106 // The generated code assumes that the receiver has slow properties,
107 // is not a global object and does not have interceptors.
53 static void GenerateDictionaryLoad(MacroAssembler* masm, 108 static void GenerateDictionaryLoad(MacroAssembler* masm,
54 Label* miss_label, 109 Label* miss_label,
110 Register elements,
111 Register name,
55 Register r0, 112 Register r0,
56 Register r1, 113 Register r1,
57 Register r2, 114 Register result) {
58 Register name,
59 Register r4,
60 Register result,
61 DictionaryCheck check_dictionary) {
62 // Register use: 115 // Register use:
63 // 116 //
64 // r0 - used to hold the property dictionary and is unchanged. 117 // elements - holds the property dictionary on entry and is unchanged.
65 // 118 //
66 // r1 - used to hold the receiver and is unchanged. 119 // name - holds the name of the property on entry and is unchanged.
67 // 120 //
68 // r2 - used to hold the capacity of the property dictionary. 121 // r0 - used to hold the capacity of the property dictionary.
69 // 122 //
70 // name - holds the name of the property and is unchanged. 123 // r1 - used to hold the index into the property dictionary.
71 //
72 // r4 - used to hold the index into the property dictionary.
73 // 124 //
74 // result - holds the result on exit if the load succeeded. 125 // result - holds the result on exit if the load succeeded.
75 126
76 Label done; 127 Label done;
77 128
78 // Check for the absence of an interceptor.
79 // Load the map into r0.
80 __ movq(r0, FieldOperand(r1, JSObject::kMapOffset));
81
82 // Bail out if the receiver has a named interceptor.
83 __ testl(FieldOperand(r0, Map::kBitFieldOffset),
84 Immediate(1 << Map::kHasNamedInterceptor));
85 __ j(not_zero, miss_label);
86
87 // Bail out if we have a JS global proxy object.
88 __ movzxbq(r0, FieldOperand(r0, Map::kInstanceTypeOffset));
89 __ cmpb(r0, Immediate(JS_GLOBAL_PROXY_TYPE));
90 __ j(equal, miss_label);
91
92 // Possible work-around for http://crbug.com/16276.
93 __ cmpb(r0, Immediate(JS_GLOBAL_OBJECT_TYPE));
94 __ j(equal, miss_label);
95 __ cmpb(r0, Immediate(JS_BUILTINS_OBJECT_TYPE));
96 __ j(equal, miss_label);
97
98 // Load properties array.
99 __ movq(r0, FieldOperand(r1, JSObject::kPropertiesOffset));
100
101 if (check_dictionary == CHECK_DICTIONARY) {
102 // Check that the properties array is a dictionary.
103 __ Cmp(FieldOperand(r0, HeapObject::kMapOffset), Factory::hash_table_map());
104 __ j(not_equal, miss_label);
105 }
106
107 // Compute the capacity mask. 129 // Compute the capacity mask.
108 const int kCapacityOffset = 130 const int kCapacityOffset =
109 StringDictionary::kHeaderSize + 131 StringDictionary::kHeaderSize +
110 StringDictionary::kCapacityIndex * kPointerSize; 132 StringDictionary::kCapacityIndex * kPointerSize;
111 __ SmiToInteger32(r2, FieldOperand(r0, kCapacityOffset)); 133 __ SmiToInteger32(r0, FieldOperand(elements, kCapacityOffset));
112 __ decl(r2); 134 __ decl(r0);
113 135
114 // Generate an unrolled loop that performs a few probes before 136 // Generate an unrolled loop that performs a few probes before
115 // giving up. Measurements done on Gmail indicate that 2 probes 137 // giving up. Measurements done on Gmail indicate that 2 probes
116 // cover ~93% of loads from dictionaries. 138 // cover ~93% of loads from dictionaries.
117 static const int kProbes = 4; 139 static const int kProbes = 4;
118 const int kElementsStartOffset = 140 const int kElementsStartOffset =
119 StringDictionary::kHeaderSize + 141 StringDictionary::kHeaderSize +
120 StringDictionary::kElementsStartIndex * kPointerSize; 142 StringDictionary::kElementsStartIndex * kPointerSize;
121 for (int i = 0; i < kProbes; i++) { 143 for (int i = 0; i < kProbes; i++) {
122 // Compute the masked index: (hash + i + i * i) & mask. 144 // Compute the masked index: (hash + i + i * i) & mask.
123 __ movl(r4, FieldOperand(name, String::kHashFieldOffset)); 145 __ movl(r1, FieldOperand(name, String::kHashFieldOffset));
124 __ shrl(r4, Immediate(String::kHashShift)); 146 __ shrl(r1, Immediate(String::kHashShift));
125 if (i > 0) { 147 if (i > 0) {
126 __ addl(r4, Immediate(StringDictionary::GetProbeOffset(i))); 148 __ addl(r1, Immediate(StringDictionary::GetProbeOffset(i)));
127 } 149 }
128 __ and_(r4, r2); 150 __ and_(r1, r0);
129 151
130 // Scale the index by multiplying by the entry size. 152 // Scale the index by multiplying by the entry size.
131 ASSERT(StringDictionary::kEntrySize == 3); 153 ASSERT(StringDictionary::kEntrySize == 3);
132 __ lea(r4, Operand(r4, r4, times_2, 0)); // r4 = r4 * 3 154 __ lea(r1, Operand(r1, r1, times_2, 0)); // r1 = r1 * 3
133 155
134 // Check if the key is identical to the name. 156 // Check if the key is identical to the name.
135 __ cmpq(name, Operand(r0, r4, times_pointer_size, 157 __ cmpq(name, Operand(elements, r1, times_pointer_size,
136 kElementsStartOffset - kHeapObjectTag)); 158 kElementsStartOffset - kHeapObjectTag));
137 if (i != kProbes - 1) { 159 if (i != kProbes - 1) {
138 __ j(equal, &done); 160 __ j(equal, &done);
139 } else { 161 } else {
140 __ j(not_equal, miss_label); 162 __ j(not_equal, miss_label);
141 } 163 }
142 } 164 }
143 165
144 // Check that the value is a normal property. 166 // Check that the value is a normal property.
145 __ bind(&done); 167 __ bind(&done);
146 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; 168 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
147 __ Test(Operand(r0, r4, times_pointer_size, kDetailsOffset - kHeapObjectTag), 169 __ Test(Operand(elements, r1, times_pointer_size,
170 kDetailsOffset - kHeapObjectTag),
148 Smi::FromInt(PropertyDetails::TypeField::mask())); 171 Smi::FromInt(PropertyDetails::TypeField::mask()));
149 __ j(not_zero, miss_label); 172 __ j(not_zero, miss_label);
150 173
151 // Get the value at the masked, scaled index. 174 // Get the value at the masked, scaled index.
152 const int kValueOffset = kElementsStartOffset + kPointerSize; 175 const int kValueOffset = kElementsStartOffset + kPointerSize;
153 __ movq(result, 176 __ movq(result,
154 Operand(r0, r4, times_pointer_size, kValueOffset - kHeapObjectTag)); 177 Operand(elements, r1, times_pointer_size,
178 kValueOffset - kHeapObjectTag));
155 } 179 }
156 180
157 181
158 static void GenerateNumberDictionaryLoad(MacroAssembler* masm, 182 static void GenerateNumberDictionaryLoad(MacroAssembler* masm,
159 Label* miss, 183 Label* miss,
160 Register elements, 184 Register elements,
161 Register key, 185 Register key,
162 Register r0, 186 Register r0,
163 Register r1, 187 Register r1,
164 Register r2, 188 Register r2,
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 } 344 }
321 345
322 346
323 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { 347 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
324 // ----------- S t a t e ------------- 348 // ----------- S t a t e -------------
325 // -- rax : key 349 // -- rax : key
326 // -- rdx : receiver 350 // -- rdx : receiver
327 // -- rsp[0] : return address 351 // -- rsp[0] : return address
328 // ----------------------------------- 352 // -----------------------------------
329 353
354 __ IncrementCounter(&Counters::keyed_load_miss, 1);
355
330 __ pop(rbx); 356 __ pop(rbx);
331 __ push(rdx); // receiver 357 __ push(rdx); // receiver
332 __ push(rax); // name 358 __ push(rax); // name
333 __ push(rbx); // return address 359 __ push(rbx); // return address
334 360
335 // Perform tail call to the entry. 361 // Perform tail call to the entry.
336 ExternalReference ref = ExternalReference(IC_Utility(kKeyedLoadIC_Miss)); 362 ExternalReference ref = ExternalReference(IC_Utility(kKeyedLoadIC_Miss));
337 __ TailCallExternalReference(ref, 2, 1); 363 __ TailCallExternalReference(ref, 2, 1);
338 } 364 }
339 365
(...skipping 13 matching lines...) Expand all
353 // Perform tail call to the entry. 379 // Perform tail call to the entry.
354 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); 380 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
355 } 381 }
356 382
357 383
358 // Checks the receiver for special cases (value type, slow case bits). 384 // Checks the receiver for special cases (value type, slow case bits).
359 // Falls through for regular JS object. 385 // Falls through for regular JS object.
360 static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, 386 static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm,
361 Register receiver, 387 Register receiver,
362 Register map, 388 Register map,
389 int interceptor_bit,
363 Label* slow) { 390 Label* slow) {
364 // Register use: 391 // Register use:
365 // receiver - holds the receiver and is unchanged. 392 // receiver - holds the receiver and is unchanged.
366 // Scratch registers: 393 // Scratch registers:
367 // map - used to hold the map of the receiver. 394 // map - used to hold the map of the receiver.
368 395
369 // Check that the object isn't a smi. 396 // Check that the object isn't a smi.
370 __ JumpIfSmi(receiver, slow); 397 __ JumpIfSmi(receiver, slow);
371 398
372 // Check that the object is some kind of JS object EXCEPT JS Value type. 399 // Check that the object is some kind of JS object EXCEPT JS Value type.
373 // In the case that the object is a value-wrapper object, 400 // In the case that the object is a value-wrapper object,
374 // we enter the runtime system to make sure that indexing 401 // we enter the runtime system to make sure that indexing
375 // into string objects work as intended. 402 // into string objects work as intended.
376 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); 403 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
377 __ CmpObjectType(receiver, JS_OBJECT_TYPE, map); 404 __ CmpObjectType(receiver, JS_OBJECT_TYPE, map);
378 __ j(below, slow); 405 __ j(below, slow);
379 406
380 // Check bit field. 407 // Check bit field.
381 __ testb(FieldOperand(map, Map::kBitFieldOffset), 408 __ testb(FieldOperand(map, Map::kBitFieldOffset),
382 Immediate(KeyedLoadIC::kSlowCaseBitFieldMask)); 409 Immediate((1 << Map::kIsAccessCheckNeeded) |
410 (1 << interceptor_bit)));
383 __ j(not_zero, slow); 411 __ j(not_zero, slow);
384 } 412 }
385 413
386 414
387 // Loads an indexed element from a fast case array. 415 // Loads an indexed element from a fast case array.
388 static void GenerateFastArrayLoad(MacroAssembler* masm, 416 static void GenerateFastArrayLoad(MacroAssembler* masm,
389 Register receiver, 417 Register receiver,
390 Register key, 418 Register key,
391 Register elements, 419 Register elements,
392 Register scratch, 420 Register scratch,
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
493 521
494 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { 522 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
495 // ----------- S t a t e ------------- 523 // ----------- S t a t e -------------
496 // -- rax : key 524 // -- rax : key
497 // -- rdx : receiver 525 // -- rdx : receiver
498 // -- rsp[0] : return address 526 // -- rsp[0] : return address
499 // ----------------------------------- 527 // -----------------------------------
500 Label slow, check_string, index_smi, index_string; 528 Label slow, check_string, index_smi, index_string;
501 Label check_pixel_array, probe_dictionary, check_number_dictionary; 529 Label check_pixel_array, probe_dictionary, check_number_dictionary;
502 530
503 GenerateKeyedLoadReceiverCheck(masm, rdx, rcx, &slow);
504
505 // Check that the key is a smi. 531 // Check that the key is a smi.
506 __ JumpIfNotSmi(rax, &check_string); 532 __ JumpIfNotSmi(rax, &check_string);
507 __ bind(&index_smi); 533 __ bind(&index_smi);
508 // Now the key is known to be a smi. This place is also jumped to from below 534 // Now the key is known to be a smi. This place is also jumped to from below
509 // where a numeric string is converted to a smi. 535 // where a numeric string is converted to a smi.
510 536
537 GenerateKeyedLoadReceiverCheck(
538 masm, rdx, rcx, Map::kHasIndexedInterceptor, &slow);
539
511 GenerateFastArrayLoad(masm, 540 GenerateFastArrayLoad(masm,
512 rdx, 541 rdx,
513 rax, 542 rax,
514 rcx, 543 rcx,
515 rbx, 544 rbx,
516 rax, 545 rax,
517 &check_pixel_array, 546 &check_pixel_array,
518 &slow); 547 &slow);
519 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); 548 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1);
520 __ ret(0); 549 __ ret(0);
(...skipping 29 matching lines...) Expand all
550 __ bind(&slow); 579 __ bind(&slow);
551 // Slow case: Jump to runtime. 580 // Slow case: Jump to runtime.
552 // rdx: receiver 581 // rdx: receiver
553 // rax: key 582 // rax: key
554 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1); 583 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1);
555 GenerateRuntimeGetProperty(masm); 584 GenerateRuntimeGetProperty(masm);
556 585
557 __ bind(&check_string); 586 __ bind(&check_string);
558 GenerateKeyStringCheck(masm, rax, rcx, rbx, &index_string, &slow); 587 GenerateKeyStringCheck(masm, rax, rcx, rbx, &index_string, &slow);
559 588
589 GenerateKeyedLoadReceiverCheck(
590 masm, rdx, rcx, Map::kHasNamedInterceptor, &slow);
591
560 // If the receiver is a fast-case object, check the keyed lookup 592 // If the receiver is a fast-case object, check the keyed lookup
561 // cache. Otherwise probe the dictionary leaving result in rcx. 593 // cache. Otherwise probe the dictionary leaving result in rcx.
562 __ movq(rbx, FieldOperand(rdx, JSObject::kPropertiesOffset)); 594 __ movq(rbx, FieldOperand(rdx, JSObject::kPropertiesOffset));
563 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), 595 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
564 Heap::kHashTableMapRootIndex); 596 Heap::kHashTableMapRootIndex);
565 __ j(equal, &probe_dictionary); 597 __ j(equal, &probe_dictionary);
566 598
567 // Load the map of the receiver, compute the keyed lookup cache hash 599 // Load the map of the receiver, compute the keyed lookup cache hash
568 // based on 32 bits of the map pointer and the string hash. 600 // based on 32 bits of the map pointer and the string hash.
569 __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset)); 601 __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset));
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
601 __ addq(rcx, rdi); 633 __ addq(rcx, rdi);
602 __ movq(rax, FieldOperand(rdx, rcx, times_pointer_size, 0)); 634 __ movq(rax, FieldOperand(rdx, rcx, times_pointer_size, 0));
603 __ IncrementCounter(&Counters::keyed_load_generic_lookup_cache, 1); 635 __ IncrementCounter(&Counters::keyed_load_generic_lookup_cache, 1);
604 __ ret(0); 636 __ ret(0);
605 637
606 // Do a quick inline probe of the receiver's dictionary, if it 638 // Do a quick inline probe of the receiver's dictionary, if it
607 // exists. 639 // exists.
608 __ bind(&probe_dictionary); 640 __ bind(&probe_dictionary);
609 // rdx: receiver 641 // rdx: receiver
610 // rax: key 642 // rax: key
611 GenerateDictionaryLoad(masm, 643 // rbx: elements
612 &slow, 644
613 rbx, 645 __ movq(rcx, FieldOperand(rdx, JSObject::kMapOffset));
614 rdx, 646 __ movb(rcx, FieldOperand(rcx, Map::kInstanceTypeOffset));
615 rcx, 647 GenerateGlobalInstanceTypeCheck(masm, rcx, &slow);
616 rax, 648
617 rdi, 649 GenerateDictionaryLoad(masm, &slow, rbx, rax, rcx, rdi, rax);
618 rax,
619 DICTIONARY_CHECK_DONE);
620 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1); 650 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1);
621 __ ret(0); 651 __ ret(0);
622 652
623 __ bind(&index_string); 653 __ bind(&index_string);
624 GenerateIndexFromHash(masm, rax, rbx); 654 GenerateIndexFromHash(masm, rax, rbx);
625 __ jmp(&index_smi); 655 __ jmp(&index_smi);
626 } 656 }
627 657
628 658
629 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { 659 void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
(...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after
1205 static void GenerateCallMiss(MacroAssembler* masm, int argc, IC::UtilityId id) { 1235 static void GenerateCallMiss(MacroAssembler* masm, int argc, IC::UtilityId id) {
1206 // ----------- S t a t e ------------- 1236 // ----------- S t a t e -------------
1207 // rcx : function name 1237 // rcx : function name
1208 // rsp[0] : return address 1238 // rsp[0] : return address
1209 // rsp[8] : argument argc 1239 // rsp[8] : argument argc
1210 // rsp[16] : argument argc - 1 1240 // rsp[16] : argument argc - 1
1211 // ... 1241 // ...
1212 // rsp[argc * 8] : argument 1 1242 // rsp[argc * 8] : argument 1
1213 // rsp[(argc + 1) * 8] : argument 0 = receiver 1243 // rsp[(argc + 1) * 8] : argument 0 = receiver
1214 // ----------------------------------- 1244 // -----------------------------------
1245
1246 if (id == IC::kCallIC_Miss) {
1247 __ IncrementCounter(&Counters::call_miss, 1);
1248 } else {
1249 __ IncrementCounter(&Counters::keyed_call_miss, 1);
1250 }
1251
1215 // Get the receiver of the function from the stack; 1 ~ return address. 1252 // Get the receiver of the function from the stack; 1 ~ return address.
1216 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 1253 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
1217 1254
1218 // Enter an internal frame. 1255 // Enter an internal frame.
1219 __ EnterInternalFrame(); 1256 __ EnterInternalFrame();
1220 1257
1221 // Push the receiver and the name of the function. 1258 // Push the receiver and the name of the function.
1222 __ push(rdx); 1259 __ push(rdx);
1223 __ push(rcx); 1260 __ push(rcx);
1224 1261
1225 // Call the entry. 1262 // Call the entry.
1226 CEntryStub stub(1); 1263 CEntryStub stub(1);
1227 __ movq(rax, Immediate(2)); 1264 __ movq(rax, Immediate(2));
1228 __ movq(rbx, ExternalReference(IC_Utility(id))); 1265 __ movq(rbx, ExternalReference(IC_Utility(id)));
1229 __ CallStub(&stub); 1266 __ CallStub(&stub);
1230 1267
1231 // Move result to rdi and exit the internal frame. 1268 // Move result to rdi and exit the internal frame.
1232 __ movq(rdi, rax); 1269 __ movq(rdi, rax);
1233 __ LeaveInternalFrame(); 1270 __ LeaveInternalFrame();
1234 1271
1235 // Check if the receiver is a global object of some sort. 1272 // Check if the receiver is a global object of some sort.
1236 Label invoke, global; 1273 // This can happen only for regular CallIC but not KeyedCallIC.
1237 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); // receiver 1274 if (id == IC::kCallIC_Miss) {
1238 __ JumpIfSmi(rdx, &invoke); 1275 Label invoke, global;
1239 __ CmpObjectType(rdx, JS_GLOBAL_OBJECT_TYPE, rcx); 1276 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); // receiver
1240 __ j(equal, &global); 1277 __ JumpIfSmi(rdx, &invoke);
1241 __ CmpInstanceType(rcx, JS_BUILTINS_OBJECT_TYPE); 1278 __ CmpObjectType(rdx, JS_GLOBAL_OBJECT_TYPE, rcx);
1242 __ j(not_equal, &invoke); 1279 __ j(equal, &global);
1280 __ CmpInstanceType(rcx, JS_BUILTINS_OBJECT_TYPE);
1281 __ j(not_equal, &invoke);
1243 1282
1244 // Patch the receiver on the stack. 1283 // Patch the receiver on the stack.
1245 __ bind(&global); 1284 __ bind(&global);
1246 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); 1285 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
1247 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); 1286 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx);
1287 __ bind(&invoke);
1288 }
1248 1289
1249 // Invoke the function. 1290 // Invoke the function.
1250 ParameterCount actual(argc); 1291 ParameterCount actual(argc);
1251 __ bind(&invoke);
1252 __ InvokeFunction(rdi, actual, JUMP_FUNCTION); 1292 __ InvokeFunction(rdi, actual, JUMP_FUNCTION);
1253 } 1293 }
1254 1294
1255 1295
1256 // The generated code does not accept smi keys. 1296 // The generated code does not accept smi keys.
1257 // The generated code falls through if both probes miss. 1297 // The generated code falls through if both probes miss.
1258 static void GenerateMonomorphicCacheProbe(MacroAssembler* masm, 1298 static void GenerateMonomorphicCacheProbe(MacroAssembler* masm,
1259 int argc, 1299 int argc,
1260 Code::Kind kind) { 1300 Code::Kind kind) {
1261 // ----------- S t a t e ------------- 1301 // ----------- S t a t e -------------
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1302 masm, Context::BOOLEAN_FUNCTION_INDEX, rdx); 1342 masm, Context::BOOLEAN_FUNCTION_INDEX, rdx);
1303 1343
1304 // Probe the stub cache for the value object. 1344 // Probe the stub cache for the value object.
1305 __ bind(&probe); 1345 __ bind(&probe);
1306 StubCache::GenerateProbe(masm, flags, rdx, rcx, rbx, no_reg); 1346 StubCache::GenerateProbe(masm, flags, rdx, rcx, rbx, no_reg);
1307 1347
1308 __ bind(&miss); 1348 __ bind(&miss);
1309 } 1349 }
1310 1350
1311 1351
1312 static void GenerateNormalHelper(MacroAssembler* masm, 1352 static void GenerateFunctionTailCall(MacroAssembler* masm,
1313 int argc, 1353 int argc,
1314 bool is_global_object, 1354 Label* miss) {
1315 Label* miss) {
1316 // ----------- S t a t e ------------- 1355 // ----------- S t a t e -------------
1317 // rcx : function name 1356 // rcx : function name
1318 // rdx : receiver 1357 // rdi : function
1319 // rsp[0] : return address 1358 // rsp[0] : return address
1320 // rsp[8] : argument argc 1359 // rsp[8] : argument argc
1321 // rsp[16] : argument argc - 1 1360 // rsp[16] : argument argc - 1
1322 // ... 1361 // ...
1323 // rsp[argc * 8] : argument 1 1362 // rsp[argc * 8] : argument 1
1324 // rsp[(argc + 1) * 8] : argument 0 = receiver 1363 // rsp[(argc + 1) * 8] : argument 0 = receiver
1325 // ----------------------------------- 1364 // -----------------------------------
1326 // Search dictionary - put result in register rdx.
1327 GenerateDictionaryLoad(
1328 masm, miss, rax, rdx, rbx, rcx, rdi, rdi, CHECK_DICTIONARY);
1329
1330 __ JumpIfSmi(rdi, miss); 1365 __ JumpIfSmi(rdi, miss);
1331 // Check that the value is a JavaScript function. 1366 // Check that the value is a JavaScript function.
1332 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rdx); 1367 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rdx);
1333 __ j(not_equal, miss); 1368 __ j(not_equal, miss);
1334 1369
1335 // Patch the receiver with the global proxy if necessary.
1336 if (is_global_object) {
1337 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
1338 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx);
1339 }
1340
1341 // Invoke the function. 1370 // Invoke the function.
1342 ParameterCount actual(argc); 1371 ParameterCount actual(argc);
1343 __ InvokeFunction(rdi, actual, JUMP_FUNCTION); 1372 __ InvokeFunction(rdi, actual, JUMP_FUNCTION);
1344 } 1373 }
1345 1374
1346 1375
1347 // The generated code falls through if the call should be handled by runtime. 1376 // The generated code falls through if the call should be handled by runtime.
1348 static void GenerateCallNormal(MacroAssembler* masm, int argc) { 1377 static void GenerateCallNormal(MacroAssembler* masm, int argc) {
1349 // ----------- S t a t e ------------- 1378 // ----------- S t a t e -------------
1350 // rcx : function name 1379 // rcx : function name
1351 // rsp[0] : return address 1380 // rsp[0] : return address
1352 // rsp[8] : argument argc 1381 // rsp[8] : argument argc
1353 // rsp[16] : argument argc - 1 1382 // rsp[16] : argument argc - 1
1354 // ... 1383 // ...
1355 // rsp[argc * 8] : argument 1 1384 // rsp[argc * 8] : argument 1
1356 // rsp[(argc + 1) * 8] : argument 0 = receiver 1385 // rsp[(argc + 1) * 8] : argument 0 = receiver
1357 // ----------------------------------- 1386 // -----------------------------------
1358 Label miss, global_object, non_global_object; 1387 Label miss;
1359 1388
1360 // Get the receiver of the function from the stack. 1389 // Get the receiver of the function from the stack.
1361 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 1390 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
1362 1391
1363 // Check that the receiver isn't a smi. 1392 GenerateDictionaryLoadReceiverCheck(masm, rdx, rax, rbx, &miss);
1364 __ JumpIfSmi(rdx, &miss);
1365 1393
1366 // Check that the receiver is a valid JS object. 1394 // rax: elements
1367 // Because there are so many map checks and type checks, do not 1395 // Search the dictionary placing the result in rdi.
1368 // use CmpObjectType, but load map and type into registers. 1396 GenerateDictionaryLoad(masm, &miss, rax, rcx, rbx, rdi, rdi);
1369 __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset));
1370 __ movb(rax, FieldOperand(rbx, Map::kInstanceTypeOffset));
1371 __ cmpb(rax, Immediate(FIRST_JS_OBJECT_TYPE));
1372 __ j(below, &miss);
1373 1397
1374 // If this assert fails, we have to check upper bound too. 1398 GenerateFunctionTailCall(masm, argc, &miss);
1375 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
1376
1377 // Check for access to global object.
1378 __ cmpb(rax, Immediate(JS_GLOBAL_OBJECT_TYPE));
1379 __ j(equal, &global_object);
1380 __ cmpb(rax, Immediate(JS_BUILTINS_OBJECT_TYPE));
1381 __ j(not_equal, &non_global_object);
1382
1383 // Accessing global object: Load and invoke.
1384 __ bind(&global_object);
1385 // Check that the global object does not require access checks.
1386 __ movb(rbx, FieldOperand(rbx, Map::kBitFieldOffset));
1387 __ testb(rbx, Immediate(1 << Map::kIsAccessCheckNeeded));
1388 __ j(not_equal, &miss);
1389 GenerateNormalHelper(masm, argc, true, &miss);
1390
1391 // Accessing non-global object: Check for access to global proxy.
1392 Label global_proxy, invoke;
1393 __ bind(&non_global_object);
1394 __ cmpb(rax, Immediate(JS_GLOBAL_PROXY_TYPE));
1395 __ j(equal, &global_proxy);
1396 // Check that the non-global, non-global-proxy object does not
1397 // require access checks.
1398 __ movb(rbx, FieldOperand(rbx, Map::kBitFieldOffset));
1399 __ testb(rbx, Immediate(1 << Map::kIsAccessCheckNeeded));
1400 __ j(not_equal, &miss);
1401 __ bind(&invoke);
1402 GenerateNormalHelper(masm, argc, false, &miss);
1403
1404 // Global object proxy access: Check access rights.
1405 __ bind(&global_proxy);
1406 __ CheckAccessGlobalProxy(rdx, rax, &miss);
1407 __ jmp(&invoke);
1408 1399
1409 __ bind(&miss); 1400 __ bind(&miss);
1410 } 1401 }
1411 1402
1412 1403
1413 void CallIC::GenerateMiss(MacroAssembler* masm, int argc) { 1404 void CallIC::GenerateMiss(MacroAssembler* masm, int argc) {
1414 // ----------- S t a t e ------------- 1405 // ----------- S t a t e -------------
1415 // rcx : function name 1406 // rcx : function name
1416 // rsp[0] : return address 1407 // rsp[0] : return address
1417 // rsp[8] : argument argc 1408 // rsp[8] : argument argc
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
1491 Label check_number_dictionary, check_string, lookup_monomorphic_cache; 1482 Label check_number_dictionary, check_string, lookup_monomorphic_cache;
1492 Label index_smi, index_string; 1483 Label index_smi, index_string;
1493 1484
1494 // Check that the key is a smi. 1485 // Check that the key is a smi.
1495 __ JumpIfNotSmi(rcx, &check_string); 1486 __ JumpIfNotSmi(rcx, &check_string);
1496 1487
1497 __ bind(&index_smi); 1488 __ bind(&index_smi);
1498 // Now the key is known to be a smi. This place is also jumped to from below 1489 // Now the key is known to be a smi. This place is also jumped to from below
1499 // where a numeric string is converted to a smi. 1490 // where a numeric string is converted to a smi.
1500 1491
1501 GenerateKeyedLoadReceiverCheck(masm, rdx, rax, &slow_call); 1492 GenerateKeyedLoadReceiverCheck(
1493 masm, rdx, rax, Map::kHasIndexedInterceptor, &slow_call);
1502 1494
1503 GenerateFastArrayLoad( 1495 GenerateFastArrayLoad(
1504 masm, rdx, rcx, rax, rbx, rdi, &check_number_dictionary, &slow_load); 1496 masm, rdx, rcx, rax, rbx, rdi, &check_number_dictionary, &slow_load);
1505 __ IncrementCounter(&Counters::keyed_call_generic_smi_fast, 1); 1497 __ IncrementCounter(&Counters::keyed_call_generic_smi_fast, 1);
1506 1498
1507 __ bind(&do_call); 1499 __ bind(&do_call);
1508 // receiver in rdx is not used after this point. 1500 // receiver in rdx is not used after this point.
1509 // rcx: key 1501 // rcx: key
1510 // rdi: function 1502 // rdi: function
1511 1503 GenerateFunctionTailCall(masm, argc, &slow_call);
1512 // Check that the value in edi is a JavaScript function.
1513 __ JumpIfSmi(rdi, &slow_call);
1514 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rax);
1515 __ j(not_equal, &slow_call);
1516 // Invoke the function.
1517 ParameterCount actual(argc);
1518 __ InvokeFunction(rdi, actual, JUMP_FUNCTION);
1519 1504
1520 __ bind(&check_number_dictionary); 1505 __ bind(&check_number_dictionary);
1521 // eax: elements 1506 // eax: elements
1522 // ecx: smi key 1507 // ecx: smi key
1523 // Check whether the elements is a number dictionary. 1508 // Check whether the elements is a number dictionary.
1524 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), 1509 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
1525 Heap::kHashTableMapRootIndex); 1510 Heap::kHashTableMapRootIndex);
1511 __ j(not_equal, &slow_load);
1526 __ SmiToInteger32(rbx, rcx); 1512 __ SmiToInteger32(rbx, rcx);
1527 // ebx: untagged index 1513 // ebx: untagged index
1528 GenerateNumberDictionaryLoad(masm, &slow_load, rax, rcx, rbx, r9, rdi, rdi); 1514 GenerateNumberDictionaryLoad(masm, &slow_load, rax, rcx, rbx, r9, rdi, rdi);
1529 __ IncrementCounter(&Counters::keyed_call_generic_smi_dict, 1); 1515 __ IncrementCounter(&Counters::keyed_call_generic_smi_dict, 1);
1530 __ jmp(&do_call); 1516 __ jmp(&do_call);
1531 1517
1532 __ bind(&slow_load); 1518 __ bind(&slow_load);
1533 // This branch is taken when calling KeyedCallIC_Miss is neither required 1519 // This branch is taken when calling KeyedCallIC_Miss is neither required
1534 // nor beneficial. 1520 // nor beneficial.
1535 __ IncrementCounter(&Counters::keyed_call_generic_slow_load, 1); 1521 __ IncrementCounter(&Counters::keyed_call_generic_slow_load, 1);
1536 __ EnterInternalFrame(); 1522 __ EnterInternalFrame();
1537 __ push(rcx); // save the key 1523 __ push(rcx); // save the key
1538 __ push(rdx); // pass the receiver 1524 __ push(rdx); // pass the receiver
1539 __ push(rcx); // pass the key 1525 __ push(rcx); // pass the key
1540 __ CallRuntime(Runtime::kKeyedGetProperty, 2); 1526 __ CallRuntime(Runtime::kKeyedGetProperty, 2);
1541 __ pop(rcx); // restore the key 1527 __ pop(rcx); // restore the key
1542 __ LeaveInternalFrame(); 1528 __ LeaveInternalFrame();
1543 __ movq(rdi, rax); 1529 __ movq(rdi, rax);
1544 __ jmp(&do_call); 1530 __ jmp(&do_call);
1545 1531
1546 __ bind(&check_string); 1532 __ bind(&check_string);
1547 GenerateKeyStringCheck(masm, rcx, rax, rbx, &index_string, &slow_call); 1533 GenerateKeyStringCheck(masm, rcx, rax, rbx, &index_string, &slow_call);
1548 1534
1549 // The key is known to be a symbol. 1535 // The key is known to be a symbol.
1550 // If the receiver is a regular JS object with slow properties then do 1536 // If the receiver is a regular JS object with slow properties then do
1551 // a quick inline probe of the receiver's dictionary. 1537 // a quick inline probe of the receiver's dictionary.
1552 // Otherwise do the monomorphic cache probe. 1538 // Otherwise do the monomorphic cache probe.
1553 GenerateKeyedLoadReceiverCheck(masm, rdx, rax, &lookup_monomorphic_cache); 1539 GenerateKeyedLoadReceiverCheck(
1540 masm, rdx, rax, Map::kHasNamedInterceptor, &lookup_monomorphic_cache);
1554 1541
1555 __ movq(rbx, FieldOperand(rdx, JSObject::kPropertiesOffset)); 1542 __ movq(rbx, FieldOperand(rdx, JSObject::kPropertiesOffset));
1556 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), 1543 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
1557 Heap::kHashTableMapRootIndex); 1544 Heap::kHashTableMapRootIndex);
1558 __ j(not_equal, &lookup_monomorphic_cache); 1545 __ j(not_equal, &lookup_monomorphic_cache);
1559 1546
1560 GenerateDictionaryLoad( 1547 GenerateDictionaryLoad(masm, &slow_load, rbx, rcx, rax, rdi, rdi);
1561 masm, &slow_load, rbx, rdx, rax, rcx, rdi, rdi, DICTIONARY_CHECK_DONE);
1562 __ IncrementCounter(&Counters::keyed_call_generic_lookup_dict, 1); 1548 __ IncrementCounter(&Counters::keyed_call_generic_lookup_dict, 1);
1563 __ jmp(&do_call); 1549 __ jmp(&do_call);
1564 1550
1565 __ bind(&lookup_monomorphic_cache); 1551 __ bind(&lookup_monomorphic_cache);
1566 __ IncrementCounter(&Counters::keyed_call_generic_lookup_cache, 1); 1552 __ IncrementCounter(&Counters::keyed_call_generic_lookup_cache, 1);
1567 GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC); 1553 GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC);
1568 // Fall through on miss. 1554 // Fall through on miss.
1569 1555
1570 __ bind(&slow_call); 1556 __ bind(&slow_call);
1571 // This branch is taken if: 1557 // This branch is taken if:
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1613 } 1599 }
1614 1600
1615 1601
1616 void LoadIC::GenerateMiss(MacroAssembler* masm) { 1602 void LoadIC::GenerateMiss(MacroAssembler* masm) {
1617 // ----------- S t a t e ------------- 1603 // ----------- S t a t e -------------
1618 // -- rax : receiver 1604 // -- rax : receiver
1619 // -- rcx : name 1605 // -- rcx : name
1620 // -- rsp[0] : return address 1606 // -- rsp[0] : return address
1621 // ----------------------------------- 1607 // -----------------------------------
1622 1608
1609 __ IncrementCounter(&Counters::load_miss, 1);
1610
1623 __ pop(rbx); 1611 __ pop(rbx);
1624 __ push(rax); // receiver 1612 __ push(rax); // receiver
1625 __ push(rcx); // name 1613 __ push(rcx); // name
1626 __ push(rbx); // return address 1614 __ push(rbx); // return address
1627 1615
1628 // Perform tail call to the entry. 1616 // Perform tail call to the entry.
1629 ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss)); 1617 ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss));
1630 __ TailCallExternalReference(ref, 2, 1); 1618 __ TailCallExternalReference(ref, 2, 1);
1631 } 1619 }
1632 1620
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1676 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); 1664 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
1677 } 1665 }
1678 1666
1679 1667
1680 void LoadIC::GenerateNormal(MacroAssembler* masm) { 1668 void LoadIC::GenerateNormal(MacroAssembler* masm) {
1681 // ----------- S t a t e ------------- 1669 // ----------- S t a t e -------------
1682 // -- rax : receiver 1670 // -- rax : receiver
1683 // -- rcx : name 1671 // -- rcx : name
1684 // -- rsp[0] : return address 1672 // -- rsp[0] : return address
1685 // ----------------------------------- 1673 // -----------------------------------
1686 Label miss, probe, global; 1674 Label miss;
1687 1675
1688 // Check that the receiver isn't a smi. 1676 GenerateDictionaryLoadReceiverCheck(masm, rax, rdx, rbx, &miss);
1689 __ JumpIfSmi(rax, &miss);
1690 1677
1691 // Check that the receiver is a valid JS object. 1678 // rdx: elements
1692 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rbx);
1693 __ j(below, &miss);
1694
1695 // If this assert fails, we have to check upper bound too.
1696 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
1697
1698 // Check for access to global object (unlikely).
1699 __ CmpInstanceType(rbx, JS_GLOBAL_PROXY_TYPE);
1700 __ j(equal, &global);
1701
1702 // Check for non-global object that requires access check.
1703 __ testl(FieldOperand(rbx, Map::kBitFieldOffset),
1704 Immediate(1 << Map::kIsAccessCheckNeeded));
1705 __ j(not_zero, &miss);
1706
1707 // Search the dictionary placing the result in rax. 1679 // Search the dictionary placing the result in rax.
1708 __ bind(&probe); 1680 GenerateDictionaryLoad(masm, &miss, rdx, rcx, rbx, rdi, rax);
1709 GenerateDictionaryLoad(masm, &miss, rdx, rax, rbx,
1710 rcx, rdi, rax, CHECK_DICTIONARY);
1711 __ ret(0); 1681 __ ret(0);
1712 1682
1713 // Global object access: Check access rights.
1714 __ bind(&global);
1715 __ CheckAccessGlobalProxy(rax, rdx, &miss);
1716 __ jmp(&probe);
1717
1718 // Cache miss: Jump to runtime. 1683 // Cache miss: Jump to runtime.
1719 __ bind(&miss); 1684 __ bind(&miss);
1720 GenerateMiss(masm); 1685 GenerateMiss(masm);
1721 } 1686 }
1722 1687
1723 1688
1724 void LoadIC::GenerateStringLength(MacroAssembler* masm) { 1689 void LoadIC::GenerateStringLength(MacroAssembler* masm) {
1725 // ----------- S t a t e ------------- 1690 // ----------- S t a t e -------------
1726 // -- rax : receiver 1691 // -- rax : receiver
1727 // -- rcx : name 1692 // -- rcx : name
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
1851 GenerateMiss(masm); 1816 GenerateMiss(masm);
1852 } 1817 }
1853 1818
1854 1819
1855 #undef __ 1820 #undef __
1856 1821
1857 1822
1858 } } // namespace v8::internal 1823 } } // namespace v8::internal
1859 1824
1860 #endif // V8_TARGET_ARCH_X64 1825 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/v8-counters.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698