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
c7513eac
Commit
c7513eac
authored
Jul 07, 2009
by
Russ Cox
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
runtime: use new reflect data structures (CL 31107)
in place of sigi, sigt. R=ken OCL=31118 CL=31277
parent
ce2e450c
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
247 additions
and
531 deletions
+247
-531
src/cmd/gc/sys.go
src/cmd/gc/sys.go
+11
-11
src/pkg/runtime/Makefile
src/pkg/runtime/Makefile
+1
-0
src/pkg/runtime/iface.c
src/pkg/runtime/iface.c
+229
-514
src/pkg/runtime/print.c
src/pkg/runtime/print.c
+2
-2
src/pkg/runtime/runtime.h
src/pkg/runtime/runtime.h
+4
-4
No files found.
src/cmd/gc/sys.go
View file @
c7513eac
...
...
@@ -36,17 +36,17 @@ func stringiter(string, int) int;
func
stringiter2
(
string
,
int
)
(
retk
int
,
retv
int
);
func
ifaceI2E
(
iface
any
)
(
ret
any
);
func
ifaceE2I
(
sigi
*
byte
,
iface
any
)
(
ret
any
);
func
ifaceT2E
(
sigt
*
byte
,
elem
any
)
(
ret
any
);
func
ifaceE2T
(
sigt
*
byte
,
elem
any
)
(
ret
any
);
func
ifaceE2I2
(
sigi
*
byte
,
iface
any
)
(
ret
any
,
ok
bool
);
func
ifaceE2T2
(
sigt
*
byte
,
elem
any
)
(
ret
any
,
ok
bool
);
func
ifaceT2I
(
sigi
*
byte
,
sigt
*
byte
,
elem
any
)
(
ret
any
);
func
ifaceI2T
(
sigt
*
byte
,
iface
any
)
(
ret
any
);
func
ifaceI2T2
(
sigt
*
byte
,
iface
any
)
(
ret
any
,
ok
bool
);
func
ifaceI2I
(
sigi
*
byte
,
iface
any
)
(
ret
any
);
func
ifaceI2Ix
(
sigi
*
byte
,
iface
any
)
(
ret
any
);
func
ifaceI2I2
(
sigi
*
byte
,
iface
any
)
(
ret
any
,
ok
bool
);
func
ifaceE2I
(
typ
*
byte
,
iface
any
)
(
ret
any
);
func
ifaceT2E
(
typ
*
byte
,
elem
any
)
(
ret
any
);
func
ifaceE2T
(
typ
*
byte
,
elem
any
)
(
ret
any
);
func
ifaceE2I2
(
typ
*
byte
,
iface
any
)
(
ret
any
,
ok
bool
);
func
ifaceE2T2
(
typ
*
byte
,
elem
any
)
(
ret
any
,
ok
bool
);
func
ifaceT2I
(
typ1
*
byte
,
typ2
*
byte
,
elem
any
)
(
ret
any
);
func
ifaceI2T
(
typ
*
byte
,
iface
any
)
(
ret
any
);
func
ifaceI2T2
(
typ
*
byte
,
iface
any
)
(
ret
any
,
ok
bool
);
func
ifaceI2I
(
typ
*
byte
,
iface
any
)
(
ret
any
);
func
ifaceI2Ix
(
typ
*
byte
,
iface
any
)
(
ret
any
);
func
ifaceI2I2
(
typ
*
byte
,
iface
any
)
(
ret
any
,
ok
bool
);
func
ifaceeq
(
i1
any
,
i2
any
)
(
ret
bool
);
func
efaceeq
(
i1
any
,
i2
any
)
(
ret
bool
);
func
ifacethash
(
i1
any
)
(
ret
uint32
);
...
...
src/pkg/runtime/Makefile
View file @
c7513eac
...
...
@@ -70,6 +70,7 @@ OFILES=\
sys.
$O
\
thread.
$O
\
traceback.
$O
\
type.
$O
\
$
(
OFILES_
$(GOARCH)
)
\
HFILES
=
\
...
...
src/pkg/runtime/iface.c
View file @
c7513eac
...
...
@@ -3,173 +3,64 @@
// license that can be found in the LICENSE file.
#include "runtime.h"
#include "type.h"
int32
iface_debug
=
0
;
static
void
printiface
(
Iface
i
)
{
printf
(
"(%p,%p)"
,
i
.
tab
,
i
.
data
);
}
typedef
struct
Sigt
Sigt
;
typedef
struct
Sigi
Sigi
;
typedef
struct
Itype
Itype
;
static
void
printeface
(
Eface
e
)
{
printf
(
"(%p,%p)"
,
e
.
type
,
e
.
data
);
}
/*
*
the layout of Iface, Sigt and Sigi are known to the compiler
*
layout of Itab known to compilers
*/
struct
Sigt
{
byte
*
name
;
// name of basic type
Sigt
*
link
;
// for linking into hash tables
uint32
thash
;
// hash of type
uint32
mhash
;
// hash of methods
uint16
width
;
// width of base type in bytes
uint16
alg
;
// algorithm
// note: on amd64 there is a 32-bit pad here.
struct
{
byte
*
fname
;
uint32
fhash
;
// hash of type
uint32
offset
;
// offset of substruct
void
(
*
fun
)(
void
);
}
meth
[
1
];
// one or more - last name is nil
};
struct
Sigi
struct
Itab
{
byte
*
name
;
uint32
hash
;
uint32
size
;
// number of methods
struct
{
byte
*
fname
;
uint32
fhash
;
uint32
perm
;
// location of fun in Sigt
}
meth
[
1
];
// [size+1] - last name is nil
};
struct
Itype
{
Sigi
*
sigi
;
Sigt
*
sigt
;
Itype
*
link
;
InterfaceType
*
inter
;
Type
*
type
;
Itab
*
link
;
int32
bad
;
int32
unused
;
void
(
*
fun
[])(
void
);
};
static
Iface
niliface
;
static
Eface
nileface
;
static
Itype
*
hash
[
1009
];
static
Itab
*
hash
[
1009
];
static
Lock
ifacelock
;
Sigi
sigi
·
empty
[
2
]
=
{
(
byte
*
)
"interface { }"
};
static
void
printsigi
(
Sigi
*
si
)
{
int32
i
;
byte
*
name
;
sys
·
printpointer
(
si
);
prints
(
"{"
);
prints
((
int8
*
)
si
->
name
);
prints
(
":"
);
for
(
i
=
0
;;
i
++
)
{
name
=
si
->
meth
[
i
].
fname
;
if
(
name
==
nil
)
break
;
prints
(
"["
);
sys
·
printint
(
i
);
prints
(
"]
\"
"
);
prints
((
int8
*
)
name
);
prints
(
"
\"
"
);
sys
·
printint
(
si
->
meth
[
i
].
fhash
%
999
);
prints
(
"/"
);
sys
·
printint
(
si
->
meth
[
i
].
perm
);
}
prints
(
"}"
);
}
static
void
printsigt
(
Sigt
*
st
)
{
int32
i
;
byte
*
name
;
sys
·
printpointer
(
st
);
prints
(
"{"
);
prints
((
int8
*
)
st
->
name
);
prints
(
":"
);
sys
·
printint
(
st
->
thash
%
999
);
// type hash
prints
(
","
);
sys
·
printint
(
st
->
mhash
%
999
);
// method hash
prints
(
","
);
sys
·
printint
(
st
->
width
);
// width
prints
(
","
);
sys
·
printint
(
st
->
alg
);
// algorithm
for
(
i
=
0
;;
i
++
)
{
name
=
st
->
meth
[
i
].
fname
;
if
(
name
==
nil
)
break
;
prints
(
"["
);
sys
·
printint
(
i
);
prints
(
"]
\"
"
);
prints
((
int8
*
)
name
);
prints
(
"
\"
"
);
sys
·
printint
(
st
->
meth
[
i
].
fhash
%
999
);
prints
(
"/"
);
sys
·
printint
(
st
->
meth
[
i
].
offset
);
prints
(
"/"
);
sys
·
printpointer
(
st
->
meth
[
i
].
fun
);
}
prints
(
"}"
);
}
static
void
printiface
(
Iface
i
)
{
prints
(
"("
);
sys
·
printpointer
(
i
.
type
);
prints
(
","
);
sys
·
printpointer
(
i
.
data
);
prints
(
")"
);
}
static
void
printeface
(
Eface
e
)
{
prints
(
"("
);
sys
·
printpointer
(
e
.
type
);
prints
(
","
);
sys
·
printpointer
(
e
.
data
);
prints
(
")"
);
}
static
Itype
*
itype
(
Sigi
*
si
,
Sigt
*
st
,
int32
canfail
)
static
Itab
*
itab
(
InterfaceType
*
inter
,
Type
*
type
,
int32
canfail
)
{
int32
locked
;
int32
nt
,
ni
;
int32
ni
;
Method
*
t
,
*
et
;
IMethod
*
i
,
*
ei
;
uint32
ihash
,
h
;
byte
*
sname
,
*
iname
;
Itype
*
m
;
String
*
iname
;
Itab
*
m
;
UncommonType
*
x
;
if
(
si
->
size
==
0
)
throw
(
"internal error - misuse of it
ype
"
);
if
(
inter
->
mhdr
.
nel
==
0
)
throw
(
"internal error - misuse of it
ab
"
);
// easy case
if
(
st
->
meth
[
0
].
fname
==
nil
)
{
x
=
type
->
x
;
if
(
x
==
nil
)
{
if
(
canfail
)
return
nil
;
iname
=
si
->
meth
[
0
].
f
name
;
goto
throw
1
;
iname
=
inter
->
m
[
0
].
name
;
goto
throw
;
}
// compiler has provided some good hash codes for us.
h
=
0
;
if
(
si
)
h
+=
si
->
hash
;
if
(
st
)
{
h
+=
st
->
thash
;
h
+=
st
->
mhash
;
}
h
=
inter
->
hash
;
h
+=
17
*
type
->
hash
;
// TODO(rsc): h += 23 * x->mhash ?
h
%=
nelem
(
hash
);
// look twice - once without lock, once with.
...
...
@@ -178,7 +69,7 @@ itype(Sigi *si, Sigt *st, int32 canfail)
if
(
locked
)
lock
(
&
ifacelock
);
for
(
m
=
hash
[
h
];
m
!=
nil
;
m
=
m
->
link
)
{
if
(
m
->
sigi
==
si
&&
m
->
sigt
==
st
)
{
if
(
m
->
inter
==
inter
&&
m
->
type
==
type
)
{
if
(
m
->
bad
)
{
m
=
nil
;
if
(
!
canfail
)
{
...
...
@@ -188,8 +79,8 @@ itype(Sigi *si, Sigt *st, int32 canfail)
// the cached result doesn't record which
// interface function was missing, so jump
// down to the interface check, which will
// give a better error.
goto
throw
;
//
do more work but
give a better error.
goto
search
;
}
}
if
(
locked
)
...
...
@@ -199,69 +90,60 @@ itype(Sigi *si, Sigt *st, int32 canfail)
}
}
ni
=
si
->
size
;
m
=
malloc
(
sizeof
(
*
m
)
+
ni
*
sizeof
(
m
->
fun
[
0
])
);
m
->
sigi
=
si
;
m
->
sigt
=
st
;
ni
=
inter
->
mhdr
.
nel
;
m
=
malloc
(
sizeof
(
*
m
)
+
ni
*
sizeof
m
->
fun
[
0
]
);
m
->
inter
=
inter
;
m
->
type
=
type
;
throw:
nt
=
0
;
for
(
ni
=
0
;;
ni
++
)
{
iname
=
si
->
meth
[
ni
].
fname
;
if
(
iname
==
nil
)
break
;
// pick up next name from
// interface signature
ihash
=
si
->
meth
[
ni
].
fhash
;
for
(;;
nt
++
)
{
// pick up and compare next name
// from structure signature
sname
=
st
->
meth
[
nt
].
fname
;
if
(
sname
==
nil
)
{
search:
// both inter and type have method sorted by hash,
// so can iterate over both in lock step;
// the loop is O(ni+nt) not O(ni*nt).
i
=
inter
->
m
;
ei
=
i
+
inter
->
mhdr
.
nel
;
t
=
x
->
m
;
et
=
t
+
x
->
mhdr
.
nel
;
for
(;
i
<
ei
;
i
++
)
{
ihash
=
i
->
hash
;
iname
=
i
->
name
;
for
(;;
t
++
)
{
if
(
t
>=
et
)
{
if
(
!
canfail
)
{
throw1:
printf
(
"cannot convert type %s to interface %s: missing method %s
\n
"
,
st
->
name
,
si
->
name
,
iname
);
if
(
iface_debug
)
{
prints
(
"interface"
);
printsigi
(
si
);
prints
(
"
\n
type"
);
printsigt
(
st
);
prints
(
"
\n
"
);
}
throw:
// didn't find method
printf
(
"%S is not %S: missing method %S
\n
"
,
*
type
->
string
,
*
inter
->
string
,
*
iname
);
throw
(
"interface conversion"
);
return
nil
;
// not reached
}
m
->
bad
=
1
;
m
->
link
=
hash
[
h
];
hash
[
h
]
=
m
;
if
(
locked
)
unlock
(
&
ifacelock
);
return
nil
;
goto
out
;
}
if
(
ihash
==
st
->
meth
[
nt
].
fhash
&&
strcmp
(
sname
,
iname
)
==
0
)
if
(
t
->
hash
==
ihash
&&
t
->
name
==
iname
)
break
;
}
m
->
fun
[
si
->
meth
[
ni
].
perm
]
=
st
->
meth
[
nt
].
fun
;
if
(
m
)
m
->
fun
[
i
->
perm
]
=
t
->
ifn
;
}
out:
m
->
link
=
hash
[
h
];
hash
[
h
]
=
m
;
if
(
locked
)
unlock
(
&
ifacelock
);
if
(
m
->
bad
)
return
nil
;
return
m
;
}
static
void
copyin
(
Sigt
*
s
t
,
void
*
src
,
void
**
dst
)
copyin
(
Type
*
t
,
void
*
src
,
void
**
dst
)
{
int32
wid
,
alg
;
void
*
p
;
wid
=
st
->
width
;
alg
=
s
t
->
alg
;
wid
=
t
->
size
;
alg
=
t
->
alg
;
if
(
wid
<=
sizeof
(
*
dst
))
algarray
[
alg
].
copy
(
wid
,
dst
,
src
);
...
...
@@ -273,12 +155,12 @@ copyin(Sigt *st, void *src, void **dst)
}
static
void
copyout
(
Sigt
*
s
t
,
void
**
src
,
void
*
dst
)
copyout
(
Type
*
t
,
void
**
src
,
void
*
dst
)
{
int32
wid
,
alg
;
wid
=
st
->
width
;
alg
=
s
t
->
alg
;
wid
=
t
->
size
;
alg
=
t
->
alg
;
if
(
wid
<=
sizeof
(
*
src
))
algarray
[
alg
].
copy
(
wid
,
dst
,
src
);
...
...
@@ -286,132 +168,123 @@ copyout(Sigt *st, void **src, void *dst)
algarray
[
alg
].
copy
(
wid
,
dst
,
*
src
);
}
// ifaceT2I(sigi *byte, sigt *byte, elem any) (ret
any
);
// ifaceT2I(sigi *byte, sigt *byte, elem any) (ret
Iface
);
#pragma textflag 7
void
sys
·
ifaceT2I
(
Sigi
*
si
,
Sigt
*
s
t
,
...)
sys
·
ifaceT2I
(
InterfaceType
*
inter
,
Type
*
t
,
...)
{
byte
*
elem
;
Iface
*
ret
;
int32
wid
;
elem
=
(
byte
*
)(
&
st
+
1
);
wid
=
st
->
width
;
ret
=
(
Iface
*
)(
elem
+
rnd
(
wid
,
sizeof
(
uintptr
)));
ret
->
type
=
itype
(
si
,
st
,
0
);
copyin
(
st
,
elem
,
&
ret
->
data
);
elem
=
(
byte
*
)(
&
t
+
1
);
wid
=
t
->
size
;
ret
=
(
Iface
*
)(
elem
+
rnd
(
wid
,
Structrnd
));
ret
->
tab
=
itab
(
inter
,
t
,
0
);
copyin
(
t
,
elem
,
&
ret
->
data
);
}
// ifaceT2E(sigt *byte, elem any) (ret
any
);
// ifaceT2E(sigt *byte, elem any) (ret
Eface
);
#pragma textflag 7
void
sys
·
ifaceT2E
(
Sigt
*
s
t
,
...)
sys
·
ifaceT2E
(
Type
*
t
,
...)
{
byte
*
elem
;
Eface
*
ret
;
int32
wid
;
elem
=
(
byte
*
)(
&
s
t
+
1
);
wid
=
st
->
width
;
ret
=
(
Eface
*
)(
elem
+
rnd
(
wid
,
sizeof
(
uintptr
)
));
elem
=
(
byte
*
)(
&
t
+
1
);
wid
=
t
->
size
;
ret
=
(
Eface
*
)(
elem
+
rnd
(
wid
,
Structrnd
));
ret
->
type
=
s
t
;
copyin
(
s
t
,
elem
,
&
ret
->
data
);
ret
->
type
=
t
;
copyin
(
t
,
elem
,
&
ret
->
data
);
}
// ifaceI2T(sigt *byte, iface any) (ret any);
#pragma textflag 7
void
sys
·
ifaceI2T
(
Sigt
*
s
t
,
Iface
i
,
...)
sys
·
ifaceI2T
(
Type
*
t
,
Iface
i
,
...)
{
It
ype
*
im
;
It
ab
*
tab
;
byte
*
ret
;
ret
=
(
byte
*
)(
&
i
+
1
);
im
=
i
.
type
;
if
(
im
==
nil
)
{
printf
(
"interface is nil, not %s
\n
"
,
st
->
name
);
tab
=
i
.
tab
;
if
(
tab
==
nil
)
{
printf
(
"interface is nil, not %S
\n
"
,
*
t
->
string
);
throw
(
"interface conversion"
);
}
if
(
im
->
sigt
!=
s
t
)
{
printf
(
"%
s is %s, not %s
\n
"
,
im
->
sigi
->
name
,
im
->
sigt
->
name
,
st
->
name
);
if
(
tab
->
type
!=
t
)
{
printf
(
"%
S is %S, not %S
\n
"
,
*
tab
->
inter
->
string
,
*
tab
->
type
->
string
,
*
t
->
string
);
throw
(
"interface conversion"
);
}
copyout
(
s
t
,
&
i
.
data
,
ret
);
copyout
(
t
,
&
i
.
data
,
ret
);
}
// ifaceI2T2(sigt *byte, i
face any
) (ret any, ok bool);
// ifaceI2T2(sigt *byte, i
Iface
) (ret any, ok bool);
#pragma textflag 7
void
sys
·
ifaceI2T2
(
Sigt
*
s
t
,
Iface
i
,
...)
sys
·
ifaceI2T2
(
Type
*
t
,
Iface
i
,
...)
{
byte
*
ret
;
bool
*
ok
;
Itype
*
im
;
int32
wid
;
ret
=
(
byte
*
)(
&
i
+
1
);
wid
=
st
->
width
;
wid
=
t
->
size
;
ok
=
(
bool
*
)(
ret
+
rnd
(
wid
,
1
));
im
=
i
.
type
;
if
(
im
==
nil
||
im
->
sigt
!=
st
)
{
if
(
i
.
tab
==
nil
||
i
.
tab
->
type
!=
t
)
{
*
ok
=
false
;
sys
·
memclr
(
ret
,
wid
);
return
;
}
*
ok
=
true
;
copyout
(
s
t
,
&
i
.
data
,
ret
);
copyout
(
t
,
&
i
.
data
,
ret
);
}
// ifaceE2T(sigt *byte,
iface any
) (ret any);
// ifaceE2T(sigt *byte,
e Eface
) (ret any);
#pragma textflag 7
void
sys
·
ifaceE2T
(
Sigt
*
s
t
,
Eface
e
,
...)
sys
·
ifaceE2T
(
Type
*
t
,
Eface
e
,
...)
{
Sigt
*
t
;
byte
*
ret
;
ret
=
(
byte
*
)(
&
e
+
1
);
t
=
e
.
type
;
if
(
t
==
nil
)
{
printf
(
"interface is nil, not %s
\n
"
,
st
->
name
);
throw
(
"interface conversion"
);
}
if
(
t
!=
st
)
{
printf
(
"interface is %s, not %s
\n
"
,
t
->
name
,
st
->
name
);
if
(
e
.
type
!=
t
)
{
if
(
e
.
type
==
nil
)
printf
(
"interface is nil, not %S
\n
"
,
*
t
->
string
);
else
printf
(
"interface is %S, not %S
\n
"
,
*
e
.
type
->
string
,
*
t
->
string
);
throw
(
"interface conversion"
);
}
copyout
(
s
t
,
&
e
.
data
,
ret
);
copyout
(
t
,
&
e
.
data
,
ret
);
}
// ifaceE2T2(sigt *byte, iface any) (ret any, ok bool);
#pragma textflag 7
void
sys
·
ifaceE2T2
(
Sigt
*
s
t
,
Eface
e
,
...)
sys
·
ifaceE2T2
(
Type
*
t
,
Eface
e
,
...)
{
byte
*
ret
;
bool
*
ok
;
Sigt
*
t
;
int32
wid
;
ret
=
(
byte
*
)(
&
e
+
1
);
wid
=
st
->
width
;
wid
=
t
->
size
;
ok
=
(
bool
*
)(
ret
+
rnd
(
wid
,
1
));
t
=
e
.
type
;
if
(
t
!=
st
)
{
if
(
t
!=
e
.
type
)
{
*
ok
=
false
;
sys
·
memclr
(
ret
,
wid
);
return
;
}
*
ok
=
true
;
copyout
(
s
t
,
&
e
.
data
,
ret
);
copyout
(
t
,
&
e
.
data
,
ret
);
}
// ifaceI2E(sigi *byte, iface any) (ret any);
...
...
@@ -419,33 +292,35 @@ sys·ifaceE2T2(Sigt *st, Eface e, ...)
void
sys
·
ifaceI2E
(
Iface
i
,
Eface
ret
)
{
It
ype
*
im
;
It
ab
*
tab
;
ret
.
data
=
i
.
data
;
im
=
i
.
type
;
if
(
im
==
nil
)
tab
=
i
.
tab
;
if
(
tab
==
nil
)
ret
.
type
=
nil
;
else
ret
.
type
=
im
->
sigt
;
ret
.
type
=
tab
->
type
;
FLUSH
(
&
ret
);
}
// ifaceI2I(sigi *byte, iface any) (ret any);
// called only for implicit (no type assertion) conversions
// called only for implicit (no type assertion) conversions.
// converting nil is okay.
void
sys
·
ifaceI2I
(
Sigi
*
si
,
Iface
i
,
Iface
ret
)
sys
·
ifaceI2I
(
InterfaceType
*
inter
,
Iface
i
,
Iface
ret
)
{
It
ype
*
im
;
It
ab
*
tab
;
im
=
i
.
type
;
if
(
im
==
nil
)
{
tab
=
i
.
tab
;
if
(
tab
==
nil
)
{
// If incoming interface is uninitialized (zeroed)
// make the outgoing interface zeroed as well.
ret
=
niliface
;
ret
.
tab
=
nil
;
ret
.
data
=
nil
;
}
else
{
ret
=
i
;
if
(
im
->
sigi
!=
si
)
ret
.
t
ype
=
itype
(
si
,
im
->
sigt
,
0
);
if
(
tab
->
inter
!=
inter
)
ret
.
t
ab
=
itab
(
inter
,
tab
->
type
,
0
);
}
FLUSH
(
&
ret
);
...
...
@@ -453,20 +328,21 @@ sys·ifaceI2I(Sigi *si, Iface i, Iface ret)
// ifaceI2Ix(sigi *byte, iface any) (ret any);
// called only for explicit conversions (with type assertion).
// converting nil is not okay.
void
sys
·
ifaceI2Ix
(
Sigi
*
si
,
Iface
i
,
Iface
ret
)
sys
·
ifaceI2Ix
(
InterfaceType
*
inter
,
Iface
i
,
Iface
ret
)
{
It
ype
*
im
;
It
ab
*
tab
;
im
=
i
.
type
;
if
(
im
==
nil
)
{
tab
=
i
.
tab
;
if
(
tab
==
nil
)
{
// explicit conversions require non-nil interface value.
printf
(
"interface is nil, not %
s
\n
"
,
si
->
name
);
printf
(
"interface is nil, not %
S
\n
"
,
*
inter
->
string
);
throw
(
"interface conversion"
);
}
else
{
ret
=
i
;
if
(
im
->
sigi
!=
si
)
ret
.
t
ype
=
itype
(
si
,
im
->
sigt
,
0
);
if
(
tab
->
inter
!=
inter
)
ret
.
t
ab
=
itab
(
inter
,
tab
->
type
,
0
);
}
FLUSH
(
&
ret
);
...
...
@@ -474,22 +350,23 @@ sys·ifaceI2Ix(Sigi *si, Iface i, Iface ret)
// ifaceI2I2(sigi *byte, iface any) (ret any, ok bool);
void
sys
·
ifaceI2I2
(
Sigi
*
si
,
Iface
i
,
Iface
ret
,
bool
ok
)
sys
·
ifaceI2I2
(
InterfaceType
*
inter
,
Iface
i
,
Iface
ret
,
bool
ok
)
{
It
ype
*
im
;
It
ab
*
tab
;
im
=
i
.
type
;
if
(
im
==
nil
)
{
tab
=
i
.
tab
;
if
(
tab
==
nil
)
{
// If incoming interface is nil, the conversion fails.
ret
=
niliface
;
ret
.
tab
=
nil
;
ret
.
data
=
nil
;
ok
=
false
;
}
else
{
ret
=
i
;
ok
=
true
;
if
(
im
->
sigi
!=
si
)
{
ret
.
t
ype
=
itype
(
si
,
im
->
sigt
,
1
);
if
(
ret
.
t
ype
==
nil
)
{
ret
=
niliface
;
if
(
tab
->
inter
!=
inter
)
{
ret
.
t
ab
=
itab
(
inter
,
tab
->
type
,
1
);
if
(
ret
.
t
ab
==
nil
)
{
ret
.
data
=
nil
;
ok
=
false
;
}
}
...
...
@@ -502,39 +379,40 @@ sys·ifaceI2I2(Sigi *si, Iface i, Iface ret, bool ok)
// ifaceE2I(sigi *byte, iface any) (ret any);
// Called only for explicit conversions (with type assertion).
void
sys
·
ifaceE2I
(
Sigi
*
si
,
Eface
e
,
Iface
ret
)
sys
·
ifaceE2I
(
InterfaceType
*
inter
,
Eface
e
,
Iface
ret
)
{
Sigt
*
t
;
Type
*
t
;
t
=
e
.
type
;
if
(
t
==
nil
)
{
// explicit conversions require non-nil interface value.
printf
(
"interface is nil, not %
s
\n
"
,
si
->
name
);
printf
(
"interface is nil, not %
S
\n
"
,
*
inter
->
string
);
throw
(
"interface conversion"
);
}
else
{
ret
.
data
=
e
.
data
;
ret
.
t
ype
=
itype
(
si
,
t
,
0
);
ret
.
t
ab
=
itab
(
inter
,
t
,
0
);
}
FLUSH
(
&
ret
);
}
// ifaceE2I2(sigi *byte, iface any) (ret any, ok bool);
void
sys
·
ifaceE2I2
(
Sigi
*
si
,
Eface
e
,
Iface
ret
,
bool
ok
)
sys
·
ifaceE2I2
(
InterfaceType
*
inter
,
Eface
e
,
Iface
ret
,
bool
ok
)
{
Sigt
*
t
;
Type
*
t
;
t
=
e
.
type
;
ok
=
true
;
if
(
t
==
nil
)
{
// If incoming interface is nil, the conversion fails.
ret
=
niliface
;
ret
.
data
=
nil
;
ret
.
tab
=
nil
;
ok
=
false
;
}
else
{
ret
.
data
=
e
.
data
;
ret
.
t
ype
=
itype
(
si
,
t
,
1
);
if
(
ret
.
t
ype
==
nil
)
{
ret
=
niliface
;
ret
.
t
ab
=
itab
(
inter
,
t
,
1
);
if
(
ret
.
t
ab
==
nil
)
{
ret
.
data
=
nil
;
ok
=
false
;
}
}
...
...
@@ -543,19 +421,19 @@ sys·ifaceE2I2(Sigi *si, Eface e, Iface ret, bool ok)
}
static
uintptr
ifacehash1
(
void
*
data
,
Sigt
*
sig
t
)
ifacehash1
(
void
*
data
,
Type
*
t
)
{
int32
alg
,
wid
;
if
(
sig
t
==
nil
)
if
(
t
==
nil
)
return
0
;
alg
=
sig
t
->
alg
;
wid
=
sigt
->
width
;
alg
=
t
->
alg
;
wid
=
t
->
size
;
if
(
algarray
[
alg
].
hash
==
nohash
)
{
// calling nohash will throw too,
// but we can print a better error.
printf
(
"hash of unhashable type %
s
\n
"
,
sigt
->
name
);
printf
(
"hash of unhashable type %
S
\n
"
,
*
t
->
string
);
if
(
alg
==
AFAKE
)
throw
(
"fake interface hash"
);
throw
(
"interface hash"
);
...
...
@@ -568,9 +446,9 @@ ifacehash1(void *data, Sigt *sigt)
uintptr
ifacehash
(
Iface
a
)
{
if
(
a
.
t
ype
==
nil
)
if
(
a
.
t
ab
==
nil
)
return
0
;
return
ifacehash1
(
a
.
data
,
a
.
t
ype
->
sigt
);
return
ifacehash1
(
a
.
data
,
a
.
t
ab
->
type
);
}
uintptr
...
...
@@ -580,17 +458,17 @@ efacehash(Eface a)
}
static
bool
ifaceeq1
(
void
*
data1
,
void
*
data2
,
Sigt
*
sig
t
)
ifaceeq1
(
void
*
data1
,
void
*
data2
,
Type
*
t
)
{
int32
alg
,
wid
;
alg
=
sig
t
->
alg
;
wid
=
sigt
->
width
;
alg
=
t
->
alg
;
wid
=
t
->
size
;
if
(
algarray
[
alg
].
equal
==
noequal
)
{
// calling noequal will throw too,
// but we can print a better error.
printf
(
"comparing uncomparable type %
s
\n
"
,
sigt
->
name
);
printf
(
"comparing uncomparable type %
S
\n
"
,
*
t
->
string
);
if
(
alg
==
AFAKE
)
throw
(
"fake interface compare"
);
throw
(
"interface compare"
);
...
...
@@ -604,11 +482,11 @@ ifaceeq1(void *data1, void *data2, Sigt *sigt)
bool
ifaceeq
(
Iface
i1
,
Iface
i2
)
{
if
(
i1
.
t
ype
!=
i2
.
type
)
if
(
i1
.
t
ab
!=
i2
.
tab
)
return
false
;
if
(
i1
.
t
ype
==
nil
)
if
(
i1
.
t
ab
==
nil
)
return
true
;
return
ifaceeq1
(
i1
.
data
,
i2
.
data
,
i1
.
t
ype
->
sigt
);
return
ifaceeq1
(
i1
.
data
,
i2
.
data
,
i1
.
t
ab
->
type
);
}
bool
...
...
@@ -641,16 +519,12 @@ sys·efaceeq(Eface e1, Eface e2, bool ret)
void
sys
·
ifacethash
(
Iface
i1
,
uint32
ret
)
{
Itype
*
im
;
Sigt
*
st
;
Itab
*
tab
;
ret
=
0
;
im
=
i1
.
type
;
if
(
im
!=
nil
)
{
st
=
im
->
sigt
;
if
(
st
!=
nil
)
ret
=
st
->
thash
;
}
tab
=
i1
.
tab
;
if
(
tab
!=
nil
)
ret
=
tab
->
type
->
hash
;
FLUSH
(
&
ret
);
}
...
...
@@ -658,12 +532,12 @@ sys·ifacethash(Iface i1, uint32 ret)
void
sys
·
efacethash
(
Eface
e1
,
uint32
ret
)
{
Sigt
*
s
t
;
Type
*
t
;
ret
=
0
;
s
t
=
e1
.
type
;
if
(
s
t
!=
nil
)
ret
=
st
->
t
hash
;
t
=
e1
.
type
;
if
(
t
!=
nil
)
ret
=
t
->
hash
;
FLUSH
(
&
ret
);
}
...
...
@@ -680,227 +554,68 @@ sys·printeface(Eface e)
}
void
unsafe
·
Reflect
(
Eface
i
,
uint64
retit
,
String
rettype
,
bool
retindir
)
{
int32
wid
;
if
(
i
.
type
==
nil
)
{
retit
=
0
;
rettype
=
emptystring
;
retindir
=
false
;
}
else
{
retit
=
(
uint64
)
i
.
data
;
rettype
=
gostring
(
i
.
type
->
name
);
wid
=
i
.
type
->
width
;
retindir
=
wid
>
sizeof
(
i
.
data
);
}
FLUSH
(
&
retit
);
FLUSH
(
&
rettype
);
FLUSH
(
&
retindir
);
}
extern
Sigt
*
gotypesigs
[];
extern
int32
ngotypesigs
;
// The reflection library can ask to unreflect on a type
// that has never been used, so we don't have a signature for it.
// For concreteness, suppose a program does
//
// type T struct{ x []int }
// var t T;
// v := reflect.NewValue(v);
// vv := v.Field(0);
// if s, ok := vv.Interface().(string) {
// print("first field is string");
// }
//
// vv.Interface() returns the result of sys.Unreflect with
// a typestring of "[]int". If []int is not used with interfaces
// in the rest of the program, there will be no signature in gotypesigs
// for "[]int", so we have to invent one. The requirements
// on the fake signature are:
//
// (1) any interface conversion using the signature will fail
// (2) calling unsafe.Reflect() returns the args to unreflect
// (3) the right algorithm type is used, for == and map insertion
//
// (1) is ensured by the fact that we allocate a new Sigt,
// so it will necessarily be != any Sigt in gotypesigs.
// (2) is ensured by storing the type string in the signature
// and setting the width to force the correct value of the bool indir.
// (3) is ensured by sniffing the type string.
//
// Note that (1) is correct behavior: if the program had tested
// for .([]int) instead of .(string) above, then there would be a
// signature with type string "[]int" in gotypesigs, and unreflect
// wouldn't call fakesigt.
static
Sigt
*
fake
[
1009
];
static
int32
nfake
;
enum
{
SizeofInt
=
4
,
SizeofFloat
=
4
,
};
// Table of prefixes of names of comparable types.
static
struct
{
int8
*
s
;
int8
n
;
int8
alg
;
int8
w
;
}
cmp
[]
=
{
// basic types
"int"
,
3
+
1
,
AMEM
,
SizeofInt
,
// +1 is NUL
"uint"
,
4
+
1
,
AMEM
,
SizeofInt
,
"int8"
,
4
+
1
,
AMEM
,
1
,
"uint8"
,
5
+
1
,
AMEM
,
1
,
"int16"
,
5
+
1
,
AMEM
,
2
,
"uint16"
,
6
+
1
,
AMEM
,
2
,
"int32"
,
5
+
1
,
AMEM
,
4
,
"uint32"
,
6
+
1
,
AMEM
,
4
,
"int64"
,
5
+
1
,
AMEM
,
8
,
"uint64"
,
6
+
1
,
AMEM
,
8
,
"uintptr"
,
7
+
1
,
AMEM
,
sizeof
(
uintptr
),
"float"
,
5
+
1
,
AMEM
,
SizeofFloat
,
"float32"
,
7
+
1
,
AMEM
,
4
,
"float64"
,
7
+
1
,
AMEM
,
8
,
"bool"
,
4
+
1
,
AMEM
,
sizeof
(
bool
),
// string compare is special
"string"
,
6
+
1
,
ASTRING
,
sizeof
(
String
),
// generic types, identified by prefix
"*"
,
1
,
AMEM
,
sizeof
(
uintptr
),
"chan "
,
5
,
AMEM
,
sizeof
(
uintptr
),
"func("
,
5
,
AMEM
,
sizeof
(
uintptr
),
"map["
,
4
,
AMEM
,
sizeof
(
uintptr
),
};
static
Sigt
*
fakesigt
(
String
type
,
bool
indir
)
unsafe
·
Typeof
(
Eface
e
,
Eface
ret
)
{
Sigt
*
sigt
;
uint32
h
;
int32
i
,
locked
;
h
=
0
;
for
(
i
=
0
;
i
<
type
.
len
;
i
++
)
h
=
h
*
37
+
type
.
str
[
i
];
h
+=
indir
;
h
%=
nelem
(
fake
);
for
(
locked
=
0
;
locked
<
2
;
locked
++
)
{
if
(
locked
)
lock
(
&
ifacelock
);
for
(
sigt
=
fake
[
h
];
sigt
!=
nil
;
sigt
=
sigt
->
link
)
{
// don't need to compare indir.
// same type string but different indir will have
// different hashes.
if
(
mcmp
(
sigt
->
name
,
type
.
str
,
type
.
len
)
==
0
)
if
(
sigt
->
name
[
type
.
len
]
==
'\0'
)
{
if
(
locked
)
unlock
(
&
ifacelock
);
return
sigt
;
}
}
}
sigt
=
malloc
(
sizeof
(
*
sigt
));
sigt
->
name
=
malloc
(
type
.
len
+
1
);
mcpy
(
sigt
->
name
,
type
.
str
,
type
.
len
);
sigt
->
alg
=
AFAKE
;
sigt
->
width
=
1
;
// small width
if
(
indir
)
sigt
->
width
=
2
*
sizeof
(
niliface
.
data
);
// big width
// AFAKE is like ANOEQ; check whether the type
// should have a more capable algorithm.
for
(
i
=
0
;
i
<
nelem
(
cmp
);
i
++
)
{
if
(
mcmp
((
byte
*
)
sigt
->
name
,
(
byte
*
)
cmp
[
i
].
s
,
cmp
[
i
].
n
)
==
0
)
{
sigt
->
alg
=
cmp
[
i
].
alg
;
sigt
->
width
=
cmp
[
i
].
w
;
break
;
}
}
sigt
->
link
=
fake
[
h
];
fake
[
h
]
=
sigt
;
unlock
(
&
ifacelock
);
return
sigt
;
if
(
e
.
type
==
nil
)
{
ret
.
type
=
nil
;
ret
.
data
=
nil
;
}
else
ret
=
*
(
Eface
*
)
e
.
type
;
FLUSH
(
&
ret
);
}
static
int32
cmpstringchars
(
String
a
,
uint8
*
b
)
void
unsafe
·
Reflect
(
Eface
e
,
Eface
rettype
,
void
*
retaddr
)
{
int32
i
;
byte
c1
,
c2
;
uintptr
*
p
;
uintptr
x
;
for
(
i
=
0
;;
i
++
)
{
c1
=
0
;
if
(
i
<
a
.
len
)
c1
=
a
.
str
[
i
];
c2
=
b
[
i
];
if
(
c1
<
c2
)
return
-
1
;
if
(
c1
>
c2
)
return
+
1
;
if
(
c1
==
0
)
return
0
;
if
(
e
.
type
==
nil
)
{
rettype
.
type
=
nil
;
rettype
.
data
=
nil
;
retaddr
=
0
;
}
else
{
rettype
=
*
(
Eface
*
)
e
.
type
;
if
(
e
.
type
->
size
<=
sizeof
(
uintptr
))
{
// Copy data into x ...
x
=
0
;
algarray
[
e
.
type
->
alg
].
copy
(
e
.
type
->
size
,
&
x
,
&
e
.
data
);
// but then build pointer to x so that Reflect
// always returns pointer to data.
p
=
mallocgc
(
sizeof
(
uintptr
));
*
p
=
x
;
}
else
{
// Already a pointer, but still make a copy,
// to preserve value semantics for interface data.
p
=
mallocgc
(
e
.
type
->
size
);
algarray
[
e
.
type
->
alg
].
copy
(
e
.
type
->
size
,
p
,
e
.
data
);
}
}
static
Sigt
*
findtype
(
String
type
,
bool
indir
)
{
int32
i
,
lo
,
hi
,
m
;
lo
=
0
;
hi
=
ngotypesigs
;
while
(
lo
<
hi
)
{
m
=
lo
+
(
hi
-
lo
)
/
2
;
i
=
cmpstringchars
(
type
,
gotypesigs
[
m
]
->
name
);
if
(
i
==
0
)
return
gotypesigs
[
m
];
if
(
i
<
0
)
hi
=
m
;
else
lo
=
m
+
1
;
retaddr
=
p
;
}
return
fakesigt
(
type
,
indir
);
FLUSH
(
&
rettype
);
FLUSH
(
&
retaddr
);
}
void
unsafe
·
Unreflect
(
uint64
it
,
String
type
,
bool
indir
,
Eface
ret
)
{
Sigt
*
sigt
;
ret
=
nileface
;
if
(
cmpstring
(
type
,
emptystring
)
==
0
)
goto
out
;
if
(
type
.
len
>
10
&&
mcmp
(
type
.
str
,
(
byte
*
)
"interface "
,
10
)
==
0
)
{
printf
(
"unsafe.Unreflect: cannot put %S in interface
\n
"
,
type
);
throw
(
"unsafe.Unreflect"
);
unsafe
·
Unreflect
(
Iface
typ
,
void
*
addr
,
Eface
e
)
{
// Reflect library has reinterpreted typ
// as its own kind of type structure.
// We know that the pointer to the original
// type structure sits before the data pointer.
e
.
type
=
(
Type
*
)((
Eface
*
)
typ
.
data
-
1
);
// Interface holds either pointer to data
// or copy of original data.
if
(
e
.
type
->
size
<=
sizeof
(
uintptr
))
algarray
[
e
.
type
->
alg
].
copy
(
e
.
type
->
size
,
&
e
.
data
,
addr
);
else
{
// Easier: already a pointer to data.
// TODO(rsc): Should this make a copy?
e
.
data
=
addr
;
}
// if we think the type should be indirect
// and caller does not, play it safe, return nil.
sigt
=
findtype
(
type
,
indir
);
if
(
indir
!=
(
sigt
->
width
>
sizeof
(
ret
.
data
)))
goto
out
;
ret
.
type
=
sigt
;
ret
.
data
=
(
void
*
)
it
;
out:
FLUSH
(
&
ret
);
FLUSH
(
&
e
);
}
src/pkg/runtime/print.c
View file @
c7513eac
...
...
@@ -76,10 +76,10 @@ printf(int8 *s, ...)
sys
·
printint
(
*
(
int64
*
)
arg
);
break
;
case
'x'
:
sys
·
printhex
(
*
(
int32
*
)
arg
);
sys
·
printhex
(
*
(
u
int32
*
)
arg
);
break
;
case
'X'
:
sys
·
printhex
(
*
(
int64
*
)
arg
);
sys
·
printhex
(
*
(
u
int64
*
)
arg
);
break
;
case
'p'
:
sys
·
printpointer
(
*
(
void
**
)
arg
);
...
...
src/pkg/runtime/runtime.h
View file @
c7513eac
...
...
@@ -56,9 +56,9 @@ typedef struct Usema Usema;
typedef
struct
SigTab
SigTab
;
typedef
struct
MCache
MCache
;
typedef
struct
Iface
Iface
;
typedef
struct
It
ype
Itype
;
typedef
struct
It
ab
Itab
;
typedef
struct
Eface
Eface
;
typedef
struct
Sigt
Sigt
;
typedef
struct
Type
Type
;
typedef
struct
Defer
Defer
;
/*
...
...
@@ -117,12 +117,12 @@ struct String
};
struct
Iface
{
It
ype
*
type
;
It
ab
*
tab
;
void
*
data
;
};
struct
Eface
{
Sigt
*
type
;
Type
*
type
;
void
*
data
;
};
...
...
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