Commit 366cddfa authored by Michael Starzinger's avatar Michael Starzinger Committed by Commit Bot

[wasm] Allow storing of arguments count in a safepoint.

This overlays the "arguments count" and the "deoptimization index"
fields within a safepoint entry. It allows for a larger value of
arguments count to be stored in entries that do not contain a
deoptimization index. Currently the arguments count is unused in
TurboFan, but it will be used to handle reference type arguments in
WebAssembly code.

R=ahaas@chromium.org
BUG=v8:7581

Change-Id: I1e1d5af7e69288f046dc327de5d6e0466fc9ceaf
Reviewed-on: https://chromium-review.googlesource.com/c/1371829
Commit-Queue: Michael Starzinger <mstarzinger@chromium.org>
Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58224}
parent 7a79c0b1
......@@ -302,11 +302,9 @@ void Deoptimizer::DeoptimizeMarkedCodeForContext(Context context) {
PrintF(scope.file(), " / %" V8PRIxPTR "]\n", function.ptr());
}
SafepointEntry safepoint = code->GetSafepointEntry(it.frame()->pc());
int deopt_index = safepoint.deoptimization_index();
// Turbofan deopt is checked when we are patching addresses on stack.
bool safe_if_deopt_triggered =
deopt_index != Safepoint::kNoDeoptimizationIndex;
bool safe_if_deopt_triggered = safepoint.has_deoptimization_index();
bool is_builtin_code = code->kind() == Code::BUILTIN;
DCHECK(topmost_optimized_code.is_null() || safe_if_deopt_triggered ||
is_builtin_code);
......
......@@ -927,10 +927,11 @@ void StandardFrame::IterateCompiledFrame(RootVisitor* v) const {
FullObjectSlot parameters_limit(frame_header_base.address() - slot_space);
// Visit the parameters that may be on top of the saved registers.
if (safepoint_entry.argument_count() > 0) {
if (safepoint_entry.has_argument_count()) {
int argument_count = safepoint_entry.argument_count();
v->VisitRootPointers(Root::kTop, nullptr, parameters_base,
parameters_base + safepoint_entry.argument_count());
parameters_base += safepoint_entry.argument_count();
parameters_base + argument_count);
parameters_base += argument_count;
}
// Skip saved double registers.
......@@ -1581,10 +1582,11 @@ DeoptimizationData OptimizedFrame::GetDeoptimizationData(
DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
SafepointEntry safepoint_entry = code->GetSafepointEntry(pc());
*deopt_index = safepoint_entry.deoptimization_index();
if (*deopt_index != Safepoint::kNoDeoptimizationIndex) {
if (safepoint_entry.has_deoptimization_index()) {
*deopt_index = safepoint_entry.deoptimization_index();
return DeoptimizationData::cast(code->deoptimization_data());
}
*deopt_index = Safepoint::kNoDeoptimizationIndex;
return DeoptimizationData();
}
......
......@@ -15254,12 +15254,12 @@ void Code::Disassemble(const char* name, std::ostream& os, Address current_pc) {
table.PrintEntry(i, os);
os << " (sp -> fp) ";
SafepointEntry entry = table.GetEntry(i);
if (entry.deoptimization_index() != Safepoint::kNoDeoptimizationIndex) {
if (entry.has_deoptimization_index()) {
os << std::setw(6) << entry.deoptimization_index();
} else {
os << "<none>";
}
if (entry.argument_count() > 0) {
if (entry.has_argument_count()) {
os << " argc: " << entry.argument_count();
}
os << "\n";
......
......@@ -46,7 +46,7 @@ SafepointTable::SafepointTable(Address instruction_start,
pc_and_deoptimization_indexes_ = header + kHeaderSize;
entries_ = pc_and_deoptimization_indexes_ + (length_ * kFixedEntrySize);
DCHECK_GT(entry_size_, 0);
STATIC_ASSERT(SafepointEntry::DeoptimizationIndexField::kMax ==
STATIC_ASSERT(SafepointEntry::DeoptimizationIndexOrArgumentsField::kMax ==
Safepoint::kNoDeoptimizationIndex);
}
......@@ -182,11 +182,19 @@ void SafepointTableBuilder::Emit(Assembler* assembler, int bits_per_entry) {
RoundUp(bits_per_entry, kBitsPerByte) >> kBitsPerByteLog2;
// Emit the table header.
STATIC_ASSERT(SafepointTable::kLengthOffset == 0 * kIntSize);
STATIC_ASSERT(SafepointTable::kEntrySizeOffset == 1 * kIntSize);
STATIC_ASSERT(SafepointTable::kHeaderSize == 2 * kIntSize);
int length = static_cast<int>(deoptimization_info_.size());
assembler->dd(length);
assembler->dd(bytes_per_entry);
// Emit sorted table of pc offsets together with deoptimization indexes.
// Emit sorted table of pc offsets together with additional info (i.e. the
// deoptimization index or arguments count) and trampoline offsets.
STATIC_ASSERT(SafepointTable::kPcOffset == 0 * kIntSize);
STATIC_ASSERT(SafepointTable::kEncodedInfoOffset == 1 * kIntSize);
STATIC_ASSERT(SafepointTable::kTrampolinePcOffset == 2 * kIntSize);
STATIC_ASSERT(SafepointTable::kFixedEntrySize == 3 * kIntSize);
for (const DeoptimizationInfo& info : deoptimization_info_) {
assembler->dd(info.pc);
assembler->dd(EncodeExceptPC(info));
......@@ -233,8 +241,11 @@ void SafepointTableBuilder::Emit(Assembler* assembler, int bits_per_entry) {
}
uint32_t SafepointTableBuilder::EncodeExceptPC(const DeoptimizationInfo& info) {
return SafepointEntry::DeoptimizationIndexField::encode(info.deopt_index) |
SafepointEntry::ArgumentsField::encode(info.arguments) |
bool has_argc = info.arguments != 0;
int argc = has_argc ? info.arguments : info.deopt_index;
DCHECK(info.deopt_index == Safepoint::kNoDeoptimizationIndex || !has_argc);
return SafepointEntry::DeoptimizationIndexOrArgumentsField::encode(argc) |
SafepointEntry::HasArgumentsField::encode(has_argc) |
SafepointEntry::SaveDoublesField::encode(info.has_doubles);
}
......
......@@ -36,34 +36,42 @@ class SafepointEntry {
bits_ = nullptr;
}
int deoptimization_index() const {
DCHECK(is_valid());
return DeoptimizationIndexField::decode(info_);
}
int trampoline_pc() { return trampoline_pc_; }
void set_trampoline_pc(int trampoline_pc) { trampoline_pc_ = trampoline_pc; }
static const int kArgumentsFieldBits = 3;
static const int kHasArgumentsFieldBits = 1;
static const int kSaveDoublesFieldBits = 1;
static const int kDeoptIndexBits =
32 - kArgumentsFieldBits - kSaveDoublesFieldBits;
class DeoptimizationIndexField:
public BitField<int, 0, kDeoptIndexBits> {}; // NOLINT
class ArgumentsField:
public BitField<unsigned,
kDeoptIndexBits,
kArgumentsFieldBits> {}; // NOLINT
class SaveDoublesField:
public BitField<bool,
kDeoptIndexBits + kArgumentsFieldBits,
kSaveDoublesFieldBits> { }; // NOLINT
static const int kDeoptIndexOrArgumentsBits =
32 - kHasArgumentsFieldBits - kSaveDoublesFieldBits;
class DeoptimizationIndexOrArgumentsField // --
: public BitField<int, 0, kDeoptIndexOrArgumentsBits> {}; // --
class HasArgumentsField // --
: public BitField<bool, kDeoptIndexOrArgumentsBits, // --
kHasArgumentsFieldBits> {}; // --
class SaveDoublesField // --
: public BitField<bool, HasArgumentsField::kNext, // --
kSaveDoublesFieldBits> {}; // --
int deoptimization_index() const {
DCHECK(is_valid() && has_deoptimization_index());
return DeoptimizationIndexOrArgumentsField::decode(info_);
}
bool has_deoptimization_index() const {
DCHECK(is_valid());
return !HasArgumentsField::decode(info_) &&
DeoptimizationIndexOrArgumentsField::decode(info_) !=
DeoptimizationIndexOrArgumentsField::kMax;
}
int argument_count() const {
DCHECK(is_valid() && has_argument_count());
return DeoptimizationIndexOrArgumentsField::decode(info_);
}
bool has_argument_count() const {
DCHECK(is_valid());
return ArgumentsField::decode(info_);
return HasArgumentsField::decode(info_);
}
bool has_doubles() const {
......@@ -113,7 +121,7 @@ class SafepointTable {
SafepointEntry GetEntry(unsigned index) const {
DCHECK(index < length_);
unsigned info = Memory<uint32_t>(GetInfoLocation(index));
unsigned info = Memory<uint32_t>(GetEncodedInfoLocation(index));
uint8_t* bits = &Memory<uint8_t>(entries_ + (index * entry_size_));
int trampoline_pc =
has_deopt_ ? Memory<int>(GetTrampolineLocation(index)) : -1;
......@@ -133,17 +141,16 @@ class SafepointTable {
static const int kEntrySizeOffset = kLengthOffset + kIntSize;
static const int kHeaderSize = kEntrySizeOffset + kIntSize;
static const int kPcOffset = 0;
static const int kDeoptimizationIndexOffset = kPcOffset + kIntSize;
static const int kTrampolinePcOffset = kDeoptimizationIndexOffset + kIntSize;
static const int kEncodedInfoOffset = kPcOffset + kIntSize;
static const int kTrampolinePcOffset = kEncodedInfoOffset + kIntSize;
static const int kFixedEntrySize = kTrampolinePcOffset + kIntSize;
Address GetPcOffsetLocation(unsigned index) const {
return pc_and_deoptimization_indexes_ + (index * kFixedEntrySize);
}
// TODO(juliana): rename this to GetDeoptimizationIndexLocation
Address GetInfoLocation(unsigned index) const {
return GetPcOffsetLocation(index) + kDeoptimizationIndexOffset;
Address GetEncodedInfoLocation(unsigned index) const {
return GetPcOffsetLocation(index) + kEncodedInfoOffset;
}
Address GetTrampolineLocation(unsigned index) const {
......@@ -184,7 +191,7 @@ class Safepoint {
};
static const int kNoDeoptimizationIndex =
(1 << (SafepointEntry::kDeoptIndexBits)) - 1;
SafepointEntry::DeoptimizationIndexOrArgumentsField::kMax;
void DefinePointerSlot(int index) { indexes_->push_back(index); }
void DefinePointerRegister(Register reg);
......@@ -228,23 +235,24 @@ class SafepointTableBuilder {
// Find the Deoptimization Info with pc offset {pc} and update its
// trampoline field. Calling this function ensures that the safepoint
// table contains the trampoline PC (trampoline} that replaced the
// table contains the trampoline PC {trampoline} that replaced the
// return PC {pc} on the stack.
int UpdateDeoptimizationInfo(int pc, int trampoline, int start);
private:
struct DeoptimizationInfo {
unsigned pc;
unsigned arguments;
unsigned arguments; // Only available if {deopt_index} unused.
unsigned deopt_index; // Only available if {arguments == 0}.
bool has_doubles;
int trampoline;
ZoneChunkList<int>* indexes;
ZoneChunkList<int>* registers;
unsigned deopt_index;
DeoptimizationInfo(Zone* zone, unsigned pc, unsigned arguments,
Safepoint::Kind kind)
: pc(pc),
arguments(arguments),
deopt_index(Safepoint::kNoDeoptimizationIndex),
has_doubles(kind & Safepoint::kWithDoubles),
trampoline(-1),
indexes(new (zone) ZoneChunkList<int>(
......@@ -252,14 +260,16 @@ class SafepointTableBuilder {
registers(kind & Safepoint::kWithRegisters
? new (zone) ZoneChunkList<int>(
zone, ZoneChunkList<int>::StartMode::kSmall)
: nullptr),
deopt_index(Safepoint::kNoDeoptimizationIndex) {}
: nullptr) {}
};
// Encodes all fields of a {DeoptimizationInfo} except {pc} and {trampoline}.
uint32_t EncodeExceptPC(const DeoptimizationInfo&);
// Compares all fields of a {DeoptimizationInfo} except {pc} and {trampoline}.
bool IsIdenticalExceptForPc(const DeoptimizationInfo&,
const DeoptimizationInfo&) const;
// If all entries are identical, replace them by 1 entry with pc = kMaxUInt32.
void RemoveDuplicates();
......
......@@ -322,10 +322,10 @@ void WasmCode::Disassemble(const char* name, std::ostream& os,
if (entry.trampoline_pc() != -1) {
os << " trampoline: " << std::hex << entry.trampoline_pc() << std::dec;
}
if (entry.deoptimization_index() != Safepoint::kNoDeoptimizationIndex) {
if (entry.has_deoptimization_index()) {
os << " deopt: " << std::setw(6) << entry.deoptimization_index();
}
if (entry.argument_count() > 0) {
if (entry.has_argument_count()) {
os << " argc: " << entry.argument_count();
}
os << "\n";
......
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