OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
53 __ j(equal, global_object); | 53 __ j(equal, global_object); |
54 __ cmpb(type, Immediate(JS_BUILTINS_OBJECT_TYPE)); | 54 __ cmpb(type, Immediate(JS_BUILTINS_OBJECT_TYPE)); |
55 __ j(equal, global_object); | 55 __ j(equal, global_object); |
56 __ cmpb(type, Immediate(JS_GLOBAL_PROXY_TYPE)); | 56 __ cmpb(type, Immediate(JS_GLOBAL_PROXY_TYPE)); |
57 __ j(equal, global_object); | 57 __ j(equal, global_object); |
58 } | 58 } |
59 | 59 |
60 | 60 |
61 // Generated code falls through if the receiver is a regular non-global | 61 // Generated code falls through if the receiver is a regular non-global |
62 // JS object with slow properties and no interceptors. | 62 // JS object with slow properties and no interceptors. |
63 static void GenerateStringDictionaryReceiverCheck(MacroAssembler* masm, | 63 static void GenerateNameDictionaryReceiverCheck(MacroAssembler* masm, |
64 Register receiver, | 64 Register receiver, |
65 Register r0, | 65 Register r0, |
66 Register r1, | 66 Register r1, |
67 Label* miss) { | 67 Label* miss) { |
68 // Register usage: | 68 // Register usage: |
69 // receiver: holds the receiver on entry and is unchanged. | 69 // receiver: holds the receiver on entry and is unchanged. |
70 // r0: used to hold receiver instance type. | 70 // r0: used to hold receiver instance type. |
71 // Holds the property dictionary on fall through. | 71 // Holds the property dictionary on fall through. |
72 // r1: used to hold receivers map. | 72 // r1: used to hold receivers map. |
73 | 73 |
74 __ JumpIfSmi(receiver, miss); | 74 __ JumpIfSmi(receiver, miss); |
75 | 75 |
76 // Check that the receiver is a valid JS object. | 76 // Check that the receiver is a valid JS object. |
77 __ movq(r1, FieldOperand(receiver, HeapObject::kMapOffset)); | 77 __ movq(r1, FieldOperand(receiver, HeapObject::kMapOffset)); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
120 // | 120 // |
121 // r0 - used to hold the capacity of the property dictionary. | 121 // r0 - used to hold the capacity of the property dictionary. |
122 // | 122 // |
123 // r1 - used to hold the index into the property dictionary. | 123 // r1 - used to hold the index into the property dictionary. |
124 // | 124 // |
125 // result - holds the result on exit if the load succeeded. | 125 // result - holds the result on exit if the load succeeded. |
126 | 126 |
127 Label done; | 127 Label done; |
128 | 128 |
129 // Probe the dictionary. | 129 // Probe the dictionary. |
130 StringDictionaryLookupStub::GeneratePositiveLookup(masm, | 130 NameDictionaryLookupStub::GeneratePositiveLookup(masm, |
131 miss_label, | 131 miss_label, |
132 &done, | 132 &done, |
133 elements, | 133 elements, |
134 name, | 134 name, |
135 r0, | 135 r0, |
136 r1); | 136 r1); |
137 | 137 |
138 // If probing finds an entry in the dictionary, r1 contains the | 138 // If probing finds an entry in the dictionary, r1 contains the |
139 // index into the dictionary. Check that the value is a normal | 139 // index into the dictionary. Check that the value is a normal |
140 // property. | 140 // property. |
141 __ bind(&done); | 141 __ bind(&done); |
142 const int kElementsStartOffset = | 142 const int kElementsStartOffset = |
143 StringDictionary::kHeaderSize + | 143 NameDictionary::kHeaderSize + |
144 StringDictionary::kElementsStartIndex * kPointerSize; | 144 NameDictionary::kElementsStartIndex * kPointerSize; |
145 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; | 145 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; |
146 __ Test(Operand(elements, r1, times_pointer_size, | 146 __ Test(Operand(elements, r1, times_pointer_size, |
147 kDetailsOffset - kHeapObjectTag), | 147 kDetailsOffset - kHeapObjectTag), |
148 Smi::FromInt(PropertyDetails::TypeField::kMask)); | 148 Smi::FromInt(PropertyDetails::TypeField::kMask)); |
149 __ j(not_zero, miss_label); | 149 __ j(not_zero, miss_label); |
150 | 150 |
151 // Get the value at the masked, scaled index. | 151 // Get the value at the masked, scaled index. |
152 const int kValueOffset = kElementsStartOffset + kPointerSize; | 152 const int kValueOffset = kElementsStartOffset + kPointerSize; |
153 __ movq(result, | 153 __ movq(result, |
154 Operand(elements, r1, times_pointer_size, | 154 Operand(elements, r1, times_pointer_size, |
(...skipping 22 matching lines...) Expand all Loading... |
177 // name - holds the name of the property on entry and is unchanged. | 177 // name - holds the name of the property on entry and is unchanged. |
178 // | 178 // |
179 // value - holds the value to store and is unchanged. | 179 // value - holds the value to store and is unchanged. |
180 // | 180 // |
181 // scratch0 - used during the positive dictionary lookup and is clobbered. | 181 // scratch0 - used during the positive dictionary lookup and is clobbered. |
182 // | 182 // |
183 // scratch1 - used for index into the property dictionary and is clobbered. | 183 // scratch1 - used for index into the property dictionary and is clobbered. |
184 Label done; | 184 Label done; |
185 | 185 |
186 // Probe the dictionary. | 186 // Probe the dictionary. |
187 StringDictionaryLookupStub::GeneratePositiveLookup(masm, | 187 NameDictionaryLookupStub::GeneratePositiveLookup(masm, |
188 miss_label, | 188 miss_label, |
189 &done, | 189 &done, |
190 elements, | 190 elements, |
191 name, | 191 name, |
192 scratch0, | 192 scratch0, |
193 scratch1); | 193 scratch1); |
194 | 194 |
195 // If probing finds an entry in the dictionary, scratch0 contains the | 195 // If probing finds an entry in the dictionary, scratch0 contains the |
196 // index into the dictionary. Check that the value is a normal | 196 // index into the dictionary. Check that the value is a normal |
197 // property that is not read only. | 197 // property that is not read only. |
198 __ bind(&done); | 198 __ bind(&done); |
199 const int kElementsStartOffset = | 199 const int kElementsStartOffset = |
200 StringDictionary::kHeaderSize + | 200 NameDictionary::kHeaderSize + |
201 StringDictionary::kElementsStartIndex * kPointerSize; | 201 NameDictionary::kElementsStartIndex * kPointerSize; |
202 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; | 202 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; |
203 const int kTypeAndReadOnlyMask = | 203 const int kTypeAndReadOnlyMask = |
204 (PropertyDetails::TypeField::kMask | | 204 (PropertyDetails::TypeField::kMask | |
205 PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize; | 205 PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize; |
206 __ Test(Operand(elements, | 206 __ Test(Operand(elements, |
207 scratch1, | 207 scratch1, |
208 times_pointer_size, | 208 times_pointer_size, |
209 kDetailsOffset - kHeapObjectTag), | 209 kDetailsOffset - kHeapObjectTag), |
210 Smi::FromInt(kTypeAndReadOnlyMask)); | 210 Smi::FromInt(kTypeAndReadOnlyMask)); |
211 __ j(not_zero, miss_label); | 211 __ j(not_zero, miss_label); |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
306 __ CompareRoot(scratch, Heap::kTheHoleValueRootIndex); | 306 __ CompareRoot(scratch, Heap::kTheHoleValueRootIndex); |
307 // In case the loaded value is the_hole we have to consult GetProperty | 307 // In case the loaded value is the_hole we have to consult GetProperty |
308 // to ensure the prototype chain is searched. | 308 // to ensure the prototype chain is searched. |
309 __ j(equal, out_of_range); | 309 __ j(equal, out_of_range); |
310 if (!result.is(scratch)) { | 310 if (!result.is(scratch)) { |
311 __ movq(result, scratch); | 311 __ movq(result, scratch); |
312 } | 312 } |
313 } | 313 } |
314 | 314 |
315 | 315 |
316 // Checks whether a key is an array index string or an internalized string. | 316 // Checks whether a key is an array index string or a unique name. |
317 // Falls through if the key is an internalized string. | 317 // Falls through if the key is a unique name. |
318 static void GenerateKeyStringCheck(MacroAssembler* masm, | 318 static void GenerateKeyNameCheck(MacroAssembler* masm, |
319 Register key, | 319 Register key, |
320 Register map, | 320 Register map, |
321 Register hash, | 321 Register hash, |
322 Label* index_string, | 322 Label* index_string, |
323 Label* not_internalized) { | 323 Label* not_unique) { |
324 // Register use: | 324 // Register use: |
325 // key - holds the key and is unchanged. Assumed to be non-smi. | 325 // key - holds the key and is unchanged. Assumed to be non-smi. |
326 // Scratch registers: | 326 // Scratch registers: |
327 // map - used to hold the map of the key. | 327 // map - used to hold the map of the key. |
328 // hash - used to hold the hash of the key. | 328 // hash - used to hold the hash of the key. |
329 __ CmpObjectType(key, FIRST_NONSTRING_TYPE, map); | 329 Label unique; |
330 __ j(above_equal, not_internalized); | 330 __ CmpObjectType(key, LAST_UNIQUE_NAME_TYPE, map); |
| 331 __ j(above, not_unique); |
| 332 STATIC_ASSERT(LAST_UNIQUE_NAME_TYPE == FIRST_NONSTRING_TYPE); |
| 333 __ j(equal, &unique); |
| 334 |
331 // Is the string an array index, with cached numeric value? | 335 // Is the string an array index, with cached numeric value? |
332 __ movl(hash, FieldOperand(key, String::kHashFieldOffset)); | 336 __ movl(hash, FieldOperand(key, Name::kHashFieldOffset)); |
333 __ testl(hash, Immediate(String::kContainsCachedArrayIndexMask)); | 337 __ testl(hash, Immediate(Name::kContainsCachedArrayIndexMask)); |
334 __ j(zero, index_string); // The value in hash is used at jump target. | 338 __ j(zero, index_string); // The value in hash is used at jump target. |
335 | 339 |
336 // Is the string internalized? | 340 // Is the string internalized? |
337 STATIC_ASSERT(kInternalizedTag != 0); | 341 STATIC_ASSERT(kInternalizedTag != 0); |
338 __ testb(FieldOperand(map, Map::kInstanceTypeOffset), | 342 __ testb(FieldOperand(map, Map::kInstanceTypeOffset), |
339 Immediate(kIsInternalizedMask)); | 343 Immediate(kIsInternalizedMask)); |
340 __ j(zero, not_internalized); | 344 __ j(zero, not_unique); |
| 345 |
| 346 __ bind(&unique); |
341 } | 347 } |
342 | 348 |
343 | 349 |
344 | 350 |
345 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { | 351 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { |
346 // ----------- S t a t e ------------- | 352 // ----------- S t a t e ------------- |
347 // -- rax : key | 353 // -- rax : key |
348 // -- rdx : receiver | 354 // -- rdx : receiver |
349 // -- rsp[0] : return address | 355 // -- rsp[0] : return address |
350 // ----------------------------------- | 356 // ----------------------------------- |
351 Label slow, check_string, index_smi, index_string, property_array_property; | 357 Label slow, check_name, index_smi, index_name, property_array_property; |
352 Label probe_dictionary, check_number_dictionary; | 358 Label probe_dictionary, check_number_dictionary; |
353 | 359 |
354 // Check that the key is a smi. | 360 // Check that the key is a smi. |
355 __ JumpIfNotSmi(rax, &check_string); | 361 __ JumpIfNotSmi(rax, &check_name); |
356 __ bind(&index_smi); | 362 __ bind(&index_smi); |
357 // Now the key is known to be a smi. This place is also jumped to from below | 363 // Now the key is known to be a smi. This place is also jumped to from below |
358 // where a numeric string is converted to a smi. | 364 // where a numeric string is converted to a smi. |
359 | 365 |
360 GenerateKeyedLoadReceiverCheck( | 366 GenerateKeyedLoadReceiverCheck( |
361 masm, rdx, rcx, Map::kHasIndexedInterceptor, &slow); | 367 masm, rdx, rcx, Map::kHasIndexedInterceptor, &slow); |
362 | 368 |
363 // Check the receiver's map to see if it has fast elements. | 369 // Check the receiver's map to see if it has fast elements. |
364 __ CheckFastElements(rcx, &check_number_dictionary); | 370 __ CheckFastElements(rcx, &check_number_dictionary); |
365 | 371 |
(...skipping 24 matching lines...) Expand all Loading... |
390 __ LoadFromNumberDictionary(&slow, rcx, rax, rbx, r9, rdi, rax); | 396 __ LoadFromNumberDictionary(&slow, rcx, rax, rbx, r9, rdi, rax); |
391 __ ret(0); | 397 __ ret(0); |
392 | 398 |
393 __ bind(&slow); | 399 __ bind(&slow); |
394 // Slow case: Jump to runtime. | 400 // Slow case: Jump to runtime. |
395 // rdx: receiver | 401 // rdx: receiver |
396 // rax: key | 402 // rax: key |
397 __ IncrementCounter(counters->keyed_load_generic_slow(), 1); | 403 __ IncrementCounter(counters->keyed_load_generic_slow(), 1); |
398 GenerateRuntimeGetProperty(masm); | 404 GenerateRuntimeGetProperty(masm); |
399 | 405 |
400 __ bind(&check_string); | 406 __ bind(&check_name); |
401 GenerateKeyStringCheck(masm, rax, rcx, rbx, &index_string, &slow); | 407 GenerateKeyNameCheck(masm, rax, rcx, rbx, &index_name, &slow); |
402 | 408 |
403 GenerateKeyedLoadReceiverCheck( | 409 GenerateKeyedLoadReceiverCheck( |
404 masm, rdx, rcx, Map::kHasNamedInterceptor, &slow); | 410 masm, rdx, rcx, Map::kHasNamedInterceptor, &slow); |
405 | 411 |
406 // If the receiver is a fast-case object, check the keyed lookup | 412 // If the receiver is a fast-case object, check the keyed lookup |
407 // cache. Otherwise probe the dictionary leaving result in rcx. | 413 // cache. Otherwise probe the dictionary leaving result in rcx. |
408 __ movq(rbx, FieldOperand(rdx, JSObject::kPropertiesOffset)); | 414 __ movq(rbx, FieldOperand(rdx, JSObject::kPropertiesOffset)); |
409 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), | 415 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), |
410 Heap::kHashTableMapRootIndex); | 416 Heap::kHashTableMapRootIndex); |
411 __ j(equal, &probe_dictionary); | 417 __ j(equal, &probe_dictionary); |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
492 // rbx: elements | 498 // rbx: elements |
493 | 499 |
494 __ movq(rcx, FieldOperand(rdx, JSObject::kMapOffset)); | 500 __ movq(rcx, FieldOperand(rdx, JSObject::kMapOffset)); |
495 __ movb(rcx, FieldOperand(rcx, Map::kInstanceTypeOffset)); | 501 __ movb(rcx, FieldOperand(rcx, Map::kInstanceTypeOffset)); |
496 GenerateGlobalInstanceTypeCheck(masm, rcx, &slow); | 502 GenerateGlobalInstanceTypeCheck(masm, rcx, &slow); |
497 | 503 |
498 GenerateDictionaryLoad(masm, &slow, rbx, rax, rcx, rdi, rax); | 504 GenerateDictionaryLoad(masm, &slow, rbx, rax, rcx, rdi, rax); |
499 __ IncrementCounter(counters->keyed_load_generic_symbol(), 1); | 505 __ IncrementCounter(counters->keyed_load_generic_symbol(), 1); |
500 __ ret(0); | 506 __ ret(0); |
501 | 507 |
502 __ bind(&index_string); | 508 __ bind(&index_name); |
503 __ IndexFromHash(rbx, rax); | 509 __ IndexFromHash(rbx, rax); |
504 __ jmp(&index_smi); | 510 __ jmp(&index_smi); |
505 } | 511 } |
506 | 512 |
507 | 513 |
508 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { | 514 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { |
509 // ----------- S t a t e ------------- | 515 // ----------- S t a t e ------------- |
510 // -- rax : key | 516 // -- rax : key |
511 // -- rdx : receiver | 517 // -- rdx : receiver |
512 // -- rsp[0] : return address | 518 // -- rsp[0] : return address |
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
893 // rsp[16] : argument argc - 1 | 899 // rsp[16] : argument argc - 1 |
894 // ... | 900 // ... |
895 // rsp[argc * 8] : argument 1 | 901 // rsp[argc * 8] : argument 1 |
896 // rsp[(argc + 1) * 8] : argument 0 = receiver | 902 // rsp[(argc + 1) * 8] : argument 0 = receiver |
897 // ----------------------------------- | 903 // ----------------------------------- |
898 Label miss; | 904 Label miss; |
899 | 905 |
900 // Get the receiver of the function from the stack. | 906 // Get the receiver of the function from the stack. |
901 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 907 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
902 | 908 |
903 GenerateStringDictionaryReceiverCheck(masm, rdx, rax, rbx, &miss); | 909 GenerateNameDictionaryReceiverCheck(masm, rdx, rax, rbx, &miss); |
904 | 910 |
905 // rax: elements | 911 // rax: elements |
906 // Search the dictionary placing the result in rdi. | 912 // Search the dictionary placing the result in rdi. |
907 GenerateDictionaryLoad(masm, &miss, rax, rcx, rbx, rdi, rdi); | 913 GenerateDictionaryLoad(masm, &miss, rax, rcx, rbx, rdi, rdi); |
908 | 914 |
909 GenerateFunctionTailCall(masm, argc, &miss); | 915 GenerateFunctionTailCall(masm, argc, &miss); |
910 | 916 |
911 __ bind(&miss); | 917 __ bind(&miss); |
912 } | 918 } |
913 | 919 |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1013 // rsp[16] : argument argc - 1 | 1019 // rsp[16] : argument argc - 1 |
1014 // ... | 1020 // ... |
1015 // rsp[argc * 8] : argument 1 | 1021 // rsp[argc * 8] : argument 1 |
1016 // rsp[(argc + 1) * 8] : argument 0 = receiver | 1022 // rsp[(argc + 1) * 8] : argument 0 = receiver |
1017 // ----------------------------------- | 1023 // ----------------------------------- |
1018 | 1024 |
1019 // Get the receiver of the function from the stack; 1 ~ return address. | 1025 // Get the receiver of the function from the stack; 1 ~ return address. |
1020 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 1026 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
1021 | 1027 |
1022 Label do_call, slow_call, slow_load; | 1028 Label do_call, slow_call, slow_load; |
1023 Label check_number_dictionary, check_string, lookup_monomorphic_cache; | 1029 Label check_number_dictionary, check_name, lookup_monomorphic_cache; |
1024 Label index_smi, index_string; | 1030 Label index_smi, index_name; |
1025 | 1031 |
1026 // Check that the key is a smi. | 1032 // Check that the key is a smi. |
1027 __ JumpIfNotSmi(rcx, &check_string); | 1033 __ JumpIfNotSmi(rcx, &check_name); |
1028 | 1034 |
1029 __ bind(&index_smi); | 1035 __ bind(&index_smi); |
1030 // Now the key is known to be a smi. This place is also jumped to from below | 1036 // Now the key is known to be a smi. This place is also jumped to from below |
1031 // where a numeric string is converted to a smi. | 1037 // where a numeric string is converted to a smi. |
1032 | 1038 |
1033 GenerateKeyedLoadReceiverCheck( | 1039 GenerateKeyedLoadReceiverCheck( |
1034 masm, rdx, rax, Map::kHasIndexedInterceptor, &slow_call); | 1040 masm, rdx, rax, Map::kHasIndexedInterceptor, &slow_call); |
1035 | 1041 |
1036 GenerateFastArrayLoad( | 1042 GenerateFastArrayLoad( |
1037 masm, rdx, rcx, rax, rbx, rdi, &check_number_dictionary, &slow_load); | 1043 masm, rdx, rcx, rax, rbx, rdi, &check_number_dictionary, &slow_load); |
(...skipping 27 matching lines...) Expand all Loading... |
1065 FrameScope scope(masm, StackFrame::INTERNAL); | 1071 FrameScope scope(masm, StackFrame::INTERNAL); |
1066 __ push(rcx); // save the key | 1072 __ push(rcx); // save the key |
1067 __ push(rdx); // pass the receiver | 1073 __ push(rdx); // pass the receiver |
1068 __ push(rcx); // pass the key | 1074 __ push(rcx); // pass the key |
1069 __ CallRuntime(Runtime::kKeyedGetProperty, 2); | 1075 __ CallRuntime(Runtime::kKeyedGetProperty, 2); |
1070 __ pop(rcx); // restore the key | 1076 __ pop(rcx); // restore the key |
1071 } | 1077 } |
1072 __ movq(rdi, rax); | 1078 __ movq(rdi, rax); |
1073 __ jmp(&do_call); | 1079 __ jmp(&do_call); |
1074 | 1080 |
1075 __ bind(&check_string); | 1081 __ bind(&check_name); |
1076 GenerateKeyStringCheck(masm, rcx, rax, rbx, &index_string, &slow_call); | 1082 GenerateKeyNameCheck(masm, rcx, rax, rbx, &index_name, &slow_call); |
1077 | 1083 |
1078 // The key is known to be an internalized string. | 1084 // The key is known to be a unique name. |
1079 // If the receiver is a regular JS object with slow properties then do | 1085 // If the receiver is a regular JS object with slow properties then do |
1080 // a quick inline probe of the receiver's dictionary. | 1086 // a quick inline probe of the receiver's dictionary. |
1081 // Otherwise do the monomorphic cache probe. | 1087 // Otherwise do the monomorphic cache probe. |
1082 GenerateKeyedLoadReceiverCheck( | 1088 GenerateKeyedLoadReceiverCheck( |
1083 masm, rdx, rax, Map::kHasNamedInterceptor, &lookup_monomorphic_cache); | 1089 masm, rdx, rax, Map::kHasNamedInterceptor, &lookup_monomorphic_cache); |
1084 | 1090 |
1085 __ movq(rbx, FieldOperand(rdx, JSObject::kPropertiesOffset)); | 1091 __ movq(rbx, FieldOperand(rdx, JSObject::kPropertiesOffset)); |
1086 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), | 1092 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), |
1087 Heap::kHashTableMapRootIndex); | 1093 Heap::kHashTableMapRootIndex); |
1088 __ j(not_equal, &lookup_monomorphic_cache); | 1094 __ j(not_equal, &lookup_monomorphic_cache); |
1089 | 1095 |
1090 GenerateDictionaryLoad(masm, &slow_load, rbx, rcx, rax, rdi, rdi); | 1096 GenerateDictionaryLoad(masm, &slow_load, rbx, rcx, rax, rdi, rdi); |
1091 __ IncrementCounter(counters->keyed_call_generic_lookup_dict(), 1); | 1097 __ IncrementCounter(counters->keyed_call_generic_lookup_dict(), 1); |
1092 __ jmp(&do_call); | 1098 __ jmp(&do_call); |
1093 | 1099 |
1094 __ bind(&lookup_monomorphic_cache); | 1100 __ bind(&lookup_monomorphic_cache); |
1095 __ IncrementCounter(counters->keyed_call_generic_lookup_cache(), 1); | 1101 __ IncrementCounter(counters->keyed_call_generic_lookup_cache(), 1); |
1096 GenerateMonomorphicCacheProbe(masm, | 1102 GenerateMonomorphicCacheProbe(masm, |
1097 argc, | 1103 argc, |
1098 Code::KEYED_CALL_IC, | 1104 Code::KEYED_CALL_IC, |
1099 Code::kNoExtraICState); | 1105 Code::kNoExtraICState); |
1100 // Fall through on miss. | 1106 // Fall through on miss. |
1101 | 1107 |
1102 __ bind(&slow_call); | 1108 __ bind(&slow_call); |
1103 // This branch is taken if: | 1109 // This branch is taken if: |
1104 // - the receiver requires boxing or access check, | 1110 // - the receiver requires boxing or access check, |
1105 // - the key is neither smi nor internalized string, | 1111 // - the key is neither smi nor a unique name, |
1106 // - the value loaded is not a function, | 1112 // - the value loaded is not a function, |
1107 // - there is hope that the runtime will create a monomorphic call stub | 1113 // - there is hope that the runtime will create a monomorphic call stub |
1108 // that will get fetched next time. | 1114 // that will get fetched next time. |
1109 __ IncrementCounter(counters->keyed_call_generic_slow(), 1); | 1115 __ IncrementCounter(counters->keyed_call_generic_slow(), 1); |
1110 GenerateMiss(masm, argc); | 1116 GenerateMiss(masm, argc); |
1111 | 1117 |
1112 __ bind(&index_string); | 1118 __ bind(&index_name); |
1113 __ IndexFromHash(rbx, rcx); | 1119 __ IndexFromHash(rbx, rcx); |
1114 // Now jump to the place where smi keys are handled. | 1120 // Now jump to the place where smi keys are handled. |
1115 __ jmp(&index_smi); | 1121 __ jmp(&index_smi); |
1116 } | 1122 } |
1117 | 1123 |
1118 | 1124 |
1119 void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { | 1125 void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { |
1120 // ----------- S t a t e ------------- | 1126 // ----------- S t a t e ------------- |
1121 // rcx : function name | 1127 // rcx : function name |
1122 // rsp[0] : return address | 1128 // rsp[0] : return address |
1123 // rsp[8] : argument argc | 1129 // rsp[8] : argument argc |
1124 // rsp[16] : argument argc - 1 | 1130 // rsp[16] : argument argc - 1 |
1125 // ... | 1131 // ... |
1126 // rsp[argc * 8] : argument 1 | 1132 // rsp[argc * 8] : argument 1 |
1127 // rsp[(argc + 1) * 8] : argument 0 = receiver | 1133 // rsp[(argc + 1) * 8] : argument 0 = receiver |
1128 // ----------------------------------- | 1134 // ----------------------------------- |
1129 | 1135 |
1130 // Check if the name is a string. | 1136 // Check if the name is really a name. |
1131 Label miss; | 1137 Label miss; |
1132 __ JumpIfSmi(rcx, &miss); | 1138 __ JumpIfSmi(rcx, &miss); |
1133 Condition cond = masm->IsObjectStringType(rcx, rax, rax); | 1139 Condition cond = masm->IsObjectNameType(rcx, rax, rax); |
1134 __ j(NegateCondition(cond), &miss); | 1140 __ j(NegateCondition(cond), &miss); |
1135 CallICBase::GenerateNormal(masm, argc); | 1141 CallICBase::GenerateNormal(masm, argc); |
1136 __ bind(&miss); | 1142 __ bind(&miss); |
1137 GenerateMiss(masm, argc); | 1143 GenerateMiss(masm, argc); |
1138 } | 1144 } |
1139 | 1145 |
1140 | 1146 |
1141 static Operand GenerateMappedArgumentsLookup(MacroAssembler* masm, | 1147 static Operand GenerateMappedArgumentsLookup(MacroAssembler* masm, |
1142 Register object, | 1148 Register object, |
1143 Register key, | 1149 Register key, |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1331 | 1337 |
1332 | 1338 |
1333 void LoadIC::GenerateNormal(MacroAssembler* masm) { | 1339 void LoadIC::GenerateNormal(MacroAssembler* masm) { |
1334 // ----------- S t a t e ------------- | 1340 // ----------- S t a t e ------------- |
1335 // -- rax : receiver | 1341 // -- rax : receiver |
1336 // -- rcx : name | 1342 // -- rcx : name |
1337 // -- rsp[0] : return address | 1343 // -- rsp[0] : return address |
1338 // ----------------------------------- | 1344 // ----------------------------------- |
1339 Label miss; | 1345 Label miss; |
1340 | 1346 |
1341 GenerateStringDictionaryReceiverCheck(masm, rax, rdx, rbx, &miss); | 1347 GenerateNameDictionaryReceiverCheck(masm, rax, rdx, rbx, &miss); |
1342 | 1348 |
1343 // rdx: elements | 1349 // rdx: elements |
1344 // Search the dictionary placing the result in rax. | 1350 // Search the dictionary placing the result in rax. |
1345 GenerateDictionaryLoad(masm, &miss, rdx, rcx, rbx, rdi, rax); | 1351 GenerateDictionaryLoad(masm, &miss, rdx, rcx, rbx, rdi, rax); |
1346 __ ret(0); | 1352 __ ret(0); |
1347 | 1353 |
1348 // Cache miss: Jump to runtime. | 1354 // Cache miss: Jump to runtime. |
1349 __ bind(&miss); | 1355 __ bind(&miss); |
1350 GenerateMiss(masm); | 1356 GenerateMiss(masm); |
1351 } | 1357 } |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1458 void StoreIC::GenerateNormal(MacroAssembler* masm) { | 1464 void StoreIC::GenerateNormal(MacroAssembler* masm) { |
1459 // ----------- S t a t e ------------- | 1465 // ----------- S t a t e ------------- |
1460 // -- rax : value | 1466 // -- rax : value |
1461 // -- rcx : name | 1467 // -- rcx : name |
1462 // -- rdx : receiver | 1468 // -- rdx : receiver |
1463 // -- rsp[0] : return address | 1469 // -- rsp[0] : return address |
1464 // ----------------------------------- | 1470 // ----------------------------------- |
1465 | 1471 |
1466 Label miss; | 1472 Label miss; |
1467 | 1473 |
1468 GenerateStringDictionaryReceiverCheck(masm, rdx, rbx, rdi, &miss); | 1474 GenerateNameDictionaryReceiverCheck(masm, rdx, rbx, rdi, &miss); |
1469 | 1475 |
1470 GenerateDictionaryStore(masm, &miss, rbx, rcx, rax, r8, r9); | 1476 GenerateDictionaryStore(masm, &miss, rbx, rcx, rax, r8, r9); |
1471 Counters* counters = masm->isolate()->counters(); | 1477 Counters* counters = masm->isolate()->counters(); |
1472 __ IncrementCounter(counters->store_normal_hit(), 1); | 1478 __ IncrementCounter(counters->store_normal_hit(), 1); |
1473 __ ret(0); | 1479 __ ret(0); |
1474 | 1480 |
1475 __ bind(&miss); | 1481 __ bind(&miss); |
1476 __ IncrementCounter(counters->store_normal_miss(), 1); | 1482 __ IncrementCounter(counters->store_normal_miss(), 1); |
1477 GenerateMiss(masm); | 1483 GenerateMiss(masm); |
1478 } | 1484 } |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1680 Condition cc = (check == ENABLE_INLINED_SMI_CHECK) | 1686 Condition cc = (check == ENABLE_INLINED_SMI_CHECK) |
1681 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) | 1687 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) |
1682 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); | 1688 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); |
1683 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); | 1689 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); |
1684 } | 1690 } |
1685 | 1691 |
1686 | 1692 |
1687 } } // namespace v8::internal | 1693 } } // namespace v8::internal |
1688 | 1694 |
1689 #endif // V8_TARGET_ARCH_X64 | 1695 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |