OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 3864 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3875 Register scratch1, | 3875 Register scratch1, |
3876 Register scratch2, | 3876 Register scratch2, |
3877 bool object_is_smi, | 3877 bool object_is_smi, |
3878 Label* not_found) { | 3878 Label* not_found) { |
3879 // Use of registers. Register result is used as a temporary. | 3879 // Use of registers. Register result is used as a temporary. |
3880 Register number_string_cache = result; | 3880 Register number_string_cache = result; |
3881 Register mask = scratch1; | 3881 Register mask = scratch1; |
3882 Register scratch = scratch2; | 3882 Register scratch = scratch2; |
3883 | 3883 |
3884 // Load the number string cache. | 3884 // Load the number string cache. |
3885 ExternalReference roots_address = | 3885 ExternalReference roots_array_start = |
3886 ExternalReference::roots_address(masm->isolate()); | 3886 ExternalReference::roots_array_start(masm->isolate()); |
3887 __ mov(scratch, Immediate(Heap::kNumberStringCacheRootIndex)); | 3887 __ mov(scratch, Immediate(Heap::kNumberStringCacheRootIndex)); |
3888 __ mov(number_string_cache, | 3888 __ mov(number_string_cache, |
3889 Operand::StaticArray(scratch, times_pointer_size, roots_address)); | 3889 Operand::StaticArray(scratch, times_pointer_size, roots_array_start)); |
3890 // Make the hash mask from the length of the number string cache. It | 3890 // Make the hash mask from the length of the number string cache. It |
3891 // contains two elements (number and string) for each cache entry. | 3891 // contains two elements (number and string) for each cache entry. |
3892 __ mov(mask, FieldOperand(number_string_cache, FixedArray::kLengthOffset)); | 3892 __ mov(mask, FieldOperand(number_string_cache, FixedArray::kLengthOffset)); |
3893 __ shr(mask, kSmiTagSize + 1); // Untag length and divide it by two. | 3893 __ shr(mask, kSmiTagSize + 1); // Untag length and divide it by two. |
3894 __ sub(mask, Immediate(1)); // Make mask. | 3894 __ sub(mask, Immediate(1)); // Make mask. |
3895 | 3895 |
3896 // Calculate the entry in the number string cache. The hash value in the | 3896 // Calculate the entry in the number string cache. The hash value in the |
3897 // number string cache for smis is just the smi value, and the hash for | 3897 // number string cache for smis is just the smi value, and the hash for |
3898 // doubles is the xor of the upper and lower words. See | 3898 // doubles is the xor of the upper and lower words. See |
3899 // Heap::GetNumberStringCache. | 3899 // Heap::GetNumberStringCache. |
(...skipping 947 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4847 Register scratch = ecx; | 4847 Register scratch = ecx; |
4848 | 4848 |
4849 // Constants describing the call site code to patch. | 4849 // Constants describing the call site code to patch. |
4850 static const int kDeltaToCmpImmediate = 2; | 4850 static const int kDeltaToCmpImmediate = 2; |
4851 static const int kDeltaToMov = 8; | 4851 static const int kDeltaToMov = 8; |
4852 static const int kDeltaToMovImmediate = 9; | 4852 static const int kDeltaToMovImmediate = 9; |
4853 static const int8_t kCmpEdiImmediateByte1 = BitCast<int8_t, uint8_t>(0x81); | 4853 static const int8_t kCmpEdiImmediateByte1 = BitCast<int8_t, uint8_t>(0x81); |
4854 static const int8_t kCmpEdiImmediateByte2 = BitCast<int8_t, uint8_t>(0xff); | 4854 static const int8_t kCmpEdiImmediateByte2 = BitCast<int8_t, uint8_t>(0xff); |
4855 static const int8_t kMovEaxImmediateByte = BitCast<int8_t, uint8_t>(0xb8); | 4855 static const int8_t kMovEaxImmediateByte = BitCast<int8_t, uint8_t>(0xb8); |
4856 | 4856 |
4857 ExternalReference roots_address = | 4857 ExternalReference roots_array_start = |
4858 ExternalReference::roots_address(masm->isolate()); | 4858 ExternalReference::roots_array_start(masm->isolate()); |
4859 | 4859 |
4860 ASSERT_EQ(object.code(), InstanceofStub::left().code()); | 4860 ASSERT_EQ(object.code(), InstanceofStub::left().code()); |
4861 ASSERT_EQ(function.code(), InstanceofStub::right().code()); | 4861 ASSERT_EQ(function.code(), InstanceofStub::right().code()); |
4862 | 4862 |
4863 // Get the object and function - they are always both needed. | 4863 // Get the object and function - they are always both needed. |
4864 Label slow, not_js_object; | 4864 Label slow, not_js_object; |
4865 if (!HasArgsInRegisters()) { | 4865 if (!HasArgsInRegisters()) { |
4866 __ mov(object, Operand(esp, 2 * kPointerSize)); | 4866 __ mov(object, Operand(esp, 2 * kPointerSize)); |
4867 __ mov(function, Operand(esp, 1 * kPointerSize)); | 4867 __ mov(function, Operand(esp, 1 * kPointerSize)); |
4868 } | 4868 } |
4869 | 4869 |
4870 // Check that the left hand is a JS object. | 4870 // Check that the left hand is a JS object. |
4871 __ JumpIfSmi(object, ¬_js_object); | 4871 __ JumpIfSmi(object, ¬_js_object); |
4872 __ IsObjectJSObjectType(object, map, scratch, ¬_js_object); | 4872 __ IsObjectJSObjectType(object, map, scratch, ¬_js_object); |
4873 | 4873 |
4874 // If there is a call site cache don't look in the global cache, but do the | 4874 // If there is a call site cache don't look in the global cache, but do the |
4875 // real lookup and update the call site cache. | 4875 // real lookup and update the call site cache. |
4876 if (!HasCallSiteInlineCheck()) { | 4876 if (!HasCallSiteInlineCheck()) { |
4877 // Look up the function and the map in the instanceof cache. | 4877 // Look up the function and the map in the instanceof cache. |
4878 Label miss; | 4878 Label miss; |
4879 __ mov(scratch, Immediate(Heap::kInstanceofCacheFunctionRootIndex)); | 4879 __ mov(scratch, Immediate(Heap::kInstanceofCacheFunctionRootIndex)); |
4880 __ cmp(function, | 4880 __ cmp(function, Operand::StaticArray(scratch, |
4881 Operand::StaticArray(scratch, times_pointer_size, roots_address)); | 4881 times_pointer_size, |
| 4882 roots_array_start)); |
4882 __ j(not_equal, &miss, Label::kNear); | 4883 __ j(not_equal, &miss, Label::kNear); |
4883 __ mov(scratch, Immediate(Heap::kInstanceofCacheMapRootIndex)); | 4884 __ mov(scratch, Immediate(Heap::kInstanceofCacheMapRootIndex)); |
4884 __ cmp(map, Operand::StaticArray( | 4885 __ cmp(map, Operand::StaticArray( |
4885 scratch, times_pointer_size, roots_address)); | 4886 scratch, times_pointer_size, roots_array_start)); |
4886 __ j(not_equal, &miss, Label::kNear); | 4887 __ j(not_equal, &miss, Label::kNear); |
4887 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex)); | 4888 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex)); |
4888 __ mov(eax, Operand::StaticArray( | 4889 __ mov(eax, Operand::StaticArray( |
4889 scratch, times_pointer_size, roots_address)); | 4890 scratch, times_pointer_size, roots_array_start)); |
4890 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); | 4891 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); |
4891 __ bind(&miss); | 4892 __ bind(&miss); |
4892 } | 4893 } |
4893 | 4894 |
4894 // Get the prototype of the function. | 4895 // Get the prototype of the function. |
4895 __ TryGetFunctionPrototype(function, prototype, scratch, &slow, true); | 4896 __ TryGetFunctionPrototype(function, prototype, scratch, &slow, true); |
4896 | 4897 |
4897 // Check that the function prototype is a JS object. | 4898 // Check that the function prototype is a JS object. |
4898 __ JumpIfSmi(prototype, &slow); | 4899 __ JumpIfSmi(prototype, &slow); |
4899 __ IsObjectJSObjectType(prototype, scratch, scratch, &slow); | 4900 __ IsObjectJSObjectType(prototype, scratch, scratch, &slow); |
4900 | 4901 |
4901 // Update the global instanceof or call site inlined cache with the current | 4902 // Update the global instanceof or call site inlined cache with the current |
4902 // map and function. The cached answer will be set when it is known below. | 4903 // map and function. The cached answer will be set when it is known below. |
4903 if (!HasCallSiteInlineCheck()) { | 4904 if (!HasCallSiteInlineCheck()) { |
4904 __ mov(scratch, Immediate(Heap::kInstanceofCacheMapRootIndex)); | 4905 __ mov(scratch, Immediate(Heap::kInstanceofCacheMapRootIndex)); |
4905 __ mov(Operand::StaticArray(scratch, times_pointer_size, roots_address), map); | 4906 __ mov(Operand::StaticArray(scratch, times_pointer_size, roots_array_start), |
| 4907 map); |
4906 __ mov(scratch, Immediate(Heap::kInstanceofCacheFunctionRootIndex)); | 4908 __ mov(scratch, Immediate(Heap::kInstanceofCacheFunctionRootIndex)); |
4907 __ mov(Operand::StaticArray(scratch, times_pointer_size, roots_address), | 4909 __ mov(Operand::StaticArray(scratch, times_pointer_size, roots_array_start), |
4908 function); | 4910 function); |
4909 } else { | 4911 } else { |
4910 // The constants for the code patching are based on no push instructions | 4912 // The constants for the code patching are based on no push instructions |
4911 // at the call site. | 4913 // at the call site. |
4912 ASSERT(HasArgsInRegisters()); | 4914 ASSERT(HasArgsInRegisters()); |
4913 // Get return address and delta to inlined map check. | 4915 // Get return address and delta to inlined map check. |
4914 __ mov(scratch, Operand(esp, 0 * kPointerSize)); | 4916 __ mov(scratch, Operand(esp, 0 * kPointerSize)); |
4915 __ sub(scratch, Operand(esp, 1 * kPointerSize)); | 4917 __ sub(scratch, Operand(esp, 1 * kPointerSize)); |
4916 if (FLAG_debug_code) { | 4918 if (FLAG_debug_code) { |
4917 __ cmpb(Operand(scratch, 0), kCmpEdiImmediateByte1); | 4919 __ cmpb(Operand(scratch, 0), kCmpEdiImmediateByte1); |
(...skipping 16 matching lines...) Expand all Loading... |
4934 __ j(equal, &is_not_instance, Label::kNear); | 4936 __ j(equal, &is_not_instance, Label::kNear); |
4935 __ mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); | 4937 __ mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); |
4936 __ mov(scratch, FieldOperand(scratch, Map::kPrototypeOffset)); | 4938 __ mov(scratch, FieldOperand(scratch, Map::kPrototypeOffset)); |
4937 __ jmp(&loop); | 4939 __ jmp(&loop); |
4938 | 4940 |
4939 __ bind(&is_instance); | 4941 __ bind(&is_instance); |
4940 if (!HasCallSiteInlineCheck()) { | 4942 if (!HasCallSiteInlineCheck()) { |
4941 __ Set(eax, Immediate(0)); | 4943 __ Set(eax, Immediate(0)); |
4942 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex)); | 4944 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex)); |
4943 __ mov(Operand::StaticArray(scratch, | 4945 __ mov(Operand::StaticArray(scratch, |
4944 times_pointer_size, roots_address), eax); | 4946 times_pointer_size, roots_array_start), eax); |
4945 } else { | 4947 } else { |
4946 // Get return address and delta to inlined map check. | 4948 // Get return address and delta to inlined map check. |
4947 __ mov(eax, factory->true_value()); | 4949 __ mov(eax, factory->true_value()); |
4948 __ mov(scratch, Operand(esp, 0 * kPointerSize)); | 4950 __ mov(scratch, Operand(esp, 0 * kPointerSize)); |
4949 __ sub(scratch, Operand(esp, 1 * kPointerSize)); | 4951 __ sub(scratch, Operand(esp, 1 * kPointerSize)); |
4950 if (FLAG_debug_code) { | 4952 if (FLAG_debug_code) { |
4951 __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte); | 4953 __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte); |
4952 __ Assert(equal, "InstanceofStub unexpected call site cache (mov)"); | 4954 __ Assert(equal, "InstanceofStub unexpected call site cache (mov)"); |
4953 } | 4955 } |
4954 __ mov(Operand(scratch, kDeltaToMovImmediate), eax); | 4956 __ mov(Operand(scratch, kDeltaToMovImmediate), eax); |
4955 if (!ReturnTrueFalseObject()) { | 4957 if (!ReturnTrueFalseObject()) { |
4956 __ Set(eax, Immediate(0)); | 4958 __ Set(eax, Immediate(0)); |
4957 } | 4959 } |
4958 } | 4960 } |
4959 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); | 4961 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); |
4960 | 4962 |
4961 __ bind(&is_not_instance); | 4963 __ bind(&is_not_instance); |
4962 if (!HasCallSiteInlineCheck()) { | 4964 if (!HasCallSiteInlineCheck()) { |
4963 __ Set(eax, Immediate(Smi::FromInt(1))); | 4965 __ Set(eax, Immediate(Smi::FromInt(1))); |
4964 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex)); | 4966 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex)); |
4965 __ mov(Operand::StaticArray( | 4967 __ mov(Operand::StaticArray( |
4966 scratch, times_pointer_size, roots_address), eax); | 4968 scratch, times_pointer_size, roots_array_start), eax); |
4967 } else { | 4969 } else { |
4968 // Get return address and delta to inlined map check. | 4970 // Get return address and delta to inlined map check. |
4969 __ mov(eax, factory->false_value()); | 4971 __ mov(eax, factory->false_value()); |
4970 __ mov(scratch, Operand(esp, 0 * kPointerSize)); | 4972 __ mov(scratch, Operand(esp, 0 * kPointerSize)); |
4971 __ sub(scratch, Operand(esp, 1 * kPointerSize)); | 4973 __ sub(scratch, Operand(esp, 1 * kPointerSize)); |
4972 if (FLAG_debug_code) { | 4974 if (FLAG_debug_code) { |
4973 __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte); | 4975 __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte); |
4974 __ Assert(equal, "InstanceofStub unexpected call site cache (mov)"); | 4976 __ Assert(equal, "InstanceofStub unexpected call site cache (mov)"); |
4975 } | 4977 } |
4976 __ mov(Operand(scratch, kDeltaToMovImmediate), eax); | 4978 __ mov(Operand(scratch, kDeltaToMovImmediate), eax); |
(...skipping 768 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5745 // Collect the two characters in a register. | 5747 // Collect the two characters in a register. |
5746 Register chars = c1; | 5748 Register chars = c1; |
5747 __ shl(c2, kBitsPerByte); | 5749 __ shl(c2, kBitsPerByte); |
5748 __ or_(chars, c2); | 5750 __ or_(chars, c2); |
5749 | 5751 |
5750 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. | 5752 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. |
5751 // hash: hash of two character string. | 5753 // hash: hash of two character string. |
5752 | 5754 |
5753 // Load the symbol table. | 5755 // Load the symbol table. |
5754 Register symbol_table = c2; | 5756 Register symbol_table = c2; |
5755 ExternalReference roots_address = | 5757 ExternalReference roots_array_start = |
5756 ExternalReference::roots_address(masm->isolate()); | 5758 ExternalReference::roots_array_start(masm->isolate()); |
5757 __ mov(scratch, Immediate(Heap::kSymbolTableRootIndex)); | 5759 __ mov(scratch, Immediate(Heap::kSymbolTableRootIndex)); |
5758 __ mov(symbol_table, | 5760 __ mov(symbol_table, |
5759 Operand::StaticArray(scratch, times_pointer_size, roots_address)); | 5761 Operand::StaticArray(scratch, times_pointer_size, roots_array_start)); |
5760 | 5762 |
5761 // Calculate capacity mask from the symbol table capacity. | 5763 // Calculate capacity mask from the symbol table capacity. |
5762 Register mask = scratch2; | 5764 Register mask = scratch2; |
5763 __ mov(mask, FieldOperand(symbol_table, SymbolTable::kCapacityOffset)); | 5765 __ mov(mask, FieldOperand(symbol_table, SymbolTable::kCapacityOffset)); |
5764 __ SmiUntag(mask); | 5766 __ SmiUntag(mask); |
5765 __ sub(mask, Immediate(1)); | 5767 __ sub(mask, Immediate(1)); |
5766 | 5768 |
5767 // Registers | 5769 // Registers |
5768 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. | 5770 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. |
5769 // hash: hash of two character string | 5771 // hash: hash of two character string |
(...skipping 1500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7270 // Restore registers. | 7272 // Restore registers. |
7271 __ pop(eax); | 7273 __ pop(eax); |
7272 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 7274 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
7273 } | 7275 } |
7274 | 7276 |
7275 #undef __ | 7277 #undef __ |
7276 | 7278 |
7277 } } // namespace v8::internal | 7279 } } // namespace v8::internal |
7278 | 7280 |
7279 #endif // V8_TARGET_ARCH_IA32 | 7281 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |