Commit 42afba51 authored by Igor Sheludko's avatar Igor Sheludko Committed by Commit Bot

[ptr-compr][x64] Introduce bottlenecks for accessing on-heap tagged fields

and fix platform builtins.

This CL also introduces MacroAssembler::xxx_tagged() operations which
operate on potentially compressed tagged values without doing decompression.

This CL also drive-by fixes compilation failures when pointer compression is
enabled.

Bug: v8:7703
Change-Id: Id417f2a78907e8911aaa79ef404f5bcc87d9a3b8
Reviewed-on: https://chromium-review.googlesource.com/c/1382740Reviewed-by: 's avatarSigurd Schneider <sigurds@chromium.org>
Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58352}
parent 62e86b88
This diff is collapsed.
......@@ -652,7 +652,8 @@ void CodeGenerator::AssembleCodeStartRegisterCheck() {
// 3. if it is not zero then it jumps to the builtin.
void CodeGenerator::BailoutIfDeoptimized() {
int offset = Code::kCodeDataContainerOffset - Code::kHeaderSize;
__ movp(rbx, Operand(kJavaScriptCallCodeStartRegister, offset));
__ LoadTaggedPointerField(rbx,
Operand(kJavaScriptCallCodeStartRegister, offset));
__ testl(FieldOperand(rbx, CodeDataContainer::kKindSpecificFlagsOffset),
Immediate(1 << Code::kMarkedForDeoptimizationBit));
// Ensure we're not serializing (otherwise we'd need to use an indirection to
......@@ -809,11 +810,12 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
Register func = i.InputRegister(0);
if (FLAG_debug_code) {
// Check the function's context matches the context argument.
__ cmpp(rsi, FieldOperand(func, JSFunction::kContextOffset));
__ cmp_tagged(rsi, FieldOperand(func, JSFunction::kContextOffset));
__ Assert(equal, AbortReason::kWrongFunctionContext);
}
static_assert(kJavaScriptCallCodeStartRegister == rcx, "ABI mismatch");
__ movp(rcx, FieldOperand(func, JSFunction::kCodeOffset));
__ LoadTaggedPointerField(rcx,
FieldOperand(func, JSFunction::kCodeOffset));
__ addp(rcx, Immediate(Code::kHeaderSize - kHeapObjectTag));
__ call(rcx);
frame_access_state()->ClearSPDelta();
......@@ -3373,12 +3375,12 @@ void CodeGenerator::AssembleConstructFrame() {
// Unpack the tuple into the instance and the target callable.
// This must be done here in the codegen because it cannot be expressed
// properly in the graph.
__ movq(kJSFunctionRegister,
Operand(kWasmInstanceRegister,
Tuple2::kValue2Offset - kHeapObjectTag));
__ movq(kWasmInstanceRegister,
Operand(kWasmInstanceRegister,
Tuple2::kValue1Offset - kHeapObjectTag));
__ LoadTaggedPointerField(
kJSFunctionRegister,
FieldOperand(kWasmInstanceRegister, Tuple2::kValue2Offset));
__ LoadTaggedPointerField(
kWasmInstanceRegister,
FieldOperand(kWasmInstanceRegister, Tuple2::kValue1Offset));
__ pushq(kWasmInstanceRegister);
}
}
......@@ -3426,8 +3428,9 @@ void CodeGenerator::AssembleConstructFrame() {
__ cmpq(rsp, kScratchRegister);
__ j(above_equal, &done);
}
__ movp(rcx, FieldOperand(kWasmInstanceRegister,
WasmInstanceObject::kCEntryStubOffset));
__ LoadTaggedPointerField(
rcx, FieldOperand(kWasmInstanceRegister,
WasmInstanceObject::kCEntryStubOffset));
__ Move(rsi, Smi::zero());
__ CallRuntimeWithCEntry(Runtime::kThrowWasmStackOverflow, rcx);
ReferenceMap* reference_map = new (zone()) ReferenceMap(zone());
......
......@@ -34,11 +34,17 @@ void DebugCodegen::GenerateFrameDropperTrampoline(MacroAssembler* masm) {
// - Look up current function on the frame.
// - Leave the frame.
// - Restart the frame by calling the function.
Register decompr_scratch_for_debug =
COMPRESS_POINTERS_BOOL ? kScratchRegister : no_reg;
__ movp(rbp, rbx);
__ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
__ leave();
__ movp(rbx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
__ LoadTaggedPointerField(
rbx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset),
decompr_scratch_for_debug);
__ movzxwq(
rbx, FieldOperand(rbx, SharedFunctionInfo::kFormalParameterCountOffset));
......
......@@ -7,6 +7,9 @@
#include "src/objects/maybe-object.h"
#ifdef V8_COMPRESS_POINTERS
#include "src/isolate.h"
#endif
#include "src/objects-inl.h"
#include "src/objects/slots-inl.h"
......
......@@ -164,6 +164,11 @@ bool CompressedMapWordSlot::contains_value(Address raw_value) const {
return value == static_cast<Tagged_t>(raw_value);
}
Object* CompressedMapWordSlot::operator*() const {
Tagged_t value = *location();
return reinterpret_cast<Object*>(DecompressTaggedPointer(address(), value));
}
ObjectPtr CompressedMapWordSlot::load() const {
Tagged_t value = *location();
return ObjectPtr(DecompressTaggedPointer(address(), value));
......
......@@ -80,6 +80,7 @@ class CompressedMapWordSlot
// raw value without decompression.
inline bool contains_value(Address raw_value) const;
inline Object* operator*() const;
inline ObjectPtr load() const;
inline void store(ObjectPtr value) const;
......
......@@ -138,7 +138,8 @@ enum ScaleFactor : int8_t {
times_4 = 2,
times_8 = 3,
times_int_size = times_4,
times_pointer_size = (kPointerSize == 8) ? times_8 : times_4
times_pointer_size = (kSystemPointerSize == 8) ? times_8 : times_4,
times_tagged_size = (kTaggedSize == 8) ? times_8 : times_4,
};
class V8_EXPORT_PRIVATE Operand {
......@@ -412,52 +413,76 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
// - Instructions on 64-bit (quadword) operands/registers use 'q'.
// - Instructions on operands/registers with pointer size use 'p'.
STATIC_ASSERT(kPointerSize == kInt64Size || kPointerSize == kInt32Size);
#define DECLARE_INSTRUCTION(instruction) \
template<class P1> \
void instruction##p(P1 p1) { \
emit_##instruction(p1, kPointerSize); \
} \
\
template<class P1> \
void instruction##l(P1 p1) { \
emit_##instruction(p1, kInt32Size); \
} \
\
template<class P1> \
void instruction##q(P1 p1) { \
emit_##instruction(p1, kInt64Size); \
} \
\
template<class P1, class P2> \
void instruction##p(P1 p1, P2 p2) { \
emit_##instruction(p1, p2, kPointerSize); \
} \
\
template<class P1, class P2> \
void instruction##l(P1 p1, P2 p2) { \
emit_##instruction(p1, p2, kInt32Size); \
} \
\
template<class P1, class P2> \
void instruction##q(P1 p1, P2 p2) { \
emit_##instruction(p1, p2, kInt64Size); \
} \
\
template<class P1, class P2, class P3> \
void instruction##p(P1 p1, P2 p2, P3 p3) { \
emit_##instruction(p1, p2, p3, kPointerSize); \
} \
\
template<class P1, class P2, class P3> \
void instruction##l(P1 p1, P2 p2, P3 p3) { \
emit_##instruction(p1, p2, p3, kInt32Size); \
} \
\
template<class P1, class P2, class P3> \
void instruction##q(P1 p1, P2 p2, P3 p3) { \
emit_##instruction(p1, p2, p3, kInt64Size); \
STATIC_ASSERT(kSystemPointerSize == kInt64Size ||
kSystemPointerSize == kInt32Size);
#define DECLARE_INSTRUCTION(instruction) \
template <class P1> \
void instruction##p(P1 p1) { \
emit_##instruction(p1, kSystemPointerSize); \
} \
\
template <class P1> \
void instruction##_tagged(P1 p1) { \
STATIC_ASSERT(kTaggedSize == kSystemPointerSize); \
/* TODO(ishell): change to kTaggedSize */ \
emit_##instruction(p1, COMPRESS_POINTERS_BOOL ? kInt32Size : kTaggedSize); \
} \
\
template <class P1> \
void instruction##l(P1 p1) { \
emit_##instruction(p1, kInt32Size); \
} \
\
template <class P1> \
void instruction##q(P1 p1) { \
emit_##instruction(p1, kInt64Size); \
} \
\
template <class P1, class P2> \
void instruction##p(P1 p1, P2 p2) { \
emit_##instruction(p1, p2, kSystemPointerSize); \
} \
\
template <class P1, class P2> \
void instruction##_tagged(P1 p1, P2 p2) { \
STATIC_ASSERT(kTaggedSize == kSystemPointerSize); \
/* TODO(ishell): change to kTaggedSize */ \
emit_##instruction(p1, p2, \
COMPRESS_POINTERS_BOOL ? kInt32Size : kTaggedSize); \
} \
\
template <class P1, class P2> \
void instruction##l(P1 p1, P2 p2) { \
emit_##instruction(p1, p2, kInt32Size); \
} \
\
template <class P1, class P2> \
void instruction##q(P1 p1, P2 p2) { \
emit_##instruction(p1, p2, kInt64Size); \
} \
\
template <class P1, class P2, class P3> \
void instruction##p(P1 p1, P2 p2, P3 p3) { \
emit_##instruction(p1, p2, p3, kSystemPointerSize); \
} \
\
template <class P1, class P2, class P3> \
void instruction##_tagged(P1 p1, P2 p2, P3 p3) { \
STATIC_ASSERT(kTaggedSize == kSystemPointerSize); \
/* TODO(ishell): change to kTaggedSize */ \
emit_##instruction(p1, p2, p3, \
COMPRESS_POINTERS_BOOL ? kInt32Size : kTaggedSize); \
} \
\
template <class P1, class P2, class P3> \
void instruction##l(P1 p1, P2 p2, P3 p3) { \
emit_##instruction(p1, p2, p3, kInt32Size); \
} \
\
template <class P1, class P2, class P3> \
void instruction##q(P1 p1, P2 p2, P3 p3) { \
emit_##instruction(p1, p2, p3, kInt64Size); \
}
ASSEMBLER_INSTRUCTION_LIST(DECLARE_INSTRUCTION)
#undef DECLARE_INSTRUCTION
......
This diff is collapsed.
......@@ -478,9 +478,43 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
void ResetSpeculationPoisonRegister();
// ---------------------------------------------------------------------------
// Pointer compresstion Support
// Pointer compression support
// TODO(ishell): remove |scratch_for_debug| once pointer compression works.
// Loads a field containing a HeapObject and decompresses it if pointer
// compression is enabled.
void LoadTaggedPointerField(Register destination, Operand field_operand,
Register scratch_for_debug = no_reg);
// Loads a field containing any tagged value and decompresses it if necessary.
// When pointer compression is enabled, uses |scratch| to decompress the
// value.
void LoadAnyTaggedField(Register destination, Operand field_operand,
Register scratch,
Register scratch_for_debug = no_reg);
// Loads a field containing a HeapObject, decompresses it if necessary and
// pushes full pointer to the stack. When pointer compression is enabled,
// uses |scratch| to decompress the value.
void PushTaggedPointerField(Operand field_operand, Register scratch,
Register scratch_for_debug = no_reg);
// Loads a field containing any tagged value, decompresses it if necessary and
// pushes the full pointer to the stack. When pointer compression is enabled,
// uses |scratch1| and |scratch2| to decompress the value.
void PushTaggedAnyField(Operand field_operand, Register scratch1,
Register scratch2,
Register scratch_for_debug = no_reg);
// Loads a field containing smi value and untags it.
void SmiUntagField(Register dst, Operand src);
// Compresses and stores tagged value to given on-heap location.
// TODO(ishell): drop once mov_tagged() can be used.
void StoreTaggedField(Operand dst_field_operand, Immediate immediate);
void StoreTaggedField(Operand dst_field_operand, Register value);
void DecompressTaggedSigned(Register destination, Operand field_operand,
Register scratch_for_debug);
void DecompressTaggedPointer(Register destination, Operand field_operand,
......
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