OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 766 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
777 index -= object->map()->inobject_properties(); | 777 index -= object->map()->inobject_properties(); |
778 | 778 |
779 if (index < 0) { | 779 if (index < 0) { |
780 // Set the property straight into the object. | 780 // Set the property straight into the object. |
781 int offset = object->map()->instance_size() + (index * kPointerSize); | 781 int offset = object->map()->instance_size() + (index * kPointerSize); |
782 __ movq(FieldOperand(receiver_reg, offset), rax); | 782 __ movq(FieldOperand(receiver_reg, offset), rax); |
783 | 783 |
784 // Update the write barrier for the array address. | 784 // Update the write barrier for the array address. |
785 // Pass the value being stored in the now unused name_reg. | 785 // Pass the value being stored in the now unused name_reg. |
786 __ movq(name_reg, rax); | 786 __ movq(name_reg, rax); |
787 __ RecordWrite(receiver_reg, offset, name_reg, scratch); | 787 __ RecordWriteField( |
| 788 receiver_reg, offset, name_reg, scratch, kDontSaveFPRegs); |
788 } else { | 789 } else { |
789 // Write to the properties array. | 790 // Write to the properties array. |
790 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 791 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
791 // Get the properties array (optimistically). | 792 // Get the properties array (optimistically). |
792 __ movq(scratch, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); | 793 __ movq(scratch, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); |
793 __ movq(FieldOperand(scratch, offset), rax); | 794 __ movq(FieldOperand(scratch, offset), rax); |
794 | 795 |
795 // Update the write barrier for the array address. | 796 // Update the write barrier for the array address. |
796 // Pass the value being stored in the now unused name_reg. | 797 // Pass the value being stored in the now unused name_reg. |
797 __ movq(name_reg, rax); | 798 __ movq(name_reg, rax); |
798 __ RecordWrite(scratch, offset, name_reg, receiver_reg); | 799 __ RecordWriteField( |
| 800 scratch, offset, name_reg, receiver_reg, kDontSaveFPRegs); |
799 } | 801 } |
800 | 802 |
801 // Return the value (register rax). | 803 // Return the value (register rax). |
802 __ ret(0); | 804 __ ret(0); |
803 } | 805 } |
804 | 806 |
805 | 807 |
806 // Generate code to check that a global property cell is empty. Create | 808 // Generate code to check that a global property cell is empty. Create |
807 // the property cell at compilation time if no cell exists for the | 809 // the property cell at compilation time if no cell exists for the |
808 // property. | 810 // property. |
(...skipping 610 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1419 | 1421 |
1420 // Get the elements array of the object. | 1422 // Get the elements array of the object. |
1421 __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset)); | 1423 __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset)); |
1422 | 1424 |
1423 // Check that the elements are in fast mode and writable. | 1425 // Check that the elements are in fast mode and writable. |
1424 __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset), | 1426 __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset), |
1425 factory()->fixed_array_map()); | 1427 factory()->fixed_array_map()); |
1426 __ j(not_equal, &call_builtin); | 1428 __ j(not_equal, &call_builtin); |
1427 | 1429 |
1428 if (argc == 1) { // Otherwise fall through to call builtin. | 1430 if (argc == 1) { // Otherwise fall through to call builtin. |
1429 Label exit, with_write_barrier, attempt_to_grow_elements; | 1431 Label attempt_to_grow_elements, with_write_barrier; |
1430 | 1432 |
1431 // Get the array's length into rax and calculate new length. | 1433 // Get the array's length into rax and calculate new length. |
1432 __ SmiToInteger32(rax, FieldOperand(rdx, JSArray::kLengthOffset)); | 1434 __ SmiToInteger32(rax, FieldOperand(rdx, JSArray::kLengthOffset)); |
1433 STATIC_ASSERT(FixedArray::kMaxLength < Smi::kMaxValue); | 1435 STATIC_ASSERT(FixedArray::kMaxLength < Smi::kMaxValue); |
1434 __ addl(rax, Immediate(argc)); | 1436 __ addl(rax, Immediate(argc)); |
1435 | 1437 |
1436 // Get the element's length into rcx. | 1438 // Get the element's length into rcx. |
1437 __ SmiToInteger32(rcx, FieldOperand(rbx, FixedArray::kLengthOffset)); | 1439 __ SmiToInteger32(rcx, FieldOperand(rbx, FixedArray::kLengthOffset)); |
1438 | 1440 |
1439 // Check if we could survive without allocation. | 1441 // Check if we could survive without allocation. |
1440 __ cmpl(rax, rcx); | 1442 __ cmpl(rax, rcx); |
1441 __ j(greater, &attempt_to_grow_elements); | 1443 __ j(greater, &attempt_to_grow_elements); |
1442 | 1444 |
1443 // Save new length. | 1445 // Save new length. |
1444 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax); | 1446 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax); |
1445 | 1447 |
1446 // Push the element. | 1448 // Push the element. |
1447 __ movq(rcx, Operand(rsp, argc * kPointerSize)); | 1449 __ movq(rcx, Operand(rsp, argc * kPointerSize)); |
1448 __ lea(rdx, FieldOperand(rbx, | 1450 __ lea(rdx, FieldOperand(rbx, |
1449 rax, times_pointer_size, | 1451 rax, times_pointer_size, |
1450 FixedArray::kHeaderSize - argc * kPointerSize)); | 1452 FixedArray::kHeaderSize - argc * kPointerSize)); |
1451 __ movq(Operand(rdx, 0), rcx); | 1453 __ movq(Operand(rdx, 0), rcx); |
1452 | 1454 |
1453 // Check if value is a smi. | 1455 // Check if value is a smi. |
1454 __ Integer32ToSmi(rax, rax); // Return new length as smi. | 1456 __ Integer32ToSmi(rax, rax); // Return new length as smi. |
1455 | 1457 |
1456 __ JumpIfNotSmi(rcx, &with_write_barrier); | 1458 __ JumpIfNotSmi(rcx, &with_write_barrier); |
1457 | 1459 |
1458 __ bind(&exit); | |
1459 __ ret((argc + 1) * kPointerSize); | 1460 __ ret((argc + 1) * kPointerSize); |
1460 | 1461 |
1461 __ bind(&with_write_barrier); | 1462 __ bind(&with_write_barrier); |
1462 | 1463 |
1463 __ InNewSpace(rbx, rcx, equal, &exit); | 1464 __ RecordWrite( |
1464 | 1465 rbx, rdx, rcx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); |
1465 __ RecordWriteHelper(rbx, rdx, rcx); | |
1466 | 1466 |
1467 __ ret((argc + 1) * kPointerSize); | 1467 __ ret((argc + 1) * kPointerSize); |
1468 | 1468 |
1469 __ bind(&attempt_to_grow_elements); | 1469 __ bind(&attempt_to_grow_elements); |
1470 if (!FLAG_inline_new) { | 1470 if (!FLAG_inline_new) { |
1471 __ jmp(&call_builtin); | 1471 __ jmp(&call_builtin); |
1472 } | 1472 } |
1473 | 1473 |
1474 ExternalReference new_space_allocation_top = | 1474 ExternalReference new_space_allocation_top = |
1475 ExternalReference::new_space_allocation_top_address(isolate()); | 1475 ExternalReference::new_space_allocation_top_address(isolate()); |
(...skipping 21 matching lines...) Expand all Loading... |
1497 __ movq(rcx, Operand(rsp, argc * kPointerSize)); | 1497 __ movq(rcx, Operand(rsp, argc * kPointerSize)); |
1498 | 1498 |
1499 // Push the argument... | 1499 // Push the argument... |
1500 __ movq(Operand(rdx, 0), rcx); | 1500 __ movq(Operand(rdx, 0), rcx); |
1501 // ... and fill the rest with holes. | 1501 // ... and fill the rest with holes. |
1502 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); | 1502 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); |
1503 for (int i = 1; i < kAllocationDelta; i++) { | 1503 for (int i = 1; i < kAllocationDelta; i++) { |
1504 __ movq(Operand(rdx, i * kPointerSize), kScratchRegister); | 1504 __ movq(Operand(rdx, i * kPointerSize), kScratchRegister); |
1505 } | 1505 } |
1506 | 1506 |
| 1507 // We know the elements array is in new space so we don't need the |
| 1508 // remembered set, but we just pushed a value onto it so we may have to |
| 1509 // tell the incremental marker to rescan the object that we just grew. We |
| 1510 // don't need to worry about the holes because they are in old space and |
| 1511 // already marked black. |
| 1512 __ RecordWrite(rbx, rdx, rcx, kDontSaveFPRegs, OMIT_REMEMBERED_SET); |
| 1513 |
1507 // Restore receiver to rdx as finish sequence assumes it's here. | 1514 // Restore receiver to rdx as finish sequence assumes it's here. |
1508 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 1515 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
1509 | 1516 |
1510 // Increment element's and array's sizes. | 1517 // Increment element's and array's sizes. |
1511 __ SmiAddConstant(FieldOperand(rbx, FixedArray::kLengthOffset), | 1518 __ SmiAddConstant(FieldOperand(rbx, FixedArray::kLengthOffset), |
1512 Smi::FromInt(kAllocationDelta)); | 1519 Smi::FromInt(kAllocationDelta)); |
1513 | 1520 |
1514 // Make new length a smi before returning it. | 1521 // Make new length a smi before returning it. |
1515 __ Integer32ToSmi(rax, rax); | 1522 __ Integer32ToSmi(rax, rax); |
1516 __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rax); | 1523 __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rax); |
1517 | 1524 |
1518 // Elements are in new space, so write barrier is not required. | |
1519 __ ret((argc + 1) * kPointerSize); | 1525 __ ret((argc + 1) * kPointerSize); |
1520 } | 1526 } |
1521 | 1527 |
1522 __ bind(&call_builtin); | 1528 __ bind(&call_builtin); |
1523 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush, | 1529 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush, |
1524 isolate()), | 1530 isolate()), |
1525 argc + 1, | 1531 argc + 1, |
1526 1); | 1532 1); |
1527 } | 1533 } |
1528 | 1534 |
(...skipping 932 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2461 // -- rdx : receiver | 2467 // -- rdx : receiver |
2462 // -- rsp[0] : return address | 2468 // -- rsp[0] : return address |
2463 // ----------------------------------- | 2469 // ----------------------------------- |
2464 Label miss; | 2470 Label miss; |
2465 | 2471 |
2466 // Check that the map of the global has not changed. | 2472 // Check that the map of the global has not changed. |
2467 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), | 2473 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), |
2468 Handle<Map>(object->map())); | 2474 Handle<Map>(object->map())); |
2469 __ j(not_equal, &miss); | 2475 __ j(not_equal, &miss); |
2470 | 2476 |
| 2477 // Compute the cell operand to use. |
| 2478 __ Move(rbx, Handle<JSGlobalPropertyCell>(cell)); |
| 2479 Operand cell_operand = FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset); |
| 2480 |
2471 // Check that the value in the cell is not the hole. If it is, this | 2481 // Check that the value in the cell is not the hole. If it is, this |
2472 // cell could have been deleted and reintroducing the global needs | 2482 // cell could have been deleted and reintroducing the global needs |
2473 // to update the property details in the property dictionary of the | 2483 // to update the property details in the property dictionary of the |
2474 // global object. We bail out to the runtime system to do that. | 2484 // global object. We bail out to the runtime system to do that. |
2475 __ Move(rbx, Handle<JSGlobalPropertyCell>(cell)); | 2485 __ CompareRoot(cell_operand, Heap::kTheHoleValueRootIndex); |
2476 __ CompareRoot(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), | |
2477 Heap::kTheHoleValueRootIndex); | |
2478 __ j(equal, &miss); | 2486 __ j(equal, &miss); |
2479 | 2487 |
2480 // Store the value in the cell. | 2488 // Store the value in the cell. |
2481 __ movq(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), rax); | 2489 __ movq(cell_operand, rax); |
| 2490 Label done; |
| 2491 __ JumpIfSmi(rax, &done); |
| 2492 |
| 2493 __ movq(rcx, rax); |
| 2494 __ lea(rdx, cell_operand); |
| 2495 // Cells are always in the remembered set. |
| 2496 __ RecordWrite(rbx, // Object. |
| 2497 rdx, // Address. |
| 2498 rcx, // Value. |
| 2499 kDontSaveFPRegs, |
| 2500 OMIT_REMEMBERED_SET, |
| 2501 OMIT_SMI_CHECK); |
| 2502 |
2482 | 2503 |
2483 // Return the value (register rax). | 2504 // Return the value (register rax). |
| 2505 __ bind(&done); |
| 2506 |
2484 Counters* counters = isolate()->counters(); | 2507 Counters* counters = isolate()->counters(); |
2485 __ IncrementCounter(counters->named_store_global_inline(), 1); | 2508 __ IncrementCounter(counters->named_store_global_inline(), 1); |
2486 __ ret(0); | 2509 __ ret(0); |
2487 | 2510 |
2488 // Handle store cache miss. | 2511 // Handle store cache miss. |
2489 __ bind(&miss); | 2512 __ bind(&miss); |
2490 __ IncrementCounter(counters->named_store_global_inline_miss(), 1); | 2513 __ IncrementCounter(counters->named_store_global_inline_miss(), 1); |
2491 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); | 2514 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); |
2492 __ Jump(ic, RelocInfo::CODE_TARGET); | 2515 __ Jump(ic, RelocInfo::CODE_TARGET); |
2493 | 2516 |
(...skipping 1169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3663 | 3686 |
3664 // Check that the key is within bounds. | 3687 // Check that the key is within bounds. |
3665 if (is_js_array) { | 3688 if (is_js_array) { |
3666 __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset)); | 3689 __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset)); |
3667 __ j(above_equal, &miss_force_generic); | 3690 __ j(above_equal, &miss_force_generic); |
3668 } else { | 3691 } else { |
3669 __ SmiCompare(rcx, FieldOperand(rdi, FixedArray::kLengthOffset)); | 3692 __ SmiCompare(rcx, FieldOperand(rdi, FixedArray::kLengthOffset)); |
3670 __ j(above_equal, &miss_force_generic); | 3693 __ j(above_equal, &miss_force_generic); |
3671 } | 3694 } |
3672 | 3695 |
3673 // Do the store and update the write barrier. Make sure to preserve | 3696 // Do the store and update the write barrier. |
3674 // the value in register eax. | 3697 __ SmiToInteger32(rcx, rcx); |
| 3698 __ lea(rcx, |
| 3699 FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize)); |
| 3700 __ movq(Operand(rcx, 0), rax); |
| 3701 // Make sure to preserve the value in register rax. |
3675 __ movq(rdx, rax); | 3702 __ movq(rdx, rax); |
3676 __ SmiToInteger32(rcx, rcx); | 3703 __ RecordWrite(rdi, rcx, rdx, kDontSaveFPRegs); |
3677 __ movq(FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize), | |
3678 rax); | |
3679 __ RecordWrite(rdi, 0, rdx, rcx); | |
3680 | 3704 |
3681 // Done. | 3705 // Done. |
3682 __ ret(0); | 3706 __ ret(0); |
3683 | 3707 |
3684 // Handle store cache miss. | 3708 // Handle store cache miss. |
3685 __ bind(&miss_force_generic); | 3709 __ bind(&miss_force_generic); |
3686 Handle<Code> ic_force_generic = | 3710 Handle<Code> ic_force_generic = |
3687 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | 3711 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
3688 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); | 3712 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); |
3689 } | 3713 } |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3772 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | 3796 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
3773 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); | 3797 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); |
3774 } | 3798 } |
3775 | 3799 |
3776 | 3800 |
3777 #undef __ | 3801 #undef __ |
3778 | 3802 |
3779 } } // namespace v8::internal | 3803 } } // namespace v8::internal |
3780 | 3804 |
3781 #endif // V8_TARGET_ARCH_X64 | 3805 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |