mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 15:17:07 +00:00
Make adding a pending deopt atomic.
Issue #27496 R=fschneider@google.com Review URL: https://codereview.chromium.org/2395123003 .
This commit is contained in:
parent
3d28d08413
commit
b85956e6d9
4 changed files with 49 additions and 44 deletions
|
@ -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",
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue