diff options
-rw-r--r-- | lib/nimbase.h | 10 | ||||
-rw-r--r-- | lib/system.nim | 10 | ||||
-rw-r--r-- | lib/system/sysstr.nim | 27 |
3 files changed, 38 insertions, 9 deletions
diff --git a/lib/nimbase.h b/lib/nimbase.h index 70391024f..34a2e43e7 100644 --- a/lib/nimbase.h +++ b/lib/nimbase.h @@ -373,11 +373,13 @@ static N_INLINE(NI32, float32ToInt32)(float x) { #define float64ToInt64(x) ((NI64) (x)) +#define NIM_STRLIT_FLAG ((NU)(1) << ((NIM_INTBITS) - 2)) /* This has to be the same as system.strlitFlag! */ + #define STRING_LITERAL(name, str, length) \ - static const struct { \ - TGenericSeq Sup; \ - NIM_CHAR data[(length) + 1]; \ - } name = {{length, length}, str} + static const struct { \ + TGenericSeq Sup; \ + NIM_CHAR data[(length) + 1]; \ + } name = {{length, (NI) ((NU)length | NIM_STRLIT_FLAG)}, str} typedef struct TStringDesc* string; diff --git a/lib/system.nim b/lib/system.nim index a4460570a..cc5ef9810 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -409,8 +409,7 @@ when not defined(JS): when not defined(JS) and not defined(nimscript): template space(s: PGenericSeq): int {.dirty.} = - s.reserved and not seqShallowFlag - + s.reserved and not (seqShallowFlag or strlitFlag) include "system/hti" type @@ -1329,6 +1328,9 @@ const ## "amd64", "mips", "mipsel", "arm", "arm64", "mips64", "mips64el". seqShallowFlag = low(int) + strlitFlag = 1 shl (sizeof(int)*8 - 2) # later versions of the codegen \ + # emit this flag + # for string literals, it allows for some optimizations. {.push profiler: off.} when defined(nimKnowsNimvm): @@ -3720,7 +3722,9 @@ proc shallow*(s: var string) {.noSideEffect, inline.} = ## purposes. when not defined(JS) and not defined(nimscript): var s = cast[PGenericSeq](s) - s.reserved = s.reserved or seqShallowFlag + # string literals cannot become 'shallow': + if (s.reserved and strlitFlag) == 0: + s.reserved = s.reserved or seqShallowFlag type NimNodeObj = object diff --git a/lib/system/sysstr.nim b/lib/system/sysstr.nim index 9ba53a5b8..8270bc525 100644 --- a/lib/system/sysstr.nim +++ b/lib/system/sysstr.nim @@ -95,6 +95,11 @@ proc cstrToNimstr(str: cstring): NimString {.compilerRtl.} = if str == nil: NimString(nil) else: toNimStr(str, str.len) +when defined(nimImmutableStrings): + template wasMoved(x: NimString): bool = (x.reserved and seqShallowFlag) != 0 +else: + template wasMoved(x: NimString): bool = false + proc copyString(src: NimString): NimString {.compilerRtl.} = if src != nil: if (src.reserved and seqShallowFlag) != 0: @@ -103,6 +108,16 @@ proc copyString(src: NimString): NimString {.compilerRtl.} = result = rawNewStringNoInit(src.len) result.len = src.len copyMem(addr(result.data), addr(src.data), src.len + 1) + sysAssert((seqShallowFlag and result.reserved) == 0, "copyString") + when defined(nimImmutableStrings): + if (src.reserved and strlitFlag) != 0: + result.reserved = (result.reserved and not strlitFlag) or seqShallowFlag + +proc newOwnedString(src: NimString; n: int): NimString = + result = rawNewStringNoInit(n) + result.len = n + copyMem(addr(result.data), addr(src.data), n) + result.data[n] = '\0' proc copyStringRC1(src: NimString): NimString {.compilerRtl.} = if src != nil: @@ -116,6 +131,10 @@ proc copyStringRC1(src: NimString): NimString {.compilerRtl.} = result = rawNewStringNoInit(src.len) result.len = src.len copyMem(addr(result.data), addr(src.data), src.len + 1) + sysAssert((seqShallowFlag and result.reserved) == 0, "copyStringRC1") + when defined(nimImmutableStrings): + if (src.reserved and strlitFlag) != 0: + result.reserved = (result.reserved and not strlitFlag) or seqShallowFlag proc copyDeepString(src: NimString): NimString {.inline.} = if src != nil: @@ -144,6 +163,8 @@ proc addChar(s: NimString, c: char): NimString = result = cast[NimString](growObj(result, sizeof(TGenericSeq) + r + 1)) result.reserved = r + elif wasMoved(s): + result = newOwnedString(s, s.len) result.data[result.len] = c result.data[result.len+1] = '\0' inc(result.len) @@ -180,7 +201,7 @@ proc addChar(s: NimString, c: char): NimString = # s = rawNewString(0); proc resizeString(dest: NimString, addlen: int): NimString {.compilerRtl.} = - if dest.len + addlen <= dest.space: + if dest.len + addlen <= dest.space and not wasMoved(dest): result = dest else: # slow path: var sp = max(resize(dest.space), dest.len + addlen) @@ -201,7 +222,9 @@ proc appendChar(dest: NimString, c: char) {.compilerproc, inline.} = proc setLengthStr(s: NimString, newLen: int): NimString {.compilerRtl.} = var n = max(newLen, 0) - if n <= s.space: + if wasMoved(s): + result = newOwnedString(s, n) + elif n <= s.space: result = s else: result = resizeString(s, n) |