| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 3938 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3949 Register result, | 3949 Register result, |
| 3950 Register scratch1, | 3950 Register scratch1, |
| 3951 Register scratch2, | 3951 Register scratch2, |
| 3952 Label* not_found) { | 3952 Label* not_found) { |
| 3953 // Use of registers. Register result is used as a temporary. | 3953 // Use of registers. Register result is used as a temporary. |
| 3954 Register number_string_cache = result; | 3954 Register number_string_cache = result; |
| 3955 Register mask = scratch1; | 3955 Register mask = scratch1; |
| 3956 Register scratch = scratch2; | 3956 Register scratch = scratch2; |
| 3957 | 3957 |
| 3958 // Load the number string cache. | 3958 // Load the number string cache. |
| 3959 ExternalReference roots_array_start = | 3959 __ LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex); |
| 3960 ExternalReference::roots_array_start(masm->isolate()); | |
| 3961 __ mov(scratch, Immediate(Heap::kNumberStringCacheRootIndex)); | |
| 3962 __ mov(number_string_cache, | |
| 3963 Operand::StaticArray(scratch, times_pointer_size, roots_array_start)); | |
| 3964 // Make the hash mask from the length of the number string cache. It | 3960 // Make the hash mask from the length of the number string cache. It |
| 3965 // contains two elements (number and string) for each cache entry. | 3961 // contains two elements (number and string) for each cache entry. |
| 3966 __ mov(mask, FieldOperand(number_string_cache, FixedArray::kLengthOffset)); | 3962 __ mov(mask, FieldOperand(number_string_cache, FixedArray::kLengthOffset)); |
| 3967 __ shr(mask, kSmiTagSize + 1); // Untag length and divide it by two. | 3963 __ shr(mask, kSmiTagSize + 1); // Untag length and divide it by two. |
| 3968 __ sub(mask, Immediate(1)); // Make mask. | 3964 __ sub(mask, Immediate(1)); // Make mask. |
| 3969 | 3965 |
| 3970 // Calculate the entry in the number string cache. The hash value in the | 3966 // Calculate the entry in the number string cache. The hash value in the |
| 3971 // number string cache for smis is just the smi value, and the hash for | 3967 // number string cache for smis is just the smi value, and the hash for |
| 3972 // doubles is the xor of the upper and lower words. See | 3968 // doubles is the xor of the upper and lower words. See |
| 3973 // Heap::GetNumberStringCache. | 3969 // Heap::GetNumberStringCache. |
| (...skipping 1029 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5003 Register scratch = ecx; | 4999 Register scratch = ecx; |
| 5004 | 5000 |
| 5005 // Constants describing the call site code to patch. | 5001 // Constants describing the call site code to patch. |
| 5006 static const int kDeltaToCmpImmediate = 2; | 5002 static const int kDeltaToCmpImmediate = 2; |
| 5007 static const int kDeltaToMov = 8; | 5003 static const int kDeltaToMov = 8; |
| 5008 static const int kDeltaToMovImmediate = 9; | 5004 static const int kDeltaToMovImmediate = 9; |
| 5009 static const int8_t kCmpEdiOperandByte1 = BitCast<int8_t, uint8_t>(0x3b); | 5005 static const int8_t kCmpEdiOperandByte1 = BitCast<int8_t, uint8_t>(0x3b); |
| 5010 static const int8_t kCmpEdiOperandByte2 = BitCast<int8_t, uint8_t>(0x3d); | 5006 static const int8_t kCmpEdiOperandByte2 = BitCast<int8_t, uint8_t>(0x3d); |
| 5011 static const int8_t kMovEaxImmediateByte = BitCast<int8_t, uint8_t>(0xb8); | 5007 static const int8_t kMovEaxImmediateByte = BitCast<int8_t, uint8_t>(0xb8); |
| 5012 | 5008 |
| 5013 ExternalReference roots_array_start = | |
| 5014 ExternalReference::roots_array_start(masm->isolate()); | |
| 5015 | |
| 5016 ASSERT_EQ(object.code(), InstanceofStub::left().code()); | 5009 ASSERT_EQ(object.code(), InstanceofStub::left().code()); |
| 5017 ASSERT_EQ(function.code(), InstanceofStub::right().code()); | 5010 ASSERT_EQ(function.code(), InstanceofStub::right().code()); |
| 5018 | 5011 |
| 5019 // Get the object and function - they are always both needed. | 5012 // Get the object and function - they are always both needed. |
| 5020 Label slow, not_js_object; | 5013 Label slow, not_js_object; |
| 5021 if (!HasArgsInRegisters()) { | 5014 if (!HasArgsInRegisters()) { |
| 5022 __ mov(object, Operand(esp, 2 * kPointerSize)); | 5015 __ mov(object, Operand(esp, 2 * kPointerSize)); |
| 5023 __ mov(function, Operand(esp, 1 * kPointerSize)); | 5016 __ mov(function, Operand(esp, 1 * kPointerSize)); |
| 5024 } | 5017 } |
| 5025 | 5018 |
| 5026 // Check that the left hand is a JS object. | 5019 // Check that the left hand is a JS object. |
| 5027 __ JumpIfSmi(object, ¬_js_object); | 5020 __ JumpIfSmi(object, ¬_js_object); |
| 5028 __ IsObjectJSObjectType(object, map, scratch, ¬_js_object); | 5021 __ IsObjectJSObjectType(object, map, scratch, ¬_js_object); |
| 5029 | 5022 |
| 5030 // If there is a call site cache don't look in the global cache, but do the | 5023 // If there is a call site cache don't look in the global cache, but do the |
| 5031 // real lookup and update the call site cache. | 5024 // real lookup and update the call site cache. |
| 5032 if (!HasCallSiteInlineCheck()) { | 5025 if (!HasCallSiteInlineCheck()) { |
| 5033 // Look up the function and the map in the instanceof cache. | 5026 // Look up the function and the map in the instanceof cache. |
| 5034 Label miss; | 5027 Label miss; |
| 5035 __ mov(scratch, Immediate(Heap::kInstanceofCacheFunctionRootIndex)); | 5028 __ CompareRoot(function, scratch, Heap::kInstanceofCacheFunctionRootIndex); |
| 5036 __ cmp(function, Operand::StaticArray(scratch, | |
| 5037 times_pointer_size, | |
| 5038 roots_array_start)); | |
| 5039 __ j(not_equal, &miss, Label::kNear); | 5029 __ j(not_equal, &miss, Label::kNear); |
| 5040 __ mov(scratch, Immediate(Heap::kInstanceofCacheMapRootIndex)); | 5030 __ CompareRoot(map, scratch, Heap::kInstanceofCacheMapRootIndex); |
| 5041 __ cmp(map, Operand::StaticArray( | |
| 5042 scratch, times_pointer_size, roots_array_start)); | |
| 5043 __ j(not_equal, &miss, Label::kNear); | 5031 __ j(not_equal, &miss, Label::kNear); |
| 5044 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex)); | 5032 __ LoadRoot(eax, Heap::kInstanceofCacheAnswerRootIndex); |
| 5045 __ mov(eax, Operand::StaticArray( | |
| 5046 scratch, times_pointer_size, roots_array_start)); | |
| 5047 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); | 5033 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); |
| 5048 __ bind(&miss); | 5034 __ bind(&miss); |
| 5049 } | 5035 } |
| 5050 | 5036 |
| 5051 // Get the prototype of the function. | 5037 // Get the prototype of the function. |
| 5052 __ TryGetFunctionPrototype(function, prototype, scratch, &slow, true); | 5038 __ TryGetFunctionPrototype(function, prototype, scratch, &slow, true); |
| 5053 | 5039 |
| 5054 // Check that the function prototype is a JS object. | 5040 // Check that the function prototype is a JS object. |
| 5055 __ JumpIfSmi(prototype, &slow); | 5041 __ JumpIfSmi(prototype, &slow); |
| 5056 __ IsObjectJSObjectType(prototype, scratch, scratch, &slow); | 5042 __ IsObjectJSObjectType(prototype, scratch, scratch, &slow); |
| 5057 | 5043 |
| 5058 // Update the global instanceof or call site inlined cache with the current | 5044 // Update the global instanceof or call site inlined cache with the current |
| 5059 // map and function. The cached answer will be set when it is known below. | 5045 // map and function. The cached answer will be set when it is known below. |
| 5060 if (!HasCallSiteInlineCheck()) { | 5046 if (!HasCallSiteInlineCheck()) { |
| 5061 __ mov(scratch, Immediate(Heap::kInstanceofCacheMapRootIndex)); | 5047 __ StoreRoot(map, scratch, Heap::kInstanceofCacheMapRootIndex); |
| 5062 __ mov(Operand::StaticArray(scratch, times_pointer_size, roots_array_start), | 5048 __ StoreRoot(function, scratch, Heap::kInstanceofCacheFunctionRootIndex); |
| 5063 map); | |
| 5064 __ mov(scratch, Immediate(Heap::kInstanceofCacheFunctionRootIndex)); | |
| 5065 __ mov(Operand::StaticArray(scratch, times_pointer_size, roots_array_start), | |
| 5066 function); | |
| 5067 } else { | 5049 } else { |
| 5068 // The constants for the code patching are based on no push instructions | 5050 // The constants for the code patching are based on no push instructions |
| 5069 // at the call site. | 5051 // at the call site. |
| 5070 ASSERT(HasArgsInRegisters()); | 5052 ASSERT(HasArgsInRegisters()); |
| 5071 // Get return address and delta to inlined map check. | 5053 // Get return address and delta to inlined map check. |
| 5072 __ mov(scratch, Operand(esp, 0 * kPointerSize)); | 5054 __ mov(scratch, Operand(esp, 0 * kPointerSize)); |
| 5073 __ sub(scratch, Operand(esp, 1 * kPointerSize)); | 5055 __ sub(scratch, Operand(esp, 1 * kPointerSize)); |
| 5074 if (FLAG_debug_code) { | 5056 if (FLAG_debug_code) { |
| 5075 __ cmpb(Operand(scratch, 0), kCmpEdiOperandByte1); | 5057 __ cmpb(Operand(scratch, 0), kCmpEdiOperandByte1); |
| 5076 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheCmp1); | 5058 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheCmp1); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 5090 __ j(equal, &is_instance, Label::kNear); | 5072 __ j(equal, &is_instance, Label::kNear); |
| 5091 Factory* factory = masm->isolate()->factory(); | 5073 Factory* factory = masm->isolate()->factory(); |
| 5092 __ cmp(scratch, Immediate(factory->null_value())); | 5074 __ cmp(scratch, Immediate(factory->null_value())); |
| 5093 __ j(equal, &is_not_instance, Label::kNear); | 5075 __ j(equal, &is_not_instance, Label::kNear); |
| 5094 __ mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); | 5076 __ mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); |
| 5095 __ mov(scratch, FieldOperand(scratch, Map::kPrototypeOffset)); | 5077 __ mov(scratch, FieldOperand(scratch, Map::kPrototypeOffset)); |
| 5096 __ jmp(&loop); | 5078 __ jmp(&loop); |
| 5097 | 5079 |
| 5098 __ bind(&is_instance); | 5080 __ bind(&is_instance); |
| 5099 if (!HasCallSiteInlineCheck()) { | 5081 if (!HasCallSiteInlineCheck()) { |
| 5100 __ Set(eax, Immediate(0)); | 5082 __ mov(eax, Immediate(0)); |
| 5101 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex)); | 5083 __ StoreRoot(eax, scratch, Heap::kInstanceofCacheAnswerRootIndex); |
| 5102 __ mov(Operand::StaticArray(scratch, | |
| 5103 times_pointer_size, roots_array_start), eax); | |
| 5104 } else { | 5084 } else { |
| 5105 // Get return address and delta to inlined map check. | 5085 // Get return address and delta to inlined map check. |
| 5106 __ mov(eax, factory->true_value()); | 5086 __ mov(eax, factory->true_value()); |
| 5107 __ mov(scratch, Operand(esp, 0 * kPointerSize)); | 5087 __ mov(scratch, Operand(esp, 0 * kPointerSize)); |
| 5108 __ sub(scratch, Operand(esp, 1 * kPointerSize)); | 5088 __ sub(scratch, Operand(esp, 1 * kPointerSize)); |
| 5109 if (FLAG_debug_code) { | 5089 if (FLAG_debug_code) { |
| 5110 __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte); | 5090 __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte); |
| 5111 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov); | 5091 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov); |
| 5112 } | 5092 } |
| 5113 __ mov(Operand(scratch, kDeltaToMovImmediate), eax); | 5093 __ mov(Operand(scratch, kDeltaToMovImmediate), eax); |
| 5114 if (!ReturnTrueFalseObject()) { | 5094 if (!ReturnTrueFalseObject()) { |
| 5115 __ Set(eax, Immediate(0)); | 5095 __ Set(eax, Immediate(0)); |
| 5116 } | 5096 } |
| 5117 } | 5097 } |
| 5118 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); | 5098 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); |
| 5119 | 5099 |
| 5120 __ bind(&is_not_instance); | 5100 __ bind(&is_not_instance); |
| 5121 if (!HasCallSiteInlineCheck()) { | 5101 if (!HasCallSiteInlineCheck()) { |
| 5122 __ Set(eax, Immediate(Smi::FromInt(1))); | 5102 __ mov(eax, Immediate(Smi::FromInt(1))); |
| 5123 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex)); | 5103 __ StoreRoot(eax, scratch, Heap::kInstanceofCacheAnswerRootIndex); |
| 5124 __ mov(Operand::StaticArray( | |
| 5125 scratch, times_pointer_size, roots_array_start), eax); | |
| 5126 } else { | 5104 } else { |
| 5127 // Get return address and delta to inlined map check. | 5105 // Get return address and delta to inlined map check. |
| 5128 __ mov(eax, factory->false_value()); | 5106 __ mov(eax, factory->false_value()); |
| 5129 __ mov(scratch, Operand(esp, 0 * kPointerSize)); | 5107 __ mov(scratch, Operand(esp, 0 * kPointerSize)); |
| 5130 __ sub(scratch, Operand(esp, 1 * kPointerSize)); | 5108 __ sub(scratch, Operand(esp, 1 * kPointerSize)); |
| 5131 if (FLAG_debug_code) { | 5109 if (FLAG_debug_code) { |
| 5132 __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte); | 5110 __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte); |
| 5133 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov); | 5111 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov); |
| 5134 } | 5112 } |
| 5135 __ mov(Operand(scratch, kDeltaToMovImmediate), eax); | 5113 __ mov(Operand(scratch, kDeltaToMovImmediate), eax); |
| (...skipping 732 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5868 // Collect the two characters in a register. | 5846 // Collect the two characters in a register. |
| 5869 Register chars = c1; | 5847 Register chars = c1; |
| 5870 __ shl(c2, kBitsPerByte); | 5848 __ shl(c2, kBitsPerByte); |
| 5871 __ or_(chars, c2); | 5849 __ or_(chars, c2); |
| 5872 | 5850 |
| 5873 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. | 5851 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. |
| 5874 // hash: hash of two character string. | 5852 // hash: hash of two character string. |
| 5875 | 5853 |
| 5876 // Load the string table. | 5854 // Load the string table. |
| 5877 Register string_table = c2; | 5855 Register string_table = c2; |
| 5878 ExternalReference roots_array_start = | 5856 __ LoadRoot(string_table, Heap::kStringTableRootIndex); |
| 5879 ExternalReference::roots_array_start(masm->isolate()); | |
| 5880 __ mov(scratch, Immediate(Heap::kStringTableRootIndex)); | |
| 5881 __ mov(string_table, | |
| 5882 Operand::StaticArray(scratch, times_pointer_size, roots_array_start)); | |
| 5883 | 5857 |
| 5884 // Calculate capacity mask from the string table capacity. | 5858 // Calculate capacity mask from the string table capacity. |
| 5885 Register mask = scratch2; | 5859 Register mask = scratch2; |
| 5886 __ mov(mask, FieldOperand(string_table, StringTable::kCapacityOffset)); | 5860 __ mov(mask, FieldOperand(string_table, StringTable::kCapacityOffset)); |
| 5887 __ SmiUntag(mask); | 5861 __ SmiUntag(mask); |
| 5888 __ sub(mask, Immediate(1)); | 5862 __ sub(mask, Immediate(1)); |
| 5889 | 5863 |
| 5890 // Registers | 5864 // Registers |
| 5891 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. | 5865 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. |
| 5892 // hash: hash of two character string | 5866 // hash: hash of two character string |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5960 } | 5934 } |
| 5961 } | 5935 } |
| 5962 | 5936 |
| 5963 | 5937 |
| 5964 void StringHelper::GenerateHashInit(MacroAssembler* masm, | 5938 void StringHelper::GenerateHashInit(MacroAssembler* masm, |
| 5965 Register hash, | 5939 Register hash, |
| 5966 Register character, | 5940 Register character, |
| 5967 Register scratch) { | 5941 Register scratch) { |
| 5968 // hash = (seed + character) + ((seed + character) << 10); | 5942 // hash = (seed + character) + ((seed + character) << 10); |
| 5969 if (Serializer::enabled()) { | 5943 if (Serializer::enabled()) { |
| 5970 ExternalReference roots_array_start = | 5944 __ LoadRoot(scratch, Heap::kHashSeedRootIndex); |
| 5971 ExternalReference::roots_array_start(masm->isolate()); | |
| 5972 __ mov(scratch, Immediate(Heap::kHashSeedRootIndex)); | |
| 5973 __ mov(scratch, Operand::StaticArray(scratch, | |
| 5974 times_pointer_size, | |
| 5975 roots_array_start)); | |
| 5976 __ SmiUntag(scratch); | 5945 __ SmiUntag(scratch); |
| 5977 __ add(scratch, character); | 5946 __ add(scratch, character); |
| 5978 __ mov(hash, scratch); | 5947 __ mov(hash, scratch); |
| 5979 __ shl(scratch, 10); | 5948 __ shl(scratch, 10); |
| 5980 __ add(hash, scratch); | 5949 __ add(hash, scratch); |
| 5981 } else { | 5950 } else { |
| 5982 int32_t seed = masm->isolate()->heap()->HashSeed(); | 5951 int32_t seed = masm->isolate()->heap()->HashSeed(); |
| 5983 __ lea(scratch, Operand(character, seed)); | 5952 __ lea(scratch, Operand(character, seed)); |
| 5984 __ shl(scratch, 10); | 5953 __ shl(scratch, 10); |
| 5985 __ lea(hash, Operand(scratch, character, times_1, seed)); | 5954 __ lea(hash, Operand(scratch, character, times_1, seed)); |
| (...skipping 1759 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7745 __ bind(&fast_elements_case); | 7714 __ bind(&fast_elements_case); |
| 7746 GenerateCase(masm, FAST_ELEMENTS); | 7715 GenerateCase(masm, FAST_ELEMENTS); |
| 7747 } | 7716 } |
| 7748 | 7717 |
| 7749 | 7718 |
| 7750 #undef __ | 7719 #undef __ |
| 7751 | 7720 |
| 7752 } } // namespace v8::internal | 7721 } } // namespace v8::internal |
| 7753 | 7722 |
| 7754 #endif // V8_TARGET_ARCH_IA32 | 7723 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |