Clean up handling of global cell stores in the optimizing compiler.

Tell the register allocator the value is not overwritten.  Never use
temporary registers on ia32, avoid them on x64 and ARM.  Restore the
original copyright date on assembler.cc.

R=fschneider@chromium.org
BUG=v8:1870
TEST=

Review URL: http://codereview.chromium.org/8965038

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10280 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 04f0e332
...@@ -1779,11 +1779,12 @@ LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) { ...@@ -1779,11 +1779,12 @@ LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) { LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) {
LOperand* temp = TempRegister(); LOperand* value = UseRegister(instr->value());
LOperand* value = UseTempRegister(instr->value()); // Use a temp to check the value in the cell in the case where we perform
LInstruction* result = new LStoreGlobalCell(value, temp); // a hole check.
if (instr->RequiresHoleCheck()) result = AssignEnvironment(result); return instr->RequiresHoleCheck()
return result; ? AssignEnvironment(new LStoreGlobalCell(value, TempRegister()))
: new LStoreGlobalCell(value, NULL);
} }
......
...@@ -1242,6 +1242,8 @@ class LStoreGlobalCell: public LTemplateInstruction<0, 1, 1> { ...@@ -1242,6 +1242,8 @@ class LStoreGlobalCell: public LTemplateInstruction<0, 1, 1> {
DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell, "store-global-cell") DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell, "store-global-cell")
DECLARE_HYDROGEN_ACCESSOR(StoreGlobalCell) DECLARE_HYDROGEN_ACCESSOR(StoreGlobalCell)
LOperand* value() { return inputs_[0]; }
}; };
......
...@@ -2262,27 +2262,26 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { ...@@ -2262,27 +2262,26 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) {
Register value = ToRegister(instr->InputAt(0)); Register value = ToRegister(instr->value());
Register scratch = scratch0(); Register cell = scratch0();
Register scratch2 = ToRegister(instr->TempAt(0));
// Load the cell. // Load the cell.
__ mov(scratch, Operand(Handle<Object>(instr->hydrogen()->cell()))); __ mov(cell, Operand(instr->hydrogen()->cell()));
// If the cell we are storing to contains the hole it could have // If the cell we are storing to contains the hole it could have
// been deleted from the property dictionary. In that case, we need // been deleted from the property dictionary. In that case, we need
// to update the property details in the property dictionary to mark // to update the property details in the property dictionary to mark
// it as no longer deleted. // it as no longer deleted.
if (instr->hydrogen()->RequiresHoleCheck()) { if (instr->hydrogen()->RequiresHoleCheck()) {
__ ldr(scratch2, // We use a temp to check the payload (CompareRoot might clobber ip).
FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); Register payload = ToRegister(instr->TempAt(0));
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex); __ ldr(payload, FieldMemOperand(cell, JSGlobalPropertyCell::kValueOffset));
__ cmp(scratch2, ip); __ CompareRoot(payload, Heap::kTheHoleValueRootIndex);
DeoptimizeIf(eq, instr->environment()); DeoptimizeIf(eq, instr->environment());
} }
// Store the value. // Store the value.
__ str(value, FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); __ str(value, FieldMemOperand(cell, JSGlobalPropertyCell::kValueOffset));
// Cells are always rescanned, so no write barrier here. // Cells are always rescanned, so no write barrier here.
} }
......
// Copyright (c) 2011 Sun Microsystems Inc. // Copyright (c) 1994-2006 Sun Microsystems Inc.
// All Rights Reserved. // All Rights Reserved.
// //
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
......
...@@ -2124,26 +2124,20 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { ...@@ -2124,26 +2124,20 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) {
Register object = ToRegister(instr->TempAt(0)); Register value = ToRegister(instr->value());
Register address = ToRegister(instr->TempAt(1)); Handle<JSGlobalPropertyCell> cell_handle = instr->hydrogen()->cell();
Register value = ToRegister(instr->InputAt(0));
ASSERT(!value.is(object));
Handle<JSGlobalPropertyCell> cell_handle(instr->hydrogen()->cell());
int offset = JSGlobalPropertyCell::kValueOffset;
__ mov(object, Immediate(cell_handle));
// If the cell we are storing to contains the hole it could have // If the cell we are storing to contains the hole it could have
// been deleted from the property dictionary. In that case, we need // been deleted from the property dictionary. In that case, we need
// to update the property details in the property dictionary to mark // to update the property details in the property dictionary to mark
// it as no longer deleted. We deoptimize in that case. // it as no longer deleted. We deoptimize in that case.
if (instr->hydrogen()->RequiresHoleCheck()) { if (instr->hydrogen()->RequiresHoleCheck()) {
__ cmp(FieldOperand(object, offset), factory()->the_hole_value()); __ cmp(Operand::Cell(cell_handle), factory()->the_hole_value());
DeoptimizeIf(equal, instr->environment()); DeoptimizeIf(equal, instr->environment());
} }
// Store the value. // Store the value.
__ mov(FieldOperand(object, offset), value); __ mov(Operand::Cell(cell_handle), value);
// Cells are always rescanned, so no write barrier here. // Cells are always rescanned, so no write barrier here.
} }
......
...@@ -1856,9 +1856,7 @@ LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) { ...@@ -1856,9 +1856,7 @@ LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) { LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) {
LStoreGlobalCell* result = LStoreGlobalCell* result =
new(zone()) LStoreGlobalCell(UseTempRegister(instr->value()), new(zone()) LStoreGlobalCell(UseRegister(instr->value()));
TempRegister(),
TempRegister());
return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result; return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
} }
......
...@@ -1269,16 +1269,16 @@ class LLoadGlobalGeneric: public LTemplateInstruction<1, 2, 0> { ...@@ -1269,16 +1269,16 @@ class LLoadGlobalGeneric: public LTemplateInstruction<1, 2, 0> {
}; };
class LStoreGlobalCell: public LTemplateInstruction<0, 1, 2> { class LStoreGlobalCell: public LTemplateInstruction<0, 1, 0> {
public: public:
explicit LStoreGlobalCell(LOperand* value, LOperand* temp1, LOperand* temp2) { explicit LStoreGlobalCell(LOperand* value) {
inputs_[0] = value; inputs_[0] = value;
temps_[0] = temp1;
temps_[1] = temp2;
} }
DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell, "store-global-cell") DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell, "store-global-cell")
DECLARE_HYDROGEN_ACCESSOR(StoreGlobalCell) DECLARE_HYDROGEN_ACCESSOR(StoreGlobalCell)
LOperand* value() { return inputs_[0]; }
}; };
......
...@@ -2028,25 +2028,27 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { ...@@ -2028,25 +2028,27 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) {
Register object = ToRegister(instr->TempAt(0)); Register value = ToRegister(instr->value());
Register address = ToRegister(instr->TempAt(1)); Handle<JSGlobalPropertyCell> cell_handle = instr->hydrogen()->cell();
Register value = ToRegister(instr->InputAt(0));
ASSERT(!value.is(object));
Handle<JSGlobalPropertyCell> cell_handle(instr->hydrogen()->cell());
__ movq(address, cell_handle, RelocInfo::GLOBAL_PROPERTY_CELL);
// If the cell we are storing to contains the hole it could have // If the cell we are storing to contains the hole it could have
// been deleted from the property dictionary. In that case, we need // been deleted from the property dictionary. In that case, we need
// to update the property details in the property dictionary to mark // to update the property details in the property dictionary to mark
// it as no longer deleted. We deoptimize in that case. // it as no longer deleted. We deoptimize in that case.
if (instr->hydrogen()->RequiresHoleCheck()) { if (instr->hydrogen()->RequiresHoleCheck()) {
__ CompareRoot(Operand(address, 0), Heap::kTheHoleValueRootIndex); // We have a temp because CompareRoot might clobber kScratchRegister.
Register cell = ToRegister(instr->TempAt(0));
ASSERT(!value.is(cell));
__ movq(cell, cell_handle, RelocInfo::GLOBAL_PROPERTY_CELL);
__ CompareRoot(Operand(cell, 0), Heap::kTheHoleValueRootIndex);
DeoptimizeIf(equal, instr->environment()); DeoptimizeIf(equal, instr->environment());
}
// Store the value. // Store the value.
__ movq(Operand(address, 0), value); __ movq(Operand(cell, 0), value);
} else {
// Store the value.
__ movq(kScratchRegister, cell_handle, RelocInfo::GLOBAL_PROPERTY_CELL);
__ movq(Operand(kScratchRegister, 0), value);
}
// Cells are always rescanned, so no write barrier here. // Cells are always rescanned, so no write barrier here.
} }
......
...@@ -1768,11 +1768,12 @@ LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) { ...@@ -1768,11 +1768,12 @@ LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) { LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) {
LStoreGlobalCell* result = LOperand* value = UseRegister(instr->value());
new LStoreGlobalCell(UseTempRegister(instr->value()), // Use a temp to avoid reloading the cell value address in the case where
TempRegister(), // we perform a hole check.
TempRegister()); return instr->RequiresHoleCheck()
return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result; ? AssignEnvironment(new LStoreGlobalCell(value, TempRegister()))
: new LStoreGlobalCell(value, NULL);
} }
......
...@@ -1231,16 +1231,17 @@ class LLoadGlobalGeneric: public LTemplateInstruction<1, 1, 0> { ...@@ -1231,16 +1231,17 @@ class LLoadGlobalGeneric: public LTemplateInstruction<1, 1, 0> {
}; };
class LStoreGlobalCell: public LTemplateInstruction<0, 1, 2> { class LStoreGlobalCell: public LTemplateInstruction<0, 1, 1> {
public: public:
explicit LStoreGlobalCell(LOperand* value, LOperand* temp1, LOperand* temp2) { explicit LStoreGlobalCell(LOperand* value, LOperand* temp) {
inputs_[0] = value; inputs_[0] = value;
temps_[0] = temp1; temps_[0] = temp;
temps_[1] = temp2;
} }
DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell, "store-global-cell") DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell, "store-global-cell")
DECLARE_HYDROGEN_ACCESSOR(StoreGlobalCell) DECLARE_HYDROGEN_ACCESSOR(StoreGlobalCell)
LOperand* value() { return inputs_[0]; }
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment