github.com/spotify/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/pkg/runtime/slice.c (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  #include "runtime.h"
     6  #include "arch_GOARCH.h"
     7  #include "type.h"
     8  #include "typekind.h"
     9  #include "malloc.h"
    10  #include "race.h"
    11  #include "../../cmd/ld/textflag.h"
    12  
    13  enum
    14  {
    15  	debug = 0
    16  };
    17  
    18  static	void	makeslice1(SliceType*, intgo, intgo, Slice*);
    19  static	void	growslice1(SliceType*, Slice, intgo, Slice *);
    20  	void	runtime·copy(Slice to, Slice fm, uintptr width, intgo ret);
    21  
    22  // see also unsafe·NewArray
    23  // makeslice(typ *Type, len, cap int64) (ary []any);
    24  void
    25  runtime·makeslice(SliceType *t, int64 len, int64 cap, Slice ret)
    26  {
    27  	// NOTE: The len > MaxMem/elemsize check here is not strictly necessary,
    28  	// but it produces a 'len out of range' error instead of a 'cap out of range' error
    29  	// when someone does make([]T, bignumber). 'cap out of range' is true too,
    30  	// but since the cap is only being supplied implicitly, saying len is clearer.
    31  	// See issue 4085.
    32  	if(len < 0 || (intgo)len != len || t->elem->size > 0 && len > MaxMem / t->elem->size)
    33  		runtime·panicstring("makeslice: len out of range");
    34  
    35  	if(cap < len || (intgo)cap != cap || t->elem->size > 0 && cap > MaxMem / t->elem->size)
    36  		runtime·panicstring("makeslice: cap out of range");
    37  
    38  	makeslice1(t, len, cap, &ret);
    39  
    40  	if(debug) {
    41  		runtime·printf("makeslice(%S, %D, %D); ret=",
    42  			*t->string, len, cap);
    43  		runtime·printslice(ret);
    44  	}
    45  }
    46  
    47  // Dummy word to use as base pointer for make([]T, 0).
    48  // Since you cannot take the address of such a slice,
    49  // you can't tell that they all have the same base pointer.
    50  uintptr runtime·zerobase;
    51  
    52  static void
    53  makeslice1(SliceType *t, intgo len, intgo cap, Slice *ret)
    54  {
    55  	ret->len = len;
    56  	ret->cap = cap;
    57  	ret->array = runtime·cnewarray(t->elem, cap);
    58  }
    59  
    60  // growslice(type *Type, x, []T, n int64) []T
    61  void
    62  runtime·growslice(SliceType *t, Slice old, int64 n, Slice ret)
    63  {
    64  	int64 cap;
    65  	void *pc;
    66  
    67  	if(n < 1)
    68  		runtime·panicstring("growslice: invalid n");
    69  
    70  	cap = old.cap + n;
    71  
    72  	if((intgo)cap != cap || cap < old.cap || (t->elem->size > 0 && cap > MaxMem/t->elem->size))
    73  		runtime·panicstring("growslice: cap out of range");
    74  
    75  	if(raceenabled) {
    76  		pc = runtime·getcallerpc(&t);
    77  		runtime·racereadrangepc(old.array, old.len*t->elem->size, pc, runtime·growslice);
    78  	}
    79  
    80  	growslice1(t, old, cap, &ret);
    81  
    82  	FLUSH(&ret);
    83  
    84  	if(debug) {
    85  		runtime·printf("growslice(%S,", *t->string);
    86  		runtime·printslice(old);
    87  		runtime·printf(", new cap=%D) =", cap);
    88  		runtime·printslice(ret);
    89  	}
    90  }
    91  
    92  static void
    93  growslice1(SliceType *t, Slice x, intgo newcap, Slice *ret)
    94  {
    95  	intgo m;
    96  
    97  	m = x.cap;
    98  	
    99  	// Using newcap directly for m+m < newcap handles
   100  	// both the case where m == 0 and also the case where
   101  	// m+m/4 wraps around, in which case the loop
   102  	// below might never terminate.
   103  	if(m+m < newcap)
   104  		m = newcap;
   105  	else {
   106  		do {
   107  			if(x.len < 1024)
   108  				m += m;
   109  			else
   110  				m += m/4;
   111  		} while(m < newcap);
   112  	}
   113  	makeslice1(t, x.len, m, ret);
   114  	runtime·memmove(ret->array, x.array, ret->len * t->elem->size);
   115  }
   116  
   117  // copy(to any, fr any, wid uintptr) int
   118  #pragma textflag NOSPLIT
   119  void
   120  runtime·copy(Slice to, Slice fm, uintptr width, intgo ret)
   121  {
   122  	void *pc;
   123  
   124  	if(fm.len == 0 || to.len == 0 || width == 0) {
   125  		ret = 0;
   126  		goto out;
   127  	}
   128  
   129  	ret = fm.len;
   130  	if(to.len < ret)
   131  		ret = to.len;
   132  
   133  	if(raceenabled) {
   134  		pc = runtime·getcallerpc(&to);
   135  		runtime·racewriterangepc(to.array, ret*width, pc, runtime·copy);
   136  		runtime·racereadrangepc(fm.array, ret*width, pc, runtime·copy);
   137  	}
   138  
   139  	if(ret == 1 && width == 1) {	// common case worth about 2x to do here
   140  		*to.array = *fm.array;	// known to be a byte pointer
   141  	} else {
   142  		runtime·memmove(to.array, fm.array, ret*width);
   143  	}
   144  
   145  out:
   146  	FLUSH(&ret);
   147  
   148  	if(debug) {
   149  		runtime·prints("main·copy: to=");
   150  		runtime·printslice(to);
   151  		runtime·prints("; fm=");
   152  		runtime·printslice(fm);
   153  		runtime·prints("; width=");
   154  		runtime·printint(width);
   155  		runtime·prints("; ret=");
   156  		runtime·printint(ret);
   157  		runtime·prints("\n");
   158  	}
   159  }
   160  
   161  #pragma textflag NOSPLIT
   162  void
   163  runtime·slicestringcopy(Slice to, String fm, intgo ret)
   164  {
   165  	void *pc;
   166  
   167  	if(fm.len == 0 || to.len == 0) {
   168  		ret = 0;
   169  		goto out;
   170  	}
   171  
   172  	ret = fm.len;
   173  	if(to.len < ret)
   174  		ret = to.len;
   175  
   176  	if(raceenabled) {
   177  		pc = runtime·getcallerpc(&to);
   178  		runtime·racewriterangepc(to.array, ret, pc, runtime·slicestringcopy);
   179  	}
   180  
   181  	runtime·memmove(to.array, fm.str, ret);
   182  
   183  out:
   184  	FLUSH(&ret);
   185  }
   186  
   187  void
   188  runtime·printslice(Slice a)
   189  {
   190  	runtime·prints("[");
   191  	runtime·printint(a.len);
   192  	runtime·prints("/");
   193  	runtime·printint(a.cap);
   194  	runtime·prints("]");
   195  	runtime·printpointer(a.array);
   196  }