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 4277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4288 void VectorStoreICStub::Generate(MacroAssembler* masm) { | 4288 void VectorStoreICStub::Generate(MacroAssembler* masm) { |
4289 GenerateImpl(masm, false); | 4289 GenerateImpl(masm, false); |
4290 } | 4290 } |
4291 | 4291 |
4292 | 4292 |
4293 void VectorStoreICStub::GenerateForTrampoline(MacroAssembler* masm) { | 4293 void VectorStoreICStub::GenerateForTrampoline(MacroAssembler* masm) { |
4294 GenerateImpl(masm, true); | 4294 GenerateImpl(masm, true); |
4295 } | 4295 } |
4296 | 4296 |
4297 | 4297 |
| 4298 // value is on the stack already. |
| 4299 static void HandlePolymorphicStoreCase(MacroAssembler* masm, Register receiver, |
| 4300 Register key, Register vector, |
| 4301 Register slot, Register feedback, |
| 4302 Label* miss) { |
| 4303 // feedback initially contains the feedback array |
| 4304 Label next, next_loop, prepare_next; |
| 4305 Label load_smi_map, compare_map; |
| 4306 Label start_polymorphic; |
| 4307 |
| 4308 __ push(receiver); |
| 4309 __ push(vector); |
| 4310 |
| 4311 Register receiver_map = receiver; |
| 4312 Register cached_map = vector; |
| 4313 |
| 4314 // Receiver might not be a heap object. |
| 4315 __ JumpIfSmi(receiver, &load_smi_map); |
| 4316 __ mov(receiver_map, FieldOperand(receiver, 0)); |
| 4317 __ bind(&compare_map); |
| 4318 __ mov(cached_map, FieldOperand(feedback, FixedArray::OffsetOfElementAt(0))); |
| 4319 |
| 4320 // A named keyed store might have a 2 element array, all other cases can count |
| 4321 // on an array with at least 2 {map, handler} pairs, so they can go right |
| 4322 // into polymorphic array handling. |
| 4323 __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset)); |
| 4324 __ j(not_equal, &start_polymorphic); |
| 4325 |
| 4326 // found, now call handler. |
| 4327 Register handler = feedback; |
| 4328 DCHECK(handler.is(VectorStoreICDescriptor::ValueRegister())); |
| 4329 __ mov(handler, FieldOperand(feedback, FixedArray::OffsetOfElementAt(1))); |
| 4330 __ pop(vector); |
| 4331 __ pop(receiver); |
| 4332 __ lea(handler, FieldOperand(handler, Code::kHeaderSize)); |
| 4333 __ xchg(handler, Operand(esp, 0)); |
| 4334 __ ret(0); |
| 4335 |
| 4336 // Polymorphic, we have to loop from 2 to N |
| 4337 |
| 4338 // TODO(mvstanton): I think there is a bug here, we are assuming the |
| 4339 // array has more than one map/handler pair, but we call this function in the |
| 4340 // keyed store with a string key case, where it might be just an array of two |
| 4341 // elements. |
| 4342 |
| 4343 __ bind(&start_polymorphic); |
| 4344 __ push(key); |
| 4345 Register counter = key; |
| 4346 __ mov(counter, Immediate(Smi::FromInt(2))); |
| 4347 __ bind(&next_loop); |
| 4348 __ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size, |
| 4349 FixedArray::kHeaderSize)); |
| 4350 __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset)); |
| 4351 __ j(not_equal, &prepare_next); |
| 4352 __ mov(handler, FieldOperand(feedback, counter, times_half_pointer_size, |
| 4353 FixedArray::kHeaderSize + kPointerSize)); |
| 4354 __ pop(key); |
| 4355 __ pop(vector); |
| 4356 __ pop(receiver); |
| 4357 __ lea(handler, FieldOperand(handler, Code::kHeaderSize)); |
| 4358 __ xchg(handler, Operand(esp, 0)); |
| 4359 __ ret(0); |
| 4360 |
| 4361 __ bind(&prepare_next); |
| 4362 __ add(counter, Immediate(Smi::FromInt(2))); |
| 4363 __ cmp(counter, FieldOperand(feedback, FixedArray::kLengthOffset)); |
| 4364 __ j(less, &next_loop); |
| 4365 |
| 4366 // We exhausted our array of map handler pairs. |
| 4367 __ pop(key); |
| 4368 __ pop(vector); |
| 4369 __ pop(receiver); |
| 4370 __ jmp(miss); |
| 4371 |
| 4372 __ bind(&load_smi_map); |
| 4373 __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex); |
| 4374 __ jmp(&compare_map); |
| 4375 } |
| 4376 |
| 4377 |
| 4378 static void HandleMonomorphicStoreCase(MacroAssembler* masm, Register receiver, |
| 4379 Register key, Register vector, |
| 4380 Register slot, Register weak_cell, |
| 4381 Label* miss) { |
| 4382 // The store ic value is on the stack. |
| 4383 DCHECK(weak_cell.is(VectorStoreICDescriptor::ValueRegister())); |
| 4384 |
| 4385 // feedback initially contains the feedback array |
| 4386 Label compare_smi_map; |
| 4387 |
| 4388 // Move the weak map into the weak_cell register. |
| 4389 Register ic_map = weak_cell; |
| 4390 __ mov(ic_map, FieldOperand(weak_cell, WeakCell::kValueOffset)); |
| 4391 |
| 4392 // Receiver might not be a heap object. |
| 4393 __ JumpIfSmi(receiver, &compare_smi_map); |
| 4394 __ cmp(ic_map, FieldOperand(receiver, 0)); |
| 4395 __ j(not_equal, miss); |
| 4396 __ mov(weak_cell, FieldOperand(vector, slot, times_half_pointer_size, |
| 4397 FixedArray::kHeaderSize + kPointerSize)); |
| 4398 __ lea(weak_cell, FieldOperand(weak_cell, Code::kHeaderSize)); |
| 4399 // Put the store ic value back in it's register. |
| 4400 __ xchg(weak_cell, Operand(esp, 0)); |
| 4401 // "return" to the handler. |
| 4402 __ ret(0); |
| 4403 |
| 4404 // In microbenchmarks, it made sense to unroll this code so that the call to |
| 4405 // the handler is duplicated for a HeapObject receiver and a Smi receiver. |
| 4406 __ bind(&compare_smi_map); |
| 4407 __ CompareRoot(ic_map, Heap::kHeapNumberMapRootIndex); |
| 4408 __ j(not_equal, miss); |
| 4409 __ mov(weak_cell, FieldOperand(vector, slot, times_half_pointer_size, |
| 4410 FixedArray::kHeaderSize + kPointerSize)); |
| 4411 __ lea(weak_cell, FieldOperand(weak_cell, Code::kHeaderSize)); |
| 4412 // Put the store ic value back in it's register. |
| 4413 __ xchg(weak_cell, Operand(esp, 0)); |
| 4414 // "return" to the handler. |
| 4415 __ ret(0); |
| 4416 } |
| 4417 |
| 4418 |
4298 void VectorStoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { | 4419 void VectorStoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { |
| 4420 Register receiver = VectorStoreICDescriptor::ReceiverRegister(); // edx |
| 4421 Register key = VectorStoreICDescriptor::NameRegister(); // ecx |
| 4422 Register value = VectorStoreICDescriptor::ValueRegister(); // eax |
| 4423 Register vector = VectorStoreICDescriptor::VectorRegister(); // ebx |
| 4424 Register slot = VectorStoreICDescriptor::SlotRegister(); // edi |
4299 Label miss; | 4425 Label miss; |
4300 | 4426 |
4301 // TODO(mvstanton): Implement. | 4427 __ push(value); |
| 4428 |
| 4429 Register scratch = value; |
| 4430 __ mov(scratch, FieldOperand(vector, slot, times_half_pointer_size, |
| 4431 FixedArray::kHeaderSize)); |
| 4432 |
| 4433 // Is it a weak cell? |
| 4434 Label try_array; |
| 4435 Label not_array, smi_key, key_okay; |
| 4436 __ CompareRoot(FieldOperand(scratch, 0), Heap::kWeakCellMapRootIndex); |
| 4437 __ j(not_equal, &try_array); |
| 4438 HandleMonomorphicStoreCase(masm, receiver, key, vector, slot, scratch, &miss); |
| 4439 |
| 4440 // Is it a fixed array? |
| 4441 __ bind(&try_array); |
| 4442 __ CompareRoot(FieldOperand(scratch, 0), Heap::kFixedArrayMapRootIndex); |
| 4443 __ j(not_equal, ¬_array); |
| 4444 HandlePolymorphicStoreCase(masm, receiver, key, vector, slot, scratch, &miss); |
| 4445 |
| 4446 __ bind(¬_array); |
| 4447 __ CompareRoot(scratch, Heap::kmegamorphic_symbolRootIndex); |
| 4448 __ j(not_equal, &miss); |
| 4449 |
| 4450 __ pop(value); |
| 4451 __ push(slot); |
| 4452 __ push(vector); |
| 4453 Code::Flags code_flags = Code::RemoveTypeAndHolderFromFlags( |
| 4454 Code::ComputeHandlerFlags(Code::STORE_IC)); |
| 4455 masm->isolate()->stub_cache()->GenerateProbe(masm, Code::STORE_IC, code_flags, |
| 4456 receiver, key, slot, no_reg); |
| 4457 __ pop(vector); |
| 4458 __ pop(slot); |
| 4459 Label no_pop_miss; |
| 4460 __ jmp(&no_pop_miss); |
| 4461 |
4302 __ bind(&miss); | 4462 __ bind(&miss); |
| 4463 __ pop(value); |
| 4464 __ bind(&no_pop_miss); |
4303 StoreIC::GenerateMiss(masm); | 4465 StoreIC::GenerateMiss(masm); |
4304 } | 4466 } |
4305 | 4467 |
4306 | 4468 |
4307 void VectorKeyedStoreICStub::Generate(MacroAssembler* masm) { | 4469 void VectorKeyedStoreICStub::Generate(MacroAssembler* masm) { |
4308 GenerateImpl(masm, false); | 4470 GenerateImpl(masm, false); |
4309 } | 4471 } |
4310 | 4472 |
4311 | 4473 |
4312 void VectorKeyedStoreICStub::GenerateForTrampoline(MacroAssembler* masm) { | 4474 void VectorKeyedStoreICStub::GenerateForTrampoline(MacroAssembler* masm) { |
4313 GenerateImpl(masm, true); | 4475 GenerateImpl(masm, true); |
4314 } | 4476 } |
4315 | 4477 |
4316 | 4478 |
| 4479 static void HandlePolymorphicKeyedStoreCase(MacroAssembler* masm, |
| 4480 Register receiver, Register key, |
| 4481 Register vector, Register slot, |
| 4482 Register feedback, Label* miss) { |
| 4483 // feedback initially contains the feedback array |
| 4484 Label next, next_loop, prepare_next; |
| 4485 Label load_smi_map, compare_map; |
| 4486 Label transition_call; |
| 4487 Label pop_and_miss; |
| 4488 |
| 4489 __ push(receiver); |
| 4490 __ push(vector); |
| 4491 |
| 4492 Register receiver_map = receiver; |
| 4493 Register cached_map = vector; |
| 4494 |
| 4495 // Receiver might not be a heap object. |
| 4496 __ JumpIfSmi(receiver, &load_smi_map); |
| 4497 __ mov(receiver_map, FieldOperand(receiver, 0)); |
| 4498 __ bind(&compare_map); |
| 4499 |
| 4500 // Polymorphic, we have to loop from 0 to N - 1 |
| 4501 __ push(key); |
| 4502 // On the stack we have: |
| 4503 // key (esp) |
| 4504 // vector |
| 4505 // receiver |
| 4506 // value |
| 4507 Register counter = key; |
| 4508 __ mov(counter, Immediate(Smi::FromInt(0))); |
| 4509 __ bind(&next_loop); |
| 4510 __ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size, |
| 4511 FixedArray::kHeaderSize)); |
| 4512 __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset)); |
| 4513 __ j(not_equal, &prepare_next); |
| 4514 __ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size, |
| 4515 FixedArray::kHeaderSize + kPointerSize)); |
| 4516 __ CompareRoot(cached_map, Heap::kUndefinedValueRootIndex); |
| 4517 __ j(not_equal, &transition_call); |
| 4518 __ mov(feedback, FieldOperand(feedback, counter, times_half_pointer_size, |
| 4519 FixedArray::kHeaderSize + 2 * kPointerSize)); |
| 4520 __ pop(key); |
| 4521 __ pop(vector); |
| 4522 __ pop(receiver); |
| 4523 __ lea(feedback, FieldOperand(feedback, Code::kHeaderSize)); |
| 4524 __ xchg(feedback, Operand(esp, 0)); |
| 4525 __ ret(0); |
| 4526 |
| 4527 __ bind(&transition_call); |
| 4528 // Oh holy hell this will be tough. |
| 4529 // The map goes in vector register. |
| 4530 __ mov(receiver, FieldOperand(cached_map, WeakCell::kValueOffset)); |
| 4531 // The weak cell may have been cleared. |
| 4532 __ JumpIfSmi(receiver, &pop_and_miss); |
| 4533 // slot goes on the stack, and holds return address. |
| 4534 __ xchg(slot, Operand(esp, 4 * kPointerSize)); |
| 4535 // Get the handler in value. |
| 4536 __ mov(feedback, FieldOperand(feedback, counter, times_half_pointer_size, |
| 4537 FixedArray::kHeaderSize + 2 * kPointerSize)); |
| 4538 __ lea(feedback, FieldOperand(feedback, Code::kHeaderSize)); |
| 4539 // Pop key into place. |
| 4540 __ pop(key); |
| 4541 // Put the return address on top of stack, vector goes in slot. |
| 4542 __ xchg(slot, Operand(esp, 0)); |
| 4543 // put the map on the stack, receiver holds receiver. |
| 4544 __ xchg(receiver, Operand(esp, 1 * kPointerSize)); |
| 4545 // put the vector on the stack, slot holds value. |
| 4546 __ xchg(slot, Operand(esp, 2 * kPointerSize)); |
| 4547 // feedback (value) = value, slot = handler. |
| 4548 __ xchg(feedback, slot); |
| 4549 __ jmp(slot); |
| 4550 |
| 4551 __ bind(&prepare_next); |
| 4552 __ add(counter, Immediate(Smi::FromInt(3))); |
| 4553 __ cmp(counter, FieldOperand(feedback, FixedArray::kLengthOffset)); |
| 4554 __ j(less, &next_loop); |
| 4555 |
| 4556 // We exhausted our array of map handler pairs. |
| 4557 __ bind(&pop_and_miss); |
| 4558 __ pop(key); |
| 4559 __ pop(vector); |
| 4560 __ pop(receiver); |
| 4561 __ jmp(miss); |
| 4562 |
| 4563 __ bind(&load_smi_map); |
| 4564 __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex); |
| 4565 __ jmp(&compare_map); |
| 4566 } |
| 4567 |
| 4568 |
4317 void VectorKeyedStoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { | 4569 void VectorKeyedStoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { |
| 4570 Register receiver = VectorStoreICDescriptor::ReceiverRegister(); // edx |
| 4571 Register key = VectorStoreICDescriptor::NameRegister(); // ecx |
| 4572 Register value = VectorStoreICDescriptor::ValueRegister(); // eax |
| 4573 Register vector = VectorStoreICDescriptor::VectorRegister(); // ebx |
| 4574 Register slot = VectorStoreICDescriptor::SlotRegister(); // edi |
4318 Label miss; | 4575 Label miss; |
4319 | 4576 |
4320 // TODO(mvstanton): Implement. | 4577 __ push(value); |
| 4578 |
| 4579 Register scratch = value; |
| 4580 __ mov(scratch, FieldOperand(vector, slot, times_half_pointer_size, |
| 4581 FixedArray::kHeaderSize)); |
| 4582 |
| 4583 // Is it a weak cell? |
| 4584 Label try_array; |
| 4585 Label not_array, smi_key, key_okay; |
| 4586 __ CompareRoot(FieldOperand(scratch, 0), Heap::kWeakCellMapRootIndex); |
| 4587 __ j(not_equal, &try_array); |
| 4588 HandleMonomorphicStoreCase(masm, receiver, key, vector, slot, scratch, &miss); |
| 4589 |
| 4590 // Is it a fixed array? |
| 4591 __ bind(&try_array); |
| 4592 __ CompareRoot(FieldOperand(scratch, 0), Heap::kFixedArrayMapRootIndex); |
| 4593 __ j(not_equal, ¬_array); |
| 4594 HandlePolymorphicKeyedStoreCase(masm, receiver, key, vector, slot, scratch, |
| 4595 &miss); |
| 4596 |
| 4597 __ bind(¬_array); |
| 4598 Label try_poly_name; |
| 4599 __ CompareRoot(scratch, Heap::kmegamorphic_symbolRootIndex); |
| 4600 __ j(not_equal, &try_poly_name); |
| 4601 |
| 4602 __ pop(value); |
| 4603 |
| 4604 Handle<Code> megamorphic_stub = |
| 4605 KeyedStoreIC::ChooseMegamorphicStub(masm->isolate(), GetExtraICState()); |
| 4606 __ jmp(megamorphic_stub, RelocInfo::CODE_TARGET); |
| 4607 |
| 4608 __ bind(&try_poly_name); |
| 4609 // We might have a name in feedback, and a fixed array in the next slot. |
| 4610 __ cmp(key, scratch); |
| 4611 __ j(not_equal, &miss); |
| 4612 // If the name comparison succeeded, we know we have a fixed array with |
| 4613 // at least one map/handler pair. |
| 4614 __ mov(scratch, FieldOperand(vector, slot, times_half_pointer_size, |
| 4615 FixedArray::kHeaderSize + kPointerSize)); |
| 4616 HandlePolymorphicStoreCase(masm, receiver, key, vector, slot, scratch, &miss); |
| 4617 |
4321 __ bind(&miss); | 4618 __ bind(&miss); |
| 4619 __ pop(value); |
4322 KeyedStoreIC::GenerateMiss(masm); | 4620 KeyedStoreIC::GenerateMiss(masm); |
4323 } | 4621 } |
4324 | 4622 |
4325 | 4623 |
4326 void CallICTrampolineStub::Generate(MacroAssembler* masm) { | 4624 void CallICTrampolineStub::Generate(MacroAssembler* masm) { |
4327 EmitLoadTypeFeedbackVector(masm, ebx); | 4625 EmitLoadTypeFeedbackVector(masm, ebx); |
4328 CallICStub stub(isolate(), state()); | 4626 CallICStub stub(isolate(), state()); |
4329 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); | 4627 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); |
4330 } | 4628 } |
4331 | 4629 |
(...skipping 920 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5252 Operand(ebp, 7 * kPointerSize), NULL); | 5550 Operand(ebp, 7 * kPointerSize), NULL); |
5253 } | 5551 } |
5254 | 5552 |
5255 | 5553 |
5256 #undef __ | 5554 #undef __ |
5257 | 5555 |
5258 } // namespace internal | 5556 } // namespace internal |
5259 } // namespace v8 | 5557 } // namespace v8 |
5260 | 5558 |
5261 #endif // V8_TARGET_ARCH_X87 | 5559 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |