Make adding a pending deopt atomic.

Issue #27496

R=fschneider@google.com

Review URL: https://codereview.chromium.org/2395123003 .
This commit is contained in:
Ryan Macnak 2016-10-07 13:43:43 -07:00
parent 3d28d08413
commit b85956e6d9
4 changed files with 49 additions and 44 deletions

View file

@ -2048,20 +2048,13 @@ void DeoptimizeAt(const Code& optimized_code, StackFrame* frame) {
uword deopt_pc = frame->pc();
ASSERT(optimized_code.ContainsInstructionAt(deopt_pc));
// N.B.: Update the pending deopt table before updating the frame. The
// profiler may attempt a stack walk in between.
MallocGrowableArray<PendingLazyDeopt>* pending_deopts =
thread->isolate()->pending_deopts();
for (intptr_t i = 0; i < pending_deopts->length(); i++) {
ASSERT((*pending_deopts)[i].fp() != frame->fp());
}
PendingLazyDeopt pair(frame->fp(), deopt_pc);
pending_deopts->Add(pair);
#if defined(DEBUG)
ValidateFrames();
#endif
// N.B.: Update the pending deopt table before updating the frame. The
// profiler may attempt a stack walk in between.
thread->isolate()->AddPendingDeopt(frame->fp(), deopt_pc);
frame->MarkForLazyDeopt();
if (FLAG_trace_deoptimization) {
@ -2168,40 +2161,18 @@ DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame,
#if !defined(TARGET_ARCH_DBC)
if (is_lazy_deopt) {
uword deopt_pc = 0;
MallocGrowableArray<PendingLazyDeopt>* pending_deopts =
isolate->pending_deopts();
for (intptr_t i = 0; i < pending_deopts->length(); i++) {
if ((*pending_deopts)[i].fp() == caller_frame->fp()) {
deopt_pc = (*pending_deopts)[i].pc();
break;
}
}
#if defined(DEBUG)
// Check for conflicting entries.
for (intptr_t i = 0; i < pending_deopts->length(); i++) {
if ((*pending_deopts)[i].fp() == caller_frame->fp()) {
ASSERT((*pending_deopts)[i].pc() == deopt_pc);
}
}
#endif
uword deopt_pc = isolate->FindPendingDeopt(caller_frame->fp());
if (FLAG_trace_deoptimization) {
THR_Print("Lazy deopt fp=%" Pp " pc=%" Pp "\n",
caller_frame->fp(), deopt_pc);
}
ASSERT(deopt_pc != 0);
// N.B.: Update frame before updating pending deopt table. The profiler
// may attempt a stack walk in between.
caller_frame->set_pc(deopt_pc);
ASSERT(caller_frame->pc() == deopt_pc);
ASSERT(optimized_code.ContainsInstructionAt(caller_frame->pc()));
for (intptr_t i = pending_deopts->length() - 1; i >= 0; i--) {
if ((*pending_deopts)[i].fp() <= caller_frame->fp()) {
pending_deopts->RemoveAt(i);
}
}
isolate->ClearPendingDeoptsAtOrBelow(caller_frame->fp());
} else {
if (FLAG_trace_deoptimization) {
THR_Print("Eager deopt fp=%" Pp " pc=%" Pp "\n",

View file

@ -1907,6 +1907,45 @@ RawClass* Isolate::GetClassForHeapWalkAt(intptr_t cid) {
}
void Isolate::AddPendingDeopt(uword fp, uword pc) {
// GrowableArray::Add is not atomic and may be interrupt by a profiler
// stack walk.
MallocGrowableArray<PendingLazyDeopt>* old_pending_deopts = pending_deopts_;
MallocGrowableArray<PendingLazyDeopt>* new_pending_deopts
= new MallocGrowableArray<PendingLazyDeopt>(
old_pending_deopts->length() + 1);
for (intptr_t i = 0; i < old_pending_deopts->length(); i++) {
ASSERT((*old_pending_deopts)[i].fp() != fp);
new_pending_deopts->Add((*old_pending_deopts)[i]);
}
PendingLazyDeopt deopt(fp, pc);
new_pending_deopts->Add(deopt);
pending_deopts_ = new_pending_deopts;
delete old_pending_deopts;
}
uword Isolate::FindPendingDeopt(uword fp) const {
for (intptr_t i = 0; i < pending_deopts_->length(); i++) {
if ((*pending_deopts_)[i].fp() == fp) {
return (*pending_deopts_)[i].pc();
}
}
FATAL("Missing pending deopt entry");
return 0;
}
void Isolate::ClearPendingDeoptsAtOrBelow(uword fp) const {
for (intptr_t i = pending_deopts_->length() - 1; i >= 0; i--) {
if ((*pending_deopts_)[i].fp() <= fp) {
pending_deopts_->RemoveAt(i);
}
}
}
#ifndef PRODUCT
static const char* ExceptionPauseInfoToServiceEnum(Dart_ExceptionPauseInfo pi) {
switch (pi) {

View file

@ -404,7 +404,10 @@ class Isolate : public BaseIsolate {
return object_id_ring_;
}
MallocGrowableArray<PendingLazyDeopt>* pending_deopts() {
void AddPendingDeopt(uword fp, uword pc);
uword FindPendingDeopt(uword fp) const;
void ClearPendingDeoptsAtOrBelow(uword fp) const;
MallocGrowableArray<PendingLazyDeopt>* pending_deopts() const {
return pending_deopts_;
}
bool IsDeoptimizing() const { return deopt_context_ != NULL; }

View file

@ -133,15 +133,7 @@ class StackFrame : public ValueObject {
fp() + (kSavedCallerPcSlotFromFp * kWordSize)));
ASSERT(raw_pc != StubCode::DeoptimizeLazyFromThrow_entry()->EntryPoint());
if (raw_pc == StubCode::DeoptimizeLazyFromReturn_entry()->EntryPoint()) {
uword fp = GetCallerFp();
MallocGrowableArray<PendingLazyDeopt>* pending_deopts =
isolate()->pending_deopts();
for (intptr_t i = 0; i < pending_deopts->length(); i++) {
if ((*pending_deopts)[i].fp() == fp) {
return (*pending_deopts)[i].pc();
}
}
FATAL("Missing pending deopt entry");
return isolate()->FindPendingDeopt(GetCallerFp());
}
return raw_pc;
}