OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 25 matching lines...) Expand all Loading... |
36 namespace internal { | 36 namespace internal { |
37 | 37 |
38 // ---------------------------------------------------------------------------- | 38 // ---------------------------------------------------------------------------- |
39 // Static IC stub generators. | 39 // Static IC stub generators. |
40 // | 40 // |
41 | 41 |
42 #define __ ACCESS_MASM(masm) | 42 #define __ ACCESS_MASM(masm) |
43 | 43 |
44 | 44 |
45 // Helper function used to load a property from a dictionary backing storage. | 45 // Helper function used to load a property from a dictionary backing storage. |
| 46 // This function may return false negatives, so miss_label |
| 47 // must always call a backup property load that is complete. |
| 48 // This function is safe to call if the receiver has fast properties, |
| 49 // or if name is not a symbol, and will jump to the miss_label in that case. |
46 static void GenerateDictionaryLoad(MacroAssembler* masm, Label* miss_label, | 50 static void GenerateDictionaryLoad(MacroAssembler* masm, Label* miss_label, |
47 Register r0, Register r1, Register r2, | 51 Register r0, Register r1, Register r2, |
48 Register name) { | 52 Register name) { |
49 // Register use: | 53 // Register use: |
50 // | 54 // |
51 // r0 - used to hold the property dictionary. | 55 // r0 - used to hold the property dictionary. |
52 // | 56 // |
53 // r1 - initially the receiver | 57 // r1 - initially the receiver |
54 // - used for the index into the property dictionary | 58 // - used for the index into the property dictionary |
55 // - holds the result on exit. | 59 // - holds the result on exit. |
56 // | 60 // |
57 // r2 - used to hold the capacity of the property dictionary. | 61 // r2 - used to hold the capacity of the property dictionary. |
58 // | 62 // |
59 // name - holds the name of the property and is unchanges. | 63 // name - holds the name of the property and is unchanged. |
60 | 64 |
61 Label done; | 65 Label done; |
62 | 66 |
63 // Check for the absence of an interceptor. | 67 // Check for the absence of an interceptor. |
64 // Load the map into r0. | 68 // Load the map into r0. |
65 __ mov(r0, FieldOperand(r1, JSObject::kMapOffset)); | 69 __ mov(r0, FieldOperand(r1, JSObject::kMapOffset)); |
66 // Test the has_named_interceptor bit in the map. | 70 // Test the has_named_interceptor bit in the map. |
67 __ test(FieldOperand(r0, Map::kInstanceAttributesOffset), | 71 __ test(FieldOperand(r0, Map::kInstanceAttributesOffset), |
68 Immediate(1 << (Map::kHasNamedInterceptor + (3 * 8)))); | 72 Immediate(1 << (Map::kHasNamedInterceptor + (3 * 8)))); |
69 | 73 |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), | 271 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), |
268 Immediate(Factory::hash_table_map())); | 272 Immediate(Factory::hash_table_map())); |
269 __ j(equal, &slow, not_taken); | 273 __ j(equal, &slow, not_taken); |
270 // Check that the key (index) is within bounds. | 274 // Check that the key (index) is within bounds. |
271 __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset)); | 275 __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset)); |
272 __ j(below, &fast, taken); | 276 __ j(below, &fast, taken); |
273 // Slow case: Load name and receiver from stack and jump to runtime. | 277 // Slow case: Load name and receiver from stack and jump to runtime. |
274 __ bind(&slow); | 278 __ bind(&slow); |
275 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1); | 279 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1); |
276 KeyedLoadIC::Generate(masm, ExternalReference(Runtime::kKeyedGetProperty)); | 280 KeyedLoadIC::Generate(masm, ExternalReference(Runtime::kKeyedGetProperty)); |
277 // Check if the key is a symbol that is not an array index. | 281 |
278 __ bind(&check_string); | 282 __ bind(&check_string); |
| 283 // The key is not a smi. |
| 284 // Is it a string? |
| 285 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edx); |
| 286 __ j(above_equal, &slow); |
| 287 // Is the string an array index, with cached numeric value? |
279 __ mov(ebx, FieldOperand(eax, String::kLengthOffset)); | 288 __ mov(ebx, FieldOperand(eax, String::kLengthOffset)); |
280 __ test(ebx, Immediate(String::kIsArrayIndexMask)); | 289 __ test(ebx, Immediate(String::kIsArrayIndexMask)); |
281 __ j(not_zero, &index_string, not_taken); | 290 __ j(not_zero, &index_string, not_taken); |
282 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 291 |
283 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); | 292 // If the string is a symbol, do a quick inline probe of the receiver's |
| 293 // dictionary, if it exists. |
| 294 __ movzx_b(ebx, FieldOperand(exd, Map::kInstanceTypeOffset)); |
284 __ test(ebx, Immediate(kIsSymbolMask)); | 295 __ test(ebx, Immediate(kIsSymbolMask)); |
285 __ j(zero, &slow, not_taken); | 296 __ j(zero, &slow, not_taken); |
286 // Probe the dictionary leaving result in ecx. | 297 // Probe the dictionary leaving result in ecx. |
287 GenerateDictionaryLoad(masm, &slow, ebx, ecx, edx, eax); | 298 GenerateDictionaryLoad(masm, &slow, ebx, ecx, edx, eax); |
288 GenerateCheckNonObjectOrLoaded(masm, &slow, ecx, edx); | 299 GenerateCheckNonObjectOrLoaded(masm, &slow, ecx, edx); |
289 __ mov(eax, Operand(ecx)); | 300 __ mov(eax, Operand(ecx)); |
290 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1); | 301 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1); |
291 __ ret(0); | 302 __ ret(0); |
292 // Array index string: If short enough use cache in length/hash field (ebx). | 303 // Array index string: If short enough use cache in length/hash field (ebx). |
293 // We assert that there are enough bits in an int32_t after the hash shift | 304 // We assert that there are enough bits in an int32_t after the hash shift |
(...skipping 685 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
979 | 990 |
980 // Do tail-call to runtime routine. | 991 // Do tail-call to runtime routine. |
981 __ TailCallRuntime( | 992 __ TailCallRuntime( |
982 ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3); | 993 ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3); |
983 } | 994 } |
984 | 995 |
985 #undef __ | 996 #undef __ |
986 | 997 |
987 | 998 |
988 } } // namespace v8::internal | 999 } } // namespace v8::internal |
OLD | NEW |