Commit 6d692dbb authored by Igor Sheludko's avatar Igor Sheludko Committed by Commit Bot

[ptr-compr][x64] Implement decompression snippets for x64

Currently, in debug mode the snippets check the result of decompression equals
to the full value stored in the field.

Bug: v8:7703
Change-Id: I0caa7fdaa7d346612084706ed96a4330fcb0c236
Reviewed-on: https://chromium-review.googlesource.com/c/1319575
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57354}
parent e15e4248
......@@ -1882,6 +1882,25 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
ASSEMBLE_MOVX(movsxlq);
EmitWordLoadPoisoningIfNeeded(this, opcode, instr, i);
break;
case kX64MovqDecompressTaggedSigned: {
CHECK(instr->HasOutput());
__ DecompressTaggedSigned(i.OutputRegister(), i.MemoryOperand(),
DEBUG_BOOL ? i.TempRegister(0) : no_reg);
break;
}
case kX64MovqDecompressTaggedPointer: {
CHECK(instr->HasOutput());
__ DecompressTaggedPointer(i.OutputRegister(), i.MemoryOperand(),
DEBUG_BOOL ? i.TempRegister(0) : no_reg);
break;
}
case kX64MovqDecompressAnyTagged: {
CHECK(instr->HasOutput());
__ DecompressAnyTagged(i.OutputRegister(), i.MemoryOperand(),
i.TempRegister(0),
DEBUG_BOOL ? i.TempRegister(1) : no_reg);
break;
}
case kX64Movq:
EmitOOLTrapIfNeeded(zone(), this, opcode, instr, i, __ pc_offset());
if (instr->HasOutput()) {
......
......@@ -132,6 +132,9 @@ namespace compiler {
V(X64Movw) \
V(X64Movl) \
V(X64Movsxlq) \
V(X64MovqDecompressTaggedSigned) \
V(X64MovqDecompressTaggedPointer) \
V(X64MovqDecompressAnyTagged) \
V(X64Movq) \
V(X64Movsd) \
V(X64Movss) \
......
......@@ -278,6 +278,9 @@ int InstructionScheduler::GetTargetInstructionFlags(
return kHasSideEffect;
}
case kX64MovqDecompressTaggedSigned:
case kX64MovqDecompressTaggedPointer:
case kX64MovqDecompressAnyTagged:
case kX64Movq:
case kX64Movsd:
case kX64Movss:
......
......@@ -234,9 +234,18 @@ ArchOpcode GetLoadOpcode(LoadRepresentation load_rep) {
case MachineRepresentation::kWord32:
opcode = kX64Movl;
break;
#ifdef V8_COMPRESS_POINTERS
case MachineRepresentation::kTaggedSigned:
return kX64MovqDecompressTaggedSigned;
case MachineRepresentation::kTaggedPointer:
return kX64MovqDecompressTaggedPointer;
case MachineRepresentation::kTagged:
return kX64MovqDecompressAnyTagged;
#else
case MachineRepresentation::kTaggedSigned: // Fall through.
case MachineRepresentation::kTaggedPointer: // Fall through.
case MachineRepresentation::kTagged: // Fall through.
#endif
case MachineRepresentation::kWord64:
opcode = kX64Movq;
break;
......@@ -309,6 +318,21 @@ void InstructionSelector::VisitLoad(Node* node) {
X64OperandGenerator g(this);
ArchOpcode opcode = GetLoadOpcode(load_rep);
size_t temp_count = 0;
InstructionOperand temps[2];
#ifdef V8_COMPRESS_POINTERS
if (opcode == kX64MovqDecompressAnyTagged) {
temps[temp_count++] = g.TempRegister();
}
#ifdef DEBUG
if (opcode == kX64MovqDecompressTaggedSigned ||
opcode == kX64MovqDecompressTaggedPointer ||
opcode == kX64MovqDecompressAnyTagged) {
temps[temp_count++] = g.TempRegister();
}
#endif // DEBUG
#endif // V8_COMPRESS_POINTERS
DCHECK_LE(temp_count, arraysize(temps));
InstructionOperand outputs[] = {g.DefineAsRegister(node)};
InstructionOperand inputs[3];
size_t input_count = 0;
......@@ -321,7 +345,7 @@ void InstructionSelector::VisitLoad(Node* node) {
CHECK_NE(poisoning_level_, PoisoningMitigationLevel::kDontPoison);
code |= MiscField::encode(kMemoryAccessPoisoned);
}
Emit(code, 1, outputs, input_count, inputs);
Emit(code, 1, outputs, input_count, inputs, temp_count, temps);
}
void InstructionSelector::VisitPoisonedLoad(Node* node) { VisitLoad(node); }
......
......@@ -224,6 +224,82 @@ void TurboAssembler::CompareRoot(Operand with, RootIndex index) {
cmpp(with, kScratchRegister);
}
void TurboAssembler::DecompressTaggedSigned(Register destination,
Operand field_operand,
Register scratch_for_debug) {
RecordComment("[ DecompressTaggedSigned");
if (DEBUG_BOOL && scratch_for_debug.is_valid()) {
Register expected_value = scratch_for_debug;
movq(expected_value, field_operand);
movsxlq(destination, expected_value);
Label check_passed;
cmpq(destination, expected_value);
j(equal, &check_passed);
RecordComment("DecompressTaggedSigned failed");
int3();
bind(&check_passed);
} else {
movsxlq(destination, field_operand);
}
RecordComment("]");
}
void TurboAssembler::DecompressTaggedPointer(Register destination,
Operand field_operand,
Register scratch_for_debug) {
RecordComment("[ DecompressTaggedPointer");
if (DEBUG_BOOL && scratch_for_debug.is_valid()) {
Register expected_value = scratch_for_debug;
movq(expected_value, field_operand);
movsxlq(destination, expected_value);
addq(destination, kRootRegister);
Label check_passed;
cmpq(destination, expected_value);
j(equal, &check_passed);
RecordComment("DecompressTaggedPointer failed");
int3();
bind(&check_passed);
} else {
movsxlq(destination, field_operand);
addq(destination, kRootRegister);
}
RecordComment("]");
}
void TurboAssembler::DecompressAnyTagged(Register destination,
Operand field_operand,
Register scratch,
Register scratch_for_debug) {
RecordComment("[ DecompressAnyTagged");
Register expected_value = scratch_for_debug;
if (DEBUG_BOOL && expected_value.is_valid()) {
movq(expected_value, field_operand);
movsxlq(destination, expected_value);
} else {
movsxlq(destination, field_operand);
}
// Branchlessly compute |masked_root|:
// masked_root = HAS_SMI_TAG(destination) ? 0 : kRootRegister;
STATIC_ASSERT((kSmiTagSize == 1) && (kSmiTag < 32));
Register masked_root = scratch;
movl(masked_root, destination);
andl(masked_root, Immediate(kSmiTagMask));
negq(masked_root);
andq(masked_root, kRootRegister);
// Now this add operation will either leave the value unchanged if it is a smi
// or add the isolate root if it is a heap object.
addq(destination, masked_root);
if (DEBUG_BOOL && expected_value.is_valid()) {
Label check_passed;
cmpq(destination, expected_value);
j(equal, &check_passed);
RecordComment("Decompression failed: Tagged");
int3();
bind(&check_passed);
}
RecordComment("]");
}
void MacroAssembler::RecordWriteField(Register object, int offset,
Register value, Register dst,
SaveFPRegsMode save_fp,
......
......@@ -512,6 +512,17 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
void ResetSpeculationPoisonRegister();
// ---------------------------------------------------------------------------
// Pointer compresstion Support
// TODO(ishell): remove |scratch_for_debug| once pointer compression works.
void DecompressTaggedSigned(Register destination, Operand field_operand,
Register scratch_for_debug);
void DecompressTaggedPointer(Register destination, Operand field_operand,
Register scratch_for_debug);
void DecompressAnyTagged(Register destination, Operand field_operand,
Register scratch, Register scratch_for_debug);
protected:
static const int kSmiShift = kSmiTagSize + kSmiShiftSize;
int smi_count = 0;
......@@ -583,9 +594,8 @@ class MacroAssembler : public TurboAssembler {
j(not_equal, if_not_equal, if_not_equal_distance);
}
// ---------------------------------------------------------------------------
// GC Support
// ---------------------------------------------------------------------------
// GC Support
// Notify the garbage collector that we wrote a pointer into an object.
// |object| is the object being stored into, |value| is the object being
......
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