Fix deoptimization address patching in Turbofan to use safepoints.
authorjarin@chromium.org <jarin@chromium.org>
Mon, 25 Aug 2014 07:02:19 +0000 (07:02 +0000)
committerjarin@chromium.org <jarin@chromium.org>
Mon, 25 Aug 2014 07:02:19 +0000 (07:02 +0000)
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

18 files changed:
src/arm/lithium-codegen-arm.cc
src/arm64/lithium-codegen-arm64.cc
src/compiler/code-generator.cc
src/compiler/code-generator.h
src/compiler/instruction-selector.cc
src/deoptimizer.cc
src/ia32/lithium-codegen-ia32.cc
src/mips/lithium-codegen-mips.cc
src/mips64/lithium-codegen-mips64.cc
src/objects-inl.h
src/objects.cc
src/objects.h
src/safepoint-table.cc
src/safepoint-table.h
src/x64/lithium-codegen-x64.cc
src/x87/lithium-codegen-x87.cc
test/cctest/compiler/test-codegen-deopt.cc
test/mjsunit/mjsunit.status

index e2658f3c439e57c3777ad295de79baff508986c2..09c677330ae01fa6cbebea4d061efbfe871e85d8 100644 (file)
@@ -931,7 +931,7 @@ void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) {
   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());
index d6c9ef6b769cb6945b556efcafcc13f03610855d..195d99dc7b77c42dd32ea84a69b3d59759909203 100644 (file)
@@ -937,7 +937,7 @@ void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) {
   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());
index 5a5d9f9674fcc1203f12f81b47e0dc223a25b9e5..1cbb59643705bd222f1b44f89b213e99f7e655a3 100644 (file)
@@ -53,6 +53,7 @@ Handle<Code> CodeGenerator::GenerateCode() {
 
   FinishCode(masm());
 
+  UpdateSafepointsWithDeoptimizationPc();
   safepoints()->Emit(masm(), frame()->GetSpillSlotCount());
 
   // TODO(titzer): what are the right code flags here?
@@ -76,9 +77,10 @@ Handle<Code> 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<InstructionOperand*>* 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<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());
@@ -222,13 +237,6 @@ void CodeGenerator::PopulateDeoptimizationData(Handle<Code> 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<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;
@@ -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));
 }
 
 
index 8bacdf3bfa79ff6698bdf09758ce6f55f5a88e3d..14ee3517aee35997375f70ca274ef434f4d02553 100644 (file)
@@ -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> code);
   int DefineDeoptimizationLiteral(Handle<Object> 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 {
index 0d014a503e2d8a6aef5f47106e349f7d15e0fdbc..64878e42bc3c3c131e2df485910a7dc00b092bf0 100644 (file)
@@ -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);
   }
 }
 
index 5209a51611915952c8ec44af98bfff76bdc581ce..e6415f4b238360dedbebd5d89dccfc00721b6312 100644 (file)
@@ -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<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());
@@ -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<int>(new_pc_offset) - pc_offset;
       }
     }
   }
index 395ae39c30e2f99bbd53849a0afd25f52094c623..38eaa6696a498c68030de4490a615ed2f3610333 100644 (file)
@@ -900,7 +900,7 @@ void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) {
   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());
index 193db1e9b76d6cd75ef2151edd2bdd776ecbe96c..d5580ea877c42fd6112ac82c4fd9525d52bc5ab7 100644 (file)
@@ -897,7 +897,7 @@ void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) {
   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());
index ab0d8c7c78fa4aa07e32b4add3eced73b381860e..50b33fee1d0f44385f3915e0fb98b7c347366f41 100644 (file)
@@ -852,7 +852,7 @@ void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) {
   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());
index e2414d290046927d3d3f4a7e13d3b09e0311d5df..0ec6feb2805e887b6f52a2bd5c8e4ca26be76f03 100644 (file)
@@ -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<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;
 }
 
 
index f223b0fc9461a138fb0abd67d7bee22fcdea85b1..b6e0eaca94a8871cc780adea4225941fb672709c 100644 (file)
@@ -7933,17 +7933,11 @@ Object* AccessorPair::GetComponent(AccessorComponent component) {
 
 
 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));
 }
 
 
@@ -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<char> buf = Vector<char>::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 << "<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();
       }
index 3c814f2127a7c3b61e1cdcced83c6a060f7ddf63..a804dc62a6d41dd0fb0abdcf146a16db03981d5f 100644 (file)
@@ -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<DeoptimizationInputData> 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); }
 };
 
 
index d00b751a05818344d71fb2b8b2bbd3d948a2c6bd..5f915476e230c56795c33db86890cb311a31b075 100644 (file)
@@ -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<int>(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.
index 0bdd43104d5a89ce1e2e55f43c25d77f1ad80824..d91a1956daf14f2789c0c8a4112b2e1e45403f68 100644 (file)
@@ -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<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_;
 
@@ -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);
index 0a6ac17f9bc784e37f5ad03c5645a030d095b4a5..a5b1cfccd27004a3a5b8b542fa90bca742e8a079 100644 (file)
@@ -810,7 +810,7 @@ void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) {
   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());
index 4116b4656a5e6851f3bc84db4c411982ecc729ac..80d5518dd1cf67191b74b8ecd82b270e75e7ded6 100644 (file)
@@ -1095,7 +1095,7 @@ void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) {
   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());
index 1e30e938b9f1ad99bbe30224e82ab444dfed6c04..fd2463e664ceee1e2f1751105e339fcb001feff6 100644 (file)
@@ -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());
index 3dafda69cd684fa2bea0f4a28fc0bd32f0a16770..636b7084db1aa8d8b5f64811f1b08e6e2db1c5da 100644 (file)
@@ -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],