From d8295050d28434395df4960290b3df81cb4634b2 Mon Sep 17 00:00:00 2001 From: "jarin@chromium.org" Date: Mon, 25 Aug 2014 07:02:19 +0000 Subject: [PATCH] Fix deoptimization address patching in Turbofan to use safepoints. Since the deopt patch address needs to be available during GC to resolve safepoints, we need to move it to the code object (instead of the deoptimization input data) - accessing a separate fixed array is not safe during GC. This CL adds a deoptimization_pc field to each safepoint. The fields points to the deoptimization block. The CL also fixes wrong register allocator constraints for frame states on calls. These should always live on the stack because registers are not preserved during a call. BUG= R=bmeurer@chromium.org Review URL: https://codereview.chromium.org/504493002 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23334 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/lithium-codegen-arm.cc | 2 +- src/arm64/lithium-codegen-arm64.cc | 2 +- src/compiler/code-generator.cc | 65 +++++++++++++------- src/compiler/code-generator.h | 15 +++-- src/compiler/instruction-selector.cc | 2 +- src/deoptimizer.cc | 24 ++------ src/ia32/lithium-codegen-ia32.cc | 2 +- src/mips/lithium-codegen-mips.cc | 2 +- src/mips64/lithium-codegen-mips64.cc | 2 +- src/objects-inl.h | 16 +---- src/objects.cc | 57 ++++-------------- src/objects.h | 69 +++++----------------- src/safepoint-table.cc | 10 +++- src/safepoint-table.h | 58 +++++++++++++++--- src/x64/lithium-codegen-x64.cc | 2 +- src/x87/lithium-codegen-x87.cc | 2 +- test/cctest/compiler/test-codegen-deopt.cc | 11 ++-- test/mjsunit/mjsunit.status | 2 - 18 files changed, 158 insertions(+), 185 deletions(-) diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc index e2658f3c4..09c677330 100644 --- a/src/arm/lithium-codegen-arm.cc +++ b/src/arm/lithium-codegen-arm.cc @@ -931,7 +931,7 @@ void LCodeGen::PopulateDeoptimizationData(Handle code) { int length = deoptimizations_.length(); if (length == 0) return; Handle data = - DeoptimizationInputData::New(isolate(), length, 0, TENURED); + DeoptimizationInputData::New(isolate(), length, TENURED); Handle translations = translations_.CreateByteArray(isolate()->factory()); diff --git a/src/arm64/lithium-codegen-arm64.cc b/src/arm64/lithium-codegen-arm64.cc index d6c9ef6b7..195d99dc7 100644 --- a/src/arm64/lithium-codegen-arm64.cc +++ b/src/arm64/lithium-codegen-arm64.cc @@ -937,7 +937,7 @@ void LCodeGen::PopulateDeoptimizationData(Handle code) { if (length == 0) return; Handle data = - DeoptimizationInputData::New(isolate(), length, 0, TENURED); + DeoptimizationInputData::New(isolate(), length, TENURED); Handle translations = translations_.CreateByteArray(isolate()->factory()); diff --git a/src/compiler/code-generator.cc b/src/compiler/code-generator.cc index 5a5d9f967..1cbb59643 100644 --- a/src/compiler/code-generator.cc +++ b/src/compiler/code-generator.cc @@ -53,6 +53,7 @@ Handle CodeGenerator::GenerateCode() { FinishCode(masm()); + UpdateSafepointsWithDeoptimizationPc(); safepoints()->Emit(masm(), frame()->GetSpillSlotCount()); // TODO(titzer): what are the right code flags here? @@ -76,9 +77,10 @@ Handle CodeGenerator::GenerateCode() { } -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* operands = pointers->GetNormalizedOperands(); Safepoint safepoint = @@ -92,6 +94,7 @@ void CodeGenerator::RecordSafepoint(PointerMap* pointers, Safepoint::Kind kind, safepoint.DefinePointerRegister(reg, zone()); } } + return safepoint.id(); } @@ -172,13 +175,25 @@ void CodeGenerator::AssembleGap(GapInstruction* instr) { } +void CodeGenerator::UpdateSafepointsWithDeoptimizationPc() { + int patch_count = static_cast(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_object) { CompilationInfo* info = linkage()->info(); int deopt_count = code()->GetDeoptimizationEntryCount(); int patch_count = static_cast(lazy_deoptimization_entries_.size()); if (patch_count == 0 && deopt_count == 0) return; - Handle data = DeoptimizationInputData::New( - isolate(), deopt_count, patch_count, TENURED); + Handle data = + DeoptimizationInputData::New(isolate(), deopt_count, TENURED); Handle translation_array = translations_.CreateByteArray(isolate()->factory()); @@ -222,13 +237,6 @@ void CodeGenerator::PopulateDeoptimizationData(Handle code_object) { 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); } @@ -238,30 +246,43 @@ void CodeGenerator::AddSafepointAndDeopt(Instruction* instr) { static_cast( 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; @@ -276,8 +297,8 @@ void CodeGenerator::RecordLazyDeoptimizationEntry(Instruction* instr) { 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)); } diff --git a/src/compiler/code-generator.h b/src/compiler/code-generator.h index 8bacdf3bf..14ee3517a 100644 --- a/src/compiler/code-generator.h +++ b/src/compiler/code-generator.h @@ -46,8 +46,8 @@ class CodeGenerator V8_FINAL : public GapResolver::Assembler { } // 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); @@ -82,7 +82,9 @@ class CodeGenerator V8_FINAL : public GapResolver::Assembler { // =========================================================================== // 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); int DefineDeoptimizationLiteral(Handle literal); void BuildTranslation(Instruction* instr, int first_argument_index, @@ -95,19 +97,22 @@ class CodeGenerator V8_FINAL : public GapResolver::Assembler { 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 { diff --git a/src/compiler/instruction-selector.cc b/src/compiler/instruction-selector.cc index 0d014a503..64878e42b 100644 --- a/src/compiler/instruction-selector.cc +++ b/src/compiler/instruction-selector.cc @@ -1039,7 +1039,7 @@ static InstructionOperand* UseOrImmediate(OperandGenerator* g, Node* input) { case IrOpcode::kHeapConstant: return g->UseImmediate(input); default: - return g->Use(input); + return g->UseUnique(input); } } diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc index 5209a5161..e6415f4b2 100644 --- a/src/deoptimizer.cc +++ b/src/deoptimizer.cc @@ -442,23 +442,6 @@ void Deoptimizer::DeoptimizeMarkedCodeForContext(Context* context) { } -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) { @@ -474,7 +457,8 @@ void Deoptimizer::PatchStackForMarkedCode(Isolate* isolate) { Address* pc_address = it.frame()->pc_address(); int pc_offset = static_cast(*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()); @@ -484,8 +468,8 @@ void Deoptimizer::PatchStackForMarkedCode(Isolate* isolate) { 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(new_pc_offset) - pc_offset; } } } diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc index 395ae39c3..38eaa6696 100644 --- a/src/ia32/lithium-codegen-ia32.cc +++ b/src/ia32/lithium-codegen-ia32.cc @@ -900,7 +900,7 @@ void LCodeGen::PopulateDeoptimizationData(Handle code) { int length = deoptimizations_.length(); if (length == 0) return; Handle data = - DeoptimizationInputData::New(isolate(), length, 0, TENURED); + DeoptimizationInputData::New(isolate(), length, TENURED); Handle translations = translations_.CreateByteArray(isolate()->factory()); diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc index 193db1e9b..d5580ea87 100644 --- a/src/mips/lithium-codegen-mips.cc +++ b/src/mips/lithium-codegen-mips.cc @@ -897,7 +897,7 @@ void LCodeGen::PopulateDeoptimizationData(Handle code) { int length = deoptimizations_.length(); if (length == 0) return; Handle data = - DeoptimizationInputData::New(isolate(), length, 0, TENURED); + DeoptimizationInputData::New(isolate(), length, TENURED); Handle translations = translations_.CreateByteArray(isolate()->factory()); diff --git a/src/mips64/lithium-codegen-mips64.cc b/src/mips64/lithium-codegen-mips64.cc index ab0d8c7c7..50b33fee1 100644 --- a/src/mips64/lithium-codegen-mips64.cc +++ b/src/mips64/lithium-codegen-mips64.cc @@ -852,7 +852,7 @@ void LCodeGen::PopulateDeoptimizationData(Handle code) { int length = deoptimizations_.length(); if (length == 0) return; Handle data = - DeoptimizationInputData::New(isolate(), length, 0, TENURED); + DeoptimizationInputData::New(isolate(), length, TENURED); Handle translations = translations_.CreateByteArray(isolate()->factory()); diff --git a/src/objects-inl.h b/src/objects-inl.h index e2414d290..0ec6feb28 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -717,19 +717,9 @@ bool Object::IsDeoptimizationInputData() const { // 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(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; } diff --git a/src/objects.cc b/src/objects.cc index f223b0fc9..b6e0eaca9 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -7933,17 +7933,11 @@ Object* AccessorPair::GetComponent(AccessorComponent component) { Handle 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 deoptimization_data = - Handle::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::cast(deoptimization_data); + Isolate* isolate, int deopt_entry_count, PretenureFlag pretenure) { + DCHECK(deopt_entry_count > 0); + return Handle::cast( + isolate->factory()->NewFixedArray(LengthFor(deopt_entry_count), + pretenure)); } @@ -10291,26 +10285,7 @@ int Code::SourceStatementPosition(Address pc) { 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); } @@ -10863,19 +10838,6 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint( 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 buf = Vector::New(128); - SNPrintF(buf, "%6d %6d %12d\n", i, ReturnAddressPc(i)->value(), - PatchedAddressPc(i)->value()); - os << buf.start(); - } } @@ -11006,6 +10968,13 @@ void Code::Disassemble(const char* name, OStream& os) { // NOLINT } else { os << ""; } + if (entry.deoptimization_pc() != Safepoint::kNoDeoptimizationPc) { + Vector buf2 = Vector::New(30); + SNPrintF(buf2, "%6d", entry.deoptimization_pc()); + os << buf2.start(); + } else { + os << ""; + } if (entry.argument_count() > 0) { os << " argc: " << entry.argument_count(); } diff --git a/src/objects.h b/src/objects.h index 3c814f212..a804dc62a 100644 --- a/src/objects.h +++ b/src/objects.h @@ -5151,16 +5151,14 @@ TYPED_ARRAYS(FIXED_TYPED_ARRAY_TRAITS) 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; @@ -5169,12 +5167,6 @@ class DeoptimizationInputData: public FixedArray { 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() { \ @@ -5195,7 +5187,7 @@ class DeoptimizationInputData: public FixedArray { #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)); \ } \ @@ -5203,28 +5195,13 @@ class DeoptimizationInputData: public FixedArray { 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()); } @@ -5234,19 +5211,12 @@ class DeoptimizationInputData: public FixedArray { } 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 New(Isolate* isolate, int deopt_entry_count, - int return_address_patch_count, PretenureFlag pretenure); DECLARE_CAST(DeoptimizationInputData) @@ -5256,21 +5226,12 @@ class DeoptimizationInputData: public FixedArray { #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); } }; diff --git a/src/safepoint-table.cc b/src/safepoint-table.cc index d00b751a0..5f915476e 100644 --- a/src/safepoint-table.cc +++ b/src/safepoint-table.cc @@ -43,8 +43,8 @@ SafepointTable::SafepointTable(Code* code) { 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); @@ -56,6 +56,7 @@ SafepointEntry SafepointTable::FindEntry(Address pc) const { 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(); } @@ -110,6 +111,8 @@ Safepoint SafepointTableBuilder::DefineSafepoint( 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) { @@ -120,7 +123,7 @@ Safepoint SafepointTableBuilder::DefineSafepoint( ? new(zone_) ZoneList(4, zone_) : NULL, zone_); - return Safepoint(indexes_.last(), registers_.last()); + return Safepoint(safepoint_id, indexes_.last(), registers_.last()); } @@ -159,6 +162,7 @@ void SafepointTableBuilder::Emit(Assembler* assembler, int bits_per_entry) { 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. diff --git a/src/safepoint-table.h b/src/safepoint-table.h index 0bdd43104..d91a1956d 100644 --- a/src/safepoint-table.h +++ b/src/safepoint-table.h @@ -17,9 +17,10 @@ struct Register; 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()); } @@ -39,6 +40,11 @@ class SafepointEntry BASE_EMBEDDED { 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 = @@ -74,6 +80,7 @@ class SafepointEntry BASE_EMBEDDED { private: unsigned info_; + unsigned deoptimization_pc_; uint8_t* bits_; }; @@ -84,7 +91,8 @@ class SafepointTable BASE_EMBEDDED { 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_; } @@ -93,11 +101,17 @@ class SafepointTable BASE_EMBEDDED { 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. @@ -114,18 +128,23 @@ class SafepointTable BASE_EMBEDDED { 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); @@ -158,15 +177,30 @@ class Safepoint BASE_EMBEDDED { 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* indexes, ZoneList* registers) : - indexes_(indexes), registers_(registers) { } + Safepoint(int id, ZoneList* indexes, ZoneList* registers) + : id_(id), indexes_(indexes), registers_(registers) {} + int id_; ZoneList* indexes_; ZoneList* registers_; @@ -200,6 +234,11 @@ class SafepointTableBuilder BASE_EMBEDDED { 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. @@ -211,6 +250,7 @@ class SafepointTableBuilder BASE_EMBEDDED { unsigned pc; unsigned arguments; bool has_doubles; + unsigned deoptimization_pc; }; uint32_t EncodeExceptPC(const DeoptimizationInfo& info, unsigned index); diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc index 0a6ac17f9..a5b1cfccd 100644 --- a/src/x64/lithium-codegen-x64.cc +++ b/src/x64/lithium-codegen-x64.cc @@ -810,7 +810,7 @@ void LCodeGen::PopulateDeoptimizationData(Handle code) { int length = deoptimizations_.length(); if (length == 0) return; Handle data = - DeoptimizationInputData::New(isolate(), length, 0, TENURED); + DeoptimizationInputData::New(isolate(), length, TENURED); Handle translations = translations_.CreateByteArray(isolate()->factory()); diff --git a/src/x87/lithium-codegen-x87.cc b/src/x87/lithium-codegen-x87.cc index 4116b4656..80d5518dd 100644 --- a/src/x87/lithium-codegen-x87.cc +++ b/src/x87/lithium-codegen-x87.cc @@ -1095,7 +1095,7 @@ void LCodeGen::PopulateDeoptimizationData(Handle code) { int length = deoptimizations_.length(); if (length == 0) return; Handle data = - DeoptimizationInputData::New(isolate(), length, 0, TENURED); + DeoptimizationInputData::New(isolate(), length, TENURED); Handle translations = translations_.CreateByteArray(isolate()->factory()); diff --git a/test/cctest/compiler/test-codegen-deopt.cc b/test/cctest/compiler/test-codegen-deopt.cc index 1e30e938b..fd2463e66 100644 --- a/test/cctest/compiler/test-codegen-deopt.cc +++ b/test/cctest/compiler/test-codegen-deopt.cc @@ -201,11 +201,12 @@ TEST(TurboTrivialDeoptCodegen) { 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()); diff --git a/test/mjsunit/mjsunit.status b/test/mjsunit/mjsunit.status index 3dafda69c..636b7084d 100644 --- a/test/mjsunit/mjsunit.status +++ b/test/mjsunit/mjsunit.status @@ -97,8 +97,6 @@ '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], -- 2.34.1