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