int length = deoptimizations_.length();
if (length == 0) return;
Handle<DeoptimizationInputData> data =
- DeoptimizationInputData::New(isolate(), length, 0, TENURED);
+ DeoptimizationInputData::New(isolate(), length, TENURED);
Handle<ByteArray> translations =
translations_.CreateByteArray(isolate()->factory());
if (length == 0) return;
Handle<DeoptimizationInputData> data =
- DeoptimizationInputData::New(isolate(), length, 0, TENURED);
+ DeoptimizationInputData::New(isolate(), length, TENURED);
Handle<ByteArray> translations =
translations_.CreateByteArray(isolate()->factory());
FinishCode(masm());
+ UpdateSafepointsWithDeoptimizationPc();
safepoints()->Emit(masm(), frame()->GetSpillSlotCount());
// TODO(titzer): what are the right code flags here?
}
-void CodeGenerator::RecordSafepoint(PointerMap* pointers, Safepoint::Kind kind,
- int arguments,
- Safepoint::DeoptMode deopt_mode) {
+Safepoint::Id CodeGenerator::RecordSafepoint(PointerMap* pointers,
+ Safepoint::Kind kind,
+ int arguments,
+ Safepoint::DeoptMode deopt_mode) {
const ZoneList<InstructionOperand*>* operands =
pointers->GetNormalizedOperands();
Safepoint safepoint =
safepoint.DefinePointerRegister(reg, zone());
}
}
+ return safepoint.id();
}
}
+void CodeGenerator::UpdateSafepointsWithDeoptimizationPc() {
+ int patch_count = static_cast<int>(lazy_deoptimization_entries_.size());
+ for (int i = 0; i < patch_count; ++i) {
+ LazyDeoptimizationEntry entry = lazy_deoptimization_entries_[i];
+ // TODO(jarin) make sure that there is no code (other than nops)
+ // between the call position and the continuation position.
+ safepoints()->SetDeoptimizationPc(entry.safepoint_id(),
+ entry.deoptimization()->pos());
+ }
+}
+
+
void CodeGenerator::PopulateDeoptimizationData(Handle<Code> code_object) {
CompilationInfo* info = linkage()->info();
int deopt_count = code()->GetDeoptimizationEntryCount();
int patch_count = static_cast<int>(lazy_deoptimization_entries_.size());
if (patch_count == 0 && deopt_count == 0) return;
- Handle<DeoptimizationInputData> data = DeoptimizationInputData::New(
- isolate(), deopt_count, patch_count, TENURED);
+ Handle<DeoptimizationInputData> data =
+ DeoptimizationInputData::New(isolate(), deopt_count, TENURED);
Handle<ByteArray> translation_array =
translations_.CreateByteArray(isolate()->factory());
data->SetPc(i, Smi::FromInt(-1));
}
- // Populate the return address patcher entries.
- for (int i = 0; i < patch_count; ++i) {
- LazyDeoptimizationEntry entry = lazy_deoptimization_entries_[i];
- data->SetReturnAddressPc(i, Smi::FromInt(entry.position_after_call()));
- data->SetPatchedAddressPc(i, Smi::FromInt(entry.deoptimization()->pos()));
- }
-
code_object->set_deoptimization_data(*data);
}
static_cast<CallDescriptor::DeoptimizationSupport>(
MiscField::decode(instr->opcode()));
- if ((deopt & CallDescriptor::kLazyDeoptimization) != 0) {
- RecordLazyDeoptimizationEntry(instr);
- }
-
bool needs_frame_state = (deopt & CallDescriptor::kNeedsFrameState) != 0;
- RecordSafepoint(
+ Safepoint::Id safepoint_id = RecordSafepoint(
instr->pointer_map(), Safepoint::kSimple, 0,
needs_frame_state ? Safepoint::kLazyDeopt : Safepoint::kNoLazyDeopt);
- if ((deopt & CallDescriptor::kNeedsFrameState) != 0) {
+ if ((deopt & CallDescriptor::kLazyDeoptimization) != 0) {
+ RecordLazyDeoptimizationEntry(instr, safepoint_id);
+ }
+
+ if (needs_frame_state) {
// If the frame state is present, it starts at argument 1
// (just after the code address).
InstructionOperandConverter converter(this, instr);
// Argument 1 is deoptimization id.
int deoptimization_id = converter.ToConstant(instr->InputAt(1)).ToInt32();
// The actual frame state values start with argument 2.
- BuildTranslation(instr, 2, deoptimization_id);
+ int first_state_value_offset = 2;
+#if DEBUG
+ // Make sure all the values live in stack slots or they are immediates.
+ // (The values should not live in register because registers are clobbered
+ // by calls.)
+ FrameStateDescriptor* descriptor =
+ code()->GetDeoptimizationEntry(deoptimization_id);
+ for (int i = 0; i < descriptor->size(); i++) {
+ InstructionOperand* op = instr->InputAt(first_state_value_offset + i);
+ CHECK(op->IsStackSlot() || op->IsImmediate());
+ }
+#endif
+ BuildTranslation(instr, first_state_value_offset, deoptimization_id);
safepoints()->RecordLazyDeoptimizationIndex(deoptimization_id);
}
}
-void CodeGenerator::RecordLazyDeoptimizationEntry(Instruction* instr) {
+void CodeGenerator::RecordLazyDeoptimizationEntry(Instruction* instr,
+ Safepoint::Id safepoint_id) {
InstructionOperandConverter i(this, instr);
Label after_call;
Label* cont_label = code_->GetLabel(cont_block);
Label* deopt_label = code_->GetLabel(deopt_block);
- lazy_deoptimization_entries_.push_back(
- LazyDeoptimizationEntry(after_call.pos(), cont_label, deopt_label));
+ lazy_deoptimization_entries_.push_back(LazyDeoptimizationEntry(
+ after_call.pos(), cont_label, deopt_label, safepoint_id));
}
}
// Record a safepoint with the given pointer map.
- void RecordSafepoint(PointerMap* pointers, Safepoint::Kind kind,
- int arguments, Safepoint::DeoptMode deopt_mode);
+ Safepoint::Id RecordSafepoint(PointerMap* pointers, Safepoint::Kind kind,
+ int arguments, Safepoint::DeoptMode deopt_mode);
// Assemble code for the specified instruction.
void AssembleInstruction(Instruction* instr);
// ===========================================================================
// Deoptimization table construction
void AddSafepointAndDeopt(Instruction* instr);
- void RecordLazyDeoptimizationEntry(Instruction* instr);
+ void UpdateSafepointsWithDeoptimizationPc();
+ void RecordLazyDeoptimizationEntry(Instruction* instr,
+ Safepoint::Id safepoint_id);
void PopulateDeoptimizationData(Handle<Code> code);
int DefineDeoptimizationLiteral(Handle<Object> literal);
void BuildTranslation(Instruction* instr, int first_argument_index,
class LazyDeoptimizationEntry V8_FINAL {
public:
LazyDeoptimizationEntry(int position_after_call, Label* continuation,
- Label* deoptimization)
+ Label* deoptimization, Safepoint::Id safepoint_id)
: position_after_call_(position_after_call),
continuation_(continuation),
- deoptimization_(deoptimization) {}
+ deoptimization_(deoptimization),
+ safepoint_id_(safepoint_id) {}
int position_after_call() const { return position_after_call_; }
Label* continuation() const { return continuation_; }
Label* deoptimization() const { return deoptimization_; }
+ Safepoint::Id safepoint_id() const { return safepoint_id_; }
private:
int position_after_call_;
Label* continuation_;
Label* deoptimization_;
+ Safepoint::Id safepoint_id_;
};
struct DeoptimizationState : ZoneObject {
case IrOpcode::kHeapConstant:
return g->UseImmediate(input);
default:
- return g->Use(input);
+ return g->UseUnique(input);
}
}
}
-static int FindPatchAddressForReturnAddress(Code* code, int pc) {
- DeoptimizationInputData* input_data =
- DeoptimizationInputData::cast(code->deoptimization_data());
- int patch_count = input_data->ReturnAddressPatchCount();
- for (int i = 0; i < patch_count; i++) {
- int return_pc = input_data->ReturnAddressPc(i)->value();
- int patch_pc = input_data->PatchedAddressPc(i)->value();
- // If the supplied pc matches the return pc or if the address
- // has been already patched, return the patch pc.
- if (pc == return_pc || pc == patch_pc) {
- return patch_pc;
- }
- }
- return -1;
-}
-
-
// For all marked Turbofanned code on stack, change the return address to go
// to the deoptimization block.
void Deoptimizer::PatchStackForMarkedCode(Isolate* isolate) {
Address* pc_address = it.frame()->pc_address();
int pc_offset =
static_cast<int>(*pc_address - code->instruction_start());
- int new_pc_offset = FindPatchAddressForReturnAddress(code, pc_offset);
+ SafepointEntry safepoint_entry = code->GetSafepointEntry(*pc_address);
+ unsigned new_pc_offset = safepoint_entry.deoptimization_pc();
if (FLAG_trace_deopt) {
CodeTracer::Scope scope(isolate->GetCodeTracer());
new_pc_offset);
}
- CHECK_LE(0, new_pc_offset);
- *pc_address += new_pc_offset - pc_offset;
+ CHECK(new_pc_offset != Safepoint::kNoDeoptimizationPc);
+ *pc_address += static_cast<int>(new_pc_offset) - pc_offset;
}
}
}
int length = deoptimizations_.length();
if (length == 0) return;
Handle<DeoptimizationInputData> data =
- DeoptimizationInputData::New(isolate(), length, 0, TENURED);
+ DeoptimizationInputData::New(isolate(), length, TENURED);
Handle<ByteArray> translations =
translations_.CreateByteArray(isolate()->factory());
int length = deoptimizations_.length();
if (length == 0) return;
Handle<DeoptimizationInputData> data =
- DeoptimizationInputData::New(isolate(), length, 0, TENURED);
+ DeoptimizationInputData::New(isolate(), length, TENURED);
Handle<ByteArray> translations =
translations_.CreateByteArray(isolate()->factory());
int length = deoptimizations_.length();
if (length == 0) return;
Handle<DeoptimizationInputData> data =
- DeoptimizationInputData::New(isolate(), length, 0, TENURED);
+ DeoptimizationInputData::New(isolate(), length, TENURED);
Handle<ByteArray> translations =
translations_.CreateByteArray(isolate()->factory());
// the entry size.
int length = FixedArray::cast(this)->length();
if (length == 0) return true;
- if (length < DeoptimizationInputData::kFirstDeoptEntryIndex) return false;
-
- FixedArray* self = FixedArray::cast(const_cast<Object*>(this));
- int deopt_count =
- Smi::cast(self->get(DeoptimizationInputData::kDeoptEntryCountIndex))
- ->value();
- int patch_count =
- Smi::cast(
- self->get(
- DeoptimizationInputData::kReturnAddressPatchEntryCountIndex))
- ->value();
-
- return length == DeoptimizationInputData::LengthFor(deopt_count, patch_count);
+
+ length -= DeoptimizationInputData::kFirstDeoptEntryIndex;
+ return length >= 0 && length % DeoptimizationInputData::kDeoptEntrySize == 0;
}
Handle<DeoptimizationInputData> DeoptimizationInputData::New(
- Isolate* isolate, int deopt_entry_count, int return_patch_address_count,
- PretenureFlag pretenure) {
- DCHECK(deopt_entry_count + return_patch_address_count > 0);
- Handle<FixedArray> deoptimization_data =
- Handle<FixedArray>::cast(isolate->factory()->NewFixedArray(
- LengthFor(deopt_entry_count, return_patch_address_count), pretenure));
- deoptimization_data->set(kDeoptEntryCountIndex,
- Smi::FromInt(deopt_entry_count));
- deoptimization_data->set(kReturnAddressPatchEntryCountIndex,
- Smi::FromInt(return_patch_address_count));
- return Handle<DeoptimizationInputData>::cast(deoptimization_data);
+ Isolate* isolate, int deopt_entry_count, PretenureFlag pretenure) {
+ DCHECK(deopt_entry_count > 0);
+ return Handle<DeoptimizationInputData>::cast(
+ isolate->factory()->NewFixedArray(LengthFor(deopt_entry_count),
+ pretenure));
}
SafepointEntry Code::GetSafepointEntry(Address pc) {
SafepointTable table(this);
- SafepointEntry entry = table.FindEntry(pc);
- if (entry.is_valid() || !is_turbofanned()) {
- return entry;
- }
-
- // If the code is turbofanned, we might be looking for
- // an address that was patched by lazy deoptimization.
- // In that case look through the patch table, try to
- // lookup the original address there, and then use this
- // to find the safepoint entry.
- DeoptimizationInputData* deopt_data =
- DeoptimizationInputData::cast(deoptimization_data());
- intptr_t offset = pc - instruction_start();
- for (int i = 0; i < deopt_data->ReturnAddressPatchCount(); i++) {
- if (deopt_data->PatchedAddressPc(i)->value() == offset) {
- int original_offset = deopt_data->ReturnAddressPc(i)->value();
- return table.FindEntry(instruction_start() + original_offset);
- }
- }
- return SafepointEntry();
+ return table.FindEntry(pc);
}
os << "\n";
}
}
-
- int return_address_patch_count = ReturnAddressPatchCount();
- if (return_address_patch_count != 0) {
- os << "Return address patch data (count = " << return_address_patch_count
- << ")\n";
- os << " index pc patched_pc\n";
- }
- for (int i = 0; i < return_address_patch_count; i++) {
- Vector<char> buf = Vector<char>::New(128);
- SNPrintF(buf, "%6d %6d %12d\n", i, ReturnAddressPc(i)->value(),
- PatchedAddressPc(i)->value());
- os << buf.start();
- }
}
} else {
os << "<none>";
}
+ if (entry.deoptimization_pc() != Safepoint::kNoDeoptimizationPc) {
+ Vector<char> buf2 = Vector<char>::New(30);
+ SNPrintF(buf2, "%6d", entry.deoptimization_pc());
+ os << buf2.start();
+ } else {
+ os << "<none>";
+ }
if (entry.argument_count() > 0) {
os << " argc: " << entry.argument_count();
}
class DeoptimizationInputData: public FixedArray {
public:
// Layout description. Indices in the array.
- static const int kDeoptEntryCountIndex = 0;
- static const int kReturnAddressPatchEntryCountIndex = 1;
- static const int kTranslationByteArrayIndex = 2;
- static const int kInlinedFunctionCountIndex = 3;
- static const int kLiteralArrayIndex = 4;
- static const int kOsrAstIdIndex = 5;
- static const int kOsrPcOffsetIndex = 6;
- static const int kOptimizationIdIndex = 7;
- static const int kSharedFunctionInfoIndex = 8;
- static const int kFirstDeoptEntryIndex = 9;
+ static const int kTranslationByteArrayIndex = 0;
+ static const int kInlinedFunctionCountIndex = 1;
+ static const int kLiteralArrayIndex = 2;
+ static const int kOsrAstIdIndex = 3;
+ static const int kOsrPcOffsetIndex = 4;
+ static const int kOptimizationIdIndex = 5;
+ static const int kSharedFunctionInfoIndex = 6;
+ static const int kFirstDeoptEntryIndex = 7;
// Offsets of deopt entry elements relative to the start of the entry.
static const int kAstIdRawOffset = 0;
static const int kPcOffset = 3;
static const int kDeoptEntrySize = 4;
- // Offsets of return address patch entry elements relative to the start of the
- // entry
- static const int kReturnAddressPcOffset = 0;
- static const int kPatchedAddressPcOffset = 1;
- static const int kReturnAddressPatchEntrySize = 2;
-
// Simple element accessors.
#define DEFINE_ELEMENT_ACCESSORS(name, type) \
type* name() { \
#undef DEFINE_ELEMENT_ACCESSORS
// Accessors for elements of the ith deoptimization entry.
-#define DEFINE_DEOPT_ENTRY_ACCESSORS(name, type) \
+#define DEFINE_ENTRY_ACCESSORS(name, type) \
type* name(int i) { \
return type::cast(get(IndexForEntry(i) + k##name##Offset)); \
} \
set(IndexForEntry(i) + k##name##Offset, value); \
}
- DEFINE_DEOPT_ENTRY_ACCESSORS(AstIdRaw, Smi)
- DEFINE_DEOPT_ENTRY_ACCESSORS(TranslationIndex, Smi)
- DEFINE_DEOPT_ENTRY_ACCESSORS(ArgumentsStackHeight, Smi)
- DEFINE_DEOPT_ENTRY_ACCESSORS(Pc, Smi)
+ DEFINE_ENTRY_ACCESSORS(AstIdRaw, Smi)
+ DEFINE_ENTRY_ACCESSORS(TranslationIndex, Smi)
+ DEFINE_ENTRY_ACCESSORS(ArgumentsStackHeight, Smi)
+ DEFINE_ENTRY_ACCESSORS(Pc, Smi)
#undef DEFINE_DEOPT_ENTRY_ACCESSORS
-// Accessors for elements of the ith deoptimization entry.
-#define DEFINE_PATCH_ENTRY_ACCESSORS(name, type) \
- type* name(int i) { \
- return type::cast( \
- get(IndexForReturnAddressPatchEntry(i) + k##name##Offset)); \
- } \
- void Set##name(int i, type* value) { \
- set(IndexForReturnAddressPatchEntry(i) + k##name##Offset, value); \
- }
-
- DEFINE_PATCH_ENTRY_ACCESSORS(ReturnAddressPc, Smi)
- DEFINE_PATCH_ENTRY_ACCESSORS(PatchedAddressPc, Smi)
-
-#undef DEFINE_PATCH_ENTRY_ACCESSORS
-
BailoutId AstId(int i) {
return BailoutId(AstIdRaw(i)->value());
}
}
int DeoptCount() {
- return length() == 0 ? 0 : Smi::cast(get(kDeoptEntryCountIndex))->value();
- }
-
- int ReturnAddressPatchCount() {
- return length() == 0
- ? 0
- : Smi::cast(get(kReturnAddressPatchEntryCountIndex))->value();
+ return (length() - kFirstDeoptEntryIndex) / kDeoptEntrySize;
}
// Allocates a DeoptimizationInputData.
static Handle<DeoptimizationInputData> New(Isolate* isolate,
int deopt_entry_count,
- int return_address_patch_count,
PretenureFlag pretenure);
DECLARE_CAST(DeoptimizationInputData)
#endif
private:
- friend class Object; // For accessing LengthFor.
-
static int IndexForEntry(int i) {
return kFirstDeoptEntryIndex + (i * kDeoptEntrySize);
}
- int IndexForReturnAddressPatchEntry(int i) {
- return kFirstDeoptEntryIndex + (DeoptCount() * kDeoptEntrySize) +
- (i * kReturnAddressPatchEntrySize);
- }
- static int LengthFor(int deopt_count, int return_address_patch_count) {
- return kFirstDeoptEntryIndex + (deopt_count * kDeoptEntrySize) +
- (return_address_patch_count * kReturnAddressPatchEntrySize);
- }
+ static int LengthFor(int entry_count) { return IndexForEntry(entry_count); }
};
length_ = Memory::uint32_at(header + kLengthOffset);
entry_size_ = Memory::uint32_at(header + kEntrySizeOffset);
pc_and_deoptimization_indexes_ = header + kHeaderSize;
- entries_ = pc_and_deoptimization_indexes_ +
- (length_ * kPcAndDeoptimizationIndexSize);
+ entries_ =
+ pc_and_deoptimization_indexes_ + (length_ * kPcAndDeoptimizationInfoSize);
DCHECK(entry_size_ > 0);
STATIC_ASSERT(SafepointEntry::DeoptimizationIndexField::kMax ==
Safepoint::kNoDeoptimizationIndex);
for (unsigned i = 0; i < length(); i++) {
// TODO(kasperl): Replace the linear search with binary search.
if (GetPcOffset(i) == pc_offset) return GetEntry(i);
+ if (GetDeoptimizationPcOffset(i) == pc_offset) return GetEntry(i);
}
return SafepointEntry();
}
info.pc = assembler->pc_offset();
info.arguments = arguments;
info.has_doubles = (kind & Safepoint::kWithDoubles);
+ info.deoptimization_pc = Safepoint::kNoDeoptimizationPc;
+ int safepoint_id = deoptimization_info_.length();
deoptimization_info_.Add(info, zone_);
deopt_index_list_.Add(Safepoint::kNoDeoptimizationIndex, zone_);
if (deopt_mode == Safepoint::kNoLazyDeopt) {
? new(zone_) ZoneList<int>(4, zone_)
: NULL,
zone_);
- return Safepoint(indexes_.last(), registers_.last());
+ return Safepoint(safepoint_id, indexes_.last(), registers_.last());
}
assembler->dd(deoptimization_info_[i].pc);
assembler->dd(EncodeExceptPC(deoptimization_info_[i],
deopt_index_list_[i]));
+ assembler->dd(deoptimization_info_[i].deoptimization_pc);
}
// Emit table of bitmaps.
class SafepointEntry BASE_EMBEDDED {
public:
- SafepointEntry() : info_(0), bits_(NULL) {}
+ SafepointEntry() : info_(0), deoptimization_pc_(0), bits_(NULL) {}
- SafepointEntry(unsigned info, uint8_t* bits) : info_(info), bits_(bits) {
+ SafepointEntry(unsigned info, unsigned deoptimization_pc, uint8_t* bits)
+ : info_(info), deoptimization_pc_(deoptimization_pc), bits_(bits) {
DCHECK(is_valid());
}
return DeoptimizationIndexField::decode(info_);
}
+ unsigned deoptimization_pc() const {
+ DCHECK(is_valid());
+ return deoptimization_pc_;
+ }
+
static const int kArgumentsFieldBits = 3;
static const int kSaveDoublesFieldBits = 1;
static const int kDeoptIndexBits =
private:
unsigned info_;
+ unsigned deoptimization_pc_;
uint8_t* bits_;
};
int size() const {
return kHeaderSize +
- (length_ * (kPcAndDeoptimizationIndexSize + entry_size_)); }
+ (length_ * (kPcAndDeoptimizationInfoSize + entry_size_));
+ }
unsigned length() const { return length_; }
unsigned entry_size() const { return entry_size_; }
return Memory::uint32_at(GetPcOffsetLocation(index));
}
+ unsigned GetDeoptimizationPcOffset(unsigned index) const {
+ DCHECK(index < length_);
+ return Memory::uint32_at(GetDeoptimizationPcLocation(index));
+ }
+
SafepointEntry GetEntry(unsigned index) const {
DCHECK(index < length_);
unsigned info = Memory::uint32_at(GetInfoLocation(index));
+ unsigned deopt_pc = Memory::uint32_at(GetDeoptimizationPcLocation(index));
uint8_t* bits = &Memory::uint8_at(entries_ + (index * entry_size_));
- return SafepointEntry(info, bits);
+ return SafepointEntry(info, deopt_pc, bits);
}
// Returns the entry for the given pc.
static const int kPcSize = kIntSize;
static const int kDeoptimizationIndexSize = kIntSize;
- static const int kPcAndDeoptimizationIndexSize =
- kPcSize + kDeoptimizationIndexSize;
+ static const int kDeoptimizationPcSize = kIntSize;
+ static const int kPcAndDeoptimizationInfoSize =
+ kPcSize + kDeoptimizationIndexSize + kDeoptimizationPcSize;
Address GetPcOffsetLocation(unsigned index) const {
return pc_and_deoptimization_indexes_ +
- (index * kPcAndDeoptimizationIndexSize);
+ (index * kPcAndDeoptimizationInfoSize);
}
Address GetInfoLocation(unsigned index) const {
return GetPcOffsetLocation(index) + kPcSize;
}
+ Address GetDeoptimizationPcLocation(unsigned index) const {
+ return GetInfoLocation(index) + kDeoptimizationIndexSize;
+ }
+
static void PrintBits(OStream& os, // NOLINT
uint8_t byte, int digits);
kLazyDeopt
};
+ class Id {
+ private:
+ explicit Id(int id) : id_(id) {}
+
+ int id_;
+
+ friend class SafepointTableBuilder;
+ friend class Safepoint;
+ };
+
static const int kNoDeoptimizationIndex =
(1 << (SafepointEntry::kDeoptIndexBits)) - 1;
+ static const unsigned kNoDeoptimizationPc = ~0U;
+
void DefinePointerSlot(int index, Zone* zone) { indexes_->Add(index, zone); }
void DefinePointerRegister(Register reg, Zone* zone);
+ Id id() const { return Id(id_); }
+
private:
- Safepoint(ZoneList<int>* indexes, ZoneList<int>* registers) :
- indexes_(indexes), registers_(registers) { }
+ Safepoint(int id, ZoneList<int>* indexes, ZoneList<int>* registers)
+ : id_(id), indexes_(indexes), registers_(registers) {}
+ int id_;
ZoneList<int>* indexes_;
ZoneList<int>* registers_;
void BumpLastLazySafepointIndex() {
last_lazy_safepoint_ = deopt_index_list_.length();
}
+ void SetDeoptimizationPc(Safepoint::Id safepoint_id,
+ unsigned deoptimization_pc) {
+ deoptimization_info_[safepoint_id.id_].deoptimization_pc =
+ deoptimization_pc;
+ }
// Emit the safepoint table after the body. The number of bits per
// entry must be enough to hold all the pointer indexes.
unsigned pc;
unsigned arguments;
bool has_doubles;
+ unsigned deoptimization_pc;
};
uint32_t EncodeExceptPC(const DeoptimizationInfo& info, unsigned index);
int length = deoptimizations_.length();
if (length == 0) return;
Handle<DeoptimizationInputData> data =
- DeoptimizationInputData::New(isolate(), length, 0, TENURED);
+ DeoptimizationInputData::New(isolate(), length, TENURED);
Handle<ByteArray> translations =
translations_.CreateByteArray(isolate()->factory());
int length = deoptimizations_.length();
if (length == 0) return;
Handle<DeoptimizationInputData> data =
- DeoptimizationInputData::New(isolate(), length, 0, TENURED);
+ DeoptimizationInputData::New(isolate(), length, TENURED);
Handle<ByteArray> translations =
translations_.CreateByteArray(isolate()->factory());
Label* cont_label = t.code->GetLabel(t.cont_block);
Label* deopt_label = t.code->GetLabel(t.deopt_block);
- // Check the patch table. It should patch the continuation address to the
- // deoptimization block address.
- CHECK_EQ(1, data->ReturnAddressPatchCount());
- CHECK_EQ(cont_label->pos(), data->ReturnAddressPc(0)->value());
- CHECK_EQ(deopt_label->pos(), data->PatchedAddressPc(0)->value());
+ // Check the safepoint - it should contain an entry for the call
+ // with the right deoptimization address.
+ SafepointEntry entry = t.result_code->GetSafepointEntry(
+ t.result_code->instruction_start() + cont_label->pos());
+ CHECK(entry.is_valid());
+ CHECK_EQ(deopt_label->pos(), entry.deoptimization_pc());
// Check that we deoptimize to the right AST id.
CHECK_EQ(1, data->DeoptCount());
'deserialize-reference': [PASS, NO_VARIANTS],
# Support for %GetFrameDetails is missing and requires checkpoints.
- 'debug-backtrace-text': [PASS, NO_VARIANTS],
- 'debug-break-inline': [PASS, NO_VARIANTS],
'debug-evaluate-bool-constructor': [PASS, NO_VARIANTS],
'debug-evaluate-closure': [PASS, NO_VARIANTS],
'debug-evaluate-const': [PASS, NO_VARIANTS],