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/code-stubs.h" | 7 #include "src/code-stubs.h" |
8 #include "src/api-arguments.h" | 8 #include "src/api-arguments.h" |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
(...skipping 3336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3347 // value is on the stack already. | 3347 // value is on the stack already. |
3348 static void HandlePolymorphicStoreCase(MacroAssembler* masm, Register receiver, | 3348 static void HandlePolymorphicStoreCase(MacroAssembler* masm, Register receiver, |
3349 Register key, Register vector, | 3349 Register key, Register vector, |
3350 Register slot, Register feedback, | 3350 Register slot, Register feedback, |
3351 bool is_polymorphic, Label* miss) { | 3351 bool is_polymorphic, Label* miss) { |
3352 // feedback initially contains the feedback array | 3352 // feedback initially contains the feedback array |
3353 Label next, next_loop, prepare_next; | 3353 Label next, next_loop, prepare_next; |
3354 Label load_smi_map, compare_map; | 3354 Label load_smi_map, compare_map; |
3355 Label start_polymorphic; | 3355 Label start_polymorphic; |
3356 Label pop_and_miss; | 3356 Label pop_and_miss; |
3357 ExternalReference virtual_register = | |
3358 ExternalReference::virtual_handler_register(masm->isolate()); | |
3359 | 3357 |
3360 __ push(receiver); | 3358 __ push(receiver); |
3361 __ push(vector); | 3359 // Value, vector and slot are passed on the stack, so no need to save/restore |
| 3360 // them. |
3362 | 3361 |
3363 Register receiver_map = receiver; | 3362 Register receiver_map = receiver; |
3364 Register cached_map = vector; | 3363 Register cached_map = vector; |
3365 | 3364 |
3366 // Receiver might not be a heap object. | 3365 // Receiver might not be a heap object. |
3367 __ JumpIfSmi(receiver, &load_smi_map); | 3366 __ JumpIfSmi(receiver, &load_smi_map); |
3368 __ mov(receiver_map, FieldOperand(receiver, 0)); | 3367 __ mov(receiver_map, FieldOperand(receiver, 0)); |
3369 __ bind(&compare_map); | 3368 __ bind(&compare_map); |
3370 __ mov(cached_map, FieldOperand(feedback, FixedArray::OffsetOfElementAt(0))); | 3369 __ mov(cached_map, FieldOperand(feedback, FixedArray::OffsetOfElementAt(0))); |
3371 | 3370 |
3372 // A named keyed store might have a 2 element array, all other cases can count | 3371 // A named keyed store might have a 2 element array, all other cases can count |
3373 // on an array with at least 2 {map, handler} pairs, so they can go right | 3372 // on an array with at least 2 {map, handler} pairs, so they can go right |
3374 // into polymorphic array handling. | 3373 // into polymorphic array handling. |
3375 __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset)); | 3374 __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset)); |
3376 __ j(not_equal, &start_polymorphic); | 3375 __ j(not_equal, &start_polymorphic); |
3377 | 3376 |
3378 // found, now call handler. | 3377 // found, now call handler. |
3379 Register handler = feedback; | 3378 Register handler = feedback; |
3380 DCHECK(handler.is(StoreWithVectorDescriptor::ValueRegister())); | 3379 DCHECK(handler.is(StoreWithVectorDescriptor::ValueRegister())); |
3381 __ mov(handler, FieldOperand(feedback, FixedArray::OffsetOfElementAt(1))); | 3380 __ mov(handler, FieldOperand(feedback, FixedArray::OffsetOfElementAt(1))); |
3382 __ pop(vector); | |
3383 __ pop(receiver); | 3381 __ pop(receiver); |
3384 __ lea(handler, FieldOperand(handler, Code::kHeaderSize)); | 3382 __ lea(handler, FieldOperand(handler, Code::kHeaderSize)); |
3385 __ mov(Operand::StaticVariable(virtual_register), handler); | 3383 __ jmp(handler); |
3386 __ pop(handler); // Pop "value". | |
3387 __ jmp(Operand::StaticVariable(virtual_register)); | |
3388 | 3384 |
3389 // Polymorphic, we have to loop from 2 to N | 3385 // Polymorphic, we have to loop from 2 to N |
3390 __ bind(&start_polymorphic); | 3386 __ bind(&start_polymorphic); |
3391 __ push(key); | 3387 __ push(key); |
3392 Register counter = key; | 3388 Register counter = key; |
3393 __ mov(counter, Immediate(Smi::FromInt(2))); | 3389 __ mov(counter, Immediate(Smi::FromInt(2))); |
3394 | 3390 |
3395 if (!is_polymorphic) { | 3391 if (!is_polymorphic) { |
3396 // If is_polymorphic is false, we may only have a two element array. | 3392 // If is_polymorphic is false, we may only have a two element array. |
3397 // Check against length now in that case. | 3393 // Check against length now in that case. |
3398 __ cmp(counter, FieldOperand(feedback, FixedArray::kLengthOffset)); | 3394 __ cmp(counter, FieldOperand(feedback, FixedArray::kLengthOffset)); |
3399 __ j(greater_equal, &pop_and_miss); | 3395 __ j(greater_equal, &pop_and_miss); |
3400 } | 3396 } |
3401 | 3397 |
3402 __ bind(&next_loop); | 3398 __ bind(&next_loop); |
3403 __ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size, | 3399 __ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size, |
3404 FixedArray::kHeaderSize)); | 3400 FixedArray::kHeaderSize)); |
3405 __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset)); | 3401 __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset)); |
3406 __ j(not_equal, &prepare_next); | 3402 __ j(not_equal, &prepare_next); |
3407 __ mov(handler, FieldOperand(feedback, counter, times_half_pointer_size, | 3403 __ mov(handler, FieldOperand(feedback, counter, times_half_pointer_size, |
3408 FixedArray::kHeaderSize + kPointerSize)); | 3404 FixedArray::kHeaderSize + kPointerSize)); |
3409 __ lea(handler, FieldOperand(handler, Code::kHeaderSize)); | 3405 __ lea(handler, FieldOperand(handler, Code::kHeaderSize)); |
3410 __ pop(key); | 3406 __ pop(key); |
3411 __ pop(vector); | |
3412 __ pop(receiver); | 3407 __ pop(receiver); |
3413 __ mov(Operand::StaticVariable(virtual_register), handler); | 3408 __ jmp(handler); |
3414 __ pop(handler); // Pop "value". | |
3415 __ jmp(Operand::StaticVariable(virtual_register)); | |
3416 | 3409 |
3417 __ bind(&prepare_next); | 3410 __ bind(&prepare_next); |
3418 __ add(counter, Immediate(Smi::FromInt(2))); | 3411 __ add(counter, Immediate(Smi::FromInt(2))); |
3419 __ cmp(counter, FieldOperand(feedback, FixedArray::kLengthOffset)); | 3412 __ cmp(counter, FieldOperand(feedback, FixedArray::kLengthOffset)); |
3420 __ j(less, &next_loop); | 3413 __ j(less, &next_loop); |
3421 | 3414 |
3422 // We exhausted our array of map handler pairs. | 3415 // We exhausted our array of map handler pairs. |
3423 __ bind(&pop_and_miss); | 3416 __ bind(&pop_and_miss); |
3424 __ pop(key); | 3417 __ pop(key); |
3425 __ pop(vector); | |
3426 __ pop(receiver); | 3418 __ pop(receiver); |
3427 __ jmp(miss); | 3419 __ jmp(miss); |
3428 | 3420 |
3429 __ bind(&load_smi_map); | 3421 __ bind(&load_smi_map); |
3430 __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex); | 3422 __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex); |
3431 __ jmp(&compare_map); | 3423 __ jmp(&compare_map); |
3432 } | 3424 } |
3433 | 3425 |
3434 | 3426 |
3435 static void HandleMonomorphicStoreCase(MacroAssembler* masm, Register receiver, | 3427 static void HandleMonomorphicStoreCase(MacroAssembler* masm, Register receiver, |
3436 Register key, Register vector, | 3428 Register key, Register vector, |
3437 Register slot, Register weak_cell, | 3429 Register slot, Register weak_cell, |
3438 Label* miss) { | 3430 Label* miss) { |
3439 // The store ic value is on the stack. | 3431 // The store ic value is on the stack. |
3440 DCHECK(weak_cell.is(StoreWithVectorDescriptor::ValueRegister())); | 3432 DCHECK(weak_cell.is(StoreWithVectorDescriptor::ValueRegister())); |
3441 ExternalReference virtual_register = | |
3442 ExternalReference::virtual_handler_register(masm->isolate()); | |
3443 | 3433 |
3444 // feedback initially contains the feedback array | 3434 // feedback initially contains the feedback array |
3445 Label compare_smi_map; | 3435 Label compare_smi_map; |
3446 | 3436 |
3447 // Move the weak map into the weak_cell register. | 3437 // Move the weak map into the weak_cell register. |
3448 Register ic_map = weak_cell; | 3438 Register ic_map = weak_cell; |
3449 __ mov(ic_map, FieldOperand(weak_cell, WeakCell::kValueOffset)); | 3439 __ mov(ic_map, FieldOperand(weak_cell, WeakCell::kValueOffset)); |
3450 | 3440 |
3451 // Receiver might not be a heap object. | 3441 // Receiver might not be a heap object. |
3452 __ JumpIfSmi(receiver, &compare_smi_map); | 3442 __ JumpIfSmi(receiver, &compare_smi_map); |
3453 __ cmp(ic_map, FieldOperand(receiver, 0)); | 3443 __ cmp(ic_map, FieldOperand(receiver, 0)); |
3454 __ j(not_equal, miss); | 3444 __ j(not_equal, miss); |
3455 __ mov(weak_cell, FieldOperand(vector, slot, times_half_pointer_size, | 3445 __ mov(weak_cell, FieldOperand(vector, slot, times_half_pointer_size, |
3456 FixedArray::kHeaderSize + kPointerSize)); | 3446 FixedArray::kHeaderSize + kPointerSize)); |
3457 __ lea(weak_cell, FieldOperand(weak_cell, Code::kHeaderSize)); | 3447 __ lea(weak_cell, FieldOperand(weak_cell, Code::kHeaderSize)); |
3458 // Put the store ic value back in it's register. | |
3459 __ mov(Operand::StaticVariable(virtual_register), weak_cell); | |
3460 __ pop(weak_cell); // Pop "value". | |
3461 // jump to the handler. | 3448 // jump to the handler. |
3462 __ jmp(Operand::StaticVariable(virtual_register)); | 3449 __ jmp(weak_cell); |
3463 | 3450 |
3464 // In microbenchmarks, it made sense to unroll this code so that the call to | 3451 // In microbenchmarks, it made sense to unroll this code so that the call to |
3465 // the handler is duplicated for a HeapObject receiver and a Smi receiver. | 3452 // the handler is duplicated for a HeapObject receiver and a Smi receiver. |
3466 __ bind(&compare_smi_map); | 3453 __ bind(&compare_smi_map); |
3467 __ CompareRoot(ic_map, Heap::kHeapNumberMapRootIndex); | 3454 __ CompareRoot(ic_map, Heap::kHeapNumberMapRootIndex); |
3468 __ j(not_equal, miss); | 3455 __ j(not_equal, miss); |
3469 __ mov(weak_cell, FieldOperand(vector, slot, times_half_pointer_size, | 3456 __ mov(weak_cell, FieldOperand(vector, slot, times_half_pointer_size, |
3470 FixedArray::kHeaderSize + kPointerSize)); | 3457 FixedArray::kHeaderSize + kPointerSize)); |
3471 __ lea(weak_cell, FieldOperand(weak_cell, Code::kHeaderSize)); | 3458 __ lea(weak_cell, FieldOperand(weak_cell, Code::kHeaderSize)); |
3472 __ mov(Operand::StaticVariable(virtual_register), weak_cell); | |
3473 __ pop(weak_cell); // Pop "value". | |
3474 // jump to the handler. | 3459 // jump to the handler. |
3475 __ jmp(Operand::StaticVariable(virtual_register)); | 3460 __ jmp(weak_cell); |
3476 } | 3461 } |
3477 | 3462 |
3478 void StoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { | 3463 void StoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { |
3479 Register receiver = StoreWithVectorDescriptor::ReceiverRegister(); // edx | 3464 Register receiver = StoreWithVectorDescriptor::ReceiverRegister(); // edx |
3480 Register key = StoreWithVectorDescriptor::NameRegister(); // ecx | 3465 Register key = StoreWithVectorDescriptor::NameRegister(); // ecx |
3481 Register value = StoreWithVectorDescriptor::ValueRegister(); // eax | 3466 Register value = StoreWithVectorDescriptor::ValueRegister(); // eax |
3482 Register vector = StoreWithVectorDescriptor::VectorRegister(); // ebx | 3467 Register vector = StoreWithVectorDescriptor::VectorRegister(); // ebx |
3483 Register slot = StoreWithVectorDescriptor::SlotRegister(); // edi | 3468 Register slot = StoreWithVectorDescriptor::SlotRegister(); // edi |
3484 Label miss; | 3469 Label miss; |
3485 | 3470 |
3486 if (StoreWithVectorDescriptor::kPassLastArgsOnStack) { | 3471 if (StoreWithVectorDescriptor::kPassLastArgsOnStack) { |
3487 // Current stack layout: | 3472 // Current stack layout: |
3488 // - esp[8] -- value | 3473 // - esp[8] -- value |
3489 // - esp[4] -- slot | 3474 // - esp[4] -- slot |
3490 // - esp[0] -- return address | 3475 // - esp[0] -- return address |
3491 STATIC_ASSERT(StoreDescriptor::kStackArgumentsCount == 2); | 3476 STATIC_ASSERT(StoreDescriptor::kStackArgumentsCount == 2); |
3492 STATIC_ASSERT(StoreWithVectorDescriptor::kStackArgumentsCount == 3); | 3477 STATIC_ASSERT(StoreWithVectorDescriptor::kStackArgumentsCount == 3); |
3493 if (in_frame) { | 3478 if (in_frame) { |
3494 __ RecordComment("[ StoreDescriptor -> StoreWithVectorDescriptor"); | 3479 __ RecordComment("[ StoreDescriptor -> StoreWithVectorDescriptor"); |
3495 // If the vector is not on the stack, then insert the vector beneath | 3480 // If the vector is not on the stack, then insert the vector beneath |
3496 // return address in order to prepare for calling handler with | 3481 // return address in order to prepare for calling handler with |
3497 // StoreWithVector calling convention. | 3482 // StoreWithVector calling convention. |
3498 __ push(Operand(esp, 0)); | 3483 __ push(Operand(esp, 0)); |
3499 __ mov(Operand(esp, 4), StoreWithVectorDescriptor::VectorRegister()); | 3484 __ mov(Operand(esp, 4), StoreWithVectorDescriptor::VectorRegister()); |
3500 __ RecordComment("]"); | 3485 __ RecordComment("]"); |
3501 } else { | 3486 } else { |
3502 __ mov(vector, Operand(esp, 1 * kPointerSize)); | 3487 __ mov(vector, Operand(esp, 1 * kPointerSize)); |
3503 } | 3488 } |
3504 __ mov(slot, Operand(esp, 2 * kPointerSize)); | 3489 __ mov(slot, Operand(esp, 2 * kPointerSize)); |
3505 __ mov(value, Operand(esp, 3 * kPointerSize)); | |
3506 } | 3490 } |
3507 | 3491 |
3508 __ push(value); | |
3509 | |
3510 Register scratch = value; | 3492 Register scratch = value; |
3511 __ mov(scratch, FieldOperand(vector, slot, times_half_pointer_size, | 3493 __ mov(scratch, FieldOperand(vector, slot, times_half_pointer_size, |
3512 FixedArray::kHeaderSize)); | 3494 FixedArray::kHeaderSize)); |
3513 | 3495 |
3514 // Is it a weak cell? | 3496 // Is it a weak cell? |
3515 Label try_array; | 3497 Label try_array; |
3516 Label not_array, smi_key, key_okay; | 3498 Label not_array, smi_key, key_okay; |
3517 __ CompareRoot(FieldOperand(scratch, 0), Heap::kWeakCellMapRootIndex); | 3499 __ CompareRoot(FieldOperand(scratch, 0), Heap::kWeakCellMapRootIndex); |
3518 __ j(not_equal, &try_array); | 3500 __ j(not_equal, &try_array); |
3519 HandleMonomorphicStoreCase(masm, receiver, key, vector, slot, scratch, &miss); | 3501 HandleMonomorphicStoreCase(masm, receiver, key, vector, slot, scratch, &miss); |
3520 | 3502 |
3521 // Is it a fixed array? | 3503 // Is it a fixed array? |
3522 __ bind(&try_array); | 3504 __ bind(&try_array); |
3523 __ CompareRoot(FieldOperand(scratch, 0), Heap::kFixedArrayMapRootIndex); | 3505 __ CompareRoot(FieldOperand(scratch, 0), Heap::kFixedArrayMapRootIndex); |
3524 __ j(not_equal, ¬_array); | 3506 __ j(not_equal, ¬_array); |
3525 HandlePolymorphicStoreCase(masm, receiver, key, vector, slot, scratch, true, | 3507 HandlePolymorphicStoreCase(masm, receiver, key, vector, slot, scratch, true, |
3526 &miss); | 3508 &miss); |
3527 | 3509 |
3528 __ bind(¬_array); | 3510 __ bind(¬_array); |
3529 __ CompareRoot(scratch, Heap::kmegamorphic_symbolRootIndex); | 3511 __ CompareRoot(scratch, Heap::kmegamorphic_symbolRootIndex); |
3530 __ j(not_equal, &miss); | 3512 __ j(not_equal, &miss); |
3531 | 3513 |
3532 __ pop(value); | |
3533 __ push(slot); | |
3534 __ push(vector); | |
3535 masm->isolate()->store_stub_cache()->GenerateProbe(masm, receiver, key, slot, | 3514 masm->isolate()->store_stub_cache()->GenerateProbe(masm, receiver, key, slot, |
3536 no_reg); | 3515 no_reg); |
3537 __ pop(vector); | |
3538 __ pop(slot); | |
3539 Label no_pop_miss; | |
3540 __ jmp(&no_pop_miss); | |
3541 | |
3542 __ bind(&miss); | 3516 __ bind(&miss); |
3543 __ pop(value); | |
3544 __ bind(&no_pop_miss); | |
3545 StoreIC::GenerateMiss(masm); | 3517 StoreIC::GenerateMiss(masm); |
3546 } | 3518 } |
3547 | 3519 |
3548 void KeyedStoreICStub::Generate(MacroAssembler* masm) { | 3520 void KeyedStoreICStub::Generate(MacroAssembler* masm) { |
3549 GenerateImpl(masm, false); | 3521 GenerateImpl(masm, false); |
3550 } | 3522 } |
3551 | 3523 |
3552 void KeyedStoreICStub::GenerateForTrampoline(MacroAssembler* masm) { | 3524 void KeyedStoreICStub::GenerateForTrampoline(MacroAssembler* masm) { |
3553 GenerateImpl(masm, true); | 3525 GenerateImpl(masm, true); |
3554 } | 3526 } |
3555 | 3527 |
3556 | 3528 |
3557 static void HandlePolymorphicKeyedStoreCase(MacroAssembler* masm, | 3529 static void HandlePolymorphicKeyedStoreCase(MacroAssembler* masm, |
3558 Register receiver, Register key, | 3530 Register receiver, Register key, |
3559 Register vector, Register slot, | 3531 Register vector, Register slot, |
3560 Register feedback, Label* miss) { | 3532 Register feedback, Label* miss) { |
3561 // feedback initially contains the feedback array | 3533 // feedback initially contains the feedback array |
3562 Label next, next_loop, prepare_next; | 3534 Label next, next_loop, prepare_next; |
3563 Label load_smi_map, compare_map; | 3535 Label load_smi_map, compare_map; |
3564 Label transition_call; | 3536 Label transition_call; |
3565 Label pop_and_miss; | 3537 Label pop_and_miss; |
3566 ExternalReference virtual_register = | |
3567 ExternalReference::virtual_handler_register(masm->isolate()); | |
3568 ExternalReference virtual_slot = | |
3569 ExternalReference::virtual_slot_register(masm->isolate()); | |
3570 | 3538 |
3571 __ push(receiver); | 3539 __ push(receiver); |
3572 __ push(vector); | 3540 // Value, vector and slot are passed on the stack, so no need to save/restore |
| 3541 // them. |
3573 | 3542 |
3574 Register receiver_map = receiver; | 3543 Register receiver_map = receiver; |
3575 Register cached_map = vector; | 3544 Register cached_map = vector; |
3576 Register value = StoreDescriptor::ValueRegister(); | |
3577 | 3545 |
3578 // Receiver might not be a heap object. | 3546 // Receiver might not be a heap object. |
3579 __ JumpIfSmi(receiver, &load_smi_map); | 3547 __ JumpIfSmi(receiver, &load_smi_map); |
3580 __ mov(receiver_map, FieldOperand(receiver, 0)); | 3548 __ mov(receiver_map, FieldOperand(receiver, 0)); |
3581 __ bind(&compare_map); | 3549 __ bind(&compare_map); |
3582 | 3550 |
3583 // Polymorphic, we have to loop from 0 to N - 1 | 3551 // Polymorphic, we have to loop from 0 to N - 1 |
3584 __ push(key); | 3552 __ push(key); |
3585 // Current stack layout: | 3553 // Current stack layout: |
3586 // - esp[0] -- key | 3554 // - esp[0] -- key |
| 3555 // - esp[4] -- receiver |
| 3556 // - esp[8] -- return address |
| 3557 // - esp[12] -- vector |
| 3558 // - esp[16] -- slot |
| 3559 // - esp[20] -- value |
| 3560 // |
| 3561 // Required stack layout for handler call (see StoreWithVectorDescriptor): |
| 3562 // - esp[0] -- return address |
3587 // - esp[4] -- vector | 3563 // - esp[4] -- vector |
3588 // - esp[8] -- receiver | 3564 // - esp[8] -- slot |
3589 // - esp[12] -- value | 3565 // - esp[12] -- value |
3590 // - esp[16] -- return address | 3566 // - receiver, key, handler in registers. |
3591 // | |
3592 // Required stack layout for handler call: | |
3593 // - esp[0] -- return address | |
3594 // - receiver, key, value, vector, slot in registers. | |
3595 // - handler in virtual register. | |
3596 Register counter = key; | 3567 Register counter = key; |
3597 __ mov(counter, Immediate(Smi::FromInt(0))); | 3568 __ mov(counter, Immediate(Smi::FromInt(0))); |
3598 __ bind(&next_loop); | 3569 __ bind(&next_loop); |
3599 __ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size, | 3570 __ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size, |
3600 FixedArray::kHeaderSize)); | 3571 FixedArray::kHeaderSize)); |
3601 __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset)); | 3572 __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset)); |
3602 __ j(not_equal, &prepare_next); | 3573 __ j(not_equal, &prepare_next); |
3603 __ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size, | 3574 __ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size, |
3604 FixedArray::kHeaderSize + kPointerSize)); | 3575 FixedArray::kHeaderSize + kPointerSize)); |
3605 __ CompareRoot(cached_map, Heap::kUndefinedValueRootIndex); | 3576 __ CompareRoot(cached_map, Heap::kUndefinedValueRootIndex); |
3606 __ j(not_equal, &transition_call); | 3577 __ j(not_equal, &transition_call); |
3607 __ mov(feedback, FieldOperand(feedback, counter, times_half_pointer_size, | 3578 __ mov(feedback, FieldOperand(feedback, counter, times_half_pointer_size, |
3608 FixedArray::kHeaderSize + 2 * kPointerSize)); | 3579 FixedArray::kHeaderSize + 2 * kPointerSize)); |
3609 __ pop(key); | 3580 __ pop(key); |
3610 __ pop(vector); | |
3611 __ pop(receiver); | 3581 __ pop(receiver); |
3612 __ lea(feedback, FieldOperand(feedback, Code::kHeaderSize)); | 3582 __ lea(feedback, FieldOperand(feedback, Code::kHeaderSize)); |
3613 __ mov(Operand::StaticVariable(virtual_register), feedback); | 3583 __ jmp(feedback); |
3614 __ pop(value); | |
3615 | |
3616 // Call store handler using StoreWithVectorDescriptor calling convention. | |
3617 __ jmp(Operand::StaticVariable(virtual_register)); | |
3618 | 3584 |
3619 __ bind(&transition_call); | 3585 __ bind(&transition_call); |
3620 // Current stack layout: | 3586 // Current stack layout: |
3621 // - esp[0] -- key | 3587 // - esp[0] -- key |
| 3588 // - esp[4] -- receiver |
| 3589 // - esp[8] -- return address |
| 3590 // - esp[12] -- vector |
| 3591 // - esp[16] -- slot |
| 3592 // - esp[20] -- value |
| 3593 // |
| 3594 // Required stack layout for handler call (see StoreTransitionDescriptor): |
| 3595 // - esp[0] -- return address |
3622 // - esp[4] -- vector | 3596 // - esp[4] -- vector |
3623 // - esp[8] -- receiver | 3597 // - esp[8] -- slot |
3624 // - esp[12] -- value | 3598 // - esp[12] -- value |
3625 // - esp[16] -- return address | 3599 // - receiver, key, map, handler in registers. |
3626 // | |
3627 // Required stack layout for handler call: | |
3628 // - esp[0] -- return address | |
3629 // - receiver, key, value, map, vector in registers. | |
3630 // - handler and slot in virtual registers. | |
3631 __ mov(Operand::StaticVariable(virtual_slot), slot); | |
3632 __ mov(feedback, FieldOperand(feedback, counter, times_half_pointer_size, | 3600 __ mov(feedback, FieldOperand(feedback, counter, times_half_pointer_size, |
3633 FixedArray::kHeaderSize + 2 * kPointerSize)); | 3601 FixedArray::kHeaderSize + 2 * kPointerSize)); |
3634 __ lea(feedback, FieldOperand(feedback, Code::kHeaderSize)); | 3602 __ lea(feedback, FieldOperand(feedback, Code::kHeaderSize)); |
3635 __ mov(Operand::StaticVariable(virtual_register), feedback); | |
3636 | 3603 |
3637 __ mov(cached_map, FieldOperand(cached_map, WeakCell::kValueOffset)); | 3604 __ mov(cached_map, FieldOperand(cached_map, WeakCell::kValueOffset)); |
3638 // The weak cell may have been cleared. | 3605 // The weak cell may have been cleared. |
3639 __ JumpIfSmi(cached_map, &pop_and_miss); | 3606 __ JumpIfSmi(cached_map, &pop_and_miss); |
3640 DCHECK(!cached_map.is(StoreTransitionDescriptor::MapRegister())); | 3607 DCHECK(!cached_map.is(StoreTransitionDescriptor::MapRegister())); |
3641 __ mov(StoreTransitionDescriptor::MapRegister(), cached_map); | 3608 __ mov(StoreTransitionDescriptor::MapRegister(), cached_map); |
3642 | 3609 |
3643 // Call store transition handler using StoreTransitionDescriptor calling | 3610 // Call store transition handler using StoreTransitionDescriptor calling |
3644 // convention. | 3611 // convention. |
3645 __ pop(key); | 3612 __ pop(key); |
3646 __ pop(vector); | |
3647 __ pop(receiver); | 3613 __ pop(receiver); |
3648 __ pop(value); | |
3649 // Ensure that the transition handler we are going to call has the same | 3614 // Ensure that the transition handler we are going to call has the same |
3650 // number of stack arguments which means that we don't have to adapt them | 3615 // number of stack arguments which means that we don't have to adapt them |
3651 // before the call. | 3616 // before the call. |
3652 STATIC_ASSERT(StoreWithVectorDescriptor::kStackArgumentsCount == 3); | 3617 STATIC_ASSERT(StoreWithVectorDescriptor::kStackArgumentsCount == 3); |
3653 STATIC_ASSERT(StoreTransitionDescriptor::kStackArgumentsCount == 3); | 3618 STATIC_ASSERT(StoreTransitionDescriptor::kStackArgumentsCount == 3); |
3654 STATIC_ASSERT(StoreWithVectorDescriptor::kParameterCount - | 3619 STATIC_ASSERT(StoreWithVectorDescriptor::kParameterCount - |
3655 StoreWithVectorDescriptor::kValue == | 3620 StoreWithVectorDescriptor::kValue == |
3656 StoreTransitionDescriptor::kParameterCount - | 3621 StoreTransitionDescriptor::kParameterCount - |
3657 StoreTransitionDescriptor::kValue); | 3622 StoreTransitionDescriptor::kValue); |
3658 STATIC_ASSERT(StoreWithVectorDescriptor::kParameterCount - | 3623 STATIC_ASSERT(StoreWithVectorDescriptor::kParameterCount - |
3659 StoreWithVectorDescriptor::kSlot == | 3624 StoreWithVectorDescriptor::kSlot == |
3660 StoreTransitionDescriptor::kParameterCount - | 3625 StoreTransitionDescriptor::kParameterCount - |
3661 StoreTransitionDescriptor::kSlot); | 3626 StoreTransitionDescriptor::kSlot); |
3662 STATIC_ASSERT(StoreWithVectorDescriptor::kParameterCount - | 3627 STATIC_ASSERT(StoreWithVectorDescriptor::kParameterCount - |
3663 StoreWithVectorDescriptor::kVector == | 3628 StoreWithVectorDescriptor::kVector == |
3664 StoreTransitionDescriptor::kParameterCount - | 3629 StoreTransitionDescriptor::kParameterCount - |
3665 StoreTransitionDescriptor::kVector); | 3630 StoreTransitionDescriptor::kVector); |
3666 __ jmp(Operand::StaticVariable(virtual_register)); | 3631 __ jmp(feedback); |
3667 | 3632 |
3668 __ bind(&prepare_next); | 3633 __ bind(&prepare_next); |
3669 __ add(counter, Immediate(Smi::FromInt(3))); | 3634 __ add(counter, Immediate(Smi::FromInt(3))); |
3670 __ cmp(counter, FieldOperand(feedback, FixedArray::kLengthOffset)); | 3635 __ cmp(counter, FieldOperand(feedback, FixedArray::kLengthOffset)); |
3671 __ j(less, &next_loop); | 3636 __ j(less, &next_loop); |
3672 | 3637 |
3673 // We exhausted our array of map handler pairs. | 3638 // We exhausted our array of map handler pairs. |
3674 __ bind(&pop_and_miss); | 3639 __ bind(&pop_and_miss); |
3675 __ pop(key); | 3640 __ pop(key); |
3676 __ pop(vector); | |
3677 __ pop(receiver); | 3641 __ pop(receiver); |
3678 __ jmp(miss); | 3642 __ jmp(miss); |
3679 | 3643 |
3680 __ bind(&load_smi_map); | 3644 __ bind(&load_smi_map); |
3681 __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex); | 3645 __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex); |
3682 __ jmp(&compare_map); | 3646 __ jmp(&compare_map); |
3683 } | 3647 } |
3684 | 3648 |
3685 void KeyedStoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { | 3649 void KeyedStoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { |
3686 Register receiver = StoreWithVectorDescriptor::ReceiverRegister(); // edx | 3650 Register receiver = StoreWithVectorDescriptor::ReceiverRegister(); // edx |
(...skipping 15 matching lines...) Expand all Loading... |
3702 // If the vector is not on the stack, then insert the vector beneath | 3666 // If the vector is not on the stack, then insert the vector beneath |
3703 // return address in order to prepare for calling handler with | 3667 // return address in order to prepare for calling handler with |
3704 // StoreWithVector calling convention. | 3668 // StoreWithVector calling convention. |
3705 __ push(Operand(esp, 0)); | 3669 __ push(Operand(esp, 0)); |
3706 __ mov(Operand(esp, 4), StoreWithVectorDescriptor::VectorRegister()); | 3670 __ mov(Operand(esp, 4), StoreWithVectorDescriptor::VectorRegister()); |
3707 __ RecordComment("]"); | 3671 __ RecordComment("]"); |
3708 } else { | 3672 } else { |
3709 __ mov(vector, Operand(esp, 1 * kPointerSize)); | 3673 __ mov(vector, Operand(esp, 1 * kPointerSize)); |
3710 } | 3674 } |
3711 __ mov(slot, Operand(esp, 2 * kPointerSize)); | 3675 __ mov(slot, Operand(esp, 2 * kPointerSize)); |
3712 __ mov(value, Operand(esp, 3 * kPointerSize)); | |
3713 } | 3676 } |
3714 | 3677 |
3715 __ push(value); | |
3716 | |
3717 Register scratch = value; | 3678 Register scratch = value; |
3718 __ mov(scratch, FieldOperand(vector, slot, times_half_pointer_size, | 3679 __ mov(scratch, FieldOperand(vector, slot, times_half_pointer_size, |
3719 FixedArray::kHeaderSize)); | 3680 FixedArray::kHeaderSize)); |
3720 | 3681 |
3721 // Is it a weak cell? | 3682 // Is it a weak cell? |
3722 Label try_array; | 3683 Label try_array; |
3723 Label not_array, smi_key, key_okay; | 3684 Label not_array, smi_key, key_okay; |
3724 __ CompareRoot(FieldOperand(scratch, 0), Heap::kWeakCellMapRootIndex); | 3685 __ CompareRoot(FieldOperand(scratch, 0), Heap::kWeakCellMapRootIndex); |
3725 __ j(not_equal, &try_array); | 3686 __ j(not_equal, &try_array); |
3726 HandleMonomorphicStoreCase(masm, receiver, key, vector, slot, scratch, &miss); | 3687 HandleMonomorphicStoreCase(masm, receiver, key, vector, slot, scratch, &miss); |
3727 | 3688 |
3728 // Is it a fixed array? | 3689 // Is it a fixed array? |
3729 __ bind(&try_array); | 3690 __ bind(&try_array); |
3730 __ CompareRoot(FieldOperand(scratch, 0), Heap::kFixedArrayMapRootIndex); | 3691 __ CompareRoot(FieldOperand(scratch, 0), Heap::kFixedArrayMapRootIndex); |
3731 __ j(not_equal, ¬_array); | 3692 __ j(not_equal, ¬_array); |
3732 HandlePolymorphicKeyedStoreCase(masm, receiver, key, vector, slot, scratch, | 3693 HandlePolymorphicKeyedStoreCase(masm, receiver, key, vector, slot, scratch, |
3733 &miss); | 3694 &miss); |
3734 | 3695 |
3735 __ bind(¬_array); | 3696 __ bind(¬_array); |
3736 Label try_poly_name; | 3697 Label try_poly_name; |
3737 __ CompareRoot(scratch, Heap::kmegamorphic_symbolRootIndex); | 3698 __ CompareRoot(scratch, Heap::kmegamorphic_symbolRootIndex); |
3738 __ j(not_equal, &try_poly_name); | 3699 __ j(not_equal, &try_poly_name); |
3739 | 3700 |
3740 __ pop(value); | |
3741 | |
3742 Handle<Code> megamorphic_stub = | 3701 Handle<Code> megamorphic_stub = |
3743 KeyedStoreIC::ChooseMegamorphicStub(masm->isolate(), GetExtraICState()); | 3702 KeyedStoreIC::ChooseMegamorphicStub(masm->isolate(), GetExtraICState()); |
3744 __ jmp(megamorphic_stub, RelocInfo::CODE_TARGET); | 3703 __ jmp(megamorphic_stub, RelocInfo::CODE_TARGET); |
3745 | 3704 |
3746 __ bind(&try_poly_name); | 3705 __ bind(&try_poly_name); |
3747 // We might have a name in feedback, and a fixed array in the next slot. | 3706 // We might have a name in feedback, and a fixed array in the next slot. |
3748 __ cmp(key, scratch); | 3707 __ cmp(key, scratch); |
3749 __ j(not_equal, &miss); | 3708 __ j(not_equal, &miss); |
3750 // If the name comparison succeeded, we know we have a fixed array with | 3709 // If the name comparison succeeded, we know we have a fixed array with |
3751 // at least one map/handler pair. | 3710 // at least one map/handler pair. |
3752 __ mov(scratch, FieldOperand(vector, slot, times_half_pointer_size, | 3711 __ mov(scratch, FieldOperand(vector, slot, times_half_pointer_size, |
3753 FixedArray::kHeaderSize + kPointerSize)); | 3712 FixedArray::kHeaderSize + kPointerSize)); |
3754 HandlePolymorphicStoreCase(masm, receiver, key, vector, slot, scratch, false, | 3713 HandlePolymorphicStoreCase(masm, receiver, key, vector, slot, scratch, false, |
3755 &miss); | 3714 &miss); |
3756 | 3715 |
3757 __ bind(&miss); | 3716 __ bind(&miss); |
3758 __ pop(value); | |
3759 KeyedStoreIC::GenerateMiss(masm); | 3717 KeyedStoreIC::GenerateMiss(masm); |
3760 } | 3718 } |
3761 | 3719 |
3762 void CallICTrampolineStub::Generate(MacroAssembler* masm) { | 3720 void CallICTrampolineStub::Generate(MacroAssembler* masm) { |
3763 __ EmitLoadTypeFeedbackVector(ebx); | 3721 __ EmitLoadTypeFeedbackVector(ebx); |
3764 CallICStub stub(isolate(), state()); | 3722 CallICStub stub(isolate(), state()); |
3765 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); | 3723 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); |
3766 } | 3724 } |
3767 | 3725 |
3768 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { | 3726 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { |
(...skipping 1534 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5303 kStackUnwindSpace, nullptr, return_value_operand, | 5261 kStackUnwindSpace, nullptr, return_value_operand, |
5304 NULL); | 5262 NULL); |
5305 } | 5263 } |
5306 | 5264 |
5307 #undef __ | 5265 #undef __ |
5308 | 5266 |
5309 } // namespace internal | 5267 } // namespace internal |
5310 } // namespace v8 | 5268 } // namespace v8 |
5311 | 5269 |
5312 #endif // V8_TARGET_ARCH_X87 | 5270 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |