| 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 |