From 6d692dbb2d01b63b011ec461accae2c6629af62c Mon Sep 17 00:00:00 2001 From: Igor Sheludko Date: Thu, 8 Nov 2018 12:43:28 +0100 Subject: [PATCH] [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 Reviewed-by: Jaroslav Sevcik Cr-Commit-Position: refs/heads/master@{#57354} --- src/compiler/x64/code-generator-x64.cc | 19 +++++ src/compiler/x64/instruction-codes-x64.h | 3 + src/compiler/x64/instruction-scheduler-x64.cc | 3 + src/compiler/x64/instruction-selector-x64.cc | 26 ++++++- src/x64/macro-assembler-x64.cc | 76 +++++++++++++++++++ src/x64/macro-assembler-x64.h | 16 +++- 6 files changed, 139 insertions(+), 4 deletions(-) diff --git a/src/compiler/x64/code-generator-x64.cc b/src/compiler/x64/code-generator-x64.cc index 4c7a783d73..c6319acede 100644 --- a/src/compiler/x64/code-generator-x64.cc +++ b/src/compiler/x64/code-generator-x64.cc @@ -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()) { diff --git a/src/compiler/x64/instruction-codes-x64.h b/src/compiler/x64/instruction-codes-x64.h index fdc13bca5f..eea9113d93 100644 --- a/src/compiler/x64/instruction-codes-x64.h +++ b/src/compiler/x64/instruction-codes-x64.h @@ -132,6 +132,9 @@ namespace compiler { V(X64Movw) \ V(X64Movl) \ V(X64Movsxlq) \ + V(X64MovqDecompressTaggedSigned) \ + V(X64MovqDecompressTaggedPointer) \ + V(X64MovqDecompressAnyTagged) \ V(X64Movq) \ V(X64Movsd) \ V(X64Movss) \ diff --git a/src/compiler/x64/instruction-scheduler-x64.cc b/src/compiler/x64/instruction-scheduler-x64.cc index 0ede4f107e..727481e227 100644 --- a/src/compiler/x64/instruction-scheduler-x64.cc +++ b/src/compiler/x64/instruction-scheduler-x64.cc @@ -278,6 +278,9 @@ int InstructionScheduler::GetTargetInstructionFlags( return kHasSideEffect; } + case kX64MovqDecompressTaggedSigned: + case kX64MovqDecompressTaggedPointer: + case kX64MovqDecompressAnyTagged: case kX64Movq: case kX64Movsd: case kX64Movss: diff --git a/src/compiler/x64/instruction-selector-x64.cc b/src/compiler/x64/instruction-selector-x64.cc index 61464d9bff..e6b1197c38 100644 --- a/src/compiler/x64/instruction-selector-x64.cc +++ b/src/compiler/x64/instruction-selector-x64.cc @@ -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); } diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc index 4fecf72ef4..cde33c8ab4 100644 --- a/src/x64/macro-assembler-x64.cc +++ b/src/x64/macro-assembler-x64.cc @@ -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, diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h index 3f096c29aa..a0e56b9a80 100644 --- a/src/x64/macro-assembler-x64.h +++ b/src/x64/macro-assembler-x64.h @@ -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