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 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
296 MemOperand(scratch1, key, LSL, kPointerSizeLog2 - kSmiTagSize)); | 296 MemOperand(scratch1, key, LSL, kPointerSizeLog2 - kSmiTagSize)); |
297 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 297 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
298 __ cmp(scratch2, ip); | 298 __ cmp(scratch2, ip); |
299 // In case the loaded value is the_hole we have to consult GetProperty | 299 // In case the loaded value is the_hole we have to consult GetProperty |
300 // to ensure the prototype chain is searched. | 300 // to ensure the prototype chain is searched. |
301 __ b(eq, out_of_range); | 301 __ b(eq, out_of_range); |
302 __ mov(result, scratch2); | 302 __ mov(result, scratch2); |
303 } | 303 } |
304 | 304 |
305 | 305 |
306 // Checks whether a key is an array index string or a symbol string. | 306 // Checks whether a key is an array index string or an internalized string. |
307 // Falls through if a key is a symbol. | 307 // Falls through if a key is an internalized string. |
308 static void GenerateKeyStringCheck(MacroAssembler* masm, | 308 static void GenerateKeyStringCheck(MacroAssembler* masm, |
309 Register key, | 309 Register key, |
310 Register map, | 310 Register map, |
311 Register hash, | 311 Register hash, |
312 Label* index_string, | 312 Label* index_string, |
313 Label* not_symbol) { | 313 Label* not_internalized) { |
314 // The key is not a smi. | 314 // The key is not a smi. |
315 // Is it a string? | 315 // Is it a string? |
316 __ CompareObjectType(key, map, hash, FIRST_NONSTRING_TYPE); | 316 __ CompareObjectType(key, map, hash, FIRST_NONSTRING_TYPE); |
317 __ b(ge, not_symbol); | 317 __ b(ge, not_internalized); |
318 | 318 |
319 // Is the string an array index, with cached numeric value? | 319 // Is the string an array index, with cached numeric value? |
320 __ ldr(hash, FieldMemOperand(key, String::kHashFieldOffset)); | 320 __ ldr(hash, FieldMemOperand(key, String::kHashFieldOffset)); |
321 __ tst(hash, Operand(String::kContainsCachedArrayIndexMask)); | 321 __ tst(hash, Operand(String::kContainsCachedArrayIndexMask)); |
322 __ b(eq, index_string); | 322 __ b(eq, index_string); |
323 | 323 |
324 // Is the string a symbol? | 324 // Is the string internalized? |
325 // map: key map | 325 // map: key map |
326 __ ldrb(hash, FieldMemOperand(map, Map::kInstanceTypeOffset)); | 326 __ ldrb(hash, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
327 STATIC_ASSERT(kSymbolTag != 0); | 327 STATIC_ASSERT(kInternalizedTag != 0); |
328 __ tst(hash, Operand(kIsSymbolMask)); | 328 __ tst(hash, Operand(kIsInternalizedMask)); |
329 __ b(eq, not_symbol); | 329 __ b(eq, not_internalized); |
330 } | 330 } |
331 | 331 |
332 | 332 |
333 // Defined in ic.cc. | 333 // Defined in ic.cc. |
334 Object* CallIC_Miss(Arguments args); | 334 Object* CallIC_Miss(Arguments args); |
335 | 335 |
336 // The generated code does not accept smi keys. | 336 // The generated code does not accept smi keys. |
337 // The generated code falls through if both probes miss. | 337 // The generated code falls through if both probes miss. |
338 void CallICBase::GenerateMonomorphicCacheProbe(MacroAssembler* masm, | 338 void CallICBase::GenerateMonomorphicCacheProbe(MacroAssembler* masm, |
339 int argc, | 339 int argc, |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
578 __ Push(r1, r2); // pass the receiver and the key | 578 __ Push(r1, r2); // pass the receiver and the key |
579 __ CallRuntime(Runtime::kKeyedGetProperty, 2); | 579 __ CallRuntime(Runtime::kKeyedGetProperty, 2); |
580 __ pop(r2); // restore the key | 580 __ pop(r2); // restore the key |
581 } | 581 } |
582 __ mov(r1, r0); | 582 __ mov(r1, r0); |
583 __ jmp(&do_call); | 583 __ jmp(&do_call); |
584 | 584 |
585 __ bind(&check_string); | 585 __ bind(&check_string); |
586 GenerateKeyStringCheck(masm, r2, r0, r3, &index_string, &slow_call); | 586 GenerateKeyStringCheck(masm, r2, r0, r3, &index_string, &slow_call); |
587 | 587 |
588 // The key is known to be a symbol. | 588 // The key is known to be internalized. |
589 // If the receiver is a regular JS object with slow properties then do | 589 // If the receiver is a regular JS object with slow properties then do |
590 // a quick inline probe of the receiver's dictionary. | 590 // a quick inline probe of the receiver's dictionary. |
591 // Otherwise do the monomorphic cache probe. | 591 // Otherwise do the monomorphic cache probe. |
592 GenerateKeyedLoadReceiverCheck( | 592 GenerateKeyedLoadReceiverCheck( |
593 masm, r1, r0, r3, Map::kHasNamedInterceptor, &lookup_monomorphic_cache); | 593 masm, r1, r0, r3, Map::kHasNamedInterceptor, &lookup_monomorphic_cache); |
594 | 594 |
595 __ ldr(r0, FieldMemOperand(r1, JSObject::kPropertiesOffset)); | 595 __ ldr(r0, FieldMemOperand(r1, JSObject::kPropertiesOffset)); |
596 __ ldr(r3, FieldMemOperand(r0, HeapObject::kMapOffset)); | 596 __ ldr(r3, FieldMemOperand(r0, HeapObject::kMapOffset)); |
597 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); | 597 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); |
598 __ cmp(r3, ip); | 598 __ cmp(r3, ip); |
599 __ b(ne, &lookup_monomorphic_cache); | 599 __ b(ne, &lookup_monomorphic_cache); |
600 | 600 |
601 GenerateDictionaryLoad(masm, &slow_load, r0, r2, r1, r3, r4); | 601 GenerateDictionaryLoad(masm, &slow_load, r0, r2, r1, r3, r4); |
602 __ IncrementCounter(counters->keyed_call_generic_lookup_dict(), 1, r0, r3); | 602 __ IncrementCounter(counters->keyed_call_generic_lookup_dict(), 1, r0, r3); |
603 __ jmp(&do_call); | 603 __ jmp(&do_call); |
604 | 604 |
605 __ bind(&lookup_monomorphic_cache); | 605 __ bind(&lookup_monomorphic_cache); |
606 __ IncrementCounter(counters->keyed_call_generic_lookup_cache(), 1, r0, r3); | 606 __ IncrementCounter(counters->keyed_call_generic_lookup_cache(), 1, r0, r3); |
607 GenerateMonomorphicCacheProbe(masm, | 607 GenerateMonomorphicCacheProbe(masm, |
608 argc, | 608 argc, |
609 Code::KEYED_CALL_IC, | 609 Code::KEYED_CALL_IC, |
610 Code::kNoExtraICState); | 610 Code::kNoExtraICState); |
611 // Fall through on miss. | 611 // Fall through on miss. |
612 | 612 |
613 __ bind(&slow_call); | 613 __ bind(&slow_call); |
614 // This branch is taken if: | 614 // This branch is taken if: |
615 // - the receiver requires boxing or access check, | 615 // - the receiver requires boxing or access check, |
616 // - the key is neither smi nor symbol, | 616 // - the key is neither smi nor an internalized string, |
617 // - the value loaded is not a function, | 617 // - the value loaded is not a function, |
618 // - there is hope that the runtime will create a monomorphic call stub | 618 // - there is hope that the runtime will create a monomorphic call stub |
619 // that will get fetched next time. | 619 // that will get fetched next time. |
620 __ IncrementCounter(counters->keyed_call_generic_slow(), 1, r0, r3); | 620 __ IncrementCounter(counters->keyed_call_generic_slow(), 1, r0, r3); |
621 GenerateMiss(masm, argc); | 621 GenerateMiss(masm, argc); |
622 | 622 |
623 __ bind(&index_string); | 623 __ bind(&index_string); |
624 __ IndexFromHash(r3, r2); | 624 __ IndexFromHash(r3, r2); |
625 // Now jump to the place where smi keys are handled. | 625 // Now jump to the place where smi keys are handled. |
626 __ jmp(&index_smi); | 626 __ jmp(&index_smi); |
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
980 | 980 |
981 // Load the map of the receiver, compute the keyed lookup cache hash | 981 // Load the map of the receiver, compute the keyed lookup cache hash |
982 // based on 32 bits of the map pointer and the string hash. | 982 // based on 32 bits of the map pointer and the string hash. |
983 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); | 983 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); |
984 __ mov(r3, Operand(r2, ASR, KeyedLookupCache::kMapHashShift)); | 984 __ mov(r3, Operand(r2, ASR, KeyedLookupCache::kMapHashShift)); |
985 __ ldr(r4, FieldMemOperand(r0, String::kHashFieldOffset)); | 985 __ ldr(r4, FieldMemOperand(r0, String::kHashFieldOffset)); |
986 __ eor(r3, r3, Operand(r4, ASR, String::kHashShift)); | 986 __ eor(r3, r3, Operand(r4, ASR, String::kHashShift)); |
987 int mask = KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask; | 987 int mask = KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask; |
988 __ And(r3, r3, Operand(mask)); | 988 __ And(r3, r3, Operand(mask)); |
989 | 989 |
990 // Load the key (consisting of map and symbol) from the cache and | 990 // Load the key (consisting of map and internalized string) from the cache and |
991 // check for match. | 991 // check for match. |
992 Label load_in_object_property; | 992 Label load_in_object_property; |
993 static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket; | 993 static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket; |
994 Label hit_on_nth_entry[kEntriesPerBucket]; | 994 Label hit_on_nth_entry[kEntriesPerBucket]; |
995 ExternalReference cache_keys = | 995 ExternalReference cache_keys = |
996 ExternalReference::keyed_lookup_cache_keys(isolate); | 996 ExternalReference::keyed_lookup_cache_keys(isolate); |
997 | 997 |
998 __ mov(r4, Operand(cache_keys)); | 998 __ mov(r4, Operand(cache_keys)); |
999 __ add(r4, r4, Operand(r3, LSL, kPointerSizeLog2 + 1)); | 999 __ add(r4, r4, Operand(r3, LSL, kPointerSizeLog2 + 1)); |
1000 | 1000 |
1001 for (int i = 0; i < kEntriesPerBucket - 1; i++) { | 1001 for (int i = 0; i < kEntriesPerBucket - 1; i++) { |
1002 Label try_next_entry; | 1002 Label try_next_entry; |
1003 // Load map and move r4 to next entry. | 1003 // Load map and move r4 to next entry. |
1004 __ ldr(r5, MemOperand(r4, kPointerSize * 2, PostIndex)); | 1004 __ ldr(r5, MemOperand(r4, kPointerSize * 2, PostIndex)); |
1005 __ cmp(r2, r5); | 1005 __ cmp(r2, r5); |
1006 __ b(ne, &try_next_entry); | 1006 __ b(ne, &try_next_entry); |
1007 __ ldr(r5, MemOperand(r4, -kPointerSize)); // Load symbol | 1007 __ ldr(r5, MemOperand(r4, -kPointerSize)); // Load string |
1008 __ cmp(r0, r5); | 1008 __ cmp(r0, r5); |
1009 __ b(eq, &hit_on_nth_entry[i]); | 1009 __ b(eq, &hit_on_nth_entry[i]); |
1010 __ bind(&try_next_entry); | 1010 __ bind(&try_next_entry); |
1011 } | 1011 } |
1012 | 1012 |
1013 // Last entry: Load map and move r4 to symbol. | 1013 // Last entry: Load map and move r4 to string. |
1014 __ ldr(r5, MemOperand(r4, kPointerSize, PostIndex)); | 1014 __ ldr(r5, MemOperand(r4, kPointerSize, PostIndex)); |
1015 __ cmp(r2, r5); | 1015 __ cmp(r2, r5); |
1016 __ b(ne, &slow); | 1016 __ b(ne, &slow); |
1017 __ ldr(r5, MemOperand(r4)); | 1017 __ ldr(r5, MemOperand(r4)); |
1018 __ cmp(r0, r5); | 1018 __ cmp(r0, r5); |
1019 __ b(ne, &slow); | 1019 __ b(ne, &slow); |
1020 | 1020 |
1021 // Get field offset. | 1021 // Get field offset. |
1022 // r0 : key | 1022 // r0 : key |
1023 // r1 : receiver | 1023 // r1 : receiver |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1065 // exists. | 1065 // exists. |
1066 __ bind(&probe_dictionary); | 1066 __ bind(&probe_dictionary); |
1067 // r1: receiver | 1067 // r1: receiver |
1068 // r0: key | 1068 // r0: key |
1069 // r3: elements | 1069 // r3: elements |
1070 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); | 1070 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); |
1071 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset)); | 1071 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset)); |
1072 GenerateGlobalInstanceTypeCheck(masm, r2, &slow); | 1072 GenerateGlobalInstanceTypeCheck(masm, r2, &slow); |
1073 // Load the property to r0. | 1073 // Load the property to r0. |
1074 GenerateDictionaryLoad(masm, &slow, r3, r0, r0, r2, r4); | 1074 GenerateDictionaryLoad(masm, &slow, r3, r0, r0, r2, r4); |
1075 __ IncrementCounter(isolate->counters()->keyed_load_generic_symbol(), | 1075 __ IncrementCounter( |
1076 1, r2, r3); | 1076 isolate->counters()->keyed_load_generic_symbol(), 1, r2, r3); |
Yang
2013/02/11 12:26:36
forgot to change this?
rossberg
2013/02/11 13:30:16
Intentional, see above.
| |
1077 __ Ret(); | 1077 __ Ret(); |
1078 | 1078 |
1079 __ bind(&index_string); | 1079 __ bind(&index_string); |
1080 __ IndexFromHash(r3, key); | 1080 __ IndexFromHash(r3, key); |
1081 // Now jump to the place where smi keys are handled. | 1081 // Now jump to the place where smi keys are handled. |
1082 __ jmp(&index_smi); | 1082 __ jmp(&index_smi); |
1083 } | 1083 } |
1084 | 1084 |
1085 | 1085 |
1086 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { | 1086 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { |
(...skipping 589 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1676 } else { | 1676 } else { |
1677 ASSERT(Assembler::GetCondition(branch_instr) == ne); | 1677 ASSERT(Assembler::GetCondition(branch_instr) == ne); |
1678 patcher.EmitCondition(eq); | 1678 patcher.EmitCondition(eq); |
1679 } | 1679 } |
1680 } | 1680 } |
1681 | 1681 |
1682 | 1682 |
1683 } } // namespace v8::internal | 1683 } } // namespace v8::internal |
1684 | 1684 |
1685 #endif // V8_TARGET_ARCH_ARM | 1685 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |