1
0
mirror of https://github.com/golang/go synced 2024-10-05 00:11:21 -06:00
go/src/pkg/runtime/string.goc

364 lines
5.7 KiB
Plaintext
Raw Normal View History

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package runtime
#include "runtime.h"
#include "arch.h"
#include "malloc.h"
String runtime·emptystring;
int32
runtime·findnull(byte *s)
{
int32 l;
if(s == nil)
return 0;
for(l=0; s[l]!=0; l++)
;
return l;
}
int32
runtime·findnullw(uint16 *s)
{
int32 l;
if(s == nil)
return 0;
for(l=0; s[l]!=0; l++)
;
return l;
}
uint32 runtime·maxstring = 256;
String
runtime·gostringsize(int32 l)
{
String s;
uint32 ms;
if(l == 0)
return runtime·emptystring;
s.str = runtime·mal(l+1); // leave room for NUL for C runtime (e.g., callers of getenv)
s.len = l;
for(;;) {
ms = runtime·maxstring;
if((uint32)l <= ms || runtime·cas(&runtime·maxstring, ms, (uint32)l))
break;
}
return s;
}
String
runtime·gostring(byte *str)
{
int32 l;
String s;
l = runtime·findnull(str);
s = runtime·gostringsize(l);
runtime·memmove(s.str, str, l);
return s;
}
String
runtime·gostringn(byte *str, int32 l)
{
String s;
s = runtime·gostringsize(l);
runtime·memmove(s.str, str, l);
return s;
}
Slice
runtime·gobytes(byte *p, int32 n)
{
Slice sl;
sl.array = runtime·mallocgc(n, FlagNoPointers, 1, 0);
sl.len = n;
sl.cap = n;
runtime·memmove(sl.array, p, n);
return sl;
}
String
runtime·gostringnocopy(byte *str)
{
String s;
s.str = str;
s.len = runtime·findnull(str);
return s;
}
String
runtime·gostringw(uint16 *str)
{
int32 n, i;
byte buf[8];
String s;
n = 0;
for(i=0; str[i]; i++)
n += runtime·runetochar(buf, str[i]);
s = runtime·gostringsize(n+4);
n = 0;
for(i=0; str[i]; i++)
n += runtime·runetochar(s.str+n, str[i]);
s.len = n;
return s;
}
String
runtime·catstring(String s1, String s2)
{
String s3;
if(s1.len == 0)
return s2;
if(s2.len == 0)
return s1;
s3 = runtime·gostringsize(s1.len + s2.len);
runtime·memmove(s3.str, s1.str, s1.len);
runtime·memmove(s3.str+s1.len, s2.str, s2.len);
return s3;
}
static String
concatstring(int32 n, String *s)
{
int32 i, l;
String out;
l = 0;
for(i=0; i<n; i++) {
if(l + s[i].len < l)
runtime·throw("string concatenation too long");
l += s[i].len;
}
out = runtime·gostringsize(l);
l = 0;
for(i=0; i<n; i++) {
runtime·memmove(out.str+l, s[i].str, s[i].len);
l += s[i].len;
}
return out;
}
#pragma textflag 7
// s1 is the first of n strings.
// the output string follows.
func concatstring(n int32, s1 String) {
(&s1)[n] = concatstring(n, &s1);
}
static int32
cmpstring(String s1, String s2)
{
uint32 i, l;
byte c1, c2;
l = s1.len;
if(s2.len < l)
l = s2.len;
for(i=0; i<l; i++) {
c1 = s1.str[i];
c2 = s2.str[i];
if(c1 < c2)
return -1;
if(c1 > c2)
return +1;
}
if(s1.len < s2.len)
return -1;
if(s1.len > s2.len)
return +1;
return 0;
}
func cmpstring(s1 String, s2 String) (v int32) {
v = cmpstring(s1, s2);
}
int32
runtime·strcmp(byte *s1, byte *s2)
{
uint32 i;
byte c1, c2;
for(i=0;; i++) {
c1 = s1[i];
c2 = s2[i];
if(c1 < c2)
return -1;
if(c1 > c2)
return +1;
if(c1 == 0)
return 0;
}
}
runtime: improve Linux mutex The implementation is hybrid active/passive spin/blocking mutex. The design minimizes amount of context switches and futex calls. The idea is that all critical sections in runtime are intentially small, so pure blocking mutex behaves badly causing a lot of context switches, thread parking/unparking and kernel calls. Note that some synthetic benchmarks become somewhat slower, that's due to increased contention on other data structures, it should not affect programs that do any real work. On 2 x Intel E5620, 8 HT cores, 2.4GHz benchmark old ns/op new ns/op delta BenchmarkSelectContended 521.00 503.00 -3.45% BenchmarkSelectContended-2 661.00 320.00 -51.59% BenchmarkSelectContended-4 1139.00 629.00 -44.78% BenchmarkSelectContended-8 2870.00 878.00 -69.41% BenchmarkSelectContended-16 5276.00 818.00 -84.50% BenchmarkChanContended 112.00 103.00 -8.04% BenchmarkChanContended-2 631.00 174.00 -72.42% BenchmarkChanContended-4 682.00 272.00 -60.12% BenchmarkChanContended-8 1601.00 520.00 -67.52% BenchmarkChanContended-16 3100.00 372.00 -88.00% BenchmarkChanSync 253.00 239.00 -5.53% BenchmarkChanSync-2 5030.00 4648.00 -7.59% BenchmarkChanSync-4 4826.00 4694.00 -2.74% BenchmarkChanSync-8 4778.00 4713.00 -1.36% BenchmarkChanSync-16 5289.00 4710.00 -10.95% BenchmarkChanProdCons0 273.00 254.00 -6.96% BenchmarkChanProdCons0-2 599.00 400.00 -33.22% BenchmarkChanProdCons0-4 1168.00 659.00 -43.58% BenchmarkChanProdCons0-8 2831.00 1057.00 -62.66% BenchmarkChanProdCons0-16 4197.00 1037.00 -75.29% BenchmarkChanProdCons10 150.00 140.00 -6.67% BenchmarkChanProdCons10-2 607.00 268.00 -55.85% BenchmarkChanProdCons10-4 1137.00 404.00 -64.47% BenchmarkChanProdCons10-8 2115.00 828.00 -60.85% BenchmarkChanProdCons10-16 4283.00 855.00 -80.04% BenchmarkChanProdCons100 117.00 110.00 -5.98% BenchmarkChanProdCons100-2 558.00 218.00 -60.93% BenchmarkChanProdCons100-4 722.00 287.00 -60.25% BenchmarkChanProdCons100-8 1840.00 431.00 -76.58% BenchmarkChanProdCons100-16 3394.00 448.00 -86.80% BenchmarkChanProdConsWork0 2014.00 1996.00 -0.89% BenchmarkChanProdConsWork0-2 1207.00 1127.00 -6.63% BenchmarkChanProdConsWork0-4 1913.00 611.00 -68.06% BenchmarkChanProdConsWork0-8 3016.00 949.00 -68.53% BenchmarkChanProdConsWork0-16 4320.00 1154.00 -73.29% BenchmarkChanProdConsWork10 1906.00 1897.00 -0.47% BenchmarkChanProdConsWork10-2 1123.00 1033.00 -8.01% BenchmarkChanProdConsWork10-4 1076.00 571.00 -46.93% BenchmarkChanProdConsWork10-8 2748.00 1096.00 -60.12% BenchmarkChanProdConsWork10-16 4600.00 1105.00 -75.98% BenchmarkChanProdConsWork100 1884.00 1852.00 -1.70% BenchmarkChanProdConsWork100-2 1235.00 1146.00 -7.21% BenchmarkChanProdConsWork100-4 1217.00 619.00 -49.14% BenchmarkChanProdConsWork100-8 1534.00 509.00 -66.82% BenchmarkChanProdConsWork100-16 4126.00 918.00 -77.75% BenchmarkSyscall 34.40 33.30 -3.20% BenchmarkSyscall-2 160.00 121.00 -24.38% BenchmarkSyscall-4 131.00 136.00 +3.82% BenchmarkSyscall-8 139.00 131.00 -5.76% BenchmarkSyscall-16 161.00 168.00 +4.35% BenchmarkSyscallWork 950.00 950.00 +0.00% BenchmarkSyscallWork-2 481.00 480.00 -0.21% BenchmarkSyscallWork-4 268.00 270.00 +0.75% BenchmarkSyscallWork-8 156.00 169.00 +8.33% BenchmarkSyscallWork-16 188.00 184.00 -2.13% BenchmarkSemaSyntNonblock 36.40 35.60 -2.20% BenchmarkSemaSyntNonblock-2 81.40 45.10 -44.59% BenchmarkSemaSyntNonblock-4 126.00 108.00 -14.29% BenchmarkSemaSyntNonblock-8 112.00 112.00 +0.00% BenchmarkSemaSyntNonblock-16 110.00 112.00 +1.82% BenchmarkSemaSyntBlock 35.30 35.30 +0.00% BenchmarkSemaSyntBlock-2 118.00 124.00 +5.08% BenchmarkSemaSyntBlock-4 105.00 108.00 +2.86% BenchmarkSemaSyntBlock-8 101.00 111.00 +9.90% BenchmarkSemaSyntBlock-16 112.00 118.00 +5.36% BenchmarkSemaWorkNonblock 810.00 811.00 +0.12% BenchmarkSemaWorkNonblock-2 476.00 414.00 -13.03% BenchmarkSemaWorkNonblock-4 238.00 228.00 -4.20% BenchmarkSemaWorkNonblock-8 140.00 126.00 -10.00% BenchmarkSemaWorkNonblock-16 117.00 116.00 -0.85% BenchmarkSemaWorkBlock 810.00 811.00 +0.12% BenchmarkSemaWorkBlock-2 454.00 466.00 +2.64% BenchmarkSemaWorkBlock-4 243.00 241.00 -0.82% BenchmarkSemaWorkBlock-8 145.00 137.00 -5.52% BenchmarkSemaWorkBlock-16 132.00 123.00 -6.82% BenchmarkContendedSemaphore 123.00 102.00 -17.07% BenchmarkContendedSemaphore-2 34.80 34.90 +0.29% BenchmarkContendedSemaphore-4 34.70 34.80 +0.29% BenchmarkContendedSemaphore-8 34.70 34.70 +0.00% BenchmarkContendedSemaphore-16 34.80 34.70 -0.29% BenchmarkMutex 26.80 26.00 -2.99% BenchmarkMutex-2 108.00 45.20 -58.15% BenchmarkMutex-4 103.00 127.00 +23.30% BenchmarkMutex-8 109.00 147.00 +34.86% BenchmarkMutex-16 102.00 152.00 +49.02% BenchmarkMutexSlack 27.00 26.90 -0.37% BenchmarkMutexSlack-2 149.00 165.00 +10.74% BenchmarkMutexSlack-4 121.00 209.00 +72.73% BenchmarkMutexSlack-8 101.00 158.00 +56.44% BenchmarkMutexSlack-16 97.00 129.00 +32.99% BenchmarkMutexWork 792.00 794.00 +0.25% BenchmarkMutexWork-2 407.00 409.00 +0.49% BenchmarkMutexWork-4 220.00 209.00 -5.00% BenchmarkMutexWork-8 267.00 160.00 -40.07% BenchmarkMutexWork-16 315.00 300.00 -4.76% BenchmarkMutexWorkSlack 792.00 793.00 +0.13% BenchmarkMutexWorkSlack-2 406.00 404.00 -0.49% BenchmarkMutexWorkSlack-4 225.00 212.00 -5.78% BenchmarkMutexWorkSlack-8 268.00 136.00 -49.25% BenchmarkMutexWorkSlack-16 300.00 300.00 +0.00% BenchmarkRWMutexWrite100 27.10 27.00 -0.37% BenchmarkRWMutexWrite100-2 33.10 40.80 +23.26% BenchmarkRWMutexWrite100-4 113.00 88.10 -22.04% BenchmarkRWMutexWrite100-8 119.00 95.30 -19.92% BenchmarkRWMutexWrite100-16 148.00 109.00 -26.35% BenchmarkRWMutexWrite10 29.60 29.40 -0.68% BenchmarkRWMutexWrite10-2 111.00 61.40 -44.68% BenchmarkRWMutexWrite10-4 270.00 208.00 -22.96% BenchmarkRWMutexWrite10-8 204.00 185.00 -9.31% BenchmarkRWMutexWrite10-16 261.00 190.00 -27.20% BenchmarkRWMutexWorkWrite100 1040.00 1036.00 -0.38% BenchmarkRWMutexWorkWrite100-2 593.00 580.00 -2.19% BenchmarkRWMutexWorkWrite100-4 470.00 365.00 -22.34% BenchmarkRWMutexWorkWrite100-8 468.00 289.00 -38.25% BenchmarkRWMutexWorkWrite100-16 604.00 374.00 -38.08% BenchmarkRWMutexWorkWrite10 951.00 951.00 +0.00% BenchmarkRWMutexWorkWrite10-2 1001.00 928.00 -7.29% BenchmarkRWMutexWorkWrite10-4 1555.00 1006.00 -35.31% BenchmarkRWMutexWorkWrite10-8 2085.00 1171.00 -43.84% BenchmarkRWMutexWorkWrite10-16 2082.00 1614.00 -22.48% R=rsc, iant, msolo, fw, iant CC=golang-dev https://golang.org/cl/4711045
2011-07-29 10:44:06 -06:00
byte*
runtime·strstr(byte *s1, byte *s2)
{
byte *sp1, *sp2;
if(*s2 == 0)
return s1;
for(; *s1; s1++) {
if(*s1 != *s2)
continue;
sp1 = s1;
sp2 = s2;
for(;;) {
if(*sp2 == 0)
return s1;
if(*sp1++ != *sp2++)
break;
}
}
return nil;
}
func slicestring(si String, lindex int32, hindex int32) (so String) {
int32 l;
if(lindex < 0 || lindex > si.len ||
hindex < lindex || hindex > si.len) {
runtime·panicslice();
}
l = hindex-lindex;
so.str = si.str + lindex;
so.len = l;
}
func slicestring1(si String, lindex int32) (so String) {
int32 l;
if(lindex < 0 || lindex > si.len) {
runtime·panicslice();
}
l = si.len-lindex;
so.str = si.str + lindex;
so.len = l;
}
func intstring(v int64) (s String) {
s = runtime·gostringsize(8);
s.len = runtime·runetochar(s.str, v);
}
func slicebytetostring(b Slice) (s String) {
s = runtime·gostringsize(b.len);
runtime·memmove(s.str, b.array, s.len);
}
func stringtoslicebyte(s String) (b Slice) {
b.array = runtime·mallocgc(s.len, FlagNoPointers, 1, 1);
b.len = s.len;
b.cap = s.len;
runtime·memmove(b.array, s.str, s.len);
}
func sliceinttostring(b Slice) (s String) {
int32 siz1, siz2, i;
int32 *a;
byte dum[8];
a = (int32*)b.array;
siz1 = 0;
for(i=0; i<b.len; i++) {
siz1 += runtime·runetochar(dum, a[i]);
}
s = runtime·gostringsize(siz1+4);
siz2 = 0;
for(i=0; i<b.len; i++) {
// check for race
if(siz2 >= siz1)
break;
siz2 += runtime·runetochar(s.str+siz2, a[i]);
}
s.len = siz2;
}
func stringtosliceint(s String) (b Slice) {
int32 n;
int32 dum, *r;
uint8 *p, *ep;
// two passes.
// unlike sliceinttostring, no race because strings are immutable.
p = s.str;
ep = s.str+s.len;
n = 0;
while(p < ep) {
p += runtime·charntorune(&dum, p, ep-p);
n++;
}
b.array = runtime·mallocgc(n*sizeof(r[0]), FlagNoPointers, 1, 1);
b.len = n;
b.cap = n;
p = s.str;
r = (int32*)b.array;
while(p < ep)
p += runtime·charntorune(r++, p, ep-p);
}
enum
{
Runeself = 0x80,
};
func stringiter(s String, k int32) (retk int32) {
2009-04-12 23:34:36 -06:00
int32 l;
if(k >= s.len) {
// retk=0 is end of iteration
retk = 0;
goto out;
}
l = s.str[k];
2009-04-12 23:34:36 -06:00
if(l < Runeself) {
retk = k+1;
goto out;
}
2009-04-12 23:34:36 -06:00
// multi-char rune
retk = k + runtime·charntorune(&l, s.str+k, s.len-k);
out:
}
func stringiter2(s String, k int32) (retk int32, retv int32) {
if(k >= s.len) {
// retk=0 is end of iteration
retk = 0;
retv = 0;
goto out;
}
2009-04-12 23:34:36 -06:00
retv = s.str[k];
if(retv < Runeself) {
retk = k+1;
goto out;
}
2009-04-12 23:34:36 -06:00
// multi-char rune
retk = k + runtime·charntorune(&retv, s.str+k, s.len-k);
out:
}