Commit e2f8c938 authored by vitalyr@chromium.org's avatar vitalyr@chromium.org

Allow arguments in safepoints with registers.

This should enable calling runtime functions with arguments from
deferred lithium code.

Review URL: http://codereview.chromium.org/6125007

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6285 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 855ffcd1
...@@ -55,8 +55,9 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) { ...@@ -55,8 +55,9 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
SafepointTable table(function->code()); SafepointTable table(function->code());
for (unsigned i = 0; i < table.length(); i++) { for (unsigned i = 0; i < table.length(); i++) {
unsigned pc_offset = table.GetPcOffset(i); unsigned pc_offset = table.GetPcOffset(i);
int deoptimization_index = table.GetDeoptimizationIndex(i); SafepointEntry safepoint_entry = table.GetEntry(i);
int gap_code_size = table.GetGapCodeSize(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. // Check that we did not shoot past next safepoint.
// TODO(srdjan): How do we guarantee that safepoint code does not // TODO(srdjan): How do we guarantee that safepoint code does not
// overlap other safepoint patching code? // overlap other safepoint patching code?
......
...@@ -329,21 +329,20 @@ void SafeStackTraceFrameIterator::Advance() { ...@@ -329,21 +329,20 @@ void SafeStackTraceFrameIterator::Advance() {
Code* StackFrame::GetSafepointData(Address pc, Code* StackFrame::GetSafepointData(Address pc,
uint8_t** safepoint_entry, SafepointEntry* safepoint_entry,
unsigned* stack_slots) { unsigned* stack_slots) {
PcToCodeCache::PcToCodeCacheEntry* entry = PcToCodeCache::GetCacheEntry(pc); PcToCodeCache::PcToCodeCacheEntry* entry = PcToCodeCache::GetCacheEntry(pc);
uint8_t* cached_safepoint_entry = entry->safepoint_entry; SafepointEntry cached_safepoint_entry = entry->safepoint_entry;
if (cached_safepoint_entry == NULL) { if (!entry->safepoint_entry.is_valid()) {
cached_safepoint_entry = entry->code->GetSafepointEntry(pc); entry->safepoint_entry = entry->code->GetSafepointEntry(pc);
ASSERT(cached_safepoint_entry != NULL); // No safepoint found. ASSERT(entry->safepoint_entry.is_valid());
entry->safepoint_entry = cached_safepoint_entry;
} else { } 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. // Fill in the results and return the code.
Code* code = entry->code; Code* code = entry->code;
*safepoint_entry = cached_safepoint_entry; *safepoint_entry = entry->safepoint_entry;
*stack_slots = code->stack_slots(); *stack_slots = code->stack_slots();
return code; return code;
} }
...@@ -536,7 +535,7 @@ void OptimizedFrame::Iterate(ObjectVisitor* v) const { ...@@ -536,7 +535,7 @@ void OptimizedFrame::Iterate(ObjectVisitor* v) const {
// Compute the safepoint information. // Compute the safepoint information.
unsigned stack_slots = 0; unsigned stack_slots = 0;
uint8_t* safepoint_entry = NULL; SafepointEntry safepoint_entry;
Code* code = StackFrame::GetSafepointData( Code* code = StackFrame::GetSafepointData(
pc(), &safepoint_entry, &stack_slots); pc(), &safepoint_entry, &stack_slots);
unsigned slot_space = stack_slots * kPointerSize; unsigned slot_space = stack_slots * kPointerSize;
...@@ -548,10 +547,17 @@ void OptimizedFrame::Iterate(ObjectVisitor* v) const { ...@@ -548,10 +547,17 @@ void OptimizedFrame::Iterate(ObjectVisitor* v) const {
Object** parameters_limit = &Memory::Object_at( Object** parameters_limit = &Memory::Object_at(
fp() + JavaScriptFrameConstants::kFunctionOffset - slot_space); 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. // 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--) { 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); int reg_stack_index = MacroAssembler::SafepointRegisterStackIndex(i);
v->VisitPointer(parameters_base + reg_stack_index); v->VisitPointer(parameters_base + reg_stack_index);
} }
...@@ -561,7 +567,8 @@ void OptimizedFrame::Iterate(ObjectVisitor* v) const { ...@@ -561,7 +567,8 @@ void OptimizedFrame::Iterate(ObjectVisitor* v) const {
} }
// We're done dealing with the register bits. // 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. // Visit the rest of the parameters.
v->VisitPointers(parameters_base, parameters_limit); v->VisitPointers(parameters_base, parameters_limit);
...@@ -570,7 +577,7 @@ void OptimizedFrame::Iterate(ObjectVisitor* v) const { ...@@ -570,7 +577,7 @@ void OptimizedFrame::Iterate(ObjectVisitor* v) const {
for (unsigned index = 0; index < stack_slots; index++) { for (unsigned index = 0; index < stack_slots; index++) {
int byte_index = index >> kBitsPerByteLog2; int byte_index = index >> kBitsPerByteLog2;
int bit_index = index & (kBitsPerByte - 1); 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); v->VisitPointer(parameters_limit + index);
} }
} }
...@@ -778,14 +785,8 @@ DeoptimizationInputData* OptimizedFrame::GetDeoptimizationData( ...@@ -778,14 +785,8 @@ DeoptimizationInputData* OptimizedFrame::GetDeoptimizationData(
ASSERT(code != NULL); ASSERT(code != NULL);
ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION); ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION);
SafepointTable table(code); SafepointEntry safepoint_entry = code->GetSafepointEntry(pc());
unsigned pc_offset = static_cast<unsigned>(pc() - code->instruction_start()); *deopt_index = safepoint_entry.deoptimization_index();
for (unsigned i = 0; i < table.length(); i++) {
if (table.GetPcOffset(i) == pc_offset) {
*deopt_index = table.GetDeoptimizationIndex(i);
break;
}
}
ASSERT(*deopt_index != AstNode::kNoNumber); ASSERT(*deopt_index != AstNode::kNoNumber);
return DeoptimizationInputData::cast(code->deoptimization_data()); return DeoptimizationInputData::cast(code->deoptimization_data());
...@@ -1150,7 +1151,7 @@ PcToCodeCache::PcToCodeCacheEntry* PcToCodeCache::GetCacheEntry(Address pc) { ...@@ -1150,7 +1151,7 @@ PcToCodeCache::PcToCodeCacheEntry* PcToCodeCache::GetCacheEntry(Address pc) {
// been set. Otherwise, we risk trying to use a cache entry before // been set. Otherwise, we risk trying to use a cache entry before
// the code has been computed. // the code has been computed.
entry->code = GcSafeFindCodeForPc(pc); entry->code = GcSafeFindCodeForPc(pc);
entry->safepoint_entry = NULL; entry->safepoint_entry.Reset();
entry->pc = pc; entry->pc = pc;
} }
return entry; return entry;
......
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
#ifndef V8_FRAMES_H_ #ifndef V8_FRAMES_H_
#define V8_FRAMES_H_ #define V8_FRAMES_H_
#include "safepoint-table.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -51,7 +53,7 @@ class PcToCodeCache : AllStatic { ...@@ -51,7 +53,7 @@ class PcToCodeCache : AllStatic {
struct PcToCodeCacheEntry { struct PcToCodeCacheEntry {
Address pc; Address pc;
Code* code; Code* code;
uint8_t* safepoint_entry; SafepointEntry safepoint_entry;
}; };
static PcToCodeCacheEntry* cache(int index) { static PcToCodeCacheEntry* cache(int index) {
...@@ -208,7 +210,7 @@ class StackFrame BASE_EMBEDDED { ...@@ -208,7 +210,7 @@ class StackFrame BASE_EMBEDDED {
// safepoint entry and the number of stack slots. The pc must be at // safepoint entry and the number of stack slots. The pc must be at
// a safepoint. // a safepoint.
static Code* GetSafepointData(Address pc, static Code* GetSafepointData(Address pc,
uint8_t** safepoint_entry, SafepointEntry* safepoint_entry,
unsigned* stack_slots); unsigned* stack_slots);
virtual void Iterate(ObjectVisitor* v) const = 0; virtual void Iterate(ObjectVisitor* v) const = 0;
......
...@@ -56,8 +56,9 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) { ...@@ -56,8 +56,9 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
SafepointTable table(function->code()); SafepointTable table(function->code());
for (unsigned i = 0; i < table.length(); i++) { for (unsigned i = 0; i < table.length(); i++) {
unsigned pc_offset = table.GetPcOffset(i); unsigned pc_offset = table.GetPcOffset(i);
int deoptimization_index = table.GetDeoptimizationIndex(i); SafepointEntry safepoint_entry = table.GetEntry(i);
int gap_code_size = table.GetGapCodeSize(i); int deoptimization_index = safepoint_entry.deoptimization_index();
int gap_code_size = safepoint_entry.gap_code_size();
#ifdef DEBUG #ifdef DEBUG
// Destroy the code which is not supposed to run again. // Destroy the code which is not supposed to run again.
unsigned instructions = pc_offset - last_pc_offset; unsigned instructions = pc_offset - last_pc_offset;
......
...@@ -5987,14 +5987,9 @@ int Code::SourceStatementPosition(Address pc) { ...@@ -5987,14 +5987,9 @@ int Code::SourceStatementPosition(Address pc) {
} }
uint8_t* Code::GetSafepointEntry(Address pc) { SafepointEntry Code::GetSafepointEntry(Address pc) {
SafepointTable table(this); SafepointTable table(this);
unsigned pc_offset = static_cast<unsigned>(pc - instruction_start()); return table.FindEntry(pc);
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;
} }
...@@ -6265,12 +6260,15 @@ void Code::Disassemble(const char* name, FILE* out) { ...@@ -6265,12 +6260,15 @@ void Code::Disassemble(const char* name, FILE* out) {
PrintF(out, "%p %4d ", (instruction_start() + pc_offset), pc_offset); PrintF(out, "%p %4d ", (instruction_start() + pc_offset), pc_offset);
table.PrintEntry(i); table.PrintEntry(i);
PrintF(out, " (sp -> fp)"); PrintF(out, " (sp -> fp)");
int deoptimization_index = table.GetDeoptimizationIndex(i); SafepointEntry entry = table.GetEntry(i);
if (deoptimization_index != Safepoint::kNoDeoptimizationIndex) { if (entry.deoptimization_index() != Safepoint::kNoDeoptimizationIndex) {
PrintF(out, " %6d", deoptimization_index); PrintF(out, " %6d", entry.deoptimization_index());
} else { } else {
PrintF(out, " <none>"); PrintF(out, " <none>");
} }
if (entry.argument_count() > 0) {
PrintF(out, " argc: %d", entry.argument_count());
}
PrintF(out, "\n"); PrintF(out, "\n");
} }
PrintF(out, "\n"); PrintF(out, "\n");
......
...@@ -3121,6 +3121,9 @@ class DeoptimizationOutputData: public FixedArray { ...@@ -3121,6 +3121,9 @@ class DeoptimizationOutputData: public FixedArray {
}; };
class SafepointEntry;
// Code describes objects with on-the-fly generated machine code. // Code describes objects with on-the-fly generated machine code.
class Code: public HeapObject { class Code: public HeapObject {
public: public:
...@@ -3268,9 +3271,8 @@ class Code: public HeapObject { ...@@ -3268,9 +3271,8 @@ class Code: public HeapObject {
inline byte compare_state(); inline byte compare_state();
inline void set_compare_state(byte value); inline void set_compare_state(byte value);
// Get the safepoint entry for the given pc. Returns NULL for // Get the safepoint entry for the given pc.
// non-safepoint pcs. SafepointEntry GetSafepointEntry(Address pc);
uint8_t* GetSafepointEntry(Address pc);
// Mark this code object as not having a stack check table. Assumes kind // Mark this code object as not having a stack check table. Assumes kind
// is FUNCTION. // is FUNCTION.
......
...@@ -26,11 +26,34 @@ ...@@ -26,11 +26,34 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "safepoint-table.h" #include "safepoint-table.h"
#include "disasm.h" #include "disasm.h"
#include "macro-assembler.h"
namespace v8 { namespace v8 {
namespace internal { 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) { SafepointTable::SafepointTable(Code* code) {
ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION); ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION);
code_ = code; code_ = code;
...@@ -41,45 +64,39 @@ SafepointTable::SafepointTable(Code* code) { ...@@ -41,45 +64,39 @@ SafepointTable::SafepointTable(Code* code) {
entries_ = pc_and_deoptimization_indexes_ + entries_ = pc_and_deoptimization_indexes_ +
(length_ * kPcAndDeoptimizationIndexSize); (length_ * kPcAndDeoptimizationIndexSize);
ASSERT(entry_size_ > 0); ASSERT(entry_size_ > 0);
ASSERT_EQ(DeoptimizationIndexField::max(), Safepoint::kNoDeoptimizationIndex); ASSERT_EQ(SafepointEntry::DeoptimizationIndexField::max(),
Safepoint::kNoDeoptimizationIndex);
} }
bool SafepointTable::HasRegisters(uint8_t* entry) { SafepointEntry SafepointTable::FindEntry(Address pc) const {
ASSERT(IsAligned(kNumSafepointRegisters, kBitsPerByte)); unsigned pc_offset = static_cast<unsigned>(pc - code_->instruction_start());
const int num_reg_bytes = kNumSafepointRegisters >> kBitsPerByteLog2; for (unsigned i = 0; i < length(); i++) {
for (int i = 0; i < num_reg_bytes; i++) { // TODO(kasperl): Replace the linear search with binary search.
if (entry[i] != kNoRegisters) return true; if (GetPcOffset(i) == pc_offset) return GetEntry(i);
} }
return false; return SafepointEntry();
}
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;
} }
void SafepointTable::PrintEntry(unsigned index) const { void SafepointTable::PrintEntry(unsigned index) const {
disasm::NameConverter converter; disasm::NameConverter converter;
uint8_t* entry = GetEntry(index); SafepointEntry entry = GetEntry(index);
uint8_t* bits = entry.bits();
// Print the stack slot bits. // Print the stack slot bits.
if (entry_size_ > 0) { if (entry_size_ > 0) {
ASSERT(IsAligned(kNumSafepointRegisters, kBitsPerByte)); ASSERT(IsAligned(kNumSafepointRegisters, kBitsPerByte));
const int first = kNumSafepointRegisters >> kBitsPerByteLog2; const int first = kNumSafepointRegisters >> kBitsPerByteLog2;
int last = entry_size_ - 1; 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); int last_bits = code_->stack_slots() - ((last - first) * kBitsPerByte);
PrintBits(entry[last], last_bits); PrintBits(bits[last], last_bits);
// Print the registers (if any). // Print the registers (if any).
if (!HasRegisters(entry)) return; if (!entry.HasRegisters()) return;
for (int j = 0; j < kNumSafepointRegisters; j++) { for (int j = 0; j < kNumSafepointRegisters; j++) {
if (HasRegisterAt(entry, j)) { if (entry.HasRegisterAt(j)) {
PrintF(" | %s", converter.NameOfCPURegister(j)); PrintF(" | %s", converter.NameOfCPURegister(j));
} }
} }
...@@ -95,6 +112,11 @@ void SafepointTable::PrintBits(uint8_t byte, int digits) { ...@@ -95,6 +112,11 @@ void SafepointTable::PrintBits(uint8_t byte, int digits) {
} }
void Safepoint::DefinePointerRegister(Register reg) {
registers_->Add(reg.code());
}
Safepoint SafepointTableBuilder::DefineSafepoint(Assembler* assembler, Safepoint SafepointTableBuilder::DefineSafepoint(Assembler* assembler,
int deoptimization_index) { int deoptimization_index) {
ASSERT(deoptimization_index != -1); ASSERT(deoptimization_index != -1);
...@@ -102,6 +124,7 @@ Safepoint SafepointTableBuilder::DefineSafepoint(Assembler* assembler, ...@@ -102,6 +124,7 @@ Safepoint SafepointTableBuilder::DefineSafepoint(Assembler* assembler,
pc_and_deoptimization_index.pc = assembler->pc_offset(); pc_and_deoptimization_index.pc = assembler->pc_offset();
pc_and_deoptimization_index.deoptimization_index = deoptimization_index; pc_and_deoptimization_index.deoptimization_index = deoptimization_index;
pc_and_deoptimization_index.pc_after_gap = assembler->pc_offset(); pc_and_deoptimization_index.pc_after_gap = assembler->pc_offset();
pc_and_deoptimization_index.arguments = 0;
deoptimization_info_.Add(pc_and_deoptimization_index); deoptimization_info_.Add(pc_and_deoptimization_index);
indexes_.Add(new ZoneList<int>(8)); indexes_.Add(new ZoneList<int>(8));
registers_.Add(NULL); registers_.Add(NULL);
...@@ -112,11 +135,12 @@ Safepoint SafepointTableBuilder::DefineSafepoint(Assembler* assembler, ...@@ -112,11 +135,12 @@ Safepoint SafepointTableBuilder::DefineSafepoint(Assembler* assembler,
Safepoint SafepointTableBuilder::DefineSafepointWithRegisters( Safepoint SafepointTableBuilder::DefineSafepointWithRegisters(
Assembler* assembler, int arguments, int deoptimization_index) { Assembler* assembler, int arguments, int deoptimization_index) {
ASSERT(deoptimization_index != -1); ASSERT(deoptimization_index != -1);
ASSERT(arguments == 0); // Only case that works for now. ASSERT(arguments >= 0);
DeoptimizationInfo pc_and_deoptimization_index; DeoptimizationInfo pc_and_deoptimization_index;
pc_and_deoptimization_index.pc = assembler->pc_offset(); pc_and_deoptimization_index.pc = assembler->pc_offset();
pc_and_deoptimization_index.deoptimization_index = deoptimization_index; pc_and_deoptimization_index.deoptimization_index = deoptimization_index;
pc_and_deoptimization_index.pc_after_gap = assembler->pc_offset(); pc_and_deoptimization_index.pc_after_gap = assembler->pc_offset();
pc_and_deoptimization_index.arguments = arguments;
deoptimization_info_.Add(pc_and_deoptimization_index); deoptimization_info_.Add(pc_and_deoptimization_index);
indexes_.Add(new ZoneList<int>(8)); indexes_.Add(new ZoneList<int>(8));
registers_.Add(new ZoneList<int>(4)); registers_.Add(new ZoneList<int>(4));
...@@ -152,7 +176,7 @@ void SafepointTableBuilder::Emit(Assembler* assembler, int bits_per_entry) { ...@@ -152,7 +176,7 @@ void SafepointTableBuilder::Emit(Assembler* assembler, int bits_per_entry) {
// pc after gap information. // pc after gap information.
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
assembler->dd(deoptimization_info_[i].pc); assembler->dd(deoptimization_info_[i].pc);
assembler->dd(EncodeDeoptimizationIndexAndGap(deoptimization_info_[i])); assembler->dd(EncodeExceptPC(deoptimization_info_[i]));
} }
// Emit table of bitmaps. // Emit table of bitmaps.
...@@ -197,12 +221,12 @@ void SafepointTableBuilder::Emit(Assembler* assembler, int bits_per_entry) { ...@@ -197,12 +221,12 @@ void SafepointTableBuilder::Emit(Assembler* assembler, int bits_per_entry) {
} }
uint32_t SafepointTableBuilder::EncodeDeoptimizationIndexAndGap( uint32_t SafepointTableBuilder::EncodeExceptPC(const DeoptimizationInfo& info) {
DeoptimizationInfo info) {
unsigned index = info.deoptimization_index; unsigned index = info.deoptimization_index;
unsigned gap_size = info.pc_after_gap - info.pc; unsigned gap_size = info.pc_after_gap - info.pc;
uint32_t encoding = SafepointTable::DeoptimizationIndexField::encode(index); uint32_t encoding = SafepointEntry::DeoptimizationIndexField::encode(index);
encoding |= SafepointTable::GapCodeSizeField::encode(gap_size); encoding |= SafepointEntry::GapCodeSizeField::encode(gap_size);
encoding |= SafepointEntry::ArgumentsField::encode(info.arguments);
return encoding; return encoding;
} }
......
...@@ -30,56 +30,102 @@ ...@@ -30,56 +30,102 @@
#include "v8.h" #include "v8.h"
#include "macro-assembler.h" #include "heap.h"
#include "zone.h" #include "zone.h"
#include "zone-inl.h" #include "zone-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
class SafepointTable BASE_EMBEDDED { struct Register;
class SafepointEntry BASE_EMBEDDED {
public: public:
explicit SafepointTable(Code* code); SafepointEntry() : info_(0), bits_(NULL) {}
int size() const { SafepointEntry(unsigned info, uint8_t* bits) : info_(info), bits_(bits) {
return kHeaderSize + ASSERT(is_valid());
(length_ * (kPcAndDeoptimizationIndexSize + entry_size_)); } }
unsigned length() const { return length_; }
unsigned entry_size() const { return entry_size_; }
unsigned GetPcOffset(unsigned index) const { bool is_valid() const { return bits_ != NULL; }
ASSERT(index < length_);
return Memory::uint32_at(GetPcOffsetLocation(index)); bool Equals(const SafepointEntry& other) const {
return info_ == other.info_ && bits_ == other.bits_;
} }
int GetDeoptimizationIndex(unsigned index) const { void Reset() {
ASSERT(index < length_); info_ = 0;
unsigned value = Memory::uint32_at(GetDeoptimizationLocation(index)); bits_ = NULL;
return DeoptimizationIndexField::decode(value);
} }
unsigned GetGapCodeSize(unsigned index) const { int deoptimization_index() const {
ASSERT(index < length_); ASSERT(is_valid());
unsigned value = Memory::uint32_at(GetDeoptimizationLocation(index)); return DeoptimizationIndexField::decode(info_);
return GapCodeSizeField::decode(value);
} }
uint8_t* GetEntry(unsigned index) const { int gap_code_size() const {
ASSERT(index < length_); ASSERT(is_valid());
return &Memory::uint8_at(entries_ + (index * entry_size_)); 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 // 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 // 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 // than what can be represented in 12 bits, so 13 bits gives room for having
// instructions before potentially emitting a constant pool. // instructions before potentially emitting a constant pool.
static const int kGapCodeSizeBits = 13; 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 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); int size() const {
static bool HasRegisterAt(uint8_t* entry, int reg_index); 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; void PrintEntry(unsigned index) const;
...@@ -100,7 +146,7 @@ class SafepointTable BASE_EMBEDDED { ...@@ -100,7 +146,7 @@ class SafepointTable BASE_EMBEDDED {
(index * kPcAndDeoptimizationIndexSize); (index * kPcAndDeoptimizationIndexSize);
} }
Address GetDeoptimizationLocation(unsigned index) const { Address GetInfoLocation(unsigned index) const {
return GetPcOffsetLocation(index) + kPcSize; return GetPcOffsetLocation(index) + kPcSize;
} }
...@@ -115,16 +161,19 @@ class SafepointTable BASE_EMBEDDED { ...@@ -115,16 +161,19 @@ class SafepointTable BASE_EMBEDDED {
Address entries_; Address entries_;
friend class SafepointTableBuilder; friend class SafepointTableBuilder;
friend class SafepointEntry;
DISALLOW_COPY_AND_ASSIGN(SafepointTable);
}; };
class Safepoint BASE_EMBEDDED { class Safepoint BASE_EMBEDDED {
public: public:
static const int kNoDeoptimizationIndex = static const int kNoDeoptimizationIndex =
(1 << (SafepointTable::kDeoptIndexBits)) - 1; (1 << (SafepointEntry::kDeoptIndexBits)) - 1;
void DefinePointerSlot(int index) { indexes_->Add(index); } void DefinePointerSlot(int index) { indexes_->Add(index); }
void DefinePointerRegister(Register reg) { registers_->Add(reg.code()); } void DefinePointerRegister(Register reg);
private: private:
Safepoint(ZoneList<int>* indexes, ZoneList<int>* registers) : Safepoint(ZoneList<int>* indexes, ZoneList<int>* registers) :
...@@ -177,9 +226,10 @@ class SafepointTableBuilder BASE_EMBEDDED { ...@@ -177,9 +226,10 @@ class SafepointTableBuilder BASE_EMBEDDED {
unsigned pc; unsigned pc;
unsigned deoptimization_index; unsigned deoptimization_index;
unsigned pc_after_gap; unsigned pc_after_gap;
unsigned arguments;
}; };
uint32_t EncodeDeoptimizationIndexAndGap(DeoptimizationInfo info); uint32_t EncodeExceptPC(const DeoptimizationInfo& info);
ZoneList<DeoptimizationInfo> deoptimization_info_; ZoneList<DeoptimizationInfo> deoptimization_info_;
ZoneList<ZoneList<int>*> indexes_; ZoneList<ZoneList<int>*> indexes_;
......
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