[vm] Use _setjmp instead of setjmp on MacOS/iOS
setjmp is extremely expensive on MacOS/iOS as it always saves signal mask. Introduce DART_SETJMP / DART_LONGJMP macros to use _setjmp instead of setjmp on MacOS/iOS. DeltaBlue on Mac/arm64 on the interpreter: 179585.3 us -> 58347.9 us. (3x faster) TEST=ci Issue: https://github.com/dart-lang/sdk/issues/60205 Change-Id: I2122f2eb4d5de66ae2ef904a7034af1ed09f1d07 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/412320 Reviewed-by: Ryan Macnak <rmacnak@google.com> Commit-Queue: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
committed by
Commit Queue
parent
462bcaf52a
commit
ebb7e1061c
@@ -297,6 +297,15 @@ struct simd128_value_t {
|
||||
#error Automatic compiler detection failed.
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
// Avoid expensive saving of sigmask in setjmp/longjmp.
|
||||
#define DART_SETJMP _setjmp
|
||||
#define DART_LONGJMP _longjmp
|
||||
#else
|
||||
#define DART_SETJMP setjmp
|
||||
#define DART_LONGJMP longjmp
|
||||
#endif
|
||||
|
||||
#if !defined(TARGET_ARCH_ARM) && !defined(TARGET_ARCH_X64) && \
|
||||
!defined(TARGET_ARCH_IA32) && !defined(TARGET_ARCH_ARM64) && \
|
||||
!defined(TARGET_ARCH_RISCV32) && !defined(TARGET_ARCH_RISCV64)
|
||||
|
||||
@@ -92,7 +92,7 @@ static void StackAllocatedLongJumpHelper(int* ptr, LongJumpScope* jump) {
|
||||
ISOLATE_UNIT_TEST_CASE(StackAllocatedLongJump) {
|
||||
LongJumpScope jump;
|
||||
int data = 1;
|
||||
if (setjmp(*jump.Set()) == 0) {
|
||||
if (DART_SETJMP(*jump.Set()) == 0) {
|
||||
StackAllocatedLongJumpHelper(&data, &jump);
|
||||
UNREACHABLE();
|
||||
} else {
|
||||
@@ -145,7 +145,7 @@ ISOLATE_UNIT_TEST_CASE(StackResourceLongJump) {
|
||||
{
|
||||
LongJumpScope jump;
|
||||
int data = 1;
|
||||
if (setjmp(*jump.Set()) == 0) {
|
||||
if (DART_SETJMP(*jump.Set()) == 0) {
|
||||
StackResourceLongJumpHelper(&data, &jump);
|
||||
UNREACHABLE();
|
||||
} else {
|
||||
|
||||
@@ -114,7 +114,7 @@ static ErrorPtr BootstrapFromKernelSingleProgram(
|
||||
std::unique_ptr<kernel::Program> program) {
|
||||
Zone* zone = thread->zone();
|
||||
LongJumpScope jump;
|
||||
if (setjmp(*jump.Set()) == 0) {
|
||||
if (DART_SETJMP(*jump.Set()) == 0) {
|
||||
kernel::KernelLoader loader(program.get(), /*uri_to_source_table=*/nullptr);
|
||||
|
||||
auto isolate_group = thread->isolate_group();
|
||||
|
||||
@@ -199,7 +199,7 @@ bool ClassFinalizer::ProcessPendingClasses() {
|
||||
}
|
||||
|
||||
LongJumpScope jump;
|
||||
if (setjmp(*jump.Set()) == 0) {
|
||||
if (DART_SETJMP(*jump.Set()) == 0) {
|
||||
GrowableObjectArray& class_array = GrowableObjectArray::Handle();
|
||||
class_array = object_store->pending_classes();
|
||||
ASSERT(!class_array.IsNull());
|
||||
@@ -827,7 +827,7 @@ ErrorPtr ClassFinalizer::LoadClassMembers(const Class& cls) {
|
||||
ASSERT(!cls.is_finalized());
|
||||
|
||||
LongJumpScope jump;
|
||||
if (setjmp(*jump.Set()) == 0) {
|
||||
if (DART_SETJMP(*jump.Set()) == 0) {
|
||||
cls.EnsureDeclarationLoaded();
|
||||
ASSERT(cls.is_type_finalized());
|
||||
ClassFinalizer::FinalizeClass(cls);
|
||||
|
||||
@@ -364,7 +364,7 @@ static void Jump(const Error& error) {
|
||||
|
||||
ErrorPtr Precompiler::CompileAll() {
|
||||
LongJumpScope jump;
|
||||
if (setjmp(*jump.Set()) == 0) {
|
||||
if (DART_SETJMP(*jump.Set()) == 0) {
|
||||
Precompiler precompiler(Thread::Current());
|
||||
precompiler.DoCompileAll();
|
||||
precompiler.ReportStats();
|
||||
@@ -3486,7 +3486,7 @@ bool PrecompileParsedFunctionHelper::GenerateCode(FlowGraph* flow_graph) {
|
||||
|
||||
while (!done) {
|
||||
LongJumpScope jump;
|
||||
const intptr_t val = setjmp(*jump.Set());
|
||||
const intptr_t val = DART_SETJMP(*jump.Set());
|
||||
if (val == 0) {
|
||||
// Even in bare instructions mode we don't directly add objects into
|
||||
// the global object pool because code generation can bail out
|
||||
|
||||
@@ -1278,7 +1278,7 @@ class CallSiteInliner : public ValueObject {
|
||||
|
||||
// Install bailout jump.
|
||||
LongJumpScope jump;
|
||||
if (setjmp(*jump.Set()) == 0) {
|
||||
if (DART_SETJMP(*jump.Set()) == 0) {
|
||||
// Load IC data for the callee.
|
||||
ZoneGrowableArray<const ICData*>* ic_data_array =
|
||||
new (Z) ZoneGrowableArray<const ICData*>();
|
||||
|
||||
@@ -498,7 +498,7 @@ CodePtr CompileParsedFunctionHelper::Compile() {
|
||||
while (!done) {
|
||||
*result = Code::null();
|
||||
LongJumpScope jump;
|
||||
if (setjmp(*jump.Set()) == 0) {
|
||||
if (DART_SETJMP(*jump.Set()) == 0) {
|
||||
FlowGraph* flow_graph = nullptr;
|
||||
ZoneGrowableArray<const ICData*>* ic_data_array = nullptr;
|
||||
|
||||
@@ -673,7 +673,7 @@ static ObjectPtr CompileFunctionHelper(const Function& function,
|
||||
ASSERT(!FLAG_precompiled_mode);
|
||||
ASSERT(!optimized || function.WasCompiled() || function.ForceOptimize());
|
||||
LongJumpScope jump;
|
||||
if (setjmp(*jump.Set()) == 0) {
|
||||
if (DART_SETJMP(*jump.Set()) == 0) {
|
||||
StackZone stack_zone(thread);
|
||||
Zone* const zone = stack_zone.GetZone();
|
||||
const bool trace_compiler =
|
||||
@@ -889,7 +889,7 @@ void Compiler::ComputeLocalVarDescriptors(const Code& code) {
|
||||
Zone* zone = thread->zone();
|
||||
CompilerState state(thread, /*is_aot=*/false, /*is_optimizing=*/false);
|
||||
LongJumpScope jump;
|
||||
if (setjmp(*jump.Set()) == 0) {
|
||||
if (DART_SETJMP(*jump.Set()) == 0) {
|
||||
ParsedFunction* parsed_function =
|
||||
new ParsedFunction(thread, Function::ZoneHandle(zone, function.ptr()));
|
||||
ZoneGrowableArray<const ICData*>* ic_data_array =
|
||||
|
||||
@@ -671,7 +671,7 @@ NO_SANITIZE_SAFE_STACK // This function manipulates the safestack pointer.
|
||||
tsan_utils->exception_pc = program_counter;
|
||||
tsan_utils->exception_sp = stack_pointer;
|
||||
tsan_utils->exception_fp = frame_pointer;
|
||||
longjmp(*(tsan_utils->setjmp_buffer), 1);
|
||||
DART_LONGJMP(*(tsan_utils->setjmp_buffer), 1);
|
||||
}
|
||||
#endif // defined(USING_THREAD_SANITIZER)
|
||||
|
||||
|
||||
@@ -282,7 +282,7 @@ class ScavengerVisitorBase : public ObjectPointerVisitor,
|
||||
page_space_->AcquireLock(freelist_);
|
||||
|
||||
LongJumpScope jump(thread_);
|
||||
if (setjmp(*jump.Set()) == 0) {
|
||||
if (DART_SETJMP(*jump.Set()) == 0) {
|
||||
scavenger_->IterateRoots(this);
|
||||
} else {
|
||||
ASSERT(scavenger_->abort_);
|
||||
@@ -291,7 +291,7 @@ class ScavengerVisitorBase : public ObjectPointerVisitor,
|
||||
|
||||
void ProcessSurvivors() {
|
||||
LongJumpScope jump(thread_);
|
||||
if (setjmp(*jump.Set()) == 0) {
|
||||
if (DART_SETJMP(*jump.Set()) == 0) {
|
||||
// Iterate until all work has been drained.
|
||||
do {
|
||||
ProcessToSpace();
|
||||
@@ -305,7 +305,7 @@ class ScavengerVisitorBase : public ObjectPointerVisitor,
|
||||
void ProcessAll() {
|
||||
TIMELINE_FUNCTION_GC_DURATION(thread_, "ProcessToSpace");
|
||||
LongJumpScope jump(thread_);
|
||||
if (setjmp(*jump.Set()) == 0) {
|
||||
if (DART_SETJMP(*jump.Set()) == 0) {
|
||||
do {
|
||||
do {
|
||||
ProcessToSpace();
|
||||
@@ -320,7 +320,7 @@ class ScavengerVisitorBase : public ObjectPointerVisitor,
|
||||
|
||||
void ProcessWeakProperties() {
|
||||
LongJumpScope jump(thread_);
|
||||
if (setjmp(*jump.Set()) == 0) {
|
||||
if (DART_SETJMP(*jump.Set()) == 0) {
|
||||
ProcessWeakPropertiesScoped();
|
||||
} else {
|
||||
ASSERT(scavenger_->abort_);
|
||||
|
||||
@@ -51,7 +51,7 @@ class InterpreterSetjmpBuffer {
|
||||
void Longjmp() {
|
||||
// "This" is now the last setjmp buffer.
|
||||
interpreter_->set_last_setjmp_buffer(this);
|
||||
longjmp(buffer_, 1);
|
||||
DART_LONGJMP(buffer_, 1);
|
||||
}
|
||||
|
||||
explicit InterpreterSetjmpBuffer(Interpreter* interpreter) {
|
||||
@@ -532,7 +532,7 @@ static DART_NOINLINE bool InvokeRuntime(Thread* thread,
|
||||
RuntimeFunction drt,
|
||||
const NativeArguments& args) {
|
||||
InterpreterSetjmpBuffer buffer(interpreter);
|
||||
if (!setjmp(buffer.buffer_)) {
|
||||
if (!DART_SETJMP(buffer.buffer_)) {
|
||||
thread->set_vm_tag(reinterpret_cast<uword>(drt));
|
||||
drt(args);
|
||||
thread->set_vm_tag(VMTag::kDartInterpretedTagId);
|
||||
@@ -581,7 +581,7 @@ DART_NOINLINE bool Interpreter::InvokeCompiled(Thread* thread,
|
||||
Exit(thread, *FP, call_top + 1, *pc);
|
||||
{
|
||||
InterpreterSetjmpBuffer buffer(this);
|
||||
if (!setjmp(buffer.buffer_)) {
|
||||
if (!DART_SETJMP(buffer.buffer_)) {
|
||||
#if defined(USING_SIMULATOR)
|
||||
// We need to beware that bouncing between the interpreter and the
|
||||
// simulator may exhaust the C stack before exhausting either the
|
||||
|
||||
@@ -1218,7 +1218,7 @@ ObjectPtr ProgramReloadContext::ReloadPhase2LoadKernel(
|
||||
Thread* thread = Thread::Current();
|
||||
|
||||
LongJumpScope jump;
|
||||
if (setjmp(*jump.Set()) == 0) {
|
||||
if (DART_SETJMP(*jump.Set()) == 0) {
|
||||
const Object& tmp = kernel::KernelLoader::LoadEntireProgram(program);
|
||||
if (tmp.IsError()) {
|
||||
return tmp.ptr();
|
||||
|
||||
@@ -382,7 +382,7 @@ ObjectPtr EvaluateStaticConstFieldInitializer(const Field& field) {
|
||||
ASSERT(field.is_static() && field.is_const());
|
||||
|
||||
LongJumpScope jump;
|
||||
if (setjmp(*jump.Set()) == 0) {
|
||||
if (DART_SETJMP(*jump.Set()) == 0) {
|
||||
Thread* thread = Thread::Current();
|
||||
Zone* zone = thread->zone();
|
||||
TranslationHelper helper(thread);
|
||||
@@ -468,7 +468,7 @@ ObjectPtr EvaluateMetadata(const Library& library,
|
||||
intptr_t kernel_offset,
|
||||
bool is_annotations_offset) {
|
||||
LongJumpScope jump;
|
||||
if (setjmp(*jump.Set()) == 0) {
|
||||
if (DART_SETJMP(*jump.Set()) == 0) {
|
||||
Thread* thread = Thread::Current();
|
||||
Zone* zone = thread->zone();
|
||||
TranslationHelper helper(thread);
|
||||
@@ -572,7 +572,7 @@ ObjectPtr ParameterDescriptorBuilder::BuildParameterDescriptor(
|
||||
|
||||
ObjectPtr BuildParameterDescriptor(const Function& function) {
|
||||
LongJumpScope jump;
|
||||
if (setjmp(*jump.Set()) == 0) {
|
||||
if (DART_SETJMP(*jump.Set()) == 0) {
|
||||
Thread* thread = Thread::Current();
|
||||
Zone* zone = thread->zone();
|
||||
|
||||
|
||||
@@ -526,7 +526,7 @@ ObjectPtr KernelLoader::LoadProgram(bool process_pending_classes) {
|
||||
}
|
||||
|
||||
LongJumpScope jump;
|
||||
if (setjmp(*jump.Set()) == 0) {
|
||||
if (DART_SETJMP(*jump.Set()) == 0) {
|
||||
// Note that `problemsAsJson` on Component is implicitly skipped.
|
||||
const intptr_t length = program_->library_count();
|
||||
for (intptr_t i = 0; i < length; i++) {
|
||||
@@ -652,7 +652,7 @@ void KernelLoader::FindModifiedLibraries(Program* program,
|
||||
intptr_t* p_num_procedures) {
|
||||
LongJumpScope jump;
|
||||
Zone* zone = Thread::Current()->zone();
|
||||
if (setjmp(*jump.Set()) == 0) {
|
||||
if (DART_SETJMP(*jump.Set()) == 0) {
|
||||
if (force_reload) {
|
||||
// If a reload is being forced we mark all libraries as having
|
||||
// been modified.
|
||||
|
||||
@@ -38,7 +38,7 @@ void LongJumpScope::Jump(int value) {
|
||||
|
||||
// Destruct all the active StackResource objects.
|
||||
StackResource::UnwindAbove(thread, top_);
|
||||
longjmp(environment_, value);
|
||||
DART_LONGJMP(environment_, value);
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ ISOLATE_UNIT_TEST_CASE(LongJump) {
|
||||
LongJumpScope* base = Thread::Current()->long_jump_base();
|
||||
{
|
||||
LongJumpScope jump;
|
||||
if (setjmp(*jump.Set()) == 0) {
|
||||
if (DART_SETJMP(*jump.Set()) == 0) {
|
||||
LongJumpHelper(&jump);
|
||||
UNREACHABLE();
|
||||
} else {
|
||||
|
||||
@@ -3483,7 +3483,7 @@ ObjectPtr ReadMessage(Thread* thread, Message* message) {
|
||||
} else {
|
||||
RELEASE_ASSERT(message->IsSnapshot());
|
||||
LongJumpScope jump(thread);
|
||||
if (setjmp(*jump.Set()) == 0) {
|
||||
if (DART_SETJMP(*jump.Set()) == 0) {
|
||||
MessageDeserializer deserializer(thread, message);
|
||||
return deserializer.Deserialize();
|
||||
} else {
|
||||
|
||||
@@ -2441,7 +2441,7 @@ class ObjectGraphCopier : public StackResource {
|
||||
|
||||
{
|
||||
LongJumpScope jump; // e.g. for OOMs.
|
||||
if (setjmp(*jump.Set()) == 0) {
|
||||
if (DART_SETJMP(*jump.Set()) == 0) {
|
||||
result = CopyObjectGraphInternal(root, &exception_msg);
|
||||
// Any allocated external typed data must have finalizers attached so
|
||||
// memory will get free()ed.
|
||||
|
||||
@@ -55,7 +55,7 @@ class SimulatorSetjmpBuffer {
|
||||
void Longjmp() {
|
||||
// "This" is now the last setjmp buffer.
|
||||
simulator_->set_last_setjmp_buffer(this);
|
||||
longjmp(buffer_, 1);
|
||||
DART_LONGJMP(buffer_, 1);
|
||||
}
|
||||
|
||||
explicit SimulatorSetjmpBuffer(Simulator* sim) {
|
||||
@@ -1416,7 +1416,7 @@ void Simulator::SupervisorCall(Instr* instr) {
|
||||
case Instr::kSimulatorRedirectCode: {
|
||||
SimulatorSetjmpBuffer buffer(this);
|
||||
|
||||
if (!setjmp(buffer.buffer_)) {
|
||||
if (!DART_SETJMP(buffer.buffer_)) {
|
||||
int32_t saved_lr = get_register(LR);
|
||||
Redirection* redirection = Redirection::FromSvcInstruction(instr);
|
||||
uword external = redirection->external_function();
|
||||
|
||||
@@ -58,7 +58,7 @@ class SimulatorSetjmpBuffer {
|
||||
void Longjmp() {
|
||||
// "This" is now the last setjmp buffer.
|
||||
simulator_->set_last_setjmp_buffer(this);
|
||||
longjmp(buffer_, 1);
|
||||
DART_LONGJMP(buffer_, 1);
|
||||
}
|
||||
|
||||
explicit SimulatorSetjmpBuffer(Simulator* sim) {
|
||||
@@ -1677,7 +1677,7 @@ void Simulator::DoRedirectedCall(Instr* instr) {
|
||||
memory_.FlushAll();
|
||||
|
||||
SimulatorSetjmpBuffer buffer(this);
|
||||
if (!setjmp(buffer.buffer_)) {
|
||||
if (!DART_SETJMP(buffer.buffer_)) {
|
||||
int64_t saved_lr = get_register(LR);
|
||||
Redirection* redirection = Redirection::FromHltInstruction(instr);
|
||||
uword external = redirection->external_function();
|
||||
|
||||
@@ -43,7 +43,7 @@ class SimulatorSetjmpBuffer {
|
||||
void Longjmp() {
|
||||
// "This" is now the last setjmp buffer.
|
||||
simulator_->set_last_setjmp_buffer(this);
|
||||
longjmp(buffer_, 1);
|
||||
DART_LONGJMP(buffer_, 1);
|
||||
}
|
||||
|
||||
explicit SimulatorSetjmpBuffer(Simulator* sim) {
|
||||
@@ -2109,7 +2109,7 @@ void Simulator::InterpretECALL(Instr instr) {
|
||||
memory_.FlushAll();
|
||||
|
||||
SimulatorSetjmpBuffer buffer(this);
|
||||
if (!setjmp(buffer.buffer_)) {
|
||||
if (!DART_SETJMP(buffer.buffer_)) {
|
||||
uintx_t saved_ra = get_xreg(RA);
|
||||
Redirection* redirection = Redirection::FromECallInstruction(pc_);
|
||||
uword external = redirection->external_function();
|
||||
|
||||
+1
-1
@@ -321,7 +321,7 @@ struct TsanUtils {
|
||||
// implementation.
|
||||
// -> See https://dartbug.com/47472#issuecomment-948235479 for details.
|
||||
#if defined(USING_THREAD_SANITIZER)
|
||||
void* setjmp_function = reinterpret_cast<void*>(&setjmp);
|
||||
void* setjmp_function = reinterpret_cast<void*>(&DART_SETJMP);
|
||||
#else
|
||||
// MSVC (on Windows) is not happy with getting address of purely intrinsic.
|
||||
void* setjmp_function = nullptr;
|
||||
|
||||
@@ -1034,7 +1034,7 @@ static void RunLockerWithLongJumpTest() {
|
||||
LockType lock;
|
||||
for (intptr_t i = 0; i < kNumIterations; ++i) {
|
||||
LongJumpScope jump;
|
||||
if (setjmp(*jump.Set()) == 0) {
|
||||
if (DART_SETJMP(*jump.Set()) == 0) {
|
||||
LockerType locker(Thread::Current(), &lock);
|
||||
execution_count = execution_count + 1;
|
||||
Thread::Current()->long_jump_base()->Jump(
|
||||
|
||||
@@ -223,7 +223,7 @@ static CodePtr RetryCompilationWithFarBranches(
|
||||
volatile intptr_t far_branch_level = 0;
|
||||
while (true) {
|
||||
LongJumpScope jump;
|
||||
if (setjmp(*jump.Set()) == 0) {
|
||||
if (DART_SETJMP(*jump.Set()) == 0) {
|
||||
// To use the already-defined __ Macro !
|
||||
compiler::Assembler assembler(nullptr, far_branch_level);
|
||||
return fun(assembler);
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
volatile intptr_t far_branch_level = 0; \
|
||||
while (true) { \
|
||||
LongJumpScope jump(thread); \
|
||||
if (setjmp(*jump.Set()) == 0) { \
|
||||
if (DART_SETJMP(*jump.Set()) == 0) { \
|
||||
compiler::ObjectPoolBuilder object_pool_builder; \
|
||||
compiler::Assembler assembler(&object_pool_builder, far_branch_level); \
|
||||
AssemblerTest test("" #name, &assembler, thread->zone()); \
|
||||
|
||||
Reference in New Issue
Block a user