OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #if V8_TARGET_ARCH_X87 | 5 #if V8_TARGET_ARCH_X87 |
6 | 6 |
7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
8 #include "src/bootstrapper.h" | 8 #include "src/bootstrapper.h" |
9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 4229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4240 | 4240 |
4241 // value is on the stack already. | 4241 // value is on the stack already. |
4242 static void HandlePolymorphicStoreCase(MacroAssembler* masm, Register receiver, | 4242 static void HandlePolymorphicStoreCase(MacroAssembler* masm, Register receiver, |
4243 Register key, Register vector, | 4243 Register key, Register vector, |
4244 Register slot, Register feedback, | 4244 Register slot, Register feedback, |
4245 Label* miss) { | 4245 Label* miss) { |
4246 // feedback initially contains the feedback array | 4246 // feedback initially contains the feedback array |
4247 Label next, next_loop, prepare_next; | 4247 Label next, next_loop, prepare_next; |
4248 Label load_smi_map, compare_map; | 4248 Label load_smi_map, compare_map; |
4249 Label start_polymorphic; | 4249 Label start_polymorphic; |
| 4250 ExternalReference virtual_register = |
| 4251 ExternalReference::vector_store_virtual_register(masm->isolate()); |
4250 | 4252 |
4251 __ push(receiver); | 4253 __ push(receiver); |
4252 __ push(vector); | 4254 __ push(vector); |
4253 | 4255 |
4254 Register receiver_map = receiver; | 4256 Register receiver_map = receiver; |
4255 Register cached_map = vector; | 4257 Register cached_map = vector; |
4256 | 4258 |
4257 // Receiver might not be a heap object. | 4259 // Receiver might not be a heap object. |
4258 __ JumpIfSmi(receiver, &load_smi_map); | 4260 __ JumpIfSmi(receiver, &load_smi_map); |
4259 __ mov(receiver_map, FieldOperand(receiver, 0)); | 4261 __ mov(receiver_map, FieldOperand(receiver, 0)); |
4260 __ bind(&compare_map); | 4262 __ bind(&compare_map); |
4261 __ mov(cached_map, FieldOperand(feedback, FixedArray::OffsetOfElementAt(0))); | 4263 __ mov(cached_map, FieldOperand(feedback, FixedArray::OffsetOfElementAt(0))); |
4262 | 4264 |
4263 // A named keyed store might have a 2 element array, all other cases can count | 4265 // A named keyed store might have a 2 element array, all other cases can count |
4264 // on an array with at least 2 {map, handler} pairs, so they can go right | 4266 // on an array with at least 2 {map, handler} pairs, so they can go right |
4265 // into polymorphic array handling. | 4267 // into polymorphic array handling. |
4266 __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset)); | 4268 __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset)); |
4267 __ j(not_equal, &start_polymorphic); | 4269 __ j(not_equal, &start_polymorphic); |
4268 | 4270 |
4269 // found, now call handler. | 4271 // found, now call handler. |
4270 Register handler = feedback; | 4272 Register handler = feedback; |
4271 DCHECK(handler.is(VectorStoreICDescriptor::ValueRegister())); | 4273 DCHECK(handler.is(VectorStoreICDescriptor::ValueRegister())); |
4272 __ mov(handler, FieldOperand(feedback, FixedArray::OffsetOfElementAt(1))); | 4274 __ mov(handler, FieldOperand(feedback, FixedArray::OffsetOfElementAt(1))); |
4273 __ pop(vector); | 4275 __ pop(vector); |
4274 __ pop(receiver); | 4276 __ pop(receiver); |
4275 __ lea(handler, FieldOperand(handler, Code::kHeaderSize)); | 4277 __ lea(handler, FieldOperand(handler, Code::kHeaderSize)); |
4276 __ xchg(handler, Operand(esp, 0)); | 4278 __ mov(Operand::StaticVariable(virtual_register), handler); |
4277 __ ret(0); | 4279 __ pop(handler); // Pop "value". |
| 4280 __ jmp(Operand::StaticVariable(virtual_register)); |
4278 | 4281 |
4279 // Polymorphic, we have to loop from 2 to N | 4282 // Polymorphic, we have to loop from 2 to N |
4280 | 4283 |
4281 // TODO(mvstanton): I think there is a bug here, we are assuming the | 4284 // TODO(mvstanton): I think there is a bug here, we are assuming the |
4282 // array has more than one map/handler pair, but we call this function in the | 4285 // array has more than one map/handler pair, but we call this function in the |
4283 // keyed store with a string key case, where it might be just an array of two | 4286 // keyed store with a string key case, where it might be just an array of two |
4284 // elements. | 4287 // elements. |
4285 | 4288 |
4286 __ bind(&start_polymorphic); | 4289 __ bind(&start_polymorphic); |
4287 __ push(key); | 4290 __ push(key); |
4288 Register counter = key; | 4291 Register counter = key; |
4289 __ mov(counter, Immediate(Smi::FromInt(2))); | 4292 __ mov(counter, Immediate(Smi::FromInt(2))); |
4290 __ bind(&next_loop); | 4293 __ bind(&next_loop); |
4291 __ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size, | 4294 __ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size, |
4292 FixedArray::kHeaderSize)); | 4295 FixedArray::kHeaderSize)); |
4293 __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset)); | 4296 __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset)); |
4294 __ j(not_equal, &prepare_next); | 4297 __ j(not_equal, &prepare_next); |
4295 __ mov(handler, FieldOperand(feedback, counter, times_half_pointer_size, | 4298 __ mov(handler, FieldOperand(feedback, counter, times_half_pointer_size, |
4296 FixedArray::kHeaderSize + kPointerSize)); | 4299 FixedArray::kHeaderSize + kPointerSize)); |
| 4300 __ lea(handler, FieldOperand(handler, Code::kHeaderSize)); |
4297 __ pop(key); | 4301 __ pop(key); |
4298 __ pop(vector); | 4302 __ pop(vector); |
4299 __ pop(receiver); | 4303 __ pop(receiver); |
4300 __ lea(handler, FieldOperand(handler, Code::kHeaderSize)); | 4304 __ mov(Operand::StaticVariable(virtual_register), handler); |
4301 __ xchg(handler, Operand(esp, 0)); | 4305 __ pop(handler); // Pop "value". |
4302 __ ret(0); | 4306 __ jmp(Operand::StaticVariable(virtual_register)); |
4303 | 4307 |
4304 __ bind(&prepare_next); | 4308 __ bind(&prepare_next); |
4305 __ add(counter, Immediate(Smi::FromInt(2))); | 4309 __ add(counter, Immediate(Smi::FromInt(2))); |
4306 __ cmp(counter, FieldOperand(feedback, FixedArray::kLengthOffset)); | 4310 __ cmp(counter, FieldOperand(feedback, FixedArray::kLengthOffset)); |
4307 __ j(less, &next_loop); | 4311 __ j(less, &next_loop); |
4308 | 4312 |
4309 // We exhausted our array of map handler pairs. | 4313 // We exhausted our array of map handler pairs. |
4310 __ pop(key); | 4314 __ pop(key); |
4311 __ pop(vector); | 4315 __ pop(vector); |
4312 __ pop(receiver); | 4316 __ pop(receiver); |
4313 __ jmp(miss); | 4317 __ jmp(miss); |
4314 | 4318 |
4315 __ bind(&load_smi_map); | 4319 __ bind(&load_smi_map); |
4316 __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex); | 4320 __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex); |
4317 __ jmp(&compare_map); | 4321 __ jmp(&compare_map); |
4318 } | 4322 } |
4319 | 4323 |
4320 | 4324 |
4321 static void HandleMonomorphicStoreCase(MacroAssembler* masm, Register receiver, | 4325 static void HandleMonomorphicStoreCase(MacroAssembler* masm, Register receiver, |
4322 Register key, Register vector, | 4326 Register key, Register vector, |
4323 Register slot, Register weak_cell, | 4327 Register slot, Register weak_cell, |
4324 Label* miss) { | 4328 Label* miss) { |
4325 // The store ic value is on the stack. | 4329 // The store ic value is on the stack. |
4326 DCHECK(weak_cell.is(VectorStoreICDescriptor::ValueRegister())); | 4330 DCHECK(weak_cell.is(VectorStoreICDescriptor::ValueRegister())); |
| 4331 ExternalReference virtual_register = |
| 4332 ExternalReference::vector_store_virtual_register(masm->isolate()); |
4327 | 4333 |
4328 // feedback initially contains the feedback array | 4334 // feedback initially contains the feedback array |
4329 Label compare_smi_map; | 4335 Label compare_smi_map; |
4330 | 4336 |
4331 // Move the weak map into the weak_cell register. | 4337 // Move the weak map into the weak_cell register. |
4332 Register ic_map = weak_cell; | 4338 Register ic_map = weak_cell; |
4333 __ mov(ic_map, FieldOperand(weak_cell, WeakCell::kValueOffset)); | 4339 __ mov(ic_map, FieldOperand(weak_cell, WeakCell::kValueOffset)); |
4334 | 4340 |
4335 // Receiver might not be a heap object. | 4341 // Receiver might not be a heap object. |
4336 __ JumpIfSmi(receiver, &compare_smi_map); | 4342 __ JumpIfSmi(receiver, &compare_smi_map); |
4337 __ cmp(ic_map, FieldOperand(receiver, 0)); | 4343 __ cmp(ic_map, FieldOperand(receiver, 0)); |
4338 __ j(not_equal, miss); | 4344 __ j(not_equal, miss); |
4339 __ mov(weak_cell, FieldOperand(vector, slot, times_half_pointer_size, | 4345 __ mov(weak_cell, FieldOperand(vector, slot, times_half_pointer_size, |
4340 FixedArray::kHeaderSize + kPointerSize)); | 4346 FixedArray::kHeaderSize + kPointerSize)); |
4341 __ lea(weak_cell, FieldOperand(weak_cell, Code::kHeaderSize)); | 4347 __ lea(weak_cell, FieldOperand(weak_cell, Code::kHeaderSize)); |
4342 // Put the store ic value back in it's register. | 4348 // Put the store ic value back in it's register. |
4343 __ xchg(weak_cell, Operand(esp, 0)); | 4349 __ mov(Operand::StaticVariable(virtual_register), weak_cell); |
4344 // "return" to the handler. | 4350 __ pop(weak_cell); // Pop "value". |
4345 __ ret(0); | 4351 // jump to the handler. |
| 4352 __ jmp(Operand::StaticVariable(virtual_register)); |
4346 | 4353 |
4347 // In microbenchmarks, it made sense to unroll this code so that the call to | 4354 // In microbenchmarks, it made sense to unroll this code so that the call to |
4348 // the handler is duplicated for a HeapObject receiver and a Smi receiver. | 4355 // the handler is duplicated for a HeapObject receiver and a Smi receiver. |
4349 __ bind(&compare_smi_map); | 4356 __ bind(&compare_smi_map); |
4350 __ CompareRoot(ic_map, Heap::kHeapNumberMapRootIndex); | 4357 __ CompareRoot(ic_map, Heap::kHeapNumberMapRootIndex); |
4351 __ j(not_equal, miss); | 4358 __ j(not_equal, miss); |
4352 __ mov(weak_cell, FieldOperand(vector, slot, times_half_pointer_size, | 4359 __ mov(weak_cell, FieldOperand(vector, slot, times_half_pointer_size, |
4353 FixedArray::kHeaderSize + kPointerSize)); | 4360 FixedArray::kHeaderSize + kPointerSize)); |
4354 __ lea(weak_cell, FieldOperand(weak_cell, Code::kHeaderSize)); | 4361 __ lea(weak_cell, FieldOperand(weak_cell, Code::kHeaderSize)); |
4355 // Put the store ic value back in it's register. | 4362 __ mov(Operand::StaticVariable(virtual_register), weak_cell); |
4356 __ xchg(weak_cell, Operand(esp, 0)); | 4363 __ pop(weak_cell); // Pop "value". |
4357 // "return" to the handler. | 4364 // jump to the handler. |
4358 __ ret(0); | 4365 __ jmp(Operand::StaticVariable(virtual_register)); |
4359 } | 4366 } |
4360 | 4367 |
4361 | 4368 |
4362 void VectorStoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { | 4369 void VectorStoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { |
4363 Register receiver = VectorStoreICDescriptor::ReceiverRegister(); // edx | 4370 Register receiver = VectorStoreICDescriptor::ReceiverRegister(); // edx |
4364 Register key = VectorStoreICDescriptor::NameRegister(); // ecx | 4371 Register key = VectorStoreICDescriptor::NameRegister(); // ecx |
4365 Register value = VectorStoreICDescriptor::ValueRegister(); // eax | 4372 Register value = VectorStoreICDescriptor::ValueRegister(); // eax |
4366 Register vector = VectorStoreICDescriptor::VectorRegister(); // ebx | 4373 Register vector = VectorStoreICDescriptor::VectorRegister(); // ebx |
4367 Register slot = VectorStoreICDescriptor::SlotRegister(); // edi | 4374 Register slot = VectorStoreICDescriptor::SlotRegister(); // edi |
4368 Label miss; | 4375 Label miss; |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4421 | 4428 |
4422 static void HandlePolymorphicKeyedStoreCase(MacroAssembler* masm, | 4429 static void HandlePolymorphicKeyedStoreCase(MacroAssembler* masm, |
4423 Register receiver, Register key, | 4430 Register receiver, Register key, |
4424 Register vector, Register slot, | 4431 Register vector, Register slot, |
4425 Register feedback, Label* miss) { | 4432 Register feedback, Label* miss) { |
4426 // feedback initially contains the feedback array | 4433 // feedback initially contains the feedback array |
4427 Label next, next_loop, prepare_next; | 4434 Label next, next_loop, prepare_next; |
4428 Label load_smi_map, compare_map; | 4435 Label load_smi_map, compare_map; |
4429 Label transition_call; | 4436 Label transition_call; |
4430 Label pop_and_miss; | 4437 Label pop_and_miss; |
| 4438 ExternalReference virtual_register = |
| 4439 ExternalReference::vector_store_virtual_register(masm->isolate()); |
4431 | 4440 |
4432 __ push(receiver); | 4441 __ push(receiver); |
4433 __ push(vector); | 4442 __ push(vector); |
4434 | 4443 |
4435 Register receiver_map = receiver; | 4444 Register receiver_map = receiver; |
4436 Register cached_map = vector; | 4445 Register cached_map = vector; |
4437 | 4446 |
4438 // Receiver might not be a heap object. | 4447 // Receiver might not be a heap object. |
4439 __ JumpIfSmi(receiver, &load_smi_map); | 4448 __ JumpIfSmi(receiver, &load_smi_map); |
4440 __ mov(receiver_map, FieldOperand(receiver, 0)); | 4449 __ mov(receiver_map, FieldOperand(receiver, 0)); |
(...skipping 16 matching lines...) Expand all Loading... |
4457 __ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size, | 4466 __ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size, |
4458 FixedArray::kHeaderSize + kPointerSize)); | 4467 FixedArray::kHeaderSize + kPointerSize)); |
4459 __ CompareRoot(cached_map, Heap::kUndefinedValueRootIndex); | 4468 __ CompareRoot(cached_map, Heap::kUndefinedValueRootIndex); |
4460 __ j(not_equal, &transition_call); | 4469 __ j(not_equal, &transition_call); |
4461 __ mov(feedback, FieldOperand(feedback, counter, times_half_pointer_size, | 4470 __ mov(feedback, FieldOperand(feedback, counter, times_half_pointer_size, |
4462 FixedArray::kHeaderSize + 2 * kPointerSize)); | 4471 FixedArray::kHeaderSize + 2 * kPointerSize)); |
4463 __ pop(key); | 4472 __ pop(key); |
4464 __ pop(vector); | 4473 __ pop(vector); |
4465 __ pop(receiver); | 4474 __ pop(receiver); |
4466 __ lea(feedback, FieldOperand(feedback, Code::kHeaderSize)); | 4475 __ lea(feedback, FieldOperand(feedback, Code::kHeaderSize)); |
4467 __ xchg(feedback, Operand(esp, 0)); | 4476 __ mov(Operand::StaticVariable(virtual_register), feedback); |
4468 __ ret(0); | 4477 __ pop(feedback); // Pop "value". |
| 4478 __ jmp(Operand::StaticVariable(virtual_register)); |
4469 | 4479 |
4470 __ bind(&transition_call); | 4480 __ bind(&transition_call); |
4471 // Oh holy hell this will be tough. | 4481 // Oh holy hell this will be tough. |
4472 // The map goes in vector register. | 4482 // The map goes in vector register. |
4473 __ mov(receiver, FieldOperand(cached_map, WeakCell::kValueOffset)); | 4483 __ mov(receiver, FieldOperand(cached_map, WeakCell::kValueOffset)); |
4474 // The weak cell may have been cleared. | 4484 // The weak cell may have been cleared. |
4475 __ JumpIfSmi(receiver, &pop_and_miss); | 4485 __ JumpIfSmi(receiver, &pop_and_miss); |
4476 // slot goes on the stack, and holds return address. | 4486 // slot goes on the stack, and holds return address. |
4477 __ xchg(slot, Operand(esp, 4 * kPointerSize)); | 4487 __ xchg(slot, Operand(esp, 4 * kPointerSize)); |
4478 // Get the handler in value. | 4488 // Get the handler in value. |
(...skipping 1007 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5486 Operand(ebp, 7 * kPointerSize), NULL); | 5496 Operand(ebp, 7 * kPointerSize), NULL); |
5487 } | 5497 } |
5488 | 5498 |
5489 | 5499 |
5490 #undef __ | 5500 #undef __ |
5491 | 5501 |
5492 } // namespace internal | 5502 } // namespace internal |
5493 } // namespace v8 | 5503 } // namespace v8 |
5494 | 5504 |
5495 #endif // V8_TARGET_ARCH_X87 | 5505 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |