mirror of
https://github.com/luau-lang/luau.git
synced 2025-04-01 17:30:53 +01:00
Significantly improve MSVC interpreter code generation
This patch adds an __assume statement for passed assertations and switches the interpreter loop to using a while-switch instead of a goto-switch loop. This seems to prevent the performance regression experienced on MSVC2022.
This commit is contained in:
parent
2621488abe
commit
e1e4a7aab2
3 changed files with 27 additions and 22 deletions
|
@ -166,12 +166,6 @@ if(LUAU_EXTERN_C)
|
|||
target_compile_definitions(Luau.CodeGen PUBLIC LUACODEGEN_API=extern\"C\")
|
||||
endif()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" AND MSVC_VERSION GREATER_EQUAL 1924)
|
||||
# disable partial redundancy elimination which regresses interpreter codegen substantially in VS2022:
|
||||
# https://developercommunity.visualstudio.com/t/performance-regression-on-a-complex-interpreter-lo/1631863
|
||||
set_source_files_properties(VM/src/lvmexecute.cpp PROPERTIES COMPILE_FLAGS /d2ssa-pre-)
|
||||
endif()
|
||||
|
||||
if (NOT MSVC)
|
||||
# disable support for math_errno which allows compilers to lower sqrt() into a single CPU instruction
|
||||
target_compile_options(Luau.VM PRIVATE -fno-math-errno)
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#define LUAU_UNLIKELY(x) x
|
||||
#define LUAU_UNREACHABLE() __assume(false)
|
||||
#define LUAU_DEBUGBREAK() __debugbreak()
|
||||
#define LUAU_ASSUME(x) __assume(x)
|
||||
#else
|
||||
#define LUAU_NORETURN __attribute__((__noreturn__))
|
||||
#define LUAU_NOINLINE __attribute__((noinline))
|
||||
|
@ -18,6 +19,7 @@
|
|||
#define LUAU_UNLIKELY(x) __builtin_expect(x, 0)
|
||||
#define LUAU_UNREACHABLE() __builtin_unreachable()
|
||||
#define LUAU_DEBUGBREAK() __builtin_trap()
|
||||
#define LUAU_ASSUME(x) __attribute__((assume(x)));
|
||||
#endif
|
||||
|
||||
// LUAU_FALLTHROUGH is a C++11-compatible alternative to [[fallthrough]] for use in the VM library
|
||||
|
@ -65,7 +67,7 @@ LUAU_NOINLINE inline int assertCallHandler(const char* expression, const char* f
|
|||
#define LUAU_ASSERT(expr) ((void)(!!(expr) || (Luau::assertCallHandler(#expr, __FILE__, __LINE__, __FUNCTION__) && (LUAU_DEBUGBREAK(), 0))))
|
||||
#define LUAU_ASSERTENABLED
|
||||
#else
|
||||
#define LUAU_ASSERT(expr) (void)sizeof(!!(expr))
|
||||
#define LUAU_ASSERT(expr) LUAU_ASSUME(expr)
|
||||
#endif
|
||||
|
||||
namespace Luau
|
||||
|
|
|
@ -77,7 +77,7 @@ LUAU_DYNAMIC_FASTFLAG(LuauPopIncompleteCi)
|
|||
if (L->status != 0) \
|
||||
{ \
|
||||
L->ci->savedpc--; \
|
||||
goto exit; \
|
||||
return; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
@ -123,10 +123,12 @@ LUAU_DYNAMIC_FASTFLAG(LuauPopIncompleteCi)
|
|||
#if VM_USE_CGOTO
|
||||
#define VM_CASE(op) CASE_##op:
|
||||
#define VM_NEXT() goto*(SingleStep ? &&dispatch : kDispatchTable[LUAU_INSN_OP(*pc)])
|
||||
#define VM_START() VM_NEXT()
|
||||
#define VM_CONTINUE(op) goto* kDispatchTable[uint8_t(op)]
|
||||
#else
|
||||
#define VM_CASE(op) case op:
|
||||
#define VM_NEXT() goto dispatch
|
||||
#define VM_NEXT() continue;
|
||||
#define VM_START()
|
||||
#define VM_CONTINUE(op) \
|
||||
dispatchOp = uint8_t(op); \
|
||||
goto dispatchContinue
|
||||
|
@ -231,10 +233,9 @@ reentry:
|
|||
base = L->base;
|
||||
k = cl->l.p->k;
|
||||
|
||||
VM_NEXT(); // starts the interpreter "loop"
|
||||
VM_START(); // starts the interpreter "loop"
|
||||
|
||||
{
|
||||
dispatch:
|
||||
while (true) {
|
||||
// Note: this code doesn't always execute! on some platforms we use computed goto which bypasses all of this unless we run in single-step mode
|
||||
// Therefore only ever put assertions here.
|
||||
LUAU_ASSERT(base == L->base && L->base == L->ci->base);
|
||||
|
@ -249,7 +250,7 @@ reentry:
|
|||
|
||||
// allow debugstep hook to put thread into error/yield state
|
||||
if (L->status != 0)
|
||||
goto exit;
|
||||
return;
|
||||
}
|
||||
|
||||
#if VM_USE_CGOTO
|
||||
|
@ -976,7 +977,7 @@ reentry:
|
|||
|
||||
// yield
|
||||
if (n < 0)
|
||||
goto exit;
|
||||
return;
|
||||
|
||||
// ci is our callinfo, cip is our parent
|
||||
CallInfo* ci = L->ci;
|
||||
|
@ -1039,7 +1040,7 @@ reentry:
|
|||
// we're done!
|
||||
if (LUAU_UNLIKELY(ci->flags & LUA_CALLINFO_RETURN))
|
||||
{
|
||||
goto exit;
|
||||
return;
|
||||
}
|
||||
|
||||
LUAU_ASSERT(isLua(L->ci));
|
||||
|
@ -1053,7 +1054,7 @@ reentry:
|
|||
if (L->global->ecb.enter(L, nextproto) == 1)
|
||||
goto reentry;
|
||||
else
|
||||
goto exit;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -2371,12 +2372,17 @@ reentry:
|
|||
|
||||
pc += LUAU_INSN_D(insn);
|
||||
LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode));
|
||||
VM_NEXT();
|
||||
break;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
if (unsigned(index) < unsigned(sizearray))
|
||||
{
|
||||
VM_NEXT();
|
||||
}
|
||||
|
||||
int sizenode = 1 << h->lsizenode;
|
||||
|
||||
// then we advance index through the hash portion
|
||||
|
@ -2392,12 +2398,17 @@ reentry:
|
|||
|
||||
pc += LUAU_INSN_D(insn);
|
||||
LUAU_ASSERT(unsigned(pc - cl->l.p->code) < unsigned(cl->l.p->sizecode));
|
||||
VM_NEXT();
|
||||
break;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
if (unsigned(index - sizearray) < unsigned(sizenode))
|
||||
{
|
||||
VM_NEXT();
|
||||
}
|
||||
|
||||
// fallthrough to exit
|
||||
pc++;
|
||||
VM_NEXT();
|
||||
|
@ -2487,7 +2498,7 @@ reentry:
|
|||
if (L->global->ecb.enter(L, p) == 1)
|
||||
goto reentry;
|
||||
else
|
||||
goto exit;
|
||||
return;
|
||||
#else
|
||||
LUAU_ASSERT(!"Opcode is only valid when VM_HAS_NATIVE is defined");
|
||||
LUAU_UNREACHABLE();
|
||||
|
@ -2975,7 +2986,7 @@ reentry:
|
|||
|
||||
// allow debugbreak hook to put thread into error/yield state
|
||||
if (L->status != 0)
|
||||
goto exit;
|
||||
return;
|
||||
}
|
||||
|
||||
VM_CONTINUE(op);
|
||||
|
@ -3047,8 +3058,6 @@ reentry:
|
|||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
exit:;
|
||||
}
|
||||
|
||||
void luau_execute(lua_State* L)
|
||||
|
|
Loading…
Add table
Reference in a new issue