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