[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: Jaroslav Sevcik <jarin@chromium.org> Cr-Commit-Position: refs/heads/master@{#57354}
This commit is contained in:
parent
e15e42487a
commit
6d692dbb2d
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user