| 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 |