Compare commits

...

42 Commits

Author SHA1 Message Date
Andrew Gerrand
1d6d8fca24 go1.1.2
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/12837043
2013-08-13 15:33:06 +10:00
Andrew Gerrand
f1f37cce1d [release-branch.go1.1] doc: release notes for go1.1.2
««« CL 12016043 / 897a42d03643
doc: release notes for go1.1.2

R=golang-dev, go.peter.90, rsc, r
CC=golang-dev
https://golang.org/cl/12016043
»»»

Fixes #5928.

R=golang-dev, r, dsymonds
CC=golang-dev
https://golang.org/cl/12835043
2013-08-13 15:19:16 +10:00
Andrew Gerrand
018854d24a [release-branch.go1.1] bufio: check buffer availability before reading in ReadFrom
This change was applied by hand, as bufio has seen some refactoring
since 1.1 was branched. The only difference between this and the
original patch is the offset of the change, and s/flush/Flush/.

««« CL 11801043 / 3ffbc06b4874
bufio: check buffer availability before reading in ReadFrom

Fixes  issue 5947 .

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/11801043
»»»

Update #5928

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/12002043
2013-07-29 18:00:58 +10:00
Andrew Gerrand
2041d55aac [release-branch.go1.1] syscall: prlimit argument error for Getrlimit and Setrlimit on Linux 32-bit
««« CL 11803043 / ba52f6399462
syscall: prlimit argument error for Getrlimit and Setrlimit on Linux 32-bit

The rlimit arguments for prlimit are reversed for linux 32-bit (386 and arm).
Getrlimit becomes Setrlimit and vice versa.
Fixes #5949.

R=iant, mikioh.mikioh, rsc
CC=golang-dev
https://golang.org/cl/11803043

»»»

Update #5928

R=golang-dev, dave
CC=golang-dev
https://golang.org/cl/11996043
2013-07-29 10:34:53 +10:00
Andrew Gerrand
3e917131a1 [release-branch.go1.1] cmd/cgo: gccgo fixes
««« CL 11406047 / 4d9c3095de9d
cmd/cgo: gccgo fixes

Don't require a full-scale callback for calls to the special
prologue functions.

Always use a simple wrapper function for C functions, so that
we can handle static functions defined in the import "C"
comment.

Disable a test that relies on gc-specific function names.

Fixes #5905.

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/11406047

»»»

Update #5928

R=golang-dev, dave
CC=golang-dev
https://golang.org/cl/11887043
2013-07-29 09:57:49 +10:00
Andrew Gerrand
89020aa72c [release-branch.go1.1] cmd/gc: avoid passing unevaluated constant expressions to backends.
««« CL 11107044 / 5baf6060648e
cmd/gc: avoid passing unevaluated constant expressions to backends.

Backends do not exactly expect receiving binary operators with
constant operands or use workarounds to move them to
register/stack in order to handle them.

Fixes #5841.

R=golang-dev, daniel.morsing, rsc
CC=golang-dev
https://golang.org/cl/11107044

»»»

Update #5928

R=golang-dev, dave
CC=golang-dev
https://golang.org/cl/11879044
2013-07-26 10:04:32 +10:00
Andrew Gerrand
b5245b9c77 [release-branch.go1.1] undo 6efaa14e2e7f
It breaks the build.

R=golang-dev
CC=golang-dev
https://golang.org/cl/11584045
2013-07-23 10:10:11 +10:00
Andrew Gerrand
ceeda72bab [release-branch.go1.1] runtime: prevent sysmon from polling network excessivly
««« CL 11569043 / 6b3c351c7fe6
runtime: prevent sysmon from polling network excessivly
If the network is not polled for 10ms, sysmon starts polling network
on every iteration (every 20us) until another thread blocks in netpoll.
Fixes  issue 5922 .

R=golang-dev, iant
CC=golang-dev
https://golang.org/cl/11569043
»»»

Update #5928

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/11438044
2013-07-23 09:50:35 +10:00
Andrew Gerrand
fc9a18f16b [release-branch.go1.1] cmd/8g: Make clearfat non-interleaved with pointer calculations.
««« CL 11383043 / dc24634de6c5
cmd/8g: Make clearfat non-interleaved with pointer calculations.

clearfat (used to zero initialize structures) will use AX for x86 block ops. If we write to AX while calculating the dest pointer, we will fill the structure with incorrect values.
Since 64-bit arithmetic uses AX to synthesize a 64-bit register, getting an adress by indexing with 64-bit ops can clobber the register.

Fixes #5820.

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/11383043
»»»

Update #5928

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/11698043
2013-07-23 09:40:49 +10:00
Andrew Gerrand
f2fa995324 [release-branch.go1.1] runtime: properly set G status after syscall
««« CL 9307045 / fab6ba2a2d10
runtime: properly set G status after syscall

R=golang-dev, r, dave
CC=golang-dev
https://golang.org/cl/9307045
»»»

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/11694043
2013-07-23 09:31:37 +10:00
Andrew Gerrand
9db29c2784 [release-branch.go1.1] cmd/6g, cmd/8g: prevent constant propagation of non-constant LEA.
««« CL 10785043 / cf792c00f410
cmd/6g, cmd/8g: prevent constant propagation of non-constant LEA.

Fixes #5809.

R=golang-dev, dave, rsc, nigeltao
CC=golang-dev
https://golang.org/cl/10785043
»»»

Update #5928

R=golang-dev, dave
CC=golang-dev
https://golang.org/cl/11515045
2013-07-23 08:00:01 +10:00
Andrew Gerrand
b82120bd3e [release-branch.go1.1] cmd/gc: fix issue with method wrappers not having escape analysis run on them.
««« CL 10383048 / 58e15340e78f
cmd/gc: fix issue with method wrappers not having escape analysis run on them.

Escape analysis needs the right curfn value on a dclfunc node, otherwise it will not analyze the function.
When generating method value wrappers, we forgot to set the curfn correctly.

Fixes #5753.

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/10383048
»»»

Update #5928

R=golang-dev, dave
CC=golang-dev
https://golang.org/cl/11669043
2013-07-22 23:45:28 +10:00
Andrew Gerrand
b315b7ffff [release-branch.go1.1] time: prevent a panic from leaving the timer mutex held
««« CL 10373047 / 974a69ed9fcf
time: prevent a panic from leaving the timer mutex held

When deleting a timer, a panic due to nil deref
would leave a lock held, possibly leading to a deadlock
in a defer. Instead return false on a nil timer.

Fixes #5745.

R=golang-dev, daniel.morsing, dvyukov, rsc, iant
CC=golang-dev
https://golang.org/cl/10373047

»»»

Update #5928

R=golang-dev, dave
CC=golang-dev
https://golang.org/cl/11666046
2013-07-22 18:41:32 +10:00
Andrew Gerrand
e33810b291 [release-branch.go1.1] cmd/gc: fix missing export data for inlining in a few other cases.
««« CL 10464043 / c224c549a3c7
cmd/gc: fix missing export data for inlining in a few other cases.

Exported inlined functions that perform a string conversion
using a non-exported named type may miss it in export data.

Fixes #5755.

R=rsc, golang-dev, ality, r
CC=golang-dev
https://golang.org/cl/10464043
»»»

Update #5928

R=golang-dev, dave
CC=golang-dev
https://golang.org/cl/11629044
2013-07-22 18:34:36 +10:00
Andrew Gerrand
6baa8dba68 [release-branch.go1.1] cmd/gc: fix pointer composite literals in exported if statements.
««« CL 10470043 / d04e6b0bcacf
cmd/gc: fix pointer composite literals in exported if statements.

Fixes #4230 (again).

R=rsc, golang-dev, r
CC=golang-dev
https://golang.org/cl/10470043
»»»

Update #5928

R=golang-dev, dave
CC=golang-dev
https://golang.org/cl/11455045
2013-07-22 18:22:30 +10:00
Andrew Gerrand
d260448f6b [release-branch.go1.1] doc: add go1.1.1 to the release notes
««« CL 10236045 / 3cda43260443
doc: add go1.1.1 to the release notes

R=golang-dev, iant
CC=golang-dev
https://golang.org/cl/10236045
»»»

R=golang-dev, iant
CC=golang-dev
https://golang.org/cl/10245044
2013-06-13 12:49:43 +10:00
Andrew Gerrand
a00b3d29de go1.1.1
R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/10253043
2013-06-13 12:21:56 +10:00
Andrew Gerrand
fa6b1232e6 [release-branch.go1.1] remove release tag from release branch
This should have been done before tagging go1.1.
Better late than never.

R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/10252043
2013-06-13 12:20:27 +10:00
Andrew Gerrand
3b7e6e8db1 [release-branch.go1.1] cmd/gc: compute initialization order for top-level blank vars too.
««« CL 8601044 / 3a74e15c5d56
cmd/gc: compute initialization order for top-level blank vars too.

Fixes #5244.

R=golang-dev, rsc, iant, r, daniel.morsing
CC=golang-dev
https://golang.org/cl/8601044
»»»

R=iant, rsc
CC=golang-dev
https://golang.org/cl/10250043
2013-06-13 10:30:45 +10:00
Andrew Gerrand
13af44f8a5 [release-branch.go1.1] cmd/gc: save local var list before inlining
««« CL 10210043 / b357e33bb414
cmd/gc: save local var list before inlining

This avoids problems with inlining in genwrappers, which
occurs after functions have been compiled.  Compiling a
function may cause some unused local vars to be removed from
the list.  Since a local var may be unused due to
optimization, it is possible that a removed local var winds up
beingused in the inlined version, in which case hilarity
ensues.

Fixes #5515.

R=golang-dev, khr, dave
CC=golang-dev
https://golang.org/cl/10210043
»»»

R=iant, rsc
CC=golang-dev
https://golang.org/cl/10242044
2013-06-13 10:04:17 +10:00
Shenghou Ma
b87a963f87 [release-branch.go1.1] doc: GCC 4.8.1 is not updated to Go 1.1
««« CL 9663045 / 6c64135360c2
doc: GCC 4.8.1 is not updated to Go 1.1

I will try again for 4.8.2.

R=golang-dev, minux.ma
CC=golang-dev
https://golang.org/cl/9663045
»»»

R=golang-dev, iant
CC=golang-dev
https://golang.org/cl/9914045
2013-06-11 23:34:53 +08:00
Andrew Gerrand
3e88a825df [release-branch.go1.1] cmd/gc: fix missing slice/array types in export data.
««« CL 9953044 / 0e1b2f7384d2
cmd/gc: fix missing slice/array types in export data.

Fixes #5614.

R=golang-dev
CC=golang-dev
https://golang.org/cl/9953044
»»»

R=iant, remyoudompheng, dsymonds
CC=golang-dev
https://golang.org/cl/10033043
2013-06-05 11:19:26 +10:00
Andrew Gerrand
d72c550f1c [release-branch.go1.1] runtime: fix heap corruption during GC
««« CL 9831043 / e84e7204b01b
runtime: fix heap corruption during GC
The 'n' variable is used during rescan initiation in GC_END case,
but it's overwritten with chan capacity in GC_CHAN case.
As the result rescan is done with the wrong object size.
Fixes #5554.

R=golang-dev, khr
CC=golang-dev
https://golang.org/cl/9831043
»»»

R=dvyukov, khr, dave
CC=golang-dev
https://golang.org/cl/10028044
2013-06-05 11:12:46 +10:00
Andrew Gerrand
371a3ab28a [release-branch.go1.1] test: do not run the test that relies on precise GC on 32-bits
««« CL 9573043 / c0f8999bd970
test: do not run the test that relies on precise GC on 32-bits
Currently most of the 32-bit builder are broken.
Fixes #5516.

R=golang-dev, dave, iant
CC=golang-dev
https://golang.org/cl/9573043
»»»

R=dvyukov, iant, minux.ma, bradfitz
CC=golang-dev
https://golang.org/cl/10032043
2013-06-05 11:07:26 +10:00
Andrew Gerrand
ff7cb872a4 [release-branch.go1.1] runtime: zeroize g->fnstart to not prevent GC of the closure
««« CL 9557043 / 2c128d417029
runtime: zeroize g->fnstart to not prevent GC of the closure
Fixes #5493.

R=golang-dev, minux.ma, iant
CC=golang-dev
https://golang.org/cl/9557043
»»»

R=dvyukov, iant, minux.ma, bradfitz, dave
CC=golang-dev
https://golang.org/cl/10031043
2013-06-05 10:52:00 +10:00
Andrew Gerrand
b9b37d1292 [release-branch.go1.1] cmd/gc: repair make(T) in export data for inlining.
««« CL 9303050 / 9a73efa2cd4e
cmd/gc: repair make(T) in export data for inlining.

When T was an unexported type it could be forgotten.

Fixes #5470.

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/9303050
»»»

R=bradfitz, iant, remyoudompheng
CC=golang-dev
https://golang.org/cl/10029043
2013-06-05 10:27:38 +10:00
Andrew Gerrand
03290b55e9 [release-branch.go1.1] runtime: fix GC scanning of slices
««« CL 9372044 / 1abed5873071
runtime: fix GC scanning of slices
If a slice points to an array embedded in a struct,
the whole struct can be incorrectly scanned as the slice buffer.
Fixes #5443.

R=cshapiro, iant, r, cshapiro, minux.ma
CC=bradfitz, gobot, golang-dev
https://golang.org/cl/9372044
»»»

R=cshapiro, iant
CC=golang-dev
https://golang.org/cl/10027043
2013-06-05 10:20:34 +10:00
Andrew Gerrand
5f1cf34402 [release-branch.go1.1] cmd/gc: do not corrupt init() with initializers of _ in closures.
««« CL 9952043 / c42a7c218440
cmd/gc: do not corrupt init() with initializers of _ in closures.

Fixes #5607.

R=golang-dev, daniel.morsing, r, dsymonds
CC=golang-dev
https://golang.org/cl/9952043
»»»

R=daniel.morsing, dsymonds, r, remyoudompheng
CC=golang-dev
https://golang.org/cl/9895044
2013-06-05 10:00:54 +10:00
Andrew Gerrand
09879160e5 [release-branch.go1.1] runtime: introduce cnewarray() to simplify allocation of typed arrays
««« CL 9648044 / 139919984600
runtime: introduce cnewarray() to simplify allocation of typed arrays

R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/9648044
»»»

R=dsymonds, dvyukov, dave
CC=golang-dev
https://golang.org/cl/9780050
2013-06-04 12:54:13 +10:00
Andrew Gerrand
ea3b4c9321 [release-branch.go1.1] doc: add Go 1.1 to release.html
««« CL 9853051 / 103cf9db59e1
doc: add Go 1.1 to release.html

Fixes #5468.

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/9853051
»»»

R=golang-dev, minux.ma
CC=golang-dev
https://golang.org/cl/9738054
2013-06-03 12:10:04 +10:00
Andrew Gerrand
41644eec2c [release-branch.go1.1] doc: update linux tarball version for Go 1.1
««« CL 9819044 / 0f679c4c5ebe
doc: update linux tarball version for Go 1.1

R=adg
CC=golang-dev
https://golang.org/cl/9819044
»»»

R=golang-dev, dave
CC=golang-dev
https://golang.org/cl/9858048
2013-06-03 11:56:41 +10:00
Andrew Gerrand
205f850cea go1.1 2013-05-13 13:03:09 -07:00
Andrew Gerrand
6c7631126f [release-branch.go1.1] runtime/race: improve public documentation
««« CL 9144050 / d29da2ced72b
runtime/race: improve public documentation
Move the documentation from race.go to doc.go, because
race.go uses +build race, so it's not normally parsed by go doc.
Rephrase the documentation for end users, provide link to race
detector manual.
Fixes #5444.

R=golang-dev, minux.ma, adg, r
CC=golang-dev
https://golang.org/cl/9144050
»»»

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/9387043
2013-05-13 09:35:18 -07:00
Andrew Gerrand
9294a08f1b [release-branch.go1.1] doc: add a "New packages" section to the 1.1 release notes.
««« CL 9344044 / 880991592ded
doc: add a "New packages" section to the 1.1 release notes.

R=adg, r
CC=golang-dev
https://golang.org/cl/9344044
»»»

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/9386043
2013-05-13 09:24:34 -07:00
Andrew Gerrand
46a6097aa7 go1.1rc3
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/9315044
2013-05-08 16:04:56 -07:00
Andrew Gerrand
91504a0e0d [release-branch.go1.1] runtime: fix crash in select
««« CL 9311043 / 53bc96b4c0c7
runtime: fix crash in select
runtime.park() can access freed select descriptor
due to a racing free in another thread.
See the comment for details.

Slightly modified version of dvyukov's CL 9259045.

No test yet.  Before this CL, the test described in issue 5422
would fail about every 40 times for me.  With this CL, I ran
the test 5900 times with no failures.

Fixes #5422.

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/9311043
»»»

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/9304044
2013-05-08 16:02:59 -07:00
Andrew Gerrand
836b670612 [release-branch.go1.1] spec: fix incorrect example
««« CL 9305043 / 87762a7629b4
spec: fix incorrect example

Fixes #5430.

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/9305043
»»»

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/9308044
2013-05-08 16:02:02 -07:00
Andrew Gerrand
0a98e78c1f [release-branch.go1.1] doc: pull front page featured articles using new blog JSON feed
««« CL 9288045 / 5785ebd7acfb
doc: pull front page featured articles using new blog JSON feed

R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/9288045
»»»

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/9050046
2013-05-08 16:01:09 -07:00
Andrew Gerrand
c785d6af66 [release-branch.go1.1] cmd/cgo: pass -Wsystem-headers when looking for errors
««« CL 9120045 / e4f62df3e6c9
cmd/cgo: pass -Wsystem-headers when looking for errors

This works around a bug in GCC 4.8.0.

Fixes #5118.

R=golang-dev, r, minux.ma
CC=golang-dev
https://golang.org/cl/9120045
»»»

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/9259047
2013-05-08 16:00:15 -07:00
Andrew Gerrand
99aa2da7ea [release-branch.go1.1] net: fix dial race on plan9 and windows
««« CL 9159043 / f1ddc3ce3dfe
net: fix dial race on plan9 and windows

Fixes #5349.

R=golang-dev, lucio.dere, dsymonds, bradfitz, iant, adg, dave, r
CC=golang-dev
https://golang.org/cl/9159043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/9315043
2013-05-08 15:58:43 -07:00
Andrew Gerrand
0f1a18b773 [release-branch.go1.1] effective_go.html: be more accepting in the guidelines for interface names
««« CL 9274043 / bbe324079abe
effective_go.html: be more accepting in the guidelines for interface names
Fixes #5421.

R=golang-dev, bradfitz, adg
CC=golang-dev
https://golang.org/cl/9274043
»»»

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/9137045
2013-05-08 15:57:44 -07:00
Andrew Gerrand
1c5438aae8 go1.1rc2 2013-05-06 17:33:44 -07:00
69 changed files with 908 additions and 1940 deletions

View File

@@ -114,4 +114,3 @@ dc5e410f0b4c32ab11dc992593a2bcf5f607381b weekly
2ccfd4b451d319941bfe3e08037e1462d3c15093 go1.0.1
5e806355a9e1491aaab53d3612fed4c550b130c0 go1.0.2
2d8bc3c94ecb3ec8f70556d5fd237788903c7281 go1.0.3
2d8bc3c94ecb3ec8f70556d5fd237788903c7281 release

1
VERSION Normal file
View File

@@ -0,0 +1 @@
go1.1.2

View File

@@ -13,6 +13,32 @@ hg pull
hg update <i>tag</i>
</pre>
<h2 id="go1.1">go1.1 (released 2013/05/13)</h2>
<p>
Go 1.1 is a major release of Go.
Read the <a href="/doc/go1.1.html">Go 1.1 Release Notes</a> for
more information.
</p>
<h3 id="go1.1.minor">Minor revisions</h3>
<p>
go1.1.1 (released 2013/06/13) includes several compiler and runtime bug fixes.
See the <a href="https://code.google.com/p/go/source/list?name=release-branch.go1.1&r=43c4a41d24382a56a90e924800c681e435d9e399">change history</a> for details.
</p>
<p>
go1.1.2 (released 2013/08/13) includes fixes to the <code>gc</code> compiler
and <code>cgo</code>, and the <code>bufio</code>, <code>runtime</code>,
<code>syscall</code>, and <code>time</code> packages.
See the <a href="https://code.google.com/p/go/source/list?name=release-branch.go1.1&r=a6a9792f94acd4ff686b2bc57383d163608b91cf">change history</a> for details.
If you use package syscall's <code>Getrlimit</code> and <code>Setrlimit</code>
functions under Linux on the ARM or 386 architectures, please note change
<a href="http://golang.org/change/55ac276af5a7">55ac276af5a7</a>
that fixes <a href="http://golang.org/issue/5949">issue 5949</a>.
</p>
<h2 id="go1">go1 (released 2012/03/28)</h2>
<p>

View File

@@ -403,8 +403,10 @@ if owner != user {
<p>
By convention, one-method interfaces are named by
the method name plus the -er suffix: <code>Reader</code>,
<code>Writer</code>, <code>Formatter</code> etc.
the method name plus an -er suffix or similar modification
to construct an agent noun: <code>Reader</code>,
<code>Writer</code>, <code>Formatter</code>,
<code>CloseNotifier</code> etc.
</p>
<p>

View File

@@ -159,7 +159,7 @@ The GCC release schedule does not coincide with the Go release schedule, so some
<code>gccgo</code>'s releases.
The 4.8.0 version of GCC shipped in March, 2013 and includes a nearly-Go 1.1 version of <code>gccgo</code>.
Its library is a little behind the release, but the biggest difference is that method values are not implemented.
Sometime around May 2013, we expect 4.8.1 of GCC to ship with a <code>gccgo</code>
Sometime around July 2013, we expect 4.8.2 of GCC to ship with a <code>gccgo</code>
providing a complete Go 1.1 implementaiton.
</p>
@@ -694,6 +694,36 @@ The old package <code>exp/norm</code> has also been moved, but to a new reposito
be developed.
</p>
<h3 id="new_packages">New packages</h3>
<p>
There are three new packages.
</p>
<ul>
<li>
The <a href="/pkg/go/format/"><code>go/format</code></a> package provides
a convenient way for a program to access the formatting capabilities of the
<a href="/cmd/go/#hdr-Run_gofmt_on_package_sources"><code>go fmt</code></a> command.
It has two functions,
<a href="/pkg/go/format/#Node"><code>Node</code></a> to format a Go parser
<a href="/pkg/go/ast/#Node"><code>Node</code></a>,
and
<a href="/pkg/go/format/#Source"><code>Source</code></a>
to reformat arbitrary Go source code into the standard format as provided by the
<a href="/cmd/go/#hdr-Run_gofmt_on_package_sources"><code>go fmt</code></a> command.
</li>
<li>
The <a href="/pkg/net/http/cookiejar/"><code>net/http/cookiejar</code></a> package provides the basics for managing HTTP cookies.
</li>
<li>
The <a href="/pkg/runtime/race/"><code>runtime/race</code></a> package provides low-level facilities for data race detection.
It is internal to the race detector and does not otherwise export any user-visible functionality.
</li>
</ul>
<h3 id="minor_library_changes">Minor changes to the library</h3>
<p>
@@ -796,17 +826,6 @@ information that the <a href="/cmd/godoc/"><code>godoc</code></a>
command can filter or present according to the value of the <code>-notes</code> flag.
</li>
<li>
A new package, <a href="/pkg/go/format/"><code>go/format</code></a>, provides
a convenient way for a program to access the formatting capabilities of <code>gofmt</code>.
It has two functions,
<a href="/pkg/go/format/#Node"><code>Node</code></a> to format a Go parser
<a href="/pkg/go/ast/#Node"><code>Node</code></a>,
and
<a href="/pkg/go/format/#Source"><code>Source</code></a>
to format arbitrary Go source code.
</li>
<li>
The undocumented and only partially implemented "noescape" feature of the
<a href="/pkg/html/template/"><code>html/template</code></a>
@@ -943,10 +962,6 @@ a <a href="/pkg/net/http/#Response"><code>Response.Body</code></a> is closed bef
being fully consumed.
</li>
<li>
The new <a href="/pkg/net/http/cookiejar/"><code>net/http/cookiejar</code></a> package provides the basics for managing HTTP cookies.
</li>
<li>
The <a href="/pkg/net/mail/"><code>net/mail</code></a> package has two new functions,
<a href="/pkg/net/mail/#ParseAddress"><code>ParseAddress</code></a> and

View File

@@ -1,6 +1,6 @@
<!--{
"Title": "The Go Programming Language Specification",
"Subtitle": "Version of April 10, 2013",
"Subtitle": "Version of May 8, 2013",
"Path": "/ref/spec"
}-->
@@ -3835,7 +3835,7 @@ const Θ float64 = 3/2 // Θ == 1.0 (type float64, 3/2 is integer divisio
const Π float64 = 3/2. // Π == 1.5 (type float64, 3/2. is float division)
const d = 1 &lt;&lt; 3.0 // d == 8 (untyped integer constant)
const e = 1.0 &lt;&lt; 3 // e == 8 (untyped integer constant)
const f = int32(1) &lt;&lt; 33 // f == 0 (type int32)
const f = int32(1) &lt;&lt; 33 // illegal (constant 8589934592 overflows int32)
const g = float64(2) &gt;&gt; 1 // illegal (float64(2) is a typed floating-point constant)
const h = "foo" &gt; "bar" // h == true (untyped boolean constant)
const j = true // j == true (untyped boolean constant)

View File

@@ -108,7 +108,7 @@ For example:
</p>
<pre>
tar -C /usr/local -xzf go1.0.3.linux-amd64.tar.gz
tar -C /usr/local -xzf go1.1.linux-amd64.tar.gz
</pre>
<p>

View File

@@ -84,41 +84,38 @@ Linux, Mac OS X, Windows, and more.
<div style="clear: both;"></div>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("feeds", "1");
function readableTime(t) {
var m = ["January", "February", "March", "April", "May", "June", "July",
"August", "September", "October", "November", "December"];
var p = t.substring(0, t.indexOf("T")).split("-");
var d = new Date(p[0], p[1]-1, p[2]);
return d.getDate() + " " + m[d.getMonth()] + " " + d.getFullYear();
}
function feedLoaded(result) {
if (result.error) {
console.log(result.error);
return;
}
var blog = document.getElementById("blog");
var read = blog.getElementsByClassName("read")[0];
for (var i = 0; i < result.feed.entries.length && i < 2; i++) {
var entry = result.feed.entries[i];
for (var i = 0; i < result.length && i < 2; i++) {
var entry = result[i];
var title = document.createElement("a");
title.className = "title";
title.href = entry.link;
title.innerHTML = entry.title;
title.href = entry.Link;
title.innerHTML = entry.Title;
blog.insertBefore(title, read);
var extract = document.createElement("div");
extract.className = "extract";
extract.innerHTML = entry.contentSnippet;
extract.innerHTML = entry.Summary;
blog.insertBefore(extract, read);
var when = document.createElement("div");
when.className = "when";
var pub = entry.publishedDate.split(" ").slice(1,3).join(" ");
when.innerHTML = "Published " + pub
when.innerHTML = "Published " + readableTime(entry.Time);
blog.insertBefore(when, read);
}
}
function init() {
// Load blog feed.
var feed = new google.feeds.Feed("http://blog.golang.org/feeds/posts/default");
feed.load(feedLoaded);
$(function() {
// Set up playground.
playground({
"codeEl": "#learn .code",
@@ -128,7 +125,11 @@ function init() {
"shareRedirect": "http://play.golang.org/p/",
"toysEl": "#learn .toys select"
});
}
google.setOnLoadCallback(init);
// Load blog feed.
$('<script/>').attr('text', 'text/javascript')
.attr('src', 'http://blog.golang.org/.json?jsonp=feedLoaded')
.appendTo('body');
});
</script>

View File

@@ -142,6 +142,10 @@ func testBlocking(t *testing.T) {
// Test that the stack can be unwound through a call out and call back
// into Go.
func testCallbackCallers(t *testing.T) {
if runtime.Compiler != "gc" {
// The exact function names are not going to be the same.
t.Skip("skipping for non-gc toolchain")
}
pc := make([]uintptr, 100)
n := 0
name := []string{

View File

@@ -152,6 +152,7 @@ peep(void)
case ALEAQ:
if(regtyp(&p->to))
if(p->from.sym != S)
if(p->from.index == D_NONE || p->from.index == D_CONST)
conprop(r);
break;

View File

@@ -78,9 +78,9 @@ clearfat(Node *nl)
c = w % 4; // bytes
q = w / 4; // quads
gconreg(AMOVL, 0, D_AX);
nodreg(&n1, types[tptr], D_DI);
agen(nl, &n1);
gconreg(AMOVL, 0, D_AX);
if(q >= 4) {
gconreg(AMOVL, q, D_CX);

View File

@@ -145,6 +145,7 @@ peep(void)
case ALEAL:
if(regtyp(&p->to))
if(p->from.sym != S)
if(p->from.index == D_NONE || p->from.index == D_CONST)
conprop(r);
break;

View File

@@ -809,6 +809,15 @@ func (p *Package) gccDefines(stdin []byte) string {
func (p *Package) gccErrors(stdin []byte) string {
// TODO(rsc): require failure
args := p.gccCmd()
// GCC 4.8.0 has a bug: it sometimes does not apply
// -Wunused-value to values that are macros defined in system
// headers. See issue 5118. Adding -Wsystem-headers avoids
// that problem. This will produce additional errors, but it
// doesn't matter because we will ignore all errors that are
// not marked for the cgo-test file.
args = append(args, "-Wsystem-headers")
if *debugGcc {
fmt.Fprintf(os.Stderr, "$ %s <<EOF\n", strings.Join(args, " "))
os.Stderr.Write(stdin)

View File

@@ -318,6 +318,9 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
Type: gtype,
}
// Builtins defined in the C prolog.
inProlog := name == "CString" || name == "GoString" || name == "GoStringN" || name == "GoBytes"
if *gccgo {
// Gccgo style hooks.
fmt.Fprint(fgo2, "\n")
@@ -331,8 +334,10 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
conf.Fprint(fgo2, fset, d)
fmt.Fprint(fgo2, " {\n")
fmt.Fprint(fgo2, "\tdefer syscall.CgocallDone()\n")
fmt.Fprint(fgo2, "\tsyscall.Cgocall()\n")
if !inProlog {
fmt.Fprint(fgo2, "\tdefer syscall.CgocallDone()\n")
fmt.Fprint(fgo2, "\tsyscall.Cgocall()\n")
}
if n.AddError {
fmt.Fprint(fgo2, "\tsyscall.SetErrno(0)\n")
}
@@ -363,7 +368,11 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
fmt.Fprint(fgo2, "}\n")
// declare the C function.
fmt.Fprintf(fgo2, "//extern %s\n", n.C)
if inProlog {
fmt.Fprintf(fgo2, "//extern %s\n", n.C)
} else {
fmt.Fprintf(fgo2, "//extern _cgo%s%s\n", cPrefix, n.Mangle)
}
d.Name = ast.NewIdent(cname)
if n.AddError {
l := d.Type.Results.List
@@ -377,8 +386,7 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
conf.Fprint(fgo2, fset, d)
fmt.Fprint(fgo2, "\n")
if name == "CString" || name == "GoString" || name == "GoStringN" || name == "GoBytes" {
// The builtins are already defined in the C prolog.
if inProlog {
return
}
@@ -466,7 +474,7 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
p.Written[name] = true
if *gccgo {
// we don't use wrappers with gccgo.
p.writeGccgoOutputFunc(fgcc, n)
return
}
@@ -518,6 +526,54 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
fmt.Fprintf(fgcc, "\n")
}
// Write out a wrapper for a function when using gccgo. This is a
// simple wrapper that just calls the real function. We only need a
// wrapper to support static functions in the prologue--without a
// wrapper, we can't refer to the function, since the reference is in
// a different file.
func (p *Package) writeGccgoOutputFunc(fgcc *os.File, n *Name) {
if t := n.FuncType.Result; t != nil {
fmt.Fprintf(fgcc, "%s\n", t.C.String())
} else {
fmt.Fprintf(fgcc, "void\n")
}
fmt.Fprintf(fgcc, "_cgo%s%s(", cPrefix, n.Mangle)
for i, t := range n.FuncType.Params {
if i > 0 {
fmt.Fprintf(fgcc, ", ")
}
c := t.Typedef
if c == "" {
c = t.C.String()
}
fmt.Fprintf(fgcc, "%s p%d", c, i)
}
fmt.Fprintf(fgcc, ")\n")
fmt.Fprintf(fgcc, "{\n")
fmt.Fprintf(fgcc, "\t")
if t := n.FuncType.Result; t != nil {
fmt.Fprintf(fgcc, "return ")
// Cast to void* to avoid warnings due to omitted qualifiers.
if c := t.C.String(); c[len(c)-1] == '*' {
fmt.Fprintf(fgcc, "(void*)")
}
}
fmt.Fprintf(fgcc, "%s(", n.C)
for i, t := range n.FuncType.Params {
if i > 0 {
fmt.Fprintf(fgcc, ", ")
}
// Cast to void* to avoid warnings due to omitted qualifiers.
if c := t.C.String(); c[len(c)-1] == '*' {
fmt.Fprintf(fgcc, "(void*)")
}
fmt.Fprintf(fgcc, "p%d", i)
}
fmt.Fprintf(fgcc, ");\n")
fmt.Fprintf(fgcc, "}\n")
fmt.Fprintf(fgcc, "\n")
}
// Write out the various stubs we need to support functions exported
// from Go so that they are callable from C.
func (p *Package) writeExports(fgo2, fc, fm *os.File) {

View File

@@ -1,5 +0,0 @@
# Copyright 2012 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.
include ../../Make.dist

View File

@@ -1,36 +0,0 @@
// 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.
// +build ignore
/*
Cov is a rudimentary code coverage tool.
Usage:
go tool cov [-lsv] [-g substring] [-m minlines] [6.out args]
Given a command to run, it runs the command while tracking which
sections of code have been executed. When the command finishes,
cov prints the line numbers of sections of code in the binary that
were not executed. With no arguments it assumes the command "6.out".
The options are:
-l
print full path names instead of paths relative to the current directory
-s
show the source code that didn't execute, in addition to the line numbers.
-v
print debugging information during the run.
-g substring
restrict the coverage analysis to functions or files whose names contain substring
-m minlines
only report uncovered sections of code larger than minlines lines
The program is the same for all architectures: 386, amd64, and arm.
*/
package main

View File

@@ -1,484 +0,0 @@
// 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.
/*
* code coverage
*/
#include <u.h>
#include <libc.h>
#include <bio.h>
#include "tree.h"
#include <ureg_amd64.h>
#include <mach.h>
typedef struct Ureg Ureg;
void
usage(void)
{
fprint(2, "usage: cov [-lsv] [-g substring] [-m minlines] [6.out args...]\n");
fprint(2, "-g specifies pattern of interesting functions or files\n");
exits("usage");
}
typedef struct Range Range;
struct Range
{
uvlong pc;
uvlong epc;
};
int chatty;
int fd;
int longnames;
int pid;
int doshowsrc;
Map *mem;
Map *text;
Fhdr fhdr;
char *substring;
char cwd[1000];
int ncwd;
int minlines = -1000;
Tree breakpoints; // code ranges not run
/*
* comparison for Range structures
* they are "equal" if they overlap, so
* that a search for [pc, pc+1) finds the
* Range containing pc.
*/
int
rangecmp(void *va, void *vb)
{
Range *a = va, *b = vb;
if(a->epc <= b->pc)
return 1;
if(b->epc <= a->pc)
return -1;
return 0;
}
/*
* remember that we ran the section of code [pc, epc).
*/
void
ran(uvlong pc, uvlong epc)
{
Range key;
Range *r;
uvlong oldepc;
if(chatty)
print("run %#llux-%#llux\n", pc, epc);
key.pc = pc;
key.epc = pc+1;
r = treeget(&breakpoints, &key);
if(r == nil)
sysfatal("unchecked breakpoint at %#llux+%d", pc, (int)(epc-pc));
// Might be that the tail of the sequence
// was run already, so r->epc is before the end.
// Adjust len.
if(epc > r->epc)
epc = r->epc;
if(r->pc == pc) {
r->pc = epc;
} else {
// Chop r to before pc;
// add new entry for after if needed.
// Changing r->epc does not affect r's position in the tree.
oldepc = r->epc;
r->epc = pc;
if(epc < oldepc) {
Range *n;
n = malloc(sizeof *n);
if(n == nil)
sysfatal("out of memory");
n->pc = epc;
n->epc = oldepc;
treeput(&breakpoints, n, n);
}
}
}
void
showsrc(char *file, int line1, int line2)
{
Biobuf *b;
char *p;
int n, stop;
if((b = Bopen(file, OREAD)) == nil) {
print("\topen %s: %r\n", file);
return;
}
for(n=1; n<line1 && (p = Brdstr(b, '\n', 1)) != nil; n++)
free(p);
// print up to five lines (this one and 4 more).
// if there are more than five lines, print 4 and "..."
stop = n+4;
if(stop > line2)
stop = line2;
if(stop < line2)
stop--;
for(; n<=stop && (p = Brdstr(b, '\n', 1)) != nil; n++) {
print(" %d %s\n", n, p);
free(p);
}
if(n < line2)
print(" ...\n");
Bterm(b);
}
/*
* if s is in the current directory or below,
* return the relative path.
*/
char*
shortname(char *s)
{
if(!longnames && strlen(s) > ncwd && memcmp(s, cwd, ncwd) == 0 && s[ncwd] == '/')
return s+ncwd+1;
return s;
}
/*
* we've decided that [pc, epc) did not run.
* do something about it.
*/
void
missing(uvlong pc, uvlong epc)
{
char file[1000];
int line1, line2;
char buf[100];
Symbol s;
char *p;
uvlong uv;
if(!findsym(pc, CTEXT, &s) || !fileline(file, sizeof file, pc)) {
notfound:
print("%#llux-%#llux\n", pc, epc);
return;
}
p = strrchr(file, ':');
*p++ = 0;
line1 = atoi(p);
for(uv=pc; uv<epc; ) {
if(!fileline(file, sizeof file, epc-2))
goto notfound;
uv += machdata->instsize(text, uv);
}
p = strrchr(file, ':');
*p++ = 0;
line2 = atoi(p);
if(line2+1-line2 < minlines)
return;
if(pc == s.value) {
// never entered function
print("%s:%d %s never called (%#llux-%#llux)\n", shortname(file), line1, s.name, pc, epc);
return;
}
if(pc <= s.value+13) {
// probably stub for stack growth.
// check whether last instruction is call to morestack.
// the -5 below is the length of
// CALL sys.morestack.
buf[0] = 0;
machdata->das(text, epc-5, 0, buf, sizeof buf);
if(strstr(buf, "morestack"))
return;
}
if(epc - pc == 5) {
// check for CALL sys.panicindex
buf[0] = 0;
machdata->das(text, pc, 0, buf, sizeof buf);
if(strstr(buf, "panicindex"))
return;
}
if(epc - pc == 2 || epc -pc == 3) {
// check for XORL inside shift.
// (on x86 have to implement large left or unsigned right shift with explicit zeroing).
// f+90 0x00002c9f CMPL CX,$20
// f+93 0x00002ca2 JCS f+97(SB)
// f+95 0x00002ca4 XORL AX,AX <<<
// f+97 0x00002ca6 SHLL CL,AX
// f+99 0x00002ca8 MOVL $1,CX
//
// f+c8 0x00002cd7 CMPL CX,$40
// f+cb 0x00002cda JCS f+d0(SB)
// f+cd 0x00002cdc XORQ AX,AX <<<
// f+d0 0x00002cdf SHLQ CL,AX
// f+d3 0x00002ce2 MOVQ $1,CX
buf[0] = 0;
machdata->das(text, pc, 0, buf, sizeof buf);
if(strncmp(buf, "XOR", 3) == 0) {
machdata->das(text, epc, 0, buf, sizeof buf);
if(strncmp(buf, "SHL", 3) == 0 || strncmp(buf, "SHR", 3) == 0)
return;
}
}
if(epc - pc == 3) {
// check for SAR inside shift.
// (on x86 have to implement large signed right shift as >>31).
// f+36 0x00016216 CMPL CX,$20
// f+39 0x00016219 JCS f+3e(SB)
// f+3b 0x0001621b SARL $1f,AX <<<
// f+3e 0x0001621e SARL CL,AX
// f+40 0x00016220 XORL CX,CX
// f+42 0x00016222 CMPL CX,AX
buf[0] = 0;
machdata->das(text, pc, 0, buf, sizeof buf);
if(strncmp(buf, "SAR", 3) == 0) {
machdata->das(text, epc, 0, buf, sizeof buf);
if(strncmp(buf, "SAR", 3) == 0)
return;
}
}
// show first instruction to make clear where we were.
machdata->das(text, pc, 0, buf, sizeof buf);
if(line1 != line2)
print("%s:%d,%d %#llux-%#llux %s\n",
shortname(file), line1, line2, pc, epc, buf);
else
print("%s:%d %#llux-%#llux %s\n",
shortname(file), line1, pc, epc, buf);
if(doshowsrc)
showsrc(file, line1, line2);
}
/*
* walk the tree, calling missing for each non-empty
* section of missing code.
*/
void
walktree(TreeNode *t)
{
Range *n;
if(t == nil)
return;
walktree(t->left);
n = t->key;
if(n->pc < n->epc)
missing(n->pc, n->epc);
walktree(t->right);
}
/*
* set a breakpoint all over [pc, epc)
* and remember that we did.
*/
void
breakpoint(uvlong pc, uvlong epc)
{
Range *r;
r = malloc(sizeof *r);
if(r == nil)
sysfatal("out of memory");
r->pc = pc;
r->epc = epc;
treeput(&breakpoints, r, r);
for(; pc < epc; pc+=machdata->bpsize)
put1(mem, pc, machdata->bpinst, machdata->bpsize);
}
/*
* install breakpoints over all text symbols
* that match the pattern.
*/
void
cover(void)
{
Symbol s;
char *lastfn;
uvlong lastpc;
int i;
char buf[200];
lastfn = nil;
lastpc = 0;
for(i=0; textsym(&s, i); i++) {
switch(s.type) {
case 'T':
case 't':
if(lastpc != 0) {
breakpoint(lastpc, s.value);
lastpc = 0;
}
// Ignore second entry for a given name;
// that's the debugging blob.
if(lastfn && strcmp(s.name, lastfn) == 0)
break;
lastfn = s.name;
buf[0] = 0;
fileline(buf, sizeof buf, s.value);
if(substring == nil || strstr(buf, substring) || strstr(s.name, substring))
lastpc = s.value;
}
}
}
uvlong
rgetzero(Map *map, char *reg)
{
USED(map);
USED(reg);
return 0;
}
/*
* remove the breakpoints at pc and successive instructions,
* up to and including the first jump or other control flow transfer.
*/
void
uncover(uvlong pc)
{
uchar buf[1000];
int n, n1, n2;
uvlong foll[2];
// Double-check that we stopped at a breakpoint.
if(get1(mem, pc, buf, machdata->bpsize) < 0)
sysfatal("read mem inst at %#llux: %r", pc);
if(memcmp(buf, machdata->bpinst, machdata->bpsize) != 0)
sysfatal("stopped at %#llux; not at breakpoint %d", pc, machdata->bpsize);
// Figure out how many bytes of straight-line code
// there are in the text starting at pc.
n = 0;
while(n < sizeof buf) {
n1 = machdata->instsize(text, pc+n);
if(n+n1 > sizeof buf)
break;
n2 = machdata->foll(text, pc+n, rgetzero, foll);
n += n1;
if(n2 != 1 || foll[0] != pc+n)
break;
}
// Record that this section of code ran.
ran(pc, pc+n);
// Put original instructions back.
if(get1(text, pc, buf, n) < 0)
sysfatal("get1: %r");
if(put1(mem, pc, buf, n) < 0)
sysfatal("put1: %r");
}
int
startprocess(char **argv)
{
int pid;
if((pid = fork()) < 0)
sysfatal("fork: %r");
if(pid == 0) {
pid = getpid();
if(ctlproc(pid, "hang") < 0)
sysfatal("ctlproc hang: %r");
exec(argv[0], argv);
sysfatal("exec %s: %r", argv[0]);
}
if(ctlproc(pid, "attached") < 0 || ctlproc(pid, "waitstop") < 0)
sysfatal("attach %d %s: %r", pid, argv[0]);
return pid;
}
int
go(void)
{
uvlong pc;
char buf[100];
int n;
for(n = 0;; n++) {
ctlproc(pid, "startstop");
if(get8(mem, offsetof(Ureg, ip), &pc) < 0) {
rerrstr(buf, sizeof buf);
if(strstr(buf, "exited") || strstr(buf, "No such process"))
return n;
sysfatal("cannot read pc: %r");
}
pc--;
if(put8(mem, offsetof(Ureg, ip), pc) < 0)
sysfatal("cannot write pc: %r");
uncover(pc);
}
}
void
main(int argc, char **argv)
{
int n;
ARGBEGIN{
case 'g':
substring = EARGF(usage());
break;
case 'l':
longnames++;
break;
case 'n':
minlines = atoi(EARGF(usage()));
break;
case 's':
doshowsrc = 1;
break;
case 'v':
chatty++;
break;
default:
usage();
}ARGEND
getwd(cwd, sizeof cwd);
ncwd = strlen(cwd);
if(argc == 0) {
*--argv = "6.out";
}
fd = open(argv[0], OREAD);
if(fd < 0)
sysfatal("open %s: %r", argv[0]);
if(crackhdr(fd, &fhdr) <= 0)
sysfatal("crackhdr: %r");
machbytype(fhdr.type);
if(syminit(fd, &fhdr) <= 0)
sysfatal("syminit: %r");
text = loadmap(nil, fd, &fhdr);
if(text == nil)
sysfatal("loadmap: %r");
pid = startprocess(argv);
mem = attachproc(pid, &fhdr);
if(mem == nil)
sysfatal("attachproc: %r");
breakpoints.cmp = rangecmp;
cover();
n = go();
walktree(breakpoints.root);
if(chatty)
print("%d breakpoints\n", n);
detachproc(mem);
exits(0);
}

View File

@@ -1,245 +0,0 @@
// Renamed from Map to Tree to avoid conflict with libmach.
/*
Copyright (c) 2003-2007 Russ Cox, Tom Bergan, Austin Clements,
Massachusetts Institute of Technology
Portions Copyright (c) 2009 The Go Authors. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
// Mutable map structure, but still based on
// Okasaki, Red Black Trees in a Functional Setting, JFP 1999,
// which is a lot easier than the traditional red-black
// and plenty fast enough for me. (Also I could copy
// and edit fmap.c.)
#include <u.h>
#include <libc.h>
#include "tree.h"
enum
{
Red = 0,
Black = 1
};
// Red-black trees are binary trees with this property:
// 1. No red node has a red parent.
// 2. Every path from the root to a leaf contains the
// same number of black nodes.
static TreeNode*
rwTreeNode(TreeNode *p, int color, TreeNode *left, void *key, void *value, TreeNode *right)
{
if(p == nil)
p = malloc(sizeof *p);
if(p == nil)
sysfatal("out of memory");
p->color = color;
p->left = left;
p->key = key;
p->value = value;
p->right = right;
return p;
}
static TreeNode*
balance(TreeNode *m0)
{
void *xk, *xv, *yk, *yv, *zk, *zv;
TreeNode *a, *b, *c, *d;
TreeNode *m1, *m2;
int color;
TreeNode *left, *right;
void *key, *value;
color = m0->color;
left = m0->left;
key = m0->key;
value = m0->value;
right = m0->right;
// Okasaki notation: (T is mkTreeNode, B is Black, R is Red, x, y, z are key-value.
//
// balance B (T R (T R a x b) y c) z d
// balance B (T R a x (T R b y c)) z d
// balance B a x (T R (T R b y c) z d)
// balance B a x (T R b y (T R c z d))
//
// = T R (T B a x b) y (T B c z d)
if(color == Black){
if(left && left->color == Red){
if(left->left && left->left->color == Red){
a = left->left->left;
xk = left->left->key;
xv = left->left->value;
b = left->left->right;
yk = left->key;
yv = left->value;
c = left->right;
zk = key;
zv = value;
d = right;
m1 = left;
m2 = left->left;
goto hard;
}else if(left->right && left->right->color == Red){
a = left->left;
xk = left->key;
xv = left->value;
b = left->right->left;
yk = left->right->key;
yv = left->right->value;
c = left->right->right;
zk = key;
zv = value;
d = right;
m1 = left;
m2 = left->right;
goto hard;
}
}else if(right && right->color == Red){
if(right->left && right->left->color == Red){
a = left;
xk = key;
xv = value;
b = right->left->left;
yk = right->left->key;
yv = right->left->value;
c = right->left->right;
zk = right->key;
zv = right->value;
d = right->right;
m1 = right;
m2 = right->left;
goto hard;
}else if(right->right && right->right->color == Red){
a = left;
xk = key;
xv = value;
b = right->left;
yk = right->key;
yv = right->value;
c = right->right->left;
zk = right->right->key;
zv = right->right->value;
d = right->right->right;
m1 = right;
m2 = right->right;
goto hard;
}
}
}
return rwTreeNode(m0, color, left, key, value, right);
hard:
return rwTreeNode(m0, Red, rwTreeNode(m1, Black, a, xk, xv, b),
yk, yv, rwTreeNode(m2, Black, c, zk, zv, d));
}
static TreeNode*
ins0(TreeNode *p, void *k, void *v, TreeNode *rw)
{
if(p == nil)
return rwTreeNode(rw, Red, nil, k, v, nil);
if(p->key == k){
if(rw)
return rwTreeNode(rw, p->color, p->left, k, v, p->right);
p->value = v;
return p;
}
if(p->key < k)
p->left = ins0(p->left, k, v, rw);
else
p->right = ins0(p->right, k, v, rw);
return balance(p);
}
static TreeNode*
ins1(Tree *m, TreeNode *p, void *k, void *v, TreeNode *rw)
{
int i;
if(p == nil)
return rwTreeNode(rw, Red, nil, k, v, nil);
i = m->cmp(p->key, k);
if(i == 0){
if(rw)
return rwTreeNode(rw, p->color, p->left, k, v, p->right);
p->value = v;
return p;
}
if(i < 0)
p->left = ins1(m, p->left, k, v, rw);
else
p->right = ins1(m, p->right, k, v, rw);
return balance(p);
}
void
treeputelem(Tree *m, void *key, void *val, TreeNode *rw)
{
if(m->cmp)
m->root = ins1(m, m->root, key, val, rw);
else
m->root = ins0(m->root, key, val, rw);
}
void
treeput(Tree *m, void *key, void *val)
{
treeputelem(m, key, val, nil);
}
void*
treeget(Tree *m, void *key)
{
int i;
TreeNode *p;
p = m->root;
if(m->cmp){
for(;;){
if(p == nil)
return nil;
i = m->cmp(p->key, key);
if(i < 0)
p = p->left;
else if(i > 0)
p = p->right;
else
return p->value;
}
}else{
for(;;){
if(p == nil)
return nil;
if(p->key == key)
return p->value;
if(p->key < key)
p = p->left;
else
p = p->right;
}
}
}

View File

@@ -1,47 +0,0 @@
// Renamed from Map to Tree to avoid conflict with libmach.
/*
Copyright (c) 2003-2007 Russ Cox, Tom Bergan, Austin Clements,
Massachusetts Institute of Technology
Portions Copyright (c) 2009 The Go Authors. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
typedef struct Tree Tree;
typedef struct TreeNode TreeNode;
struct Tree
{
int (*cmp)(void*, void*);
TreeNode *root;
};
struct TreeNode
{
int color;
TreeNode *left;
void *key;
void *value;
TreeNode *right;
};
void *treeget(Tree*, void*);
void treeput(Tree*, void*, void*);
void treeputelem(Tree*, void*, void*, TreeNode*);

View File

@@ -280,7 +280,7 @@ typecheckpartialcall(Node *fn, Node *sym)
static Node*
makepartialcall(Node *fn, Type *t0, Node *meth)
{
Node *ptr, *n, *fld, *call, *xtype, *xfunc, *cv;
Node *ptr, *n, *fld, *call, *xtype, *xfunc, *cv, *savecurfn;
Type *rcvrtype, *basetype, *t;
NodeList *body, *l, *callargs, *retargs;
char *p;
@@ -304,6 +304,9 @@ makepartialcall(Node *fn, Type *t0, Node *meth)
if(sym->flags & SymUniq)
return sym->def;
sym->flags |= SymUniq;
savecurfn = curfn;
curfn = N;
xtype = nod(OTFUNC, N, N);
i = 0;
@@ -311,6 +314,7 @@ makepartialcall(Node *fn, Type *t0, Node *meth)
callargs = nil;
ddd = 0;
xfunc = nod(ODCLFUNC, N, N);
curfn = xfunc;
for(t = getinargx(t0)->type; t; t = t->down) {
snprint(namebuf, sizeof namebuf, "a%d", i++);
n = newname(lookup(namebuf));
@@ -385,6 +389,7 @@ makepartialcall(Node *fn, Type *t0, Node *meth)
typecheck(&xfunc, Etop);
sym->def = xfunc;
xtop = list(xtop, xfunc);
curfn = savecurfn;
return xfunc;
}

View File

@@ -161,16 +161,25 @@ reexportdep(Node *n)
case OCONV:
case OCONVIFACE:
case OCONVNOP:
case ORUNESTR:
case OARRAYBYTESTR:
case OARRAYRUNESTR:
case OSTRARRAYBYTE:
case OSTRARRAYRUNE:
case ODOTTYPE:
case ODOTTYPE2:
case OSTRUCTLIT:
case OARRAYLIT:
case OPTRLIT:
case OMAKEMAP:
case OMAKESLICE:
case OMAKECHAN:
t = n->type;
if(!t->sym && t->type)
t = t->type;
if(t && t->sym && t->sym->def && !exportedsym(t->sym)) {
if(debug['E'])
print("reexport type for convnop %S\n", t->sym);
print("reexport type for expression %S\n", t->sym);
exportlist = list(exportlist, t->sym->def);
}
break;

View File

@@ -1218,7 +1218,7 @@ exprfmt(Fmt *f, Node *n, int prec)
}
if(fmtmode == FExp && ptrlit)
// typecheck has overwritten OIND by OTYPE with pointer type.
return fmtprint(f, "&%T{ %,H }", n->right->type->type, n->list);
return fmtprint(f, "(&%T{ %,H })", n->right->type->type, n->list);
return fmtprint(f, "(%N{ %,H })", n->right, n->list);
case OPTRLIT:

View File

@@ -282,6 +282,7 @@ struct Node
NodeList* cvars; // closure params
NodeList* dcl; // autodcl for this func/closure
NodeList* inl; // copy of the body for use in inlining
NodeList* inldcl; // copy of dcl for use in inlining
// OLITERAL/OREGISTER
Val val;

View File

@@ -146,6 +146,7 @@ caninl(Node *fn)
fn->nname->inl = fn->nbody;
fn->nbody = inlcopylist(fn->nname->inl);
fn->nname->inldcl = inlcopylist(fn->nname->defn->dcl);
// hack, TODO, check for better way to link method nodes back to the thing with the ->inl
// this is so export can find the body of a method
@@ -558,8 +559,8 @@ mkinlcall1(Node **np, Node *fn, int isddd)
//dumplist("ninit pre", ninit);
if (fn->defn) // local function
dcl = fn->defn->dcl;
if(fn->defn) // local function
dcl = fn->inldcl;
else // imported function
dcl = fn->dcl;

View File

@@ -50,9 +50,10 @@ init1(Node *n, NodeList **out)
case PFUNC:
break;
default:
if(isblank(n) && n->defn != N && n->defn->initorder == InitNotStarted) {
n->defn->initorder = InitDone;
*out = list(*out, n->defn);
if(isblank(n) && n->curfn == N && n->defn != N && n->defn->initorder == InitNotStarted) {
// blank names initialization is part of init() but not
// when they are inside a function.
break;
}
return;
}
@@ -62,7 +63,7 @@ init1(Node *n, NodeList **out)
if(n->initorder == InitPending) {
if(n->class == PFUNC)
return;
// if there have already been errors printed,
// those errors probably confused us and
// there might not be a loop. let the user
@@ -127,8 +128,8 @@ init1(Node *n, NodeList **out)
init2(n->defn->right, out);
if(debug['j'])
print("%S\n", n->sym);
if(!staticinit(n, out)) {
if(debug['%']) dump("nonstatic", n->defn);
if(isblank(n) || !staticinit(n, out)) {
if(debug['%']) dump("nonstatic", n->defn);
*out = list(*out, n->defn);
}
} else if(0) {
@@ -149,6 +150,7 @@ if(debug['%']) dump("nonstatic", n->defn);
n->defn->initorder = InitDone;
for(l=n->defn->rlist; l; l=l->next)
init1(l->n, out);
if(debug['%']) dump("nonstatic", n->defn);
*out = list(*out, n->defn);
break;
}

View File

@@ -1338,6 +1338,13 @@ walkexpr(Node **np, NodeList **init)
fatal("missing switch %O", n->op);
ret:
// Expressions that are constant at run time but not
// considered const by the language spec are not turned into
// constants until walk. For example, if n is y%1 == 0, the
// walk of y%1 may have replaced it by 0.
// Check whether n with its updated args is itself now a constant.
evconst(n);
ullmancalc(n);
if(debug['w'] && n != N)

View File

@@ -1,5 +0,0 @@
# Copyright 2012 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.
include ../../Make.dist

View File

@@ -1,49 +0,0 @@
// 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.
// +build ignore
/*
Prof is a rudimentary real-time profiler.
Given a command to run or the process id (pid) of a command already
running, it samples the program's state at regular intervals and reports
on its behavior. With no options, it prints a histogram of the locations
in the code that were sampled during execution.
Since it is a real-time profiler, unlike a traditional profiler it samples
the program's state even when it is not running, such as when it is
asleep or waiting for I/O. Each thread contributes equally to the
statistics.
Usage:
go tool prof -p pid [-t total_secs] [-d delta_msec] [6.out args ...]
The output modes (default -h) are:
-P file.prof:
Write the profile information to file.prof, in the format used by pprof.
At the moment, this only works on Linux amd64 binaries and requires that the
binary be written using 6l -e to produce ELF debug info.
See http://code.google.com/p/google-perftools for details.
-h: histograms
How many times a sample occurred at each location.
-f: dynamic functions
At each sample period, print the name of the executing function.
-l: dynamic file and line numbers
At each sample period, print the file and line number of the executing instruction.
-r: dynamic registers
At each sample period, print the register contents.
-s: dynamic function stack traces
At each sample period, print the symbolic stack trace.
Flag -t sets the maximum real time to sample, in seconds, and -d
sets the sampling interval in milliseconds. The default is to sample
every 100ms until the program completes.
It is installed as go tool prof and is architecture-independent.
*/
package main

View File

@@ -1,910 +0,0 @@
// 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.
// +build !plan9
#include <u.h>
#include <time.h>
#include <libc.h>
#include <bio.h>
#include <ctype.h>
#define Ureg Ureg_amd64
#include <ureg_amd64.h>
#undef Ureg
#define Ureg Ureg_x86
#include <ureg_x86.h>
#undef Ureg
#include <mach.h>
char* file = "6.out";
static Fhdr fhdr;
int have_syms;
int fd;
struct Ureg_amd64 ureg_amd64;
struct Ureg_x86 ureg_x86;
int total_sec = 0;
int delta_msec = 100;
int nsample;
int nsamplethread;
// pprof data, stored as sequences of N followed by N PC values.
// See http://code.google.com/p/google-perftools .
uvlong *ppdata; // traces
Biobuf* pproffd; // file descriptor to write trace info
long ppstart; // start position of current trace
long nppdata; // length of data
long ppalloc; // size of allocated data
char ppmapdata[10*1024]; // the map information for the output file
// output formats
int pprof; // print pprof output to named file
int functions; // print functions
int histograms; // print histograms
int linenums; // print file and line numbers rather than function names
int registers; // print registers
int stacks; // print stack traces
int pid; // main process pid
int nthread; // number of threads
int thread[32]; // thread pids
Map *map[32]; // thread maps
void
Usage(void)
{
fprint(2, "Usage: prof -p pid [-t total_secs] [-d delta_msec]\n");
fprint(2, " prof [-t total_secs] [-d delta_msec] 6.out args ...\n");
fprint(2, "\tformats (default -h):\n");
fprint(2, "\t\t-P file.prof: write [c]pprof output to file.prof\n");
fprint(2, "\t\t-h: histograms\n");
fprint(2, "\t\t-f: dynamic functions\n");
fprint(2, "\t\t-l: dynamic file and line numbers\n");
fprint(2, "\t\t-r: dynamic registers\n");
fprint(2, "\t\t-s: dynamic function stack traces\n");
fprint(2, "\t\t-hs: include stack info in histograms\n");
exit(2);
}
typedef struct PC PC;
struct PC {
uvlong pc;
uvlong callerpc;
unsigned int count;
PC* next;
};
enum {
Ncounters = 256
};
PC *counters[Ncounters];
// Set up by setarch() to make most of the code architecture-independent.
typedef struct Arch Arch;
struct Arch {
char* name;
void (*regprint)(void);
int (*getregs)(Map*);
int (*getPC)(Map*);
int (*getSP)(Map*);
uvlong (*uregPC)(void);
uvlong (*uregSP)(void);
void (*ppword)(uvlong w);
};
void
amd64_regprint(void)
{
fprint(2, "ax\t0x%llux\n", ureg_amd64.ax);
fprint(2, "bx\t0x%llux\n", ureg_amd64.bx);
fprint(2, "cx\t0x%llux\n", ureg_amd64.cx);
fprint(2, "dx\t0x%llux\n", ureg_amd64.dx);
fprint(2, "si\t0x%llux\n", ureg_amd64.si);
fprint(2, "di\t0x%llux\n", ureg_amd64.di);
fprint(2, "bp\t0x%llux\n", ureg_amd64.bp);
fprint(2, "r8\t0x%llux\n", ureg_amd64.r8);
fprint(2, "r9\t0x%llux\n", ureg_amd64.r9);
fprint(2, "r10\t0x%llux\n", ureg_amd64.r10);
fprint(2, "r11\t0x%llux\n", ureg_amd64.r11);
fprint(2, "r12\t0x%llux\n", ureg_amd64.r12);
fprint(2, "r13\t0x%llux\n", ureg_amd64.r13);
fprint(2, "r14\t0x%llux\n", ureg_amd64.r14);
fprint(2, "r15\t0x%llux\n", ureg_amd64.r15);
fprint(2, "ds\t0x%llux\n", ureg_amd64.ds);
fprint(2, "es\t0x%llux\n", ureg_amd64.es);
fprint(2, "fs\t0x%llux\n", ureg_amd64.fs);
fprint(2, "gs\t0x%llux\n", ureg_amd64.gs);
fprint(2, "type\t0x%llux\n", ureg_amd64.type);
fprint(2, "error\t0x%llux\n", ureg_amd64.error);
fprint(2, "pc\t0x%llux\n", ureg_amd64.ip);
fprint(2, "cs\t0x%llux\n", ureg_amd64.cs);
fprint(2, "flags\t0x%llux\n", ureg_amd64.flags);
fprint(2, "sp\t0x%llux\n", ureg_amd64.sp);
fprint(2, "ss\t0x%llux\n", ureg_amd64.ss);
}
int
amd64_getregs(Map *map)
{
int i;
union {
uvlong regs[1];
struct Ureg_amd64 ureg;
} u;
for(i = 0; i < sizeof ureg_amd64; i+=8) {
if(get8(map, (uvlong)i, &u.regs[i/8]) < 0)
return -1;
}
ureg_amd64 = u.ureg;
return 0;
}
int
amd64_getPC(Map *map)
{
uvlong x;
int r;
r = get8(map, offsetof(struct Ureg_amd64, ip), &x);
ureg_amd64.ip = x;
return r;
}
int
amd64_getSP(Map *map)
{
uvlong x;
int r;
r = get8(map, offsetof(struct Ureg_amd64, sp), &x);
ureg_amd64.sp = x;
return r;
}
uvlong
amd64_uregPC(void)
{
return ureg_amd64.ip;
}
uvlong
amd64_uregSP(void)
{
return ureg_amd64.sp;
}
void
amd64_ppword(uvlong w)
{
uchar buf[8];
buf[0] = w;
buf[1] = w >> 8;
buf[2] = w >> 16;
buf[3] = w >> 24;
buf[4] = w >> 32;
buf[5] = w >> 40;
buf[6] = w >> 48;
buf[7] = w >> 56;
Bwrite(pproffd, buf, 8);
}
void
x86_regprint(void)
{
fprint(2, "ax\t0x%ux\n", ureg_x86.ax);
fprint(2, "bx\t0x%ux\n", ureg_x86.bx);
fprint(2, "cx\t0x%ux\n", ureg_x86.cx);
fprint(2, "dx\t0x%ux\n", ureg_x86.dx);
fprint(2, "si\t0x%ux\n", ureg_x86.si);
fprint(2, "di\t0x%ux\n", ureg_x86.di);
fprint(2, "bp\t0x%ux\n", ureg_x86.bp);
fprint(2, "ds\t0x%ux\n", ureg_x86.ds);
fprint(2, "es\t0x%ux\n", ureg_x86.es);
fprint(2, "fs\t0x%ux\n", ureg_x86.fs);
fprint(2, "gs\t0x%ux\n", ureg_x86.gs);
fprint(2, "cs\t0x%ux\n", ureg_x86.cs);
fprint(2, "flags\t0x%ux\n", ureg_x86.flags);
fprint(2, "pc\t0x%ux\n", ureg_x86.pc);
fprint(2, "sp\t0x%ux\n", ureg_x86.sp);
fprint(2, "ss\t0x%ux\n", ureg_x86.ss);
}
int
x86_getregs(Map *map)
{
int i;
for(i = 0; i < sizeof ureg_x86; i+=4) {
if(get4(map, (uvlong)i, &((uint32*)&ureg_x86)[i/4]) < 0)
return -1;
}
return 0;
}
int
x86_getPC(Map* map)
{
return get4(map, offsetof(struct Ureg_x86, pc), &ureg_x86.pc);
}
int
x86_getSP(Map* map)
{
return get4(map, offsetof(struct Ureg_x86, sp), &ureg_x86.sp);
}
uvlong
x86_uregPC(void)
{
return (uvlong)ureg_x86.pc;
}
uvlong
x86_uregSP(void)
{
return (uvlong)ureg_x86.sp;
}
void
x86_ppword(uvlong w)
{
uchar buf[4];
buf[0] = w;
buf[1] = w >> 8;
buf[2] = w >> 16;
buf[3] = w >> 24;
Bwrite(pproffd, buf, 4);
}
Arch archtab[] = {
{
"amd64",
amd64_regprint,
amd64_getregs,
amd64_getPC,
amd64_getSP,
amd64_uregPC,
amd64_uregSP,
amd64_ppword,
},
{
"386",
x86_regprint,
x86_getregs,
x86_getPC,
x86_getSP,
x86_uregPC,
x86_uregSP,
x86_ppword,
},
{
nil
}
};
Arch *arch;
int
setarch(void)
{
int i;
if(mach != nil) {
for(i = 0; archtab[i].name != nil; i++) {
if (strcmp(mach->name, archtab[i].name) == 0) {
arch = &archtab[i];
return 0;
}
}
}
return -1;
}
int
getthreads(void)
{
int i, j, curn, found;
Map *curmap[nelem(map)];
int curthread[nelem(map)];
static int complained = 0;
curn = procthreadpids(pid, curthread, nelem(curthread));
if(curn <= 0)
return curn;
if(curn > nelem(map)) {
if(complained == 0) {
fprint(2, "prof: too many threads; limiting to %d\n", nthread, nelem(map));
complained = 1;
}
curn = nelem(map);
}
if(curn == nthread && memcmp(thread, curthread, curn*sizeof(*thread)) == 0)
return curn; // no changes
// Number of threads has changed (might be the init case).
// A bit expensive but rare enough not to bother being clever.
for(i = 0; i < curn; i++) {
found = 0;
for(j = 0; j < nthread; j++) {
if(curthread[i] == thread[j]) {
found = 1;
curmap[i] = map[j];
map[j] = nil;
break;
}
}
if(found)
continue;
// map new thread
curmap[i] = attachproc(curthread[i], &fhdr);
if(curmap[i] == nil) {
fprint(2, "prof: can't attach to %d: %r\n", curthread[i]);
return -1;
}
}
for(j = 0; j < nthread; j++)
if(map[j] != nil)
detachproc(map[j]);
nthread = curn;
memmove(thread, curthread, nthread*sizeof thread[0]);
memmove(map, curmap, sizeof map);
return nthread;
}
int
sample(Map *map)
{
static int n;
n++;
if(registers) {
if(arch->getregs(map) < 0)
goto bad;
} else {
// we need only two registers
if(arch->getPC(map) < 0)
goto bad;
if(arch->getSP(map) < 0)
goto bad;
}
return 1;
bad:
if(n == 1)
fprint(2, "prof: can't read registers: %r\n");
return 0;
}
void
addtohistogram(uvlong pc, uvlong callerpc, uvlong sp)
{
int h;
PC *x;
USED(sp);
h = (pc + callerpc*101) % Ncounters;
for(x = counters[h]; x != NULL; x = x->next) {
if(x->pc == pc && x->callerpc == callerpc) {
x->count++;
return;
}
}
x = malloc(sizeof(PC));
if(x == nil)
sysfatal("out of memory");
x->pc = pc;
x->callerpc = callerpc;
x->count = 1;
x->next = counters[h];
counters[h] = x;
}
void
addppword(uvlong pc)
{
if(pc == 0) {
return;
}
if(nppdata == ppalloc) {
ppalloc = (1000+nppdata)*2;
ppdata = realloc(ppdata, ppalloc * sizeof ppdata[0]);
if(ppdata == nil) {
fprint(2, "prof: realloc failed: %r\n");
exit(2);
}
}
ppdata[nppdata++] = pc;
}
void
startpptrace(void)
{
ppstart = nppdata;
addppword(~0);
}
void
endpptrace(void)
{
ppdata[ppstart] = nppdata-ppstart-1;
}
uvlong nextpc;
void
xptrace(Map *map, uvlong pc, uvlong sp, Symbol *sym)
{
USED(map);
char buf[1024];
if(sym == nil){
fprint(2, "syms\n");
return;
}
if(histograms)
addtohistogram(nextpc, pc, sp);
if(!histograms || stacks > 1 || pprof) {
if(nextpc == 0)
nextpc = sym->value;
if(stacks){
fprint(2, "%s(", sym->name);
fprint(2, ")");
if(nextpc != sym->value)
fprint(2, "+%#llux ", nextpc - sym->value);
if(have_syms && linenums && fileline(buf, sizeof buf, pc)) {
fprint(2, " %s", buf);
}
fprint(2, "\n");
}
if (pprof) {
addppword(nextpc);
}
}
nextpc = pc;
}
void
stacktracepcsp(Map *map, uvlong pc, uvlong sp)
{
nextpc = pc;
if(pprof){
startpptrace();
}
if(machdata->ctrace==nil)
fprint(2, "no machdata->ctrace\n");
else if(machdata->ctrace(map, pc, sp, 0, xptrace) <= 0)
fprint(2, "no stack frame: pc=%#p sp=%#p\n", pc, sp);
else {
addtohistogram(nextpc, 0, sp);
if(stacks)
fprint(2, "\n");
}
if(pprof){
endpptrace();
}
}
void
printpc(Map *map, uvlong pc, uvlong sp)
{
char buf[1024];
if(registers)
arch->regprint();
if(have_syms > 0 && linenums && fileline(buf, sizeof buf, pc))
fprint(2, "%s\n", buf);
if(have_syms > 0 && functions) {
symoff(buf, sizeof(buf), pc, CANY);
fprint(2, "%s\n", buf);
}
if(stacks || pprof){
stacktracepcsp(map, pc, sp);
}
else if(histograms){
addtohistogram(pc, 0, sp);
}
}
void
ppmaps(void)
{
int fd, n;
char tmp[100];
Seg *seg;
// If it's Linux, the info is in /proc/$pid/maps
snprint(tmp, sizeof tmp, "/proc/%d/maps", pid);
fd = open(tmp, 0);
if(fd >= 0) {
n = read(fd, ppmapdata, sizeof ppmapdata - 1);
close(fd);
if(n < 0) {
fprint(2, "prof: can't read %s: %r\n", tmp);
exit(2);
}
ppmapdata[n] = 0;
return;
}
// It's probably a mac. Synthesize an entry for the text file.
// The register segment may come first but it has a zero offset, so grab the first non-zero offset segment.
for(n = 0; n < 3; n++){
seg = &map[0]->seg[n];
if(seg->b == 0) {
continue;
}
snprint(ppmapdata, sizeof ppmapdata,
"%.16x-%.16x r-xp %d 00:00 34968549 %s\n",
seg->b, seg->e, seg->f, "/home/r/6.out"
);
return;
}
fprint(2, "prof: no text segment in maps for %s\n", file);
exit(2);
}
void
samples(void)
{
int i, pid, msec;
struct timespec req;
int getmaps;
req.tv_sec = delta_msec/1000;
req.tv_nsec = 1000000*(delta_msec % 1000);
getmaps = 0;
if(pprof)
getmaps= 1;
for(msec = 0; total_sec <= 0 || msec < 1000*total_sec; msec += delta_msec) {
nsample++;
nsamplethread += nthread;
for(i = 0; i < nthread; i++) {
pid = thread[i];
if(ctlproc(pid, "stop") < 0)
return;
if(!sample(map[i])) {
ctlproc(pid, "start");
return;
}
printpc(map[i], arch->uregPC(), arch->uregSP());
ctlproc(pid, "start");
}
nanosleep(&req, NULL);
getthreads();
if(nthread == 0)
break;
if(getmaps) {
getmaps = 0;
ppmaps();
}
}
}
typedef struct Func Func;
struct Func
{
Func *next;
Symbol s;
uint onstack;
uint leaf;
};
Func *func[257];
int nfunc;
Func*
findfunc(uvlong pc)
{
Func *f;
uint h;
Symbol s;
if(pc == 0)
return nil;
if(!findsym(pc, CTEXT, &s))
return nil;
h = s.value % nelem(func);
for(f = func[h]; f != NULL; f = f->next)
if(f->s.value == s.value)
return f;
f = malloc(sizeof *f);
if(f == nil)
sysfatal("out of memory");
memset(f, 0, sizeof *f);
f->s = s;
f->next = func[h];
func[h] = f;
nfunc++;
return f;
}
int
compareleaf(const void *va, const void *vb)
{
Func *a, *b;
a = *(Func**)va;
b = *(Func**)vb;
if(a->leaf != b->leaf)
return b->leaf - a->leaf;
if(a->onstack != b->onstack)
return b->onstack - a->onstack;
return strcmp(a->s.name, b->s.name);
}
void
dumphistogram(void)
{
int i, h, n;
PC *x;
Func *f, **ff;
if(!histograms)
return;
// assign counts to functions.
for(h = 0; h < Ncounters; h++) {
for(x = counters[h]; x != NULL; x = x->next) {
f = findfunc(x->pc);
if(f) {
f->onstack += x->count;
f->leaf += x->count;
}
f = findfunc(x->callerpc);
if(f)
f->leaf -= x->count;
}
}
// build array
ff = malloc(nfunc*sizeof ff[0]);
if(ff == nil)
sysfatal("out of memory");
n = 0;
for(h = 0; h < nelem(func); h++)
for(f = func[h]; f != NULL; f = f->next)
ff[n++] = f;
// sort by leaf counts
qsort(ff, nfunc, sizeof ff[0], compareleaf);
// print.
fprint(2, "%d samples (avg %.1g threads)\n", nsample, (double)nsamplethread/nsample);
for(i = 0; i < nfunc; i++) {
f = ff[i];
fprint(2, "%6.2f%%\t", 100.0*(double)f->leaf/nsample);
if(stacks)
fprint(2, "%6.2f%%\t", 100.0*(double)f->onstack/nsample);
fprint(2, "%s\n", f->s.name);
}
}
typedef struct Trace Trace;
struct Trace {
int count;
int npc;
uvlong *pc;
Trace *next;
};
void
dumppprof(void)
{
uvlong i, n, *p, *e;
int ntrace;
Trace *trace, *tp, *up, *prev;
if(!pprof)
return;
e = ppdata + nppdata;
// Create list of traces. First, count the traces
ntrace = 0;
for(p = ppdata; p < e;) {
n = *p++;
p += n;
if(n == 0)
continue;
ntrace++;
}
if(ntrace <= 0)
return;
// Allocate and link the traces together.
trace = malloc(ntrace * sizeof(Trace));
if(trace == nil)
sysfatal("out of memory");
tp = trace;
for(p = ppdata; p < e;) {
n = *p++;
if(n == 0)
continue;
tp->count = 1;
tp->npc = n;
tp->pc = p;
tp->next = tp+1;
tp++;
p += n;
}
trace[ntrace-1].next = nil;
// Eliminate duplicates. Lousy algorithm, although not as bad as it looks because
// the list collapses fast.
for(tp = trace; tp != nil; tp = tp->next) {
prev = tp;
for(up = tp->next; up != nil; up = up->next) {
if(up->npc == tp->npc && memcmp(up->pc, tp->pc, up->npc*sizeof up->pc[0]) == 0) {
tp->count++;
prev->next = up->next;
} else {
prev = up;
}
}
}
// Write file.
// See http://code.google.com/p/google-perftools/source/browse/trunk/doc/cpuprofile-fileformat.html
// 1) Header
arch->ppword(0); // must be zero
arch->ppword(3); // 3 words follow in header
arch->ppword(0); // must be zero
arch->ppword(delta_msec * 1000); // sampling period in microseconds
arch->ppword(0); // must be zero (padding)
// 2) One record for each trace.
for(tp = trace; tp != nil; tp = tp->next) {
arch->ppword(tp->count);
arch->ppword(tp->npc);
for(i = 0; i < tp->npc; i++) {
arch->ppword(tp->pc[i]);
}
}
// 3) Binary trailer
arch->ppword(0); // must be zero
arch->ppword(1); // must be one
arch->ppword(0); // must be zero
// 4) Mapped objects.
Bwrite(pproffd, ppmapdata, strlen(ppmapdata));
// 5) That's it.
Bterm(pproffd);
}
int
startprocess(char **argv)
{
int pid;
if((pid = fork()) == 0) {
pid = getpid();
if(ctlproc(pid, "hang") < 0){
fprint(2, "prof: child process could not hang\n");
exits(0);
}
execv(argv[0], argv);
fprint(2, "prof: could not exec %s: %r\n", argv[0]);
exits(0);
}
if(pid == -1) {
fprint(2, "prof: could not fork\n");
exit(1);
}
if(ctlproc(pid, "attached") < 0 || ctlproc(pid, "waitstop") < 0) {
fprint(2, "prof: could not attach to child process: %r\n");
exit(1);
}
return pid;
}
void
detach(void)
{
int i;
for(i = 0; i < nthread; i++)
detachproc(map[i]);
}
int
main(int argc, char *argv[])
{
int i;
char *ppfile;
ARGBEGIN{
case 'P':
pprof =1;
ppfile = EARGF(Usage());
pproffd = Bopen(ppfile, OWRITE);
if(pproffd == nil) {
fprint(2, "prof: cannot open %s: %r\n", ppfile);
exit(2);
}
break;
case 'd':
delta_msec = atoi(EARGF(Usage()));
break;
case 't':
total_sec = atoi(EARGF(Usage()));
break;
case 'p':
pid = atoi(EARGF(Usage()));
break;
case 'f':
functions = 1;
break;
case 'h':
histograms = 1;
break;
case 'l':
linenums = 1;
break;
case 'r':
registers = 1;
break;
case 's':
stacks++;
break;
default:
Usage();
}ARGEND
if(pid <= 0 && argc == 0)
Usage();
if(functions+linenums+registers+stacks+pprof == 0)
histograms = 1;
if(!machbyname("amd64")) {
fprint(2, "prof: no amd64 support\n", pid);
exit(1);
}
if(argc > 0)
file = argv[0];
else if(pid) {
file = proctextfile(pid);
if (file == NULL) {
fprint(2, "prof: can't find file for pid %d: %r\n", pid);
fprint(2, "prof: on Darwin, need to provide file name explicitly\n");
exit(1);
}
}
fd = open(file, 0);
if(fd < 0) {
fprint(2, "prof: can't open %s: %r\n", file);
exit(1);
}
if(crackhdr(fd, &fhdr)) {
have_syms = syminit(fd, &fhdr);
if(!have_syms) {
fprint(2, "prof: no symbols for %s: %r\n", file);
}
} else {
fprint(2, "prof: crack header for %s: %r\n", file);
exit(1);
}
if(pid <= 0)
pid = startprocess(argv);
attachproc(pid, &fhdr); // initializes thread list
if(setarch() < 0) {
detach();
fprint(2, "prof: can't identify binary architecture for pid %d\n", pid);
exit(1);
}
if(getthreads() <= 0) {
detach();
fprint(2, "prof: can't find threads for pid %d\n", pid);
exit(1);
}
for(i = 0; i < nthread; i++)
ctlproc(thread[i], "start");
samples();
detach();
dumphistogram();
dumppprof();
exit(0);
}

View File

@@ -585,23 +585,28 @@ func (b *Writer) ReadFrom(r io.Reader) (n int64, err error) {
}
var m int
for {
if b.Available() == 0 {
if err1 := b.Flush(); err1 != nil {
return n, err1
}
}
m, err = r.Read(b.buf[b.n:])
if m == 0 {
break
}
b.n += m
n += int64(m)
if b.Available() == 0 {
if err1 := b.Flush(); err1 != nil {
return n, err1
}
}
if err != nil {
break
}
}
if err == io.EOF {
err = nil
// If we filled the buffer exactly, flush pre-emptively.
if b.Available() == 0 {
err = b.Flush()
} else {
err = nil
}
}
return n, err
}

View File

@@ -847,6 +847,10 @@ func TestWriterReadFrom(t *testing.T) {
t.Errorf("ws[%d],rs[%d]: w.ReadFrom(r) = %d, %v, want %d, nil", wi, ri, n, err, len(input))
continue
}
if err := w.Flush(); err != nil {
t.Errorf("Flush returned %v", err)
continue
}
if got, want := b.String(), string(input); got != want {
t.Errorf("ws[%d], rs[%d]:\ngot %q\nwant %q\n", wi, ri, got, want)
}
@@ -1003,6 +1007,24 @@ func TestReaderClearError(t *testing.T) {
}
}
// Test for golang.org/issue/5947
func TestWriterReadFromWhileFull(t *testing.T) {
buf := new(bytes.Buffer)
w := NewWriterSize(buf, 10)
// Fill buffer exactly.
n, err := w.Write([]byte("0123456789"))
if n != 10 || err != nil {
t.Fatalf("Write returned (%v, %v), want (10, nil)", n, err)
}
// Use ReadFrom to read in some data.
n2, err := w.ReadFrom(strings.NewReader("abcdef"))
if n2 != 6 || err != nil {
t.Fatalf("ReadFrom returned (%v, %v), want (6, nil)", n, err)
}
}
// An onlyReader only implements io.Reader, no matter what other methods the underlying implementation may have.
type onlyReader struct {
r io.Reader

View File

@@ -10,14 +10,23 @@ import (
"time"
)
var testingIssue5349 bool // used during tests
// resolveAndDialChannel is the simple pure-Go implementation of
// resolveAndDial, still used on operating systems where the deadline
// hasn't been pushed down into the pollserver. (Plan 9 and some old
// versions of Windows)
func resolveAndDialChannel(net, addr string, localAddr Addr, deadline time.Time) (Conn, error) {
timeout := deadline.Sub(time.Now())
if timeout < 0 {
timeout = 0
var timeout time.Duration
if !deadline.IsZero() {
timeout = deadline.Sub(time.Now())
}
if timeout <= 0 {
ra, err := resolveAddr("dial", net, addr, noDeadline)
if err != nil {
return nil, err
}
return dial(net, addr, localAddr, ra, noDeadline)
}
t := time.NewTimer(timeout)
defer t.Stop()
@@ -28,6 +37,9 @@ func resolveAndDialChannel(net, addr string, localAddr Addr, deadline time.Time)
ch := make(chan pair, 1)
resolvedAddr := make(chan Addr, 1)
go func() {
if testingIssue5349 {
time.Sleep(time.Millisecond)
}
ra, err := resolveAddr("dial", net, addr, noDeadline)
if err != nil {
ch <- pair{nil, err}

View File

@@ -0,0 +1,11 @@
// Copyright 2013 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.
// +build windows plan9
package net
func init() {
testingIssue5349 = true
}

View File

@@ -3032,6 +3032,25 @@ func TestSliceOf(t *testing.T) {
checkSameType(t, Zero(SliceOf(TypeOf(T1(1)))).Interface(), []T1{})
}
func TestSliceOverflow(t *testing.T) {
// check that MakeSlice panics when size of slice overflows uint
const S = 1e6
s := uint(S)
l := (1<<(unsafe.Sizeof((*byte)(nil))*8)-1)/s + 1
if l*s >= s {
t.Fatal("slice size does not overflow")
}
var x [S]byte
st := SliceOf(TypeOf(x))
defer func() {
err := recover()
if err == nil {
t.Fatal("slice overflow does not panic")
}
}()
MakeSlice(st, int(l), int(l))
}
func TestSliceOfGC(t *testing.T) {
type T *uintptr
tt := TypeOf(T(nil))

View File

@@ -809,16 +809,27 @@ sellock(Select *sel)
static void
selunlock(Select *sel)
{
uint32 i;
Hchan *c, *c0;
int32 i, n, r;
Hchan *c;
c = nil;
for(i=sel->ncase; i-->0;) {
c0 = sel->lockorder[i];
if(c0 && c0 != c) {
c = c0;
runtime·unlock(c);
}
// We must be very careful here to not touch sel after we have unlocked
// the last lock, because sel can be freed right after the last unlock.
// Consider the following situation.
// First M calls runtime·park() in runtime·selectgo() passing the sel.
// Once runtime·park() has unlocked the last lock, another M makes
// the G that calls select runnable again and schedules it for execution.
// When the G runs on another M, it locks all the locks and frees sel.
// Now if the first M touches sel, it will access freed memory.
n = (int32)sel->ncase;
r = 0;
// skip the default case
if(n>0 && sel->lockorder[0] == nil)
r = 1;
for(i = n-1; i >= r; i--) {
c = sel->lockorder[i];
if(i>0 && sel->lockorder[i-1] == c)
continue; // will unlock it on the next iteration
runtime·unlock(c);
}
}

View File

@@ -97,3 +97,55 @@ func TestGcHashmapIndirection(t *testing.T) {
m[a] = T{}
}
}
func TestGcArraySlice(t *testing.T) {
type X struct {
buf [1]byte
nextbuf []byte
next *X
}
var head *X
for i := 0; i < 10; i++ {
p := &X{}
p.buf[0] = 42
p.next = head
if head != nil {
p.nextbuf = head.buf[:]
}
head = p
runtime.GC()
}
for p := head; p != nil; p = p.next {
if p.buf[0] != 42 {
t.Fatal("corrupted heap")
}
}
}
func TestGcRescan(t *testing.T) {
type X struct {
c chan error
nextx *X
}
type Y struct {
X
nexty *Y
p *int
}
var head *Y
for i := 0; i < 10; i++ {
p := &Y{}
p.c = make(chan error)
p.nextx = &head.X
p.nexty = head
p.p = new(int)
*p.p = 42
head = p
runtime.GC()
}
for p := head; p != nil; p = p.nexty {
if *p.p != 42 {
t.Fatal("corrupted heap")
}
}
}

View File

@@ -687,42 +687,14 @@ reflect·unsafe_Typeof(Eface e, Eface ret)
void
reflect·unsafe_New(Type *t, void *ret)
{
uint32 flag;
flag = t->kind&KindNoPointers ? FlagNoPointers : 0;
ret = runtime·mallocgc(t->size, flag, 1, 1);
if(UseSpanType && !flag) {
if(false) {
runtime·printf("unsafe_New %S: %p\n", *t->string, ret);
}
runtime·settype(ret, (uintptr)t | TypeInfo_SingleObject);
}
ret = runtime·cnew(t);
FLUSH(&ret);
}
void
reflect·unsafe_NewArray(Type *t, intgo n, void *ret)
{
uint64 size;
size = n*t->size;
if(size == 0)
ret = (byte*)&runtime·zerobase;
else if(t->kind&KindNoPointers)
ret = runtime·mallocgc(size, FlagNoPointers, 1, 1);
else {
ret = runtime·mallocgc(size, 0, 1, 1);
if(UseSpanType) {
if(false) {
runtime·printf("unsafe_NewArray [%D]%S: %p\n", (int64)n, *t->string, ret);
}
runtime·settype(ret, (uintptr)t | TypeInfo_Array);
}
}
ret = runtime·cnewarray(t, n);
FLUSH(&ret);
}

View File

@@ -717,9 +717,8 @@ runtime·new(Type *typ, uint8 *ret)
ret = runtime·mallocgc(typ->size, flag, 1, 1);
if(UseSpanType && !flag) {
if(false) {
if(false)
runtime·printf("new %S: %p\n", *typ->string, ret);
}
runtime·settype(ret, (uintptr)typ | TypeInfo_SingleObject);
}
}
@@ -727,36 +726,45 @@ runtime·new(Type *typ, uint8 *ret)
FLUSH(&ret);
}
// same as runtime·new, but callable from C
void*
runtime·cnew(Type *typ)
static void*
cnew(Type *typ, intgo n, int32 objtyp)
{
uint32 flag;
void *ret;
if(raceenabled)
m->racepc = runtime·getcallerpc(&typ);
if(typ->size == 0) {
if((objtyp&(PtrSize-1)) != objtyp)
runtime·throw("runtime: invalid objtyp");
if(n < 0 || (typ->size > 0 && n > MaxMem/typ->size))
runtime·panicstring("runtime: allocation size out of range");
if(typ->size == 0 || n == 0) {
// All 0-length allocations use this pointer.
// The language does not require the allocations to
// have distinct values.
ret = (uint8*)&runtime·zerobase;
} else {
flag = typ->kind&KindNoPointers ? FlagNoPointers : 0;
ret = runtime·mallocgc(typ->size, flag, 1, 1);
if(UseSpanType && !flag) {
if(false) {
runtime·printf("new %S: %p\n", *typ->string, ret);
}
runtime·settype(ret, (uintptr)typ | TypeInfo_SingleObject);
}
return &runtime·zerobase;
}
flag = typ->kind&KindNoPointers ? FlagNoPointers : 0;
ret = runtime·mallocgc(typ->size*n, flag, 1, 1);
if(UseSpanType && !flag) {
if(false)
runtime·printf("cnew [%D]%S: %p\n", (int64)n, *typ->string, ret);
runtime·settype(ret, (uintptr)typ | objtyp);
}
return ret;
}
// same as runtime·new, but callable from C
void*
runtime·cnew(Type *typ)
{
return cnew(typ, 1, TypeInfo_SingleObject);
}
void*
runtime·cnewarray(Type *typ, intgo n)
{
return cnew(typ, n, TypeInfo_Array);
}
func GC() {
runtime·gc(1);
}

View File

@@ -461,6 +461,7 @@ bool runtime·blockspecial(void*);
void runtime·setblockspecial(void*, bool);
void runtime·purgecachedstats(MCache*);
void* runtime·cnew(Type*);
void* runtime·cnewarray(Type*, intgo);
void runtime·settype(void*, uintptr);
void runtime·settype_flush(M*, bool);

View File

@@ -623,7 +623,7 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking)
byte *b, *arena_start, *arena_used;
uintptr n, i, end_b, elemsize, size, ti, objti, count, type;
uintptr *pc, precise_type, nominal_size;
uintptr *map_ret, mapkey_size, mapval_size, mapkey_ti, mapval_ti, *chan_ret;
uintptr *map_ret, mapkey_size, mapval_size, mapkey_ti, mapval_ti, *chan_ret, chancap;
void *obj;
Type *t;
Slice *sliceptr;
@@ -799,7 +799,11 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking)
sliceptr = (Slice*)(stack_top.b + pc[1]);
if(sliceptr->cap != 0) {
obj = sliceptr->array;
objti = pc[2] | PRECISE | LOOP;
// Can't use slice element type for scanning,
// because if it points to an array embedded
// in the beginning of a struct,
// we will scan the whole struct as the slice.
// So just obtain type info from heap.
}
pc += 3;
break;
@@ -1058,13 +1062,13 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking)
if(!(chantype->elem->kind & KindNoPointers)) {
// Channel's buffer follows Hchan immediately in memory.
// Size of buffer (cap(c)) is second int in the chan struct.
n = ((uintgo*)chan)[1];
if(n > 0) {
chancap = ((uintgo*)chan)[1];
if(chancap > 0) {
// TODO(atom): split into two chunks so that only the
// in-use part of the circular buffer is scanned.
// (Channel routines zero the unused part, so the current
// code does not lead to leaks, it's just a little inefficient.)
*objbufpos++ = (Obj){(byte*)chan+runtime·Hchansize, n*chantype->elem->size,
*objbufpos++ = (Obj){(byte*)chan+runtime·Hchansize, chancap*chantype->elem->size,
(uintptr)chantype->elem->gc | PRECISE | LOOP};
if(objbufpos == objbuf_end)
flushobjbuf(objbuf, &objbufpos, &wp, &wbuf, &nobj);

View File

@@ -1232,6 +1232,7 @@ static void
goexit0(G *gp)
{
gp->status = Gdead;
gp->fnstart = nil;
gp->m = nil;
gp->lockedm = nil;
m->curg = nil;
@@ -1370,6 +1371,8 @@ runtime·exitsyscall(void)
runtime·unlock(&runtime·sched);
if(p) {
acquirep(p);
m->p->tick++;
g->status = Grunning;
g->gcstack = (uintptr)nil;
g->gcsp = (uintptr)nil;
return;

View File

@@ -0,0 +1,9 @@
// Copyright 2013 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 race implements data race detection logic.
// No public interface is provided.
// For details about the race detector see
// http://golang.org/doc/articles/race_detector.html
package race

View File

@@ -4,7 +4,6 @@
// +build race,linux,amd64 race,darwin,amd64 race,windows,amd64
// Package race provides low-level facilities for data race detection.
package race
/*

View File

@@ -48,27 +48,9 @@ uintptr runtime·zerobase;
static void
makeslice1(SliceType *t, intgo len, intgo cap, Slice *ret)
{
uintptr size;
size = cap*t->elem->size;
ret->len = len;
ret->cap = cap;
if(size == 0)
ret->array = (byte*)&runtime·zerobase;
else if((t->elem->kind&KindNoPointers))
ret->array = runtime·mallocgc(size, FlagNoPointers, 1, 1);
else {
ret->array = runtime·mallocgc(size, 0, 1, 1);
if(UseSpanType) {
if(false) {
runtime·printf("new slice [%D]%S: %p\n", (int64)cap, *t->elem->string, ret->array);
}
runtime·settype(ret->array, (uintptr)t->elem | TypeInfo_Array);
}
}
ret->array = runtime·cnewarray(t->elem, cap);
}
// appendslice(type *Type, x, y, []T) []T

View File

@@ -131,6 +131,11 @@ runtime·deltimer(Timer *t)
{
int32 i;
// Dereference t so that any panic happens before the lock is held.
// Discard result, because t might be moving in the heap.
i = t->i;
USED(i);
runtime·lock(&timers);
// t may not be registered anymore and may have

View File

@@ -0,0 +1,41 @@
// Copyright 2013 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 syscall_test
import (
"syscall"
"testing"
)
func TestRlimit(t *testing.T) {
var rlimit, zero syscall.Rlimit
err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlimit)
if err != nil {
t.Fatalf("Getrlimit: save failed: %v", err)
}
if zero == rlimit {
t.Fatalf("Getrlimit: save failed: got zero value %#v", rlimit)
}
set := rlimit
set.Cur = set.Max - 1
err = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &set)
if err != nil {
t.Fatalf("Setrlimit: set failed: %#v %v", set, err)
}
var get syscall.Rlimit
err = syscall.Getrlimit(syscall.RLIMIT_NOFILE, &get)
if err != nil {
t.Fatalf("Getrlimit: get failed: %v", err)
}
set = rlimit
set.Cur = set.Max - 1
if set != get {
t.Fatalf("Rlimit: change failed: wanted %#v got %#v", set, get)
}
err = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rlimit)
if err != nil {
t.Fatalf("Setrlimit: restore failed: %#v %v", rlimit, err)
}
}

View File

@@ -78,7 +78,7 @@ const rlimInf32 = ^uint32(0)
const rlimInf64 = ^uint64(0)
func Getrlimit(resource int, rlim *Rlimit) (err error) {
err = prlimit(0, resource, rlim, nil)
err = prlimit(0, resource, nil, rlim)
if err != ENOSYS {
return err
}
@@ -106,7 +106,7 @@ func Getrlimit(resource int, rlim *Rlimit) (err error) {
//sysnb setrlimit(resource int, rlim *rlimit32) (err error) = SYS_SETRLIMIT
func Setrlimit(resource int, rlim *Rlimit) (err error) {
err = prlimit(0, resource, nil, rlim)
err = prlimit(0, resource, rlim, nil)
if err != ENOSYS {
return err
}

View File

@@ -119,7 +119,7 @@ const rlimInf32 = ^uint32(0)
const rlimInf64 = ^uint64(0)
func Getrlimit(resource int, rlim *Rlimit) (err error) {
err = prlimit(0, resource, rlim, nil)
err = prlimit(0, resource, nil, rlim)
if err != ENOSYS {
return err
}
@@ -147,7 +147,7 @@ func Getrlimit(resource int, rlim *Rlimit) (err error) {
//sysnb setrlimit(resource int, rlim *rlimit32) (err error) = SYS_SETRLIMIT
func Setrlimit(resource int, rlim *Rlimit) (err error) {
err = prlimit(0, resource, nil, rlim)
err = prlimit(0, resource, rlim, nil)
if err != ENOSYS {
return err
}

View File

@@ -314,3 +314,23 @@ func TestOverflowSleep(t *testing.T) {
t.Fatalf("negative timeout didn't fire")
}
}
// Test that a panic while deleting a timer does not leave
// the timers mutex held, deadlocking a ticker.Stop in a defer.
func TestIssue5745(t *testing.T) {
ticker := NewTicker(Hour)
defer func() {
// would deadlock here before the fix due to
// lock taken before the segfault.
ticker.Stop()
if r := recover(); r == nil {
t.Error("Expected panic, but none happened.")
}
}()
// cause a panic due to a segfault
var timer *Timer
timer.Stop()
t.Error("Should be unreachable.")
}

View File

@@ -59,3 +59,18 @@ func F7() int {
}
return 0
}
func F8() int {
if a := (&T{1, 1}); a != nil {
return 1
}
return 0
}
func F9() int {
var a *T
if a = (&T{1, 1}); a != nil {
return 1
}
return 0
}

View File

@@ -9,7 +9,7 @@ import "./a"
func main() {
for _, f := range []func() int{
a.F1, a.F2, a.F3, a.F4,
a.F5, a.F6, a.F7} {
a.F5, a.F6, a.F7, a.F8, a.F9} {
if f() > 1 {
panic("f() > 1")
}

View File

@@ -0,0 +1,18 @@
// run
// Copyright 2013 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.
// Issue 5244: the init order computation uses the wrong
// order for top-level blank identifier assignments.
// The example used to panic because it tries calling a
// nil function instead of assigning to f before.
package main
var f = func() int { return 1 }
var _ = f() + g()
var g = func() int { return 2 }
func main() {}

View File

@@ -0,0 +1,27 @@
// Copyright 2013 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 a
type Foo interface {
Hi() string
}
func Test1() Foo { return make(tst1) }
type tst1 map[string]bool
func (r tst1) Hi() string { return "Hi!" }
func Test2() Foo { return make(tst2, 0) }
type tst2 []string
func (r tst2) Hi() string { return "Hi!" }
func Test3() Foo { return make(tst3) }
type tst3 chan string
func (r tst3) Hi() string { return "Hi!" }

View File

@@ -0,0 +1,13 @@
// Copyright 2013 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 b
import "./a"
func main() {
a.Test1()
a.Test2()
a.Test3()
}

View File

@@ -0,0 +1,10 @@
// compiledir
// Copyright 2013 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.
// Issue 5470: exported data for inlining may miss
// the type argument of make.
package ignored

View File

@@ -0,0 +1,58 @@
// run
// Copyright 2013 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 main
import (
"runtime"
"sync"
"sync/atomic"
"time"
)
const N = 10
var count int64
func run() error {
f1 := func() {}
f2 := func() {
func() {
f1()
}()
}
runtime.SetFinalizer(&f1, func(f *func()) {
atomic.AddInt64(&count, -1)
})
go f2()
return nil
}
func main() {
// Does not work on 32-bits due to partially conservative GC.
// Try to enable when we have fully precise GC.
if runtime.GOARCH != "amd64" {
return
}
count = N
var wg sync.WaitGroup
wg.Add(N)
for i := 0; i < N; i++ {
go func() {
run()
wg.Done()
}()
}
wg.Wait()
for i := 0; i < 2*N; i++ {
time.Sleep(10 * time.Millisecond)
runtime.GC()
}
if count != 0 {
println(count, "out of", N, "finalizer are called")
panic("not all finalizers are called")
}
}

View File

@@ -0,0 +1,34 @@
// run
// Copyright 2013 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.
// issue 5515: miscompilation doing inlining in generated method wrapper
package main
type T uint32
func main() {
b := make([]T, 8)
b[0] = 0xdeadbeef
rs := Slice(b)
sort(rs)
}
type Slice []T
func (s Slice) Swap(i, j int) {
tmp := s[i]
s[i] = s[j]
s[j] = tmp
}
type Interface interface {
Swap(i, j int)
}
func sort(data Interface) {
data.Swap(0, 4)
}

View File

@@ -0,0 +1,36 @@
// run
// Copyright 2013 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.
// Issue 5607: generation of init() function incorrectly
// uses initializers of blank variables inside closures.
package main
var Test = func() {
var mymap = map[string]string{"a": "b"}
var innerTest = func() {
// Used to crash trying to compile this line as
// part of init() (funcdepth mismatch).
var _, x = mymap["a"]
println(x)
}
innerTest()
}
var Test2 = func() {
// The following initializer should not be part of init()
// The compiler used to generate a call to Panic() in init().
var _, x = Panic()
_ = x
}
func Panic() (int, int) {
panic("omg")
return 1, 2
}
func main() {}

View File

@@ -0,0 +1,16 @@
package rethinkgo
type Session struct {
}
func (s *Session) Run(query Exp) *int { return nil }
type List []interface{}
type Exp struct {
args []interface{}
}
func (e Exp) UseOutdated(useOutdated bool) Exp {
return Exp{args: List{e, useOutdated}}
}

View File

@@ -0,0 +1,7 @@
package x
import "./rethinkgo"
var S *rethinkgo.Session

View File

@@ -0,0 +1,5 @@
package y
import "./x"
var T = x.S

View File

@@ -0,0 +1,11 @@
// compiledir
// Copyright 2013 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.
// Issue 5614: exported data for inlining may miss
// named types when used in implicit conversion to
// their underlying type.
package ignored

View File

@@ -0,0 +1,29 @@
// run
// Copyright 2013 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.
// issue 5753: bad typecheck info causes escape analysis to
// not run on method thunks.
package main
type Thing struct{}
func (t *Thing) broken(s string) []string {
foo := [1]string{s}
return foo[:]
}
func main() {
t := &Thing{}
f := t.broken
s := f("foo")
_ = f("bar")
if s[0] != "foo" {
panic(`s[0] != "foo"`)
}
}

View File

@@ -0,0 +1,60 @@
// Copyright 2013 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 a
type I interface {
F()
}
type foo1 []byte
type foo2 []rune
type foo3 []uint8
type foo4 []int32
type foo5 string
type foo6 string
type foo7 string
type foo8 string
type foo9 string
func (f foo1) F() { return }
func (f foo2) F() { return }
func (f foo3) F() { return }
func (f foo4) F() { return }
func (f foo5) F() { return }
func (f foo6) F() { return }
func (f foo7) F() { return }
func (f foo8) F() { return }
func (f foo9) F() { return }
func Test1(s string) I { return foo1(s) }
func Test2(s string) I { return foo2(s) }
func Test3(s string) I { return foo3(s) }
func Test4(s string) I { return foo4(s) }
func Test5(s []byte) I { return foo5(s) }
func Test6(s []rune) I { return foo6(s) }
func Test7(s []uint8) I { return foo7(s) }
func Test8(s []int32) I { return foo8(s) }
func Test9(s int) I { return foo9(s) }
type bar map[int]int
func (b bar) F() { return }
func TestBar() I { return bar{1: 2} }
type baz int
func IsBaz(x interface{}) bool { _, ok := x.(baz); return ok }
type baz2 int
func IsBaz2(x interface{}) bool {
switch x.(type) {
case baz2:
return true
default:
return false
}
}

View File

@@ -0,0 +1,23 @@
// Copyright 2013 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 main
import "./a"
func main() {
a.Test1("frumious")
a.Test2("frumious")
a.Test3("frumious")
a.Test4("frumious")
a.Test5(nil)
a.Test6(nil)
a.Test7(nil)
a.Test8(nil)
a.Test9(0)
a.TestBar()
a.IsBaz(nil)
}

View File

@@ -0,0 +1,10 @@
// compiledir
// Copyright 2013 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.
// Issue 5755: exported data for inlining may miss
// named types when used in string conversions.
package ignored

View File

@@ -0,0 +1,27 @@
// run
// Copyright 2013 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.
// issue 5809: 6g and 8g attempted to constant propagate indexed LEA
package main
import "fmt"
func main() {
const d16 = "0123456789ABCDEF"
k := 0x1234
var x [4]byte
x[0] = d16[k>>12&0xf]
x[1] = d16[k>>8&0xf]
x[2] = d16[k>>4&0xf]
x[3] = d16[k&0xf]
if x != [4]byte{'1','2','3','4'} {
fmt.Println(x)
panic("x != [4]byte{'1','2','3','4'}")
}
}

View File

@@ -0,0 +1,18 @@
// run
// Copyright 2013 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.
// issue 5820: register clobber when clearfat and 64 bit arithmetic is interleaved.
package main
func main() {
array := make([][]int, 2)
index := uint64(1)
array[index] = nil
if array[1] != nil {
panic("array[1] != nil")
}
}

View File

@@ -0,0 +1,16 @@
// build
// Copyright 2013 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.
// Issue 5841: 8g produces invalid CMPL $0, $0.
// Similar to issue 5002, used to fail at link time.
package main
func main() {
var y int
if y%1 == 0 {
}
}