dart-sdk/runtime/vm/ffi_callback_trampolines.cc
Martin Kustermann fb43937e20 [vm] Make Thread::IsAtSafepoint() only be true if thread is blocked at a "safe" point
During safepoint we can distinguish between

  * owner of the safepoint operation (which is running code)
  * everyone else (which are all blocked

Currently `Thread::IsAtSafepoint()` will return true for both. Since the
thread owning the safepoint operation is running, it's not actually
guaranteed that it's at "safe" point (e.g. to GC or to deopt) - it
really depends on what it's doing.

=> This CL will change it so that only actually parked threads will
have `Thread::IsAtSafepoint()`.

In order to do that we change varrious usages of `IsAtSafepoint()` to be
more precise:

  * `Thread::OwnsSafepoint()`: True if this thread owns the
    active safepoint. The thread is running.

  * `Thread::OwnsGCSafepoint()`: True if the active safepoint is a GC
    (or Deopt) safepoint and this thread owns it. The thread is running.

  * `Thread::OwnsDeoptSafepoint()`: True if the active safepoint is a
    Deopt safepoint and this thread owns it. The thread is running.

  * `Thread::CanAcquireSafepointLocks()`: True if the thread is allowed
    to acquire safepoint locks.

  * `Thread::IsAtSafepoint()`: true if this thread is parked at a
    safepoint

TEST=ci

Change-Id: I1a5a6727e84843ae79e0a344c438da19b7d6d916
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/295781
Commit-Queue: Martin Kustermann <kustermann@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2023-04-19 08:47:31 +00:00

109 lines
3.7 KiB
C++

// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/ffi_callback_trampolines.h"
#if !defined(DART_PRECOMPILED_RUNTIME)
#include "vm/code_comments.h"
#include "vm/code_observers.h"
#include "vm/compiler/assembler/assembler.h"
#include "vm/compiler/assembler/disassembler.h"
#include "vm/exceptions.h"
#endif // !defined(DART_PRECOMPILED_RUNTIME)
namespace dart {
#if !defined(DART_PRECOMPILED_RUNTIME)
uword NativeCallbackTrampolines::TrampolineForId(int32_t callback_id) {
#if defined(DART_PRECOMPILER)
ASSERT(!Enabled());
UNREACHABLE();
#else
const intptr_t trampolines_per_page = NumCallbackTrampolinesPerPage();
const intptr_t page_index = callback_id / trampolines_per_page;
const uword entry_point = trampoline_pages_[page_index]->start();
return entry_point +
(callback_id % trampolines_per_page) *
compiler::StubCodeCompiler::kNativeCallbackTrampolineSize;
#endif
}
void NativeCallbackTrampolines::AllocateTrampoline() {
#if defined(DART_PRECOMPILER)
ASSERT(!Enabled());
UNREACHABLE();
#else
// Callback IDs are limited to 32-bits for trampoline compactness.
if (kWordSize == 8 &&
!Utils::IsInt(32, next_callback_id_ + NumCallbackTrampolinesPerPage())) {
Exceptions::ThrowOOM();
}
if (trampolines_left_on_page_ == 0) {
// Fuchsia requires memory to be allocated with ZX_RIGHT_EXECUTE in order
// to be flipped to kReadExecute after being kReadWrite.
VirtualMemory* const memory = VirtualMemory::AllocateAligned(
/*size=*/VirtualMemory::PageSize(),
/*alignment=*/VirtualMemory::PageSize(),
/*is_executable=*/true,
/*is_compressed=*/false,
/*name=*/"Dart VM FFI callback trampolines");
memory->Protect(VirtualMemory::kReadWrite);
if (memory == nullptr) {
Exceptions::ThrowOOM();
}
trampoline_pages_.Add(memory);
compiler::Assembler assembler(/*object_pool_builder=*/nullptr);
compiler::StubCodeCompiler stubCodeCompiler(&assembler);
stubCodeCompiler.GenerateJITCallbackTrampolines(next_callback_id_);
MemoryRegion region(memory->address(), memory->size());
assembler.FinalizeInstructions(region);
memory->Protect(VirtualMemory::kReadExecute);
#if !defined(PRODUCT)
const char* name = "FfiJitCallbackTrampolines";
ASSERT(!Thread::Current()->OwnsSafepoint());
if (CodeObservers::AreActive()) {
const auto& comments = CreateCommentsFrom(&assembler);
CodeObservers::NotifyAll(name,
/*base=*/memory->start(),
/*prologue_offset=*/0,
/*size=*/assembler.CodeSize(),
/*optimized=*/false, // not really relevant
&comments);
}
#endif
#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
if (FLAG_disassemble_stubs && FLAG_support_disassembler) {
DisassembleToStdout formatter;
THR_Print(
"Code for native callback trampolines "
"[%" Pd " -> %" Pd "]: {\n",
next_callback_id_,
next_callback_id_ + NumCallbackTrampolinesPerPage() - 1);
const auto& comments = CreateCommentsFrom(&assembler);
Disassembler::Disassemble(memory->start(),
memory->start() + assembler.CodeSize(),
&formatter, &comments);
}
#endif
trampolines_left_on_page_ = NumCallbackTrampolinesPerPage();
}
trampolines_left_on_page_--;
next_callback_id_++;
#endif // defined(DART_PRECOMPILER)
}
#endif // !defined(DART_PRECOMPILED_RUNTIME)
} // namespace dart