Commit f1478bd1 authored by zhengxing.li's avatar zhengxing.li Committed by Commit bot

X87: [turbofan] Avoid unnecessary write barriers and improve code generation.

   port 1e277012 (r31914)

   original commit message:
   Avoid write barriers when storing values in the root set, and use
   cheaper write barriers for storing maps or tagged pointers. Also
   improve the generated code for write barriers, utilizing the out
   of line code mechanism that is available to TurboFan backends,
   which moves the unlikely case out of the hot path.

BUG=

Review URL: https://codereview.chromium.org/1435743003

Cr-Commit-Position: refs/heads/master@{#31935}
parent e9528b83
...@@ -218,6 +218,46 @@ class OutOfLineTruncateDoubleToI final : public OutOfLineCode { ...@@ -218,6 +218,46 @@ class OutOfLineTruncateDoubleToI final : public OutOfLineCode {
X87Register const input_; X87Register const input_;
}; };
class OutOfLineRecordWrite final : public OutOfLineCode {
public:
OutOfLineRecordWrite(CodeGenerator* gen, Register object, Operand operand,
Register value, Register scratch0, Register scratch1,
RecordWriteMode mode)
: OutOfLineCode(gen),
object_(object),
operand_(operand),
value_(value),
scratch0_(scratch0),
scratch1_(scratch1),
mode_(mode) {}
void Generate() final {
if (mode_ > RecordWriteMode::kValueIsPointer) {
__ JumpIfSmi(value_, exit());
}
if (mode_ > RecordWriteMode::kValueIsMap) {
__ CheckPageFlag(value_, scratch0_,
MemoryChunk::kPointersToHereAreInterestingMask, zero,
exit());
}
SaveFPRegsMode const save_fp_mode =
frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs;
RecordWriteStub stub(isolate(), object_, scratch0_, scratch1_,
EMIT_REMEMBERED_SET, save_fp_mode);
__ lea(scratch1_, operand_);
__ CallStub(&stub);
}
private:
Register const object_;
Operand const operand_;
Register const value_;
Register const scratch0_;
Register const scratch1_;
RecordWriteMode const mode_;
};
} // namespace } // namespace
...@@ -456,6 +496,24 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -456,6 +496,24 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
} }
break; break;
} }
case kArchStoreWithWriteBarrier: {
RecordWriteMode mode =
static_cast<RecordWriteMode>(MiscField::decode(instr->opcode()));
Register object = i.InputRegister(0);
size_t index = 0;
Operand operand = i.MemoryOperand(&index);
Register value = i.InputRegister(index);
Register scratch0 = i.TempRegister(0);
Register scratch1 = i.TempRegister(1);
auto ool = new (zone()) OutOfLineRecordWrite(this, object, operand, value,
scratch0, scratch1, mode);
__ mov(operand, value);
__ CheckPageFlag(object, scratch0,
MemoryChunk::kPointersFromHereAreInterestingMask,
not_zero, ool->entry());
__ bind(ool->exit());
break;
}
case kX87Add: case kX87Add:
if (HasImmediateInput(instr, 1)) { if (HasImmediateInput(instr, 1)) {
__ add(i.InputOperand(0), i.InputImmediate(1)); __ add(i.InputOperand(0), i.InputImmediate(1));
...@@ -1216,24 +1274,6 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -1216,24 +1274,6 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
UNREACHABLE(); UNREACHABLE();
} }
break; break;
case kX87StoreWriteBarrier: {
Register object = i.InputRegister(0);
Register value = i.InputRegister(2);
SaveFPRegsMode mode =
frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs;
if (HasImmediateInput(instr, 1)) {
int index = i.InputInt32(1);
Register scratch = i.TempRegister(1);
__ mov(Operand(object, index), value);
__ RecordWriteContextSlot(object, index, value, scratch, mode);
} else {
Register index = i.InputRegister(1);
__ mov(Operand(object, index, times_1, 0), value);
__ lea(index, Operand(object, index, times_1, 0));
__ RecordWrite(object, index, value, mode);
}
break;
}
case kCheckedLoadInt8: case kCheckedLoadInt8:
ASSEMBLE_CHECKED_LOAD_INTEGER(movsx_b); ASSEMBLE_CHECKED_LOAD_INTEGER(movsx_b);
break; break;
......
...@@ -81,7 +81,6 @@ namespace compiler { ...@@ -81,7 +81,6 @@ namespace compiler {
V(X87PushFloat64) \ V(X87PushFloat64) \
V(X87PushFloat32) \ V(X87PushFloat32) \
V(X87Poke) \ V(X87Poke) \
V(X87StoreWriteBarrier) \
V(X87StackCheck) V(X87StackCheck)
......
...@@ -176,26 +176,47 @@ void InstructionSelector::VisitStore(Node* node) { ...@@ -176,26 +176,47 @@ void InstructionSelector::VisitStore(Node* node) {
Node* value = node->InputAt(2); Node* value = node->InputAt(2);
StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node); StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node);
WriteBarrierKind write_barrier_kind = store_rep.write_barrier_kind();
MachineType rep = RepresentationOf(store_rep.machine_type()); MachineType rep = RepresentationOf(store_rep.machine_type());
if (store_rep.write_barrier_kind() == kFullWriteBarrier) {
if (write_barrier_kind != kNoWriteBarrier) {
DCHECK_EQ(kRepTagged, rep); DCHECK_EQ(kRepTagged, rep);
// TODO(dcarney): refactor RecordWrite function to take temp registers AddressingMode addressing_mode;
// and pass them here instead of using fixed regs InstructionOperand inputs[3];
size_t input_count = 0;
inputs[input_count++] = g.UseUniqueRegister(base);
if (g.CanBeImmediate(index)) { if (g.CanBeImmediate(index)) {
InstructionOperand temps[] = {g.TempRegister(ecx), g.TempRegister()}; inputs[input_count++] = g.UseImmediate(index);
Emit(kX87StoreWriteBarrier, g.NoOutput(), g.UseFixed(base, ebx), addressing_mode = kMode_MRI;
g.UseImmediate(index), g.UseFixed(value, ecx), arraysize(temps),
temps);
} else { } else {
InstructionOperand temps[] = {g.TempRegister(ecx), g.TempRegister(edx)}; inputs[input_count++] = g.UseUniqueRegister(index);
Emit(kX87StoreWriteBarrier, g.NoOutput(), g.UseFixed(base, ebx), addressing_mode = kMode_MR1;
g.UseFixed(index, ecx), g.UseFixed(value, edx), arraysize(temps), }
temps); inputs[input_count++] = (write_barrier_kind == kMapWriteBarrier)
} ? g.UseRegister(value)
return; : g.UseUniqueRegister(value);
RecordWriteMode record_write_mode = RecordWriteMode::kValueIsAny;
switch (write_barrier_kind) {
case kNoWriteBarrier:
UNREACHABLE();
break;
case kMapWriteBarrier:
record_write_mode = RecordWriteMode::kValueIsMap;
break;
case kPointerWriteBarrier:
record_write_mode = RecordWriteMode::kValueIsPointer;
break;
case kFullWriteBarrier:
record_write_mode = RecordWriteMode::kValueIsAny;
break;
} }
DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind()); InstructionOperand temps[] = {g.TempRegister(), g.TempRegister()};
size_t const temp_count = arraysize(temps);
InstructionCode code = kArchStoreWithWriteBarrier;
code |= AddressingModeField::encode(addressing_mode);
code |= MiscField::encode(static_cast<int>(record_write_mode));
Emit(code, 0, nullptr, input_count, inputs, temp_count, temps);
} else {
ArchOpcode opcode; ArchOpcode opcode;
switch (rep) { switch (rep) {
case kRepFloat32: case kRepFloat32:
...@@ -231,11 +252,13 @@ void InstructionSelector::VisitStore(Node* node) { ...@@ -231,11 +252,13 @@ void InstructionSelector::VisitStore(Node* node) {
InstructionOperand inputs[4]; InstructionOperand inputs[4];
size_t input_count = 0; size_t input_count = 0;
AddressingMode mode = AddressingMode addressing_mode =
g.GetEffectiveAddressMemoryOperand(node, inputs, &input_count); g.GetEffectiveAddressMemoryOperand(node, inputs, &input_count);
InstructionCode code = opcode | AddressingModeField::encode(mode); InstructionCode code =
opcode | AddressingModeField::encode(addressing_mode);
inputs[input_count++] = val; inputs[input_count++] = val;
Emit(code, 0, static_cast<InstructionOperand*>(NULL), input_count, inputs); Emit(code, 0, static_cast<InstructionOperand*>(NULL), input_count, inputs);
}
} }
......
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