Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
go
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
go
Commits
d6b29259
Commit
d6b29259
authored
May 11, 2011
by
Luuk van Dijk
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
gc: inline append when len<cap
issue 1604 R=rsc, bradfitz CC=golang-dev
https://golang.org/cl/4313062
parent
b276293a
Changes
13
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
419 additions
and
112 deletions
+419
-112
src/cmd/6g/cgen.c
src/cmd/6g/cgen.c
+29
-9
src/cmd/6g/ggen.c
src/cmd/6g/ggen.c
+23
-11
src/cmd/6g/gsubr.c
src/cmd/6g/gsubr.c
+33
-8
src/cmd/6g/reg.c
src/cmd/6g/reg.c
+4
-1
src/cmd/8g/cgen.c
src/cmd/8g/cgen.c
+29
-11
src/cmd/8g/ggen.c
src/cmd/8g/ggen.c
+21
-8
src/cmd/8g/gsubr.c
src/cmd/8g/gsubr.c
+53
-11
src/cmd/gc/builtin.c.boot
src/cmd/gc/builtin.c.boot
+3
-0
src/cmd/gc/runtime.go
src/cmd/gc/runtime.go
+1
-0
src/cmd/gc/subr.c
src/cmd/gc/subr.c
+8
-4
src/cmd/gc/walk.c
src/cmd/gc/walk.c
+109
-27
src/pkg/runtime/append_test.go
src/pkg/runtime/append_test.go
+51
-0
src/pkg/runtime/slice.c
src/pkg/runtime/slice.c
+55
-22
No files found.
src/cmd/6g/cgen.c
View file @
d6b29259
...
...
@@ -283,11 +283,9 @@ cgen(Node *n, Node *res)
if
(
istype
(
nl
->
type
,
TSTRING
)
||
isslice
(
nl
->
type
))
{
// both slice and string have len one pointer into the struct.
// a zero pointer means zero length
regalloc
(
&
n1
,
types
[
tptr
],
res
);
agen
(
nl
,
&
n1
);
n1
.
op
=
OINDREG
;
igen
(
nl
,
&
n1
,
res
);
n1
.
type
=
types
[
TUINT32
];
n1
.
xoffset
=
Array_nel
;
n1
.
xoffset
+
=
Array_nel
;
gmove
(
&
n1
,
res
);
regfree
(
&
n1
);
break
;
...
...
@@ -319,11 +317,9 @@ cgen(Node *n, Node *res)
break
;
}
if
(
isslice
(
nl
->
type
))
{
regalloc
(
&
n1
,
types
[
tptr
],
res
);
agen
(
nl
,
&
n1
);
n1
.
op
=
OINDREG
;
igen
(
nl
,
&
n1
,
res
);
n1
.
type
=
types
[
TUINT32
];
n1
.
xoffset
=
Array_cap
;
n1
.
xoffset
+
=
Array_cap
;
gmove
(
&
n1
,
res
);
regfree
(
&
n1
);
break
;
...
...
@@ -542,6 +538,7 @@ agen(Node *n, Node *res)
gmove
(
&
n1
,
&
n3
);
}
if
(
v
*
w
!=
0
)
ginscon
(
optoas
(
OADD
,
types
[
tptr
]),
v
*
w
,
&
n3
);
gmove
(
&
n3
,
res
);
regfree
(
&
n3
);
...
...
@@ -682,6 +679,28 @@ ret:
void
igen
(
Node
*
n
,
Node
*
a
,
Node
*
res
)
{
Type
*
fp
;
Iter
flist
;
switch
(
n
->
op
)
{
case
ONAME
:
if
((
n
->
class
&
PHEAP
)
||
n
->
class
==
PPARAMREF
)
break
;
*
a
=
*
n
;
return
;
case
OCALLFUNC
:
fp
=
structfirst
(
&
flist
,
getoutarg
(
n
->
left
->
type
));
cgen_call
(
n
,
0
);
memset
(
a
,
0
,
sizeof
*
a
);
a
->
op
=
OINDREG
;
a
->
val
.
u
.
reg
=
D_SP
;
a
->
addable
=
1
;
a
->
xoffset
=
fp
->
width
;
a
->
type
=
n
->
type
;
return
;
}
regalloc
(
a
,
types
[
tptr
],
res
);
agen
(
n
,
a
);
a
->
op
=
OINDREG
;
...
...
@@ -848,6 +867,7 @@ bgen(Node *n, int true, Prog *to)
n2
=
n1
;
n2
.
op
=
OINDREG
;
n2
.
xoffset
=
Array_array
;
n2
.
type
=
types
[
tptr
];
nodconst
(
&
tmp
,
types
[
tptr
],
0
);
gins
(
optoas
(
OCMP
,
types
[
tptr
]),
&
n2
,
&
tmp
);
patch
(
gbranch
(
a
,
types
[
tptr
]),
to
);
...
...
src/cmd/6g/ggen.c
View file @
d6b29259
...
...
@@ -1206,7 +1206,7 @@ cgen_inline(Node *n, Node *res)
Node
nodes
[
5
];
Node
n1
,
n2
,
nres
,
ntemp
;
vlong
v
;
int
i
,
narg
;
int
i
,
narg
,
nochk
;
if
(
n
->
op
!=
OCALLFUNC
)
goto
no
;
...
...
@@ -1242,6 +1242,7 @@ slicearray:
// len = hb[3] - lb[2] (destroys hb)
n2
=
*
res
;
n2
.
xoffset
+=
Array_nel
;
n2
.
type
=
types
[
TUINT32
];
if
(
smallintconst
(
&
nodes
[
3
])
&&
smallintconst
(
&
nodes
[
2
]))
{
v
=
mpgetfix
(
nodes
[
3
].
val
.
u
.
xval
)
-
...
...
@@ -1260,6 +1261,7 @@ slicearray:
// cap = nel[1] - lb[2] (destroys nel)
n2
=
*
res
;
n2
.
xoffset
+=
Array_cap
;
n2
.
type
=
types
[
TUINT32
];
if
(
smallintconst
(
&
nodes
[
1
])
&&
smallintconst
(
&
nodes
[
2
]))
{
v
=
mpgetfix
(
nodes
[
1
].
val
.
u
.
xval
)
-
...
...
@@ -1288,6 +1290,7 @@ slicearray:
// ary = old[0] + (lb[2] * width[4]) (destroys old)
n2
=
*
res
;
n2
.
xoffset
+=
Array_array
;
n2
.
type
=
types
[
tptr
];
if
(
smallintconst
(
&
nodes
[
2
])
&&
smallintconst
(
&
nodes
[
4
]))
{
v
=
mpgetfix
(
nodes
[
2
].
val
.
u
.
xval
)
*
...
...
@@ -1311,6 +1314,7 @@ slicearray:
return
1
;
sliceslice:
nochk
=
n
->
etype
;
// skip bounds checking
ntemp
.
op
=
OXXX
;
if
(
!
sleasy
(
n
->
list
->
n
->
right
))
{
Node
*
n0
;
...
...
@@ -1340,11 +1344,13 @@ sliceslice:
n2
=
nodes
[
0
];
n2
.
xoffset
+=
Array_nel
;
n2
.
type
=
types
[
TUINT32
];
if
(
!
nochk
)
cmpandthrow
(
&
nodes
[
1
],
&
n2
);
// ret.nel = old.nel[0]-lb[1];
n2
=
nodes
[
0
];
n2
.
xoffset
+=
Array_nel
;
n2
.
type
=
types
[
TUINT32
];
regalloc
(
&
n1
,
types
[
TUINT32
],
N
);
gins
(
optoas
(
OAS
,
types
[
TUINT32
]),
&
n2
,
&
n1
);
...
...
@@ -1353,21 +1359,23 @@ sliceslice:
n2
=
nres
;
n2
.
xoffset
+=
Array_nel
;
n2
.
type
=
types
[
TUINT32
];
gins
(
optoas
(
OAS
,
types
[
TUINT32
]),
&
n1
,
&
n2
);
regfree
(
&
n1
);
}
else
{
// old[lb:hb]
// if(hb[2] > old.cap[0]) goto throw;
n2
=
nodes
[
0
];
n2
.
xoffset
+=
Array_cap
;
n2
.
type
=
types
[
TUINT32
];
if
(
!
nochk
)
{
// if(hb[2] > old.cap[0]) goto throw;
cmpandthrow
(
&
nodes
[
2
],
&
n2
);
// if(lb[1] > hb[2]) goto throw;
cmpandthrow
(
&
nodes
[
1
],
&
nodes
[
2
]);
}
// ret.len = hb[2]-lb[1]; (destroys hb[2])
n2
=
nres
;
n2
.
xoffset
+=
Array_nel
;
n2
.
type
=
types
[
TUINT32
];
if
(
smallintconst
(
&
nodes
[
2
])
&&
smallintconst
(
&
nodes
[
1
]))
{
v
=
mpgetfix
(
nodes
[
2
].
val
.
u
.
xval
)
-
...
...
@@ -1387,6 +1395,7 @@ sliceslice:
// ret.cap = old.cap[0]-lb[1]; (uses hb[2])
n2
=
nodes
[
0
];
n2
.
xoffset
+=
Array_cap
;
n2
.
type
=
types
[
TUINT32
];
regalloc
(
&
n1
,
types
[
TUINT32
],
&
nodes
[
2
]);
gins
(
optoas
(
OAS
,
types
[
TUINT32
]),
&
n2
,
&
n1
);
...
...
@@ -1395,13 +1404,15 @@ sliceslice:
n2
=
nres
;
n2
.
xoffset
+=
Array_cap
;
n2
.
type
=
types
[
TUINT32
];
gins
(
optoas
(
OAS
,
types
[
TUINT32
]),
&
n1
,
&
n2
);
regfree
(
&
n1
);
// ret.array = old.array[0]+lb[1]*width[3]; (uses lb[1])
n2
=
nodes
[
0
];
n2
.
xoffset
+=
Array_array
;
n2
.
type
=
types
[
tptr
];
regalloc
(
&
n1
,
types
[
tptr
],
&
nodes
[
1
]);
if
(
smallintconst
(
&
nodes
[
1
])
&&
smallintconst
(
&
nodes
[
3
]))
{
gins
(
optoas
(
OAS
,
types
[
tptr
]),
&
n2
,
&
n1
);
...
...
@@ -1418,6 +1429,7 @@ sliceslice:
n2
=
nres
;
n2
.
xoffset
+=
Array_array
;
n2
.
type
=
types
[
tptr
];
gins
(
optoas
(
OAS
,
types
[
tptr
]),
&
n1
,
&
n2
);
regfree
(
&
n1
);
...
...
src/cmd/6g/gsubr.c
View file @
d6b29259
...
...
@@ -330,11 +330,13 @@ regfree(Node *n)
{
int
i
;
if
(
n
->
op
==
ONAME
&&
iscomplex
[
n
->
type
->
etype
]
)
if
(
n
->
op
==
ONAME
)
return
;
if
(
n
->
op
!=
OREGISTER
&&
n
->
op
!=
OINDREG
)
fatal
(
"regfree: not a register"
);
i
=
n
->
val
.
u
.
reg
;
if
(
i
==
D_SP
)
return
;
if
(
i
<
0
||
i
>=
sizeof
(
reg
))
fatal
(
"regfree: reg out of range"
);
if
(
reg
[
i
]
<=
0
)
...
...
@@ -888,7 +890,7 @@ Prog*
gins
(
int
as
,
Node
*
f
,
Node
*
t
)
{
// Node nod;
// int32 v
;
int32
w
;
Prog
*
p
;
Addr
af
,
at
;
...
...
@@ -933,6 +935,27 @@ gins(int as, Node *f, Node *t)
p
->
to
=
at
;
if
(
debug
[
'g'
])
print
(
"%P
\n
"
,
p
);
w
=
0
;
switch
(
as
)
{
case
AMOVB
:
w
=
1
;
break
;
case
AMOVW
:
w
=
2
;
break
;
case
AMOVL
:
w
=
4
;
break
;
case
AMOVQ
:
w
=
8
;
break
;
}
if
(
w
!=
0
&&
f
!=
N
&&
(
af
.
width
>
w
||
at
.
width
>
w
))
{
fatal
(
"bad width: %P (%d, %d)
\n
"
,
p
,
af
.
width
,
at
.
width
);
}
return
p
;
}
...
...
@@ -1106,8 +1129,9 @@ naddr(Node *n, Addr *a, int canemitcode)
naddr
(
n
->
left
,
a
,
canemitcode
);
if
(
a
->
type
==
D_CONST
&&
a
->
offset
==
0
)
break
;
// len(nil)
a
->
etype
=
TUINT
;
a
->
etype
=
TUINT
32
;
a
->
offset
+=
Array_nel
;
a
->
width
=
4
;
if
(
a
->
offset
>=
unmappedzero
&&
a
->
offset
-
Array_nel
<
unmappedzero
)
checkoffset
(
a
,
canemitcode
);
break
;
...
...
@@ -1117,8 +1141,9 @@ naddr(Node *n, Addr *a, int canemitcode)
naddr
(
n
->
left
,
a
,
canemitcode
);
if
(
a
->
type
==
D_CONST
&&
a
->
offset
==
0
)
break
;
// cap(nil)
a
->
etype
=
TUINT
;
a
->
etype
=
TUINT
32
;
a
->
offset
+=
Array_cap
;
a
->
width
=
4
;
if
(
a
->
offset
>=
unmappedzero
&&
a
->
offset
-
Array_cap
<
unmappedzero
)
checkoffset
(
a
,
canemitcode
);
break
;
...
...
@@ -1962,12 +1987,12 @@ oindex:
if
(
o
&
OAddable
)
{
n2
=
*
l
;
n2
.
xoffset
+=
Array_array
;
n2
.
type
=
types
[
TUINT64
];
n2
.
type
=
types
[
tptr
];
gmove
(
&
n2
,
reg
);
}
else
{
n2
=
*
reg
;
n2
.
xoffset
=
Array_array
;
n2
.
op
=
OINDREG
;
n2
.
xoffset
=
Array_array
;
n2
.
type
=
types
[
tptr
];
gmove
(
&
n2
,
reg
);
}
...
...
src/cmd/6g/reg.c
View file @
d6b29259
...
...
@@ -873,14 +873,17 @@ mkvar(Reg *r, Adr *a)
// if they overlaps, disable both
if
(
overlap
(
v
->
offset
,
v
->
width
,
o
,
w
))
{
// print("disable overlap %s %d %d %d %d, %E != %E\n", s->name, v->offset, v->width, o, w, v->etype, et);
v
->
addr
=
1
;
flag
=
1
;
}
}
}
if
(
a
->
pun
)
if
(
a
->
pun
)
{
// print("disable pun %s\n", s->name);
flag
=
1
;
}
switch
(
et
)
{
case
0
:
case
TFUNC
:
...
...
src/cmd/8g/cgen.c
View file @
d6b29259
...
...
@@ -232,6 +232,7 @@ cgen(Node *n, Node *res)
cgen
(
nl
,
res
);
break
;
}
tempname
(
&
n2
,
n
->
type
);
mgen
(
nl
,
&
n1
,
res
);
gmove
(
&
n1
,
&
n2
);
...
...
@@ -277,15 +278,10 @@ cgen(Node *n, Node *res)
if
(
istype
(
nl
->
type
,
TSTRING
)
||
isslice
(
nl
->
type
))
{
// both slice and string have len one pointer into the struct.
igen
(
nl
,
&
n1
,
res
);
n1
.
op
=
OREGISTER
;
// was OINDREG
regalloc
(
&
n2
,
types
[
TUINT32
],
&
n1
);
n1
.
op
=
OINDREG
;
n1
.
type
=
types
[
TUINT32
];
n1
.
xoffset
=
Array_nel
;
gmove
(
&
n1
,
&
n2
);
gmove
(
&
n2
,
res
);
n1
.
xoffset
+=
Array_nel
;
gmove
(
&
n1
,
res
);
regfree
(
&
n1
);
regfree
(
&
n2
);
break
;
}
fatal
(
"cgen: OLEN: unknown type %lT"
,
nl
->
type
);
...
...
@@ -594,9 +590,10 @@ agen(Node *n, Node *res)
gmove
(
&
n1
,
&
n3
);
}
if
(
v
*
w
!=
0
)
{
nodconst
(
&
n2
,
types
[
tptr
],
v
*
w
);
gins
(
optoas
(
OADD
,
types
[
tptr
]),
&
n2
,
&
n3
);
}
gmove
(
&
n3
,
res
);
regfree
(
&
n3
);
break
;
...
...
@@ -729,7 +726,27 @@ void
igen
(
Node
*
n
,
Node
*
a
,
Node
*
res
)
{
Node
n1
;
Type
*
fp
;
Iter
flist
;
switch
(
n
->
op
)
{
case
ONAME
:
if
((
n
->
class
&
PHEAP
)
||
n
->
class
==
PPARAMREF
)
break
;
*
a
=
*
n
;
return
;
case
OCALLFUNC
:
fp
=
structfirst
(
&
flist
,
getoutarg
(
n
->
left
->
type
));
cgen_call
(
n
,
0
);
memset
(
a
,
0
,
sizeof
*
a
);
a
->
op
=
OINDREG
;
a
->
val
.
u
.
reg
=
D_SP
;
a
->
addable
=
1
;
a
->
xoffset
=
fp
->
width
;
a
->
type
=
n
->
type
;
return
;
}
// release register for now, to avoid
// confusing tempname.
if
(
res
!=
N
&&
res
->
op
==
OREGISTER
)
...
...
@@ -919,6 +936,7 @@ bgen(Node *n, int true, Prog *to)
n2
=
n1
;
n2
.
op
=
OINDREG
;
n2
.
xoffset
=
Array_array
;
n2
.
type
=
types
[
tptr
];
nodconst
(
&
tmp
,
types
[
tptr
],
0
);
gins
(
optoas
(
OCMP
,
types
[
tptr
]),
&
n2
,
&
tmp
);
patch
(
gbranch
(
a
,
types
[
tptr
]),
to
);
...
...
src/cmd/8g/ggen.c
View file @
d6b29259
...
...
@@ -915,7 +915,7 @@ cgen_inline(Node *n, Node *res)
Node
nodes
[
5
];
Node
n1
,
n2
,
nres
,
ntemp
;
vlong
v
;
int
i
,
narg
;
int
i
,
narg
,
nochk
;
if
(
n
->
op
!=
OCALLFUNC
)
goto
no
;
...
...
@@ -953,6 +953,7 @@ slicearray:
// len = hb[3] - lb[2] (destroys hb)
n2
=
*
res
;
n2
.
xoffset
+=
Array_nel
;
n2
.
type
=
types
[
TUINT32
];
if
(
smallintconst
(
&
nodes
[
3
])
&&
smallintconst
(
&
nodes
[
2
]))
{
v
=
mpgetfix
(
nodes
[
3
].
val
.
u
.
xval
)
-
...
...
@@ -971,6 +972,7 @@ slicearray:
// cap = nel[1] - lb[2] (destroys nel)
n2
=
*
res
;
n2
.
xoffset
+=
Array_cap
;
n2
.
type
=
types
[
TUINT32
];
if
(
smallintconst
(
&
nodes
[
1
])
&&
smallintconst
(
&
nodes
[
2
]))
{
v
=
mpgetfix
(
nodes
[
1
].
val
.
u
.
xval
)
-
...
...
@@ -999,6 +1001,7 @@ slicearray:
// ary = old[0] + (lb[2] * width[4]) (destroys old)
n2
=
*
res
;
n2
.
xoffset
+=
Array_array
;
n2
.
type
=
types
[
tptr
];
if
(
smallintconst
(
&
nodes
[
2
])
&&
smallintconst
(
&
nodes
[
4
]))
{
v
=
mpgetfix
(
nodes
[
2
].
val
.
u
.
xval
)
*
...
...
@@ -1026,6 +1029,7 @@ slicearray:
sliceslice:
if
(
!
fix64
(
n
->
list
,
narg
))
goto
no
;
nochk
=
n
->
etype
;
// skip bounds checking
ntemp
.
op
=
OXXX
;
if
(
!
sleasy
(
n
->
list
->
n
->
right
))
{
Node
*
n0
;
...
...
@@ -1055,11 +1059,13 @@ sliceslice:
n2
=
nodes
[
0
];
n2
.
xoffset
+=
Array_nel
;
n2
.
type
=
types
[
TUINT32
];
if
(
!
nochk
)
cmpandthrow
(
&
nodes
[
1
],
&
n2
);
// ret.nel = old.nel[0]-lb[1];
n2
=
nodes
[
0
];
n2
.
xoffset
+=
Array_nel
;
n2
.
type
=
types
[
TUINT32
];
regalloc
(
&
n1
,
types
[
TUINT32
],
N
);
gins
(
optoas
(
OAS
,
types
[
TUINT32
]),
&
n2
,
&
n1
);
...
...
@@ -1068,21 +1074,24 @@ sliceslice:
n2
=
nres
;
n2
.
xoffset
+=
Array_nel
;
n2
.
type
=
types
[
TUINT32
];
gins
(
optoas
(
OAS
,
types
[
TUINT32
]),
&
n1
,
&
n2
);
regfree
(
&
n1
);
}
else
{
// old[lb:hb]
// if(hb[2] > old.cap[0]) goto throw;
n2
=
nodes
[
0
];
n2
.
xoffset
+=
Array_cap
;
n2
.
type
=
types
[
TUINT32
];
if
(
!
nochk
)
{
// if(hb[2] > old.cap[0]) goto throw;
cmpandthrow
(
&
nodes
[
2
],
&
n2
);
// if(lb[1] > hb[2]) goto throw;
cmpandthrow
(
&
nodes
[
1
],
&
nodes
[
2
]);
}
// ret.len = hb[2]-lb[1]; (destroys hb[2])
n2
=
nres
;
n2
.
xoffset
+=
Array_nel
;
n2
.
type
=
types
[
TUINT32
];
if
(
smallintconst
(
&
nodes
[
2
])
&&
smallintconst
(
&
nodes
[
1
]))
{
v
=
mpgetfix
(
nodes
[
2
].
val
.
u
.
xval
)
-
...
...
@@ -1102,6 +1111,7 @@ sliceslice:
// ret.cap = old.cap[0]-lb[1]; (uses hb[2])
n2
=
nodes
[
0
];
n2
.
xoffset
+=
Array_cap
;
n2
.
type
=
types
[
TUINT32
];
regalloc
(
&
n1
,
types
[
TUINT32
],
&
nodes
[
2
]);
gins
(
optoas
(
OAS
,
types
[
TUINT32
]),
&
n2
,
&
n1
);
...
...
@@ -1110,12 +1120,14 @@ sliceslice:
n2
=
nres
;
n2
.
xoffset
+=
Array_cap
;
n2
.
type
=
types
[
TUINT32
];
gins
(
optoas
(
OAS
,
types
[
TUINT32
]),
&
n1
,
&
n2
);
regfree
(
&
n1
);
// ret.array = old.array[0]+lb[1]*width[3]; (uses lb[1])
n2
=
nodes
[
0
];
n2
.
xoffset
+=
Array_array
;
n2
.
type
=
types
[
tptr
];
regalloc
(
&
n1
,
types
[
tptr
],
&
nodes
[
1
]);
if
(
smallintconst
(
&
nodes
[
1
])
&&
smallintconst
(
&
nodes
[
3
]))
{
...
...
@@ -1135,6 +1147,7 @@ sliceslice:
n2
=
nres
;
n2
.
xoffset
+=
Array_array
;
n2
.
type
=
types
[
tptr
];
gins
(
optoas
(
OAS
,
types
[
tptr
]),
&
n1
,
&
n2
);
regfree
(
&
n1
);
...
...
src/cmd/8g/gsubr.c
View file @
d6b29259
...
...
@@ -698,7 +698,6 @@ ginit(void)
reg
[
i
]
=
1
;
for
(
i
=
D_AL
;
i
<=
D_DI
;
i
++
)
reg
[
i
]
=
0
;
for
(
i
=
0
;
i
<
nelem
(
resvd
);
i
++
)
reg
[
resvd
[
i
]]
++
;
}
...
...
@@ -789,6 +788,8 @@ err:
return
;
out:
if
(
i
==
D_SP
)
print
(
"alloc SP
\n
"
);
if
(
reg
[
i
]
==
0
)
{
regpc
[
i
]
=
(
ulong
)
__builtin_return_address
(
0
);
if
(
i
==
D_AX
||
i
==
D_CX
||
i
==
D_DX
||
i
==
D_SP
)
{
...
...
@@ -805,9 +806,13 @@ regfree(Node *n)
{
int
i
;
if
(
n
->
op
==
ONAME
)
return
;
if
(
n
->
op
!=
OREGISTER
&&
n
->
op
!=
OINDREG
)
fatal
(
"regfree: not a register"
);
i
=
n
->
val
.
u
.
reg
;
if
(
i
==
D_SP
)
return
;
if
(
i
<
0
||
i
>=
sizeof
(
reg
))
fatal
(
"regfree: reg out of range"
);
if
(
reg
[
i
]
<=
0
)
...
...
@@ -1129,6 +1134,9 @@ gmove(Node *f, Node *t)
case
CASE
(
TINT8
,
TUINT8
):
case
CASE
(
TUINT8
,
TINT8
):
case
CASE
(
TUINT8
,
TUINT8
):
a
=
AMOVB
;
break
;
case
CASE
(
TINT16
,
TINT8
):
// truncate
case
CASE
(
TUINT16
,
TINT8
):
case
CASE
(
TINT32
,
TINT8
):
...
...
@@ -1138,7 +1146,7 @@ gmove(Node *f, Node *t)
case
CASE
(
TINT32
,
TUINT8
):
case
CASE
(
TUINT32
,
TUINT8
):
a
=
AMOVB
;
break
;
goto
rsrc
;
case
CASE
(
TINT64
,
TINT8
):
// truncate low word
case
CASE
(
TUINT64
,
TINT8
):
...
...
@@ -1146,7 +1154,7 @@ gmove(Node *f, Node *t)
case
CASE
(
TUINT64
,
TUINT8
):
split64
(
f
,
&
flo
,
&
fhi
);
nodreg
(
&
r1
,
t
->
type
,
D_AX
);
g
ins
(
AMOVB
,
&
flo
,
&
r1
);
g
move
(
&
flo
,
&
r1
);
gins
(
AMOVB
,
&
r1
,
t
);
splitclean
();
return
;
...
...
@@ -1155,12 +1163,15 @@ gmove(Node *f, Node *t)
case
CASE
(
TINT16
,
TUINT16
):
case
CASE
(
TUINT16
,
TINT16
):
case
CASE
(
TUINT16
,
TUINT16
):
a
=
AMOVW
;
break
;
case
CASE
(
TINT32
,
TINT16
):
// truncate
case
CASE
(
TUINT32
,
TINT16
):
case
CASE
(
TINT32
,
TUINT16
):
case
CASE
(
TUINT32
,
TUINT16
):
a
=
AMOVW
;
break
;
goto
rsrc
;
case
CASE
(
TINT64
,
TINT16
):
// truncate low word
case
CASE
(
TUINT64
,
TINT16
):
...
...
@@ -1168,7 +1179,7 @@ gmove(Node *f, Node *t)
case
CASE
(
TUINT64
,
TUINT16
):
split64
(
f
,
&
flo
,
&
fhi
);
nodreg
(
&
r1
,
t
->
type
,
D_AX
);
g
ins
(
AMOVW
,
&
flo
,
&
r1
);
g
move
(
&
flo
,
&
r1
);
gins
(
AMOVW
,
&
r1
,
t
);
splitclean
();
return
;
...
...
@@ -1186,7 +1197,7 @@ gmove(Node *f, Node *t)
case
CASE
(
TUINT64
,
TUINT32
):
split64
(
f
,
&
flo
,
&
fhi
);
nodreg
(
&
r1
,
t
->
type
,
D_AX
);
g
ins
(
AMOVL
,
&
flo
,
&
r1
);
g
move
(
&
flo
,
&
r1
);
gins
(
AMOVL
,
&
r1
,
t
);
splitclean
();
return
;
...
...
@@ -1340,14 +1351,14 @@ gmove(Node *f, Node *t)
case
TUINT8
:
gins
(
ATESTL
,
ncon
(
0xffffff00
),
&
t1
);
p1
=
gbranch
(
AJEQ
,
T
);
gins
(
AMOV
B
,
ncon
(
0
),
&
t1
);
gins
(
AMOV
L
,
ncon
(
0
),
&
t1
);
patch
(
p1
,
pc
);
gmove
(
&
t1
,
t
);
break
;
case
TUINT16
:
gins
(
ATESTL
,
ncon
(
0xffff0000
),
&
t1
);
p1
=
gbranch
(
AJEQ
,
T
);
gins
(
AMOV
W
,
ncon
(
0
),
&
t1
);
gins
(
AMOV
L
,
ncon
(
0
),
&
t1
);
patch
(
p1
,
pc
);
gmove
(
&
t1
,
t
);
break
;
...
...
@@ -1571,6 +1582,14 @@ gmove(Node *f, Node *t)
gins
(
a
,
f
,
t
);
return
;
rsrc:
// requires register source
regalloc
(
&
r1
,
f
->
type
,
t
);
gmove
(
f
,
&
r1
);
gins
(
a
,
&
r1
,
t
);
regfree
(
&
r1
);
return
;
rdst:
// requires register destination
regalloc
(
&
r1
,
t
->
type
,
t
);
...
...
@@ -1623,6 +1642,7 @@ gins(int as, Node *f, Node *t)
{
Prog
*
p
;
Addr
af
,
at
;
int
w
;
if
(
as
==
AFMOVF
&&
f
&&
f
->
op
==
OREGISTER
&&
t
&&
t
->
op
==
OREGISTER
)
fatal
(
"gins MOVF reg, reg"
);
...
...
@@ -1648,6 +1668,26 @@ gins(int as, Node *f, Node *t)
p
->
to
=
at
;
if
(
debug
[
'g'
])
print
(
"%P
\n
"
,
p
);
w
=
0
;
switch
(
as
)
{
case
AMOVB
:
w
=
1
;
break
;
case
AMOVW
:
w
=
2
;
break
;
case
AMOVL
:
w
=
4
;
break
;
}
if
(
1
&&
w
!=
0
&&
f
!=
N
&&
(
af
.
width
>
w
||
at
.
width
>
w
))
{
dump
(
"bad width from:"
,
f
);
dump
(
"bad width to:"
,
t
);
fatal
(
"bad width: %P (%d, %d)
\n
"
,
p
,
af
.
width
,
at
.
width
);
}
return
p
;
}
...
...
@@ -1799,8 +1839,9 @@ naddr(Node *n, Addr *a, int canemitcode)
naddr
(
n
->
left
,
a
,
canemitcode
);
if
(
a
->
type
==
D_CONST
&&
a
->
offset
==
0
)
break
;
// len(nil)
a
->
etype
=
TUINT
;
a
->
etype
=
TUINT
32
;
a
->
offset
+=
Array_nel
;
a
->
width
=
4
;
if
(
a
->
offset
>=
unmappedzero
&&
a
->
offset
-
Array_nel
<
unmappedzero
)
checkoffset
(
a
,
canemitcode
);
break
;
...
...
@@ -1810,8 +1851,9 @@ naddr(Node *n, Addr *a, int canemitcode)
naddr
(
n
->
left
,
a
,
canemitcode
);
if
(
a
->
type
==
D_CONST
&&
a
->
offset
==
0
)
break
;
// cap(nil)
a
->
etype
=
TUINT
;
a
->
etype
=
TUINT
32
;
a
->
offset
+=
Array_cap
;
a
->
width
=
4
;
if
(
a
->
offset
>=
unmappedzero
&&
a
->
offset
-
Array_nel
<
unmappedzero
)
checkoffset
(
a
,
canemitcode
);
break
;
...
...
src/cmd/gc/builtin.c.boot
View file @
d6b29259
char *runtimeimport =
"package runtime\n"
"import runtime \"runtime\"\n"
"func \"\".new (? int32) *any\n"
"func \"\".panicindex ()\n"
"func \"\".panicslice ()\n"
...
...
@@ -81,6 +82,7 @@ char *runtimeimport =
"func \"\".selectgo (sel *uint8)\n"
"func \"\".block ()\n"
"func \"\".makeslice (typ *uint8, nel int64, cap int64) []any\n"
"func \"\".growslice (typ *uint8, old []any, cap int64) []any\n"
"func \"\".sliceslice1 (old []any, lb uint64, width uint64) []any\n"
"func \"\".sliceslice (old []any, lb uint64, hb uint64, width uint64) []any\n"
"func \"\".slicearray (old *any, nel uint64, lb uint64, hb uint64, width uint64) []any\n"
...
...
@@ -98,6 +100,7 @@ char *runtimeimport =
"$$\n";
char *unsafeimport =
"package unsafe\n"
"import runtime \"runtime\"\n"
"type \"\".Pointer uintptr\n"
"func \"\".Offsetof (? any) int\n"
"func \"\".Sizeof (? any) int\n"
...
...
src/cmd/gc/runtime.go
View file @
d6b29259
...
...
@@ -110,6 +110,7 @@ func selectgo(sel *byte)
func
block
()
func
makeslice
(
typ
*
byte
,
nel
int64
,
cap
int64
)
(
ary
[]
any
)
func
growslice
(
typ
*
byte
,
old
[]
any
,
n
int64
)
(
ary
[]
any
)
func
sliceslice1
(
old
[]
any
,
lb
uint64
,
width
uint64
)
(
ary
[]
any
)
func
sliceslice
(
old
[]
any
,
lb
uint64
,
hb
uint64
,
width
uint64
)
(
ary
[]
any
)
func
slicearray
(
old
*
any
,
nel
uint64
,
lb
uint64
,
hb
uint64
,
width
uint64
)
(
ary
[]
any
)
...
...
src/cmd/gc/subr.c
View file @
d6b29259
...
...
@@ -1073,6 +1073,9 @@ Jconv(Fmt *fp)
if
(
n
->
implicit
!=
0
)
fmtprint
(
fp
,
" implicit(%d)"
,
n
->
implicit
);
if
(
n
->
pun
!=
0
)
fmtprint
(
fp
,
" pun(%d)"
,
n
->
pun
);
return
0
;
}
...
...
@@ -1141,7 +1144,7 @@ Tpretty(Fmt *fp, Type *t)
Type
*
t1
;
Sym
*
s
;
if
(
debug
[
'r'
])
{
if
(
0
&&
debug
[
'r'
])
{
debug
[
'r'
]
=
0
;
fmtprint
(
fp
,
"%T (orig=%T)"
,
t
,
t
->
orig
);
debug
[
'r'
]
=
1
;
...
...
@@ -3109,7 +3112,7 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
Type
*
tpad
;
int
isddd
;
if
(
debug
[
'r'
])
if
(
0
&&
debug
[
'r'
])
print
(
"genwrapper rcvrtype=%T method=%T newnam=%S
\n
"
,
rcvr
,
method
,
newnam
);
...
...
@@ -3163,7 +3166,7 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
fn
->
nbody
=
list1
(
n
);
}
if
(
debug
[
'r'
])
if
(
0
&&
debug
[
'r'
])
dumplist
(
"genwrapper body"
,
fn
->
nbody
);
funcbody
(
fn
);
...
...
@@ -3258,8 +3261,9 @@ implements(Type *t, Type *iface, Type **m, Type **samename, int *ptr)
// the method does not exist for value types.
rcvr
=
getthisx
(
tm
->
type
)
->
type
->
type
;
if
(
isptr
[
rcvr
->
etype
]
&&
!
isptr
[
t0
->
etype
]
&&
!
followptr
&&
!
isifacemethod
(
tm
->
type
))
{
if
(
debug
[
'r'
])
if
(
0
&&
debug
[
'r'
])
yyerror
(
"interface pointer mismatch"
);
*
m
=
im
;
*
samename
=
nil
;
*
ptr
=
1
;
...
...
src/cmd/gc/walk.c
View file @
d6b29259
...
...
@@ -18,12 +18,14 @@ static NodeList* paramstoheap(Type **argin, int out);
static
NodeList
*
reorder1
(
NodeList
*
);
static
NodeList
*
reorder3
(
NodeList
*
);
static
Node
*
addstr
(
Node
*
,
NodeList
**
);
static
Node
*
appendslice
(
Node
*
,
NodeList
**
);
static
Node
*
append
(
Node
*
,
NodeList
**
);
static
int
oasappend
(
Node
**
,
NodeList
**
);
static
NodeList
*
walkdefstack
;
// can this code branch reach the end
// without an un
dcont
itional RETURN
// without an un
cond
itional RETURN
// this is hard, so it is conservative
static
int
walkret
(
NodeList
*
l
)
...
...
@@ -805,18 +807,20 @@ walkexpr(Node **np, NodeList **init)
n
->
ninit
=
nil
;
walkexpr
(
&
n
->
left
,
init
);
n
->
left
=
safeexpr
(
n
->
left
,
init
);
if
(
oaslit
(
n
,
init
))
goto
ret
;
walkexpr
(
&
n
->
right
,
init
);
l
=
n
->
left
;
r
=
n
->
right
;
if
(
l
==
N
||
r
==
N
)
if
(
oasappend
(
&
n
,
init
))
goto
ret
;
r
=
ascompatee1
(
n
->
op
,
l
,
r
,
init
);
if
(
r
!=
N
)
{
walkexpr
(
&
n
->
right
,
init
);
if
(
n
->
left
!=
N
&&
n
->
right
!=
N
)
{
r
=
convas
(
nod
(
OAS
,
n
->
left
,
n
->
right
),
init
);
r
->
dodata
=
n
->
dodata
;
n
=
r
;
}
goto
ret
;
case
OAS2
:
...
...
@@ -1134,6 +1138,7 @@ walkexpr(Node **np, NodeList **init)
case
OINDEXMAP
:
if
(
n
->
etype
==
1
)
goto
ret
;
t
=
n
->
left
->
type
;
n
=
mkcall1
(
mapfn
(
"mapaccess1"
,
t
),
t
->
type
,
init
,
n
->
left
,
n
->
right
);
goto
ret
;
...
...
@@ -1188,6 +1193,7 @@ walkexpr(Node **np, NodeList **init)
// sliceslice(old []any, lb uint64, hb uint64, width uint64) (ary []any)
// sliceslice1(old []any, lb uint64, width uint64) (ary []any)
t
=
n
->
type
;
et
=
n
->
etype
;
if
(
n
->
right
->
left
==
N
)
l
=
nodintconst
(
0
);
else
...
...
@@ -1210,6 +1216,7 @@ walkexpr(Node **np, NodeList **init)
l
,
nodintconst
(
t
->
type
->
width
));
}
n
->
etype
=
et
;
// preserve no-typecheck flag from OSLICE to the slice* call.
goto
ret
;
slicearray:
...
...
@@ -1332,6 +1339,9 @@ walkexpr(Node **np, NodeList **init)
goto
ret
;
case
OAPPEND
:
if
(
n
->
isddd
)
n
=
appendslice
(
n
,
init
);
else
n
=
append
(
n
,
init
);
goto
ret
;
...
...
@@ -1953,23 +1963,18 @@ callnew(Type *t)
static
Node
*
convas
(
Node
*
n
,
NodeList
**
init
)
{
Node
*
l
,
*
r
;
Type
*
lt
,
*
rt
;
if
(
n
->
op
!=
OAS
)
fatal
(
"convas: not OAS %O"
,
n
->
op
);
n
->
typecheck
=
1
;
lt
=
T
;
rt
=
T
;
n
->
typecheck
=
1
;
l
=
n
->
left
;
r
=
n
->
right
;
if
(
l
==
N
||
r
==
N
)
if
(
n
->
left
==
N
||
n
->
right
==
N
)
goto
out
;
lt
=
l
->
type
;
rt
=
r
->
type
;
lt
=
n
->
left
->
type
;
rt
=
n
->
right
->
type
;
if
(
lt
==
T
||
rt
==
T
)
goto
out
;
...
...
@@ -1987,7 +1992,7 @@ convas(Node *n, NodeList **init)
if
(
eqtype
(
lt
,
rt
))
goto
out
;
n
->
right
=
assignconv
(
r
,
lt
,
"assignment"
);
n
->
right
=
assignconv
(
n
->
right
,
lt
,
"assignment"
);
walkexpr
(
&
n
->
right
,
init
);
out:
...
...
@@ -2365,20 +2370,23 @@ addstr(Node *n, NodeList **init)
}
static
Node
*
append
(
Node
*
n
,
NodeList
**
init
)
append
slice
(
Node
*
n
,
NodeList
**
init
)
{
int
i
,
j
;
Node
*
f
,
*
r
;
NodeList
*
in
,
*
args
;
Node
*
f
;
if
(
n
->
isddd
)
{
f
=
syslook
(
"appendslice"
,
1
);
argtype
(
f
,
n
->
type
);
argtype
(
f
,
n
->
type
->
type
);
argtype
(
f
,
n
->
type
);
r
=
mkcall1
(
f
,
n
->
type
,
init
,
typename
(
n
->
type
),
n
->
list
->
n
,
n
->
list
->
next
->
n
);
return
r
;
}
return
mkcall1
(
f
,
n
->
type
,
init
,
typename
(
n
->
type
),
n
->
list
->
n
,
n
->
list
->
next
->
n
);
}
static
Node
*
append
(
Node
*
n
,
NodeList
**
init
)
{
int
i
,
j
;
Node
*
f
,
*
r
;
NodeList
*
in
,
*
args
;
j
=
count
(
n
->
list
)
-
1
;
f
=
syslook
(
"append"
,
1
);
...
...
@@ -2404,3 +2412,77 @@ append(Node *n, NodeList **init)
return
r
;
}
// expand s = append(s, a [, b]* ) to
//
// const argc = len(args) - 1
// if cap(s) - len(s) < argc {
// s = growslice(s, argc)
// }
// n := len(s)
// s = s[:n+argc]
// s[n] = a
// s[n+1] = b
// ...
//
static
int
oasappend
(
Node
**
np
,
NodeList
**
init
)
{
NodeList
*
l
,
*
a
;
Node
*
n
,
*
ns
,
*
nn
,
*
na
,
*
nx
,
*
fn
;
int
argc
;
n
=
*
np
;
// Check that it's an assignment of the form s = append(s, elem), where s is ONAME.
if
(
n
->
right
==
N
||
n
->
right
->
op
!=
OAPPEND
||
n
->
right
->
isddd
||
n
->
left
==
N
||
n
->
left
->
op
!=
ONAME
||
n
->
left
!=
n
->
right
->
list
->
n
)
return
0
;
ns
=
cheapexpr
(
n
->
left
,
init
);
walkexprlistsafe
(
n
->
right
->
list
,
init
);
argc
=
count
(
n
->
right
->
list
)
-
1
;
if
(
argc
<
1
)
{
n
->
op
=
OEMPTY
;
return
1
;
}
na
=
nodintconst
(
argc
);
// const argc
nx
=
nod
(
OIF
,
N
,
N
);
// if cap(s) - len(s) < argc
nx
->
lineno
=
n
->
lineno
;
nx
->
ntest
=
nod
(
OLT
,
nod
(
OSUB
,
nod
(
OCAP
,
ns
,
N
),
nod
(
OLEN
,
ns
,
N
)),
na
);
fn
=
syslook
(
"growslice"
,
1
);
// growslice(<type>, old []T, n int64) (ret []T)
argtype
(
fn
,
ns
->
type
->
type
);
// 1 old []any
argtype
(
fn
,
ns
->
type
->
type
);
// 2 ret []any
nx
->
nbody
=
list1
(
nod
(
OAS
,
ns
,
mkcall1
(
fn
,
ns
->
type
,
&
nx
->
ninit
,
typename
(
ns
->
type
),
ns
,
conv
(
na
,
types
[
TINT64
]))));
l
=
list1
(
nx
);
nn
=
nod
(
OXXX
,
N
,
N
);
// var n
tempname
(
nn
,
types
[
TINT
]);
l
=
list
(
l
,
nod
(
OAS
,
nn
,
nod
(
OLEN
,
ns
,
N
)));
// n = len(s)
nx
=
nod
(
OSLICE
,
ns
,
nod
(
OKEY
,
N
,
nod
(
OADD
,
nn
,
na
)));
// ...s[:n+argc]
nx
->
etype
=
1
;
// disable bounds check
l
=
list
(
l
,
nod
(
OAS
,
ns
,
nx
));
// s = s[:n+argc]
for
(
a
=
n
->
right
->
list
->
next
;
a
!=
nil
;
a
=
a
->
next
)
{
nx
=
nod
(
OINDEX
,
ns
,
nn
);
// s[n] ...
nx
->
etype
=
1
;
// disable bounds check
l
=
list
(
l
,
nod
(
OAS
,
nx
,
a
->
n
));
// s[n] = arg
if
(
a
->
next
!=
nil
)
l
=
list
(
l
,
nod
(
OAS
,
nn
,
nod
(
OADD
,
nn
,
nodintconst
(
1
))));
// n = n + 1
}
typechecklist
(
l
,
Etop
);
*
np
=
liststmt
(
l
);
walkstmt
(
np
);
return
1
;
}
src/pkg/runtime/append_test.go
0 → 100644
View file @
d6b29259
// Copyright 2011 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_test
import
"testing"
const
N
=
20
func
BenchmarkAppend
(
b
*
testing
.
B
)
{
b
.
StopTimer
()
x
:=
make
([]
int
,
0
,
N
)
b
.
StartTimer
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
x
=
x
[
0
:
0
]
for
j
:=
0
;
j
<
N
;
j
++
{
x
=
append
(
x
,
j
)
}
}
}
func
BenchmarkAppendSpecialCase
(
b
*
testing
.
B
)
{
b
.
StopTimer
()
x
:=
make
([]
int
,
0
,
N
)
b
.
StartTimer
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
x
=
x
[
0
:
0
]
for
j
:=
0
;
j
<
N
;
j
++
{
if
len
(
x
)
<
cap
(
x
)
{
x
=
x
[
:
len
(
x
)
+
1
]
x
[
len
(
x
)
-
1
]
=
j
}
else
{
x
=
append
(
x
,
j
)
}
}
}
}
var
x
=
make
([]
int
,
0
,
10
)
func
f
()
int
{
x
[
:
1
][
0
]
=
3
return
2
}
func
TestSideEffectOrder
(
t
*
testing
.
T
)
{
x
=
append
(
x
,
1
,
f
())
if
x
[
0
]
!=
1
||
x
[
1
]
!=
2
{
t
.
Error
(
"append failed: "
,
x
[
0
],
x
[
1
])
}
}
src/pkg/runtime/slice.c
View file @
d6b29259
...
...
@@ -9,6 +9,8 @@
static
int32
debug
=
0
;
static
void
makeslice1
(
SliceType
*
,
int32
,
int32
,
Slice
*
);
static
void
growslice1
(
SliceType
*
,
Slice
,
int32
,
Slice
*
);
static
void
appendslice1
(
SliceType
*
,
Slice
,
Slice
,
Slice
*
);
void
runtime
·
slicecopy
(
Slice
to
,
Slice
fm
,
uintptr
width
,
int32
ret
);
// see also unsafe·NewArray
...
...
@@ -46,8 +48,6 @@ makeslice1(SliceType *t, int32 len, int32 cap, Slice *ret)
ret
->
array
=
runtime
·
mal
(
size
);
}
static
void
appendslice1
(
SliceType
*
,
Slice
,
Slice
,
Slice
*
);
// append(type *Type, n int, old []T, ...,) []T
#pragma textflag 7
void
...
...
@@ -72,37 +72,70 @@ runtime·appendslice(SliceType *t, Slice x, Slice y, Slice ret)
static
void
appendslice1
(
SliceType
*
t
,
Slice
x
,
Slice
y
,
Slice
*
ret
)
{
Slice
newx
;
int32
m
;
uintptr
w
;
if
(
x
.
len
+
y
.
len
<
x
.
len
)
m
=
x
.
len
+
y
.
len
;
if
(
m
<
x
.
len
)
runtime
·
throw
(
"append: slice overflow"
);
if
(
m
>
x
.
cap
)
growslice1
(
t
,
x
,
m
,
ret
);
else
*
ret
=
x
;
w
=
t
->
elem
->
size
;
if
(
x
.
len
+
y
.
len
>
x
.
cap
)
{
runtime
·
memmove
(
ret
->
array
+
ret
->
len
*
w
,
y
.
array
,
y
.
len
*
w
);
ret
->
len
+=
y
.
len
;
}
// growslice(type *Type, x, []T, n int64) []T
void
runtime
·
growslice
(
SliceType
*
t
,
Slice
old
,
int64
n
,
Slice
ret
)
{
int64
cap
;
if
(
n
<
1
)
runtime
·
panicstring
(
"growslice: invalid n"
);
cap
=
old
.
cap
+
n
;
if
((
int32
)
cap
!=
cap
||
cap
>
((
uintptr
)
-
1
)
/
t
->
elem
->
size
)
runtime
·
panicstring
(
"growslice: cap out of range"
);
growslice1
(
t
,
old
,
cap
,
&
ret
);
FLUSH
(
&
ret
);
if
(
debug
)
{
runtime
·
printf
(
"growslice(%S,"
,
*
t
->
string
);
runtime
·
printslice
(
old
);
runtime
·
printf
(
", new cap=%D) ="
,
cap
);
runtime
·
printslice
(
ret
);
}
}
static
void
growslice1
(
SliceType
*
t
,
Slice
x
,
int32
newcap
,
Slice
*
ret
)
{
int32
m
;
m
=
x
.
cap
;
if
(
m
==
0
)
m
=
y
.
len
;
m
=
newcap
;
else
{
do
{
if
(
x
.
len
<
1024
)
m
+=
m
;
else
m
+=
m
/
4
;
}
while
(
m
<
x
.
len
+
y
.
len
);
}
while
(
m
<
newcap
);
}
makeslice1
(
t
,
x
.
len
,
m
,
&
newx
);
runtime
·
memmove
(
newx
.
array
,
x
.
array
,
x
.
len
*
w
);
x
=
newx
;
}
runtime
·
memmove
(
x
.
array
+
x
.
len
*
w
,
y
.
array
,
y
.
len
*
w
);
x
.
len
+=
y
.
len
;
*
ret
=
x
;
makeslice1
(
t
,
x
.
len
,
m
,
ret
);
runtime
·
memmove
(
ret
->
array
,
x
.
array
,
ret
->
len
*
t
->
elem
->
size
);
}
// sliceslice(old []any, lb uint64, hb uint64, width uint64) (ary []any);
void
runtime
·
sliceslice
(
Slice
old
,
uint64
lb
,
uint64
hb
,
uint64
width
,
Slice
ret
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment