SafepointTable table(function->code());
for (unsigned i = 0; i < table.length(); i++) {
unsigned pc_offset = table.GetPcOffset(i);
- int deoptimization_index = table.GetDeoptimizationIndex(i);
- int gap_code_size = table.GetGapCodeSize(i);
+ SafepointEntry safepoint_entry = table.GetEntry(i);
+ int deoptimization_index = safepoint_entry.deoptimization_index();
+ int gap_code_size = safepoint_entry.gap_code_size();
// Check that we did not shoot past next safepoint.
// TODO(srdjan): How do we guarantee that safepoint code does not
// overlap other safepoint patching code?
Code* StackFrame::GetSafepointData(Address pc,
- uint8_t** safepoint_entry,
+ SafepointEntry* safepoint_entry,
unsigned* stack_slots) {
PcToCodeCache::PcToCodeCacheEntry* entry = PcToCodeCache::GetCacheEntry(pc);
- uint8_t* cached_safepoint_entry = entry->safepoint_entry;
- if (cached_safepoint_entry == NULL) {
- cached_safepoint_entry = entry->code->GetSafepointEntry(pc);
- ASSERT(cached_safepoint_entry != NULL); // No safepoint found.
- entry->safepoint_entry = cached_safepoint_entry;
+ SafepointEntry cached_safepoint_entry = entry->safepoint_entry;
+ if (!entry->safepoint_entry.is_valid()) {
+ entry->safepoint_entry = entry->code->GetSafepointEntry(pc);
+ ASSERT(entry->safepoint_entry.is_valid());
} else {
- ASSERT(cached_safepoint_entry == entry->code->GetSafepointEntry(pc));
+ ASSERT(entry->safepoint_entry.Equals(entry->code->GetSafepointEntry(pc)));
}
// Fill in the results and return the code.
Code* code = entry->code;
- *safepoint_entry = cached_safepoint_entry;
+ *safepoint_entry = entry->safepoint_entry;
*stack_slots = code->stack_slots();
return code;
}
// Compute the safepoint information.
unsigned stack_slots = 0;
- uint8_t* safepoint_entry = NULL;
+ SafepointEntry safepoint_entry;
Code* code = StackFrame::GetSafepointData(
pc(), &safepoint_entry, &stack_slots);
unsigned slot_space = stack_slots * kPointerSize;
Object** parameters_limit = &Memory::Object_at(
fp() + JavaScriptFrameConstants::kFunctionOffset - slot_space);
+ // Visit the parameters that may be on top of the saved registers.
+ if (safepoint_entry.argument_count() > 0) {
+ v->VisitPointers(parameters_base,
+ parameters_base + safepoint_entry.argument_count());
+ parameters_base += safepoint_entry.argument_count();
+ }
+
// Visit the registers that contain pointers if any.
- if (SafepointTable::HasRegisters(safepoint_entry)) {
+ if (safepoint_entry.HasRegisters()) {
for (int i = kNumSafepointRegisters - 1; i >=0; i--) {
- if (SafepointTable::HasRegisterAt(safepoint_entry, i)) {
+ if (safepoint_entry.HasRegisterAt(i)) {
int reg_stack_index = MacroAssembler::SafepointRegisterStackIndex(i);
v->VisitPointer(parameters_base + reg_stack_index);
}
}
// We're done dealing with the register bits.
- safepoint_entry += kNumSafepointRegisters >> kBitsPerByteLog2;
+ uint8_t* safepoint_bits = safepoint_entry.bits();
+ safepoint_bits += kNumSafepointRegisters >> kBitsPerByteLog2;
// Visit the rest of the parameters.
v->VisitPointers(parameters_base, parameters_limit);
for (unsigned index = 0; index < stack_slots; index++) {
int byte_index = index >> kBitsPerByteLog2;
int bit_index = index & (kBitsPerByte - 1);
- if ((safepoint_entry[byte_index] & (1U << bit_index)) != 0) {
+ if ((safepoint_bits[byte_index] & (1U << bit_index)) != 0) {
v->VisitPointer(parameters_limit + index);
}
}
ASSERT(code != NULL);
ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION);
- SafepointTable table(code);
- unsigned pc_offset = static_cast<unsigned>(pc() - code->instruction_start());
- for (unsigned i = 0; i < table.length(); i++) {
- if (table.GetPcOffset(i) == pc_offset) {
- *deopt_index = table.GetDeoptimizationIndex(i);
- break;
- }
- }
+ SafepointEntry safepoint_entry = code->GetSafepointEntry(pc());
+ *deopt_index = safepoint_entry.deoptimization_index();
ASSERT(*deopt_index != AstNode::kNoNumber);
return DeoptimizationInputData::cast(code->deoptimization_data());
// been set. Otherwise, we risk trying to use a cache entry before
// the code has been computed.
entry->code = GcSafeFindCodeForPc(pc);
- entry->safepoint_entry = NULL;
+ entry->safepoint_entry.Reset();
entry->pc = pc;
}
return entry;
#ifndef V8_FRAMES_H_
#define V8_FRAMES_H_
+#include "safepoint-table.h"
+
namespace v8 {
namespace internal {
struct PcToCodeCacheEntry {
Address pc;
Code* code;
- uint8_t* safepoint_entry;
+ SafepointEntry safepoint_entry;
};
static PcToCodeCacheEntry* cache(int index) {
// safepoint entry and the number of stack slots. The pc must be at
// a safepoint.
static Code* GetSafepointData(Address pc,
- uint8_t** safepoint_entry,
+ SafepointEntry* safepoint_entry,
unsigned* stack_slots);
virtual void Iterate(ObjectVisitor* v) const = 0;
SafepointTable table(function->code());
for (unsigned i = 0; i < table.length(); i++) {
unsigned pc_offset = table.GetPcOffset(i);
- int deoptimization_index = table.GetDeoptimizationIndex(i);
- int gap_code_size = table.GetGapCodeSize(i);
+ SafepointEntry safepoint_entry = table.GetEntry(i);
+ int deoptimization_index = safepoint_entry.deoptimization_index();
+ int gap_code_size = safepoint_entry.gap_code_size();
#ifdef DEBUG
// Destroy the code which is not supposed to run again.
unsigned instructions = pc_offset - last_pc_offset;
}
-uint8_t* Code::GetSafepointEntry(Address pc) {
+SafepointEntry Code::GetSafepointEntry(Address pc) {
SafepointTable table(this);
- unsigned pc_offset = static_cast<unsigned>(pc - instruction_start());
- for (unsigned i = 0; i < table.length(); i++) {
- // TODO(kasperl): Replace the linear search with binary search.
- if (table.GetPcOffset(i) == pc_offset) return table.GetEntry(i);
- }
- return NULL;
+ return table.FindEntry(pc);
}
PrintF(out, "%p %4d ", (instruction_start() + pc_offset), pc_offset);
table.PrintEntry(i);
PrintF(out, " (sp -> fp)");
- int deoptimization_index = table.GetDeoptimizationIndex(i);
- if (deoptimization_index != Safepoint::kNoDeoptimizationIndex) {
- PrintF(out, " %6d", deoptimization_index);
+ SafepointEntry entry = table.GetEntry(i);
+ if (entry.deoptimization_index() != Safepoint::kNoDeoptimizationIndex) {
+ PrintF(out, " %6d", entry.deoptimization_index());
} else {
PrintF(out, " <none>");
}
+ if (entry.argument_count() > 0) {
+ PrintF(out, " argc: %d", entry.argument_count());
+ }
PrintF(out, "\n");
}
PrintF(out, "\n");
};
+class SafepointEntry;
+
+
// Code describes objects with on-the-fly generated machine code.
class Code: public HeapObject {
public:
inline byte compare_state();
inline void set_compare_state(byte value);
- // Get the safepoint entry for the given pc. Returns NULL for
- // non-safepoint pcs.
- uint8_t* GetSafepointEntry(Address pc);
+ // Get the safepoint entry for the given pc.
+ SafepointEntry GetSafepointEntry(Address pc);
// Mark this code object as not having a stack check table. Assumes kind
// is FUNCTION.
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "safepoint-table.h"
+
#include "disasm.h"
+#include "macro-assembler.h"
namespace v8 {
namespace internal {
+
+bool SafepointEntry::HasRegisters() const {
+ ASSERT(is_valid());
+ ASSERT(IsAligned(kNumSafepointRegisters, kBitsPerByte));
+ const int num_reg_bytes = kNumSafepointRegisters >> kBitsPerByteLog2;
+ for (int i = 0; i < num_reg_bytes; i++) {
+ if (bits_[i] != SafepointTable::kNoRegisters) return true;
+ }
+ return false;
+}
+
+
+bool SafepointEntry::HasRegisterAt(int reg_index) const {
+ ASSERT(is_valid());
+ ASSERT(reg_index >= 0 && reg_index < kNumSafepointRegisters);
+ int byte_index = reg_index >> kBitsPerByteLog2;
+ int bit_index = reg_index & (kBitsPerByte - 1);
+ return (bits_[byte_index] & (1 << bit_index)) != 0;
+}
+
+
SafepointTable::SafepointTable(Code* code) {
ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION);
code_ = code;
entries_ = pc_and_deoptimization_indexes_ +
(length_ * kPcAndDeoptimizationIndexSize);
ASSERT(entry_size_ > 0);
- ASSERT_EQ(DeoptimizationIndexField::max(), Safepoint::kNoDeoptimizationIndex);
+ ASSERT_EQ(SafepointEntry::DeoptimizationIndexField::max(),
+ Safepoint::kNoDeoptimizationIndex);
}
-bool SafepointTable::HasRegisters(uint8_t* entry) {
- ASSERT(IsAligned(kNumSafepointRegisters, kBitsPerByte));
- const int num_reg_bytes = kNumSafepointRegisters >> kBitsPerByteLog2;
- for (int i = 0; i < num_reg_bytes; i++) {
- if (entry[i] != kNoRegisters) return true;
+SafepointEntry SafepointTable::FindEntry(Address pc) const {
+ unsigned pc_offset = static_cast<unsigned>(pc - code_->instruction_start());
+ for (unsigned i = 0; i < length(); i++) {
+ // TODO(kasperl): Replace the linear search with binary search.
+ if (GetPcOffset(i) == pc_offset) return GetEntry(i);
}
- return false;
-}
-
-
-bool SafepointTable::HasRegisterAt(uint8_t* entry, int reg_index) {
- ASSERT(reg_index >= 0 && reg_index < kNumSafepointRegisters);
- int byte_index = reg_index >> kBitsPerByteLog2;
- int bit_index = reg_index & (kBitsPerByte - 1);
- return (entry[byte_index] & (1 << bit_index)) != 0;
+ return SafepointEntry();
}
void SafepointTable::PrintEntry(unsigned index) const {
disasm::NameConverter converter;
- uint8_t* entry = GetEntry(index);
+ SafepointEntry entry = GetEntry(index);
+ uint8_t* bits = entry.bits();
// Print the stack slot bits.
if (entry_size_ > 0) {
ASSERT(IsAligned(kNumSafepointRegisters, kBitsPerByte));
const int first = kNumSafepointRegisters >> kBitsPerByteLog2;
int last = entry_size_ - 1;
- for (int i = first; i < last; i++) PrintBits(entry[i], kBitsPerByte);
+ for (int i = first; i < last; i++) PrintBits(bits[i], kBitsPerByte);
int last_bits = code_->stack_slots() - ((last - first) * kBitsPerByte);
- PrintBits(entry[last], last_bits);
+ PrintBits(bits[last], last_bits);
// Print the registers (if any).
- if (!HasRegisters(entry)) return;
+ if (!entry.HasRegisters()) return;
for (int j = 0; j < kNumSafepointRegisters; j++) {
- if (HasRegisterAt(entry, j)) {
+ if (entry.HasRegisterAt(j)) {
PrintF(" | %s", converter.NameOfCPURegister(j));
}
}
}
+void Safepoint::DefinePointerRegister(Register reg) {
+ registers_->Add(reg.code());
+}
+
+
Safepoint SafepointTableBuilder::DefineSafepoint(Assembler* assembler,
int deoptimization_index) {
ASSERT(deoptimization_index != -1);
pc_and_deoptimization_index.pc = assembler->pc_offset();
pc_and_deoptimization_index.deoptimization_index = deoptimization_index;
pc_and_deoptimization_index.pc_after_gap = assembler->pc_offset();
+ pc_and_deoptimization_index.arguments = 0;
deoptimization_info_.Add(pc_and_deoptimization_index);
indexes_.Add(new ZoneList<int>(8));
registers_.Add(NULL);
Safepoint SafepointTableBuilder::DefineSafepointWithRegisters(
Assembler* assembler, int arguments, int deoptimization_index) {
ASSERT(deoptimization_index != -1);
- ASSERT(arguments == 0); // Only case that works for now.
+ ASSERT(arguments >= 0);
DeoptimizationInfo pc_and_deoptimization_index;
pc_and_deoptimization_index.pc = assembler->pc_offset();
pc_and_deoptimization_index.deoptimization_index = deoptimization_index;
pc_and_deoptimization_index.pc_after_gap = assembler->pc_offset();
+ pc_and_deoptimization_index.arguments = arguments;
deoptimization_info_.Add(pc_and_deoptimization_index);
indexes_.Add(new ZoneList<int>(8));
registers_.Add(new ZoneList<int>(4));
// pc after gap information.
for (int i = 0; i < length; i++) {
assembler->dd(deoptimization_info_[i].pc);
- assembler->dd(EncodeDeoptimizationIndexAndGap(deoptimization_info_[i]));
+ assembler->dd(EncodeExceptPC(deoptimization_info_[i]));
}
// Emit table of bitmaps.
}
-uint32_t SafepointTableBuilder::EncodeDeoptimizationIndexAndGap(
- DeoptimizationInfo info) {
+uint32_t SafepointTableBuilder::EncodeExceptPC(const DeoptimizationInfo& info) {
unsigned index = info.deoptimization_index;
unsigned gap_size = info.pc_after_gap - info.pc;
- uint32_t encoding = SafepointTable::DeoptimizationIndexField::encode(index);
- encoding |= SafepointTable::GapCodeSizeField::encode(gap_size);
+ uint32_t encoding = SafepointEntry::DeoptimizationIndexField::encode(index);
+ encoding |= SafepointEntry::GapCodeSizeField::encode(gap_size);
+ encoding |= SafepointEntry::ArgumentsField::encode(info.arguments);
return encoding;
}
#include "v8.h"
-#include "macro-assembler.h"
+#include "heap.h"
#include "zone.h"
#include "zone-inl.h"
namespace v8 {
namespace internal {
-class SafepointTable BASE_EMBEDDED {
+struct Register;
+
+class SafepointEntry BASE_EMBEDDED {
public:
- explicit SafepointTable(Code* code);
+ SafepointEntry() : info_(0), bits_(NULL) {}
- int size() const {
- return kHeaderSize +
- (length_ * (kPcAndDeoptimizationIndexSize + entry_size_)); }
- unsigned length() const { return length_; }
- unsigned entry_size() const { return entry_size_; }
+ SafepointEntry(unsigned info, uint8_t* bits) : info_(info), bits_(bits) {
+ ASSERT(is_valid());
+ }
- unsigned GetPcOffset(unsigned index) const {
- ASSERT(index < length_);
- return Memory::uint32_at(GetPcOffsetLocation(index));
+ bool is_valid() const { return bits_ != NULL; }
+
+ bool Equals(const SafepointEntry& other) const {
+ return info_ == other.info_ && bits_ == other.bits_;
}
- int GetDeoptimizationIndex(unsigned index) const {
- ASSERT(index < length_);
- unsigned value = Memory::uint32_at(GetDeoptimizationLocation(index));
- return DeoptimizationIndexField::decode(value);
+ void Reset() {
+ info_ = 0;
+ bits_ = NULL;
}
- unsigned GetGapCodeSize(unsigned index) const {
- ASSERT(index < length_);
- unsigned value = Memory::uint32_at(GetDeoptimizationLocation(index));
- return GapCodeSizeField::decode(value);
+ int deoptimization_index() const {
+ ASSERT(is_valid());
+ return DeoptimizationIndexField::decode(info_);
}
- uint8_t* GetEntry(unsigned index) const {
- ASSERT(index < length_);
- return &Memory::uint8_at(entries_ + (index * entry_size_));
+ int gap_code_size() const {
+ ASSERT(is_valid());
+ return GapCodeSizeField::decode(info_);
}
+ int argument_count() const {
+ ASSERT(is_valid());
+ return ArgumentsField::decode(info_);
+ }
+
+ uint8_t* bits() {
+ ASSERT(is_valid());
+ return bits_;
+ }
+
+ bool HasRegisters() const;
+ bool HasRegisterAt(int reg_index) const;
+
// Reserve 13 bits for the gap code size. On ARM a constant pool can be
// emitted when generating the gap code. The size of the const pool is less
// than what can be represented in 12 bits, so 13 bits gives room for having
// instructions before potentially emitting a constant pool.
static const int kGapCodeSizeBits = 13;
- static const int kDeoptIndexBits = 32 - kGapCodeSizeBits;
+ static const int kArgumentsFieldBits = 3;
+ static const int kDeoptIndexBits =
+ 32 - kGapCodeSizeBits - kArgumentsFieldBits;
class GapCodeSizeField: public BitField<unsigned, 0, kGapCodeSizeBits> {};
- class DeoptimizationIndexField: public BitField<int, kGapCodeSizeBits, kDeoptIndexBits> {}; // NOLINT
+ class DeoptimizationIndexField: public BitField<int,
+ kGapCodeSizeBits,
+ kDeoptIndexBits> {}; // NOLINT
+ class ArgumentsField: public BitField<unsigned,
+ kGapCodeSizeBits + kDeoptIndexBits,
+ kArgumentsFieldBits> {}; // NOLINT
+ private:
+ unsigned info_;
+ uint8_t* bits_;
+};
+
+
+class SafepointTable BASE_EMBEDDED {
+ public:
+ explicit SafepointTable(Code* code);
- static bool HasRegisters(uint8_t* entry);
- static bool HasRegisterAt(uint8_t* entry, int reg_index);
+ int size() const {
+ return kHeaderSize +
+ (length_ * (kPcAndDeoptimizationIndexSize + entry_size_)); }
+ unsigned length() const { return length_; }
+ unsigned entry_size() const { return entry_size_; }
+
+ unsigned GetPcOffset(unsigned index) const {
+ ASSERT(index < length_);
+ return Memory::uint32_at(GetPcOffsetLocation(index));
+ }
+
+ SafepointEntry GetEntry(unsigned index) const {
+ ASSERT(index < length_);
+ unsigned info = Memory::uint32_at(GetInfoLocation(index));
+ uint8_t* bits = &Memory::uint8_at(entries_ + (index * entry_size_));
+ return SafepointEntry(info, bits);
+ }
+
+ // Returns the entry for the given pc.
+ SafepointEntry FindEntry(Address pc) const;
void PrintEntry(unsigned index) const;
(index * kPcAndDeoptimizationIndexSize);
}
- Address GetDeoptimizationLocation(unsigned index) const {
+ Address GetInfoLocation(unsigned index) const {
return GetPcOffsetLocation(index) + kPcSize;
}
Address entries_;
friend class SafepointTableBuilder;
+ friend class SafepointEntry;
+
+ DISALLOW_COPY_AND_ASSIGN(SafepointTable);
};
class Safepoint BASE_EMBEDDED {
public:
static const int kNoDeoptimizationIndex =
- (1 << (SafepointTable::kDeoptIndexBits)) - 1;
+ (1 << (SafepointEntry::kDeoptIndexBits)) - 1;
void DefinePointerSlot(int index) { indexes_->Add(index); }
- void DefinePointerRegister(Register reg) { registers_->Add(reg.code()); }
+ void DefinePointerRegister(Register reg);
private:
Safepoint(ZoneList<int>* indexes, ZoneList<int>* registers) :
unsigned pc;
unsigned deoptimization_index;
unsigned pc_after_gap;
+ unsigned arguments;
};
- uint32_t EncodeDeoptimizationIndexAndGap(DeoptimizationInfo info);
+ uint32_t EncodeExceptPC(const DeoptimizationInfo& info);
ZoneList<DeoptimizationInfo> deoptimization_info_;
ZoneList<ZoneList<int>*> indexes_;