perf(runtime): inline header checks into _StringRelease
_StringReleaseCheck was a separate 4-argument call on every string release (~350M per compiler self-compile) and showed up as 12.7% of all instructions on its own. The three sanity checks (double-free, length, capacity) now run inline in _StringRelease with DiagAbort as the cold path; the diagnostics remain always-on. Compiler self-compile: 9.2G -> 8.7G instructions, 0.80 s -> 0.78 s.
This commit is contained in:
parent
475d579968
commit
9d08c7913a
|
|
@ -56,7 +56,6 @@ procedure _ClassRelease(UserPtr: Pointer);
|
|||
function _ClassAlloc(Size: Int64; Cleanup: Pointer): Pointer;
|
||||
procedure _ClassFree(UserPtr: Pointer);
|
||||
function _HasClassAttribute(AClassTI, AAttrTI: Pointer): Boolean;
|
||||
procedure _StringReleaseCheck(DataPtr: Pointer; RefCount, Length, Capacity: Integer);
|
||||
procedure _AbstractMethodError;
|
||||
procedure _LeakTrackerEnable;
|
||||
procedure _LeakTrackerRegister(UserPtr: Pointer; ClassName: Pointer;
|
||||
|
|
@ -115,16 +114,6 @@ begin
|
|||
_libc_abort;
|
||||
end;
|
||||
|
||||
procedure _StringReleaseCheck(DataPtr: Pointer; RefCount, Length, Capacity: Integer);
|
||||
begin
|
||||
if RefCount < -1 then
|
||||
DiagAbort('blaise: _StringRelease double-free (refcount < -1)', 51);
|
||||
if (Length < 0) or (Length > MAX_1GIB) then
|
||||
DiagAbort('blaise: _StringRelease corrupted header (bad length)', 55);
|
||||
if (Capacity < Length) or (Capacity > MAX_1GIB) then
|
||||
DiagAbort('blaise: _StringRelease corrupted header (bad capacity)', 57);
|
||||
end;
|
||||
|
||||
procedure _AbstractMethodError;
|
||||
begin
|
||||
DiagAbort('Runtime error: abstract method called.', 39);
|
||||
|
|
@ -454,7 +443,16 @@ begin
|
|||
if RC^ = IMMORTAL then Exit;
|
||||
LN := Base + 4;
|
||||
CP := Base + 8;
|
||||
_StringReleaseCheck(Ptr, RC^, LN^, CP^);
|
||||
{ Header sanity checks inlined — this is the hottest runtime function
|
||||
(one call per string release, ~350M per compiler self-compile) and the
|
||||
out-of-line _StringReleaseCheck call doubled its cost. DiagAbort is
|
||||
the cold path. }
|
||||
if RC^ < -1 then
|
||||
DiagAbort('blaise: _StringRelease double-free (refcount < -1)', 51);
|
||||
if (LN^ < 0) or (LN^ > MAX_1GIB) then
|
||||
DiagAbort('blaise: _StringRelease corrupted header (bad length)', 55);
|
||||
if (CP^ < LN^) or (CP^ > MAX_1GIB) then
|
||||
DiagAbort('blaise: _StringRelease corrupted header (bad capacity)', 57);
|
||||
OldRC := _AtomicSubInt32(RC, 1);
|
||||
if OldRC = 1 then
|
||||
begin
|
||||
|
|
|
|||
Loading…
Reference in a new issue