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 772 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
783 index -= object->map()->inobject_properties(); | 783 index -= object->map()->inobject_properties(); |
784 | 784 |
785 if (index < 0) { | 785 if (index < 0) { |
786 // Set the property straight into the object. | 786 // Set the property straight into the object. |
787 int offset = object->map()->instance_size() + (index * kPointerSize); | 787 int offset = object->map()->instance_size() + (index * kPointerSize); |
788 __ mov(FieldOperand(receiver_reg, offset), eax); | 788 __ mov(FieldOperand(receiver_reg, offset), eax); |
789 | 789 |
790 // Update the write barrier for the array address. | 790 // Update the write barrier for the array address. |
791 // Pass the value being stored in the now unused name_reg. | 791 // Pass the value being stored in the now unused name_reg. |
792 __ mov(name_reg, Operand(eax)); | 792 __ mov(name_reg, Operand(eax)); |
793 __ RecordWrite(receiver_reg, offset, name_reg, scratch); | 793 __ RecordWriteField(receiver_reg, |
| 794 offset, |
| 795 name_reg, |
| 796 scratch, |
| 797 kDontSaveFPRegs); |
794 } else { | 798 } else { |
795 // Write to the properties array. | 799 // Write to the properties array. |
796 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 800 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
797 // Get the properties array (optimistically). | 801 // Get the properties array (optimistically). |
798 __ mov(scratch, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); | 802 __ mov(scratch, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); |
799 __ mov(FieldOperand(scratch, offset), eax); | 803 __ mov(FieldOperand(scratch, offset), eax); |
800 | 804 |
801 // Update the write barrier for the array address. | 805 // Update the write barrier for the array address. |
802 // Pass the value being stored in the now unused name_reg. | 806 // Pass the value being stored in the now unused name_reg. |
803 __ mov(name_reg, Operand(eax)); | 807 __ mov(name_reg, Operand(eax)); |
804 __ RecordWrite(scratch, offset, name_reg, receiver_reg); | 808 __ RecordWriteField(scratch, |
| 809 offset, |
| 810 name_reg, |
| 811 receiver_reg, |
| 812 kDontSaveFPRegs); |
805 } | 813 } |
806 | 814 |
807 // Return the value (register eax). | 815 // Return the value (register eax). |
808 __ ret(0); | 816 __ ret(0); |
809 } | 817 } |
810 | 818 |
811 | 819 |
812 // Generate code to check that a global property cell is empty. Create | 820 // Generate code to check that a global property cell is empty. Create |
813 // the property cell at compilation time if no cell exists for the | 821 // the property cell at compilation time if no cell exists for the |
814 // property. | 822 // property. |
(...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1439 | 1447 |
1440 // Get the elements array of the object. | 1448 // Get the elements array of the object. |
1441 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); | 1449 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); |
1442 | 1450 |
1443 // Check that the elements are in fast mode and writable. | 1451 // Check that the elements are in fast mode and writable. |
1444 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), | 1452 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), |
1445 Immediate(factory()->fixed_array_map())); | 1453 Immediate(factory()->fixed_array_map())); |
1446 __ j(not_equal, &call_builtin); | 1454 __ j(not_equal, &call_builtin); |
1447 | 1455 |
1448 if (argc == 1) { // Otherwise fall through to call builtin. | 1456 if (argc == 1) { // Otherwise fall through to call builtin. |
1449 Label exit, with_write_barrier, attempt_to_grow_elements; | 1457 Label exit, attempt_to_grow_elements, with_write_barrier; |
1450 | 1458 |
1451 // Get the array's length into eax and calculate new length. | 1459 // Get the array's length into eax and calculate new length. |
1452 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); | 1460 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); |
1453 STATIC_ASSERT(kSmiTagSize == 1); | 1461 STATIC_ASSERT(kSmiTagSize == 1); |
1454 STATIC_ASSERT(kSmiTag == 0); | 1462 STATIC_ASSERT(kSmiTag == 0); |
1455 __ add(Operand(eax), Immediate(Smi::FromInt(argc))); | 1463 __ add(Operand(eax), Immediate(Smi::FromInt(argc))); |
1456 | 1464 |
1457 // Get the element's length into ecx. | 1465 // Get the element's length into ecx. |
1458 __ mov(ecx, FieldOperand(ebx, FixedArray::kLengthOffset)); | 1466 __ mov(ecx, FieldOperand(ebx, FixedArray::kLengthOffset)); |
1459 | 1467 |
(...skipping 12 matching lines...) Expand all Loading... |
1472 __ mov(Operand(edx, 0), ecx); | 1480 __ mov(Operand(edx, 0), ecx); |
1473 | 1481 |
1474 // Check if value is a smi. | 1482 // Check if value is a smi. |
1475 __ JumpIfNotSmi(ecx, &with_write_barrier); | 1483 __ JumpIfNotSmi(ecx, &with_write_barrier); |
1476 | 1484 |
1477 __ bind(&exit); | 1485 __ bind(&exit); |
1478 __ ret((argc + 1) * kPointerSize); | 1486 __ ret((argc + 1) * kPointerSize); |
1479 | 1487 |
1480 __ bind(&with_write_barrier); | 1488 __ bind(&with_write_barrier); |
1481 | 1489 |
1482 __ InNewSpace(ebx, ecx, equal, &exit); | 1490 __ RecordWrite( |
| 1491 ebx, edx, ecx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); |
1483 | 1492 |
1484 __ RecordWriteHelper(ebx, edx, ecx); | |
1485 __ ret((argc + 1) * kPointerSize); | 1493 __ ret((argc + 1) * kPointerSize); |
1486 | 1494 |
1487 __ bind(&attempt_to_grow_elements); | 1495 __ bind(&attempt_to_grow_elements); |
1488 if (!FLAG_inline_new) { | 1496 if (!FLAG_inline_new) { |
1489 __ jmp(&call_builtin); | 1497 __ jmp(&call_builtin); |
1490 } | 1498 } |
1491 | 1499 |
| 1500 // We could be lucky and the elements array could be at the top of |
| 1501 // new-space. In this case we can just grow it in place by moving the |
| 1502 // allocation pointer up. |
| 1503 |
1492 ExternalReference new_space_allocation_top = | 1504 ExternalReference new_space_allocation_top = |
1493 ExternalReference::new_space_allocation_top_address(isolate()); | 1505 ExternalReference::new_space_allocation_top_address(isolate()); |
1494 ExternalReference new_space_allocation_limit = | 1506 ExternalReference new_space_allocation_limit = |
1495 ExternalReference::new_space_allocation_limit_address(isolate()); | 1507 ExternalReference::new_space_allocation_limit_address(isolate()); |
1496 | 1508 |
1497 const int kAllocationDelta = 4; | 1509 const int kAllocationDelta = 4; |
1498 // Load top. | 1510 // Load top. |
1499 __ mov(ecx, Operand::StaticVariable(new_space_allocation_top)); | 1511 __ mov(ecx, Operand::StaticVariable(new_space_allocation_top)); |
1500 | 1512 |
1501 // Check if it's the end of elements. | 1513 // Check if it's the end of elements. |
(...skipping 11 matching lines...) Expand all Loading... |
1513 __ mov(ecx, Operand(esp, argc * kPointerSize)); | 1525 __ mov(ecx, Operand(esp, argc * kPointerSize)); |
1514 | 1526 |
1515 // Push the argument... | 1527 // Push the argument... |
1516 __ mov(Operand(edx, 0), ecx); | 1528 __ mov(Operand(edx, 0), ecx); |
1517 // ... and fill the rest with holes. | 1529 // ... and fill the rest with holes. |
1518 for (int i = 1; i < kAllocationDelta; i++) { | 1530 for (int i = 1; i < kAllocationDelta; i++) { |
1519 __ mov(Operand(edx, i * kPointerSize), | 1531 __ mov(Operand(edx, i * kPointerSize), |
1520 Immediate(factory()->the_hole_value())); | 1532 Immediate(factory()->the_hole_value())); |
1521 } | 1533 } |
1522 | 1534 |
| 1535 // We know the elements array is in new space so we don't need the |
| 1536 // remembered set, but we just pushed a value onto it so we may have to |
| 1537 // tell the incremental marker to rescan the object that we just grew. We |
| 1538 // don't need to worry about the holes because they are in old space and |
| 1539 // already marked black. |
| 1540 __ RecordWrite(ebx, edx, ecx, kDontSaveFPRegs, OMIT_REMEMBERED_SET); |
| 1541 |
1523 // Restore receiver to edx as finish sequence assumes it's here. | 1542 // Restore receiver to edx as finish sequence assumes it's here. |
1524 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1543 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
1525 | 1544 |
1526 // Increment element's and array's sizes. | 1545 // Increment element's and array's sizes. |
1527 __ add(FieldOperand(ebx, FixedArray::kLengthOffset), | 1546 __ add(FieldOperand(ebx, FixedArray::kLengthOffset), |
1528 Immediate(Smi::FromInt(kAllocationDelta))); | 1547 Immediate(Smi::FromInt(kAllocationDelta))); |
| 1548 |
| 1549 // NOTE: This only happen in new-space, where we don't |
| 1550 // care about the black-byte-count on pages. Otherwise we should |
| 1551 // update that too if the object is black. |
| 1552 |
1529 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); | 1553 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); |
1530 | 1554 |
1531 // Elements are in new space, so write barrier is not required. | |
1532 __ ret((argc + 1) * kPointerSize); | 1555 __ ret((argc + 1) * kPointerSize); |
1533 } | 1556 } |
1534 | 1557 |
1535 __ bind(&call_builtin); | 1558 __ bind(&call_builtin); |
1536 __ TailCallExternalReference( | 1559 __ TailCallExternalReference( |
1537 ExternalReference(Builtins::c_ArrayPush, isolate()), | 1560 ExternalReference(Builtins::c_ArrayPush, isolate()), |
1538 argc + 1, | 1561 argc + 1, |
1539 1); | 1562 1); |
1540 } | 1563 } |
1541 | 1564 |
(...skipping 1055 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2597 // -- edx : receiver | 2620 // -- edx : receiver |
2598 // -- esp[0] : return address | 2621 // -- esp[0] : return address |
2599 // ----------------------------------- | 2622 // ----------------------------------- |
2600 Label miss; | 2623 Label miss; |
2601 | 2624 |
2602 // Check that the map of the global has not changed. | 2625 // Check that the map of the global has not changed. |
2603 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 2626 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
2604 Immediate(Handle<Map>(object->map()))); | 2627 Immediate(Handle<Map>(object->map()))); |
2605 __ j(not_equal, &miss); | 2628 __ j(not_equal, &miss); |
2606 | 2629 |
2607 | |
2608 // Compute the cell operand to use. | 2630 // Compute the cell operand to use. |
2609 Operand cell_operand = Operand::Cell(Handle<JSGlobalPropertyCell>(cell)); | 2631 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); |
2610 if (Serializer::enabled()) { | 2632 Operand cell_operand = FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset); |
2611 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); | |
2612 cell_operand = FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset); | |
2613 } | |
2614 | 2633 |
2615 // Check that the value in the cell is not the hole. If it is, this | 2634 // Check that the value in the cell is not the hole. If it is, this |
2616 // cell could have been deleted and reintroducing the global needs | 2635 // cell could have been deleted and reintroducing the global needs |
2617 // to update the property details in the property dictionary of the | 2636 // to update the property details in the property dictionary of the |
2618 // global object. We bail out to the runtime system to do that. | 2637 // global object. We bail out to the runtime system to do that. |
2619 __ cmp(cell_operand, factory()->the_hole_value()); | 2638 __ cmp(cell_operand, factory()->the_hole_value()); |
2620 __ j(equal, &miss); | 2639 __ j(equal, &miss); |
2621 | 2640 |
2622 // Store the value in the cell. | 2641 // Store the value in the cell. |
2623 __ mov(cell_operand, eax); | 2642 __ mov(cell_operand, eax); |
| 2643 Label done; |
| 2644 __ test(eax, Immediate(kSmiTagMask)); |
| 2645 __ j(zero, &done); |
| 2646 |
| 2647 __ mov(ecx, eax); |
| 2648 __ lea(edx, cell_operand); |
| 2649 // Cells are always in the remembered set. |
| 2650 __ RecordWrite(ebx, // Object. |
| 2651 edx, // Address. |
| 2652 ecx, // Value. |
| 2653 kDontSaveFPRegs, |
| 2654 OMIT_REMEMBERED_SET, |
| 2655 OMIT_SMI_CHECK); |
2624 | 2656 |
2625 // Return the value (register eax). | 2657 // Return the value (register eax). |
| 2658 __ bind(&done); |
| 2659 |
2626 Counters* counters = isolate()->counters(); | 2660 Counters* counters = isolate()->counters(); |
2627 __ IncrementCounter(counters->named_store_global_inline(), 1); | 2661 __ IncrementCounter(counters->named_store_global_inline(), 1); |
2628 __ ret(0); | 2662 __ ret(0); |
2629 | 2663 |
2630 // Handle store cache miss. | 2664 // Handle store cache miss. |
2631 __ bind(&miss); | 2665 __ bind(&miss); |
2632 __ IncrementCounter(counters->named_store_global_inline_miss(), 1); | 2666 __ IncrementCounter(counters->named_store_global_inline_miss(), 1); |
2633 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); | 2667 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); |
2634 __ jmp(ic, RelocInfo::CODE_TARGET); | 2668 __ jmp(ic, RelocInfo::CODE_TARGET); |
2635 | 2669 |
(...skipping 1232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3868 if (is_js_array) { | 3902 if (is_js_array) { |
3869 // Check that the key is within bounds. | 3903 // Check that the key is within bounds. |
3870 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // smis. | 3904 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // smis. |
3871 __ j(above_equal, &miss_force_generic); | 3905 __ j(above_equal, &miss_force_generic); |
3872 } else { | 3906 } else { |
3873 // Check that the key is within bounds. | 3907 // Check that the key is within bounds. |
3874 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // smis. | 3908 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // smis. |
3875 __ j(above_equal, &miss_force_generic); | 3909 __ j(above_equal, &miss_force_generic); |
3876 } | 3910 } |
3877 | 3911 |
3878 // Do the store and update the write barrier. Make sure to preserve | 3912 // Do the store and update the write barrier. |
3879 // the value in register eax. | 3913 __ lea(ecx, FieldOperand(edi, ecx, times_2, FixedArray::kHeaderSize)); |
| 3914 __ mov(Operand(ecx, 0), eax); |
| 3915 // Make sure to preserve the value in register eax. |
3880 __ mov(edx, Operand(eax)); | 3916 __ mov(edx, Operand(eax)); |
3881 __ mov(FieldOperand(edi, ecx, times_2, FixedArray::kHeaderSize), eax); | 3917 __ RecordWrite(edi, ecx, edx, kDontSaveFPRegs); |
3882 __ RecordWrite(edi, 0, edx, ecx); | |
3883 | 3918 |
3884 // Done. | 3919 // Done. |
3885 __ ret(0); | 3920 __ ret(0); |
3886 | 3921 |
3887 // Handle store cache miss, replacing the ic with the generic stub. | 3922 // Handle store cache miss, replacing the ic with the generic stub. |
3888 __ bind(&miss_force_generic); | 3923 __ bind(&miss_force_generic); |
3889 Handle<Code> ic_force_generic = | 3924 Handle<Code> ic_force_generic = |
3890 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | 3925 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
3891 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); | 3926 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); |
3892 } | 3927 } |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3984 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | 4019 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
3985 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); | 4020 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); |
3986 } | 4021 } |
3987 | 4022 |
3988 | 4023 |
3989 #undef __ | 4024 #undef __ |
3990 | 4025 |
3991 } } // namespace v8::internal | 4026 } } // namespace v8::internal |
3992 | 4027 |
3993 #endif // V8_TARGET_ARCH_IA32 | 4028 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |