| Index: src/safepoint-table.h
|
| ===================================================================
|
| --- src/safepoint-table.h (revision 6800)
|
| +++ src/safepoint-table.h (working copy)
|
| @@ -1,4 +1,4 @@
|
| -// Copyright 2010 the V8 project authors. All rights reserved.
|
| +// Copyright 2011 the V8 project authors. All rights reserved.
|
| // Redistribution and use in source and binary forms, with or without
|
| // modification, are permitted provided that the following conditions are
|
| // met:
|
| @@ -30,13 +30,89 @@
|
|
|
| #include "v8.h"
|
|
|
| -#include "macro-assembler.h"
|
| +#include "heap.h"
|
| #include "zone.h"
|
| #include "zone-inl.h"
|
|
|
| namespace v8 {
|
| namespace internal {
|
|
|
| +struct Register;
|
| +
|
| +class SafepointEntry BASE_EMBEDDED {
|
| + public:
|
| + SafepointEntry() : info_(0), bits_(NULL) {}
|
| +
|
| + SafepointEntry(unsigned info, uint8_t* bits) : info_(info), bits_(bits) {
|
| + ASSERT(is_valid());
|
| + }
|
| +
|
| + bool is_valid() const { return bits_ != NULL; }
|
| +
|
| + bool Equals(const SafepointEntry& other) const {
|
| + return info_ == other.info_ && bits_ == other.bits_;
|
| + }
|
| +
|
| + void Reset() {
|
| + info_ = 0;
|
| + bits_ = NULL;
|
| + }
|
| +
|
| + int deoptimization_index() const {
|
| + ASSERT(is_valid());
|
| + return DeoptimizationIndexField::decode(info_);
|
| + }
|
| +
|
| + int gap_code_size() const {
|
| + ASSERT(is_valid());
|
| + return GapCodeSizeField::decode(info_);
|
| + }
|
| +
|
| + int argument_count() const {
|
| + ASSERT(is_valid());
|
| + return ArgumentsField::decode(info_);
|
| + }
|
| +
|
| + bool has_doubles() const {
|
| + ASSERT(is_valid());
|
| + return SaveDoublesField::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 kArgumentsFieldBits = 3;
|
| + static const int kSaveDoublesFieldBits = 1;
|
| + static const int kDeoptIndexBits =
|
| + 32 - kGapCodeSizeBits - kArgumentsFieldBits - kSaveDoublesFieldBits;
|
| + class GapCodeSizeField: public BitField<unsigned, 0, kGapCodeSizeBits> {};
|
| + class DeoptimizationIndexField: public BitField<int,
|
| + kGapCodeSizeBits,
|
| + kDeoptIndexBits> {}; // NOLINT
|
| + class ArgumentsField: public BitField<unsigned,
|
| + kGapCodeSizeBits + kDeoptIndexBits,
|
| + kArgumentsFieldBits> {}; // NOLINT
|
| + class SaveDoublesField: public BitField<bool,
|
| + kGapCodeSizeBits + kDeoptIndexBits +
|
| + kArgumentsFieldBits,
|
| + kSaveDoublesFieldBits> { }; // NOLINT
|
| +
|
| + private:
|
| + unsigned info_;
|
| + uint8_t* bits_;
|
| +};
|
| +
|
| +
|
| class SafepointTable BASE_EMBEDDED {
|
| public:
|
| explicit SafepointTable(Code* code);
|
| @@ -52,29 +128,16 @@
|
| return Memory::uint32_at(GetPcOffsetLocation(index));
|
| }
|
|
|
| - int GetDeoptimizationIndex(unsigned index) const {
|
| + SafepointEntry GetEntry(unsigned index) const {
|
| ASSERT(index < length_);
|
| - unsigned value = Memory::uint32_at(GetDeoptimizationLocation(index));
|
| - return DeoptimizationIndexField::decode(value);
|
| + unsigned info = Memory::uint32_at(GetInfoLocation(index));
|
| + uint8_t* bits = &Memory::uint8_at(entries_ + (index * entry_size_));
|
| + return SafepointEntry(info, bits);
|
| }
|
|
|
| - unsigned GetGapCodeSize(unsigned index) const {
|
| - ASSERT(index < length_);
|
| - unsigned value = Memory::uint32_at(GetDeoptimizationLocation(index));
|
| - return GapCodeSizeField::decode(value);
|
| - }
|
| + // Returns the entry for the given pc.
|
| + SafepointEntry FindEntry(Address pc) const;
|
|
|
| - uint8_t* GetEntry(unsigned index) const {
|
| - ASSERT(index < length_);
|
| - return &Memory::uint8_at(entries_ + (index * entry_size_));
|
| - }
|
| -
|
| - class GapCodeSizeField: public BitField<unsigned, 0, 8> {};
|
| - class DeoptimizationIndexField: public BitField<int, 8, 24> {};
|
| -
|
| - static bool HasRegisters(uint8_t* entry);
|
| - static bool HasRegisterAt(uint8_t* entry, int reg_index);
|
| -
|
| void PrintEntry(unsigned index) const;
|
|
|
| private:
|
| @@ -94,7 +157,7 @@
|
| (index * kPcAndDeoptimizationIndexSize);
|
| }
|
|
|
| - Address GetDeoptimizationLocation(unsigned index) const {
|
| + Address GetInfoLocation(unsigned index) const {
|
| return GetPcOffsetLocation(index) + kPcSize;
|
| }
|
|
|
| @@ -109,15 +172,26 @@
|
| Address entries_;
|
|
|
| friend class SafepointTableBuilder;
|
| + friend class SafepointEntry;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(SafepointTable);
|
| };
|
|
|
|
|
| class Safepoint BASE_EMBEDDED {
|
| public:
|
| - static const int kNoDeoptimizationIndex = 0x00ffffff;
|
| + typedef enum {
|
| + kSimple = 0,
|
| + kWithRegisters = 1 << 0,
|
| + kWithDoubles = 1 << 1,
|
| + kWithRegistersAndDoubles = kWithRegisters | kWithDoubles
|
| + } Kind;
|
|
|
| + static const int kNoDeoptimizationIndex =
|
| + (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) :
|
| @@ -141,20 +215,13 @@
|
| unsigned GetCodeOffset() const;
|
|
|
| // Define a new safepoint for the current position in the body.
|
| - Safepoint DefineSafepoint(
|
| - Assembler* assembler,
|
| - int deoptimization_index = Safepoint::kNoDeoptimizationIndex);
|
| + Safepoint DefineSafepoint(Assembler* assembler,
|
| + Safepoint::Kind kind,
|
| + int arguments,
|
| + int deoptimization_index);
|
|
|
| - // Define a new safepoint with registers on the stack for the
|
| - // current position in the body and take the number of arguments on
|
| - // top of the registers into account.
|
| - Safepoint DefineSafepointWithRegisters(
|
| - Assembler* assembler,
|
| - int arguments,
|
| - int deoptimization_index = Safepoint::kNoDeoptimizationIndex);
|
| -
|
| - // Update the last safepoint with the size of the code generated for the gap
|
| - // following it.
|
| + // Update the last safepoint with the size of the code generated until the
|
| + // end of the gap following it.
|
| void SetPcAfterGap(int pc) {
|
| ASSERT(!deoptimization_info_.is_empty());
|
| int index = deoptimization_info_.length() - 1;
|
| @@ -165,21 +232,28 @@
|
| // entry must be enough to hold all the pointer indexes.
|
| void Emit(Assembler* assembler, int bits_per_entry);
|
|
|
| + // Count the number of deoptimization points where the next
|
| + // following deoptimization point comes less than limit bytes
|
| + // after the end of this point's gap.
|
| + int CountShortDeoptimizationIntervals(unsigned limit);
|
| +
|
| private:
|
| struct DeoptimizationInfo {
|
| unsigned pc;
|
| unsigned deoptimization_index;
|
| unsigned pc_after_gap;
|
| + unsigned arguments;
|
| + bool has_doubles;
|
| };
|
|
|
| - uint32_t EncodeDeoptimizationIndexAndGap(DeoptimizationInfo info);
|
| + uint32_t EncodeExceptPC(const DeoptimizationInfo& info);
|
|
|
| ZoneList<DeoptimizationInfo> deoptimization_info_;
|
| ZoneList<ZoneList<int>*> indexes_;
|
| ZoneList<ZoneList<int>*> registers_;
|
|
|
| + unsigned offset_;
|
| bool emitted_;
|
| - unsigned offset_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(SafepointTableBuilder);
|
| };
|
|
|