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 |