| Index: src/x64/full-codegen-x64.cc
 | 
| ===================================================================
 | 
| --- src/x64/full-codegen-x64.cc	(revision 9327)
 | 
| +++ src/x64/full-codegen-x64.cc	(working copy)
 | 
| @@ -200,11 +200,9 @@
 | 
|          // Store it in the context.
 | 
|          int context_offset = Context::SlotOffset(var->index());
 | 
|          __ movq(Operand(rsi, context_offset), rax);
 | 
| -        // Update the write barrier. This clobbers all involved
 | 
| -        // registers, so we have use a third register to avoid
 | 
| -        // clobbering rsi.
 | 
| -        __ movq(rcx, rsi);
 | 
| -        __ RecordWrite(rcx, context_offset, rax, rbx);
 | 
| +        // Update the write barrier.  This clobbers rax and rbx.
 | 
| +        __ RecordWriteContextSlot(
 | 
| +            rsi, context_offset, rax, rbx, kDontSaveFPRegs);
 | 
|        }
 | 
|      }
 | 
|    }
 | 
| @@ -643,10 +641,11 @@
 | 
|    ASSERT(!scratch1.is(src));
 | 
|    MemOperand location = VarOperand(var, scratch0);
 | 
|    __ movq(location, src);
 | 
| +
 | 
|    // Emit the write barrier code if the location is in the heap.
 | 
|    if (var->IsContextSlot()) {
 | 
|      int offset = Context::SlotOffset(var->index());
 | 
| -    __ RecordWrite(scratch0, offset, src, scratch1);
 | 
| +    __ RecordWriteContextSlot(scratch0, offset, src, scratch1, kDontSaveFPRegs);
 | 
|    }
 | 
|  }
 | 
|  
 | 
| @@ -720,8 +719,14 @@
 | 
|          VisitForAccumulatorValue(function);
 | 
|          __ movq(ContextOperand(rsi, variable->index()), result_register());
 | 
|          int offset = Context::SlotOffset(variable->index());
 | 
| -        __ movq(rbx, rsi);
 | 
| -        __ RecordWrite(rbx, offset, result_register(), rcx);
 | 
| +        // We know that we have written a function, which is not a smi.
 | 
| +        __ RecordWriteContextSlot(rsi,
 | 
| +                                  offset,
 | 
| +                                  result_register(),
 | 
| +                                  rcx,
 | 
| +                                  kDontSaveFPRegs,
 | 
| +                                  EMIT_REMEMBERED_SET,
 | 
| +                                  OMIT_SMI_CHECK);
 | 
|          PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
 | 
|        } else if (mode == Variable::CONST || mode == Variable::LET) {
 | 
|          Comment cmnt(masm_, "[ Declaration");
 | 
| @@ -1456,7 +1461,7 @@
 | 
|      __ movq(FieldOperand(rbx, offset), result_register());
 | 
|  
 | 
|      // Update the write barrier for the array store.
 | 
| -    __ RecordWrite(rbx, offset, result_register(), rcx);
 | 
| +    __ RecordWriteField(rbx, offset, result_register(), rcx, kDontSaveFPRegs);
 | 
|  
 | 
|      PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
 | 
|    }
 | 
| @@ -1782,7 +1787,8 @@
 | 
|        __ movq(location, rax);
 | 
|        if (var->IsContextSlot()) {
 | 
|          __ movq(rdx, rax);
 | 
| -        __ RecordWrite(rcx, Context::SlotOffset(var->index()), rdx, rbx);
 | 
| +        __ RecordWriteContextSlot(
 | 
| +            rcx, Context::SlotOffset(var->index()), rdx, rbx, kDontSaveFPRegs);
 | 
|        }
 | 
|      }
 | 
|  
 | 
| @@ -1800,7 +1806,8 @@
 | 
|        __ movq(location, rax);
 | 
|        if (var->IsContextSlot()) {
 | 
|          __ movq(rdx, rax);
 | 
| -        __ RecordWrite(rcx, Context::SlotOffset(var->index()), rdx, rbx);
 | 
| +        __ RecordWriteContextSlot(
 | 
| +            rcx, Context::SlotOffset(var->index()), rdx, rbx, kDontSaveFPRegs);
 | 
|        }
 | 
|      } else {
 | 
|        ASSERT(var->IsLookupSlot());
 | 
| @@ -2731,7 +2738,7 @@
 | 
|    // Update the write barrier.  Save the value as it will be
 | 
|    // overwritten by the write barrier code and is needed afterward.
 | 
|    __ movq(rdx, rax);
 | 
| -  __ RecordWrite(rbx, JSValue::kValueOffset, rdx, rcx);
 | 
| +  __ RecordWriteField(rbx, JSValue::kValueOffset, rdx, rcx, kDontSaveFPRegs);
 | 
|  
 | 
|    __ bind(&done);
 | 
|    context()->Plug(rax);
 | 
| @@ -3015,14 +3022,27 @@
 | 
|    __ movq(Operand(index_2, 0), object);
 | 
|    __ movq(Operand(index_1, 0), temp);
 | 
|  
 | 
| -  Label new_space;
 | 
| -  __ InNewSpace(elements, temp, equal, &new_space);
 | 
| +  Label no_remembered_set;
 | 
| +  __ CheckPageFlag(elements,
 | 
| +                   temp,
 | 
| +                   1 << MemoryChunk::SCAN_ON_SCAVENGE,
 | 
| +                   not_zero,
 | 
| +                   &no_remembered_set,
 | 
| +                   Label::kNear);
 | 
| +  // Possible optimization: do a check that both values are Smis
 | 
| +  // (or them and test against Smi mask.)
 | 
|  
 | 
| -  __ movq(object, elements);
 | 
| -  __ RecordWriteHelper(object, index_1, temp);
 | 
| -  __ RecordWriteHelper(elements, index_2, temp);
 | 
| +  // We are swapping two objects in an array and the incremental marker never
 | 
| +  // pauses in the middle of scanning a single object.  Therefore the
 | 
| +  // incremental marker is not disturbed, so we don't need to call the
 | 
| +  // RecordWrite stub that notifies the incremental marker.
 | 
| +  __ RememberedSetHelper(
 | 
| +      index_1, temp, kDontSaveFPRegs, MacroAssembler::kFallThroughAtEnd);
 | 
| +  __ RememberedSetHelper(
 | 
| +      index_2, temp, kDontSaveFPRegs, MacroAssembler::kFallThroughAtEnd);
 | 
|  
 | 
| -  __ bind(&new_space);
 | 
| +  __ bind(&no_remembered_set);
 | 
| +
 | 
|    // We are done. Drop elements from the stack, and return undefined.
 | 
|    __ addq(rsp, Immediate(3 * kPointerSize));
 | 
|    __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
 | 
| 
 |