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