summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2011-10-06 08:56:54 +0200
committerOndřej Surý <ondrej@sury.org>2011-10-06 08:56:54 +0200
commitc3a31f07d2b94710623b6230bb33b30d95d85a2f (patch)
tree8feb57d75d3db3946f86da61507182b268e7d795
parent1f2428d83c863122381a00475b5b6a98335c4026 (diff)
parent766f2d101fd4d91ab470b79fdf93cbc2fc72c515 (diff)
downloadgolang-c3a31f07d2b94710623b6230bb33b30d95d85a2f.tar.gz
Merge commit 'upstream/60.2' into debian-sid
-rw-r--r--doc/debugging_with_gdb.html479
-rw-r--r--doc/devel/release.html6
-rw-r--r--doc/docs.html17
-rw-r--r--doc/go_tutorial.html5
-rw-r--r--doc/go_tutorial.tmpl4
-rw-r--r--doc/install.html3
-rw-r--r--doc/root.html7
-rw-r--r--src/cmd/ld/dwarf.c2
-rw-r--r--src/pkg/image/draw/draw.go8
-rw-r--r--src/pkg/image/image.go3
-rw-r--r--src/pkg/runtime/hashmap.c58
-rw-r--r--src/pkg/runtime/hashmap.h2
-rw-r--r--src/pkg/runtime/runtime-gdb.py4
13 files changed, 553 insertions, 45 deletions
diff --git a/doc/debugging_with_gdb.html b/doc/debugging_with_gdb.html
new file mode 100644
index 000000000..04850c026
--- /dev/null
+++ b/doc/debugging_with_gdb.html
@@ -0,0 +1,479 @@
+<!-- title Debugging Go Code with GDB -->
+
+<p><i>
+This applies to the 6g toolchain. Gccgo has native gdb support. Besides this
+overview you might want to consult the
+<a href="http://sourceware.org/gdb/current/onlinedocs/gdb/">GDB manual</a>.
+</i></p>
+
+<h2 id="Introduction">Introduction</h2>
+
+<p>
+When you compile and link your Go programs with the 6g/6l or 8g/8l toolchains
+on Linux, Mac OSX or FreeBSD, the resulting binaries contain DWARFv3
+debugging information that recent versions (>7.1) of the GDB debugger can
+use to inspect a live process or a core dump.
+</p>
+
+<p>
+Pass the <code>'-s'</code> flag to the linker to omit the debug information.
+</p>
+
+
+<h3 id="Common_Operations">Common Operations</h3>
+
+<ul>
+<li>
+Show file and line number for code
+and set breakpoints:
+<pre>(gdb) <b>list</b>
+(gdb) <b>list <i>line</i></b>
+(gdb) <b>list <i>file.go</i>:<i>line</i></b>
+(gdb) <b>break <i>line</i></b>
+(gdb) <b>break <i>file.go</i>:<i>line</i></b>
+(gdb) <b>disas</b></pre>
+</li>
+<li>
+Unwind stack frames:
+<pre>(gdb) <b>bt</b>
+(gdb) <b>frame <i>n</i></b></pre>
+</li>
+<li>
+Show the name, type and location on the stack frame of local variables,
+arguments and return values:
+<pre>(gdb) <b>info locals</b>
+(gdb) <b>info args</b>
+(gdb) <b>p variable</b>
+(gdb) <b>whatis variable</b></pre>
+</li>
+<li>
+Show the name, type and location of global variables:
+<pre>(gdb) <b>info variables <i>regexp</i></b></pre>
+</li>
+</ul>
+
+
+<h3 id="Go_Extensions">Go Extensions</h3>
+
+<p>
+A recent extension mechanism to GDB allows it to load extension scripts for a
+given binary. The tool chain uses this to extend GDB with a handful of
+commands to inspect internals of the runtime code (such as goroutines) and to
+pretty print the built-in map, slice and channel types.
+</p>
+
+<ul>
+<li>
+Pretty printing a string, slice, map, channel or interface:
+<pre>(gdb) <b>p <i>var</i></b></pre>
+</li>
+<li>
+A $len() and $cap() function for strings, slices and maps:
+<pre>(gdb) <b>p $len(<i>var</i>)</b></pre>
+</li>
+<li>
+A function to cast interfaces to their dynamic types:
+<pre>(gdb) <b>p $dtype(<i>var</i>)</b>
+(gdb) <b>iface <i>var</i></b></pre>
+<p class="detail"><b>Known issue:</b> GDB can’t automatically find the dynamic
+type of an interface value if its long name differs from its short name
+(annoying when printing stacktraces, the pretty printer falls back to printing
+the short type name and a pointer).</p>
+</li>
+<li>
+Inspecting goroutines:
+<pre>(gdb) <b>info goroutines</b>
+(gdb) <b>goroutine <i>n</i> <i>cmd</i></b>
+(gdb) <b>help goroutine</b></pre>
+For example:
+<pre>(gdb) <b>goroutine 12 bt</b></pre>
+</li>
+</ul>
+
+<p>
+If you'd like to see how this works, or want to extend it, take a look at <a
+href="/src/pkg/runtime/runtime-gdb.py">src/pkg/runtime/runtime-gdb.py</a> in
+the Go source distribution. It depends on some special magic types
+(<code>hash&lt;T,U&gt;</code>) and variables (<code>runtime.m</code> and
+<code>runtime.g</code>) that the linker
+(<a href="/src/cmd/ld/dwarf.c">src/cmd/ld/dwarf.c</a>) ensures are described in
+the DWARF code.
+</ines
+
+<p>
+If you're interested in what the debugging information looks like, run
+'<code>objdump -W 6.out</code>' and browse through the <code>.debug_*</code>
+sections.
+</p>
+
+
+<h3 id="Known_Issues">Known Issues</h3>
+
+<ol>
+<li>String pretty printing only triggers for type string, not for types derived
+from it.</li>
+<li>Type information is missing for the C parts of the runtime library.</li>
+<li>GDB does not understand Go’s name qualifications and treats
+<code>"fmt.Print"</code> as an unstructured literal with a <code>"."</code>
+that needs to be quoted. It objects even more strongly to method names of
+the form <code>pkg.(*MyType).Meth</code>.
+<li>All global variables are lumped into package <code>"main"</code>.</li>
+</ol>
+
+<h2 id="Tutorial">Tutorial</h2>
+
+<p>
+In this tutorial we will inspect the binary of the
+<a href="/pkg/regexp/">regexp</a> package's unit tests. To build the binary,
+change to <code>$GOROOT/src/pkg/regexp</code> and run <code>gotest</code>.
+This should produce an executable file named <code>6.out</code>.
+</p>
+
+
+<h3 id="Getting_Started">Getting Started</h3>
+
+<p>
+Launch GDB, debugging <code>6.out</code>:
+</p>
+
+<pre>
+$ <b>gdb 6.out</b>
+GNU gdb (GDB) 7.2-gg8
+Copyright (C) 2010 Free Software Foundation, Inc.
+License GPLv 3+: GNU GPL version 3 or later &lt;http://gnu.org/licenses/gpl.html&gt;
+Type "show copying" and "show warranty" for licensing/warranty details.
+This GDB was configured as "x86_64-linux".
+
+Reading symbols from /home/user/go/src/pkg/regexp/6.out...
+done.
+Loading Go Runtime support.
+(gdb)
+</pre>
+
+<p>
+The message <code>"Loading Go Runtime support"</code> means that GDB loaded the
+extension from <code>$GOROOT/src/pkg/runtime/runtime-gdb.py</code>.
+</p>
+
+<p>
+To help GDB find the Go runtime sources and the accompanying support script,
+pass your <code>$GOROOT</code> with the <code>'-d'</code> flag:
+</p>
+
+<pre>
+$ <b>gdb 6.out -d $GOROOT</b>
+</pre>
+
+<p>
+If for some reason GDB still can't find that directory or that script, you can load
+it by hand by telling gdb (assuming you have the go sources in
+<code>~/go/</code>):
+<p>
+
+<pre>
+(gdb) <b>source ~/go/src/pkg/runtime/runtime-gdb.py</b>
+Loading Go Runtime support.
+</pre>
+
+<h3 id="Inspecting_the_source">Inspecting the source</h3>
+
+<p>
+Use the <code>"l"</code> or <code>"list"</code> command to inspect source code.
+</p>
+
+<pre>
+(gdb) <b>l</b>
+</pre>
+
+<p>
+List a specific part of the source parametrizing <code>"list"</code> with a
+function name (it must be qualified with its package name).
+</p>
+
+<pre>
+(gdb) <b>l main.main</b>
+</pre>
+
+<p>
+List a specific file and line number:
+</p>
+
+<pre>
+(gdb) <b>l regexp.go:1</b>
+(gdb) <i># Hit enter to repeat last command. Here, this lists next 10 lines.</i>
+</pre>
+
+
+<h3 id="Naming">Naming</h3>
+
+<p>
+Variable and function names must be qualified with the name of the packages
+they belong to. The <code>Compile</code> function from the <code>regexp</code>
+package is known to GDB as <code>'regexp.Compile'</code>.
+</p>
+
+<p>
+Methods must be qualified with the name of their receiver types. For example,
+the <code>*Regexp</code> type’s <code>doParse</code> method is known as
+<code>'regexp.*Regexp.doParse'</code>. (Note that the second dot is a "middot,"
+an artifact of Go’s internal representation of methods.)
+</p>
+
+<p>
+Variables that shadow other variables are magically suffixed with a number in the debug info.
+Variables referenced by closures will appear as pointers magically prefixed with '&amp'.
+</p>
+
+<h3 id="Setting_breakpoints">Setting breakpoints</h3>
+
+<p>
+Set a breakpoint at the <code>TestFind</code> function:
+</p>
+
+<pre>
+(gdb) <b>b 'regexp.TestFind'</b>
+Breakpoint 1 at 0x424908: file /home/user/go/src/pkg/regexp/find_test.go, line 148.
+</pre>
+
+<p>
+Run the program:
+</p>
+
+<pre>
+(gdb) <b>run</b>
+Starting program: /home/lvd/g/src/pkg/regexp/6.out
+
+Breakpoint 1, regexp.TestFind (t=0xf8404a89c0) at /home/user/go/src/pkg/regexp/find_test.go:148
+148 func TestFind(t *testing.T) {
+</pre>
+
+<p>
+Execution has paused at the breakpoint.
+See which goroutines are running, and what they're doing:
+</p>
+
+<pre>
+(gdb) <b>info goroutines</b>
+ 1 waiting runtime.gosched
+* 13 running runtime.goexit
+</pre>
+
+<p>
+the one marked with the <code>*</code> is the current goroutine.
+</p>
+
+<h3 id="Inspecting_the_stack">Inspecting the stack</h3>
+
+<p>
+Look at the stack trace for where we’ve paused the program:
+</p>
+
+<pre>
+(gdb) <b>bt</b> <i># backtrace</i>
+#0 regexp.TestFind (t=0xf8404a89c0) at /home/user/go/src/pkg/regexp/find_test.go:148
+#1 0x000000000042f60b in testing.tRunner (t=0xf8404a89c0, test=0x573720) at /home/user/go/src/pkg/testing/testing.go:156
+#2 0x000000000040df64 in runtime.initdone () at /home/user/go/src/pkg/runtime/proc.c:242
+#3 0x000000f8404a89c0 in ?? ()
+#4 0x0000000000573720 in ?? ()
+#5 0x0000000000000000 in ?? ()
+</pre>
+
+<p>
+The other goroutine, number 1, is stuck in <code>runtime.gosched</code>, blocked on a channel receive:
+</p>
+
+<pre>
+(gdb) <b>goroutine 1 bt</b>
+#0 0x000000000040facb in runtime.gosched () at /home/lvd/g/src/pkg/runtime/proc.c:873
+#1 0x00000000004031c9 in runtime.chanrecv (c=void, ep=void, selected=void, received=void)
+ at /home/lvd/g/src/pkg/runtime/chan.c:342
+#2 0x0000000000403299 in runtime.chanrecv1 (t=void, c=void) at/home/lvd/g/src/pkg/runtime/chan.c:423
+#3 0x000000000043075b in testing.RunTests (matchString={void (struct string, struct string, bool *, os.Error *)} 0x7ffff7f9ef60, tests= []testing.InternalTest = {...}) at /home/lvd/g/src/pkg/testing/testing.go:201
+#4 0x00000000004302b1 in testing.Main (matchString={void (struct string, struct string, bool *, os.Error *)} 0x7ffff7f9ef80, tests= []testing.InternalTest = {...}, benchmarks= []testing.InternalBenchmark = {...})
+ at /home/lvd/g/src/pkg/testing/testing.go:168
+#5 0x0000000000400dc1 in main.main () at /home/lvd/g/src/pkg/regexp/_testmain.go:98
+#6 0x00000000004022e7 in runtime.mainstart () at /home/lvd/g/src/pkg/runtime/amd64/asm.s:78
+#7 0x000000000040ea6f in runtime.initdone () at /home/lvd/g/src/pkg/runtime/proc.c:243
+#8 0x0000000000000000 in ?? ()
+</pre>
+
+<p>
+The stack frame shows we’re currently executing the <code>regexp.TestFind</code> function, as expected.
+</p>
+
+<pre>
+(gdb) <b>info frame</b>
+Stack level 0, frame at 0x7ffff7f9ff88:
+ rip = 0x425530 in regexp.TestFind (/home/lvd/g/src/pkg/regexp/find_test.go:148);
+ saved rip 0x430233
+ called by frame at 0x7ffff7f9ffa8
+ source language minimal.
+ Arglist at 0x7ffff7f9ff78, args: t=0xf840688b60
+ Locals at 0x7ffff7f9ff78, Previous frame's sp is 0x7ffff7f9ff88
+ Saved registers:
+ rip at 0x7ffff7f9ff80
+</pre>
+
+<p>
+The command <code>info locals</code> lists all variables local to the function and their values, but is a bit
+dangerous to use, since it will also try to print uninitialized variables. Uninitialized slices may cause gdb to try
+to print arbitrary large arrays.
+</p>
+
+<p>
+The function’s arguments:
+</p>
+
+<pre>
+(gdb) <b>info args</b>
+t = 0xf840688b60
+</pre>
+
+<p>
+When printing the argument, notice that it’s a pointer to a
+<code>Regexp</code> value. Note that GDB has incorrectly put the <code>*</code>
+on the right-hand side of the type name and made up a 'struct' keyword, in traditional C style.
+</p>
+
+<pre>
+(gdb) <b>p re</b>
+(gdb) p t
+$1 = (struct testing.T *) 0xf840688b60
+(gdb) p t
+$1 = (struct testing.T *) 0xf840688b60
+(gdb) p *t
+$2 = {errors = "", failed = false, ch = 0xf8406f5690}
+(gdb) p *t->ch
+$3 = struct hchan<*testing.T>
+</pre>
+
+<p>
+That <code>struct hchan<*testing.T></code> is the runtime-internal represntation of a channel. It is currently empty, or gdb would have pretty-printed it's contents.
+</p>
+
+<p>
+Stepping forward:
+</p>
+
+<pre>
+(gdb) <b>n</b> <i># execute next line</i>
+149 for _, test := range findTests {
+(gdb) <i># enter is repeat</i>
+150 re := MustCompile(test.pat)
+(gdb) <b>p test.pat</b>
+$4 = ""
+(gdb) <b>p re</b>
+$5 = (struct regexp.Regexp *) 0xf84068d070
+(gdb) <b>p *re</b>
+$6 = {expr = "", prog = 0xf840688b80, prefix = "", prefixBytes = []uint8, prefixComplete = true,
+ prefixRune = 0, cond = 0 '\000', numSubexp = 0, longest = false, mu = {state = 0, sema = 0},
+ machine = []*regexp.machine}
+(gdb) <b>p *re->prog</b>
+$7 = {Inst = []regexp/syntax.Inst = {{Op = 5 '\005', Out = 0, Arg = 0, Rune = []int}, {Op =
+ 6 '\006', Out = 2, Arg = 0, Rune = []int}, {Op = 4 '\004', Out = 0, Arg = 0, Rune = []int}},
+ Start = 1, NumCap = 2}
+</pre>
+
+
+<p>
+We can step into the <code>String</code>function call with <code>"s"</code>:
+</p>
+
+<pre>
+(gdb) <b>s</b>
+regexp.(*Regexp).String (re=0xf84068d070, noname=void) at /home/lvd/g/src/pkg/regexp/regexp.go:97
+97 func (re *Regexp) String() string {
+</pre>
+
+<p>
+Get a stack trace to see where we are:
+</p>
+
+<pre>
+(gdb) <b>bt</b>
+(gdb) bt
+#0 regexp.(*Regexp).String (re=0xf84068d070, noname=void)
+ at /home/lvd/g/src/pkg/regexp/regexp.go:97
+#1 0x0000000000425615 in regexp.TestFind (t=0xf840688b60)
+ at /home/lvd/g/src/pkg/regexp/find_test.go:151
+#2 0x0000000000430233 in testing.tRunner (t=0xf840688b60, test=0x5747b8)
+ at /home/lvd/g/src/pkg/testing/testing.go:156
+#3 0x000000000040ea6f in runtime.initdone () at /home/lvd/g/src/pkg/runtime/proc.c:243
+....
+</pre>
+
+<p>
+Look at the source code:
+</p>
+
+<pre>
+(gdb) <b>l</b>
+92 mu sync.Mutex
+93 machine []*machine
+94 }
+95
+96 // String returns the source text used to compile the regular expression.
+97 func (re *Regexp) String() string {
+98 return re.expr
+99 }
+100
+101 // Compile parses a regular expression and returns, if successful,
+</pre>
+
+<h3 id="Pretty_Printing">Pretty Printing</h3>
+
+<p>
+GDB's pretty printing mechanism is triggered by regexp matches on type names. An example for slices:
+</p>
+
+<pre>
+(gdb) <b>p utf</b>
+$22 = []uint8 = {0 '\000', 0 '\000', 0 '\000', 0 '\000'}
+</pre>
+
+<p>
+Since slices, arrays and strings are not C pointers, GDB can't interpret the subscripting operation for you, but
+you can look inside the runtime representation to do that (tab completion helps here):
+</p>
+<pre>
+
+(gdb) <b>p slc</b>
+$11 = []int = {0, 0}
+(gdb) <b>p slc-&gt</b><i>&ltTAB&gt</i>
+array slc len
+(gdb) <b>p slc->array</b>
+$12 = (int *) 0xf84057af00
+(gdb) <b>p slc->array[1]</b>
+$13 = 0</pre>
+
+
+
+<p>
+The extension functions $len and $cap work on strings, arrays and slices:
+</p>
+
+<pre>
+(gdb) <b>p $len(utf)</b>
+$23 = 4
+(gdb) <b>p $cap(utf)</b>
+$24 = 4
+</pre>
+
+<p>
+Channels and maps are 'reference' types, which gdb shows as pointers to C++-like types <code>hash&ltint,string&gt*</code>. Dereferencing will trigger prettyprinting
+</p>
+
+<p>
+Interfaces are represented in the runtime as a pointer to a type descriptor and a pointer to a value. The Go GDB runtime extension decodes this and automatically triggers pretty printing for the runtime type. The extension function <code>$dtype</code> decodes the dynamic type for you (examples are taken from a breakpoint at <code>regexp.go</code> line 293.)
+</p>
+
+<pre>
+(gdb) <b>p i</b>
+$4 = {str = "cbb"}
+(gdb) <b>whatis i</b>
+type = regexp.input
+(gdb) <b>p $dtype(i)</b>
+$26 = (struct regexp.inputBytes *) 0xf8400b4930
+(gdb) <b>iface i</b>
+regexp.input: struct regexp.inputBytes *
+</pre>
diff --git a/doc/devel/release.html b/doc/devel/release.html
index 4ce3d37c1..d6de1d71c 100644
--- a/doc/devel/release.html
+++ b/doc/devel/release.html
@@ -104,6 +104,12 @@ a new
option</a>.
</p>
+<p>
+r60.2
+<a href="http://code.google.com/p/go/source/detail?r=ff19536042ac">fixes</a>
+a memory leak involving maps.
+</p>
+
<h2 id="r59">r59 (released 2011/08/01)</h2>
<p>
diff --git a/doc/docs.html b/doc/docs.html
index ce833fdd1..a86d1714e 100644
--- a/doc/docs.html
+++ b/doc/docs.html
@@ -16,6 +16,16 @@ Once you've learned a little about the language,
idioms of programming in Go.
</p>
+<h3 id="go_tour"><a href="http://go-tour.appspot.com/">A Tour of Go</a></h3>
+<p>
+An interactive introduction to Go in three sections.
+The first section covers basic syntax and data structures; the second discusses
+methods and interfaces; and the third introduces Go's concurrency primitives.
+Each section concludes with a few exercises so you can practice what you've
+learned. You can <a href="http://go-tour.appspot.com/">take the tour online</a> or
+<a href="http://code.google.com/p/go-tour/">install it locally</a>.
+</p>
+
<h3 id="orig_tutorial"><a href="go_tutorial.html">A Tutorial for the Go Programming Language</a></h3>
<p>
The first tutorial. An introductory text that touches upon several core
@@ -97,6 +107,8 @@ Notable articles from the <a href="http://blog.golang.org/">Go Blog</a>.
<li><a href="http://blog.golang.org/2011/01/json-and-go.html">JSON and Go</a> - using the <a href="/pkg/json/">json</a> package.</li>
<li><a href="http://blog.golang.org/2011/03/gobs-of-data.html">Gobs of data</a> - the design and use of the <a href="/pkg/gob/">gob</a> package.</li>
<li><a href="http://blog.golang.org/2011/09/laws-of-reflection.html">The Laws of Reflection</a> - the fundamentals of the <a href="/pkg/reflect/">reflect</a> package.</li>
+<li><a href="http://blog.golang.org/2011/09/go-image-package.html">The Go image package</a> - the fundamentals of the <a href="/pkg/image/">image</a> package.</li>
+<li><a href="http://blog.golang.org/2011/09/go-imagedraw-package.html">The Go image/draw package</a> - the fundamentals of the <a href="/pkg/image/draw/">image/draw</a> package.</li>
</ul>
<h3>Tools</h3>
@@ -179,6 +191,11 @@ one goroutine can be guaranteed to observe values produced by writes to the
same variable in a different goroutine.
</p>
+<h3 id="debugging_with_gdb"><a href="debugging_with_gdb.html">Debugging Go Code with GDB</a></h3>
+<p>
+Using GDB to debug Go programs.
+</p>
+
<h2 id="videos_talks">Videos and Talks</h2>
<h3 id="writing_web_apps"><a href="http://www.youtube.com/watch?v=-i0hat7pdpk">Writing Web Apps in Go</a></h3>
diff --git a/doc/go_tutorial.html b/doc/go_tutorial.html
index 0b366bb2b..8f6e07b06 100644
--- a/doc/go_tutorial.html
+++ b/doc/go_tutorial.html
@@ -95,7 +95,7 @@ Here's how to compile and run our program. With <code>6g</code>, say,
<pre>
$ 6g helloworld.go # compile; object goes into helloworld.6
$ 6l helloworld.6 # link; output goes into 6.out
-$ 6.out
+$ ./6.out
Hello, world; or Καλημέρα κόσμε; or こんにちは 世界
$
</pre>
@@ -544,13 +544,12 @@ composite literal, as is done here in the <code>return</code> statement from <co
<p>
We can use the factory to construct some familiar, exported variables of type <code>*File</code>:
<p>
-<pre><!--{{code "progs/file.go" `/var/` `/^.$/`}}
+<pre><!--{{code "progs/file.go" `/var/` `/^\)/`}}
-->var (
Stdin = newFile(syscall.Stdin, &#34;/dev/stdin&#34;)
Stdout = newFile(syscall.Stdout, &#34;/dev/stdout&#34;)
Stderr = newFile(syscall.Stderr, &#34;/dev/stderr&#34;)
)
-
</pre>
<p>
The <code>newFile</code> function was not exported because it's internal. The proper,
diff --git a/doc/go_tutorial.tmpl b/doc/go_tutorial.tmpl
index c170c25aa..15f87ca4b 100644
--- a/doc/go_tutorial.tmpl
+++ b/doc/go_tutorial.tmpl
@@ -87,7 +87,7 @@ Here's how to compile and run our program. With <code>6g</code>, say,
<pre>
$ 6g helloworld.go # compile; object goes into helloworld.6
$ 6l helloworld.6 # link; output goes into 6.out
-$ 6.out
+$ ./6.out
Hello, world; or Καλημέρα κόσμε; or こんにちは 世界
$
</pre>
@@ -470,7 +470,7 @@ composite literal, as is done here in the <code>return</code> statement from <co
<p>
We can use the factory to construct some familiar, exported variables of type <code>*File</code>:
<p>
-{{code "progs/file.go" `/var/` `/^.$/`}}
+{{code "progs/file.go" `/var/` `/^\)/`}}
<p>
The <code>newFile</code> function was not exported because it's internal. The proper,
exported factory to use is <code>OpenFile</code> (we'll explain that name in a moment):
diff --git a/doc/install.html b/doc/install.html
index a1bc89982..c47f9218b 100644
--- a/doc/install.html
+++ b/doc/install.html
@@ -257,7 +257,8 @@ the process of building and testing Go programs.
<h2 id="next">What's next</h2>
<p>
-Start by reading the <a href="go_tutorial.html">Go Tutorial</a>.
+Start by taking <a href="http://code.google.com/p/go-tour/">A Tour of Go</a>
+or reading the <a href="go_tutorial.html">Go Tutorial</a>.
</p>
<p>
diff --git a/doc/root.html b/doc/root.html
index 8d76928c8..2d9a8979b 100644
--- a/doc/root.html
+++ b/doc/root.html
@@ -49,10 +49,13 @@ google.setOnLoadCallback(loadFeed);
It's a fast, statically typed, compiled language that feels like a
dynamically typed, interpreted language.
</p>
- <h2>Check it out!</h2>
+ <h2>
+ Get started now with
+ <a target="_blank" href="http://go-tour.appspot.com/">A Tour of Go</a>.
+ </h2>
<p>
<div class="how">[<a href="/doc/playground.html">How does this work?</a>]</div>
- <a href="/doc/install.html">Install Go now</a>, or try it right here in your browser:</p>
+ Or try it right here in your browser:</p>
<div id="playground" class="small"></div>
<script src="/doc/play/playground.js"></script>
</div>
diff --git a/src/cmd/ld/dwarf.c b/src/cmd/ld/dwarf.c
index 77536018a..373cf5523 100644
--- a/src/cmd/ld/dwarf.c
+++ b/src/cmd/ld/dwarf.c
@@ -1356,7 +1356,7 @@ synthesizemaptypes(DWDie *die)
getattr(keytype, DW_AT_name)->data,
getattr(valtype, DW_AT_name)->data));
copychildren(dwhs, hash_subtable);
- substitutetype(dwhs, "end", defptrto(dwhe));
+ substitutetype(dwhs, "last", defptrto(dwhe));
substitutetype(dwhs, "entry", dwhe); // todo: []hash_entry with dynamic size
newattr(dwhs, DW_AT_byte_size, DW_CLS_CONSTANT,
getattr(hash_subtable, DW_AT_byte_size)->value, nil);
diff --git a/src/pkg/image/draw/draw.go b/src/pkg/image/draw/draw.go
index a748ff8c7..5171e03b1 100644
--- a/src/pkg/image/draw/draw.go
+++ b/src/pkg/image/draw/draw.go
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Package draw provides image composition functions
-// in the style of the Plan 9 graphics library
-// (see http://plan9.bell-labs.com/magic/man2html/2/draw)
-// and the X Render extension.
+// Package draw provides image composition functions.
+//
+// See "The Go image/draw package" for an introduction to this package:
+// http://blog.golang.org/2011/09/go-imagedraw-package.html
package draw
import (
diff --git a/src/pkg/image/image.go b/src/pkg/image/image.go
index 11def9435..7c7a4b7a7 100644
--- a/src/pkg/image/image.go
+++ b/src/pkg/image/image.go
@@ -3,6 +3,9 @@
// license that can be found in the LICENSE file.
// Package image implements a basic 2-D image library.
+//
+// See "The Go image package" for an introduction to this package:
+// http://blog.golang.org/2011/09/go-image-package.html
package image
// Config holds an image's color model and dimensions.
diff --git a/src/pkg/runtime/hashmap.c b/src/pkg/runtime/hashmap.c
index 0c0e3e4a2..22664b548 100644
--- a/src/pkg/runtime/hashmap.c
+++ b/src/pkg/runtime/hashmap.c
@@ -54,7 +54,7 @@ struct hash_subtable {
uint8 datasize; /* bytes of client data in an entry */
uint8 max_probes; /* max number of probes when searching */
int16 limit_bytes; /* max_probes * (datasize+sizeof (hash_hash_t)) */
- struct hash_entry *end; /* points just past end of entry[] */
+ struct hash_entry *last; /* points to last element of entry[] */
struct hash_entry entry[1]; /* 2**power+max_probes-1 elements of elemsize bytes */
};
@@ -101,7 +101,7 @@ hash_subtable_new (Hmap *h, int32 power, int32 used)
st->datasize = h->datasize;
st->max_probes = max_probes;
st->limit_bytes = limit_bytes;
- st->end = HASH_OFFSET (st->entry, bytes);
+ st->last = HASH_OFFSET (st->entry, bytes) - 1;
memset (st->entry, HASH_NIL_MEMSET, bytes);
return (st);
}
@@ -160,7 +160,7 @@ hash_remove_n (struct hash_subtable *st, struct hash_entry *dst_e, int32 n)
{
int32 elemsize = st->datasize + offsetof (struct hash_entry, data[0]);
struct hash_entry *src_e = HASH_OFFSET (dst_e, n * elemsize);
- struct hash_entry *end_e = st->end;
+ struct hash_entry *last_e = st->last;
int32 shift = HASH_BITS - (st->power + st->used);
int32 index_mask = (((hash_hash_t)1) << st->power) - 1;
int32 dst_i = (((byte *) dst_e) - ((byte *) st->entry)) / elemsize;
@@ -170,10 +170,10 @@ hash_remove_n (struct hash_subtable *st, struct hash_entry *dst_e, int32 n)
int32 bytes;
while (dst_e != src_e) {
- if (src_e != end_e) {
+ if (src_e <= last_e) {
struct hash_entry *cp_e = src_e;
int32 save_dst_i = dst_i;
- while (cp_e != end_e && (hash = cp_e->hash) != HASH_NIL &&
+ while (cp_e <= last_e && (hash = cp_e->hash) != HASH_NIL &&
((hash >> shift) & index_mask) <= dst_i) {
cp_e = HASH_OFFSET (cp_e, elemsize);
dst_i++;
@@ -183,7 +183,7 @@ hash_remove_n (struct hash_subtable *st, struct hash_entry *dst_e, int32 n)
dst_e = HASH_OFFSET (dst_e, bytes);
src_e = cp_e;
src_i += dst_i - save_dst_i;
- if (src_e != end_e && (hash = src_e->hash) != HASH_NIL) {
+ if (src_e <= last_e && (hash = src_e->hash) != HASH_NIL) {
skip = ((hash >> shift) & index_mask) - dst_i;
} else {
skip = src_i - dst_i;
@@ -224,7 +224,7 @@ hash_conv (Hmap *h,
}
de = e;
- while (e != st->end &&
+ while (e <= st->last &&
(e_hash = e->hash) != HASH_NIL &&
(e_hash & HASH_MASK) != HASH_SUBHASH) {
struct hash_entry *target_e = HASH_OFFSET (st->entry, ((e_hash >> shift) & index_mask) * elemsize);
@@ -235,14 +235,14 @@ hash_conv (Hmap *h,
de = target_e;
}
if ((hash & prefix_mask) == current ||
- (ne != st->end && (e_hash = ne->hash) != HASH_NIL &&
+ (ne <= st->last && (e_hash = ne->hash) != HASH_NIL &&
(e_hash & prefix_mask) == current)) {
struct hash_subtable *new_st = hash_subtable_new (h, 1, HASH_USED (new_flags));
int32 rc = hash_insert_internal (&new_st, new_flags, e->hash, h, e->data, &dummy_result);
assert (rc == 0);
memcpy(dummy_result, e->data, h->datasize);
e = ne;
- while (e != st->end && (e_hash = e->hash) != HASH_NIL && (e_hash & prefix_mask) == current) {
+ while (e <= st->last && (e_hash = e->hash) != HASH_NIL && (e_hash & prefix_mask) == current) {
assert ((e_hash & HASH_MASK) != HASH_SUBHASH);
rc = hash_insert_internal (&new_st, new_flags, e_hash, h, e->data, &dummy_result);
assert (rc == 0);
@@ -271,13 +271,13 @@ hash_grow (Hmap *h, struct hash_subtable **pst, int32 flags)
struct hash_subtable *old_st = *pst;
int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]);
*pst = hash_subtable_new (h, old_st->power + 1, HASH_USED (flags));
- struct hash_entry *end_e = old_st->end;
+ struct hash_entry *last_e = old_st->last;
struct hash_entry *e;
void *dummy_result;
int32 used = 0;
flags |= HASH_REHASH;
- for (e = old_st->entry; e != end_e; e = HASH_OFFSET (e, elemsize)) {
+ for (e = old_st->entry; e <= last_e; e = HASH_OFFSET (e, elemsize)) {
hash_hash_t hash = e->hash;
if (hash != HASH_NIL) {
int32 rc = hash_insert_internal (pst, flags, e->hash, h, e->data, &dummy_result);
@@ -428,13 +428,13 @@ hash_insert_internal (struct hash_subtable **pst, int32 flags, hash_hash_t hash,
ins_e_hash = 0;
/* move ins_e to point at the end of the contiguous block, but
stop if any element can't be moved by one up */
- while (ins_e != st->end && (ins_e_hash = ins_e->hash) != HASH_NIL &&
+ while (ins_e <= st->last && (ins_e_hash = ins_e->hash) != HASH_NIL &&
ins_i + 1 - ((ins_e_hash >> shift) & index_mask) < st->max_probes &&
(ins_e_hash & HASH_MASK) != HASH_SUBHASH) {
ins_e = HASH_OFFSET (ins_e, elemsize);
ins_i++;
}
- if (e == end_e || ins_e == st->end || ins_e_hash != HASH_NIL) {
+ if (e == end_e || ins_e > st->last || ins_e_hash != HASH_NIL) {
e = end_e; /* can't insert; must grow or convert to subtable */
} else { /* make space for element */
memmove (HASH_OFFSET (e, elemsize), e, ((byte *) ins_e) - (byte *) e);
@@ -477,17 +477,17 @@ iter_restart (struct hash_iter *it, struct hash_subtable *st, int32 used)
struct hash_entry *e;
hash_hash_t e_hash;
struct hash_iter_sub *sub = &it->subtable_state[it->i];
- struct hash_entry *end;
+ struct hash_entry *last;
for (;;) {
int32 shift = HASH_BITS - (st->power + used);
int32 index_mask = (1 << st->power) - 1;
int32 i = (last_hash >> shift) & index_mask;
- end = st->end;
+ last = st->last;
e = HASH_OFFSET (st->entry, i * elemsize);
sub->start = st->entry;
- sub->end = end;
+ sub->last = last;
if ((e->hash & HASH_MASK) != HASH_SUBHASH) {
break;
@@ -497,7 +497,7 @@ iter_restart (struct hash_iter *it, struct hash_subtable *st, int32 used)
used += st->power;
st = *(struct hash_subtable **)e->data;
}
- while (e != end && ((e_hash = e->hash) == HASH_NIL || e_hash <= last_hash)) {
+ while (e <= last && ((e_hash = e->hash) == HASH_NIL || e_hash <= last_hash)) {
e = HASH_OFFSET (e, elemsize);
}
sub->e = e;
@@ -509,7 +509,7 @@ hash_next (struct hash_iter *it)
int32 elemsize = it->elemsize;
struct hash_iter_sub *sub = &it->subtable_state[it->i];
struct hash_entry *e = sub->e;
- struct hash_entry *end = sub->end;
+ struct hash_entry *last = sub->last;
hash_hash_t e_hash = 0;
if (it->changes != it->h->changes) { /* hash table's structure changed; recompute */
@@ -518,7 +518,7 @@ hash_next (struct hash_iter *it)
iter_restart (it, it->h->st, 0);
sub = &it->subtable_state[it->i];
e = sub->e;
- end = sub->end;
+ last = sub->last;
}
if (e != sub->start && it->last_hash != HASH_OFFSET (e, -elemsize)->hash) {
struct hash_entry *start = HASH_OFFSET (e, -(elemsize * it->h->max_probes));
@@ -531,16 +531,16 @@ hash_next (struct hash_iter *it)
e = pe;
pe = HASH_OFFSET (pe, -elemsize);
}
- while (e != end && ((e_hash = e->hash) == HASH_NIL || e_hash <= last_hash)) {
+ while (e <= last && ((e_hash = e->hash) == HASH_NIL || e_hash <= last_hash)) {
e = HASH_OFFSET (e, elemsize);
}
}
for (;;) {
- while (e != end && (e_hash = e->hash) == HASH_NIL) {
+ while (e <= last && (e_hash = e->hash) == HASH_NIL) {
e = HASH_OFFSET (e, elemsize);
}
- if (e == end) {
+ if (e > last) {
if (it->i == 0) {
it->last_hash = HASH_OFFSET (e, -elemsize)->hash;
sub->e = e;
@@ -549,7 +549,7 @@ hash_next (struct hash_iter *it)
it->i--;
sub = &it->subtable_state[it->i];
e = sub->e;
- end = sub->end;
+ last = sub->last;
}
} else if ((e_hash & HASH_MASK) != HASH_SUBHASH) {
it->last_hash = e->hash;
@@ -565,7 +565,7 @@ hash_next (struct hash_iter *it)
sub = &it->subtable_state[it->i];
sub->e = e = st->entry;
sub->start = st->entry;
- sub->end = end = st->end;
+ sub->last = last = st->last;
}
}
}
@@ -580,7 +580,7 @@ hash_iter_init (Hmap *h, struct hash_iter *it)
it->last_hash = 0;
it->subtable_state[0].e = h->st->entry;
it->subtable_state[0].start = h->st->entry;
- it->subtable_state[0].end = h->st->end;
+ it->subtable_state[0].last = h->st->last;
}
static void
@@ -588,11 +588,11 @@ clean_st (struct hash_subtable *st, int32 *slots, int32 *used)
{
int32 elemsize = st->datasize + offsetof (struct hash_entry, data[0]);
struct hash_entry *e = st->entry;
- struct hash_entry *end = st->end;
- int32 lslots = (((byte *) end) - (byte *) e) / elemsize;
+ struct hash_entry *last = st->last;
+ int32 lslots = (((byte *) (last+1)) - (byte *) e) / elemsize;
int32 lused = 0;
- while (e != end) {
+ while (e <= last) {
hash_hash_t hash = e->hash;
if ((hash & HASH_MASK) == HASH_SUBHASH) {
clean_st (*(struct hash_subtable **)e->data, slots, used);
@@ -627,7 +627,7 @@ hash_visit_internal (struct hash_subtable *st,
int32 shift = HASH_BITS - (used + st->power);
int32 i = 0;
- while (e != st->end) {
+ while (e <= st->last) {
int32 index = ((e->hash >> (shift - 1)) >> 1) & ((1 << st->power) - 1);
if ((e->hash & HASH_MASK) == HASH_SUBHASH) {
(*data_visit) (arg, level, e->data);
diff --git a/src/pkg/runtime/hashmap.h b/src/pkg/runtime/hashmap.h
index 19ff41697..81b0cff88 100644
--- a/src/pkg/runtime/hashmap.h
+++ b/src/pkg/runtime/hashmap.h
@@ -87,7 +87,7 @@ struct hash_iter {
struct hash_iter_sub {
struct hash_entry *e; /* pointer into subtable */
struct hash_entry *start; /* start of subtable */
- struct hash_entry *end; /* end of subtable */
+ struct hash_entry *last; /* last entry in subtable */
} subtable_state[4]; /* Should be large enough unless the hashing is
so bad that many distinct data values hash
to the same hash value. */
diff --git a/src/pkg/runtime/runtime-gdb.py b/src/pkg/runtime/runtime-gdb.py
index a96f3f382..b74705e5f 100644
--- a/src/pkg/runtime/runtime-gdb.py
+++ b/src/pkg/runtime/runtime-gdb.py
@@ -91,8 +91,8 @@ class MapTypePrinter:
def traverse_hash(self, stab):
ptr = stab['entry'].address
- end = stab['end']
- while ptr < end:
+ last = stab['last']
+ while ptr <= last:
v = ptr.dereference()
ptr = ptr + 1
if v['hash'] == 0: continue