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 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 void FastNewContextStub::Generate(MacroAssembler* masm) { | 121 void FastNewContextStub::Generate(MacroAssembler* masm) { |
122 // Try to allocate the context in new space. | 122 // Try to allocate the context in new space. |
123 Label gc; | 123 Label gc; |
124 int length = slots_ + Context::MIN_CONTEXT_SLOTS; | 124 int length = slots_ + Context::MIN_CONTEXT_SLOTS; |
125 __ AllocateInNewSpace((length * kPointerSize) + FixedArray::kHeaderSize, | 125 __ AllocateInNewSpace((length * kPointerSize) + FixedArray::kHeaderSize, |
126 eax, ebx, ecx, &gc, TAG_OBJECT); | 126 eax, ebx, ecx, &gc, TAG_OBJECT); |
127 | 127 |
128 // Get the function from the stack. | 128 // Get the function from the stack. |
129 __ mov(ecx, Operand(esp, 1 * kPointerSize)); | 129 __ mov(ecx, Operand(esp, 1 * kPointerSize)); |
130 | 130 |
131 // Setup the object header. | 131 // Set up the object header. |
132 Factory* factory = masm->isolate()->factory(); | 132 Factory* factory = masm->isolate()->factory(); |
133 __ mov(FieldOperand(eax, HeapObject::kMapOffset), | 133 __ mov(FieldOperand(eax, HeapObject::kMapOffset), |
134 factory->function_context_map()); | 134 factory->function_context_map()); |
135 __ mov(FieldOperand(eax, Context::kLengthOffset), | 135 __ mov(FieldOperand(eax, Context::kLengthOffset), |
136 Immediate(Smi::FromInt(length))); | 136 Immediate(Smi::FromInt(length))); |
137 | 137 |
138 // Setup the fixed slots. | 138 // Set up the fixed slots. |
139 __ Set(ebx, Immediate(0)); // Set to NULL. | 139 __ Set(ebx, Immediate(0)); // Set to NULL. |
140 __ mov(Operand(eax, Context::SlotOffset(Context::CLOSURE_INDEX)), ecx); | 140 __ mov(Operand(eax, Context::SlotOffset(Context::CLOSURE_INDEX)), ecx); |
141 __ mov(Operand(eax, Context::SlotOffset(Context::PREVIOUS_INDEX)), esi); | 141 __ mov(Operand(eax, Context::SlotOffset(Context::PREVIOUS_INDEX)), esi); |
142 __ mov(Operand(eax, Context::SlotOffset(Context::EXTENSION_INDEX)), ebx); | 142 __ mov(Operand(eax, Context::SlotOffset(Context::EXTENSION_INDEX)), ebx); |
143 | 143 |
144 // Copy the global object from the previous context. | 144 // Copy the global object from the previous context. |
145 __ mov(ebx, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); | 145 __ mov(ebx, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); |
146 __ mov(Operand(eax, Context::SlotOffset(Context::GLOBAL_INDEX)), ebx); | 146 __ mov(Operand(eax, Context::SlotOffset(Context::GLOBAL_INDEX)), ebx); |
147 | 147 |
148 // Initialize the rest of the slots to undefined. | 148 // Initialize the rest of the slots to undefined. |
(...skipping 23 matching lines...) Expand all Loading... |
172 int length = slots_ + Context::MIN_CONTEXT_SLOTS; | 172 int length = slots_ + Context::MIN_CONTEXT_SLOTS; |
173 __ AllocateInNewSpace(FixedArray::SizeFor(length), | 173 __ AllocateInNewSpace(FixedArray::SizeFor(length), |
174 eax, ebx, ecx, &gc, TAG_OBJECT); | 174 eax, ebx, ecx, &gc, TAG_OBJECT); |
175 | 175 |
176 // Get the function or sentinel from the stack. | 176 // Get the function or sentinel from the stack. |
177 __ mov(ecx, Operand(esp, 1 * kPointerSize)); | 177 __ mov(ecx, Operand(esp, 1 * kPointerSize)); |
178 | 178 |
179 // Get the serialized scope info from the stack. | 179 // Get the serialized scope info from the stack. |
180 __ mov(ebx, Operand(esp, 2 * kPointerSize)); | 180 __ mov(ebx, Operand(esp, 2 * kPointerSize)); |
181 | 181 |
182 // Setup the object header. | 182 // Set up the object header. |
183 Factory* factory = masm->isolate()->factory(); | 183 Factory* factory = masm->isolate()->factory(); |
184 __ mov(FieldOperand(eax, HeapObject::kMapOffset), | 184 __ mov(FieldOperand(eax, HeapObject::kMapOffset), |
185 factory->block_context_map()); | 185 factory->block_context_map()); |
186 __ mov(FieldOperand(eax, Context::kLengthOffset), | 186 __ mov(FieldOperand(eax, Context::kLengthOffset), |
187 Immediate(Smi::FromInt(length))); | 187 Immediate(Smi::FromInt(length))); |
188 | 188 |
189 // If this block context is nested in the global context we get a smi | 189 // If this block context is nested in the global context we get a smi |
190 // sentinel instead of a function. The block context should get the | 190 // sentinel instead of a function. The block context should get the |
191 // canonical empty function of the global context as its closure which | 191 // canonical empty function of the global context as its closure which |
192 // we still have to look up. | 192 // we still have to look up. |
193 Label after_sentinel; | 193 Label after_sentinel; |
194 __ JumpIfNotSmi(ecx, &after_sentinel, Label::kNear); | 194 __ JumpIfNotSmi(ecx, &after_sentinel, Label::kNear); |
195 if (FLAG_debug_code) { | 195 if (FLAG_debug_code) { |
196 const char* message = "Expected 0 as a Smi sentinel"; | 196 const char* message = "Expected 0 as a Smi sentinel"; |
197 __ cmp(ecx, 0); | 197 __ cmp(ecx, 0); |
198 __ Assert(equal, message); | 198 __ Assert(equal, message); |
199 } | 199 } |
200 __ mov(ecx, GlobalObjectOperand()); | 200 __ mov(ecx, GlobalObjectOperand()); |
201 __ mov(ecx, FieldOperand(ecx, GlobalObject::kGlobalContextOffset)); | 201 __ mov(ecx, FieldOperand(ecx, GlobalObject::kGlobalContextOffset)); |
202 __ mov(ecx, ContextOperand(ecx, Context::CLOSURE_INDEX)); | 202 __ mov(ecx, ContextOperand(ecx, Context::CLOSURE_INDEX)); |
203 __ bind(&after_sentinel); | 203 __ bind(&after_sentinel); |
204 | 204 |
205 // Setup the fixed slots. | 205 // Set up the fixed slots. |
206 __ mov(ContextOperand(eax, Context::CLOSURE_INDEX), ecx); | 206 __ mov(ContextOperand(eax, Context::CLOSURE_INDEX), ecx); |
207 __ mov(ContextOperand(eax, Context::PREVIOUS_INDEX), esi); | 207 __ mov(ContextOperand(eax, Context::PREVIOUS_INDEX), esi); |
208 __ mov(ContextOperand(eax, Context::EXTENSION_INDEX), ebx); | 208 __ mov(ContextOperand(eax, Context::EXTENSION_INDEX), ebx); |
209 | 209 |
210 // Copy the global object from the previous context. | 210 // Copy the global object from the previous context. |
211 __ mov(ebx, ContextOperand(esi, Context::GLOBAL_INDEX)); | 211 __ mov(ebx, ContextOperand(esi, Context::GLOBAL_INDEX)); |
212 __ mov(ContextOperand(eax, Context::GLOBAL_INDEX), ebx); | 212 __ mov(ContextOperand(eax, Context::GLOBAL_INDEX), ebx); |
213 | 213 |
214 // Initialize the rest of the slots to the hole value. | 214 // Initialize the rest of the slots to the hole value. |
215 if (slots_ == 1) { | 215 if (slots_ == 1) { |
(...skipping 3156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3372 // edi = address of boilerplate object (tagged) | 3372 // edi = address of boilerplate object (tagged) |
3373 // esp[0] = mapped parameter count (tagged) | 3373 // esp[0] = mapped parameter count (tagged) |
3374 // esp[8] = parameter count (tagged) | 3374 // esp[8] = parameter count (tagged) |
3375 // esp[12] = address of receiver argument | 3375 // esp[12] = address of receiver argument |
3376 // Copy the JS object part. | 3376 // Copy the JS object part. |
3377 for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) { | 3377 for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) { |
3378 __ mov(edx, FieldOperand(edi, i)); | 3378 __ mov(edx, FieldOperand(edi, i)); |
3379 __ mov(FieldOperand(eax, i), edx); | 3379 __ mov(FieldOperand(eax, i), edx); |
3380 } | 3380 } |
3381 | 3381 |
3382 // Setup the callee in-object property. | 3382 // Set up the callee in-object property. |
3383 STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1); | 3383 STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1); |
3384 __ mov(edx, Operand(esp, 4 * kPointerSize)); | 3384 __ mov(edx, Operand(esp, 4 * kPointerSize)); |
3385 __ mov(FieldOperand(eax, JSObject::kHeaderSize + | 3385 __ mov(FieldOperand(eax, JSObject::kHeaderSize + |
3386 Heap::kArgumentsCalleeIndex * kPointerSize), | 3386 Heap::kArgumentsCalleeIndex * kPointerSize), |
3387 edx); | 3387 edx); |
3388 | 3388 |
3389 // Use the length (smi tagged) and set that as an in-object property too. | 3389 // Use the length (smi tagged) and set that as an in-object property too. |
3390 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); | 3390 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); |
3391 __ mov(FieldOperand(eax, JSObject::kHeaderSize + | 3391 __ mov(FieldOperand(eax, JSObject::kHeaderSize + |
3392 Heap::kArgumentsLengthIndex * kPointerSize), | 3392 Heap::kArgumentsLengthIndex * kPointerSize), |
3393 ecx); | 3393 ecx); |
3394 | 3394 |
3395 // Setup the elements pointer in the allocated arguments object. | 3395 // Set up the elements pointer in the allocated arguments object. |
3396 // If we allocated a parameter map, edi will point there, otherwise to the | 3396 // If we allocated a parameter map, edi will point there, otherwise to the |
3397 // backing store. | 3397 // backing store. |
3398 __ lea(edi, Operand(eax, Heap::kArgumentsObjectSize)); | 3398 __ lea(edi, Operand(eax, Heap::kArgumentsObjectSize)); |
3399 __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi); | 3399 __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi); |
3400 | 3400 |
3401 // eax = address of new object (tagged) | 3401 // eax = address of new object (tagged) |
3402 // ebx = mapped parameter count (tagged) | 3402 // ebx = mapped parameter count (tagged) |
3403 // ecx = argument count (tagged) | 3403 // ecx = argument count (tagged) |
3404 // edi = address of parameter map or backing store (tagged) | 3404 // edi = address of parameter map or backing store (tagged) |
3405 // esp[0] = mapped parameter count (tagged) | 3405 // esp[0] = mapped parameter count (tagged) |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3564 ecx); | 3564 ecx); |
3565 | 3565 |
3566 // If there are no actual arguments, we're done. | 3566 // If there are no actual arguments, we're done. |
3567 Label done; | 3567 Label done; |
3568 __ test(ecx, ecx); | 3568 __ test(ecx, ecx); |
3569 __ j(zero, &done, Label::kNear); | 3569 __ j(zero, &done, Label::kNear); |
3570 | 3570 |
3571 // Get the parameters pointer from the stack. | 3571 // Get the parameters pointer from the stack. |
3572 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 3572 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
3573 | 3573 |
3574 // Setup the elements pointer in the allocated arguments object and | 3574 // Set up the elements pointer in the allocated arguments object and |
3575 // initialize the header in the elements fixed array. | 3575 // initialize the header in the elements fixed array. |
3576 __ lea(edi, Operand(eax, Heap::kArgumentsObjectSizeStrict)); | 3576 __ lea(edi, Operand(eax, Heap::kArgumentsObjectSizeStrict)); |
3577 __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi); | 3577 __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi); |
3578 __ mov(FieldOperand(edi, FixedArray::kMapOffset), | 3578 __ mov(FieldOperand(edi, FixedArray::kMapOffset), |
3579 Immediate(FACTORY->fixed_array_map())); | 3579 Immediate(FACTORY->fixed_array_map())); |
3580 | 3580 |
3581 __ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx); | 3581 __ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx); |
3582 // Untag the length for the loop below. | 3582 // Untag the length for the loop below. |
3583 __ SmiUntag(ecx); | 3583 __ SmiUntag(ecx); |
3584 | 3584 |
(...skipping 1358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4943 | 4943 |
4944 __ bind(&throw_normal_exception); | 4944 __ bind(&throw_normal_exception); |
4945 GenerateThrowTOS(masm); | 4945 GenerateThrowTOS(masm); |
4946 } | 4946 } |
4947 | 4947 |
4948 | 4948 |
4949 void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { | 4949 void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { |
4950 Label invoke, handler_entry, exit; | 4950 Label invoke, handler_entry, exit; |
4951 Label not_outermost_js, not_outermost_js_2; | 4951 Label not_outermost_js, not_outermost_js_2; |
4952 | 4952 |
4953 // Setup frame. | 4953 // Set up frame. |
4954 __ push(ebp); | 4954 __ push(ebp); |
4955 __ mov(ebp, esp); | 4955 __ mov(ebp, esp); |
4956 | 4956 |
4957 // Push marker in two places. | 4957 // Push marker in two places. |
4958 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY; | 4958 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY; |
4959 __ push(Immediate(Smi::FromInt(marker))); // context slot | 4959 __ push(Immediate(Smi::FromInt(marker))); // context slot |
4960 __ push(Immediate(Smi::FromInt(marker))); // function slot | 4960 __ push(Immediate(Smi::FromInt(marker))); // function slot |
4961 // Save callee-saved registers (C calling conventions). | 4961 // Save callee-saved registers (C calling conventions). |
4962 __ push(edi); | 4962 __ push(edi); |
4963 __ push(esi); | 4963 __ push(esi); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5074 Register object = eax; // Object (lhs). | 5074 Register object = eax; // Object (lhs). |
5075 Register map = ebx; // Map of the object. | 5075 Register map = ebx; // Map of the object. |
5076 Register function = edx; // Function (rhs). | 5076 Register function = edx; // Function (rhs). |
5077 Register prototype = edi; // Prototype of the function. | 5077 Register prototype = edi; // Prototype of the function. |
5078 Register scratch = ecx; | 5078 Register scratch = ecx; |
5079 | 5079 |
5080 // Constants describing the call site code to patch. | 5080 // Constants describing the call site code to patch. |
5081 static const int kDeltaToCmpImmediate = 2; | 5081 static const int kDeltaToCmpImmediate = 2; |
5082 static const int kDeltaToMov = 8; | 5082 static const int kDeltaToMov = 8; |
5083 static const int kDeltaToMovImmediate = 9; | 5083 static const int kDeltaToMovImmediate = 9; |
5084 static const int8_t kCmpEdiImmediateByte1 = BitCast<int8_t, uint8_t>(0x81); | 5084 static const int8_t kCmpEdiOperandByte1 = BitCast<int8_t, uint8_t>(0x3b); |
5085 static const int8_t kCmpEdiImmediateByte2 = BitCast<int8_t, uint8_t>(0xff); | 5085 static const int8_t kCmpEdiOperandByte2 = BitCast<int8_t, uint8_t>(0x3d); |
5086 static const int8_t kMovEaxImmediateByte = BitCast<int8_t, uint8_t>(0xb8); | 5086 static const int8_t kMovEaxImmediateByte = BitCast<int8_t, uint8_t>(0xb8); |
5087 | 5087 |
5088 ExternalReference roots_array_start = | 5088 ExternalReference roots_array_start = |
5089 ExternalReference::roots_array_start(masm->isolate()); | 5089 ExternalReference::roots_array_start(masm->isolate()); |
5090 | 5090 |
5091 ASSERT_EQ(object.code(), InstanceofStub::left().code()); | 5091 ASSERT_EQ(object.code(), InstanceofStub::left().code()); |
5092 ASSERT_EQ(function.code(), InstanceofStub::right().code()); | 5092 ASSERT_EQ(function.code(), InstanceofStub::right().code()); |
5093 | 5093 |
5094 // Get the object and function - they are always both needed. | 5094 // Get the object and function - they are always both needed. |
5095 Label slow, not_js_object; | 5095 Label slow, not_js_object; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5140 __ mov(Operand::StaticArray(scratch, times_pointer_size, roots_array_start), | 5140 __ mov(Operand::StaticArray(scratch, times_pointer_size, roots_array_start), |
5141 function); | 5141 function); |
5142 } else { | 5142 } else { |
5143 // The constants for the code patching are based on no push instructions | 5143 // The constants for the code patching are based on no push instructions |
5144 // at the call site. | 5144 // at the call site. |
5145 ASSERT(HasArgsInRegisters()); | 5145 ASSERT(HasArgsInRegisters()); |
5146 // Get return address and delta to inlined map check. | 5146 // Get return address and delta to inlined map check. |
5147 __ mov(scratch, Operand(esp, 0 * kPointerSize)); | 5147 __ mov(scratch, Operand(esp, 0 * kPointerSize)); |
5148 __ sub(scratch, Operand(esp, 1 * kPointerSize)); | 5148 __ sub(scratch, Operand(esp, 1 * kPointerSize)); |
5149 if (FLAG_debug_code) { | 5149 if (FLAG_debug_code) { |
5150 __ cmpb(Operand(scratch, 0), kCmpEdiImmediateByte1); | 5150 __ cmpb(Operand(scratch, 0), kCmpEdiOperandByte1); |
5151 __ Assert(equal, "InstanceofStub unexpected call site cache (cmp 1)"); | 5151 __ Assert(equal, "InstanceofStub unexpected call site cache (cmp 1)"); |
5152 __ cmpb(Operand(scratch, 1), kCmpEdiImmediateByte2); | 5152 __ cmpb(Operand(scratch, 1), kCmpEdiOperandByte2); |
5153 __ Assert(equal, "InstanceofStub unexpected call site cache (cmp 2)"); | 5153 __ Assert(equal, "InstanceofStub unexpected call site cache (cmp 2)"); |
5154 } | 5154 } |
5155 __ mov(Operand(scratch, kDeltaToCmpImmediate), map); | 5155 __ mov(scratch, Operand(scratch, kDeltaToCmpImmediate)); |
| 5156 __ mov(Operand(scratch, 0), map); |
5156 } | 5157 } |
5157 | 5158 |
5158 // Loop through the prototype chain of the object looking for the function | 5159 // Loop through the prototype chain of the object looking for the function |
5159 // prototype. | 5160 // prototype. |
5160 __ mov(scratch, FieldOperand(map, Map::kPrototypeOffset)); | 5161 __ mov(scratch, FieldOperand(map, Map::kPrototypeOffset)); |
5161 Label loop, is_instance, is_not_instance; | 5162 Label loop, is_instance, is_not_instance; |
5162 __ bind(&loop); | 5163 __ bind(&loop); |
5163 __ cmp(scratch, prototype); | 5164 __ cmp(scratch, prototype); |
5164 __ j(equal, &is_instance, Label::kNear); | 5165 __ j(equal, &is_instance, Label::kNear); |
5165 Factory* factory = masm->isolate()->factory(); | 5166 Factory* factory = masm->isolate()->factory(); |
(...skipping 864 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6030 | 6031 |
6031 | 6032 |
6032 void StringHelper::GenerateHashInit(MacroAssembler* masm, | 6033 void StringHelper::GenerateHashInit(MacroAssembler* masm, |
6033 Register hash, | 6034 Register hash, |
6034 Register character, | 6035 Register character, |
6035 Register scratch) { | 6036 Register scratch) { |
6036 // hash = (seed + character) + ((seed + character) << 10); | 6037 // hash = (seed + character) + ((seed + character) << 10); |
6037 if (Serializer::enabled()) { | 6038 if (Serializer::enabled()) { |
6038 ExternalReference roots_array_start = | 6039 ExternalReference roots_array_start = |
6039 ExternalReference::roots_array_start(masm->isolate()); | 6040 ExternalReference::roots_array_start(masm->isolate()); |
6040 __ mov(scratch, Immediate(Heap::kStringHashSeedRootIndex)); | 6041 __ mov(scratch, Immediate(Heap::kHashSeedRootIndex)); |
6041 __ mov(scratch, Operand::StaticArray(scratch, | 6042 __ mov(scratch, Operand::StaticArray(scratch, |
6042 times_pointer_size, | 6043 times_pointer_size, |
6043 roots_array_start)); | 6044 roots_array_start)); |
6044 __ add(scratch, character); | 6045 __ add(scratch, character); |
6045 __ mov(hash, scratch); | 6046 __ mov(hash, scratch); |
6046 __ shl(scratch, 10); | 6047 __ shl(scratch, 10); |
6047 __ add(hash, scratch); | 6048 __ add(hash, scratch); |
6048 } else { | 6049 } else { |
6049 int32_t seed = masm->isolate()->heap()->StringHashSeed(); | 6050 int32_t seed = masm->isolate()->heap()->HashSeed(); |
6050 __ lea(scratch, Operand(character, seed)); | 6051 __ lea(scratch, Operand(character, seed)); |
6051 __ shl(scratch, 10); | 6052 __ shl(scratch, 10); |
6052 __ lea(hash, Operand(scratch, character, times_1, seed)); | 6053 __ lea(hash, Operand(scratch, character, times_1, seed)); |
6053 } | 6054 } |
6054 // hash ^= hash >> 6; | 6055 // hash ^= hash >> 6; |
6055 __ mov(scratch, hash); | 6056 __ mov(scratch, hash); |
6056 __ shr(scratch, 6); | 6057 __ shr(scratch, 6); |
6057 __ xor_(hash, scratch); | 6058 __ xor_(hash, scratch); |
6058 } | 6059 } |
6059 | 6060 |
(...skipping 24 matching lines...) Expand all Loading... |
6084 __ add(hash, scratch); | 6085 __ add(hash, scratch); |
6085 // hash ^= hash >> 11; | 6086 // hash ^= hash >> 11; |
6086 __ mov(scratch, hash); | 6087 __ mov(scratch, hash); |
6087 __ shr(scratch, 11); | 6088 __ shr(scratch, 11); |
6088 __ xor_(hash, scratch); | 6089 __ xor_(hash, scratch); |
6089 // hash += hash << 15; | 6090 // hash += hash << 15; |
6090 __ mov(scratch, hash); | 6091 __ mov(scratch, hash); |
6091 __ shl(scratch, 15); | 6092 __ shl(scratch, 15); |
6092 __ add(hash, scratch); | 6093 __ add(hash, scratch); |
6093 | 6094 |
6094 uint32_t kHashShiftCutOffMask = (1 << (32 - String::kHashShift)) - 1; | 6095 __ and_(hash, String::kHashBitMask); |
6095 __ and_(hash, kHashShiftCutOffMask); | |
6096 | 6096 |
6097 // if (hash == 0) hash = 27; | 6097 // if (hash == 0) hash = 27; |
6098 Label hash_not_zero; | 6098 Label hash_not_zero; |
6099 __ test(hash, hash); | |
6100 __ j(not_zero, &hash_not_zero, Label::kNear); | 6099 __ j(not_zero, &hash_not_zero, Label::kNear); |
6101 __ mov(hash, Immediate(27)); | 6100 __ mov(hash, Immediate(StringHasher::kZeroHash)); |
6102 __ bind(&hash_not_zero); | 6101 __ bind(&hash_not_zero); |
6103 } | 6102 } |
6104 | 6103 |
6105 | 6104 |
6106 void SubStringStub::Generate(MacroAssembler* masm) { | 6105 void SubStringStub::Generate(MacroAssembler* masm) { |
6107 Label runtime; | 6106 Label runtime; |
6108 | 6107 |
6109 // Stack frame on entry. | 6108 // Stack frame on entry. |
6110 // esp[0]: return address | 6109 // esp[0]: return address |
6111 // esp[4]: to | 6110 // esp[4]: to |
(...skipping 1234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7346 false); | 7345 false); |
7347 __ pop(edx); | 7346 __ pop(edx); |
7348 __ ret(0); | 7347 __ ret(0); |
7349 } | 7348 } |
7350 | 7349 |
7351 #undef __ | 7350 #undef __ |
7352 | 7351 |
7353 } } // namespace v8::internal | 7352 } } // namespace v8::internal |
7354 | 7353 |
7355 #endif // V8_TARGET_ARCH_IA32 | 7354 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |