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 23 matching lines...) Expand all Loading... |
34 | 34 |
35 namespace v8 { namespace internal { | 35 namespace v8 { namespace internal { |
36 | 36 |
37 // ---------------------------------------------------------------------------- | 37 // ---------------------------------------------------------------------------- |
38 // Static IC stub generators. | 38 // Static IC stub generators. |
39 // | 39 // |
40 | 40 |
41 #define __ masm-> | 41 #define __ masm-> |
42 | 42 |
43 | 43 |
44 // Helper function used from LoadIC/CallIC GenerateNormal. | 44 // Helper function used to load a property from a dictionary backing storage. |
45 static void GenerateDictionaryLoad(MacroAssembler* masm, Label* miss_label, | 45 static void GenerateDictionaryLoad(MacroAssembler* masm, Label* miss_label, |
46 Register r0, Register r1, Register r2, | 46 Register r0, Register r1, Register r2, |
47 Register name) { | 47 Register name) { |
48 // Register use: | 48 // Register use: |
49 // | 49 // |
50 // r0 - used to hold the property dictionary. | 50 // r0 - used to hold the property dictionary. |
51 // | 51 // |
52 // r1 - initially the receiver | 52 // r1 - initially the receiver |
53 // - used for the index into the property dictionary | 53 // - used for the index into the property dictionary |
54 // - holds the result on exit. | 54 // - holds the result on exit. |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
114 __ test(Operand(r0, r1, times_4, kDetailsOffset - kHeapObjectTag), | 114 __ test(Operand(r0, r1, times_4, kDetailsOffset - kHeapObjectTag), |
115 Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize)); | 115 Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize)); |
116 __ j(not_zero, miss_label, not_taken); | 116 __ j(not_zero, miss_label, not_taken); |
117 | 117 |
118 // Get the value at the masked, scaled index. | 118 // Get the value at the masked, scaled index. |
119 const int kValueOffset = kElementsStartOffset + kPointerSize; | 119 const int kValueOffset = kElementsStartOffset + kPointerSize; |
120 __ mov(r1, Operand(r0, r1, times_4, kValueOffset - kHeapObjectTag)); | 120 __ mov(r1, Operand(r0, r1, times_4, kValueOffset - kHeapObjectTag)); |
121 } | 121 } |
122 | 122 |
123 | 123 |
| 124 // Helper function used to check that a value is either not a function |
| 125 // or is loaded if it is a function. |
| 126 static void GenerateCheckNonFunctionOrLoaded(MacroAssembler* masm, Label* miss, |
| 127 Register value, Register scratch) { |
| 128 Label done; |
| 129 // Check if the value is a Smi. |
| 130 __ test(value, Immediate(kSmiTagMask)); |
| 131 __ j(zero, &done, not_taken); |
| 132 // Check if the value is a function. |
| 133 __ mov(scratch, FieldOperand(value, HeapObject::kMapOffset)); |
| 134 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); |
| 135 __ cmp(scratch, JS_FUNCTION_TYPE); |
| 136 __ j(not_equal, &done, taken); |
| 137 // Check if the function has been loaded. |
| 138 __ mov(scratch, FieldOperand(value, JSFunction::kSharedFunctionInfoOffset)); |
| 139 __ mov(scratch, |
| 140 FieldOperand(scratch, SharedFunctionInfo::kLazyLoadDataOffset)); |
| 141 __ cmp(scratch, Factory::undefined_value()); |
| 142 __ j(not_equal, miss, not_taken); |
| 143 __ bind(&done); |
| 144 } |
| 145 |
| 146 |
124 void LoadIC::GenerateArrayLength(MacroAssembler* masm) { | 147 void LoadIC::GenerateArrayLength(MacroAssembler* masm) { |
125 // ----------- S t a t e ------------- | 148 // ----------- S t a t e ------------- |
126 // -- ecx : name | 149 // -- ecx : name |
127 // -- esp[0] : return address | 150 // -- esp[0] : return address |
128 // -- esp[4] : receiver | 151 // -- esp[4] : receiver |
129 // ----------------------------------- | 152 // ----------------------------------- |
130 | 153 |
131 Label miss; | 154 Label miss; |
132 | 155 |
133 __ mov(eax, Operand(esp, kPointerSize)); | 156 __ mov(eax, Operand(esp, kPointerSize)); |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
229 __ bind(&check_string); | 252 __ bind(&check_string); |
230 __ mov(ebx, FieldOperand(eax, String::kLengthOffset)); | 253 __ mov(ebx, FieldOperand(eax, String::kLengthOffset)); |
231 __ test(ebx, Immediate(String::kIsArrayIndexMask)); | 254 __ test(ebx, Immediate(String::kIsArrayIndexMask)); |
232 __ j(not_zero, &index_string, not_taken); | 255 __ j(not_zero, &index_string, not_taken); |
233 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 256 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
234 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); | 257 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); |
235 __ test(ebx, Immediate(kIsSymbolMask)); | 258 __ test(ebx, Immediate(kIsSymbolMask)); |
236 __ j(not_zero, &slow, not_taken); | 259 __ j(not_zero, &slow, not_taken); |
237 // Probe the dictionary leaving result in ecx. | 260 // Probe the dictionary leaving result in ecx. |
238 GenerateDictionaryLoad(masm, &slow, ebx, ecx, edx, eax); | 261 GenerateDictionaryLoad(masm, &slow, ebx, ecx, edx, eax); |
| 262 GenerateCheckNonFunctionOrLoaded(masm, &slow, ecx, edx); |
239 __ mov(eax, Operand(ecx)); | 263 __ mov(eax, Operand(ecx)); |
240 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1); | 264 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1); |
241 __ ret(0); | 265 __ ret(0); |
242 // Array index string: If short enough use cache in length/hash field (ebx). | 266 // Array index string: If short enough use cache in length/hash field (ebx). |
243 // We assert that there are enough bits in an int32_t after the hash shift | 267 // We assert that there are enough bits in an int32_t after the hash shift |
244 // bits have been subtracted to allow space for the length and the cached | 268 // bits have been subtracted to allow space for the length and the cached |
245 // array index. | 269 // array index. |
246 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < | 270 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < |
247 (1 << (String::kShortLengthShift - String::kHashShift))); | 271 (1 << (String::kShortLengthShift - String::kHashShift))); |
248 __ bind(&index_string); | 272 __ bind(&index_string); |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
449 __ mov(edi, Operand(edx)); | 473 __ mov(edi, Operand(edx)); |
450 __ test(edx, Immediate(kSmiTagMask)); | 474 __ test(edx, Immediate(kSmiTagMask)); |
451 __ j(zero, miss, not_taken); | 475 __ j(zero, miss, not_taken); |
452 | 476 |
453 // Check that the value is a JavaScript function. | 477 // Check that the value is a JavaScript function. |
454 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset)); | 478 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset)); |
455 __ movzx_b(edx, FieldOperand(edx, Map::kInstanceTypeOffset)); | 479 __ movzx_b(edx, FieldOperand(edx, Map::kInstanceTypeOffset)); |
456 __ cmp(edx, JS_FUNCTION_TYPE); | 480 __ cmp(edx, JS_FUNCTION_TYPE); |
457 __ j(not_equal, miss, not_taken); | 481 __ j(not_equal, miss, not_taken); |
458 | 482 |
| 483 // Check that the function has been loaded. |
| 484 __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
| 485 __ mov(edx, FieldOperand(edx, SharedFunctionInfo::kLazyLoadDataOffset)); |
| 486 __ cmp(edx, Factory::undefined_value()); |
| 487 __ j(not_equal, miss, not_taken); |
| 488 |
459 // Patch the receiver with the global proxy if necessary. | 489 // Patch the receiver with the global proxy if necessary. |
460 if (is_global_object) { | 490 if (is_global_object) { |
461 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 491 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
462 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 492 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
463 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 493 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
464 } | 494 } |
465 | 495 |
466 // Invoke the function. | 496 // Invoke the function. |
467 ParameterCount actual(argc); | 497 ParameterCount actual(argc); |
468 __ InvokeFunction(edi, actual, JUMP_FUNCTION); | 498 __ InvokeFunction(edi, actual, JUMP_FUNCTION); |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
620 // If this assert fails, we have to check upper bound too. | 650 // If this assert fails, we have to check upper bound too. |
621 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); | 651 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); |
622 | 652 |
623 // Check for access to global object (unlikely). | 653 // Check for access to global object (unlikely). |
624 __ cmp(edx, JS_GLOBAL_PROXY_TYPE); | 654 __ cmp(edx, JS_GLOBAL_PROXY_TYPE); |
625 __ j(equal, &global, not_taken); | 655 __ j(equal, &global, not_taken); |
626 | 656 |
627 // Search the dictionary placing the result in eax. | 657 // Search the dictionary placing the result in eax. |
628 __ bind(&probe); | 658 __ bind(&probe); |
629 GenerateDictionaryLoad(masm, &miss, edx, eax, ebx, ecx); | 659 GenerateDictionaryLoad(masm, &miss, edx, eax, ebx, ecx); |
| 660 GenerateCheckNonFunctionOrLoaded(masm, &miss, eax, edx); |
630 __ ret(0); | 661 __ ret(0); |
631 | 662 |
632 // Global object access: Check access rights. | 663 // Global object access: Check access rights. |
633 __ bind(&global); | 664 __ bind(&global); |
634 __ CheckAccessGlobalProxy(eax, edx, &miss); | 665 __ CheckAccessGlobalProxy(eax, edx, &miss); |
635 __ jmp(&probe); | 666 __ jmp(&probe); |
636 | 667 |
637 // Cache miss: Restore receiver from stack and jump to runtime. | 668 // Cache miss: Restore receiver from stack and jump to runtime. |
638 __ bind(&miss); | 669 __ bind(&miss); |
639 __ mov(eax, Operand(esp, 1 * kPointerSize)); | 670 __ mov(eax, Operand(esp, 1 * kPointerSize)); |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
807 | 838 |
808 // Do tail-call to runtime routine. | 839 // Do tail-call to runtime routine. |
809 __ TailCallRuntime( | 840 __ TailCallRuntime( |
810 ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3); | 841 ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3); |
811 } | 842 } |
812 | 843 |
813 #undef __ | 844 #undef __ |
814 | 845 |
815 | 846 |
816 } } // namespace v8::internal | 847 } } // namespace v8::internal |
OLD | NEW |