aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/builtin/builtin.go6
-rw-r--r--src/bytes/buffer.go15
-rw-r--r--src/bytes/bytes.go37
-rw-r--r--src/bytes/bytes_test.go6
-rw-r--r--src/cmd/asm/internal/asm/testdata/386.s2
-rw-r--r--src/cmd/asm/internal/asm/testdata/arm64.s1
-rw-r--r--src/cmd/asm/internal/asm/testdata/arm64enc.s4
-rw-r--r--src/cmd/asm/internal/asm/testdata/arm64error.s36
-rw-r--r--src/cmd/asm/internal/asm/testdata/ppc64.s2
-rw-r--r--src/cmd/compile/fmt_test.go1
-rw-r--r--src/cmd/compile/internal/amd64/ssa.go28
-rw-r--r--src/cmd/compile/internal/arm/ssa.go49
-rw-r--r--src/cmd/compile/internal/arm64/ssa.go20
-rw-r--r--src/cmd/compile/internal/gc/bexport.go1744
-rw-r--r--src/cmd/compile/internal/gc/bimport.go1323
-rw-r--r--src/cmd/compile/internal/gc/const.go15
-rw-r--r--src/cmd/compile/internal/gc/dump.go287
-rw-r--r--src/cmd/compile/internal/gc/esc.go126
-rw-r--r--src/cmd/compile/internal/gc/export.go10
-rw-r--r--src/cmd/compile/internal/gc/float_test.go14
-rw-r--r--src/cmd/compile/internal/gc/fmt.go45
-rw-r--r--src/cmd/compile/internal/gc/inl.go4
-rw-r--r--src/cmd/compile/internal/gc/main.go24
-rw-r--r--src/cmd/compile/internal/gc/mpfloat.go45
-rw-r--r--src/cmd/compile/internal/gc/mpint.go11
-rw-r--r--src/cmd/compile/internal/gc/obj.go5
-rw-r--r--src/cmd/compile/internal/gc/op_string.go4
-rw-r--r--src/cmd/compile/internal/gc/order.go12
-rw-r--r--src/cmd/compile/internal/gc/pgen.go20
-rw-r--r--src/cmd/compile/internal/gc/plive.go235
-rw-r--r--src/cmd/compile/internal/gc/sinit.go18
-rw-r--r--src/cmd/compile/internal/gc/ssa.go94
-rw-r--r--src/cmd/compile/internal/gc/subr.go33
-rw-r--r--src/cmd/compile/internal/gc/syntax.go1
-rw-r--r--src/cmd/compile/internal/gc/typecheck.go49
-rw-r--r--src/cmd/compile/internal/gc/walk.go6
-rw-r--r--src/cmd/compile/internal/ppc64/ssa.go35
-rw-r--r--src/cmd/compile/internal/ssa/gen/386.rules12
-rw-r--r--src/cmd/compile/internal/ssa/gen/AMD64.rules84
-rw-r--r--src/cmd/compile/internal/ssa/gen/AMD64Ops.go30
-rw-r--r--src/cmd/compile/internal/ssa/gen/ARM64.rules202
-rw-r--r--src/cmd/compile/internal/ssa/gen/ARM64Ops.go18
-rw-r--r--src/cmd/compile/internal/ssa/gen/PPC64.rules135
-rw-r--r--src/cmd/compile/internal/ssa/gen/PPC64Ops.go30
-rw-r--r--src/cmd/compile/internal/ssa/gen/Wasm.rules4
-rw-r--r--src/cmd/compile/internal/ssa/gen/generic.rules158
-rw-r--r--src/cmd/compile/internal/ssa/gen/genericOps.go5
-rw-r--r--src/cmd/compile/internal/ssa/gen/main.go9
-rw-r--r--src/cmd/compile/internal/ssa/html.go2
-rw-r--r--src/cmd/compile/internal/ssa/op.go12
-rw-r--r--src/cmd/compile/internal/ssa/opGen.go798
-rw-r--r--src/cmd/compile/internal/ssa/prove.go4
-rw-r--r--src/cmd/compile/internal/ssa/regalloc.go2
-rw-r--r--src/cmd/compile/internal/ssa/rewrite.go40
-rw-r--r--src/cmd/compile/internal/ssa/rewrite386.go104
-rw-r--r--src/cmd/compile/internal/ssa/rewriteAMD64.go2057
-rw-r--r--src/cmd/compile/internal/ssa/rewriteARM64.go5943
-rw-r--r--src/cmd/compile/internal/ssa/rewritePPC64.go3362
-rw-r--r--src/cmd/compile/internal/ssa/rewriteWasm.go8
-rw-r--r--src/cmd/compile/internal/ssa/rewritegeneric.go434
-rw-r--r--src/cmd/compile/internal/ssa/softfloat.go2
-rw-r--r--src/cmd/compile/internal/ssa/stmtlines_test.go3
-rw-r--r--src/cmd/compile/internal/ssa/testdata/hist.gdb-opt.nexts20
-rw-r--r--src/cmd/compile/internal/types/type.go2
-rw-r--r--src/cmd/compile/internal/x86/ssa.go26
-rw-r--r--src/cmd/dist/build.go4
-rw-r--r--src/cmd/dist/buildruntime.go4
-rw-r--r--src/cmd/dist/main.go3
-rw-r--r--src/cmd/dist/test.go4
-rw-r--r--src/cmd/fix/main.go2
-rw-r--r--src/cmd/fix/typecheck.go4
-rw-r--r--src/cmd/go/alldocs.go8
-rw-r--r--src/cmd/go/go_test.go55
-rw-r--r--src/cmd/go/internal/clean/clean.go14
-rw-r--r--src/cmd/go/internal/envcmd/env.go2
-rw-r--r--src/cmd/go/internal/get/vcs.go2
-rw-r--r--src/cmd/go/internal/help/helpdoc.go6
-rw-r--r--src/cmd/go/internal/modconv/convert_test.go2
-rw-r--r--src/cmd/go/internal/modfetch/codehost/codehost.go2
-rw-r--r--src/cmd/go/internal/modfetch/coderepo_test.go16
-rw-r--r--src/cmd/go/internal/modfetch/fetch.go2
-rw-r--r--src/cmd/go/internal/modfetch/proxy.go2
-rw-r--r--src/cmd/go/internal/modload/build.go18
-rw-r--r--src/cmd/go/internal/modload/import.go5
-rw-r--r--src/cmd/go/internal/modload/import_test.go2
-rw-r--r--src/cmd/go/internal/modload/query.go4
-rw-r--r--src/cmd/go/internal/modload/query_test.go2
-rw-r--r--src/cmd/go/internal/search/search.go4
-rw-r--r--src/cmd/go/internal/work/build.go6
-rw-r--r--src/cmd/go/internal/work/buildid.go8
-rw-r--r--src/cmd/go/internal/work/exec.go10
-rw-r--r--src/cmd/go/internal/work/security.go4
-rw-r--r--src/cmd/go/main.go18
-rw-r--r--src/cmd/go/proxy_test.go4
-rw-r--r--src/cmd/go/script_test.go12
-rw-r--r--src/cmd/go/testdata/addmod.go2
-rw-r--r--src/cmd/go/testdata/script/help.txt5
-rw-r--r--src/cmd/go/testdata/script/list_bad_import.txt2
-rw-r--r--src/cmd/go/testdata/script/mod_clean_cache.txt23
-rw-r--r--src/cmd/go/testdata/script/mod_help.txt6
-rw-r--r--src/cmd/go/testdata/script/mod_list_bad_import.txt2
-rw-r--r--src/cmd/go/testdata/script/mod_string_alias.txt14
-rw-r--r--src/cmd/go/testdata/script/mod_test.txt7
-rw-r--r--src/cmd/go/vendor_test.go2
-rw-r--r--src/cmd/gofmt/gofmt_test.go2
-rw-r--r--src/cmd/internal/dwarf/dwarf.go13
-rw-r--r--src/cmd/internal/goobj/read.go2
-rw-r--r--src/cmd/internal/obj/arm/asm5.go2
-rw-r--r--src/cmd/internal/obj/arm64/asm7.go72
-rw-r--r--src/cmd/internal/obj/link.go7
-rw-r--r--src/cmd/internal/objabi/funcdata.go1
-rw-r--r--src/cmd/internal/objabi/funcid.go2
-rw-r--r--src/cmd/internal/objabi/head.go5
-rw-r--r--src/cmd/link/dwarf_test.go3
-rw-r--r--src/cmd/link/internal/ld/dwarf.go155
-rw-r--r--src/cmd/link/internal/ld/dwarf_test.go114
-rw-r--r--src/cmd/link/internal/ld/lib.go73
-rw-r--r--src/cmd/link/internal/ld/pcln.go97
-rw-r--r--src/cmd/link/internal/ld/util.go10
-rw-r--r--src/cmd/link/internal/objfile/objfile.go2
-rw-r--r--src/cmd/link/internal/ppc64/asm.go12
-rw-r--r--src/cmd/trace/trace.go12
-rw-r--r--src/cmd/vendor/golang.org/x/sys/windows/aliases.go13
-rw-r--r--src/cmd/vendor/golang.org/x/sys/windows/asm_windows_arm.s11
-rw-r--r--src/cmd/vendor/golang.org/x/sys/windows/registry/zsyscall_windows.go2
-rw-r--r--src/cmd/vendor/golang.org/x/sys/windows/security_windows.go4
-rw-r--r--src/cmd/vendor/golang.org/x/sys/windows/service.go18
-rw-r--r--src/cmd/vendor/golang.org/x/sys/windows/svc/mgr/config.go38
-rw-r--r--src/cmd/vendor/golang.org/x/sys/windows/svc/mgr/mgr_test.go113
-rw-r--r--src/cmd/vendor/golang.org/x/sys/windows/svc/mgr/recovery.go135
-rw-r--r--src/cmd/vendor/golang.org/x/sys/windows/svc/sys_arm.s38
-rw-r--r--src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go60
-rw-r--r--src/cmd/vendor/golang.org/x/sys/windows/syscall_windows_test.go6
-rw-r--r--src/cmd/vendor/golang.org/x/sys/windows/types_windows.go176
-rw-r--r--src/cmd/vendor/golang.org/x/sys/windows/types_windows_arm.go22
-rw-r--r--src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go2
-rw-r--r--src/cmd/vendor/vendor.json32
-rw-r--r--src/cmd/vet/all/main.go12
-rw-r--r--src/cmd/vet/all/whitelist/all.txt1
-rw-r--r--src/cmd/vet/all/whitelist/windows_386.txt1
-rw-r--r--src/cmd/vet/all/whitelist/windows_amd64.txt1
-rw-r--r--src/cmd/vet/main.go3
-rw-r--r--src/cmd/vet/shadow.go9
-rw-r--r--src/cmd/vet/testdata/shadow.go32
-rw-r--r--src/cmd/vet/types.go24
-rw-r--r--src/cmd/vet/vet_test.go2
-rw-r--r--src/compress/bzip2/bzip2_test.go4
-rw-r--r--src/compress/bzip2/testdata/Isaac.Newton-Opticks.txt.bz2bin0 -> 132469 bytes
-rw-r--r--src/compress/bzip2/testdata/Mark.Twain-Tom.Sawyer.txt.bz2bin118509 -> 0 bytes
-rw-r--r--src/compress/flate/deflate_test.go8
-rw-r--r--src/compress/flate/reader_test.go4
-rw-r--r--src/compress/testdata/Mark.Twain-Tom.Sawyer.txt8465
-rw-r--r--src/compress/zlib/writer.go12
-rw-r--r--src/context/context.go2
-rw-r--r--src/crypto/cipher/benchmark_test.go67
-rw-r--r--src/crypto/md5/md5block_386.s2
-rw-r--r--src/crypto/md5/md5block_amd64.s4
-rw-r--r--src/crypto/md5/md5block_amd64p32.s4
-rw-r--r--src/crypto/rand/rand.go4
-rw-r--r--src/crypto/rand/rand_unix.go8
-rw-r--r--src/crypto/rand/rand_windows.go9
-rw-r--r--src/crypto/rsa/pss_test.go2
-rw-r--r--src/crypto/sha1/sha1block_386.s8
-rw-r--r--src/crypto/sha1/sha1block_amd64.s10
-rw-r--r--src/crypto/sha1/sha1block_amd64p32.s10
-rw-r--r--src/crypto/sha1/sha1block_arm.s10
-rw-r--r--src/crypto/x509/cert_pool.go2
-rw-r--r--src/crypto/x509/root_darwin_arm_gen.go6
-rw-r--r--src/crypto/x509/verify.go4
-rw-r--r--src/crypto/x509/verify_test.go1
-rw-r--r--src/database/sql/driver/driver.go2
-rw-r--r--src/database/sql/sql.go10
-rw-r--r--src/database/sql/sql_test.go52
-rw-r--r--src/debug/elf/elf.go2
-rw-r--r--src/encoding/base32/base32_test.go10
-rw-r--r--src/encoding/base64/base64_test.go8
-rw-r--r--src/encoding/json/decode.go133
-rw-r--r--src/encoding/json/decode_test.go19
-rw-r--r--src/flag/flag.go2
-rw-r--r--src/fmt/example_test.go335
-rw-r--r--src/fmt/fmt_test.go7
-rw-r--r--src/fmt/print.go10
-rw-r--r--src/go/build/build.go10
-rw-r--r--src/go/build/deps_test.go3
-rw-r--r--src/go/build/doc.go3
-rw-r--r--src/go/build/gc.go120
-rw-r--r--src/go/build/gccgo.go6
-rw-r--r--src/go/build/syslist.go2
-rw-r--r--src/go/constant/value_test.go2
-rw-r--r--src/go/doc/doc_test.go6
-rw-r--r--src/go/internal/gccgoimporter/importer_test.go4
-rw-r--r--src/go/internal/gccgoimporter/parser.go227
-rw-r--r--src/go/internal/gccgoimporter/testdata/alias.gox4
-rw-r--r--src/go/internal/gccgoimporter/testdata/aliases.go65
-rw-r--r--src/go/internal/gccgoimporter/testdata/aliases.gox33
-rw-r--r--src/go/internal/gccgoimporter/testdata/issue27856.go9
-rw-r--r--src/go/internal/gccgoimporter/testdata/issue27856.gox9
-rw-r--r--src/go/printer/example_test.go4
-rw-r--r--src/go/token/position.go17
-rw-r--r--src/go/token/position_test.go15
-rw-r--r--src/go/types/api.go4
-rw-r--r--src/go/types/decl.go14
-rw-r--r--src/go/types/example_test.go21
-rw-r--r--src/go/types/expr.go2
-rw-r--r--src/go/types/scope.go10
-rw-r--r--src/go/types/sizes.go3
-rw-r--r--src/go/types/testdata/cycles5.src21
-rw-r--r--src/go/types/testdata/decls0.src10
-rw-r--r--src/go/types/typexpr.go20
-rw-r--r--src/html/template/js.go2
-rw-r--r--src/html/template/url.go2
-rw-r--r--src/image/draw/draw.go122
-rw-r--r--src/image/format.go13
-rw-r--r--src/image/image.go149
-rw-r--r--src/image/image_test.go214
-rw-r--r--src/image/png/reader_test.go4
-rw-r--r--src/image/png/writer.go90
-rw-r--r--src/image/png/writer_test.go112
-rw-r--r--src/internal/bytealg/compare_amd64.s2
-rw-r--r--src/internal/bytealg/compare_amd64p32.s2
-rw-r--r--src/internal/bytealg/count_generic.go2
-rw-r--r--src/internal/bytealg/count_native.go2
-rw-r--r--src/internal/bytealg/count_ppc64x.s97
-rw-r--r--src/internal/bytealg/equal_amd64.s2
-rw-r--r--src/internal/bytealg/equal_amd64p32.s2
-rw-r--r--src/internal/bytealg/equal_arm.s2
-rw-r--r--src/internal/bytealg/equal_arm64.s44
-rw-r--r--src/internal/bytealg/indexbyte_ppc64x.s28
-rw-r--r--src/internal/goroot/gc.go140
-rw-r--r--src/internal/goroot/gccgo.go27
-rw-r--r--src/internal/poll/export_posix_test.go2
-rw-r--r--src/internal/poll/fd_poll_runtime.go2
-rw-r--r--src/internal/poll/fd_posix.go2
-rw-r--r--src/internal/poll/fd_posix_test.go2
-rw-r--r--src/internal/poll/fd_unix.go2
-rw-r--r--src/internal/poll/fd_windows.go155
-rw-r--r--src/internal/poll/hook_unix.go2
-rw-r--r--src/internal/poll/sockopt.go2
-rw-r--r--src/internal/poll/sockopt_unix.go2
-rw-r--r--src/internal/poll/sockoptip.go2
-rw-r--r--src/internal/poll/splice_linux.go17
-rw-r--r--src/internal/poll/sys_cloexec.go2
-rw-r--r--src/internal/syscall/unix/nonblocking.go2
-rw-r--r--src/io/io.go8
-rw-r--r--src/io/multi.go4
-rw-r--r--src/math/all_test.go38
-rw-r--r--src/math/big/arith_386.s2
-rw-r--r--src/math/big/arith_amd64.s6
-rw-r--r--src/math/big/arith_arm.s4
-rw-r--r--src/math/big/arith_s390x.s14
-rw-r--r--src/math/bits/bits.go194
-rw-r--r--src/math/bits/bits_test.go266
-rw-r--r--src/math/expm1_386.s4
-rw-r--r--src/math/sin_386.s2
-rw-r--r--src/math/sqrt_386.s2
-rw-r--r--src/math/sqrt_arm.s2
-rw-r--r--src/mime/mediatype.go2
-rw-r--r--src/mime/mediatype_test.go3
-rw-r--r--src/mime/multipart/formdata_test.go8
-rw-r--r--src/mime/multipart/multipart_test.go6
-rw-r--r--src/net/dnsclient.go7
-rw-r--r--src/net/dnsclient_unix.go115
-rw-r--r--src/net/dnsclient_unix_test.go196
-rw-r--r--src/net/dnsname_test.go1
-rw-r--r--src/net/http/cgi/child.go2
-rw-r--r--src/net/http/client.go2
-rw-r--r--src/net/http/clientserver_test.go30
-rw-r--r--src/net/http/cookie.go4
-rw-r--r--src/net/http/example_handle_test.go29
-rw-r--r--src/net/http/example_test.go18
-rw-r--r--src/net/http/export_test.go6
-rw-r--r--src/net/http/header.go40
-rw-r--r--src/net/http/http.go4
-rw-r--r--src/net/http/httputil/dump_test.go2
-rw-r--r--src/net/http/proxy_test.go2
-rw-r--r--src/net/http/readrequest_test.go2
-rw-r--r--src/net/http/request.go28
-rw-r--r--src/net/http/request_test.go6
-rw-r--r--src/net/http/roundtrip_js.go4
-rw-r--r--src/net/http/serve_test.go11
-rw-r--r--src/net/http/server.go28
-rw-r--r--src/net/http/transport.go49
-rw-r--r--src/net/http/transport_internal_test.go83
-rw-r--r--src/net/http/transport_test.go4
-rw-r--r--src/net/lookup_unix.go16
-rw-r--r--src/net/lookup_windows_test.go2
-rw-r--r--src/net/mail/message_test.go4
-rw-r--r--src/net/net_windows_test.go2
-rw-r--r--src/net/sendfile_test.go22
-rw-r--r--src/net/splice_linux.go5
-rw-r--r--src/net/splice_test.go52
-rw-r--r--src/net/testdata/Mark.Twain-Tom.Sawyer.txt8465
-rw-r--r--src/net/textproto/reader_test.go44
-rw-r--r--src/net/unixsock_windows_test.go4
-rw-r--r--src/net/url/example_test.go2
-rw-r--r--src/net/url/url.go72
-rw-r--r--src/net/url/url_test.go120
-rw-r--r--src/os/example_test.go33
-rw-r--r--src/os/file.go18
-rw-r--r--src/os/os_test.go14
-rw-r--r--src/os/os_unix_test.go2
-rw-r--r--src/os/os_windows_test.go62
-rw-r--r--src/os/path_windows_test.go6
-rw-r--r--src/os/stat_test.go276
-rw-r--r--src/os/types.go2
-rw-r--r--src/os/types_windows.go8
-rw-r--r--src/os/user/lookup.go4
-rw-r--r--src/os/user/lookup_stubs.go11
-rw-r--r--src/os/user/user_test.go18
-rw-r--r--src/path/filepath/path.go15
-rw-r--r--src/path/filepath/path_test.go19
-rw-r--r--src/path/filepath/path_windows.go2
-rw-r--r--src/path/filepath/path_windows_test.go2
-rw-r--r--src/path/filepath/symlink.go191
-rw-r--r--src/reflect/all_test.go7
-rw-r--r--src/reflect/asm_386.s10
-rw-r--r--src/reflect/asm_amd64.s10
-rw-r--r--src/reflect/asm_amd64p32.s10
-rw-r--r--src/reflect/asm_arm.s12
-rw-r--r--src/reflect/asm_arm64.s10
-rw-r--r--src/reflect/asm_mips64x.s10
-rw-r--r--src/reflect/asm_mipsx.s10
-rw-r--r--src/reflect/asm_ppc64x.s10
-rw-r--r--src/reflect/asm_s390x.s10
-rw-r--r--src/reflect/asm_wasm.s10
-rw-r--r--src/reflect/example_test.go18
-rw-r--r--src/reflect/export_test.go4
-rw-r--r--src/reflect/makefunc.go27
-rw-r--r--src/reflect/type.go16
-rw-r--r--src/reflect/value.go92
-rw-r--r--src/regexp/regexp.go2
-rw-r--r--src/runtime/asm_386.s84
-rw-r--r--src/runtime/asm_amd64.s26
-rw-r--r--src/runtime/asm_amd64p32.s4
-rw-r--r--src/runtime/asm_arm.s12
-rw-r--r--src/runtime/asm_ppc64x.s39
-rw-r--r--src/runtime/cgo/asm_amd64.s6
-rw-r--r--src/runtime/cgo/asm_arm.s2
-rw-r--r--src/runtime/cgo/signal_darwin_arm64.s2
-rw-r--r--src/runtime/cgocheck.go2
-rw-r--r--src/runtime/chan.go28
-rw-r--r--src/runtime/crash_test.go2
-rw-r--r--src/runtime/crash_unix_test.go2
-rw-r--r--src/runtime/debug_test.go33
-rw-r--r--src/runtime/defs2_linux.go5
-rw-r--r--src/runtime/defs_aix.go170
-rw-r--r--src/runtime/defs_aix_ppc64.go203
-rw-r--r--src/runtime/defs_linux.go5
-rw-r--r--src/runtime/defs_linux_386.go1
-rw-r--r--src/runtime/defs_linux_amd64.go1
-rw-r--r--src/runtime/defs_linux_arm.go1
-rw-r--r--src/runtime/defs_linux_arm64.go1
-rw-r--r--src/runtime/defs_linux_mips64x.go1
-rw-r--r--src/runtime/defs_linux_mipsx.go1
-rw-r--r--src/runtime/defs_linux_ppc64.go1
-rw-r--r--src/runtime/defs_linux_ppc64le.go1
-rw-r--r--src/runtime/defs_linux_s390x.go1
-rw-r--r--src/runtime/defs_windows_386.go3
-rw-r--r--src/runtime/defs_windows_amd64.go3
-rw-r--r--src/runtime/defs_windows_arm.go149
-rw-r--r--src/runtime/env_posix.go2
-rw-r--r--src/runtime/export_unix_test.go2
-rw-r--r--src/runtime/extern.go8
-rw-r--r--src/runtime/funcdata.h1
-rw-r--r--src/runtime/gc_test.go7
-rw-r--r--src/runtime/gcinfo_test.go48
-rw-r--r--src/runtime/heapdump.go10
-rw-r--r--src/runtime/internal/sys/zgoos_aix.go21
-rw-r--r--src/runtime/internal/sys/zgoos_android.go1
-rw-r--r--src/runtime/internal/sys/zgoos_darwin.go1
-rw-r--r--src/runtime/internal/sys/zgoos_dragonfly.go1
-rw-r--r--src/runtime/internal/sys/zgoos_freebsd.go1
-rw-r--r--src/runtime/internal/sys/zgoos_linux.go1
-rw-r--r--src/runtime/internal/sys/zgoos_nacl.go1
-rw-r--r--src/runtime/internal/sys/zgoos_netbsd.go1
-rw-r--r--src/runtime/internal/sys/zgoos_openbsd.go1
-rw-r--r--src/runtime/internal/sys/zgoos_plan9.go1
-rw-r--r--src/runtime/internal/sys/zgoos_solaris.go1
-rw-r--r--src/runtime/internal/sys/zgoos_windows.go1
-rw-r--r--src/runtime/internal/sys/zgoos_zos.go1
-rw-r--r--src/runtime/lock_sema.go2
-rw-r--r--src/runtime/malloc.go29
-rw-r--r--src/runtime/mbarrier.go13
-rw-r--r--src/runtime/mbitmap.go24
-rw-r--r--src/runtime/mcache.go57
-rw-r--r--src/runtime/mcentral.go55
-rw-r--r--src/runtime/mem_aix.go (renamed from src/runtime/mem_darwin.go)42
-rw-r--r--src/runtime/mem_bsd.go2
-rw-r--r--src/runtime/mem_linux.go13
-rw-r--r--src/runtime/memmove_amd64p32.s2
-rw-r--r--src/runtime/memmove_arm.s2
-rw-r--r--src/runtime/memmove_plan9_386.s2
-rw-r--r--src/runtime/memmove_plan9_amd64.s2
-rw-r--r--src/runtime/mgc.go580
-rw-r--r--src/runtime/mgcmark.go332
-rw-r--r--src/runtime/mgcstack.go330
-rw-r--r--src/runtime/mgcsweep.go34
-rw-r--r--src/runtime/mgcwork.go103
-rw-r--r--src/runtime/mheap.go73
-rw-r--r--src/runtime/mmap.go1
-rw-r--r--src/runtime/mprof.go2
-rw-r--r--src/runtime/mstats.go2
-rw-r--r--src/runtime/mwbbuf.go12
-rw-r--r--src/runtime/netpoll.go6
-rw-r--r--src/runtime/netpoll_aix.go247
-rw-r--r--src/runtime/os2_aix.go479
-rw-r--r--src/runtime/os_aix.go262
-rw-r--r--src/runtime/os_darwin.go11
-rw-r--r--src/runtime/os_nacl.go12
-rw-r--r--src/runtime/os_netbsd.go31
-rw-r--r--src/runtime/os_windows.go45
-rw-r--r--src/runtime/os_windows_arm.go18
-rw-r--r--src/runtime/pprof/internal/profile/profile.go2
-rw-r--r--src/runtime/pprof/pprof_test.go2
-rw-r--r--src/runtime/pprof/proto.go8
-rw-r--r--src/runtime/pprof/proto_test.go95
-rw-r--r--src/runtime/proc.go168
-rw-r--r--src/runtime/race/testdata/chan_test.go30
-rw-r--r--src/runtime/rt0_aix_ppc64.s40
-rw-r--r--src/runtime/rt0_linux_ppc64le.s2
-rw-r--r--src/runtime/rt0_nacl_amd64p32.s2
-rw-r--r--src/runtime/rt0_windows_arm.s12
-rw-r--r--src/runtime/runtime-gdb_test.go27
-rw-r--r--src/runtime/runtime1.go6
-rw-r--r--src/runtime/runtime2.go21
-rw-r--r--src/runtime/runtime_unix_test.go2
-rw-r--r--src/runtime/select.go4
-rw-r--r--src/runtime/semasleep_test.go88
-rw-r--r--src/runtime/signal_aix_ppc64.go85
-rw-r--r--src/runtime/signal_ppc64x.go2
-rw-r--r--src/runtime/signal_sighandler.go2
-rw-r--r--src/runtime/signal_unix.go2
-rw-r--r--src/runtime/signal_windows.go10
-rw-r--r--src/runtime/sigtab_aix.go264
-rw-r--r--src/runtime/stack.go79
-rw-r--r--src/runtime/stubs2.go4
-rw-r--r--src/runtime/stubs3.go1
-rw-r--r--src/runtime/symtab.go5
-rw-r--r--src/runtime/sys_aix_ppc64.s201
-rw-r--r--src/runtime/sys_darwin.go2
-rw-r--r--src/runtime/sys_dragonfly_amd64.s8
-rw-r--r--src/runtime/sys_freebsd_386.s8
-rw-r--r--src/runtime/sys_freebsd_amd64.s6
-rw-r--r--src/runtime/sys_freebsd_arm.s15
-rw-r--r--src/runtime/sys_linux_386.s13
-rw-r--r--src/runtime/sys_linux_amd64.s16
-rw-r--r--src/runtime/sys_linux_arm.s14
-rw-r--r--src/runtime/sys_linux_arm64.s14
-rw-r--r--src/runtime/sys_linux_mips64x.s14
-rw-r--r--src/runtime/sys_linux_mipsx.s16
-rw-r--r--src/runtime/sys_linux_ppc64x.s13
-rw-r--r--src/runtime/sys_linux_s390x.s14
-rw-r--r--src/runtime/sys_nacl_386.s8
-rw-r--r--src/runtime/sys_nacl_amd64p32.s4
-rw-r--r--src/runtime/sys_netbsd_386.s4
-rw-r--r--src/runtime/sys_netbsd_amd64.s6
-rw-r--r--src/runtime/sys_netbsd_arm.s11
-rw-r--r--src/runtime/sys_openbsd_386.s5
-rw-r--r--src/runtime/sys_openbsd_amd64.s4
-rw-r--r--src/runtime/sys_openbsd_arm.s4
-rw-r--r--src/runtime/sys_plan9_386.s2
-rw-r--r--src/runtime/sys_plan9_amd64.s2
-rw-r--r--src/runtime/sys_solaris_amd64.s8
-rw-r--r--src/runtime/sys_windows_386.s8
-rw-r--r--src/runtime/sys_windows_amd64.s2
-rw-r--r--src/runtime/sys_windows_arm.s605
-rw-r--r--src/runtime/syscall_windows.go24
-rw-r--r--src/runtime/testdata/testprogcgo/exec.go16
-rw-r--r--src/runtime/timestub2.go1
-rw-r--r--src/runtime/tls_arm.s43
-rw-r--r--src/runtime/traceback.go34
-rw-r--r--src/runtime/vlop_arm.s2
-rw-r--r--src/runtime/wincallback.go42
-rw-r--r--src/runtime/zcallback_windows.go2
-rw-r--r--src/runtime/zcallback_windows.s4
-rw-r--r--src/runtime/zcallback_windows_arm.s4012
-rw-r--r--src/strings/example_test.go2
-rw-r--r--src/strings/replace.go8
-rw-r--r--src/strings/strings.go75
-rw-r--r--src/strings/strings_test.go10
-rw-r--r--src/sync/map.go12
-rw-r--r--src/syscall/asm_nacl_386.s2
-rw-r--r--src/syscall/asm_nacl_amd64p32.s2
-rw-r--r--src/syscall/asm_nacl_arm.s2
-rw-r--r--src/syscall/asm_plan9_386.s20
-rw-r--r--src/syscall/asm_plan9_amd64.s20
-rw-r--r--src/syscall/syscall_linux_386.go15
-rw-r--r--src/syscall/syscall_linux_amd64.go10
-rw-r--r--src/syscall/syscall_linux_arm.go15
-rw-r--r--src/syscall/syscall_linux_test.go3
-rw-r--r--src/syscall/zsyscall_linux_386.go45
-rw-r--r--src/syscall/zsyscall_linux_amd64.go30
-rw-r--r--src/syscall/zsyscall_linux_arm.go45
-rw-r--r--src/testdata/Isaac.Newton-Opticks.txt9286
-rw-r--r--src/testing/sub_test.go4
-rw-r--r--src/text/template/exec.go2
-rw-r--r--src/time/zoneinfo.go11
-rw-r--r--src/time/zoneinfo_android.go3
-rw-r--r--src/time/zoneinfo_read.go2
-rw-r--r--src/time/zoneinfo_test.go11
500 files changed, 37047 insertions, 24118 deletions
diff --git a/src/builtin/builtin.go b/src/builtin/builtin.go
index 4578c855a9..c78fe09ea6 100644
--- a/src/builtin/builtin.go
+++ b/src/builtin/builtin.go
@@ -152,6 +152,9 @@ func delete(m map[Type]Type1, key Type)
// String: the number of bytes in v.
// Channel: the number of elements queued (unread) in the channel buffer;
// if v is nil, len(v) is zero.
+// For some arguments, such as a string literal or a simple array expression, the
+// result can be a constant. See the Go language specification's "Length and
+// capacity" section for details.
func len(v Type) int
// The cap built-in function returns the capacity of v, according to its type:
@@ -161,6 +164,9 @@ func len(v Type) int
// if v is nil, cap(v) is zero.
// Channel: the channel buffer capacity, in units of elements;
// if v is nil, cap(v) is zero.
+// For some arguments, such as a simple array expression, the result can be a
+// constant. See the Go language specification's "Length and capacity" section for
+// details.
func cap(v Type) int
// The make built-in function allocates and initializes an object of type
diff --git a/src/bytes/buffer.go b/src/bytes/buffer.go
index 14c5bc38d6..087cc0e427 100644
--- a/src/bytes/buffer.go
+++ b/src/bytes/buffer.go
@@ -12,13 +12,15 @@ import (
"unicode/utf8"
)
+// smallBufferSize is an initial allocation minimal capacity.
+const smallBufferSize = 64
+
// A Buffer is a variable-sized buffer of bytes with Read and Write methods.
// The zero value for Buffer is an empty buffer ready to use.
type Buffer struct {
- buf []byte // contents are the bytes buf[off : len(buf)]
- off int // read at &buf[off], write at &buf[len(buf)]
- bootstrap [64]byte // memory to hold first slice; helps small buffers avoid allocation.
- lastRead readOp // last read operation, so that Unread* can work correctly.
+ buf []byte // contents are the bytes buf[off : len(buf)]
+ off int // read at &buf[off], write at &buf[len(buf)]
+ lastRead readOp // last read operation, so that Unread* can work correctly.
// FIXME: it would be advisable to align Buffer to cachelines to avoid false
// sharing.
@@ -125,9 +127,8 @@ func (b *Buffer) grow(n int) int {
if i, ok := b.tryGrowByReslice(n); ok {
return i
}
- // Check if we can make use of bootstrap array.
- if b.buf == nil && n <= len(b.bootstrap) {
- b.buf = b.bootstrap[:n]
+ if b.buf == nil && n <= smallBufferSize {
+ b.buf = make([]byte, n, smallBufferSize)
return 0
}
c := cap(b.buf)
diff --git a/src/bytes/bytes.go b/src/bytes/bytes.go
index 77a7ce98e0..6492db088a 100644
--- a/src/bytes/bytes.go
+++ b/src/bytes/bytes.go
@@ -774,6 +774,15 @@ func Replace(s, old, new []byte, n int) []byte {
return t[0:w]
}
+// ReplaceAll returns a copy of the slice s with all
+// non-overlapping instances of old replaced by new.
+// If old is empty, it matches at the beginning of the slice
+// and after each UTF-8 sequence, yielding up to k+1 replacements
+// for a k-rune slice.
+func ReplaceAll(s, old, new []byte) []byte {
+ return Replace(s, old, new, -1)
+}
+
// EqualFold reports whether s and t, interpreted as UTF-8 strings,
// are equal under Unicode case-folding.
func EqualFold(s, t []byte) bool {
@@ -849,21 +858,22 @@ func Index(s, sep []byte) int {
if len(s) <= bytealg.MaxBruteForce {
return bytealg.Index(s, sep)
}
- c := sep[0]
+ c0 := sep[0]
+ c1 := sep[1]
i := 0
- t := s[:len(s)-n+1]
+ t := len(s) - n + 1
fails := 0
- for i < len(t) {
- if t[i] != c {
+ for i < t {
+ if s[i] != c0 {
// IndexByte is faster than bytealg.Index, so use it as long as
// we're not getting lots of false positives.
- o := IndexByte(t[i:], c)
+ o := IndexByte(s[i:t], c0)
if o < 0 {
return -1
}
i += o
}
- if Equal(s[i:i+n], sep) {
+ if s[i+1] == c1 && Equal(s[i:i+n], sep) {
return i
}
fails++
@@ -879,24 +889,25 @@ func Index(s, sep []byte) int {
}
return -1
}
- c := sep[0]
+ c0 := sep[0]
+ c1 := sep[1]
i := 0
fails := 0
- t := s[:len(s)-n+1]
- for i < len(t) {
- if t[i] != c {
- o := IndexByte(t[i:], c)
+ t := len(s) - n + 1
+ for i < t {
+ if s[i] != c0 {
+ o := IndexByte(s[i:t], c0)
if o < 0 {
break
}
i += o
}
- if Equal(s[i:i+n], sep) {
+ if s[i+1] == c1 && Equal(s[i:i+n], sep) {
return i
}
i++
fails++
- if fails >= 4+i>>4 && i < len(t) {
+ if fails >= 4+i>>4 && i < t {
// Give up on IndexByte, it isn't skipping ahead
// far enough to be better than Rabin-Karp.
// Experiments (using IndexPeriodic) suggest
diff --git a/src/bytes/bytes_test.go b/src/bytes/bytes_test.go
index 55a22bae22..f4c0ffd2a9 100644
--- a/src/bytes/bytes_test.go
+++ b/src/bytes/bytes_test.go
@@ -1362,6 +1362,12 @@ func TestReplace(t *testing.T) {
if cap(in) == cap(out) && &in[:1][0] == &out[:1][0] {
t.Errorf("Replace(%q, %q, %q, %d) didn't copy", tt.in, tt.old, tt.new, tt.n)
}
+ if tt.n == -1 {
+ out := ReplaceAll(in, []byte(tt.old), []byte(tt.new))
+ if s := string(out); s != tt.out {
+ t.Errorf("ReplaceAll(%q, %q, %q) = %q, want %q", tt.in, tt.old, tt.new, s, tt.out)
+ }
+ }
}
}
diff --git a/src/cmd/asm/internal/asm/testdata/386.s b/src/cmd/asm/internal/asm/testdata/386.s
index 90a66167a1..d524a4c8c1 100644
--- a/src/cmd/asm/internal/asm/testdata/386.s
+++ b/src/cmd/asm/internal/asm/testdata/386.s
@@ -70,7 +70,7 @@ label:
// LTYPEM spec6 { outcode(int($1), &$2); }
MOVL AX, BX
MOVL $4, BX
-
+
// LTYPEI spec7 { outcode(int($1), &$2); }
IMULL AX
IMULL $4, CX
diff --git a/src/cmd/asm/internal/asm/testdata/arm64.s b/src/cmd/asm/internal/asm/testdata/arm64.s
index 361b7a45c0..9e2e2b1dc5 100644
--- a/src/cmd/asm/internal/asm/testdata/arm64.s
+++ b/src/cmd/asm/internal/asm/testdata/arm64.s
@@ -654,6 +654,7 @@ again:
CALL foo(SB)
// LDP/STP
+ LDP (R0), (R0, R1) // 000440a9
LDP (R0), (R1, R2) // 010840a9
LDP 8(R0), (R1, R2) // 018840a9
LDP -8(R0), (R1, R2) // 01887fa9
diff --git a/src/cmd/asm/internal/asm/testdata/arm64enc.s b/src/cmd/asm/internal/asm/testdata/arm64enc.s
index ee4673c1ae..432ab74493 100644
--- a/src/cmd/asm/internal/asm/testdata/arm64enc.s
+++ b/src/cmd/asm/internal/asm/testdata/arm64enc.s
@@ -188,8 +188,8 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
MOVBU (R18)(R14<<0), R23 // 577a6e38
MOVBU (R2)(R8.SXTX), R19 // 53e86838
MOVBU (R27)(R23), R14 // MOVBU (R27)(R23*1), R14 // 6e6b7738
- MOVHU.P 107(R13), R13 // adb54678
- MOVHU.W 192(R2), R2 // 420c4c78
+ MOVHU.P 107(R14), R13 // cdb54678
+ MOVHU.W 192(R3), R2 // 620c4c78
MOVHU 6844(R4), R18 // 92787579
MOVHU (R5)(R25.SXTW), R15 // afc87978
//TODO MOVBW.P 77(R18), R11 // 4bd6c438
diff --git a/src/cmd/asm/internal/asm/testdata/arm64error.s b/src/cmd/asm/internal/asm/testdata/arm64error.s
index b2ec0cc425..357db80222 100644
--- a/src/cmd/asm/internal/asm/testdata/arm64error.s
+++ b/src/cmd/asm/internal/asm/testdata/arm64error.s
@@ -8,7 +8,19 @@ TEXT errors(SB),$0
ADDSW R7->32, R14, R13 // ERROR "shift amount out of range 0 to 31"
ADD R1.UXTB<<5, R2, R3 // ERROR "shift amount out of range 0 to 4"
ADDS R1.UXTX<<7, R2, R3 // ERROR "shift amount out of range 0 to 4"
+ AND $0x22220000, R2, RSP // ERROR "illegal combination"
+ ANDS $0x22220000, R2, RSP // ERROR "illegal combination"
+ ADD R1, R2, R3, R4 // ERROR "illegal combination"
BICW R7@>33, R5, R16 // ERROR "shift amount out of range 0 to 31"
+ CINC CS, R2, R3, R4 // ERROR "illegal combination"
+ CSEL LT, R1, R2 // ERROR "illegal combination"
+ LDP.P 8(R2), (R2, R3) // ERROR "constrained unpredictable behavior"
+ LDP.W 8(R3), (R2, R3) // ERROR "constrained unpredictable behavior"
+ LDP (R1), (R2, R2) // ERROR "constrained unpredictable behavior"
+ LDP (R0), (F0, F1) // ERROR "invalid register pair"
+ LDP (R0), (R3, ZR) // ERROR "invalid register pair"
+ LDXPW (RSP), (R2, R2) // ERROR "constrained unpredictable behavior"
+ LDAXPW (R5), (R2, R2) // ERROR "constrained unpredictable behavior"
MOVD.P 300(R2), R3 // ERROR "offset out of range [-255,254]"
MOVD.P R3, 344(R2) // ERROR "offset out of range [-255,254]"
MOVD (R3)(R7.SXTX<<2), R8 // ERROR "invalid index shift amount"
@@ -16,6 +28,17 @@ TEXT errors(SB),$0
MOVWU (R5)(R4<<1), R10 // ERROR "invalid index shift amount"
MOVB (R5)(R4.SXTW<<5), R10 // ERROR "invalid index shift amount"
MOVH R5, (R6)(R2<<3) // ERROR "invalid index shift amount"
+ MADD R1, R2, R3 // ERROR "illegal combination"
+ MOVD.P R1, 8(R1) // ERROR "constrained unpredictable behavior"
+ MOVD.W 16(R2), R2 // ERROR "constrained unpredictable behavior"
+ STP (F2, F3), (R0) // ERROR "invalid register pair"
+ STP.W (R1, R2), 8(R1) // ERROR "constrained unpredictable behavior"
+ STP.P (R1, R2), 8(R2) // ERROR "constrained unpredictable behavior"
+ STLXP (R6, R11), (RSP), R6 // ERROR "constrained unpredictable behavior"
+ STXP (R6, R11), (R2), R2 // ERROR "constrained unpredictable behavior"
+ STLXR R3, (RSP), R3 // ERROR "constrained unpredictable behavior"
+ STXR R3, (R4), R4 // ERROR "constrained unpredictable behavior"
+ STLXRB R2, (R5), R5 // ERROR "constrained unpredictable behavior"
VLD1 (R8)(R13), [V2.B16] // ERROR "illegal combination"
VLD1 8(R9), [V2.B16] // ERROR "illegal combination"
VST1 [V1.B16], (R8)(R13) // ERROR "illegal combination"
@@ -83,15 +106,10 @@ TEXT errors(SB),$0
VST1.P [V1.B16], (R8)(R9<<1) // ERROR "invalid extended register"
VREV64 V1.H4, V2.H8 // ERROR "invalid arrangement"
VREV64 V1.D1, V2.D1 // ERROR "invalid arrangement"
- ADD R1, R2, R3, R4 // ERROR "illegal combination"
- MADD R1, R2, R3 // ERROR "illegal combination"
- CINC CS, R2, R3, R4 // ERROR "illegal combination"
- CSEL LT, R1, R2 // ERROR "illegal combination"
- AND $0x22220000, R2, RSP // ERROR "illegal combination"
- ANDS $0x22220000, R2, RSP // ERROR "illegal combination"
- LDP (R0), (F0, F1) // ERROR "invalid register pair"
- LDP (R0), (R3, ZR) // ERROR "invalid register pair"
- STP (F2, F3), (R0) // ERROR "invalid register pair"
FLDPD (R0), (R1, R2) // ERROR "invalid register pair"
+ FLDPD (R1), (F2, F2) // ERROR "constrained unpredictable behavior"
+ FLDPS (R2), (F3, F3) // ERROR "constrained unpredictable behavior"
FSTPD (R1, R2), (R0) // ERROR "invalid register pair"
+ FMOVS (F2), F0 // ERROR "illegal combination"
+ FMOVD F0, (F1) // ERROR "illegal combination"
RET
diff --git a/src/cmd/asm/internal/asm/testdata/ppc64.s b/src/cmd/asm/internal/asm/testdata/ppc64.s
index ba00b8f6e2..9e8929dac4 100644
--- a/src/cmd/asm/internal/asm/testdata/ppc64.s
+++ b/src/cmd/asm/internal/asm/testdata/ppc64.s
@@ -550,7 +550,7 @@ label1:
// ftsqrt BF, FRB
FTSQRT F2,$7
-// FCFID
+// FCFID
// FCFIDS
FCFID F2,F3
diff --git a/src/cmd/compile/fmt_test.go b/src/cmd/compile/fmt_test.go
index e28e428a17..65f88dfff9 100644
--- a/src/cmd/compile/fmt_test.go
+++ b/src/cmd/compile/fmt_test.go
@@ -700,6 +700,7 @@ var knownFormats = map[string]string{
"int8 %x": "",
"interface{} %#v": "",
"interface{} %T": "",
+ "interface{} %p": "",
"interface{} %q": "",
"interface{} %s": "",
"interface{} %v": "",
diff --git a/src/cmd/compile/internal/amd64/ssa.go b/src/cmd/compile/internal/amd64/ssa.go
index ae6141dd12..b4c4b1f4cd 100644
--- a/src/cmd/compile/internal/amd64/ssa.go
+++ b/src/cmd/compile/internal/amd64/ssa.go
@@ -583,7 +583,11 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
p.From.Reg = v.Args[0].Reg()
p.To.Type = obj.TYPE_CONST
p.To.Offset = v.AuxInt
- case ssa.OpAMD64BTLconst, ssa.OpAMD64BTQconst:
+ case ssa.OpAMD64BTLconst, ssa.OpAMD64BTQconst,
+ ssa.OpAMD64TESTQconst, ssa.OpAMD64TESTLconst, ssa.OpAMD64TESTWconst, ssa.OpAMD64TESTBconst,
+ ssa.OpAMD64BTSLconst, ssa.OpAMD64BTSQconst,
+ ssa.OpAMD64BTCLconst, ssa.OpAMD64BTCQconst,
+ ssa.OpAMD64BTRLconst, ssa.OpAMD64BTRQconst:
op := v.Op
if op == ssa.OpAMD64BTQconst && v.AuxInt < 32 {
// Emit 32-bit version because it's shorter
@@ -594,15 +598,6 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
p.From.Offset = v.AuxInt
p.To.Type = obj.TYPE_REG
p.To.Reg = v.Args[0].Reg()
- case ssa.OpAMD64TESTQconst, ssa.OpAMD64TESTLconst, ssa.OpAMD64TESTWconst, ssa.OpAMD64TESTBconst,
- ssa.OpAMD64BTSLconst, ssa.OpAMD64BTSQconst,
- ssa.OpAMD64BTCLconst, ssa.OpAMD64BTCQconst,
- ssa.OpAMD64BTRLconst, ssa.OpAMD64BTRQconst:
- p := s.Prog(v.Op.Asm())
- p.From.Type = obj.TYPE_CONST
- p.From.Offset = v.AuxInt
- p.To.Type = obj.TYPE_REG
- p.To.Reg = v.Args[0].Reg()
case ssa.OpAMD64CMPQload, ssa.OpAMD64CMPLload, ssa.OpAMD64CMPWload, ssa.OpAMD64CMPBload:
p := s.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_MEM
@@ -700,6 +695,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg()
case ssa.OpAMD64MOVQstore, ssa.OpAMD64MOVSSstore, ssa.OpAMD64MOVSDstore, ssa.OpAMD64MOVLstore, ssa.OpAMD64MOVWstore, ssa.OpAMD64MOVBstore, ssa.OpAMD64MOVOstore,
+ ssa.OpAMD64BTCQmodify, ssa.OpAMD64BTCLmodify, ssa.OpAMD64BTRQmodify, ssa.OpAMD64BTRLmodify, ssa.OpAMD64BTSQmodify, ssa.OpAMD64BTSLmodify,
ssa.OpAMD64ADDQmodify, ssa.OpAMD64SUBQmodify, ssa.OpAMD64ANDQmodify, ssa.OpAMD64ORQmodify, ssa.OpAMD64XORQmodify,
ssa.OpAMD64ADDLmodify, ssa.OpAMD64SUBLmodify, ssa.OpAMD64ANDLmodify, ssa.OpAMD64ORLmodify, ssa.OpAMD64XORLmodify:
p := s.Prog(v.Op.Asm())
@@ -764,16 +760,12 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
p.To.Type = obj.TYPE_MEM
p.To.Reg = v.Args[0].Reg()
gc.AddAux2(&p.To, v, off)
- } else {
- p := s.Prog(v.Op.Asm())
- p.From.Type = obj.TYPE_CONST
- p.From.Offset = val
- p.To.Type = obj.TYPE_MEM
- p.To.Reg = v.Args[0].Reg()
- gc.AddAux2(&p.To, v, off)
+ break
}
+ fallthrough
case ssa.OpAMD64ANDQconstmodify, ssa.OpAMD64ANDLconstmodify, ssa.OpAMD64ORQconstmodify, ssa.OpAMD64ORLconstmodify,
- ssa.OpAMD64XORQconstmodify, ssa.OpAMD64XORLconstmodify:
+ ssa.OpAMD64BTCQconstmodify, ssa.OpAMD64BTCLconstmodify, ssa.OpAMD64BTSQconstmodify, ssa.OpAMD64BTSLconstmodify,
+ ssa.OpAMD64BTRQconstmodify, ssa.OpAMD64BTRLconstmodify, ssa.OpAMD64XORQconstmodify, ssa.OpAMD64XORLconstmodify:
sc := v.AuxValAndOff()
off := sc.Off()
val := sc.Val()
diff --git a/src/cmd/compile/internal/arm/ssa.go b/src/cmd/compile/internal/arm/ssa.go
index 98627344b8..9a8fabf622 100644
--- a/src/cmd/compile/internal/arm/ssa.go
+++ b/src/cmd/compile/internal/arm/ssa.go
@@ -7,6 +7,7 @@ package arm
import (
"fmt"
"math"
+ "math/bits"
"cmd/compile/internal/gc"
"cmd/compile/internal/ssa"
@@ -119,6 +120,28 @@ func genregshift(s *gc.SSAGenState, as obj.As, r0, r1, r2, r int16, typ int64) *
return p
}
+// find a (lsb, width) pair for BFC
+// lsb must be in [0, 31], width must be in [1, 32 - lsb]
+// return (0xffffffff, 0) if v is not a binary like 0...01...10...0
+func getBFC(v uint32) (uint32, uint32) {
+ var m, l uint32
+ // BFC is not applicable with zero
+ if v == 0 {
+ return 0xffffffff, 0
+ }
+ // find the lowest set bit, for example l=2 for 0x3ffffffc
+ l = uint32(bits.TrailingZeros32(v))
+ // m-1 represents the highest set bit index, for example m=30 for 0x3ffffffc
+ m = 32 - uint32(bits.LeadingZeros32(v))
+ // check if v is a binary like 0...01...10...0
+ if (1<<m)-(1<<l) == v {
+ // it must be m > l for non-zero v
+ return l, m - l
+ }
+ // invalid
+ return 0xffffffff, 0
+}
+
func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
switch v.Op {
case ssa.OpCopy, ssa.OpARMMOVWreg:
@@ -267,16 +290,38 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
p.Reg = v.Args[0].Reg()
p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg()
+ case ssa.OpARMANDconst, ssa.OpARMBICconst:
+ // try to optimize ANDconst and BICconst to BFC, which saves bytes and ticks
+ // BFC is only available on ARMv7, and its result and source are in the same register
+ if objabi.GOARM == 7 && v.Reg() == v.Args[0].Reg() {
+ var val uint32
+ if v.Op == ssa.OpARMANDconst {
+ val = ^uint32(v.AuxInt)
+ } else { // BICconst
+ val = uint32(v.AuxInt)
+ }
+ lsb, width := getBFC(val)
+ // omit BFC for ARM's imm12
+ if 8 < width && width < 24 {
+ p := s.Prog(arm.ABFC)
+ p.From.Type = obj.TYPE_CONST
+ p.From.Offset = int64(width)
+ p.SetFrom3(obj.Addr{Type: obj.TYPE_CONST, Offset: int64(lsb)})
+ p.To.Type = obj.TYPE_REG
+ p.To.Reg = v.Reg()
+ break
+ }
+ }
+ // fall back to ordinary form
+ fallthrough
case ssa.OpARMADDconst,
ssa.OpARMADCconst,
ssa.OpARMSUBconst,
ssa.OpARMSBCconst,
ssa.OpARMRSBconst,
ssa.OpARMRSCconst,
- ssa.OpARMANDconst,
ssa.OpARMORconst,
ssa.OpARMXORconst,
- ssa.OpARMBICconst,
ssa.OpARMSLLconst,
ssa.OpARMSRLconst,
ssa.OpARMSRAconst:
diff --git a/src/cmd/compile/internal/arm64/ssa.go b/src/cmd/compile/internal/arm64/ssa.go
index db7064cff0..87703dd80d 100644
--- a/src/cmd/compile/internal/arm64/ssa.go
+++ b/src/cmd/compile/internal/arm64/ssa.go
@@ -195,7 +195,9 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
ssa.OpARM64FNMULS,
ssa.OpARM64FNMULD,
ssa.OpARM64FDIVS,
- ssa.OpARM64FDIVD:
+ ssa.OpARM64FDIVD,
+ ssa.OpARM64ROR,
+ ssa.OpARM64RORW:
r := v.Reg()
r1 := v.Args[0].Reg()
r2 := v.Args[1].Reg()
@@ -253,6 +255,12 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
p.Reg = v.Args[1].Reg()
p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg()
+ case ssa.OpARM64MVNshiftLL, ssa.OpARM64NEGshiftLL:
+ genshift(s, v.Op.Asm(), 0, v.Args[0].Reg(), v.Reg(), arm64.SHIFT_LL, v.AuxInt)
+ case ssa.OpARM64MVNshiftRL, ssa.OpARM64NEGshiftRL:
+ genshift(s, v.Op.Asm(), 0, v.Args[0].Reg(), v.Reg(), arm64.SHIFT_LR, v.AuxInt)
+ case ssa.OpARM64MVNshiftRA, ssa.OpARM64NEGshiftRA:
+ genshift(s, v.Op.Asm(), 0, v.Args[0].Reg(), v.Reg(), arm64.SHIFT_AR, v.AuxInt)
case ssa.OpARM64ADDshiftLL,
ssa.OpARM64SUBshiftLL,
ssa.OpARM64ANDshiftLL,
@@ -315,11 +323,11 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
p.From.Type = obj.TYPE_CONST
p.From.Offset = v.AuxInt
p.Reg = v.Args[0].Reg()
- case ssa.OpARM64CMPshiftLL:
+ case ssa.OpARM64CMPshiftLL, ssa.OpARM64CMNshiftLL, ssa.OpARM64TSTshiftLL:
genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), 0, arm64.SHIFT_LL, v.AuxInt)
- case ssa.OpARM64CMPshiftRL:
+ case ssa.OpARM64CMPshiftRL, ssa.OpARM64CMNshiftRL, ssa.OpARM64TSTshiftRL:
genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), 0, arm64.SHIFT_LR, v.AuxInt)
- case ssa.OpARM64CMPshiftRA:
+ case ssa.OpARM64CMPshiftRA, ssa.OpARM64CMNshiftRA, ssa.OpARM64TSTshiftRA:
genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), 0, arm64.SHIFT_AR, v.AuxInt)
case ssa.OpARM64MOVDaddr:
p := s.Prog(arm64.AMOVD)
@@ -696,8 +704,11 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
fallthrough
case ssa.OpARM64MVN,
ssa.OpARM64NEG,
+ ssa.OpARM64FABSD,
ssa.OpARM64FMOVDfpgp,
ssa.OpARM64FMOVDgpfp,
+ ssa.OpARM64FMOVSfpgp,
+ ssa.OpARM64FMOVSgpfp,
ssa.OpARM64FNEGS,
ssa.OpARM64FNEGD,
ssa.OpARM64FSQRTD,
@@ -728,6 +739,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
ssa.OpARM64CLZW,
ssa.OpARM64FRINTAD,
ssa.OpARM64FRINTMD,
+ ssa.OpARM64FRINTND,
ssa.OpARM64FRINTPD,
ssa.OpARM64FRINTZD:
p := s.Prog(v.Op.Asm())
diff --git a/src/cmd/compile/internal/gc/bexport.go b/src/cmd/compile/internal/gc/bexport.go
index d0b1804eb6..3ef1e6af4d 100644
--- a/src/cmd/compile/internal/gc/bexport.go
+++ b/src/cmd/compile/internal/gc/bexport.go
@@ -2,444 +2,14 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Binary package export.
-
-/*
-1) Export data encoding principles:
-
-The export data is a serialized description of the graph of exported
-"objects": constants, types, variables, and functions. Aliases may be
-directly reexported, and unaliased types may be indirectly reexported
-(as part of the type of a directly exported object). More generally,
-objects referred to from inlined function bodies can be reexported.
-We need to know which package declares these reexported objects, and
-therefore packages are also part of the export graph.
-
-The roots of the graph are two lists of objects. The 1st list (phase 1,
-see Export) contains all objects that are exported at the package level.
-These objects are the full representation of the package's API, and they
-are the only information a platform-independent tool (e.g., go/types)
-needs to know to type-check against a package.
-
-The 2nd list of objects contains all objects referred to from exported
-inlined function bodies. These objects are needed by the compiler to
-make sense of the function bodies; the exact list contents are compiler-
-specific.
-
-Finally, the export data contains a list of representations for inlined
-function bodies. The format of this representation is compiler specific.
-
-The graph is serialized in in-order fashion, starting with the roots.
-Each object in the graph is serialized by writing its fields sequentially.
-If the field is a pointer to another object, that object is serialized in
-place, recursively. Otherwise the field is written in place. Non-pointer
-fields are all encoded as integer or string values.
-
-Some objects (packages, types) may be referred to more than once. When
-reaching an object that was not serialized before, an integer _index_
-is assigned to it, starting at 0. In this case, the encoding starts
-with an integer _tag_ < 0. The tag value indicates the kind of object
-that follows and that this is the first time that we see this object.
-If the object was already serialized, the encoding is simply the object
-index >= 0. An importer can trivially determine if an object needs to
-be read in for the first time (tag < 0) and entered into the respective
-object table, or if the object was seen already (index >= 0), in which
-case the index is used to look up the object in the respective table.
-
-Before exporting or importing, the type tables are populated with the
-predeclared types (int, string, error, unsafe.Pointer, etc.). This way
-they are automatically encoded with a known and fixed type index.
-
-2) Encoding format:
-
-The export data starts with two newline-terminated strings: a version
-string and either an empty string, or "debug", when emitting the debug
-format. These strings are followed by version-specific encoding options.
-
-(The Go1.7 version starts with a couple of bytes specifying the format.
-That format encoding is no longer used but is supported to avoid spurious
-errors when importing old installed package files.)
-
-This header is followed by the package object for the exported package,
-two lists of objects, and the list of inlined function bodies.
-
-The encoding of objects is straight-forward: Constants, variables, and
-functions start with their name, type, and possibly a value. Named types
-record their name and package so that they can be canonicalized: If the
-same type was imported before via another import, the importer must use
-the previously imported type pointer so that we have exactly one version
-(i.e., one pointer) for each named type (and read but discard the current
-type encoding). Unnamed types simply encode their respective fields.
-Aliases are encoded starting with their name followed by the qualified
-identifier denoting the original (aliased) object, which was exported
-earlier.
-
-In the encoding, some lists start with the list length. Some lists are
-terminated with an end marker (usually for lists where we may not know
-the length a priori).
-
-Integers use variable-length encoding for compact representation.
-
-Strings are canonicalized similar to objects that may occur multiple times:
-If the string was exported already, it is represented by its index only.
-Otherwise, the export data starts with the negative string length (negative,
-so we can distinguish from string index), followed by the string bytes.
-The empty string is mapped to index 0. (The initial format string is an
-exception; it is encoded as the string bytes followed by a newline).
-
-The exporter and importer are completely symmetric in implementation: For
-each encoding routine there is a matching and symmetric decoding routine.
-This symmetry makes it very easy to change or extend the format: If a new
-field needs to be encoded, a symmetric change can be made to exporter and
-importer.
-
-3) Making changes to the encoding format:
-
-Any change to the encoding format requires a respective change in the
-exporter below and a corresponding symmetric change to the importer in
-bimport.go.
-
-Furthermore, it requires a corresponding change to go/internal/gcimporter
-and golang.org/x/tools/go/gcimporter15. Changes to the latter must preserve
-compatibility with both the last release of the compiler, and with the
-corresponding compiler at tip. That change is necessarily more involved,
-as it must switch based on the version number in the export data file.
-
-It is recommended to turn on debugFormat temporarily when working on format
-changes as it will help finding encoding/decoding inconsistencies quickly.
-*/
-
package gc
import (
- "bufio"
- "bytes"
"cmd/compile/internal/types"
- "cmd/internal/src"
- "encoding/binary"
- "fmt"
- "math/big"
- "sort"
- "strings"
)
-// If debugFormat is set, each integer and string value is preceded by a marker
-// and position information in the encoding. This mechanism permits an importer
-// to recognize immediately when it is out of sync. The importer recognizes this
-// mode automatically (i.e., it can import export data produced with debugging
-// support even if debugFormat is not set at the time of import). This mode will
-// lead to massively larger export data (by a factor of 2 to 3) and should only
-// be enabled during development and debugging.
-//
-// NOTE: This flag is the first flag to enable if importing dies because of
-// (suspected) format errors, and whenever a change is made to the format.
-const debugFormat = false // default: false
-
-// Current export format version. Increase with each format change.
-// 6: package height (CL 105038)
-// 5: improved position encoding efficiency (issue 20080, CL 41619)
-// 4: type name objects support type aliases, uses aliasTag
-// 3: Go1.8 encoding (same as version 2, aliasTag defined but never used)
-// 2: removed unused bool in ODCL export (compiler only)
-// 1: header format change (more regular), export package for _ struct fields
-// 0: Go1.7 encoding
-const exportVersion = 6
-
-// exportInlined enables the export of inlined function bodies and related
-// dependencies. The compiler should work w/o any loss of functionality with
-// the flag disabled, but the generated code will lose access to inlined
-// function bodies across packages, leading to performance bugs.
-// Leave for debugging.
-const exportInlined = true // default: true
-
-// trackAllTypes enables cycle tracking for all types, not just named
-// types. The existing compiler invariants assume that unnamed types
-// that are not completely set up are not used, or else there are spurious
-// errors.
-// If disabled, only named types are tracked, possibly leading to slightly
-// less efficient encoding in rare cases. It also prevents the export of
-// some corner-case type declarations (but those were not handled correctly
-// with the former textual export format either).
-// Note that when a type is only seen once, as many unnamed types are,
-// it is less efficient to track it, since we then also record an index for it.
-// See CLs 41622 and 41623 for some data and discussion.
-// TODO(gri) enable selectively and remove once issues caused by it are fixed
-const trackAllTypes = false
-
type exporter struct {
- out *bufio.Writer
-
- // object -> index maps, indexed in order of serialization
- strIndex map[string]int
- pathIndex map[string]int
- pkgIndex map[*types.Pkg]int
- typIndex map[*types.Type]int
- funcList []*Func
-
marked map[*types.Type]bool // types already seen by markType
-
- // position encoding
- posInfoFormat bool
- prevFile string
- prevLine int
-
- // debugging support
- written int // bytes written
- indent int // for p.trace
- trace bool
-}
-
-// export writes the exportlist for localpkg to out and returns the number of bytes written.
-func export(out *bufio.Writer, trace bool) int {
- p := exporter{
- out: out,
- strIndex: map[string]int{"": 0}, // empty string is mapped to 0
- pathIndex: map[string]int{"": 0}, // empty path is mapped to 0
- pkgIndex: make(map[*types.Pkg]int),
- typIndex: make(map[*types.Type]int),
- posInfoFormat: true,
- trace: trace,
- }
-
- // write version info
- // The version string must start with "version %d" where %d is the version
- // number. Additional debugging information may follow after a blank; that
- // text is ignored by the importer.
- p.rawStringln(fmt.Sprintf("version %d", exportVersion))
- var debug string
- if debugFormat {
- debug = "debug"
- }
- p.rawStringln(debug) // cannot use p.bool since it's affected by debugFormat; also want to see this clearly
- p.bool(trackAllTypes)
- p.bool(p.posInfoFormat)
-
- // --- generic export data ---
-
- // populate type map with predeclared "known" types
- predecl := predeclared()
- for index, typ := range predecl {
- p.typIndex[typ] = index
- }
- if len(p.typIndex) != len(predecl) {
- Fatalf("exporter: duplicate entries in type map?")
- }
-
- // write package data
- if localpkg.Path != "" {
- Fatalf("exporter: local package path not empty: %q", localpkg.Path)
- }
- p.pkg(localpkg)
- if p.trace {
- p.tracef("\n")
- }
-
- // export objects
- //
- // We've already added all exported (package-level) objects to
- // exportlist. These objects represent all information
- // required to import this package and type-check against it;
- // i.e., this is the platform-independent export data. The
- // format is generic in the sense that different compilers can
- // use the same representation.
- //
- // However, due to inlineable function and their dependencies,
- // we may need to export (or possibly reexport) additional
- // objects. We handle these objects separately. This data is
- // platform-specific as it depends on the inlining decisions
- // of the compiler and the representation of the inlined
- // function bodies.
-
- // Remember initial exportlist length.
- numglobals := len(exportlist)
-
- // Phase 0: Mark all inlineable functions that an importing
- // package could call. This is done by tracking down all
- // inlineable methods reachable from exported declarations.
- //
- // Along the way, we add to exportlist any function and
- // variable declarations needed by the inline bodies.
- if exportInlined {
- p.marked = make(map[*types.Type]bool)
- for _, n := range exportlist {
- sym := n.Sym
- p.markType(asNode(sym.Def).Type)
- }
- p.marked = nil
- }
-
- // Phase 1: Export package-level objects.
- objcount := 0
- for _, n := range exportlist[:numglobals] {
- sym := n.Sym
-
- // TODO(gri) Closures have dots in their names;
- // e.g., TestFloatZeroValue.func1 in math/big tests.
- if strings.Contains(sym.Name, ".") {
- Fatalf("exporter: unexpected symbol: %v", sym)
- }
-
- if sym.Def == nil {
- Fatalf("exporter: unknown export symbol: %v", sym)
- }
-
- // TODO(gri) Optimization: Probably worthwhile collecting
- // long runs of constants and export them "in bulk" (saving
- // tags and types, and making import faster).
-
- if p.trace {
- p.tracef("\n")
- }
- p.obj(sym)
- objcount++
- }
-
- // indicate end of list
- if p.trace {
- p.tracef("\n")
- }
- p.tag(endTag)
-
- // for self-verification only (redundant)
- p.int(objcount)
-
- // --- compiler-specific export data ---
-
- if p.trace {
- p.tracef("\n--- compiler-specific export data ---\n[ ")
- if p.indent != 0 {
- Fatalf("exporter: incorrect indentation")
- }
- }
-
- // write compiler-specific flags
- if p.trace {
- p.tracef("\n")
- }
-
- // Phase 2: Export objects added to exportlist during phase 0.
- objcount = 0
- for _, n := range exportlist[numglobals:] {
- sym := n.Sym
-
- // TODO(gri) The rest of this loop body is identical with
- // the loop body above. Leave alone for now since there
- // are different optimization opportunities, but factor
- // eventually.
-
- // TODO(gri) Closures have dots in their names;
- // e.g., TestFloatZeroValue.func1 in math/big tests.
- if strings.Contains(sym.Name, ".") {
- Fatalf("exporter: unexpected symbol: %v", sym)
- }
-
- if sym.Def == nil {
- Fatalf("exporter: unknown export symbol: %v", sym)
- }
-
- // TODO(gri) Optimization: Probably worthwhile collecting
- // long runs of constants and export them "in bulk" (saving
- // tags and types, and making import faster).
-
- if p.trace {
- p.tracef("\n")
- }
-
- if IsAlias(sym) {
- Fatalf("exporter: unexpected type alias %v in inlined function body", sym)
- }
-
- p.obj(sym)
- objcount++
- }
-
- // indicate end of list
- if p.trace {
- p.tracef("\n")
- }
- p.tag(endTag)
-
- // for self-verification only (redundant)
- p.int(objcount)
-
- // --- inlined function bodies ---
-
- if p.trace {
- p.tracef("\n--- inlined function bodies ---\n")
- if p.indent != 0 {
- Fatalf("exporter: incorrect indentation")
- }
- }
-
- // write inlineable function bodies
- // Don't use range since funcList may grow.
- objcount = 0
- for i := 0; i < len(p.funcList); i++ {
- if f := p.funcList[i]; f.ExportInline() {
- // function has inlineable body:
- // write index and body
- if p.trace {
- p.tracef("\n----\nfunc { %#v }\n", asNodes(f.Inl.Body))
- }
- p.int(i)
- p.int(int(f.Inl.Cost))
- p.stmtList(asNodes(f.Inl.Body))
- if p.trace {
- p.tracef("\n")
- }
- objcount++
- }
- }
-
- // indicate end of list
- if p.trace {
- p.tracef("\n")
- }
- p.int(-1) // invalid index terminates list
-
- // for self-verification only (redundant)
- p.int(objcount)
-
- if p.trace {
- p.tracef("\n--- end ---\n")
- }
-
- // --- end of export data ---
-
- return p.written
-}
-
-func (p *exporter) pkg(pkg *types.Pkg) {
- if pkg == nil {
- Fatalf("exporter: unexpected nil pkg")
- }
-
- // if we saw the package before, write its index (>= 0)
- if i, ok := p.pkgIndex[pkg]; ok {
- p.index('P', i)
- return
- }
-
- // otherwise, remember the package, write the package tag (< 0) and package data
- if p.trace {
- p.tracef("P%d = { ", len(p.pkgIndex))
- defer p.tracef("} ")
- }
- p.pkgIndex[pkg] = len(p.pkgIndex)
-
- p.tag(packageTag)
- p.string(pkg.Name)
- p.path(pkg.Path)
- p.int(pkg.Height)
-}
-
-func unidealType(typ *types.Type, val Val) *types.Type {
- // Untyped (ideal) constants get their own type. This decouples
- // the constant type from the encoding of the constant value.
- if typ == nil || typ.IsUntyped() {
- typ = untype(val.Ctype())
- }
- return typ
}
// markType recursively visits types reachable from t to identify
@@ -508,1287 +78,11 @@ func (p *exporter) markType(t *types.Type) {
}
}
-func (p *exporter) obj(sym *types.Sym) {
- // Exported objects may be from different packages because they
- // may be re-exported via an exported alias or as dependencies in
- // exported inlined function bodies. Thus, exported object names
- // must be fully qualified.
- //
- // (This can only happen for aliased objects or during phase 2
- // (exportInlined enabled) of object export. Unaliased Objects
- // exported in phase 1 (compiler-indendepent objects) are by
- // definition only the objects from the current package and not
- // pulled in via inlined function bodies. In that case the package
- // qualifier is not needed. Possible space optimization.)
-
- n := asNode(sym.Def)
- switch n.Op {
- case OLITERAL:
- // constant
- // TODO(gri) determine if we need the typecheck call here
- n = typecheck(n, Erv)
- if n == nil || n.Op != OLITERAL {
- Fatalf("exporter: dumpexportconst: oconst nil: %v", sym)
- }
-
- p.tag(constTag)
- p.pos(n.Pos)
- // TODO(gri) In inlined functions, constants are used directly
- // so they should never occur as re-exported objects. We may
- // not need the qualified name here. See also comment above.
- // Possible space optimization.
- p.qualifiedName(sym)
- p.typ(unidealType(n.Type, n.Val()))
- p.value(n.Val())
-
- case OTYPE:
- // named type
- t := n.Type
- if t.Etype == TFORW {
- Fatalf("exporter: export of incomplete type %v", sym)
- }
-
- if IsAlias(sym) {
- p.tag(aliasTag)
- p.pos(n.Pos)
- p.qualifiedName(sym)
- } else {
- p.tag(typeTag)
- }
- p.typ(t)
-
- case ONAME:
- // variable or function
- n = typecheck(n, Erv|Ecall)
- if n == nil || n.Type == nil {
- Fatalf("exporter: variable/function exported but not defined: %v", sym)
- }
-
- if n.Type.Etype == TFUNC && n.Class() == PFUNC {
- // function
- p.tag(funcTag)
- p.pos(n.Pos)
- p.qualifiedName(sym)
-
- sig := asNode(sym.Def).Type
-
- // Theoretically, we only need numbered
- // parameters if we're supplying an inline
- // function body. However, it's possible to
- // import a function from a package that
- // didn't supply the inline body, and then
- // another that did. In this case, we would
- // need to rename the parameters during
- // import, which is a little sketchy.
- //
- // For simplicity, just always number
- // parameters.
- p.paramList(sig.Params(), true)
- p.paramList(sig.Results(), true)
-
- p.funcList = append(p.funcList, asNode(sym.Def).Func)
- } else {
- // variable
- p.tag(varTag)
- p.pos(n.Pos)
- p.qualifiedName(sym)
- p.typ(asNode(sym.Def).Type)
- }
-
- default:
- Fatalf("exporter: unexpected export symbol: %v %v", n.Op, sym)
- }
-}
-
// deltaNewFile is a magic line delta offset indicating a new file.
// We use -64 because it is rare; see issue 20080 and CL 41619.
// -64 is the smallest int that fits in a single byte as a varint.
const deltaNewFile = -64
-func (p *exporter) pos(pos src.XPos) {
- if !p.posInfoFormat {
- return
- }
-
- file, line := fileLine(pos)
- if file == p.prevFile {
- // common case: write line delta
- // delta == deltaNewFile means different file
- // if the actual line delta is deltaNewFile,
- // follow up with a negative int to indicate that.
- // only non-negative ints can follow deltaNewFile
- // when writing a new file.
- delta := line - p.prevLine
- p.int(delta)
- if delta == deltaNewFile {
- p.int(-1) // -1 means no file change
- }
- } else {
- // different file
- p.int(deltaNewFile)
- p.int(line) // line >= 0
- p.path(file)
- p.prevFile = file
- }
- p.prevLine = line
-}
-
-func (p *exporter) path(s string) {
- if i, ok := p.pathIndex[s]; ok {
- // Note: Using p.index(i) here requires the use of p.tag(-len(c)) below
- // to get matching debug markers ('t'). But in trace mode p.tag
- // assumes that the tag argument is a valid tag that can be looked
- // up in the tagString list, rather then some arbitrary slice length.
- // Use p.int instead.
- p.int(i) // i >= 0
- return
- }
- p.pathIndex[s] = len(p.pathIndex)
- c := strings.Split(s, "/")
- p.int(-len(c)) // -len(c) < 0
- for _, x := range c {
- p.string(x)
- }
-}
-
-func fileLine(pos0 src.XPos) (file string, line int) {
- pos := Ctxt.PosTable.Pos(pos0)
- file = pos.Base().AbsFilename()
- line = int(pos.RelLine())
- return
-}
-
-func (p *exporter) typ(t *types.Type) {
- if t == nil {
- Fatalf("exporter: nil type")
- }
-
- // Possible optimization: Anonymous pointer types *T where
- // T is a named type are common. We could canonicalize all
- // such types *T to a single type PT = *T. This would lead
- // to at most one *T entry in typIndex, and all future *T's
- // would be encoded as the respective index directly. Would
- // save 1 byte (pointerTag) per *T and reduce the typIndex
- // size (at the cost of a canonicalization map). We can do
- // this later, without encoding format change.
-
- // if we saw the type before, write its index (>= 0)
- if i, ok := p.typIndex[t]; ok {
- p.index('T', i)
- return
- }
-
- // otherwise, remember the type, write the type tag (< 0) and type data
- if trackAllTypes {
- if p.trace {
- p.tracef("T%d = {>\n", len(p.typIndex))
- defer p.tracef("<\n} ")
- }
- p.typIndex[t] = len(p.typIndex)
- }
-
- // pick off named types
- if tsym := t.Sym; tsym != nil {
- if !trackAllTypes {
- // if we don't track all types, track named types now
- p.typIndex[t] = len(p.typIndex)
- }
-
- // Predeclared types should have been found in the type map.
- if t.Orig == t {
- Fatalf("exporter: predeclared type missing from type map?")
- }
-
- n := typenod(t)
- if n.Type != t {
- Fatalf("exporter: named type definition incorrectly set up")
- }
-
- p.tag(namedTag)
- p.pos(n.Pos)
- p.qualifiedName(tsym)
-
- // write underlying type
- p.typ(t.Orig)
-
- // interfaces don't have associated methods
- if t.Orig.IsInterface() {
- return
- }
-
- // sort methods for reproducible export format
- // TODO(gri) Determine if they are already sorted
- // in which case we can drop this step.
- var methods []*types.Field
- methods = append(methods, t.Methods().Slice()...)
- sort.Sort(methodbyname(methods))
- p.int(len(methods))
-
- if p.trace && len(methods) > 0 {
- p.tracef("associated methods {>")
- }
-
- for _, m := range methods {
- if p.trace {
- p.tracef("\n")
- }
- if strings.Contains(m.Sym.Name, ".") {
- Fatalf("invalid symbol name: %s (%v)", m.Sym.Name, m.Sym)
- }
-
- p.pos(m.Pos)
- p.fieldSym(m.Sym, false)
-
- sig := m.Type
- mfn := asNode(sig.FuncType().Nname)
-
- // See comment in (*exporter).obj about
- // numbered parameters.
- p.paramList(sig.Recvs(), true)
- p.paramList(sig.Params(), true)
- p.paramList(sig.Results(), true)
- p.bool(m.Nointerface()) // record go:nointerface pragma value (see also #16243)
-
- p.funcList = append(p.funcList, mfn.Func)
- }
-
- if p.trace && len(methods) > 0 {
- p.tracef("<\n} ")
- }
-
- return
- }
-
- // otherwise we have a type literal
- switch t.Etype {
- case TARRAY:
- if t.IsDDDArray() {
- Fatalf("array bounds should be known at export time: %v", t)
- }
- p.tag(arrayTag)
- p.int64(t.NumElem())
- p.typ(t.Elem())
-
- case TSLICE:
- p.tag(sliceTag)
- p.typ(t.Elem())
-
- case TDDDFIELD:
- // see p.param use of TDDDFIELD
- p.tag(dddTag)
- p.typ(t.DDDField())
-
- case TSTRUCT:
- p.tag(structTag)
- p.fieldList(t)
-
- case TPTR32, TPTR64: // could use Tptr but these are constants
- p.tag(pointerTag)
- p.typ(t.Elem())
-
- case TFUNC:
- p.tag(signatureTag)
- p.paramList(t.Params(), false)
- p.paramList(t.Results(), false)
-
- case TINTER:
- p.tag(interfaceTag)
- p.methodList(t)
-
- case TMAP:
- p.tag(mapTag)
- p.typ(t.Key())
- p.typ(t.Elem())
-
- case TCHAN:
- p.tag(chanTag)
- p.int(int(t.ChanDir()))
- p.typ(t.Elem())
-
- default:
- Fatalf("exporter: unexpected type: %v (Etype = %d)", t, t.Etype)
- }
-}
-
-func (p *exporter) qualifiedName(sym *types.Sym) {
- p.string(sym.Name)
- p.pkg(sym.Pkg)
-}
-
-func (p *exporter) fieldList(t *types.Type) {
- if p.trace && t.NumFields() > 0 {
- p.tracef("fields {>")
- defer p.tracef("<\n} ")
- }
-
- p.int(t.NumFields())
- for _, f := range t.Fields().Slice() {
- if p.trace {
- p.tracef("\n")
- }
- p.field(f)
- }
-}
-
-func (p *exporter) field(f *types.Field) {
- p.pos(f.Pos)
- p.fieldName(f)
- p.typ(f.Type)
- p.string(f.Note)
-}
-
-func (p *exporter) methodList(t *types.Type) {
- var embeddeds, methods []*types.Field
-
- for _, m := range t.Methods().Slice() {
- if m.Sym != nil {
- methods = append(methods, m)
- } else {
- embeddeds = append(embeddeds, m)
- }
- }
-
- if p.trace && len(embeddeds) > 0 {
- p.tracef("embeddeds {>")
- }
- p.int(len(embeddeds))
- for _, m := range embeddeds {
- if p.trace {
- p.tracef("\n")
- }
- p.pos(m.Pos)
- p.typ(m.Type)
- }
- if p.trace && len(embeddeds) > 0 {
- p.tracef("<\n} ")
- }
-
- if p.trace && len(methods) > 0 {
- p.tracef("methods {>")
- }
- p.int(len(methods))
- for _, m := range methods {
- if p.trace {
- p.tracef("\n")
- }
- p.method(m)
- }
- if p.trace && len(methods) > 0 {
- p.tracef("<\n} ")
- }
-}
-
-func (p *exporter) method(m *types.Field) {
- p.pos(m.Pos)
- p.methodName(m.Sym)
- p.paramList(m.Type.Params(), false)
- p.paramList(m.Type.Results(), false)
-}
-
-func (p *exporter) fieldName(t *types.Field) {
- name := t.Sym.Name
- if t.Embedded != 0 {
- // anonymous field - we distinguish between 3 cases:
- // 1) field name matches base type name and is exported
- // 2) field name matches base type name and is not exported
- // 3) field name doesn't match base type name (alias name)
- bname := basetypeName(t.Type)
- if name == bname {
- if types.IsExported(name) {
- name = "" // 1) we don't need to know the field name or package
- } else {
- name = "?" // 2) use unexported name "?" to force package export
- }
- } else {
- // 3) indicate alias and export name as is
- // (this requires an extra "@" but this is a rare case)
- p.string("@")
- }
- }
- p.string(name)
- if name != "" && !types.IsExported(name) {
- p.pkg(t.Sym.Pkg)
- }
-}
-
-// methodName is like qualifiedName but it doesn't record the package for exported names.
-func (p *exporter) methodName(sym *types.Sym) {
- p.string(sym.Name)
- if !types.IsExported(sym.Name) {
- p.pkg(sym.Pkg)
- }
-}
-
-func basetypeName(t *types.Type) string {
- s := t.Sym
- if s == nil && t.IsPtr() {
- s = t.Elem().Sym // deref
- }
- if s != nil {
- return s.Name
- }
- return "" // unnamed type
-}
-
-func (p *exporter) paramList(params *types.Type, numbered bool) {
- if !params.IsFuncArgStruct() {
- Fatalf("exporter: parameter list expected")
- }
-
- // use negative length to indicate unnamed parameters
- // (look at the first parameter only since either all
- // names are present or all are absent)
- //
- // TODO(gri) If we don't have an exported function
- // body, the parameter names are irrelevant for the
- // compiler (though they may be of use for other tools).
- // Possible space optimization.
- n := params.NumFields()
- if n > 0 && parName(params.Field(0), numbered) == "" {
- n = -n
- }
- p.int(n)
- for _, q := range params.Fields().Slice() {
- p.param(q, n, numbered)
- }
-}
-
-func (p *exporter) param(q *types.Field, n int, numbered bool) {
- t := q.Type
- if q.Isddd() {
- // create a fake type to encode ... just for the p.typ call
- t = types.NewDDDField(t.Elem())
- }
- p.typ(t)
- if n > 0 {
- name := parName(q, numbered)
- if name == "" {
- // Sometimes we see an empty name even for n > 0.
- // This appears to happen for interface methods
- // with _ (blank) parameter names. Make sure we
- // have a proper name and package so we don't crash
- // during import (see also issue #15470).
- // (parName uses "" instead of "?" as in fmt.go)
- // TODO(gri) review parameter name encoding
- name = "_"
- }
- p.string(name)
- if name != "_" {
- // Because of (re-)exported inlined functions
- // the importpkg may not be the package to which this
- // function (and thus its parameter) belongs. We need to
- // supply the parameter package here. We need the package
- // when the function is inlined so we can properly resolve
- // the name. The _ (blank) parameter cannot be accessed, so
- // we don't need to export a package.
- //
- // TODO(gri) This is compiler-specific. Try using importpkg
- // here and then update the symbols if we find an inlined
- // body only. Otherwise, the parameter name is ignored and
- // the package doesn't matter. This would remove an int
- // (likely 1 byte) for each named parameter.
- p.pkg(q.Sym.Pkg)
- }
- }
- // TODO(gri) This is compiler-specific (escape info).
- // Move into compiler-specific section eventually?
- // (Not having escape info causes tests to fail, e.g. runtime GCInfoTest)
- p.string(q.Note)
-}
-
-func parName(f *types.Field, numbered bool) string {
- s := origSym(f.Sym)
- if s == nil {
- return ""
- }
-
- if s.Name == "_" {
- return "_"
- }
-
- // print symbol with Vargen number or not as desired
- name := s.Name
- if strings.Contains(name, ".") {
- Fatalf("invalid symbol name: %s", name)
- }
-
- // Functions that can be inlined use numbered parameters so we can distinguish them
- // from other names in their context after inlining (i.e., the parameter numbering
- // is a form of parameter rewriting). See issue 4326 for an example and test case.
- if numbered {
- if n := asNode(f.Nname); !strings.Contains(name, "·") && n != nil && n.Name.Vargen > 0 {
- name = fmt.Sprintf("%s·%d", name, n.Name.Vargen) // append Vargen
- }
- } else {
- if i := strings.Index(name, "·"); i > 0 {
- name = name[:i] // cut off Vargen
- }
- }
- return name
-}
-
-func (p *exporter) value(x Val) {
- if p.trace {
- p.tracef("= ")
- }
-
- switch x := x.U.(type) {
- case bool:
- tag := falseTag
- if x {
- tag = trueTag
- }
- p.tag(tag)
-
- case *Mpint:
- if minintval[TINT64].Cmp(x) <= 0 && x.Cmp(maxintval[TINT64]) <= 0 {
- // common case: x fits into an int64 - use compact encoding
- p.tag(int64Tag)
- p.int64(x.Int64())
- return
- }
- // uncommon case: large x - use float encoding
- // (powers of 2 will be encoded efficiently with exponent)
- f := newMpflt()
- f.SetInt(x)
- p.tag(floatTag)
- p.float(f)
-
- case *Mpflt:
- p.tag(floatTag)
- p.float(x)
-
- case *Mpcplx:
- p.tag(complexTag)
- p.float(&x.Real)
- p.float(&x.Imag)
-
- case string:
- p.tag(stringTag)
- p.string(x)
-
- case *NilVal:
- // not a constant but used in exported function bodies
- p.tag(nilTag)
-
- default:
- Fatalf("exporter: unexpected value %v (%T)", x, x)
- }
-}
-
-func (p *exporter) float(x *Mpflt) {
- // extract sign (there is no -0)
- f := &x.Val
- sign := f.Sign()
- if sign == 0 {
- // x == 0
- p.int(0)
- return
- }
- // x != 0
-
- // extract exponent such that 0.5 <= m < 1.0
- var m big.Float
- exp := f.MantExp(&m)
-
- // extract mantissa as *big.Int
- // - set exponent large enough so mant satisfies mant.IsInt()
- // - get *big.Int from mant
- m.SetMantExp(&m, int(m.MinPrec()))
- mant, acc := m.Int(nil)
- if acc != big.Exact {
- Fatalf("exporter: internal error")
- }
-
- p.int(sign)
- p.int(exp)
- p.string(string(mant.Bytes()))
-}
-
-// ----------------------------------------------------------------------------
-// Inlined function bodies
-
-// Approach: More or less closely follow what fmt.go is doing for FExp mode
-// but instead of emitting the information textually, emit the node tree in
-// binary form.
-
-// TODO(gri) Improve tracing output. The current format is difficult to read.
-
-// stmtList may emit more (or fewer) than len(list) nodes.
-func (p *exporter) stmtList(list Nodes) {
- if p.trace {
- if list.Len() == 0 {
- p.tracef("{}")
- } else {
- p.tracef("{>")
- defer p.tracef("<\n}")
- }
- }
-
- for _, n := range list.Slice() {
- if p.trace {
- p.tracef("\n")
- }
- // TODO inlining produces expressions with ninits. we can't export these yet.
- // (from fmt.go:1461ff)
- p.node(n)
- }
-
- p.op(OEND)
-}
-
-func (p *exporter) node(n *Node) {
- if opprec[n.Op] < 0 {
- p.stmt(n)
- } else {
- p.expr(n)
- }
-}
-
-func (p *exporter) exprList(list Nodes) {
- if p.trace {
- if list.Len() == 0 {
- p.tracef("{}")
- } else {
- p.tracef("{>")
- defer p.tracef("<\n}")
- }
- }
-
- for _, n := range list.Slice() {
- if p.trace {
- p.tracef("\n")
- }
- p.expr(n)
- }
-
- p.op(OEND)
-}
-
-func (p *exporter) elemList(list Nodes) {
- if p.trace {
- p.tracef("[ ")
- }
- p.int(list.Len())
- if p.trace {
- if list.Len() == 0 {
- p.tracef("] {}")
- } else {
- p.tracef("] {>")
- defer p.tracef("<\n}")
- }
- }
-
- for _, n := range list.Slice() {
- if p.trace {
- p.tracef("\n")
- }
- p.fieldSym(n.Sym, false)
- p.expr(n.Left)
- }
-}
-
-func (p *exporter) expr(n *Node) {
- if p.trace {
- p.tracef("( ")
- defer p.tracef(") ")
- }
-
- // from nodefmt (fmt.go)
- //
- // nodefmt reverts nodes back to their original - we don't need to do
- // it because we are not bound to produce valid Go syntax when exporting
- //
- // if (fmtmode != FExp || n.Op != OLITERAL) && n.Orig != nil {
- // n = n.Orig
- // }
-
- // from exprfmt (fmt.go)
- for n != nil && n.Implicit() && (n.Op == OIND || n.Op == OADDR) {
- n = n.Left
- }
-
- switch op := n.Op; op {
- // expressions
- // (somewhat closely following the structure of exprfmt in fmt.go)
- case OPAREN:
- p.expr(n.Left) // unparen
-
- // case ODDDARG:
- // unimplemented - handled by default case
-
- case OLITERAL:
- if n.Val().Ctype() == CTNIL && n.Orig != nil && n.Orig != n {
- p.expr(n.Orig)
- break
- }
- p.op(OLITERAL)
- p.pos(n.Pos)
- p.typ(unidealType(n.Type, n.Val()))
- p.value(n.Val())
-
- case ONAME:
- // Special case: explicit name of func (*T) method(...) is turned into pkg.(*T).method,
- // but for export, this should be rendered as (*pkg.T).meth.
- // These nodes have the special property that they are names with a left OTYPE and a right ONAME.
- if n.isMethodExpression() {
- p.op(OXDOT)
- p.pos(n.Pos)
- p.expr(n.Left) // n.Left.Op == OTYPE
- p.fieldSym(n.Right.Sym, true)
- break
- }
-
- p.op(ONAME)
- p.pos(n.Pos)
- p.sym(n)
-
- // case OPACK, ONONAME:
- // should have been resolved by typechecking - handled by default case
-
- case OTYPE:
- p.op(OTYPE)
- p.pos(n.Pos)
- p.typ(n.Type)
-
- // case OTARRAY, OTMAP, OTCHAN, OTSTRUCT, OTINTER, OTFUNC:
- // should have been resolved by typechecking - handled by default case
-
- // case OCLOSURE:
- // unimplemented - handled by default case
-
- // case OCOMPLIT:
- // should have been resolved by typechecking - handled by default case
-
- case OPTRLIT:
- p.op(OPTRLIT)
- p.pos(n.Pos)
- p.expr(n.Left)
- p.bool(n.Implicit())
-
- case OSTRUCTLIT:
- p.op(OSTRUCTLIT)
- p.pos(n.Pos)
- p.typ(n.Type)
- p.elemList(n.List) // special handling of field names
-
- case OARRAYLIT, OSLICELIT, OMAPLIT:
- p.op(OCOMPLIT)
- p.pos(n.Pos)
- p.typ(n.Type)
- p.exprList(n.List)
-
- case OKEY:
- p.op(OKEY)
- p.pos(n.Pos)
- p.exprsOrNil(n.Left, n.Right)
-
- // case OSTRUCTKEY:
- // unreachable - handled in case OSTRUCTLIT by elemList
-
- // case OCALLPART:
- // unimplemented - handled by default case
-
- case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH:
- p.op(OXDOT)
- p.pos(n.Pos)
- p.expr(n.Left)
- p.fieldSym(n.Sym, true)
-
- case ODOTTYPE, ODOTTYPE2:
- p.op(ODOTTYPE)
- p.pos(n.Pos)
- p.expr(n.Left)
- p.typ(n.Type)
-
- case OINDEX, OINDEXMAP:
- p.op(OINDEX)
- p.pos(n.Pos)
- p.expr(n.Left)
- p.expr(n.Right)
-
- case OSLICE, OSLICESTR, OSLICEARR:
- p.op(OSLICE)
- p.pos(n.Pos)
- p.expr(n.Left)
- low, high, _ := n.SliceBounds()
- p.exprsOrNil(low, high)
-
- case OSLICE3, OSLICE3ARR:
- p.op(OSLICE3)
- p.pos(n.Pos)
- p.expr(n.Left)
- low, high, max := n.SliceBounds()
- p.exprsOrNil(low, high)
- p.expr(max)
-
- case OCOPY, OCOMPLEX:
- // treated like other builtin calls (see e.g., OREAL)
- p.op(op)
- p.pos(n.Pos)
- p.expr(n.Left)
- p.expr(n.Right)
- p.op(OEND)
-
- case OCONV, OCONVIFACE, OCONVNOP, OARRAYBYTESTR, OARRAYRUNESTR, OSTRARRAYBYTE, OSTRARRAYRUNE, ORUNESTR:
- p.op(OCONV)
- p.pos(n.Pos)
- p.expr(n.Left)
- p.typ(n.Type)
-
- case OREAL, OIMAG, OAPPEND, OCAP, OCLOSE, ODELETE, OLEN, OMAKE, ONEW, OPANIC, ORECOVER, OPRINT, OPRINTN:
- p.op(op)
- p.pos(n.Pos)
- if n.Left != nil {
- p.expr(n.Left)
- p.op(OEND)
- } else {
- p.exprList(n.List) // emits terminating OEND
- }
- // only append() calls may contain '...' arguments
- if op == OAPPEND {
- p.bool(n.Isddd())
- } else if n.Isddd() {
- Fatalf("exporter: unexpected '...' with %v call", op)
- }
-
- case OCALL, OCALLFUNC, OCALLMETH, OCALLINTER, OGETG:
- p.op(OCALL)
- p.pos(n.Pos)
- p.expr(n.Left)
- p.exprList(n.List)
- p.bool(n.Isddd())
-
- case OMAKEMAP, OMAKECHAN, OMAKESLICE:
- p.op(op) // must keep separate from OMAKE for importer
- p.pos(n.Pos)
- p.typ(n.Type)
- switch {
- default:
- // empty list
- p.op(OEND)
- case n.List.Len() != 0: // pre-typecheck
- p.exprList(n.List) // emits terminating OEND
- case n.Right != nil:
- p.expr(n.Left)
- p.expr(n.Right)
- p.op(OEND)
- case n.Left != nil && (n.Op == OMAKESLICE || !n.Left.Type.IsUntyped()):
- p.expr(n.Left)
- p.op(OEND)
- }
-
- // unary expressions
- case OPLUS, OMINUS, OADDR, OCOM, OIND, ONOT, ORECV:
- p.op(op)
- p.pos(n.Pos)
- p.expr(n.Left)
-
- // binary expressions
- case OADD, OAND, OANDAND, OANDNOT, ODIV, OEQ, OGE, OGT, OLE, OLT,
- OLSH, OMOD, OMUL, ONE, OOR, OOROR, ORSH, OSEND, OSUB, OXOR:
- p.op(op)
- p.pos(n.Pos)
- p.expr(n.Left)
- p.expr(n.Right)
-
- case OADDSTR:
- p.op(OADDSTR)
- p.pos(n.Pos)
- p.exprList(n.List)
-
- case OCMPSTR, OCMPIFACE:
- p.op(n.SubOp())
- p.pos(n.Pos)
- p.expr(n.Left)
- p.expr(n.Right)
-
- case ODCLCONST:
- // if exporting, DCLCONST should just be removed as its usage
- // has already been replaced with literals
- // TODO(gri) these should not be exported in the first place
- // TODO(gri) why is this considered an expression in fmt.go?
- p.op(ODCLCONST)
- p.pos(n.Pos)
-
- default:
- Fatalf("cannot export %v (%d) node\n"+
- "==> please file an issue and assign to gri@\n", n.Op, int(n.Op))
- }
-}
-
-// Caution: stmt will emit more than one node for statement nodes n that have a non-empty
-// n.Ninit and where n cannot have a natural init section (such as in "if", "for", etc.).
-func (p *exporter) stmt(n *Node) {
- if p.trace {
- p.tracef("( ")
- defer p.tracef(") ")
- }
-
- if n.Ninit.Len() > 0 && !stmtwithinit(n.Op) {
- if p.trace {
- p.tracef("( /* Ninits */ ")
- }
-
- // can't use stmtList here since we don't want the final OEND
- for _, n := range n.Ninit.Slice() {
- p.stmt(n)
- }
-
- if p.trace {
- p.tracef(") ")
- }
- }
-
- switch op := n.Op; op {
- case ODCL:
- p.op(ODCL)
- p.pos(n.Left.Pos) // use declared variable's pos
- p.sym(n.Left)
- p.typ(n.Left.Type)
-
- // case ODCLFIELD:
- // unimplemented - handled by default case
-
- case OAS:
- // Don't export "v = <N>" initializing statements, hope they're always
- // preceded by the DCL which will be re-parsed and typecheck to reproduce
- // the "v = <N>" again.
- if n.Right != nil {
- p.op(OAS)
- p.pos(n.Pos)
- p.expr(n.Left)
- p.expr(n.Right)
- }
-
- case OASOP:
- p.op(OASOP)
- p.pos(n.Pos)
- p.op(n.SubOp())
- p.expr(n.Left)
- if p.bool(!n.Implicit()) {
- p.expr(n.Right)
- }
-
- case OAS2, OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV:
- p.op(OAS2)
- p.pos(n.Pos)
- p.exprList(n.List)
- p.exprList(n.Rlist)
-
- case ORETURN:
- p.op(ORETURN)
- p.pos(n.Pos)
- p.exprList(n.List)
-
- // case ORETJMP:
- // unreachable - generated by compiler for trampolin routines
-
- case OPROC, ODEFER:
- p.op(op)
- p.pos(n.Pos)
- p.expr(n.Left)
-
- case OIF:
- p.op(OIF)
- p.pos(n.Pos)
- p.stmtList(n.Ninit)
- p.expr(n.Left)
- p.stmtList(n.Nbody)
- p.stmtList(n.Rlist)
-
- case OFOR:
- p.op(OFOR)
- p.pos(n.Pos)
- p.stmtList(n.Ninit)
- p.exprsOrNil(n.Left, n.Right)
- p.stmtList(n.Nbody)
-
- case ORANGE:
- p.op(ORANGE)
- p.pos(n.Pos)
- p.stmtList(n.List)
- p.expr(n.Right)
- p.stmtList(n.Nbody)
-
- case OSELECT, OSWITCH:
- p.op(op)
- p.pos(n.Pos)
- p.stmtList(n.Ninit)
- p.exprsOrNil(n.Left, nil)
- p.stmtList(n.List)
-
- case OCASE, OXCASE:
- p.op(OXCASE)
- p.pos(n.Pos)
- p.stmtList(n.List)
- p.stmtList(n.Nbody)
-
- case OFALL:
- p.op(OFALL)
- p.pos(n.Pos)
-
- case OBREAK, OCONTINUE:
- p.op(op)
- p.pos(n.Pos)
- p.exprsOrNil(n.Left, nil)
-
- case OEMPTY:
- // nothing to emit
-
- case OGOTO, OLABEL:
- p.op(op)
- p.pos(n.Pos)
- p.expr(n.Left)
-
- default:
- Fatalf("exporter: CANNOT EXPORT: %v\nPlease notify gri@\n", n.Op)
- }
-}
-
-func (p *exporter) exprsOrNil(a, b *Node) {
- ab := 0
- if a != nil {
- ab |= 1
- }
- if b != nil {
- ab |= 2
- }
- p.int(ab)
- if ab&1 != 0 {
- p.expr(a)
- }
- if ab&2 != 0 {
- p.node(b)
- }
-}
-
-func (p *exporter) fieldSym(s *types.Sym, short bool) {
- name := s.Name
-
- // remove leading "type." in method names ("(T).m" -> "m")
- if short {
- if i := strings.LastIndex(name, "."); i >= 0 {
- name = name[i+1:]
- }
- }
-
- // we should never see a _ (blank) here - these are accessible ("read") fields
- // TODO(gri) can we assert this with an explicit check?
- p.string(name)
- if !types.IsExported(name) {
- p.pkg(s.Pkg)
- }
-}
-
-// sym must encode the _ (blank) identifier as a single string "_" since
-// encoding for some nodes is based on this assumption (e.g. ONAME nodes).
-func (p *exporter) sym(n *Node) {
- s := n.Sym
- if s.Pkg != nil {
- if len(s.Name) > 0 && s.Name[0] == '.' {
- Fatalf("exporter: exporting synthetic symbol %s", s.Name)
- }
- }
-
- if p.trace {
- p.tracef("{ SYM ")
- defer p.tracef("} ")
- }
-
- name := s.Name
-
- // remove leading "type." in method names ("(T).m" -> "m")
- if i := strings.LastIndex(name, "."); i >= 0 {
- name = name[i+1:]
- }
-
- if strings.Contains(name, "·") && n.Name.Vargen > 0 {
- Fatalf("exporter: unexpected · in symbol name")
- }
-
- if i := n.Name.Vargen; i > 0 {
- name = fmt.Sprintf("%s·%d", name, i)
- }
-
- p.string(name)
- if name != "_" {
- p.pkg(s.Pkg)
- }
- // Fixes issue #18167.
- p.string(s.Linkname)
-}
-
-func (p *exporter) bool(b bool) bool {
- if p.trace {
- p.tracef("[")
- defer p.tracef("= %v] ", b)
- }
-
- x := 0
- if b {
- x = 1
- }
- p.int(x)
- return b
-}
-
-func (p *exporter) op(op Op) {
- if p.trace {
- p.tracef("[")
- defer p.tracef("= %v] ", op)
- }
-
- p.int(int(op))
-}
-
-// ----------------------------------------------------------------------------
-// Low-level encoders
-
-func (p *exporter) index(marker byte, index int) {
- if index < 0 {
- Fatalf("exporter: invalid index < 0")
- }
- if debugFormat {
- p.marker('t')
- }
- if p.trace {
- p.tracef("%c%d ", marker, index)
- }
- p.rawInt64(int64(index))
-}
-
-func (p *exporter) tag(tag int) {
- if tag >= 0 {
- Fatalf("exporter: invalid tag >= 0")
- }
- if debugFormat {
- p.marker('t')
- }
- if p.trace {
- p.tracef("%s ", tagString[-tag])
- }
- p.rawInt64(int64(tag))
-}
-
-func (p *exporter) int(x int) {
- p.int64(int64(x))
-}
-
-func (p *exporter) int64(x int64) {
- if debugFormat {
- p.marker('i')
- }
- if p.trace {
- p.tracef("%d ", x)
- }
- p.rawInt64(x)
-}
-
-func (p *exporter) string(s string) {
- if debugFormat {
- p.marker('s')
- }
- if p.trace {
- p.tracef("%q ", s)
- }
- // if we saw the string before, write its index (>= 0)
- // (the empty string is mapped to 0)
- if i, ok := p.strIndex[s]; ok {
- p.rawInt64(int64(i))
- return
- }
- // otherwise, remember string and write its negative length and bytes
- p.strIndex[s] = len(p.strIndex)
- p.rawInt64(-int64(len(s)))
- for i := 0; i < len(s); i++ {
- p.rawByte(s[i])
- }
-}
-
-// marker emits a marker byte and position information which makes
-// it easy for a reader to detect if it is "out of sync". Used only
-// if debugFormat is set.
-func (p *exporter) marker(m byte) {
- p.rawByte(m)
- // Uncomment this for help tracking down the location
- // of an incorrect marker when running in debugFormat.
- // if p.trace {
- // p.tracef("#%d ", p.written)
- // }
- p.rawInt64(int64(p.written))
-}
-
-// rawInt64 should only be used by low-level encoders.
-func (p *exporter) rawInt64(x int64) {
- var tmp [binary.MaxVarintLen64]byte
- n := binary.PutVarint(tmp[:], x)
- for i := 0; i < n; i++ {
- p.rawByte(tmp[i])
- }
-}
-
-// rawStringln should only be used to emit the initial version string.
-func (p *exporter) rawStringln(s string) {
- for i := 0; i < len(s); i++ {
- p.rawByte(s[i])
- }
- p.rawByte('\n')
-}
-
-// rawByte is the bottleneck interface to write to p.out.
-// rawByte escapes b as follows (any encoding does that
-// hides '$'):
-//
-// '$' => '|' 'S'
-// '|' => '|' '|'
-//
-// Necessary so other tools can find the end of the
-// export data by searching for "$$".
-// rawByte should only be used by low-level encoders.
-func (p *exporter) rawByte(b byte) {
- switch b {
- case '$':
- // write '$' as '|' 'S'
- b = 'S'
- fallthrough
- case '|':
- // write '|' as '|' '|'
- p.out.WriteByte('|')
- p.written++
- }
- p.out.WriteByte(b)
- p.written++
-}
-
-// tracef is like fmt.Printf but it rewrites the format string
-// to take care of indentation.
-func (p *exporter) tracef(format string, args ...interface{}) {
- if strings.ContainsAny(format, "<>\n") {
- var buf bytes.Buffer
- for i := 0; i < len(format); i++ {
- // no need to deal with runes
- ch := format[i]
- switch ch {
- case '>':
- p.indent++
- continue
- case '<':
- p.indent--
- continue
- }
- buf.WriteByte(ch)
- if ch == '\n' {
- for j := p.indent; j > 0; j-- {
- buf.WriteString(". ")
- }
- }
- }
- format = buf.String()
- }
- fmt.Printf(format, args...)
-}
-
// ----------------------------------------------------------------------------
// Export format
@@ -1829,44 +123,6 @@ const (
aliasTag
)
-// Debugging support.
-// (tagString is only used when tracing is enabled)
-var tagString = [...]string{
- // Objects
- -packageTag: "package",
- -constTag: "const",
- -typeTag: "type",
- -varTag: "var",
- -funcTag: "func",
- -endTag: "end",
-
- // Types
- -namedTag: "named type",
- -arrayTag: "array",
- -sliceTag: "slice",
- -dddTag: "ddd",
- -structTag: "struct",
- -pointerTag: "pointer",
- -signatureTag: "signature",
- -interfaceTag: "interface",
- -mapTag: "map",
- -chanTag: "chan",
-
- // Values
- -falseTag: "false",
- -trueTag: "true",
- -int64Tag: "int64",
- -floatTag: "float",
- -fractionTag: "fraction",
- -complexTag: "complex",
- -stringTag: "string",
- -nilTag: "nil",
- -unknownTag: "unknown",
-
- // Type aliases
- -aliasTag: "alias",
-}
-
// untype returns the "pseudo" untyped type for a Ctype (import/export use only).
// (we can't use an pre-initialized array because we must be sure all types are
// set up)
diff --git a/src/cmd/compile/internal/gc/bimport.go b/src/cmd/compile/internal/gc/bimport.go
index c19f548e18..7aabae764e 100644
--- a/src/cmd/compile/internal/gc/bimport.go
+++ b/src/cmd/compile/internal/gc/bimport.go
@@ -2,340 +2,19 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Binary package import.
-// See bexport.go for the export data format and how
-// to make a format change.
-
package gc
import (
- "bufio"
"cmd/compile/internal/types"
"cmd/internal/src"
- "encoding/binary"
- "fmt"
- "math/big"
- "strconv"
- "strings"
)
-// The overall structure of Import is symmetric to Export: For each
-// export method in bexport.go there is a matching and symmetric method
-// in bimport.go. Changing the export format requires making symmetric
-// changes to bimport.go and bexport.go.
-
-type importer struct {
- in *bufio.Reader
- imp *types.Pkg // imported package
- buf []byte // reused for reading strings
- version int // export format version
-
- // object lists, in order of deserialization
- strList []string
- pathList []string
- pkgList []*types.Pkg
- typList []*types.Type
- funcList []*Node // nil entry means already declared
- trackAllTypes bool
-
- // for delayed type verification
- cmpList []struct{ pt, t *types.Type }
-
- // position encoding
- posInfoFormat bool
- prevFile string
- prevLine int
- posBase *src.PosBase
-
- // debugging support
- debugFormat bool
- read int // bytes read
-}
-
-// Import populates imp from the serialized package data read from in.
-func Import(imp *types.Pkg, in *bufio.Reader) {
- inimport = true
- defer func() { inimport = false }()
-
- p := importer{
- in: in,
- imp: imp,
- version: -1, // unknown version
- strList: []string{""}, // empty string is mapped to 0
- pathList: []string{""}, // empty path is mapped to 0
- }
-
- // read version info
- var versionstr string
- if b := p.rawByte(); b == 'c' || b == 'd' {
- // Go1.7 encoding; first byte encodes low-level
- // encoding format (compact vs debug).
- // For backward-compatibility only (avoid problems with
- // old installed packages). Newly compiled packages use
- // the extensible format string.
- // TODO(gri) Remove this support eventually; after Go1.8.
- if b == 'd' {
- p.debugFormat = true
- }
- p.trackAllTypes = p.rawByte() == 'a'
- p.posInfoFormat = p.bool()
- versionstr = p.string()
- if versionstr == "v1" {
- p.version = 0
- }
- } else {
- // Go1.8 extensible encoding
- // read version string and extract version number (ignore anything after the version number)
- versionstr = p.rawStringln(b)
- if s := strings.SplitN(versionstr, " ", 3); len(s) >= 2 && s[0] == "version" {
- if v, err := strconv.Atoi(s[1]); err == nil && v > 0 {
- p.version = v
- }
- }
- }
-
- // read version specific flags - extend as necessary
- switch p.version {
- // case 7:
- // ...
- // fallthrough
- case 6, 5, 4, 3, 2, 1:
- p.debugFormat = p.rawStringln(p.rawByte()) == "debug"
- p.trackAllTypes = p.bool()
- p.posInfoFormat = p.bool()
- case 0:
- // Go1.7 encoding format - nothing to do here
- default:
- p.formatErrorf("unknown export format version %d (%q)", p.version, versionstr)
- }
-
- // --- generic export data ---
-
- // populate typList with predeclared "known" types
- p.typList = append(p.typList, predeclared()...)
-
- // read package data
- p.pkg()
-
- // defer some type-checking until all types are read in completely
- tcok := typecheckok
- typecheckok = true
- defercheckwidth()
-
- // read objects
-
- // phase 1
- objcount := 0
- for {
- tag := p.tagOrIndex()
- if tag == endTag {
- break
- }
- p.obj(tag)
- objcount++
- }
-
- // self-verification
- if count := p.int(); count != objcount {
- p.formatErrorf("got %d objects; want %d", objcount, count)
- }
-
- // --- compiler-specific export data ---
-
- // read compiler-specific flags
-
- // phase 2
- objcount = 0
- for {
- tag := p.tagOrIndex()
- if tag == endTag {
- break
- }
- p.obj(tag)
- objcount++
- }
-
- // self-verification
- if count := p.int(); count != objcount {
- p.formatErrorf("got %d objects; want %d", objcount, count)
- }
-
- // read inlineable functions bodies
- if dclcontext != PEXTERN {
- p.formatErrorf("unexpected context %d", dclcontext)
- }
-
- objcount = 0
- for i0 := -1; ; {
- i := p.int() // index of function with inlineable body
- if i < 0 {
- break
- }
-
- // don't process the same function twice
- if i <= i0 {
- p.formatErrorf("index not increasing: %d <= %d", i, i0)
- }
- i0 = i
-
- if Curfn != nil {
- p.formatErrorf("unexpected Curfn %v", Curfn)
- }
-
- // Note: In the original code, funchdr and funcbody are called for
- // all functions (that were not yet imported). Now, we are calling
- // them only for functions with inlineable bodies. funchdr does
- // parameter renaming which doesn't matter if we don't have a body.
-
- inlCost := p.int()
- if f := p.funcList[i]; f != nil && f.Func.Inl == nil {
- // function not yet imported - read body and set it
- funchdr(f)
- body := p.stmtList()
- funcbody()
- f.Func.Inl = &Inline{
- Cost: int32(inlCost),
- Body: body,
- }
- importlist = append(importlist, f)
- if Debug['E'] > 0 && Debug['m'] > 2 {
- if Debug['m'] > 3 {
- fmt.Printf("inl body for %v: %+v\n", f, asNodes(body))
- } else {
- fmt.Printf("inl body for %v: %v\n", f, asNodes(body))
- }
- }
- } else {
- // function already imported - read body but discard declarations
- dclcontext = PDISCARD // throw away any declarations
- p.stmtList()
- dclcontext = PEXTERN
- }
-
- objcount++
- }
-
- // self-verification
- if count := p.int(); count != objcount {
- p.formatErrorf("got %d functions; want %d", objcount, count)
- }
-
- if dclcontext != PEXTERN {
- p.formatErrorf("unexpected context %d", dclcontext)
- }
-
- p.verifyTypes()
-
- // --- end of export data ---
-
- typecheckok = tcok
- resumecheckwidth()
-
- if debug_dclstack != 0 {
- testdclstack()
- }
-}
-
-func (p *importer) formatErrorf(format string, args ...interface{}) {
- if debugFormat {
- Fatalf(format, args...)
- }
-
- yyerror("cannot import %q due to version skew - reinstall package (%s)",
- p.imp.Path, fmt.Sprintf(format, args...))
- errorexit()
-}
-
-func (p *importer) verifyTypes() {
- for _, pair := range p.cmpList {
- pt := pair.pt
- t := pair.t
- if !eqtype(pt.Orig, t) {
- p.formatErrorf("inconsistent definition for type %v during import\n\t%L (in %q)\n\t%L (in %q)", pt.Sym, pt, pt.Sym.Importdef.Path, t, p.imp.Path)
- }
- }
-}
-
// numImport tracks how often a package with a given name is imported.
// It is used to provide a better error message (by using the package
// path to disambiguate) if a package that appears multiple times with
// the same name appears in an error message.
var numImport = make(map[string]int)
-func (p *importer) pkg() *types.Pkg {
- // if the package was seen before, i is its index (>= 0)
- i := p.tagOrIndex()
- if i >= 0 {
- return p.pkgList[i]
- }
-
- // otherwise, i is the package tag (< 0)
- if i != packageTag {
- p.formatErrorf("expected package tag, found tag = %d", i)
- }
-
- // read package data
- name := p.string()
- var path string
- if p.version >= 5 {
- path = p.path()
- } else {
- path = p.string()
- }
- var height int
- if p.version >= 6 {
- height = p.int()
- }
-
- // we should never see an empty package name
- if name == "" {
- p.formatErrorf("empty package name for path %q", path)
- }
-
- // we should never see a bad import path
- if isbadimport(path, true) {
- p.formatErrorf("bad package path %q for package %s", path, name)
- }
-
- // an empty path denotes the package we are currently importing;
- // it must be the first package we see
- if (path == "") != (len(p.pkgList) == 0) {
- p.formatErrorf("package path %q for pkg index %d", path, len(p.pkgList))
- }
-
- if p.version >= 6 {
- if height < 0 || height >= types.MaxPkgHeight {
- p.formatErrorf("bad package height %v for package %s", height, name)
- }
-
- // reexported packages should always have a lower height than
- // the main package
- if len(p.pkgList) != 0 && height >= p.imp.Height {
- p.formatErrorf("package %q (height %d) reexports package %q (height %d)", p.imp.Path, p.imp.Height, path, height)
- }
- }
-
- // add package to pkgList
- pkg := p.imp
- if path != "" {
- pkg = types.NewPkg(path, "")
- }
- if pkg.Name == "" {
- pkg.Name = name
- numImport[name]++
- } else if pkg.Name != name {
- yyerror("conflicting package names %s and %s for path %q", pkg.Name, name, path)
- }
- if myimportpath != "" && path == myimportpath {
- yyerror("import %q: package depends on %q (import cycle)", p.imp.Path, path)
- errorexit()
- }
- pkg.Height = height
- p.pkgList = append(p.pkgList, pkg)
-
- return pkg
-}
-
func idealType(typ *types.Type) *types.Type {
switch typ {
case types.Idealint, types.Idealrune, types.Idealfloat, types.Idealcomplex:
@@ -345,1013 +24,11 @@ func idealType(typ *types.Type) *types.Type {
return typ
}
-func (p *importer) obj(tag int) {
- switch tag {
- case constTag:
- pos := p.pos()
- sym := p.qualifiedName()
- typ := p.typ()
- val := p.value(typ)
- importconst(p.imp, pos, sym, idealType(typ), val)
-
- case aliasTag:
- pos := p.pos()
- sym := p.qualifiedName()
- typ := p.typ()
- importalias(p.imp, pos, sym, typ)
-
- case typeTag:
- p.typ()
-
- case varTag:
- pos := p.pos()
- sym := p.qualifiedName()
- typ := p.typ()
- importvar(p.imp, pos, sym, typ)
-
- case funcTag:
- pos := p.pos()
- sym := p.qualifiedName()
- params := p.paramList()
- result := p.paramList()
-
- sig := functypefield(nil, params, result)
- importfunc(p.imp, pos, sym, sig)
- p.funcList = append(p.funcList, asNode(sym.Def))
-
- default:
- p.formatErrorf("unexpected object (tag = %d)", tag)
- }
-}
-
-func (p *importer) pos() src.XPos {
- if !p.posInfoFormat {
- return src.NoXPos
- }
-
- file := p.prevFile
- line := p.prevLine
- delta := p.int()
- line += delta
- if p.version >= 5 {
- if delta == deltaNewFile {
- if n := p.int(); n >= 0 {
- // file changed
- file = p.path()
- line = n
- }
- }
- } else {
- if delta == 0 {
- if n := p.int(); n >= 0 {
- // file changed
- file = p.prevFile[:n] + p.string()
- line = p.int()
- }
- }
- }
- if file != p.prevFile {
- p.prevFile = file
- p.posBase = src.NewFileBase(file, file)
- }
- p.prevLine = line
-
- pos := src.MakePos(p.posBase, uint(line), 0)
- xpos := Ctxt.PosTable.XPos(pos)
- return xpos
-}
-
-func (p *importer) path() string {
- // if the path was seen before, i is its index (>= 0)
- // (the empty string is at index 0)
- i := p.int()
- if i >= 0 {
- return p.pathList[i]
- }
- // otherwise, i is the negative path length (< 0)
- a := make([]string, -i)
- for n := range a {
- a[n] = p.string()
- }
- s := strings.Join(a, "/")
- p.pathList = append(p.pathList, s)
- return s
-}
-
-func (p *importer) newtyp(etype types.EType) *types.Type {
- t := types.New(etype)
- if p.trackAllTypes {
- p.typList = append(p.typList, t)
- }
- return t
-}
-
-// importtype declares that pt, an imported named type, has underlying type t.
-func (p *importer) importtype(pt, t *types.Type) {
- if pt.Etype == TFORW {
- copytype(typenod(pt), t)
- checkwidth(pt)
- } else {
- // pt.Orig and t must be identical.
- if p.trackAllTypes {
- // If we track all types, t may not be fully set up yet.
- // Collect the types and verify identity later.
- p.cmpList = append(p.cmpList, struct{ pt, t *types.Type }{pt, t})
- } else if !eqtype(pt.Orig, t) {
- yyerror("inconsistent definition for type %v during import\n\t%L (in %q)\n\t%L (in %q)", pt.Sym, pt, pt.Sym.Importdef.Path, t, p.imp.Path)
- }
- }
-
- if Debug['E'] != 0 {
- fmt.Printf("import type %v %L\n", pt, t)
- }
-}
-
-func (p *importer) typ() *types.Type {
- // if the type was seen before, i is its index (>= 0)
- i := p.tagOrIndex()
- if i >= 0 {
- return p.typList[i]
- }
-
- // otherwise, i is the type tag (< 0)
- var t *types.Type
- switch i {
- case namedTag:
- pos := p.pos()
- tsym := p.qualifiedName()
-
- t = importtype(p.imp, pos, tsym)
- p.typList = append(p.typList, t)
- dup := !t.IsKind(types.TFORW) // type already imported
-
- // read underlying type
- t0 := p.typ()
- p.importtype(t, t0)
-
- // interfaces don't have associated methods
- if t0.IsInterface() {
- break
- }
-
- // set correct import context (since p.typ() may be called
- // while importing the body of an inlined function)
- savedContext := dclcontext
- dclcontext = PEXTERN
-
- // read associated methods
- for i := p.int(); i > 0; i-- {
- mpos := p.pos()
- sym := p.fieldSym()
-
- // during import unexported method names should be in the type's package
- if !types.IsExported(sym.Name) && sym.Pkg != tsym.Pkg {
- Fatalf("imported method name %+v in wrong package %s\n", sym, tsym.Pkg.Name)
- }
-
- recv := p.paramList() // TODO(gri) do we need a full param list for the receiver?
- params := p.paramList()
- result := p.paramList()
- nointerface := p.bool()
-
- mt := functypefield(recv[0], params, result)
- oldm := addmethod(sym, mt, false, nointerface)
-
- if dup {
- // An earlier import already declared this type and its methods.
- // Discard the duplicate method declaration.
- n := asNode(oldm.Type.Nname())
- p.funcList = append(p.funcList, n)
- continue
- }
-
- n := newfuncnamel(mpos, methodSym(recv[0].Type, sym))
- n.Type = mt
- n.SetClass(PFUNC)
- checkwidth(n.Type)
- p.funcList = append(p.funcList, n)
-
- // (comment from parser.go)
- // inl.C's inlnode in on a dotmeth node expects to find the inlineable body as
- // (dotmeth's type).Nname.Inl, and dotmeth's type has been pulled
- // out by typecheck's lookdot as this $$.ttype. So by providing
- // this back link here we avoid special casing there.
- mt.SetNname(asTypesNode(n))
-
- if Debug['E'] > 0 {
- fmt.Printf("import [%q] meth %v \n", p.imp.Path, n)
- }
- }
-
- dclcontext = savedContext
-
- case arrayTag:
- t = p.newtyp(TARRAY)
- bound := p.int64()
- elem := p.typ()
- t.Extra = &types.Array{Elem: elem, Bound: bound}
-
- case sliceTag:
- t = p.newtyp(TSLICE)
- elem := p.typ()
- t.Extra = types.Slice{Elem: elem}
-
- case dddTag:
- t = p.newtyp(TDDDFIELD)
- t.Extra = types.DDDField{T: p.typ()}
-
- case structTag:
- t = p.newtyp(TSTRUCT)
- t.SetFields(p.fieldList())
- checkwidth(t)
-
- case pointerTag:
- t = p.newtyp(types.Tptr)
- t.Extra = types.Ptr{Elem: p.typ()}
-
- case signatureTag:
- t = p.newtyp(TFUNC)
- params := p.paramList()
- result := p.paramList()
- functypefield0(t, nil, params, result)
-
- case interfaceTag:
- if ml := p.methodList(); len(ml) == 0 {
- t = types.Types[TINTER]
- } else {
- t = p.newtyp(TINTER)
- t.SetInterface(ml)
- }
-
- case mapTag:
- t = p.newtyp(TMAP)
- mt := t.MapType()
- mt.Key = p.typ()
- mt.Elem = p.typ()
-
- case chanTag:
- t = p.newtyp(TCHAN)
- ct := t.ChanType()
- ct.Dir = types.ChanDir(p.int())
- ct.Elem = p.typ()
-
- default:
- p.formatErrorf("unexpected type (tag = %d)", i)
- }
-
- if t == nil {
- p.formatErrorf("nil type (type tag = %d)", i)
- }
-
- return t
-}
-
-func (p *importer) qualifiedName() *types.Sym {
- name := p.string()
- pkg := p.pkg()
- return pkg.Lookup(name)
-}
-
-func (p *importer) fieldList() (fields []*types.Field) {
- if n := p.int(); n > 0 {
- fields = make([]*types.Field, n)
- for i := range fields {
- fields[i] = p.field()
- }
- }
- return
-}
-
-func (p *importer) field() *types.Field {
- pos := p.pos()
- sym, alias := p.fieldName()
- typ := p.typ()
- note := p.string()
-
- f := types.NewField()
- if sym.Name == "" {
- // anonymous field: typ must be T or *T and T must be a type name
- s := typ.Sym
- if s == nil && typ.IsPtr() {
- s = typ.Elem().Sym // deref
- }
- sym = sym.Pkg.Lookup(s.Name)
- f.Embedded = 1
- } else if alias {
- // anonymous field: we have an explicit name because it's a type alias
- f.Embedded = 1
- }
-
- f.Pos = pos
- f.Sym = sym
- f.Type = typ
- f.Note = note
-
- return f
-}
-
-func (p *importer) methodList() (methods []*types.Field) {
- for n := p.int(); n > 0; n-- {
- f := types.NewField()
- f.Pos = p.pos()
- f.Type = p.typ()
- methods = append(methods, f)
- }
-
- for n := p.int(); n > 0; n-- {
- methods = append(methods, p.method())
- }
-
- return
-}
-
-func (p *importer) method() *types.Field {
- pos := p.pos()
- sym := p.methodName()
- params := p.paramList()
- result := p.paramList()
-
- f := types.NewField()
- f.Pos = pos
- f.Sym = sym
- f.Type = functypefield(fakeRecvField(), params, result)
- return f
-}
-
-func (p *importer) fieldName() (*types.Sym, bool) {
- name := p.string()
- if p.version == 0 && name == "_" {
- // version 0 didn't export a package for _ field names
- // but used the builtin package instead
- return builtinpkg.Lookup(name), false
- }
- pkg := localpkg
- alias := false
- switch name {
- case "":
- // 1) field name matches base type name and is exported: nothing to do
- case "?":
- // 2) field name matches base type name and is not exported: need package
- name = ""
- pkg = p.pkg()
- case "@":
- // 3) field name doesn't match base type name (alias name): need name and possibly package
- name = p.string()
- alias = true
- fallthrough
- default:
- if !types.IsExported(name) {
- pkg = p.pkg()
- }
- }
- return pkg.Lookup(name), alias
-}
-
-func (p *importer) methodName() *types.Sym {
- name := p.string()
- if p.version == 0 && name == "_" {
- // version 0 didn't export a package for _ method names
- // but used the builtin package instead
- return builtinpkg.Lookup(name)
- }
- pkg := localpkg
- if !types.IsExported(name) {
- pkg = p.pkg()
- }
- return pkg.Lookup(name)
-}
-
-func (p *importer) paramList() []*types.Field {
- i := p.int()
- if i == 0 {
- return nil
- }
- // negative length indicates unnamed parameters
- named := true
- if i < 0 {
- i = -i
- named = false
- }
- // i > 0
- fs := make([]*types.Field, i)
- for i := range fs {
- fs[i] = p.param(named)
- }
- return fs
-}
-
-func (p *importer) param(named bool) *types.Field {
- f := types.NewField()
- // TODO(mdempsky): Need param position.
- f.Pos = lineno
- f.Type = p.typ()
- if f.Type.Etype == TDDDFIELD {
- // TDDDFIELD indicates wrapped ... slice type
- f.Type = types.NewSlice(f.Type.DDDField())
- f.SetIsddd(true)
- }
-
- if named {
- name := p.string()
- if name == "" {
- p.formatErrorf("expected named parameter")
- }
- // TODO(gri) Supply function/method package rather than
- // encoding the package for each parameter repeatedly.
- pkg := localpkg
- if name != "_" {
- pkg = p.pkg()
- }
- f.Sym = pkg.Lookup(name)
- }
-
- // TODO(gri) This is compiler-specific (escape info).
- // Move into compiler-specific section eventually?
- f.Note = p.string()
-
- return f
-}
-
-func (p *importer) value(typ *types.Type) (x Val) {
- switch tag := p.tagOrIndex(); tag {
- case falseTag:
- x.U = false
-
- case trueTag:
- x.U = true
-
- case int64Tag:
- u := new(Mpint)
- u.SetInt64(p.int64())
- u.Rune = typ == types.Idealrune
- x.U = u
-
- case floatTag:
- f := newMpflt()
- p.float(f)
- if typ == types.Idealint || typ.IsInteger() || typ.IsPtr() || typ.IsUnsafePtr() {
- // uncommon case: large int encoded as float
- //
- // This happens for unsigned typed integers
- // and (on 64-bit platforms) pointers because
- // of values in the range [2^63, 2^64).
- u := new(Mpint)
- u.SetFloat(f)
- x.U = u
- break
- }
- x.U = f
-
- case complexTag:
- u := new(Mpcplx)
- p.float(&u.Real)
- p.float(&u.Imag)
- x.U = u
-
- case stringTag:
- x.U = p.string()
-
- case unknownTag:
- p.formatErrorf("unknown constant (importing package with errors)")
-
- case nilTag:
- x.U = new(NilVal)
-
- default:
- p.formatErrorf("unexpected value tag %d", tag)
- }
-
- // verify ideal type
- if typ.IsUntyped() && untype(x.Ctype()) != typ {
- p.formatErrorf("value %v and type %v don't match", x, typ)
- }
-
- return
-}
-
-func (p *importer) float(x *Mpflt) {
- sign := p.int()
- if sign == 0 {
- x.SetFloat64(0)
- return
- }
-
- exp := p.int()
- mant := new(big.Int).SetBytes([]byte(p.string()))
-
- m := x.Val.SetInt(mant)
- m.SetMantExp(m, exp-mant.BitLen())
- if sign < 0 {
- m.Neg(m)
- }
-}
-
-// ----------------------------------------------------------------------------
-// Inlined function bodies
-
-// Approach: Read nodes and use them to create/declare the same data structures
-// as done originally by the (hidden) parser by closely following the parser's
-// original code. In other words, "parsing" the import data (which happens to
-// be encoded in binary rather textual form) is the best way at the moment to
-// re-establish the syntax tree's invariants. At some future point we might be
-// able to avoid this round-about way and create the rewritten nodes directly,
-// possibly avoiding a lot of duplicate work (name resolution, type checking).
-//
-// Refined nodes (e.g., ODOTPTR as a refinement of OXDOT) are exported as their
-// unrefined nodes (since this is what the importer uses). The respective case
-// entries are unreachable in the importer.
-
-func (p *importer) stmtList() []*Node {
- var list []*Node
- for {
- n := p.node()
- if n == nil {
- break
- }
- // OBLOCK nodes may be created when importing ODCL nodes - unpack them
- if n.Op == OBLOCK {
- list = append(list, n.List.Slice()...)
- } else {
- list = append(list, n)
- }
- }
- return list
-}
-
-func (p *importer) exprList() []*Node {
- var list []*Node
- for {
- n := p.expr()
- if n == nil {
- break
- }
- list = append(list, n)
- }
- return list
-}
-
-func (p *importer) elemList() []*Node {
- c := p.int()
- list := make([]*Node, c)
- for i := range list {
- s := p.fieldSym()
- list[i] = nodSym(OSTRUCTKEY, p.expr(), s)
- }
- return list
-}
-
-func (p *importer) expr() *Node {
- n := p.node()
- if n != nil && n.Op == OBLOCK {
- Fatalf("unexpected block node: %v", n)
- }
- return n
-}
-
func npos(pos src.XPos, n *Node) *Node {
n.Pos = pos
return n
}
-// TODO(gri) split into expr and stmt
-func (p *importer) node() *Node {
- switch op := p.op(); op {
- // expressions
- // case OPAREN:
- // unreachable - unpacked by exporter
-
- // case ODDDARG:
- // unimplemented
-
- case OLITERAL:
- pos := p.pos()
- typ := p.typ()
- n := npos(pos, nodlit(p.value(typ)))
- n.Type = idealType(typ)
- return n
-
- case ONAME:
- return npos(p.pos(), mkname(p.sym()))
-
- // case OPACK, ONONAME:
- // unreachable - should have been resolved by typechecking
-
- case OTYPE:
- return npos(p.pos(), typenod(p.typ()))
-
- // case OTARRAY, OTMAP, OTCHAN, OTSTRUCT, OTINTER, OTFUNC:
- // unreachable - should have been resolved by typechecking
-
- // case OCLOSURE:
- // unimplemented
-
- case OPTRLIT:
- pos := p.pos()
- n := npos(pos, p.expr())
- if !p.bool() /* !implicit, i.e. '&' operator */ {
- if n.Op == OCOMPLIT {
- // Special case for &T{...}: turn into (*T){...}.
- n.Right = nodl(pos, OIND, n.Right, nil)
- n.Right.SetImplicit(true)
- } else {
- n = nodl(pos, OADDR, n, nil)
- }
- }
- return n
-
- case OSTRUCTLIT:
- // TODO(mdempsky): Export position information for OSTRUCTKEY nodes.
- savedlineno := lineno
- lineno = p.pos()
- n := nodl(lineno, OCOMPLIT, nil, typenod(p.typ()))
- n.List.Set(p.elemList()) // special handling of field names
- lineno = savedlineno
- return n
-
- // case OARRAYLIT, OSLICELIT, OMAPLIT:
- // unreachable - mapped to case OCOMPLIT below by exporter
-
- case OCOMPLIT:
- n := nodl(p.pos(), OCOMPLIT, nil, typenod(p.typ()))
- n.List.Set(p.exprList())
- return n
-
- case OKEY:
- pos := p.pos()
- left, right := p.exprsOrNil()
- return nodl(pos, OKEY, left, right)
-
- // case OSTRUCTKEY:
- // unreachable - handled in case OSTRUCTLIT by elemList
-
- // case OCALLPART:
- // unimplemented
-
- // case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH:
- // unreachable - mapped to case OXDOT below by exporter
-
- case OXDOT:
- // see parser.new_dotname
- return npos(p.pos(), nodSym(OXDOT, p.expr(), p.fieldSym()))
-
- // case ODOTTYPE, ODOTTYPE2:
- // unreachable - mapped to case ODOTTYPE below by exporter
-
- case ODOTTYPE:
- n := nodl(p.pos(), ODOTTYPE, p.expr(), nil)
- n.Type = p.typ()
- return n
-
- // case OINDEX, OINDEXMAP, OSLICE, OSLICESTR, OSLICEARR, OSLICE3, OSLICE3ARR:
- // unreachable - mapped to cases below by exporter
-
- case OINDEX:
- return nodl(p.pos(), op, p.expr(), p.expr())
-
- case OSLICE, OSLICE3:
- n := nodl(p.pos(), op, p.expr(), nil)
- low, high := p.exprsOrNil()
- var max *Node
- if n.Op.IsSlice3() {
- max = p.expr()
- }
- n.SetSliceBounds(low, high, max)
- return n
-
- // case OCONV, OCONVIFACE, OCONVNOP, OARRAYBYTESTR, OARRAYRUNESTR, OSTRARRAYBYTE, OSTRARRAYRUNE, ORUNESTR:
- // unreachable - mapped to OCONV case below by exporter
-
- case OCONV:
- n := nodl(p.pos(), OCONV, p.expr(), nil)
- n.Type = p.typ()
- return n
-
- case OCOPY, OCOMPLEX, OREAL, OIMAG, OAPPEND, OCAP, OCLOSE, ODELETE, OLEN, OMAKE, ONEW, OPANIC, ORECOVER, OPRINT, OPRINTN:
- n := npos(p.pos(), builtinCall(op))
- n.List.Set(p.exprList())
- if op == OAPPEND {
- n.SetIsddd(p.bool())
- }
- return n
-
- // case OCALL, OCALLFUNC, OCALLMETH, OCALLINTER, OGETG:
- // unreachable - mapped to OCALL case below by exporter
-
- case OCALL:
- n := nodl(p.pos(), OCALL, p.expr(), nil)
- n.List.Set(p.exprList())
- n.SetIsddd(p.bool())
- return n
-
- case OMAKEMAP, OMAKECHAN, OMAKESLICE:
- n := npos(p.pos(), builtinCall(OMAKE))
- n.List.Append(typenod(p.typ()))
- n.List.Append(p.exprList()...)
- return n
-
- // unary expressions
- case OPLUS, OMINUS, OADDR, OCOM, OIND, ONOT, ORECV:
- return nodl(p.pos(), op, p.expr(), nil)
-
- // binary expressions
- case OADD, OAND, OANDAND, OANDNOT, ODIV, OEQ, OGE, OGT, OLE, OLT,
- OLSH, OMOD, OMUL, ONE, OOR, OOROR, ORSH, OSEND, OSUB, OXOR:
- return nodl(p.pos(), op, p.expr(), p.expr())
-
- case OADDSTR:
- pos := p.pos()
- list := p.exprList()
- x := npos(pos, list[0])
- for _, y := range list[1:] {
- x = nodl(pos, OADD, x, y)
- }
- return x
-
- // case OCMPSTR, OCMPIFACE:
- // unreachable - mapped to std comparison operators by exporter
-
- case ODCLCONST:
- // TODO(gri) these should not be exported in the first place
- return nodl(p.pos(), OEMPTY, nil, nil)
-
- // --------------------------------------------------------------------
- // statements
- case ODCL:
- if p.version < 2 {
- // versions 0 and 1 exported a bool here but it
- // was always false - simply ignore in this case
- p.bool()
- }
- pos := p.pos()
- lhs := npos(pos, dclname(p.sym()))
- typ := typenod(p.typ())
- return npos(pos, liststmt(variter([]*Node{lhs}, typ, nil))) // TODO(gri) avoid list creation
-
- // case ODCLFIELD:
- // unimplemented
-
- // case OAS, OASWB:
- // unreachable - mapped to OAS case below by exporter
-
- case OAS:
- return nodl(p.pos(), OAS, p.expr(), p.expr())
-
- case OASOP:
- n := nodl(p.pos(), OASOP, nil, nil)
- n.SetSubOp(p.op())
- n.Left = p.expr()
- if !p.bool() {
- n.Right = nodintconst(1)
- n.SetImplicit(true)
- } else {
- n.Right = p.expr()
- }
- return n
-
- // case OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV:
- // unreachable - mapped to OAS2 case below by exporter
-
- case OAS2:
- n := nodl(p.pos(), OAS2, nil, nil)
- n.List.Set(p.exprList())
- n.Rlist.Set(p.exprList())
- return n
-
- case ORETURN:
- n := nodl(p.pos(), ORETURN, nil, nil)
- n.List.Set(p.exprList())
- return n
-
- // case ORETJMP:
- // unreachable - generated by compiler for trampolin routines (not exported)
-
- case OPROC, ODEFER:
- return nodl(p.pos(), op, p.expr(), nil)
-
- case OIF:
- n := nodl(p.pos(), OIF, nil, nil)
- n.Ninit.Set(p.stmtList())
- n.Left = p.expr()
- n.Nbody.Set(p.stmtList())
- n.Rlist.Set(p.stmtList())
- return n
-
- case OFOR:
- n := nodl(p.pos(), OFOR, nil, nil)
- n.Ninit.Set(p.stmtList())
- n.Left, n.Right = p.exprsOrNil()
- n.Nbody.Set(p.stmtList())
- return n
-
- case ORANGE:
- n := nodl(p.pos(), ORANGE, nil, nil)
- n.List.Set(p.stmtList())
- n.Right = p.expr()
- n.Nbody.Set(p.stmtList())
- return n
-
- case OSELECT, OSWITCH:
- n := nodl(p.pos(), op, nil, nil)
- n.Ninit.Set(p.stmtList())
- n.Left, _ = p.exprsOrNil()
- n.List.Set(p.stmtList())
- return n
-
- // case OCASE, OXCASE:
- // unreachable - mapped to OXCASE case below by exporter
-
- case OXCASE:
- n := nodl(p.pos(), OXCASE, nil, nil)
- n.List.Set(p.exprList())
- // TODO(gri) eventually we must declare variables for type switch
- // statements (type switch statements are not yet exported)
- n.Nbody.Set(p.stmtList())
- return n
-
- // case OFALL:
- // unreachable - mapped to OXFALL case below by exporter
-
- case OFALL:
- n := nodl(p.pos(), OFALL, nil, nil)
- return n
-
- case OBREAK, OCONTINUE:
- pos := p.pos()
- left, _ := p.exprsOrNil()
- if left != nil {
- left = newname(left.Sym)
- }
- return nodl(pos, op, left, nil)
-
- // case OEMPTY:
- // unreachable - not emitted by exporter
-
- case OGOTO, OLABEL:
- return nodl(p.pos(), op, newname(p.expr().Sym), nil)
-
- case OEND:
- return nil
-
- default:
- Fatalf("cannot import %v (%d) node\n"+
- "==> please file an issue and assign to gri@\n", op, int(op))
- panic("unreachable") // satisfy compiler
- }
-}
-
func builtinCall(op Op) *Node {
return nod(OCALL, mkname(builtinpkg.Lookup(goopnames[op])), nil)
}
-
-func (p *importer) exprsOrNil() (a, b *Node) {
- ab := p.int()
- if ab&1 != 0 {
- a = p.expr()
- }
- if ab&2 != 0 {
- b = p.node()
- }
- return
-}
-
-func (p *importer) fieldSym() *types.Sym {
- name := p.string()
- pkg := localpkg
- if !types.IsExported(name) {
- pkg = p.pkg()
- }
- return pkg.Lookup(name)
-}
-
-func (p *importer) sym() *types.Sym {
- name := p.string()
- pkg := localpkg
- if name != "_" {
- pkg = p.pkg()
- }
- linkname := p.string()
- sym := pkg.Lookup(name)
- sym.Linkname = linkname
- return sym
-}
-
-func (p *importer) bool() bool {
- return p.int() != 0
-}
-
-func (p *importer) op() Op {
- return Op(p.int())
-}
-
-// ----------------------------------------------------------------------------
-// Low-level decoders
-
-func (p *importer) tagOrIndex() int {
- if p.debugFormat {
- p.marker('t')
- }
-
- return int(p.rawInt64())
-}
-
-func (p *importer) int() int {
- x := p.int64()
- if int64(int(x)) != x {
- p.formatErrorf("exported integer too large")
- }
- return int(x)
-}
-
-func (p *importer) int64() int64 {
- if p.debugFormat {
- p.marker('i')
- }
-
- return p.rawInt64()
-}
-
-func (p *importer) string() string {
- if p.debugFormat {
- p.marker('s')
- }
- // if the string was seen before, i is its index (>= 0)
- // (the empty string is at index 0)
- i := p.rawInt64()
- if i >= 0 {
- return p.strList[i]
- }
- // otherwise, i is the negative string length (< 0)
- if n := int(-i); n <= cap(p.buf) {
- p.buf = p.buf[:n]
- } else {
- p.buf = make([]byte, n)
- }
- for i := range p.buf {
- p.buf[i] = p.rawByte()
- }
- s := string(p.buf)
- p.strList = append(p.strList, s)
- return s
-}
-
-func (p *importer) marker(want byte) {
- if got := p.rawByte(); got != want {
- p.formatErrorf("incorrect marker: got %c; want %c (pos = %d)", got, want, p.read)
- }
-
- pos := p.read
- if n := int(p.rawInt64()); n != pos {
- p.formatErrorf("incorrect position: got %d; want %d", n, pos)
- }
-}
-
-// rawInt64 should only be used by low-level decoders.
-func (p *importer) rawInt64() int64 {
- i, err := binary.ReadVarint(p)
- if err != nil {
- p.formatErrorf("read error: %v", err)
- }
- return i
-}
-
-// rawStringln should only be used to read the initial version string.
-func (p *importer) rawStringln(b byte) string {
- p.buf = p.buf[:0]
- for b != '\n' {
- p.buf = append(p.buf, b)
- b = p.rawByte()
- }
- return string(p.buf)
-}
-
-// needed for binary.ReadVarint in rawInt64
-func (p *importer) ReadByte() (byte, error) {
- return p.rawByte(), nil
-}
-
-// rawByte is the bottleneck interface for reading from p.in.
-// It unescapes '|' 'S' to '$' and '|' '|' to '|'.
-// rawByte should only be used by low-level decoders.
-func (p *importer) rawByte() byte {
- c, err := p.in.ReadByte()
- p.read++
- if err != nil {
- p.formatErrorf("read error: %v", err)
- }
- if c == '|' {
- c, err = p.in.ReadByte()
- p.read++
- if err != nil {
- p.formatErrorf("read error: %v", err)
- }
- switch c {
- case 'S':
- c = '$'
- case '|':
- // nothing to do
- default:
- p.formatErrorf("unexpected escape sequence in export data")
- }
- }
- return c
-}
diff --git a/src/cmd/compile/internal/gc/const.go b/src/cmd/compile/internal/gc/const.go
index 1403a2be11..02d51678be 100644
--- a/src/cmd/compile/internal/gc/const.go
+++ b/src/cmd/compile/internal/gc/const.go
@@ -234,7 +234,7 @@ func convlit1(n *Node, t *types.Type, explicit bool, reuse canReuseNode) *Node {
if n.Op == OLITERAL && !reuse {
// Can't always set n.Type directly on OLITERAL nodes.
// See discussion on CL 20813.
- n = n.copy()
+ n = n.rawcopy()
reuse = true
}
@@ -476,7 +476,7 @@ func toflt(v Val) Val {
f := newMpflt()
f.Set(&u.Real)
if u.Imag.CmpFloat64(0) != 0 {
- yyerror("constant %v%vi truncated to real", fconv(&u.Real, FmtSharp), fconv(&u.Imag, FmtSharp|FmtSign))
+ yyerror("constant %v truncated to real", u.GoString())
}
v.U = f
}
@@ -509,11 +509,11 @@ func toint(v Val) Val {
// value from the error message.
// (See issue #11371).
var t big.Float
- t.Parse(fconv(u, FmtSharp), 10)
+ t.Parse(u.GoString(), 10)
if t.IsInt() {
yyerror("constant truncated to integer")
} else {
- yyerror("constant %v truncated to integer", fconv(u, FmtSharp))
+ yyerror("constant %v truncated to integer", u.GoString())
}
}
}
@@ -522,7 +522,7 @@ func toint(v Val) Val {
case *Mpcplx:
i := new(Mpint)
if !i.SetFloat(&u.Real) || u.Imag.CmpFloat64(0) != 0 {
- yyerror("constant %v%vi truncated to integer", fconv(&u.Real, FmtSharp), fconv(&u.Imag, FmtSharp|FmtSign))
+ yyerror("constant %v truncated to integer", u.GoString())
}
v.U = i
@@ -1200,8 +1200,7 @@ func setconst(n *Node, v Val) {
// Ensure n.Orig still points to a semantically-equivalent
// expression after we rewrite n into a constant.
if n.Orig == n {
- n.Orig = n.copy()
- n.Orig.Orig = n.Orig
+ n.Orig = n.sepcopy()
}
*n = Node{
@@ -1331,7 +1330,7 @@ func defaultlitreuse(n *Node, t *types.Type, reuse canReuseNode) *Node {
}
if n.Op == OLITERAL && !reuse {
- n = n.copy()
+ n = n.rawcopy()
reuse = true
}
diff --git a/src/cmd/compile/internal/gc/dump.go b/src/cmd/compile/internal/gc/dump.go
new file mode 100644
index 0000000000..8de90adf05
--- /dev/null
+++ b/src/cmd/compile/internal/gc/dump.go
@@ -0,0 +1,287 @@
+// Copyright 2018 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.
+
+// This file implements textual dumping of arbitrary data structures
+// for debugging purposes. The code is customized for Node graphs
+// and may be used for an alternative view of the node structure.
+
+package gc
+
+import (
+ "cmd/compile/internal/types"
+ "cmd/internal/src"
+ "fmt"
+ "io"
+ "os"
+ "reflect"
+ "regexp"
+ "unicode"
+ "unicode/utf8"
+)
+
+// dump is like fdump but prints to stderr.
+func dump(root interface{}, filter string, depth int) {
+ fdump(os.Stderr, root, filter, depth)
+}
+
+// fdump prints the structure of a rooted data structure
+// to w by depth-first traversal of the data structure.
+//
+// The filter parameter is a regular expression. If it is
+// non-empty, only struct fields whose names match filter
+// are printed.
+//
+// The depth parameter controls how deep traversal recurses
+// before it returns (higher value means greater depth).
+// If an empty field filter is given, a good depth default value
+// is 4. A negative depth means no depth limit, which may be fine
+// for small data structures or if there is a non-empty filter.
+//
+// In the output, Node structs are identified by their Op name
+// rather than their type; struct fields with zero values or
+// non-matching field names are omitted, and "…" means recursion
+// depth has been reached or struct fields have been omitted.
+func fdump(w io.Writer, root interface{}, filter string, depth int) {
+ if root == nil {
+ fmt.Fprintln(w, "nil")
+ return
+ }
+
+ if filter == "" {
+ filter = ".*" // default
+ }
+
+ p := dumper{
+ output: w,
+ fieldrx: regexp.MustCompile(filter),
+ ptrmap: make(map[uintptr]int),
+ last: '\n', // force printing of line number on first line
+ }
+
+ p.dump(reflect.ValueOf(root), depth)
+ p.printf("\n")
+}
+
+type dumper struct {
+ output io.Writer
+ fieldrx *regexp.Regexp // field name filter
+ ptrmap map[uintptr]int // ptr -> dump line number
+ lastadr string // last address string printed (for shortening)
+
+ // output
+ indent int // current indentation level
+ last byte // last byte processed by Write
+ line int // current line number
+}
+
+var indentBytes = []byte(". ")
+
+func (p *dumper) Write(data []byte) (n int, err error) {
+ var m int
+ for i, b := range data {
+ // invariant: data[0:n] has been written
+ if b == '\n' {
+ m, err = p.output.Write(data[n : i+1])
+ n += m
+ if err != nil {
+ return
+ }
+ } else if p.last == '\n' {
+ p.line++
+ _, err = fmt.Fprintf(p.output, "%6d ", p.line)
+ if err != nil {
+ return
+ }
+ for j := p.indent; j > 0; j-- {
+ _, err = p.output.Write(indentBytes)
+ if err != nil {
+ return
+ }
+ }
+ }
+ p.last = b
+ }
+ if len(data) > n {
+ m, err = p.output.Write(data[n:])
+ n += m
+ }
+ return
+}
+
+// printf is a convenience wrapper.
+func (p *dumper) printf(format string, args ...interface{}) {
+ if _, err := fmt.Fprintf(p, format, args...); err != nil {
+ panic(err)
+ }
+}
+
+// addr returns the (hexadecimal) address string of the object
+// represented by x (or "?" if x is not addressable), with the
+// common prefix between this and the prior address replaced by
+// "0x…" to make it easier to visually match addresses.
+func (p *dumper) addr(x reflect.Value) string {
+ if !x.CanAddr() {
+ return "?"
+ }
+ adr := fmt.Sprintf("%p", x.Addr().Interface())
+ s := adr
+ if i := commonPrefixLen(p.lastadr, adr); i > 0 {
+ s = "0x…" + adr[i:]
+ }
+ p.lastadr = adr
+ return s
+}
+
+// dump prints the contents of x.
+func (p *dumper) dump(x reflect.Value, depth int) {
+ if depth == 0 {
+ p.printf("…")
+ return
+ }
+
+ // special cases
+ switch v := x.Interface().(type) {
+ case Nodes:
+ // unpack Nodes since reflect cannot look inside
+ // due to the unexported field in its struct
+ x = reflect.ValueOf(v.Slice())
+
+ case src.XPos:
+ p.printf("%s", linestr(v))
+ return
+
+ case *types.Node:
+ x = reflect.ValueOf(asNode(v))
+ }
+
+ switch x.Kind() {
+ case reflect.String:
+ p.printf("%q", x.Interface()) // print strings in quotes
+
+ case reflect.Interface:
+ if x.IsNil() {
+ p.printf("nil")
+ return
+ }
+ p.dump(x.Elem(), depth-1)
+
+ case reflect.Ptr:
+ if x.IsNil() {
+ p.printf("nil")
+ return
+ }
+
+ p.printf("*")
+ ptr := x.Pointer()
+ if line, exists := p.ptrmap[ptr]; exists {
+ p.printf("(@%d)", line)
+ return
+ }
+ p.ptrmap[ptr] = p.line
+ p.dump(x.Elem(), depth) // don't count pointer indirection towards depth
+
+ case reflect.Slice:
+ if x.IsNil() {
+ p.printf("nil")
+ return
+ }
+ p.printf("%s (%d entries) {", x.Type(), x.Len())
+ if x.Len() > 0 {
+ p.indent++
+ p.printf("\n")
+ for i, n := 0, x.Len(); i < n; i++ {
+ p.printf("%d: ", i)
+ p.dump(x.Index(i), depth-1)
+ p.printf("\n")
+ }
+ p.indent--
+ }
+ p.printf("}")
+
+ case reflect.Struct:
+ typ := x.Type()
+
+ isNode := false
+ if n, ok := x.Interface().(Node); ok {
+ isNode = true
+ p.printf("%s %s {", n.Op.String(), p.addr(x))
+ } else {
+ p.printf("%s {", typ)
+ }
+ p.indent++
+
+ first := true
+ omitted := false
+ for i, n := 0, typ.NumField(); i < n; i++ {
+ // Exclude non-exported fields because their
+ // values cannot be accessed via reflection.
+ if name := typ.Field(i).Name; isExported(name) {
+ if !p.fieldrx.MatchString(name) {
+ omitted = true
+ continue // field name not selected by filter
+ }
+
+ // special cases
+ if isNode && name == "Op" {
+ omitted = true
+ continue // Op field already printed for Nodes
+ }
+ x := x.Field(i)
+ if isZeroVal(x) {
+ omitted = true
+ continue // exclude zero-valued fields
+ }
+ if n, ok := x.Interface().(Nodes); ok && n.Len() == 0 {
+ omitted = true
+ continue // exclude empty Nodes slices
+ }
+
+ if first {
+ p.printf("\n")
+ first = false
+ }
+ p.printf("%s: ", name)
+ p.dump(x, depth-1)
+ p.printf("\n")
+ }
+ }
+ if omitted {
+ p.printf("…\n")
+ }
+
+ p.indent--
+ p.printf("}")
+
+ default:
+ p.printf("%v", x.Interface())
+ }
+}
+
+func isZeroVal(x reflect.Value) bool {
+ switch x.Kind() {
+ case reflect.Bool:
+ return !x.Bool()
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return x.Int() == 0
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ return x.Uint() == 0
+ case reflect.String:
+ return x.String() == ""
+ case reflect.Interface, reflect.Ptr, reflect.Slice:
+ return x.IsNil()
+ }
+ return false
+}
+
+func isExported(name string) bool {
+ ch, _ := utf8.DecodeRuneInString(name)
+ return unicode.IsUpper(ch)
+}
+
+func commonPrefixLen(a, b string) (i int) {
+ for i < len(a) && i < len(b) && a[i] == b[i] {
+ i++
+ }
+ return
+}
diff --git a/src/cmd/compile/internal/gc/esc.go b/src/cmd/compile/internal/gc/esc.go
index 9db6c8e0b4..145007f5e1 100644
--- a/src/cmd/compile/internal/gc/esc.go
+++ b/src/cmd/compile/internal/gc/esc.go
@@ -654,9 +654,71 @@ func (e *EscState) esclist(l Nodes, parent *Node) {
}
}
+func (e *EscState) isSliceSelfAssign(dst, src *Node) bool {
+ // Detect the following special case.
+ //
+ // func (b *Buffer) Foo() {
+ // n, m := ...
+ // b.buf = b.buf[n:m]
+ // }
+ //
+ // This assignment is a no-op for escape analysis,
+ // it does not store any new pointers into b that were not already there.
+ // However, without this special case b will escape, because we assign to OIND/ODOTPTR.
+ // Here we assume that the statement will not contain calls,
+ // that is, that order will move any calls to init.
+ // Otherwise base ONAME value could change between the moments
+ // when we evaluate it for dst and for src.
+
+ // dst is ONAME dereference.
+ if dst.Op != OIND && dst.Op != ODOTPTR || dst.Left.Op != ONAME {
+ return false
+ }
+ // src is a slice operation.
+ switch src.Op {
+ case OSLICE, OSLICE3, OSLICESTR:
+ // OK.
+ case OSLICEARR, OSLICE3ARR:
+ // Since arrays are embedded into containing object,
+ // slice of non-pointer array will introduce a new pointer into b that was not already there
+ // (pointer to b itself). After such assignment, if b contents escape,
+ // b escapes as well. If we ignore such OSLICEARR, we will conclude
+ // that b does not escape when b contents do.
+ //
+ // Pointer to an array is OK since it's not stored inside b directly.
+ // For slicing an array (not pointer to array), there is an implicit OADDR.
+ // We check that to determine non-pointer array slicing.
+ if src.Left.Op == OADDR {
+ return false
+ }
+ default:
+ return false
+ }
+ // slice is applied to ONAME dereference.
+ if src.Left.Op != OIND && src.Left.Op != ODOTPTR || src.Left.Left.Op != ONAME {
+ return false
+ }
+ // dst and src reference the same base ONAME.
+ return dst.Left == src.Left.Left
+}
+
// isSelfAssign reports whether assignment from src to dst can
// be ignored by the escape analysis as it's effectively a self-assignment.
func (e *EscState) isSelfAssign(dst, src *Node) bool {
+ if e.isSliceSelfAssign(dst, src) {
+ return true
+ }
+
+ // Detect trivial assignments that assign back to the same object.
+ //
+ // It covers these cases:
+ // val.x = val.y
+ // val.x[i] = val.y[j]
+ // val.x1.x2 = val.x1.y2
+ // ... etc
+ //
+ // These assignments do not change assigned object lifetime.
+
if dst == nil || src == nil || dst.Op != src.Op {
return false
}
@@ -689,18 +751,16 @@ func (e *EscState) mayAffectMemory(n *Node) bool {
switch n.Op {
case ONAME, OCLOSUREVAR, OLITERAL:
return false
- case ODOT, ODOTPTR:
- return e.mayAffectMemory(n.Left)
- case OIND, OCONVNOP:
- return e.mayAffectMemory(n.Left)
- case OCONV:
- return e.mayAffectMemory(n.Left)
- case OINDEX:
- return e.mayAffectMemory(n.Left) || e.mayAffectMemory(n.Right)
- case OADD, OSUB, OOR, OXOR, OMUL, OLSH, ORSH, OAND, OANDNOT, ODIV, OMOD:
+
+ // Left+Right group.
+ case OINDEX, OADD, OSUB, OOR, OXOR, OMUL, OLSH, ORSH, OAND, OANDNOT, ODIV, OMOD:
return e.mayAffectMemory(n.Left) || e.mayAffectMemory(n.Right)
- case ONOT, OCOM, OPLUS, OMINUS, OALIGNOF, OOFFSETOF, OSIZEOF:
+
+ // Left group.
+ case ODOT, ODOTPTR, OIND, OCONVNOP, OCONV, OLEN, OCAP,
+ ONOT, OCOM, OPLUS, OMINUS, OALIGNOF, OOFFSETOF, OSIZEOF:
return e.mayAffectMemory(n.Left)
+
default:
return true
}
@@ -832,48 +892,8 @@ opSwitch:
}
}
- // Filter out the following special case.
- //
- // func (b *Buffer) Foo() {
- // n, m := ...
- // b.buf = b.buf[n:m]
- // }
- //
- // This assignment is a no-op for escape analysis,
- // it does not store any new pointers into b that were not already there.
- // However, without this special case b will escape, because we assign to OIND/ODOTPTR.
case OAS, OASOP:
- if (n.Left.Op == OIND || n.Left.Op == ODOTPTR) && n.Left.Left.Op == ONAME && // dst is ONAME dereference
- (n.Right.Op == OSLICE || n.Right.Op == OSLICE3 || n.Right.Op == OSLICESTR) && // src is slice operation
- (n.Right.Left.Op == OIND || n.Right.Left.Op == ODOTPTR) && n.Right.Left.Left.Op == ONAME && // slice is applied to ONAME dereference
- n.Left.Left == n.Right.Left.Left { // dst and src reference the same base ONAME
-
- // Here we also assume that the statement will not contain calls,
- // that is, that order will move any calls to init.
- // Otherwise base ONAME value could change between the moments
- // when we evaluate it for dst and for src.
- //
- // Note, this optimization does not apply to OSLICEARR,
- // because it does introduce a new pointer into b that was not already there
- // (pointer to b itself). After such assignment, if b contents escape,
- // b escapes as well. If we ignore such OSLICEARR, we will conclude
- // that b does not escape when b contents do.
- if Debug['m'] != 0 {
- Warnl(n.Pos, "%v ignoring self-assignment to %S", e.curfnSym(n), n.Left)
- }
-
- break
- }
-
- // Also skip trivial assignments that assign back to the same object.
- //
- // It covers these cases:
- // val.x = val.y
- // val.x[i] = val.y[j]
- // val.x1.x2 = val.x1.y2
- // ... etc
- //
- // These assignments do not change assigned object lifetime.
+ // Filter out some no-op assignments for escape analysis.
if e.isSelfAssign(n.Left, n.Right) {
if Debug['m'] != 0 {
Warnl(n.Pos, "%v ignoring self-assignment in %S", e.curfnSym(n), n)
@@ -1396,7 +1416,7 @@ func describeEscape(em uint16) string {
}
s += "contentToHeap"
}
- for em >>= EscReturnBits; em != 0; em = em >> bitsPerOutputInTag {
+ for em >>= EscReturnBits; em != 0; em >>= bitsPerOutputInTag {
// See encoding description above
if s != "" {
s += " "
@@ -1446,7 +1466,7 @@ func (e *EscState) escassignfromtag(note string, dsts Nodes, src, call *Node) ui
em0 := em
dstsi := 0
- for em >>= EscReturnBits; em != 0 && dstsi < dsts.Len(); em = em >> bitsPerOutputInTag {
+ for em >>= EscReturnBits; em != 0 && dstsi < dsts.Len(); em >>= bitsPerOutputInTag {
// Prefer the lowest-level path to the reference (for escape purposes).
// Two-bit encoding (for example. 1, 3, and 4 bits are other options)
// 01 = 0-level
diff --git a/src/cmd/compile/internal/gc/export.go b/src/cmd/compile/internal/gc/export.go
index 3aa7c39067..6ee660988a 100644
--- a/src/cmd/compile/internal/gc/export.go
+++ b/src/cmd/compile/internal/gc/export.go
@@ -12,8 +12,6 @@ import (
)
var (
- flagiexport bool // if set, use indexed export data format
-
Debug_export int // if set, print debugging information about export data
)
@@ -75,11 +73,7 @@ func dumpexport(bout *bio.Writer) {
// The linker also looks for the $$ marker - use char after $$ to distinguish format.
exportf(bout, "\n$$B\n") // indicate binary export format
off := bout.Offset()
- if flagiexport {
- iexport(bout.Writer)
- } else {
- export(bout.Writer, Debug_export != 0)
- }
+ iexport(bout.Writer)
size := bout.Offset() - off
exportf(bout, "\n$$\n")
@@ -95,7 +89,7 @@ func importsym(ipkg *types.Pkg, s *types.Sym, op Op) *Node {
// declaration for all imported symbols. The exception
// is declarations for Runtimepkg, which are populated
// by loadsys instead.
- if flagiexport && s.Pkg != Runtimepkg {
+ if s.Pkg != Runtimepkg {
Fatalf("missing ONONAME for %v\n", s)
}
diff --git a/src/cmd/compile/internal/gc/float_test.go b/src/cmd/compile/internal/gc/float_test.go
index c0a8cfc89e..c5c604003a 100644
--- a/src/cmd/compile/internal/gc/float_test.go
+++ b/src/cmd/compile/internal/gc/float_test.go
@@ -6,6 +6,8 @@ package gc
import (
"math"
+ "os"
+ "runtime"
"testing"
)
@@ -364,11 +366,19 @@ func TestFloatConvertFolded(t *testing.T) {
func TestFloat32StoreToLoadConstantFold(t *testing.T) {
// Test that math.Float32{,from}bits constant fold correctly.
- // In particular we need to be careful that signalling NaN (sNaN) values
+ // In particular we need to be careful that signaling NaN (sNaN) values
// are not converted to quiet NaN (qNaN) values during compilation.
// See issue #27193 for more information.
- // signalling NaNs
+ // TODO: this method for detecting 387 won't work if the compiler has been
+ // built using GOARCH=386 GO386=387 and either the target is a different
+ // architecture or the GO386=387 environment variable is not set when the
+ // test is run.
+ if runtime.GOARCH == "386" && os.Getenv("GO386") == "387" {
+ t.Skip("signaling NaNs are not propagated on 387 (issue #27516)")
+ }
+
+ // signaling NaNs
{
const nan = uint32(0x7f800001) // sNaN
if x := math.Float32bits(math.Float32frombits(nan)); x != nan {
diff --git a/src/cmd/compile/internal/gc/fmt.go b/src/cmd/compile/internal/gc/fmt.go
index 5b7445d4db..5d2e36ee51 100644
--- a/src/cmd/compile/internal/gc/fmt.go
+++ b/src/cmd/compile/internal/gc/fmt.go
@@ -119,7 +119,7 @@ const (
// *types.Type:
// %#v Go format
// %#L type definition instead of name
-// %#S omit"func" and receiver in function signature
+// %#S omit "func" and receiver in function signature
//
// %-v type identifiers
// %-S type identifiers without "func" and arg names in type signatures (methodsym)
@@ -514,10 +514,10 @@ func (v Val) vconv(s fmt.State, flag FmtFlag) {
case *Mpint:
if !u.Rune {
if flag&FmtSharp != 0 {
- fmt.Fprint(s, bconv(u, FmtSharp))
+ fmt.Fprint(s, u.String())
return
}
- fmt.Fprint(s, bconv(u, 0))
+ fmt.Fprint(s, u.GoString())
return
}
@@ -537,29 +537,19 @@ func (v Val) vconv(s fmt.State, flag FmtFlag) {
case *Mpflt:
if flag&FmtSharp != 0 {
- fmt.Fprint(s, fconv(u, 0))
+ fmt.Fprint(s, u.String())
return
}
- fmt.Fprint(s, fconv(u, FmtSharp))
+ fmt.Fprint(s, u.GoString())
return
case *Mpcplx:
- switch {
- case flag&FmtSharp != 0:
- fmt.Fprintf(s, "(%v+%vi)", &u.Real, &u.Imag)
-
- case v.U.(*Mpcplx).Real.CmpFloat64(0) == 0:
- fmt.Fprintf(s, "%vi", fconv(&u.Imag, FmtSharp))
-
- case v.U.(*Mpcplx).Imag.CmpFloat64(0) == 0:
- fmt.Fprint(s, fconv(&u.Real, FmtSharp))
-
- case v.U.(*Mpcplx).Imag.CmpFloat64(0) < 0:
- fmt.Fprintf(s, "(%v%vi)", fconv(&u.Real, FmtSharp), fconv(&u.Imag, FmtSharp))
-
- default:
- fmt.Fprintf(s, "(%v+%vi)", fconv(&u.Real, FmtSharp), fconv(&u.Imag, FmtSharp))
+ if flag&FmtSharp != 0 {
+ fmt.Fprint(s, u.String())
+ return
}
+ fmt.Fprint(s, u.GoString())
+ return
case string:
fmt.Fprint(s, strconv.Quote(u))
@@ -671,7 +661,7 @@ func typefmt(t *types.Type, flag FmtFlag, mode fmtMode, depth int) string {
return "error"
}
- // Unless the 'l' flag was specified, if the type has a name, just print that name.
+ // Unless the 'L' flag was specified, if the type has a name, just print that name.
if flag&FmtLong == 0 && t.Sym != nil && t != types.Types[t.Etype] {
switch mode {
case FTypeId, FTypeIdName:
@@ -1314,16 +1304,14 @@ func (n *Node) exprfmt(s fmt.State, prec int, mode fmtMode) {
mode.Fprintf(s, "%v { %v }", n.Type, n.Func.Closure.Nbody)
case OCOMPLIT:
- ptrlit := n.Right != nil && n.Right.Implicit() && n.Right.Type != nil && n.Right.Type.IsPtr()
if mode == FErr {
if n.Right != nil && n.Right.Type != nil && !n.Implicit() {
- if ptrlit {
+ if n.Right.Implicit() && n.Right.Type.IsPtr() {
mode.Fprintf(s, "&%v literal", n.Right.Type.Elem())
return
- } else {
- mode.Fprintf(s, "%v literal", n.Right.Type)
- return
}
+ mode.Fprintf(s, "%v literal", n.Right.Type)
+ return
}
fmt.Fprint(s, "composite literal")
@@ -1532,9 +1520,8 @@ func (n *Node) exprfmt(s fmt.State, prec int, mode fmtMode) {
func (n *Node) nodefmt(s fmt.State, flag FmtFlag, mode fmtMode) {
t := n.Type
- // We almost always want the original, except in export mode for literals.
- // This saves the importer some work, and avoids us having to redo some
- // special casing for package unsafe.
+ // We almost always want the original.
+ // TODO(gri) Why the special case for OLITERAL?
if n.Op != OLITERAL && n.Orig != nil {
n = n.Orig
}
diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go
index fb5a413b84..f188c9a9cd 100644
--- a/src/cmd/compile/internal/gc/inl.go
+++ b/src/cmd/compile/internal/gc/inl.go
@@ -71,9 +71,7 @@ func fnpkg(fn *Node) *types.Pkg {
func typecheckinl(fn *Node) {
lno := setlineno(fn)
- if flagiexport {
- expandInline(fn)
- }
+ expandInline(fn)
// typecheckinl is only for imported functions;
// their bodies may refer to unsafe as long as the package
diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go
index 44cf75e7c9..68f6294724 100644
--- a/src/cmd/compile/internal/gc/main.go
+++ b/src/cmd/compile/internal/gc/main.go
@@ -249,7 +249,6 @@ func Main(archInit func(*Arch)) {
flag.StringVar(&blockprofile, "blockprofile", "", "write block profile to `file`")
flag.StringVar(&mutexprofile, "mutexprofile", "", "write mutex profile to `file`")
flag.StringVar(&benchfile, "bench", "", "append benchmark times to `file`")
- flag.BoolVar(&flagiexport, "iexport", true, "export indexed package data")
objabi.Flagparse(usage)
// Record flags that affect the build result. (And don't
@@ -1129,24 +1128,13 @@ func importfile(f *Val) *types.Pkg {
errorexit()
}
- // New indexed format is distinguished by an 'i' byte,
- // whereas old export format always starts with 'c', 'd', or 'v'.
- if c == 'i' {
- if !flagiexport {
- yyerror("import %s: cannot import package compiled with -iexport=true", file)
- errorexit()
- }
-
- iimport(importpkg, imp)
- } else {
- if flagiexport {
- yyerror("import %s: cannot import package compiled with -iexport=false", file)
- errorexit()
- }
-
- imp.UnreadByte()
- Import(importpkg, imp.Reader)
+ // Indexed format is distinguished by an 'i' byte,
+ // whereas previous export formats started with 'c', 'd', or 'v'.
+ if c != 'i' {
+ yyerror("import %s: unexpected package format byte: %v", file, c)
+ errorexit()
}
+ iimport(importpkg, imp)
default:
yyerror("no import in %q", path_)
diff --git a/src/cmd/compile/internal/gc/mpfloat.go b/src/cmd/compile/internal/gc/mpfloat.go
index 5977ef9748..d1f5cb1200 100644
--- a/src/cmd/compile/internal/gc/mpfloat.go
+++ b/src/cmd/compile/internal/gc/mpfloat.go
@@ -201,24 +201,16 @@ func (a *Mpflt) SetString(as string) {
}
func (f *Mpflt) String() string {
- return fconv(f, 0)
+ return f.Val.Text('b', 0)
}
-func fconv(fvp *Mpflt, flag FmtFlag) string {
- if flag&FmtSharp == 0 {
- return fvp.Val.Text('b', 0)
- }
-
- // use decimal format for error messages
-
+func (fvp *Mpflt) GoString() string {
// determine sign
+ sign := ""
f := &fvp.Val
- var sign string
if f.Sign() < 0 {
sign = "-"
f = new(big.Float).Abs(f)
- } else if flag&FmtSign != 0 {
- sign = "+"
}
// Don't try to convert infinities (will not terminate).
@@ -334,3 +326,34 @@ func (v *Mpcplx) Div(rv *Mpcplx) bool {
return true
}
+
+func (v *Mpcplx) String() string {
+ return fmt.Sprintf("(%s+%si)", v.Real.String(), v.Imag.String())
+}
+
+func (v *Mpcplx) GoString() string {
+ var re string
+ sre := v.Real.CmpFloat64(0)
+ if sre != 0 {
+ re = v.Real.GoString()
+ }
+
+ var im string
+ sim := v.Imag.CmpFloat64(0)
+ if sim != 0 {
+ im = v.Imag.GoString()
+ }
+
+ switch {
+ case sre == 0 && sim == 0:
+ return "0"
+ case sre == 0:
+ return im + "i"
+ case sim == 0:
+ return re
+ case sim < 0:
+ return fmt.Sprintf("(%s%si)", re, im)
+ default:
+ return fmt.Sprintf("(%s+%si)", re, im)
+ }
+}
diff --git a/src/cmd/compile/internal/gc/mpint.go b/src/cmd/compile/internal/gc/mpint.go
index de47205435..e4dd22d0a0 100644
--- a/src/cmd/compile/internal/gc/mpint.go
+++ b/src/cmd/compile/internal/gc/mpint.go
@@ -299,13 +299,10 @@ func (a *Mpint) SetString(as string) {
}
}
-func (a *Mpint) String() string {
- return bconv(a, 0)
+func (a *Mpint) GoString() string {
+ return a.Val.String()
}
-func bconv(xval *Mpint, flag FmtFlag) string {
- if flag&FmtSharp != 0 {
- return fmt.Sprintf("%#x", &xval.Val)
- }
- return xval.Val.String()
+func (a *Mpint) String() string {
+ return fmt.Sprintf("%#x", &a.Val)
}
diff --git a/src/cmd/compile/internal/gc/obj.go b/src/cmd/compile/internal/gc/obj.go
index fb749d171f..19862c03aa 100644
--- a/src/cmd/compile/internal/gc/obj.go
+++ b/src/cmd/compile/internal/gc/obj.go
@@ -281,7 +281,7 @@ func dumpglobls() {
funcsyms = nil
}
-// addGCLocals adds gcargs and gclocals symbols to Ctxt.Data.
+// addGCLocals adds gcargs, gclocals, gcregs, and stack object symbols to Ctxt.Data.
// It takes care not to add any duplicates.
// Though the object file format handles duplicates efficiently,
// storing only a single copy of the data,
@@ -299,6 +299,9 @@ func addGCLocals() {
Ctxt.Data = append(Ctxt.Data, gcsym)
seen[gcsym.Name] = true
}
+ if x := s.Func.StackObjects; x != nil {
+ ggloblsym(x, int32(len(x.P)), obj.RODATA|obj.LOCAL)
+ }
}
}
diff --git a/src/cmd/compile/internal/gc/op_string.go b/src/cmd/compile/internal/gc/op_string.go
index 857234e45d..90b95d769f 100644
--- a/src/cmd/compile/internal/gc/op_string.go
+++ b/src/cmd/compile/internal/gc/op_string.go
@@ -4,9 +4,9 @@ package gc
import "strconv"
-const _Op_name = "XXXNAMENONAMETYPEPACKLITERALADDSUBORXORADDSTRADDRANDANDAPPENDARRAYBYTESTRARRAYBYTESTRTMPARRAYRUNESTRSTRARRAYBYTESTRARRAYBYTETMPSTRARRAYRUNEASAS2AS2FUNCAS2RECVAS2MAPRAS2DOTTYPEASOPCALLCALLFUNCCALLMETHCALLINTERCALLPARTCAPCLOSECLOSURECMPIFACECMPSTRCOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLFIELDDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTINDINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMULDIVMODLSHRSHANDANDNOTNEWNOTCOMPLUSMINUSORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRRECOVERRECVRUNESTRSELRECVSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFBLOCKBREAKCASEXCASECONTINUEDEFEREMPTYFALLFORFORUNTILGOTOIFLABELPROCRANGERETURNSELECTSWITCHTYPESWTCHANTMAPTSTRUCTTINTERTFUNCTARRAYDDDDDDARGINLCALLEFACEITABIDATASPTRCLOSUREVARCFUNCCHECKNILVARKILLVARLIVEINDREGSPRETJMPGETGEND"
+const _Op_name = "XXXNAMENONAMETYPEPACKLITERALADDSUBORXORADDSTRADDRANDANDAPPENDARRAYBYTESTRARRAYBYTESTRTMPARRAYRUNESTRSTRARRAYBYTESTRARRAYBYTETMPSTRARRAYRUNEASAS2AS2FUNCAS2RECVAS2MAPRAS2DOTTYPEASOPCALLCALLFUNCCALLMETHCALLINTERCALLPARTCAPCLOSECLOSURECMPIFACECMPSTRCOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLFIELDDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTINDINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMULDIVMODLSHRSHANDANDNOTNEWNOTCOMPLUSMINUSORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRRECOVERRECVRUNESTRSELRECVSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFBLOCKBREAKCASEXCASECONTINUEDEFEREMPTYFALLFORFORUNTILGOTOIFLABELPROCRANGERETURNSELECTSWITCHTYPESWTCHANTMAPTSTRUCTTINTERTFUNCTARRAYDDDDDDARGINLCALLEFACEITABIDATASPTRCLOSUREVARCFUNCCHECKNILVARDEFVARKILLVARLIVEINDREGSPRETJMPGETGEND"
-var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 36, 39, 45, 49, 55, 61, 73, 88, 100, 112, 127, 139, 141, 144, 151, 158, 165, 175, 179, 183, 191, 199, 208, 216, 219, 224, 231, 239, 245, 252, 258, 267, 275, 283, 289, 293, 302, 309, 313, 316, 323, 331, 339, 346, 352, 355, 361, 368, 376, 380, 387, 395, 397, 399, 401, 403, 405, 407, 410, 415, 423, 426, 435, 438, 442, 450, 457, 466, 469, 472, 475, 478, 481, 484, 490, 493, 496, 499, 503, 508, 512, 517, 522, 528, 533, 537, 542, 550, 558, 564, 573, 580, 584, 591, 598, 606, 610, 614, 618, 625, 632, 640, 646, 651, 656, 660, 665, 673, 678, 683, 687, 690, 698, 702, 704, 709, 713, 718, 724, 730, 736, 742, 747, 751, 758, 764, 769, 775, 778, 784, 791, 796, 800, 805, 809, 819, 824, 832, 839, 846, 854, 860, 864, 867}
+var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 36, 39, 45, 49, 55, 61, 73, 88, 100, 112, 127, 139, 141, 144, 151, 158, 165, 175, 179, 183, 191, 199, 208, 216, 219, 224, 231, 239, 245, 252, 258, 267, 275, 283, 289, 293, 302, 309, 313, 316, 323, 331, 339, 346, 352, 355, 361, 368, 376, 380, 387, 395, 397, 399, 401, 403, 405, 407, 410, 415, 423, 426, 435, 438, 442, 450, 457, 466, 469, 472, 475, 478, 481, 484, 490, 493, 496, 499, 503, 508, 512, 517, 522, 528, 533, 537, 542, 550, 558, 564, 573, 580, 584, 591, 598, 606, 610, 614, 618, 625, 632, 640, 646, 651, 656, 660, 665, 673, 678, 683, 687, 690, 698, 702, 704, 709, 713, 718, 724, 730, 736, 742, 747, 751, 758, 764, 769, 775, 778, 784, 791, 796, 800, 805, 809, 819, 824, 832, 838, 845, 852, 860, 866, 870, 873}
func (i Op) String() string {
if i >= Op(len(_Op_index)-1) {
diff --git a/src/cmd/compile/internal/gc/order.go b/src/cmd/compile/internal/gc/order.go
index dce68a6c17..1e22ecfcdf 100644
--- a/src/cmd/compile/internal/gc/order.go
+++ b/src/cmd/compile/internal/gc/order.go
@@ -109,8 +109,7 @@ func (o *Order) cheapExpr(n *Node) *Node {
if l == n.Left {
return n
}
- a := n.copy()
- a.Orig = a
+ a := n.sepcopy()
a.Left = l
return typecheck(a, Erv)
}
@@ -135,8 +134,7 @@ func (o *Order) safeExpr(n *Node) *Node {
if l == n.Left {
return n
}
- a := n.copy()
- a.Orig = a
+ a := n.sepcopy()
a.Left = l
return typecheck(a, Erv)
@@ -145,8 +143,7 @@ func (o *Order) safeExpr(n *Node) *Node {
if l == n.Left {
return n
}
- a := n.copy()
- a.Orig = a
+ a := n.sepcopy()
a.Left = l
return typecheck(a, Erv)
@@ -161,8 +158,7 @@ func (o *Order) safeExpr(n *Node) *Node {
if l == n.Left && r == n.Right {
return n
}
- a := n.copy()
- a.Orig = a
+ a := n.sepcopy()
a.Left = l
a.Right = r
return typecheck(a, Erv)
diff --git a/src/cmd/compile/internal/gc/pgen.go b/src/cmd/compile/internal/gc/pgen.go
index 563eb9e966..e6bbf04400 100644
--- a/src/cmd/compile/internal/gc/pgen.go
+++ b/src/cmd/compile/internal/gc/pgen.go
@@ -233,6 +233,26 @@ func compile(fn *Node) {
// Set up the function's LSym early to avoid data races with the assemblers.
fn.Func.initLSym()
+ // Make sure type syms are declared for all types that might
+ // be types of stack objects. We need to do this here
+ // because symbols must be allocated before the parallel
+ // phase of the compiler.
+ if fn.Func.lsym != nil { // not func _(){}
+ for _, n := range fn.Func.Dcl {
+ switch n.Class() {
+ case PPARAM, PPARAMOUT, PAUTO:
+ if livenessShouldTrack(n) && n.Addrtaken() {
+ dtypesym(n.Type)
+ // Also make sure we allocate a linker symbol
+ // for the stack object data, for the same reason.
+ if fn.Func.lsym.Func.StackObjects == nil {
+ fn.Func.lsym.Func.StackObjects = lookup(fmt.Sprintf("%s.stkobj", fn.funcname())).Linksym()
+ }
+ }
+ }
+ }
+ }
+
if compilenow() {
compileSSA(fn, 0)
} else {
diff --git a/src/cmd/compile/internal/gc/plive.go b/src/cmd/compile/internal/gc/plive.go
index e070a5cd1a..563b425db7 100644
--- a/src/cmd/compile/internal/gc/plive.go
+++ b/src/cmd/compile/internal/gc/plive.go
@@ -78,6 +78,10 @@ import (
// that its argument is certainly dead, for use when the liveness analysis
// would not otherwise be able to deduce that fact.
+// TODO: get rid of OpVarKill here. It's useful for stack frame allocation
+// so the compiler can allocate two temps to the same location. Here it's now
+// useless, since the implementation of stack objects.
+
// BlockEffects summarizes the liveness effects on an SSA block.
type BlockEffects struct {
// Computed during Liveness.prologue using only the content of
@@ -85,23 +89,15 @@ type BlockEffects struct {
//
// uevar: upward exposed variables (used before set in block)
// varkill: killed variables (set in block)
- // avarinit: addrtaken variables set or used (proof of initialization)
- uevar varRegVec
- varkill varRegVec
- avarinit bvec
+ uevar varRegVec
+ varkill varRegVec
// Computed during Liveness.solve using control flow information:
//
// livein: variables live at block entry
// liveout: variables live at block exit
- // avarinitany: addrtaken variables possibly initialized at block exit
- // (initialized in block or at exit from any predecessor block)
- // avarinitall: addrtaken variables certainly initialized at block exit
- // (initialized in block or at exit from all predecessor blocks)
- livein varRegVec
- liveout varRegVec
- avarinitany bvec
- avarinitall bvec
+ livein varRegVec
+ liveout varRegVec
}
// A collection of global state used by liveness analysis.
@@ -186,10 +182,9 @@ func (idx LivenessIndex) Valid() bool {
}
type progeffectscache struct {
- textavarinit []int32
- retuevar []int32
- tailuevar []int32
- initialized bool
+ retuevar []int32
+ tailuevar []int32
+ initialized bool
}
// varRegVec contains liveness bitmaps for variables and registers.
@@ -264,24 +259,13 @@ func (lv *Liveness) initcache() {
// all the parameters for correctness, and similarly it must not
// read the out arguments - they won't be set until the new
// function runs.
-
lv.cache.tailuevar = append(lv.cache.tailuevar, int32(i))
- if node.Addrtaken() {
- lv.cache.textavarinit = append(lv.cache.textavarinit, int32(i))
- }
-
case PPARAMOUT:
- // If the result had its address taken, it is being tracked
- // by the avarinit code, which does not use uevar.
- // If we added it to uevar too, we'd not see any kill
- // and decide that the variable was live entry, which it is not.
- // So only use uevar in the non-addrtaken case.
- // The p.to.type == obj.TYPE_NONE limits the bvset to
- // non-tail-call return instructions; see note below for details.
- if !node.Addrtaken() {
- lv.cache.retuevar = append(lv.cache.retuevar, int32(i))
- }
+ // All results are live at every return point.
+ // Note that this point is after escaping return values
+ // are copied back to the stack using their PAUTOHEAP references.
+ lv.cache.retuevar = append(lv.cache.retuevar, int32(i))
}
}
}
@@ -291,21 +275,13 @@ func (lv *Liveness) initcache() {
//
// The possible flags are:
// uevar - used by the instruction
-// varkill - killed by the instruction
-// for variables without address taken, means variable was set
-// for variables with address taken, means variable was marked dead
-// avarinit - initialized or referred to by the instruction,
-// only for variables with address taken but not escaping to heap
-//
-// The avarinit output serves as a signal that the data has been
-// initialized, because any use of a variable must come after its
-// initialization.
+// varkill - killed by the instruction (set)
+// A kill happens after the use (for an instruction that updates a value, for example).
type liveEffect int
const (
uevar liveEffect = 1 << iota
varkill
- avarinit
)
// valueEffects returns the index of a variable in lv.vars and the
@@ -329,27 +305,15 @@ func (lv *Liveness) valueEffects(v *ssa.Value) (int32, liveEffect) {
}
var effect liveEffect
- if n.Addrtaken() {
- if v.Op != ssa.OpVarKill {
- effect |= avarinit
- }
- if v.Op == ssa.OpVarDef || v.Op == ssa.OpVarKill {
- effect |= varkill
- }
- } else {
- // Read is a read, obviously.
- // Addr by itself is also implicitly a read.
- //
- // Addr|Write means that the address is being taken
- // but only so that the instruction can write to the value.
- // It is not a read.
-
- if e&ssa.SymRead != 0 || e&(ssa.SymAddr|ssa.SymWrite) == ssa.SymAddr {
- effect |= uevar
- }
- if e&ssa.SymWrite != 0 && (!isfat(n.Type) || v.Op == ssa.OpVarDef) {
- effect |= varkill
- }
+ // Read is a read, obviously.
+ //
+ // Addr is a read also, as any subseqent holder of the pointer must be able
+ // to see all the values (including initialization) written so far.
+ if e&(ssa.SymRead|ssa.SymAddr) != 0 {
+ effect |= uevar
+ }
+ if e&ssa.SymWrite != 0 && (!isfat(n.Type) || v.Op == ssa.OpVarDef) {
+ effect |= varkill
}
if effect == 0 {
@@ -545,9 +509,6 @@ func newliveness(fn *Node, f *ssa.Func, vars []*Node, idx map[*Node]int32, stkpt
be.varkill = varRegVec{vars: bulk.next()}
be.livein = varRegVec{vars: bulk.next()}
be.liveout = varRegVec{vars: bulk.next()}
- be.avarinit = bulk.next()
- be.avarinitany = bulk.next()
- be.avarinitall = bulk.next()
}
lv.livenessMap.reset(lv.f.NumValues())
@@ -869,19 +830,6 @@ func (lv *Liveness) prologue() {
}
be.uevar.regs |= regUevar
}
-
- // Walk the block instructions forward to update avarinit bits.
- // avarinit describes the effect at the end of the block, not the beginning.
- for _, val := range b.Values {
- pos, e := lv.valueEffects(val)
- // No need for regEffects because registers never appear in avarinit.
- if e&varkill != 0 {
- be.avarinit.Unset(pos)
- }
- if e&avarinit != 0 {
- be.avarinit.Set(pos)
- }
- }
}
}
@@ -892,51 +840,10 @@ func (lv *Liveness) solve() {
nvars := int32(len(lv.vars))
newlivein := varRegVec{vars: bvalloc(nvars)}
newliveout := varRegVec{vars: bvalloc(nvars)}
- any := bvalloc(nvars)
- all := bvalloc(nvars)
- // Push avarinitall, avarinitany forward.
- // avarinitall says the addressed var is initialized along all paths reaching the block exit.
- // avarinitany says the addressed var is initialized along some path reaching the block exit.
- for _, b := range lv.f.Blocks {
- be := lv.blockEffects(b)
- if b == lv.f.Entry {
- be.avarinitall.Copy(be.avarinit)
- } else {
- be.avarinitall.Clear()
- be.avarinitall.Not()
- }
- be.avarinitany.Copy(be.avarinit)
- }
-
- // Walk blocks in the general direction of propagation (RPO
- // for avarinit{any,all}, and PO for live{in,out}). This
- // improves convergence.
+ // Walk blocks in postorder ordering. This improves convergence.
po := lv.f.Postorder()
- for change := true; change; {
- change = false
- for i := len(po) - 1; i >= 0; i-- {
- b := po[i]
- be := lv.blockEffects(b)
- lv.avarinitanyall(b, any, all)
-
- any.AndNot(any, be.varkill.vars)
- all.AndNot(all, be.varkill.vars)
- any.Or(any, be.avarinit)
- all.Or(all, be.avarinit)
- if !any.Eq(be.avarinitany) {
- change = true
- be.avarinitany.Copy(any)
- }
-
- if !all.Eq(be.avarinitall) {
- change = true
- be.avarinitall.Copy(all)
- }
- }
- }
-
// Iterate through the blocks in reverse round-robin fashion. A work
// queue might be slightly faster. As is, the number of iterations is
// so low that it hardly seems to be worth the complexity.
@@ -957,7 +864,7 @@ func (lv *Liveness) solve() {
newliveout.vars.Set(pos)
}
case ssa.BlockExit:
- // nothing to do
+ // panic exit - nothing to do
default:
// A variable is live on output from this block
// if it is live on input to some successor.
@@ -975,7 +882,7 @@ func (lv *Liveness) solve() {
}
// A variable is live on input to this block
- // if it is live on output from this block and
+ // if it is used by this block, or live on output from this block and
// not set by the code in this block.
//
// in[b] = uevar[b] \cup (out[b] \setminus varkill[b])
@@ -990,8 +897,6 @@ func (lv *Liveness) solve() {
func (lv *Liveness) epilogue() {
nvars := int32(len(lv.vars))
liveout := varRegVec{vars: bvalloc(nvars)}
- any := bvalloc(nvars)
- all := bvalloc(nvars)
livedefer := bvalloc(nvars) // always-live variables
// If there is a defer (that could recover), then all output
@@ -1017,6 +922,9 @@ func (lv *Liveness) epilogue() {
livedefer.Set(int32(i))
}
if n.IsOutputParamHeapAddr() {
+ // This variable will be overwritten early in the function
+ // prologue (from the result of a mallocgc) but we need to
+ // zero it in case that malloc causes a stack scan.
n.Name.SetNeedzero(true)
livedefer.Set(int32(i))
}
@@ -1033,9 +941,6 @@ func (lv *Liveness) epilogue() {
{
// Reserve an entry for function entry.
live := bvalloc(nvars)
- for _, pos := range lv.cache.textavarinit {
- live.Set(pos)
- }
lv.livevars = append(lv.livevars, varRegVec{vars: live})
}
@@ -1043,53 +948,14 @@ func (lv *Liveness) epilogue() {
be := lv.blockEffects(b)
firstBitmapIndex := len(lv.livevars)
- // Compute avarinitany and avarinitall for entry to block.
- // This duplicates information known during Liveness.solve
- // but avoids storing two more vectors for each block.
- lv.avarinitanyall(b, any, all)
-
// Walk forward through the basic block instructions and
// allocate liveness maps for those instructions that need them.
- // Seed the maps with information about the addrtaken variables.
for _, v := range b.Values {
- pos, e := lv.valueEffects(v)
- // No need for regEffects because registers never appear in avarinit.
- if e&varkill != 0 {
- any.Unset(pos)
- all.Unset(pos)
- }
- if e&avarinit != 0 {
- any.Set(pos)
- all.Set(pos)
- }
-
if !lv.issafepoint(v) {
continue
}
- // Annotate ambiguously live variables so that they can
- // be zeroed at function entry and at VARKILL points.
- // liveout is dead here and used as a temporary.
- liveout.vars.AndNot(any, all)
- if !liveout.vars.IsEmpty() {
- for pos := int32(0); pos < liveout.vars.n; pos++ {
- if !liveout.vars.Get(pos) {
- continue
- }
- all.Set(pos) // silence future warnings in this block
- n := lv.vars[pos]
- if !n.Name.Needzero() {
- n.Name.SetNeedzero(true)
- if debuglive >= 1 {
- Warnl(v.Pos, "%v: %L is ambiguously live", lv.fn.Func.Nname, n)
- }
- }
- }
- }
-
- // Live stuff first.
live := bvalloc(nvars)
- live.Copy(any)
lv.livevars = append(lv.livevars, varRegVec{vars: live})
}
@@ -1128,6 +994,17 @@ func (lv *Liveness) epilogue() {
Fatalf("bad index for entry point: %v", index)
}
+ // Check to make sure only input variables are live.
+ for i, n := range lv.vars {
+ if !liveout.vars.Get(int32(i)) {
+ continue
+ }
+ if n.Class() == PPARAM {
+ continue // ok
+ }
+ Fatalf("bad live variable at entry of %v: %L", lv.fn.Func.Nname, n)
+ }
+
// Record live variables.
live := &lv.livevars[index]
live.Or(*live, liveout)
@@ -1330,28 +1207,6 @@ func clobberPtr(b *ssa.Block, v *Node, offset int64) {
b.NewValue0IA(src.NoXPos, ssa.OpClobber, types.TypeVoid, offset, v)
}
-func (lv *Liveness) avarinitanyall(b *ssa.Block, any, all bvec) {
- if len(b.Preds) == 0 {
- any.Clear()
- all.Clear()
- for _, pos := range lv.cache.textavarinit {
- any.Set(pos)
- all.Set(pos)
- }
- return
- }
-
- be := lv.blockEffects(b.Preds[0].Block())
- any.Copy(be.avarinitany)
- all.Copy(be.avarinitall)
-
- for _, pred := range b.Preds[1:] {
- be := lv.blockEffects(pred.Block())
- any.Or(any, be.avarinitany)
- all.And(all, be.avarinitall)
- }
-}
-
// Compact coalesces identical bitmaps from lv.livevars into the sets
// lv.stackMapSet and lv.regMaps.
//
@@ -1559,7 +1414,6 @@ func (lv *Liveness) printDebug() {
printed = false
printed = lv.printeffect(printed, "uevar", pos, effect&uevar != 0, regUevar)
printed = lv.printeffect(printed, "varkill", pos, effect&varkill != 0, regKill)
- printed = lv.printeffect(printed, "avarinit", pos, effect&avarinit != 0, 0)
if printed {
fmt.Printf("\n")
}
@@ -1596,9 +1450,6 @@ func (lv *Liveness) printDebug() {
printed = false
printed = lv.printbvec(printed, "varkill", be.varkill)
printed = lv.printbvec(printed, "liveout", be.liveout)
- printed = lv.printbvec(printed, "avarinit", varRegVec{vars: be.avarinit})
- printed = lv.printbvec(printed, "avarinitany", varRegVec{vars: be.avarinitany})
- printed = lv.printbvec(printed, "avarinitall", varRegVec{vars: be.avarinitall})
if printed {
fmt.Printf("\n")
}
diff --git a/src/cmd/compile/internal/gc/sinit.go b/src/cmd/compile/internal/gc/sinit.go
index c6455c3693..9d1114fa43 100644
--- a/src/cmd/compile/internal/gc/sinit.go
+++ b/src/cmd/compile/internal/gc/sinit.go
@@ -349,15 +349,13 @@ func staticcopy(l *Node, r *Node, out *[]*Node) bool {
gdata(n, e.Expr, int(n.Type.Width))
continue
}
- ll := n.copy()
- ll.Orig = ll // completely separate copy
+ ll := n.sepcopy()
if staticassign(ll, e.Expr, out) {
continue
}
// Requires computation, but we're
// copying someone else's computation.
- rr := orig.copy()
- rr.Orig = rr // completely separate copy
+ rr := orig.sepcopy()
rr.Type = ll.Type
rr.Xoffset += e.Xoffset
setlineno(rr)
@@ -453,8 +451,7 @@ func staticassign(l *Node, r *Node, out *[]*Node) bool {
continue
}
setlineno(e.Expr)
- a := n.copy()
- a.Orig = a // completely separate copy
+ a := n.sepcopy()
if !staticassign(a, e.Expr, out) {
*out = append(*out, nod(OAS, a, e.Expr))
}
@@ -518,8 +515,7 @@ func staticassign(l *Node, r *Node, out *[]*Node) bool {
// Copy val directly into n.
n.Type = val.Type
setlineno(val)
- a := n.copy()
- a.Orig = a
+ a := n.sepcopy()
if !staticassign(a, val, out) {
*out = append(*out, nod(OAS, a, val))
}
@@ -843,6 +839,10 @@ func slicelit(ctxt initContext, n *Node, var_ *Node, init *Nodes) {
a = nod(OAS, x, nil)
a = typecheck(a, Etop)
init.Append(a) // zero new temp
+ } else {
+ // Declare that we're about to initialize all of x.
+ // (Which happens at the *vauto = vstat below.)
+ init.Append(nod(OVARDEF, x, nil))
}
a = nod(OADDR, x, nil)
@@ -853,6 +853,8 @@ func slicelit(ctxt initContext, n *Node, var_ *Node, init *Nodes) {
a = typecheck(a, Etop)
init.Append(a) // zero new temp
a = a.Left
+ } else {
+ init.Append(nod(OVARDEF, a, nil))
}
a = nod(OADDR, a, nil)
diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go
index 00ff7d4bd5..138ce08fec 100644
--- a/src/cmd/compile/internal/gc/ssa.go
+++ b/src/cmd/compile/internal/gc/ssa.go
@@ -16,6 +16,7 @@ import (
"cmd/compile/internal/ssa"
"cmd/compile/internal/types"
"cmd/internal/obj"
+ "cmd/internal/objabi"
"cmd/internal/src"
"cmd/internal/sys"
)
@@ -754,8 +755,8 @@ func (s *state) stmtList(l Nodes) {
// stmt converts the statement n to SSA and adds it to s.
func (s *state) stmt(n *Node) {
- if !(n.Op == OVARKILL || n.Op == OVARLIVE) {
- // OVARKILL and OVARLIVE are invisible to the programmer, so we don't use their line numbers to avoid confusion in debugging.
+ if !(n.Op == OVARKILL || n.Op == OVARLIVE || n.Op == OVARDEF) {
+ // OVARKILL, OVARLIVE, and OVARDEF are invisible to the programmer, so we don't use their line numbers to avoid confusion in debugging.
s.pushLine(n.Pos)
defer s.popLine()
}
@@ -1169,6 +1170,10 @@ func (s *state) stmt(n *Node) {
}
s.startBlock(bEnd)
+ case OVARDEF:
+ if !s.canSSA(n.Left) {
+ s.vars[&memVar] = s.newValue1Apos(ssa.OpVarDef, types.TypeMem, n.Left, s.mem(), false)
+ }
case OVARKILL:
// Insert a varkill op to record that a variable is no longer live.
// We only care about liveness info at call sites, so putting the
@@ -3149,12 +3154,12 @@ func init() {
func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
return s.newValue1(ssa.OpRoundToEven, types.Types[TFLOAT64], args[0])
},
- sys.S390X)
+ sys.ARM64, sys.S390X)
addF("math", "Abs",
func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
return s.newValue1(ssa.OpAbs, types.Types[TFLOAT64], args[0])
},
- sys.PPC64)
+ sys.ARM64, sys.PPC64)
addF("math", "Copysign",
func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
return s.newValue2(ssa.OpCopysign, types.Types[TFLOAT64], args[0], args[1])
@@ -3361,12 +3366,12 @@ func init() {
func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
return s.newValue2(ssa.OpRotateLeft32, types.Types[TUINT32], args[0], args[1])
},
- sys.AMD64, sys.S390X)
+ sys.AMD64, sys.ARM64, sys.S390X)
addF("math/bits", "RotateLeft64",
func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
return s.newValue2(ssa.OpRotateLeft64, types.Types[TUINT64], args[0], args[1])
},
- sys.AMD64, sys.S390X)
+ sys.AMD64, sys.ARM64, sys.S390X)
alias("math/bits", "RotateLeft", "math/bits", "RotateLeft64", p8...)
makeOnesCountAMD64 := func(op64 ssa.Op, op32 ssa.Op) func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
@@ -3435,6 +3440,12 @@ func init() {
addF("math/bits", "OnesCount",
makeOnesCountAMD64(ssa.OpPopCount64, ssa.OpPopCount32),
sys.AMD64)
+ alias("math/bits", "Mul", "math/bits", "Mul64", sys.ArchAMD64, sys.ArchARM64, sys.ArchPPC64)
+ addF("math/bits", "Mul64",
+ func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
+ return s.newValue2(ssa.OpMul64uhilo, types.NewTuple(types.Types[TUINT64], types.Types[TUINT64]), args[0], args[1])
+ },
+ sys.AMD64, sys.ARM64, sys.PPC64)
/******** sync/atomic ********/
@@ -4927,6 +4938,57 @@ func (s *SSAGenState) DebugFriendlySetPosFrom(v *ssa.Value) {
}
}
+// byXoffset implements sort.Interface for []*Node using Xoffset as the ordering.
+type byXoffset []*Node
+
+func (s byXoffset) Len() int { return len(s) }
+func (s byXoffset) Less(i, j int) bool { return s[i].Xoffset < s[j].Xoffset }
+func (s byXoffset) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+
+func emitStackObjects(e *ssafn, pp *Progs) {
+ var vars []*Node
+ for _, n := range e.curfn.Func.Dcl {
+ if livenessShouldTrack(n) && n.Addrtaken() {
+ vars = append(vars, n)
+ }
+ }
+ if len(vars) == 0 {
+ return
+ }
+
+ // Sort variables from lowest to highest address.
+ sort.Sort(byXoffset(vars))
+
+ // Populate the stack object data.
+ // Format must match runtime/stack.go:stackObjectRecord.
+ x := e.curfn.Func.lsym.Func.StackObjects
+ off := 0
+ off = duintptr(x, off, uint64(len(vars)))
+ for _, v := range vars {
+ // Note: arguments and return values have non-negative Xoffset,
+ // in which case the offset is relative to argp.
+ // Locals have a negative Xoffset, in which case the offset is relative to varp.
+ off = duintptr(x, off, uint64(v.Xoffset))
+ if !typesym(v.Type).Siggen() {
+ Fatalf("stack object's type symbol not generated for type %s", v.Type)
+ }
+ off = dsymptr(x, off, dtypesym(v.Type), 0)
+ }
+
+ // Emit a funcdata pointing at the stack object data.
+ p := pp.Prog(obj.AFUNCDATA)
+ Addrconst(&p.From, objabi.FUNCDATA_StackObjects)
+ p.To.Type = obj.TYPE_MEM
+ p.To.Name = obj.NAME_EXTERN
+ p.To.Sym = x
+
+ if debuglive != 0 {
+ for _, v := range vars {
+ Warnl(v.Pos, "stack object %v %s", v, v.Type.String())
+ }
+ }
+}
+
// genssa appends entries to pp for each instruction in f.
func genssa(f *ssa.Func, pp *Progs) {
var s SSAGenState
@@ -4934,6 +4996,7 @@ func genssa(f *ssa.Func, pp *Progs) {
e := f.Frontend().(*ssafn)
s.livenessMap = liveness(e, f)
+ emitStackObjects(e, pp)
// Remember where each block starts.
s.bstart = make([]*obj.Prog, f.NumBlocks())
@@ -5003,24 +5066,8 @@ func genssa(f *ssa.Func, pp *Progs) {
case ssa.OpGetG:
// nothing to do when there's a g register,
// and checkLower complains if there's not
- case ssa.OpVarDef, ssa.OpVarLive, ssa.OpKeepAlive:
+ case ssa.OpVarDef, ssa.OpVarLive, ssa.OpKeepAlive, ssa.OpVarKill:
// nothing to do; already used by liveness
- case ssa.OpVarKill:
- // Zero variable if it is ambiguously live.
- // After the VARKILL anything this variable references
- // might be collected. If it were to become live again later,
- // the GC will see references to already-collected objects.
- // See issue 20029.
- n := v.Aux.(*Node)
- if n.Name.Needzero() {
- if n.Class() != PAUTO {
- v.Fatalf("zero of variable which isn't PAUTO %v", n)
- }
- if n.Type.Size()%int64(Widthptr) != 0 {
- v.Fatalf("zero of variable not a multiple of ptr size %v", n)
- }
- thearch.ZeroAuto(s.pp, n)
- }
case ssa.OpPhi:
CheckLoweredPhi(v)
case ssa.OpConvert:
@@ -5048,7 +5095,6 @@ func genssa(f *ssa.Func, pp *Progs) {
}
}
}
-
// Emit control flow instructions for block
var next *ssa.Block
if i < len(f.Blocks)-1 && Debug['N'] == 0 {
diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go
index 61a3b2385d..7e450e2e66 100644
--- a/src/cmd/compile/internal/gc/subr.go
+++ b/src/cmd/compile/internal/gc/subr.go
@@ -364,9 +364,35 @@ func nodSym(op Op, left *Node, sym *types.Sym) *Node {
return n
}
+// rawcopy returns a shallow copy of n.
+// Note: copy or sepcopy (rather than rawcopy) is usually the
+// correct choice (see comment with Node.copy, below).
+func (n *Node) rawcopy() *Node {
+ copy := *n
+ return &copy
+}
+
+// sepcopy returns a separate shallow copy of n, with the copy's
+// Orig pointing to itself.
+func (n *Node) sepcopy() *Node {
+ copy := *n
+ copy.Orig = &copy
+ return &copy
+}
+
+// copy returns shallow copy of n and adjusts the copy's Orig if
+// necessary: In general, if n.Orig points to itself, the copy's
+// Orig should point to itself as well. Otherwise, if n is modified,
+// the copy's Orig node appears modified, too, and then doesn't
+// represent the original node anymore.
+// (This caused the wrong complit Op to be used when printing error
+// messages; see issues #26855, #27765).
func (n *Node) copy() *Node {
- n2 := *n
- return &n2
+ copy := *n
+ if n.Orig == n {
+ copy.Orig = &copy
+ }
+ return &copy
}
// methcmp sorts methods by symbol.
@@ -412,8 +438,7 @@ func treecopy(n *Node, pos src.XPos) *Node {
switch n.Op {
default:
- m := n.copy()
- m.Orig = m
+ m := n.sepcopy()
m.Left = treecopy(n.Left, pos)
m.Right = treecopy(n.Right, pos)
m.List.Set(listtreecopy(n.List.Slice(), pos))
diff --git a/src/cmd/compile/internal/gc/syntax.go b/src/cmd/compile/internal/gc/syntax.go
index df23b83f29..eb2ab6b916 100644
--- a/src/cmd/compile/internal/gc/syntax.go
+++ b/src/cmd/compile/internal/gc/syntax.go
@@ -739,6 +739,7 @@ const (
OCLOSUREVAR // variable reference at beginning of closure function
OCFUNC // reference to c function pointer (not go func value)
OCHECKNIL // emit code to ensure pointer/interface not nil
+ OVARDEF // variable is about to be fully initialized
OVARKILL // variable is dead
OVARLIVE // variable is alive
OINDREGSP // offset plus indirect of REGSP, such as 8(SP).
diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go
index bb78d8bf73..4831ecca34 100644
--- a/src/cmd/compile/internal/gc/typecheck.go
+++ b/src/cmd/compile/internal/gc/typecheck.go
@@ -2436,7 +2436,7 @@ func isMethodApplicable(t *types.Type, m *types.Field) bool {
}
func derefall(t *types.Type) *types.Type {
- for t != nil && t.Etype == types.Tptr {
+ for t != nil && t.IsPtr() {
t = t.Elem()
}
return t
@@ -2506,20 +2506,20 @@ func lookdot(n *Node, t *types.Type, dostrcmp int) *types.Field {
dowidth(tt)
rcvr := f2.Type.Recv().Type
if !eqtype(rcvr, tt) {
- if rcvr.Etype == types.Tptr && eqtype(rcvr.Elem(), tt) {
+ if rcvr.IsPtr() && eqtype(rcvr.Elem(), tt) {
checklvalue(n.Left, "call pointer method on")
n.Left = nod(OADDR, n.Left, nil)
n.Left.SetImplicit(true)
n.Left = typecheck(n.Left, Etype|Erv)
- } else if tt.Etype == types.Tptr && rcvr.Etype != types.Tptr && eqtype(tt.Elem(), rcvr) {
+ } else if tt.IsPtr() && !rcvr.IsPtr() && eqtype(tt.Elem(), rcvr) {
n.Left = nod(OIND, n.Left, nil)
n.Left.SetImplicit(true)
n.Left = typecheck(n.Left, Etype|Erv)
- } else if tt.Etype == types.Tptr && tt.Elem().Etype == types.Tptr && eqtype(derefall(tt), derefall(rcvr)) {
+ } else if tt.IsPtr() && tt.Elem().IsPtr() && eqtype(derefall(tt), derefall(rcvr)) {
yyerror("calling method %v with receiver %L requires explicit dereference", n.Sym, n.Left)
- for tt.Etype == types.Tptr {
+ for tt.IsPtr() {
// Stop one level early for method with pointer receiver.
- if rcvr.Etype == types.Tptr && tt.Elem().Etype != types.Tptr {
+ if rcvr.IsPtr() && !tt.Elem().IsPtr() {
break
}
n.Left = nod(OIND, n.Left, nil)
@@ -3298,7 +3298,8 @@ func samesafeexpr(l *Node, r *Node) bool {
case ODOT, ODOTPTR:
return l.Sym != nil && r.Sym != nil && l.Sym == r.Sym && samesafeexpr(l.Left, r.Left)
- case OIND, OCONVNOP:
+ case OIND, OCONVNOP,
+ ONOT, OCOM, OPLUS, OMINUS:
return samesafeexpr(l.Left, r.Left)
case OCONV:
@@ -3306,7 +3307,8 @@ func samesafeexpr(l *Node, r *Node) bool {
// Allow only numeric-ish types. This is a bit conservative.
return issimple[l.Type.Etype] && samesafeexpr(l.Left, r.Left)
- case OINDEX, OINDEXMAP:
+ case OINDEX, OINDEXMAP,
+ OADD, OSUB, OOR, OXOR, OMUL, OLSH, ORSH, OAND, OANDNOT, ODIV, OMOD:
return samesafeexpr(l.Left, r.Left) && samesafeexpr(l.Right, r.Right)
case OLITERAL:
@@ -3339,7 +3341,7 @@ func typecheckas(n *Node) {
checkassign(n, n.Left)
if n.Right != nil && n.Right.Type != nil {
if n.Right.Type.IsFuncArgStruct() {
- yyerror("assignment mismatch: 1 variable but %d values", n.Right.Type.NumFields())
+ yyerror("assignment mismatch: 1 variable but %v returns %d values", n.Right.Left, n.Right.Type.NumFields())
// Multi-value RHS isn't actually valid for OAS; nil out
// to indicate failed typechecking.
n.Right.Type = nil
@@ -3484,7 +3486,12 @@ func typecheckas2(n *Node) {
}
mismatch:
- yyerror("assignment mismatch: %d variables but %d values", cl, cr)
+ switch r.Op {
+ default:
+ yyerror("assignment mismatch: %d variable but %d values", cl, cr)
+ case OCALLFUNC, OCALLMETH, OCALLINTER:
+ yyerror("assignment mismatch: %d variables but %v returns %d values", cl, r.Left, cr)
+ }
// second half of dance
out:
@@ -3640,25 +3647,22 @@ func typecheckdeftype(n *Node) {
}
func typecheckdef(n *Node) {
- lno := lineno
- setlineno(n)
+ lno := setlineno(n)
if n.Op == ONONAME {
if !n.Diag() {
n.SetDiag(true)
- if n.Pos.IsKnown() {
- lineno = n.Pos
- }
// Note: adderrorname looks for this string and
// adds context about the outer expression
- yyerror("undefined: %v", n.Sym)
+ yyerrorl(lineno, "undefined: %v", n.Sym)
}
-
+ lineno = lno
return
}
if n.Walkdef() == 1 {
+ lineno = lno
return
}
@@ -3701,20 +3705,19 @@ func typecheckdef(n *Node) {
e := n.Name.Defn
n.Name.Defn = nil
if e == nil {
- lineno = n.Pos
Dump("typecheckdef nil defn", n)
- yyerror("xxx")
+ yyerrorl(n.Pos, "xxx")
}
e = typecheck(e, Erv)
if Isconst(e, CTNIL) {
- yyerror("const initializer cannot be nil")
+ yyerrorl(n.Pos, "const initializer cannot be nil")
goto ret
}
if e.Type != nil && e.Op != OLITERAL || !e.isGoConst() {
if !e.Diag() {
- yyerror("const initializer %v is not a constant", e)
+ yyerrorl(n.Pos, "const initializer %v is not a constant", e)
e.SetDiag(true)
}
@@ -3724,12 +3727,12 @@ func typecheckdef(n *Node) {
t := n.Type
if t != nil {
if !okforconst[t.Etype] {
- yyerror("invalid constant type %v", t)
+ yyerrorl(n.Pos, "invalid constant type %v", t)
goto ret
}
if !e.Type.IsUntyped() && !eqtype(t, e.Type) {
- yyerror("cannot use %L as type %v in const initializer", e, t)
+ yyerrorl(n.Pos, "cannot use %L as type %v in const initializer", e, t)
goto ret
}
diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go
index 2993e08fc2..1b1d36b61d 100644
--- a/src/cmd/compile/internal/gc/walk.go
+++ b/src/cmd/compile/internal/gc/walk.go
@@ -1312,7 +1312,7 @@ opswitch:
b = conv(b, convType)
b = nod(OLSH, b, nodintconst(int64(8*offset)))
ncsubstr = nod(OOR, ncsubstr, b)
- csubstr = csubstr | int64(s[i+offset])<<uint8(8*offset)
+ csubstr |= int64(s[i+offset]) << uint8(8*offset)
}
csubstrPart := nodintconst(csubstr)
// Compare "step" bytes as once
@@ -1418,7 +1418,7 @@ opswitch:
// Maximum key and value size is 128 bytes, larger objects
// are stored with an indirection. So max bucket size is 2048+eps.
if !Isconst(hint, CTINT) ||
- !(hint.Val().U.(*Mpint).CmpInt64(BUCKETSIZE) > 0) {
+ hint.Val().U.(*Mpint).CmpInt64(BUCKETSIZE) <= 0 {
// var bv bmap
bv := temp(bmap(t))
@@ -4052,7 +4052,7 @@ func wrapCall(n *Node, init *Nodes) *Node {
// The result of substArgTypes MUST be assigned back to old, e.g.
// n.Left = substArgTypes(n.Left, t1, t2)
func substArgTypes(old *Node, types_ ...*types.Type) *Node {
- n := old.copy() // make shallow copy
+ n := old.copy()
for _, t := range types_ {
dowidth(t)
diff --git a/src/cmd/compile/internal/ppc64/ssa.go b/src/cmd/compile/internal/ppc64/ssa.go
index fd226a2e98..0a7238850c 100644
--- a/src/cmd/compile/internal/ppc64/ssa.go
+++ b/src/cmd/compile/internal/ppc64/ssa.go
@@ -153,6 +153,24 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
p.To.Reg = y
}
+ case ssa.OpPPC64LoweredMuluhilo:
+ // MULHDU Rarg1, Rarg0, Reg0
+ // MULLD Rarg1, Rarg0, Reg1
+ r0 := v.Args[0].Reg()
+ r1 := v.Args[1].Reg()
+ p := s.Prog(ppc64.AMULHDU)
+ p.From.Type = obj.TYPE_REG
+ p.From.Reg = r1
+ p.Reg = r0
+ p.To.Type = obj.TYPE_REG
+ p.To.Reg = v.Reg0()
+ p1 := s.Prog(ppc64.AMULLD)
+ p1.From.Type = obj.TYPE_REG
+ p1.From.Reg = r1
+ p1.Reg = r0
+ p1.To.Type = obj.TYPE_REG
+ p1.To.Reg = v.Reg1()
+
case ssa.OpPPC64LoweredAtomicAnd8,
ssa.OpPPC64LoweredAtomicOr8:
// LWSYNC
@@ -717,7 +735,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
// Not a go.string, generate a normal load
fallthrough
- case ssa.OpPPC64MOVWload, ssa.OpPPC64MOVHload, ssa.OpPPC64MOVWZload, ssa.OpPPC64MOVBZload, ssa.OpPPC64MOVHZload:
+ case ssa.OpPPC64MOVWload, ssa.OpPPC64MOVHload, ssa.OpPPC64MOVWZload, ssa.OpPPC64MOVBZload, ssa.OpPPC64MOVHZload, ssa.OpPPC64FMOVDload, ssa.OpPPC64FMOVSload:
p := s.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_MEM
p.From.Reg = v.Args[0].Reg()
@@ -739,10 +757,13 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
p.From.Type = obj.TYPE_REG
p.From.Reg = v.Args[1].Reg()
- case ssa.OpPPC64FMOVDload, ssa.OpPPC64FMOVSload:
+ case ssa.OpPPC64MOVDloadidx, ssa.OpPPC64MOVWloadidx, ssa.OpPPC64MOVHloadidx, ssa.OpPPC64MOVWZloadidx,
+ ssa.OpPPC64MOVBZloadidx, ssa.OpPPC64MOVHZloadidx, ssa.OpPPC64FMOVDloadidx, ssa.OpPPC64FMOVSloadidx,
+ ssa.OpPPC64MOVDBRloadidx, ssa.OpPPC64MOVWBRloadidx, ssa.OpPPC64MOVHBRloadidx:
p := s.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_MEM
p.From.Reg = v.Args[0].Reg()
+ p.From.Index = v.Args[1].Reg()
gc.AddAux(&p.From, v)
p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg()
@@ -755,17 +776,21 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
p.To.Reg = v.Args[0].Reg()
gc.AddAux(&p.To, v)
- case ssa.OpPPC64MOVDstore, ssa.OpPPC64MOVWstore, ssa.OpPPC64MOVHstore, ssa.OpPPC64MOVBstore:
+ case ssa.OpPPC64MOVDstore, ssa.OpPPC64MOVWstore, ssa.OpPPC64MOVHstore, ssa.OpPPC64MOVBstore, ssa.OpPPC64FMOVDstore, ssa.OpPPC64FMOVSstore:
p := s.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_REG
p.From.Reg = v.Args[1].Reg()
p.To.Type = obj.TYPE_MEM
p.To.Reg = v.Args[0].Reg()
gc.AddAux(&p.To, v)
- case ssa.OpPPC64FMOVDstore, ssa.OpPPC64FMOVSstore:
+
+ case ssa.OpPPC64MOVDstoreidx, ssa.OpPPC64MOVWstoreidx, ssa.OpPPC64MOVHstoreidx, ssa.OpPPC64MOVBstoreidx,
+ ssa.OpPPC64FMOVDstoreidx, ssa.OpPPC64FMOVSstoreidx, ssa.OpPPC64MOVDBRstoreidx, ssa.OpPPC64MOVWBRstoreidx,
+ ssa.OpPPC64MOVHBRstoreidx:
p := s.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_REG
- p.From.Reg = v.Args[1].Reg()
+ p.From.Reg = v.Args[2].Reg()
+ p.To.Index = v.Args[1].Reg()
p.To.Type = obj.TYPE_MEM
p.To.Reg = v.Args[0].Reg()
gc.AddAux(&p.To, v)
diff --git a/src/cmd/compile/internal/ssa/gen/386.rules b/src/cmd/compile/internal/ssa/gen/386.rules
index 8131f1117a..f6aa37e884 100644
--- a/src/cmd/compile/internal/ssa/gen/386.rules
+++ b/src/cmd/compile/internal/ssa/gen/386.rules
@@ -44,8 +44,8 @@
(Xor(32|16|8) x y) -> (XORL x y)
(Neg(32|16|8) x) -> (NEGL x)
-(Neg32F x) && !config.use387 -> (PXOR x (MOVSSconst <typ.Float32> [f2i(math.Copysign(0, -1))]))
-(Neg64F x) && !config.use387 -> (PXOR x (MOVSDconst <typ.Float64> [f2i(math.Copysign(0, -1))]))
+(Neg32F x) && !config.use387 -> (PXOR x (MOVSSconst <typ.Float32> [auxFrom32F(float32(math.Copysign(0, -1)))]))
+(Neg64F x) && !config.use387 -> (PXOR x (MOVSDconst <typ.Float64> [auxFrom64F(math.Copysign(0, -1))]))
(Neg32F x) && config.use387 -> (FCHS x)
(Neg64F x) && config.use387 -> (FCHS x)
@@ -1116,10 +1116,10 @@
(XORL x x) -> (MOVLconst [0])
// checking AND against 0.
-(CMP(L|W|B)const (ANDL x y) [0]) -> (TEST(L|W|B) x y)
-(CMPLconst (ANDLconst [c] x) [0]) -> (TESTLconst [c] x)
-(CMPWconst (ANDLconst [c] x) [0]) -> (TESTWconst [int64(int16(c))] x)
-(CMPBconst (ANDLconst [c] x) [0]) -> (TESTBconst [int64(int8(c))] x)
+(CMP(L|W|B)const l:(ANDL x y) [0]) && l.Uses==1 -> (TEST(L|W|B) x y)
+(CMPLconst l:(ANDLconst [c] x) [0]) && l.Uses==1 -> (TESTLconst [c] x)
+(CMPWconst l:(ANDLconst [c] x) [0]) && l.Uses==1 -> (TESTWconst [int64(int16(c))] x)
+(CMPBconst l:(ANDLconst [c] x) [0]) && l.Uses==1 -> (TESTBconst [int64(int8(c))] x)
// TEST %reg,%reg is shorter than CMP
(CMP(L|W|B)const x [0]) -> (TEST(L|W|B) x x)
diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules
index 4c11f8d036..f9ac5e4dce 100644
--- a/src/cmd/compile/internal/ssa/gen/AMD64.rules
+++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules
@@ -41,8 +41,8 @@
(Com(64|32|16|8) x) -> (NOT(Q|L|L|L) x)
(Neg(64|32|16|8) x) -> (NEG(Q|L|L|L) x)
-(Neg32F x) -> (PXOR x (MOVSSconst <typ.Float32> [f2i(math.Copysign(0, -1))]))
-(Neg64F x) -> (PXOR x (MOVSDconst <typ.Float64> [f2i(math.Copysign(0, -1))]))
+(Neg32F x) -> (PXOR x (MOVSSconst <typ.Float32> [auxFrom32F(float32(math.Copysign(0, -1)))]))
+(Neg64F x) -> (PXOR x (MOVSDconst <typ.Float64> [auxFrom64F(math.Copysign(0, -1))]))
// Lowering boolean ops
(AndB x y) -> (ANDL x y)
@@ -709,7 +709,17 @@
(ANDL x (MOVLconst [c])) -> (ANDLconst [c] x)
(AND(L|Q)const [c] (AND(L|Q)const [d] x)) -> (AND(L|Q)const [c & d] x)
+(BTR(L|Q)const [c] (AND(L|Q)const [d] x)) -> (AND(L|Q)const [d &^ (1<<uint32(c))] x)
+(AND(L|Q)const [c] (BTR(L|Q)const [d] x)) -> (AND(L|Q)const [c &^ (1<<uint32(d))] x)
+(BTR(L|Q)const [c] (BTR(L|Q)const [d] x)) -> (AND(L|Q)const [^(1<<uint32(c) | 1<<uint32(d))] x)
(XOR(L|Q)const [c] (XOR(L|Q)const [d] x)) -> (XOR(L|Q)const [c ^ d] x)
+(BTC(L|Q)const [c] (XOR(L|Q)const [d] x)) -> (XOR(L|Q)const [d ^ 1<<uint32(c)] x)
+(XOR(L|Q)const [c] (BTC(L|Q)const [d] x)) -> (XOR(L|Q)const [c ^ 1<<uint32(d)] x)
+(BTC(L|Q)const [c] (BTC(L|Q)const [d] x)) -> (XOR(L|Q)const [1<<uint32(c) ^ 1<<uint32(d)] x)
+(OR(L|Q)const [c] (OR(L|Q)const [d] x)) -> (OR(L|Q)const [c | d] x)
+(OR(L|Q)const [c] (BTS(L|Q)const [d] x)) -> (OR(L|Q)const [c | 1<<uint32(d)] x)
+(BTS(L|Q)const [c] (OR(L|Q)const [d] x)) -> (OR(L|Q)const [d | 1<<uint32(c)] x)
+(BTS(L|Q)const [c] (BTS(L|Q)const [d] x)) -> (OR(L|Q)const [1<<uint32(d) | 1<<uint32(c)] x)
(MULLconst [c] (MULLconst [d] x)) -> (MULLconst [int64(int32(c * d))] x)
(MULQconst [c] (MULQconst [d] x)) && is32Bit(c*d) -> (MULQconst [c * d] x)
@@ -1042,18 +1052,23 @@
((ADD|SUB|AND|OR|XOR)Qload [off1+off2] {sym} val base mem)
((ADD|SUB|AND|OR|XOR)Lload [off1] {sym} val (ADDQconst [off2] base) mem) && is32Bit(off1+off2) ->
((ADD|SUB|AND|OR|XOR)Lload [off1+off2] {sym} val base mem)
+(CMP(Q|L|W|B)load [off1] {sym} (ADDQconst [off2] base) val mem) && is32Bit(off1+off2) ->
+ (CMP(Q|L|W|B)load [off1+off2] {sym} base val mem)
+(CMP(Q|L|W|B)constload [valoff1] {sym} (ADDQconst [off2] base) mem) && ValAndOff(valoff1).canAdd(off2) ->
+ (CMP(Q|L|W|B)constload [ValAndOff(valoff1).add(off2)] {sym} base mem)
+
((ADD|SUB|MUL|DIV)SSload [off1] {sym} val (ADDQconst [off2] base) mem) && is32Bit(off1+off2) ->
((ADD|SUB|MUL|DIV)SSload [off1+off2] {sym} val base mem)
((ADD|SUB|MUL|DIV)SDload [off1] {sym} val (ADDQconst [off2] base) mem) && is32Bit(off1+off2) ->
((ADD|SUB|MUL|DIV)SDload [off1+off2] {sym} val base mem)
-((ADD|AND|OR|XOR)Qconstmodify [valoff1] {sym} (ADDQconst [off2] base) mem) && ValAndOff(valoff1).canAdd(off2) ->
- ((ADD|AND|OR|XOR)Qconstmodify [ValAndOff(valoff1).add(off2)] {sym} base mem)
-((ADD|AND|OR|XOR)Lconstmodify [valoff1] {sym} (ADDQconst [off2] base) mem) && ValAndOff(valoff1).canAdd(off2) ->
- ((ADD|AND|OR|XOR)Lconstmodify [ValAndOff(valoff1).add(off2)] {sym} base mem)
-((ADD|SUB|AND|OR|XOR)Qmodify [off1] {sym} (ADDQconst [off2] base) val mem) && is32Bit(off1+off2) ->
- ((ADD|SUB|AND|OR|XOR)Qmodify [off1+off2] {sym} base val mem)
-((ADD|SUB|AND|OR|XOR)Lmodify [off1] {sym} (ADDQconst [off2] base) val mem) && is32Bit(off1+off2) ->
- ((ADD|SUB|AND|OR|XOR)Lmodify [off1+off2] {sym} base val mem)
+((ADD|AND|OR|XOR|BTC|BTR|BTS)Qconstmodify [valoff1] {sym} (ADDQconst [off2] base) mem) && ValAndOff(valoff1).canAdd(off2) ->
+ ((ADD|AND|OR|XOR|BTC|BTR|BTS)Qconstmodify [ValAndOff(valoff1).add(off2)] {sym} base mem)
+((ADD|AND|OR|XOR|BTC|BTR|BTS)Lconstmodify [valoff1] {sym} (ADDQconst [off2] base) mem) && ValAndOff(valoff1).canAdd(off2) ->
+ ((ADD|AND|OR|XOR|BTC|BTR|BTS)Lconstmodify [ValAndOff(valoff1).add(off2)] {sym} base mem)
+((ADD|SUB|AND|OR|XOR|BTC|BTR|BTS)Qmodify [off1] {sym} (ADDQconst [off2] base) val mem) && is32Bit(off1+off2) ->
+ ((ADD|SUB|AND|OR|XOR|BTC|BTR|BTS)Qmodify [off1+off2] {sym} base val mem)
+((ADD|SUB|AND|OR|XOR|BTC|BTR|BTS)Lmodify [off1] {sym} (ADDQconst [off2] base) val mem) && is32Bit(off1+off2) ->
+ ((ADD|SUB|AND|OR|XOR|BTC|BTR|BTS)Lmodify [off1+off2] {sym} base val mem)
// Fold constants into stores.
(MOVQstore [off] {sym} ptr (MOVQconst [c]) mem) && validValAndOff(c,off) ->
@@ -1088,24 +1103,31 @@
((ADD|SUB|AND|OR|XOR)Lload [off1] {sym1} val (LEAQ [off2] {sym2} base) mem)
&& is32Bit(off1+off2) && canMergeSym(sym1, sym2) ->
((ADD|SUB|AND|OR|XOR)Lload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
+(CMP(Q|L|W|B)load [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ && is32Bit(off1+off2) && canMergeSym(sym1, sym2) ->
+ (CMP(Q|L|W|B)load [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+(CMP(Q|L|W|B)constload [valoff1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ && ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2) ->
+ (CMP(Q|L|W|B)constload [ValAndOff(valoff1).add(off2)] {mergeSym(sym1,sym2)} base mem)
+
((ADD|SUB|MUL|DIV)SSload [off1] {sym1} val (LEAQ [off2] {sym2} base) mem)
&& is32Bit(off1+off2) && canMergeSym(sym1, sym2) ->
((ADD|SUB|MUL|DIV)SSload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
((ADD|SUB|MUL|DIV)SDload [off1] {sym1} val (LEAQ [off2] {sym2} base) mem)
&& is32Bit(off1+off2) && canMergeSym(sym1, sym2) ->
((ADD|SUB|MUL|DIV)SDload [off1+off2] {mergeSym(sym1,sym2)} val base mem)
-((ADD|AND|OR|XOR)Qconstmodify [valoff1] {sym1} (LEAQ [off2] {sym2} base) mem)
+((ADD|AND|OR|XOR|BTC|BTR|BTS)Qconstmodify [valoff1] {sym1} (LEAQ [off2] {sym2} base) mem)
&& ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2) ->
- ((ADD|AND|OR|XOR)Qconstmodify [ValAndOff(valoff1).add(off2)] {mergeSym(sym1,sym2)} base mem)
-((ADD|AND|OR|XOR)Lconstmodify [valoff1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ ((ADD|AND|OR|XOR|BTC|BTR|BTS)Qconstmodify [ValAndOff(valoff1).add(off2)] {mergeSym(sym1,sym2)} base mem)
+((ADD|AND|OR|XOR|BTC|BTR|BTS)Lconstmodify [valoff1] {sym1} (LEAQ [off2] {sym2} base) mem)
&& ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2) ->
- ((ADD|AND|OR|XOR)Lconstmodify [ValAndOff(valoff1).add(off2)] {mergeSym(sym1,sym2)} base mem)
-((ADD|SUB|AND|OR|XOR)Qmodify [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ ((ADD|AND|OR|XOR|BTC|BTR|BTS)Lconstmodify [ValAndOff(valoff1).add(off2)] {mergeSym(sym1,sym2)} base mem)
+((ADD|SUB|AND|OR|XOR|BTC|BTR|BTS)Qmodify [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
&& is32Bit(off1+off2) && canMergeSym(sym1, sym2) ->
- ((ADD|SUB|AND|OR|XOR)Qmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
-((ADD|SUB|AND|OR|XOR)Lmodify [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ ((ADD|SUB|AND|OR|XOR|BTC|BTR|BTS)Qmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+((ADD|SUB|AND|OR|XOR|BTC|BTR|BTS)Lmodify [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
&& is32Bit(off1+off2) && canMergeSym(sym1, sym2) ->
- ((ADD|SUB|AND|OR|XOR)Lmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ ((ADD|SUB|AND|OR|XOR|BTC|BTR|BTS)Lmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
// generating indexed loads and stores
(MOV(B|W|L|Q|SS|SD)load [off1] {sym1} (LEAQ1 [off2] {sym2} ptr idx) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) ->
@@ -1412,6 +1434,12 @@
(XORLconst [c] (MOVLconst [d])) -> (MOVLconst [c^d])
(NOTQ (MOVQconst [c])) -> (MOVQconst [^c])
(NOTL (MOVLconst [c])) -> (MOVLconst [^c])
+(BTSQconst [c] (MOVQconst [d])) -> (MOVQconst [d|(1<<uint32(c))])
+(BTSLconst [c] (MOVLconst [d])) -> (MOVLconst [d|(1<<uint32(c))])
+(BTRQconst [c] (MOVQconst [d])) -> (MOVQconst [d&^(1<<uint32(c))])
+(BTRLconst [c] (MOVLconst [d])) -> (MOVLconst [d&^(1<<uint32(c))])
+(BTCQconst [c] (MOVQconst [d])) -> (MOVQconst [d^(1<<uint32(c))])
+(BTCLconst [c] (MOVLconst [d])) -> (MOVLconst [d^(1<<uint32(c))])
// generic simplifications
// TODO: more of this
@@ -2292,11 +2320,11 @@
((ADD|SUB|MUL|DIV)SD x l:(MOVSDload [off] {sym} ptr mem)) && canMergeLoad(v, l, x) && clobber(l) -> ((ADD|SUB|MUL|DIV)SDload x [off] {sym} ptr mem)
((ADD|SUB|MUL|DIV)SS x l:(MOVSSload [off] {sym} ptr mem)) && canMergeLoad(v, l, x) && clobber(l) -> ((ADD|SUB|MUL|DIV)SSload x [off] {sym} ptr mem)
(MOVLstore {sym} [off] ptr y:((ADD|AND|OR|XOR)Lload x [off] {sym} ptr mem) mem) && y.Uses==1 && clobber(y) -> ((ADD|AND|OR|XOR)Lmodify [off] {sym} ptr x mem)
-(MOVLstore {sym} [off] ptr y:((ADD|SUB|AND|OR|XOR)L l:(MOVLload [off] {sym} ptr mem) x) mem) && y.Uses==1 && l.Uses==1 && clobber(y) && clobber(l) ->
- ((ADD|SUB|AND|OR|XOR)Lmodify [off] {sym} ptr x mem)
+(MOVLstore {sym} [off] ptr y:((ADD|SUB|AND|OR|XOR|BTC|BTR|BTS)L l:(MOVLload [off] {sym} ptr mem) x) mem) && y.Uses==1 && l.Uses==1 && clobber(y) && clobber(l) ->
+ ((ADD|SUB|AND|OR|XOR|BTC|BTR|BTS)Lmodify [off] {sym} ptr x mem)
(MOVQstore {sym} [off] ptr y:((ADD|AND|OR|XOR)Qload x [off] {sym} ptr mem) mem) && y.Uses==1 && clobber(y) -> ((ADD|AND|OR|XOR)Qmodify [off] {sym} ptr x mem)
-(MOVQstore {sym} [off] ptr y:((ADD|SUB|AND|OR|XOR)Q l:(MOVQload [off] {sym} ptr mem) x) mem) && y.Uses==1 && l.Uses==1 && clobber(y) && clobber(l) ->
- ((ADD|SUB|AND|OR|XOR)Qmodify [off] {sym} ptr x mem)
+(MOVQstore {sym} [off] ptr y:((ADD|SUB|AND|OR|XOR|BTC|BTR|BTS)Q l:(MOVQload [off] {sym} ptr mem) x) mem) && y.Uses==1 && l.Uses==1 && clobber(y) && clobber(l) ->
+ ((ADD|SUB|AND|OR|XOR|BTC|BTR|BTS)Qmodify [off] {sym} ptr x mem)
// Merge ADDQconst and LEAQ into atomic loads.
(MOVQatomicload [off1] {sym} (ADDQconst [off2] ptr) mem) && is32Bit(off1+off2) ->
@@ -2380,12 +2408,12 @@
(MOVWQZX (MOVBQZX x)) -> (MOVBQZX x)
(MOVBQZX (MOVBQZX x)) -> (MOVBQZX x)
-(MOVQstore [off] {sym} ptr a:((ADD|AND|OR|XOR)Qconst [c] l:(MOVQload [off] {sym} ptr2 mem)) mem)
- && isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c,off) ->
- ((ADD|AND|OR|XOR)Qconstmodify {sym} [makeValAndOff(c,off)] ptr mem)
-(MOVLstore [off] {sym} ptr a:((ADD|AND|OR|XOR)Lconst [c] l:(MOVLload [off] {sym} ptr2 mem)) mem)
- && isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c,off) ->
- ((ADD|AND|OR|XOR)Lconstmodify {sym} [makeValAndOff(c,off)] ptr mem)
+(MOVQstore [off] {sym} ptr a:((ADD|AND|OR|XOR|BTC|BTR|BTS)Qconst [c] l:(MOVQload [off] {sym} ptr2 mem)) mem)
+ && isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c,off) && clobber(l) && clobber(a) ->
+ ((ADD|AND|OR|XOR|BTC|BTR|BTS)Qconstmodify {sym} [makeValAndOff(c,off)] ptr mem)
+(MOVLstore [off] {sym} ptr a:((ADD|AND|OR|XOR|BTC|BTR|BTS)Lconst [c] l:(MOVLload [off] {sym} ptr2 mem)) mem)
+ && isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c,off) && clobber(l) && clobber(a) ->
+ ((ADD|AND|OR|XOR|BTC|BTR|BTS)Lconstmodify {sym} [makeValAndOff(c,off)] ptr mem)
// float <-> int register moves, with no conversion.
// These come up when compiling math.{Float{32,64}bits,Float{32,64}frombits}.
diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go
index 512df99694..017c07071d 100644
--- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go
+++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go
@@ -272,14 +272,14 @@ func init() {
{name: "UCOMISS", argLength: 2, reg: fp2flags, asm: "UCOMISS", typ: "Flags"}, // arg0 compare to arg1, f32
{name: "UCOMISD", argLength: 2, reg: fp2flags, asm: "UCOMISD", typ: "Flags"}, // arg0 compare to arg1, f64
- {name: "BTL", argLength: 2, reg: gp2flags, asm: "BTL", typ: "Flags"}, // test whether bit arg0 % 32 in arg1 is set
- {name: "BTQ", argLength: 2, reg: gp2flags, asm: "BTQ", typ: "Flags"}, // test whether bit arg0 % 64 in arg1 is set
- {name: "BTCL", argLength: 2, reg: gp21, asm: "BTCL", resultInArg0: true, clobberFlags: true}, // complement bit arg0 % 32 in arg1
- {name: "BTCQ", argLength: 2, reg: gp21, asm: "BTCQ", resultInArg0: true, clobberFlags: true}, // complement bit arg0 % 64 in arg1
- {name: "BTRL", argLength: 2, reg: gp21, asm: "BTRL", resultInArg0: true, clobberFlags: true}, // reset bit arg0 % 32 in arg1
- {name: "BTRQ", argLength: 2, reg: gp21, asm: "BTRQ", resultInArg0: true, clobberFlags: true}, // reset bit arg0 % 64 in arg1
- {name: "BTSL", argLength: 2, reg: gp21, asm: "BTSL", resultInArg0: true, clobberFlags: true}, // set bit arg0 % 32 in arg1
- {name: "BTSQ", argLength: 2, reg: gp21, asm: "BTSQ", resultInArg0: true, clobberFlags: true}, // set bit arg0 % 64 in arg1
+ {name: "BTL", argLength: 2, reg: gp2flags, asm: "BTL", typ: "Flags"}, // test whether bit arg0%32 in arg1 is set
+ {name: "BTQ", argLength: 2, reg: gp2flags, asm: "BTQ", typ: "Flags"}, // test whether bit arg0%64 in arg1 is set
+ {name: "BTCL", argLength: 2, reg: gp21, asm: "BTCL", resultInArg0: true, clobberFlags: true}, // complement bit arg1%32 in arg0
+ {name: "BTCQ", argLength: 2, reg: gp21, asm: "BTCQ", resultInArg0: true, clobberFlags: true}, // complement bit arg1%64 in arg0
+ {name: "BTRL", argLength: 2, reg: gp21, asm: "BTRL", resultInArg0: true, clobberFlags: true}, // reset bit arg1%32 in arg0
+ {name: "BTRQ", argLength: 2, reg: gp21, asm: "BTRQ", resultInArg0: true, clobberFlags: true}, // reset bit arg1%64 in arg0
+ {name: "BTSL", argLength: 2, reg: gp21, asm: "BTSL", resultInArg0: true, clobberFlags: true}, // set bit arg1%32 in arg0
+ {name: "BTSQ", argLength: 2, reg: gp21, asm: "BTSQ", resultInArg0: true, clobberFlags: true}, // set bit arg1%64 in arg0
{name: "BTLconst", argLength: 1, reg: gp1flags, asm: "BTL", typ: "Flags", aux: "Int8"}, // test whether bit auxint in arg0 is set, 0 <= auxint < 32
{name: "BTQconst", argLength: 1, reg: gp1flags, asm: "BTQ", typ: "Flags", aux: "Int8"}, // test whether bit auxint in arg0 is set, 0 <= auxint < 64
{name: "BTCLconst", argLength: 1, reg: gp11, asm: "BTCL", resultInArg0: true, clobberFlags: true, aux: "Int8"}, // complement bit auxint in arg0, 0 <= auxint < 32
@@ -289,6 +289,20 @@ func init() {
{name: "BTSLconst", argLength: 1, reg: gp11, asm: "BTSL", resultInArg0: true, clobberFlags: true, aux: "Int8"}, // set bit auxint in arg0, 0 <= auxint < 32
{name: "BTSQconst", argLength: 1, reg: gp11, asm: "BTSQ", resultInArg0: true, clobberFlags: true, aux: "Int8"}, // set bit auxint in arg0, 0 <= auxint < 64
+ // direct bit operation on memory operand
+ {name: "BTCQmodify", argLength: 3, reg: gpstore, asm: "BTCQ", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // complement bit arg1 in 64-bit arg0+auxint+aux, arg2=mem
+ {name: "BTCLmodify", argLength: 3, reg: gpstore, asm: "BTCL", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // complement bit arg1 in 32-bit arg0+auxint+aux, arg2=mem
+ {name: "BTSQmodify", argLength: 3, reg: gpstore, asm: "BTSQ", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // set bit arg1 in 64-bit arg0+auxint+aux, arg2=mem
+ {name: "BTSLmodify", argLength: 3, reg: gpstore, asm: "BTSL", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // set bit arg1 in 32-bit arg0+auxint+aux, arg2=mem
+ {name: "BTRQmodify", argLength: 3, reg: gpstore, asm: "BTRQ", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // reset bit arg1 in 64-bit arg0+auxint+aux, arg2=mem
+ {name: "BTRLmodify", argLength: 3, reg: gpstore, asm: "BTRL", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // reset bit arg1 in 32-bit arg0+auxint+aux, arg2=mem
+ {name: "BTCQconstmodify", argLength: 2, reg: gpstoreconst, asm: "BTCQ", aux: "SymValAndOff", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // complement bit ValAndOff(AuxInt).Val() in 64-bit arg0+ValAndOff(AuxInt).Off()+aux, arg1=mem
+ {name: "BTCLconstmodify", argLength: 2, reg: gpstoreconst, asm: "BTCL", aux: "SymValAndOff", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // complement bit ValAndOff(AuxInt).Val() in 32-bit arg0+ValAndOff(AuxInt).Off()+aux, arg1=mem
+ {name: "BTSQconstmodify", argLength: 2, reg: gpstoreconst, asm: "BTSQ", aux: "SymValAndOff", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // set bit ValAndOff(AuxInt).Val() in 64-bit arg0+ValAndOff(AuxInt).Off()+aux, arg1=mem
+ {name: "BTSLconstmodify", argLength: 2, reg: gpstoreconst, asm: "BTSL", aux: "SymValAndOff", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // set bit ValAndOff(AuxInt).Val() in 32-bit arg0+ValAndOff(AuxInt).Off()+aux, arg1=mem
+ {name: "BTRQconstmodify", argLength: 2, reg: gpstoreconst, asm: "BTRQ", aux: "SymValAndOff", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // reset bit ValAndOff(AuxInt).Val() in 64-bit arg0+ValAndOff(AuxInt).Off()+aux, arg1=mem
+ {name: "BTRLconstmodify", argLength: 2, reg: gpstoreconst, asm: "BTRL", aux: "SymValAndOff", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // reset bit ValAndOff(AuxInt).Val() in 32-bit arg0+ValAndOff(AuxInt).Off()+aux, arg1=mem
+
{name: "TESTQ", argLength: 2, reg: gp2flags, commutative: true, asm: "TESTQ", typ: "Flags"}, // (arg0 & arg1) compare to 0
{name: "TESTL", argLength: 2, reg: gp2flags, commutative: true, asm: "TESTL", typ: "Flags"}, // (arg0 & arg1) compare to 0
{name: "TESTW", argLength: 2, reg: gp2flags, commutative: true, asm: "TESTW", typ: "Flags"}, // (arg0 & arg1) compare to 0
diff --git a/src/cmd/compile/internal/ssa/gen/ARM64.rules b/src/cmd/compile/internal/ssa/gen/ARM64.rules
index ede7ed3d7a..659081ec8b 100644
--- a/src/cmd/compile/internal/ssa/gen/ARM64.rules
+++ b/src/cmd/compile/internal/ssa/gen/ARM64.rules
@@ -83,12 +83,18 @@
(Com8 x) -> (MVN x)
// math package intrinsics
+(Abs x) -> (FABSD x)
(Sqrt x) -> (FSQRTD x)
(Ceil x) -> (FRINTPD x)
(Floor x) -> (FRINTMD x)
(Round x) -> (FRINTAD x)
+(RoundToEven x) -> (FRINTND x)
(Trunc x) -> (FRINTZD x)
+// lowering rotates
+(RotateLeft32 x y) -> (RORW x (NEG <y.Type> y))
+(RotateLeft64 x y) -> (ROR x (NEG <y.Type> y))
+
(Ctz64NonZero x) -> (Ctz64 x)
(Ctz32NonZero x) -> (Ctz32 x)
@@ -101,9 +107,20 @@
// Load args directly into the register class where it will be used.
(FMOVDgpfp <t> (Arg [off] {sym})) -> @b.Func.Entry (Arg <t> [off] {sym})
+(FMOVDfpgp <t> (Arg [off] {sym})) -> @b.Func.Entry (Arg <t> [off] {sym})
+
// Similarly for stores, if we see a store after FPR <-> GPR move, then redirect store to use the other register set.
-(MOVDstore ptr (FMOVDfpgp val) mem) -> (FMOVDstore ptr val mem)
-(FMOVDstore ptr (FMOVDgpfp val) mem) -> (MOVDstore ptr val mem)
+(MOVDstore [off] {sym} ptr (FMOVDfpgp val) mem) -> (FMOVDstore [off] {sym} ptr val mem)
+(FMOVDstore [off] {sym} ptr (FMOVDgpfp val) mem) -> (MOVDstore [off] {sym} ptr val mem)
+(MOVWstore [off] {sym} ptr (FMOVSfpgp val) mem) -> (FMOVSstore [off] {sym} ptr val mem)
+(FMOVSstore [off] {sym} ptr (FMOVSgpfp val) mem) -> (MOVWstore [off] {sym} ptr val mem)
+
+// float <-> int register moves, with no conversion.
+// These come up when compiling math.{Float64bits, Float64frombits, Float32bits, Float32frombits}.
+(MOVDload [off] {sym} ptr (FMOVDstore [off] {sym} ptr val _)) -> (FMOVDfpgp val)
+(FMOVDload [off] {sym} ptr (MOVDstore [off] {sym} ptr val _)) -> (FMOVDgpfp val)
+(MOVWUload [off] {sym} ptr (FMOVSstore [off] {sym} ptr val _)) -> (FMOVSfpgp val)
+(FMOVSload [off] {sym} ptr (MOVWstore [off] {sym} ptr val _)) -> (FMOVSgpfp val)
(BitLen64 x) -> (SUB (MOVDconst [64]) (CLZ <typ.Int> x))
@@ -125,6 +142,8 @@
// shifts
// hardware instruction uses only the low 6 bits of the shift
// we compare to 64 to ensure Go semantics for large shifts
+// Rules about rotates with non-const shift are based on the following rules,
+// if the following rules change, please also modify the rules based on them.
(Lsh64x64 <t> x y) -> (CSEL {OpARM64LessThanU} (SLL <t> x y) (Const64 <t> [0]) (CMPconst [64] y))
(Lsh64x32 <t> x y) -> (CSEL {OpARM64LessThanU} (SLL <t> x (ZeroExt32to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt32to64 y)))
(Lsh64x16 <t> x y) -> (CSEL {OpARM64LessThanU} (SLL <t> x (ZeroExt16to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt16to64 y)))
@@ -1135,15 +1154,15 @@
(MULW (NEG x) y) -> (MNEGW x y)
// madd/msub
-(ADD a l:(MUL x y)) && l.Uses==1 && x.Op!=OpARM64MOVDconst && y.Op!=OpARM64MOVDconst && a.Op!=OpARM64MOVDconst && clobber(l) -> (MADD a x y)
-(SUB a l:(MUL x y)) && l.Uses==1 && x.Op!=OpARM64MOVDconst && y.Op!=OpARM64MOVDconst && a.Op!=OpARM64MOVDconst && clobber(l) -> (MSUB a x y)
-(ADD a l:(MNEG x y)) && l.Uses==1 && x.Op!=OpARM64MOVDconst && y.Op!=OpARM64MOVDconst && a.Op!=OpARM64MOVDconst && clobber(l) -> (MSUB a x y)
-(SUB a l:(MNEG x y)) && l.Uses==1 && x.Op!=OpARM64MOVDconst && y.Op!=OpARM64MOVDconst && a.Op!=OpARM64MOVDconst && clobber(l) -> (MADD a x y)
+(ADD a l:(MUL x y)) && l.Uses==1 && clobber(l) -> (MADD a x y)
+(SUB a l:(MUL x y)) && l.Uses==1 && clobber(l) -> (MSUB a x y)
+(ADD a l:(MNEG x y)) && l.Uses==1 && clobber(l) -> (MSUB a x y)
+(SUB a l:(MNEG x y)) && l.Uses==1 && clobber(l) -> (MADD a x y)
-(ADD a l:(MULW x y)) && l.Uses==1 && a.Type.Size() != 8 && x.Op!=OpARM64MOVDconst && y.Op!=OpARM64MOVDconst && a.Op!=OpARM64MOVDconst && clobber(l) -> (MADDW a x y)
-(SUB a l:(MULW x y)) && l.Uses==1 && a.Type.Size() != 8 && x.Op!=OpARM64MOVDconst && y.Op!=OpARM64MOVDconst && a.Op!=OpARM64MOVDconst && clobber(l) -> (MSUBW a x y)
-(ADD a l:(MNEGW x y)) && l.Uses==1 && a.Type.Size() != 8 && x.Op!=OpARM64MOVDconst && y.Op!=OpARM64MOVDconst && a.Op!=OpARM64MOVDconst && clobber(l) -> (MSUBW a x y)
-(SUB a l:(MNEGW x y)) && l.Uses==1 && a.Type.Size() != 8 && x.Op!=OpARM64MOVDconst && y.Op!=OpARM64MOVDconst && a.Op!=OpARM64MOVDconst && clobber(l) -> (MADDW a x y)
+(ADD a l:(MULW x y)) && a.Type.Size() != 8 && l.Uses==1 && clobber(l) -> (MADDW a x y)
+(SUB a l:(MULW x y)) && a.Type.Size() != 8 && l.Uses==1 && clobber(l) -> (MSUBW a x y)
+(ADD a l:(MNEGW x y)) && a.Type.Size() != 8 && l.Uses==1 && clobber(l) -> (MSUBW a x y)
+(SUB a l:(MNEGW x y)) && a.Type.Size() != 8 && l.Uses==1 && clobber(l) -> (MADDW a x y)
// mul by constant
(MUL x (MOVDconst [-1])) -> (NEG x)
@@ -1191,6 +1210,94 @@
(MNEGW x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) -> (SLLconst <x.Type> [log2(c/7)] (SUBshiftLL <x.Type> x x [3]))
(MNEGW x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) -> (NEG (SLLconst <x.Type> [log2(c/9)] (ADDshiftLL <x.Type> x x [3])))
+(MADD a x (MOVDconst [-1])) -> (SUB a x)
+(MADD a _ (MOVDconst [0])) -> a
+(MADD a x (MOVDconst [1])) -> (ADD a x)
+(MADD a x (MOVDconst [c])) && isPowerOfTwo(c) -> (ADDshiftLL a x [log2(c)])
+(MADD a x (MOVDconst [c])) && isPowerOfTwo(c-1) && c>=3 -> (ADD a (ADDshiftLL <x.Type> x x [log2(c-1)]))
+(MADD a x (MOVDconst [c])) && isPowerOfTwo(c+1) && c>=7 -> (SUB a (SUBshiftLL <x.Type> x x [log2(c+1)]))
+(MADD a x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo(c/3) -> (SUBshiftLL a (SUBshiftLL <x.Type> x x [2]) [log2(c/3)])
+(MADD a x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo(c/5) -> (ADDshiftLL a (ADDshiftLL <x.Type> x x [2]) [log2(c/5)])
+(MADD a x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo(c/7) -> (SUBshiftLL a (SUBshiftLL <x.Type> x x [3]) [log2(c/7)])
+(MADD a x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo(c/9) -> (ADDshiftLL a (ADDshiftLL <x.Type> x x [3]) [log2(c/9)])
+
+(MADD a (MOVDconst [-1]) x) -> (SUB a x)
+(MADD a (MOVDconst [0]) _) -> a
+(MADD a (MOVDconst [1]) x) -> (ADD a x)
+(MADD a (MOVDconst [c]) x) && isPowerOfTwo(c) -> (ADDshiftLL a x [log2(c)])
+(MADD a (MOVDconst [c]) x) && isPowerOfTwo(c-1) && c>=3 -> (ADD a (ADDshiftLL <x.Type> x x [log2(c-1)]))
+(MADD a (MOVDconst [c]) x) && isPowerOfTwo(c+1) && c>=7 -> (SUB a (SUBshiftLL <x.Type> x x [log2(c+1)]))
+(MADD a (MOVDconst [c]) x) && c%3 == 0 && isPowerOfTwo(c/3) -> (SUBshiftLL a (SUBshiftLL <x.Type> x x [2]) [log2(c/3)])
+(MADD a (MOVDconst [c]) x) && c%5 == 0 && isPowerOfTwo(c/5) -> (ADDshiftLL a (ADDshiftLL <x.Type> x x [2]) [log2(c/5)])
+(MADD a (MOVDconst [c]) x) && c%7 == 0 && isPowerOfTwo(c/7) -> (SUBshiftLL a (SUBshiftLL <x.Type> x x [3]) [log2(c/7)])
+(MADD a (MOVDconst [c]) x) && c%9 == 0 && isPowerOfTwo(c/9) -> (ADDshiftLL a (ADDshiftLL <x.Type> x x [3]) [log2(c/9)])
+
+(MADDW a x (MOVDconst [c])) && int32(c)==-1 -> (SUB a x)
+(MADDW a _ (MOVDconst [c])) && int32(c)==0 -> a
+(MADDW a x (MOVDconst [c])) && int32(c)==1 -> (ADD a x)
+(MADDW a x (MOVDconst [c])) && isPowerOfTwo(c) -> (ADDshiftLL a x [log2(c)])
+(MADDW a x (MOVDconst [c])) && isPowerOfTwo(c-1) && int32(c)>=3 -> (ADD a (ADDshiftLL <x.Type> x x [log2(c-1)]))
+(MADDW a x (MOVDconst [c])) && isPowerOfTwo(c+1) && int32(c)>=7 -> (SUB a (SUBshiftLL <x.Type> x x [log2(c+1)]))
+(MADDW a x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) -> (SUBshiftLL a (SUBshiftLL <x.Type> x x [2]) [log2(c/3)])
+(MADDW a x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) -> (ADDshiftLL a (ADDshiftLL <x.Type> x x [2]) [log2(c/5)])
+(MADDW a x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) -> (SUBshiftLL a (SUBshiftLL <x.Type> x x [3]) [log2(c/7)])
+(MADDW a x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) -> (ADDshiftLL a (ADDshiftLL <x.Type> x x [3]) [log2(c/9)])
+
+(MADDW a (MOVDconst [c]) x) && int32(c)==-1 -> (SUB a x)
+(MADDW a (MOVDconst [c]) _) && int32(c)==0 -> a
+(MADDW a (MOVDconst [c]) x) && int32(c)==1 -> (ADD a x)
+(MADDW a (MOVDconst [c]) x) && isPowerOfTwo(c) -> (ADDshiftLL a x [log2(c)])
+(MADDW a (MOVDconst [c]) x) && isPowerOfTwo(c-1) && int32(c)>=3 -> (ADD a (ADDshiftLL <x.Type> x x [log2(c-1)]))
+(MADDW a (MOVDconst [c]) x) && isPowerOfTwo(c+1) && int32(c)>=7 -> (SUB a (SUBshiftLL <x.Type> x x [log2(c+1)]))
+(MADDW a (MOVDconst [c]) x) && c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) -> (SUBshiftLL a (SUBshiftLL <x.Type> x x [2]) [log2(c/3)])
+(MADDW a (MOVDconst [c]) x) && c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) -> (ADDshiftLL a (ADDshiftLL <x.Type> x x [2]) [log2(c/5)])
+(MADDW a (MOVDconst [c]) x) && c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) -> (SUBshiftLL a (SUBshiftLL <x.Type> x x [3]) [log2(c/7)])
+(MADDW a (MOVDconst [c]) x) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) -> (ADDshiftLL a (ADDshiftLL <x.Type> x x [3]) [log2(c/9)])
+
+(MSUB a x (MOVDconst [-1])) -> (ADD a x)
+(MSUB a _ (MOVDconst [0])) -> a
+(MSUB a x (MOVDconst [1])) -> (SUB a x)
+(MSUB a x (MOVDconst [c])) && isPowerOfTwo(c) -> (SUBshiftLL a x [log2(c)])
+(MSUB a x (MOVDconst [c])) && isPowerOfTwo(c-1) && c>=3 -> (SUB a (ADDshiftLL <x.Type> x x [log2(c-1)]))
+(MSUB a x (MOVDconst [c])) && isPowerOfTwo(c+1) && c>=7 -> (ADD a (SUBshiftLL <x.Type> x x [log2(c+1)]))
+(MSUB a x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo(c/3) -> (ADDshiftLL a (SUBshiftLL <x.Type> x x [2]) [log2(c/3)])
+(MSUB a x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo(c/5) -> (SUBshiftLL a (ADDshiftLL <x.Type> x x [2]) [log2(c/5)])
+(MSUB a x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo(c/7) -> (ADDshiftLL a (SUBshiftLL <x.Type> x x [3]) [log2(c/7)])
+(MSUB a x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo(c/9) -> (SUBshiftLL a (ADDshiftLL <x.Type> x x [3]) [log2(c/9)])
+
+(MSUB a (MOVDconst [-1]) x) -> (ADD a x)
+(MSUB a (MOVDconst [0]) _) -> a
+(MSUB a (MOVDconst [1]) x) -> (SUB a x)
+(MSUB a (MOVDconst [c]) x) && isPowerOfTwo(c) -> (SUBshiftLL a x [log2(c)])
+(MSUB a (MOVDconst [c]) x) && isPowerOfTwo(c-1) && c>=3 -> (SUB a (ADDshiftLL <x.Type> x x [log2(c-1)]))
+(MSUB a (MOVDconst [c]) x) && isPowerOfTwo(c+1) && c>=7 -> (ADD a (SUBshiftLL <x.Type> x x [log2(c+1)]))
+(MSUB a (MOVDconst [c]) x) && c%3 == 0 && isPowerOfTwo(c/3) -> (ADDshiftLL a (SUBshiftLL <x.Type> x x [2]) [log2(c/3)])
+(MSUB a (MOVDconst [c]) x) && c%5 == 0 && isPowerOfTwo(c/5) -> (SUBshiftLL a (ADDshiftLL <x.Type> x x [2]) [log2(c/5)])
+(MSUB a (MOVDconst [c]) x) && c%7 == 0 && isPowerOfTwo(c/7) -> (ADDshiftLL a (SUBshiftLL <x.Type> x x [3]) [log2(c/7)])
+(MSUB a (MOVDconst [c]) x) && c%9 == 0 && isPowerOfTwo(c/9) -> (SUBshiftLL a (ADDshiftLL <x.Type> x x [3]) [log2(c/9)])
+
+(MSUBW a x (MOVDconst [c])) && int32(c)==-1 -> (ADD a x)
+(MSUBW a _ (MOVDconst [c])) && int32(c)==0 -> a
+(MSUBW a x (MOVDconst [c])) && int32(c)==1 -> (SUB a x)
+(MSUBW a x (MOVDconst [c])) && isPowerOfTwo(c) -> (SUBshiftLL a x [log2(c)])
+(MSUBW a x (MOVDconst [c])) && isPowerOfTwo(c-1) && int32(c)>=3 -> (SUB a (ADDshiftLL <x.Type> x x [log2(c-1)]))
+(MSUBW a x (MOVDconst [c])) && isPowerOfTwo(c+1) && int32(c)>=7 -> (ADD a (SUBshiftLL <x.Type> x x [log2(c+1)]))
+(MSUBW a x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) -> (ADDshiftLL a (SUBshiftLL <x.Type> x x [2]) [log2(c/3)])
+(MSUBW a x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) -> (SUBshiftLL a (ADDshiftLL <x.Type> x x [2]) [log2(c/5)])
+(MSUBW a x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) -> (ADDshiftLL a (SUBshiftLL <x.Type> x x [3]) [log2(c/7)])
+(MSUBW a x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) -> (SUBshiftLL a (ADDshiftLL <x.Type> x x [3]) [log2(c/9)])
+
+(MSUBW a (MOVDconst [c]) x) && int32(c)==-1 -> (ADD a x)
+(MSUBW a (MOVDconst [c]) _) && int32(c)==0 -> a
+(MSUBW a (MOVDconst [c]) x) && int32(c)==1 -> (SUB a x)
+(MSUBW a (MOVDconst [c]) x) && isPowerOfTwo(c) -> (SUBshiftLL a x [log2(c)])
+(MSUBW a (MOVDconst [c]) x) && isPowerOfTwo(c-1) && int32(c)>=3 -> (SUB a (ADDshiftLL <x.Type> x x [log2(c-1)]))
+(MSUBW a (MOVDconst [c]) x) && isPowerOfTwo(c+1) && int32(c)>=7 -> (ADD a (SUBshiftLL <x.Type> x x [log2(c+1)]))
+(MSUBW a (MOVDconst [c]) x) && c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) -> (ADDshiftLL a (SUBshiftLL <x.Type> x x [2]) [log2(c/3)])
+(MSUBW a (MOVDconst [c]) x) && c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) -> (SUBshiftLL a (ADDshiftLL <x.Type> x x [2]) [log2(c/5)])
+(MSUBW a (MOVDconst [c]) x) && c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) -> (ADDshiftLL a (SUBshiftLL <x.Type> x x [3]) [log2(c/7)])
+(MSUBW a (MOVDconst [c]) x) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) -> (SUBshiftLL a (ADDshiftLL <x.Type> x x [3]) [log2(c/9)])
+
// div by constant
(UDIV x (MOVDconst [1])) -> x
(UDIV x (MOVDconst [c])) && isPowerOfTwo(c) -> (SRLconst [log2(c)] x)
@@ -1242,6 +1349,14 @@
(MULW (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [int64(int32(c)*int32(d))])
(MNEG (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [-c*d])
(MNEGW (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [-int64(int32(c)*int32(d))])
+(MADD (MOVDconst [c]) x y) -> (ADDconst [c] (MUL <x.Type> x y))
+(MADDW (MOVDconst [c]) x y) -> (ADDconst [c] (MULW <x.Type> x y))
+(MSUB (MOVDconst [c]) x y) -> (ADDconst [c] (MNEG <x.Type> x y))
+(MSUBW (MOVDconst [c]) x y) -> (ADDconst [c] (MNEGW <x.Type> x y))
+(MADD a (MOVDconst [c]) (MOVDconst [d])) -> (ADDconst [c*d] a)
+(MADDW a (MOVDconst [c]) (MOVDconst [d])) -> (ADDconst [int64(int32(c)*int32(d))] a)
+(MSUB a (MOVDconst [c]) (MOVDconst [d])) -> (SUBconst [c*d] a)
+(MSUBW a (MOVDconst [c]) (MOVDconst [d])) -> (SUBconst [int64(int32(c)*int32(d))] a)
(DIV (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [c/d])
(UDIV (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [int64(uint64(c)/uint64(d))])
(DIVW (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [int64(int32(c)/int32(d))])
@@ -1490,6 +1605,12 @@
(CSEL0 {arm64Negate(bool.Op)} x flagArg(bool))
// absorb shifts into ops
+(NEG x:(SLLconst [c] y)) && clobberIfDead(x) -> (NEGshiftLL [c] y)
+(NEG x:(SRLconst [c] y)) && clobberIfDead(x) -> (NEGshiftRL [c] y)
+(NEG x:(SRAconst [c] y)) && clobberIfDead(x) -> (NEGshiftRA [c] y)
+(MVN x:(SLLconst [c] y)) && clobberIfDead(x) -> (MVNshiftLL [c] y)
+(MVN x:(SRLconst [c] y)) && clobberIfDead(x) -> (MVNshiftRL [c] y)
+(MVN x:(SRAconst [c] y)) && clobberIfDead(x) -> (MVNshiftRA [c] y)
(ADD x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) -> (ADDshiftLL x0 y [c])
(ADD x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) -> (ADDshiftRL x0 y [c])
(ADD x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) -> (ADDshiftRA x0 y [c])
@@ -1520,6 +1641,12 @@
(CMP x0:(SRLconst [c] y) x1) && clobberIfDead(x0) -> (InvertFlags (CMPshiftRL x1 y [c]))
(CMP x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) -> (CMPshiftRA x0 y [c])
(CMP x0:(SRAconst [c] y) x1) && clobberIfDead(x0) -> (InvertFlags (CMPshiftRA x1 y [c]))
+(CMN x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) -> (CMNshiftLL x0 y [c])
+(CMN x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) -> (CMNshiftRL x0 y [c])
+(CMN x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) -> (CMNshiftRA x0 y [c])
+(TST x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) -> (TSTshiftLL x0 y [c])
+(TST x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) -> (TSTshiftRL x0 y [c])
+(TST x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) -> (TSTshiftRA x0 y [c])
// prefer *const ops to *shift ops
(ADDshiftLL (MOVDconst [c]) x [d]) -> (ADDconst [c] (SLLconst <x.Type> x [d]))
@@ -1537,8 +1664,20 @@
(CMPshiftLL (MOVDconst [c]) x [d]) -> (InvertFlags (CMPconst [c] (SLLconst <x.Type> x [d])))
(CMPshiftRL (MOVDconst [c]) x [d]) -> (InvertFlags (CMPconst [c] (SRLconst <x.Type> x [d])))
(CMPshiftRA (MOVDconst [c]) x [d]) -> (InvertFlags (CMPconst [c] (SRAconst <x.Type> x [d])))
+(CMNshiftLL (MOVDconst [c]) x [d]) -> (CMNconst [c] (SLLconst <x.Type> x [d]))
+(CMNshiftRL (MOVDconst [c]) x [d]) -> (CMNconst [c] (SRLconst <x.Type> x [d]))
+(CMNshiftRA (MOVDconst [c]) x [d]) -> (CMNconst [c] (SRAconst <x.Type> x [d]))
+(TSTshiftLL (MOVDconst [c]) x [d]) -> (TSTconst [c] (SLLconst <x.Type> x [d]))
+(TSTshiftRL (MOVDconst [c]) x [d]) -> (TSTconst [c] (SRLconst <x.Type> x [d]))
+(TSTshiftRA (MOVDconst [c]) x [d]) -> (TSTconst [c] (SRAconst <x.Type> x [d]))
// constant folding in *shift ops
+(MVNshiftLL (MOVDconst [c]) [d]) -> (MOVDconst [^int64(uint64(c)<<uint64(d))])
+(MVNshiftRL (MOVDconst [c]) [d]) -> (MOVDconst [^int64(uint64(c)>>uint64(d))])
+(MVNshiftRA (MOVDconst [c]) [d]) -> (MOVDconst [^(c>>uint64(d))])
+(NEGshiftLL (MOVDconst [c]) [d]) -> (MOVDconst [-int64(uint64(c)<<uint64(d))])
+(NEGshiftRL (MOVDconst [c]) [d]) -> (MOVDconst [-int64(uint64(c)>>uint64(d))])
+(NEGshiftRA (MOVDconst [c]) [d]) -> (MOVDconst [-(c>>uint64(d))])
(ADDshiftLL x (MOVDconst [c]) [d]) -> (ADDconst x [int64(uint64(c)<<uint64(d))])
(ADDshiftRL x (MOVDconst [c]) [d]) -> (ADDconst x [int64(uint64(c)>>uint64(d))])
(ADDshiftRA x (MOVDconst [c]) [d]) -> (ADDconst x [c>>uint64(d)])
@@ -1566,6 +1705,12 @@
(CMPshiftLL x (MOVDconst [c]) [d]) -> (CMPconst x [int64(uint64(c)<<uint64(d))])
(CMPshiftRL x (MOVDconst [c]) [d]) -> (CMPconst x [int64(uint64(c)>>uint64(d))])
(CMPshiftRA x (MOVDconst [c]) [d]) -> (CMPconst x [c>>uint64(d)])
+(CMNshiftLL x (MOVDconst [c]) [d]) -> (CMNconst x [int64(uint64(c)<<uint64(d))])
+(CMNshiftRL x (MOVDconst [c]) [d]) -> (CMNconst x [int64(uint64(c)>>uint64(d))])
+(CMNshiftRA x (MOVDconst [c]) [d]) -> (CMNconst x [c>>uint64(d)])
+(TSTshiftLL x (MOVDconst [c]) [d]) -> (TSTconst x [int64(uint64(c)<<uint64(d))])
+(TSTshiftRL x (MOVDconst [c]) [d]) -> (TSTconst x [int64(uint64(c)>>uint64(d))])
+(TSTshiftRA x (MOVDconst [c]) [d]) -> (TSTconst x [c>>uint64(d)])
// simplification with *shift ops
(SUBshiftLL x (SLLconst x [c]) [d]) && c==d -> (MOVDconst [0])
@@ -1590,7 +1735,7 @@
(ORNshiftRL x (SRLconst x [c]) [d]) && c==d -> (MOVDconst [-1])
(ORNshiftRA x (SRAconst x [c]) [d]) && c==d -> (MOVDconst [-1])
-// Generate rotates
+// Generate rotates with const shift
(ADDshiftLL [c] (SRLconst x [64-c]) x) -> (RORconst [64-c] x)
( ORshiftLL [c] (SRLconst x [64-c]) x) -> (RORconst [64-c] x)
(XORshiftLL [c] (SRLconst x [64-c]) x) -> (RORconst [64-c] x)
@@ -1608,6 +1753,38 @@
( ORshiftRL <t> [c] (SLLconst x [32-c]) (MOVWUreg x)) && c < 32 && t.Size() == 4 -> (RORWconst [c] x)
(XORshiftRL <t> [c] (SLLconst x [32-c]) (MOVWUreg x)) && c < 32 && t.Size() == 4 -> (RORWconst [c] x)
+(RORconst [c] (RORconst [d] x)) -> (RORconst [(c+d)&63] x)
+(RORWconst [c] (RORWconst [d] x)) -> (RORWconst [(c+d)&31] x)
+
+// Generate rotates with non-const shift.
+// These rules match the Go source code like
+// y &= 63
+// x << y | x >> (64-y)
+// "|" can also be "^" or "+".
+// As arm64 does not have a ROL instruction, so ROL(x, y) is replaced by ROR(x, -y).
+((ADD|OR|XOR) (SLL x (ANDconst <t> [63] y))
+ (CSEL0 <typ.UInt64> {cc} (SRL <typ.UInt64> x (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y)))
+ (CMPconst [64] (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y))))) && cc.(Op) == OpARM64LessThanU
+ -> (ROR x (NEG <t> y))
+((ADD|OR|XOR) (SRL <typ.UInt64> x (ANDconst <t> [63] y))
+ (CSEL0 <typ.UInt64> {cc} (SLL x (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y)))
+ (CMPconst [64] (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y))))) && cc.(Op) == OpARM64LessThanU
+ -> (ROR x y)
+
+// These rules match the Go source code like
+// y &= 31
+// x << y | x >> (32-y)
+// "|" can also be "^" or "+".
+// As arm64 does not have a ROLW instruction, so ROLW(x, y) is replaced by RORW(x, -y).
+((ADD|OR|XOR) (SLL x (ANDconst <t> [31] y))
+ (CSEL0 <typ.UInt32> {cc} (SRL <typ.UInt32> (MOVWUreg x) (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y)))
+ (CMPconst [64] (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y))))) && cc.(Op) == OpARM64LessThanU
+ -> (RORW x (NEG <t> y))
+((ADD|OR|XOR) (SRL <typ.UInt32> (MOVWUreg x) (ANDconst <t> [31] y))
+ (CSEL0 <typ.UInt32> {cc} (SLL x (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y)))
+ (CMPconst [64] (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y))))) && cc.(Op) == OpARM64LessThanU
+ -> (RORW x y)
+
// Extract from reg pair
(ADDshiftLL [c] (SRLconst x [64-c]) x2) -> (EXTRconst [64-c] x2 x)
( ORshiftLL [c] (SRLconst x [64-c]) x2) -> (EXTRconst [64-c] x2 x)
@@ -1626,6 +1803,9 @@
(SRLconst [c] (SLLconst [c] x)) && 0 < c && c < 64 -> (ANDconst [1<<uint(64-c)-1] x) // mask out high bits
(SLLconst [c] (SRLconst [c] x)) && 0 < c && c < 64 -> (ANDconst [^(1<<uint(c)-1)] x) // mask out low bits
+// Special case setting bit as 1. An example is math.Copysign(c,-1)
+(ORconst [c1] (ANDconst [c2] x)) && c2|c1 == ^0 -> (ORconst [c1] x)
+
// bitfield ops
// sbfiz
diff --git a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go
index eb0ad530a1..fc0a41527b 100644
--- a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go
+++ b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go
@@ -212,6 +212,7 @@ func init() {
// unary ops
{name: "MVN", argLength: 1, reg: gp11, asm: "MVN"}, // ^arg0
{name: "NEG", argLength: 1, reg: gp11, asm: "NEG"}, // -arg0
+ {name: "FABSD", argLength: 1, reg: fp11, asm: "FABSD"}, // abs(arg0), float64
{name: "FNEGS", argLength: 1, reg: fp11, asm: "FNEGS"}, // -arg0, float32
{name: "FNEGD", argLength: 1, reg: fp11, asm: "FNEGD"}, // -arg0, float64
{name: "FSQRTD", argLength: 1, reg: fp11, asm: "FSQRTD"}, // sqrt(arg0), float64
@@ -248,6 +249,8 @@ func init() {
{name: "SRLconst", argLength: 1, reg: gp11, asm: "LSR", aux: "Int64"}, // arg0 >> auxInt, unsigned
{name: "SRA", argLength: 2, reg: gp21, asm: "ASR"}, // arg0 >> arg1, signed, shift amount is mod 64
{name: "SRAconst", argLength: 1, reg: gp11, asm: "ASR", aux: "Int64"}, // arg0 >> auxInt, signed
+ {name: "ROR", argLength: 2, reg: gp21, asm: "ROR"}, // arg0 right rotate by (arg1 mod 64) bits
+ {name: "RORW", argLength: 2, reg: gp21, asm: "RORW"}, // arg0 right rotate by (arg1 mod 32) bits
{name: "RORconst", argLength: 1, reg: gp11, asm: "ROR", aux: "Int64"}, // arg0 right rotate by auxInt bits
{name: "RORWconst", argLength: 1, reg: gp11, asm: "RORW", aux: "Int64"}, // uint32(arg0) right rotate by auxInt bits
{name: "EXTRconst", argLength: 2, reg: gp21, asm: "EXTR", aux: "Int64"}, // extract 64 bits from arg0:arg1 starting at lsb auxInt
@@ -270,6 +273,12 @@ func init() {
{name: "FCMPD", argLength: 2, reg: fp2flags, asm: "FCMPD", typ: "Flags"}, // arg0 compare to arg1, float64
// shifted ops
+ {name: "MVNshiftLL", argLength: 1, reg: gp11, asm: "MVN", aux: "Int64"}, // ^(arg0<<auxInt)
+ {name: "MVNshiftRL", argLength: 1, reg: gp11, asm: "MVN", aux: "Int64"}, // ^(arg0>>auxInt), unsigned shift
+ {name: "MVNshiftRA", argLength: 1, reg: gp11, asm: "MVN", aux: "Int64"}, // ^(arg0>>auxInt), signed shift
+ {name: "NEGshiftLL", argLength: 1, reg: gp11, asm: "NEG", aux: "Int64"}, // -(arg0<<auxInt)
+ {name: "NEGshiftRL", argLength: 1, reg: gp11, asm: "NEG", aux: "Int64"}, // -(arg0>>auxInt), unsigned shift
+ {name: "NEGshiftRA", argLength: 1, reg: gp11, asm: "NEG", aux: "Int64"}, // -(arg0>>auxInt), signed shift
{name: "ADDshiftLL", argLength: 2, reg: gp21, asm: "ADD", aux: "Int64"}, // arg0 + arg1<<auxInt
{name: "ADDshiftRL", argLength: 2, reg: gp21, asm: "ADD", aux: "Int64"}, // arg0 + arg1>>auxInt, unsigned shift
{name: "ADDshiftRA", argLength: 2, reg: gp21, asm: "ADD", aux: "Int64"}, // arg0 + arg1>>auxInt, signed shift
@@ -297,6 +306,12 @@ func init() {
{name: "CMPshiftLL", argLength: 2, reg: gp2flags, asm: "CMP", aux: "Int64", typ: "Flags"}, // arg0 compare to arg1<<auxInt
{name: "CMPshiftRL", argLength: 2, reg: gp2flags, asm: "CMP", aux: "Int64", typ: "Flags"}, // arg0 compare to arg1>>auxInt, unsigned shift
{name: "CMPshiftRA", argLength: 2, reg: gp2flags, asm: "CMP", aux: "Int64", typ: "Flags"}, // arg0 compare to arg1>>auxInt, signed shift
+ {name: "CMNshiftLL", argLength: 2, reg: gp2flags, asm: "CMN", aux: "Int64", typ: "Flags"}, // (arg0 + arg1<<auxInt) compare to 0
+ {name: "CMNshiftRL", argLength: 2, reg: gp2flags, asm: "CMN", aux: "Int64", typ: "Flags"}, // (arg0 + arg1>>auxInt) compare to 0, unsigned shift
+ {name: "CMNshiftRA", argLength: 2, reg: gp2flags, asm: "CMN", aux: "Int64", typ: "Flags"}, // (arg0 + arg1>>auxInt) compare to 0, signed shift
+ {name: "TSTshiftLL", argLength: 2, reg: gp2flags, asm: "TST", aux: "Int64", typ: "Flags"}, // (arg0 & arg1<<auxInt) compare to 0
+ {name: "TSTshiftRL", argLength: 2, reg: gp2flags, asm: "TST", aux: "Int64", typ: "Flags"}, // (arg0 & arg1>>auxInt) compare to 0, unsigned shift
+ {name: "TSTshiftRA", argLength: 2, reg: gp2flags, asm: "TST", aux: "Int64", typ: "Flags"}, // (arg0 & arg1>>auxInt) compare to 0, signed shift
// bitfield ops
// for all bitfield ops lsb is auxInt>>8, width is auxInt&0xff
@@ -388,6 +403,8 @@ func init() {
{name: "FMOVDgpfp", argLength: 1, reg: gpfp, asm: "FMOVD"}, // move int64 to float64 (no conversion)
{name: "FMOVDfpgp", argLength: 1, reg: fpgp, asm: "FMOVD"}, // move float64 to int64 (no conversion)
+ {name: "FMOVSgpfp", argLength: 1, reg: gpfp, asm: "FMOVS"}, // move 32bits from int to float reg (no conversion)
+ {name: "FMOVSfpgp", argLength: 1, reg: fpgp, asm: "FMOVS"}, // move 32bits from float to int reg, zero extend (no conversion)
// conversions
{name: "MOVBreg", argLength: 1, reg: gp11, asm: "MOVB"}, // move from arg0, sign-extended from byte
@@ -422,6 +439,7 @@ func init() {
// floating-point round to integral
{name: "FRINTAD", argLength: 1, reg: fp11, asm: "FRINTAD"},
{name: "FRINTMD", argLength: 1, reg: fp11, asm: "FRINTMD"},
+ {name: "FRINTND", argLength: 1, reg: fp11, asm: "FRINTND"},
{name: "FRINTPD", argLength: 1, reg: fp11, asm: "FRINTPD"},
{name: "FRINTZD", argLength: 1, reg: fp11, asm: "FRINTZD"},
diff --git a/src/cmd/compile/internal/ssa/gen/PPC64.rules b/src/cmd/compile/internal/ssa/gen/PPC64.rules
index 6ef8c7b5b9..7d79c9ad50 100644
--- a/src/cmd/compile/internal/ssa/gen/PPC64.rules
+++ b/src/cmd/compile/internal/ssa/gen/PPC64.rules
@@ -25,6 +25,7 @@
(Mul64 x y) -> (MULLD x y)
(Mul(32|16|8) x y) -> (MULLW x y)
+(Mul64uhilo x y) -> (LoweredMuluhilo x y)
(Div64 x y) -> (DIVD x y)
(Div64u x y) -> (DIVDU x y)
@@ -74,11 +75,11 @@
(ConstBool [b]) -> (MOVDconst [b])
// Constant folding
-(FABS (FMOVDconst [x])) -> (FMOVDconst [f2i(math.Abs(i2f(x)))])
-(FSQRT (FMOVDconst [x])) -> (FMOVDconst [f2i(math.Sqrt(i2f(x)))])
-(FFLOOR (FMOVDconst [x])) -> (FMOVDconst [f2i(math.Floor(i2f(x)))])
-(FCEIL (FMOVDconst [x])) -> (FMOVDconst [f2i(math.Ceil(i2f(x)))])
-(FTRUNC (FMOVDconst [x])) -> (FMOVDconst [f2i(math.Trunc(i2f(x)))])
+(FABS (FMOVDconst [x])) -> (FMOVDconst [auxFrom64F(math.Abs(auxTo64F(x)))])
+(FSQRT (FMOVDconst [x])) -> (FMOVDconst [auxFrom64F(math.Sqrt(auxTo64F(x)))])
+(FFLOOR (FMOVDconst [x])) -> (FMOVDconst [auxFrom64F(math.Floor(auxTo64F(x)))])
+(FCEIL (FMOVDconst [x])) -> (FMOVDconst [auxFrom64F(math.Ceil(auxTo64F(x)))])
+(FTRUNC (FMOVDconst [x])) -> (FMOVDconst [auxFrom64F(math.Trunc(auxTo64F(x)))])
// Rotate generation with const shift
(ADD (SLDconst x [c]) (SRDconst x [d])) && d == 64-c -> (ROTLconst [c] x)
@@ -168,6 +169,20 @@
(Rsh8x32 x (MOVDconst [c])) && uint32(c) < 8 -> (SRAWconst (SignExt8to32 x) [c])
(Rsh8Ux32 x (MOVDconst [c])) && uint32(c) < 8 -> (SRWconst (ZeroExt8to32 x) [c])
+// Lower bounded shifts first. No need to check shift value.
+(Lsh64x(64|32|16|8) x y) && shiftIsBounded(v) -> (SLD x y)
+(Lsh32x(64|32|16|8) x y) && shiftIsBounded(v) -> (SLW x y)
+(Lsh16x(64|32|16|8) x y) && shiftIsBounded(v) -> (SLW x y)
+(Lsh8x(64|32|16|8) x y) && shiftIsBounded(v) -> (SLW x y)
+(Rsh64Ux(64|32|16|8) x y) && shiftIsBounded(v) -> (SRD x y)
+(Rsh32Ux(64|32|16|8) x y) && shiftIsBounded(v) -> (SRW x y)
+(Rsh16Ux(64|32|16|8) x y) && shiftIsBounded(v) -> (SRW (MOVHZreg x) y)
+(Rsh8Ux(64|32|16|8) x y) && shiftIsBounded(v) -> (SRW (MOVBZreg x) y)
+(Rsh64x(64|32|16|8) x y) && shiftIsBounded(v) -> (SRAD x y)
+(Rsh32x(64|32|16|8) x y) && shiftIsBounded(v) -> (SRAW x y)
+(Rsh16x(64|32|16|8) x y) && shiftIsBounded(v) -> (SRAW (MOVHreg x) y)
+(Rsh8x(64|32|16|8) x y) && shiftIsBounded(v) -> (SRAW (MOVBreg x) y)
+
// non-constant rotates
// These are subexpressions found in statements that can become rotates
// In these cases the shift count is known to be < 64 so the more complicated expressions
@@ -660,14 +675,51 @@
(MOVWreg y:(AND (MOVDconst [c]) _)) && uint64(c) <= 0x7FFFFFFF -> y
// small and of zero-extend -> either zero-extend or small and
- // degenerate-and
(ANDconst [c] y:(MOVBZreg _)) && c&0xFF == 0xFF -> y
+(ANDconst [0xFF] y:(MOVBreg _)) -> y
(ANDconst [c] y:(MOVHZreg _)) && c&0xFFFF == 0xFFFF -> y
-(ANDconst [c] y:(MOVWZreg _)) && c&0xFFFFFFFF == 0xFFFFFFFF -> y
- // normal case
-(ANDconst [c] (MOVBZreg x)) -> (ANDconst [c&0xFF] x)
-(ANDconst [c] (MOVHZreg x)) -> (ANDconst [c&0xFFFF] x)
-(ANDconst [c] (MOVWZreg x)) -> (ANDconst [c&0xFFFFFFFF] x)
+(ANDconst [0xFFFF] y:(MOVHreg _)) -> y
+
+(AND (MOVDconst [c]) y:(MOVWZreg _)) && c&0xFFFFFFFF == 0xFFFFFFFF -> y
+(AND (MOVDconst [0xFFFFFFFF]) y:(MOVWreg x)) -> (MOVWZreg x)
+// normal case
+(ANDconst [c] (MOV(B|BZ)reg x)) -> (ANDconst [c&0xFF] x)
+(ANDconst [c] (MOV(H|HZ)reg x)) -> (ANDconst [c&0xFFFF] x)
+(ANDconst [c] (MOV(W|WZ)reg x)) -> (ANDconst [c&0xFFFFFFFF] x)
+
+// Eliminate unnecessary sign/zero extend following right shift
+(MOV(B|H|W)Zreg (SRWconst [c] (MOVBZreg x))) -> (SRWconst [c] (MOVBZreg x))
+(MOV(H|W)Zreg (SRWconst [c] (MOVHZreg x))) -> (SRWconst [c] (MOVHZreg x))
+(MOVWZreg (SRWconst [c] (MOVWZreg x))) -> (SRWconst [c] (MOVWZreg x))
+(MOV(B|H|W)reg (SRAWconst [c] (MOVBreg x))) -> (SRAWconst [c] (MOVBreg x))
+(MOV(H|W)reg (SRAWconst [c] (MOVHreg x))) -> (SRAWconst [c] (MOVHreg x))
+(MOVWreg (SRAWconst [c] (MOVWreg x))) -> (SRAWconst [c] (MOVWreg x))
+
+(MOVWZreg (SRWconst [c] x)) && sizeof(x.Type) <= 32 -> (SRWconst [c] x)
+(MOVHZreg (SRWconst [c] x)) && sizeof(x.Type) <= 16 -> (SRWconst [c] x)
+(MOVBZreg (SRWconst [c] x)) && sizeof(x.Type) == 8 -> (SRWconst [c] x)
+(MOVWreg (SRAWconst [c] x)) && sizeof(x.Type) <= 32 -> (SRAWconst [c] x)
+(MOVHreg (SRAWconst [c] x)) && sizeof(x.Type) <= 16 -> (SRAWconst [c] x)
+(MOVBreg (SRAWconst [c] x)) && sizeof(x.Type) == 8 -> (SRAWconst [c] x)
+
+// initial right shift will handle sign/zero extend
+(MOVBZreg (SRDconst [c] x)) && c>=56 -> (SRDconst [c] x)
+(MOVBreg (SRDconst [c] x)) && c>56 -> (SRDconst [c] x)
+(MOVBreg (SRDconst [c] x)) && c==56 -> (SRADconst [c] x)
+(MOVBZreg (SRWconst [c] x)) && c>=24 -> (SRWconst [c] x)
+(MOVBreg (SRWconst [c] x)) && c>24 -> (SRWconst [c] x)
+(MOVBreg (SRWconst [c] x)) && c==24 -> (SRAWconst [c] x)
+
+(MOVHZreg (SRDconst [c] x)) && c>=48 -> (SRDconst [c] x)
+(MOVHreg (SRDconst [c] x)) && c>48 -> (SRDconst [c] x)
+(MOVHreg (SRDconst [c] x)) && c==48 -> (SRADconst [c] x)
+(MOVHZreg (SRWconst [c] x)) && c>=16 -> (SRWconst [c] x)
+(MOVHreg (SRWconst [c] x)) && c>16 -> (SRWconst [c] x)
+(MOVHreg (SRWconst [c] x)) && c==16 -> (SRAWconst [c] x)
+
+(MOVWZreg (SRDconst [c] x)) && c>=32 -> (SRDconst [c] x)
+(MOVWreg (SRDconst [c] x)) && c>32 -> (SRDconst [c] x)
+(MOVWreg (SRDconst [c] x)) && c==32 -> (SRADconst [c] x)
// Various redundant zero/sign extension combinations.
(MOVBZreg y:(MOVBZreg _)) -> y // repeat
@@ -796,11 +848,19 @@
(MOVHZload [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(off1+off2) -> (MOVHZload [off1+off2] {sym} x mem)
(MOVBZload [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(off1+off2) -> (MOVBZload [off1+off2] {sym} x mem)
+// Determine load + addressing that can be done as a register indexed load
+(MOV(D|W|WZ|H|HZ|BZ)load [0] {sym} p:(ADD ptr idx) mem) && sym == nil && p.Uses == 1 -> (MOV(D|W|WZ|H|HZ|BZ)loadidx ptr idx mem)
+
+// Determine indexed loads with constant values that can be done without index
+(MOV(D|W|WZ|H|HZ|BZ)loadidx ptr (MOVDconst [c]) mem) && is16Bit(c) -> (MOV(D|W|WZ|H|HZ|BZ)load [c] ptr mem)
+(MOV(D|W|WZ|H|HZ|BZ)loadidx (MOVDconst [c]) ptr mem) && is16Bit(c) -> (MOV(D|W|WZ|H|HZ|BZ)load [c] ptr mem)
+
+
// Store of zero -> storezero
-(MOVDstore [off] {sym} ptr (MOVDconst [c]) mem) && c == 0 -> (MOVDstorezero [off] {sym} ptr mem)
-(MOVWstore [off] {sym} ptr (MOVDconst [c]) mem) && c == 0 -> (MOVWstorezero [off] {sym} ptr mem)
-(MOVHstore [off] {sym} ptr (MOVDconst [c]) mem) && c == 0 -> (MOVHstorezero [off] {sym} ptr mem)
-(MOVBstore [off] {sym} ptr (MOVDconst [c]) mem) && c == 0 -> (MOVBstorezero [off] {sym} ptr mem)
+(MOVDstore [off] {sym} ptr (MOVDconst [0]) mem) -> (MOVDstorezero [off] {sym} ptr mem)
+(MOVWstore [off] {sym} ptr (MOVDconst [0]) mem) -> (MOVWstorezero [off] {sym} ptr mem)
+(MOVHstore [off] {sym} ptr (MOVDconst [0]) mem) -> (MOVHstorezero [off] {sym} ptr mem)
+(MOVBstore [off] {sym} ptr (MOVDconst [0]) mem) -> (MOVBstorezero [off] {sym} ptr mem)
// Fold offsets for storezero
(MOVDstorezero [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(off1+off2) ->
@@ -812,6 +872,13 @@
(MOVBstorezero [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(off1+off2) ->
(MOVBstorezero [off1+off2] {sym} x mem)
+// Stores with addressing that can be done as indexed stores
+(MOV(D|W|H|B)store [off] {sym} p:(ADD ptr idx) val mem) && off == 0 && sym == nil && p.Uses == 1 -> (MOV(D|W|H|B)storeidx ptr idx val mem)
+
+// Stores with constant index values can be done without indexed instructions
+(MOV(D|W|H|B)storeidx ptr (MOVDconst [c]) val mem) && is16Bit(c) -> (MOV(D|W|H|B)store [c] ptr val mem)
+(MOV(D|W|H|B)storeidx (MOVDconst [c]) ptr val mem) && is16Bit(c) -> (MOV(D|W|H|B)store [c] ptr val mem)
+
// Fold symbols into storezero
(MOVDstorezero [off1] {sym1} p:(MOVDaddr [off2] {sym2} x) mem) && canMergeSym(sym1,sym2)
&& (x.Op != OpSB || p.Uses == 1) ->
@@ -851,22 +918,43 @@
(ZeroExt16to(32|64) x) -> (MOVHZreg x)
(ZeroExt32to64 x) -> (MOVWZreg x)
-(Trunc(16|32|64)to8 x) -> (MOVBreg x)
-(Trunc(32|64)to16 x) -> (MOVHreg x)
-(Trunc64to32 x) -> (MOVWreg x)
+(Trunc(16|32|64)to8 x) && isSigned(x.Type) -> (MOVBreg x)
+(Trunc(16|32|64)to8 x) -> (MOVBZreg x)
+(Trunc(32|64)to16 x) && isSigned(x.Type) -> (MOVHreg x)
+(Trunc(32|64)to16 x) -> (MOVHZreg x)
+(Trunc64to32 x) && isSigned(x.Type) -> (MOVWreg x)
+(Trunc64to32 x) -> (MOVWZreg x)
(Slicemask <t> x) -> (SRADconst (NEG <t> x) [63])
// Note that MOV??reg returns a 64-bit int, x is not necessarily that wide
// This may interact with other patterns in the future. (Compare with arm64)
-(MOVBZreg x:(MOVBZload _ _)) -> x
-(MOVHZreg x:(MOVHZload _ _)) -> x
-(MOVHreg x:(MOVHload _ _)) -> x
+(MOV(B|H|W)Zreg x:(MOVBZload _ _)) -> x
+(MOV(B|H|W)Zreg x:(MOVBZloadidx _ _ _)) -> x
+(MOV(H|W)Zreg x:(MOVHZload _ _)) -> x
+(MOV(H|W)Zreg x:(MOVHZloadidx _ _ _)) -> x
+(MOV(H|W)reg x:(MOVHload _ _)) -> x
+(MOV(H|W)reg x:(MOVHloadidx _ _ _)) -> x
+(MOVWZreg x:(MOVWZload _ _)) -> x
+(MOVWZreg x:(MOVWZloadidx _ _ _)) -> x
+(MOVWreg x:(MOVWload _ _)) -> x
+(MOVWreg x:(MOVWloadidx _ _ _)) -> x
+
+// don't extend if argument is already extended
+(MOVBreg x:(Arg <t>)) && is8BitInt(t) && isSigned(t) -> x
+(MOVBZreg x:(Arg <t>)) && is8BitInt(t) && !isSigned(t) -> x
+(MOVHreg x:(Arg <t>)) && (is8BitInt(t) || is16BitInt(t)) && isSigned(t) -> x
+(MOVHZreg x:(Arg <t>)) && (is8BitInt(t) || is16BitInt(t)) && !isSigned(t) -> x
+(MOVWreg x:(Arg <t>)) && (is8BitInt(t) || is16BitInt(t) || is32BitInt(t)) && isSigned(t) -> x
+(MOVWZreg x:(Arg <t>)) && (is8BitInt(t) || is16BitInt(t) || is32BitInt(t)) && !isSigned(t) -> x
(MOVBZreg (MOVDconst [c])) -> (MOVDconst [int64(uint8(c))])
(MOVBreg (MOVDconst [c])) -> (MOVDconst [int64(int8(c))])
(MOVHZreg (MOVDconst [c])) -> (MOVDconst [int64(uint16(c))])
(MOVHreg (MOVDconst [c])) -> (MOVDconst [int64(int16(c))])
+(MOVWreg (MOVDconst [c])) -> (MOVDconst [int64(int32(c))])
+(MOVWZreg (MOVDconst [c])) -> (MOVDconst [int64(uint32(c))])
+
// Lose widening ops fed to to stores
(MOVBstore [off] {sym} ptr (MOV(B|BZ|H|HZ|W|WZ)reg x) mem) -> (MOVBstore [off] {sym} ptr x mem)
@@ -874,6 +962,11 @@
(MOVWstore [off] {sym} ptr (MOV(W|WZ)reg x) mem) -> (MOVWstore [off] {sym} ptr x mem)
(MOVBstore [off] {sym} ptr (SRWconst (MOV(H|HZ)reg x) [c]) mem) && c <= 8 -> (MOVBstore [off] {sym} ptr (SRWconst <typ.UInt32> x [c]) mem)
(MOVBstore [off] {sym} ptr (SRWconst (MOV(W|WZ)reg x) [c]) mem) && c <= 24 -> (MOVBstore [off] {sym} ptr (SRWconst <typ.UInt32> x [c]) mem)
+(MOVBstoreidx [off] {sym} ptr idx (MOV(B|BZ|H|HZ|W|WZ)reg x) mem) -> (MOVBstoreidx [off] {sym} ptr idx x mem)
+(MOVHstoreidx [off] {sym} ptr idx (MOV(H|HZ|W|WZ)reg x) mem) -> (MOVHstoreidx [off] {sym} ptr idx x mem)
+(MOVWstoreidx [off] {sym} ptr idx (MOV(W|WZ)reg x) mem) -> (MOVWstoreidx [off] {sym} ptr idx x mem)
+(MOVBstoreidx [off] {sym} ptr idx (SRWconst (MOV(H|HZ)reg x) [c]) mem) && c <= 8 -> (MOVBstoreidx [off] {sym} ptr idx (SRWconst <typ.UInt32> x [c]) mem)
+(MOVBstoreidx [off] {sym} ptr idx (SRWconst (MOV(W|WZ)reg x) [c]) mem) && c <= 24 -> (MOVBstoreidx [off] {sym} ptr idx (SRWconst <typ.UInt32> x [c]) mem)
(MOVHBRstore {sym} ptr (MOV(H|HZ|W|WZ)reg x) mem) -> (MOVHBRstore {sym} ptr x mem)
(MOVWBRstore {sym} ptr (MOV(W|WZ)reg x) mem) -> (MOVWBRstore {sym} ptr x mem)
diff --git a/src/cmd/compile/internal/ssa/gen/PPC64Ops.go b/src/cmd/compile/internal/ssa/gen/PPC64Ops.go
index ce5d552375..c82f7312fe 100644
--- a/src/cmd/compile/internal/ssa/gen/PPC64Ops.go
+++ b/src/cmd/compile/internal/ssa/gen/PPC64Ops.go
@@ -135,11 +135,14 @@ func init() {
gp01 = regInfo{inputs: nil, outputs: []regMask{gp}}
gp11 = regInfo{inputs: []regMask{gp | sp | sb}, outputs: []regMask{gp}}
gp21 = regInfo{inputs: []regMask{gp | sp | sb, gp | sp | sb}, outputs: []regMask{gp}}
+ gp22 = regInfo{inputs: []regMask{gp | sp | sb, gp | sp | sb}, outputs: []regMask{gp, gp}}
gp1cr = regInfo{inputs: []regMask{gp | sp | sb}}
gp2cr = regInfo{inputs: []regMask{gp | sp | sb, gp | sp | sb}}
crgp = regInfo{inputs: nil, outputs: []regMask{gp}}
gpload = regInfo{inputs: []regMask{gp | sp | sb}, outputs: []regMask{gp}}
+ gploadidx = regInfo{inputs: []regMask{gp | sp | sb, gp}, outputs: []regMask{gp}}
gpstore = regInfo{inputs: []regMask{gp | sp | sb, gp | sp | sb}}
+ gpstoreidx = regInfo{inputs: []regMask{gp | sp | sb, gp | sp | sb, gp | sp | sb}}
gpstorezero = regInfo{inputs: []regMask{gp | sp | sb}} // ppc64.REGZERO is reserved zero value
gpxchg = regInfo{inputs: []regMask{gp | sp | sb, gp}, outputs: []regMask{gp}}
gpcas = regInfo{inputs: []regMask{gp | sp | sb, gp, gp}, outputs: []regMask{gp}}
@@ -151,7 +154,9 @@ func init() {
fp31 = regInfo{inputs: []regMask{fp, fp, fp}, outputs: []regMask{fp}}
fp2cr = regInfo{inputs: []regMask{fp, fp}}
fpload = regInfo{inputs: []regMask{gp | sp | sb}, outputs: []regMask{fp}}
+ fploadidx = regInfo{inputs: []regMask{gp | sp | sb, gp | sp | sb}, outputs: []regMask{fp}}
fpstore = regInfo{inputs: []regMask{gp | sp | sb, fp}}
+ fpstoreidx = regInfo{inputs: []regMask{gp | sp | sb, gp | sp | sb, fp}}
callerSave = regMask(gp | fp | gr)
)
ops := []opData{
@@ -170,6 +175,7 @@ func init() {
{name: "MULHW", argLength: 2, reg: gp21, asm: "MULHW", commutative: true}, // (arg0 * arg1) >> 32, signed
{name: "MULHDU", argLength: 2, reg: gp21, asm: "MULHDU", commutative: true}, // (arg0 * arg1) >> 64, unsigned
{name: "MULHWU", argLength: 2, reg: gp21, asm: "MULHWU", commutative: true}, // (arg0 * arg1) >> 32, unsigned
+ {name: "LoweredMuluhilo", argLength: 2, reg: gp22, resultNotInArgs: true}, // arg0 * arg1, returns (hi, lo)
{name: "FMUL", argLength: 2, reg: fp21, asm: "FMUL", commutative: true}, // arg0*arg1
{name: "FMULS", argLength: 2, reg: fp21, asm: "FMULS", commutative: true}, // arg0*arg1
@@ -281,6 +287,19 @@ func init() {
{name: "MOVWBRload", argLength: 2, reg: gpload, asm: "MOVWBR", aux: "SymOff", typ: "Int32", faultOnNilArg0: true, symEffect: "Read"}, // load 4 bytes zero extend reverse order
{name: "MOVHBRload", argLength: 2, reg: gpload, asm: "MOVHBR", aux: "SymOff", typ: "Int16", faultOnNilArg0: true, symEffect: "Read"}, // load 2 bytes zero extend reverse order
+ // In these cases an index register is used in addition to a base register
+ {name: "MOVBZloadidx", argLength: 3, reg: gploadidx, asm: "MOVBZ", aux: "SymOff", typ: "UInt8", faultOnNilArg0: true, symEffect: "Read"}, // zero extend uint8 to uint64
+ {name: "MOVHloadidx", argLength: 3, reg: gploadidx, asm: "MOVH", aux: "SymOff", typ: "Int16", faultOnNilArg0: true, symEffect: "Read"}, // sign extend int16 to int64
+ {name: "MOVHZloadidx", argLength: 3, reg: gploadidx, asm: "MOVHZ", aux: "SymOff", typ: "UInt16", faultOnNilArg0: true, symEffect: "Read"}, // zero extend uint16 to uint64
+ {name: "MOVWloadidx", argLength: 3, reg: gploadidx, asm: "MOVW", aux: "SymOff", typ: "Int32", faultOnNilArg0: true, symEffect: "Read"}, // sign extend int32 to int64
+ {name: "MOVWZloadidx", argLength: 3, reg: gploadidx, asm: "MOVWZ", aux: "SymOff", typ: "UInt32", faultOnNilArg0: true, symEffect: "Read"}, // zero extend uint32 to uint64
+ {name: "MOVDloadidx", argLength: 3, reg: gploadidx, asm: "MOVD", aux: "SymOff", typ: "Int64", faultOnNilArg0: true, symEffect: "Read"},
+ {name: "MOVHBRloadidx", argLength: 3, reg: gploadidx, asm: "MOVHBR", aux: "SymOff", typ: "Int16", faultOnNilArg0: true, symEffect: "Read"}, // sign extend int16 to int64
+ {name: "MOVWBRloadidx", argLength: 3, reg: gploadidx, asm: "MOVWBR", aux: "SymOff", typ: "Int32", faultOnNilArg0: true, symEffect: "Read"}, // sign extend int32 to int64
+ {name: "MOVDBRloadidx", argLength: 3, reg: gploadidx, asm: "MOVDBR", aux: "SymOff", typ: "Int64", faultOnNilArg0: true, symEffect: "Read"},
+ {name: "FMOVDloadidx", argLength: 3, reg: fploadidx, asm: "FMOVD", aux: "SymOff", typ: "Float64", faultOnNilArg0: true, symEffect: "Read"},
+ {name: "FMOVSloadidx", argLength: 3, reg: fploadidx, asm: "FMOVS", aux: "SymOff", typ: "Float32", faultOnNilArg0: true, symEffect: "Read"},
+
// Store bytes in the reverse endian order of the arch into arg0.
// These are indexes stores with no offset field in the instruction so the aux fields are not used.
{name: "MOVDBRstore", argLength: 3, reg: gpstore, asm: "MOVDBR", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 8 bytes reverse order
@@ -301,6 +320,17 @@ func init() {
{name: "FMOVDstore", argLength: 3, reg: fpstore, asm: "FMOVD", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store double flot
{name: "FMOVSstore", argLength: 3, reg: fpstore, asm: "FMOVS", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store single float
+ // Stores using index and base registers
+ {name: "MOVBstoreidx", argLength: 4, reg: gpstoreidx, asm: "MOVB", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store bye
+ {name: "MOVHstoreidx", argLength: 4, reg: gpstoreidx, asm: "MOVH", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store half word
+ {name: "MOVWstoreidx", argLength: 4, reg: gpstoreidx, asm: "MOVW", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store word
+ {name: "MOVDstoreidx", argLength: 4, reg: gpstoreidx, asm: "MOVD", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store double word
+ {name: "FMOVDstoreidx", argLength: 4, reg: fpstoreidx, asm: "FMOVD", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store double float
+ {name: "FMOVSstoreidx", argLength: 4, reg: fpstoreidx, asm: "FMOVS", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store single float
+ {name: "MOVHBRstoreidx", argLength: 4, reg: gpstoreidx, asm: "MOVHBR", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store half word reversed byte using index reg
+ {name: "MOVWBRstoreidx", argLength: 4, reg: gpstoreidx, asm: "MOVWBR", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store word reversed byte using index reg
+ {name: "MOVDBRstoreidx", argLength: 4, reg: gpstoreidx, asm: "MOVDBR", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store double word reversed byte using index reg
+
// The following ops store 0 into arg0+aux+auxint arg1=mem
{name: "MOVBstorezero", argLength: 2, reg: gpstorezero, asm: "MOVB", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store zero 1 byte
{name: "MOVHstorezero", argLength: 2, reg: gpstorezero, asm: "MOVH", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store zero 2 bytes
diff --git a/src/cmd/compile/internal/ssa/gen/Wasm.rules b/src/cmd/compile/internal/ssa/gen/Wasm.rules
index dc1581362c..64198839d0 100644
--- a/src/cmd/compile/internal/ssa/gen/Wasm.rules
+++ b/src/cmd/compile/internal/ssa/gen/Wasm.rules
@@ -363,8 +363,8 @@
(I64And (I64Const [x]) (I64Const [y])) -> (I64Const [x & y])
(I64Or (I64Const [x]) (I64Const [y])) -> (I64Const [x | y])
(I64Xor (I64Const [x]) (I64Const [y])) -> (I64Const [x ^ y])
-(F64Add (F64Const [x]) (F64Const [y])) -> (F64Const [f2i(i2f(x) + i2f(y))])
-(F64Mul (F64Const [x]) (F64Const [y])) -> (F64Const [f2i(i2f(x) * i2f(y))])
+(F64Add (F64Const [x]) (F64Const [y])) -> (F64Const [auxFrom64F(auxTo64F(x) + auxTo64F(y))])
+(F64Mul (F64Const [x]) (F64Const [y])) -> (F64Const [auxFrom64F(auxTo64F(x) * auxTo64F(y))])
(I64Eq (I64Const [x]) (I64Const [y])) && x == y -> (I64Const [1])
(I64Eq (I64Const [x]) (I64Const [y])) && x != y -> (I64Const [0])
(I64Ne (I64Const [x]) (I64Const [y])) && x == y -> (I64Const [0])
diff --git a/src/cmd/compile/internal/ssa/gen/generic.rules b/src/cmd/compile/internal/ssa/gen/generic.rules
index aa944b5379..d490e32f3d 100644
--- a/src/cmd/compile/internal/ssa/gen/generic.rules
+++ b/src/cmd/compile/internal/ssa/gen/generic.rules
@@ -44,16 +44,16 @@
(Trunc64to8 (Const64 [c])) -> (Const8 [int64(int8(c))])
(Trunc64to16 (Const64 [c])) -> (Const16 [int64(int16(c))])
(Trunc64to32 (Const64 [c])) -> (Const32 [int64(int32(c))])
-(Cvt64Fto32F (Const64F [c])) -> (Const32F [f2i(float64(i2f32(c)))])
+(Cvt64Fto32F (Const64F [c])) -> (Const32F [auxFrom32F(float32(auxTo64F(c)))])
(Cvt32Fto64F (Const32F [c])) -> (Const64F [c]) // c is already a 64 bit float
-(Cvt32to32F (Const32 [c])) -> (Const32F [f2i(float64(float32(int32(c))))])
-(Cvt32to64F (Const32 [c])) -> (Const64F [f2i(float64(int32(c)))])
-(Cvt64to32F (Const64 [c])) -> (Const32F [f2i(float64(float32(c)))])
-(Cvt64to64F (Const64 [c])) -> (Const64F [f2i(float64(c))])
-(Cvt32Fto32 (Const32F [c])) -> (Const32 [int64(int32(i2f(c)))])
-(Cvt32Fto64 (Const32F [c])) -> (Const64 [int64(i2f(c))])
-(Cvt64Fto32 (Const64F [c])) -> (Const32 [int64(int32(i2f(c)))])
-(Cvt64Fto64 (Const64F [c])) -> (Const64 [int64(i2f(c))])
+(Cvt32to32F (Const32 [c])) -> (Const32F [auxFrom32F(float32(int32(c)))])
+(Cvt32to64F (Const32 [c])) -> (Const64F [auxFrom64F(float64(int32(c)))])
+(Cvt64to32F (Const64 [c])) -> (Const32F [auxFrom32F(float32(c))])
+(Cvt64to64F (Const64 [c])) -> (Const64F [auxFrom64F(float64(c))])
+(Cvt32Fto32 (Const32F [c])) -> (Const32 [int64(int32(auxTo32F(c)))])
+(Cvt32Fto64 (Const32F [c])) -> (Const64 [int64(auxTo32F(c))])
+(Cvt64Fto32 (Const64F [c])) -> (Const32 [int64(int32(auxTo64F(c)))])
+(Cvt64Fto64 (Const64F [c])) -> (Const64 [int64(auxTo64F(c))])
(Round32F x:(Const32F)) -> x
(Round64F x:(Const64F)) -> x
@@ -95,16 +95,15 @@
(Neg16 (Const16 [c])) -> (Const16 [int64(-int16(c))])
(Neg32 (Const32 [c])) -> (Const32 [int64(-int32(c))])
(Neg64 (Const64 [c])) -> (Const64 [-c])
-(Neg32F (Const32F [c])) && i2f(c) != 0 -> (Const32F [f2i(-i2f(c))])
-(Neg64F (Const64F [c])) && i2f(c) != 0 -> (Const64F [f2i(-i2f(c))])
+(Neg32F (Const32F [c])) && auxTo32F(c) != 0 -> (Const32F [auxFrom32F(-auxTo32F(c))])
+(Neg64F (Const64F [c])) && auxTo64F(c) != 0 -> (Const64F [auxFrom64F(-auxTo64F(c))])
(Add8 (Const8 [c]) (Const8 [d])) -> (Const8 [int64(int8(c+d))])
(Add16 (Const16 [c]) (Const16 [d])) -> (Const16 [int64(int16(c+d))])
(Add32 (Const32 [c]) (Const32 [d])) -> (Const32 [int64(int32(c+d))])
(Add64 (Const64 [c]) (Const64 [d])) -> (Const64 [c+d])
-(Add32F (Const32F [c]) (Const32F [d])) ->
- (Const32F [f2i(float64(i2f32(c) + i2f32(d)))]) // ensure we combine the operands with 32 bit precision
-(Add64F (Const64F [c]) (Const64F [d])) -> (Const64F [f2i(i2f(c) + i2f(d))])
+(Add32F (Const32F [c]) (Const32F [d])) -> (Const32F [auxFrom32F(auxTo32F(c) + auxTo32F(d))])
+(Add64F (Const64F [c]) (Const64F [d])) -> (Const64F [auxFrom64F(auxTo64F(c) + auxTo64F(d))])
(AddPtr <t> x (Const64 [c])) -> (OffPtr <t> x [c])
(AddPtr <t> x (Const32 [c])) -> (OffPtr <t> x [c])
@@ -112,17 +111,15 @@
(Sub16 (Const16 [c]) (Const16 [d])) -> (Const16 [int64(int16(c-d))])
(Sub32 (Const32 [c]) (Const32 [d])) -> (Const32 [int64(int32(c-d))])
(Sub64 (Const64 [c]) (Const64 [d])) -> (Const64 [c-d])
-(Sub32F (Const32F [c]) (Const32F [d])) ->
- (Const32F [f2i(float64(i2f32(c) - i2f32(d)))])
-(Sub64F (Const64F [c]) (Const64F [d])) -> (Const64F [f2i(i2f(c) - i2f(d))])
+(Sub32F (Const32F [c]) (Const32F [d])) -> (Const32F [auxFrom32F(auxTo32F(c) - auxTo32F(d))])
+(Sub64F (Const64F [c]) (Const64F [d])) -> (Const64F [auxFrom64F(auxTo64F(c) - auxTo64F(d))])
(Mul8 (Const8 [c]) (Const8 [d])) -> (Const8 [int64(int8(c*d))])
(Mul16 (Const16 [c]) (Const16 [d])) -> (Const16 [int64(int16(c*d))])
(Mul32 (Const32 [c]) (Const32 [d])) -> (Const32 [int64(int32(c*d))])
(Mul64 (Const64 [c]) (Const64 [d])) -> (Const64 [c*d])
-(Mul32F (Const32F [c]) (Const32F [d])) ->
- (Const32F [f2i(float64(i2f32(c) * i2f32(d)))])
-(Mul64F (Const64F [c]) (Const64F [d])) -> (Const64F [f2i(i2f(c) * i2f(d))])
+(Mul32F (Const32F [c]) (Const32F [d])) -> (Const32F [auxFrom32F(auxTo32F(c) * auxTo32F(d))])
+(Mul64F (Const64F [c]) (Const64F [d])) -> (Const64F [auxFrom64F(auxTo64F(c) * auxTo64F(d))])
(And8 (Const8 [c]) (Const8 [d])) -> (Const8 [int64(int8(c&d))])
(And16 (Const16 [c]) (Const16 [d])) -> (Const16 [int64(int16(c&d))])
@@ -147,8 +144,8 @@
(Div16u (Const16 [c]) (Const16 [d])) && d != 0 -> (Const16 [int64(int16(uint16(c)/uint16(d)))])
(Div32u (Const32 [c]) (Const32 [d])) && d != 0 -> (Const32 [int64(int32(uint32(c)/uint32(d)))])
(Div64u (Const64 [c]) (Const64 [d])) && d != 0 -> (Const64 [int64(uint64(c)/uint64(d))])
-(Div32F (Const32F [c]) (Const32F [d])) -> (Const32F [f2i(float64(i2f32(c) / i2f32(d)))])
-(Div64F (Const64F [c]) (Const64F [d])) -> (Const64F [f2i(i2f(c) / i2f(d))])
+(Div32F (Const32F [c]) (Const32F [d])) -> (Const32F [auxFrom32F(auxTo32F(c) / auxTo32F(d))])
+(Div64F (Const64F [c]) (Const64F [d])) -> (Const64F [auxFrom64F(auxTo64F(c) / auxTo64F(d))])
(Not (ConstBool [c])) -> (ConstBool [1-c])
@@ -444,12 +441,18 @@
(Leq8U (Const8 [c]) (Const8 [d])) -> (ConstBool [b2i(uint8(c) <= uint8(d))])
// constant floating point comparisons
-(Eq(64|32)F (Const(64|32)F [c]) (Const(64|32)F [d])) -> (ConstBool [b2i(i2f(c) == i2f(d))])
-(Neq(64|32)F (Const(64|32)F [c]) (Const(64|32)F [d])) -> (ConstBool [b2i(i2f(c) != i2f(d))])
-(Greater(64|32)F (Const(64|32)F [c]) (Const(64|32)F [d])) -> (ConstBool [b2i(i2f(c) > i2f(d))])
-(Geq(64|32)F (Const(64|32)F [c]) (Const(64|32)F [d])) -> (ConstBool [b2i(i2f(c) >= i2f(d))])
-(Less(64|32)F (Const(64|32)F [c]) (Const(64|32)F [d])) -> (ConstBool [b2i(i2f(c) < i2f(d))])
-(Leq(64|32)F (Const(64|32)F [c]) (Const(64|32)F [d])) -> (ConstBool [b2i(i2f(c) <= i2f(d))])
+(Eq32F (Const32F [c]) (Const32F [d])) -> (ConstBool [b2i(auxTo32F(c) == auxTo32F(d))])
+(Eq64F (Const64F [c]) (Const64F [d])) -> (ConstBool [b2i(auxTo64F(c) == auxTo64F(d))])
+(Neq32F (Const32F [c]) (Const32F [d])) -> (ConstBool [b2i(auxTo32F(c) != auxTo32F(d))])
+(Neq64F (Const64F [c]) (Const64F [d])) -> (ConstBool [b2i(auxTo64F(c) != auxTo64F(d))])
+(Greater32F (Const32F [c]) (Const32F [d])) -> (ConstBool [b2i(auxTo32F(c) > auxTo32F(d))])
+(Greater64F (Const64F [c]) (Const64F [d])) -> (ConstBool [b2i(auxTo64F(c) > auxTo64F(d))])
+(Geq32F (Const32F [c]) (Const32F [d])) -> (ConstBool [b2i(auxTo32F(c) >= auxTo32F(d))])
+(Geq64F (Const64F [c]) (Const64F [d])) -> (ConstBool [b2i(auxTo64F(c) >= auxTo64F(d))])
+(Less32F (Const32F [c]) (Const32F [d])) -> (ConstBool [b2i(auxTo32F(c) < auxTo32F(d))])
+(Less64F (Const64F [c]) (Const64F [d])) -> (ConstBool [b2i(auxTo64F(c) < auxTo64F(d))])
+(Leq32F (Const32F [c]) (Const32F [d])) -> (ConstBool [b2i(auxTo32F(c) <= auxTo32F(d))])
+(Leq64F (Const64F [c]) (Const64F [d])) -> (ConstBool [b2i(auxTo64F(c) <= auxTo64F(d))])
// simplifications
(Or(64|32|16|8) x x) -> x
@@ -572,9 +575,9 @@
// Pass constants through math.Float{32,64}bits and math.Float{32,64}frombits
(Load <t1> p1 (Store {t2} p2 (Const64 [x]) _)) && isSamePtr(p1,p2) && sizeof(t2) == 8 && is64BitFloat(t1) -> (Const64F [x])
-(Load <t1> p1 (Store {t2} p2 (Const32 [x]) _)) && isSamePtr(p1,p2) && sizeof(t2) == 4 && is32BitFloat(t1) -> (Const32F [f2i(extend32Fto64F(math.Float32frombits(uint32(x))))])
+(Load <t1> p1 (Store {t2} p2 (Const32 [x]) _)) && isSamePtr(p1,p2) && sizeof(t2) == 4 && is32BitFloat(t1) -> (Const32F [auxFrom32F(math.Float32frombits(uint32(x)))])
(Load <t1> p1 (Store {t2} p2 (Const64F [x]) _)) && isSamePtr(p1,p2) && sizeof(t2) == 8 && is64BitInt(t1) -> (Const64 [x])
-(Load <t1> p1 (Store {t2} p2 (Const32F [x]) _)) && isSamePtr(p1,p2) && sizeof(t2) == 4 && is32BitInt(t1) -> (Const32 [int64(int32(math.Float32bits(truncate64Fto32F(i2f(x)))))])
+(Load <t1> p1 (Store {t2} p2 (Const32F [x]) _)) && isSamePtr(p1,p2) && sizeof(t2) == 4 && is32BitInt(t1) -> (Const32 [int64(int32(math.Float32bits(auxTo32F(x))))])
// Float Loads up to Zeros so they can be constant folded.
(Load <t1> op:(OffPtr [o1] p1)
@@ -1326,19 +1329,16 @@
(Mul8 (Const8 <t> [c]) (Mul8 (Const8 <t> [d]) x)) -> (Mul8 (Const8 <t> [int64(int8(c*d))]) x)
// floating point optimizations
-(Add(32|64)F x (Const(32|64)F [0])) -> x
-(Sub(32|64)F x (Const(32|64)F [0])) -> x
+(Mul(32|64)F x (Const(32|64)F [auxFrom64F(1)])) -> x
+(Mul32F x (Const32F [auxFrom32F(-1)])) -> (Neg32F x)
+(Mul64F x (Const64F [auxFrom64F(-1)])) -> (Neg64F x)
+(Mul32F x (Const32F [auxFrom32F(2)])) -> (Add32F x x)
+(Mul64F x (Const64F [auxFrom64F(2)])) -> (Add64F x x)
-(Mul(32|64)F x (Const(32|64)F [f2i(1)])) -> x
-(Mul32F x (Const32F [f2i(-1)])) -> (Neg32F x)
-(Mul64F x (Const64F [f2i(-1)])) -> (Neg64F x)
-(Mul32F x (Const32F [f2i(2)])) -> (Add32F x x)
-(Mul64F x (Const64F [f2i(2)])) -> (Add64F x x)
+(Div32F x (Const32F <t> [c])) && reciprocalExact32(auxTo32F(c)) -> (Mul32F x (Const32F <t> [auxFrom32F(1/auxTo32F(c))]))
+(Div64F x (Const64F <t> [c])) && reciprocalExact64(auxTo64F(c)) -> (Mul64F x (Const64F <t> [auxFrom64F(1/auxTo64F(c))]))
-(Div32F x (Const32F <t> [c])) && reciprocalExact32(float32(i2f(c))) -> (Mul32F x (Const32F <t> [f2i(1/i2f(c))]))
-(Div64F x (Const64F <t> [c])) && reciprocalExact64(i2f(c)) -> (Mul64F x (Const64F <t> [f2i(1/i2f(c))]))
-
-(Sqrt (Const64F [c])) -> (Const64F [f2i(math.Sqrt(i2f(c)))])
+(Sqrt (Const64F [c])) -> (Const64F [auxFrom64F(math.Sqrt(auxTo64F(c)))])
// recognize runtime.newobject and don't Zero/Nilcheck it
(Zero (Load (OffPtr [c] (SP)) mem) mem)
@@ -1363,12 +1363,12 @@
(NilCheck (Load (OffPtr [c] (SP)) (StaticCall {sym} _)) _)
&& isSameSym(sym, "runtime.newobject")
&& c == config.ctxt.FixedFrameSize() + config.RegSize // offset of return value
- && warnRule(fe.Debug_checknil() && v.Pos.Line() > 1, v, "removed nil check")
+ && warnRule(fe.Debug_checknil(), v, "removed nil check")
-> (Invalid)
(NilCheck (OffPtr (Load (OffPtr [c] (SP)) (StaticCall {sym} _))) _)
&& isSameSym(sym, "runtime.newobject")
&& c == config.ctxt.FixedFrameSize() + config.RegSize // offset of return value
- && warnRule(fe.Debug_checknil() && v.Pos.Line() > 1, v, "removed nil check")
+ && warnRule(fe.Debug_checknil(), v, "removed nil check")
-> (Invalid)
// Evaluate constant address comparisons.
@@ -1545,8 +1545,8 @@
// Don't Move from memory if the values are likely to already be
// in registers.
(Move {t1} [n] dst p1
- mem:(Store {t2} op2:(OffPtr [o2] p2) d1
- (Store {t3} op3:(OffPtr [0] p3) d2 _)))
+ mem:(Store {t2} op2:(OffPtr <tt2> [o2] p2) d1
+ (Store {t3} op3:(OffPtr <tt3> [0] p3) d2 _)))
&& isSamePtr(p1, p2) && isSamePtr(p2, p3)
&& alignof(t2) <= alignof(t1)
&& alignof(t3) <= alignof(t1)
@@ -1554,12 +1554,12 @@
&& registerizable(b, t3)
&& o2 == sizeof(t3)
&& n == sizeof(t2) + sizeof(t3)
- -> (Store {t2} (OffPtr <t2.(*types.Type)> [o2] dst) d1
- (Store {t3} (OffPtr <t3.(*types.Type)> [0] dst) d2 mem))
+ -> (Store {t2} (OffPtr <tt2> [o2] dst) d1
+ (Store {t3} (OffPtr <tt3> [0] dst) d2 mem))
(Move {t1} [n] dst p1
- mem:(Store {t2} op2:(OffPtr [o2] p2) d1
- (Store {t3} op3:(OffPtr [o3] p3) d2
- (Store {t4} op4:(OffPtr [0] p4) d3 _))))
+ mem:(Store {t2} op2:(OffPtr <tt2> [o2] p2) d1
+ (Store {t3} op3:(OffPtr <tt3> [o3] p3) d2
+ (Store {t4} op4:(OffPtr <tt4> [0] p4) d3 _))))
&& isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4)
&& alignof(t2) <= alignof(t1)
&& alignof(t3) <= alignof(t1)
@@ -1570,14 +1570,14 @@
&& o3 == sizeof(t4)
&& o2-o3 == sizeof(t3)
&& n == sizeof(t2) + sizeof(t3) + sizeof(t4)
- -> (Store {t2} (OffPtr <t2.(*types.Type)> [o2] dst) d1
- (Store {t3} (OffPtr <t3.(*types.Type)> [o3] dst) d2
- (Store {t4} (OffPtr <t4.(*types.Type)> [0] dst) d3 mem)))
+ -> (Store {t2} (OffPtr <tt2> [o2] dst) d1
+ (Store {t3} (OffPtr <tt3> [o3] dst) d2
+ (Store {t4} (OffPtr <tt4> [0] dst) d3 mem)))
(Move {t1} [n] dst p1
- mem:(Store {t2} op2:(OffPtr [o2] p2) d1
- (Store {t3} op3:(OffPtr [o3] p3) d2
- (Store {t4} op4:(OffPtr [o4] p4) d3
- (Store {t5} op5:(OffPtr [0] p5) d4 _)))))
+ mem:(Store {t2} op2:(OffPtr <tt2> [o2] p2) d1
+ (Store {t3} op3:(OffPtr <tt3> [o3] p3) d2
+ (Store {t4} op4:(OffPtr <tt4> [o4] p4) d3
+ (Store {t5} op5:(OffPtr <tt5> [0] p5) d4 _)))))
&& isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5)
&& alignof(t2) <= alignof(t1)
&& alignof(t3) <= alignof(t1)
@@ -1591,16 +1591,16 @@
&& o3-o4 == sizeof(t4)
&& o2-o3 == sizeof(t3)
&& n == sizeof(t2) + sizeof(t3) + sizeof(t4) + sizeof(t5)
- -> (Store {t2} (OffPtr <t2.(*types.Type)> [o2] dst) d1
- (Store {t3} (OffPtr <t3.(*types.Type)> [o3] dst) d2
- (Store {t4} (OffPtr <t4.(*types.Type)> [o4] dst) d3
- (Store {t5} (OffPtr <t5.(*types.Type)> [0] dst) d4 mem))))
+ -> (Store {t2} (OffPtr <tt2> [o2] dst) d1
+ (Store {t3} (OffPtr <tt3> [o3] dst) d2
+ (Store {t4} (OffPtr <tt4> [o4] dst) d3
+ (Store {t5} (OffPtr <tt5> [0] dst) d4 mem))))
// Same thing but with VarDef in the middle.
(Move {t1} [n] dst p1
mem:(VarDef
- (Store {t2} op2:(OffPtr [o2] p2) d1
- (Store {t3} op3:(OffPtr [0] p3) d2 _))))
+ (Store {t2} op2:(OffPtr <tt2> [o2] p2) d1
+ (Store {t3} op3:(OffPtr <tt3> [0] p3) d2 _))))
&& isSamePtr(p1, p2) && isSamePtr(p2, p3)
&& alignof(t2) <= alignof(t1)
&& alignof(t3) <= alignof(t1)
@@ -1608,13 +1608,13 @@
&& registerizable(b, t3)
&& o2 == sizeof(t3)
&& n == sizeof(t2) + sizeof(t3)
- -> (Store {t2} (OffPtr <t2.(*types.Type)> [o2] dst) d1
- (Store {t3} (OffPtr <t3.(*types.Type)> [0] dst) d2 mem))
+ -> (Store {t2} (OffPtr <tt2> [o2] dst) d1
+ (Store {t3} (OffPtr <tt3> [0] dst) d2 mem))
(Move {t1} [n] dst p1
mem:(VarDef
- (Store {t2} op2:(OffPtr [o2] p2) d1
- (Store {t3} op3:(OffPtr [o3] p3) d2
- (Store {t4} op4:(OffPtr [0] p4) d3 _)))))
+ (Store {t2} op2:(OffPtr <tt2> [o2] p2) d1
+ (Store {t3} op3:(OffPtr <tt3> [o3] p3) d2
+ (Store {t4} op4:(OffPtr <tt4> [0] p4) d3 _)))))
&& isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4)
&& alignof(t2) <= alignof(t1)
&& alignof(t3) <= alignof(t1)
@@ -1625,15 +1625,15 @@
&& o3 == sizeof(t4)
&& o2-o3 == sizeof(t3)
&& n == sizeof(t2) + sizeof(t3) + sizeof(t4)
- -> (Store {t2} (OffPtr <t2.(*types.Type)> [o2] dst) d1
- (Store {t3} (OffPtr <t3.(*types.Type)> [o3] dst) d2
- (Store {t4} (OffPtr <t4.(*types.Type)> [0] dst) d3 mem)))
+ -> (Store {t2} (OffPtr <tt2> [o2] dst) d1
+ (Store {t3} (OffPtr <tt3> [o3] dst) d2
+ (Store {t4} (OffPtr <tt4> [0] dst) d3 mem)))
(Move {t1} [n] dst p1
mem:(VarDef
- (Store {t2} op2:(OffPtr [o2] p2) d1
- (Store {t3} op3:(OffPtr [o3] p3) d2
- (Store {t4} op4:(OffPtr [o4] p4) d3
- (Store {t5} op5:(OffPtr [0] p5) d4 _))))))
+ (Store {t2} op2:(OffPtr <tt2> [o2] p2) d1
+ (Store {t3} op3:(OffPtr <tt3> [o3] p3) d2
+ (Store {t4} op4:(OffPtr <tt4> [o4] p4) d3
+ (Store {t5} op5:(OffPtr <tt5> [0] p5) d4 _))))))
&& isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5)
&& alignof(t2) <= alignof(t1)
&& alignof(t3) <= alignof(t1)
@@ -1647,10 +1647,10 @@
&& o3-o4 == sizeof(t4)
&& o2-o3 == sizeof(t3)
&& n == sizeof(t2) + sizeof(t3) + sizeof(t4) + sizeof(t5)
- -> (Store {t2} (OffPtr <t2.(*types.Type)> [o2] dst) d1
- (Store {t3} (OffPtr <t3.(*types.Type)> [o3] dst) d2
- (Store {t4} (OffPtr <t4.(*types.Type)> [o4] dst) d3
- (Store {t5} (OffPtr <t5.(*types.Type)> [0] dst) d4 mem))))
+ -> (Store {t2} (OffPtr <tt2> [o2] dst) d1
+ (Store {t3} (OffPtr <tt3> [o3] dst) d2
+ (Store {t4} (OffPtr <tt4> [o4] dst) d3
+ (Store {t5} (OffPtr <tt5> [0] dst) d4 mem))))
// Prefer to Zero and Store than to Move.
(Move {t1} [n] dst p1
diff --git a/src/cmd/compile/internal/ssa/gen/genericOps.go b/src/cmd/compile/internal/ssa/gen/genericOps.go
index 7292012d26..ee9c6fa0f6 100644
--- a/src/cmd/compile/internal/ssa/gen/genericOps.go
+++ b/src/cmd/compile/internal/ssa/gen/genericOps.go
@@ -470,8 +470,9 @@ var genericOps = []opData{
{name: "VarDef", argLength: 1, aux: "Sym", typ: "Mem", symEffect: "None", zeroWidth: true}, // aux is a *gc.Node of a variable that is about to be initialized. arg0=mem, returns mem
{name: "VarKill", argLength: 1, aux: "Sym", symEffect: "None"}, // aux is a *gc.Node of a variable that is known to be dead. arg0=mem, returns mem
- {name: "VarLive", argLength: 1, aux: "Sym", symEffect: "Read", zeroWidth: true}, // aux is a *gc.Node of a variable that must be kept live. arg0=mem, returns mem
- {name: "KeepAlive", argLength: 2, typ: "Mem", zeroWidth: true}, // arg[0] is a value that must be kept alive until this mark. arg[1]=mem, returns mem
+ // TODO: what's the difference betweeen VarLive and KeepAlive?
+ {name: "VarLive", argLength: 1, aux: "Sym", symEffect: "Read", zeroWidth: true}, // aux is a *gc.Node of a variable that must be kept live. arg0=mem, returns mem
+ {name: "KeepAlive", argLength: 2, typ: "Mem", zeroWidth: true}, // arg[0] is a value that must be kept alive until this mark. arg[1]=mem, returns mem
// Ops for breaking 64-bit operations on 32-bit architectures
{name: "Int64Make", argLength: 2, typ: "UInt64"}, // arg0=hi, arg1=lo
diff --git a/src/cmd/compile/internal/ssa/gen/main.go b/src/cmd/compile/internal/ssa/gen/main.go
index f35a991db2..f7195bf536 100644
--- a/src/cmd/compile/internal/ssa/gen/main.go
+++ b/src/cmd/compile/internal/ssa/gen/main.go
@@ -63,9 +63,14 @@ type blockData struct {
}
type regInfo struct {
- inputs []regMask
+ // inputs[i] encodes the set of registers allowed for the i'th input.
+ // Inputs that don't use registers (flags, memory, etc.) should be 0.
+ inputs []regMask
+ // clobbers encodes the set of registers that are overwritten by
+ // the instruction (other than the output registers).
clobbers regMask
- outputs []regMask
+ // outpus[i] encodes the set of registers allowed for the i'th output.
+ outputs []regMask
}
type regMask uint64
diff --git a/src/cmd/compile/internal/ssa/html.go b/src/cmd/compile/internal/ssa/html.go
index c51ea02262..b7d5f912db 100644
--- a/src/cmd/compile/internal/ssa/html.go
+++ b/src/cmd/compile/internal/ssa/html.go
@@ -484,7 +484,7 @@ func (x ByTopo) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
func (x ByTopo) Less(i, j int) bool {
a := x[i]
b := x[j]
- if a.Filename == a.Filename {
+ if a.Filename == b.Filename {
return a.StartLineno < b.StartLineno
}
return a.Filename < b.Filename
diff --git a/src/cmd/compile/internal/ssa/op.go b/src/cmd/compile/internal/ssa/op.go
index 610921808e..43f5c59591 100644
--- a/src/cmd/compile/internal/ssa/op.go
+++ b/src/cmd/compile/internal/ssa/op.go
@@ -50,9 +50,17 @@ type outputInfo struct {
}
type regInfo struct {
- inputs []inputInfo // ordered in register allocation order
+ // inputs encodes the register restrictions for an instruction's inputs.
+ // Each entry specifies an allowed register set for a particular input.
+ // They are listed in the order in which regalloc should pick a register
+ // from the register set (most constrained first).
+ // Inputs which do not need registers are not listed.
+ inputs []inputInfo
+ // clobbers encodes the set of registers that are overwritten by
+ // the instruction (other than the output registers).
clobbers regMask
- outputs []outputInfo // ordered in register allocation order
+ // outputs is the same as inputs, but for the outputs of the instruction.
+ outputs []outputInfo
}
type auxType int8
diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go
index 5bf7021432..2145c6e723 100644
--- a/src/cmd/compile/internal/ssa/opGen.go
+++ b/src/cmd/compile/internal/ssa/opGen.go
@@ -550,6 +550,18 @@ const (
OpAMD64BTRQconst
OpAMD64BTSLconst
OpAMD64BTSQconst
+ OpAMD64BTCQmodify
+ OpAMD64BTCLmodify
+ OpAMD64BTSQmodify
+ OpAMD64BTSLmodify
+ OpAMD64BTRQmodify
+ OpAMD64BTRLmodify
+ OpAMD64BTCQconstmodify
+ OpAMD64BTCLconstmodify
+ OpAMD64BTSQconstmodify
+ OpAMD64BTSLconstmodify
+ OpAMD64BTRQconstmodify
+ OpAMD64BTRLconstmodify
OpAMD64TESTQ
OpAMD64TESTL
OpAMD64TESTW
@@ -1107,6 +1119,7 @@ const (
OpARM64LoweredMuluhilo
OpARM64MVN
OpARM64NEG
+ OpARM64FABSD
OpARM64FNEGS
OpARM64FNEGD
OpARM64FSQRTD
@@ -1139,6 +1152,8 @@ const (
OpARM64SRLconst
OpARM64SRA
OpARM64SRAconst
+ OpARM64ROR
+ OpARM64RORW
OpARM64RORconst
OpARM64RORWconst
OpARM64EXTRconst
@@ -1157,6 +1172,12 @@ const (
OpARM64TSTWconst
OpARM64FCMPS
OpARM64FCMPD
+ OpARM64MVNshiftLL
+ OpARM64MVNshiftRL
+ OpARM64MVNshiftRA
+ OpARM64NEGshiftLL
+ OpARM64NEGshiftRL
+ OpARM64NEGshiftRA
OpARM64ADDshiftLL
OpARM64ADDshiftRL
OpARM64ADDshiftRA
@@ -1184,6 +1205,12 @@ const (
OpARM64CMPshiftLL
OpARM64CMPshiftRL
OpARM64CMPshiftRA
+ OpARM64CMNshiftLL
+ OpARM64CMNshiftRL
+ OpARM64CMNshiftRA
+ OpARM64TSTshiftLL
+ OpARM64TSTshiftRL
+ OpARM64TSTshiftRA
OpARM64BFI
OpARM64BFXIL
OpARM64SBFIZ
@@ -1247,6 +1274,8 @@ const (
OpARM64MOVDstorezeroidx8
OpARM64FMOVDgpfp
OpARM64FMOVDfpgp
+ OpARM64FMOVSgpfp
+ OpARM64FMOVSfpgp
OpARM64MOVBreg
OpARM64MOVBUreg
OpARM64MOVHreg
@@ -1275,6 +1304,7 @@ const (
OpARM64FCVTDS
OpARM64FRINTAD
OpARM64FRINTMD
+ OpARM64FRINTND
OpARM64FRINTPD
OpARM64FRINTZD
OpARM64CSEL
@@ -1551,6 +1581,7 @@ const (
OpPPC64MULHW
OpPPC64MULHDU
OpPPC64MULHWU
+ OpPPC64LoweredMuluhilo
OpPPC64FMUL
OpPPC64FMULS
OpPPC64FMADD
@@ -1630,6 +1661,17 @@ const (
OpPPC64MOVDBRload
OpPPC64MOVWBRload
OpPPC64MOVHBRload
+ OpPPC64MOVBZloadidx
+ OpPPC64MOVHloadidx
+ OpPPC64MOVHZloadidx
+ OpPPC64MOVWloadidx
+ OpPPC64MOVWZloadidx
+ OpPPC64MOVDloadidx
+ OpPPC64MOVHBRloadidx
+ OpPPC64MOVWBRloadidx
+ OpPPC64MOVDBRloadidx
+ OpPPC64FMOVDloadidx
+ OpPPC64FMOVSloadidx
OpPPC64MOVDBRstore
OpPPC64MOVWBRstore
OpPPC64MOVHBRstore
@@ -1641,6 +1683,15 @@ const (
OpPPC64MOVDstore
OpPPC64FMOVDstore
OpPPC64FMOVSstore
+ OpPPC64MOVBstoreidx
+ OpPPC64MOVHstoreidx
+ OpPPC64MOVWstoreidx
+ OpPPC64MOVDstoreidx
+ OpPPC64FMOVDstoreidx
+ OpPPC64FMOVSstoreidx
+ OpPPC64MOVHBRstoreidx
+ OpPPC64MOVWBRstoreidx
+ OpPPC64MOVDBRstoreidx
OpPPC64MOVBstorezero
OpPPC64MOVHstorezero
OpPPC64MOVWstorezero
@@ -6896,6 +6947,180 @@ var opcodeTable = [...]opInfo{
},
},
{
+ name: "BTCQmodify",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.ABTCQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 65535}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "BTCLmodify",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.ABTCL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 65535}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "BTSQmodify",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.ABTSQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 65535}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "BTSLmodify",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.ABTSL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 65535}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "BTRQmodify",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.ABTRQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 65535}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "BTRLmodify",
+ auxType: auxSymOff,
+ argLen: 3,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.ABTRL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 65535}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "BTCQconstmodify",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.ABTCQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "BTCLconstmodify",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.ABTCL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "BTSQconstmodify",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.ABTSQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "BTSLconstmodify",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.ABTSL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "BTRQconstmodify",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.ABTRQ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
+ name: "BTRLconstmodify",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ clobberFlags: true,
+ faultOnNilArg0: true,
+ symEffect: SymRead | SymWrite,
+ asm: x86.ABTRL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 4295032831}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15 SB
+ },
+ },
+ },
+ {
name: "TESTQ",
argLen: 2,
commutative: true,
@@ -14657,6 +14882,19 @@ var opcodeTable = [...]opInfo{
},
},
{
+ name: "FABSD",
+ argLen: 1,
+ asm: arm64.AFABSD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
name: "FNEGS",
argLen: 1,
asm: arm64.AFNEGS,
@@ -15105,6 +15343,34 @@ var opcodeTable = [...]opInfo{
},
},
{
+ name: "ROR",
+ argLen: 2,
+ asm: arm64.AROR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "RORW",
+ argLen: 2,
+ asm: arm64.ARORW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
name: "RORconst",
auxType: auxInt64,
argLen: 1,
@@ -15321,6 +15587,90 @@ var opcodeTable = [...]opInfo{
},
},
{
+ name: "MVNshiftLL",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: arm64.AMVN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MVNshiftRL",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: arm64.AMVN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "MVNshiftRA",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: arm64.AMVN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "NEGshiftLL",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: arm64.ANEG,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "NEGshiftRL",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: arm64.ANEG,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
+ name: "NEGshiftRA",
+ auxType: auxInt64,
+ argLen: 1,
+ asm: arm64.ANEG,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
name: "ADDshiftLL",
auxType: auxInt64,
argLen: 2,
@@ -15717,6 +16067,78 @@ var opcodeTable = [...]opInfo{
},
},
{
+ name: "CMNshiftLL",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.ACMN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ },
+ },
+ {
+ name: "CMNshiftRL",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.ACMN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ },
+ },
+ {
+ name: "CMNshiftRA",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.ACMN,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ },
+ },
+ {
+ name: "TSTshiftLL",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.ATST,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ },
+ },
+ {
+ name: "TSTshiftRL",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.ATST,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ },
+ },
+ {
+ name: "TSTshiftRA",
+ auxType: auxInt64,
+ argLen: 2,
+ asm: arm64.ATST,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
+ },
+ },
+ },
+ {
name: "BFI",
auxType: auxInt64,
argLen: 2,
@@ -16572,6 +16994,32 @@ var opcodeTable = [...]opInfo{
},
},
{
+ name: "FMOVSgpfp",
+ argLen: 1,
+ asm: arm64.AFMOVS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
+ name: "FMOVSfpgp",
+ argLen: 1,
+ asm: arm64.AFMOVS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
+ },
+ },
+ },
+ {
name: "MOVBreg",
argLen: 1,
asm: arm64.AMOVB,
@@ -16936,6 +17384,19 @@ var opcodeTable = [...]opInfo{
},
},
{
+ name: "FRINTND",
+ argLen: 1,
+ asm: arm64.AFRINTND,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ outputs: []outputInfo{
+ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+ },
+ },
+ },
+ {
name: "FRINTPD",
argLen: 1,
asm: arm64.AFRINTPD,
@@ -20590,6 +21051,21 @@ var opcodeTable = [...]opInfo{
},
},
{
+ name: "LoweredMuluhilo",
+ argLen: 2,
+ resultNotInArgs: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
name: "FMUL",
argLen: 2,
commutative: true,
@@ -21691,6 +22167,193 @@ var opcodeTable = [...]opInfo{
},
},
{
+ name: "MOVBZloadidx",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: ppc64.AMOVBZ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVHloadidx",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: ppc64.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVHZloadidx",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: ppc64.AMOVHZ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVWloadidx",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: ppc64.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVWZloadidx",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: ppc64.AMOVWZ,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVDloadidx",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: ppc64.AMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVHBRloadidx",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: ppc64.AMOVHBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVWBRloadidx",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: ppc64.AMOVWBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVDBRloadidx",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: ppc64.AMOVDBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "FMOVDloadidx",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: ppc64.AFMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
+ name: "FMOVSloadidx",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: ppc64.AFMOVS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ outputs: []outputInfo{
+ {0, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ },
+ },
+ },
+ {
name: "MOVDBRstore",
auxType: auxSymOff,
argLen: 3,
@@ -21849,6 +22512,141 @@ var opcodeTable = [...]opInfo{
},
},
{
+ name: "MOVBstoreidx",
+ auxType: auxSymOff,
+ argLen: 4,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: ppc64.AMOVB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {2, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVHstoreidx",
+ auxType: auxSymOff,
+ argLen: 4,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: ppc64.AMOVH,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {2, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVWstoreidx",
+ auxType: auxSymOff,
+ argLen: 4,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: ppc64.AMOVW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {2, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVDstoreidx",
+ auxType: auxSymOff,
+ argLen: 4,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: ppc64.AMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {2, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "FMOVDstoreidx",
+ auxType: auxSymOff,
+ argLen: 4,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: ppc64.AFMOVD,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {2, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "FMOVSstoreidx",
+ auxType: auxSymOff,
+ argLen: 4,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: ppc64.AFMOVS,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {2, 576460743713488896}, // F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVHBRstoreidx",
+ auxType: auxSymOff,
+ argLen: 4,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: ppc64.AMOVHBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {2, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVWBRstoreidx",
+ auxType: auxSymOff,
+ argLen: 4,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: ppc64.AMOVWBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {2, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
+ name: "MOVDBRstoreidx",
+ auxType: auxSymOff,
+ argLen: 4,
+ faultOnNilArg0: true,
+ symEffect: SymWrite,
+ asm: ppc64.AMOVDBR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {1, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ {2, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
+ },
+ },
+ },
+ {
name: "MOVBstorezero",
auxType: auxSymOff,
argLen: 2,
diff --git a/src/cmd/compile/internal/ssa/prove.go b/src/cmd/compile/internal/ssa/prove.go
index af2b9ef0ed..6462370d5c 100644
--- a/src/cmd/compile/internal/ssa/prove.go
+++ b/src/cmd/compile/internal/ssa/prove.go
@@ -58,7 +58,7 @@ func (r relation) String() string {
}
// domain represents the domain of a variable pair in which a set
-// of relations is known. For example, relations learned for unsigned
+// of relations is known. For example, relations learned for unsigned
// pairs cannot be transferred to signed pairs because the same bit
// representation can mean something else.
type domain uint
@@ -625,7 +625,7 @@ var (
// For example:
// OpLess8: {signed, lt},
// v1 = (OpLess8 v2 v3).
- // If v1 branch is taken than we learn that the rangeMaks
+ // If v1 branch is taken then we learn that the rangeMask
// can be at most lt.
domainRelationTable = map[Op]struct {
d domain
diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go
index 278da6fe99..8946cf6b5c 100644
--- a/src/cmd/compile/internal/ssa/regalloc.go
+++ b/src/cmd/compile/internal/ssa/regalloc.go
@@ -150,6 +150,8 @@ type register uint8
const noRegister register = 255
+// A regMask encodes a set of machine registers.
+// TODO: regMask -> regSet?
type regMask uint64
func (m regMask) String() string {
diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go
index ca6280deb1..fd5f684eda 100644
--- a/src/cmd/compile/internal/ssa/rewrite.go
+++ b/src/cmd/compile/internal/ssa/rewrite.go
@@ -234,7 +234,6 @@ func canMergeLoad(target, load, x *Value) bool {
// memPreds contains memory states known to be predecessors of load's
// memory state. It is lazily initialized.
var memPreds map[*Value]bool
-search:
for i := 0; len(args) > 0; i++ {
const limit = 100
if i >= limit {
@@ -246,13 +245,13 @@ search:
if target.Block.ID != v.Block.ID {
// Since target and load are in the same block
// we can stop searching when we leave the block.
- continue search
+ continue
}
if v.Op == OpPhi {
// A Phi implies we have reached the top of the block.
// The memory phi, if it exists, is always
// the first logical store in the block.
- continue search
+ continue
}
if v.Type.IsTuple() && v.Type.FieldType(1).IsMemory() {
// We could handle this situation however it is likely
@@ -296,14 +295,14 @@ search:
// load = read ... mem
// target = add x load
if memPreds[v] {
- continue search
+ continue
}
return false
}
if len(v.Args) > 0 && v.Args[len(v.Args)-1] == mem {
// If v takes mem as an input then we know mem
// is valid at this point.
- continue search
+ continue
}
for _, a := range v.Args {
if target.Block.ID == a.Block.ID {
@@ -450,19 +449,24 @@ func extend32Fto64F(f float32) float64 {
return math.Float64frombits(r)
}
-// i2f is used in rules for converting from an AuxInt to a float.
-func i2f(i int64) float64 {
- return math.Float64frombits(uint64(i))
+// auxFrom64F encodes a float64 value so it can be stored in an AuxInt.
+func auxFrom64F(f float64) int64 {
+ return int64(math.Float64bits(f))
}
-// i2f32 is used in rules for converting from an AuxInt to a float32.
-func i2f32(i int64) float32 {
- return float32(math.Float64frombits(uint64(i)))
+// auxFrom32F encodes a float32 value so it can be stored in an AuxInt.
+func auxFrom32F(f float32) int64 {
+ return int64(math.Float64bits(extend32Fto64F(f)))
}
-// f2i is used in the rules for storing a float in AuxInt.
-func f2i(f float64) int64 {
- return int64(math.Float64bits(f))
+// auxTo32F decodes a float32 from the AuxInt value provided.
+func auxTo32F(i int64) float32 {
+ return truncate64Fto32F(math.Float64frombits(uint64(i)))
+}
+
+// auxTo64F decodes a float64 from the AuxInt value provided.
+func auxTo64F(i int64) float64 {
+ return math.Float64frombits(uint64(i))
}
// uaddOvf returns true if unsigned a+b would overflow.
@@ -646,11 +650,11 @@ func noteRule(s string) bool {
return true
}
-// warnRule generates a compiler debug output with string s when
-// cond is true and the rule is fired.
+// warnRule generates compiler debug output with string s when
+// v is not in autogenerated code, cond is true and the rule has fired.
func warnRule(cond bool, v *Value, s string) bool {
- if cond {
- v.Block.Func.Warnl(v.Pos, s)
+ if pos := v.Pos; pos.Line() > 1 && cond {
+ v.Block.Func.Warnl(pos, s)
}
return true
}
diff --git a/src/cmd/compile/internal/ssa/rewrite386.go b/src/cmd/compile/internal/ssa/rewrite386.go
index abc1d18309..5481b4e773 100644
--- a/src/cmd/compile/internal/ssa/rewrite386.go
+++ b/src/cmd/compile/internal/ssa/rewrite386.go
@@ -2507,38 +2507,44 @@ func rewriteValue386_Op386CMPBconst_0(v *Value) bool {
v.reset(Op386FlagLT_ULT)
return true
}
- // match: (CMPBconst (ANDL x y) [0])
- // cond:
+ // match: (CMPBconst l:(ANDL x y) [0])
+ // cond: l.Uses==1
// result: (TESTB x y)
for {
if v.AuxInt != 0 {
break
}
- v_0 := v.Args[0]
- if v_0.Op != Op386ANDL {
+ l := v.Args[0]
+ if l.Op != Op386ANDL {
+ break
+ }
+ _ = l.Args[1]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
break
}
- _ = v_0.Args[1]
- x := v_0.Args[0]
- y := v_0.Args[1]
v.reset(Op386TESTB)
v.AddArg(x)
v.AddArg(y)
return true
}
- // match: (CMPBconst (ANDLconst [c] x) [0])
- // cond:
+ // match: (CMPBconst l:(ANDLconst [c] x) [0])
+ // cond: l.Uses==1
// result: (TESTBconst [int64(int8(c))] x)
for {
if v.AuxInt != 0 {
break
}
- v_0 := v.Args[0]
- if v_0.Op != Op386ANDLconst {
+ l := v.Args[0]
+ if l.Op != Op386ANDLconst {
+ break
+ }
+ c := l.AuxInt
+ x := l.Args[0]
+ if !(l.Uses == 1) {
break
}
- c := v_0.AuxInt
- x := v_0.Args[0]
v.reset(Op386TESTBconst)
v.AuxInt = int64(int8(c))
v.AddArg(x)
@@ -2819,38 +2825,44 @@ func rewriteValue386_Op386CMPLconst_0(v *Value) bool {
v.reset(Op386FlagLT_ULT)
return true
}
- // match: (CMPLconst (ANDL x y) [0])
- // cond:
+ // match: (CMPLconst l:(ANDL x y) [0])
+ // cond: l.Uses==1
// result: (TESTL x y)
for {
if v.AuxInt != 0 {
break
}
- v_0 := v.Args[0]
- if v_0.Op != Op386ANDL {
+ l := v.Args[0]
+ if l.Op != Op386ANDL {
+ break
+ }
+ _ = l.Args[1]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
break
}
- _ = v_0.Args[1]
- x := v_0.Args[0]
- y := v_0.Args[1]
v.reset(Op386TESTL)
v.AddArg(x)
v.AddArg(y)
return true
}
- // match: (CMPLconst (ANDLconst [c] x) [0])
- // cond:
+ // match: (CMPLconst l:(ANDLconst [c] x) [0])
+ // cond: l.Uses==1
// result: (TESTLconst [c] x)
for {
if v.AuxInt != 0 {
break
}
- v_0 := v.Args[0]
- if v_0.Op != Op386ANDLconst {
+ l := v.Args[0]
+ if l.Op != Op386ANDLconst {
+ break
+ }
+ c := l.AuxInt
+ x := l.Args[0]
+ if !(l.Uses == 1) {
break
}
- c := v_0.AuxInt
- x := v_0.Args[0]
v.reset(Op386TESTLconst)
v.AuxInt = c
v.AddArg(x)
@@ -3122,38 +3134,44 @@ func rewriteValue386_Op386CMPWconst_0(v *Value) bool {
v.reset(Op386FlagLT_ULT)
return true
}
- // match: (CMPWconst (ANDL x y) [0])
- // cond:
+ // match: (CMPWconst l:(ANDL x y) [0])
+ // cond: l.Uses==1
// result: (TESTW x y)
for {
if v.AuxInt != 0 {
break
}
- v_0 := v.Args[0]
- if v_0.Op != Op386ANDL {
+ l := v.Args[0]
+ if l.Op != Op386ANDL {
+ break
+ }
+ _ = l.Args[1]
+ x := l.Args[0]
+ y := l.Args[1]
+ if !(l.Uses == 1) {
break
}
- _ = v_0.Args[1]
- x := v_0.Args[0]
- y := v_0.Args[1]
v.reset(Op386TESTW)
v.AddArg(x)
v.AddArg(y)
return true
}
- // match: (CMPWconst (ANDLconst [c] x) [0])
- // cond:
+ // match: (CMPWconst l:(ANDLconst [c] x) [0])
+ // cond: l.Uses==1
// result: (TESTWconst [int64(int16(c))] x)
for {
if v.AuxInt != 0 {
break
}
- v_0 := v.Args[0]
- if v_0.Op != Op386ANDLconst {
+ l := v.Args[0]
+ if l.Op != Op386ANDLconst {
+ break
+ }
+ c := l.AuxInt
+ x := l.Args[0]
+ if !(l.Uses == 1) {
break
}
- c := v_0.AuxInt
- x := v_0.Args[0]
v.reset(Op386TESTWconst)
v.AuxInt = int64(int16(c))
v.AddArg(x)
@@ -19804,7 +19822,7 @@ func rewriteValue386_OpNeg32F_0(v *Value) bool {
_ = typ
// match: (Neg32F x)
// cond: !config.use387
- // result: (PXOR x (MOVSSconst <typ.Float32> [f2i(math.Copysign(0, -1))]))
+ // result: (PXOR x (MOVSSconst <typ.Float32> [auxFrom32F(float32(math.Copysign(0, -1)))]))
for {
x := v.Args[0]
if !(!config.use387) {
@@ -19813,7 +19831,7 @@ func rewriteValue386_OpNeg32F_0(v *Value) bool {
v.reset(Op386PXOR)
v.AddArg(x)
v0 := b.NewValue0(v.Pos, Op386MOVSSconst, typ.Float32)
- v0.AuxInt = f2i(math.Copysign(0, -1))
+ v0.AuxInt = auxFrom32F(float32(math.Copysign(0, -1)))
v.AddArg(v0)
return true
}
@@ -19840,7 +19858,7 @@ func rewriteValue386_OpNeg64F_0(v *Value) bool {
_ = typ
// match: (Neg64F x)
// cond: !config.use387
- // result: (PXOR x (MOVSDconst <typ.Float64> [f2i(math.Copysign(0, -1))]))
+ // result: (PXOR x (MOVSDconst <typ.Float64> [auxFrom64F(math.Copysign(0, -1))]))
for {
x := v.Args[0]
if !(!config.use387) {
@@ -19849,7 +19867,7 @@ func rewriteValue386_OpNeg64F_0(v *Value) bool {
v.reset(Op386PXOR)
v.AddArg(x)
v0 := b.NewValue0(v.Pos, Op386MOVSDconst, typ.Float64)
- v0.AuxInt = f2i(math.Copysign(0, -1))
+ v0.AuxInt = auxFrom64F(math.Copysign(0, -1))
v.AddArg(v0)
return true
}
diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go
index 1b531954db..89fc6780b9 100644
--- a/src/cmd/compile/internal/ssa/rewriteAMD64.go
+++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go
@@ -65,18 +65,46 @@ func rewriteValueAMD64(v *Value) bool {
return rewriteValueAMD64_OpAMD64ANDQmodify_0(v)
case OpAMD64BSFQ:
return rewriteValueAMD64_OpAMD64BSFQ_0(v)
+ case OpAMD64BTCLconst:
+ return rewriteValueAMD64_OpAMD64BTCLconst_0(v)
+ case OpAMD64BTCLconstmodify:
+ return rewriteValueAMD64_OpAMD64BTCLconstmodify_0(v)
+ case OpAMD64BTCLmodify:
+ return rewriteValueAMD64_OpAMD64BTCLmodify_0(v)
+ case OpAMD64BTCQconst:
+ return rewriteValueAMD64_OpAMD64BTCQconst_0(v)
+ case OpAMD64BTCQconstmodify:
+ return rewriteValueAMD64_OpAMD64BTCQconstmodify_0(v)
+ case OpAMD64BTCQmodify:
+ return rewriteValueAMD64_OpAMD64BTCQmodify_0(v)
case OpAMD64BTLconst:
return rewriteValueAMD64_OpAMD64BTLconst_0(v)
case OpAMD64BTQconst:
return rewriteValueAMD64_OpAMD64BTQconst_0(v)
case OpAMD64BTRLconst:
return rewriteValueAMD64_OpAMD64BTRLconst_0(v)
+ case OpAMD64BTRLconstmodify:
+ return rewriteValueAMD64_OpAMD64BTRLconstmodify_0(v)
+ case OpAMD64BTRLmodify:
+ return rewriteValueAMD64_OpAMD64BTRLmodify_0(v)
case OpAMD64BTRQconst:
return rewriteValueAMD64_OpAMD64BTRQconst_0(v)
+ case OpAMD64BTRQconstmodify:
+ return rewriteValueAMD64_OpAMD64BTRQconstmodify_0(v)
+ case OpAMD64BTRQmodify:
+ return rewriteValueAMD64_OpAMD64BTRQmodify_0(v)
case OpAMD64BTSLconst:
return rewriteValueAMD64_OpAMD64BTSLconst_0(v)
+ case OpAMD64BTSLconstmodify:
+ return rewriteValueAMD64_OpAMD64BTSLconstmodify_0(v)
+ case OpAMD64BTSLmodify:
+ return rewriteValueAMD64_OpAMD64BTSLmodify_0(v)
case OpAMD64BTSQconst:
return rewriteValueAMD64_OpAMD64BTSQconst_0(v)
+ case OpAMD64BTSQconstmodify:
+ return rewriteValueAMD64_OpAMD64BTSQconstmodify_0(v)
+ case OpAMD64BTSQmodify:
+ return rewriteValueAMD64_OpAMD64BTSQmodify_0(v)
case OpAMD64CMOVLCC:
return rewriteValueAMD64_OpAMD64CMOVLCC_0(v)
case OpAMD64CMOVLCS:
@@ -141,24 +169,32 @@ func rewriteValueAMD64(v *Value) bool {
return rewriteValueAMD64_OpAMD64CMPB_0(v)
case OpAMD64CMPBconst:
return rewriteValueAMD64_OpAMD64CMPBconst_0(v)
+ case OpAMD64CMPBconstload:
+ return rewriteValueAMD64_OpAMD64CMPBconstload_0(v)
case OpAMD64CMPBload:
return rewriteValueAMD64_OpAMD64CMPBload_0(v)
case OpAMD64CMPL:
return rewriteValueAMD64_OpAMD64CMPL_0(v)
case OpAMD64CMPLconst:
return rewriteValueAMD64_OpAMD64CMPLconst_0(v) || rewriteValueAMD64_OpAMD64CMPLconst_10(v)
+ case OpAMD64CMPLconstload:
+ return rewriteValueAMD64_OpAMD64CMPLconstload_0(v)
case OpAMD64CMPLload:
return rewriteValueAMD64_OpAMD64CMPLload_0(v)
case OpAMD64CMPQ:
return rewriteValueAMD64_OpAMD64CMPQ_0(v)
case OpAMD64CMPQconst:
return rewriteValueAMD64_OpAMD64CMPQconst_0(v) || rewriteValueAMD64_OpAMD64CMPQconst_10(v)
+ case OpAMD64CMPQconstload:
+ return rewriteValueAMD64_OpAMD64CMPQconstload_0(v)
case OpAMD64CMPQload:
return rewriteValueAMD64_OpAMD64CMPQload_0(v)
case OpAMD64CMPW:
return rewriteValueAMD64_OpAMD64CMPW_0(v)
case OpAMD64CMPWconst:
return rewriteValueAMD64_OpAMD64CMPWconst_0(v)
+ case OpAMD64CMPWconstload:
+ return rewriteValueAMD64_OpAMD64CMPWconstload_0(v)
case OpAMD64CMPWload:
return rewriteValueAMD64_OpAMD64CMPWload_0(v)
case OpAMD64CMPXCHGLlock:
@@ -270,7 +306,7 @@ func rewriteValueAMD64(v *Value) bool {
case OpAMD64MOVQloadidx8:
return rewriteValueAMD64_OpAMD64MOVQloadidx8_0(v)
case OpAMD64MOVQstore:
- return rewriteValueAMD64_OpAMD64MOVQstore_0(v) || rewriteValueAMD64_OpAMD64MOVQstore_10(v) || rewriteValueAMD64_OpAMD64MOVQstore_20(v)
+ return rewriteValueAMD64_OpAMD64MOVQstore_0(v) || rewriteValueAMD64_OpAMD64MOVQstore_10(v) || rewriteValueAMD64_OpAMD64MOVQstore_20(v) || rewriteValueAMD64_OpAMD64MOVQstore_30(v)
case OpAMD64MOVQstoreconst:
return rewriteValueAMD64_OpAMD64MOVQstoreconst_0(v)
case OpAMD64MOVQstoreconstidx1:
@@ -3582,6 +3618,22 @@ func rewriteValueAMD64_OpAMD64ANDLconst_0(v *Value) bool {
v.AddArg(x)
return true
}
+ // match: (ANDLconst [c] (BTRLconst [d] x))
+ // cond:
+ // result: (ANDLconst [c &^ (1<<uint32(d))] x)
+ for {
+ c := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64BTRLconst {
+ break
+ }
+ d := v_0.AuxInt
+ x := v_0.Args[0]
+ v.reset(OpAMD64ANDLconst)
+ v.AuxInt = c &^ (1 << uint32(d))
+ v.AddArg(x)
+ return true
+ }
// match: (ANDLconst [ 0xFF] x)
// cond:
// result: (MOVBQZX x)
@@ -4093,6 +4145,22 @@ func rewriteValueAMD64_OpAMD64ANDQconst_0(v *Value) bool {
v.AddArg(x)
return true
}
+ // match: (ANDQconst [c] (BTRQconst [d] x))
+ // cond:
+ // result: (ANDQconst [c &^ (1<<uint32(d))] x)
+ for {
+ c := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64BTRQconst {
+ break
+ }
+ d := v_0.AuxInt
+ x := v_0.Args[0]
+ v.reset(OpAMD64ANDQconst)
+ v.AuxInt = c &^ (1 << uint32(d))
+ v.AddArg(x)
+ return true
+ }
// match: (ANDQconst [ 0xFF] x)
// cond:
// result: (MOVBQZX x)
@@ -4421,6 +4489,320 @@ func rewriteValueAMD64_OpAMD64BSFQ_0(v *Value) bool {
}
return false
}
+func rewriteValueAMD64_OpAMD64BTCLconst_0(v *Value) bool {
+ // match: (BTCLconst [c] (XORLconst [d] x))
+ // cond:
+ // result: (XORLconst [d ^ 1<<uint32(c)] x)
+ for {
+ c := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64XORLconst {
+ break
+ }
+ d := v_0.AuxInt
+ x := v_0.Args[0]
+ v.reset(OpAMD64XORLconst)
+ v.AuxInt = d ^ 1<<uint32(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTCLconst [c] (BTCLconst [d] x))
+ // cond:
+ // result: (XORLconst [1<<uint32(c) ^ 1<<uint32(d)] x)
+ for {
+ c := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64BTCLconst {
+ break
+ }
+ d := v_0.AuxInt
+ x := v_0.Args[0]
+ v.reset(OpAMD64XORLconst)
+ v.AuxInt = 1<<uint32(c) ^ 1<<uint32(d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTCLconst [c] (MOVLconst [d]))
+ // cond:
+ // result: (MOVLconst [d^(1<<uint32(c))])
+ for {
+ c := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64MOVLconst {
+ break
+ }
+ d := v_0.AuxInt
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = d ^ (1 << uint32(c))
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64BTCLconstmodify_0(v *Value) bool {
+ // match: (BTCLconstmodify [valoff1] {sym} (ADDQconst [off2] base) mem)
+ // cond: ValAndOff(valoff1).canAdd(off2)
+ // result: (BTCLconstmodify [ValAndOff(valoff1).add(off2)] {sym} base mem)
+ for {
+ valoff1 := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := v_0.AuxInt
+ base := v_0.Args[0]
+ mem := v.Args[1]
+ if !(ValAndOff(valoff1).canAdd(off2)) {
+ break
+ }
+ v.reset(OpAMD64BTCLconstmodify)
+ v.AuxInt = ValAndOff(valoff1).add(off2)
+ v.Aux = sym
+ v.AddArg(base)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (BTCLconstmodify [valoff1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2)
+ // result: (BTCLconstmodify [ValAndOff(valoff1).add(off2)] {mergeSym(sym1,sym2)} base mem)
+ for {
+ valoff1 := v.AuxInt
+ sym1 := v.Aux
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := v_0.AuxInt
+ sym2 := v_0.Aux
+ base := v_0.Args[0]
+ mem := v.Args[1]
+ if !(ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64BTCLconstmodify)
+ v.AuxInt = ValAndOff(valoff1).add(off2)
+ v.Aux = mergeSym(sym1, sym2)
+ v.AddArg(base)
+ v.AddArg(mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64BTCLmodify_0(v *Value) bool {
+ // match: (BTCLmodify [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(off1+off2)
+ // result: (BTCLmodify [off1+off2] {sym} base val mem)
+ for {
+ off1 := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[2]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := v_0.AuxInt
+ base := v_0.Args[0]
+ val := v.Args[1]
+ mem := v.Args[2]
+ if !(is32Bit(off1 + off2)) {
+ break
+ }
+ v.reset(OpAMD64BTCLmodify)
+ v.AuxInt = off1 + off2
+ v.Aux = sym
+ v.AddArg(base)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (BTCLmodify [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2)
+ // result: (BTCLmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := v.AuxInt
+ sym1 := v.Aux
+ _ = v.Args[2]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := v_0.AuxInt
+ sym2 := v_0.Aux
+ base := v_0.Args[0]
+ val := v.Args[1]
+ mem := v.Args[2]
+ if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64BTCLmodify)
+ v.AuxInt = off1 + off2
+ v.Aux = mergeSym(sym1, sym2)
+ v.AddArg(base)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64BTCQconst_0(v *Value) bool {
+ // match: (BTCQconst [c] (XORQconst [d] x))
+ // cond:
+ // result: (XORQconst [d ^ 1<<uint32(c)] x)
+ for {
+ c := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64XORQconst {
+ break
+ }
+ d := v_0.AuxInt
+ x := v_0.Args[0]
+ v.reset(OpAMD64XORQconst)
+ v.AuxInt = d ^ 1<<uint32(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTCQconst [c] (BTCQconst [d] x))
+ // cond:
+ // result: (XORQconst [1<<uint32(c) ^ 1<<uint32(d)] x)
+ for {
+ c := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64BTCQconst {
+ break
+ }
+ d := v_0.AuxInt
+ x := v_0.Args[0]
+ v.reset(OpAMD64XORQconst)
+ v.AuxInt = 1<<uint32(c) ^ 1<<uint32(d)
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTCQconst [c] (MOVQconst [d]))
+ // cond:
+ // result: (MOVQconst [d^(1<<uint32(c))])
+ for {
+ c := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64MOVQconst {
+ break
+ }
+ d := v_0.AuxInt
+ v.reset(OpAMD64MOVQconst)
+ v.AuxInt = d ^ (1 << uint32(c))
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64BTCQconstmodify_0(v *Value) bool {
+ // match: (BTCQconstmodify [valoff1] {sym} (ADDQconst [off2] base) mem)
+ // cond: ValAndOff(valoff1).canAdd(off2)
+ // result: (BTCQconstmodify [ValAndOff(valoff1).add(off2)] {sym} base mem)
+ for {
+ valoff1 := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := v_0.AuxInt
+ base := v_0.Args[0]
+ mem := v.Args[1]
+ if !(ValAndOff(valoff1).canAdd(off2)) {
+ break
+ }
+ v.reset(OpAMD64BTCQconstmodify)
+ v.AuxInt = ValAndOff(valoff1).add(off2)
+ v.Aux = sym
+ v.AddArg(base)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (BTCQconstmodify [valoff1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2)
+ // result: (BTCQconstmodify [ValAndOff(valoff1).add(off2)] {mergeSym(sym1,sym2)} base mem)
+ for {
+ valoff1 := v.AuxInt
+ sym1 := v.Aux
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := v_0.AuxInt
+ sym2 := v_0.Aux
+ base := v_0.Args[0]
+ mem := v.Args[1]
+ if !(ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64BTCQconstmodify)
+ v.AuxInt = ValAndOff(valoff1).add(off2)
+ v.Aux = mergeSym(sym1, sym2)
+ v.AddArg(base)
+ v.AddArg(mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64BTCQmodify_0(v *Value) bool {
+ // match: (BTCQmodify [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(off1+off2)
+ // result: (BTCQmodify [off1+off2] {sym} base val mem)
+ for {
+ off1 := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[2]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := v_0.AuxInt
+ base := v_0.Args[0]
+ val := v.Args[1]
+ mem := v.Args[2]
+ if !(is32Bit(off1 + off2)) {
+ break
+ }
+ v.reset(OpAMD64BTCQmodify)
+ v.AuxInt = off1 + off2
+ v.Aux = sym
+ v.AddArg(base)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (BTCQmodify [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2)
+ // result: (BTCQmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := v.AuxInt
+ sym1 := v.Aux
+ _ = v.Args[2]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := v_0.AuxInt
+ sym2 := v_0.Aux
+ base := v_0.Args[0]
+ val := v.Args[1]
+ mem := v.Args[2]
+ if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64BTCQmodify)
+ v.AuxInt = off1 + off2
+ v.Aux = mergeSym(sym1, sym2)
+ v.AddArg(base)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
+ return false
+}
func rewriteValueAMD64_OpAMD64BTLconst_0(v *Value) bool {
// match: (BTLconst [c] (SHRQconst [d] x))
// cond: (c+d)<64
@@ -4635,6 +5017,160 @@ func rewriteValueAMD64_OpAMD64BTRLconst_0(v *Value) bool {
v.AddArg(x)
return true
}
+ // match: (BTRLconst [c] (ANDLconst [d] x))
+ // cond:
+ // result: (ANDLconst [d &^ (1<<uint32(c))] x)
+ for {
+ c := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64ANDLconst {
+ break
+ }
+ d := v_0.AuxInt
+ x := v_0.Args[0]
+ v.reset(OpAMD64ANDLconst)
+ v.AuxInt = d &^ (1 << uint32(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTRLconst [c] (BTRLconst [d] x))
+ // cond:
+ // result: (ANDLconst [^(1<<uint32(c) | 1<<uint32(d))] x)
+ for {
+ c := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64BTRLconst {
+ break
+ }
+ d := v_0.AuxInt
+ x := v_0.Args[0]
+ v.reset(OpAMD64ANDLconst)
+ v.AuxInt = ^(1<<uint32(c) | 1<<uint32(d))
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTRLconst [c] (MOVLconst [d]))
+ // cond:
+ // result: (MOVLconst [d&^(1<<uint32(c))])
+ for {
+ c := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64MOVLconst {
+ break
+ }
+ d := v_0.AuxInt
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = d &^ (1 << uint32(c))
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64BTRLconstmodify_0(v *Value) bool {
+ // match: (BTRLconstmodify [valoff1] {sym} (ADDQconst [off2] base) mem)
+ // cond: ValAndOff(valoff1).canAdd(off2)
+ // result: (BTRLconstmodify [ValAndOff(valoff1).add(off2)] {sym} base mem)
+ for {
+ valoff1 := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := v_0.AuxInt
+ base := v_0.Args[0]
+ mem := v.Args[1]
+ if !(ValAndOff(valoff1).canAdd(off2)) {
+ break
+ }
+ v.reset(OpAMD64BTRLconstmodify)
+ v.AuxInt = ValAndOff(valoff1).add(off2)
+ v.Aux = sym
+ v.AddArg(base)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (BTRLconstmodify [valoff1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2)
+ // result: (BTRLconstmodify [ValAndOff(valoff1).add(off2)] {mergeSym(sym1,sym2)} base mem)
+ for {
+ valoff1 := v.AuxInt
+ sym1 := v.Aux
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := v_0.AuxInt
+ sym2 := v_0.Aux
+ base := v_0.Args[0]
+ mem := v.Args[1]
+ if !(ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64BTRLconstmodify)
+ v.AuxInt = ValAndOff(valoff1).add(off2)
+ v.Aux = mergeSym(sym1, sym2)
+ v.AddArg(base)
+ v.AddArg(mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64BTRLmodify_0(v *Value) bool {
+ // match: (BTRLmodify [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(off1+off2)
+ // result: (BTRLmodify [off1+off2] {sym} base val mem)
+ for {
+ off1 := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[2]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := v_0.AuxInt
+ base := v_0.Args[0]
+ val := v.Args[1]
+ mem := v.Args[2]
+ if !(is32Bit(off1 + off2)) {
+ break
+ }
+ v.reset(OpAMD64BTRLmodify)
+ v.AuxInt = off1 + off2
+ v.Aux = sym
+ v.AddArg(base)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (BTRLmodify [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2)
+ // result: (BTRLmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := v.AuxInt
+ sym1 := v.Aux
+ _ = v.Args[2]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := v_0.AuxInt
+ sym2 := v_0.Aux
+ base := v_0.Args[0]
+ val := v.Args[1]
+ mem := v.Args[2]
+ if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64BTRLmodify)
+ v.AuxInt = off1 + off2
+ v.Aux = mergeSym(sym1, sym2)
+ v.AddArg(base)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
return false
}
func rewriteValueAMD64_OpAMD64BTRQconst_0(v *Value) bool {
@@ -4674,6 +5210,160 @@ func rewriteValueAMD64_OpAMD64BTRQconst_0(v *Value) bool {
v.AddArg(x)
return true
}
+ // match: (BTRQconst [c] (ANDQconst [d] x))
+ // cond:
+ // result: (ANDQconst [d &^ (1<<uint32(c))] x)
+ for {
+ c := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64ANDQconst {
+ break
+ }
+ d := v_0.AuxInt
+ x := v_0.Args[0]
+ v.reset(OpAMD64ANDQconst)
+ v.AuxInt = d &^ (1 << uint32(c))
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTRQconst [c] (BTRQconst [d] x))
+ // cond:
+ // result: (ANDQconst [^(1<<uint32(c) | 1<<uint32(d))] x)
+ for {
+ c := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64BTRQconst {
+ break
+ }
+ d := v_0.AuxInt
+ x := v_0.Args[0]
+ v.reset(OpAMD64ANDQconst)
+ v.AuxInt = ^(1<<uint32(c) | 1<<uint32(d))
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTRQconst [c] (MOVQconst [d]))
+ // cond:
+ // result: (MOVQconst [d&^(1<<uint32(c))])
+ for {
+ c := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64MOVQconst {
+ break
+ }
+ d := v_0.AuxInt
+ v.reset(OpAMD64MOVQconst)
+ v.AuxInt = d &^ (1 << uint32(c))
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64BTRQconstmodify_0(v *Value) bool {
+ // match: (BTRQconstmodify [valoff1] {sym} (ADDQconst [off2] base) mem)
+ // cond: ValAndOff(valoff1).canAdd(off2)
+ // result: (BTRQconstmodify [ValAndOff(valoff1).add(off2)] {sym} base mem)
+ for {
+ valoff1 := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := v_0.AuxInt
+ base := v_0.Args[0]
+ mem := v.Args[1]
+ if !(ValAndOff(valoff1).canAdd(off2)) {
+ break
+ }
+ v.reset(OpAMD64BTRQconstmodify)
+ v.AuxInt = ValAndOff(valoff1).add(off2)
+ v.Aux = sym
+ v.AddArg(base)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (BTRQconstmodify [valoff1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2)
+ // result: (BTRQconstmodify [ValAndOff(valoff1).add(off2)] {mergeSym(sym1,sym2)} base mem)
+ for {
+ valoff1 := v.AuxInt
+ sym1 := v.Aux
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := v_0.AuxInt
+ sym2 := v_0.Aux
+ base := v_0.Args[0]
+ mem := v.Args[1]
+ if !(ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64BTRQconstmodify)
+ v.AuxInt = ValAndOff(valoff1).add(off2)
+ v.Aux = mergeSym(sym1, sym2)
+ v.AddArg(base)
+ v.AddArg(mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64BTRQmodify_0(v *Value) bool {
+ // match: (BTRQmodify [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(off1+off2)
+ // result: (BTRQmodify [off1+off2] {sym} base val mem)
+ for {
+ off1 := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[2]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := v_0.AuxInt
+ base := v_0.Args[0]
+ val := v.Args[1]
+ mem := v.Args[2]
+ if !(is32Bit(off1 + off2)) {
+ break
+ }
+ v.reset(OpAMD64BTRQmodify)
+ v.AuxInt = off1 + off2
+ v.Aux = sym
+ v.AddArg(base)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (BTRQmodify [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2)
+ // result: (BTRQmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := v.AuxInt
+ sym1 := v.Aux
+ _ = v.Args[2]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := v_0.AuxInt
+ sym2 := v_0.Aux
+ base := v_0.Args[0]
+ val := v.Args[1]
+ mem := v.Args[2]
+ if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64BTRQmodify)
+ v.AuxInt = off1 + off2
+ v.Aux = mergeSym(sym1, sym2)
+ v.AddArg(base)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
return false
}
func rewriteValueAMD64_OpAMD64BTSLconst_0(v *Value) bool {
@@ -4713,6 +5403,160 @@ func rewriteValueAMD64_OpAMD64BTSLconst_0(v *Value) bool {
v.AddArg(x)
return true
}
+ // match: (BTSLconst [c] (ORLconst [d] x))
+ // cond:
+ // result: (ORLconst [d | 1<<uint32(c)] x)
+ for {
+ c := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64ORLconst {
+ break
+ }
+ d := v_0.AuxInt
+ x := v_0.Args[0]
+ v.reset(OpAMD64ORLconst)
+ v.AuxInt = d | 1<<uint32(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTSLconst [c] (BTSLconst [d] x))
+ // cond:
+ // result: (ORLconst [1<<uint32(d) | 1<<uint32(c)] x)
+ for {
+ c := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64BTSLconst {
+ break
+ }
+ d := v_0.AuxInt
+ x := v_0.Args[0]
+ v.reset(OpAMD64ORLconst)
+ v.AuxInt = 1<<uint32(d) | 1<<uint32(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTSLconst [c] (MOVLconst [d]))
+ // cond:
+ // result: (MOVLconst [d|(1<<uint32(c))])
+ for {
+ c := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64MOVLconst {
+ break
+ }
+ d := v_0.AuxInt
+ v.reset(OpAMD64MOVLconst)
+ v.AuxInt = d | (1 << uint32(c))
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64BTSLconstmodify_0(v *Value) bool {
+ // match: (BTSLconstmodify [valoff1] {sym} (ADDQconst [off2] base) mem)
+ // cond: ValAndOff(valoff1).canAdd(off2)
+ // result: (BTSLconstmodify [ValAndOff(valoff1).add(off2)] {sym} base mem)
+ for {
+ valoff1 := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := v_0.AuxInt
+ base := v_0.Args[0]
+ mem := v.Args[1]
+ if !(ValAndOff(valoff1).canAdd(off2)) {
+ break
+ }
+ v.reset(OpAMD64BTSLconstmodify)
+ v.AuxInt = ValAndOff(valoff1).add(off2)
+ v.Aux = sym
+ v.AddArg(base)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (BTSLconstmodify [valoff1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2)
+ // result: (BTSLconstmodify [ValAndOff(valoff1).add(off2)] {mergeSym(sym1,sym2)} base mem)
+ for {
+ valoff1 := v.AuxInt
+ sym1 := v.Aux
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := v_0.AuxInt
+ sym2 := v_0.Aux
+ base := v_0.Args[0]
+ mem := v.Args[1]
+ if !(ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64BTSLconstmodify)
+ v.AuxInt = ValAndOff(valoff1).add(off2)
+ v.Aux = mergeSym(sym1, sym2)
+ v.AddArg(base)
+ v.AddArg(mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64BTSLmodify_0(v *Value) bool {
+ // match: (BTSLmodify [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(off1+off2)
+ // result: (BTSLmodify [off1+off2] {sym} base val mem)
+ for {
+ off1 := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[2]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := v_0.AuxInt
+ base := v_0.Args[0]
+ val := v.Args[1]
+ mem := v.Args[2]
+ if !(is32Bit(off1 + off2)) {
+ break
+ }
+ v.reset(OpAMD64BTSLmodify)
+ v.AuxInt = off1 + off2
+ v.Aux = sym
+ v.AddArg(base)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (BTSLmodify [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2)
+ // result: (BTSLmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := v.AuxInt
+ sym1 := v.Aux
+ _ = v.Args[2]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := v_0.AuxInt
+ sym2 := v_0.Aux
+ base := v_0.Args[0]
+ val := v.Args[1]
+ mem := v.Args[2]
+ if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64BTSLmodify)
+ v.AuxInt = off1 + off2
+ v.Aux = mergeSym(sym1, sym2)
+ v.AddArg(base)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
return false
}
func rewriteValueAMD64_OpAMD64BTSQconst_0(v *Value) bool {
@@ -4752,6 +5596,160 @@ func rewriteValueAMD64_OpAMD64BTSQconst_0(v *Value) bool {
v.AddArg(x)
return true
}
+ // match: (BTSQconst [c] (ORQconst [d] x))
+ // cond:
+ // result: (ORQconst [d | 1<<uint32(c)] x)
+ for {
+ c := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64ORQconst {
+ break
+ }
+ d := v_0.AuxInt
+ x := v_0.Args[0]
+ v.reset(OpAMD64ORQconst)
+ v.AuxInt = d | 1<<uint32(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTSQconst [c] (BTSQconst [d] x))
+ // cond:
+ // result: (ORQconst [1<<uint32(d) | 1<<uint32(c)] x)
+ for {
+ c := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64BTSQconst {
+ break
+ }
+ d := v_0.AuxInt
+ x := v_0.Args[0]
+ v.reset(OpAMD64ORQconst)
+ v.AuxInt = 1<<uint32(d) | 1<<uint32(c)
+ v.AddArg(x)
+ return true
+ }
+ // match: (BTSQconst [c] (MOVQconst [d]))
+ // cond:
+ // result: (MOVQconst [d|(1<<uint32(c))])
+ for {
+ c := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64MOVQconst {
+ break
+ }
+ d := v_0.AuxInt
+ v.reset(OpAMD64MOVQconst)
+ v.AuxInt = d | (1 << uint32(c))
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64BTSQconstmodify_0(v *Value) bool {
+ // match: (BTSQconstmodify [valoff1] {sym} (ADDQconst [off2] base) mem)
+ // cond: ValAndOff(valoff1).canAdd(off2)
+ // result: (BTSQconstmodify [ValAndOff(valoff1).add(off2)] {sym} base mem)
+ for {
+ valoff1 := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := v_0.AuxInt
+ base := v_0.Args[0]
+ mem := v.Args[1]
+ if !(ValAndOff(valoff1).canAdd(off2)) {
+ break
+ }
+ v.reset(OpAMD64BTSQconstmodify)
+ v.AuxInt = ValAndOff(valoff1).add(off2)
+ v.Aux = sym
+ v.AddArg(base)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (BTSQconstmodify [valoff1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2)
+ // result: (BTSQconstmodify [ValAndOff(valoff1).add(off2)] {mergeSym(sym1,sym2)} base mem)
+ for {
+ valoff1 := v.AuxInt
+ sym1 := v.Aux
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := v_0.AuxInt
+ sym2 := v_0.Aux
+ base := v_0.Args[0]
+ mem := v.Args[1]
+ if !(ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64BTSQconstmodify)
+ v.AuxInt = ValAndOff(valoff1).add(off2)
+ v.Aux = mergeSym(sym1, sym2)
+ v.AddArg(base)
+ v.AddArg(mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64BTSQmodify_0(v *Value) bool {
+ // match: (BTSQmodify [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(off1+off2)
+ // result: (BTSQmodify [off1+off2] {sym} base val mem)
+ for {
+ off1 := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[2]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := v_0.AuxInt
+ base := v_0.Args[0]
+ val := v.Args[1]
+ mem := v.Args[2]
+ if !(is32Bit(off1 + off2)) {
+ break
+ }
+ v.reset(OpAMD64BTSQmodify)
+ v.AuxInt = off1 + off2
+ v.Aux = sym
+ v.AddArg(base)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (BTSQmodify [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2)
+ // result: (BTSQmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := v.AuxInt
+ sym1 := v.Aux
+ _ = v.Args[2]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := v_0.AuxInt
+ sym2 := v_0.Aux
+ base := v_0.Args[0]
+ val := v.Args[1]
+ mem := v.Args[2]
+ if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64BTSQmodify)
+ v.AuxInt = off1 + off2
+ v.Aux = mergeSym(sym1, sym2)
+ v.AddArg(base)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
return false
}
func rewriteValueAMD64_OpAMD64CMOVLCC_0(v *Value) bool {
@@ -7932,7 +8930,112 @@ func rewriteValueAMD64_OpAMD64CMPBconst_0(v *Value) bool {
}
return false
}
+func rewriteValueAMD64_OpAMD64CMPBconstload_0(v *Value) bool {
+ // match: (CMPBconstload [valoff1] {sym} (ADDQconst [off2] base) mem)
+ // cond: ValAndOff(valoff1).canAdd(off2)
+ // result: (CMPBconstload [ValAndOff(valoff1).add(off2)] {sym} base mem)
+ for {
+ valoff1 := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := v_0.AuxInt
+ base := v_0.Args[0]
+ mem := v.Args[1]
+ if !(ValAndOff(valoff1).canAdd(off2)) {
+ break
+ }
+ v.reset(OpAMD64CMPBconstload)
+ v.AuxInt = ValAndOff(valoff1).add(off2)
+ v.Aux = sym
+ v.AddArg(base)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (CMPBconstload [valoff1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2)
+ // result: (CMPBconstload [ValAndOff(valoff1).add(off2)] {mergeSym(sym1,sym2)} base mem)
+ for {
+ valoff1 := v.AuxInt
+ sym1 := v.Aux
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := v_0.AuxInt
+ sym2 := v_0.Aux
+ base := v_0.Args[0]
+ mem := v.Args[1]
+ if !(ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64CMPBconstload)
+ v.AuxInt = ValAndOff(valoff1).add(off2)
+ v.Aux = mergeSym(sym1, sym2)
+ v.AddArg(base)
+ v.AddArg(mem)
+ return true
+ }
+ return false
+}
func rewriteValueAMD64_OpAMD64CMPBload_0(v *Value) bool {
+ // match: (CMPBload [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(off1+off2)
+ // result: (CMPBload [off1+off2] {sym} base val mem)
+ for {
+ off1 := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[2]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := v_0.AuxInt
+ base := v_0.Args[0]
+ val := v.Args[1]
+ mem := v.Args[2]
+ if !(is32Bit(off1 + off2)) {
+ break
+ }
+ v.reset(OpAMD64CMPBload)
+ v.AuxInt = off1 + off2
+ v.Aux = sym
+ v.AddArg(base)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (CMPBload [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2)
+ // result: (CMPBload [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := v.AuxInt
+ sym1 := v.Aux
+ _ = v.Args[2]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := v_0.AuxInt
+ sym2 := v_0.Aux
+ base := v_0.Args[0]
+ val := v.Args[1]
+ mem := v.Args[2]
+ if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64CMPBload)
+ v.AuxInt = off1 + off2
+ v.Aux = mergeSym(sym1, sym2)
+ v.AddArg(base)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
// match: (CMPBload {sym} [off] ptr (MOVLconst [c]) mem)
// cond: validValAndOff(int64(int8(c)),off)
// result: (CMPBconstload {sym} [makeValAndOff(int64(int8(c)),off)] ptr mem)
@@ -8249,7 +9352,112 @@ func rewriteValueAMD64_OpAMD64CMPLconst_10(v *Value) bool {
}
return false
}
+func rewriteValueAMD64_OpAMD64CMPLconstload_0(v *Value) bool {
+ // match: (CMPLconstload [valoff1] {sym} (ADDQconst [off2] base) mem)
+ // cond: ValAndOff(valoff1).canAdd(off2)
+ // result: (CMPLconstload [ValAndOff(valoff1).add(off2)] {sym} base mem)
+ for {
+ valoff1 := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := v_0.AuxInt
+ base := v_0.Args[0]
+ mem := v.Args[1]
+ if !(ValAndOff(valoff1).canAdd(off2)) {
+ break
+ }
+ v.reset(OpAMD64CMPLconstload)
+ v.AuxInt = ValAndOff(valoff1).add(off2)
+ v.Aux = sym
+ v.AddArg(base)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (CMPLconstload [valoff1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2)
+ // result: (CMPLconstload [ValAndOff(valoff1).add(off2)] {mergeSym(sym1,sym2)} base mem)
+ for {
+ valoff1 := v.AuxInt
+ sym1 := v.Aux
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := v_0.AuxInt
+ sym2 := v_0.Aux
+ base := v_0.Args[0]
+ mem := v.Args[1]
+ if !(ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64CMPLconstload)
+ v.AuxInt = ValAndOff(valoff1).add(off2)
+ v.Aux = mergeSym(sym1, sym2)
+ v.AddArg(base)
+ v.AddArg(mem)
+ return true
+ }
+ return false
+}
func rewriteValueAMD64_OpAMD64CMPLload_0(v *Value) bool {
+ // match: (CMPLload [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(off1+off2)
+ // result: (CMPLload [off1+off2] {sym} base val mem)
+ for {
+ off1 := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[2]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := v_0.AuxInt
+ base := v_0.Args[0]
+ val := v.Args[1]
+ mem := v.Args[2]
+ if !(is32Bit(off1 + off2)) {
+ break
+ }
+ v.reset(OpAMD64CMPLload)
+ v.AuxInt = off1 + off2
+ v.Aux = sym
+ v.AddArg(base)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (CMPLload [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2)
+ // result: (CMPLload [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := v.AuxInt
+ sym1 := v.Aux
+ _ = v.Args[2]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := v_0.AuxInt
+ sym2 := v_0.Aux
+ base := v_0.Args[0]
+ val := v.Args[1]
+ mem := v.Args[2]
+ if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64CMPLload)
+ v.AuxInt = off1 + off2
+ v.Aux = mergeSym(sym1, sym2)
+ v.AddArg(base)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
// match: (CMPLload {sym} [off] ptr (MOVLconst [c]) mem)
// cond: validValAndOff(c,off)
// result: (CMPLconstload {sym} [makeValAndOff(c,off)] ptr mem)
@@ -8689,7 +9897,112 @@ func rewriteValueAMD64_OpAMD64CMPQconst_10(v *Value) bool {
}
return false
}
+func rewriteValueAMD64_OpAMD64CMPQconstload_0(v *Value) bool {
+ // match: (CMPQconstload [valoff1] {sym} (ADDQconst [off2] base) mem)
+ // cond: ValAndOff(valoff1).canAdd(off2)
+ // result: (CMPQconstload [ValAndOff(valoff1).add(off2)] {sym} base mem)
+ for {
+ valoff1 := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := v_0.AuxInt
+ base := v_0.Args[0]
+ mem := v.Args[1]
+ if !(ValAndOff(valoff1).canAdd(off2)) {
+ break
+ }
+ v.reset(OpAMD64CMPQconstload)
+ v.AuxInt = ValAndOff(valoff1).add(off2)
+ v.Aux = sym
+ v.AddArg(base)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (CMPQconstload [valoff1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2)
+ // result: (CMPQconstload [ValAndOff(valoff1).add(off2)] {mergeSym(sym1,sym2)} base mem)
+ for {
+ valoff1 := v.AuxInt
+ sym1 := v.Aux
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := v_0.AuxInt
+ sym2 := v_0.Aux
+ base := v_0.Args[0]
+ mem := v.Args[1]
+ if !(ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64CMPQconstload)
+ v.AuxInt = ValAndOff(valoff1).add(off2)
+ v.Aux = mergeSym(sym1, sym2)
+ v.AddArg(base)
+ v.AddArg(mem)
+ return true
+ }
+ return false
+}
func rewriteValueAMD64_OpAMD64CMPQload_0(v *Value) bool {
+ // match: (CMPQload [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(off1+off2)
+ // result: (CMPQload [off1+off2] {sym} base val mem)
+ for {
+ off1 := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[2]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := v_0.AuxInt
+ base := v_0.Args[0]
+ val := v.Args[1]
+ mem := v.Args[2]
+ if !(is32Bit(off1 + off2)) {
+ break
+ }
+ v.reset(OpAMD64CMPQload)
+ v.AuxInt = off1 + off2
+ v.Aux = sym
+ v.AddArg(base)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (CMPQload [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2)
+ // result: (CMPQload [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := v.AuxInt
+ sym1 := v.Aux
+ _ = v.Args[2]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := v_0.AuxInt
+ sym2 := v_0.Aux
+ base := v_0.Args[0]
+ val := v.Args[1]
+ mem := v.Args[2]
+ if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64CMPQload)
+ v.AuxInt = off1 + off2
+ v.Aux = mergeSym(sym1, sym2)
+ v.AddArg(base)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
// match: (CMPQload {sym} [off] ptr (MOVQconst [c]) mem)
// cond: validValAndOff(c,off)
// result: (CMPQconstload {sym} [makeValAndOff(c,off)] ptr mem)
@@ -8987,7 +10300,112 @@ func rewriteValueAMD64_OpAMD64CMPWconst_0(v *Value) bool {
}
return false
}
+func rewriteValueAMD64_OpAMD64CMPWconstload_0(v *Value) bool {
+ // match: (CMPWconstload [valoff1] {sym} (ADDQconst [off2] base) mem)
+ // cond: ValAndOff(valoff1).canAdd(off2)
+ // result: (CMPWconstload [ValAndOff(valoff1).add(off2)] {sym} base mem)
+ for {
+ valoff1 := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := v_0.AuxInt
+ base := v_0.Args[0]
+ mem := v.Args[1]
+ if !(ValAndOff(valoff1).canAdd(off2)) {
+ break
+ }
+ v.reset(OpAMD64CMPWconstload)
+ v.AuxInt = ValAndOff(valoff1).add(off2)
+ v.Aux = sym
+ v.AddArg(base)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (CMPWconstload [valoff1] {sym1} (LEAQ [off2] {sym2} base) mem)
+ // cond: ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2)
+ // result: (CMPWconstload [ValAndOff(valoff1).add(off2)] {mergeSym(sym1,sym2)} base mem)
+ for {
+ valoff1 := v.AuxInt
+ sym1 := v.Aux
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := v_0.AuxInt
+ sym2 := v_0.Aux
+ base := v_0.Args[0]
+ mem := v.Args[1]
+ if !(ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64CMPWconstload)
+ v.AuxInt = ValAndOff(valoff1).add(off2)
+ v.Aux = mergeSym(sym1, sym2)
+ v.AddArg(base)
+ v.AddArg(mem)
+ return true
+ }
+ return false
+}
func rewriteValueAMD64_OpAMD64CMPWload_0(v *Value) bool {
+ // match: (CMPWload [off1] {sym} (ADDQconst [off2] base) val mem)
+ // cond: is32Bit(off1+off2)
+ // result: (CMPWload [off1+off2] {sym} base val mem)
+ for {
+ off1 := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[2]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64ADDQconst {
+ break
+ }
+ off2 := v_0.AuxInt
+ base := v_0.Args[0]
+ val := v.Args[1]
+ mem := v.Args[2]
+ if !(is32Bit(off1 + off2)) {
+ break
+ }
+ v.reset(OpAMD64CMPWload)
+ v.AuxInt = off1 + off2
+ v.Aux = sym
+ v.AddArg(base)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (CMPWload [off1] {sym1} (LEAQ [off2] {sym2} base) val mem)
+ // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2)
+ // result: (CMPWload [off1+off2] {mergeSym(sym1,sym2)} base val mem)
+ for {
+ off1 := v.AuxInt
+ sym1 := v.Aux
+ _ = v.Args[2]
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64LEAQ {
+ break
+ }
+ off2 := v_0.AuxInt
+ sym2 := v_0.Aux
+ base := v_0.Args[0]
+ val := v.Args[1]
+ mem := v.Args[2]
+ if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) {
+ break
+ }
+ v.reset(OpAMD64CMPWload)
+ v.AuxInt = off1 + off2
+ v.Aux = mergeSym(sym1, sym2)
+ v.AddArg(base)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
// match: (CMPWload {sym} [off] ptr (MOVLconst [c]) mem)
// cond: validValAndOff(int64(int16(c)),off)
// result: (CMPWconstload {sym} [makeValAndOff(int64(int16(c)),off)] ptr mem)
@@ -15448,8 +16866,140 @@ func rewriteValueAMD64_OpAMD64MOVLstore_20(v *Value) bool {
v.AddArg(mem)
return true
}
+ // match: (MOVLstore {sym} [off] ptr y:(BTCL l:(MOVLload [off] {sym} ptr mem) x) mem)
+ // cond: y.Uses==1 && l.Uses==1 && clobber(y) && clobber(l)
+ // result: (BTCLmodify [off] {sym} ptr x mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[2]
+ ptr := v.Args[0]
+ y := v.Args[1]
+ if y.Op != OpAMD64BTCL {
+ break
+ }
+ _ = y.Args[1]
+ l := y.Args[0]
+ if l.Op != OpAMD64MOVLload {
+ break
+ }
+ if l.AuxInt != off {
+ break
+ }
+ if l.Aux != sym {
+ break
+ }
+ _ = l.Args[1]
+ if ptr != l.Args[0] {
+ break
+ }
+ mem := l.Args[1]
+ x := y.Args[1]
+ if mem != v.Args[2] {
+ break
+ }
+ if !(y.Uses == 1 && l.Uses == 1 && clobber(y) && clobber(l)) {
+ break
+ }
+ v.reset(OpAMD64BTCLmodify)
+ v.AuxInt = off
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(x)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (MOVLstore {sym} [off] ptr y:(BTRL l:(MOVLload [off] {sym} ptr mem) x) mem)
+ // cond: y.Uses==1 && l.Uses==1 && clobber(y) && clobber(l)
+ // result: (BTRLmodify [off] {sym} ptr x mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[2]
+ ptr := v.Args[0]
+ y := v.Args[1]
+ if y.Op != OpAMD64BTRL {
+ break
+ }
+ _ = y.Args[1]
+ l := y.Args[0]
+ if l.Op != OpAMD64MOVLload {
+ break
+ }
+ if l.AuxInt != off {
+ break
+ }
+ if l.Aux != sym {
+ break
+ }
+ _ = l.Args[1]
+ if ptr != l.Args[0] {
+ break
+ }
+ mem := l.Args[1]
+ x := y.Args[1]
+ if mem != v.Args[2] {
+ break
+ }
+ if !(y.Uses == 1 && l.Uses == 1 && clobber(y) && clobber(l)) {
+ break
+ }
+ v.reset(OpAMD64BTRLmodify)
+ v.AuxInt = off
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(x)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (MOVLstore {sym} [off] ptr y:(BTSL l:(MOVLload [off] {sym} ptr mem) x) mem)
+ // cond: y.Uses==1 && l.Uses==1 && clobber(y) && clobber(l)
+ // result: (BTSLmodify [off] {sym} ptr x mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[2]
+ ptr := v.Args[0]
+ y := v.Args[1]
+ if y.Op != OpAMD64BTSL {
+ break
+ }
+ _ = y.Args[1]
+ l := y.Args[0]
+ if l.Op != OpAMD64MOVLload {
+ break
+ }
+ if l.AuxInt != off {
+ break
+ }
+ if l.Aux != sym {
+ break
+ }
+ _ = l.Args[1]
+ if ptr != l.Args[0] {
+ break
+ }
+ mem := l.Args[1]
+ x := y.Args[1]
+ if mem != v.Args[2] {
+ break
+ }
+ if !(y.Uses == 1 && l.Uses == 1 && clobber(y) && clobber(l)) {
+ break
+ }
+ v.reset(OpAMD64BTSLmodify)
+ v.AuxInt = off
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(x)
+ v.AddArg(mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MOVLstore_30(v *Value) bool {
// match: (MOVLstore [off] {sym} ptr a:(ADDLconst [c] l:(MOVLload [off] {sym} ptr2 mem)) mem)
- // cond: isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c,off)
+ // cond: isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c,off) && clobber(l) && clobber(a)
// result: (ADDLconstmodify {sym} [makeValAndOff(c,off)] ptr mem)
for {
off := v.AuxInt
@@ -15477,7 +17027,7 @@ func rewriteValueAMD64_OpAMD64MOVLstore_20(v *Value) bool {
if mem != v.Args[2] {
break
}
- if !(isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c, off)) {
+ if !(isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c, off) && clobber(l) && clobber(a)) {
break
}
v.reset(OpAMD64ADDLconstmodify)
@@ -15488,7 +17038,7 @@ func rewriteValueAMD64_OpAMD64MOVLstore_20(v *Value) bool {
return true
}
// match: (MOVLstore [off] {sym} ptr a:(ANDLconst [c] l:(MOVLload [off] {sym} ptr2 mem)) mem)
- // cond: isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c,off)
+ // cond: isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c,off) && clobber(l) && clobber(a)
// result: (ANDLconstmodify {sym} [makeValAndOff(c,off)] ptr mem)
for {
off := v.AuxInt
@@ -15516,7 +17066,7 @@ func rewriteValueAMD64_OpAMD64MOVLstore_20(v *Value) bool {
if mem != v.Args[2] {
break
}
- if !(isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c, off)) {
+ if !(isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c, off) && clobber(l) && clobber(a)) {
break
}
v.reset(OpAMD64ANDLconstmodify)
@@ -15527,7 +17077,7 @@ func rewriteValueAMD64_OpAMD64MOVLstore_20(v *Value) bool {
return true
}
// match: (MOVLstore [off] {sym} ptr a:(ORLconst [c] l:(MOVLload [off] {sym} ptr2 mem)) mem)
- // cond: isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c,off)
+ // cond: isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c,off) && clobber(l) && clobber(a)
// result: (ORLconstmodify {sym} [makeValAndOff(c,off)] ptr mem)
for {
off := v.AuxInt
@@ -15555,7 +17105,7 @@ func rewriteValueAMD64_OpAMD64MOVLstore_20(v *Value) bool {
if mem != v.Args[2] {
break
}
- if !(isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c, off)) {
+ if !(isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c, off) && clobber(l) && clobber(a)) {
break
}
v.reset(OpAMD64ORLconstmodify)
@@ -15565,11 +17115,8 @@ func rewriteValueAMD64_OpAMD64MOVLstore_20(v *Value) bool {
v.AddArg(mem)
return true
}
- return false
-}
-func rewriteValueAMD64_OpAMD64MOVLstore_30(v *Value) bool {
// match: (MOVLstore [off] {sym} ptr a:(XORLconst [c] l:(MOVLload [off] {sym} ptr2 mem)) mem)
- // cond: isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c,off)
+ // cond: isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c,off) && clobber(l) && clobber(a)
// result: (XORLconstmodify {sym} [makeValAndOff(c,off)] ptr mem)
for {
off := v.AuxInt
@@ -15597,7 +17144,7 @@ func rewriteValueAMD64_OpAMD64MOVLstore_30(v *Value) bool {
if mem != v.Args[2] {
break
}
- if !(isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c, off)) {
+ if !(isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c, off) && clobber(l) && clobber(a)) {
break
}
v.reset(OpAMD64XORLconstmodify)
@@ -15607,6 +17154,123 @@ func rewriteValueAMD64_OpAMD64MOVLstore_30(v *Value) bool {
v.AddArg(mem)
return true
}
+ // match: (MOVLstore [off] {sym} ptr a:(BTCLconst [c] l:(MOVLload [off] {sym} ptr2 mem)) mem)
+ // cond: isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c,off) && clobber(l) && clobber(a)
+ // result: (BTCLconstmodify {sym} [makeValAndOff(c,off)] ptr mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[2]
+ ptr := v.Args[0]
+ a := v.Args[1]
+ if a.Op != OpAMD64BTCLconst {
+ break
+ }
+ c := a.AuxInt
+ l := a.Args[0]
+ if l.Op != OpAMD64MOVLload {
+ break
+ }
+ if l.AuxInt != off {
+ break
+ }
+ if l.Aux != sym {
+ break
+ }
+ _ = l.Args[1]
+ ptr2 := l.Args[0]
+ mem := l.Args[1]
+ if mem != v.Args[2] {
+ break
+ }
+ if !(isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c, off) && clobber(l) && clobber(a)) {
+ break
+ }
+ v.reset(OpAMD64BTCLconstmodify)
+ v.AuxInt = makeValAndOff(c, off)
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (MOVLstore [off] {sym} ptr a:(BTRLconst [c] l:(MOVLload [off] {sym} ptr2 mem)) mem)
+ // cond: isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c,off) && clobber(l) && clobber(a)
+ // result: (BTRLconstmodify {sym} [makeValAndOff(c,off)] ptr mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[2]
+ ptr := v.Args[0]
+ a := v.Args[1]
+ if a.Op != OpAMD64BTRLconst {
+ break
+ }
+ c := a.AuxInt
+ l := a.Args[0]
+ if l.Op != OpAMD64MOVLload {
+ break
+ }
+ if l.AuxInt != off {
+ break
+ }
+ if l.Aux != sym {
+ break
+ }
+ _ = l.Args[1]
+ ptr2 := l.Args[0]
+ mem := l.Args[1]
+ if mem != v.Args[2] {
+ break
+ }
+ if !(isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c, off) && clobber(l) && clobber(a)) {
+ break
+ }
+ v.reset(OpAMD64BTRLconstmodify)
+ v.AuxInt = makeValAndOff(c, off)
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (MOVLstore [off] {sym} ptr a:(BTSLconst [c] l:(MOVLload [off] {sym} ptr2 mem)) mem)
+ // cond: isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c,off) && clobber(l) && clobber(a)
+ // result: (BTSLconstmodify {sym} [makeValAndOff(c,off)] ptr mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[2]
+ ptr := v.Args[0]
+ a := v.Args[1]
+ if a.Op != OpAMD64BTSLconst {
+ break
+ }
+ c := a.AuxInt
+ l := a.Args[0]
+ if l.Op != OpAMD64MOVLload {
+ break
+ }
+ if l.AuxInt != off {
+ break
+ }
+ if l.Aux != sym {
+ break
+ }
+ _ = l.Args[1]
+ ptr2 := l.Args[0]
+ mem := l.Args[1]
+ if mem != v.Args[2] {
+ break
+ }
+ if !(isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c, off) && clobber(l) && clobber(a)) {
+ break
+ }
+ v.reset(OpAMD64BTSLconstmodify)
+ v.AuxInt = makeValAndOff(c, off)
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(mem)
+ return true
+ }
// match: (MOVLstore [off] {sym} ptr (MOVLf2i val) mem)
// cond:
// result: (MOVSSstore [off] {sym} ptr val mem)
@@ -18099,8 +19763,137 @@ func rewriteValueAMD64_OpAMD64MOVQstore_20(v *Value) bool {
v.AddArg(mem)
return true
}
+ // match: (MOVQstore {sym} [off] ptr y:(BTCQ l:(MOVQload [off] {sym} ptr mem) x) mem)
+ // cond: y.Uses==1 && l.Uses==1 && clobber(y) && clobber(l)
+ // result: (BTCQmodify [off] {sym} ptr x mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[2]
+ ptr := v.Args[0]
+ y := v.Args[1]
+ if y.Op != OpAMD64BTCQ {
+ break
+ }
+ _ = y.Args[1]
+ l := y.Args[0]
+ if l.Op != OpAMD64MOVQload {
+ break
+ }
+ if l.AuxInt != off {
+ break
+ }
+ if l.Aux != sym {
+ break
+ }
+ _ = l.Args[1]
+ if ptr != l.Args[0] {
+ break
+ }
+ mem := l.Args[1]
+ x := y.Args[1]
+ if mem != v.Args[2] {
+ break
+ }
+ if !(y.Uses == 1 && l.Uses == 1 && clobber(y) && clobber(l)) {
+ break
+ }
+ v.reset(OpAMD64BTCQmodify)
+ v.AuxInt = off
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(x)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (MOVQstore {sym} [off] ptr y:(BTRQ l:(MOVQload [off] {sym} ptr mem) x) mem)
+ // cond: y.Uses==1 && l.Uses==1 && clobber(y) && clobber(l)
+ // result: (BTRQmodify [off] {sym} ptr x mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[2]
+ ptr := v.Args[0]
+ y := v.Args[1]
+ if y.Op != OpAMD64BTRQ {
+ break
+ }
+ _ = y.Args[1]
+ l := y.Args[0]
+ if l.Op != OpAMD64MOVQload {
+ break
+ }
+ if l.AuxInt != off {
+ break
+ }
+ if l.Aux != sym {
+ break
+ }
+ _ = l.Args[1]
+ if ptr != l.Args[0] {
+ break
+ }
+ mem := l.Args[1]
+ x := y.Args[1]
+ if mem != v.Args[2] {
+ break
+ }
+ if !(y.Uses == 1 && l.Uses == 1 && clobber(y) && clobber(l)) {
+ break
+ }
+ v.reset(OpAMD64BTRQmodify)
+ v.AuxInt = off
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(x)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (MOVQstore {sym} [off] ptr y:(BTSQ l:(MOVQload [off] {sym} ptr mem) x) mem)
+ // cond: y.Uses==1 && l.Uses==1 && clobber(y) && clobber(l)
+ // result: (BTSQmodify [off] {sym} ptr x mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[2]
+ ptr := v.Args[0]
+ y := v.Args[1]
+ if y.Op != OpAMD64BTSQ {
+ break
+ }
+ _ = y.Args[1]
+ l := y.Args[0]
+ if l.Op != OpAMD64MOVQload {
+ break
+ }
+ if l.AuxInt != off {
+ break
+ }
+ if l.Aux != sym {
+ break
+ }
+ _ = l.Args[1]
+ if ptr != l.Args[0] {
+ break
+ }
+ mem := l.Args[1]
+ x := y.Args[1]
+ if mem != v.Args[2] {
+ break
+ }
+ if !(y.Uses == 1 && l.Uses == 1 && clobber(y) && clobber(l)) {
+ break
+ }
+ v.reset(OpAMD64BTSQmodify)
+ v.AuxInt = off
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(x)
+ v.AddArg(mem)
+ return true
+ }
// match: (MOVQstore [off] {sym} ptr a:(ADDQconst [c] l:(MOVQload [off] {sym} ptr2 mem)) mem)
- // cond: isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c,off)
+ // cond: isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c,off) && clobber(l) && clobber(a)
// result: (ADDQconstmodify {sym} [makeValAndOff(c,off)] ptr mem)
for {
off := v.AuxInt
@@ -18128,7 +19921,7 @@ func rewriteValueAMD64_OpAMD64MOVQstore_20(v *Value) bool {
if mem != v.Args[2] {
break
}
- if !(isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c, off)) {
+ if !(isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c, off) && clobber(l) && clobber(a)) {
break
}
v.reset(OpAMD64ADDQconstmodify)
@@ -18139,7 +19932,7 @@ func rewriteValueAMD64_OpAMD64MOVQstore_20(v *Value) bool {
return true
}
// match: (MOVQstore [off] {sym} ptr a:(ANDQconst [c] l:(MOVQload [off] {sym} ptr2 mem)) mem)
- // cond: isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c,off)
+ // cond: isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c,off) && clobber(l) && clobber(a)
// result: (ANDQconstmodify {sym} [makeValAndOff(c,off)] ptr mem)
for {
off := v.AuxInt
@@ -18167,7 +19960,7 @@ func rewriteValueAMD64_OpAMD64MOVQstore_20(v *Value) bool {
if mem != v.Args[2] {
break
}
- if !(isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c, off)) {
+ if !(isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c, off) && clobber(l) && clobber(a)) {
break
}
v.reset(OpAMD64ANDQconstmodify)
@@ -18178,7 +19971,7 @@ func rewriteValueAMD64_OpAMD64MOVQstore_20(v *Value) bool {
return true
}
// match: (MOVQstore [off] {sym} ptr a:(ORQconst [c] l:(MOVQload [off] {sym} ptr2 mem)) mem)
- // cond: isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c,off)
+ // cond: isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c,off) && clobber(l) && clobber(a)
// result: (ORQconstmodify {sym} [makeValAndOff(c,off)] ptr mem)
for {
off := v.AuxInt
@@ -18206,7 +19999,7 @@ func rewriteValueAMD64_OpAMD64MOVQstore_20(v *Value) bool {
if mem != v.Args[2] {
break
}
- if !(isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c, off)) {
+ if !(isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c, off) && clobber(l) && clobber(a)) {
break
}
v.reset(OpAMD64ORQconstmodify)
@@ -18217,7 +20010,7 @@ func rewriteValueAMD64_OpAMD64MOVQstore_20(v *Value) bool {
return true
}
// match: (MOVQstore [off] {sym} ptr a:(XORQconst [c] l:(MOVQload [off] {sym} ptr2 mem)) mem)
- // cond: isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c,off)
+ // cond: isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c,off) && clobber(l) && clobber(a)
// result: (XORQconstmodify {sym} [makeValAndOff(c,off)] ptr mem)
for {
off := v.AuxInt
@@ -18245,7 +20038,7 @@ func rewriteValueAMD64_OpAMD64MOVQstore_20(v *Value) bool {
if mem != v.Args[2] {
break
}
- if !(isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c, off)) {
+ if !(isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c, off) && clobber(l) && clobber(a)) {
break
}
v.reset(OpAMD64XORQconstmodify)
@@ -18255,6 +20048,126 @@ func rewriteValueAMD64_OpAMD64MOVQstore_20(v *Value) bool {
v.AddArg(mem)
return true
}
+ // match: (MOVQstore [off] {sym} ptr a:(BTCQconst [c] l:(MOVQload [off] {sym} ptr2 mem)) mem)
+ // cond: isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c,off) && clobber(l) && clobber(a)
+ // result: (BTCQconstmodify {sym} [makeValAndOff(c,off)] ptr mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[2]
+ ptr := v.Args[0]
+ a := v.Args[1]
+ if a.Op != OpAMD64BTCQconst {
+ break
+ }
+ c := a.AuxInt
+ l := a.Args[0]
+ if l.Op != OpAMD64MOVQload {
+ break
+ }
+ if l.AuxInt != off {
+ break
+ }
+ if l.Aux != sym {
+ break
+ }
+ _ = l.Args[1]
+ ptr2 := l.Args[0]
+ mem := l.Args[1]
+ if mem != v.Args[2] {
+ break
+ }
+ if !(isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c, off) && clobber(l) && clobber(a)) {
+ break
+ }
+ v.reset(OpAMD64BTCQconstmodify)
+ v.AuxInt = makeValAndOff(c, off)
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (MOVQstore [off] {sym} ptr a:(BTRQconst [c] l:(MOVQload [off] {sym} ptr2 mem)) mem)
+ // cond: isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c,off) && clobber(l) && clobber(a)
+ // result: (BTRQconstmodify {sym} [makeValAndOff(c,off)] ptr mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[2]
+ ptr := v.Args[0]
+ a := v.Args[1]
+ if a.Op != OpAMD64BTRQconst {
+ break
+ }
+ c := a.AuxInt
+ l := a.Args[0]
+ if l.Op != OpAMD64MOVQload {
+ break
+ }
+ if l.AuxInt != off {
+ break
+ }
+ if l.Aux != sym {
+ break
+ }
+ _ = l.Args[1]
+ ptr2 := l.Args[0]
+ mem := l.Args[1]
+ if mem != v.Args[2] {
+ break
+ }
+ if !(isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c, off) && clobber(l) && clobber(a)) {
+ break
+ }
+ v.reset(OpAMD64BTRQconstmodify)
+ v.AuxInt = makeValAndOff(c, off)
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(mem)
+ return true
+ }
+ return false
+}
+func rewriteValueAMD64_OpAMD64MOVQstore_30(v *Value) bool {
+ // match: (MOVQstore [off] {sym} ptr a:(BTSQconst [c] l:(MOVQload [off] {sym} ptr2 mem)) mem)
+ // cond: isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c,off) && clobber(l) && clobber(a)
+ // result: (BTSQconstmodify {sym} [makeValAndOff(c,off)] ptr mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[2]
+ ptr := v.Args[0]
+ a := v.Args[1]
+ if a.Op != OpAMD64BTSQconst {
+ break
+ }
+ c := a.AuxInt
+ l := a.Args[0]
+ if l.Op != OpAMD64MOVQload {
+ break
+ }
+ if l.AuxInt != off {
+ break
+ }
+ if l.Aux != sym {
+ break
+ }
+ _ = l.Args[1]
+ ptr2 := l.Args[0]
+ mem := l.Args[1]
+ if mem != v.Args[2] {
+ break
+ }
+ if !(isSamePtr(ptr, ptr2) && a.Uses == 1 && l.Uses == 1 && validValAndOff(c, off) && clobber(l) && clobber(a)) {
+ break
+ }
+ v.reset(OpAMD64BTSQconstmodify)
+ v.AuxInt = makeValAndOff(c, off)
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(mem)
+ return true
+ }
// match: (MOVQstore [off] {sym} ptr (MOVQf2i val) mem)
// cond:
// result: (MOVSDstore [off] {sym} ptr val mem)
@@ -32713,6 +34626,38 @@ func rewriteValueAMD64_OpAMD64ORLconst_0(v *Value) bool {
v.AddArg(x)
return true
}
+ // match: (ORLconst [c] (ORLconst [d] x))
+ // cond:
+ // result: (ORLconst [c | d] x)
+ for {
+ c := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64ORLconst {
+ break
+ }
+ d := v_0.AuxInt
+ x := v_0.Args[0]
+ v.reset(OpAMD64ORLconst)
+ v.AuxInt = c | d
+ v.AddArg(x)
+ return true
+ }
+ // match: (ORLconst [c] (BTSLconst [d] x))
+ // cond:
+ // result: (ORLconst [c | 1<<uint32(d)] x)
+ for {
+ c := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64BTSLconst {
+ break
+ }
+ d := v_0.AuxInt
+ x := v_0.Args[0]
+ v.reset(OpAMD64ORLconst)
+ v.AuxInt = c | 1<<uint32(d)
+ v.AddArg(x)
+ return true
+ }
// match: (ORLconst [c] x)
// cond: int32(c)==0
// result: x
@@ -43732,6 +45677,38 @@ func rewriteValueAMD64_OpAMD64ORQconst_0(v *Value) bool {
v.AddArg(x)
return true
}
+ // match: (ORQconst [c] (ORQconst [d] x))
+ // cond:
+ // result: (ORQconst [c | d] x)
+ for {
+ c := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64ORQconst {
+ break
+ }
+ d := v_0.AuxInt
+ x := v_0.Args[0]
+ v.reset(OpAMD64ORQconst)
+ v.AuxInt = c | d
+ v.AddArg(x)
+ return true
+ }
+ // match: (ORQconst [c] (BTSQconst [d] x))
+ // cond:
+ // result: (ORQconst [c | 1<<uint32(d)] x)
+ for {
+ c := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64BTSQconst {
+ break
+ }
+ d := v_0.AuxInt
+ x := v_0.Args[0]
+ v.reset(OpAMD64ORQconst)
+ v.AuxInt = c | 1<<uint32(d)
+ v.AddArg(x)
+ return true
+ }
// match: (ORQconst [0] x)
// cond:
// result: x
@@ -54458,6 +56435,22 @@ func rewriteValueAMD64_OpAMD64XORLconst_10(v *Value) bool {
v.AddArg(x)
return true
}
+ // match: (XORLconst [c] (BTCLconst [d] x))
+ // cond:
+ // result: (XORLconst [c ^ 1<<uint32(d)] x)
+ for {
+ c := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64BTCLconst {
+ break
+ }
+ d := v_0.AuxInt
+ x := v_0.Args[0]
+ v.reset(OpAMD64XORLconst)
+ v.AuxInt = c ^ 1<<uint32(d)
+ v.AddArg(x)
+ return true
+ }
// match: (XORLconst [c] x)
// cond: int32(c)==0
// result: x
@@ -54981,6 +56974,22 @@ func rewriteValueAMD64_OpAMD64XORQconst_0(v *Value) bool {
v.AddArg(x)
return true
}
+ // match: (XORQconst [c] (BTCQconst [d] x))
+ // cond:
+ // result: (XORQconst [c ^ 1<<uint32(d)] x)
+ for {
+ c := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpAMD64BTCQconst {
+ break
+ }
+ d := v_0.AuxInt
+ x := v_0.Args[0]
+ v.reset(OpAMD64XORQconst)
+ v.AuxInt = c ^ 1<<uint32(d)
+ v.AddArg(x)
+ return true
+ }
// match: (XORQconst [0] x)
// cond:
// result: x
@@ -60410,13 +62419,13 @@ func rewriteValueAMD64_OpNeg32F_0(v *Value) bool {
_ = typ
// match: (Neg32F x)
// cond:
- // result: (PXOR x (MOVSSconst <typ.Float32> [f2i(math.Copysign(0, -1))]))
+ // result: (PXOR x (MOVSSconst <typ.Float32> [auxFrom32F(float32(math.Copysign(0, -1)))]))
for {
x := v.Args[0]
v.reset(OpAMD64PXOR)
v.AddArg(x)
v0 := b.NewValue0(v.Pos, OpAMD64MOVSSconst, typ.Float32)
- v0.AuxInt = f2i(math.Copysign(0, -1))
+ v0.AuxInt = auxFrom32F(float32(math.Copysign(0, -1)))
v.AddArg(v0)
return true
}
@@ -60439,13 +62448,13 @@ func rewriteValueAMD64_OpNeg64F_0(v *Value) bool {
_ = typ
// match: (Neg64F x)
// cond:
- // result: (PXOR x (MOVSDconst <typ.Float64> [f2i(math.Copysign(0, -1))]))
+ // result: (PXOR x (MOVSDconst <typ.Float64> [auxFrom64F(math.Copysign(0, -1))]))
for {
x := v.Args[0]
v.reset(OpAMD64PXOR)
v.AddArg(x)
v0 := b.NewValue0(v.Pos, OpAMD64MOVSDconst, typ.Float64)
- v0.AuxInt = f2i(math.Copysign(0, -1))
+ v0.AuxInt = auxFrom64F(math.Copysign(0, -1))
v.AddArg(v0)
return true
}
diff --git a/src/cmd/compile/internal/ssa/rewriteARM64.go b/src/cmd/compile/internal/ssa/rewriteARM64.go
index fbdf352998..ba38ae0505 100644
--- a/src/cmd/compile/internal/ssa/rewriteARM64.go
+++ b/src/cmd/compile/internal/ssa/rewriteARM64.go
@@ -16,7 +16,7 @@ var _ = types.TypeMem // in case not otherwise used
func rewriteValueARM64(v *Value) bool {
switch v.Op {
case OpARM64ADD:
- return rewriteValueARM64_OpARM64ADD_0(v) || rewriteValueARM64_OpARM64ADD_10(v)
+ return rewriteValueARM64_OpARM64ADD_0(v) || rewriteValueARM64_OpARM64ADD_10(v) || rewriteValueARM64_OpARM64ADD_20(v)
case OpARM64ADDconst:
return rewriteValueARM64_OpARM64ADDconst_0(v)
case OpARM64ADDshiftLL:
@@ -51,6 +51,12 @@ func rewriteValueARM64(v *Value) bool {
return rewriteValueARM64_OpARM64CMNWconst_0(v)
case OpARM64CMNconst:
return rewriteValueARM64_OpARM64CMNconst_0(v)
+ case OpARM64CMNshiftLL:
+ return rewriteValueARM64_OpARM64CMNshiftLL_0(v)
+ case OpARM64CMNshiftRA:
+ return rewriteValueARM64_OpARM64CMNshiftRA_0(v)
+ case OpARM64CMNshiftRL:
+ return rewriteValueARM64_OpARM64CMNshiftRL_0(v)
case OpARM64CMP:
return rewriteValueARM64_OpARM64CMP_0(v)
case OpARM64CMPW:
@@ -87,6 +93,8 @@ func rewriteValueARM64(v *Value) bool {
return rewriteValueARM64_OpARM64FADDD_0(v)
case OpARM64FADDS:
return rewriteValueARM64_OpARM64FADDS_0(v)
+ case OpARM64FMOVDfpgp:
+ return rewriteValueARM64_OpARM64FMOVDfpgp_0(v)
case OpARM64FMOVDgpfp:
return rewriteValueARM64_OpARM64FMOVDgpfp_0(v)
case OpARM64FMOVDload:
@@ -137,6 +145,10 @@ func rewriteValueARM64(v *Value) bool {
return rewriteValueARM64_OpARM64LessThan_0(v)
case OpARM64LessThanU:
return rewriteValueARM64_OpARM64LessThanU_0(v)
+ case OpARM64MADD:
+ return rewriteValueARM64_OpARM64MADD_0(v) || rewriteValueARM64_OpARM64MADD_10(v) || rewriteValueARM64_OpARM64MADD_20(v)
+ case OpARM64MADDW:
+ return rewriteValueARM64_OpARM64MADDW_0(v) || rewriteValueARM64_OpARM64MADDW_10(v) || rewriteValueARM64_OpARM64MADDW_20(v)
case OpARM64MNEG:
return rewriteValueARM64_OpARM64MNEG_0(v) || rewriteValueARM64_OpARM64MNEG_10(v) || rewriteValueARM64_OpARM64MNEG_20(v)
case OpARM64MNEGW:
@@ -243,18 +255,34 @@ func rewriteValueARM64(v *Value) bool {
return rewriteValueARM64_OpARM64MOVWstorezeroidx_0(v)
case OpARM64MOVWstorezeroidx4:
return rewriteValueARM64_OpARM64MOVWstorezeroidx4_0(v)
+ case OpARM64MSUB:
+ return rewriteValueARM64_OpARM64MSUB_0(v) || rewriteValueARM64_OpARM64MSUB_10(v) || rewriteValueARM64_OpARM64MSUB_20(v)
+ case OpARM64MSUBW:
+ return rewriteValueARM64_OpARM64MSUBW_0(v) || rewriteValueARM64_OpARM64MSUBW_10(v) || rewriteValueARM64_OpARM64MSUBW_20(v)
case OpARM64MUL:
return rewriteValueARM64_OpARM64MUL_0(v) || rewriteValueARM64_OpARM64MUL_10(v) || rewriteValueARM64_OpARM64MUL_20(v)
case OpARM64MULW:
return rewriteValueARM64_OpARM64MULW_0(v) || rewriteValueARM64_OpARM64MULW_10(v) || rewriteValueARM64_OpARM64MULW_20(v)
case OpARM64MVN:
return rewriteValueARM64_OpARM64MVN_0(v)
+ case OpARM64MVNshiftLL:
+ return rewriteValueARM64_OpARM64MVNshiftLL_0(v)
+ case OpARM64MVNshiftRA:
+ return rewriteValueARM64_OpARM64MVNshiftRA_0(v)
+ case OpARM64MVNshiftRL:
+ return rewriteValueARM64_OpARM64MVNshiftRL_0(v)
case OpARM64NEG:
return rewriteValueARM64_OpARM64NEG_0(v)
+ case OpARM64NEGshiftLL:
+ return rewriteValueARM64_OpARM64NEGshiftLL_0(v)
+ case OpARM64NEGshiftRA:
+ return rewriteValueARM64_OpARM64NEGshiftRA_0(v)
+ case OpARM64NEGshiftRL:
+ return rewriteValueARM64_OpARM64NEGshiftRL_0(v)
case OpARM64NotEqual:
return rewriteValueARM64_OpARM64NotEqual_0(v)
case OpARM64OR:
- return rewriteValueARM64_OpARM64OR_0(v) || rewriteValueARM64_OpARM64OR_10(v) || rewriteValueARM64_OpARM64OR_20(v) || rewriteValueARM64_OpARM64OR_30(v)
+ return rewriteValueARM64_OpARM64OR_0(v) || rewriteValueARM64_OpARM64OR_10(v) || rewriteValueARM64_OpARM64OR_20(v) || rewriteValueARM64_OpARM64OR_30(v) || rewriteValueARM64_OpARM64OR_40(v)
case OpARM64ORN:
return rewriteValueARM64_OpARM64ORN_0(v)
case OpARM64ORNshiftLL:
@@ -271,6 +299,10 @@ func rewriteValueARM64(v *Value) bool {
return rewriteValueARM64_OpARM64ORshiftRA_0(v)
case OpARM64ORshiftRL:
return rewriteValueARM64_OpARM64ORshiftRL_0(v)
+ case OpARM64RORWconst:
+ return rewriteValueARM64_OpARM64RORWconst_0(v)
+ case OpARM64RORconst:
+ return rewriteValueARM64_OpARM64RORconst_0(v)
case OpARM64SLL:
return rewriteValueARM64_OpARM64SLL_0(v)
case OpARM64SLLconst:
@@ -303,6 +335,12 @@ func rewriteValueARM64(v *Value) bool {
return rewriteValueARM64_OpARM64TSTWconst_0(v)
case OpARM64TSTconst:
return rewriteValueARM64_OpARM64TSTconst_0(v)
+ case OpARM64TSTshiftLL:
+ return rewriteValueARM64_OpARM64TSTshiftLL_0(v)
+ case OpARM64TSTshiftRA:
+ return rewriteValueARM64_OpARM64TSTshiftRA_0(v)
+ case OpARM64TSTshiftRL:
+ return rewriteValueARM64_OpARM64TSTshiftRL_0(v)
case OpARM64UBFIZ:
return rewriteValueARM64_OpARM64UBFIZ_0(v)
case OpARM64UBFX:
@@ -325,6 +363,8 @@ func rewriteValueARM64(v *Value) bool {
return rewriteValueARM64_OpARM64XORshiftRA_0(v)
case OpARM64XORshiftRL:
return rewriteValueARM64_OpARM64XORshiftRL_0(v)
+ case OpAbs:
+ return rewriteValueARM64_OpAbs_0(v)
case OpAdd16:
return rewriteValueARM64_OpAdd16_0(v)
case OpAdd32:
@@ -731,12 +771,18 @@ func rewriteValueARM64(v *Value) bool {
return rewriteValueARM64_OpPopCount32_0(v)
case OpPopCount64:
return rewriteValueARM64_OpPopCount64_0(v)
+ case OpRotateLeft32:
+ return rewriteValueARM64_OpRotateLeft32_0(v)
+ case OpRotateLeft64:
+ return rewriteValueARM64_OpRotateLeft64_0(v)
case OpRound:
return rewriteValueARM64_OpRound_0(v)
case OpRound32F:
return rewriteValueARM64_OpRound32F_0(v)
case OpRound64F:
return rewriteValueARM64_OpRound64F_0(v)
+ case OpRoundToEven:
+ return rewriteValueARM64_OpRoundToEven_0(v)
case OpRsh16Ux16:
return rewriteValueARM64_OpRsh16Ux16_0(v)
case OpRsh16Ux32:
@@ -910,7 +956,7 @@ func rewriteValueARM64_OpARM64ADD_0(v *Value) bool {
return true
}
// match: (ADD a l:(MUL x y))
- // cond: l.Uses==1 && x.Op!=OpARM64MOVDconst && y.Op!=OpARM64MOVDconst && a.Op!=OpARM64MOVDconst && clobber(l)
+ // cond: l.Uses==1 && clobber(l)
// result: (MADD a x y)
for {
_ = v.Args[1]
@@ -922,7 +968,7 @@ func rewriteValueARM64_OpARM64ADD_0(v *Value) bool {
_ = l.Args[1]
x := l.Args[0]
y := l.Args[1]
- if !(l.Uses == 1 && x.Op != OpARM64MOVDconst && y.Op != OpARM64MOVDconst && a.Op != OpARM64MOVDconst && clobber(l)) {
+ if !(l.Uses == 1 && clobber(l)) {
break
}
v.reset(OpARM64MADD)
@@ -932,7 +978,7 @@ func rewriteValueARM64_OpARM64ADD_0(v *Value) bool {
return true
}
// match: (ADD l:(MUL x y) a)
- // cond: l.Uses==1 && x.Op!=OpARM64MOVDconst && y.Op!=OpARM64MOVDconst && a.Op!=OpARM64MOVDconst && clobber(l)
+ // cond: l.Uses==1 && clobber(l)
// result: (MADD a x y)
for {
_ = v.Args[1]
@@ -944,7 +990,7 @@ func rewriteValueARM64_OpARM64ADD_0(v *Value) bool {
x := l.Args[0]
y := l.Args[1]
a := v.Args[1]
- if !(l.Uses == 1 && x.Op != OpARM64MOVDconst && y.Op != OpARM64MOVDconst && a.Op != OpARM64MOVDconst && clobber(l)) {
+ if !(l.Uses == 1 && clobber(l)) {
break
}
v.reset(OpARM64MADD)
@@ -954,7 +1000,7 @@ func rewriteValueARM64_OpARM64ADD_0(v *Value) bool {
return true
}
// match: (ADD a l:(MNEG x y))
- // cond: l.Uses==1 && x.Op!=OpARM64MOVDconst && y.Op!=OpARM64MOVDconst && a.Op!=OpARM64MOVDconst && clobber(l)
+ // cond: l.Uses==1 && clobber(l)
// result: (MSUB a x y)
for {
_ = v.Args[1]
@@ -966,7 +1012,7 @@ func rewriteValueARM64_OpARM64ADD_0(v *Value) bool {
_ = l.Args[1]
x := l.Args[0]
y := l.Args[1]
- if !(l.Uses == 1 && x.Op != OpARM64MOVDconst && y.Op != OpARM64MOVDconst && a.Op != OpARM64MOVDconst && clobber(l)) {
+ if !(l.Uses == 1 && clobber(l)) {
break
}
v.reset(OpARM64MSUB)
@@ -976,7 +1022,7 @@ func rewriteValueARM64_OpARM64ADD_0(v *Value) bool {
return true
}
// match: (ADD l:(MNEG x y) a)
- // cond: l.Uses==1 && x.Op!=OpARM64MOVDconst && y.Op!=OpARM64MOVDconst && a.Op!=OpARM64MOVDconst && clobber(l)
+ // cond: l.Uses==1 && clobber(l)
// result: (MSUB a x y)
for {
_ = v.Args[1]
@@ -988,7 +1034,7 @@ func rewriteValueARM64_OpARM64ADD_0(v *Value) bool {
x := l.Args[0]
y := l.Args[1]
a := v.Args[1]
- if !(l.Uses == 1 && x.Op != OpARM64MOVDconst && y.Op != OpARM64MOVDconst && a.Op != OpARM64MOVDconst && clobber(l)) {
+ if !(l.Uses == 1 && clobber(l)) {
break
}
v.reset(OpARM64MSUB)
@@ -998,7 +1044,7 @@ func rewriteValueARM64_OpARM64ADD_0(v *Value) bool {
return true
}
// match: (ADD a l:(MULW x y))
- // cond: l.Uses==1 && a.Type.Size() != 8 && x.Op!=OpARM64MOVDconst && y.Op!=OpARM64MOVDconst && a.Op!=OpARM64MOVDconst && clobber(l)
+ // cond: a.Type.Size() != 8 && l.Uses==1 && clobber(l)
// result: (MADDW a x y)
for {
_ = v.Args[1]
@@ -1010,7 +1056,7 @@ func rewriteValueARM64_OpARM64ADD_0(v *Value) bool {
_ = l.Args[1]
x := l.Args[0]
y := l.Args[1]
- if !(l.Uses == 1 && a.Type.Size() != 8 && x.Op != OpARM64MOVDconst && y.Op != OpARM64MOVDconst && a.Op != OpARM64MOVDconst && clobber(l)) {
+ if !(a.Type.Size() != 8 && l.Uses == 1 && clobber(l)) {
break
}
v.reset(OpARM64MADDW)
@@ -1020,7 +1066,7 @@ func rewriteValueARM64_OpARM64ADD_0(v *Value) bool {
return true
}
// match: (ADD l:(MULW x y) a)
- // cond: l.Uses==1 && a.Type.Size() != 8 && x.Op!=OpARM64MOVDconst && y.Op!=OpARM64MOVDconst && a.Op!=OpARM64MOVDconst && clobber(l)
+ // cond: a.Type.Size() != 8 && l.Uses==1 && clobber(l)
// result: (MADDW a x y)
for {
_ = v.Args[1]
@@ -1032,7 +1078,7 @@ func rewriteValueARM64_OpARM64ADD_0(v *Value) bool {
x := l.Args[0]
y := l.Args[1]
a := v.Args[1]
- if !(l.Uses == 1 && a.Type.Size() != 8 && x.Op != OpARM64MOVDconst && y.Op != OpARM64MOVDconst && a.Op != OpARM64MOVDconst && clobber(l)) {
+ if !(a.Type.Size() != 8 && l.Uses == 1 && clobber(l)) {
break
}
v.reset(OpARM64MADDW)
@@ -1042,7 +1088,7 @@ func rewriteValueARM64_OpARM64ADD_0(v *Value) bool {
return true
}
// match: (ADD a l:(MNEGW x y))
- // cond: l.Uses==1 && a.Type.Size() != 8 && x.Op!=OpARM64MOVDconst && y.Op!=OpARM64MOVDconst && a.Op!=OpARM64MOVDconst && clobber(l)
+ // cond: a.Type.Size() != 8 && l.Uses==1 && clobber(l)
// result: (MSUBW a x y)
for {
_ = v.Args[1]
@@ -1054,7 +1100,7 @@ func rewriteValueARM64_OpARM64ADD_0(v *Value) bool {
_ = l.Args[1]
x := l.Args[0]
y := l.Args[1]
- if !(l.Uses == 1 && a.Type.Size() != 8 && x.Op != OpARM64MOVDconst && y.Op != OpARM64MOVDconst && a.Op != OpARM64MOVDconst && clobber(l)) {
+ if !(a.Type.Size() != 8 && l.Uses == 1 && clobber(l)) {
break
}
v.reset(OpARM64MSUBW)
@@ -1064,7 +1110,7 @@ func rewriteValueARM64_OpARM64ADD_0(v *Value) bool {
return true
}
// match: (ADD l:(MNEGW x y) a)
- // cond: l.Uses==1 && a.Type.Size() != 8 && x.Op!=OpARM64MOVDconst && y.Op!=OpARM64MOVDconst && a.Op!=OpARM64MOVDconst && clobber(l)
+ // cond: a.Type.Size() != 8 && l.Uses==1 && clobber(l)
// result: (MSUBW a x y)
for {
_ = v.Args[1]
@@ -1076,7 +1122,7 @@ func rewriteValueARM64_OpARM64ADD_0(v *Value) bool {
x := l.Args[0]
y := l.Args[1]
a := v.Args[1]
- if !(l.Uses == 1 && a.Type.Size() != 8 && x.Op != OpARM64MOVDconst && y.Op != OpARM64MOVDconst && a.Op != OpARM64MOVDconst && clobber(l)) {
+ if !(a.Type.Size() != 8 && l.Uses == 1 && clobber(l)) {
break
}
v.reset(OpARM64MSUBW)
@@ -1088,6 +1134,10 @@ func rewriteValueARM64_OpARM64ADD_0(v *Value) bool {
return false
}
func rewriteValueARM64_OpARM64ADD_10(v *Value) bool {
+ b := v.Block
+ _ = b
+ typ := &b.Func.Config.Types
+ _ = typ
// match: (ADD x (NEG y))
// cond:
// result: (SUB x y)
@@ -1246,6 +1296,925 @@ func rewriteValueARM64_OpARM64ADD_10(v *Value) bool {
v.AddArg(y)
return true
}
+ // match: (ADD (SLL x (ANDconst <t> [63] y)) (CSEL0 <typ.UInt64> {cc} (SRL <typ.UInt64> x (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y))) (CMPconst [64] (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y)))))
+ // cond: cc.(Op) == OpARM64LessThanU
+ // result: (ROR x (NEG <t> y))
+ for {
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64SLL {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARM64ANDconst {
+ break
+ }
+ t := v_0_1.Type
+ if v_0_1.AuxInt != 63 {
+ break
+ }
+ y := v_0_1.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64CSEL0 {
+ break
+ }
+ if v_1.Type != typ.UInt64 {
+ break
+ }
+ cc := v_1.Aux
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpARM64SRL {
+ break
+ }
+ if v_1_0.Type != typ.UInt64 {
+ break
+ }
+ _ = v_1_0.Args[1]
+ if x != v_1_0.Args[0] {
+ break
+ }
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpARM64SUB {
+ break
+ }
+ if v_1_0_1.Type != t {
+ break
+ }
+ _ = v_1_0_1.Args[1]
+ v_1_0_1_0 := v_1_0_1.Args[0]
+ if v_1_0_1_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_1_0_1_0.AuxInt != 64 {
+ break
+ }
+ v_1_0_1_1 := v_1_0_1.Args[1]
+ if v_1_0_1_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_1_0_1_1.Type != t {
+ break
+ }
+ if v_1_0_1_1.AuxInt != 63 {
+ break
+ }
+ if y != v_1_0_1_1.Args[0] {
+ break
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpARM64CMPconst {
+ break
+ }
+ if v_1_1.AuxInt != 64 {
+ break
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpARM64SUB {
+ break
+ }
+ if v_1_1_0.Type != t {
+ break
+ }
+ _ = v_1_1_0.Args[1]
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_1_1_0_0.AuxInt != 64 {
+ break
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_1_1_0_1.Type != t {
+ break
+ }
+ if v_1_1_0_1.AuxInt != 63 {
+ break
+ }
+ if y != v_1_1_0_1.Args[0] {
+ break
+ }
+ if !(cc.(Op) == OpARM64LessThanU) {
+ break
+ }
+ v.reset(OpARM64ROR)
+ v.AddArg(x)
+ v0 := b.NewValue0(v.Pos, OpARM64NEG, t)
+ v0.AddArg(y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (ADD (CSEL0 <typ.UInt64> {cc} (SRL <typ.UInt64> x (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y))) (CMPconst [64] (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y)))) (SLL x (ANDconst <t> [63] y)))
+ // cond: cc.(Op) == OpARM64LessThanU
+ // result: (ROR x (NEG <t> y))
+ for {
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64CSEL0 {
+ break
+ }
+ if v_0.Type != typ.UInt64 {
+ break
+ }
+ cc := v_0.Aux
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARM64SRL {
+ break
+ }
+ if v_0_0.Type != typ.UInt64 {
+ break
+ }
+ _ = v_0_0.Args[1]
+ x := v_0_0.Args[0]
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpARM64SUB {
+ break
+ }
+ t := v_0_0_1.Type
+ _ = v_0_0_1.Args[1]
+ v_0_0_1_0 := v_0_0_1.Args[0]
+ if v_0_0_1_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_0_0_1_0.AuxInt != 64 {
+ break
+ }
+ v_0_0_1_1 := v_0_0_1.Args[1]
+ if v_0_0_1_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_0_0_1_1.Type != t {
+ break
+ }
+ if v_0_0_1_1.AuxInt != 63 {
+ break
+ }
+ y := v_0_0_1_1.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARM64CMPconst {
+ break
+ }
+ if v_0_1.AuxInt != 64 {
+ break
+ }
+ v_0_1_0 := v_0_1.Args[0]
+ if v_0_1_0.Op != OpARM64SUB {
+ break
+ }
+ if v_0_1_0.Type != t {
+ break
+ }
+ _ = v_0_1_0.Args[1]
+ v_0_1_0_0 := v_0_1_0.Args[0]
+ if v_0_1_0_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_0_1_0_0.AuxInt != 64 {
+ break
+ }
+ v_0_1_0_1 := v_0_1_0.Args[1]
+ if v_0_1_0_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_0_1_0_1.Type != t {
+ break
+ }
+ if v_0_1_0_1.AuxInt != 63 {
+ break
+ }
+ if y != v_0_1_0_1.Args[0] {
+ break
+ }
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64SLL {
+ break
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ break
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_1_1.Type != t {
+ break
+ }
+ if v_1_1.AuxInt != 63 {
+ break
+ }
+ if y != v_1_1.Args[0] {
+ break
+ }
+ if !(cc.(Op) == OpARM64LessThanU) {
+ break
+ }
+ v.reset(OpARM64ROR)
+ v.AddArg(x)
+ v0 := b.NewValue0(v.Pos, OpARM64NEG, t)
+ v0.AddArg(y)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64ADD_20(v *Value) bool {
+ b := v.Block
+ _ = b
+ typ := &b.Func.Config.Types
+ _ = typ
+ // match: (ADD (SRL <typ.UInt64> x (ANDconst <t> [63] y)) (CSEL0 <typ.UInt64> {cc} (SLL x (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y))) (CMPconst [64] (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y)))))
+ // cond: cc.(Op) == OpARM64LessThanU
+ // result: (ROR x y)
+ for {
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64SRL {
+ break
+ }
+ if v_0.Type != typ.UInt64 {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARM64ANDconst {
+ break
+ }
+ t := v_0_1.Type
+ if v_0_1.AuxInt != 63 {
+ break
+ }
+ y := v_0_1.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64CSEL0 {
+ break
+ }
+ if v_1.Type != typ.UInt64 {
+ break
+ }
+ cc := v_1.Aux
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpARM64SLL {
+ break
+ }
+ _ = v_1_0.Args[1]
+ if x != v_1_0.Args[0] {
+ break
+ }
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpARM64SUB {
+ break
+ }
+ if v_1_0_1.Type != t {
+ break
+ }
+ _ = v_1_0_1.Args[1]
+ v_1_0_1_0 := v_1_0_1.Args[0]
+ if v_1_0_1_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_1_0_1_0.AuxInt != 64 {
+ break
+ }
+ v_1_0_1_1 := v_1_0_1.Args[1]
+ if v_1_0_1_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_1_0_1_1.Type != t {
+ break
+ }
+ if v_1_0_1_1.AuxInt != 63 {
+ break
+ }
+ if y != v_1_0_1_1.Args[0] {
+ break
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpARM64CMPconst {
+ break
+ }
+ if v_1_1.AuxInt != 64 {
+ break
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpARM64SUB {
+ break
+ }
+ if v_1_1_0.Type != t {
+ break
+ }
+ _ = v_1_1_0.Args[1]
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_1_1_0_0.AuxInt != 64 {
+ break
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_1_1_0_1.Type != t {
+ break
+ }
+ if v_1_1_0_1.AuxInt != 63 {
+ break
+ }
+ if y != v_1_1_0_1.Args[0] {
+ break
+ }
+ if !(cc.(Op) == OpARM64LessThanU) {
+ break
+ }
+ v.reset(OpARM64ROR)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+ // match: (ADD (CSEL0 <typ.UInt64> {cc} (SLL x (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y))) (CMPconst [64] (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y)))) (SRL <typ.UInt64> x (ANDconst <t> [63] y)))
+ // cond: cc.(Op) == OpARM64LessThanU
+ // result: (ROR x y)
+ for {
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64CSEL0 {
+ break
+ }
+ if v_0.Type != typ.UInt64 {
+ break
+ }
+ cc := v_0.Aux
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARM64SLL {
+ break
+ }
+ _ = v_0_0.Args[1]
+ x := v_0_0.Args[0]
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpARM64SUB {
+ break
+ }
+ t := v_0_0_1.Type
+ _ = v_0_0_1.Args[1]
+ v_0_0_1_0 := v_0_0_1.Args[0]
+ if v_0_0_1_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_0_0_1_0.AuxInt != 64 {
+ break
+ }
+ v_0_0_1_1 := v_0_0_1.Args[1]
+ if v_0_0_1_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_0_0_1_1.Type != t {
+ break
+ }
+ if v_0_0_1_1.AuxInt != 63 {
+ break
+ }
+ y := v_0_0_1_1.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARM64CMPconst {
+ break
+ }
+ if v_0_1.AuxInt != 64 {
+ break
+ }
+ v_0_1_0 := v_0_1.Args[0]
+ if v_0_1_0.Op != OpARM64SUB {
+ break
+ }
+ if v_0_1_0.Type != t {
+ break
+ }
+ _ = v_0_1_0.Args[1]
+ v_0_1_0_0 := v_0_1_0.Args[0]
+ if v_0_1_0_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_0_1_0_0.AuxInt != 64 {
+ break
+ }
+ v_0_1_0_1 := v_0_1_0.Args[1]
+ if v_0_1_0_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_0_1_0_1.Type != t {
+ break
+ }
+ if v_0_1_0_1.AuxInt != 63 {
+ break
+ }
+ if y != v_0_1_0_1.Args[0] {
+ break
+ }
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64SRL {
+ break
+ }
+ if v_1.Type != typ.UInt64 {
+ break
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ break
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_1_1.Type != t {
+ break
+ }
+ if v_1_1.AuxInt != 63 {
+ break
+ }
+ if y != v_1_1.Args[0] {
+ break
+ }
+ if !(cc.(Op) == OpARM64LessThanU) {
+ break
+ }
+ v.reset(OpARM64ROR)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+ // match: (ADD (SLL x (ANDconst <t> [31] y)) (CSEL0 <typ.UInt32> {cc} (SRL <typ.UInt32> (MOVWUreg x) (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y))) (CMPconst [64] (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y)))))
+ // cond: cc.(Op) == OpARM64LessThanU
+ // result: (RORW x (NEG <t> y))
+ for {
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64SLL {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARM64ANDconst {
+ break
+ }
+ t := v_0_1.Type
+ if v_0_1.AuxInt != 31 {
+ break
+ }
+ y := v_0_1.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64CSEL0 {
+ break
+ }
+ if v_1.Type != typ.UInt32 {
+ break
+ }
+ cc := v_1.Aux
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpARM64SRL {
+ break
+ }
+ if v_1_0.Type != typ.UInt32 {
+ break
+ }
+ _ = v_1_0.Args[1]
+ v_1_0_0 := v_1_0.Args[0]
+ if v_1_0_0.Op != OpARM64MOVWUreg {
+ break
+ }
+ if x != v_1_0_0.Args[0] {
+ break
+ }
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpARM64SUB {
+ break
+ }
+ if v_1_0_1.Type != t {
+ break
+ }
+ _ = v_1_0_1.Args[1]
+ v_1_0_1_0 := v_1_0_1.Args[0]
+ if v_1_0_1_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_1_0_1_0.AuxInt != 32 {
+ break
+ }
+ v_1_0_1_1 := v_1_0_1.Args[1]
+ if v_1_0_1_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_1_0_1_1.Type != t {
+ break
+ }
+ if v_1_0_1_1.AuxInt != 31 {
+ break
+ }
+ if y != v_1_0_1_1.Args[0] {
+ break
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpARM64CMPconst {
+ break
+ }
+ if v_1_1.AuxInt != 64 {
+ break
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpARM64SUB {
+ break
+ }
+ if v_1_1_0.Type != t {
+ break
+ }
+ _ = v_1_1_0.Args[1]
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_1_1_0_0.AuxInt != 32 {
+ break
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_1_1_0_1.Type != t {
+ break
+ }
+ if v_1_1_0_1.AuxInt != 31 {
+ break
+ }
+ if y != v_1_1_0_1.Args[0] {
+ break
+ }
+ if !(cc.(Op) == OpARM64LessThanU) {
+ break
+ }
+ v.reset(OpARM64RORW)
+ v.AddArg(x)
+ v0 := b.NewValue0(v.Pos, OpARM64NEG, t)
+ v0.AddArg(y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (ADD (CSEL0 <typ.UInt32> {cc} (SRL <typ.UInt32> (MOVWUreg x) (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y))) (CMPconst [64] (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y)))) (SLL x (ANDconst <t> [31] y)))
+ // cond: cc.(Op) == OpARM64LessThanU
+ // result: (RORW x (NEG <t> y))
+ for {
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64CSEL0 {
+ break
+ }
+ if v_0.Type != typ.UInt32 {
+ break
+ }
+ cc := v_0.Aux
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARM64SRL {
+ break
+ }
+ if v_0_0.Type != typ.UInt32 {
+ break
+ }
+ _ = v_0_0.Args[1]
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpARM64MOVWUreg {
+ break
+ }
+ x := v_0_0_0.Args[0]
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpARM64SUB {
+ break
+ }
+ t := v_0_0_1.Type
+ _ = v_0_0_1.Args[1]
+ v_0_0_1_0 := v_0_0_1.Args[0]
+ if v_0_0_1_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_0_0_1_0.AuxInt != 32 {
+ break
+ }
+ v_0_0_1_1 := v_0_0_1.Args[1]
+ if v_0_0_1_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_0_0_1_1.Type != t {
+ break
+ }
+ if v_0_0_1_1.AuxInt != 31 {
+ break
+ }
+ y := v_0_0_1_1.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARM64CMPconst {
+ break
+ }
+ if v_0_1.AuxInt != 64 {
+ break
+ }
+ v_0_1_0 := v_0_1.Args[0]
+ if v_0_1_0.Op != OpARM64SUB {
+ break
+ }
+ if v_0_1_0.Type != t {
+ break
+ }
+ _ = v_0_1_0.Args[1]
+ v_0_1_0_0 := v_0_1_0.Args[0]
+ if v_0_1_0_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_0_1_0_0.AuxInt != 32 {
+ break
+ }
+ v_0_1_0_1 := v_0_1_0.Args[1]
+ if v_0_1_0_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_0_1_0_1.Type != t {
+ break
+ }
+ if v_0_1_0_1.AuxInt != 31 {
+ break
+ }
+ if y != v_0_1_0_1.Args[0] {
+ break
+ }
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64SLL {
+ break
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ break
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_1_1.Type != t {
+ break
+ }
+ if v_1_1.AuxInt != 31 {
+ break
+ }
+ if y != v_1_1.Args[0] {
+ break
+ }
+ if !(cc.(Op) == OpARM64LessThanU) {
+ break
+ }
+ v.reset(OpARM64RORW)
+ v.AddArg(x)
+ v0 := b.NewValue0(v.Pos, OpARM64NEG, t)
+ v0.AddArg(y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (ADD (SRL <typ.UInt32> (MOVWUreg x) (ANDconst <t> [31] y)) (CSEL0 <typ.UInt32> {cc} (SLL x (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y))) (CMPconst [64] (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y)))))
+ // cond: cc.(Op) == OpARM64LessThanU
+ // result: (RORW x y)
+ for {
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64SRL {
+ break
+ }
+ if v_0.Type != typ.UInt32 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARM64MOVWUreg {
+ break
+ }
+ x := v_0_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARM64ANDconst {
+ break
+ }
+ t := v_0_1.Type
+ if v_0_1.AuxInt != 31 {
+ break
+ }
+ y := v_0_1.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64CSEL0 {
+ break
+ }
+ if v_1.Type != typ.UInt32 {
+ break
+ }
+ cc := v_1.Aux
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpARM64SLL {
+ break
+ }
+ _ = v_1_0.Args[1]
+ if x != v_1_0.Args[0] {
+ break
+ }
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpARM64SUB {
+ break
+ }
+ if v_1_0_1.Type != t {
+ break
+ }
+ _ = v_1_0_1.Args[1]
+ v_1_0_1_0 := v_1_0_1.Args[0]
+ if v_1_0_1_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_1_0_1_0.AuxInt != 32 {
+ break
+ }
+ v_1_0_1_1 := v_1_0_1.Args[1]
+ if v_1_0_1_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_1_0_1_1.Type != t {
+ break
+ }
+ if v_1_0_1_1.AuxInt != 31 {
+ break
+ }
+ if y != v_1_0_1_1.Args[0] {
+ break
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpARM64CMPconst {
+ break
+ }
+ if v_1_1.AuxInt != 64 {
+ break
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpARM64SUB {
+ break
+ }
+ if v_1_1_0.Type != t {
+ break
+ }
+ _ = v_1_1_0.Args[1]
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_1_1_0_0.AuxInt != 32 {
+ break
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_1_1_0_1.Type != t {
+ break
+ }
+ if v_1_1_0_1.AuxInt != 31 {
+ break
+ }
+ if y != v_1_1_0_1.Args[0] {
+ break
+ }
+ if !(cc.(Op) == OpARM64LessThanU) {
+ break
+ }
+ v.reset(OpARM64RORW)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+ // match: (ADD (CSEL0 <typ.UInt32> {cc} (SLL x (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y))) (CMPconst [64] (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y)))) (SRL <typ.UInt32> (MOVWUreg x) (ANDconst <t> [31] y)))
+ // cond: cc.(Op) == OpARM64LessThanU
+ // result: (RORW x y)
+ for {
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64CSEL0 {
+ break
+ }
+ if v_0.Type != typ.UInt32 {
+ break
+ }
+ cc := v_0.Aux
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARM64SLL {
+ break
+ }
+ _ = v_0_0.Args[1]
+ x := v_0_0.Args[0]
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpARM64SUB {
+ break
+ }
+ t := v_0_0_1.Type
+ _ = v_0_0_1.Args[1]
+ v_0_0_1_0 := v_0_0_1.Args[0]
+ if v_0_0_1_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_0_0_1_0.AuxInt != 32 {
+ break
+ }
+ v_0_0_1_1 := v_0_0_1.Args[1]
+ if v_0_0_1_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_0_0_1_1.Type != t {
+ break
+ }
+ if v_0_0_1_1.AuxInt != 31 {
+ break
+ }
+ y := v_0_0_1_1.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARM64CMPconst {
+ break
+ }
+ if v_0_1.AuxInt != 64 {
+ break
+ }
+ v_0_1_0 := v_0_1.Args[0]
+ if v_0_1_0.Op != OpARM64SUB {
+ break
+ }
+ if v_0_1_0.Type != t {
+ break
+ }
+ _ = v_0_1_0.Args[1]
+ v_0_1_0_0 := v_0_1_0.Args[0]
+ if v_0_1_0_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_0_1_0_0.AuxInt != 32 {
+ break
+ }
+ v_0_1_0_1 := v_0_1_0.Args[1]
+ if v_0_1_0_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_0_1_0_1.Type != t {
+ break
+ }
+ if v_0_1_0_1.AuxInt != 31 {
+ break
+ }
+ if y != v_0_1_0_1.Args[0] {
+ break
+ }
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64SRL {
+ break
+ }
+ if v_1.Type != typ.UInt32 {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpARM64MOVWUreg {
+ break
+ }
+ if x != v_1_0.Args[0] {
+ break
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_1_1.Type != t {
+ break
+ }
+ if v_1_1.AuxInt != 31 {
+ break
+ }
+ if y != v_1_1.Args[0] {
+ break
+ }
+ if !(cc.(Op) == OpARM64LessThanU) {
+ break
+ }
+ v.reset(OpARM64RORW)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
return false
}
func rewriteValueARM64_OpARM64ADDconst_0(v *Value) bool {
@@ -2395,6 +3364,132 @@ func rewriteValueARM64_OpARM64CMN_0(v *Value) bool {
v.AddArg(x)
return true
}
+ // match: (CMN x0 x1:(SLLconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (CMNshiftLL x0 y [c])
+ for {
+ _ = v.Args[1]
+ x0 := v.Args[0]
+ x1 := v.Args[1]
+ if x1.Op != OpARM64SLLconst {
+ break
+ }
+ c := x1.AuxInt
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ break
+ }
+ v.reset(OpARM64CMNshiftLL)
+ v.AuxInt = c
+ v.AddArg(x0)
+ v.AddArg(y)
+ return true
+ }
+ // match: (CMN x1:(SLLconst [c] y) x0)
+ // cond: clobberIfDead(x1)
+ // result: (CMNshiftLL x0 y [c])
+ for {
+ _ = v.Args[1]
+ x1 := v.Args[0]
+ if x1.Op != OpARM64SLLconst {
+ break
+ }
+ c := x1.AuxInt
+ y := x1.Args[0]
+ x0 := v.Args[1]
+ if !(clobberIfDead(x1)) {
+ break
+ }
+ v.reset(OpARM64CMNshiftLL)
+ v.AuxInt = c
+ v.AddArg(x0)
+ v.AddArg(y)
+ return true
+ }
+ // match: (CMN x0 x1:(SRLconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (CMNshiftRL x0 y [c])
+ for {
+ _ = v.Args[1]
+ x0 := v.Args[0]
+ x1 := v.Args[1]
+ if x1.Op != OpARM64SRLconst {
+ break
+ }
+ c := x1.AuxInt
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ break
+ }
+ v.reset(OpARM64CMNshiftRL)
+ v.AuxInt = c
+ v.AddArg(x0)
+ v.AddArg(y)
+ return true
+ }
+ // match: (CMN x1:(SRLconst [c] y) x0)
+ // cond: clobberIfDead(x1)
+ // result: (CMNshiftRL x0 y [c])
+ for {
+ _ = v.Args[1]
+ x1 := v.Args[0]
+ if x1.Op != OpARM64SRLconst {
+ break
+ }
+ c := x1.AuxInt
+ y := x1.Args[0]
+ x0 := v.Args[1]
+ if !(clobberIfDead(x1)) {
+ break
+ }
+ v.reset(OpARM64CMNshiftRL)
+ v.AuxInt = c
+ v.AddArg(x0)
+ v.AddArg(y)
+ return true
+ }
+ // match: (CMN x0 x1:(SRAconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (CMNshiftRA x0 y [c])
+ for {
+ _ = v.Args[1]
+ x0 := v.Args[0]
+ x1 := v.Args[1]
+ if x1.Op != OpARM64SRAconst {
+ break
+ }
+ c := x1.AuxInt
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ break
+ }
+ v.reset(OpARM64CMNshiftRA)
+ v.AuxInt = c
+ v.AddArg(x0)
+ v.AddArg(y)
+ return true
+ }
+ // match: (CMN x1:(SRAconst [c] y) x0)
+ // cond: clobberIfDead(x1)
+ // result: (CMNshiftRA x0 y [c])
+ for {
+ _ = v.Args[1]
+ x1 := v.Args[0]
+ if x1.Op != OpARM64SRAconst {
+ break
+ }
+ c := x1.AuxInt
+ y := x1.Args[0]
+ x0 := v.Args[1]
+ if !(clobberIfDead(x1)) {
+ break
+ }
+ v.reset(OpARM64CMNshiftRA)
+ v.AuxInt = c
+ v.AddArg(x0)
+ v.AddArg(y)
+ return true
+ }
return false
}
func rewriteValueARM64_OpARM64CMNW_0(v *Value) bool {
@@ -2598,6 +3693,132 @@ func rewriteValueARM64_OpARM64CMNconst_0(v *Value) bool {
}
return false
}
+func rewriteValueARM64_OpARM64CMNshiftLL_0(v *Value) bool {
+ b := v.Block
+ _ = b
+ // match: (CMNshiftLL (MOVDconst [c]) x [d])
+ // cond:
+ // result: (CMNconst [c] (SLLconst <x.Type> x [d]))
+ for {
+ d := v.AuxInt
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_0.AuxInt
+ x := v.Args[1]
+ v.reset(OpARM64CMNconst)
+ v.AuxInt = c
+ v0 := b.NewValue0(v.Pos, OpARM64SLLconst, x.Type)
+ v0.AuxInt = d
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMNshiftLL x (MOVDconst [c]) [d])
+ // cond:
+ // result: (CMNconst x [int64(uint64(c)<<uint64(d))])
+ for {
+ d := v.AuxInt
+ _ = v.Args[1]
+ x := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ v.reset(OpARM64CMNconst)
+ v.AuxInt = int64(uint64(c) << uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64CMNshiftRA_0(v *Value) bool {
+ b := v.Block
+ _ = b
+ // match: (CMNshiftRA (MOVDconst [c]) x [d])
+ // cond:
+ // result: (CMNconst [c] (SRAconst <x.Type> x [d]))
+ for {
+ d := v.AuxInt
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_0.AuxInt
+ x := v.Args[1]
+ v.reset(OpARM64CMNconst)
+ v.AuxInt = c
+ v0 := b.NewValue0(v.Pos, OpARM64SRAconst, x.Type)
+ v0.AuxInt = d
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMNshiftRA x (MOVDconst [c]) [d])
+ // cond:
+ // result: (CMNconst x [c>>uint64(d)])
+ for {
+ d := v.AuxInt
+ _ = v.Args[1]
+ x := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ v.reset(OpARM64CMNconst)
+ v.AuxInt = c >> uint64(d)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64CMNshiftRL_0(v *Value) bool {
+ b := v.Block
+ _ = b
+ // match: (CMNshiftRL (MOVDconst [c]) x [d])
+ // cond:
+ // result: (CMNconst [c] (SRLconst <x.Type> x [d]))
+ for {
+ d := v.AuxInt
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_0.AuxInt
+ x := v.Args[1]
+ v.reset(OpARM64CMNconst)
+ v.AuxInt = c
+ v0 := b.NewValue0(v.Pos, OpARM64SRLconst, x.Type)
+ v0.AuxInt = d
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (CMNshiftRL x (MOVDconst [c]) [d])
+ // cond:
+ // result: (CMNconst x [int64(uint64(c)>>uint64(d))])
+ for {
+ d := v.AuxInt
+ _ = v.Args[1]
+ x := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ v.reset(OpARM64CMNconst)
+ v.AuxInt = int64(uint64(c) >> uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
func rewriteValueARM64_OpARM64CMP_0(v *Value) bool {
b := v.Block
_ = b
@@ -3960,6 +5181,30 @@ func rewriteValueARM64_OpARM64FADDS_0(v *Value) bool {
}
return false
}
+func rewriteValueARM64_OpARM64FMOVDfpgp_0(v *Value) bool {
+ b := v.Block
+ _ = b
+ // match: (FMOVDfpgp <t> (Arg [off] {sym}))
+ // cond:
+ // result: @b.Func.Entry (Arg <t> [off] {sym})
+ for {
+ t := v.Type
+ v_0 := v.Args[0]
+ if v_0.Op != OpArg {
+ break
+ }
+ off := v_0.AuxInt
+ sym := v_0.Aux
+ b = b.Func.Entry
+ v0 := b.NewValue0(v.Pos, OpArg, t)
+ v.reset(OpCopy)
+ v.AddArg(v0)
+ v0.AuxInt = off
+ v0.Aux = sym
+ return true
+ }
+ return false
+}
func rewriteValueARM64_OpARM64FMOVDgpfp_0(v *Value) bool {
b := v.Block
_ = b
@@ -3989,6 +5234,33 @@ func rewriteValueARM64_OpARM64FMOVDload_0(v *Value) bool {
_ = b
config := b.Func.Config
_ = config
+ // match: (FMOVDload [off] {sym} ptr (MOVDstore [off] {sym} ptr val _))
+ // cond:
+ // result: (FMOVDgpfp val)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[1]
+ ptr := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDstore {
+ break
+ }
+ if v_1.AuxInt != off {
+ break
+ }
+ if v_1.Aux != sym {
+ break
+ }
+ _ = v_1.Args[2]
+ if ptr != v_1.Args[0] {
+ break
+ }
+ val := v_1.Args[1]
+ v.reset(OpARM64FMOVDgpfp)
+ v.AddArg(val)
+ return true
+ }
// match: (FMOVDload [off1] {sym} (ADDconst [off2] ptr) mem)
// cond: is32Bit(off1+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
// result: (FMOVDload [off1+off2] {sym} ptr mem)
@@ -4108,10 +5380,12 @@ func rewriteValueARM64_OpARM64FMOVDstore_0(v *Value) bool {
_ = b
config := b.Func.Config
_ = config
- // match: (FMOVDstore ptr (FMOVDgpfp val) mem)
+ // match: (FMOVDstore [off] {sym} ptr (FMOVDgpfp val) mem)
// cond:
- // result: (MOVDstore ptr val mem)
+ // result: (MOVDstore [off] {sym} ptr val mem)
for {
+ off := v.AuxInt
+ sym := v.Aux
_ = v.Args[2]
ptr := v.Args[0]
v_1 := v.Args[1]
@@ -4121,6 +5395,8 @@ func rewriteValueARM64_OpARM64FMOVDstore_0(v *Value) bool {
val := v_1.Args[0]
mem := v.Args[2]
v.reset(OpARM64MOVDstore)
+ v.AuxInt = off
+ v.Aux = sym
v.AddArg(ptr)
v.AddArg(val)
v.AddArg(mem)
@@ -4255,6 +5531,33 @@ func rewriteValueARM64_OpARM64FMOVSload_0(v *Value) bool {
_ = b
config := b.Func.Config
_ = config
+ // match: (FMOVSload [off] {sym} ptr (MOVWstore [off] {sym} ptr val _))
+ // cond:
+ // result: (FMOVSgpfp val)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[1]
+ ptr := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVWstore {
+ break
+ }
+ if v_1.AuxInt != off {
+ break
+ }
+ if v_1.Aux != sym {
+ break
+ }
+ _ = v_1.Args[2]
+ if ptr != v_1.Args[0] {
+ break
+ }
+ val := v_1.Args[1]
+ v.reset(OpARM64FMOVSgpfp)
+ v.AddArg(val)
+ return true
+ }
// match: (FMOVSload [off1] {sym} (ADDconst [off2] ptr) mem)
// cond: is32Bit(off1+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
// result: (FMOVSload [off1+off2] {sym} ptr mem)
@@ -4374,6 +5677,28 @@ func rewriteValueARM64_OpARM64FMOVSstore_0(v *Value) bool {
_ = b
config := b.Func.Config
_ = config
+ // match: (FMOVSstore [off] {sym} ptr (FMOVSgpfp val) mem)
+ // cond:
+ // result: (MOVWstore [off] {sym} ptr val mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[2]
+ ptr := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64FMOVSgpfp {
+ break
+ }
+ val := v_1.Args[0]
+ mem := v.Args[2]
+ v.reset(OpARM64MOVWstore)
+ v.AuxInt = off
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
// match: (FMOVSstore [off1] {sym} (ADDconst [off2] ptr) val mem)
// cond: is32Bit(off1+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
// result: (FMOVSstore [off1+off2] {sym} ptr val mem)
@@ -5474,6 +6799,1024 @@ func rewriteValueARM64_OpARM64LessThanU_0(v *Value) bool {
}
return false
}
+func rewriteValueARM64_OpARM64MADD_0(v *Value) bool {
+ b := v.Block
+ _ = b
+ // match: (MADD a x (MOVDconst [-1]))
+ // cond:
+ // result: (SUB a x)
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ x := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_2.AuxInt != -1 {
+ break
+ }
+ v.reset(OpARM64SUB)
+ v.AddArg(a)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MADD a _ (MOVDconst [0]))
+ // cond:
+ // result: a
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_2.AuxInt != 0 {
+ break
+ }
+ v.reset(OpCopy)
+ v.Type = a.Type
+ v.AddArg(a)
+ return true
+ }
+ // match: (MADD a x (MOVDconst [1]))
+ // cond:
+ // result: (ADD a x)
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ x := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_2.AuxInt != 1 {
+ break
+ }
+ v.reset(OpARM64ADD)
+ v.AddArg(a)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MADD a x (MOVDconst [c]))
+ // cond: isPowerOfTwo(c)
+ // result: (ADDshiftLL a x [log2(c)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ x := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_2.AuxInt
+ if !(isPowerOfTwo(c)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = log2(c)
+ v.AddArg(a)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MADD a x (MOVDconst [c]))
+ // cond: isPowerOfTwo(c-1) && c>=3
+ // result: (ADD a (ADDshiftLL <x.Type> x x [log2(c-1)]))
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ x := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_2.AuxInt
+ if !(isPowerOfTwo(c-1) && c >= 3) {
+ break
+ }
+ v.reset(OpARM64ADD)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = log2(c - 1)
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MADD a x (MOVDconst [c]))
+ // cond: isPowerOfTwo(c+1) && c>=7
+ // result: (SUB a (SUBshiftLL <x.Type> x x [log2(c+1)]))
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ x := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_2.AuxInt
+ if !(isPowerOfTwo(c+1) && c >= 7) {
+ break
+ }
+ v.reset(OpARM64SUB)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = log2(c + 1)
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MADD a x (MOVDconst [c]))
+ // cond: c%3 == 0 && isPowerOfTwo(c/3)
+ // result: (SUBshiftLL a (SUBshiftLL <x.Type> x x [2]) [log2(c/3)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ x := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_2.AuxInt
+ if !(c%3 == 0 && isPowerOfTwo(c/3)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = log2(c / 3)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = 2
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MADD a x (MOVDconst [c]))
+ // cond: c%5 == 0 && isPowerOfTwo(c/5)
+ // result: (ADDshiftLL a (ADDshiftLL <x.Type> x x [2]) [log2(c/5)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ x := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_2.AuxInt
+ if !(c%5 == 0 && isPowerOfTwo(c/5)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = log2(c / 5)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = 2
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MADD a x (MOVDconst [c]))
+ // cond: c%7 == 0 && isPowerOfTwo(c/7)
+ // result: (SUBshiftLL a (SUBshiftLL <x.Type> x x [3]) [log2(c/7)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ x := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_2.AuxInt
+ if !(c%7 == 0 && isPowerOfTwo(c/7)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = log2(c / 7)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = 3
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MADD a x (MOVDconst [c]))
+ // cond: c%9 == 0 && isPowerOfTwo(c/9)
+ // result: (ADDshiftLL a (ADDshiftLL <x.Type> x x [3]) [log2(c/9)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ x := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_2.AuxInt
+ if !(c%9 == 0 && isPowerOfTwo(c/9)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = log2(c / 9)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = 3
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MADD_10(v *Value) bool {
+ b := v.Block
+ _ = b
+ // match: (MADD a (MOVDconst [-1]) x)
+ // cond:
+ // result: (SUB a x)
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_1.AuxInt != -1 {
+ break
+ }
+ x := v.Args[2]
+ v.reset(OpARM64SUB)
+ v.AddArg(a)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MADD a (MOVDconst [0]) _)
+ // cond:
+ // result: a
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_1.AuxInt != 0 {
+ break
+ }
+ v.reset(OpCopy)
+ v.Type = a.Type
+ v.AddArg(a)
+ return true
+ }
+ // match: (MADD a (MOVDconst [1]) x)
+ // cond:
+ // result: (ADD a x)
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_1.AuxInt != 1 {
+ break
+ }
+ x := v.Args[2]
+ v.reset(OpARM64ADD)
+ v.AddArg(a)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MADD a (MOVDconst [c]) x)
+ // cond: isPowerOfTwo(c)
+ // result: (ADDshiftLL a x [log2(c)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ x := v.Args[2]
+ if !(isPowerOfTwo(c)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = log2(c)
+ v.AddArg(a)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MADD a (MOVDconst [c]) x)
+ // cond: isPowerOfTwo(c-1) && c>=3
+ // result: (ADD a (ADDshiftLL <x.Type> x x [log2(c-1)]))
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ x := v.Args[2]
+ if !(isPowerOfTwo(c-1) && c >= 3) {
+ break
+ }
+ v.reset(OpARM64ADD)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = log2(c - 1)
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MADD a (MOVDconst [c]) x)
+ // cond: isPowerOfTwo(c+1) && c>=7
+ // result: (SUB a (SUBshiftLL <x.Type> x x [log2(c+1)]))
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ x := v.Args[2]
+ if !(isPowerOfTwo(c+1) && c >= 7) {
+ break
+ }
+ v.reset(OpARM64SUB)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = log2(c + 1)
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MADD a (MOVDconst [c]) x)
+ // cond: c%3 == 0 && isPowerOfTwo(c/3)
+ // result: (SUBshiftLL a (SUBshiftLL <x.Type> x x [2]) [log2(c/3)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ x := v.Args[2]
+ if !(c%3 == 0 && isPowerOfTwo(c/3)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = log2(c / 3)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = 2
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MADD a (MOVDconst [c]) x)
+ // cond: c%5 == 0 && isPowerOfTwo(c/5)
+ // result: (ADDshiftLL a (ADDshiftLL <x.Type> x x [2]) [log2(c/5)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ x := v.Args[2]
+ if !(c%5 == 0 && isPowerOfTwo(c/5)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = log2(c / 5)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = 2
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MADD a (MOVDconst [c]) x)
+ // cond: c%7 == 0 && isPowerOfTwo(c/7)
+ // result: (SUBshiftLL a (SUBshiftLL <x.Type> x x [3]) [log2(c/7)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ x := v.Args[2]
+ if !(c%7 == 0 && isPowerOfTwo(c/7)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = log2(c / 7)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = 3
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MADD a (MOVDconst [c]) x)
+ // cond: c%9 == 0 && isPowerOfTwo(c/9)
+ // result: (ADDshiftLL a (ADDshiftLL <x.Type> x x [3]) [log2(c/9)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ x := v.Args[2]
+ if !(c%9 == 0 && isPowerOfTwo(c/9)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = log2(c / 9)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = 3
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MADD_20(v *Value) bool {
+ b := v.Block
+ _ = b
+ // match: (MADD (MOVDconst [c]) x y)
+ // cond:
+ // result: (ADDconst [c] (MUL <x.Type> x y))
+ for {
+ _ = v.Args[2]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_0.AuxInt
+ x := v.Args[1]
+ y := v.Args[2]
+ v.reset(OpARM64ADDconst)
+ v.AuxInt = c
+ v0 := b.NewValue0(v.Pos, OpARM64MUL, x.Type)
+ v0.AddArg(x)
+ v0.AddArg(y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MADD a (MOVDconst [c]) (MOVDconst [d]))
+ // cond:
+ // result: (ADDconst [c*d] a)
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ d := v_2.AuxInt
+ v.reset(OpARM64ADDconst)
+ v.AuxInt = c * d
+ v.AddArg(a)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MADDW_0(v *Value) bool {
+ b := v.Block
+ _ = b
+ // match: (MADDW a x (MOVDconst [c]))
+ // cond: int32(c)==-1
+ // result: (SUB a x)
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ x := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_2.AuxInt
+ if !(int32(c) == -1) {
+ break
+ }
+ v.reset(OpARM64SUB)
+ v.AddArg(a)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MADDW a _ (MOVDconst [c]))
+ // cond: int32(c)==0
+ // result: a
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_2.AuxInt
+ if !(int32(c) == 0) {
+ break
+ }
+ v.reset(OpCopy)
+ v.Type = a.Type
+ v.AddArg(a)
+ return true
+ }
+ // match: (MADDW a x (MOVDconst [c]))
+ // cond: int32(c)==1
+ // result: (ADD a x)
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ x := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_2.AuxInt
+ if !(int32(c) == 1) {
+ break
+ }
+ v.reset(OpARM64ADD)
+ v.AddArg(a)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MADDW a x (MOVDconst [c]))
+ // cond: isPowerOfTwo(c)
+ // result: (ADDshiftLL a x [log2(c)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ x := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_2.AuxInt
+ if !(isPowerOfTwo(c)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = log2(c)
+ v.AddArg(a)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MADDW a x (MOVDconst [c]))
+ // cond: isPowerOfTwo(c-1) && int32(c)>=3
+ // result: (ADD a (ADDshiftLL <x.Type> x x [log2(c-1)]))
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ x := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_2.AuxInt
+ if !(isPowerOfTwo(c-1) && int32(c) >= 3) {
+ break
+ }
+ v.reset(OpARM64ADD)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = log2(c - 1)
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MADDW a x (MOVDconst [c]))
+ // cond: isPowerOfTwo(c+1) && int32(c)>=7
+ // result: (SUB a (SUBshiftLL <x.Type> x x [log2(c+1)]))
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ x := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_2.AuxInt
+ if !(isPowerOfTwo(c+1) && int32(c) >= 7) {
+ break
+ }
+ v.reset(OpARM64SUB)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = log2(c + 1)
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MADDW a x (MOVDconst [c]))
+ // cond: c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c)
+ // result: (SUBshiftLL a (SUBshiftLL <x.Type> x x [2]) [log2(c/3)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ x := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_2.AuxInt
+ if !(c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = log2(c / 3)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = 2
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MADDW a x (MOVDconst [c]))
+ // cond: c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c)
+ // result: (ADDshiftLL a (ADDshiftLL <x.Type> x x [2]) [log2(c/5)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ x := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_2.AuxInt
+ if !(c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = log2(c / 5)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = 2
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MADDW a x (MOVDconst [c]))
+ // cond: c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c)
+ // result: (SUBshiftLL a (SUBshiftLL <x.Type> x x [3]) [log2(c/7)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ x := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_2.AuxInt
+ if !(c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = log2(c / 7)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = 3
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MADDW a x (MOVDconst [c]))
+ // cond: c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c)
+ // result: (ADDshiftLL a (ADDshiftLL <x.Type> x x [3]) [log2(c/9)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ x := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_2.AuxInt
+ if !(c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = log2(c / 9)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = 3
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MADDW_10(v *Value) bool {
+ b := v.Block
+ _ = b
+ // match: (MADDW a (MOVDconst [c]) x)
+ // cond: int32(c)==-1
+ // result: (SUB a x)
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ x := v.Args[2]
+ if !(int32(c) == -1) {
+ break
+ }
+ v.reset(OpARM64SUB)
+ v.AddArg(a)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MADDW a (MOVDconst [c]) _)
+ // cond: int32(c)==0
+ // result: a
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ if !(int32(c) == 0) {
+ break
+ }
+ v.reset(OpCopy)
+ v.Type = a.Type
+ v.AddArg(a)
+ return true
+ }
+ // match: (MADDW a (MOVDconst [c]) x)
+ // cond: int32(c)==1
+ // result: (ADD a x)
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ x := v.Args[2]
+ if !(int32(c) == 1) {
+ break
+ }
+ v.reset(OpARM64ADD)
+ v.AddArg(a)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MADDW a (MOVDconst [c]) x)
+ // cond: isPowerOfTwo(c)
+ // result: (ADDshiftLL a x [log2(c)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ x := v.Args[2]
+ if !(isPowerOfTwo(c)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = log2(c)
+ v.AddArg(a)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MADDW a (MOVDconst [c]) x)
+ // cond: isPowerOfTwo(c-1) && int32(c)>=3
+ // result: (ADD a (ADDshiftLL <x.Type> x x [log2(c-1)]))
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ x := v.Args[2]
+ if !(isPowerOfTwo(c-1) && int32(c) >= 3) {
+ break
+ }
+ v.reset(OpARM64ADD)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = log2(c - 1)
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MADDW a (MOVDconst [c]) x)
+ // cond: isPowerOfTwo(c+1) && int32(c)>=7
+ // result: (SUB a (SUBshiftLL <x.Type> x x [log2(c+1)]))
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ x := v.Args[2]
+ if !(isPowerOfTwo(c+1) && int32(c) >= 7) {
+ break
+ }
+ v.reset(OpARM64SUB)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = log2(c + 1)
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MADDW a (MOVDconst [c]) x)
+ // cond: c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c)
+ // result: (SUBshiftLL a (SUBshiftLL <x.Type> x x [2]) [log2(c/3)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ x := v.Args[2]
+ if !(c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = log2(c / 3)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = 2
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MADDW a (MOVDconst [c]) x)
+ // cond: c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c)
+ // result: (ADDshiftLL a (ADDshiftLL <x.Type> x x [2]) [log2(c/5)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ x := v.Args[2]
+ if !(c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = log2(c / 5)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = 2
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MADDW a (MOVDconst [c]) x)
+ // cond: c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c)
+ // result: (SUBshiftLL a (SUBshiftLL <x.Type> x x [3]) [log2(c/7)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ x := v.Args[2]
+ if !(c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = log2(c / 7)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = 3
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MADDW a (MOVDconst [c]) x)
+ // cond: c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c)
+ // result: (ADDshiftLL a (ADDshiftLL <x.Type> x x [3]) [log2(c/9)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ x := v.Args[2]
+ if !(c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = log2(c / 9)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = 3
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MADDW_20(v *Value) bool {
+ b := v.Block
+ _ = b
+ // match: (MADDW (MOVDconst [c]) x y)
+ // cond:
+ // result: (ADDconst [c] (MULW <x.Type> x y))
+ for {
+ _ = v.Args[2]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_0.AuxInt
+ x := v.Args[1]
+ y := v.Args[2]
+ v.reset(OpARM64ADDconst)
+ v.AuxInt = c
+ v0 := b.NewValue0(v.Pos, OpARM64MULW, x.Type)
+ v0.AddArg(x)
+ v0.AddArg(y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MADDW a (MOVDconst [c]) (MOVDconst [d]))
+ // cond:
+ // result: (ADDconst [int64(int32(c)*int32(d))] a)
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ d := v_2.AuxInt
+ v.reset(OpARM64ADDconst)
+ v.AuxInt = int64(int32(c) * int32(d))
+ v.AddArg(a)
+ return true
+ }
+ return false
+}
func rewriteValueARM64_OpARM64MNEG_0(v *Value) bool {
b := v.Block
_ = b
@@ -10145,6 +12488,33 @@ func rewriteValueARM64_OpARM64MOVDload_0(v *Value) bool {
_ = b
config := b.Func.Config
_ = config
+ // match: (MOVDload [off] {sym} ptr (FMOVDstore [off] {sym} ptr val _))
+ // cond:
+ // result: (FMOVDfpgp val)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[1]
+ ptr := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64FMOVDstore {
+ break
+ }
+ if v_1.AuxInt != off {
+ break
+ }
+ if v_1.Aux != sym {
+ break
+ }
+ _ = v_1.Args[2]
+ if ptr != v_1.Args[0] {
+ break
+ }
+ val := v_1.Args[1]
+ v.reset(OpARM64FMOVDfpgp)
+ v.AddArg(val)
+ return true
+ }
// match: (MOVDload [off1] {sym} (ADDconst [off2] ptr) mem)
// cond: is32Bit(off1+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
// result: (MOVDload [off1+off2] {sym} ptr mem)
@@ -10447,10 +12817,12 @@ func rewriteValueARM64_OpARM64MOVDstore_0(v *Value) bool {
_ = b
config := b.Func.Config
_ = config
- // match: (MOVDstore ptr (FMOVDfpgp val) mem)
+ // match: (MOVDstore [off] {sym} ptr (FMOVDfpgp val) mem)
// cond:
- // result: (FMOVDstore ptr val mem)
+ // result: (FMOVDstore [off] {sym} ptr val mem)
for {
+ off := v.AuxInt
+ sym := v.Aux
_ = v.Args[2]
ptr := v.Args[0]
v_1 := v.Args[1]
@@ -10460,6 +12832,8 @@ func rewriteValueARM64_OpARM64MOVDstore_0(v *Value) bool {
val := v_1.Args[0]
mem := v.Args[2]
v.reset(OpARM64FMOVDstore)
+ v.AuxInt = off
+ v.Aux = sym
v.AddArg(ptr)
v.AddArg(val)
v.AddArg(mem)
@@ -13659,6 +16033,33 @@ func rewriteValueARM64_OpARM64MOVWUload_0(v *Value) bool {
_ = b
config := b.Func.Config
_ = config
+ // match: (MOVWUload [off] {sym} ptr (FMOVSstore [off] {sym} ptr val _))
+ // cond:
+ // result: (FMOVSfpgp val)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[1]
+ ptr := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64FMOVSstore {
+ break
+ }
+ if v_1.AuxInt != off {
+ break
+ }
+ if v_1.Aux != sym {
+ break
+ }
+ _ = v_1.Args[2]
+ if ptr != v_1.Args[0] {
+ break
+ }
+ val := v_1.Args[1]
+ v.reset(OpARM64FMOVSfpgp)
+ v.AddArg(val)
+ return true
+ }
// match: (MOVWUload [off1] {sym} (ADDconst [off2] ptr) mem)
// cond: is32Bit(off1+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
// result: (MOVWUload [off1+off2] {sym} ptr mem)
@@ -14683,6 +17084,28 @@ func rewriteValueARM64_OpARM64MOVWstore_0(v *Value) bool {
_ = b
config := b.Func.Config
_ = config
+ // match: (MOVWstore [off] {sym} ptr (FMOVSfpgp val) mem)
+ // cond:
+ // result: (FMOVSstore [off] {sym} ptr val mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[2]
+ ptr := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64FMOVSfpgp {
+ break
+ }
+ val := v_1.Args[0]
+ mem := v.Args[2]
+ v.reset(OpARM64FMOVSstore)
+ v.AuxInt = off
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
// match: (MOVWstore [off1] {sym} (ADDconst [off2] ptr) val mem)
// cond: is32Bit(off1+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_shared)
// result: (MOVWstore [off1+off2] {sym} ptr val mem)
@@ -14946,6 +17369,11 @@ func rewriteValueARM64_OpARM64MOVWstore_0(v *Value) bool {
v.AddArg(mem)
return true
}
+ return false
+}
+func rewriteValueARM64_OpARM64MOVWstore_10(v *Value) bool {
+ b := v.Block
+ _ = b
// match: (MOVWstore [4] {s} (ADDshiftLL [2] ptr0 idx0) (SRLconst [32] w) x:(MOVWstoreidx4 ptr1 idx1 w mem))
// cond: x.Uses == 1 && s == nil && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) && clobber(x)
// result: (MOVDstoreidx ptr1 (SLLconst <idx1.Type> [2] idx1) w mem)
@@ -14997,11 +17425,6 @@ func rewriteValueARM64_OpARM64MOVWstore_0(v *Value) bool {
v.AddArg(mem)
return true
}
- return false
-}
-func rewriteValueARM64_OpARM64MOVWstore_10(v *Value) bool {
- b := v.Block
- _ = b
// match: (MOVWstore [i] {s} ptr0 (SRLconst [j] w) x:(MOVWstore [i-4] {s} ptr1 w0:(SRLconst [j-32] w) mem))
// cond: x.Uses == 1 && isSamePtr(ptr0, ptr1) && clobber(x)
// result: (MOVDstore [i-4] {s} ptr0 w0 mem)
@@ -15784,6 +18207,1024 @@ func rewriteValueARM64_OpARM64MOVWstorezeroidx4_0(v *Value) bool {
}
return false
}
+func rewriteValueARM64_OpARM64MSUB_0(v *Value) bool {
+ b := v.Block
+ _ = b
+ // match: (MSUB a x (MOVDconst [-1]))
+ // cond:
+ // result: (ADD a x)
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ x := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_2.AuxInt != -1 {
+ break
+ }
+ v.reset(OpARM64ADD)
+ v.AddArg(a)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MSUB a _ (MOVDconst [0]))
+ // cond:
+ // result: a
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_2.AuxInt != 0 {
+ break
+ }
+ v.reset(OpCopy)
+ v.Type = a.Type
+ v.AddArg(a)
+ return true
+ }
+ // match: (MSUB a x (MOVDconst [1]))
+ // cond:
+ // result: (SUB a x)
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ x := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_2.AuxInt != 1 {
+ break
+ }
+ v.reset(OpARM64SUB)
+ v.AddArg(a)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MSUB a x (MOVDconst [c]))
+ // cond: isPowerOfTwo(c)
+ // result: (SUBshiftLL a x [log2(c)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ x := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_2.AuxInt
+ if !(isPowerOfTwo(c)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = log2(c)
+ v.AddArg(a)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MSUB a x (MOVDconst [c]))
+ // cond: isPowerOfTwo(c-1) && c>=3
+ // result: (SUB a (ADDshiftLL <x.Type> x x [log2(c-1)]))
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ x := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_2.AuxInt
+ if !(isPowerOfTwo(c-1) && c >= 3) {
+ break
+ }
+ v.reset(OpARM64SUB)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = log2(c - 1)
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MSUB a x (MOVDconst [c]))
+ // cond: isPowerOfTwo(c+1) && c>=7
+ // result: (ADD a (SUBshiftLL <x.Type> x x [log2(c+1)]))
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ x := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_2.AuxInt
+ if !(isPowerOfTwo(c+1) && c >= 7) {
+ break
+ }
+ v.reset(OpARM64ADD)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = log2(c + 1)
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MSUB a x (MOVDconst [c]))
+ // cond: c%3 == 0 && isPowerOfTwo(c/3)
+ // result: (ADDshiftLL a (SUBshiftLL <x.Type> x x [2]) [log2(c/3)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ x := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_2.AuxInt
+ if !(c%3 == 0 && isPowerOfTwo(c/3)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = log2(c / 3)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = 2
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MSUB a x (MOVDconst [c]))
+ // cond: c%5 == 0 && isPowerOfTwo(c/5)
+ // result: (SUBshiftLL a (ADDshiftLL <x.Type> x x [2]) [log2(c/5)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ x := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_2.AuxInt
+ if !(c%5 == 0 && isPowerOfTwo(c/5)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = log2(c / 5)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = 2
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MSUB a x (MOVDconst [c]))
+ // cond: c%7 == 0 && isPowerOfTwo(c/7)
+ // result: (ADDshiftLL a (SUBshiftLL <x.Type> x x [3]) [log2(c/7)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ x := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_2.AuxInt
+ if !(c%7 == 0 && isPowerOfTwo(c/7)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = log2(c / 7)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = 3
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MSUB a x (MOVDconst [c]))
+ // cond: c%9 == 0 && isPowerOfTwo(c/9)
+ // result: (SUBshiftLL a (ADDshiftLL <x.Type> x x [3]) [log2(c/9)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ x := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_2.AuxInt
+ if !(c%9 == 0 && isPowerOfTwo(c/9)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = log2(c / 9)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = 3
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MSUB_10(v *Value) bool {
+ b := v.Block
+ _ = b
+ // match: (MSUB a (MOVDconst [-1]) x)
+ // cond:
+ // result: (ADD a x)
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_1.AuxInt != -1 {
+ break
+ }
+ x := v.Args[2]
+ v.reset(OpARM64ADD)
+ v.AddArg(a)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MSUB a (MOVDconst [0]) _)
+ // cond:
+ // result: a
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_1.AuxInt != 0 {
+ break
+ }
+ v.reset(OpCopy)
+ v.Type = a.Type
+ v.AddArg(a)
+ return true
+ }
+ // match: (MSUB a (MOVDconst [1]) x)
+ // cond:
+ // result: (SUB a x)
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_1.AuxInt != 1 {
+ break
+ }
+ x := v.Args[2]
+ v.reset(OpARM64SUB)
+ v.AddArg(a)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MSUB a (MOVDconst [c]) x)
+ // cond: isPowerOfTwo(c)
+ // result: (SUBshiftLL a x [log2(c)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ x := v.Args[2]
+ if !(isPowerOfTwo(c)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = log2(c)
+ v.AddArg(a)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MSUB a (MOVDconst [c]) x)
+ // cond: isPowerOfTwo(c-1) && c>=3
+ // result: (SUB a (ADDshiftLL <x.Type> x x [log2(c-1)]))
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ x := v.Args[2]
+ if !(isPowerOfTwo(c-1) && c >= 3) {
+ break
+ }
+ v.reset(OpARM64SUB)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = log2(c - 1)
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MSUB a (MOVDconst [c]) x)
+ // cond: isPowerOfTwo(c+1) && c>=7
+ // result: (ADD a (SUBshiftLL <x.Type> x x [log2(c+1)]))
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ x := v.Args[2]
+ if !(isPowerOfTwo(c+1) && c >= 7) {
+ break
+ }
+ v.reset(OpARM64ADD)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = log2(c + 1)
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MSUB a (MOVDconst [c]) x)
+ // cond: c%3 == 0 && isPowerOfTwo(c/3)
+ // result: (ADDshiftLL a (SUBshiftLL <x.Type> x x [2]) [log2(c/3)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ x := v.Args[2]
+ if !(c%3 == 0 && isPowerOfTwo(c/3)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = log2(c / 3)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = 2
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MSUB a (MOVDconst [c]) x)
+ // cond: c%5 == 0 && isPowerOfTwo(c/5)
+ // result: (SUBshiftLL a (ADDshiftLL <x.Type> x x [2]) [log2(c/5)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ x := v.Args[2]
+ if !(c%5 == 0 && isPowerOfTwo(c/5)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = log2(c / 5)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = 2
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MSUB a (MOVDconst [c]) x)
+ // cond: c%7 == 0 && isPowerOfTwo(c/7)
+ // result: (ADDshiftLL a (SUBshiftLL <x.Type> x x [3]) [log2(c/7)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ x := v.Args[2]
+ if !(c%7 == 0 && isPowerOfTwo(c/7)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = log2(c / 7)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = 3
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MSUB a (MOVDconst [c]) x)
+ // cond: c%9 == 0 && isPowerOfTwo(c/9)
+ // result: (SUBshiftLL a (ADDshiftLL <x.Type> x x [3]) [log2(c/9)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ x := v.Args[2]
+ if !(c%9 == 0 && isPowerOfTwo(c/9)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = log2(c / 9)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = 3
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MSUB_20(v *Value) bool {
+ b := v.Block
+ _ = b
+ // match: (MSUB (MOVDconst [c]) x y)
+ // cond:
+ // result: (ADDconst [c] (MNEG <x.Type> x y))
+ for {
+ _ = v.Args[2]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_0.AuxInt
+ x := v.Args[1]
+ y := v.Args[2]
+ v.reset(OpARM64ADDconst)
+ v.AuxInt = c
+ v0 := b.NewValue0(v.Pos, OpARM64MNEG, x.Type)
+ v0.AddArg(x)
+ v0.AddArg(y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MSUB a (MOVDconst [c]) (MOVDconst [d]))
+ // cond:
+ // result: (SUBconst [c*d] a)
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ d := v_2.AuxInt
+ v.reset(OpARM64SUBconst)
+ v.AuxInt = c * d
+ v.AddArg(a)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MSUBW_0(v *Value) bool {
+ b := v.Block
+ _ = b
+ // match: (MSUBW a x (MOVDconst [c]))
+ // cond: int32(c)==-1
+ // result: (ADD a x)
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ x := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_2.AuxInt
+ if !(int32(c) == -1) {
+ break
+ }
+ v.reset(OpARM64ADD)
+ v.AddArg(a)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MSUBW a _ (MOVDconst [c]))
+ // cond: int32(c)==0
+ // result: a
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_2.AuxInt
+ if !(int32(c) == 0) {
+ break
+ }
+ v.reset(OpCopy)
+ v.Type = a.Type
+ v.AddArg(a)
+ return true
+ }
+ // match: (MSUBW a x (MOVDconst [c]))
+ // cond: int32(c)==1
+ // result: (SUB a x)
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ x := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_2.AuxInt
+ if !(int32(c) == 1) {
+ break
+ }
+ v.reset(OpARM64SUB)
+ v.AddArg(a)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MSUBW a x (MOVDconst [c]))
+ // cond: isPowerOfTwo(c)
+ // result: (SUBshiftLL a x [log2(c)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ x := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_2.AuxInt
+ if !(isPowerOfTwo(c)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = log2(c)
+ v.AddArg(a)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MSUBW a x (MOVDconst [c]))
+ // cond: isPowerOfTwo(c-1) && int32(c)>=3
+ // result: (SUB a (ADDshiftLL <x.Type> x x [log2(c-1)]))
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ x := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_2.AuxInt
+ if !(isPowerOfTwo(c-1) && int32(c) >= 3) {
+ break
+ }
+ v.reset(OpARM64SUB)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = log2(c - 1)
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MSUBW a x (MOVDconst [c]))
+ // cond: isPowerOfTwo(c+1) && int32(c)>=7
+ // result: (ADD a (SUBshiftLL <x.Type> x x [log2(c+1)]))
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ x := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_2.AuxInt
+ if !(isPowerOfTwo(c+1) && int32(c) >= 7) {
+ break
+ }
+ v.reset(OpARM64ADD)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = log2(c + 1)
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MSUBW a x (MOVDconst [c]))
+ // cond: c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c)
+ // result: (ADDshiftLL a (SUBshiftLL <x.Type> x x [2]) [log2(c/3)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ x := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_2.AuxInt
+ if !(c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = log2(c / 3)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = 2
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MSUBW a x (MOVDconst [c]))
+ // cond: c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c)
+ // result: (SUBshiftLL a (ADDshiftLL <x.Type> x x [2]) [log2(c/5)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ x := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_2.AuxInt
+ if !(c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = log2(c / 5)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = 2
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MSUBW a x (MOVDconst [c]))
+ // cond: c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c)
+ // result: (ADDshiftLL a (SUBshiftLL <x.Type> x x [3]) [log2(c/7)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ x := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_2.AuxInt
+ if !(c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = log2(c / 7)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = 3
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MSUBW a x (MOVDconst [c]))
+ // cond: c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c)
+ // result: (SUBshiftLL a (ADDshiftLL <x.Type> x x [3]) [log2(c/9)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ x := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_2.AuxInt
+ if !(c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = log2(c / 9)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = 3
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MSUBW_10(v *Value) bool {
+ b := v.Block
+ _ = b
+ // match: (MSUBW a (MOVDconst [c]) x)
+ // cond: int32(c)==-1
+ // result: (ADD a x)
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ x := v.Args[2]
+ if !(int32(c) == -1) {
+ break
+ }
+ v.reset(OpARM64ADD)
+ v.AddArg(a)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MSUBW a (MOVDconst [c]) _)
+ // cond: int32(c)==0
+ // result: a
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ if !(int32(c) == 0) {
+ break
+ }
+ v.reset(OpCopy)
+ v.Type = a.Type
+ v.AddArg(a)
+ return true
+ }
+ // match: (MSUBW a (MOVDconst [c]) x)
+ // cond: int32(c)==1
+ // result: (SUB a x)
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ x := v.Args[2]
+ if !(int32(c) == 1) {
+ break
+ }
+ v.reset(OpARM64SUB)
+ v.AddArg(a)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MSUBW a (MOVDconst [c]) x)
+ // cond: isPowerOfTwo(c)
+ // result: (SUBshiftLL a x [log2(c)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ x := v.Args[2]
+ if !(isPowerOfTwo(c)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = log2(c)
+ v.AddArg(a)
+ v.AddArg(x)
+ return true
+ }
+ // match: (MSUBW a (MOVDconst [c]) x)
+ // cond: isPowerOfTwo(c-1) && int32(c)>=3
+ // result: (SUB a (ADDshiftLL <x.Type> x x [log2(c-1)]))
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ x := v.Args[2]
+ if !(isPowerOfTwo(c-1) && int32(c) >= 3) {
+ break
+ }
+ v.reset(OpARM64SUB)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = log2(c - 1)
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MSUBW a (MOVDconst [c]) x)
+ // cond: isPowerOfTwo(c+1) && int32(c)>=7
+ // result: (ADD a (SUBshiftLL <x.Type> x x [log2(c+1)]))
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ x := v.Args[2]
+ if !(isPowerOfTwo(c+1) && int32(c) >= 7) {
+ break
+ }
+ v.reset(OpARM64ADD)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = log2(c + 1)
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MSUBW a (MOVDconst [c]) x)
+ // cond: c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c)
+ // result: (ADDshiftLL a (SUBshiftLL <x.Type> x x [2]) [log2(c/3)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ x := v.Args[2]
+ if !(c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = log2(c / 3)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = 2
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MSUBW a (MOVDconst [c]) x)
+ // cond: c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c)
+ // result: (SUBshiftLL a (ADDshiftLL <x.Type> x x [2]) [log2(c/5)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ x := v.Args[2]
+ if !(c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = log2(c / 5)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = 2
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MSUBW a (MOVDconst [c]) x)
+ // cond: c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c)
+ // result: (ADDshiftLL a (SUBshiftLL <x.Type> x x [3]) [log2(c/7)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ x := v.Args[2]
+ if !(c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64ADDshiftLL)
+ v.AuxInt = log2(c / 7)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64SUBshiftLL, x.Type)
+ v0.AuxInt = 3
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MSUBW a (MOVDconst [c]) x)
+ // cond: c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c)
+ // result: (SUBshiftLL a (ADDshiftLL <x.Type> x x [3]) [log2(c/9)])
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ x := v.Args[2]
+ if !(c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c)) {
+ break
+ }
+ v.reset(OpARM64SUBshiftLL)
+ v.AuxInt = log2(c / 9)
+ v.AddArg(a)
+ v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type)
+ v0.AuxInt = 3
+ v0.AddArg(x)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MSUBW_20(v *Value) bool {
+ b := v.Block
+ _ = b
+ // match: (MSUBW (MOVDconst [c]) x y)
+ // cond:
+ // result: (ADDconst [c] (MNEGW <x.Type> x y))
+ for {
+ _ = v.Args[2]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_0.AuxInt
+ x := v.Args[1]
+ y := v.Args[2]
+ v.reset(OpARM64ADDconst)
+ v.AuxInt = c
+ v0 := b.NewValue0(v.Pos, OpARM64MNEGW, x.Type)
+ v0.AddArg(x)
+ v0.AddArg(y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MSUBW a (MOVDconst [c]) (MOVDconst [d]))
+ // cond:
+ // result: (SUBconst [int64(int32(c)*int32(d))] a)
+ for {
+ _ = v.Args[2]
+ a := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ v_2 := v.Args[2]
+ if v_2.Op != OpARM64MOVDconst {
+ break
+ }
+ d := v_2.AuxInt
+ v.reset(OpARM64SUBconst)
+ v.AuxInt = int64(int32(c) * int32(d))
+ v.AddArg(a)
+ return true
+ }
+ return false
+}
func rewriteValueARM64_OpARM64MUL_0(v *Value) bool {
// match: (MUL (NEG x) y)
// cond:
@@ -16794,6 +20235,111 @@ func rewriteValueARM64_OpARM64MVN_0(v *Value) bool {
v.AuxInt = ^c
return true
}
+ // match: (MVN x:(SLLconst [c] y))
+ // cond: clobberIfDead(x)
+ // result: (MVNshiftLL [c] y)
+ for {
+ x := v.Args[0]
+ if x.Op != OpARM64SLLconst {
+ break
+ }
+ c := x.AuxInt
+ y := x.Args[0]
+ if !(clobberIfDead(x)) {
+ break
+ }
+ v.reset(OpARM64MVNshiftLL)
+ v.AuxInt = c
+ v.AddArg(y)
+ return true
+ }
+ // match: (MVN x:(SRLconst [c] y))
+ // cond: clobberIfDead(x)
+ // result: (MVNshiftRL [c] y)
+ for {
+ x := v.Args[0]
+ if x.Op != OpARM64SRLconst {
+ break
+ }
+ c := x.AuxInt
+ y := x.Args[0]
+ if !(clobberIfDead(x)) {
+ break
+ }
+ v.reset(OpARM64MVNshiftRL)
+ v.AuxInt = c
+ v.AddArg(y)
+ return true
+ }
+ // match: (MVN x:(SRAconst [c] y))
+ // cond: clobberIfDead(x)
+ // result: (MVNshiftRA [c] y)
+ for {
+ x := v.Args[0]
+ if x.Op != OpARM64SRAconst {
+ break
+ }
+ c := x.AuxInt
+ y := x.Args[0]
+ if !(clobberIfDead(x)) {
+ break
+ }
+ v.reset(OpARM64MVNshiftRA)
+ v.AuxInt = c
+ v.AddArg(y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MVNshiftLL_0(v *Value) bool {
+ // match: (MVNshiftLL (MOVDconst [c]) [d])
+ // cond:
+ // result: (MOVDconst [^int64(uint64(c)<<uint64(d))])
+ for {
+ d := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_0.AuxInt
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = ^int64(uint64(c) << uint64(d))
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MVNshiftRA_0(v *Value) bool {
+ // match: (MVNshiftRA (MOVDconst [c]) [d])
+ // cond:
+ // result: (MOVDconst [^(c>>uint64(d))])
+ for {
+ d := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_0.AuxInt
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = ^(c >> uint64(d))
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64MVNshiftRL_0(v *Value) bool {
+ // match: (MVNshiftRL (MOVDconst [c]) [d])
+ // cond:
+ // result: (MOVDconst [^int64(uint64(c)>>uint64(d))])
+ for {
+ d := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_0.AuxInt
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = ^int64(uint64(c) >> uint64(d))
+ return true
+ }
return false
}
func rewriteValueARM64_OpARM64NEG_0(v *Value) bool {
@@ -16842,6 +20388,111 @@ func rewriteValueARM64_OpARM64NEG_0(v *Value) bool {
v.AuxInt = -c
return true
}
+ // match: (NEG x:(SLLconst [c] y))
+ // cond: clobberIfDead(x)
+ // result: (NEGshiftLL [c] y)
+ for {
+ x := v.Args[0]
+ if x.Op != OpARM64SLLconst {
+ break
+ }
+ c := x.AuxInt
+ y := x.Args[0]
+ if !(clobberIfDead(x)) {
+ break
+ }
+ v.reset(OpARM64NEGshiftLL)
+ v.AuxInt = c
+ v.AddArg(y)
+ return true
+ }
+ // match: (NEG x:(SRLconst [c] y))
+ // cond: clobberIfDead(x)
+ // result: (NEGshiftRL [c] y)
+ for {
+ x := v.Args[0]
+ if x.Op != OpARM64SRLconst {
+ break
+ }
+ c := x.AuxInt
+ y := x.Args[0]
+ if !(clobberIfDead(x)) {
+ break
+ }
+ v.reset(OpARM64NEGshiftRL)
+ v.AuxInt = c
+ v.AddArg(y)
+ return true
+ }
+ // match: (NEG x:(SRAconst [c] y))
+ // cond: clobberIfDead(x)
+ // result: (NEGshiftRA [c] y)
+ for {
+ x := v.Args[0]
+ if x.Op != OpARM64SRAconst {
+ break
+ }
+ c := x.AuxInt
+ y := x.Args[0]
+ if !(clobberIfDead(x)) {
+ break
+ }
+ v.reset(OpARM64NEGshiftRA)
+ v.AuxInt = c
+ v.AddArg(y)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64NEGshiftLL_0(v *Value) bool {
+ // match: (NEGshiftLL (MOVDconst [c]) [d])
+ // cond:
+ // result: (MOVDconst [-int64(uint64(c)<<uint64(d))])
+ for {
+ d := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_0.AuxInt
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = -int64(uint64(c) << uint64(d))
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64NEGshiftRA_0(v *Value) bool {
+ // match: (NEGshiftRA (MOVDconst [c]) [d])
+ // cond:
+ // result: (MOVDconst [-(c>>uint64(d))])
+ for {
+ d := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_0.AuxInt
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = -(c >> uint64(d))
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64NEGshiftRL_0(v *Value) bool {
+ // match: (NEGshiftRL (MOVDconst [c]) [d])
+ // cond:
+ // result: (MOVDconst [-int64(uint64(c)>>uint64(d))])
+ for {
+ d := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_0.AuxInt
+ v.reset(OpARM64MOVDconst)
+ v.AuxInt = -int64(uint64(c) >> uint64(d))
+ return true
+ }
return false
}
func rewriteValueARM64_OpARM64NotEqual_0(v *Value) bool {
@@ -17109,6 +20760,8 @@ func rewriteValueARM64_OpARM64OR_0(v *Value) bool {
func rewriteValueARM64_OpARM64OR_10(v *Value) bool {
b := v.Block
_ = b
+ typ := &b.Func.Config.Types
+ _ = typ
// match: (OR x1:(SRAconst [c] y) x0)
// cond: clobberIfDead(x1)
// result: (ORshiftRA x0 y [c])
@@ -17130,6 +20783,918 @@ func rewriteValueARM64_OpARM64OR_10(v *Value) bool {
v.AddArg(y)
return true
}
+ // match: (OR (SLL x (ANDconst <t> [63] y)) (CSEL0 <typ.UInt64> {cc} (SRL <typ.UInt64> x (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y))) (CMPconst [64] (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y)))))
+ // cond: cc.(Op) == OpARM64LessThanU
+ // result: (ROR x (NEG <t> y))
+ for {
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64SLL {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARM64ANDconst {
+ break
+ }
+ t := v_0_1.Type
+ if v_0_1.AuxInt != 63 {
+ break
+ }
+ y := v_0_1.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64CSEL0 {
+ break
+ }
+ if v_1.Type != typ.UInt64 {
+ break
+ }
+ cc := v_1.Aux
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpARM64SRL {
+ break
+ }
+ if v_1_0.Type != typ.UInt64 {
+ break
+ }
+ _ = v_1_0.Args[1]
+ if x != v_1_0.Args[0] {
+ break
+ }
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpARM64SUB {
+ break
+ }
+ if v_1_0_1.Type != t {
+ break
+ }
+ _ = v_1_0_1.Args[1]
+ v_1_0_1_0 := v_1_0_1.Args[0]
+ if v_1_0_1_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_1_0_1_0.AuxInt != 64 {
+ break
+ }
+ v_1_0_1_1 := v_1_0_1.Args[1]
+ if v_1_0_1_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_1_0_1_1.Type != t {
+ break
+ }
+ if v_1_0_1_1.AuxInt != 63 {
+ break
+ }
+ if y != v_1_0_1_1.Args[0] {
+ break
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpARM64CMPconst {
+ break
+ }
+ if v_1_1.AuxInt != 64 {
+ break
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpARM64SUB {
+ break
+ }
+ if v_1_1_0.Type != t {
+ break
+ }
+ _ = v_1_1_0.Args[1]
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_1_1_0_0.AuxInt != 64 {
+ break
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_1_1_0_1.Type != t {
+ break
+ }
+ if v_1_1_0_1.AuxInt != 63 {
+ break
+ }
+ if y != v_1_1_0_1.Args[0] {
+ break
+ }
+ if !(cc.(Op) == OpARM64LessThanU) {
+ break
+ }
+ v.reset(OpARM64ROR)
+ v.AddArg(x)
+ v0 := b.NewValue0(v.Pos, OpARM64NEG, t)
+ v0.AddArg(y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (OR (CSEL0 <typ.UInt64> {cc} (SRL <typ.UInt64> x (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y))) (CMPconst [64] (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y)))) (SLL x (ANDconst <t> [63] y)))
+ // cond: cc.(Op) == OpARM64LessThanU
+ // result: (ROR x (NEG <t> y))
+ for {
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64CSEL0 {
+ break
+ }
+ if v_0.Type != typ.UInt64 {
+ break
+ }
+ cc := v_0.Aux
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARM64SRL {
+ break
+ }
+ if v_0_0.Type != typ.UInt64 {
+ break
+ }
+ _ = v_0_0.Args[1]
+ x := v_0_0.Args[0]
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpARM64SUB {
+ break
+ }
+ t := v_0_0_1.Type
+ _ = v_0_0_1.Args[1]
+ v_0_0_1_0 := v_0_0_1.Args[0]
+ if v_0_0_1_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_0_0_1_0.AuxInt != 64 {
+ break
+ }
+ v_0_0_1_1 := v_0_0_1.Args[1]
+ if v_0_0_1_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_0_0_1_1.Type != t {
+ break
+ }
+ if v_0_0_1_1.AuxInt != 63 {
+ break
+ }
+ y := v_0_0_1_1.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARM64CMPconst {
+ break
+ }
+ if v_0_1.AuxInt != 64 {
+ break
+ }
+ v_0_1_0 := v_0_1.Args[0]
+ if v_0_1_0.Op != OpARM64SUB {
+ break
+ }
+ if v_0_1_0.Type != t {
+ break
+ }
+ _ = v_0_1_0.Args[1]
+ v_0_1_0_0 := v_0_1_0.Args[0]
+ if v_0_1_0_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_0_1_0_0.AuxInt != 64 {
+ break
+ }
+ v_0_1_0_1 := v_0_1_0.Args[1]
+ if v_0_1_0_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_0_1_0_1.Type != t {
+ break
+ }
+ if v_0_1_0_1.AuxInt != 63 {
+ break
+ }
+ if y != v_0_1_0_1.Args[0] {
+ break
+ }
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64SLL {
+ break
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ break
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_1_1.Type != t {
+ break
+ }
+ if v_1_1.AuxInt != 63 {
+ break
+ }
+ if y != v_1_1.Args[0] {
+ break
+ }
+ if !(cc.(Op) == OpARM64LessThanU) {
+ break
+ }
+ v.reset(OpARM64ROR)
+ v.AddArg(x)
+ v0 := b.NewValue0(v.Pos, OpARM64NEG, t)
+ v0.AddArg(y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (OR (SRL <typ.UInt64> x (ANDconst <t> [63] y)) (CSEL0 <typ.UInt64> {cc} (SLL x (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y))) (CMPconst [64] (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y)))))
+ // cond: cc.(Op) == OpARM64LessThanU
+ // result: (ROR x y)
+ for {
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64SRL {
+ break
+ }
+ if v_0.Type != typ.UInt64 {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARM64ANDconst {
+ break
+ }
+ t := v_0_1.Type
+ if v_0_1.AuxInt != 63 {
+ break
+ }
+ y := v_0_1.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64CSEL0 {
+ break
+ }
+ if v_1.Type != typ.UInt64 {
+ break
+ }
+ cc := v_1.Aux
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpARM64SLL {
+ break
+ }
+ _ = v_1_0.Args[1]
+ if x != v_1_0.Args[0] {
+ break
+ }
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpARM64SUB {
+ break
+ }
+ if v_1_0_1.Type != t {
+ break
+ }
+ _ = v_1_0_1.Args[1]
+ v_1_0_1_0 := v_1_0_1.Args[0]
+ if v_1_0_1_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_1_0_1_0.AuxInt != 64 {
+ break
+ }
+ v_1_0_1_1 := v_1_0_1.Args[1]
+ if v_1_0_1_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_1_0_1_1.Type != t {
+ break
+ }
+ if v_1_0_1_1.AuxInt != 63 {
+ break
+ }
+ if y != v_1_0_1_1.Args[0] {
+ break
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpARM64CMPconst {
+ break
+ }
+ if v_1_1.AuxInt != 64 {
+ break
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpARM64SUB {
+ break
+ }
+ if v_1_1_0.Type != t {
+ break
+ }
+ _ = v_1_1_0.Args[1]
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_1_1_0_0.AuxInt != 64 {
+ break
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_1_1_0_1.Type != t {
+ break
+ }
+ if v_1_1_0_1.AuxInt != 63 {
+ break
+ }
+ if y != v_1_1_0_1.Args[0] {
+ break
+ }
+ if !(cc.(Op) == OpARM64LessThanU) {
+ break
+ }
+ v.reset(OpARM64ROR)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+ // match: (OR (CSEL0 <typ.UInt64> {cc} (SLL x (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y))) (CMPconst [64] (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y)))) (SRL <typ.UInt64> x (ANDconst <t> [63] y)))
+ // cond: cc.(Op) == OpARM64LessThanU
+ // result: (ROR x y)
+ for {
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64CSEL0 {
+ break
+ }
+ if v_0.Type != typ.UInt64 {
+ break
+ }
+ cc := v_0.Aux
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARM64SLL {
+ break
+ }
+ _ = v_0_0.Args[1]
+ x := v_0_0.Args[0]
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpARM64SUB {
+ break
+ }
+ t := v_0_0_1.Type
+ _ = v_0_0_1.Args[1]
+ v_0_0_1_0 := v_0_0_1.Args[0]
+ if v_0_0_1_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_0_0_1_0.AuxInt != 64 {
+ break
+ }
+ v_0_0_1_1 := v_0_0_1.Args[1]
+ if v_0_0_1_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_0_0_1_1.Type != t {
+ break
+ }
+ if v_0_0_1_1.AuxInt != 63 {
+ break
+ }
+ y := v_0_0_1_1.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARM64CMPconst {
+ break
+ }
+ if v_0_1.AuxInt != 64 {
+ break
+ }
+ v_0_1_0 := v_0_1.Args[0]
+ if v_0_1_0.Op != OpARM64SUB {
+ break
+ }
+ if v_0_1_0.Type != t {
+ break
+ }
+ _ = v_0_1_0.Args[1]
+ v_0_1_0_0 := v_0_1_0.Args[0]
+ if v_0_1_0_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_0_1_0_0.AuxInt != 64 {
+ break
+ }
+ v_0_1_0_1 := v_0_1_0.Args[1]
+ if v_0_1_0_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_0_1_0_1.Type != t {
+ break
+ }
+ if v_0_1_0_1.AuxInt != 63 {
+ break
+ }
+ if y != v_0_1_0_1.Args[0] {
+ break
+ }
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64SRL {
+ break
+ }
+ if v_1.Type != typ.UInt64 {
+ break
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ break
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_1_1.Type != t {
+ break
+ }
+ if v_1_1.AuxInt != 63 {
+ break
+ }
+ if y != v_1_1.Args[0] {
+ break
+ }
+ if !(cc.(Op) == OpARM64LessThanU) {
+ break
+ }
+ v.reset(OpARM64ROR)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+ // match: (OR (SLL x (ANDconst <t> [31] y)) (CSEL0 <typ.UInt32> {cc} (SRL <typ.UInt32> (MOVWUreg x) (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y))) (CMPconst [64] (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y)))))
+ // cond: cc.(Op) == OpARM64LessThanU
+ // result: (RORW x (NEG <t> y))
+ for {
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64SLL {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARM64ANDconst {
+ break
+ }
+ t := v_0_1.Type
+ if v_0_1.AuxInt != 31 {
+ break
+ }
+ y := v_0_1.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64CSEL0 {
+ break
+ }
+ if v_1.Type != typ.UInt32 {
+ break
+ }
+ cc := v_1.Aux
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpARM64SRL {
+ break
+ }
+ if v_1_0.Type != typ.UInt32 {
+ break
+ }
+ _ = v_1_0.Args[1]
+ v_1_0_0 := v_1_0.Args[0]
+ if v_1_0_0.Op != OpARM64MOVWUreg {
+ break
+ }
+ if x != v_1_0_0.Args[0] {
+ break
+ }
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpARM64SUB {
+ break
+ }
+ if v_1_0_1.Type != t {
+ break
+ }
+ _ = v_1_0_1.Args[1]
+ v_1_0_1_0 := v_1_0_1.Args[0]
+ if v_1_0_1_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_1_0_1_0.AuxInt != 32 {
+ break
+ }
+ v_1_0_1_1 := v_1_0_1.Args[1]
+ if v_1_0_1_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_1_0_1_1.Type != t {
+ break
+ }
+ if v_1_0_1_1.AuxInt != 31 {
+ break
+ }
+ if y != v_1_0_1_1.Args[0] {
+ break
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpARM64CMPconst {
+ break
+ }
+ if v_1_1.AuxInt != 64 {
+ break
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpARM64SUB {
+ break
+ }
+ if v_1_1_0.Type != t {
+ break
+ }
+ _ = v_1_1_0.Args[1]
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_1_1_0_0.AuxInt != 32 {
+ break
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_1_1_0_1.Type != t {
+ break
+ }
+ if v_1_1_0_1.AuxInt != 31 {
+ break
+ }
+ if y != v_1_1_0_1.Args[0] {
+ break
+ }
+ if !(cc.(Op) == OpARM64LessThanU) {
+ break
+ }
+ v.reset(OpARM64RORW)
+ v.AddArg(x)
+ v0 := b.NewValue0(v.Pos, OpARM64NEG, t)
+ v0.AddArg(y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (OR (CSEL0 <typ.UInt32> {cc} (SRL <typ.UInt32> (MOVWUreg x) (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y))) (CMPconst [64] (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y)))) (SLL x (ANDconst <t> [31] y)))
+ // cond: cc.(Op) == OpARM64LessThanU
+ // result: (RORW x (NEG <t> y))
+ for {
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64CSEL0 {
+ break
+ }
+ if v_0.Type != typ.UInt32 {
+ break
+ }
+ cc := v_0.Aux
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARM64SRL {
+ break
+ }
+ if v_0_0.Type != typ.UInt32 {
+ break
+ }
+ _ = v_0_0.Args[1]
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpARM64MOVWUreg {
+ break
+ }
+ x := v_0_0_0.Args[0]
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpARM64SUB {
+ break
+ }
+ t := v_0_0_1.Type
+ _ = v_0_0_1.Args[1]
+ v_0_0_1_0 := v_0_0_1.Args[0]
+ if v_0_0_1_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_0_0_1_0.AuxInt != 32 {
+ break
+ }
+ v_0_0_1_1 := v_0_0_1.Args[1]
+ if v_0_0_1_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_0_0_1_1.Type != t {
+ break
+ }
+ if v_0_0_1_1.AuxInt != 31 {
+ break
+ }
+ y := v_0_0_1_1.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARM64CMPconst {
+ break
+ }
+ if v_0_1.AuxInt != 64 {
+ break
+ }
+ v_0_1_0 := v_0_1.Args[0]
+ if v_0_1_0.Op != OpARM64SUB {
+ break
+ }
+ if v_0_1_0.Type != t {
+ break
+ }
+ _ = v_0_1_0.Args[1]
+ v_0_1_0_0 := v_0_1_0.Args[0]
+ if v_0_1_0_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_0_1_0_0.AuxInt != 32 {
+ break
+ }
+ v_0_1_0_1 := v_0_1_0.Args[1]
+ if v_0_1_0_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_0_1_0_1.Type != t {
+ break
+ }
+ if v_0_1_0_1.AuxInt != 31 {
+ break
+ }
+ if y != v_0_1_0_1.Args[0] {
+ break
+ }
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64SLL {
+ break
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ break
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_1_1.Type != t {
+ break
+ }
+ if v_1_1.AuxInt != 31 {
+ break
+ }
+ if y != v_1_1.Args[0] {
+ break
+ }
+ if !(cc.(Op) == OpARM64LessThanU) {
+ break
+ }
+ v.reset(OpARM64RORW)
+ v.AddArg(x)
+ v0 := b.NewValue0(v.Pos, OpARM64NEG, t)
+ v0.AddArg(y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (OR (SRL <typ.UInt32> (MOVWUreg x) (ANDconst <t> [31] y)) (CSEL0 <typ.UInt32> {cc} (SLL x (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y))) (CMPconst [64] (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y)))))
+ // cond: cc.(Op) == OpARM64LessThanU
+ // result: (RORW x y)
+ for {
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64SRL {
+ break
+ }
+ if v_0.Type != typ.UInt32 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARM64MOVWUreg {
+ break
+ }
+ x := v_0_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARM64ANDconst {
+ break
+ }
+ t := v_0_1.Type
+ if v_0_1.AuxInt != 31 {
+ break
+ }
+ y := v_0_1.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64CSEL0 {
+ break
+ }
+ if v_1.Type != typ.UInt32 {
+ break
+ }
+ cc := v_1.Aux
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpARM64SLL {
+ break
+ }
+ _ = v_1_0.Args[1]
+ if x != v_1_0.Args[0] {
+ break
+ }
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpARM64SUB {
+ break
+ }
+ if v_1_0_1.Type != t {
+ break
+ }
+ _ = v_1_0_1.Args[1]
+ v_1_0_1_0 := v_1_0_1.Args[0]
+ if v_1_0_1_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_1_0_1_0.AuxInt != 32 {
+ break
+ }
+ v_1_0_1_1 := v_1_0_1.Args[1]
+ if v_1_0_1_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_1_0_1_1.Type != t {
+ break
+ }
+ if v_1_0_1_1.AuxInt != 31 {
+ break
+ }
+ if y != v_1_0_1_1.Args[0] {
+ break
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpARM64CMPconst {
+ break
+ }
+ if v_1_1.AuxInt != 64 {
+ break
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpARM64SUB {
+ break
+ }
+ if v_1_1_0.Type != t {
+ break
+ }
+ _ = v_1_1_0.Args[1]
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_1_1_0_0.AuxInt != 32 {
+ break
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_1_1_0_1.Type != t {
+ break
+ }
+ if v_1_1_0_1.AuxInt != 31 {
+ break
+ }
+ if y != v_1_1_0_1.Args[0] {
+ break
+ }
+ if !(cc.(Op) == OpARM64LessThanU) {
+ break
+ }
+ v.reset(OpARM64RORW)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+ // match: (OR (CSEL0 <typ.UInt32> {cc} (SLL x (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y))) (CMPconst [64] (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y)))) (SRL <typ.UInt32> (MOVWUreg x) (ANDconst <t> [31] y)))
+ // cond: cc.(Op) == OpARM64LessThanU
+ // result: (RORW x y)
+ for {
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64CSEL0 {
+ break
+ }
+ if v_0.Type != typ.UInt32 {
+ break
+ }
+ cc := v_0.Aux
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARM64SLL {
+ break
+ }
+ _ = v_0_0.Args[1]
+ x := v_0_0.Args[0]
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpARM64SUB {
+ break
+ }
+ t := v_0_0_1.Type
+ _ = v_0_0_1.Args[1]
+ v_0_0_1_0 := v_0_0_1.Args[0]
+ if v_0_0_1_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_0_0_1_0.AuxInt != 32 {
+ break
+ }
+ v_0_0_1_1 := v_0_0_1.Args[1]
+ if v_0_0_1_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_0_0_1_1.Type != t {
+ break
+ }
+ if v_0_0_1_1.AuxInt != 31 {
+ break
+ }
+ y := v_0_0_1_1.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARM64CMPconst {
+ break
+ }
+ if v_0_1.AuxInt != 64 {
+ break
+ }
+ v_0_1_0 := v_0_1.Args[0]
+ if v_0_1_0.Op != OpARM64SUB {
+ break
+ }
+ if v_0_1_0.Type != t {
+ break
+ }
+ _ = v_0_1_0.Args[1]
+ v_0_1_0_0 := v_0_1_0.Args[0]
+ if v_0_1_0_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_0_1_0_0.AuxInt != 32 {
+ break
+ }
+ v_0_1_0_1 := v_0_1_0.Args[1]
+ if v_0_1_0_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_0_1_0_1.Type != t {
+ break
+ }
+ if v_0_1_0_1.AuxInt != 31 {
+ break
+ }
+ if y != v_0_1_0_1.Args[0] {
+ break
+ }
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64SRL {
+ break
+ }
+ if v_1.Type != typ.UInt32 {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpARM64MOVWUreg {
+ break
+ }
+ if x != v_1_0.Args[0] {
+ break
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_1_1.Type != t {
+ break
+ }
+ if v_1_1.AuxInt != 31 {
+ break
+ }
+ if y != v_1_1.Args[0] {
+ break
+ }
+ if !(cc.(Op) == OpARM64LessThanU) {
+ break
+ }
+ v.reset(OpARM64RORW)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
// match: (OR (UBFIZ [bfc] x) (ANDconst [ac] y))
// cond: ac == ^((1<<uint(getARM64BFwidth(bfc))-1) << uint(getARM64BFlsb(bfc)))
// result: (BFI [bfc] y x)
@@ -17156,6 +21721,11 @@ func rewriteValueARM64_OpARM64OR_10(v *Value) bool {
v.AddArg(x)
return true
}
+ return false
+}
+func rewriteValueARM64_OpARM64OR_20(v *Value) bool {
+ b := v.Block
+ _ = b
// match: (OR (ANDconst [ac] y) (UBFIZ [bfc] x))
// cond: ac == ^((1<<uint(getARM64BFwidth(bfc))-1) << uint(getARM64BFlsb(bfc)))
// result: (BFI [bfc] y x)
@@ -17822,11 +22392,6 @@ func rewriteValueARM64_OpARM64OR_10(v *Value) bool {
v0.AddArg(mem)
return true
}
- return false
-}
-func rewriteValueARM64_OpARM64OR_20(v *Value) bool {
- b := v.Block
- _ = b
// match: (OR <t> y3:(MOVDnop x3:(MOVBUloadidx ptr idx mem)) o0:(ORshiftLL [8] o1:(ORshiftLL [16] s0:(SLLconst [24] y0:(MOVDnop x0:(MOVBUloadidx ptr (ADDconst [3] idx) mem))) y1:(MOVDnop x1:(MOVBUloadidx ptr (ADDconst [2] idx) mem))) y2:(MOVDnop x2:(MOVBUloadidx ptr (ADDconst [1] idx) mem))))
// cond: x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && s0.Uses == 1 && mergePoint(b,x0,x1,x2,x3) != nil && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3) && clobber(y0) && clobber(y1) && clobber(y2) && clobber(y3) && clobber(o0) && clobber(o1) && clobber(s0)
// result: @mergePoint(b,x0,x1,x2,x3) (MOVWUloadidx <t> ptr idx mem)
@@ -18177,6 +22742,11 @@ func rewriteValueARM64_OpARM64OR_20(v *Value) bool {
v0.AddArg(mem)
return true
}
+ return false
+}
+func rewriteValueARM64_OpARM64OR_30(v *Value) bool {
+ b := v.Block
+ _ = b
// match: (OR <t> y7:(MOVDnop x7:(MOVBUload [i0] {s} p mem)) o0:(ORshiftLL [8] o1:(ORshiftLL [16] o2:(ORshiftLL [24] o3:(ORshiftLL [32] o4:(ORshiftLL [40] o5:(ORshiftLL [48] s0:(SLLconst [56] y0:(MOVDnop x0:(MOVBUload [i7] {s} p mem))) y1:(MOVDnop x1:(MOVBUload [i6] {s} p mem))) y2:(MOVDnop x2:(MOVBUload [i5] {s} p mem))) y3:(MOVDnop x3:(MOVBUload [i4] {s} p mem))) y4:(MOVDnop x4:(MOVBUload [i3] {s} p mem))) y5:(MOVDnop x5:(MOVBUload [i2] {s} p mem))) y6:(MOVDnop x6:(MOVBUload [i1] {s} p mem))))
// cond: i1 == i0+1 && i2 == i0+2 && i3 == i0+3 && i4 == i0+4 && i5 == i0+5 && i6 == i0+6 && i7 == i0+7 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && x7.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1 && y5.Uses == 1 && y6.Uses == 1 && y7.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && o3.Uses == 1 && o4.Uses == 1 && o5.Uses == 1 && s0.Uses == 1 && mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) != nil && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3) && clobber(x4) && clobber(x5) && clobber(x6) && clobber(x7) && clobber(y0) && clobber(y1) && clobber(y2) && clobber(y3) && clobber(y4) && clobber(y5) && clobber(y6) && clobber(y7) && clobber(o0) && clobber(o1) && clobber(o2) && clobber(o3) && clobber(o4) && clobber(o5) && clobber(s0)
// result: @mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) (MOVDload <t> {s} (OffPtr <p.Type> [i0] p) mem)
@@ -19733,11 +24303,6 @@ func rewriteValueARM64_OpARM64OR_20(v *Value) bool {
v0.AddArg(v1)
return true
}
- return false
-}
-func rewriteValueARM64_OpARM64OR_30(v *Value) bool {
- b := v.Block
- _ = b
// match: (OR <t> y3:(MOVDnop x3:(MOVBUload [3] {s} p mem)) o0:(ORshiftLL [8] o1:(ORshiftLL [16] s0:(SLLconst [24] y0:(MOVDnop x0:(MOVBUloadidx ptr0 idx0 mem))) y1:(MOVDnop x1:(MOVBUload [1] {s} p1:(ADD ptr1 idx1) mem))) y2:(MOVDnop x2:(MOVBUload [2] {s} p mem))))
// cond: s == nil && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && s0.Uses == 1 && mergePoint(b,x0,x1,x2,x3) != nil && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1)) && isSamePtr(p1, p) && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3) && clobber(y0) && clobber(y1) && clobber(y2) && clobber(y3) && clobber(o0) && clobber(o1) && clobber(s0)
// result: @mergePoint(b,x0,x1,x2,x3) (REVW <t> (MOVWUloadidx <t> ptr0 idx0 mem))
@@ -19986,6 +24551,11 @@ func rewriteValueARM64_OpARM64OR_30(v *Value) bool {
v0.AddArg(v1)
return true
}
+ return false
+}
+func rewriteValueARM64_OpARM64OR_40(v *Value) bool {
+ b := v.Block
+ _ = b
// match: (OR <t> y3:(MOVDnop x3:(MOVBUloadidx ptr (ADDconst [3] idx) mem)) o0:(ORshiftLL [8] o1:(ORshiftLL [16] s0:(SLLconst [24] y0:(MOVDnop x0:(MOVBUloadidx ptr idx mem))) y1:(MOVDnop x1:(MOVBUloadidx ptr (ADDconst [1] idx) mem))) y2:(MOVDnop x2:(MOVBUloadidx ptr (ADDconst [2] idx) mem))))
// cond: x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && s0.Uses == 1 && mergePoint(b,x0,x1,x2,x3) != nil && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3) && clobber(y0) && clobber(y1) && clobber(y2) && clobber(y3) && clobber(o0) && clobber(o1) && clobber(s0)
// result: @mergePoint(b,x0,x1,x2,x3) (REVW <t> (MOVWUloadidx <t> ptr idx mem))
@@ -21834,6 +26404,25 @@ func rewriteValueARM64_OpARM64ORconst_0(v *Value) bool {
v.AddArg(x)
return true
}
+ // match: (ORconst [c1] (ANDconst [c2] x))
+ // cond: c2|c1 == ^0
+ // result: (ORconst [c1] x)
+ for {
+ c1 := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64ANDconst {
+ break
+ }
+ c2 := v_0.AuxInt
+ x := v_0.Args[0]
+ if !(c2|c1 == ^0) {
+ break
+ }
+ v.reset(OpARM64ORconst)
+ v.AuxInt = c1
+ v.AddArg(x)
+ return true
+ }
return false
}
func rewriteValueARM64_OpARM64ORshiftLL_0(v *Value) bool {
@@ -24183,6 +28772,44 @@ func rewriteValueARM64_OpARM64ORshiftRL_0(v *Value) bool {
}
return false
}
+func rewriteValueARM64_OpARM64RORWconst_0(v *Value) bool {
+ // match: (RORWconst [c] (RORWconst [d] x))
+ // cond:
+ // result: (RORWconst [(c+d)&31] x)
+ for {
+ c := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64RORWconst {
+ break
+ }
+ d := v_0.AuxInt
+ x := v_0.Args[0]
+ v.reset(OpARM64RORWconst)
+ v.AuxInt = (c + d) & 31
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64RORconst_0(v *Value) bool {
+ // match: (RORconst [c] (RORconst [d] x))
+ // cond:
+ // result: (RORconst [(c+d)&63] x)
+ for {
+ c := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64RORconst {
+ break
+ }
+ d := v_0.AuxInt
+ x := v_0.Args[0]
+ v.reset(OpARM64RORconst)
+ v.AuxInt = (c + d) & 63
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
func rewriteValueARM64_OpARM64SLL_0(v *Value) bool {
// match: (SLL x (MOVDconst [c]))
// cond:
@@ -24859,7 +29486,7 @@ func rewriteValueARM64_OpARM64SUB_0(v *Value) bool {
return true
}
// match: (SUB a l:(MUL x y))
- // cond: l.Uses==1 && x.Op!=OpARM64MOVDconst && y.Op!=OpARM64MOVDconst && a.Op!=OpARM64MOVDconst && clobber(l)
+ // cond: l.Uses==1 && clobber(l)
// result: (MSUB a x y)
for {
_ = v.Args[1]
@@ -24871,7 +29498,7 @@ func rewriteValueARM64_OpARM64SUB_0(v *Value) bool {
_ = l.Args[1]
x := l.Args[0]
y := l.Args[1]
- if !(l.Uses == 1 && x.Op != OpARM64MOVDconst && y.Op != OpARM64MOVDconst && a.Op != OpARM64MOVDconst && clobber(l)) {
+ if !(l.Uses == 1 && clobber(l)) {
break
}
v.reset(OpARM64MSUB)
@@ -24881,7 +29508,7 @@ func rewriteValueARM64_OpARM64SUB_0(v *Value) bool {
return true
}
// match: (SUB a l:(MNEG x y))
- // cond: l.Uses==1 && x.Op!=OpARM64MOVDconst && y.Op!=OpARM64MOVDconst && a.Op!=OpARM64MOVDconst && clobber(l)
+ // cond: l.Uses==1 && clobber(l)
// result: (MADD a x y)
for {
_ = v.Args[1]
@@ -24893,7 +29520,7 @@ func rewriteValueARM64_OpARM64SUB_0(v *Value) bool {
_ = l.Args[1]
x := l.Args[0]
y := l.Args[1]
- if !(l.Uses == 1 && x.Op != OpARM64MOVDconst && y.Op != OpARM64MOVDconst && a.Op != OpARM64MOVDconst && clobber(l)) {
+ if !(l.Uses == 1 && clobber(l)) {
break
}
v.reset(OpARM64MADD)
@@ -24903,7 +29530,7 @@ func rewriteValueARM64_OpARM64SUB_0(v *Value) bool {
return true
}
// match: (SUB a l:(MULW x y))
- // cond: l.Uses==1 && a.Type.Size() != 8 && x.Op!=OpARM64MOVDconst && y.Op!=OpARM64MOVDconst && a.Op!=OpARM64MOVDconst && clobber(l)
+ // cond: a.Type.Size() != 8 && l.Uses==1 && clobber(l)
// result: (MSUBW a x y)
for {
_ = v.Args[1]
@@ -24915,7 +29542,7 @@ func rewriteValueARM64_OpARM64SUB_0(v *Value) bool {
_ = l.Args[1]
x := l.Args[0]
y := l.Args[1]
- if !(l.Uses == 1 && a.Type.Size() != 8 && x.Op != OpARM64MOVDconst && y.Op != OpARM64MOVDconst && a.Op != OpARM64MOVDconst && clobber(l)) {
+ if !(a.Type.Size() != 8 && l.Uses == 1 && clobber(l)) {
break
}
v.reset(OpARM64MSUBW)
@@ -24925,7 +29552,7 @@ func rewriteValueARM64_OpARM64SUB_0(v *Value) bool {
return true
}
// match: (SUB a l:(MNEGW x y))
- // cond: l.Uses==1 && a.Type.Size() != 8 && x.Op!=OpARM64MOVDconst && y.Op!=OpARM64MOVDconst && a.Op!=OpARM64MOVDconst && clobber(l)
+ // cond: a.Type.Size() != 8 && l.Uses==1 && clobber(l)
// result: (MADDW a x y)
for {
_ = v.Args[1]
@@ -24937,7 +29564,7 @@ func rewriteValueARM64_OpARM64SUB_0(v *Value) bool {
_ = l.Args[1]
x := l.Args[0]
y := l.Args[1]
- if !(l.Uses == 1 && a.Type.Size() != 8 && x.Op != OpARM64MOVDconst && y.Op != OpARM64MOVDconst && a.Op != OpARM64MOVDconst && clobber(l)) {
+ if !(a.Type.Size() != 8 && l.Uses == 1 && clobber(l)) {
break
}
v.reset(OpARM64MADDW)
@@ -25290,6 +29917,132 @@ func rewriteValueARM64_OpARM64TST_0(v *Value) bool {
v.AddArg(x)
return true
}
+ // match: (TST x0 x1:(SLLconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (TSTshiftLL x0 y [c])
+ for {
+ _ = v.Args[1]
+ x0 := v.Args[0]
+ x1 := v.Args[1]
+ if x1.Op != OpARM64SLLconst {
+ break
+ }
+ c := x1.AuxInt
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ break
+ }
+ v.reset(OpARM64TSTshiftLL)
+ v.AuxInt = c
+ v.AddArg(x0)
+ v.AddArg(y)
+ return true
+ }
+ // match: (TST x1:(SLLconst [c] y) x0)
+ // cond: clobberIfDead(x1)
+ // result: (TSTshiftLL x0 y [c])
+ for {
+ _ = v.Args[1]
+ x1 := v.Args[0]
+ if x1.Op != OpARM64SLLconst {
+ break
+ }
+ c := x1.AuxInt
+ y := x1.Args[0]
+ x0 := v.Args[1]
+ if !(clobberIfDead(x1)) {
+ break
+ }
+ v.reset(OpARM64TSTshiftLL)
+ v.AuxInt = c
+ v.AddArg(x0)
+ v.AddArg(y)
+ return true
+ }
+ // match: (TST x0 x1:(SRLconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (TSTshiftRL x0 y [c])
+ for {
+ _ = v.Args[1]
+ x0 := v.Args[0]
+ x1 := v.Args[1]
+ if x1.Op != OpARM64SRLconst {
+ break
+ }
+ c := x1.AuxInt
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ break
+ }
+ v.reset(OpARM64TSTshiftRL)
+ v.AuxInt = c
+ v.AddArg(x0)
+ v.AddArg(y)
+ return true
+ }
+ // match: (TST x1:(SRLconst [c] y) x0)
+ // cond: clobberIfDead(x1)
+ // result: (TSTshiftRL x0 y [c])
+ for {
+ _ = v.Args[1]
+ x1 := v.Args[0]
+ if x1.Op != OpARM64SRLconst {
+ break
+ }
+ c := x1.AuxInt
+ y := x1.Args[0]
+ x0 := v.Args[1]
+ if !(clobberIfDead(x1)) {
+ break
+ }
+ v.reset(OpARM64TSTshiftRL)
+ v.AuxInt = c
+ v.AddArg(x0)
+ v.AddArg(y)
+ return true
+ }
+ // match: (TST x0 x1:(SRAconst [c] y))
+ // cond: clobberIfDead(x1)
+ // result: (TSTshiftRA x0 y [c])
+ for {
+ _ = v.Args[1]
+ x0 := v.Args[0]
+ x1 := v.Args[1]
+ if x1.Op != OpARM64SRAconst {
+ break
+ }
+ c := x1.AuxInt
+ y := x1.Args[0]
+ if !(clobberIfDead(x1)) {
+ break
+ }
+ v.reset(OpARM64TSTshiftRA)
+ v.AuxInt = c
+ v.AddArg(x0)
+ v.AddArg(y)
+ return true
+ }
+ // match: (TST x1:(SRAconst [c] y) x0)
+ // cond: clobberIfDead(x1)
+ // result: (TSTshiftRA x0 y [c])
+ for {
+ _ = v.Args[1]
+ x1 := v.Args[0]
+ if x1.Op != OpARM64SRAconst {
+ break
+ }
+ c := x1.AuxInt
+ y := x1.Args[0]
+ x0 := v.Args[1]
+ if !(clobberIfDead(x1)) {
+ break
+ }
+ v.reset(OpARM64TSTshiftRA)
+ v.AuxInt = c
+ v.AddArg(x0)
+ v.AddArg(y)
+ return true
+ }
return false
}
func rewriteValueARM64_OpARM64TSTW_0(v *Value) bool {
@@ -25429,6 +30182,132 @@ func rewriteValueARM64_OpARM64TSTconst_0(v *Value) bool {
}
return false
}
+func rewriteValueARM64_OpARM64TSTshiftLL_0(v *Value) bool {
+ b := v.Block
+ _ = b
+ // match: (TSTshiftLL (MOVDconst [c]) x [d])
+ // cond:
+ // result: (TSTconst [c] (SLLconst <x.Type> x [d]))
+ for {
+ d := v.AuxInt
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_0.AuxInt
+ x := v.Args[1]
+ v.reset(OpARM64TSTconst)
+ v.AuxInt = c
+ v0 := b.NewValue0(v.Pos, OpARM64SLLconst, x.Type)
+ v0.AuxInt = d
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (TSTshiftLL x (MOVDconst [c]) [d])
+ // cond:
+ // result: (TSTconst x [int64(uint64(c)<<uint64(d))])
+ for {
+ d := v.AuxInt
+ _ = v.Args[1]
+ x := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ v.reset(OpARM64TSTconst)
+ v.AuxInt = int64(uint64(c) << uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64TSTshiftRA_0(v *Value) bool {
+ b := v.Block
+ _ = b
+ // match: (TSTshiftRA (MOVDconst [c]) x [d])
+ // cond:
+ // result: (TSTconst [c] (SRAconst <x.Type> x [d]))
+ for {
+ d := v.AuxInt
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_0.AuxInt
+ x := v.Args[1]
+ v.reset(OpARM64TSTconst)
+ v.AuxInt = c
+ v0 := b.NewValue0(v.Pos, OpARM64SRAconst, x.Type)
+ v0.AuxInt = d
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (TSTshiftRA x (MOVDconst [c]) [d])
+ // cond:
+ // result: (TSTconst x [c>>uint64(d)])
+ for {
+ d := v.AuxInt
+ _ = v.Args[1]
+ x := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ v.reset(OpARM64TSTconst)
+ v.AuxInt = c >> uint64(d)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64TSTshiftRL_0(v *Value) bool {
+ b := v.Block
+ _ = b
+ // match: (TSTshiftRL (MOVDconst [c]) x [d])
+ // cond:
+ // result: (TSTconst [c] (SRLconst <x.Type> x [d]))
+ for {
+ d := v.AuxInt
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_0.AuxInt
+ x := v.Args[1]
+ v.reset(OpARM64TSTconst)
+ v.AuxInt = c
+ v0 := b.NewValue0(v.Pos, OpARM64SRLconst, x.Type)
+ v0.AuxInt = d
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (TSTshiftRL x (MOVDconst [c]) [d])
+ // cond:
+ // result: (TSTconst x [int64(uint64(c)>>uint64(d))])
+ for {
+ d := v.AuxInt
+ _ = v.Args[1]
+ x := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ v.reset(OpARM64TSTconst)
+ v.AuxInt = int64(uint64(c) >> uint64(d))
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
func rewriteValueARM64_OpARM64UBFIZ_0(v *Value) bool {
// match: (UBFIZ [bfc] (SLLconst [sc] x))
// cond: sc < getARM64BFwidth(bfc)
@@ -25950,6 +30829,10 @@ func rewriteValueARM64_OpARM64XOR_0(v *Value) bool {
return false
}
func rewriteValueARM64_OpARM64XOR_10(v *Value) bool {
+ b := v.Block
+ _ = b
+ typ := &b.Func.Config.Types
+ _ = typ
// match: (XOR x1:(SRAconst [c] y) x0)
// cond: clobberIfDead(x1)
// result: (XORshiftRA x0 y [c])
@@ -25971,6 +30854,918 @@ func rewriteValueARM64_OpARM64XOR_10(v *Value) bool {
v.AddArg(y)
return true
}
+ // match: (XOR (SLL x (ANDconst <t> [63] y)) (CSEL0 <typ.UInt64> {cc} (SRL <typ.UInt64> x (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y))) (CMPconst [64] (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y)))))
+ // cond: cc.(Op) == OpARM64LessThanU
+ // result: (ROR x (NEG <t> y))
+ for {
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64SLL {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARM64ANDconst {
+ break
+ }
+ t := v_0_1.Type
+ if v_0_1.AuxInt != 63 {
+ break
+ }
+ y := v_0_1.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64CSEL0 {
+ break
+ }
+ if v_1.Type != typ.UInt64 {
+ break
+ }
+ cc := v_1.Aux
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpARM64SRL {
+ break
+ }
+ if v_1_0.Type != typ.UInt64 {
+ break
+ }
+ _ = v_1_0.Args[1]
+ if x != v_1_0.Args[0] {
+ break
+ }
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpARM64SUB {
+ break
+ }
+ if v_1_0_1.Type != t {
+ break
+ }
+ _ = v_1_0_1.Args[1]
+ v_1_0_1_0 := v_1_0_1.Args[0]
+ if v_1_0_1_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_1_0_1_0.AuxInt != 64 {
+ break
+ }
+ v_1_0_1_1 := v_1_0_1.Args[1]
+ if v_1_0_1_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_1_0_1_1.Type != t {
+ break
+ }
+ if v_1_0_1_1.AuxInt != 63 {
+ break
+ }
+ if y != v_1_0_1_1.Args[0] {
+ break
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpARM64CMPconst {
+ break
+ }
+ if v_1_1.AuxInt != 64 {
+ break
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpARM64SUB {
+ break
+ }
+ if v_1_1_0.Type != t {
+ break
+ }
+ _ = v_1_1_0.Args[1]
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_1_1_0_0.AuxInt != 64 {
+ break
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_1_1_0_1.Type != t {
+ break
+ }
+ if v_1_1_0_1.AuxInt != 63 {
+ break
+ }
+ if y != v_1_1_0_1.Args[0] {
+ break
+ }
+ if !(cc.(Op) == OpARM64LessThanU) {
+ break
+ }
+ v.reset(OpARM64ROR)
+ v.AddArg(x)
+ v0 := b.NewValue0(v.Pos, OpARM64NEG, t)
+ v0.AddArg(y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (XOR (CSEL0 <typ.UInt64> {cc} (SRL <typ.UInt64> x (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y))) (CMPconst [64] (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y)))) (SLL x (ANDconst <t> [63] y)))
+ // cond: cc.(Op) == OpARM64LessThanU
+ // result: (ROR x (NEG <t> y))
+ for {
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64CSEL0 {
+ break
+ }
+ if v_0.Type != typ.UInt64 {
+ break
+ }
+ cc := v_0.Aux
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARM64SRL {
+ break
+ }
+ if v_0_0.Type != typ.UInt64 {
+ break
+ }
+ _ = v_0_0.Args[1]
+ x := v_0_0.Args[0]
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpARM64SUB {
+ break
+ }
+ t := v_0_0_1.Type
+ _ = v_0_0_1.Args[1]
+ v_0_0_1_0 := v_0_0_1.Args[0]
+ if v_0_0_1_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_0_0_1_0.AuxInt != 64 {
+ break
+ }
+ v_0_0_1_1 := v_0_0_1.Args[1]
+ if v_0_0_1_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_0_0_1_1.Type != t {
+ break
+ }
+ if v_0_0_1_1.AuxInt != 63 {
+ break
+ }
+ y := v_0_0_1_1.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARM64CMPconst {
+ break
+ }
+ if v_0_1.AuxInt != 64 {
+ break
+ }
+ v_0_1_0 := v_0_1.Args[0]
+ if v_0_1_0.Op != OpARM64SUB {
+ break
+ }
+ if v_0_1_0.Type != t {
+ break
+ }
+ _ = v_0_1_0.Args[1]
+ v_0_1_0_0 := v_0_1_0.Args[0]
+ if v_0_1_0_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_0_1_0_0.AuxInt != 64 {
+ break
+ }
+ v_0_1_0_1 := v_0_1_0.Args[1]
+ if v_0_1_0_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_0_1_0_1.Type != t {
+ break
+ }
+ if v_0_1_0_1.AuxInt != 63 {
+ break
+ }
+ if y != v_0_1_0_1.Args[0] {
+ break
+ }
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64SLL {
+ break
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ break
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_1_1.Type != t {
+ break
+ }
+ if v_1_1.AuxInt != 63 {
+ break
+ }
+ if y != v_1_1.Args[0] {
+ break
+ }
+ if !(cc.(Op) == OpARM64LessThanU) {
+ break
+ }
+ v.reset(OpARM64ROR)
+ v.AddArg(x)
+ v0 := b.NewValue0(v.Pos, OpARM64NEG, t)
+ v0.AddArg(y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (XOR (SRL <typ.UInt64> x (ANDconst <t> [63] y)) (CSEL0 <typ.UInt64> {cc} (SLL x (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y))) (CMPconst [64] (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y)))))
+ // cond: cc.(Op) == OpARM64LessThanU
+ // result: (ROR x y)
+ for {
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64SRL {
+ break
+ }
+ if v_0.Type != typ.UInt64 {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARM64ANDconst {
+ break
+ }
+ t := v_0_1.Type
+ if v_0_1.AuxInt != 63 {
+ break
+ }
+ y := v_0_1.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64CSEL0 {
+ break
+ }
+ if v_1.Type != typ.UInt64 {
+ break
+ }
+ cc := v_1.Aux
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpARM64SLL {
+ break
+ }
+ _ = v_1_0.Args[1]
+ if x != v_1_0.Args[0] {
+ break
+ }
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpARM64SUB {
+ break
+ }
+ if v_1_0_1.Type != t {
+ break
+ }
+ _ = v_1_0_1.Args[1]
+ v_1_0_1_0 := v_1_0_1.Args[0]
+ if v_1_0_1_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_1_0_1_0.AuxInt != 64 {
+ break
+ }
+ v_1_0_1_1 := v_1_0_1.Args[1]
+ if v_1_0_1_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_1_0_1_1.Type != t {
+ break
+ }
+ if v_1_0_1_1.AuxInt != 63 {
+ break
+ }
+ if y != v_1_0_1_1.Args[0] {
+ break
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpARM64CMPconst {
+ break
+ }
+ if v_1_1.AuxInt != 64 {
+ break
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpARM64SUB {
+ break
+ }
+ if v_1_1_0.Type != t {
+ break
+ }
+ _ = v_1_1_0.Args[1]
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_1_1_0_0.AuxInt != 64 {
+ break
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_1_1_0_1.Type != t {
+ break
+ }
+ if v_1_1_0_1.AuxInt != 63 {
+ break
+ }
+ if y != v_1_1_0_1.Args[0] {
+ break
+ }
+ if !(cc.(Op) == OpARM64LessThanU) {
+ break
+ }
+ v.reset(OpARM64ROR)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+ // match: (XOR (CSEL0 <typ.UInt64> {cc} (SLL x (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y))) (CMPconst [64] (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y)))) (SRL <typ.UInt64> x (ANDconst <t> [63] y)))
+ // cond: cc.(Op) == OpARM64LessThanU
+ // result: (ROR x y)
+ for {
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64CSEL0 {
+ break
+ }
+ if v_0.Type != typ.UInt64 {
+ break
+ }
+ cc := v_0.Aux
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARM64SLL {
+ break
+ }
+ _ = v_0_0.Args[1]
+ x := v_0_0.Args[0]
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpARM64SUB {
+ break
+ }
+ t := v_0_0_1.Type
+ _ = v_0_0_1.Args[1]
+ v_0_0_1_0 := v_0_0_1.Args[0]
+ if v_0_0_1_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_0_0_1_0.AuxInt != 64 {
+ break
+ }
+ v_0_0_1_1 := v_0_0_1.Args[1]
+ if v_0_0_1_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_0_0_1_1.Type != t {
+ break
+ }
+ if v_0_0_1_1.AuxInt != 63 {
+ break
+ }
+ y := v_0_0_1_1.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARM64CMPconst {
+ break
+ }
+ if v_0_1.AuxInt != 64 {
+ break
+ }
+ v_0_1_0 := v_0_1.Args[0]
+ if v_0_1_0.Op != OpARM64SUB {
+ break
+ }
+ if v_0_1_0.Type != t {
+ break
+ }
+ _ = v_0_1_0.Args[1]
+ v_0_1_0_0 := v_0_1_0.Args[0]
+ if v_0_1_0_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_0_1_0_0.AuxInt != 64 {
+ break
+ }
+ v_0_1_0_1 := v_0_1_0.Args[1]
+ if v_0_1_0_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_0_1_0_1.Type != t {
+ break
+ }
+ if v_0_1_0_1.AuxInt != 63 {
+ break
+ }
+ if y != v_0_1_0_1.Args[0] {
+ break
+ }
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64SRL {
+ break
+ }
+ if v_1.Type != typ.UInt64 {
+ break
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ break
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_1_1.Type != t {
+ break
+ }
+ if v_1_1.AuxInt != 63 {
+ break
+ }
+ if y != v_1_1.Args[0] {
+ break
+ }
+ if !(cc.(Op) == OpARM64LessThanU) {
+ break
+ }
+ v.reset(OpARM64ROR)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+ // match: (XOR (SLL x (ANDconst <t> [31] y)) (CSEL0 <typ.UInt32> {cc} (SRL <typ.UInt32> (MOVWUreg x) (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y))) (CMPconst [64] (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y)))))
+ // cond: cc.(Op) == OpARM64LessThanU
+ // result: (RORW x (NEG <t> y))
+ for {
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64SLL {
+ break
+ }
+ _ = v_0.Args[1]
+ x := v_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARM64ANDconst {
+ break
+ }
+ t := v_0_1.Type
+ if v_0_1.AuxInt != 31 {
+ break
+ }
+ y := v_0_1.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64CSEL0 {
+ break
+ }
+ if v_1.Type != typ.UInt32 {
+ break
+ }
+ cc := v_1.Aux
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpARM64SRL {
+ break
+ }
+ if v_1_0.Type != typ.UInt32 {
+ break
+ }
+ _ = v_1_0.Args[1]
+ v_1_0_0 := v_1_0.Args[0]
+ if v_1_0_0.Op != OpARM64MOVWUreg {
+ break
+ }
+ if x != v_1_0_0.Args[0] {
+ break
+ }
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpARM64SUB {
+ break
+ }
+ if v_1_0_1.Type != t {
+ break
+ }
+ _ = v_1_0_1.Args[1]
+ v_1_0_1_0 := v_1_0_1.Args[0]
+ if v_1_0_1_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_1_0_1_0.AuxInt != 32 {
+ break
+ }
+ v_1_0_1_1 := v_1_0_1.Args[1]
+ if v_1_0_1_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_1_0_1_1.Type != t {
+ break
+ }
+ if v_1_0_1_1.AuxInt != 31 {
+ break
+ }
+ if y != v_1_0_1_1.Args[0] {
+ break
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpARM64CMPconst {
+ break
+ }
+ if v_1_1.AuxInt != 64 {
+ break
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpARM64SUB {
+ break
+ }
+ if v_1_1_0.Type != t {
+ break
+ }
+ _ = v_1_1_0.Args[1]
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_1_1_0_0.AuxInt != 32 {
+ break
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_1_1_0_1.Type != t {
+ break
+ }
+ if v_1_1_0_1.AuxInt != 31 {
+ break
+ }
+ if y != v_1_1_0_1.Args[0] {
+ break
+ }
+ if !(cc.(Op) == OpARM64LessThanU) {
+ break
+ }
+ v.reset(OpARM64RORW)
+ v.AddArg(x)
+ v0 := b.NewValue0(v.Pos, OpARM64NEG, t)
+ v0.AddArg(y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (XOR (CSEL0 <typ.UInt32> {cc} (SRL <typ.UInt32> (MOVWUreg x) (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y))) (CMPconst [64] (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y)))) (SLL x (ANDconst <t> [31] y)))
+ // cond: cc.(Op) == OpARM64LessThanU
+ // result: (RORW x (NEG <t> y))
+ for {
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64CSEL0 {
+ break
+ }
+ if v_0.Type != typ.UInt32 {
+ break
+ }
+ cc := v_0.Aux
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARM64SRL {
+ break
+ }
+ if v_0_0.Type != typ.UInt32 {
+ break
+ }
+ _ = v_0_0.Args[1]
+ v_0_0_0 := v_0_0.Args[0]
+ if v_0_0_0.Op != OpARM64MOVWUreg {
+ break
+ }
+ x := v_0_0_0.Args[0]
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpARM64SUB {
+ break
+ }
+ t := v_0_0_1.Type
+ _ = v_0_0_1.Args[1]
+ v_0_0_1_0 := v_0_0_1.Args[0]
+ if v_0_0_1_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_0_0_1_0.AuxInt != 32 {
+ break
+ }
+ v_0_0_1_1 := v_0_0_1.Args[1]
+ if v_0_0_1_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_0_0_1_1.Type != t {
+ break
+ }
+ if v_0_0_1_1.AuxInt != 31 {
+ break
+ }
+ y := v_0_0_1_1.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARM64CMPconst {
+ break
+ }
+ if v_0_1.AuxInt != 64 {
+ break
+ }
+ v_0_1_0 := v_0_1.Args[0]
+ if v_0_1_0.Op != OpARM64SUB {
+ break
+ }
+ if v_0_1_0.Type != t {
+ break
+ }
+ _ = v_0_1_0.Args[1]
+ v_0_1_0_0 := v_0_1_0.Args[0]
+ if v_0_1_0_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_0_1_0_0.AuxInt != 32 {
+ break
+ }
+ v_0_1_0_1 := v_0_1_0.Args[1]
+ if v_0_1_0_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_0_1_0_1.Type != t {
+ break
+ }
+ if v_0_1_0_1.AuxInt != 31 {
+ break
+ }
+ if y != v_0_1_0_1.Args[0] {
+ break
+ }
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64SLL {
+ break
+ }
+ _ = v_1.Args[1]
+ if x != v_1.Args[0] {
+ break
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_1_1.Type != t {
+ break
+ }
+ if v_1_1.AuxInt != 31 {
+ break
+ }
+ if y != v_1_1.Args[0] {
+ break
+ }
+ if !(cc.(Op) == OpARM64LessThanU) {
+ break
+ }
+ v.reset(OpARM64RORW)
+ v.AddArg(x)
+ v0 := b.NewValue0(v.Pos, OpARM64NEG, t)
+ v0.AddArg(y)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (XOR (SRL <typ.UInt32> (MOVWUreg x) (ANDconst <t> [31] y)) (CSEL0 <typ.UInt32> {cc} (SLL x (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y))) (CMPconst [64] (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y)))))
+ // cond: cc.(Op) == OpARM64LessThanU
+ // result: (RORW x y)
+ for {
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64SRL {
+ break
+ }
+ if v_0.Type != typ.UInt32 {
+ break
+ }
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARM64MOVWUreg {
+ break
+ }
+ x := v_0_0.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARM64ANDconst {
+ break
+ }
+ t := v_0_1.Type
+ if v_0_1.AuxInt != 31 {
+ break
+ }
+ y := v_0_1.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64CSEL0 {
+ break
+ }
+ if v_1.Type != typ.UInt32 {
+ break
+ }
+ cc := v_1.Aux
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpARM64SLL {
+ break
+ }
+ _ = v_1_0.Args[1]
+ if x != v_1_0.Args[0] {
+ break
+ }
+ v_1_0_1 := v_1_0.Args[1]
+ if v_1_0_1.Op != OpARM64SUB {
+ break
+ }
+ if v_1_0_1.Type != t {
+ break
+ }
+ _ = v_1_0_1.Args[1]
+ v_1_0_1_0 := v_1_0_1.Args[0]
+ if v_1_0_1_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_1_0_1_0.AuxInt != 32 {
+ break
+ }
+ v_1_0_1_1 := v_1_0_1.Args[1]
+ if v_1_0_1_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_1_0_1_1.Type != t {
+ break
+ }
+ if v_1_0_1_1.AuxInt != 31 {
+ break
+ }
+ if y != v_1_0_1_1.Args[0] {
+ break
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpARM64CMPconst {
+ break
+ }
+ if v_1_1.AuxInt != 64 {
+ break
+ }
+ v_1_1_0 := v_1_1.Args[0]
+ if v_1_1_0.Op != OpARM64SUB {
+ break
+ }
+ if v_1_1_0.Type != t {
+ break
+ }
+ _ = v_1_1_0.Args[1]
+ v_1_1_0_0 := v_1_1_0.Args[0]
+ if v_1_1_0_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_1_1_0_0.AuxInt != 32 {
+ break
+ }
+ v_1_1_0_1 := v_1_1_0.Args[1]
+ if v_1_1_0_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_1_1_0_1.Type != t {
+ break
+ }
+ if v_1_1_0_1.AuxInt != 31 {
+ break
+ }
+ if y != v_1_1_0_1.Args[0] {
+ break
+ }
+ if !(cc.(Op) == OpARM64LessThanU) {
+ break
+ }
+ v.reset(OpARM64RORW)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+ // match: (XOR (CSEL0 <typ.UInt32> {cc} (SLL x (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y))) (CMPconst [64] (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y)))) (SRL <typ.UInt32> (MOVWUreg x) (ANDconst <t> [31] y)))
+ // cond: cc.(Op) == OpARM64LessThanU
+ // result: (RORW x y)
+ for {
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64CSEL0 {
+ break
+ }
+ if v_0.Type != typ.UInt32 {
+ break
+ }
+ cc := v_0.Aux
+ _ = v_0.Args[1]
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARM64SLL {
+ break
+ }
+ _ = v_0_0.Args[1]
+ x := v_0_0.Args[0]
+ v_0_0_1 := v_0_0.Args[1]
+ if v_0_0_1.Op != OpARM64SUB {
+ break
+ }
+ t := v_0_0_1.Type
+ _ = v_0_0_1.Args[1]
+ v_0_0_1_0 := v_0_0_1.Args[0]
+ if v_0_0_1_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_0_0_1_0.AuxInt != 32 {
+ break
+ }
+ v_0_0_1_1 := v_0_0_1.Args[1]
+ if v_0_0_1_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_0_0_1_1.Type != t {
+ break
+ }
+ if v_0_0_1_1.AuxInt != 31 {
+ break
+ }
+ y := v_0_0_1_1.Args[0]
+ v_0_1 := v_0.Args[1]
+ if v_0_1.Op != OpARM64CMPconst {
+ break
+ }
+ if v_0_1.AuxInt != 64 {
+ break
+ }
+ v_0_1_0 := v_0_1.Args[0]
+ if v_0_1_0.Op != OpARM64SUB {
+ break
+ }
+ if v_0_1_0.Type != t {
+ break
+ }
+ _ = v_0_1_0.Args[1]
+ v_0_1_0_0 := v_0_1_0.Args[0]
+ if v_0_1_0_0.Op != OpARM64MOVDconst {
+ break
+ }
+ if v_0_1_0_0.AuxInt != 32 {
+ break
+ }
+ v_0_1_0_1 := v_0_1_0.Args[1]
+ if v_0_1_0_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_0_1_0_1.Type != t {
+ break
+ }
+ if v_0_1_0_1.AuxInt != 31 {
+ break
+ }
+ if y != v_0_1_0_1.Args[0] {
+ break
+ }
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64SRL {
+ break
+ }
+ if v_1.Type != typ.UInt32 {
+ break
+ }
+ _ = v_1.Args[1]
+ v_1_0 := v_1.Args[0]
+ if v_1_0.Op != OpARM64MOVWUreg {
+ break
+ }
+ if x != v_1_0.Args[0] {
+ break
+ }
+ v_1_1 := v_1.Args[1]
+ if v_1_1.Op != OpARM64ANDconst {
+ break
+ }
+ if v_1_1.Type != t {
+ break
+ }
+ if v_1_1.AuxInt != 31 {
+ break
+ }
+ if y != v_1_1.Args[0] {
+ break
+ }
+ if !(cc.(Op) == OpARM64LessThanU) {
+ break
+ }
+ v.reset(OpARM64RORW)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
return false
}
func rewriteValueARM64_OpARM64XORconst_0(v *Value) bool {
@@ -26365,6 +32160,17 @@ func rewriteValueARM64_OpARM64XORshiftRL_0(v *Value) bool {
}
return false
}
+func rewriteValueARM64_OpAbs_0(v *Value) bool {
+ // match: (Abs x)
+ // cond:
+ // result: (FABSD x)
+ for {
+ x := v.Args[0]
+ v.reset(OpARM64FABSD)
+ v.AddArg(x)
+ return true
+ }
+}
func rewriteValueARM64_OpAdd16_0(v *Value) bool {
// match: (Add16 x y)
// cond:
@@ -30489,6 +36295,42 @@ func rewriteValueARM64_OpPopCount64_0(v *Value) bool {
return true
}
}
+func rewriteValueARM64_OpRotateLeft32_0(v *Value) bool {
+ b := v.Block
+ _ = b
+ // match: (RotateLeft32 x y)
+ // cond:
+ // result: (RORW x (NEG <y.Type> y))
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ v.reset(OpARM64RORW)
+ v.AddArg(x)
+ v0 := b.NewValue0(v.Pos, OpARM64NEG, y.Type)
+ v0.AddArg(y)
+ v.AddArg(v0)
+ return true
+ }
+}
+func rewriteValueARM64_OpRotateLeft64_0(v *Value) bool {
+ b := v.Block
+ _ = b
+ // match: (RotateLeft64 x y)
+ // cond:
+ // result: (ROR x (NEG <y.Type> y))
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ v.reset(OpARM64ROR)
+ v.AddArg(x)
+ v0 := b.NewValue0(v.Pos, OpARM64NEG, y.Type)
+ v0.AddArg(y)
+ v.AddArg(v0)
+ return true
+ }
+}
func rewriteValueARM64_OpRound_0(v *Value) bool {
// match: (Round x)
// cond:
@@ -30522,6 +36364,17 @@ func rewriteValueARM64_OpRound64F_0(v *Value) bool {
return true
}
}
+func rewriteValueARM64_OpRoundToEven_0(v *Value) bool {
+ // match: (RoundToEven x)
+ // cond:
+ // result: (FRINTND x)
+ for {
+ x := v.Args[0]
+ v.reset(OpARM64FRINTND)
+ v.AddArg(x)
+ return true
+ }
+}
func rewriteValueARM64_OpRsh16Ux16_0(v *Value) bool {
b := v.Block
_ = b
diff --git a/src/cmd/compile/internal/ssa/rewritePPC64.go b/src/cmd/compile/internal/ssa/rewritePPC64.go
index ba6a862989..9aff3106db 100644
--- a/src/cmd/compile/internal/ssa/rewritePPC64.go
+++ b/src/cmd/compile/internal/ssa/rewritePPC64.go
@@ -337,6 +337,8 @@ func rewriteValuePPC64(v *Value) bool {
return rewriteValuePPC64_OpMul64_0(v)
case OpMul64F:
return rewriteValuePPC64_OpMul64F_0(v)
+ case OpMul64uhilo:
+ return rewriteValuePPC64_OpMul64uhilo_0(v)
case OpMul8:
return rewriteValuePPC64_OpMul8_0(v)
case OpNeg16:
@@ -388,9 +390,9 @@ func rewriteValuePPC64(v *Value) bool {
case OpPPC64ADDconst:
return rewriteValuePPC64_OpPPC64ADDconst_0(v)
case OpPPC64AND:
- return rewriteValuePPC64_OpPPC64AND_0(v)
+ return rewriteValuePPC64_OpPPC64AND_0(v) || rewriteValuePPC64_OpPPC64AND_10(v)
case OpPPC64ANDconst:
- return rewriteValuePPC64_OpPPC64ANDconst_0(v)
+ return rewriteValuePPC64_OpPPC64ANDconst_0(v) || rewriteValuePPC64_OpPPC64ANDconst_10(v)
case OpPPC64CMP:
return rewriteValuePPC64_OpPPC64CMP_0(v)
case OpPPC64CMPU:
@@ -449,46 +451,66 @@ func rewriteValuePPC64(v *Value) bool {
return rewriteValuePPC64_OpPPC64MFVSRD_0(v)
case OpPPC64MOVBZload:
return rewriteValuePPC64_OpPPC64MOVBZload_0(v)
+ case OpPPC64MOVBZloadidx:
+ return rewriteValuePPC64_OpPPC64MOVBZloadidx_0(v)
case OpPPC64MOVBZreg:
- return rewriteValuePPC64_OpPPC64MOVBZreg_0(v)
+ return rewriteValuePPC64_OpPPC64MOVBZreg_0(v) || rewriteValuePPC64_OpPPC64MOVBZreg_10(v)
case OpPPC64MOVBreg:
- return rewriteValuePPC64_OpPPC64MOVBreg_0(v)
+ return rewriteValuePPC64_OpPPC64MOVBreg_0(v) || rewriteValuePPC64_OpPPC64MOVBreg_10(v)
case OpPPC64MOVBstore:
return rewriteValuePPC64_OpPPC64MOVBstore_0(v) || rewriteValuePPC64_OpPPC64MOVBstore_10(v) || rewriteValuePPC64_OpPPC64MOVBstore_20(v)
+ case OpPPC64MOVBstoreidx:
+ return rewriteValuePPC64_OpPPC64MOVBstoreidx_0(v) || rewriteValuePPC64_OpPPC64MOVBstoreidx_10(v)
case OpPPC64MOVBstorezero:
return rewriteValuePPC64_OpPPC64MOVBstorezero_0(v)
case OpPPC64MOVDload:
return rewriteValuePPC64_OpPPC64MOVDload_0(v)
+ case OpPPC64MOVDloadidx:
+ return rewriteValuePPC64_OpPPC64MOVDloadidx_0(v)
case OpPPC64MOVDstore:
return rewriteValuePPC64_OpPPC64MOVDstore_0(v)
+ case OpPPC64MOVDstoreidx:
+ return rewriteValuePPC64_OpPPC64MOVDstoreidx_0(v)
case OpPPC64MOVDstorezero:
return rewriteValuePPC64_OpPPC64MOVDstorezero_0(v)
case OpPPC64MOVHBRstore:
return rewriteValuePPC64_OpPPC64MOVHBRstore_0(v)
case OpPPC64MOVHZload:
return rewriteValuePPC64_OpPPC64MOVHZload_0(v)
+ case OpPPC64MOVHZloadidx:
+ return rewriteValuePPC64_OpPPC64MOVHZloadidx_0(v)
case OpPPC64MOVHZreg:
- return rewriteValuePPC64_OpPPC64MOVHZreg_0(v)
+ return rewriteValuePPC64_OpPPC64MOVHZreg_0(v) || rewriteValuePPC64_OpPPC64MOVHZreg_10(v)
case OpPPC64MOVHload:
return rewriteValuePPC64_OpPPC64MOVHload_0(v)
+ case OpPPC64MOVHloadidx:
+ return rewriteValuePPC64_OpPPC64MOVHloadidx_0(v)
case OpPPC64MOVHreg:
- return rewriteValuePPC64_OpPPC64MOVHreg_0(v)
+ return rewriteValuePPC64_OpPPC64MOVHreg_0(v) || rewriteValuePPC64_OpPPC64MOVHreg_10(v)
case OpPPC64MOVHstore:
return rewriteValuePPC64_OpPPC64MOVHstore_0(v)
+ case OpPPC64MOVHstoreidx:
+ return rewriteValuePPC64_OpPPC64MOVHstoreidx_0(v)
case OpPPC64MOVHstorezero:
return rewriteValuePPC64_OpPPC64MOVHstorezero_0(v)
case OpPPC64MOVWBRstore:
return rewriteValuePPC64_OpPPC64MOVWBRstore_0(v)
case OpPPC64MOVWZload:
return rewriteValuePPC64_OpPPC64MOVWZload_0(v)
+ case OpPPC64MOVWZloadidx:
+ return rewriteValuePPC64_OpPPC64MOVWZloadidx_0(v)
case OpPPC64MOVWZreg:
- return rewriteValuePPC64_OpPPC64MOVWZreg_0(v)
+ return rewriteValuePPC64_OpPPC64MOVWZreg_0(v) || rewriteValuePPC64_OpPPC64MOVWZreg_10(v) || rewriteValuePPC64_OpPPC64MOVWZreg_20(v)
case OpPPC64MOVWload:
return rewriteValuePPC64_OpPPC64MOVWload_0(v)
+ case OpPPC64MOVWloadidx:
+ return rewriteValuePPC64_OpPPC64MOVWloadidx_0(v)
case OpPPC64MOVWreg:
- return rewriteValuePPC64_OpPPC64MOVWreg_0(v)
+ return rewriteValuePPC64_OpPPC64MOVWreg_0(v) || rewriteValuePPC64_OpPPC64MOVWreg_10(v)
case OpPPC64MOVWstore:
return rewriteValuePPC64_OpPPC64MOVWstore_0(v)
+ case OpPPC64MOVWstoreidx:
+ return rewriteValuePPC64_OpPPC64MOVWstoreidx_0(v)
case OpPPC64MOVWstorezero:
return rewriteValuePPC64_OpPPC64MOVWstorezero_0(v)
case OpPPC64MTVSRD:
@@ -544,7 +566,7 @@ func rewriteValuePPC64(v *Value) bool {
case OpRsh32Ux32:
return rewriteValuePPC64_OpRsh32Ux32_0(v)
case OpRsh32Ux64:
- return rewriteValuePPC64_OpRsh32Ux64_0(v)
+ return rewriteValuePPC64_OpRsh32Ux64_0(v) || rewriteValuePPC64_OpRsh32Ux64_10(v)
case OpRsh32Ux8:
return rewriteValuePPC64_OpRsh32Ux8_0(v)
case OpRsh32x16:
@@ -552,7 +574,7 @@ func rewriteValuePPC64(v *Value) bool {
case OpRsh32x32:
return rewriteValuePPC64_OpRsh32x32_0(v)
case OpRsh32x64:
- return rewriteValuePPC64_OpRsh32x64_0(v)
+ return rewriteValuePPC64_OpRsh32x64_0(v) || rewriteValuePPC64_OpRsh32x64_10(v)
case OpRsh32x8:
return rewriteValuePPC64_OpRsh32x8_0(v)
case OpRsh64Ux16:
@@ -560,7 +582,7 @@ func rewriteValuePPC64(v *Value) bool {
case OpRsh64Ux32:
return rewriteValuePPC64_OpRsh64Ux32_0(v)
case OpRsh64Ux64:
- return rewriteValuePPC64_OpRsh64Ux64_0(v)
+ return rewriteValuePPC64_OpRsh64Ux64_0(v) || rewriteValuePPC64_OpRsh64Ux64_10(v)
case OpRsh64Ux8:
return rewriteValuePPC64_OpRsh64Ux8_0(v)
case OpRsh64x16:
@@ -568,7 +590,7 @@ func rewriteValuePPC64(v *Value) bool {
case OpRsh64x32:
return rewriteValuePPC64_OpRsh64x32_0(v)
case OpRsh64x64:
- return rewriteValuePPC64_OpRsh64x64_0(v)
+ return rewriteValuePPC64_OpRsh64x64_0(v) || rewriteValuePPC64_OpRsh64x64_10(v)
case OpRsh64x8:
return rewriteValuePPC64_OpRsh64x8_0(v)
case OpRsh8Ux16:
@@ -3070,6 +3092,21 @@ func rewriteValuePPC64_OpLsh16x16_0(v *Value) bool {
typ := &b.Func.Config.Types
_ = typ
// match: (Lsh16x16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLW x y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SLW)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Lsh16x16 x y)
// cond:
// result: (SLW x (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-16] (ZeroExt16to64 y)))))
for {
@@ -3136,6 +3173,21 @@ func rewriteValuePPC64_OpLsh16x32_0(v *Value) bool {
return true
}
// match: (Lsh16x32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLW x y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SLW)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Lsh16x32 x y)
// cond:
// result: (SLW x (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-16] (ZeroExt32to64 y)))))
for {
@@ -3219,6 +3271,21 @@ func rewriteValuePPC64_OpLsh16x64_0(v *Value) bool {
return true
}
// match: (Lsh16x64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLW x y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SLW)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Lsh16x64 x y)
// cond:
// result: (SLW x (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-16] y))))
for {
@@ -3245,6 +3312,21 @@ func rewriteValuePPC64_OpLsh16x8_0(v *Value) bool {
typ := &b.Func.Config.Types
_ = typ
// match: (Lsh16x8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLW x y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SLW)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Lsh16x8 x y)
// cond:
// result: (SLW x (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-16] (ZeroExt8to64 y)))))
for {
@@ -3273,6 +3355,21 @@ func rewriteValuePPC64_OpLsh32x16_0(v *Value) bool {
typ := &b.Func.Config.Types
_ = typ
// match: (Lsh32x16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLW x y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SLW)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Lsh32x16 x y)
// cond:
// result: (SLW x (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-32] (ZeroExt16to64 y)))))
for {
@@ -3339,6 +3436,21 @@ func rewriteValuePPC64_OpLsh32x32_0(v *Value) bool {
return true
}
// match: (Lsh32x32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLW x y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SLW)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Lsh32x32 x y)
// cond:
// result: (SLW x (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-32] (ZeroExt32to64 y)))))
for {
@@ -3421,6 +3533,21 @@ func rewriteValuePPC64_OpLsh32x64_0(v *Value) bool {
v.AddArg(x)
return true
}
+ // match: (Lsh32x64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLW x y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SLW)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
// match: (Lsh32x64 x (AND y (MOVDconst [31])))
// cond:
// result: (SLW x (ANDconst <typ.Int32> [31] y))
@@ -3527,6 +3654,21 @@ func rewriteValuePPC64_OpLsh32x8_0(v *Value) bool {
typ := &b.Func.Config.Types
_ = typ
// match: (Lsh32x8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLW x y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SLW)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Lsh32x8 x y)
// cond:
// result: (SLW x (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-32] (ZeroExt8to64 y)))))
for {
@@ -3555,6 +3697,21 @@ func rewriteValuePPC64_OpLsh64x16_0(v *Value) bool {
typ := &b.Func.Config.Types
_ = typ
// match: (Lsh64x16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLD x y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SLD)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Lsh64x16 x y)
// cond:
// result: (SLD x (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-64] (ZeroExt16to64 y)))))
for {
@@ -3621,6 +3778,21 @@ func rewriteValuePPC64_OpLsh64x32_0(v *Value) bool {
return true
}
// match: (Lsh64x32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLD x y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SLD)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Lsh64x32 x y)
// cond:
// result: (SLD x (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-64] (ZeroExt32to64 y)))))
for {
@@ -3703,6 +3875,21 @@ func rewriteValuePPC64_OpLsh64x64_0(v *Value) bool {
v.AddArg(x)
return true
}
+ // match: (Lsh64x64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLD x y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SLD)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
// match: (Lsh64x64 x (AND y (MOVDconst [63])))
// cond:
// result: (SLD x (ANDconst <typ.Int64> [63] y))
@@ -3809,6 +3996,21 @@ func rewriteValuePPC64_OpLsh64x8_0(v *Value) bool {
typ := &b.Func.Config.Types
_ = typ
// match: (Lsh64x8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLD x y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SLD)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Lsh64x8 x y)
// cond:
// result: (SLD x (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-64] (ZeroExt8to64 y)))))
for {
@@ -3837,6 +4039,21 @@ func rewriteValuePPC64_OpLsh8x16_0(v *Value) bool {
typ := &b.Func.Config.Types
_ = typ
// match: (Lsh8x16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLW x y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SLW)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Lsh8x16 x y)
// cond:
// result: (SLW x (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-8] (ZeroExt16to64 y)))))
for {
@@ -3903,6 +4120,21 @@ func rewriteValuePPC64_OpLsh8x32_0(v *Value) bool {
return true
}
// match: (Lsh8x32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLW x y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SLW)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Lsh8x32 x y)
// cond:
// result: (SLW x (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-8] (ZeroExt32to64 y)))))
for {
@@ -3986,6 +4218,21 @@ func rewriteValuePPC64_OpLsh8x64_0(v *Value) bool {
return true
}
// match: (Lsh8x64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLW x y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SLW)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Lsh8x64 x y)
// cond:
// result: (SLW x (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-8] y))))
for {
@@ -4012,6 +4259,21 @@ func rewriteValuePPC64_OpLsh8x8_0(v *Value) bool {
typ := &b.Func.Config.Types
_ = typ
// match: (Lsh8x8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SLW x y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SLW)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Lsh8x8 x y)
// cond:
// result: (SLW x (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-8] (ZeroExt8to64 y)))))
for {
@@ -4569,6 +4831,20 @@ func rewriteValuePPC64_OpMul64F_0(v *Value) bool {
return true
}
}
+func rewriteValuePPC64_OpMul64uhilo_0(v *Value) bool {
+ // match: (Mul64uhilo x y)
+ // cond:
+ // result: (LoweredMuluhilo x y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ v.reset(OpPPC64LoweredMuluhilo)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+}
func rewriteValuePPC64_OpMul8_0(v *Value) bool {
// match: (Mul8 x y)
// cond:
@@ -5533,6 +5809,95 @@ func rewriteValuePPC64_OpPPC64AND_0(v *Value) bool {
v.AddArg(x)
return true
}
+ // match: (AND (MOVDconst [c]) y:(MOVWZreg _))
+ // cond: c&0xFFFFFFFF == 0xFFFFFFFF
+ // result: y
+ for {
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := v_0.AuxInt
+ y := v.Args[1]
+ if y.Op != OpPPC64MOVWZreg {
+ break
+ }
+ if !(c&0xFFFFFFFF == 0xFFFFFFFF) {
+ break
+ }
+ v.reset(OpCopy)
+ v.Type = y.Type
+ v.AddArg(y)
+ return true
+ }
+ // match: (AND y:(MOVWZreg _) (MOVDconst [c]))
+ // cond: c&0xFFFFFFFF == 0xFFFFFFFF
+ // result: y
+ for {
+ _ = v.Args[1]
+ y := v.Args[0]
+ if y.Op != OpPPC64MOVWZreg {
+ break
+ }
+ v_1 := v.Args[1]
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ if !(c&0xFFFFFFFF == 0xFFFFFFFF) {
+ break
+ }
+ v.reset(OpCopy)
+ v.Type = y.Type
+ v.AddArg(y)
+ return true
+ }
+ // match: (AND (MOVDconst [0xFFFFFFFF]) y:(MOVWreg x))
+ // cond:
+ // result: (MOVWZreg x)
+ for {
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ if v_0.AuxInt != 0xFFFFFFFF {
+ break
+ }
+ y := v.Args[1]
+ if y.Op != OpPPC64MOVWreg {
+ break
+ }
+ x := y.Args[0]
+ v.reset(OpPPC64MOVWZreg)
+ v.AddArg(x)
+ return true
+ }
+ // match: (AND y:(MOVWreg x) (MOVDconst [0xFFFFFFFF]))
+ // cond:
+ // result: (MOVWZreg x)
+ for {
+ _ = v.Args[1]
+ y := v.Args[0]
+ if y.Op != OpPPC64MOVWreg {
+ break
+ }
+ x := y.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ if v_1.AuxInt != 0xFFFFFFFF {
+ break
+ }
+ v.reset(OpPPC64MOVWZreg)
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64AND_10(v *Value) bool {
// match: (AND (MOVDconst [c]) x:(MOVBZload _ _))
// cond:
// result: (ANDconst [c&0xFF] x)
@@ -5673,6 +6038,22 @@ func rewriteValuePPC64_OpPPC64ANDconst_0(v *Value) bool {
v.AddArg(y)
return true
}
+ // match: (ANDconst [0xFF] y:(MOVBreg _))
+ // cond:
+ // result: y
+ for {
+ if v.AuxInt != 0xFF {
+ break
+ }
+ y := v.Args[0]
+ if y.Op != OpPPC64MOVBreg {
+ break
+ }
+ v.reset(OpCopy)
+ v.Type = y.Type
+ v.AddArg(y)
+ return true
+ }
// match: (ANDconst [c] y:(MOVHZreg _))
// cond: c&0xFFFF == 0xFFFF
// result: y
@@ -5690,16 +6071,15 @@ func rewriteValuePPC64_OpPPC64ANDconst_0(v *Value) bool {
v.AddArg(y)
return true
}
- // match: (ANDconst [c] y:(MOVWZreg _))
- // cond: c&0xFFFFFFFF == 0xFFFFFFFF
+ // match: (ANDconst [0xFFFF] y:(MOVHreg _))
+ // cond:
// result: y
for {
- c := v.AuxInt
- y := v.Args[0]
- if y.Op != OpPPC64MOVWZreg {
+ if v.AuxInt != 0xFFFF {
break
}
- if !(c&0xFFFFFFFF == 0xFFFFFFFF) {
+ y := v.Args[0]
+ if y.Op != OpPPC64MOVHreg {
break
}
v.reset(OpCopy)
@@ -5707,6 +6087,21 @@ func rewriteValuePPC64_OpPPC64ANDconst_0(v *Value) bool {
v.AddArg(y)
return true
}
+ // match: (ANDconst [c] (MOVBreg x))
+ // cond:
+ // result: (ANDconst [c&0xFF] x)
+ for {
+ c := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64MOVBreg {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpPPC64ANDconst)
+ v.AuxInt = c & 0xFF
+ v.AddArg(x)
+ return true
+ }
// match: (ANDconst [c] (MOVBZreg x))
// cond:
// result: (ANDconst [c&0xFF] x)
@@ -5722,6 +6117,24 @@ func rewriteValuePPC64_OpPPC64ANDconst_0(v *Value) bool {
v.AddArg(x)
return true
}
+ // match: (ANDconst [c] (MOVHreg x))
+ // cond:
+ // result: (ANDconst [c&0xFFFF] x)
+ for {
+ c := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64MOVHreg {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpPPC64ANDconst)
+ v.AuxInt = c & 0xFFFF
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64ANDconst_10(v *Value) bool {
// match: (ANDconst [c] (MOVHZreg x))
// cond:
// result: (ANDconst [c&0xFFFF] x)
@@ -5737,6 +6150,21 @@ func rewriteValuePPC64_OpPPC64ANDconst_0(v *Value) bool {
v.AddArg(x)
return true
}
+ // match: (ANDconst [c] (MOVWreg x))
+ // cond:
+ // result: (ANDconst [c&0xFFFFFFFF] x)
+ for {
+ c := v.AuxInt
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64MOVWreg {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpPPC64ANDconst)
+ v.AuxInt = c & 0xFFFFFFFF
+ v.AddArg(x)
+ return true
+ }
// match: (ANDconst [c] (MOVWZreg x))
// cond:
// result: (ANDconst [c&0xFFFFFFFF] x)
@@ -6257,7 +6685,7 @@ func rewriteValuePPC64_OpPPC64Equal_0(v *Value) bool {
func rewriteValuePPC64_OpPPC64FABS_0(v *Value) bool {
// match: (FABS (FMOVDconst [x]))
// cond:
- // result: (FMOVDconst [f2i(math.Abs(i2f(x)))])
+ // result: (FMOVDconst [auxFrom64F(math.Abs(auxTo64F(x)))])
for {
v_0 := v.Args[0]
if v_0.Op != OpPPC64FMOVDconst {
@@ -6265,7 +6693,7 @@ func rewriteValuePPC64_OpPPC64FABS_0(v *Value) bool {
}
x := v_0.AuxInt
v.reset(OpPPC64FMOVDconst)
- v.AuxInt = f2i(math.Abs(i2f(x)))
+ v.AuxInt = auxFrom64F(math.Abs(auxTo64F(x)))
return true
}
return false
@@ -6355,7 +6783,7 @@ func rewriteValuePPC64_OpPPC64FADDS_0(v *Value) bool {
func rewriteValuePPC64_OpPPC64FCEIL_0(v *Value) bool {
// match: (FCEIL (FMOVDconst [x]))
// cond:
- // result: (FMOVDconst [f2i(math.Ceil(i2f(x)))])
+ // result: (FMOVDconst [auxFrom64F(math.Ceil(auxTo64F(x)))])
for {
v_0 := v.Args[0]
if v_0.Op != OpPPC64FMOVDconst {
@@ -6363,7 +6791,7 @@ func rewriteValuePPC64_OpPPC64FCEIL_0(v *Value) bool {
}
x := v_0.AuxInt
v.reset(OpPPC64FMOVDconst)
- v.AuxInt = f2i(math.Ceil(i2f(x)))
+ v.AuxInt = auxFrom64F(math.Ceil(auxTo64F(x)))
return true
}
return false
@@ -6371,7 +6799,7 @@ func rewriteValuePPC64_OpPPC64FCEIL_0(v *Value) bool {
func rewriteValuePPC64_OpPPC64FFLOOR_0(v *Value) bool {
// match: (FFLOOR (FMOVDconst [x]))
// cond:
- // result: (FMOVDconst [f2i(math.Floor(i2f(x)))])
+ // result: (FMOVDconst [auxFrom64F(math.Floor(auxTo64F(x)))])
for {
v_0 := v.Args[0]
if v_0.Op != OpPPC64FMOVDconst {
@@ -6379,7 +6807,7 @@ func rewriteValuePPC64_OpPPC64FFLOOR_0(v *Value) bool {
}
x := v_0.AuxInt
v.reset(OpPPC64FMOVDconst)
- v.AuxInt = f2i(math.Floor(i2f(x)))
+ v.AuxInt = auxFrom64F(math.Floor(auxTo64F(x)))
return true
}
return false
@@ -6681,7 +7109,7 @@ func rewriteValuePPC64_OpPPC64FNEG_0(v *Value) bool {
func rewriteValuePPC64_OpPPC64FSQRT_0(v *Value) bool {
// match: (FSQRT (FMOVDconst [x]))
// cond:
- // result: (FMOVDconst [f2i(math.Sqrt(i2f(x)))])
+ // result: (FMOVDconst [auxFrom64F(math.Sqrt(auxTo64F(x)))])
for {
v_0 := v.Args[0]
if v_0.Op != OpPPC64FMOVDconst {
@@ -6689,7 +7117,7 @@ func rewriteValuePPC64_OpPPC64FSQRT_0(v *Value) bool {
}
x := v_0.AuxInt
v.reset(OpPPC64FMOVDconst)
- v.AuxInt = f2i(math.Sqrt(i2f(x)))
+ v.AuxInt = auxFrom64F(math.Sqrt(auxTo64F(x)))
return true
}
return false
@@ -6741,7 +7169,7 @@ func rewriteValuePPC64_OpPPC64FSUBS_0(v *Value) bool {
func rewriteValuePPC64_OpPPC64FTRUNC_0(v *Value) bool {
// match: (FTRUNC (FMOVDconst [x]))
// cond:
- // result: (FMOVDconst [f2i(math.Trunc(i2f(x)))])
+ // result: (FMOVDconst [auxFrom64F(math.Trunc(auxTo64F(x)))])
for {
v_0 := v.Args[0]
if v_0.Op != OpPPC64FMOVDconst {
@@ -6749,7 +7177,7 @@ func rewriteValuePPC64_OpPPC64FTRUNC_0(v *Value) bool {
}
x := v_0.AuxInt
v.reset(OpPPC64FMOVDconst)
- v.AuxInt = f2i(math.Trunc(i2f(x)))
+ v.AuxInt = auxFrom64F(math.Trunc(auxTo64F(x)))
return true
}
return false
@@ -7058,9 +7486,84 @@ func rewriteValuePPC64_OpPPC64MOVBZload_0(v *Value) bool {
v.AddArg(mem)
return true
}
+ // match: (MOVBZload [0] {sym} p:(ADD ptr idx) mem)
+ // cond: sym == nil && p.Uses == 1
+ // result: (MOVBZloadidx ptr idx mem)
+ for {
+ if v.AuxInt != 0 {
+ break
+ }
+ sym := v.Aux
+ _ = v.Args[1]
+ p := v.Args[0]
+ if p.Op != OpPPC64ADD {
+ break
+ }
+ _ = p.Args[1]
+ ptr := p.Args[0]
+ idx := p.Args[1]
+ mem := v.Args[1]
+ if !(sym == nil && p.Uses == 1) {
+ break
+ }
+ v.reset(OpPPC64MOVBZloadidx)
+ v.AddArg(ptr)
+ v.AddArg(idx)
+ v.AddArg(mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVBZloadidx_0(v *Value) bool {
+ // match: (MOVBZloadidx ptr (MOVDconst [c]) mem)
+ // cond: is16Bit(c)
+ // result: (MOVBZload [c] ptr mem)
+ for {
+ _ = v.Args[2]
+ ptr := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ mem := v.Args[2]
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64MOVBZload)
+ v.AuxInt = c
+ v.AddArg(ptr)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (MOVBZloadidx (MOVDconst [c]) ptr mem)
+ // cond: is16Bit(c)
+ // result: (MOVBZload [c] ptr mem)
+ for {
+ _ = v.Args[2]
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := v_0.AuxInt
+ ptr := v.Args[1]
+ mem := v.Args[2]
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64MOVBZload)
+ v.AuxInt = c
+ v.AddArg(ptr)
+ v.AddArg(mem)
+ return true
+ }
return false
}
func rewriteValuePPC64_OpPPC64MOVBZreg_0(v *Value) bool {
+ b := v.Block
+ _ = b
+ typ := &b.Func.Config.Types
+ _ = typ
// match: (MOVBZreg y:(ANDconst [c] _))
// cond: uint64(c) <= 0xFF
// result: y
@@ -7078,6 +7581,81 @@ func rewriteValuePPC64_OpPPC64MOVBZreg_0(v *Value) bool {
v.AddArg(y)
return true
}
+ // match: (MOVBZreg (SRWconst [c] (MOVBZreg x)))
+ // cond:
+ // result: (SRWconst [c] (MOVBZreg x))
+ for {
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64SRWconst {
+ break
+ }
+ c := v_0.AuxInt
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64MOVBZreg {
+ break
+ }
+ x := v_0_0.Args[0]
+ v.reset(OpPPC64SRWconst)
+ v.AuxInt = c
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVBZreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MOVBZreg (SRWconst [c] x))
+ // cond: sizeof(x.Type) == 8
+ // result: (SRWconst [c] x)
+ for {
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64SRWconst {
+ break
+ }
+ c := v_0.AuxInt
+ x := v_0.Args[0]
+ if !(sizeof(x.Type) == 8) {
+ break
+ }
+ v.reset(OpPPC64SRWconst)
+ v.AuxInt = c
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBZreg (SRDconst [c] x))
+ // cond: c>=56
+ // result: (SRDconst [c] x)
+ for {
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64SRDconst {
+ break
+ }
+ c := v_0.AuxInt
+ x := v_0.Args[0]
+ if !(c >= 56) {
+ break
+ }
+ v.reset(OpPPC64SRDconst)
+ v.AuxInt = c
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBZreg (SRWconst [c] x))
+ // cond: c>=24
+ // result: (SRWconst [c] x)
+ for {
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64SRWconst {
+ break
+ }
+ c := v_0.AuxInt
+ x := v_0.Args[0]
+ if !(c >= 24) {
+ break
+ }
+ v.reset(OpPPC64SRWconst)
+ v.AuxInt = c
+ v.AddArg(x)
+ return true
+ }
// match: (MOVBZreg y:(MOVBZreg _))
// cond:
// result: y
@@ -7118,6 +7696,40 @@ func rewriteValuePPC64_OpPPC64MOVBZreg_0(v *Value) bool {
v.AddArg(x)
return true
}
+ // match: (MOVBZreg x:(MOVBZloadidx _ _ _))
+ // cond:
+ // result: x
+ for {
+ x := v.Args[0]
+ if x.Op != OpPPC64MOVBZloadidx {
+ break
+ }
+ _ = x.Args[2]
+ v.reset(OpCopy)
+ v.Type = x.Type
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBZreg x:(Arg <t>))
+ // cond: is8BitInt(t) && !isSigned(t)
+ // result: x
+ for {
+ x := v.Args[0]
+ if x.Op != OpArg {
+ break
+ }
+ t := x.Type
+ if !(is8BitInt(t) && !isSigned(t)) {
+ break
+ }
+ v.reset(OpCopy)
+ v.Type = x.Type
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVBZreg_10(v *Value) bool {
// match: (MOVBZreg (MOVDconst [c]))
// cond:
// result: (MOVDconst [int64(uint8(c))])
@@ -7134,6 +7746,10 @@ func rewriteValuePPC64_OpPPC64MOVBZreg_0(v *Value) bool {
return false
}
func rewriteValuePPC64_OpPPC64MOVBreg_0(v *Value) bool {
+ b := v.Block
+ _ = b
+ typ := &b.Func.Config.Types
+ _ = typ
// match: (MOVBreg y:(ANDconst [c] _))
// cond: uint64(c) <= 0x7F
// result: y
@@ -7151,6 +7767,117 @@ func rewriteValuePPC64_OpPPC64MOVBreg_0(v *Value) bool {
v.AddArg(y)
return true
}
+ // match: (MOVBreg (SRAWconst [c] (MOVBreg x)))
+ // cond:
+ // result: (SRAWconst [c] (MOVBreg x))
+ for {
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64SRAWconst {
+ break
+ }
+ c := v_0.AuxInt
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64MOVBreg {
+ break
+ }
+ x := v_0_0.Args[0]
+ v.reset(OpPPC64SRAWconst)
+ v.AuxInt = c
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVBreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MOVBreg (SRAWconst [c] x))
+ // cond: sizeof(x.Type) == 8
+ // result: (SRAWconst [c] x)
+ for {
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64SRAWconst {
+ break
+ }
+ c := v_0.AuxInt
+ x := v_0.Args[0]
+ if !(sizeof(x.Type) == 8) {
+ break
+ }
+ v.reset(OpPPC64SRAWconst)
+ v.AuxInt = c
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBreg (SRDconst [c] x))
+ // cond: c>56
+ // result: (SRDconst [c] x)
+ for {
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64SRDconst {
+ break
+ }
+ c := v_0.AuxInt
+ x := v_0.Args[0]
+ if !(c > 56) {
+ break
+ }
+ v.reset(OpPPC64SRDconst)
+ v.AuxInt = c
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBreg (SRDconst [c] x))
+ // cond: c==56
+ // result: (SRADconst [c] x)
+ for {
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64SRDconst {
+ break
+ }
+ c := v_0.AuxInt
+ x := v_0.Args[0]
+ if !(c == 56) {
+ break
+ }
+ v.reset(OpPPC64SRADconst)
+ v.AuxInt = c
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBreg (SRWconst [c] x))
+ // cond: c>24
+ // result: (SRWconst [c] x)
+ for {
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64SRWconst {
+ break
+ }
+ c := v_0.AuxInt
+ x := v_0.Args[0]
+ if !(c > 24) {
+ break
+ }
+ v.reset(OpPPC64SRWconst)
+ v.AuxInt = c
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVBreg (SRWconst [c] x))
+ // cond: c==24
+ // result: (SRAWconst [c] x)
+ for {
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64SRWconst {
+ break
+ }
+ c := v_0.AuxInt
+ x := v_0.Args[0]
+ if !(c == 24) {
+ break
+ }
+ v.reset(OpPPC64SRAWconst)
+ v.AuxInt = c
+ v.AddArg(x)
+ return true
+ }
// match: (MOVBreg y:(MOVBreg _))
// cond:
// result: y
@@ -7177,6 +7904,26 @@ func rewriteValuePPC64_OpPPC64MOVBreg_0(v *Value) bool {
v.AddArg(x)
return true
}
+ // match: (MOVBreg x:(Arg <t>))
+ // cond: is8BitInt(t) && isSigned(t)
+ // result: x
+ for {
+ x := v.Args[0]
+ if x.Op != OpArg {
+ break
+ }
+ t := x.Type
+ if !(is8BitInt(t) && isSigned(t)) {
+ break
+ }
+ v.reset(OpCopy)
+ v.Type = x.Type
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVBreg_10(v *Value) bool {
// match: (MOVBreg (MOVDconst [c]))
// cond:
// result: (MOVDconst [int64(int8(c))])
@@ -7193,10 +7940,6 @@ func rewriteValuePPC64_OpPPC64MOVBreg_0(v *Value) bool {
return false
}
func rewriteValuePPC64_OpPPC64MOVBstore_0(v *Value) bool {
- b := v.Block
- _ = b
- typ := &b.Func.Config.Types
- _ = typ
// match: (MOVBstore [off1] {sym} (ADDconst [off2] x) val mem)
// cond: is16Bit(off1+off2)
// result: (MOVBstore [off1+off2] {sym} x val mem)
@@ -7250,8 +7993,8 @@ func rewriteValuePPC64_OpPPC64MOVBstore_0(v *Value) bool {
v.AddArg(mem)
return true
}
- // match: (MOVBstore [off] {sym} ptr (MOVDconst [c]) mem)
- // cond: c == 0
+ // match: (MOVBstore [off] {sym} ptr (MOVDconst [0]) mem)
+ // cond:
// result: (MOVBstorezero [off] {sym} ptr mem)
for {
off := v.AuxInt
@@ -7262,11 +8005,10 @@ func rewriteValuePPC64_OpPPC64MOVBstore_0(v *Value) bool {
if v_1.Op != OpPPC64MOVDconst {
break
}
- c := v_1.AuxInt
- mem := v.Args[2]
- if !(c == 0) {
+ if v_1.AuxInt != 0 {
break
}
+ mem := v.Args[2]
v.reset(OpPPC64MOVBstorezero)
v.AuxInt = off
v.Aux = sym
@@ -7274,6 +8016,32 @@ func rewriteValuePPC64_OpPPC64MOVBstore_0(v *Value) bool {
v.AddArg(mem)
return true
}
+ // match: (MOVBstore [off] {sym} p:(ADD ptr idx) val mem)
+ // cond: off == 0 && sym == nil && p.Uses == 1
+ // result: (MOVBstoreidx ptr idx val mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[2]
+ p := v.Args[0]
+ if p.Op != OpPPC64ADD {
+ break
+ }
+ _ = p.Args[1]
+ ptr := p.Args[0]
+ idx := p.Args[1]
+ val := v.Args[1]
+ mem := v.Args[2]
+ if !(off == 0 && sym == nil && p.Uses == 1) {
+ break
+ }
+ v.reset(OpPPC64MOVBstoreidx)
+ v.AddArg(ptr)
+ v.AddArg(idx)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
// match: (MOVBstore [off] {sym} ptr (MOVBreg x) mem)
// cond:
// result: (MOVBstore [off] {sym} ptr x mem)
@@ -7406,6 +8174,15 @@ func rewriteValuePPC64_OpPPC64MOVBstore_0(v *Value) bool {
v.AddArg(mem)
return true
}
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVBstore_10(v *Value) bool {
+ b := v.Block
+ _ = b
+ config := b.Func.Config
+ _ = config
+ typ := &b.Func.Config.Types
+ _ = typ
// match: (MOVBstore [off] {sym} ptr (SRWconst (MOVHreg x) [c]) mem)
// cond: c <= 8
// result: (MOVBstore [off] {sym} ptr (SRWconst <typ.UInt32> x [c]) mem)
@@ -7439,15 +8216,6 @@ func rewriteValuePPC64_OpPPC64MOVBstore_0(v *Value) bool {
v.AddArg(mem)
return true
}
- return false
-}
-func rewriteValuePPC64_OpPPC64MOVBstore_10(v *Value) bool {
- b := v.Block
- _ = b
- config := b.Func.Config
- _ = config
- typ := &b.Func.Config.Types
- _ = typ
// match: (MOVBstore [off] {sym} ptr (SRWconst (MOVHZreg x) [c]) mem)
// cond: c <= 8
// result: (MOVBstore [off] {sym} ptr (SRWconst <typ.UInt32> x [c]) mem)
@@ -7873,6 +8641,15 @@ func rewriteValuePPC64_OpPPC64MOVBstore_10(v *Value) bool {
v.AddArg(mem)
return true
}
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVBstore_20(v *Value) bool {
+ b := v.Block
+ _ = b
+ config := b.Func.Config
+ _ = config
+ typ := &b.Func.Config.Types
+ _ = typ
// match: (MOVBstore [i7] {s} p (SRDconst w [56]) x0:(MOVBstore [i6] {s} p (SRDconst w [48]) x1:(MOVBstore [i5] {s} p (SRDconst w [40]) x2:(MOVBstore [i4] {s} p (SRDconst w [32]) x3:(MOVWstore [i0] {s} p w mem)))))
// cond: !config.BigEndian && i0%4 == 0 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && i4 == i0+4 && i5 == i0+5 && i6 == i0+6 && i7 == i0+7 && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3)
// result: (MOVDstore [i0] {s} p w mem)
@@ -7982,15 +8759,6 @@ func rewriteValuePPC64_OpPPC64MOVBstore_10(v *Value) bool {
v.AddArg(mem)
return true
}
- return false
-}
-func rewriteValuePPC64_OpPPC64MOVBstore_20(v *Value) bool {
- b := v.Block
- _ = b
- config := b.Func.Config
- _ = config
- typ := &b.Func.Config.Types
- _ = typ
// match: (MOVBstore [i7] {s} p w x0:(MOVBstore [i6] {s} p (SRDconst w [8]) x1:(MOVBstore [i5] {s} p (SRDconst w [16]) x2:(MOVBstore [i4] {s} p (SRDconst w [24]) x3:(MOVBstore [i3] {s} p (SRDconst w [32]) x4:(MOVBstore [i2] {s} p (SRDconst w [40]) x5:(MOVBstore [i1] {s} p (SRDconst w [48]) x6:(MOVBstore [i0] {s} p (SRDconst w [56]) mem))))))))
// cond: !config.BigEndian && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && i1 == i0+1 && i2 == i0+2 && i3 == i0+3 && i4 == i0+4 && i5 == i0+5 && i6 == i0+6 && i7 == i0+7 && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3) && clobber(x4) && clobber(x5) && clobber(x6)
// result: (MOVDBRstore (MOVDaddr <typ.Uintptr> [i0] {s} p) w mem)
@@ -8170,6 +8938,350 @@ func rewriteValuePPC64_OpPPC64MOVBstore_20(v *Value) bool {
}
return false
}
+func rewriteValuePPC64_OpPPC64MOVBstoreidx_0(v *Value) bool {
+ b := v.Block
+ _ = b
+ typ := &b.Func.Config.Types
+ _ = typ
+ // match: (MOVBstoreidx ptr (MOVDconst [c]) val mem)
+ // cond: is16Bit(c)
+ // result: (MOVBstore [c] ptr val mem)
+ for {
+ _ = v.Args[3]
+ ptr := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ val := v.Args[2]
+ mem := v.Args[3]
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64MOVBstore)
+ v.AuxInt = c
+ v.AddArg(ptr)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (MOVBstoreidx (MOVDconst [c]) ptr val mem)
+ // cond: is16Bit(c)
+ // result: (MOVBstore [c] ptr val mem)
+ for {
+ _ = v.Args[3]
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := v_0.AuxInt
+ ptr := v.Args[1]
+ val := v.Args[2]
+ mem := v.Args[3]
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64MOVBstore)
+ v.AuxInt = c
+ v.AddArg(ptr)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (MOVBstoreidx [off] {sym} ptr idx (MOVBreg x) mem)
+ // cond:
+ // result: (MOVBstoreidx [off] {sym} ptr idx x mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[3]
+ ptr := v.Args[0]
+ idx := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpPPC64MOVBreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v.Args[3]
+ v.reset(OpPPC64MOVBstoreidx)
+ v.AuxInt = off
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(idx)
+ v.AddArg(x)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (MOVBstoreidx [off] {sym} ptr idx (MOVBZreg x) mem)
+ // cond:
+ // result: (MOVBstoreidx [off] {sym} ptr idx x mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[3]
+ ptr := v.Args[0]
+ idx := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpPPC64MOVBZreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v.Args[3]
+ v.reset(OpPPC64MOVBstoreidx)
+ v.AuxInt = off
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(idx)
+ v.AddArg(x)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (MOVBstoreidx [off] {sym} ptr idx (MOVHreg x) mem)
+ // cond:
+ // result: (MOVBstoreidx [off] {sym} ptr idx x mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[3]
+ ptr := v.Args[0]
+ idx := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpPPC64MOVHreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v.Args[3]
+ v.reset(OpPPC64MOVBstoreidx)
+ v.AuxInt = off
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(idx)
+ v.AddArg(x)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (MOVBstoreidx [off] {sym} ptr idx (MOVHZreg x) mem)
+ // cond:
+ // result: (MOVBstoreidx [off] {sym} ptr idx x mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[3]
+ ptr := v.Args[0]
+ idx := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpPPC64MOVHZreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v.Args[3]
+ v.reset(OpPPC64MOVBstoreidx)
+ v.AuxInt = off
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(idx)
+ v.AddArg(x)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (MOVBstoreidx [off] {sym} ptr idx (MOVWreg x) mem)
+ // cond:
+ // result: (MOVBstoreidx [off] {sym} ptr idx x mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[3]
+ ptr := v.Args[0]
+ idx := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpPPC64MOVWreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v.Args[3]
+ v.reset(OpPPC64MOVBstoreidx)
+ v.AuxInt = off
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(idx)
+ v.AddArg(x)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (MOVBstoreidx [off] {sym} ptr idx (MOVWZreg x) mem)
+ // cond:
+ // result: (MOVBstoreidx [off] {sym} ptr idx x mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[3]
+ ptr := v.Args[0]
+ idx := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpPPC64MOVWZreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v.Args[3]
+ v.reset(OpPPC64MOVBstoreidx)
+ v.AuxInt = off
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(idx)
+ v.AddArg(x)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (MOVBstoreidx [off] {sym} ptr idx (SRWconst (MOVHreg x) [c]) mem)
+ // cond: c <= 8
+ // result: (MOVBstoreidx [off] {sym} ptr idx (SRWconst <typ.UInt32> x [c]) mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[3]
+ ptr := v.Args[0]
+ idx := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpPPC64SRWconst {
+ break
+ }
+ c := v_2.AuxInt
+ v_2_0 := v_2.Args[0]
+ if v_2_0.Op != OpPPC64MOVHreg {
+ break
+ }
+ x := v_2_0.Args[0]
+ mem := v.Args[3]
+ if !(c <= 8) {
+ break
+ }
+ v.reset(OpPPC64MOVBstoreidx)
+ v.AuxInt = off
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(idx)
+ v0 := b.NewValue0(v.Pos, OpPPC64SRWconst, typ.UInt32)
+ v0.AuxInt = c
+ v0.AddArg(x)
+ v.AddArg(v0)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (MOVBstoreidx [off] {sym} ptr idx (SRWconst (MOVHZreg x) [c]) mem)
+ // cond: c <= 8
+ // result: (MOVBstoreidx [off] {sym} ptr idx (SRWconst <typ.UInt32> x [c]) mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[3]
+ ptr := v.Args[0]
+ idx := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpPPC64SRWconst {
+ break
+ }
+ c := v_2.AuxInt
+ v_2_0 := v_2.Args[0]
+ if v_2_0.Op != OpPPC64MOVHZreg {
+ break
+ }
+ x := v_2_0.Args[0]
+ mem := v.Args[3]
+ if !(c <= 8) {
+ break
+ }
+ v.reset(OpPPC64MOVBstoreidx)
+ v.AuxInt = off
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(idx)
+ v0 := b.NewValue0(v.Pos, OpPPC64SRWconst, typ.UInt32)
+ v0.AuxInt = c
+ v0.AddArg(x)
+ v.AddArg(v0)
+ v.AddArg(mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVBstoreidx_10(v *Value) bool {
+ b := v.Block
+ _ = b
+ typ := &b.Func.Config.Types
+ _ = typ
+ // match: (MOVBstoreidx [off] {sym} ptr idx (SRWconst (MOVWreg x) [c]) mem)
+ // cond: c <= 24
+ // result: (MOVBstoreidx [off] {sym} ptr idx (SRWconst <typ.UInt32> x [c]) mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[3]
+ ptr := v.Args[0]
+ idx := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpPPC64SRWconst {
+ break
+ }
+ c := v_2.AuxInt
+ v_2_0 := v_2.Args[0]
+ if v_2_0.Op != OpPPC64MOVWreg {
+ break
+ }
+ x := v_2_0.Args[0]
+ mem := v.Args[3]
+ if !(c <= 24) {
+ break
+ }
+ v.reset(OpPPC64MOVBstoreidx)
+ v.AuxInt = off
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(idx)
+ v0 := b.NewValue0(v.Pos, OpPPC64SRWconst, typ.UInt32)
+ v0.AuxInt = c
+ v0.AddArg(x)
+ v.AddArg(v0)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (MOVBstoreidx [off] {sym} ptr idx (SRWconst (MOVWZreg x) [c]) mem)
+ // cond: c <= 24
+ // result: (MOVBstoreidx [off] {sym} ptr idx (SRWconst <typ.UInt32> x [c]) mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[3]
+ ptr := v.Args[0]
+ idx := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpPPC64SRWconst {
+ break
+ }
+ c := v_2.AuxInt
+ v_2_0 := v_2.Args[0]
+ if v_2_0.Op != OpPPC64MOVWZreg {
+ break
+ }
+ x := v_2_0.Args[0]
+ mem := v.Args[3]
+ if !(c <= 24) {
+ break
+ }
+ v.reset(OpPPC64MOVBstoreidx)
+ v.AuxInt = off
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(idx)
+ v0 := b.NewValue0(v.Pos, OpPPC64SRWconst, typ.UInt32)
+ v0.AuxInt = c
+ v0.AddArg(x)
+ v.AddArg(v0)
+ v.AddArg(mem)
+ return true
+ }
+ return false
+}
func rewriteValuePPC64_OpPPC64MOVBstorezero_0(v *Value) bool {
// match: (MOVBstorezero [off1] {sym} (ADDconst [off2] x) mem)
// cond: is16Bit(off1+off2)
@@ -8299,6 +9411,77 @@ func rewriteValuePPC64_OpPPC64MOVDload_0(v *Value) bool {
v.AddArg(mem)
return true
}
+ // match: (MOVDload [0] {sym} p:(ADD ptr idx) mem)
+ // cond: sym == nil && p.Uses == 1
+ // result: (MOVDloadidx ptr idx mem)
+ for {
+ if v.AuxInt != 0 {
+ break
+ }
+ sym := v.Aux
+ _ = v.Args[1]
+ p := v.Args[0]
+ if p.Op != OpPPC64ADD {
+ break
+ }
+ _ = p.Args[1]
+ ptr := p.Args[0]
+ idx := p.Args[1]
+ mem := v.Args[1]
+ if !(sym == nil && p.Uses == 1) {
+ break
+ }
+ v.reset(OpPPC64MOVDloadidx)
+ v.AddArg(ptr)
+ v.AddArg(idx)
+ v.AddArg(mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVDloadidx_0(v *Value) bool {
+ // match: (MOVDloadidx ptr (MOVDconst [c]) mem)
+ // cond: is16Bit(c)
+ // result: (MOVDload [c] ptr mem)
+ for {
+ _ = v.Args[2]
+ ptr := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ mem := v.Args[2]
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64MOVDload)
+ v.AuxInt = c
+ v.AddArg(ptr)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (MOVDloadidx (MOVDconst [c]) ptr mem)
+ // cond: is16Bit(c)
+ // result: (MOVDload [c] ptr mem)
+ for {
+ _ = v.Args[2]
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := v_0.AuxInt
+ ptr := v.Args[1]
+ mem := v.Args[2]
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64MOVDload)
+ v.AuxInt = c
+ v.AddArg(ptr)
+ v.AddArg(mem)
+ return true
+ }
return false
}
func rewriteValuePPC64_OpPPC64MOVDstore_0(v *Value) bool {
@@ -8377,8 +9560,8 @@ func rewriteValuePPC64_OpPPC64MOVDstore_0(v *Value) bool {
v.AddArg(mem)
return true
}
- // match: (MOVDstore [off] {sym} ptr (MOVDconst [c]) mem)
- // cond: c == 0
+ // match: (MOVDstore [off] {sym} ptr (MOVDconst [0]) mem)
+ // cond:
// result: (MOVDstorezero [off] {sym} ptr mem)
for {
off := v.AuxInt
@@ -8389,11 +9572,10 @@ func rewriteValuePPC64_OpPPC64MOVDstore_0(v *Value) bool {
if v_1.Op != OpPPC64MOVDconst {
break
}
- c := v_1.AuxInt
- mem := v.Args[2]
- if !(c == 0) {
+ if v_1.AuxInt != 0 {
break
}
+ mem := v.Args[2]
v.reset(OpPPC64MOVDstorezero)
v.AuxInt = off
v.Aux = sym
@@ -8401,6 +9583,81 @@ func rewriteValuePPC64_OpPPC64MOVDstore_0(v *Value) bool {
v.AddArg(mem)
return true
}
+ // match: (MOVDstore [off] {sym} p:(ADD ptr idx) val mem)
+ // cond: off == 0 && sym == nil && p.Uses == 1
+ // result: (MOVDstoreidx ptr idx val mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[2]
+ p := v.Args[0]
+ if p.Op != OpPPC64ADD {
+ break
+ }
+ _ = p.Args[1]
+ ptr := p.Args[0]
+ idx := p.Args[1]
+ val := v.Args[1]
+ mem := v.Args[2]
+ if !(off == 0 && sym == nil && p.Uses == 1) {
+ break
+ }
+ v.reset(OpPPC64MOVDstoreidx)
+ v.AddArg(ptr)
+ v.AddArg(idx)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVDstoreidx_0(v *Value) bool {
+ // match: (MOVDstoreidx ptr (MOVDconst [c]) val mem)
+ // cond: is16Bit(c)
+ // result: (MOVDstore [c] ptr val mem)
+ for {
+ _ = v.Args[3]
+ ptr := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ val := v.Args[2]
+ mem := v.Args[3]
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64MOVDstore)
+ v.AuxInt = c
+ v.AddArg(ptr)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (MOVDstoreidx (MOVDconst [c]) ptr val mem)
+ // cond: is16Bit(c)
+ // result: (MOVDstore [c] ptr val mem)
+ for {
+ _ = v.Args[3]
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := v_0.AuxInt
+ ptr := v.Args[1]
+ val := v.Args[2]
+ mem := v.Args[3]
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64MOVDstore)
+ v.AuxInt = c
+ v.AddArg(ptr)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
return false
}
func rewriteValuePPC64_OpPPC64MOVDstorezero_0(v *Value) bool {
@@ -8588,9 +9845,84 @@ func rewriteValuePPC64_OpPPC64MOVHZload_0(v *Value) bool {
v.AddArg(mem)
return true
}
+ // match: (MOVHZload [0] {sym} p:(ADD ptr idx) mem)
+ // cond: sym == nil && p.Uses == 1
+ // result: (MOVHZloadidx ptr idx mem)
+ for {
+ if v.AuxInt != 0 {
+ break
+ }
+ sym := v.Aux
+ _ = v.Args[1]
+ p := v.Args[0]
+ if p.Op != OpPPC64ADD {
+ break
+ }
+ _ = p.Args[1]
+ ptr := p.Args[0]
+ idx := p.Args[1]
+ mem := v.Args[1]
+ if !(sym == nil && p.Uses == 1) {
+ break
+ }
+ v.reset(OpPPC64MOVHZloadidx)
+ v.AddArg(ptr)
+ v.AddArg(idx)
+ v.AddArg(mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVHZloadidx_0(v *Value) bool {
+ // match: (MOVHZloadidx ptr (MOVDconst [c]) mem)
+ // cond: is16Bit(c)
+ // result: (MOVHZload [c] ptr mem)
+ for {
+ _ = v.Args[2]
+ ptr := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ mem := v.Args[2]
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64MOVHZload)
+ v.AuxInt = c
+ v.AddArg(ptr)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (MOVHZloadidx (MOVDconst [c]) ptr mem)
+ // cond: is16Bit(c)
+ // result: (MOVHZload [c] ptr mem)
+ for {
+ _ = v.Args[2]
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := v_0.AuxInt
+ ptr := v.Args[1]
+ mem := v.Args[2]
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64MOVHZload)
+ v.AuxInt = c
+ v.AddArg(ptr)
+ v.AddArg(mem)
+ return true
+ }
return false
}
func rewriteValuePPC64_OpPPC64MOVHZreg_0(v *Value) bool {
+ b := v.Block
+ _ = b
+ typ := &b.Func.Config.Types
+ _ = typ
// match: (MOVHZreg y:(ANDconst [c] _))
// cond: uint64(c) <= 0xFFFF
// result: y
@@ -8608,6 +9940,102 @@ func rewriteValuePPC64_OpPPC64MOVHZreg_0(v *Value) bool {
v.AddArg(y)
return true
}
+ // match: (MOVHZreg (SRWconst [c] (MOVBZreg x)))
+ // cond:
+ // result: (SRWconst [c] (MOVBZreg x))
+ for {
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64SRWconst {
+ break
+ }
+ c := v_0.AuxInt
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64MOVBZreg {
+ break
+ }
+ x := v_0_0.Args[0]
+ v.reset(OpPPC64SRWconst)
+ v.AuxInt = c
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVBZreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MOVHZreg (SRWconst [c] (MOVHZreg x)))
+ // cond:
+ // result: (SRWconst [c] (MOVHZreg x))
+ for {
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64SRWconst {
+ break
+ }
+ c := v_0.AuxInt
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64MOVHZreg {
+ break
+ }
+ x := v_0_0.Args[0]
+ v.reset(OpPPC64SRWconst)
+ v.AuxInt = c
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVHZreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MOVHZreg (SRWconst [c] x))
+ // cond: sizeof(x.Type) <= 16
+ // result: (SRWconst [c] x)
+ for {
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64SRWconst {
+ break
+ }
+ c := v_0.AuxInt
+ x := v_0.Args[0]
+ if !(sizeof(x.Type) <= 16) {
+ break
+ }
+ v.reset(OpPPC64SRWconst)
+ v.AuxInt = c
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHZreg (SRDconst [c] x))
+ // cond: c>=48
+ // result: (SRDconst [c] x)
+ for {
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64SRDconst {
+ break
+ }
+ c := v_0.AuxInt
+ x := v_0.Args[0]
+ if !(c >= 48) {
+ break
+ }
+ v.reset(OpPPC64SRDconst)
+ v.AuxInt = c
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHZreg (SRWconst [c] x))
+ // cond: c>=16
+ // result: (SRWconst [c] x)
+ for {
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64SRWconst {
+ break
+ }
+ c := v_0.AuxInt
+ x := v_0.Args[0]
+ if !(c >= 16) {
+ break
+ }
+ v.reset(OpPPC64SRWconst)
+ v.AuxInt = c
+ v.AddArg(x)
+ return true
+ }
// match: (MOVHZreg y:(MOVHZreg _))
// cond:
// result: y
@@ -8661,6 +10089,37 @@ func rewriteValuePPC64_OpPPC64MOVHZreg_0(v *Value) bool {
v.AddArg(x)
return true
}
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVHZreg_10(v *Value) bool {
+ // match: (MOVHZreg x:(MOVBZload _ _))
+ // cond:
+ // result: x
+ for {
+ x := v.Args[0]
+ if x.Op != OpPPC64MOVBZload {
+ break
+ }
+ _ = x.Args[1]
+ v.reset(OpCopy)
+ v.Type = x.Type
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHZreg x:(MOVBZloadidx _ _ _))
+ // cond:
+ // result: x
+ for {
+ x := v.Args[0]
+ if x.Op != OpPPC64MOVBZloadidx {
+ break
+ }
+ _ = x.Args[2]
+ v.reset(OpCopy)
+ v.Type = x.Type
+ v.AddArg(x)
+ return true
+ }
// match: (MOVHZreg x:(MOVHZload _ _))
// cond:
// result: x
@@ -8675,6 +10134,37 @@ func rewriteValuePPC64_OpPPC64MOVHZreg_0(v *Value) bool {
v.AddArg(x)
return true
}
+ // match: (MOVHZreg x:(MOVHZloadidx _ _ _))
+ // cond:
+ // result: x
+ for {
+ x := v.Args[0]
+ if x.Op != OpPPC64MOVHZloadidx {
+ break
+ }
+ _ = x.Args[2]
+ v.reset(OpCopy)
+ v.Type = x.Type
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHZreg x:(Arg <t>))
+ // cond: (is8BitInt(t) || is16BitInt(t)) && !isSigned(t)
+ // result: x
+ for {
+ x := v.Args[0]
+ if x.Op != OpArg {
+ break
+ }
+ t := x.Type
+ if !((is8BitInt(t) || is16BitInt(t)) && !isSigned(t)) {
+ break
+ }
+ v.reset(OpCopy)
+ v.Type = x.Type
+ v.AddArg(x)
+ return true
+ }
// match: (MOVHZreg (MOVDconst [c]))
// cond:
// result: (MOVDconst [int64(uint16(c))])
@@ -8740,9 +10230,84 @@ func rewriteValuePPC64_OpPPC64MOVHload_0(v *Value) bool {
v.AddArg(mem)
return true
}
+ // match: (MOVHload [0] {sym} p:(ADD ptr idx) mem)
+ // cond: sym == nil && p.Uses == 1
+ // result: (MOVHloadidx ptr idx mem)
+ for {
+ if v.AuxInt != 0 {
+ break
+ }
+ sym := v.Aux
+ _ = v.Args[1]
+ p := v.Args[0]
+ if p.Op != OpPPC64ADD {
+ break
+ }
+ _ = p.Args[1]
+ ptr := p.Args[0]
+ idx := p.Args[1]
+ mem := v.Args[1]
+ if !(sym == nil && p.Uses == 1) {
+ break
+ }
+ v.reset(OpPPC64MOVHloadidx)
+ v.AddArg(ptr)
+ v.AddArg(idx)
+ v.AddArg(mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVHloadidx_0(v *Value) bool {
+ // match: (MOVHloadidx ptr (MOVDconst [c]) mem)
+ // cond: is16Bit(c)
+ // result: (MOVHload [c] ptr mem)
+ for {
+ _ = v.Args[2]
+ ptr := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ mem := v.Args[2]
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64MOVHload)
+ v.AuxInt = c
+ v.AddArg(ptr)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (MOVHloadidx (MOVDconst [c]) ptr mem)
+ // cond: is16Bit(c)
+ // result: (MOVHload [c] ptr mem)
+ for {
+ _ = v.Args[2]
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := v_0.AuxInt
+ ptr := v.Args[1]
+ mem := v.Args[2]
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64MOVHload)
+ v.AuxInt = c
+ v.AddArg(ptr)
+ v.AddArg(mem)
+ return true
+ }
return false
}
func rewriteValuePPC64_OpPPC64MOVHreg_0(v *Value) bool {
+ b := v.Block
+ _ = b
+ typ := &b.Func.Config.Types
+ _ = typ
// match: (MOVHreg y:(ANDconst [c] _))
// cond: uint64(c) <= 0x7FFF
// result: y
@@ -8760,6 +10325,138 @@ func rewriteValuePPC64_OpPPC64MOVHreg_0(v *Value) bool {
v.AddArg(y)
return true
}
+ // match: (MOVHreg (SRAWconst [c] (MOVBreg x)))
+ // cond:
+ // result: (SRAWconst [c] (MOVBreg x))
+ for {
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64SRAWconst {
+ break
+ }
+ c := v_0.AuxInt
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64MOVBreg {
+ break
+ }
+ x := v_0_0.Args[0]
+ v.reset(OpPPC64SRAWconst)
+ v.AuxInt = c
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVBreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MOVHreg (SRAWconst [c] (MOVHreg x)))
+ // cond:
+ // result: (SRAWconst [c] (MOVHreg x))
+ for {
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64SRAWconst {
+ break
+ }
+ c := v_0.AuxInt
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64MOVHreg {
+ break
+ }
+ x := v_0_0.Args[0]
+ v.reset(OpPPC64SRAWconst)
+ v.AuxInt = c
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVHreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MOVHreg (SRAWconst [c] x))
+ // cond: sizeof(x.Type) <= 16
+ // result: (SRAWconst [c] x)
+ for {
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64SRAWconst {
+ break
+ }
+ c := v_0.AuxInt
+ x := v_0.Args[0]
+ if !(sizeof(x.Type) <= 16) {
+ break
+ }
+ v.reset(OpPPC64SRAWconst)
+ v.AuxInt = c
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg (SRDconst [c] x))
+ // cond: c>48
+ // result: (SRDconst [c] x)
+ for {
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64SRDconst {
+ break
+ }
+ c := v_0.AuxInt
+ x := v_0.Args[0]
+ if !(c > 48) {
+ break
+ }
+ v.reset(OpPPC64SRDconst)
+ v.AuxInt = c
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg (SRDconst [c] x))
+ // cond: c==48
+ // result: (SRADconst [c] x)
+ for {
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64SRDconst {
+ break
+ }
+ c := v_0.AuxInt
+ x := v_0.Args[0]
+ if !(c == 48) {
+ break
+ }
+ v.reset(OpPPC64SRADconst)
+ v.AuxInt = c
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg (SRWconst [c] x))
+ // cond: c>16
+ // result: (SRWconst [c] x)
+ for {
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64SRWconst {
+ break
+ }
+ c := v_0.AuxInt
+ x := v_0.Args[0]
+ if !(c > 16) {
+ break
+ }
+ v.reset(OpPPC64SRWconst)
+ v.AuxInt = c
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg (SRWconst [c] x))
+ // cond: c==16
+ // result: (SRAWconst [c] x)
+ for {
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64SRWconst {
+ break
+ }
+ c := v_0.AuxInt
+ x := v_0.Args[0]
+ if !(c == 16) {
+ break
+ }
+ v.reset(OpPPC64SRAWconst)
+ v.AuxInt = c
+ v.AddArg(x)
+ return true
+ }
// match: (MOVHreg y:(MOVHreg _))
// cond:
// result: y
@@ -8786,6 +10483,9 @@ func rewriteValuePPC64_OpPPC64MOVHreg_0(v *Value) bool {
v.AddArg(y)
return true
}
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVHreg_10(v *Value) bool {
// match: (MOVHreg y:(MOVHZreg x))
// cond:
// result: (MOVHreg x)
@@ -8813,6 +10513,37 @@ func rewriteValuePPC64_OpPPC64MOVHreg_0(v *Value) bool {
v.AddArg(x)
return true
}
+ // match: (MOVHreg x:(MOVHloadidx _ _ _))
+ // cond:
+ // result: x
+ for {
+ x := v.Args[0]
+ if x.Op != OpPPC64MOVHloadidx {
+ break
+ }
+ _ = x.Args[2]
+ v.reset(OpCopy)
+ v.Type = x.Type
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVHreg x:(Arg <t>))
+ // cond: (is8BitInt(t) || is16BitInt(t)) && isSigned(t)
+ // result: x
+ for {
+ x := v.Args[0]
+ if x.Op != OpArg {
+ break
+ }
+ t := x.Type
+ if !((is8BitInt(t) || is16BitInt(t)) && isSigned(t)) {
+ break
+ }
+ v.reset(OpCopy)
+ v.Type = x.Type
+ v.AddArg(x)
+ return true
+ }
// match: (MOVHreg (MOVDconst [c]))
// cond:
// result: (MOVDconst [int64(int16(c))])
@@ -8886,8 +10617,8 @@ func rewriteValuePPC64_OpPPC64MOVHstore_0(v *Value) bool {
v.AddArg(mem)
return true
}
- // match: (MOVHstore [off] {sym} ptr (MOVDconst [c]) mem)
- // cond: c == 0
+ // match: (MOVHstore [off] {sym} ptr (MOVDconst [0]) mem)
+ // cond:
// result: (MOVHstorezero [off] {sym} ptr mem)
for {
off := v.AuxInt
@@ -8898,11 +10629,10 @@ func rewriteValuePPC64_OpPPC64MOVHstore_0(v *Value) bool {
if v_1.Op != OpPPC64MOVDconst {
break
}
- c := v_1.AuxInt
- mem := v.Args[2]
- if !(c == 0) {
+ if v_1.AuxInt != 0 {
break
}
+ mem := v.Args[2]
v.reset(OpPPC64MOVHstorezero)
v.AuxInt = off
v.Aux = sym
@@ -8910,6 +10640,32 @@ func rewriteValuePPC64_OpPPC64MOVHstore_0(v *Value) bool {
v.AddArg(mem)
return true
}
+ // match: (MOVHstore [off] {sym} p:(ADD ptr idx) val mem)
+ // cond: off == 0 && sym == nil && p.Uses == 1
+ // result: (MOVHstoreidx ptr idx val mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[2]
+ p := v.Args[0]
+ if p.Op != OpPPC64ADD {
+ break
+ }
+ _ = p.Args[1]
+ ptr := p.Args[0]
+ idx := p.Args[1]
+ val := v.Args[1]
+ mem := v.Args[2]
+ if !(off == 0 && sym == nil && p.Uses == 1) {
+ break
+ }
+ v.reset(OpPPC64MOVHstoreidx)
+ v.AddArg(ptr)
+ v.AddArg(idx)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
// match: (MOVHstore [off] {sym} ptr (MOVHreg x) mem)
// cond:
// result: (MOVHstore [off] {sym} ptr x mem)
@@ -9086,6 +10842,151 @@ func rewriteValuePPC64_OpPPC64MOVHstore_0(v *Value) bool {
}
return false
}
+func rewriteValuePPC64_OpPPC64MOVHstoreidx_0(v *Value) bool {
+ // match: (MOVHstoreidx ptr (MOVDconst [c]) val mem)
+ // cond: is16Bit(c)
+ // result: (MOVHstore [c] ptr val mem)
+ for {
+ _ = v.Args[3]
+ ptr := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ val := v.Args[2]
+ mem := v.Args[3]
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64MOVHstore)
+ v.AuxInt = c
+ v.AddArg(ptr)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (MOVHstoreidx (MOVDconst [c]) ptr val mem)
+ // cond: is16Bit(c)
+ // result: (MOVHstore [c] ptr val mem)
+ for {
+ _ = v.Args[3]
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := v_0.AuxInt
+ ptr := v.Args[1]
+ val := v.Args[2]
+ mem := v.Args[3]
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64MOVHstore)
+ v.AuxInt = c
+ v.AddArg(ptr)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (MOVHstoreidx [off] {sym} ptr idx (MOVHreg x) mem)
+ // cond:
+ // result: (MOVHstoreidx [off] {sym} ptr idx x mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[3]
+ ptr := v.Args[0]
+ idx := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpPPC64MOVHreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v.Args[3]
+ v.reset(OpPPC64MOVHstoreidx)
+ v.AuxInt = off
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(idx)
+ v.AddArg(x)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (MOVHstoreidx [off] {sym} ptr idx (MOVHZreg x) mem)
+ // cond:
+ // result: (MOVHstoreidx [off] {sym} ptr idx x mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[3]
+ ptr := v.Args[0]
+ idx := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpPPC64MOVHZreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v.Args[3]
+ v.reset(OpPPC64MOVHstoreidx)
+ v.AuxInt = off
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(idx)
+ v.AddArg(x)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (MOVHstoreidx [off] {sym} ptr idx (MOVWreg x) mem)
+ // cond:
+ // result: (MOVHstoreidx [off] {sym} ptr idx x mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[3]
+ ptr := v.Args[0]
+ idx := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpPPC64MOVWreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v.Args[3]
+ v.reset(OpPPC64MOVHstoreidx)
+ v.AuxInt = off
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(idx)
+ v.AddArg(x)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (MOVHstoreidx [off] {sym} ptr idx (MOVWZreg x) mem)
+ // cond:
+ // result: (MOVHstoreidx [off] {sym} ptr idx x mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[3]
+ ptr := v.Args[0]
+ idx := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpPPC64MOVWZreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v.Args[3]
+ v.reset(OpPPC64MOVHstoreidx)
+ v.AuxInt = off
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(idx)
+ v.AddArg(x)
+ v.AddArg(mem)
+ return true
+ }
+ return false
+}
func rewriteValuePPC64_OpPPC64MOVHstorezero_0(v *Value) bool {
// match: (MOVHstorezero [off1] {sym} (ADDconst [off2] x) mem)
// cond: is16Bit(off1+off2)
@@ -9231,9 +11132,84 @@ func rewriteValuePPC64_OpPPC64MOVWZload_0(v *Value) bool {
v.AddArg(mem)
return true
}
+ // match: (MOVWZload [0] {sym} p:(ADD ptr idx) mem)
+ // cond: sym == nil && p.Uses == 1
+ // result: (MOVWZloadidx ptr idx mem)
+ for {
+ if v.AuxInt != 0 {
+ break
+ }
+ sym := v.Aux
+ _ = v.Args[1]
+ p := v.Args[0]
+ if p.Op != OpPPC64ADD {
+ break
+ }
+ _ = p.Args[1]
+ ptr := p.Args[0]
+ idx := p.Args[1]
+ mem := v.Args[1]
+ if !(sym == nil && p.Uses == 1) {
+ break
+ }
+ v.reset(OpPPC64MOVWZloadidx)
+ v.AddArg(ptr)
+ v.AddArg(idx)
+ v.AddArg(mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVWZloadidx_0(v *Value) bool {
+ // match: (MOVWZloadidx ptr (MOVDconst [c]) mem)
+ // cond: is16Bit(c)
+ // result: (MOVWZload [c] ptr mem)
+ for {
+ _ = v.Args[2]
+ ptr := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ mem := v.Args[2]
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64MOVWZload)
+ v.AuxInt = c
+ v.AddArg(ptr)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (MOVWZloadidx (MOVDconst [c]) ptr mem)
+ // cond: is16Bit(c)
+ // result: (MOVWZload [c] ptr mem)
+ for {
+ _ = v.Args[2]
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := v_0.AuxInt
+ ptr := v.Args[1]
+ mem := v.Args[2]
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64MOVWZload)
+ v.AuxInt = c
+ v.AddArg(ptr)
+ v.AddArg(mem)
+ return true
+ }
return false
}
func rewriteValuePPC64_OpPPC64MOVWZreg_0(v *Value) bool {
+ b := v.Block
+ _ = b
+ typ := &b.Func.Config.Types
+ _ = typ
// match: (MOVWZreg y:(ANDconst [c] _))
// cond: uint64(c) <= 0xFFFFFFFF
// result: y
@@ -9295,6 +11271,105 @@ func rewriteValuePPC64_OpPPC64MOVWZreg_0(v *Value) bool {
v.AddArg(y)
return true
}
+ // match: (MOVWZreg (SRWconst [c] (MOVBZreg x)))
+ // cond:
+ // result: (SRWconst [c] (MOVBZreg x))
+ for {
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64SRWconst {
+ break
+ }
+ c := v_0.AuxInt
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64MOVBZreg {
+ break
+ }
+ x := v_0_0.Args[0]
+ v.reset(OpPPC64SRWconst)
+ v.AuxInt = c
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVBZreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MOVWZreg (SRWconst [c] (MOVHZreg x)))
+ // cond:
+ // result: (SRWconst [c] (MOVHZreg x))
+ for {
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64SRWconst {
+ break
+ }
+ c := v_0.AuxInt
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64MOVHZreg {
+ break
+ }
+ x := v_0_0.Args[0]
+ v.reset(OpPPC64SRWconst)
+ v.AuxInt = c
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVHZreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MOVWZreg (SRWconst [c] (MOVWZreg x)))
+ // cond:
+ // result: (SRWconst [c] (MOVWZreg x))
+ for {
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64SRWconst {
+ break
+ }
+ c := v_0.AuxInt
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64MOVWZreg {
+ break
+ }
+ x := v_0_0.Args[0]
+ v.reset(OpPPC64SRWconst)
+ v.AuxInt = c
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVWZreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MOVWZreg (SRWconst [c] x))
+ // cond: sizeof(x.Type) <= 32
+ // result: (SRWconst [c] x)
+ for {
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64SRWconst {
+ break
+ }
+ c := v_0.AuxInt
+ x := v_0.Args[0]
+ if !(sizeof(x.Type) <= 32) {
+ break
+ }
+ v.reset(OpPPC64SRWconst)
+ v.AuxInt = c
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWZreg (SRDconst [c] x))
+ // cond: c>=32
+ // result: (SRDconst [c] x)
+ for {
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64SRDconst {
+ break
+ }
+ c := v_0.AuxInt
+ x := v_0.Args[0]
+ if !(c >= 32) {
+ break
+ }
+ v.reset(OpPPC64SRDconst)
+ v.AuxInt = c
+ v.AddArg(x)
+ return true
+ }
// match: (MOVWZreg y:(MOVWZreg _))
// cond:
// result: y
@@ -9321,6 +11396,9 @@ func rewriteValuePPC64_OpPPC64MOVWZreg_0(v *Value) bool {
v.AddArg(y)
return true
}
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVWZreg_10(v *Value) bool {
// match: (MOVWZreg y:(MOVBZreg _))
// cond:
// result: y
@@ -9375,6 +11453,123 @@ func rewriteValuePPC64_OpPPC64MOVWZreg_0(v *Value) bool {
v.AddArg(x)
return true
}
+ // match: (MOVWZreg x:(MOVBZload _ _))
+ // cond:
+ // result: x
+ for {
+ x := v.Args[0]
+ if x.Op != OpPPC64MOVBZload {
+ break
+ }
+ _ = x.Args[1]
+ v.reset(OpCopy)
+ v.Type = x.Type
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWZreg x:(MOVBZloadidx _ _ _))
+ // cond:
+ // result: x
+ for {
+ x := v.Args[0]
+ if x.Op != OpPPC64MOVBZloadidx {
+ break
+ }
+ _ = x.Args[2]
+ v.reset(OpCopy)
+ v.Type = x.Type
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWZreg x:(MOVHZload _ _))
+ // cond:
+ // result: x
+ for {
+ x := v.Args[0]
+ if x.Op != OpPPC64MOVHZload {
+ break
+ }
+ _ = x.Args[1]
+ v.reset(OpCopy)
+ v.Type = x.Type
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWZreg x:(MOVHZloadidx _ _ _))
+ // cond:
+ // result: x
+ for {
+ x := v.Args[0]
+ if x.Op != OpPPC64MOVHZloadidx {
+ break
+ }
+ _ = x.Args[2]
+ v.reset(OpCopy)
+ v.Type = x.Type
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWZreg x:(MOVWZload _ _))
+ // cond:
+ // result: x
+ for {
+ x := v.Args[0]
+ if x.Op != OpPPC64MOVWZload {
+ break
+ }
+ _ = x.Args[1]
+ v.reset(OpCopy)
+ v.Type = x.Type
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWZreg x:(MOVWZloadidx _ _ _))
+ // cond:
+ // result: x
+ for {
+ x := v.Args[0]
+ if x.Op != OpPPC64MOVWZloadidx {
+ break
+ }
+ _ = x.Args[2]
+ v.reset(OpCopy)
+ v.Type = x.Type
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVWZreg_20(v *Value) bool {
+ // match: (MOVWZreg x:(Arg <t>))
+ // cond: (is8BitInt(t) || is16BitInt(t) || is32BitInt(t)) && !isSigned(t)
+ // result: x
+ for {
+ x := v.Args[0]
+ if x.Op != OpArg {
+ break
+ }
+ t := x.Type
+ if !((is8BitInt(t) || is16BitInt(t) || is32BitInt(t)) && !isSigned(t)) {
+ break
+ }
+ v.reset(OpCopy)
+ v.Type = x.Type
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWZreg (MOVDconst [c]))
+ // cond:
+ // result: (MOVDconst [int64(uint32(c))])
+ for {
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := v_0.AuxInt
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64(uint32(c))
+ return true
+ }
return false
}
func rewriteValuePPC64_OpPPC64MOVWload_0(v *Value) bool {
@@ -9427,9 +11622,84 @@ func rewriteValuePPC64_OpPPC64MOVWload_0(v *Value) bool {
v.AddArg(mem)
return true
}
+ // match: (MOVWload [0] {sym} p:(ADD ptr idx) mem)
+ // cond: sym == nil && p.Uses == 1
+ // result: (MOVWloadidx ptr idx mem)
+ for {
+ if v.AuxInt != 0 {
+ break
+ }
+ sym := v.Aux
+ _ = v.Args[1]
+ p := v.Args[0]
+ if p.Op != OpPPC64ADD {
+ break
+ }
+ _ = p.Args[1]
+ ptr := p.Args[0]
+ idx := p.Args[1]
+ mem := v.Args[1]
+ if !(sym == nil && p.Uses == 1) {
+ break
+ }
+ v.reset(OpPPC64MOVWloadidx)
+ v.AddArg(ptr)
+ v.AddArg(idx)
+ v.AddArg(mem)
+ return true
+ }
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVWloadidx_0(v *Value) bool {
+ // match: (MOVWloadidx ptr (MOVDconst [c]) mem)
+ // cond: is16Bit(c)
+ // result: (MOVWload [c] ptr mem)
+ for {
+ _ = v.Args[2]
+ ptr := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ mem := v.Args[2]
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64MOVWload)
+ v.AuxInt = c
+ v.AddArg(ptr)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (MOVWloadidx (MOVDconst [c]) ptr mem)
+ // cond: is16Bit(c)
+ // result: (MOVWload [c] ptr mem)
+ for {
+ _ = v.Args[2]
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := v_0.AuxInt
+ ptr := v.Args[1]
+ mem := v.Args[2]
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64MOVWload)
+ v.AuxInt = c
+ v.AddArg(ptr)
+ v.AddArg(mem)
+ return true
+ }
return false
}
func rewriteValuePPC64_OpPPC64MOVWreg_0(v *Value) bool {
+ b := v.Block
+ _ = b
+ typ := &b.Func.Config.Types
+ _ = typ
// match: (MOVWreg y:(ANDconst [c] _))
// cond: uint64(c) <= 0xFFFF
// result: y
@@ -9491,6 +11761,123 @@ func rewriteValuePPC64_OpPPC64MOVWreg_0(v *Value) bool {
v.AddArg(y)
return true
}
+ // match: (MOVWreg (SRAWconst [c] (MOVBreg x)))
+ // cond:
+ // result: (SRAWconst [c] (MOVBreg x))
+ for {
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64SRAWconst {
+ break
+ }
+ c := v_0.AuxInt
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64MOVBreg {
+ break
+ }
+ x := v_0_0.Args[0]
+ v.reset(OpPPC64SRAWconst)
+ v.AuxInt = c
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVBreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MOVWreg (SRAWconst [c] (MOVHreg x)))
+ // cond:
+ // result: (SRAWconst [c] (MOVHreg x))
+ for {
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64SRAWconst {
+ break
+ }
+ c := v_0.AuxInt
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64MOVHreg {
+ break
+ }
+ x := v_0_0.Args[0]
+ v.reset(OpPPC64SRAWconst)
+ v.AuxInt = c
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVHreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MOVWreg (SRAWconst [c] (MOVWreg x)))
+ // cond:
+ // result: (SRAWconst [c] (MOVWreg x))
+ for {
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64SRAWconst {
+ break
+ }
+ c := v_0.AuxInt
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64MOVWreg {
+ break
+ }
+ x := v_0_0.Args[0]
+ v.reset(OpPPC64SRAWconst)
+ v.AuxInt = c
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVWreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (MOVWreg (SRAWconst [c] x))
+ // cond: sizeof(x.Type) <= 32
+ // result: (SRAWconst [c] x)
+ for {
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64SRAWconst {
+ break
+ }
+ c := v_0.AuxInt
+ x := v_0.Args[0]
+ if !(sizeof(x.Type) <= 32) {
+ break
+ }
+ v.reset(OpPPC64SRAWconst)
+ v.AuxInt = c
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg (SRDconst [c] x))
+ // cond: c>32
+ // result: (SRDconst [c] x)
+ for {
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64SRDconst {
+ break
+ }
+ c := v_0.AuxInt
+ x := v_0.Args[0]
+ if !(c > 32) {
+ break
+ }
+ v.reset(OpPPC64SRDconst)
+ v.AuxInt = c
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg (SRDconst [c] x))
+ // cond: c==32
+ // result: (SRADconst [c] x)
+ for {
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64SRDconst {
+ break
+ }
+ c := v_0.AuxInt
+ x := v_0.Args[0]
+ if !(c == 32) {
+ break
+ }
+ v.reset(OpPPC64SRADconst)
+ v.AuxInt = c
+ v.AddArg(x)
+ return true
+ }
// match: (MOVWreg y:(MOVWreg _))
// cond:
// result: y
@@ -9504,6 +11891,9 @@ func rewriteValuePPC64_OpPPC64MOVWreg_0(v *Value) bool {
v.AddArg(y)
return true
}
+ return false
+}
+func rewriteValuePPC64_OpPPC64MOVWreg_10(v *Value) bool {
// match: (MOVWreg y:(MOVHreg _))
// cond:
// result: y
@@ -9543,6 +11933,92 @@ func rewriteValuePPC64_OpPPC64MOVWreg_0(v *Value) bool {
v.AddArg(x)
return true
}
+ // match: (MOVWreg x:(MOVHload _ _))
+ // cond:
+ // result: x
+ for {
+ x := v.Args[0]
+ if x.Op != OpPPC64MOVHload {
+ break
+ }
+ _ = x.Args[1]
+ v.reset(OpCopy)
+ v.Type = x.Type
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVHloadidx _ _ _))
+ // cond:
+ // result: x
+ for {
+ x := v.Args[0]
+ if x.Op != OpPPC64MOVHloadidx {
+ break
+ }
+ _ = x.Args[2]
+ v.reset(OpCopy)
+ v.Type = x.Type
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVWload _ _))
+ // cond:
+ // result: x
+ for {
+ x := v.Args[0]
+ if x.Op != OpPPC64MOVWload {
+ break
+ }
+ _ = x.Args[1]
+ v.reset(OpCopy)
+ v.Type = x.Type
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(MOVWloadidx _ _ _))
+ // cond:
+ // result: x
+ for {
+ x := v.Args[0]
+ if x.Op != OpPPC64MOVWloadidx {
+ break
+ }
+ _ = x.Args[2]
+ v.reset(OpCopy)
+ v.Type = x.Type
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg x:(Arg <t>))
+ // cond: (is8BitInt(t) || is16BitInt(t) || is32BitInt(t)) && isSigned(t)
+ // result: x
+ for {
+ x := v.Args[0]
+ if x.Op != OpArg {
+ break
+ }
+ t := x.Type
+ if !((is8BitInt(t) || is16BitInt(t) || is32BitInt(t)) && isSigned(t)) {
+ break
+ }
+ v.reset(OpCopy)
+ v.Type = x.Type
+ v.AddArg(x)
+ return true
+ }
+ // match: (MOVWreg (MOVDconst [c]))
+ // cond:
+ // result: (MOVDconst [int64(int32(c))])
+ for {
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := v_0.AuxInt
+ v.reset(OpPPC64MOVDconst)
+ v.AuxInt = int64(int32(c))
+ return true
+ }
return false
}
func rewriteValuePPC64_OpPPC64MOVWstore_0(v *Value) bool {
@@ -9599,8 +12075,8 @@ func rewriteValuePPC64_OpPPC64MOVWstore_0(v *Value) bool {
v.AddArg(mem)
return true
}
- // match: (MOVWstore [off] {sym} ptr (MOVDconst [c]) mem)
- // cond: c == 0
+ // match: (MOVWstore [off] {sym} ptr (MOVDconst [0]) mem)
+ // cond:
// result: (MOVWstorezero [off] {sym} ptr mem)
for {
off := v.AuxInt
@@ -9611,11 +12087,10 @@ func rewriteValuePPC64_OpPPC64MOVWstore_0(v *Value) bool {
if v_1.Op != OpPPC64MOVDconst {
break
}
- c := v_1.AuxInt
- mem := v.Args[2]
- if !(c == 0) {
+ if v_1.AuxInt != 0 {
break
}
+ mem := v.Args[2]
v.reset(OpPPC64MOVWstorezero)
v.AuxInt = off
v.Aux = sym
@@ -9623,6 +12098,32 @@ func rewriteValuePPC64_OpPPC64MOVWstore_0(v *Value) bool {
v.AddArg(mem)
return true
}
+ // match: (MOVWstore [off] {sym} p:(ADD ptr idx) val mem)
+ // cond: off == 0 && sym == nil && p.Uses == 1
+ // result: (MOVWstoreidx ptr idx val mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[2]
+ p := v.Args[0]
+ if p.Op != OpPPC64ADD {
+ break
+ }
+ _ = p.Args[1]
+ ptr := p.Args[0]
+ idx := p.Args[1]
+ val := v.Args[1]
+ mem := v.Args[2]
+ if !(off == 0 && sym == nil && p.Uses == 1) {
+ break
+ }
+ v.reset(OpPPC64MOVWstoreidx)
+ v.AddArg(ptr)
+ v.AddArg(idx)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
// match: (MOVWstore [off] {sym} ptr (MOVWreg x) mem)
// cond:
// result: (MOVWstore [off] {sym} ptr x mem)
@@ -9669,6 +12170,103 @@ func rewriteValuePPC64_OpPPC64MOVWstore_0(v *Value) bool {
}
return false
}
+func rewriteValuePPC64_OpPPC64MOVWstoreidx_0(v *Value) bool {
+ // match: (MOVWstoreidx ptr (MOVDconst [c]) val mem)
+ // cond: is16Bit(c)
+ // result: (MOVWstore [c] ptr val mem)
+ for {
+ _ = v.Args[3]
+ ptr := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ val := v.Args[2]
+ mem := v.Args[3]
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64MOVWstore)
+ v.AuxInt = c
+ v.AddArg(ptr)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (MOVWstoreidx (MOVDconst [c]) ptr val mem)
+ // cond: is16Bit(c)
+ // result: (MOVWstore [c] ptr val mem)
+ for {
+ _ = v.Args[3]
+ v_0 := v.Args[0]
+ if v_0.Op != OpPPC64MOVDconst {
+ break
+ }
+ c := v_0.AuxInt
+ ptr := v.Args[1]
+ val := v.Args[2]
+ mem := v.Args[3]
+ if !(is16Bit(c)) {
+ break
+ }
+ v.reset(OpPPC64MOVWstore)
+ v.AuxInt = c
+ v.AddArg(ptr)
+ v.AddArg(val)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (MOVWstoreidx [off] {sym} ptr idx (MOVWreg x) mem)
+ // cond:
+ // result: (MOVWstoreidx [off] {sym} ptr idx x mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[3]
+ ptr := v.Args[0]
+ idx := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpPPC64MOVWreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v.Args[3]
+ v.reset(OpPPC64MOVWstoreidx)
+ v.AuxInt = off
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(idx)
+ v.AddArg(x)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (MOVWstoreidx [off] {sym} ptr idx (MOVWZreg x) mem)
+ // cond:
+ // result: (MOVWstoreidx [off] {sym} ptr idx x mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[3]
+ ptr := v.Args[0]
+ idx := v.Args[1]
+ v_2 := v.Args[2]
+ if v_2.Op != OpPPC64MOVWZreg {
+ break
+ }
+ x := v_2.Args[0]
+ mem := v.Args[3]
+ v.reset(OpPPC64MOVWstoreidx)
+ v.AuxInt = off
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(idx)
+ v.AddArg(x)
+ v.AddArg(mem)
+ return true
+ }
+ return false
+}
func rewriteValuePPC64_OpPPC64MOVWstorezero_0(v *Value) bool {
// match: (MOVWstorezero [off1] {sym} (ADDconst [off2] x) mem)
// cond: is16Bit(off1+off2)
@@ -24104,6 +26702,23 @@ func rewriteValuePPC64_OpRsh16Ux16_0(v *Value) bool {
typ := &b.Func.Config.Types
_ = typ
// match: (Rsh16Ux16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRW (MOVHZreg x) y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVHZreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Rsh16Ux16 x y)
// cond:
// result: (SRW (ZeroExt16to32 x) (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-16] (ZeroExt16to64 y)))))
for {
@@ -24176,6 +26791,23 @@ func rewriteValuePPC64_OpRsh16Ux32_0(v *Value) bool {
return true
}
// match: (Rsh16Ux32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRW (MOVHZreg x) y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVHZreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Rsh16Ux32 x y)
// cond:
// result: (SRW (ZeroExt16to32 x) (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-16] (ZeroExt32to64 y)))))
for {
@@ -24265,6 +26897,23 @@ func rewriteValuePPC64_OpRsh16Ux64_0(v *Value) bool {
return true
}
// match: (Rsh16Ux64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRW (MOVHZreg x) y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVHZreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Rsh16Ux64 x y)
// cond:
// result: (SRW (ZeroExt16to32 x) (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-16] y))))
for {
@@ -24293,6 +26942,23 @@ func rewriteValuePPC64_OpRsh16Ux8_0(v *Value) bool {
typ := &b.Func.Config.Types
_ = typ
// match: (Rsh16Ux8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRW (MOVHZreg x) y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVHZreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Rsh16Ux8 x y)
// cond:
// result: (SRW (ZeroExt16to32 x) (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-16] (ZeroExt8to64 y)))))
for {
@@ -24323,6 +26989,23 @@ func rewriteValuePPC64_OpRsh16x16_0(v *Value) bool {
typ := &b.Func.Config.Types
_ = typ
// match: (Rsh16x16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAW (MOVHreg x) y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRAW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVHreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Rsh16x16 x y)
// cond:
// result: (SRAW (SignExt16to32 x) (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-16] (ZeroExt16to64 y)))))
for {
@@ -24395,6 +27078,23 @@ func rewriteValuePPC64_OpRsh16x32_0(v *Value) bool {
return true
}
// match: (Rsh16x32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAW (MOVHreg x) y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRAW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVHreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Rsh16x32 x y)
// cond:
// result: (SRAW (SignExt16to32 x) (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-16] (ZeroExt32to64 y)))))
for {
@@ -24488,6 +27188,23 @@ func rewriteValuePPC64_OpRsh16x64_0(v *Value) bool {
return true
}
// match: (Rsh16x64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAW (MOVHreg x) y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRAW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVHreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Rsh16x64 x y)
// cond:
// result: (SRAW (SignExt16to32 x) (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-16] y))))
for {
@@ -24516,6 +27233,23 @@ func rewriteValuePPC64_OpRsh16x8_0(v *Value) bool {
typ := &b.Func.Config.Types
_ = typ
// match: (Rsh16x8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAW (MOVHreg x) y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRAW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVHreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Rsh16x8 x y)
// cond:
// result: (SRAW (SignExt16to32 x) (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-16] (ZeroExt8to64 y)))))
for {
@@ -24546,6 +27280,21 @@ func rewriteValuePPC64_OpRsh32Ux16_0(v *Value) bool {
typ := &b.Func.Config.Types
_ = typ
// match: (Rsh32Ux16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRW x y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRW)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Rsh32Ux16 x y)
// cond:
// result: (SRW x (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-32] (ZeroExt16to64 y)))))
for {
@@ -24612,6 +27361,21 @@ func rewriteValuePPC64_OpRsh32Ux32_0(v *Value) bool {
return true
}
// match: (Rsh32Ux32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRW x y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRW)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Rsh32Ux32 x y)
// cond:
// result: (SRW x (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-32] (ZeroExt32to64 y)))))
for {
@@ -24694,6 +27458,21 @@ func rewriteValuePPC64_OpRsh32Ux64_0(v *Value) bool {
v.AddArg(x)
return true
}
+ // match: (Rsh32Ux64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRW x y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRW)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
// match: (Rsh32Ux64 x (AND y (MOVDconst [31])))
// cond:
// result: (SRW x (ANDconst <typ.Int32> [31] y))
@@ -24918,6 +27697,13 @@ func rewriteValuePPC64_OpRsh32Ux64_0(v *Value) bool {
v.AddArg(v0)
return true
}
+ return false
+}
+func rewriteValuePPC64_OpRsh32Ux64_10(v *Value) bool {
+ b := v.Block
+ _ = b
+ typ := &b.Func.Config.Types
+ _ = typ
// match: (Rsh32Ux64 x y)
// cond:
// result: (SRW x (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-32] y))))
@@ -24945,6 +27731,21 @@ func rewriteValuePPC64_OpRsh32Ux8_0(v *Value) bool {
typ := &b.Func.Config.Types
_ = typ
// match: (Rsh32Ux8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRW x y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRW)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Rsh32Ux8 x y)
// cond:
// result: (SRW x (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-32] (ZeroExt8to64 y)))))
for {
@@ -24973,6 +27774,21 @@ func rewriteValuePPC64_OpRsh32x16_0(v *Value) bool {
typ := &b.Func.Config.Types
_ = typ
// match: (Rsh32x16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAW x y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRAW)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Rsh32x16 x y)
// cond:
// result: (SRAW x (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-32] (ZeroExt16to64 y)))))
for {
@@ -25039,6 +27855,21 @@ func rewriteValuePPC64_OpRsh32x32_0(v *Value) bool {
return true
}
// match: (Rsh32x32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAW x y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRAW)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Rsh32x32 x y)
// cond:
// result: (SRAW x (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-32] (ZeroExt32to64 y)))))
for {
@@ -25123,6 +27954,21 @@ func rewriteValuePPC64_OpRsh32x64_0(v *Value) bool {
v.AddArg(x)
return true
}
+ // match: (Rsh32x64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAW x y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRAW)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
// match: (Rsh32x64 x (AND y (MOVDconst [31])))
// cond:
// result: (SRAW x (ANDconst <typ.Int32> [31] y))
@@ -25347,6 +28193,13 @@ func rewriteValuePPC64_OpRsh32x64_0(v *Value) bool {
v.AddArg(v0)
return true
}
+ return false
+}
+func rewriteValuePPC64_OpRsh32x64_10(v *Value) bool {
+ b := v.Block
+ _ = b
+ typ := &b.Func.Config.Types
+ _ = typ
// match: (Rsh32x64 x y)
// cond:
// result: (SRAW x (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-32] y))))
@@ -25374,6 +28227,21 @@ func rewriteValuePPC64_OpRsh32x8_0(v *Value) bool {
typ := &b.Func.Config.Types
_ = typ
// match: (Rsh32x8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAW x y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRAW)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Rsh32x8 x y)
// cond:
// result: (SRAW x (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-32] (ZeroExt8to64 y)))))
for {
@@ -25402,6 +28270,21 @@ func rewriteValuePPC64_OpRsh64Ux16_0(v *Value) bool {
typ := &b.Func.Config.Types
_ = typ
// match: (Rsh64Ux16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRD x y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRD)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Rsh64Ux16 x y)
// cond:
// result: (SRD x (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-64] (ZeroExt16to64 y)))))
for {
@@ -25468,6 +28351,21 @@ func rewriteValuePPC64_OpRsh64Ux32_0(v *Value) bool {
return true
}
// match: (Rsh64Ux32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRD x y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRD)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Rsh64Ux32 x y)
// cond:
// result: (SRD x (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-64] (ZeroExt32to64 y)))))
for {
@@ -25550,6 +28448,21 @@ func rewriteValuePPC64_OpRsh64Ux64_0(v *Value) bool {
v.AddArg(x)
return true
}
+ // match: (Rsh64Ux64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRD x y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRD)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
// match: (Rsh64Ux64 x (AND y (MOVDconst [63])))
// cond:
// result: (SRD x (ANDconst <typ.Int64> [63] y))
@@ -25774,6 +28687,13 @@ func rewriteValuePPC64_OpRsh64Ux64_0(v *Value) bool {
v.AddArg(v0)
return true
}
+ return false
+}
+func rewriteValuePPC64_OpRsh64Ux64_10(v *Value) bool {
+ b := v.Block
+ _ = b
+ typ := &b.Func.Config.Types
+ _ = typ
// match: (Rsh64Ux64 x y)
// cond:
// result: (SRD x (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-64] y))))
@@ -25801,6 +28721,21 @@ func rewriteValuePPC64_OpRsh64Ux8_0(v *Value) bool {
typ := &b.Func.Config.Types
_ = typ
// match: (Rsh64Ux8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRD x y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRD)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Rsh64Ux8 x y)
// cond:
// result: (SRD x (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-64] (ZeroExt8to64 y)))))
for {
@@ -25829,6 +28764,21 @@ func rewriteValuePPC64_OpRsh64x16_0(v *Value) bool {
typ := &b.Func.Config.Types
_ = typ
// match: (Rsh64x16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAD x y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRAD)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Rsh64x16 x y)
// cond:
// result: (SRAD x (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-64] (ZeroExt16to64 y)))))
for {
@@ -25895,6 +28845,21 @@ func rewriteValuePPC64_OpRsh64x32_0(v *Value) bool {
return true
}
// match: (Rsh64x32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAD x y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRAD)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Rsh64x32 x y)
// cond:
// result: (SRAD x (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-64] (ZeroExt32to64 y)))))
for {
@@ -25979,6 +28944,21 @@ func rewriteValuePPC64_OpRsh64x64_0(v *Value) bool {
v.AddArg(x)
return true
}
+ // match: (Rsh64x64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAD x y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRAD)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
// match: (Rsh64x64 x (AND y (MOVDconst [63])))
// cond:
// result: (SRAD x (ANDconst <typ.Int64> [63] y))
@@ -26203,6 +29183,13 @@ func rewriteValuePPC64_OpRsh64x64_0(v *Value) bool {
v.AddArg(v0)
return true
}
+ return false
+}
+func rewriteValuePPC64_OpRsh64x64_10(v *Value) bool {
+ b := v.Block
+ _ = b
+ typ := &b.Func.Config.Types
+ _ = typ
// match: (Rsh64x64 x y)
// cond:
// result: (SRAD x (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-64] y))))
@@ -26230,6 +29217,21 @@ func rewriteValuePPC64_OpRsh64x8_0(v *Value) bool {
typ := &b.Func.Config.Types
_ = typ
// match: (Rsh64x8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAD x y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRAD)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Rsh64x8 x y)
// cond:
// result: (SRAD x (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-64] (ZeroExt8to64 y)))))
for {
@@ -26258,6 +29260,23 @@ func rewriteValuePPC64_OpRsh8Ux16_0(v *Value) bool {
typ := &b.Func.Config.Types
_ = typ
// match: (Rsh8Ux16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRW (MOVBZreg x) y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVBZreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Rsh8Ux16 x y)
// cond:
// result: (SRW (ZeroExt8to32 x) (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-8] (ZeroExt16to64 y)))))
for {
@@ -26330,6 +29349,23 @@ func rewriteValuePPC64_OpRsh8Ux32_0(v *Value) bool {
return true
}
// match: (Rsh8Ux32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRW (MOVBZreg x) y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVBZreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Rsh8Ux32 x y)
// cond:
// result: (SRW (ZeroExt8to32 x) (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-8] (ZeroExt32to64 y)))))
for {
@@ -26419,6 +29455,23 @@ func rewriteValuePPC64_OpRsh8Ux64_0(v *Value) bool {
return true
}
// match: (Rsh8Ux64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRW (MOVBZreg x) y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVBZreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Rsh8Ux64 x y)
// cond:
// result: (SRW (ZeroExt8to32 x) (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-8] y))))
for {
@@ -26447,6 +29500,23 @@ func rewriteValuePPC64_OpRsh8Ux8_0(v *Value) bool {
typ := &b.Func.Config.Types
_ = typ
// match: (Rsh8Ux8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRW (MOVBZreg x) y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVBZreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Rsh8Ux8 x y)
// cond:
// result: (SRW (ZeroExt8to32 x) (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-8] (ZeroExt8to64 y)))))
for {
@@ -26477,6 +29547,23 @@ func rewriteValuePPC64_OpRsh8x16_0(v *Value) bool {
typ := &b.Func.Config.Types
_ = typ
// match: (Rsh8x16 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAW (MOVBreg x) y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRAW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVBreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Rsh8x16 x y)
// cond:
// result: (SRAW (SignExt8to32 x) (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-8] (ZeroExt16to64 y)))))
for {
@@ -26549,6 +29636,23 @@ func rewriteValuePPC64_OpRsh8x32_0(v *Value) bool {
return true
}
// match: (Rsh8x32 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAW (MOVBreg x) y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRAW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVBreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Rsh8x32 x y)
// cond:
// result: (SRAW (SignExt8to32 x) (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-8] (ZeroExt32to64 y)))))
for {
@@ -26642,6 +29746,23 @@ func rewriteValuePPC64_OpRsh8x64_0(v *Value) bool {
return true
}
// match: (Rsh8x64 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAW (MOVBreg x) y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRAW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVBreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Rsh8x64 x y)
// cond:
// result: (SRAW (SignExt8to32 x) (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-8] y))))
for {
@@ -26670,6 +29791,23 @@ func rewriteValuePPC64_OpRsh8x8_0(v *Value) bool {
typ := &b.Func.Config.Types
_ = typ
// match: (Rsh8x8 x y)
+ // cond: shiftIsBounded(v)
+ // result: (SRAW (MOVBreg x) y)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ y := v.Args[1]
+ if !(shiftIsBounded(v)) {
+ break
+ }
+ v.reset(OpPPC64SRAW)
+ v0 := b.NewValue0(v.Pos, OpPPC64MOVBreg, typ.Int64)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ v.AddArg(y)
+ return true
+ }
+ // match: (Rsh8x8 x y)
// cond:
// result: (SRAW (SignExt8to32 x) (ORN y <typ.Int64> (MaskIfNotCarry (ADDconstForCarry [-8] (ZeroExt8to64 y)))))
for {
@@ -27043,69 +30181,141 @@ func rewriteValuePPC64_OpTrunc_0(v *Value) bool {
}
func rewriteValuePPC64_OpTrunc16to8_0(v *Value) bool {
// match: (Trunc16to8 x)
- // cond:
+ // cond: isSigned(x.Type)
// result: (MOVBreg x)
for {
x := v.Args[0]
+ if !(isSigned(x.Type)) {
+ break
+ }
v.reset(OpPPC64MOVBreg)
v.AddArg(x)
return true
}
+ // match: (Trunc16to8 x)
+ // cond:
+ // result: (MOVBZreg x)
+ for {
+ x := v.Args[0]
+ v.reset(OpPPC64MOVBZreg)
+ v.AddArg(x)
+ return true
+ }
}
func rewriteValuePPC64_OpTrunc32to16_0(v *Value) bool {
// match: (Trunc32to16 x)
- // cond:
+ // cond: isSigned(x.Type)
// result: (MOVHreg x)
for {
x := v.Args[0]
+ if !(isSigned(x.Type)) {
+ break
+ }
v.reset(OpPPC64MOVHreg)
v.AddArg(x)
return true
}
+ // match: (Trunc32to16 x)
+ // cond:
+ // result: (MOVHZreg x)
+ for {
+ x := v.Args[0]
+ v.reset(OpPPC64MOVHZreg)
+ v.AddArg(x)
+ return true
+ }
}
func rewriteValuePPC64_OpTrunc32to8_0(v *Value) bool {
// match: (Trunc32to8 x)
- // cond:
+ // cond: isSigned(x.Type)
// result: (MOVBreg x)
for {
x := v.Args[0]
+ if !(isSigned(x.Type)) {
+ break
+ }
v.reset(OpPPC64MOVBreg)
v.AddArg(x)
return true
}
+ // match: (Trunc32to8 x)
+ // cond:
+ // result: (MOVBZreg x)
+ for {
+ x := v.Args[0]
+ v.reset(OpPPC64MOVBZreg)
+ v.AddArg(x)
+ return true
+ }
}
func rewriteValuePPC64_OpTrunc64to16_0(v *Value) bool {
// match: (Trunc64to16 x)
- // cond:
+ // cond: isSigned(x.Type)
// result: (MOVHreg x)
for {
x := v.Args[0]
+ if !(isSigned(x.Type)) {
+ break
+ }
v.reset(OpPPC64MOVHreg)
v.AddArg(x)
return true
}
+ // match: (Trunc64to16 x)
+ // cond:
+ // result: (MOVHZreg x)
+ for {
+ x := v.Args[0]
+ v.reset(OpPPC64MOVHZreg)
+ v.AddArg(x)
+ return true
+ }
}
func rewriteValuePPC64_OpTrunc64to32_0(v *Value) bool {
// match: (Trunc64to32 x)
- // cond:
+ // cond: isSigned(x.Type)
// result: (MOVWreg x)
for {
x := v.Args[0]
+ if !(isSigned(x.Type)) {
+ break
+ }
v.reset(OpPPC64MOVWreg)
v.AddArg(x)
return true
}
+ // match: (Trunc64to32 x)
+ // cond:
+ // result: (MOVWZreg x)
+ for {
+ x := v.Args[0]
+ v.reset(OpPPC64MOVWZreg)
+ v.AddArg(x)
+ return true
+ }
}
func rewriteValuePPC64_OpTrunc64to8_0(v *Value) bool {
// match: (Trunc64to8 x)
- // cond:
+ // cond: isSigned(x.Type)
// result: (MOVBreg x)
for {
x := v.Args[0]
+ if !(isSigned(x.Type)) {
+ break
+ }
v.reset(OpPPC64MOVBreg)
v.AddArg(x)
return true
}
+ // match: (Trunc64to8 x)
+ // cond:
+ // result: (MOVBZreg x)
+ for {
+ x := v.Args[0]
+ v.reset(OpPPC64MOVBZreg)
+ v.AddArg(x)
+ return true
+ }
}
func rewriteValuePPC64_OpWB_0(v *Value) bool {
// match: (WB {fn} destptr srcptr mem)
diff --git a/src/cmd/compile/internal/ssa/rewriteWasm.go b/src/cmd/compile/internal/ssa/rewriteWasm.go
index c07651ef0e..b92556db90 100644
--- a/src/cmd/compile/internal/ssa/rewriteWasm.go
+++ b/src/cmd/compile/internal/ssa/rewriteWasm.go
@@ -5071,7 +5071,7 @@ func rewriteValueWasm_OpWasmF64Add_0(v *Value) bool {
_ = typ
// match: (F64Add (F64Const [x]) (F64Const [y]))
// cond:
- // result: (F64Const [f2i(i2f(x) + i2f(y))])
+ // result: (F64Const [auxFrom64F(auxTo64F(x) + auxTo64F(y))])
for {
_ = v.Args[1]
v_0 := v.Args[0]
@@ -5085,7 +5085,7 @@ func rewriteValueWasm_OpWasmF64Add_0(v *Value) bool {
}
y := v_1.AuxInt
v.reset(OpWasmF64Const)
- v.AuxInt = f2i(i2f(x) + i2f(y))
+ v.AuxInt = auxFrom64F(auxTo64F(x) + auxTo64F(y))
return true
}
// match: (F64Add (F64Const [x]) y)
@@ -5115,7 +5115,7 @@ func rewriteValueWasm_OpWasmF64Mul_0(v *Value) bool {
_ = typ
// match: (F64Mul (F64Const [x]) (F64Const [y]))
// cond:
- // result: (F64Const [f2i(i2f(x) * i2f(y))])
+ // result: (F64Const [auxFrom64F(auxTo64F(x) * auxTo64F(y))])
for {
_ = v.Args[1]
v_0 := v.Args[0]
@@ -5129,7 +5129,7 @@ func rewriteValueWasm_OpWasmF64Mul_0(v *Value) bool {
}
y := v_1.AuxInt
v.reset(OpWasmF64Const)
- v.AuxInt = f2i(i2f(x) * i2f(y))
+ v.AuxInt = auxFrom64F(auxTo64F(x) * auxTo64F(y))
return true
}
// match: (F64Mul (F64Const [x]) y)
diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go
index 81bebede46..2f239faa49 100644
--- a/src/cmd/compile/internal/ssa/rewritegeneric.go
+++ b/src/cmd/compile/internal/ssa/rewritegeneric.go
@@ -2409,7 +2409,7 @@ func rewriteValuegeneric_OpAdd32_30(v *Value) bool {
func rewriteValuegeneric_OpAdd32F_0(v *Value) bool {
// match: (Add32F (Const32F [c]) (Const32F [d]))
// cond:
- // result: (Const32F [f2i(float64(i2f32(c) + i2f32(d)))])
+ // result: (Const32F [auxFrom32F(auxTo32F(c) + auxTo32F(d))])
for {
_ = v.Args[1]
v_0 := v.Args[0]
@@ -2423,12 +2423,12 @@ func rewriteValuegeneric_OpAdd32F_0(v *Value) bool {
}
d := v_1.AuxInt
v.reset(OpConst32F)
- v.AuxInt = f2i(float64(i2f32(c) + i2f32(d)))
+ v.AuxInt = auxFrom32F(auxTo32F(c) + auxTo32F(d))
return true
}
// match: (Add32F (Const32F [d]) (Const32F [c]))
// cond:
- // result: (Const32F [f2i(float64(i2f32(c) + i2f32(d)))])
+ // result: (Const32F [auxFrom32F(auxTo32F(c) + auxTo32F(d))])
for {
_ = v.Args[1]
v_0 := v.Args[0]
@@ -2442,43 +2442,7 @@ func rewriteValuegeneric_OpAdd32F_0(v *Value) bool {
}
c := v_1.AuxInt
v.reset(OpConst32F)
- v.AuxInt = f2i(float64(i2f32(c) + i2f32(d)))
- return true
- }
- // match: (Add32F x (Const32F [0]))
- // cond:
- // result: x
- for {
- _ = v.Args[1]
- x := v.Args[0]
- v_1 := v.Args[1]
- if v_1.Op != OpConst32F {
- break
- }
- if v_1.AuxInt != 0 {
- break
- }
- v.reset(OpCopy)
- v.Type = x.Type
- v.AddArg(x)
- return true
- }
- // match: (Add32F (Const32F [0]) x)
- // cond:
- // result: x
- for {
- _ = v.Args[1]
- v_0 := v.Args[0]
- if v_0.Op != OpConst32F {
- break
- }
- if v_0.AuxInt != 0 {
- break
- }
- x := v.Args[1]
- v.reset(OpCopy)
- v.Type = x.Type
- v.AddArg(x)
+ v.AuxInt = auxFrom32F(auxTo32F(c) + auxTo32F(d))
return true
}
return false
@@ -3454,7 +3418,7 @@ func rewriteValuegeneric_OpAdd64_30(v *Value) bool {
func rewriteValuegeneric_OpAdd64F_0(v *Value) bool {
// match: (Add64F (Const64F [c]) (Const64F [d]))
// cond:
- // result: (Const64F [f2i(i2f(c) + i2f(d))])
+ // result: (Const64F [auxFrom64F(auxTo64F(c) + auxTo64F(d))])
for {
_ = v.Args[1]
v_0 := v.Args[0]
@@ -3468,12 +3432,12 @@ func rewriteValuegeneric_OpAdd64F_0(v *Value) bool {
}
d := v_1.AuxInt
v.reset(OpConst64F)
- v.AuxInt = f2i(i2f(c) + i2f(d))
+ v.AuxInt = auxFrom64F(auxTo64F(c) + auxTo64F(d))
return true
}
// match: (Add64F (Const64F [d]) (Const64F [c]))
// cond:
- // result: (Const64F [f2i(i2f(c) + i2f(d))])
+ // result: (Const64F [auxFrom64F(auxTo64F(c) + auxTo64F(d))])
for {
_ = v.Args[1]
v_0 := v.Args[0]
@@ -3487,43 +3451,7 @@ func rewriteValuegeneric_OpAdd64F_0(v *Value) bool {
}
c := v_1.AuxInt
v.reset(OpConst64F)
- v.AuxInt = f2i(i2f(c) + i2f(d))
- return true
- }
- // match: (Add64F x (Const64F [0]))
- // cond:
- // result: x
- for {
- _ = v.Args[1]
- x := v.Args[0]
- v_1 := v.Args[1]
- if v_1.Op != OpConst64F {
- break
- }
- if v_1.AuxInt != 0 {
- break
- }
- v.reset(OpCopy)
- v.Type = x.Type
- v.AddArg(x)
- return true
- }
- // match: (Add64F (Const64F [0]) x)
- // cond:
- // result: x
- for {
- _ = v.Args[1]
- v_0 := v.Args[0]
- if v_0.Op != OpConst64F {
- break
- }
- if v_0.AuxInt != 0 {
- break
- }
- x := v.Args[1]
- v.reset(OpCopy)
- v.Type = x.Type
- v.AddArg(x)
+ v.AuxInt = auxFrom64F(auxTo64F(c) + auxTo64F(d))
return true
}
return false
@@ -7566,7 +7494,7 @@ func rewriteValuegeneric_OpConvert_0(v *Value) bool {
func rewriteValuegeneric_OpCvt32Fto32_0(v *Value) bool {
// match: (Cvt32Fto32 (Const32F [c]))
// cond:
- // result: (Const32 [int64(int32(i2f(c)))])
+ // result: (Const32 [int64(int32(auxTo32F(c)))])
for {
v_0 := v.Args[0]
if v_0.Op != OpConst32F {
@@ -7574,7 +7502,7 @@ func rewriteValuegeneric_OpCvt32Fto32_0(v *Value) bool {
}
c := v_0.AuxInt
v.reset(OpConst32)
- v.AuxInt = int64(int32(i2f(c)))
+ v.AuxInt = int64(int32(auxTo32F(c)))
return true
}
return false
@@ -7582,7 +7510,7 @@ func rewriteValuegeneric_OpCvt32Fto32_0(v *Value) bool {
func rewriteValuegeneric_OpCvt32Fto64_0(v *Value) bool {
// match: (Cvt32Fto64 (Const32F [c]))
// cond:
- // result: (Const64 [int64(i2f(c))])
+ // result: (Const64 [int64(auxTo32F(c))])
for {
v_0 := v.Args[0]
if v_0.Op != OpConst32F {
@@ -7590,7 +7518,7 @@ func rewriteValuegeneric_OpCvt32Fto64_0(v *Value) bool {
}
c := v_0.AuxInt
v.reset(OpConst64)
- v.AuxInt = int64(i2f(c))
+ v.AuxInt = int64(auxTo32F(c))
return true
}
return false
@@ -7614,7 +7542,7 @@ func rewriteValuegeneric_OpCvt32Fto64F_0(v *Value) bool {
func rewriteValuegeneric_OpCvt32to32F_0(v *Value) bool {
// match: (Cvt32to32F (Const32 [c]))
// cond:
- // result: (Const32F [f2i(float64(float32(int32(c))))])
+ // result: (Const32F [auxFrom32F(float32(int32(c)))])
for {
v_0 := v.Args[0]
if v_0.Op != OpConst32 {
@@ -7622,7 +7550,7 @@ func rewriteValuegeneric_OpCvt32to32F_0(v *Value) bool {
}
c := v_0.AuxInt
v.reset(OpConst32F)
- v.AuxInt = f2i(float64(float32(int32(c))))
+ v.AuxInt = auxFrom32F(float32(int32(c)))
return true
}
return false
@@ -7630,7 +7558,7 @@ func rewriteValuegeneric_OpCvt32to32F_0(v *Value) bool {
func rewriteValuegeneric_OpCvt32to64F_0(v *Value) bool {
// match: (Cvt32to64F (Const32 [c]))
// cond:
- // result: (Const64F [f2i(float64(int32(c)))])
+ // result: (Const64F [auxFrom64F(float64(int32(c)))])
for {
v_0 := v.Args[0]
if v_0.Op != OpConst32 {
@@ -7638,7 +7566,7 @@ func rewriteValuegeneric_OpCvt32to64F_0(v *Value) bool {
}
c := v_0.AuxInt
v.reset(OpConst64F)
- v.AuxInt = f2i(float64(int32(c)))
+ v.AuxInt = auxFrom64F(float64(int32(c)))
return true
}
return false
@@ -7646,7 +7574,7 @@ func rewriteValuegeneric_OpCvt32to64F_0(v *Value) bool {
func rewriteValuegeneric_OpCvt64Fto32_0(v *Value) bool {
// match: (Cvt64Fto32 (Const64F [c]))
// cond:
- // result: (Const32 [int64(int32(i2f(c)))])
+ // result: (Const32 [int64(int32(auxTo64F(c)))])
for {
v_0 := v.Args[0]
if v_0.Op != OpConst64F {
@@ -7654,7 +7582,7 @@ func rewriteValuegeneric_OpCvt64Fto32_0(v *Value) bool {
}
c := v_0.AuxInt
v.reset(OpConst32)
- v.AuxInt = int64(int32(i2f(c)))
+ v.AuxInt = int64(int32(auxTo64F(c)))
return true
}
return false
@@ -7662,7 +7590,7 @@ func rewriteValuegeneric_OpCvt64Fto32_0(v *Value) bool {
func rewriteValuegeneric_OpCvt64Fto32F_0(v *Value) bool {
// match: (Cvt64Fto32F (Const64F [c]))
// cond:
- // result: (Const32F [f2i(float64(i2f32(c)))])
+ // result: (Const32F [auxFrom32F(float32(auxTo64F(c)))])
for {
v_0 := v.Args[0]
if v_0.Op != OpConst64F {
@@ -7670,7 +7598,7 @@ func rewriteValuegeneric_OpCvt64Fto32F_0(v *Value) bool {
}
c := v_0.AuxInt
v.reset(OpConst32F)
- v.AuxInt = f2i(float64(i2f32(c)))
+ v.AuxInt = auxFrom32F(float32(auxTo64F(c)))
return true
}
return false
@@ -7678,7 +7606,7 @@ func rewriteValuegeneric_OpCvt64Fto32F_0(v *Value) bool {
func rewriteValuegeneric_OpCvt64Fto64_0(v *Value) bool {
// match: (Cvt64Fto64 (Const64F [c]))
// cond:
- // result: (Const64 [int64(i2f(c))])
+ // result: (Const64 [int64(auxTo64F(c))])
for {
v_0 := v.Args[0]
if v_0.Op != OpConst64F {
@@ -7686,7 +7614,7 @@ func rewriteValuegeneric_OpCvt64Fto64_0(v *Value) bool {
}
c := v_0.AuxInt
v.reset(OpConst64)
- v.AuxInt = int64(i2f(c))
+ v.AuxInt = int64(auxTo64F(c))
return true
}
return false
@@ -7694,7 +7622,7 @@ func rewriteValuegeneric_OpCvt64Fto64_0(v *Value) bool {
func rewriteValuegeneric_OpCvt64to32F_0(v *Value) bool {
// match: (Cvt64to32F (Const64 [c]))
// cond:
- // result: (Const32F [f2i(float64(float32(c)))])
+ // result: (Const32F [auxFrom32F(float32(c))])
for {
v_0 := v.Args[0]
if v_0.Op != OpConst64 {
@@ -7702,7 +7630,7 @@ func rewriteValuegeneric_OpCvt64to32F_0(v *Value) bool {
}
c := v_0.AuxInt
v.reset(OpConst32F)
- v.AuxInt = f2i(float64(float32(c)))
+ v.AuxInt = auxFrom32F(float32(c))
return true
}
return false
@@ -7710,7 +7638,7 @@ func rewriteValuegeneric_OpCvt64to32F_0(v *Value) bool {
func rewriteValuegeneric_OpCvt64to64F_0(v *Value) bool {
// match: (Cvt64to64F (Const64 [c]))
// cond:
- // result: (Const64F [f2i(float64(c))])
+ // result: (Const64F [auxFrom64F(float64(c))])
for {
v_0 := v.Args[0]
if v_0.Op != OpConst64 {
@@ -7718,7 +7646,7 @@ func rewriteValuegeneric_OpCvt64to64F_0(v *Value) bool {
}
c := v_0.AuxInt
v.reset(OpConst64F)
- v.AuxInt = f2i(float64(c))
+ v.AuxInt = auxFrom64F(float64(c))
return true
}
return false
@@ -8342,7 +8270,7 @@ func rewriteValuegeneric_OpDiv32F_0(v *Value) bool {
_ = b
// match: (Div32F (Const32F [c]) (Const32F [d]))
// cond:
- // result: (Const32F [f2i(float64(i2f32(c) / i2f32(d)))])
+ // result: (Const32F [auxFrom32F(auxTo32F(c) / auxTo32F(d))])
for {
_ = v.Args[1]
v_0 := v.Args[0]
@@ -8356,12 +8284,12 @@ func rewriteValuegeneric_OpDiv32F_0(v *Value) bool {
}
d := v_1.AuxInt
v.reset(OpConst32F)
- v.AuxInt = f2i(float64(i2f32(c) / i2f32(d)))
+ v.AuxInt = auxFrom32F(auxTo32F(c) / auxTo32F(d))
return true
}
// match: (Div32F x (Const32F <t> [c]))
- // cond: reciprocalExact32(float32(i2f(c)))
- // result: (Mul32F x (Const32F <t> [f2i(1/i2f(c))]))
+ // cond: reciprocalExact32(auxTo32F(c))
+ // result: (Mul32F x (Const32F <t> [auxFrom32F(1/auxTo32F(c))]))
for {
_ = v.Args[1]
x := v.Args[0]
@@ -8371,13 +8299,13 @@ func rewriteValuegeneric_OpDiv32F_0(v *Value) bool {
}
t := v_1.Type
c := v_1.AuxInt
- if !(reciprocalExact32(float32(i2f(c)))) {
+ if !(reciprocalExact32(auxTo32F(c))) {
break
}
v.reset(OpMul32F)
v.AddArg(x)
v0 := b.NewValue0(v.Pos, OpConst32F, t)
- v0.AuxInt = f2i(1 / i2f(c))
+ v0.AuxInt = auxFrom32F(1 / auxTo32F(c))
v.AddArg(v0)
return true
}
@@ -8866,7 +8794,7 @@ func rewriteValuegeneric_OpDiv64F_0(v *Value) bool {
_ = b
// match: (Div64F (Const64F [c]) (Const64F [d]))
// cond:
- // result: (Const64F [f2i(i2f(c) / i2f(d))])
+ // result: (Const64F [auxFrom64F(auxTo64F(c) / auxTo64F(d))])
for {
_ = v.Args[1]
v_0 := v.Args[0]
@@ -8880,12 +8808,12 @@ func rewriteValuegeneric_OpDiv64F_0(v *Value) bool {
}
d := v_1.AuxInt
v.reset(OpConst64F)
- v.AuxInt = f2i(i2f(c) / i2f(d))
+ v.AuxInt = auxFrom64F(auxTo64F(c) / auxTo64F(d))
return true
}
// match: (Div64F x (Const64F <t> [c]))
- // cond: reciprocalExact64(i2f(c))
- // result: (Mul64F x (Const64F <t> [f2i(1/i2f(c))]))
+ // cond: reciprocalExact64(auxTo64F(c))
+ // result: (Mul64F x (Const64F <t> [auxFrom64F(1/auxTo64F(c))]))
for {
_ = v.Args[1]
x := v.Args[0]
@@ -8895,13 +8823,13 @@ func rewriteValuegeneric_OpDiv64F_0(v *Value) bool {
}
t := v_1.Type
c := v_1.AuxInt
- if !(reciprocalExact64(i2f(c))) {
+ if !(reciprocalExact64(auxTo64F(c))) {
break
}
v.reset(OpMul64F)
v.AddArg(x)
v0 := b.NewValue0(v.Pos, OpConst64F, t)
- v0.AuxInt = f2i(1 / i2f(c))
+ v0.AuxInt = auxFrom64F(1 / auxTo64F(c))
v.AddArg(v0)
return true
}
@@ -9802,7 +9730,7 @@ func rewriteValuegeneric_OpEq32_0(v *Value) bool {
func rewriteValuegeneric_OpEq32F_0(v *Value) bool {
// match: (Eq32F (Const32F [c]) (Const32F [d]))
// cond:
- // result: (ConstBool [b2i(i2f(c) == i2f(d))])
+ // result: (ConstBool [b2i(auxTo32F(c) == auxTo32F(d))])
for {
_ = v.Args[1]
v_0 := v.Args[0]
@@ -9816,12 +9744,12 @@ func rewriteValuegeneric_OpEq32F_0(v *Value) bool {
}
d := v_1.AuxInt
v.reset(OpConstBool)
- v.AuxInt = b2i(i2f(c) == i2f(d))
+ v.AuxInt = b2i(auxTo32F(c) == auxTo32F(d))
return true
}
// match: (Eq32F (Const32F [d]) (Const32F [c]))
// cond:
- // result: (ConstBool [b2i(i2f(c) == i2f(d))])
+ // result: (ConstBool [b2i(auxTo32F(c) == auxTo32F(d))])
for {
_ = v.Args[1]
v_0 := v.Args[0]
@@ -9835,7 +9763,7 @@ func rewriteValuegeneric_OpEq32F_0(v *Value) bool {
}
c := v_1.AuxInt
v.reset(OpConstBool)
- v.AuxInt = b2i(i2f(c) == i2f(d))
+ v.AuxInt = b2i(auxTo32F(c) == auxTo32F(d))
return true
}
return false
@@ -10081,7 +10009,7 @@ func rewriteValuegeneric_OpEq64_0(v *Value) bool {
func rewriteValuegeneric_OpEq64F_0(v *Value) bool {
// match: (Eq64F (Const64F [c]) (Const64F [d]))
// cond:
- // result: (ConstBool [b2i(i2f(c) == i2f(d))])
+ // result: (ConstBool [b2i(auxTo64F(c) == auxTo64F(d))])
for {
_ = v.Args[1]
v_0 := v.Args[0]
@@ -10095,12 +10023,12 @@ func rewriteValuegeneric_OpEq64F_0(v *Value) bool {
}
d := v_1.AuxInt
v.reset(OpConstBool)
- v.AuxInt = b2i(i2f(c) == i2f(d))
+ v.AuxInt = b2i(auxTo64F(c) == auxTo64F(d))
return true
}
// match: (Eq64F (Const64F [d]) (Const64F [c]))
// cond:
- // result: (ConstBool [b2i(i2f(c) == i2f(d))])
+ // result: (ConstBool [b2i(auxTo64F(c) == auxTo64F(d))])
for {
_ = v.Args[1]
v_0 := v.Args[0]
@@ -10114,7 +10042,7 @@ func rewriteValuegeneric_OpEq64F_0(v *Value) bool {
}
c := v_1.AuxInt
v.reset(OpConstBool)
- v.AuxInt = b2i(i2f(c) == i2f(d))
+ v.AuxInt = b2i(auxTo64F(c) == auxTo64F(d))
return true
}
return false
@@ -11077,7 +11005,7 @@ func rewriteValuegeneric_OpGeq32_0(v *Value) bool {
func rewriteValuegeneric_OpGeq32F_0(v *Value) bool {
// match: (Geq32F (Const32F [c]) (Const32F [d]))
// cond:
- // result: (ConstBool [b2i(i2f(c) >= i2f(d))])
+ // result: (ConstBool [b2i(auxTo32F(c) >= auxTo32F(d))])
for {
_ = v.Args[1]
v_0 := v.Args[0]
@@ -11091,7 +11019,7 @@ func rewriteValuegeneric_OpGeq32F_0(v *Value) bool {
}
d := v_1.AuxInt
v.reset(OpConstBool)
- v.AuxInt = b2i(i2f(c) >= i2f(d))
+ v.AuxInt = b2i(auxTo32F(c) >= auxTo32F(d))
return true
}
return false
@@ -11143,7 +11071,7 @@ func rewriteValuegeneric_OpGeq64_0(v *Value) bool {
func rewriteValuegeneric_OpGeq64F_0(v *Value) bool {
// match: (Geq64F (Const64F [c]) (Const64F [d]))
// cond:
- // result: (ConstBool [b2i(i2f(c) >= i2f(d))])
+ // result: (ConstBool [b2i(auxTo64F(c) >= auxTo64F(d))])
for {
_ = v.Args[1]
v_0 := v.Args[0]
@@ -11157,7 +11085,7 @@ func rewriteValuegeneric_OpGeq64F_0(v *Value) bool {
}
d := v_1.AuxInt
v.reset(OpConstBool)
- v.AuxInt = b2i(i2f(c) >= i2f(d))
+ v.AuxInt = b2i(auxTo64F(c) >= auxTo64F(d))
return true
}
return false
@@ -11297,7 +11225,7 @@ func rewriteValuegeneric_OpGreater32_0(v *Value) bool {
func rewriteValuegeneric_OpGreater32F_0(v *Value) bool {
// match: (Greater32F (Const32F [c]) (Const32F [d]))
// cond:
- // result: (ConstBool [b2i(i2f(c) > i2f(d))])
+ // result: (ConstBool [b2i(auxTo32F(c) > auxTo32F(d))])
for {
_ = v.Args[1]
v_0 := v.Args[0]
@@ -11311,7 +11239,7 @@ func rewriteValuegeneric_OpGreater32F_0(v *Value) bool {
}
d := v_1.AuxInt
v.reset(OpConstBool)
- v.AuxInt = b2i(i2f(c) > i2f(d))
+ v.AuxInt = b2i(auxTo32F(c) > auxTo32F(d))
return true
}
return false
@@ -11363,7 +11291,7 @@ func rewriteValuegeneric_OpGreater64_0(v *Value) bool {
func rewriteValuegeneric_OpGreater64F_0(v *Value) bool {
// match: (Greater64F (Const64F [c]) (Const64F [d]))
// cond:
- // result: (ConstBool [b2i(i2f(c) > i2f(d))])
+ // result: (ConstBool [b2i(auxTo64F(c) > auxTo64F(d))])
for {
_ = v.Args[1]
v_0 := v.Args[0]
@@ -11377,7 +11305,7 @@ func rewriteValuegeneric_OpGreater64F_0(v *Value) bool {
}
d := v_1.AuxInt
v.reset(OpConstBool)
- v.AuxInt = b2i(i2f(c) > i2f(d))
+ v.AuxInt = b2i(auxTo64F(c) > auxTo64F(d))
return true
}
return false
@@ -12945,7 +12873,7 @@ func rewriteValuegeneric_OpLeq32_0(v *Value) bool {
func rewriteValuegeneric_OpLeq32F_0(v *Value) bool {
// match: (Leq32F (Const32F [c]) (Const32F [d]))
// cond:
- // result: (ConstBool [b2i(i2f(c) <= i2f(d))])
+ // result: (ConstBool [b2i(auxTo32F(c) <= auxTo32F(d))])
for {
_ = v.Args[1]
v_0 := v.Args[0]
@@ -12959,7 +12887,7 @@ func rewriteValuegeneric_OpLeq32F_0(v *Value) bool {
}
d := v_1.AuxInt
v.reset(OpConstBool)
- v.AuxInt = b2i(i2f(c) <= i2f(d))
+ v.AuxInt = b2i(auxTo32F(c) <= auxTo32F(d))
return true
}
return false
@@ -13011,7 +12939,7 @@ func rewriteValuegeneric_OpLeq64_0(v *Value) bool {
func rewriteValuegeneric_OpLeq64F_0(v *Value) bool {
// match: (Leq64F (Const64F [c]) (Const64F [d]))
// cond:
- // result: (ConstBool [b2i(i2f(c) <= i2f(d))])
+ // result: (ConstBool [b2i(auxTo64F(c) <= auxTo64F(d))])
for {
_ = v.Args[1]
v_0 := v.Args[0]
@@ -13025,7 +12953,7 @@ func rewriteValuegeneric_OpLeq64F_0(v *Value) bool {
}
d := v_1.AuxInt
v.reset(OpConstBool)
- v.AuxInt = b2i(i2f(c) <= i2f(d))
+ v.AuxInt = b2i(auxTo64F(c) <= auxTo64F(d))
return true
}
return false
@@ -13165,7 +13093,7 @@ func rewriteValuegeneric_OpLess32_0(v *Value) bool {
func rewriteValuegeneric_OpLess32F_0(v *Value) bool {
// match: (Less32F (Const32F [c]) (Const32F [d]))
// cond:
- // result: (ConstBool [b2i(i2f(c) < i2f(d))])
+ // result: (ConstBool [b2i(auxTo32F(c) < auxTo32F(d))])
for {
_ = v.Args[1]
v_0 := v.Args[0]
@@ -13179,7 +13107,7 @@ func rewriteValuegeneric_OpLess32F_0(v *Value) bool {
}
d := v_1.AuxInt
v.reset(OpConstBool)
- v.AuxInt = b2i(i2f(c) < i2f(d))
+ v.AuxInt = b2i(auxTo32F(c) < auxTo32F(d))
return true
}
return false
@@ -13231,7 +13159,7 @@ func rewriteValuegeneric_OpLess64_0(v *Value) bool {
func rewriteValuegeneric_OpLess64F_0(v *Value) bool {
// match: (Less64F (Const64F [c]) (Const64F [d]))
// cond:
- // result: (ConstBool [b2i(i2f(c) < i2f(d))])
+ // result: (ConstBool [b2i(auxTo64F(c) < auxTo64F(d))])
for {
_ = v.Args[1]
v_0 := v.Args[0]
@@ -13245,7 +13173,7 @@ func rewriteValuegeneric_OpLess64F_0(v *Value) bool {
}
d := v_1.AuxInt
v.reset(OpConstBool)
- v.AuxInt = b2i(i2f(c) < i2f(d))
+ v.AuxInt = b2i(auxTo64F(c) < auxTo64F(d))
return true
}
return false
@@ -13483,7 +13411,7 @@ func rewriteValuegeneric_OpLoad_0(v *Value) bool {
}
// match: (Load <t1> p1 (Store {t2} p2 (Const32 [x]) _))
// cond: isSamePtr(p1,p2) && sizeof(t2) == 4 && is32BitFloat(t1)
- // result: (Const32F [f2i(extend32Fto64F(math.Float32frombits(uint32(x))))])
+ // result: (Const32F [auxFrom32F(math.Float32frombits(uint32(x)))])
for {
t1 := v.Type
_ = v.Args[1]
@@ -13504,7 +13432,7 @@ func rewriteValuegeneric_OpLoad_0(v *Value) bool {
break
}
v.reset(OpConst32F)
- v.AuxInt = f2i(extend32Fto64F(math.Float32frombits(uint32(x))))
+ v.AuxInt = auxFrom32F(math.Float32frombits(uint32(x)))
return true
}
// match: (Load <t1> p1 (Store {t2} p2 (Const64F [x]) _))
@@ -13535,7 +13463,7 @@ func rewriteValuegeneric_OpLoad_0(v *Value) bool {
}
// match: (Load <t1> p1 (Store {t2} p2 (Const32F [x]) _))
// cond: isSamePtr(p1,p2) && sizeof(t2) == 4 && is32BitInt(t1)
- // result: (Const32 [int64(int32(math.Float32bits(truncate64Fto32F(i2f(x)))))])
+ // result: (Const32 [int64(int32(math.Float32bits(auxTo32F(x))))])
for {
t1 := v.Type
_ = v.Args[1]
@@ -13556,7 +13484,7 @@ func rewriteValuegeneric_OpLoad_0(v *Value) bool {
break
}
v.reset(OpConst32)
- v.AuxInt = int64(int32(math.Float32bits(truncate64Fto32F(i2f(x)))))
+ v.AuxInt = int64(int32(math.Float32bits(auxTo32F(x))))
return true
}
// match: (Load <t1> op:(OffPtr [o1] p1) (Store {t2} p2 _ mem:(Zero [n] p3 _)))
@@ -16223,9 +16151,9 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
v.AddArg(v0)
return true
}
- // match: (Move {t1} [n] dst p1 mem:(Store {t2} op2:(OffPtr [o2] p2) d1 (Store {t3} op3:(OffPtr [0] p3) d2 _)))
+ // match: (Move {t1} [n] dst p1 mem:(Store {t2} op2:(OffPtr <tt2> [o2] p2) d1 (Store {t3} op3:(OffPtr <tt3> [0] p3) d2 _)))
// cond: isSamePtr(p1, p2) && isSamePtr(p2, p3) && alignof(t2) <= alignof(t1) && alignof(t3) <= alignof(t1) && registerizable(b, t2) && registerizable(b, t3) && o2 == sizeof(t3) && n == sizeof(t2) + sizeof(t3)
- // result: (Store {t2} (OffPtr <t2.(*types.Type)> [o2] dst) d1 (Store {t3} (OffPtr <t3.(*types.Type)> [0] dst) d2 mem))
+ // result: (Store {t2} (OffPtr <tt2> [o2] dst) d1 (Store {t3} (OffPtr <tt3> [0] dst) d2 mem))
for {
n := v.AuxInt
t1 := v.Aux
@@ -16242,6 +16170,7 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
if op2.Op != OpOffPtr {
break
}
+ tt2 := op2.Type
o2 := op2.AuxInt
p2 := op2.Args[0]
d1 := mem.Args[1]
@@ -16255,6 +16184,7 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
if op3.Op != OpOffPtr {
break
}
+ tt3 := op3.Type
if op3.AuxInt != 0 {
break
}
@@ -16265,14 +16195,14 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
}
v.reset(OpStore)
v.Aux = t2
- v0 := b.NewValue0(v.Pos, OpOffPtr, t2.(*types.Type))
+ v0 := b.NewValue0(v.Pos, OpOffPtr, tt2)
v0.AuxInt = o2
v0.AddArg(dst)
v.AddArg(v0)
v.AddArg(d1)
v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
v1.Aux = t3
- v2 := b.NewValue0(v.Pos, OpOffPtr, t3.(*types.Type))
+ v2 := b.NewValue0(v.Pos, OpOffPtr, tt3)
v2.AuxInt = 0
v2.AddArg(dst)
v1.AddArg(v2)
@@ -16281,9 +16211,9 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
v.AddArg(v1)
return true
}
- // match: (Move {t1} [n] dst p1 mem:(Store {t2} op2:(OffPtr [o2] p2) d1 (Store {t3} op3:(OffPtr [o3] p3) d2 (Store {t4} op4:(OffPtr [0] p4) d3 _))))
+ // match: (Move {t1} [n] dst p1 mem:(Store {t2} op2:(OffPtr <tt2> [o2] p2) d1 (Store {t3} op3:(OffPtr <tt3> [o3] p3) d2 (Store {t4} op4:(OffPtr <tt4> [0] p4) d3 _))))
// cond: isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && alignof(t2) <= alignof(t1) && alignof(t3) <= alignof(t1) && alignof(t4) <= alignof(t1) && registerizable(b, t2) && registerizable(b, t3) && registerizable(b, t4) && o3 == sizeof(t4) && o2-o3 == sizeof(t3) && n == sizeof(t2) + sizeof(t3) + sizeof(t4)
- // result: (Store {t2} (OffPtr <t2.(*types.Type)> [o2] dst) d1 (Store {t3} (OffPtr <t3.(*types.Type)> [o3] dst) d2 (Store {t4} (OffPtr <t4.(*types.Type)> [0] dst) d3 mem)))
+ // result: (Store {t2} (OffPtr <tt2> [o2] dst) d1 (Store {t3} (OffPtr <tt3> [o3] dst) d2 (Store {t4} (OffPtr <tt4> [0] dst) d3 mem)))
for {
n := v.AuxInt
t1 := v.Aux
@@ -16300,6 +16230,7 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
if op2.Op != OpOffPtr {
break
}
+ tt2 := op2.Type
o2 := op2.AuxInt
p2 := op2.Args[0]
d1 := mem.Args[1]
@@ -16313,6 +16244,7 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
if op3.Op != OpOffPtr {
break
}
+ tt3 := op3.Type
o3 := op3.AuxInt
p3 := op3.Args[0]
d2 := mem_2.Args[1]
@@ -16326,6 +16258,7 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
if op4.Op != OpOffPtr {
break
}
+ tt4 := op4.Type
if op4.AuxInt != 0 {
break
}
@@ -16336,21 +16269,21 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
}
v.reset(OpStore)
v.Aux = t2
- v0 := b.NewValue0(v.Pos, OpOffPtr, t2.(*types.Type))
+ v0 := b.NewValue0(v.Pos, OpOffPtr, tt2)
v0.AuxInt = o2
v0.AddArg(dst)
v.AddArg(v0)
v.AddArg(d1)
v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
v1.Aux = t3
- v2 := b.NewValue0(v.Pos, OpOffPtr, t3.(*types.Type))
+ v2 := b.NewValue0(v.Pos, OpOffPtr, tt3)
v2.AuxInt = o3
v2.AddArg(dst)
v1.AddArg(v2)
v1.AddArg(d2)
v3 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
v3.Aux = t4
- v4 := b.NewValue0(v.Pos, OpOffPtr, t4.(*types.Type))
+ v4 := b.NewValue0(v.Pos, OpOffPtr, tt4)
v4.AuxInt = 0
v4.AddArg(dst)
v3.AddArg(v4)
@@ -16360,9 +16293,9 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
v.AddArg(v1)
return true
}
- // match: (Move {t1} [n] dst p1 mem:(Store {t2} op2:(OffPtr [o2] p2) d1 (Store {t3} op3:(OffPtr [o3] p3) d2 (Store {t4} op4:(OffPtr [o4] p4) d3 (Store {t5} op5:(OffPtr [0] p5) d4 _)))))
+ // match: (Move {t1} [n] dst p1 mem:(Store {t2} op2:(OffPtr <tt2> [o2] p2) d1 (Store {t3} op3:(OffPtr <tt3> [o3] p3) d2 (Store {t4} op4:(OffPtr <tt4> [o4] p4) d3 (Store {t5} op5:(OffPtr <tt5> [0] p5) d4 _)))))
// cond: isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5) && alignof(t2) <= alignof(t1) && alignof(t3) <= alignof(t1) && alignof(t4) <= alignof(t1) && alignof(t5) <= alignof(t1) && registerizable(b, t2) && registerizable(b, t3) && registerizable(b, t4) && registerizable(b, t5) && o4 == sizeof(t5) && o3-o4 == sizeof(t4) && o2-o3 == sizeof(t3) && n == sizeof(t2) + sizeof(t3) + sizeof(t4) + sizeof(t5)
- // result: (Store {t2} (OffPtr <t2.(*types.Type)> [o2] dst) d1 (Store {t3} (OffPtr <t3.(*types.Type)> [o3] dst) d2 (Store {t4} (OffPtr <t4.(*types.Type)> [o4] dst) d3 (Store {t5} (OffPtr <t5.(*types.Type)> [0] dst) d4 mem))))
+ // result: (Store {t2} (OffPtr <tt2> [o2] dst) d1 (Store {t3} (OffPtr <tt3> [o3] dst) d2 (Store {t4} (OffPtr <tt4> [o4] dst) d3 (Store {t5} (OffPtr <tt5> [0] dst) d4 mem))))
for {
n := v.AuxInt
t1 := v.Aux
@@ -16379,6 +16312,7 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
if op2.Op != OpOffPtr {
break
}
+ tt2 := op2.Type
o2 := op2.AuxInt
p2 := op2.Args[0]
d1 := mem.Args[1]
@@ -16392,6 +16326,7 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
if op3.Op != OpOffPtr {
break
}
+ tt3 := op3.Type
o3 := op3.AuxInt
p3 := op3.Args[0]
d2 := mem_2.Args[1]
@@ -16405,6 +16340,7 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
if op4.Op != OpOffPtr {
break
}
+ tt4 := op4.Type
o4 := op4.AuxInt
p4 := op4.Args[0]
d3 := mem_2_2.Args[1]
@@ -16418,6 +16354,7 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
if op5.Op != OpOffPtr {
break
}
+ tt5 := op5.Type
if op5.AuxInt != 0 {
break
}
@@ -16428,28 +16365,28 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
}
v.reset(OpStore)
v.Aux = t2
- v0 := b.NewValue0(v.Pos, OpOffPtr, t2.(*types.Type))
+ v0 := b.NewValue0(v.Pos, OpOffPtr, tt2)
v0.AuxInt = o2
v0.AddArg(dst)
v.AddArg(v0)
v.AddArg(d1)
v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
v1.Aux = t3
- v2 := b.NewValue0(v.Pos, OpOffPtr, t3.(*types.Type))
+ v2 := b.NewValue0(v.Pos, OpOffPtr, tt3)
v2.AuxInt = o3
v2.AddArg(dst)
v1.AddArg(v2)
v1.AddArg(d2)
v3 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
v3.Aux = t4
- v4 := b.NewValue0(v.Pos, OpOffPtr, t4.(*types.Type))
+ v4 := b.NewValue0(v.Pos, OpOffPtr, tt4)
v4.AuxInt = o4
v4.AddArg(dst)
v3.AddArg(v4)
v3.AddArg(d3)
v5 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
v5.Aux = t5
- v6 := b.NewValue0(v.Pos, OpOffPtr, t5.(*types.Type))
+ v6 := b.NewValue0(v.Pos, OpOffPtr, tt5)
v6.AuxInt = 0
v6.AddArg(dst)
v5.AddArg(v6)
@@ -16465,9 +16402,9 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
func rewriteValuegeneric_OpMove_10(v *Value) bool {
b := v.Block
_ = b
- // match: (Move {t1} [n] dst p1 mem:(VarDef (Store {t2} op2:(OffPtr [o2] p2) d1 (Store {t3} op3:(OffPtr [0] p3) d2 _))))
+ // match: (Move {t1} [n] dst p1 mem:(VarDef (Store {t2} op2:(OffPtr <tt2> [o2] p2) d1 (Store {t3} op3:(OffPtr <tt3> [0] p3) d2 _))))
// cond: isSamePtr(p1, p2) && isSamePtr(p2, p3) && alignof(t2) <= alignof(t1) && alignof(t3) <= alignof(t1) && registerizable(b, t2) && registerizable(b, t3) && o2 == sizeof(t3) && n == sizeof(t2) + sizeof(t3)
- // result: (Store {t2} (OffPtr <t2.(*types.Type)> [o2] dst) d1 (Store {t3} (OffPtr <t3.(*types.Type)> [0] dst) d2 mem))
+ // result: (Store {t2} (OffPtr <tt2> [o2] dst) d1 (Store {t3} (OffPtr <tt3> [0] dst) d2 mem))
for {
n := v.AuxInt
t1 := v.Aux
@@ -16488,6 +16425,7 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
if op2.Op != OpOffPtr {
break
}
+ tt2 := op2.Type
o2 := op2.AuxInt
p2 := op2.Args[0]
d1 := mem_0.Args[1]
@@ -16501,6 +16439,7 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
if op3.Op != OpOffPtr {
break
}
+ tt3 := op3.Type
if op3.AuxInt != 0 {
break
}
@@ -16511,14 +16450,14 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
}
v.reset(OpStore)
v.Aux = t2
- v0 := b.NewValue0(v.Pos, OpOffPtr, t2.(*types.Type))
+ v0 := b.NewValue0(v.Pos, OpOffPtr, tt2)
v0.AuxInt = o2
v0.AddArg(dst)
v.AddArg(v0)
v.AddArg(d1)
v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
v1.Aux = t3
- v2 := b.NewValue0(v.Pos, OpOffPtr, t3.(*types.Type))
+ v2 := b.NewValue0(v.Pos, OpOffPtr, tt3)
v2.AuxInt = 0
v2.AddArg(dst)
v1.AddArg(v2)
@@ -16527,9 +16466,9 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
v.AddArg(v1)
return true
}
- // match: (Move {t1} [n] dst p1 mem:(VarDef (Store {t2} op2:(OffPtr [o2] p2) d1 (Store {t3} op3:(OffPtr [o3] p3) d2 (Store {t4} op4:(OffPtr [0] p4) d3 _)))))
+ // match: (Move {t1} [n] dst p1 mem:(VarDef (Store {t2} op2:(OffPtr <tt2> [o2] p2) d1 (Store {t3} op3:(OffPtr <tt3> [o3] p3) d2 (Store {t4} op4:(OffPtr <tt4> [0] p4) d3 _)))))
// cond: isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && alignof(t2) <= alignof(t1) && alignof(t3) <= alignof(t1) && alignof(t4) <= alignof(t1) && registerizable(b, t2) && registerizable(b, t3) && registerizable(b, t4) && o3 == sizeof(t4) && o2-o3 == sizeof(t3) && n == sizeof(t2) + sizeof(t3) + sizeof(t4)
- // result: (Store {t2} (OffPtr <t2.(*types.Type)> [o2] dst) d1 (Store {t3} (OffPtr <t3.(*types.Type)> [o3] dst) d2 (Store {t4} (OffPtr <t4.(*types.Type)> [0] dst) d3 mem)))
+ // result: (Store {t2} (OffPtr <tt2> [o2] dst) d1 (Store {t3} (OffPtr <tt3> [o3] dst) d2 (Store {t4} (OffPtr <tt4> [0] dst) d3 mem)))
for {
n := v.AuxInt
t1 := v.Aux
@@ -16550,6 +16489,7 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
if op2.Op != OpOffPtr {
break
}
+ tt2 := op2.Type
o2 := op2.AuxInt
p2 := op2.Args[0]
d1 := mem_0.Args[1]
@@ -16563,6 +16503,7 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
if op3.Op != OpOffPtr {
break
}
+ tt3 := op3.Type
o3 := op3.AuxInt
p3 := op3.Args[0]
d2 := mem_0_2.Args[1]
@@ -16576,6 +16517,7 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
if op4.Op != OpOffPtr {
break
}
+ tt4 := op4.Type
if op4.AuxInt != 0 {
break
}
@@ -16586,21 +16528,21 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
}
v.reset(OpStore)
v.Aux = t2
- v0 := b.NewValue0(v.Pos, OpOffPtr, t2.(*types.Type))
+ v0 := b.NewValue0(v.Pos, OpOffPtr, tt2)
v0.AuxInt = o2
v0.AddArg(dst)
v.AddArg(v0)
v.AddArg(d1)
v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
v1.Aux = t3
- v2 := b.NewValue0(v.Pos, OpOffPtr, t3.(*types.Type))
+ v2 := b.NewValue0(v.Pos, OpOffPtr, tt3)
v2.AuxInt = o3
v2.AddArg(dst)
v1.AddArg(v2)
v1.AddArg(d2)
v3 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
v3.Aux = t4
- v4 := b.NewValue0(v.Pos, OpOffPtr, t4.(*types.Type))
+ v4 := b.NewValue0(v.Pos, OpOffPtr, tt4)
v4.AuxInt = 0
v4.AddArg(dst)
v3.AddArg(v4)
@@ -16610,9 +16552,9 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
v.AddArg(v1)
return true
}
- // match: (Move {t1} [n] dst p1 mem:(VarDef (Store {t2} op2:(OffPtr [o2] p2) d1 (Store {t3} op3:(OffPtr [o3] p3) d2 (Store {t4} op4:(OffPtr [o4] p4) d3 (Store {t5} op5:(OffPtr [0] p5) d4 _))))))
+ // match: (Move {t1} [n] dst p1 mem:(VarDef (Store {t2} op2:(OffPtr <tt2> [o2] p2) d1 (Store {t3} op3:(OffPtr <tt3> [o3] p3) d2 (Store {t4} op4:(OffPtr <tt4> [o4] p4) d3 (Store {t5} op5:(OffPtr <tt5> [0] p5) d4 _))))))
// cond: isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5) && alignof(t2) <= alignof(t1) && alignof(t3) <= alignof(t1) && alignof(t4) <= alignof(t1) && alignof(t5) <= alignof(t1) && registerizable(b, t2) && registerizable(b, t3) && registerizable(b, t4) && registerizable(b, t5) && o4 == sizeof(t5) && o3-o4 == sizeof(t4) && o2-o3 == sizeof(t3) && n == sizeof(t2) + sizeof(t3) + sizeof(t4) + sizeof(t5)
- // result: (Store {t2} (OffPtr <t2.(*types.Type)> [o2] dst) d1 (Store {t3} (OffPtr <t3.(*types.Type)> [o3] dst) d2 (Store {t4} (OffPtr <t4.(*types.Type)> [o4] dst) d3 (Store {t5} (OffPtr <t5.(*types.Type)> [0] dst) d4 mem))))
+ // result: (Store {t2} (OffPtr <tt2> [o2] dst) d1 (Store {t3} (OffPtr <tt3> [o3] dst) d2 (Store {t4} (OffPtr <tt4> [o4] dst) d3 (Store {t5} (OffPtr <tt5> [0] dst) d4 mem))))
for {
n := v.AuxInt
t1 := v.Aux
@@ -16633,6 +16575,7 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
if op2.Op != OpOffPtr {
break
}
+ tt2 := op2.Type
o2 := op2.AuxInt
p2 := op2.Args[0]
d1 := mem_0.Args[1]
@@ -16646,6 +16589,7 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
if op3.Op != OpOffPtr {
break
}
+ tt3 := op3.Type
o3 := op3.AuxInt
p3 := op3.Args[0]
d2 := mem_0_2.Args[1]
@@ -16659,6 +16603,7 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
if op4.Op != OpOffPtr {
break
}
+ tt4 := op4.Type
o4 := op4.AuxInt
p4 := op4.Args[0]
d3 := mem_0_2_2.Args[1]
@@ -16672,6 +16617,7 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
if op5.Op != OpOffPtr {
break
}
+ tt5 := op5.Type
if op5.AuxInt != 0 {
break
}
@@ -16682,28 +16628,28 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
}
v.reset(OpStore)
v.Aux = t2
- v0 := b.NewValue0(v.Pos, OpOffPtr, t2.(*types.Type))
+ v0 := b.NewValue0(v.Pos, OpOffPtr, tt2)
v0.AuxInt = o2
v0.AddArg(dst)
v.AddArg(v0)
v.AddArg(d1)
v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
v1.Aux = t3
- v2 := b.NewValue0(v.Pos, OpOffPtr, t3.(*types.Type))
+ v2 := b.NewValue0(v.Pos, OpOffPtr, tt3)
v2.AuxInt = o3
v2.AddArg(dst)
v1.AddArg(v2)
v1.AddArg(d2)
v3 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
v3.Aux = t4
- v4 := b.NewValue0(v.Pos, OpOffPtr, t4.(*types.Type))
+ v4 := b.NewValue0(v.Pos, OpOffPtr, tt4)
v4.AuxInt = o4
v4.AddArg(dst)
v3.AddArg(v4)
v3.AddArg(d3)
v5 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
v5.Aux = t5
- v6 := b.NewValue0(v.Pos, OpOffPtr, t5.(*types.Type))
+ v6 := b.NewValue0(v.Pos, OpOffPtr, tt5)
v6.AuxInt = 0
v6.AddArg(dst)
v5.AddArg(v6)
@@ -18320,7 +18266,7 @@ func rewriteValuegeneric_OpMul32_10(v *Value) bool {
func rewriteValuegeneric_OpMul32F_0(v *Value) bool {
// match: (Mul32F (Const32F [c]) (Const32F [d]))
// cond:
- // result: (Const32F [f2i(float64(i2f32(c) * i2f32(d)))])
+ // result: (Const32F [auxFrom32F(auxTo32F(c) * auxTo32F(d))])
for {
_ = v.Args[1]
v_0 := v.Args[0]
@@ -18334,12 +18280,12 @@ func rewriteValuegeneric_OpMul32F_0(v *Value) bool {
}
d := v_1.AuxInt
v.reset(OpConst32F)
- v.AuxInt = f2i(float64(i2f32(c) * i2f32(d)))
+ v.AuxInt = auxFrom32F(auxTo32F(c) * auxTo32F(d))
return true
}
// match: (Mul32F (Const32F [d]) (Const32F [c]))
// cond:
- // result: (Const32F [f2i(float64(i2f32(c) * i2f32(d)))])
+ // result: (Const32F [auxFrom32F(auxTo32F(c) * auxTo32F(d))])
for {
_ = v.Args[1]
v_0 := v.Args[0]
@@ -18353,10 +18299,10 @@ func rewriteValuegeneric_OpMul32F_0(v *Value) bool {
}
c := v_1.AuxInt
v.reset(OpConst32F)
- v.AuxInt = f2i(float64(i2f32(c) * i2f32(d)))
+ v.AuxInt = auxFrom32F(auxTo32F(c) * auxTo32F(d))
return true
}
- // match: (Mul32F x (Const32F [f2i(1)]))
+ // match: (Mul32F x (Const32F [auxFrom64F(1)]))
// cond:
// result: x
for {
@@ -18366,7 +18312,7 @@ func rewriteValuegeneric_OpMul32F_0(v *Value) bool {
if v_1.Op != OpConst32F {
break
}
- if v_1.AuxInt != f2i(1) {
+ if v_1.AuxInt != auxFrom64F(1) {
break
}
v.reset(OpCopy)
@@ -18374,7 +18320,7 @@ func rewriteValuegeneric_OpMul32F_0(v *Value) bool {
v.AddArg(x)
return true
}
- // match: (Mul32F (Const32F [f2i(1)]) x)
+ // match: (Mul32F (Const32F [auxFrom64F(1)]) x)
// cond:
// result: x
for {
@@ -18383,7 +18329,7 @@ func rewriteValuegeneric_OpMul32F_0(v *Value) bool {
if v_0.Op != OpConst32F {
break
}
- if v_0.AuxInt != f2i(1) {
+ if v_0.AuxInt != auxFrom64F(1) {
break
}
x := v.Args[1]
@@ -18392,7 +18338,7 @@ func rewriteValuegeneric_OpMul32F_0(v *Value) bool {
v.AddArg(x)
return true
}
- // match: (Mul32F x (Const32F [f2i(-1)]))
+ // match: (Mul32F x (Const32F [auxFrom32F(-1)]))
// cond:
// result: (Neg32F x)
for {
@@ -18402,14 +18348,14 @@ func rewriteValuegeneric_OpMul32F_0(v *Value) bool {
if v_1.Op != OpConst32F {
break
}
- if v_1.AuxInt != f2i(-1) {
+ if v_1.AuxInt != auxFrom32F(-1) {
break
}
v.reset(OpNeg32F)
v.AddArg(x)
return true
}
- // match: (Mul32F (Const32F [f2i(-1)]) x)
+ // match: (Mul32F (Const32F [auxFrom32F(-1)]) x)
// cond:
// result: (Neg32F x)
for {
@@ -18418,7 +18364,7 @@ func rewriteValuegeneric_OpMul32F_0(v *Value) bool {
if v_0.Op != OpConst32F {
break
}
- if v_0.AuxInt != f2i(-1) {
+ if v_0.AuxInt != auxFrom32F(-1) {
break
}
x := v.Args[1]
@@ -18426,7 +18372,7 @@ func rewriteValuegeneric_OpMul32F_0(v *Value) bool {
v.AddArg(x)
return true
}
- // match: (Mul32F x (Const32F [f2i(2)]))
+ // match: (Mul32F x (Const32F [auxFrom32F(2)]))
// cond:
// result: (Add32F x x)
for {
@@ -18436,7 +18382,7 @@ func rewriteValuegeneric_OpMul32F_0(v *Value) bool {
if v_1.Op != OpConst32F {
break
}
- if v_1.AuxInt != f2i(2) {
+ if v_1.AuxInt != auxFrom32F(2) {
break
}
v.reset(OpAdd32F)
@@ -18444,7 +18390,7 @@ func rewriteValuegeneric_OpMul32F_0(v *Value) bool {
v.AddArg(x)
return true
}
- // match: (Mul32F (Const32F [f2i(2)]) x)
+ // match: (Mul32F (Const32F [auxFrom32F(2)]) x)
// cond:
// result: (Add32F x x)
for {
@@ -18453,7 +18399,7 @@ func rewriteValuegeneric_OpMul32F_0(v *Value) bool {
if v_0.Op != OpConst32F {
break
}
- if v_0.AuxInt != f2i(2) {
+ if v_0.AuxInt != auxFrom32F(2) {
break
}
x := v.Args[1]
@@ -19001,7 +18947,7 @@ func rewriteValuegeneric_OpMul64_10(v *Value) bool {
func rewriteValuegeneric_OpMul64F_0(v *Value) bool {
// match: (Mul64F (Const64F [c]) (Const64F [d]))
// cond:
- // result: (Const64F [f2i(i2f(c) * i2f(d))])
+ // result: (Const64F [auxFrom64F(auxTo64F(c) * auxTo64F(d))])
for {
_ = v.Args[1]
v_0 := v.Args[0]
@@ -19015,12 +18961,12 @@ func rewriteValuegeneric_OpMul64F_0(v *Value) bool {
}
d := v_1.AuxInt
v.reset(OpConst64F)
- v.AuxInt = f2i(i2f(c) * i2f(d))
+ v.AuxInt = auxFrom64F(auxTo64F(c) * auxTo64F(d))
return true
}
// match: (Mul64F (Const64F [d]) (Const64F [c]))
// cond:
- // result: (Const64F [f2i(i2f(c) * i2f(d))])
+ // result: (Const64F [auxFrom64F(auxTo64F(c) * auxTo64F(d))])
for {
_ = v.Args[1]
v_0 := v.Args[0]
@@ -19034,10 +18980,10 @@ func rewriteValuegeneric_OpMul64F_0(v *Value) bool {
}
c := v_1.AuxInt
v.reset(OpConst64F)
- v.AuxInt = f2i(i2f(c) * i2f(d))
+ v.AuxInt = auxFrom64F(auxTo64F(c) * auxTo64F(d))
return true
}
- // match: (Mul64F x (Const64F [f2i(1)]))
+ // match: (Mul64F x (Const64F [auxFrom64F(1)]))
// cond:
// result: x
for {
@@ -19047,7 +18993,7 @@ func rewriteValuegeneric_OpMul64F_0(v *Value) bool {
if v_1.Op != OpConst64F {
break
}
- if v_1.AuxInt != f2i(1) {
+ if v_1.AuxInt != auxFrom64F(1) {
break
}
v.reset(OpCopy)
@@ -19055,7 +19001,7 @@ func rewriteValuegeneric_OpMul64F_0(v *Value) bool {
v.AddArg(x)
return true
}
- // match: (Mul64F (Const64F [f2i(1)]) x)
+ // match: (Mul64F (Const64F [auxFrom64F(1)]) x)
// cond:
// result: x
for {
@@ -19064,7 +19010,7 @@ func rewriteValuegeneric_OpMul64F_0(v *Value) bool {
if v_0.Op != OpConst64F {
break
}
- if v_0.AuxInt != f2i(1) {
+ if v_0.AuxInt != auxFrom64F(1) {
break
}
x := v.Args[1]
@@ -19073,7 +19019,7 @@ func rewriteValuegeneric_OpMul64F_0(v *Value) bool {
v.AddArg(x)
return true
}
- // match: (Mul64F x (Const64F [f2i(-1)]))
+ // match: (Mul64F x (Const64F [auxFrom64F(-1)]))
// cond:
// result: (Neg64F x)
for {
@@ -19083,14 +19029,14 @@ func rewriteValuegeneric_OpMul64F_0(v *Value) bool {
if v_1.Op != OpConst64F {
break
}
- if v_1.AuxInt != f2i(-1) {
+ if v_1.AuxInt != auxFrom64F(-1) {
break
}
v.reset(OpNeg64F)
v.AddArg(x)
return true
}
- // match: (Mul64F (Const64F [f2i(-1)]) x)
+ // match: (Mul64F (Const64F [auxFrom64F(-1)]) x)
// cond:
// result: (Neg64F x)
for {
@@ -19099,7 +19045,7 @@ func rewriteValuegeneric_OpMul64F_0(v *Value) bool {
if v_0.Op != OpConst64F {
break
}
- if v_0.AuxInt != f2i(-1) {
+ if v_0.AuxInt != auxFrom64F(-1) {
break
}
x := v.Args[1]
@@ -19107,7 +19053,7 @@ func rewriteValuegeneric_OpMul64F_0(v *Value) bool {
v.AddArg(x)
return true
}
- // match: (Mul64F x (Const64F [f2i(2)]))
+ // match: (Mul64F x (Const64F [auxFrom64F(2)]))
// cond:
// result: (Add64F x x)
for {
@@ -19117,7 +19063,7 @@ func rewriteValuegeneric_OpMul64F_0(v *Value) bool {
if v_1.Op != OpConst64F {
break
}
- if v_1.AuxInt != f2i(2) {
+ if v_1.AuxInt != auxFrom64F(2) {
break
}
v.reset(OpAdd64F)
@@ -19125,7 +19071,7 @@ func rewriteValuegeneric_OpMul64F_0(v *Value) bool {
v.AddArg(x)
return true
}
- // match: (Mul64F (Const64F [f2i(2)]) x)
+ // match: (Mul64F (Const64F [auxFrom64F(2)]) x)
// cond:
// result: (Add64F x x)
for {
@@ -19134,7 +19080,7 @@ func rewriteValuegeneric_OpMul64F_0(v *Value) bool {
if v_0.Op != OpConst64F {
break
}
- if v_0.AuxInt != f2i(2) {
+ if v_0.AuxInt != auxFrom64F(2) {
break
}
x := v.Args[1]
@@ -19585,19 +19531,19 @@ func rewriteValuegeneric_OpNeg32_0(v *Value) bool {
}
func rewriteValuegeneric_OpNeg32F_0(v *Value) bool {
// match: (Neg32F (Const32F [c]))
- // cond: i2f(c) != 0
- // result: (Const32F [f2i(-i2f(c))])
+ // cond: auxTo32F(c) != 0
+ // result: (Const32F [auxFrom32F(-auxTo32F(c))])
for {
v_0 := v.Args[0]
if v_0.Op != OpConst32F {
break
}
c := v_0.AuxInt
- if !(i2f(c) != 0) {
+ if !(auxTo32F(c) != 0) {
break
}
v.reset(OpConst32F)
- v.AuxInt = f2i(-i2f(c))
+ v.AuxInt = auxFrom32F(-auxTo32F(c))
return true
}
return false
@@ -19636,19 +19582,19 @@ func rewriteValuegeneric_OpNeg64_0(v *Value) bool {
}
func rewriteValuegeneric_OpNeg64F_0(v *Value) bool {
// match: (Neg64F (Const64F [c]))
- // cond: i2f(c) != 0
- // result: (Const64F [f2i(-i2f(c))])
+ // cond: auxTo64F(c) != 0
+ // result: (Const64F [auxFrom64F(-auxTo64F(c))])
for {
v_0 := v.Args[0]
if v_0.Op != OpConst64F {
break
}
c := v_0.AuxInt
- if !(i2f(c) != 0) {
+ if !(auxTo64F(c) != 0) {
break
}
v.reset(OpConst64F)
- v.AuxInt = f2i(-i2f(c))
+ v.AuxInt = auxFrom64F(-auxTo64F(c))
return true
}
return false
@@ -20164,7 +20110,7 @@ func rewriteValuegeneric_OpNeq32_0(v *Value) bool {
func rewriteValuegeneric_OpNeq32F_0(v *Value) bool {
// match: (Neq32F (Const32F [c]) (Const32F [d]))
// cond:
- // result: (ConstBool [b2i(i2f(c) != i2f(d))])
+ // result: (ConstBool [b2i(auxTo32F(c) != auxTo32F(d))])
for {
_ = v.Args[1]
v_0 := v.Args[0]
@@ -20178,12 +20124,12 @@ func rewriteValuegeneric_OpNeq32F_0(v *Value) bool {
}
d := v_1.AuxInt
v.reset(OpConstBool)
- v.AuxInt = b2i(i2f(c) != i2f(d))
+ v.AuxInt = b2i(auxTo32F(c) != auxTo32F(d))
return true
}
// match: (Neq32F (Const32F [d]) (Const32F [c]))
// cond:
- // result: (ConstBool [b2i(i2f(c) != i2f(d))])
+ // result: (ConstBool [b2i(auxTo32F(c) != auxTo32F(d))])
for {
_ = v.Args[1]
v_0 := v.Args[0]
@@ -20197,7 +20143,7 @@ func rewriteValuegeneric_OpNeq32F_0(v *Value) bool {
}
c := v_1.AuxInt
v.reset(OpConstBool)
- v.AuxInt = b2i(i2f(c) != i2f(d))
+ v.AuxInt = b2i(auxTo32F(c) != auxTo32F(d))
return true
}
return false
@@ -20443,7 +20389,7 @@ func rewriteValuegeneric_OpNeq64_0(v *Value) bool {
func rewriteValuegeneric_OpNeq64F_0(v *Value) bool {
// match: (Neq64F (Const64F [c]) (Const64F [d]))
// cond:
- // result: (ConstBool [b2i(i2f(c) != i2f(d))])
+ // result: (ConstBool [b2i(auxTo64F(c) != auxTo64F(d))])
for {
_ = v.Args[1]
v_0 := v.Args[0]
@@ -20457,12 +20403,12 @@ func rewriteValuegeneric_OpNeq64F_0(v *Value) bool {
}
d := v_1.AuxInt
v.reset(OpConstBool)
- v.AuxInt = b2i(i2f(c) != i2f(d))
+ v.AuxInt = b2i(auxTo64F(c) != auxTo64F(d))
return true
}
// match: (Neq64F (Const64F [d]) (Const64F [c]))
// cond:
- // result: (ConstBool [b2i(i2f(c) != i2f(d))])
+ // result: (ConstBool [b2i(auxTo64F(c) != auxTo64F(d))])
for {
_ = v.Args[1]
v_0 := v.Args[0]
@@ -20476,7 +20422,7 @@ func rewriteValuegeneric_OpNeq64F_0(v *Value) bool {
}
c := v_1.AuxInt
v.reset(OpConstBool)
- v.AuxInt = b2i(i2f(c) != i2f(d))
+ v.AuxInt = b2i(auxTo64F(c) != auxTo64F(d))
return true
}
return false
@@ -21412,7 +21358,7 @@ func rewriteValuegeneric_OpNilCheck_0(v *Value) bool {
return true
}
// match: (NilCheck (Load (OffPtr [c] (SP)) (StaticCall {sym} _)) _)
- // cond: isSameSym(sym, "runtime.newobject") && c == config.ctxt.FixedFrameSize() + config.RegSize && warnRule(fe.Debug_checknil() && v.Pos.Line() > 1, v, "removed nil check")
+ // cond: isSameSym(sym, "runtime.newobject") && c == config.ctxt.FixedFrameSize() + config.RegSize && warnRule(fe.Debug_checknil(), v, "removed nil check")
// result: (Invalid)
for {
_ = v.Args[1]
@@ -21435,14 +21381,14 @@ func rewriteValuegeneric_OpNilCheck_0(v *Value) bool {
break
}
sym := v_0_1.Aux
- if !(isSameSym(sym, "runtime.newobject") && c == config.ctxt.FixedFrameSize()+config.RegSize && warnRule(fe.Debug_checknil() && v.Pos.Line() > 1, v, "removed nil check")) {
+ if !(isSameSym(sym, "runtime.newobject") && c == config.ctxt.FixedFrameSize()+config.RegSize && warnRule(fe.Debug_checknil(), v, "removed nil check")) {
break
}
v.reset(OpInvalid)
return true
}
// match: (NilCheck (OffPtr (Load (OffPtr [c] (SP)) (StaticCall {sym} _))) _)
- // cond: isSameSym(sym, "runtime.newobject") && c == config.ctxt.FixedFrameSize() + config.RegSize && warnRule(fe.Debug_checknil() && v.Pos.Line() > 1, v, "removed nil check")
+ // cond: isSameSym(sym, "runtime.newobject") && c == config.ctxt.FixedFrameSize() + config.RegSize && warnRule(fe.Debug_checknil(), v, "removed nil check")
// result: (Invalid)
for {
_ = v.Args[1]
@@ -21469,7 +21415,7 @@ func rewriteValuegeneric_OpNilCheck_0(v *Value) bool {
break
}
sym := v_0_0_1.Aux
- if !(isSameSym(sym, "runtime.newobject") && c == config.ctxt.FixedFrameSize()+config.RegSize && warnRule(fe.Debug_checknil() && v.Pos.Line() > 1, v, "removed nil check")) {
+ if !(isSameSym(sym, "runtime.newobject") && c == config.ctxt.FixedFrameSize()+config.RegSize && warnRule(fe.Debug_checknil(), v, "removed nil check")) {
break
}
v.reset(OpInvalid)
@@ -27601,7 +27547,7 @@ func rewriteValuegeneric_OpSlicemask_0(v *Value) bool {
func rewriteValuegeneric_OpSqrt_0(v *Value) bool {
// match: (Sqrt (Const64F [c]))
// cond:
- // result: (Const64F [f2i(math.Sqrt(i2f(c)))])
+ // result: (Const64F [auxFrom64F(math.Sqrt(auxTo64F(c)))])
for {
v_0 := v.Args[0]
if v_0.Op != OpConst64F {
@@ -27609,7 +27555,7 @@ func rewriteValuegeneric_OpSqrt_0(v *Value) bool {
}
c := v_0.AuxInt
v.reset(OpConst64F)
- v.AuxInt = f2i(math.Sqrt(i2f(c)))
+ v.AuxInt = auxFrom64F(math.Sqrt(auxTo64F(c)))
return true
}
return false
@@ -29824,7 +29770,7 @@ func rewriteValuegeneric_OpSub32_10(v *Value) bool {
func rewriteValuegeneric_OpSub32F_0(v *Value) bool {
// match: (Sub32F (Const32F [c]) (Const32F [d]))
// cond:
- // result: (Const32F [f2i(float64(i2f32(c) - i2f32(d)))])
+ // result: (Const32F [auxFrom32F(auxTo32F(c) - auxTo32F(d))])
for {
_ = v.Args[1]
v_0 := v.Args[0]
@@ -29838,25 +29784,7 @@ func rewriteValuegeneric_OpSub32F_0(v *Value) bool {
}
d := v_1.AuxInt
v.reset(OpConst32F)
- v.AuxInt = f2i(float64(i2f32(c) - i2f32(d)))
- return true
- }
- // match: (Sub32F x (Const32F [0]))
- // cond:
- // result: x
- for {
- _ = v.Args[1]
- x := v.Args[0]
- v_1 := v.Args[1]
- if v_1.Op != OpConst32F {
- break
- }
- if v_1.AuxInt != 0 {
- break
- }
- v.reset(OpCopy)
- v.Type = x.Type
- v.AddArg(x)
+ v.AuxInt = auxFrom32F(auxTo32F(c) - auxTo32F(d))
return true
}
return false
@@ -30248,7 +30176,7 @@ func rewriteValuegeneric_OpSub64_10(v *Value) bool {
func rewriteValuegeneric_OpSub64F_0(v *Value) bool {
// match: (Sub64F (Const64F [c]) (Const64F [d]))
// cond:
- // result: (Const64F [f2i(i2f(c) - i2f(d))])
+ // result: (Const64F [auxFrom64F(auxTo64F(c) - auxTo64F(d))])
for {
_ = v.Args[1]
v_0 := v.Args[0]
@@ -30262,25 +30190,7 @@ func rewriteValuegeneric_OpSub64F_0(v *Value) bool {
}
d := v_1.AuxInt
v.reset(OpConst64F)
- v.AuxInt = f2i(i2f(c) - i2f(d))
- return true
- }
- // match: (Sub64F x (Const64F [0]))
- // cond:
- // result: x
- for {
- _ = v.Args[1]
- x := v.Args[0]
- v_1 := v.Args[1]
- if v_1.Op != OpConst64F {
- break
- }
- if v_1.AuxInt != 0 {
- break
- }
- v.reset(OpCopy)
- v.Type = x.Type
- v.AddArg(x)
+ v.AuxInt = auxFrom64F(auxTo64F(c) - auxTo64F(d))
return true
}
return false
diff --git a/src/cmd/compile/internal/ssa/softfloat.go b/src/cmd/compile/internal/ssa/softfloat.go
index 39829b046c..b41819c6ad 100644
--- a/src/cmd/compile/internal/ssa/softfloat.go
+++ b/src/cmd/compile/internal/ssa/softfloat.go
@@ -25,7 +25,7 @@ func softfloat(f *Func) {
case OpConst32F:
v.Op = OpConst32
v.Type = f.Config.Types.UInt32
- v.AuxInt = int64(int32(math.Float32bits(i2f32(v.AuxInt))))
+ v.AuxInt = int64(int32(math.Float32bits(auxTo32F(v.AuxInt))))
case OpConst64F:
v.Op = OpConst64
v.Type = f.Config.Types.UInt64
diff --git a/src/cmd/compile/internal/ssa/stmtlines_test.go b/src/cmd/compile/internal/ssa/stmtlines_test.go
index 1081f83f6d..c0fc7adab5 100644
--- a/src/cmd/compile/internal/ssa/stmtlines_test.go
+++ b/src/cmd/compile/internal/ssa/stmtlines_test.go
@@ -62,6 +62,9 @@ func TestStmtLines(t *testing.T) {
if pkgname == "runtime" {
continue
}
+ if e.Val(dwarf.AttrStmtList) == nil {
+ continue
+ }
lrdr, err := dw.LineReader(e)
must(err)
diff --git a/src/cmd/compile/internal/ssa/testdata/hist.gdb-opt.nexts b/src/cmd/compile/internal/ssa/testdata/hist.gdb-opt.nexts
index ad2719185e..6586f243e2 100644
--- a/src/cmd/compile/internal/ssa/testdata/hist.gdb-opt.nexts
+++ b/src/cmd/compile/internal/ssa/testdata/hist.gdb-opt.nexts
@@ -19,7 +19,7 @@ dy = <Optimized out, as expected>
65: if len(os.Args) > 1 {
73: scanner := bufio.NewScanner(reader)
74: for scanner.Scan() { //gdb-opt=(scanner/A)
-scanner = (struct bufio.Scanner *) <A>
+scanner = (bufio.Scanner *) <A>
75: s := scanner.Text()
76: i, err := strconv.ParseInt(s, 10, 64)
77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
@@ -29,7 +29,7 @@ i = 1
81: hist = ensure(int(i), hist)
82: hist[int(i)]++
74: for scanner.Scan() { //gdb-opt=(scanner/A)
-scanner = (struct bufio.Scanner *) <A>
+scanner = (bufio.Scanner *) <A>
75: s := scanner.Text()
76: i, err := strconv.ParseInt(s, 10, 64)
77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
@@ -39,7 +39,7 @@ i = 1
81: hist = ensure(int(i), hist)
82: hist[int(i)]++
74: for scanner.Scan() { //gdb-opt=(scanner/A)
-scanner = (struct bufio.Scanner *) <A>
+scanner = (bufio.Scanner *) <A>
75: s := scanner.Text()
76: i, err := strconv.ParseInt(s, 10, 64)
77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
@@ -49,7 +49,7 @@ i = 1
81: hist = ensure(int(i), hist)
82: hist[int(i)]++
74: for scanner.Scan() { //gdb-opt=(scanner/A)
-scanner = (struct bufio.Scanner *) <A>
+scanner = (bufio.Scanner *) <A>
75: s := scanner.Text()
76: i, err := strconv.ParseInt(s, 10, 64)
77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
@@ -59,7 +59,7 @@ i = 2
81: hist = ensure(int(i), hist)
82: hist[int(i)]++
74: for scanner.Scan() { //gdb-opt=(scanner/A)
-scanner = (struct bufio.Scanner *) <A>
+scanner = (bufio.Scanner *) <A>
75: s := scanner.Text()
76: i, err := strconv.ParseInt(s, 10, 64)
77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
@@ -69,7 +69,7 @@ i = 2
81: hist = ensure(int(i), hist)
82: hist[int(i)]++
74: for scanner.Scan() { //gdb-opt=(scanner/A)
-scanner = (struct bufio.Scanner *) <A>
+scanner = (bufio.Scanner *) <A>
75: s := scanner.Text()
76: i, err := strconv.ParseInt(s, 10, 64)
77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
@@ -79,7 +79,7 @@ i = 2
81: hist = ensure(int(i), hist)
82: hist[int(i)]++
74: for scanner.Scan() { //gdb-opt=(scanner/A)
-scanner = (struct bufio.Scanner *) <A>
+scanner = (bufio.Scanner *) <A>
75: s := scanner.Text()
76: i, err := strconv.ParseInt(s, 10, 64)
77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
@@ -89,7 +89,7 @@ i = 4
81: hist = ensure(int(i), hist)
82: hist[int(i)]++
74: for scanner.Scan() { //gdb-opt=(scanner/A)
-scanner = (struct bufio.Scanner *) <A>
+scanner = (bufio.Scanner *) <A>
75: s := scanner.Text()
76: i, err := strconv.ParseInt(s, 10, 64)
77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
@@ -99,7 +99,7 @@ i = 4
81: hist = ensure(int(i), hist)
82: hist[int(i)]++
74: for scanner.Scan() { //gdb-opt=(scanner/A)
-scanner = (struct bufio.Scanner *) <A>
+scanner = (bufio.Scanner *) <A>
75: s := scanner.Text()
76: i, err := strconv.ParseInt(s, 10, 64)
77: if err != nil { //gdb-dbg=(i) //gdb-opt=(err,hist,i)
@@ -109,7 +109,7 @@ i = 5
81: hist = ensure(int(i), hist)
82: hist[int(i)]++
74: for scanner.Scan() { //gdb-opt=(scanner/A)
-scanner = (struct bufio.Scanner *) <A>
+scanner = (bufio.Scanner *) <A>
86: for i, a := range hist {
87: if a == 0 { //gdb-opt=(a,n,t)
a = 0
diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go
index d367cd1944..25f8f826e6 100644
--- a/src/cmd/compile/internal/types/type.go
+++ b/src/cmd/compile/internal/types/type.go
@@ -817,7 +817,7 @@ func (t *Type) ChanArgs() *Type {
return t.Extra.(ChanArgs).T
}
-// FuncArgs returns the channel type for TFUNCARGS type t.
+// FuncArgs returns the func type for TFUNCARGS type t.
func (t *Type) FuncArgs() *Type {
t.wantEtype(TFUNCARGS)
return t.Extra.(FuncArgs).T
diff --git a/src/cmd/compile/internal/x86/ssa.go b/src/cmd/compile/internal/x86/ssa.go
index a53b63ab92..e0bb4418ec 100644
--- a/src/cmd/compile/internal/x86/ssa.go
+++ b/src/cmd/compile/internal/x86/ssa.go
@@ -547,22 +547,22 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
p.To.Reg = v.Args[0].Reg()
gc.AddAux(&p.To, v)
case ssa.Op386ADDLconstmodify:
- var p *obj.Prog = nil
sc := v.AuxValAndOff()
- off := sc.Off()
val := sc.Val()
- if val == 1 {
- p = s.Prog(x86.AINCL)
- } else if val == -1 {
- p = s.Prog(x86.ADECL)
- } else {
- p = s.Prog(v.Op.Asm())
- p.From.Type = obj.TYPE_CONST
- p.From.Offset = val
+ if val == 1 || val == -1 {
+ var p *obj.Prog
+ if val == 1 {
+ p = s.Prog(x86.AINCL)
+ } else {
+ p = s.Prog(x86.ADECL)
+ }
+ off := sc.Off()
+ p.To.Type = obj.TYPE_MEM
+ p.To.Reg = v.Args[0].Reg()
+ gc.AddAux2(&p.To, v, off)
+ break
}
- p.To.Type = obj.TYPE_MEM
- p.To.Reg = v.Args[0].Reg()
- gc.AddAux2(&p.To, v, off)
+ fallthrough
case ssa.Op386ANDLconstmodify, ssa.Op386ORLconstmodify, ssa.Op386XORLconstmodify:
sc := v.AuxValAndOff()
off := sc.Off()
diff --git a/src/cmd/dist/build.go b/src/cmd/dist/build.go
index d4f9dc4fbb..49f4a5e6a7 100644
--- a/src/cmd/dist/build.go
+++ b/src/cmd/dist/build.go
@@ -69,6 +69,7 @@ var okgoarch = []string{
"ppc64le",
"riscv64",
"s390x",
+ "sparc64",
"wasm",
}
@@ -86,6 +87,7 @@ var okgoos = []string{
"openbsd",
"plan9",
"windows",
+ "aix",
}
// find reports the first index of p in l[0:n], or else -1.
@@ -1387,6 +1389,7 @@ func checkNotStale(goBinary string, targets ...string) {
// single point of truth for supported platforms. This list is used
// by 'go tool dist list'.
var cgoEnabled = map[string]bool{
+ "aix/ppc64": false,
"darwin/386": true,
"darwin/amd64": true,
"darwin/arm": true,
@@ -1407,6 +1410,7 @@ var cgoEnabled = map[string]bool{
"linux/mips64le": true,
"linux/riscv64": true,
"linux/s390x": true,
+ "linux/sparc64": true,
"android/386": true,
"android/amd64": true,
"android/arm": true,
diff --git a/src/cmd/dist/buildruntime.go b/src/cmd/dist/buildruntime.go
index acf2230cb4..10d1552c94 100644
--- a/src/cmd/dist/buildruntime.go
+++ b/src/cmd/dist/buildruntime.go
@@ -87,6 +87,10 @@ func mkzbootstrap(file string) {
// stack guard size. Larger multipliers are used for non-optimized
// builds that have larger stack frames.
func stackGuardMultiplier() int {
+ // On AIX, a larger stack is needed for syscalls
+ if goos == "aix" {
+ return 2
+ }
for _, s := range strings.Split(os.Getenv("GO_GCFLAGS"), " ") {
if s == "-N" {
return 2
diff --git a/src/cmd/dist/main.go b/src/cmd/dist/main.go
index 37e37e2733..bf08869afb 100644
--- a/src/cmd/dist/main.go
+++ b/src/cmd/dist/main.go
@@ -81,6 +81,9 @@ func main() {
}
case "windows":
exe = ".exe"
+ case "aix":
+ // uname -m doesn't work under AIX
+ gohostarch = "ppc64"
}
sysinit()
diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go
index 4cd854773f..2d7f7bd2f9 100644
--- a/src/cmd/dist/test.go
+++ b/src/cmd/dist/test.go
@@ -1469,8 +1469,10 @@ func (t *tester) packageHasBenchmarks(pkg string) bool {
// because cmd/dist has to be buildable by Go 1.4.
func raceDetectorSupported(goos, goarch string) bool {
switch goos {
- case "linux", "darwin", "freebsd", "netbsd", "windows":
+ case "linux":
return goarch == "amd64" || goarch == "ppc64le"
+ case "darwin", "freebsd", "netbsd", "windows":
+ return goarch == "amd64"
default:
return false
}
diff --git a/src/cmd/fix/main.go b/src/cmd/fix/main.go
index f06abae171..f54a5e0d96 100644
--- a/src/cmd/fix/main.go
+++ b/src/cmd/fix/main.go
@@ -52,7 +52,7 @@ func usage() {
fmt.Fprintf(os.Stderr, "\n%s\n", f.name)
}
desc := strings.TrimSpace(f.desc)
- desc = strings.Replace(desc, "\n", "\n\t", -1)
+ desc = strings.ReplaceAll(desc, "\n", "\n\t")
fmt.Fprintf(os.Stderr, "\t%s\n", desc)
}
os.Exit(2)
diff --git a/src/cmd/fix/typecheck.go b/src/cmd/fix/typecheck.go
index eafb626c74..66e0cdcec0 100644
--- a/src/cmd/fix/typecheck.go
+++ b/src/cmd/fix/typecheck.go
@@ -193,12 +193,12 @@ func typecheck(cfg *TypeConfig, f *ast.File) (typeof map[interface{}]string, ass
var params, results []string
for _, p := range fn.Type.Params.List {
t := gofmt(p.Type)
- t = strings.Replace(t, "_Ctype_", "C.", -1)
+ t = strings.ReplaceAll(t, "_Ctype_", "C.")
params = append(params, t)
}
for _, r := range fn.Type.Results.List {
t := gofmt(r.Type)
- t = strings.Replace(t, "_Ctype_", "C.", -1)
+ t = strings.ReplaceAll(t, "_Ctype_", "C.")
results = append(results, t)
}
cfg.External["C."+fn.Name.Name[7:]] = joinFunc(params, results)
diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go
index 35cabcac14..9528ca2984 100644
--- a/src/cmd/go/alldocs.go
+++ b/src/cmd/go/alldocs.go
@@ -144,7 +144,7 @@
// link against shared libraries previously created with
// -buildmode=shared.
// -mod mode
-// module download mode to use: readonly, release, or vendor.
+// module download mode to use: readonly or vendor.
// See 'go help modules' for more.
// -pkgdir dir
// install and load all packages from dir instead of the usual locations.
@@ -1449,6 +1449,12 @@
// The directory where the go command will write
// temporary source files, packages, and binaries.
//
+// Each entry in the GOFLAGS list must be a standalone flag.
+// Because the entries are space-separated, flag values must
+// not contain spaces. In some cases, you can provide multiple flag
+// values instead: for example, to set '-ldflags=-s -w'
+// you can use 'GOFLAGS=-ldflags=-s -ldflags=-w'.
+//
// Environment variables for use with cgo:
//
// CC
diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go
index 85dcada9ec..73d7663ad6 100644
--- a/src/cmd/go/go_test.go
+++ b/src/cmd/go/go_test.go
@@ -1074,6 +1074,8 @@ func testMove(t *testing.T, vcs, url, base, config string) {
defer tg.cleanup()
tg.parallel()
tg.tempDir("src")
+ tg.must(os.Mkdir(tg.path(".hg"), 0700))
+ tg.must(ioutil.WriteFile(filepath.Join(tg.path(".hg"), "hgrc"), nil, 0600))
tg.setenv("GOPATH", tg.path("."))
tg.run("get", "-d", url)
tg.run("get", "-d", "-u", url)
@@ -1088,7 +1090,7 @@ func testMove(t *testing.T, vcs, url, base, config string) {
path := tg.path(filepath.Join("src", config))
data, err := ioutil.ReadFile(path)
tg.must(err)
- data = bytes.Replace(data, []byte(base), []byte(base+"XXX"), -1)
+ data = bytes.ReplaceAll(data, []byte(base), []byte(base+"XXX"))
tg.must(ioutil.WriteFile(path, data, 0644))
}
if vcs == "git" {
@@ -1185,6 +1187,7 @@ func TestImportCycle(t *testing.T) {
}
func TestListImportMap(t *testing.T) {
+ skipIfGccgo(t, "gccgo does not have standard packages")
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
@@ -1418,6 +1421,7 @@ func TestRelativeGOBINFail(t *testing.T) {
defer tg.cleanup()
tg.tempFile("triv.go", `package main; func main() {}`)
tg.setenv("GOBIN", ".")
+ tg.cd(tg.path("."))
tg.runFail("install")
tg.grepStderr("cannot install, GOBIN must be an absolute path", "go install must fail if $GOBIN is a relative path")
}
@@ -1729,20 +1733,23 @@ func TestGoListDeps(t *testing.T) {
tg.run("list", "-deps", "p1")
tg.grepStdout("p1/p2/p3/p4", "-deps p1 does not mention p4")
- // Check the list is in dependency order.
- tg.run("list", "-deps", "math")
- want := "internal/cpu\nunsafe\nmath\n"
- out := tg.stdout.String()
- if !strings.Contains(out, "internal/cpu") {
- // Some systems don't use internal/cpu.
- want = "unsafe\nmath\n"
- }
- if tg.stdout.String() != want {
- t.Fatalf("list -deps math: wrong order\nhave %q\nwant %q", tg.stdout.String(), want)
+ if runtime.Compiler != "gccgo" {
+ // Check the list is in dependency order.
+ tg.run("list", "-deps", "math")
+ want := "internal/cpu\nunsafe\nmath\n"
+ out := tg.stdout.String()
+ if !strings.Contains(out, "internal/cpu") {
+ // Some systems don't use internal/cpu.
+ want = "unsafe\nmath\n"
+ }
+ if tg.stdout.String() != want {
+ t.Fatalf("list -deps math: wrong order\nhave %q\nwant %q", tg.stdout.String(), want)
+ }
}
}
func TestGoListTest(t *testing.T) {
+ skipIfGccgo(t, "gccgo does not have standard packages")
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
@@ -1815,6 +1822,7 @@ func TestGoListCompiledCgo(t *testing.T) {
}
func TestGoListExport(t *testing.T) {
+ skipIfGccgo(t, "gccgo does not have standard packages")
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
@@ -2051,6 +2059,7 @@ func TestGoTestCpuprofileLeavesBinaryBehind(t *testing.T) {
}
func TestGoTestCpuprofileDashOControlsBinaryLocation(t *testing.T) {
+ skipIfGccgo(t, "gccgo has no standard packages")
tooSlow(t)
tg := testgo(t)
defer tg.cleanup()
@@ -2107,6 +2116,7 @@ func TestGoTestDashCDashOControlsBinaryLocation(t *testing.T) {
}
func TestGoTestDashOWritesBinary(t *testing.T) {
+ skipIfGccgo(t, "gccgo has no standard packages")
tooSlow(t)
tg := testgo(t)
defer tg.cleanup()
@@ -2350,14 +2360,14 @@ func TestShadowingLogic(t *testing.T) {
// The math in root1 is not "math" because the standard math is.
tg.run("list", "-f", "({{.ImportPath}}) ({{.ConflictDir}})", "./testdata/shadow/root1/src/math")
- pwdForwardSlash := strings.Replace(pwd, string(os.PathSeparator), "/", -1)
+ pwdForwardSlash := strings.ReplaceAll(pwd, string(os.PathSeparator), "/")
if !strings.HasPrefix(pwdForwardSlash, "/") {
pwdForwardSlash = "/" + pwdForwardSlash
}
// The output will have makeImportValid applies, but we only
// bother to deal with characters we might reasonably see.
for _, r := range " :" {
- pwdForwardSlash = strings.Replace(pwdForwardSlash, string(r), "_", -1)
+ pwdForwardSlash = strings.ReplaceAll(pwdForwardSlash, string(r), "_")
}
want := "(_" + pwdForwardSlash + "/testdata/shadow/root1/src/math) (" + filepath.Join(runtime.GOROOT(), "src", "math") + ")"
if strings.TrimSpace(tg.getStdout()) != want {
@@ -2402,6 +2412,7 @@ func checkCoverage(tg *testgoData, data string) {
}
func TestCoverageRuns(t *testing.T) {
+ skipIfGccgo(t, "gccgo has no cover tool")
tooSlow(t)
tg := testgo(t)
defer tg.cleanup()
@@ -2413,6 +2424,7 @@ func TestCoverageRuns(t *testing.T) {
}
func TestCoverageDotImport(t *testing.T) {
+ skipIfGccgo(t, "gccgo has no cover tool")
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
@@ -2425,6 +2437,7 @@ func TestCoverageDotImport(t *testing.T) {
// Check that coverage analysis uses set mode.
// Also check that coverage profiles merge correctly.
func TestCoverageUsesSetMode(t *testing.T) {
+ skipIfGccgo(t, "gccgo has no cover tool")
tooSlow(t)
tg := testgo(t)
defer tg.cleanup()
@@ -2455,6 +2468,7 @@ func TestCoverageUsesAtomicModeForRace(t *testing.T) {
if !canRace {
t.Skip("skipping because race detector not supported")
}
+ skipIfGccgo(t, "gccgo has no cover tool")
tg := testgo(t)
defer tg.cleanup()
@@ -2472,6 +2486,7 @@ func TestCoverageUsesAtomicModeForRace(t *testing.T) {
}
func TestCoverageSyncAtomicImport(t *testing.T) {
+ skipIfGccgo(t, "gccgo has no cover tool")
tooSlow(t)
tg := testgo(t)
defer tg.cleanup()
@@ -2493,6 +2508,7 @@ func TestCoverageDepLoop(t *testing.T) {
}
func TestCoverageImportMainLoop(t *testing.T) {
+ skipIfGccgo(t, "gccgo has no cover tool")
tg := testgo(t)
defer tg.cleanup()
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
@@ -2503,6 +2519,7 @@ func TestCoverageImportMainLoop(t *testing.T) {
}
func TestCoveragePattern(t *testing.T) {
+ skipIfGccgo(t, "gccgo has no cover tool")
tooSlow(t)
tg := testgo(t)
defer tg.cleanup()
@@ -2518,6 +2535,7 @@ func TestCoveragePattern(t *testing.T) {
}
func TestCoverageErrorLine(t *testing.T) {
+ skipIfGccgo(t, "gccgo has no cover tool")
tooSlow(t)
tg := testgo(t)
defer tg.cleanup()
@@ -2539,7 +2557,7 @@ func TestCoverageErrorLine(t *testing.T) {
// It's OK that stderr2 drops the character position in the error,
// because of the //line directive (see golang.org/issue/22662).
- stderr = strings.Replace(stderr, "p.go:4:2:", "p.go:4:", -1)
+ stderr = strings.ReplaceAll(stderr, "p.go:4:2:", "p.go:4:")
if stderr != stderr2 {
t.Logf("test -cover changed error messages:\nbefore:\n%s\n\nafter:\n%s", stderr, stderr2)
t.Skip("golang.org/issue/22660")
@@ -2561,6 +2579,7 @@ func TestTestBuildFailureOutput(t *testing.T) {
}
func TestCoverageFunc(t *testing.T) {
+ skipIfGccgo(t, "gccgo has no cover tool")
tooSlow(t)
tg := testgo(t)
defer tg.cleanup()
@@ -2576,6 +2595,7 @@ func TestCoverageFunc(t *testing.T) {
// Issue 24588.
func TestCoverageDashC(t *testing.T) {
+ skipIfGccgo(t, "gccgo has no cover tool")
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
@@ -2684,6 +2704,7 @@ func main() {
}
func TestCoverageWithCgo(t *testing.T) {
+ skipIfGccgo(t, "gccgo has no cover tool")
tooSlow(t)
if !canCgo {
t.Skip("skipping because cgo not enabled")
@@ -5164,6 +5185,7 @@ func TestCacheCoverage(t *testing.T) {
}
func TestCacheVet(t *testing.T) {
+ skipIfGccgo(t, "gccgo has no standard packages")
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
@@ -6082,6 +6104,7 @@ func TestNoRelativeTmpdir(t *testing.T) {
// Issue 24704.
func TestLinkerTmpDirIsDeleted(t *testing.T) {
+ skipIfGccgo(t, "gccgo does not use cmd/link")
if !canCgo {
t.Skip("skipping because cgo not enabled")
}
@@ -6129,6 +6152,7 @@ func TestLinkerTmpDirIsDeleted(t *testing.T) {
}
func testCDAndGOPATHAreDifferent(tg *testgoData, cd, gopath string) {
+ skipIfGccgo(tg.t, "gccgo does not support -ldflags -X")
tg.setenv("GOPATH", gopath)
tg.tempDir("dir")
@@ -6155,7 +6179,7 @@ func TestCDAndGOPATHAreDifferent(t *testing.T) {
testCDAndGOPATHAreDifferent(tg, cd, gopath)
if runtime.GOOS == "windows" {
- testCDAndGOPATHAreDifferent(tg, cd, strings.Replace(gopath, `\`, `/`, -1))
+ testCDAndGOPATHAreDifferent(tg, cd, strings.ReplaceAll(gopath, `\`, `/`))
testCDAndGOPATHAreDifferent(tg, cd, strings.ToUpper(gopath))
testCDAndGOPATHAreDifferent(tg, cd, strings.ToLower(gopath))
}
@@ -6184,6 +6208,7 @@ func TestGoBuildDashODevNull(t *testing.T) {
// Issue 25093.
func TestCoverpkgTestOnly(t *testing.T) {
+ skipIfGccgo(t, "gccgo has no cover tool")
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
diff --git a/src/cmd/go/internal/clean/clean.go b/src/cmd/go/internal/clean/clean.go
index d023592eed..b12bd981a7 100644
--- a/src/cmd/go/internal/clean/clean.go
+++ b/src/cmd/go/internal/clean/clean.go
@@ -112,9 +112,10 @@ func runClean(cmd *base.Command, args []string) {
}
}
+ var b work.Builder
+ b.Print = fmt.Print
+
if cleanCache {
- var b work.Builder
- b.Print = fmt.Print
dir := cache.DefaultDir()
if dir != "off" {
// Remove the cache subdirectories but not the top cache directory.
@@ -156,8 +157,13 @@ func runClean(cmd *base.Command, args []string) {
if modfetch.PkgMod == "" {
base.Fatalf("go clean -modcache: no module cache")
}
- if err := removeAll(modfetch.PkgMod); err != nil {
- base.Errorf("go clean -modcache: %v", err)
+ if cfg.BuildN || cfg.BuildX {
+ b.Showcmd("", "rm -rf %s", modfetch.PkgMod)
+ }
+ if !cfg.BuildN {
+ if err := removeAll(modfetch.PkgMod); err != nil {
+ base.Errorf("go clean -modcache: %v", err)
+ }
}
}
}
diff --git a/src/cmd/go/internal/envcmd/env.go b/src/cmd/go/internal/envcmd/env.go
index afadbade38..85a42e0519 100644
--- a/src/cmd/go/internal/envcmd/env.go
+++ b/src/cmd/go/internal/envcmd/env.go
@@ -203,7 +203,7 @@ func runEnv(cmd *base.Command, args []string) {
fmt.Printf("%s=\"%s\"\n", e.Name, e.Value)
case "plan9":
if strings.IndexByte(e.Value, '\x00') < 0 {
- fmt.Printf("%s='%s'\n", e.Name, strings.Replace(e.Value, "'", "''", -1))
+ fmt.Printf("%s='%s'\n", e.Name, strings.ReplaceAll(e.Value, "'", "''"))
} else {
v := strings.Split(e.Value, "\x00")
fmt.Printf("%s=(", e.Name)
diff --git a/src/cmd/go/internal/get/vcs.go b/src/cmd/go/internal/get/vcs.go
index 0f7b623ec3..173934b84e 100644
--- a/src/cmd/go/internal/get/vcs.go
+++ b/src/cmd/go/internal/get/vcs.go
@@ -964,7 +964,7 @@ func matchGoImport(imports []metaImport, importPath string) (metaImport, error)
// expand rewrites s to replace {k} with match[k] for each key k in match.
func expand(match map[string]string, s string) string {
for k, v := range match {
- s = strings.Replace(s, "{"+k+"}", v, -1)
+ s = strings.ReplaceAll(s, "{"+k+"}", v)
}
return s
}
diff --git a/src/cmd/go/internal/help/helpdoc.go b/src/cmd/go/internal/help/helpdoc.go
index aff4ce12f6..e2c4e61615 100644
--- a/src/cmd/go/internal/help/helpdoc.go
+++ b/src/cmd/go/internal/help/helpdoc.go
@@ -507,6 +507,12 @@ General-purpose environment variables:
The directory where the go command will write
temporary source files, packages, and binaries.
+Each entry in the GOFLAGS list must be a standalone flag.
+Because the entries are space-separated, flag values must
+not contain spaces. In some cases, you can provide multiple flag
+values instead: for example, to set '-ldflags=-s -w'
+you can use 'GOFLAGS=-ldflags=-s -ldflags=-w'.
+
Environment variables for use with cgo:
CC
diff --git a/src/cmd/go/internal/modconv/convert_test.go b/src/cmd/go/internal/modconv/convert_test.go
index ad27abb8ef..4d55d73f21 100644
--- a/src/cmd/go/internal/modconv/convert_test.go
+++ b/src/cmd/go/internal/modconv/convert_test.go
@@ -146,7 +146,7 @@ func TestConvertLegacyConfig(t *testing.T) {
}
for _, tt := range tests {
- t.Run(strings.Replace(tt.path, "/", "_", -1)+"_"+tt.vers, func(t *testing.T) {
+ t.Run(strings.ReplaceAll(tt.path, "/", "_")+"_"+tt.vers, func(t *testing.T) {
f, err := modfile.Parse("golden", []byte(tt.gomod), nil)
if err != nil {
t.Fatal(err)
diff --git a/src/cmd/go/internal/modfetch/codehost/codehost.go b/src/cmd/go/internal/modfetch/codehost/codehost.go
index 4103ddc717..4205cd26bd 100644
--- a/src/cmd/go/internal/modfetch/codehost/codehost.go
+++ b/src/cmd/go/internal/modfetch/codehost/codehost.go
@@ -185,7 +185,7 @@ func (e *RunError) Error() string {
text := e.Cmd + ": " + e.Err.Error()
stderr := bytes.TrimRight(e.Stderr, "\n")
if len(stderr) > 0 {
- text += ":\n\t" + strings.Replace(string(stderr), "\n", "\n\t", -1)
+ text += ":\n\t" + strings.ReplaceAll(string(stderr), "\n", "\n\t")
}
return text
}
diff --git a/src/cmd/go/internal/modfetch/coderepo_test.go b/src/cmd/go/internal/modfetch/coderepo_test.go
index 79b82786cb..73c4bd2cca 100644
--- a/src/cmd/go/internal/modfetch/coderepo_test.go
+++ b/src/cmd/go/internal/modfetch/coderepo_test.go
@@ -423,7 +423,7 @@ func TestCodeRepo(t *testing.T) {
}
}
}
- t.Run(strings.Replace(tt.path, "/", "_", -1)+"/"+tt.rev, f)
+ t.Run(strings.ReplaceAll(tt.path, "/", "_")+"/"+tt.rev, f)
if strings.HasPrefix(tt.path, vgotest1git) {
for _, alt := range altVgotests {
// Note: Communicating with f through tt; should be cleaned up.
@@ -442,7 +442,7 @@ func TestCodeRepo(t *testing.T) {
tt.rev = remap(tt.rev, m)
tt.gomoderr = remap(tt.gomoderr, m)
tt.ziperr = remap(tt.ziperr, m)
- t.Run(strings.Replace(tt.path, "/", "_", -1)+"/"+tt.rev, f)
+ t.Run(strings.ReplaceAll(tt.path, "/", "_")+"/"+tt.rev, f)
tt = old
}
}
@@ -473,9 +473,9 @@ func remap(name string, m map[string]string) string {
}
}
for k, v := range m {
- name = strings.Replace(name, k, v, -1)
+ name = strings.ReplaceAll(name, k, v)
if codehost.AllHex(k) {
- name = strings.Replace(name, k[:12], v[:12], -1)
+ name = strings.ReplaceAll(name, k[:12], v[:12])
}
}
return name
@@ -505,11 +505,11 @@ var codeRepoVersionsTests = []struct {
},
{
path: "gopkg.in/russross/blackfriday.v2",
- versions: []string{"v2.0.0"},
+ versions: []string{"v2.0.0", "v2.0.1"},
},
{
path: "gopkg.in/natefinch/lumberjack.v2",
- versions: nil,
+ versions: []string{"v2.0.0"},
},
}
@@ -522,7 +522,7 @@ func TestCodeRepoVersions(t *testing.T) {
}
defer os.RemoveAll(tmpdir)
for _, tt := range codeRepoVersionsTests {
- t.Run(strings.Replace(tt.path, "/", "_", -1), func(t *testing.T) {
+ t.Run(strings.ReplaceAll(tt.path, "/", "_"), func(t *testing.T) {
repo, err := Lookup(tt.path)
if err != nil {
t.Fatalf("Lookup(%q): %v", tt.path, err)
@@ -570,7 +570,7 @@ func TestLatest(t *testing.T) {
}
defer os.RemoveAll(tmpdir)
for _, tt := range latestTests {
- name := strings.Replace(tt.path, "/", "_", -1)
+ name := strings.ReplaceAll(tt.path, "/", "_")
t.Run(name, func(t *testing.T) {
repo, err := Lookup(tt.path)
if err != nil {
diff --git a/src/cmd/go/internal/modfetch/fetch.go b/src/cmd/go/internal/modfetch/fetch.go
index 2e26bac434..8485932b42 100644
--- a/src/cmd/go/internal/modfetch/fetch.go
+++ b/src/cmd/go/internal/modfetch/fetch.go
@@ -123,7 +123,7 @@ func downloadZip(mod module.Version, target string) error {
for _, f := range z.File {
if !strings.HasPrefix(f.Name, prefix) {
z.Close()
- return fmt.Errorf("zip for %s has unexpected file %s", prefix[:len(prefix)-1], f.Name)
+ return fmt.Errorf("zip for %s has unexpected file %s", prefix, f.Name)
}
}
z.Close()
diff --git a/src/cmd/go/internal/modfetch/proxy.go b/src/cmd/go/internal/modfetch/proxy.go
index 5f856b80d2..7c78502f31 100644
--- a/src/cmd/go/internal/modfetch/proxy.go
+++ b/src/cmd/go/internal/modfetch/proxy.go
@@ -248,5 +248,5 @@ func (p *proxyRepo) Zip(version string, tmpdir string) (tmpfile string, err erro
// That is, it escapes things like ? and # (which really shouldn't appear anyway).
// It does not escape / to %2F: our REST API is designed so that / can be left as is.
func pathEscape(s string) string {
- return strings.Replace(url.PathEscape(s), "%2F", "/", -1)
+ return strings.ReplaceAll(url.PathEscape(s), "%2F", "/")
}
diff --git a/src/cmd/go/internal/modload/build.go b/src/cmd/go/internal/modload/build.go
index cebb802db9..acee4a91e7 100644
--- a/src/cmd/go/internal/modload/build.go
+++ b/src/cmd/go/internal/modload/build.go
@@ -14,6 +14,7 @@ import (
"cmd/go/internal/search"
"encoding/hex"
"fmt"
+ "internal/goroot"
"os"
"path/filepath"
"strings"
@@ -30,13 +31,11 @@ func isStandardImportPath(path string) bool {
func findStandardImportPath(path string) string {
if search.IsStandardImportPath(path) {
- dir := filepath.Join(cfg.GOROOT, "src", path)
- if _, err := os.Stat(dir); err == nil {
- return dir
+ if goroot.IsStandardPackage(cfg.GOROOT, cfg.BuildContext.Compiler, path) {
+ return filepath.Join(cfg.GOROOT, "src", path)
}
- dir = filepath.Join(cfg.GOROOT, "src/vendor", path)
- if _, err := os.Stat(dir); err == nil {
- return dir
+ if goroot.IsStandardPackage(cfg.GOROOT, cfg.BuildContext.Compiler, "vendor/"+path) {
+ return filepath.Join(cfg.GOROOT, "src/vendor", path)
}
}
return ""
@@ -232,11 +231,16 @@ func findModule(target, path string) module.Version {
}
func ModInfoProg(info string) []byte {
+ // Inject a variable with the debug information as runtime/debug.modinfo,
+ // but compile it in package main so that it is specific to the binary.
+ // Populate it in an init func so that it will work with go:linkname,
+ // but use a string constant instead of the name 'string' in case
+ // package main shadows the built-in 'string' with some local declaration.
return []byte(fmt.Sprintf(`
package main
import _ "unsafe"
//go:linkname __debug_modinfo__ runtime/debug.modinfo
- var __debug_modinfo__ string
+ var __debug_modinfo__ = ""
func init() {
__debug_modinfo__ = %q
}
diff --git a/src/cmd/go/internal/modload/import.go b/src/cmd/go/internal/modload/import.go
index 12d9407f6e..44c2a23726 100644
--- a/src/cmd/go/internal/modload/import.go
+++ b/src/cmd/go/internal/modload/import.go
@@ -9,6 +9,7 @@ import (
"errors"
"fmt"
"go/build"
+ "internal/goroot"
"os"
"path/filepath"
"strings"
@@ -60,8 +61,8 @@ func Import(path string) (m module.Version, dir string, err error) {
if strings.HasPrefix(path, "golang_org/") {
return module.Version{}, filepath.Join(cfg.GOROOT, "src/vendor", path), nil
}
- dir := filepath.Join(cfg.GOROOT, "src", path)
- if _, err := os.Stat(dir); err == nil {
+ if goroot.IsStandardPackage(cfg.GOROOT, cfg.BuildContext.Compiler, path) {
+ dir := filepath.Join(cfg.GOROOT, "src", path)
return module.Version{}, dir, nil
}
}
diff --git a/src/cmd/go/internal/modload/import_test.go b/src/cmd/go/internal/modload/import_test.go
index 3f4ddab436..9422a3d960 100644
--- a/src/cmd/go/internal/modload/import_test.go
+++ b/src/cmd/go/internal/modload/import_test.go
@@ -45,7 +45,7 @@ func TestImport(t *testing.T) {
testenv.MustHaveExternalNetwork(t)
for _, tt := range importTests {
- t.Run(strings.Replace(tt.path, "/", "_", -1), func(t *testing.T) {
+ t.Run(strings.ReplaceAll(tt.path, "/", "_"), func(t *testing.T) {
// Note that there is no build list, so Import should always fail.
m, dir, err := Import(tt.path)
if err == nil {
diff --git a/src/cmd/go/internal/modload/query.go b/src/cmd/go/internal/modload/query.go
index 3b550f1db7..4071341313 100644
--- a/src/cmd/go/internal/modload/query.go
+++ b/src/cmd/go/internal/modload/query.go
@@ -207,7 +207,7 @@ func matchSemverPrefix(p, v string) bool {
// If multiple modules with revisions matching the query provide the requested
// package, QueryPackage picks the one with the longest module path.
//
-// If the path is in the the main module and the query is "latest",
+// If the path is in the main module and the query is "latest",
// QueryPackage returns Target as the version.
func QueryPackage(path, query string, allowed func(module.Version) bool) (module.Version, *modfetch.RevInfo, error) {
if _, ok := dirInModule(path, Target.Path, ModRoot, true); ok {
@@ -221,7 +221,7 @@ func QueryPackage(path, query string, allowed func(module.Version) bool) (module
}
finalErr := errMissing
- for p := path; p != "."; p = pathpkg.Dir(p) {
+ for p := path; p != "." && p != "/"; p = pathpkg.Dir(p) {
info, err := Query(p, query, allowed)
if err != nil {
if _, ok := err.(*codehost.VCSError); ok {
diff --git a/src/cmd/go/internal/modload/query_test.go b/src/cmd/go/internal/modload/query_test.go
index 7f3ffabef7..9b07383217 100644
--- a/src/cmd/go/internal/modload/query_test.go
+++ b/src/cmd/go/internal/modload/query_test.go
@@ -132,7 +132,7 @@ func TestQuery(t *testing.T) {
ok, _ := path.Match(allow, m.Version)
return ok
}
- t.Run(strings.Replace(tt.path, "/", "_", -1)+"/"+tt.query+"/"+allow, func(t *testing.T) {
+ t.Run(strings.ReplaceAll(tt.path, "/", "_")+"/"+tt.query+"/"+allow, func(t *testing.T) {
info, err := Query(tt.path, tt.query, allowed)
if tt.err != "" {
if err != nil && err.Error() == tt.err {
diff --git a/src/cmd/go/internal/search/search.go b/src/cmd/go/internal/search/search.go
index 60ae73696b..0ca60e7349 100644
--- a/src/cmd/go/internal/search/search.go
+++ b/src/cmd/go/internal/search/search.go
@@ -275,7 +275,7 @@ func MatchPattern(pattern string) func(name string) bool {
case strings.HasSuffix(re, `/\.\.\.`):
re = strings.TrimSuffix(re, `/\.\.\.`) + `(/\.\.\.)?`
}
- re = strings.Replace(re, `\.\.\.`, `[^`+vendorChar+`]*`, -1)
+ re = strings.ReplaceAll(re, `\.\.\.`, `[^`+vendorChar+`]*`)
reg := regexp.MustCompile(`^` + re + `$`)
@@ -353,7 +353,7 @@ func CleanPatterns(patterns []string) []string {
// as a courtesy to Windows developers, rewrite \ to /
// in command-line arguments. Handles .\... and so on.
if filepath.Separator == '\\' {
- a = strings.Replace(a, `\`, `/`, -1)
+ a = strings.ReplaceAll(a, `\`, `/`)
}
// Put argument in canonical form, but preserve leading ./.
diff --git a/src/cmd/go/internal/work/build.go b/src/cmd/go/internal/work/build.go
index ed41ce5d07..145b87513a 100644
--- a/src/cmd/go/internal/work/build.go
+++ b/src/cmd/go/internal/work/build.go
@@ -99,7 +99,7 @@ and test commands:
link against shared libraries previously created with
-buildmode=shared.
-mod mode
- module download mode to use: readonly, release, or vendor.
+ module download mode to use: readonly or vendor.
See 'go help modules' for more.
-pkgdir dir
install and load all packages from dir instead of the usual locations.
@@ -398,10 +398,10 @@ func libname(args []string, pkgs []*load.Package) (string, error) {
arg = bp.ImportPath
}
}
- appendName(strings.Replace(arg, "/", "-", -1))
+ appendName(strings.ReplaceAll(arg, "/", "-"))
} else {
for _, pkg := range pkgs {
- appendName(strings.Replace(pkg.ImportPath, "/", "-", -1))
+ appendName(strings.ReplaceAll(pkg.ImportPath, "/", "-"))
}
}
} else if haveNonMeta { // have both meta package and a non-meta one
diff --git a/src/cmd/go/internal/work/buildid.go b/src/cmd/go/internal/work/buildid.go
index f6b79711f9..8b97e8b75b 100644
--- a/src/cmd/go/internal/work/buildid.go
+++ b/src/cmd/go/internal/work/buildid.go
@@ -348,8 +348,12 @@ func (b *Builder) gccgoBuildIDELFFile(a *Action) (string, error) {
}
fmt.Fprintf(&buf, "\n")
if cfg.Goos != "solaris" {
- fmt.Fprintf(&buf, "\t"+`.section .note.GNU-stack,"",@progbits`+"\n")
- fmt.Fprintf(&buf, "\t"+`.section .note.GNU-split-stack,"",@progbits`+"\n")
+ secType := "@progbits"
+ if cfg.Goarch == "arm" {
+ secType = "%progbits"
+ }
+ fmt.Fprintf(&buf, "\t"+`.section .note.GNU-stack,"",%s`+"\n", secType)
+ fmt.Fprintf(&buf, "\t"+`.section .note.GNU-split-stack,"",%s`+"\n", secType)
}
if cfg.BuildN || cfg.BuildX {
diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go
index 01414a3d57..158f5f3b17 100644
--- a/src/cmd/go/internal/work/exec.go
+++ b/src/cmd/go/internal/work/exec.go
@@ -1705,14 +1705,14 @@ func (b *Builder) fmtcmd(dir string, format string, args ...interface{}) string
if dir[len(dir)-1] == filepath.Separator {
dot += string(filepath.Separator)
}
- cmd = strings.Replace(" "+cmd, " "+dir, dot, -1)[1:]
+ cmd = strings.ReplaceAll(" "+cmd, " "+dir, dot)[1:]
if b.scriptDir != dir {
b.scriptDir = dir
cmd = "cd " + dir + "\n" + cmd
}
}
if b.WorkDir != "" {
- cmd = strings.Replace(cmd, b.WorkDir, "$WORK", -1)
+ cmd = strings.ReplaceAll(cmd, b.WorkDir, "$WORK")
}
return cmd
}
@@ -1754,10 +1754,10 @@ func (b *Builder) showOutput(a *Action, dir, desc, out string) {
prefix := "# " + desc
suffix := "\n" + out
if reldir := base.ShortPath(dir); reldir != dir {
- suffix = strings.Replace(suffix, " "+dir, " "+reldir, -1)
- suffix = strings.Replace(suffix, "\n"+dir, "\n"+reldir, -1)
+ suffix = strings.ReplaceAll(suffix, " "+dir, " "+reldir)
+ suffix = strings.ReplaceAll(suffix, "\n"+dir, "\n"+reldir)
}
- suffix = strings.Replace(suffix, " "+b.WorkDir, " $WORK", -1)
+ suffix = strings.ReplaceAll(suffix, " "+b.WorkDir, " $WORK")
if a != nil && a.output != nil {
a.output = append(a.output, prefix...)
diff --git a/src/cmd/go/internal/work/security.go b/src/cmd/go/internal/work/security.go
index d5d126123a..1a401b8981 100644
--- a/src/cmd/go/internal/work/security.go
+++ b/src/cmd/go/internal/work/security.go
@@ -89,7 +89,9 @@ var validCompilerFlags = []*regexp.Regexp{
re(`-m32`),
re(`-m64`),
re(`-m(abi|arch|cpu|fpu|tune)=([^@\-].*)`),
+ re(`-m(no-)?v?aes`),
re(`-marm`),
+ re(`-m(no-)?avx[0-9a-z]*`),
re(`-mfloat-abi=([^@\-].*)`),
re(`-mfpmath=[0-9a-z,+]*`),
re(`-m(no-)?avx[0-9a-z.]*`),
@@ -100,6 +102,7 @@ var validCompilerFlags = []*regexp.Regexp{
re(`-miphoneos-version-min=(.+)`),
re(`-mnop-fun-dllimport`),
re(`-m(no-)?sse[0-9.]*`),
+ re(`-m(no-)?ssse3`),
re(`-mthumb(-interwork)?`),
re(`-mthreads`),
re(`-mwindows`),
@@ -170,6 +173,7 @@ var validLinkerFlags = []*regexp.Regexp{
re(`-Wl,-e[=,][a-zA-Z0-9]*`),
re(`-Wl,--enable-new-dtags`),
re(`-Wl,--end-group`),
+ re(`-Wl,--(no-)?export-dynamic`),
re(`-Wl,-framework,[^,@\-][^,]+`),
re(`-Wl,-headerpad_max_install_names`),
re(`-Wl,--no-undefined`),
diff --git a/src/cmd/go/main.go b/src/cmd/go/main.go
index 31c554e715..d6934ce5e9 100644
--- a/src/cmd/go/main.go
+++ b/src/cmd/go/main.go
@@ -93,6 +93,15 @@ func main() {
*get.CmdGet = *modget.CmdGet
}
+ if args[0] == "get" || args[0] == "help" {
+ // Replace get with module-aware get if appropriate.
+ // Note that if MustUseModules is true, this happened already above,
+ // but no harm in doing it again.
+ if modload.Init(); modload.Enabled() {
+ *get.CmdGet = *modget.CmdGet
+ }
+ }
+
cfg.CmdName = args[0] // for error messages
if args[0] == "help" {
help.Help(os.Stdout, args[1:])
@@ -161,15 +170,6 @@ func main() {
os.Exit(2)
}
- if args[0] == "get" {
- // Replace get with module-aware get if appropriate.
- // Note that if MustUseModules is true, this happened already above,
- // but no harm in doing it again.
- if modload.Init(); modload.Enabled() {
- *get.CmdGet = *modget.CmdGet
- }
- }
-
// Set environment (GOOS, GOARCH, etc) explicitly.
// In theory all the commands we invoke should have
// the same default computation of these as we do,
diff --git a/src/cmd/go/proxy_test.go b/src/cmd/go/proxy_test.go
index 212e5aa08f..97fc4b0e80 100644
--- a/src/cmd/go/proxy_test.go
+++ b/src/cmd/go/proxy_test.go
@@ -78,7 +78,7 @@ func readModList() {
if i < 0 {
continue
}
- encPath := strings.Replace(name[:i], "_", "/", -1)
+ encPath := strings.ReplaceAll(name[:i], "_", "/")
path, err := module.DecodePath(encPath)
if err != nil {
fmt.Fprintf(os.Stderr, "go proxy_test: %v\n", err)
@@ -256,7 +256,7 @@ func readArchive(path, vers string) *txtar.Archive {
return nil
}
- prefix := strings.Replace(enc, "/", "_", -1)
+ prefix := strings.ReplaceAll(enc, "/", "_")
name := filepath.Join(cmdGoDir, "testdata/mod", prefix+"_"+encVers+".txt")
a := archiveCache.Do(name, func() interface{} {
a, err := txtar.ParseFile(name)
diff --git a/src/cmd/go/script_test.go b/src/cmd/go/script_test.go
index 7c083a87b9..31c6ede2a5 100644
--- a/src/cmd/go/script_test.go
+++ b/src/cmd/go/script_test.go
@@ -329,7 +329,7 @@ func (ts *testScript) cmdAddcrlf(neg bool, args []string) {
file = ts.mkabs(file)
data, err := ioutil.ReadFile(file)
ts.check(err)
- ts.check(ioutil.WriteFile(file, bytes.Replace(data, []byte("\n"), []byte("\r\n"), -1), 0666))
+ ts.check(ioutil.WriteFile(file, bytes.ReplaceAll(data, []byte("\n"), []byte("\r\n")), 0666))
}
}
@@ -630,7 +630,7 @@ func scriptMatch(ts *testScript, neg bool, args []string, text, name string) {
}
// Matching against workdir would be misleading.
- text = strings.Replace(text, ts.workdir, "$WORK", -1)
+ text = strings.ReplaceAll(text, ts.workdir, "$WORK")
if neg {
if re.MatchString(text) {
@@ -691,7 +691,7 @@ func (ts *testScript) cmdSymlink(neg bool, args []string) {
// abbrev abbreviates the actual work directory in the string s to the literal string "$WORK".
func (ts *testScript) abbrev(s string) string {
- s = strings.Replace(s, ts.workdir, "$WORK", -1)
+ s = strings.ReplaceAll(s, ts.workdir, "$WORK")
if *testWork {
// Expose actual $WORK value in environment dump on first line of work script,
// so that the user can find out what directory -testwork left behind.
@@ -885,17 +885,17 @@ var diffTests = []struct {
func TestDiff(t *testing.T) {
for _, tt := range diffTests {
// Turn spaces into \n.
- text1 := strings.Replace(tt.text1, " ", "\n", -1)
+ text1 := strings.ReplaceAll(tt.text1, " ", "\n")
if text1 != "" {
text1 += "\n"
}
- text2 := strings.Replace(tt.text2, " ", "\n", -1)
+ text2 := strings.ReplaceAll(tt.text2, " ", "\n")
if text2 != "" {
text2 += "\n"
}
out := diff(text1, text2)
// Cut final \n, cut spaces, turn remaining \n into spaces.
- out = strings.Replace(strings.Replace(strings.TrimSuffix(out, "\n"), " ", "", -1), "\n", " ", -1)
+ out = strings.ReplaceAll(strings.ReplaceAll(strings.TrimSuffix(out, "\n"), " ", ""), "\n", " ")
if out != tt.diff {
t.Errorf("diff(%q, %q) = %q, want %q", text1, text2, out, tt.diff)
}
diff --git a/src/cmd/go/testdata/addmod.go b/src/cmd/go/testdata/addmod.go
index 19850af0f3..8bb6056a54 100644
--- a/src/cmd/go/testdata/addmod.go
+++ b/src/cmd/go/testdata/addmod.go
@@ -142,7 +142,7 @@ func main() {
}
data := txtar.Format(a)
- target := filepath.Join("mod", strings.Replace(path, "/", "_", -1)+"_"+vers+".txt")
+ target := filepath.Join("mod", strings.ReplaceAll(path, "/", "_")+"_"+vers+".txt")
if err := ioutil.WriteFile(target, data, 0666); err != nil {
log.Printf("%s: %v", arg, err)
exitCode = 1
diff --git a/src/cmd/go/testdata/script/help.txt b/src/cmd/go/testdata/script/help.txt
index 939da30283..656e680100 100644
--- a/src/cmd/go/testdata/script/help.txt
+++ b/src/cmd/go/testdata/script/help.txt
@@ -34,3 +34,8 @@ stderr 'Run ''go help mod'' for usage.'
! go vet -h
stderr 'usage: go vet'
stderr 'Run ''go help vet'' for details'
+
+# go help get shows usage for get
+go help get
+stdout 'usage: go get'
+stdout 'get when using GOPATH' \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/list_bad_import.txt b/src/cmd/go/testdata/script/list_bad_import.txt
index ba66b0937f..3d9cac0d5f 100644
--- a/src/cmd/go/testdata/script/list_bad_import.txt
+++ b/src/cmd/go/testdata/script/list_bad_import.txt
@@ -47,7 +47,7 @@ stdout error
stdout incomplete
-# The pattern "all" should match only packages that acutally exist,
+# The pattern "all" should match only packages that actually exist,
# ignoring those whose existence is merely implied by imports.
go list -e -f '{{.ImportPath}}' all
stdout example.com/direct
diff --git a/src/cmd/go/testdata/script/mod_clean_cache.txt b/src/cmd/go/testdata/script/mod_clean_cache.txt
new file mode 100644
index 0000000000..66a0e9ea7e
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_clean_cache.txt
@@ -0,0 +1,23 @@
+env GO111MODULE=on
+
+go mod download rsc.io/quote@v1.5.0
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.info
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.mod
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.zip
+
+go clean -modcache -n
+stdout '^rm -rf .*pkg.mod$'
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.info
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.mod
+exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.zip
+
+go clean -modcache
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.info
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.mod
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.zip
+
+-- go.mod --
+module m
+
+-- m.go --
+package m \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/mod_help.txt b/src/cmd/go/testdata/script/mod_help.txt
new file mode 100644
index 0000000000..b5cd30c521
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_help.txt
@@ -0,0 +1,6 @@
+env GO111MODULE=on
+
+# go help get shows usage for get
+go help get
+stdout 'usage: go get'
+stdout 'get using modules to manage source' \ No newline at end of file
diff --git a/src/cmd/go/testdata/script/mod_list_bad_import.txt b/src/cmd/go/testdata/script/mod_list_bad_import.txt
index 258eb6a567..8a66e0b72a 100644
--- a/src/cmd/go/testdata/script/mod_list_bad_import.txt
+++ b/src/cmd/go/testdata/script/mod_list_bad_import.txt
@@ -47,7 +47,7 @@ stdout error
stdout incomplete
-# The pattern "all" should match only packages that acutally exist,
+# The pattern "all" should match only packages that actually exist,
# ignoring those whose existence is merely implied by imports.
go list -e -f '{{.ImportPath}} {{.Error}}' all
stdout example.com/direct
diff --git a/src/cmd/go/testdata/script/mod_string_alias.txt b/src/cmd/go/testdata/script/mod_string_alias.txt
new file mode 100644
index 0000000000..5c3d4287cc
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_string_alias.txt
@@ -0,0 +1,14 @@
+[short] skip
+
+env GO111MODULE=on
+
+go mod init golang.org/issue/27584
+
+go build .
+
+-- main.go --
+package main
+
+type string = []int
+
+func main() {}
diff --git a/src/cmd/go/testdata/script/mod_test.txt b/src/cmd/go/testdata/script/mod_test.txt
index caeb25ada8..af4fd76d70 100644
--- a/src/cmd/go/testdata/script/mod_test.txt
+++ b/src/cmd/go/testdata/script/mod_test.txt
@@ -1,5 +1,8 @@
env GO111MODULE=on
+# TODO(bcmills): Convert the 'go test' calls below to 'go list -test' once 'go
+# list' is more sensitive to package loading errors.
+
# A test in the module's root package should work.
cd a/
cp go.mod.empty go.mod
@@ -48,6 +51,10 @@ cd ../d_test
go test
stdout PASS
+cd ../e
+go test
+stdout PASS
+
-- a/go.mod.empty --
module example.com/user/a
diff --git a/src/cmd/go/vendor_test.go b/src/cmd/go/vendor_test.go
index 22aa643b00..c302d7e9b5 100644
--- a/src/cmd/go/vendor_test.go
+++ b/src/cmd/go/vendor_test.go
@@ -37,7 +37,7 @@ func TestVendorImports(t *testing.T) {
vend/x/vendor/p/p [notfound]
vend/x/vendor/r []
`
- want = strings.Replace(want+"\t", "\n\t\t", "\n", -1)
+ want = strings.ReplaceAll(want+"\t", "\n\t\t", "\n")
want = strings.TrimPrefix(want, "\n")
have := tg.stdout.String()
diff --git a/src/cmd/gofmt/gofmt_test.go b/src/cmd/gofmt/gofmt_test.go
index 16b653b646..3008365cd2 100644
--- a/src/cmd/gofmt/gofmt_test.go
+++ b/src/cmd/gofmt/gofmt_test.go
@@ -200,7 +200,7 @@ func TestDiff(t *testing.T) {
}
if runtime.GOOS == "windows" {
- b = bytes.Replace(b, []byte{'\r', '\n'}, []byte{'\n'}, -1)
+ b = bytes.ReplaceAll(b, []byte{'\r', '\n'}, []byte{'\n'})
}
bs := bytes.SplitN(b, []byte{'\n'}, 3)
diff --git a/src/cmd/internal/dwarf/dwarf.go b/src/cmd/internal/dwarf/dwarf.go
index 96fb2b765b..355091feda 100644
--- a/src/cmd/internal/dwarf/dwarf.go
+++ b/src/cmd/internal/dwarf/dwarf.go
@@ -304,6 +304,7 @@ const (
const (
DW_ABRV_NULL = iota
DW_ABRV_COMPUNIT
+ DW_ABRV_COMPUNIT_TEXTLESS
DW_ABRV_FUNCTION
DW_ABRV_FUNCTION_ABSTRACT
DW_ABRV_FUNCTION_CONCRETE
@@ -368,6 +369,18 @@ var abbrevs = [DW_NABRV]dwAbbrev{
},
},
+ /* COMPUNIT_TEXTLESS */
+ {
+ DW_TAG_compile_unit,
+ DW_CHILDREN_yes,
+ []dwAttrForm{
+ {DW_AT_name, DW_FORM_string},
+ {DW_AT_language, DW_FORM_data1},
+ {DW_AT_comp_dir, DW_FORM_string},
+ {DW_AT_producer, DW_FORM_string},
+ },
+ },
+
/* FUNCTION */
{
DW_TAG_subprogram,
diff --git a/src/cmd/internal/goobj/read.go b/src/cmd/internal/goobj/read.go
index e39180cad6..2d618eefa5 100644
--- a/src/cmd/internal/goobj/read.go
+++ b/src/cmd/internal/goobj/read.go
@@ -293,7 +293,7 @@ func (r *objReader) readRef() {
// In a symbol name in an object file, "". denotes the
// prefix for the package in which the object file has been found.
// Expand it.
- name = strings.Replace(name, `"".`, r.pkgprefix, -1)
+ name = strings.ReplaceAll(name, `"".`, r.pkgprefix)
// An individual object file only records version 0 (extern) or 1 (static).
// To make static symbols unique across all files being read, we
diff --git a/src/cmd/internal/obj/arm/asm5.go b/src/cmd/internal/obj/arm/asm5.go
index 3427ea9161..dd6d9265c4 100644
--- a/src/cmd/internal/obj/arm/asm5.go
+++ b/src/cmd/internal/obj/arm/asm5.go
@@ -2007,7 +2007,7 @@ func (c *ctxt5) asmout(p *obj.Prog, o *Optab, out []uint32) {
o2 = c.oprrr(p, p.As, int(p.Scond))
o2 |= REGTMP & 15
r := int(p.Reg)
- if p.As == AMOVW || p.As == AMVN {
+ if p.As == AMVN {
r = 0
} else if r == 0 {
r = int(p.To.Reg)
diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go
index 7507976257..46fdcdcf7d 100644
--- a/src/cmd/internal/obj/arm64/asm7.go
+++ b/src/cmd/internal/obj/arm64/asm7.go
@@ -1085,6 +1085,23 @@ func (c *ctxt7) regoff(a *obj.Addr) uint32 {
return uint32(c.instoffset)
}
+func isSTLXRop(op obj.As) bool {
+ switch op {
+ case ASTLXR, ASTLXRW, ASTLXRB, ASTLXRH,
+ ASTXR, ASTXRW, ASTXRB, ASTXRH:
+ return true
+ }
+ return false
+}
+
+func isSTXPop(op obj.As) bool {
+ switch op {
+ case ASTXP, ASTLXP, ASTXPW, ASTLXPW:
+ return true
+ }
+ return false
+}
+
func isRegShiftOrExt(a *obj.Addr) bool {
return (a.Index-obj.RBaseARM64)&REG_EXT != 0 || (a.Index-obj.RBaseARM64)&REG_LSL != 0
}
@@ -1409,6 +1426,10 @@ func (c *ctxt7) aclass(a *obj.Addr) int {
return C_LIST
case obj.TYPE_MEM:
+ // The base register should be an integer register.
+ if int16(REG_F0) <= a.Reg && a.Reg <= int16(REG_V31) {
+ break
+ }
switch a.Name {
case obj.NAME_EXTERN, obj.NAME_STATIC:
if a.Sym == nil {
@@ -2502,6 +2523,17 @@ func SYSARG4(op1 int, Cn int, Cm int, op2 int) int {
return SYSARG5(0, op1, Cn, Cm, op2)
}
+// checkUnpredictable checks if the sourse and transfer registers are the same register.
+// ARM64 manual says it is "constrained unpredictable" if the src and dst registers of STP/LDP are same.
+func (c *ctxt7) checkUnpredictable(p *obj.Prog, isload bool, wback bool, rn int16, rt1 int16, rt2 int16) {
+ if wback && rn != REGSP && (rn == rt1 || rn == rt2) {
+ c.ctxt.Diag("constrained unpredictable behavior: %v", p)
+ }
+ if isload && rt1 == rt2 {
+ c.ctxt.Diag("constrained unpredictable behavior: %v", p)
+ }
+}
+
/* checkindex checks if index >= 0 && index <= maxindex */
func (c *ctxt7) checkindex(p *obj.Prog, index, maxindex int) {
if index < 0 || index > maxindex {
@@ -2940,6 +2972,10 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
}
case 22: /* movT (R)O!,R; movT O(R)!, R -> ldrT */
+ if p.From.Reg != REGSP && p.From.Reg == p.To.Reg {
+ c.ctxt.Diag("constrained unpredictable behavior: %v", p)
+ }
+
v := int32(p.From.Offset)
if v < -256 || v > 255 {
@@ -2954,6 +2990,10 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
o1 |= ((uint32(v) & 0x1FF) << 12) | (uint32(p.From.Reg&31) << 5) | uint32(p.To.Reg&31)
case 23: /* movT R,(R)O!; movT O(R)!, R -> strT */
+ if p.To.Reg != REGSP && p.From.Reg == p.To.Reg {
+ c.ctxt.Diag("constrained unpredictable behavior: %v", p)
+ }
+
v := int32(p.To.Offset)
if v < -256 || v > 255 {
@@ -3551,6 +3591,9 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
o1 |= 0x1F << 16
o1 |= uint32(p.From.Reg&31) << 5
if p.As == ALDXP || p.As == ALDXPW || p.As == ALDAXP || p.As == ALDAXPW {
+ if int(p.To.Reg) == int(p.To.Offset) {
+ c.ctxt.Diag("constrained unpredictable behavior: %v", p)
+ }
o1 |= uint32(p.To.Offset&31) << 10
} else {
o1 |= 0x1F << 10
@@ -3558,6 +3601,19 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
o1 |= uint32(p.To.Reg & 31)
case 59: /* stxr/stlxr/stxp/stlxp */
+ s := p.RegTo2
+ n := p.To.Reg
+ t := p.From.Reg
+ if isSTLXRop(p.As) {
+ if s == t || (s == n && n != REGSP) {
+ c.ctxt.Diag("constrained unpredictable behavior: %v", p)
+ }
+ } else if isSTXPop(p.As) {
+ t2 := int16(p.From.Offset)
+ if (s == t || s == t2) || (s == n && n != REGSP) {
+ c.ctxt.Diag("constrained unpredictable behavior: %v", p)
+ }
+ }
o1 = c.opstore(p, p.As)
if p.RegTo2 != obj.REG_NONE {
@@ -3565,7 +3621,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
} else {
o1 |= 0x1F << 16
}
- if p.As == ASTXP || p.As == ASTXPW || p.As == ASTLXP || p.As == ASTLXPW {
+ if isSTXPop(p.As) {
o1 |= uint32(p.From.Offset&31) << 10
}
o1 |= uint32(p.To.Reg&31)<<5 | uint32(p.From.Reg&31)
@@ -6177,6 +6233,20 @@ func (c *ctxt7) opextr(p *obj.Prog, a obj.As, v int32, rn int, rm int, rt int) u
/* genrate instruction encoding for LDP/LDPW/LDPSW/STP/STPW */
func (c *ctxt7) opldpstp(p *obj.Prog, o *Optab, vo int32, rbase, rl, rh, ldp uint32) uint32 {
+ wback := false
+ if o.scond == C_XPOST || o.scond == C_XPRE {
+ wback = true
+ }
+ switch p.As {
+ case ALDP, ALDPW, ALDPSW:
+ c.checkUnpredictable(p, true, wback, p.From.Reg, p.To.Reg, int16(p.To.Offset))
+ case ASTP, ASTPW:
+ if wback == true {
+ c.checkUnpredictable(p, false, true, p.To.Reg, p.From.Reg, int16(p.From.Offset))
+ }
+ case AFLDPD, AFLDPS:
+ c.checkUnpredictable(p, true, false, p.From.Reg, p.To.Reg, int16(p.To.Offset))
+ }
var ret uint32
// check offset
switch p.As {
diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go
index 132f7836ef..354bda5e48 100644
--- a/src/cmd/internal/obj/link.go
+++ b/src/cmd/internal/obj/link.go
@@ -402,9 +402,10 @@ type FuncInfo struct {
dwarfAbsFnSym *LSym
dwarfIsStmtSym *LSym
- GCArgs LSym
- GCLocals LSym
- GCRegs LSym
+ GCArgs LSym
+ GCLocals LSym
+ GCRegs LSym
+ StackObjects *LSym
}
// Attribute is a set of symbol attributes.
diff --git a/src/cmd/internal/objabi/funcdata.go b/src/cmd/internal/objabi/funcdata.go
index a7827125bf..231d11b185 100644
--- a/src/cmd/internal/objabi/funcdata.go
+++ b/src/cmd/internal/objabi/funcdata.go
@@ -18,6 +18,7 @@ const (
FUNCDATA_LocalsPointerMaps = 1
FUNCDATA_InlTree = 2
FUNCDATA_RegPointerMaps = 3
+ FUNCDATA_StackObjects = 4
// ArgsSizeUnknown is set in Func.argsize to mark all functions
// whose argument size is unknown (C vararg functions, and
diff --git a/src/cmd/internal/objabi/funcid.go b/src/cmd/internal/objabi/funcid.go
index 15a63ab8b3..92799107da 100644
--- a/src/cmd/internal/objabi/funcid.go
+++ b/src/cmd/internal/objabi/funcid.go
@@ -9,7 +9,7 @@ package objabi
// Note that in some situations involving plugins, there may be multiple
// copies of a particular special runtime function.
// Note: this list must match the list in runtime/symtab.go.
-type FuncID uint32
+type FuncID uint8
const (
FuncID_normal FuncID = iota // not a special function
diff --git a/src/cmd/internal/objabi/head.go b/src/cmd/internal/objabi/head.go
index 23c7b62daf..db2221d6b1 100644
--- a/src/cmd/internal/objabi/head.go
+++ b/src/cmd/internal/objabi/head.go
@@ -48,10 +48,13 @@ const (
Hplan9
Hsolaris
Hwindows
+ Haix
)
func (h *HeadType) Set(s string) error {
switch s {
+ case "aix":
+ *h = Haix
case "darwin":
*h = Hdarwin
case "dragonfly":
@@ -82,6 +85,8 @@ func (h *HeadType) Set(s string) error {
func (h *HeadType) String() string {
switch *h {
+ case Haix:
+ return "aix"
case Hdarwin:
return "darwin"
case Hdragonfly:
diff --git a/src/cmd/link/dwarf_test.go b/src/cmd/link/dwarf_test.go
index ff11689bbc..2c01456f6b 100644
--- a/src/cmd/link/dwarf_test.go
+++ b/src/cmd/link/dwarf_test.go
@@ -122,6 +122,9 @@ func testDWARF(t *testing.T, buildmode string, expectDWARF bool, env ...string)
r.SkipChildren()
continue
}
+ if cu.Val(dwarf.AttrStmtList) == nil {
+ continue
+ }
lr, err := d.LineReader(cu)
if err != nil {
t.Fatal(err)
diff --git a/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go
index 959fc8290c..743f4cedd4 100644
--- a/src/cmd/link/internal/ld/dwarf.go
+++ b/src/cmd/link/internal/ld/dwarf.go
@@ -5,7 +5,7 @@
// TODO/NICETOHAVE:
// - eliminate DW_CLS_ if not used
// - package info in compilation units
-// - assign global variables and types to their packages
+// - assign types to their packages
// - gdb uses c syntax, meaning clumsy quoting is needed for go identifiers. eg
// ptype struct '[]uint8' and qualifiers need to be quoted away
// - file:line info for variables
@@ -106,15 +106,8 @@ func writeabbrev(ctxt *Link) *sym.Symbol {
return s
}
-/*
- * Root DIEs for compilation units, types and global variables.
- */
-var dwroot dwarf.DWDie
-
var dwtypes dwarf.DWDie
-var dwglobals dwarf.DWDie
-
func newattr(die *dwarf.DWDie, attr uint16, cls int, value int64, data interface{}) *dwarf.DWAttr {
a := new(dwarf.DWAttr)
a.Link = die.Attr
@@ -340,19 +333,19 @@ func lookupOrDiag(ctxt *Link, n string) *sym.Symbol {
return s
}
-func dotypedef(ctxt *Link, parent *dwarf.DWDie, name string, def *dwarf.DWDie) {
+func dotypedef(ctxt *Link, parent *dwarf.DWDie, name string, def *dwarf.DWDie) *dwarf.DWDie {
// Only emit typedefs for real names.
if strings.HasPrefix(name, "map[") {
- return
+ return nil
}
if strings.HasPrefix(name, "struct {") {
- return
+ return nil
}
if strings.HasPrefix(name, "chan ") {
- return
+ return nil
}
if name[0] == '[' || name[0] == '*' {
- return
+ return nil
}
if def == nil {
Errorf(nil, "dwarf: bad def in dotypedef")
@@ -370,6 +363,8 @@ func dotypedef(ctxt *Link, parent *dwarf.DWDie, name string, def *dwarf.DWDie) {
die := newdie(ctxt, parent, dwarf.DW_ABRV_TYPEDECL, name, 0)
newrefattr(die, dwarf.DW_AT_type, s)
+
+ return die
}
// Define gotype, for composite ones recurse into constituents.
@@ -399,7 +394,7 @@ func newtype(ctxt *Link, gotype *sym.Symbol) *dwarf.DWDie {
kind := decodetypeKind(ctxt.Arch, gotype)
bytesize := decodetypeSize(ctxt.Arch, gotype)
- var die *dwarf.DWDie
+ var die, typedefdie *dwarf.DWDie
switch kind {
case objabi.KindBool:
die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BASETYPE, name, 0)
@@ -439,7 +434,7 @@ func newtype(ctxt *Link, gotype *sym.Symbol) *dwarf.DWDie {
case objabi.KindArray:
die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_ARRAYTYPE, name, 0)
- dotypedef(ctxt, &dwtypes, name, die)
+ typedefdie = dotypedef(ctxt, &dwtypes, name, die)
newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
s := decodetypeArrayElem(ctxt.Arch, gotype)
newrefattr(die, dwarf.DW_AT_type, defgotype(ctxt, s))
@@ -461,7 +456,7 @@ func newtype(ctxt *Link, gotype *sym.Symbol) *dwarf.DWDie {
case objabi.KindFunc:
die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_FUNCTYPE, name, 0)
newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
- dotypedef(ctxt, &dwtypes, name, die)
+ typedefdie = dotypedef(ctxt, &dwtypes, name, die)
nfields := decodetypeFuncInCount(ctxt.Arch, gotype)
for i := 0; i < nfields; i++ {
s := decodetypeFuncInType(ctxt.Arch, gotype, i)
@@ -481,7 +476,7 @@ func newtype(ctxt *Link, gotype *sym.Symbol) *dwarf.DWDie {
case objabi.KindInterface:
die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_IFACETYPE, name, 0)
- dotypedef(ctxt, &dwtypes, name, die)
+ typedefdie = dotypedef(ctxt, &dwtypes, name, die)
nfields := int(decodetypeIfaceMethodCount(ctxt.Arch, gotype))
var s *sym.Symbol
if nfields == 0 {
@@ -503,13 +498,13 @@ func newtype(ctxt *Link, gotype *sym.Symbol) *dwarf.DWDie {
case objabi.KindPtr:
die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_PTRTYPE, name, 0)
- dotypedef(ctxt, &dwtypes, name, die)
+ typedefdie = dotypedef(ctxt, &dwtypes, name, die)
s := decodetypePtrElem(ctxt.Arch, gotype)
newrefattr(die, dwarf.DW_AT_type, defgotype(ctxt, s))
case objabi.KindSlice:
die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_SLICETYPE, name, 0)
- dotypedef(ctxt, &dwtypes, name, die)
+ typedefdie = dotypedef(ctxt, &dwtypes, name, die)
newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
s := decodetypeArrayElem(ctxt.Arch, gotype)
elem := defgotype(ctxt, s)
@@ -521,7 +516,7 @@ func newtype(ctxt *Link, gotype *sym.Symbol) *dwarf.DWDie {
case objabi.KindStruct:
die = newdie(ctxt, &dwtypes, dwarf.DW_ABRV_STRUCTTYPE, name, 0)
- dotypedef(ctxt, &dwtypes, name, die)
+ typedefdie = dotypedef(ctxt, &dwtypes, name, die)
newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, bytesize, 0)
nfields := decodetypeStructFieldCount(ctxt.Arch, gotype)
for i := 0; i < nfields; i++ {
@@ -557,6 +552,9 @@ func newtype(ctxt *Link, gotype *sym.Symbol) *dwarf.DWDie {
prototypedies[gotype.Name] = die
}
+ if typedefdie != nil {
+ return typedefdie
+ }
return die
}
@@ -830,7 +828,11 @@ func synthesizechantypes(ctxt *Link, die *dwarf.DWDie) {
}
func dwarfDefineGlobal(ctxt *Link, s *sym.Symbol, str string, v int64, gotype *sym.Symbol) {
- dv := newdie(ctxt, &dwglobals, dwarf.DW_ABRV_VARIABLE, str, int(s.Version))
+ lib := s.Lib
+ if lib == nil {
+ lib = ctxt.LibraryByPkg["runtime"]
+ }
+ dv := newdie(ctxt, ctxt.compUnitByPackage[lib].dwinfo, dwarf.DW_ABRV_VARIABLE, str, int(s.Version))
newabslocexprattr(dv, v, s)
if s.Version == 0 {
newattr(dv, dwarf.DW_AT_external, dwarf.DW_CLS_FLAG, 1, 0)
@@ -905,10 +907,11 @@ func calcCompUnitRanges(ctxt *Link) {
}
}
-func movetomodule(parent *dwarf.DWDie) {
- die := dwroot.Child.Child
+func movetomodule(ctxt *Link, parent *dwarf.DWDie) {
+ runtimelib := ctxt.LibraryByPkg["runtime"]
+ die := ctxt.compUnitByPackage[runtimelib].dwinfo.Child
if die == nil {
- dwroot.Child.Child = parent.Child
+ ctxt.compUnitByPackage[runtimelib].dwinfo.Child = parent.Child
return
}
for die.Link != nil {
@@ -1062,7 +1065,7 @@ func importInfoSymbol(ctxt *Link, dsym *sym.Symbol) {
}
}
-func writelines(ctxt *Link, unit *compilationUnit, ls *sym.Symbol) (dwinfo *dwarf.DWDie) {
+func writelines(ctxt *Link, unit *compilationUnit, ls *sym.Symbol) {
var dwarfctxt dwarf.Context = dwctxt{ctxt}
is_stmt := uint8(1) // initially = recommended default_is_stmt = 1, tracks is_stmt toggles.
@@ -1071,29 +1074,7 @@ func writelines(ctxt *Link, unit *compilationUnit, ls *sym.Symbol) (dwinfo *dwar
headerstart := int64(-1)
headerend := int64(-1)
- lang := dwarf.DW_LANG_Go
-
- dwinfo = newdie(ctxt, &dwroot, dwarf.DW_ABRV_COMPUNIT, unit.lib.Pkg, 0)
- newattr(dwinfo, dwarf.DW_AT_language, dwarf.DW_CLS_CONSTANT, int64(lang), 0)
- newattr(dwinfo, dwarf.DW_AT_stmt_list, dwarf.DW_CLS_PTR, ls.Size, ls)
- // OS X linker requires compilation dir or absolute path in comp unit name to output debug info.
- compDir := getCompilationDir()
- // TODO: Make this be the actual compilation directory, not
- // the linker directory. If we move CU construction into the
- // compiler, this should happen naturally.
- newattr(dwinfo, dwarf.DW_AT_comp_dir, dwarf.DW_CLS_STRING, int64(len(compDir)), compDir)
- producerExtra := ctxt.Syms.Lookup(dwarf.CUInfoPrefix+"producer."+unit.lib.Pkg, 0)
- producer := "Go cmd/compile " + objabi.Version
- if len(producerExtra.P) > 0 {
- // We put a semicolon before the flags to clearly
- // separate them from the version, which can be long
- // and have lots of weird things in it in development
- // versions. We promise not to put a semicolon in the
- // version, so it should be safe for readers to scan
- // forward to the semicolon.
- producer += "; " + string(producerExtra.P)
- }
- newattr(dwinfo, dwarf.DW_AT_producer, dwarf.DW_CLS_STRING, int64(len(producer)), producer)
+ newattr(unit.dwinfo, dwarf.DW_AT_stmt_list, dwarf.DW_CLS_PTR, ls.Size, ls)
// Write .debug_line Line Number Program Header (sec 6.2.4)
// Fields marked with (*) must be changed for 64-bit dwarf
@@ -1295,8 +1276,6 @@ func writelines(ctxt *Link, unit *compilationUnit, ls *sym.Symbol) (dwinfo *dwar
}
}
}
-
- return dwinfo
}
// writepcranges generates the DW_AT_ranges table for compilation unit cu.
@@ -1463,15 +1442,13 @@ func writeinfo(ctxt *Link, syms []*sym.Symbol, units []*compilationUnit, abbrevs
var dwarfctxt dwarf.Context = dwctxt{ctxt}
- // Re-index per-package information by its CU die.
- unitByDIE := make(map[*dwarf.DWDie]*compilationUnit)
for _, u := range units {
- unitByDIE[u.dwinfo] = u
- }
-
- for compunit := dwroot.Child; compunit != nil; compunit = compunit.Link {
+ compunit := u.dwinfo
s := dtolsym(compunit.Sym)
- u := unitByDIE[compunit]
+
+ if len(u.lib.Textp) == 0 && u.dwinfo.Child == nil {
+ continue
+ }
// Write .debug_info Compilation Unit Header (sec 7.5.1)
// Fields marked with (*) must be changed for 64-bit dwarf
@@ -1531,7 +1508,11 @@ func writepub(ctxt *Link, sname string, ispub func(*dwarf.DWDie) bool, syms []*s
s.Type = sym.SDWARFSECT
syms = append(syms, s)
- for compunit := dwroot.Child; compunit != nil; compunit = compunit.Link {
+ for _, u := range ctxt.compUnits {
+ if len(u.lib.Textp) == 0 && u.dwinfo.Child == nil {
+ continue
+ }
+ compunit := u.dwinfo
sectionstart := s.Size
culength := uint32(getattr(compunit, dwarf.DW_AT_byte_size).Value) + 4
@@ -1666,13 +1647,10 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
defgotype(ctxt, lookupOrDiag(ctxt, typ))
}
- // Create DIEs for global variables and the types they use.
- genasmsym(ctxt, defdwsymb)
+ // fake root DIE for compile unit DIEs
+ var dwroot dwarf.DWDie
for _, lib := range ctxt.Library {
- if len(lib.Textp) == 0 {
- continue
- }
unit := &compilationUnit{lib: lib}
if s := ctxt.Syms.ROLookup(dwarf.ConstInfoPrefix+lib.Pkg, 0); s != nil {
importInfoSymbol(ctxt, s)
@@ -1681,6 +1659,31 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
ctxt.compUnits = append(ctxt.compUnits, unit)
ctxt.compUnitByPackage[lib] = unit
+ unit.dwinfo = newdie(ctxt, &dwroot, dwarf.DW_ABRV_COMPUNIT, unit.lib.Pkg, 0)
+ newattr(unit.dwinfo, dwarf.DW_AT_language, dwarf.DW_CLS_CONSTANT, int64(dwarf.DW_LANG_Go), 0)
+ // OS X linker requires compilation dir or absolute path in comp unit name to output debug info.
+ compDir := getCompilationDir()
+ // TODO: Make this be the actual compilation directory, not
+ // the linker directory. If we move CU construction into the
+ // compiler, this should happen naturally.
+ newattr(unit.dwinfo, dwarf.DW_AT_comp_dir, dwarf.DW_CLS_STRING, int64(len(compDir)), compDir)
+ producerExtra := ctxt.Syms.Lookup(dwarf.CUInfoPrefix+"producer."+unit.lib.Pkg, 0)
+ producer := "Go cmd/compile " + objabi.Version
+ if len(producerExtra.P) > 0 {
+ // We put a semicolon before the flags to clearly
+ // separate them from the version, which can be long
+ // and have lots of weird things in it in development
+ // versions. We promise not to put a semicolon in the
+ // version, so it should be safe for readers to scan
+ // forward to the semicolon.
+ producer += "; " + string(producerExtra.P)
+ }
+ newattr(unit.dwinfo, dwarf.DW_AT_producer, dwarf.DW_CLS_STRING, int64(len(producer)), producer)
+
+ if len(lib.Textp) == 0 {
+ unit.dwinfo.Abbrev = dwarf.DW_ABRV_COMPUNIT_TEXTLESS
+ }
+
// Scan all functions in this compilation unit, create DIEs for all
// referenced types, create the file table for debug_line, find all
// referenced abstract functions.
@@ -1721,6 +1724,9 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
}
}
+ // Create DIEs for global variables and the types they use.
+ genasmsym(ctxt, defdwsymb)
+
synthesizestringtypes(ctxt, dwtypes.Child)
synthesizeslicetypes(ctxt, dwtypes.Child)
synthesizemaptypes(ctxt, dwtypes.Child)
@@ -1753,19 +1759,19 @@ func dwarfGenerateDebugSyms(ctxt *Link) {
debugRanges.Attr |= sym.AttrReachable
syms = append(syms, debugLine)
for _, u := range ctxt.compUnits {
- u.dwinfo = writelines(ctxt, u, debugLine)
+ reversetree(&u.dwinfo.Child)
+ if u.dwinfo.Abbrev == dwarf.DW_ABRV_COMPUNIT_TEXTLESS {
+ continue
+ }
+ writelines(ctxt, u, debugLine)
writepcranges(ctxt, u.dwinfo, u.lib.Textp[0], u.pcs, debugRanges)
}
// newdie adds DIEs to the *beginning* of the parent's DIE list.
// Now that we're done creating DIEs, reverse the trees so DIEs
// appear in the order they were created.
- reversetree(&dwroot.Child)
reversetree(&dwtypes.Child)
- reversetree(&dwglobals.Child)
-
- movetomodule(&dwtypes)
- movetomodule(&dwglobals)
+ movetomodule(ctxt, &dwtypes)
// Need to reorder symbols so sym.SDWARFINFO is after all sym.SDWARFSECT
// (but we need to generate dies before writepub)
@@ -2000,5 +2006,14 @@ func (v compilationUnitByStartPC) Len() int { return len(v) }
func (v compilationUnitByStartPC) Swap(i, j int) { v[i], v[j] = v[j], v[i] }
func (v compilationUnitByStartPC) Less(i, j int) bool {
- return v[i].lib.Textp[0].Value < v[j].lib.Textp[0].Value
+ switch {
+ case len(v[i].lib.Textp) == 0 && len(v[j].lib.Textp) == 0:
+ return v[i].lib.Pkg < v[j].lib.Pkg
+ case len(v[i].lib.Textp) != 0 && len(v[j].lib.Textp) == 0:
+ return true
+ case len(v[i].lib.Textp) == 0 && len(v[j].lib.Textp) != 0:
+ return false
+ default:
+ return v[i].lib.Textp[0].Value < v[j].lib.Textp[0].Value
+ }
}
diff --git a/src/cmd/link/internal/ld/dwarf_test.go b/src/cmd/link/internal/ld/dwarf_test.go
index 157bebbb41..5d2aadf589 100644
--- a/src/cmd/link/internal/ld/dwarf_test.go
+++ b/src/cmd/link/internal/ld/dwarf_test.go
@@ -948,3 +948,117 @@ func main() {
t.Errorf("DWARF type offset was %#x+%#x, but test program said %#x", rtAttr.(uint64), types.Addr, addr)
}
}
+
+func TestIssue27614(t *testing.T) {
+ // Type references in debug_info should always use the DW_TAG_typedef_type
+ // for the type, when that's generated.
+
+ testenv.MustHaveGoBuild(t)
+
+ if runtime.GOOS == "plan9" {
+ t.Skip("skipping on plan9; no DWARF symbol table in executables")
+ }
+
+ dir, err := ioutil.TempDir("", "go-build")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(dir)
+
+ const prog = `package main
+
+import "fmt"
+
+type astruct struct {
+ X int
+}
+
+type bstruct struct {
+ X float32
+}
+
+var globalptr *astruct
+var globalvar astruct
+var bvar0, bvar1, bvar2 bstruct
+
+func main() {
+ fmt.Println(globalptr, globalvar, bvar0, bvar1, bvar2)
+}
+`
+
+ f := gobuild(t, dir, prog, NoOpt)
+
+ defer f.Close()
+
+ data, err := f.DWARF()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ rdr := data.Reader()
+
+ var astructTypeDIE, bstructTypeDIE, ptrastructTypeDIE *dwarf.Entry
+ var globalptrDIE, globalvarDIE *dwarf.Entry
+ var bvarDIE [3]*dwarf.Entry
+
+ for {
+ e, err := rdr.Next()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if e == nil {
+ break
+ }
+
+ name, _ := e.Val(dwarf.AttrName).(string)
+
+ switch e.Tag {
+ case dwarf.TagTypedef:
+ switch name {
+ case "main.astruct":
+ astructTypeDIE = e
+ case "main.bstruct":
+ bstructTypeDIE = e
+ }
+ case dwarf.TagPointerType:
+ if name == "*main.astruct" {
+ ptrastructTypeDIE = e
+ }
+ case dwarf.TagVariable:
+ switch name {
+ case "main.globalptr":
+ globalptrDIE = e
+ case "main.globalvar":
+ globalvarDIE = e
+ default:
+ const bvarprefix = "main.bvar"
+ if strings.HasPrefix(name, bvarprefix) {
+ i, _ := strconv.Atoi(name[len(bvarprefix):])
+ bvarDIE[i] = e
+ }
+ }
+ }
+ }
+
+ typedieof := func(e *dwarf.Entry) dwarf.Offset {
+ return e.Val(dwarf.AttrType).(dwarf.Offset)
+ }
+
+ if off := typedieof(ptrastructTypeDIE); off != astructTypeDIE.Offset {
+ t.Errorf("type attribute of *main.astruct references %#x, not main.astruct DIE at %#x\n", off, astructTypeDIE.Offset)
+ }
+
+ if off := typedieof(globalptrDIE); off != ptrastructTypeDIE.Offset {
+ t.Errorf("type attribute of main.globalptr references %#x, not *main.astruct DIE at %#x\n", off, ptrastructTypeDIE.Offset)
+ }
+
+ if off := typedieof(globalvarDIE); off != astructTypeDIE.Offset {
+ t.Errorf("type attribute of main.globalvar1 references %#x, not main.astruct DIE at %#x\n", off, astructTypeDIE.Offset)
+ }
+
+ for i := range bvarDIE {
+ if off := typedieof(bvarDIE[i]); off != bstructTypeDIE.Offset {
+ t.Errorf("type attribute of main.bvar%d references %#x, not main.bstruct DIE at %#x\n", i, off, bstructTypeDIE.Offset)
+ }
+ }
+}
diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go
index 919fa08f21..e911d7bf08 100644
--- a/src/cmd/link/internal/ld/lib.go
+++ b/src/cmd/link/internal/ld/lib.go
@@ -1380,9 +1380,58 @@ func linkerFlagSupported(linker, flag string) bool {
}
})
+ flagsWithNextArgSkip := []string{
+ "-F",
+ "-l",
+ "-L",
+ "-framework",
+ "-Wl,-framework",
+ "-Wl,-rpath",
+ "-Wl,-undefined",
+ }
+ flagsWithNextArgKeep := []string{
+ "-arch",
+ "-isysroot",
+ "--sysroot",
+ "-target",
+ }
+ prefixesToKeep := []string{
+ "-f",
+ "-m",
+ "-p",
+ "-Wl,",
+ "-arch",
+ "-isysroot",
+ "--sysroot",
+ "-target",
+ }
+
var flags []string
- flags = append(flags, ldflag...)
- flags = append(flags, strings.Fields(*flagExtldflags)...)
+ keep := false
+ skip := false
+ extldflags := strings.Fields(*flagExtldflags)
+ for _, f := range append(extldflags, ldflag...) {
+ if keep {
+ flags = append(flags, f)
+ keep = false
+ } else if skip {
+ skip = false
+ } else if f == "" || f[0] != '-' {
+ } else if contains(flagsWithNextArgSkip, f) {
+ skip = true
+ } else if contains(flagsWithNextArgKeep, f) {
+ flags = append(flags, f)
+ keep = true
+ } else {
+ for _, p := range prefixesToKeep {
+ if strings.HasPrefix(f, p) {
+ flags = append(flags, f)
+ break
+ }
+ }
+ }
+ }
+
flags = append(flags, flag, "trivial.c")
cmd := exec.Command(linker, flags...)
@@ -1758,26 +1807,6 @@ func addsection(arch *sys.Arch, seg *sym.Segment, name string, rwx int) *sym.Sec
return sect
}
-func Le16(b []byte) uint16 {
- return uint16(b[0]) | uint16(b[1])<<8
-}
-
-func Le32(b []byte) uint32 {
- return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
-}
-
-func Le64(b []byte) uint64 {
- return uint64(Le32(b)) | uint64(Le32(b[4:]))<<32
-}
-
-func Be16(b []byte) uint16 {
- return uint16(b[0])<<8 | uint16(b[1])
-}
-
-func Be32(b []byte) uint32 {
- return uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3])
-}
-
type chain struct {
sym *sym.Symbol
up *chain
diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go
index 7b7f7068e7..24398fcc87 100644
--- a/src/cmd/link/internal/ld/pcln.go
+++ b/src/cmd/link/internal/ld/pcln.go
@@ -312,45 +312,19 @@ func (ctxt *Link) pclntab() {
}
off = int32(ftab.SetUint32(ctxt.Arch, int64(off), args))
- // funcID uint32
- funcID := objabi.FuncID_normal
- switch s.Name {
- case "runtime.main":
- funcID = objabi.FuncID_runtime_main
- case "runtime.goexit":
- funcID = objabi.FuncID_goexit
- case "runtime.jmpdefer":
- funcID = objabi.FuncID_jmpdefer
- case "runtime.mcall":
- funcID = objabi.FuncID_mcall
- case "runtime.morestack":
- funcID = objabi.FuncID_morestack
- case "runtime.mstart":
- funcID = objabi.FuncID_mstart
- case "runtime.rt0_go":
- funcID = objabi.FuncID_rt0_go
- case "runtime.asmcgocall":
- funcID = objabi.FuncID_asmcgocall
- case "runtime.sigpanic":
- funcID = objabi.FuncID_sigpanic
- case "runtime.runfinq":
- funcID = objabi.FuncID_runfinq
- case "runtime.gcBgMarkWorker":
- funcID = objabi.FuncID_gcBgMarkWorker
- case "runtime.systemstack_switch":
- funcID = objabi.FuncID_systemstack_switch
- case "runtime.systemstack":
- funcID = objabi.FuncID_systemstack
- case "runtime.cgocallback_gofunc":
- funcID = objabi.FuncID_cgocallback_gofunc
- case "runtime.gogo":
- funcID = objabi.FuncID_gogo
- case "runtime.externalthreadhandler":
- funcID = objabi.FuncID_externalthreadhandler
- case "runtime.debugCallV1":
- funcID = objabi.FuncID_debugCallV1
+ // deferreturn
+ deferreturn := uint32(0)
+ for _, r := range s.R {
+ if r.Sym != nil && r.Sym.Name == "runtime.deferreturn" && r.Add == 0 {
+ // Note: the relocation target is in the call instruction, but
+ // is not necessarily the whole instruction (for instance, on
+ // x86 the relocation applies to bytes [1:5] of the 5 byte call
+ // instruction).
+ deferreturn = uint32(r.Off)
+ break // only need one
+ }
}
- off = int32(ftab.SetUint32(ctxt.Arch, int64(off), uint32(funcID)))
+ off = int32(ftab.SetUint32(ctxt.Arch, int64(off), deferreturn))
if pcln != &pclntabZpcln {
renumberfiles(ctxt, pcln.File, &pcln.Pcfile)
@@ -396,7 +370,52 @@ func (ctxt *Link) pclntab() {
off = addpctab(ctxt, ftab, off, &pcln.Pcfile)
off = addpctab(ctxt, ftab, off, &pcln.Pcline)
off = int32(ftab.SetUint32(ctxt.Arch, int64(off), uint32(len(pcln.Pcdata))))
- off = int32(ftab.SetUint32(ctxt.Arch, int64(off), uint32(len(pcln.Funcdata))))
+
+ // funcID uint8
+ funcID := objabi.FuncID_normal
+ switch s.Name {
+ case "runtime.main":
+ funcID = objabi.FuncID_runtime_main
+ case "runtime.goexit":
+ funcID = objabi.FuncID_goexit
+ case "runtime.jmpdefer":
+ funcID = objabi.FuncID_jmpdefer
+ case "runtime.mcall":
+ funcID = objabi.FuncID_mcall
+ case "runtime.morestack":
+ funcID = objabi.FuncID_morestack
+ case "runtime.mstart":
+ funcID = objabi.FuncID_mstart
+ case "runtime.rt0_go":
+ funcID = objabi.FuncID_rt0_go
+ case "runtime.asmcgocall":
+ funcID = objabi.FuncID_asmcgocall
+ case "runtime.sigpanic":
+ funcID = objabi.FuncID_sigpanic
+ case "runtime.runfinq":
+ funcID = objabi.FuncID_runfinq
+ case "runtime.gcBgMarkWorker":
+ funcID = objabi.FuncID_gcBgMarkWorker
+ case "runtime.systemstack_switch":
+ funcID = objabi.FuncID_systemstack_switch
+ case "runtime.systemstack":
+ funcID = objabi.FuncID_systemstack
+ case "runtime.cgocallback_gofunc":
+ funcID = objabi.FuncID_cgocallback_gofunc
+ case "runtime.gogo":
+ funcID = objabi.FuncID_gogo
+ case "runtime.externalthreadhandler":
+ funcID = objabi.FuncID_externalthreadhandler
+ case "runtime.debugCallV1":
+ funcID = objabi.FuncID_debugCallV1
+ }
+ off = int32(ftab.SetUint8(ctxt.Arch, int64(off), uint8(funcID)))
+
+ // unused
+ off += 2
+
+ // nfuncdata must be the final entry.
+ off = int32(ftab.SetUint8(ctxt.Arch, int64(off), uint8(len(pcln.Funcdata))))
for i := range pcln.Pcdata {
off = addpctab(ctxt, ftab, off, &pcln.Pcdata[i])
}
diff --git a/src/cmd/link/internal/ld/util.go b/src/cmd/link/internal/ld/util.go
index b80e6106ba..b5b02296a1 100644
--- a/src/cmd/link/internal/ld/util.go
+++ b/src/cmd/link/internal/ld/util.go
@@ -89,3 +89,13 @@ var start = time.Now()
func elapsed() float64 {
return time.Since(start).Seconds()
}
+
+// contains reports whether v is in s.
+func contains(s []string, v string) bool {
+ for _, x := range s {
+ if x == v {
+ return true
+ }
+ }
+ return false
+}
diff --git a/src/cmd/link/internal/objfile/objfile.go b/src/cmd/link/internal/objfile/objfile.go
index e3800de304..3a8923b073 100644
--- a/src/cmd/link/internal/objfile/objfile.go
+++ b/src/cmd/link/internal/objfile/objfile.go
@@ -203,6 +203,7 @@ func (r *objReader) readSym() {
overwrite:
s.File = pkg
+ s.Lib = r.lib
if dupok {
s.Attr |= sym.AttrDuplicateOK
}
@@ -320,7 +321,6 @@ overwrite:
s.FuncInfo.IsStmtSym = r.syms.Lookup(dwarf.IsStmtPrefix+s.Name, int(s.Version))
- s.Lib = r.lib
if !dupok {
if s.Attr.OnList() {
log.Fatalf("symbol %s listed multiple times", s.Name)
diff --git a/src/cmd/link/internal/ppc64/asm.go b/src/cmd/link/internal/ppc64/asm.go
index 9445fbebcb..3e833b686e 100644
--- a/src/cmd/link/internal/ppc64/asm.go
+++ b/src/cmd/link/internal/ppc64/asm.go
@@ -716,9 +716,9 @@ func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64
// overflow depends on the instruction
var o1 uint32
if ctxt.Arch.ByteOrder == binary.BigEndian {
- o1 = ld.Be32(s.P[r.Off-2:])
+ o1 = binary.BigEndian.Uint32(s.P[r.Off-2:])
} else {
- o1 = ld.Le32(s.P[r.Off:])
+ o1 = binary.LittleEndian.Uint32(s.P[r.Off:])
}
switch o1 >> 26 {
case 24, // ori
@@ -750,9 +750,9 @@ func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64
// overflow depends on the instruction
var o1 uint32
if ctxt.Arch.ByteOrder == binary.BigEndian {
- o1 = ld.Be32(s.P[r.Off-2:])
+ o1 = binary.BigEndian.Uint32(s.P[r.Off-2:])
} else {
- o1 = ld.Le32(s.P[r.Off:])
+ o1 = binary.LittleEndian.Uint32(s.P[r.Off:])
}
switch o1 >> 26 {
case 25, // oris
@@ -774,9 +774,9 @@ func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64
case sym.RV_POWER_DS:
var o1 uint32
if ctxt.Arch.ByteOrder == binary.BigEndian {
- o1 = uint32(ld.Be16(s.P[r.Off:]))
+ o1 = uint32(binary.BigEndian.Uint16(s.P[r.Off:]))
} else {
- o1 = uint32(ld.Le16(s.P[r.Off:]))
+ o1 = uint32(binary.LittleEndian.Uint16(s.P[r.Off:]))
}
if t&3 != 0 {
ld.Errorf(s, "relocation for %s+%d is not aligned: %d", r.Sym.Name, r.Off, t)
diff --git a/src/cmd/trace/trace.go b/src/cmd/trace/trace.go
index d986b71f79..07fc4333eb 100644
--- a/src/cmd/trace/trace.go
+++ b/src/cmd/trace/trace.go
@@ -38,7 +38,7 @@ func httpTrace(w http.ResponseWriter, r *http.Request) {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
- html := strings.Replace(templTrace, "{{PARAMS}}", r.Form.Encode(), -1)
+ html := strings.ReplaceAll(templTrace, "{{PARAMS}}", r.Form.Encode())
w.Write([]byte(html))
}
@@ -685,13 +685,14 @@ func generateTrace(params *traceParams, consumer traceConsumer) error {
}
ctx.emitSlice(&fakeMarkStart, text)
case trace.EvGCSweepStart:
- slice := ctx.emitSlice(ev, "SWEEP")
+ slice := ctx.makeSlice(ev, "SWEEP")
if done := ev.Link; done != nil && done.Args[0] != 0 {
slice.Arg = struct {
Swept uint64 `json:"Swept bytes"`
Reclaimed uint64 `json:"Reclaimed bytes"`
}{done.Args[0], done.Args[1]}
}
+ ctx.emit(slice)
case trace.EvGoStart, trace.EvGoStartLabel:
info := getGInfo(ev.G)
if ev.Type == trace.EvGoStartLabel {
@@ -846,7 +847,11 @@ func (ctx *traceContext) proc(ev *trace.Event) uint64 {
}
}
-func (ctx *traceContext) emitSlice(ev *trace.Event, name string) *ViewerEvent {
+func (ctx *traceContext) emitSlice(ev *trace.Event, name string) {
+ ctx.emit(ctx.makeSlice(ev, name))
+}
+
+func (ctx *traceContext) makeSlice(ev *trace.Event, name string) *ViewerEvent {
// If ViewerEvent.Dur is not a positive value,
// trace viewer handles it as a non-terminating time interval.
// Avoid it by setting the field with a small value.
@@ -885,7 +890,6 @@ func (ctx *traceContext) emitSlice(ev *trace.Event, name string) *ViewerEvent {
sl.Cname = colorLightGrey
}
}
- ctx.emit(sl)
return sl
}
diff --git a/src/cmd/vendor/golang.org/x/sys/windows/aliases.go b/src/cmd/vendor/golang.org/x/sys/windows/aliases.go
new file mode 100644
index 0000000000..af3af60db9
--- /dev/null
+++ b/src/cmd/vendor/golang.org/x/sys/windows/aliases.go
@@ -0,0 +1,13 @@
+// Copyright 2018 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
+// +build go1.9
+
+package windows
+
+import "syscall"
+
+type Errno = syscall.Errno
+type SysProcAttr = syscall.SysProcAttr
diff --git a/src/cmd/vendor/golang.org/x/sys/windows/asm_windows_arm.s b/src/cmd/vendor/golang.org/x/sys/windows/asm_windows_arm.s
new file mode 100644
index 0000000000..55d8b91a28
--- /dev/null
+++ b/src/cmd/vendor/golang.org/x/sys/windows/asm_windows_arm.s
@@ -0,0 +1,11 @@
+// Copyright 2018 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 "textflag.h"
+
+TEXT ·getprocaddress(SB),NOSPLIT,$0
+ B syscall·getprocaddress(SB)
+
+TEXT ·loadlibrary(SB),NOSPLIT,$0
+ B syscall·loadlibrary(SB)
diff --git a/src/cmd/vendor/golang.org/x/sys/windows/registry/zsyscall_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/registry/zsyscall_windows.go
index ceebdd7726..3778075da0 100644
--- a/src/cmd/vendor/golang.org/x/sys/windows/registry/zsyscall_windows.go
+++ b/src/cmd/vendor/golang.org/x/sys/windows/registry/zsyscall_windows.go
@@ -1,4 +1,4 @@
-// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT
+// Code generated by 'go generate'; DO NOT EDIT.
package registry
diff --git a/src/cmd/vendor/golang.org/x/sys/windows/security_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/security_windows.go
index f1ec5dc4ee..4f17a3331f 100644
--- a/src/cmd/vendor/golang.org/x/sys/windows/security_windows.go
+++ b/src/cmd/vendor/golang.org/x/sys/windows/security_windows.go
@@ -296,6 +296,7 @@ const (
TOKEN_ADJUST_PRIVILEGES
TOKEN_ADJUST_GROUPS
TOKEN_ADJUST_DEFAULT
+ TOKEN_ADJUST_SESSIONID
TOKEN_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED |
TOKEN_ASSIGN_PRIMARY |
@@ -305,7 +306,8 @@ const (
TOKEN_QUERY_SOURCE |
TOKEN_ADJUST_PRIVILEGES |
TOKEN_ADJUST_GROUPS |
- TOKEN_ADJUST_DEFAULT
+ TOKEN_ADJUST_DEFAULT |
+ TOKEN_ADJUST_SESSIONID
TOKEN_READ = STANDARD_RIGHTS_READ | TOKEN_QUERY
TOKEN_WRITE = STANDARD_RIGHTS_WRITE |
TOKEN_ADJUST_PRIVILEGES |
diff --git a/src/cmd/vendor/golang.org/x/sys/windows/service.go b/src/cmd/vendor/golang.org/x/sys/windows/service.go
index 24aa90bbbe..62fc31b40b 100644
--- a/src/cmd/vendor/golang.org/x/sys/windows/service.go
+++ b/src/cmd/vendor/golang.org/x/sys/windows/service.go
@@ -43,6 +43,11 @@ const (
SC_STATUS_PROCESS_INFO = 0
+ SC_ACTION_NONE = 0
+ SC_ACTION_RESTART = 1
+ SC_ACTION_REBOOT = 2
+ SC_ACTION_RUN_COMMAND = 3
+
SERVICE_STOPPED = 1
SERVICE_START_PENDING = 2
SERVICE_STOP_PENDING = 3
@@ -148,6 +153,19 @@ type ENUM_SERVICE_STATUS_PROCESS struct {
ServiceStatusProcess SERVICE_STATUS_PROCESS
}
+type SERVICE_FAILURE_ACTIONS struct {
+ ResetPeriod uint32
+ RebootMsg *uint16
+ Command *uint16
+ ActionsCount uint32
+ Actions *SC_ACTION
+}
+
+type SC_ACTION struct {
+ Type uint32
+ Delay uint32
+}
+
//sys CloseServiceHandle(handle Handle) (err error) = advapi32.CloseServiceHandle
//sys CreateService(mgr Handle, serviceName *uint16, displayName *uint16, access uint32, srvType uint32, startType uint32, errCtl uint32, pathName *uint16, loadOrderGroup *uint16, tagId *uint32, dependencies *uint16, serviceStartName *uint16, password *uint16) (handle Handle, err error) [failretval==0] = advapi32.CreateServiceW
//sys OpenService(mgr Handle, serviceName *uint16, access uint32) (handle Handle, err error) [failretval==0] = advapi32.OpenServiceW
diff --git a/src/cmd/vendor/golang.org/x/sys/windows/svc/mgr/config.go b/src/cmd/vendor/golang.org/x/sys/windows/svc/mgr/config.go
index 03bf41f516..d804e31f1f 100644
--- a/src/cmd/vendor/golang.org/x/sys/windows/svc/mgr/config.go
+++ b/src/cmd/vendor/golang.org/x/sys/windows/svc/mgr/config.go
@@ -88,23 +88,11 @@ func (s *Service) Config() (Config, error) {
}
}
- var p2 *windows.SERVICE_DESCRIPTION
- n = uint32(1024)
- for {
- b := make([]byte, n)
- p2 = (*windows.SERVICE_DESCRIPTION)(unsafe.Pointer(&b[0]))
- err := windows.QueryServiceConfig2(s.Handle,
- windows.SERVICE_CONFIG_DESCRIPTION, &b[0], n, &n)
- if err == nil {
- break
- }
- if err.(syscall.Errno) != syscall.ERROR_INSUFFICIENT_BUFFER {
- return Config{}, err
- }
- if n <= uint32(len(b)) {
- return Config{}, err
- }
+ b, err := s.queryServiceConfig2(windows.SERVICE_CONFIG_DESCRIPTION)
+ if err != nil {
+ return Config{}, err
}
+ p2 := (*windows.SERVICE_DESCRIPTION)(unsafe.Pointer(&b[0]))
return Config{
ServiceType: p.ServiceType,
@@ -137,3 +125,21 @@ func (s *Service) UpdateConfig(c Config) error {
}
return updateDescription(s.Handle, c.Description)
}
+
+// queryServiceConfig2 calls Windows QueryServiceConfig2 with infoLevel parameter and returns retrieved service configuration information.
+func (s *Service) queryServiceConfig2(infoLevel uint32) ([]byte, error) {
+ n := uint32(1024)
+ for {
+ b := make([]byte, n)
+ err := windows.QueryServiceConfig2(s.Handle, infoLevel, &b[0], n, &n)
+ if err == nil {
+ return b, nil
+ }
+ if err.(syscall.Errno) != syscall.ERROR_INSUFFICIENT_BUFFER {
+ return nil, err
+ }
+ if n <= uint32(len(b)) {
+ return nil, err
+ }
+ }
+}
diff --git a/src/cmd/vendor/golang.org/x/sys/windows/svc/mgr/mgr_test.go b/src/cmd/vendor/golang.org/x/sys/windows/svc/mgr/mgr_test.go
index 1569a22177..9171f5bcf1 100644
--- a/src/cmd/vendor/golang.org/x/sys/windows/svc/mgr/mgr_test.go
+++ b/src/cmd/vendor/golang.org/x/sys/windows/svc/mgr/mgr_test.go
@@ -95,6 +95,113 @@ func testConfig(t *testing.T, s *mgr.Service, should mgr.Config) mgr.Config {
return is
}
+func testRecoveryActions(t *testing.T, s *mgr.Service, should []mgr.RecoveryAction) {
+ is, err := s.RecoveryActions()
+ if err != nil {
+ t.Fatalf("RecoveryActions failed: %s", err)
+ }
+ if len(should) != len(is) {
+ t.Errorf("recovery action mismatch: contains %v actions, but should have %v", len(is), len(should))
+ }
+ for i, _ := range is {
+ if should[i].Type != is[i].Type {
+ t.Errorf("recovery action mismatch: Type is %v, but should have %v", is[i].Type, should[i].Type)
+ }
+ if should[i].Delay != is[i].Delay {
+ t.Errorf("recovery action mismatch: Delay is %v, but should have %v", is[i].Delay, should[i].Delay)
+ }
+ }
+}
+
+func testResetPeriod(t *testing.T, s *mgr.Service, should uint32) {
+ is, err := s.ResetPeriod()
+ if err != nil {
+ t.Fatalf("ResetPeriod failed: %s", err)
+ }
+ if should != is {
+ t.Errorf("reset period mismatch: reset period is %v, but should have %v", is, should)
+ }
+}
+
+func testSetRecoveryActions(t *testing.T, s *mgr.Service) {
+ r := []mgr.RecoveryAction{
+ mgr.RecoveryAction{
+ Type: mgr.NoAction,
+ Delay: 60000 * time.Millisecond,
+ },
+ mgr.RecoveryAction{
+ Type: mgr.ServiceRestart,
+ Delay: 4 * time.Minute,
+ },
+ mgr.RecoveryAction{
+ Type: mgr.ServiceRestart,
+ Delay: time.Minute,
+ },
+ mgr.RecoveryAction{
+ Type: mgr.RunCommand,
+ Delay: 4000 * time.Millisecond,
+ },
+ }
+
+ // 4 recovery actions with reset period
+ err := s.SetRecoveryActions(r, uint32(10000))
+ if err != nil {
+ t.Fatalf("SetRecoveryActions failed: %v", err)
+ }
+ testRecoveryActions(t, s, r)
+ testResetPeriod(t, s, uint32(10000))
+
+ // Infinite reset period
+ err = s.SetRecoveryActions(r, syscall.INFINITE)
+ if err != nil {
+ t.Fatalf("SetRecoveryActions failed: %v", err)
+ }
+ testRecoveryActions(t, s, r)
+ testResetPeriod(t, s, syscall.INFINITE)
+
+ // nil recovery actions
+ err = s.SetRecoveryActions(nil, 0)
+ if err.Error() != "recoveryActions cannot be nil" {
+ t.Fatalf("SetRecoveryActions failed with unexpected error message of %q", err)
+ }
+
+ // Delete all recovery actions and reset period
+ err = s.ResetRecoveryActions()
+ if err != nil {
+ t.Fatalf("ResetRecoveryActions failed: %v", err)
+ }
+ testRecoveryActions(t, s, nil)
+ testResetPeriod(t, s, 0)
+}
+
+func testRebootMessage(t *testing.T, s *mgr.Service, should string) {
+ err := s.SetRebootMessage(should)
+ if err != nil {
+ t.Fatalf("SetRebootMessage failed: %v", err)
+ }
+ is, err := s.RebootMessage()
+ if err != nil {
+ t.Fatalf("RebootMessage failed: %v", err)
+ }
+ if should != is {
+ t.Errorf("reboot message mismatch: message is %q, but should have %q", is, should)
+ }
+}
+
+func testRecoveryCommand(t *testing.T, s *mgr.Service, should string) {
+ err := s.SetRecoveryCommand(should)
+ if err != nil {
+ t.Fatalf("SetRecoveryCommand failed: %v", err)
+ }
+ is, err := s.RecoveryCommand()
+ if err != nil {
+ t.Fatalf("RecoveryCommand failed: %v", err)
+ }
+ if should != is {
+ t.Errorf("recovery command mismatch: command is %q, but should have %q", is, should)
+ }
+}
+
func remove(t *testing.T, s *mgr.Service) {
err := s.Delete()
if err != nil {
@@ -165,5 +272,11 @@ func TestMyService(t *testing.T) {
t.Errorf("ListServices failed to find %q service", name)
}
+ testSetRecoveryActions(t, s)
+ testRebootMessage(t, s, "myservice failed")
+ testRebootMessage(t, s, "") // delete reboot message
+ testRecoveryCommand(t, s, "sc query myservice")
+ testRecoveryCommand(t, s, "") // delete recovery command
+
remove(t, s)
}
diff --git a/src/cmd/vendor/golang.org/x/sys/windows/svc/mgr/recovery.go b/src/cmd/vendor/golang.org/x/sys/windows/svc/mgr/recovery.go
new file mode 100644
index 0000000000..71ce2b8199
--- /dev/null
+++ b/src/cmd/vendor/golang.org/x/sys/windows/svc/mgr/recovery.go
@@ -0,0 +1,135 @@
+// Copyright 2018 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
+
+package mgr
+
+import (
+ "errors"
+ "syscall"
+ "time"
+ "unsafe"
+
+ "golang.org/x/sys/windows"
+)
+
+const (
+ // Possible recovery actions that the service control manager can perform.
+ NoAction = windows.SC_ACTION_NONE // no action
+ ComputerReboot = windows.SC_ACTION_REBOOT // reboot the computer
+ ServiceRestart = windows.SC_ACTION_RESTART // restart the service
+ RunCommand = windows.SC_ACTION_RUN_COMMAND // run a command
+)
+
+// RecoveryAction represents an action that the service control manager can perform when service fails.
+// A service is considered failed when it terminates without reporting a status of SERVICE_STOPPED to the service controller.
+type RecoveryAction struct {
+ Type int // one of NoAction, ComputerReboot, ServiceRestart or RunCommand
+ Delay time.Duration // the time to wait before performing the specified action
+}
+
+// SetRecoveryActions sets actions that service controller performs when service fails and
+// the time after which to reset the service failure count to zero if there are no failures, in seconds.
+// Specify INFINITE to indicate that service failure count should never be reset.
+func (s *Service) SetRecoveryActions(recoveryActions []RecoveryAction, resetPeriod uint32) error {
+ if recoveryActions == nil {
+ return errors.New("recoveryActions cannot be nil")
+ }
+ actions := []windows.SC_ACTION{}
+ for _, a := range recoveryActions {
+ action := windows.SC_ACTION{
+ Type: uint32(a.Type),
+ Delay: uint32(a.Delay.Nanoseconds() / 1000000),
+ }
+ actions = append(actions, action)
+ }
+ rActions := windows.SERVICE_FAILURE_ACTIONS{
+ ActionsCount: uint32(len(actions)),
+ Actions: &actions[0],
+ ResetPeriod: resetPeriod,
+ }
+ return windows.ChangeServiceConfig2(s.Handle, windows.SERVICE_CONFIG_FAILURE_ACTIONS, (*byte)(unsafe.Pointer(&rActions)))
+}
+
+// RecoveryActions returns actions that service controller performs when service fails.
+// The service control manager counts the number of times service s has failed since the system booted.
+// The count is reset to 0 if the service has not failed for ResetPeriod seconds.
+// When the service fails for the Nth time, the service controller performs the action specified in element [N-1] of returned slice.
+// If N is greater than slice length, the service controller repeats the last action in the slice.
+func (s *Service) RecoveryActions() ([]RecoveryAction, error) {
+ b, err := s.queryServiceConfig2(windows.SERVICE_CONFIG_FAILURE_ACTIONS)
+ if err != nil {
+ return nil, err
+ }
+ p := (*windows.SERVICE_FAILURE_ACTIONS)(unsafe.Pointer(&b[0]))
+ if p.Actions == nil {
+ return nil, err
+ }
+
+ var recoveryActions []RecoveryAction
+ actions := (*[1024]windows.SC_ACTION)(unsafe.Pointer(p.Actions))[:p.ActionsCount]
+ for _, action := range actions {
+ recoveryActions = append(recoveryActions, RecoveryAction{Type: int(action.Type), Delay: time.Duration(action.Delay) * time.Millisecond})
+ }
+ return recoveryActions, nil
+}
+
+// ResetRecoveryActions deletes both reset period and array of failure actions.
+func (s *Service) ResetRecoveryActions() error {
+ actions := make([]windows.SC_ACTION, 1)
+ rActions := windows.SERVICE_FAILURE_ACTIONS{
+ Actions: &actions[0],
+ }
+ return windows.ChangeServiceConfig2(s.Handle, windows.SERVICE_CONFIG_FAILURE_ACTIONS, (*byte)(unsafe.Pointer(&rActions)))
+}
+
+// ResetPeriod is the time after which to reset the service failure
+// count to zero if there are no failures, in seconds.
+func (s *Service) ResetPeriod() (uint32, error) {
+ b, err := s.queryServiceConfig2(windows.SERVICE_CONFIG_FAILURE_ACTIONS)
+ if err != nil {
+ return 0, err
+ }
+ p := (*windows.SERVICE_FAILURE_ACTIONS)(unsafe.Pointer(&b[0]))
+ return p.ResetPeriod, nil
+}
+
+// SetRebootMessage sets service s reboot message.
+// If msg is "", the reboot message is deleted and no message is broadcast.
+func (s *Service) SetRebootMessage(msg string) error {
+ rActions := windows.SERVICE_FAILURE_ACTIONS{
+ RebootMsg: syscall.StringToUTF16Ptr(msg),
+ }
+ return windows.ChangeServiceConfig2(s.Handle, windows.SERVICE_CONFIG_FAILURE_ACTIONS, (*byte)(unsafe.Pointer(&rActions)))
+}
+
+// RebootMessage is broadcast to server users before rebooting in response to the ComputerReboot service controller action.
+func (s *Service) RebootMessage() (string, error) {
+ b, err := s.queryServiceConfig2(windows.SERVICE_CONFIG_FAILURE_ACTIONS)
+ if err != nil {
+ return "", err
+ }
+ p := (*windows.SERVICE_FAILURE_ACTIONS)(unsafe.Pointer(&b[0]))
+ return toString(p.RebootMsg), nil
+}
+
+// SetRecoveryCommand sets the command line of the process to execute in response to the RunCommand service controller action.
+// If cmd is "", the command is deleted and no program is run when the service fails.
+func (s *Service) SetRecoveryCommand(cmd string) error {
+ rActions := windows.SERVICE_FAILURE_ACTIONS{
+ Command: syscall.StringToUTF16Ptr(cmd),
+ }
+ return windows.ChangeServiceConfig2(s.Handle, windows.SERVICE_CONFIG_FAILURE_ACTIONS, (*byte)(unsafe.Pointer(&rActions)))
+}
+
+// RecoveryCommand is the command line of the process to execute in response to the RunCommand service controller action. This process runs under the same account as the service.
+func (s *Service) RecoveryCommand() (string, error) {
+ b, err := s.queryServiceConfig2(windows.SERVICE_CONFIG_FAILURE_ACTIONS)
+ if err != nil {
+ return "", err
+ }
+ p := (*windows.SERVICE_FAILURE_ACTIONS)(unsafe.Pointer(&b[0]))
+ return toString(p.Command), nil
+}
diff --git a/src/cmd/vendor/golang.org/x/sys/windows/svc/sys_arm.s b/src/cmd/vendor/golang.org/x/sys/windows/svc/sys_arm.s
new file mode 100644
index 0000000000..33c692a8de
--- /dev/null
+++ b/src/cmd/vendor/golang.org/x/sys/windows/svc/sys_arm.s
@@ -0,0 +1,38 @@
+// Copyright 2018 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
+
+#include "textflag.h"
+
+// func servicemain(argc uint32, argv **uint16)
+TEXT ·servicemain(SB),NOSPLIT|NOFRAME,$0
+ MOVM.DB.W [R4, R14], (R13) // push {r4, lr}
+ MOVW R13, R4
+ BIC $0x7, R13 // alignment for ABI
+
+ MOVW R0, ·sArgc(SB)
+ MOVW R1, ·sArgv(SB)
+
+ MOVW ·sName(SB), R0
+ MOVW ·ctlHandlerExProc(SB), R1
+ MOVW $0, R2
+ MOVW ·cRegisterServiceCtrlHandlerExW(SB), R3
+ BL (R3)
+ CMP $0, R0
+ BEQ exit
+ MOVW R0, ·ssHandle(SB)
+
+ MOVW ·goWaitsH(SB), R0
+ MOVW ·cSetEvent(SB), R1
+ BL (R1)
+
+ MOVW ·cWaitsH(SB), R0
+ MOVW $-1, R1
+ MOVW ·cWaitForSingleObject(SB), R2
+ BL (R2)
+
+exit:
+ MOVW R4, R13 // free extra stack space
+ MOVM.IA.W (R13), [R4, R15] // pop {r4, pc}
diff --git a/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go
index 1e9f4bb4a3..8a00b71f1d 100644
--- a/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go
+++ b/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go
@@ -112,12 +112,14 @@ func Getpagesize() int { return 4096 }
// NewCallback converts a Go function to a function pointer conforming to the stdcall calling convention.
// This is useful when interoperating with Windows code requiring callbacks.
+// The argument is expected to be a function with with one uintptr-sized result. The function must not have arguments with size larger than the size of uintptr.
func NewCallback(fn interface{}) uintptr {
return syscall.NewCallback(fn)
}
// NewCallbackCDecl converts a Go function to a function pointer conforming to the cdecl calling convention.
// This is useful when interoperating with Windows code requiring callbacks.
+// The argument is expected to be a function with with one uintptr-sized result. The function must not have arguments with size larger than the size of uintptr.
func NewCallbackCDecl(fn interface{}) uintptr {
return syscall.NewCallbackCDecl(fn)
}
@@ -653,7 +655,7 @@ type RawSockaddr struct {
type RawSockaddrAny struct {
Addr RawSockaddr
- Pad [96]int8
+ Pad [100]int8
}
type Sockaddr interface {
@@ -702,19 +704,69 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, int32, error) {
return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil
}
+type RawSockaddrUnix struct {
+ Family uint16
+ Path [UNIX_PATH_MAX]int8
+}
+
type SockaddrUnix struct {
Name string
+ raw RawSockaddrUnix
}
func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, int32, error) {
- // TODO(brainman): implement SockaddrUnix.sockaddr()
- return nil, 0, syscall.EWINDOWS
+ name := sa.Name
+ n := len(name)
+ if n > len(sa.raw.Path) {
+ return nil, 0, syscall.EINVAL
+ }
+ if n == len(sa.raw.Path) && name[0] != '@' {
+ return nil, 0, syscall.EINVAL
+ }
+ sa.raw.Family = AF_UNIX
+ for i := 0; i < n; i++ {
+ sa.raw.Path[i] = int8(name[i])
+ }
+ // length is family (uint16), name, NUL.
+ sl := int32(2)
+ if n > 0 {
+ sl += int32(n) + 1
+ }
+ if sa.raw.Path[0] == '@' {
+ sa.raw.Path[0] = 0
+ // Don't count trailing NUL for abstract address.
+ sl--
+ }
+
+ return unsafe.Pointer(&sa.raw), sl, nil
}
func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, error) {
switch rsa.Addr.Family {
case AF_UNIX:
- return nil, syscall.EWINDOWS
+ pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
+ sa := new(SockaddrUnix)
+ if pp.Path[0] == 0 {
+ // "Abstract" Unix domain socket.
+ // Rewrite leading NUL as @ for textual display.
+ // (This is the standard convention.)
+ // Not friendly to overwrite in place,
+ // but the callers below don't care.
+ pp.Path[0] = '@'
+ }
+
+ // Assume path ends at NUL.
+ // This is not technically the Linux semantics for
+ // abstract Unix domain sockets--they are supposed
+ // to be uninterpreted fixed-size binary blobs--but
+ // everyone uses this convention.
+ n := 0
+ for n < len(pp.Path) && pp.Path[n] != 0 {
+ n++
+ }
+ bytes := (*[10000]byte)(unsafe.Pointer(&pp.Path[0]))[0:n]
+ sa.Name = string(bytes)
+ return sa, nil
case AF_INET:
pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
diff --git a/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows_test.go b/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows_test.go
index 9c7133cc41..0e27464e8c 100644
--- a/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows_test.go
+++ b/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows_test.go
@@ -105,3 +105,9 @@ func ExampleLoadLibrary() {
build := uint16(r >> 16)
print("windows version ", major, ".", minor, " (Build ", build, ")\n")
}
+
+func TestTOKEN_ALL_ACCESS(t *testing.T) {
+ if windows.TOKEN_ALL_ACCESS != 0xF01FF {
+ t.Errorf("TOKEN_ALL_ACCESS = %x, want 0xF01FF", windows.TOKEN_ALL_ACCESS)
+ }
+}
diff --git a/src/cmd/vendor/golang.org/x/sys/windows/types_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/types_windows.go
index 52c2037b68..141ca81bd7 100644
--- a/src/cmd/vendor/golang.org/x/sys/windows/types_windows.go
+++ b/src/cmd/vendor/golang.org/x/sys/windows/types_windows.go
@@ -94,16 +94,29 @@ const (
FILE_APPEND_DATA = 0x00000004
FILE_WRITE_ATTRIBUTES = 0x00000100
- FILE_SHARE_READ = 0x00000001
- FILE_SHARE_WRITE = 0x00000002
- FILE_SHARE_DELETE = 0x00000004
- FILE_ATTRIBUTE_READONLY = 0x00000001
- FILE_ATTRIBUTE_HIDDEN = 0x00000002
- FILE_ATTRIBUTE_SYSTEM = 0x00000004
- FILE_ATTRIBUTE_DIRECTORY = 0x00000010
- FILE_ATTRIBUTE_ARCHIVE = 0x00000020
- FILE_ATTRIBUTE_NORMAL = 0x00000080
- FILE_ATTRIBUTE_REPARSE_POINT = 0x00000400
+ FILE_SHARE_READ = 0x00000001
+ FILE_SHARE_WRITE = 0x00000002
+ FILE_SHARE_DELETE = 0x00000004
+
+ FILE_ATTRIBUTE_READONLY = 0x00000001
+ FILE_ATTRIBUTE_HIDDEN = 0x00000002
+ FILE_ATTRIBUTE_SYSTEM = 0x00000004
+ FILE_ATTRIBUTE_DIRECTORY = 0x00000010
+ FILE_ATTRIBUTE_ARCHIVE = 0x00000020
+ FILE_ATTRIBUTE_DEVICE = 0x00000040
+ FILE_ATTRIBUTE_NORMAL = 0x00000080
+ FILE_ATTRIBUTE_TEMPORARY = 0x00000100
+ FILE_ATTRIBUTE_SPARSE_FILE = 0x00000200
+ FILE_ATTRIBUTE_REPARSE_POINT = 0x00000400
+ FILE_ATTRIBUTE_COMPRESSED = 0x00000800
+ FILE_ATTRIBUTE_OFFLINE = 0x00001000
+ FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x00002000
+ FILE_ATTRIBUTE_ENCRYPTED = 0x00004000
+ FILE_ATTRIBUTE_INTEGRITY_STREAM = 0x00008000
+ FILE_ATTRIBUTE_VIRTUAL = 0x00010000
+ FILE_ATTRIBUTE_NO_SCRUB_DATA = 0x00020000
+ FILE_ATTRIBUTE_RECALL_ON_OPEN = 0x00040000
+ FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS = 0x00400000
INVALID_FILE_ATTRIBUTES = 0xffffffff
@@ -257,15 +270,87 @@ const (
USAGE_MATCH_TYPE_AND = 0
USAGE_MATCH_TYPE_OR = 1
+ /* msgAndCertEncodingType values for CertOpenStore function */
X509_ASN_ENCODING = 0x00000001
PKCS_7_ASN_ENCODING = 0x00010000
- CERT_STORE_PROV_MEMORY = 2
-
- CERT_STORE_ADD_ALWAYS = 4
+ /* storeProvider values for CertOpenStore function */
+ CERT_STORE_PROV_MSG = 1
+ CERT_STORE_PROV_MEMORY = 2
+ CERT_STORE_PROV_FILE = 3
+ CERT_STORE_PROV_REG = 4
+ CERT_STORE_PROV_PKCS7 = 5
+ CERT_STORE_PROV_SERIALIZED = 6
+ CERT_STORE_PROV_FILENAME_A = 7
+ CERT_STORE_PROV_FILENAME_W = 8
+ CERT_STORE_PROV_FILENAME = CERT_STORE_PROV_FILENAME_W
+ CERT_STORE_PROV_SYSTEM_A = 9
+ CERT_STORE_PROV_SYSTEM_W = 10
+ CERT_STORE_PROV_SYSTEM = CERT_STORE_PROV_SYSTEM_W
+ CERT_STORE_PROV_COLLECTION = 11
+ CERT_STORE_PROV_SYSTEM_REGISTRY_A = 12
+ CERT_STORE_PROV_SYSTEM_REGISTRY_W = 13
+ CERT_STORE_PROV_SYSTEM_REGISTRY = CERT_STORE_PROV_SYSTEM_REGISTRY_W
+ CERT_STORE_PROV_PHYSICAL_W = 14
+ CERT_STORE_PROV_PHYSICAL = CERT_STORE_PROV_PHYSICAL_W
+ CERT_STORE_PROV_SMART_CARD_W = 15
+ CERT_STORE_PROV_SMART_CARD = CERT_STORE_PROV_SMART_CARD_W
+ CERT_STORE_PROV_LDAP_W = 16
+ CERT_STORE_PROV_LDAP = CERT_STORE_PROV_LDAP_W
+ CERT_STORE_PROV_PKCS12 = 17
+ /* store characteristics (low WORD of flag) for CertOpenStore function */
+ CERT_STORE_NO_CRYPT_RELEASE_FLAG = 0x00000001
+ CERT_STORE_SET_LOCALIZED_NAME_FLAG = 0x00000002
CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG = 0x00000004
+ CERT_STORE_DELETE_FLAG = 0x00000010
+ CERT_STORE_UNSAFE_PHYSICAL_FLAG = 0x00000020
+ CERT_STORE_SHARE_STORE_FLAG = 0x00000040
+ CERT_STORE_SHARE_CONTEXT_FLAG = 0x00000080
+ CERT_STORE_MANIFOLD_FLAG = 0x00000100
+ CERT_STORE_ENUM_ARCHIVED_FLAG = 0x00000200
+ CERT_STORE_UPDATE_KEYID_FLAG = 0x00000400
+ CERT_STORE_BACKUP_RESTORE_FLAG = 0x00000800
+ CERT_STORE_MAXIMUM_ALLOWED_FLAG = 0x00001000
+ CERT_STORE_CREATE_NEW_FLAG = 0x00002000
+ CERT_STORE_OPEN_EXISTING_FLAG = 0x00004000
+ CERT_STORE_READONLY_FLAG = 0x00008000
+
+ /* store locations (high WORD of flag) for CertOpenStore function */
+ CERT_SYSTEM_STORE_CURRENT_USER = 0x00010000
+ CERT_SYSTEM_STORE_LOCAL_MACHINE = 0x00020000
+ CERT_SYSTEM_STORE_CURRENT_SERVICE = 0x00040000
+ CERT_SYSTEM_STORE_SERVICES = 0x00050000
+ CERT_SYSTEM_STORE_USERS = 0x00060000
+ CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY = 0x00070000
+ CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY = 0x00080000
+ CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE = 0x00090000
+ CERT_SYSTEM_STORE_UNPROTECTED_FLAG = 0x40000000
+ CERT_SYSTEM_STORE_RELOCATE_FLAG = 0x80000000
+
+ /* Miscellaneous high-WORD flags for CertOpenStore function */
+ CERT_REGISTRY_STORE_REMOTE_FLAG = 0x00010000
+ CERT_REGISTRY_STORE_SERIALIZED_FLAG = 0x00020000
+ CERT_REGISTRY_STORE_ROAMING_FLAG = 0x00040000
+ CERT_REGISTRY_STORE_MY_IE_DIRTY_FLAG = 0x00080000
+ CERT_REGISTRY_STORE_LM_GPT_FLAG = 0x01000000
+ CERT_REGISTRY_STORE_CLIENT_GPT_FLAG = 0x80000000
+ CERT_FILE_STORE_COMMIT_ENABLE_FLAG = 0x00010000
+ CERT_LDAP_STORE_SIGN_FLAG = 0x00010000
+ CERT_LDAP_STORE_AREC_EXCLUSIVE_FLAG = 0x00020000
+ CERT_LDAP_STORE_OPENED_FLAG = 0x00040000
+ CERT_LDAP_STORE_UNBIND_FLAG = 0x00080000
+ /* addDisposition values for CertAddCertificateContextToStore function */
+ CERT_STORE_ADD_NEW = 1
+ CERT_STORE_ADD_USE_EXISTING = 2
+ CERT_STORE_ADD_REPLACE_EXISTING = 3
+ CERT_STORE_ADD_ALWAYS = 4
+ CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES = 5
+ CERT_STORE_ADD_NEWER = 6
+ CERT_STORE_ADD_NEWER_INHERIT_PROPERTIES = 7
+
+ /* ErrorStatus values for CertTrustStatus struct */
CERT_TRUST_NO_ERROR = 0x00000000
CERT_TRUST_IS_NOT_TIME_VALID = 0x00000001
CERT_TRUST_IS_REVOKED = 0x00000004
@@ -282,11 +367,31 @@ const (
CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT = 0x00002000
CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT = 0x00004000
CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT = 0x00008000
+ CERT_TRUST_IS_PARTIAL_CHAIN = 0x00010000
+ CERT_TRUST_CTL_IS_NOT_TIME_VALID = 0x00020000
+ CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID = 0x00040000
+ CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE = 0x00080000
+ CERT_TRUST_HAS_WEAK_SIGNATURE = 0x00100000
CERT_TRUST_IS_OFFLINE_REVOCATION = 0x01000000
CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY = 0x02000000
CERT_TRUST_IS_EXPLICIT_DISTRUST = 0x04000000
CERT_TRUST_HAS_NOT_SUPPORTED_CRITICAL_EXT = 0x08000000
+ /* InfoStatus values for CertTrustStatus struct */
+ CERT_TRUST_HAS_EXACT_MATCH_ISSUER = 0x00000001
+ CERT_TRUST_HAS_KEY_MATCH_ISSUER = 0x00000002
+ CERT_TRUST_HAS_NAME_MATCH_ISSUER = 0x00000004
+ CERT_TRUST_IS_SELF_SIGNED = 0x00000008
+ CERT_TRUST_HAS_PREFERRED_ISSUER = 0x00000100
+ CERT_TRUST_HAS_ISSUANCE_CHAIN_POLICY = 0x00000400
+ CERT_TRUST_HAS_VALID_NAME_CONSTRAINTS = 0x00000400
+ CERT_TRUST_IS_PEER_TRUSTED = 0x00000800
+ CERT_TRUST_HAS_CRL_VALIDITY_EXTENDED = 0x00001000
+ CERT_TRUST_IS_FROM_EXCLUSIVE_TRUST_STORE = 0x00002000
+ CERT_TRUST_IS_CA_TRUSTED = 0x00004000
+ CERT_TRUST_IS_COMPLEX_CHAIN = 0x00010000
+
+ /* policyOID values for CertVerifyCertificateChainPolicy function */
CERT_CHAIN_POLICY_BASE = 1
CERT_CHAIN_POLICY_AUTHENTICODE = 2
CERT_CHAIN_POLICY_AUTHENTICODE_TS = 3
@@ -295,6 +400,7 @@ const (
CERT_CHAIN_POLICY_NT_AUTH = 6
CERT_CHAIN_POLICY_MICROSOFT_ROOT = 7
CERT_CHAIN_POLICY_EV = 8
+ CERT_CHAIN_POLICY_SSL_F12 = 9
CERT_E_EXPIRED = 0x800B0101
CERT_E_ROLE = 0x800B0103
@@ -302,8 +408,16 @@ const (
CERT_E_UNTRUSTEDROOT = 0x800B0109
CERT_E_CN_NO_MATCH = 0x800B010F
+ /* AuthType values for SSLExtraCertChainPolicyPara struct */
AUTHTYPE_CLIENT = 1
AUTHTYPE_SERVER = 2
+
+ /* Checks values for SSLExtraCertChainPolicyPara struct */
+ SECURITY_FLAG_IGNORE_REVOCATION = 0x00000080
+ SECURITY_FLAG_IGNORE_UNKNOWN_CA = 0x00000100
+ SECURITY_FLAG_IGNORE_WRONG_USAGE = 0x00000200
+ SECURITY_FLAG_IGNORE_CERT_CN_INVALID = 0x00001000
+ SECURITY_FLAG_IGNORE_CERT_DATE_INVALID = 0x00002000
)
var (
@@ -312,6 +426,14 @@ var (
OID_SGC_NETSCAPE = []byte("2.16.840.1.113730.4.1\x00")
)
+// Pointer represents a pointer to an arbitrary Windows type.
+//
+// Pointer-typed fields may point to one of many different types. It's
+// up to the caller to provide a pointer to the appropriate type, cast
+// to Pointer. The caller must obey the unsafe.Pointer rules while
+// doing so.
+type Pointer *struct{}
+
// Invented values to support what package os expects.
type Timeval struct {
Sec int32
@@ -880,11 +1002,15 @@ type MibIfRow struct {
Descr [MAXLEN_IFDESCR]byte
}
+type CertInfo struct {
+ // Not implemented
+}
+
type CertContext struct {
EncodingType uint32
EncodedCert *byte
Length uint32
- CertInfo uintptr
+ CertInfo *CertInfo
Store Handle
}
@@ -899,12 +1025,16 @@ type CertChainContext struct {
RevocationFreshnessTime uint32
}
+type CertTrustListInfo struct {
+ // Not implemented
+}
+
type CertSimpleChain struct {
Size uint32
TrustStatus CertTrustStatus
NumElements uint32
Elements **CertChainElement
- TrustListInfo uintptr
+ TrustListInfo *CertTrustListInfo
HasRevocationFreshnessTime uint32
RevocationFreshnessTime uint32
}
@@ -919,14 +1049,18 @@ type CertChainElement struct {
ExtendedErrorInfo *uint16
}
+type CertRevocationCrlInfo struct {
+ // Not implemented
+}
+
type CertRevocationInfo struct {
Size uint32
RevocationResult uint32
RevocationOid *byte
- OidSpecificInfo uintptr
+ OidSpecificInfo Pointer
HasFreshnessTime uint32
FreshnessTime uint32
- CrlInfo uintptr // *CertRevocationCrlInfo
+ CrlInfo *CertRevocationCrlInfo
}
type CertTrustStatus struct {
@@ -957,7 +1091,7 @@ type CertChainPara struct {
type CertChainPolicyPara struct {
Size uint32
Flags uint32
- ExtraPolicyPara uintptr
+ ExtraPolicyPara Pointer
}
type SSLExtraCertChainPolicyPara struct {
@@ -972,7 +1106,7 @@ type CertChainPolicyStatus struct {
Error uint32
ChainIndex uint32
ElementIndex uint32
- ExtraPolicyStatus uintptr
+ ExtraPolicyStatus Pointer
}
const (
@@ -1319,7 +1453,7 @@ type SmallRect struct {
Bottom int16
}
-// Used with GetConsoleScreenBuffer to retreive information about a console
+// Used with GetConsoleScreenBuffer to retrieve information about a console
// screen buffer. See
// https://docs.microsoft.com/en-us/windows/console/console-screen-buffer-info-str
// for details.
@@ -1331,3 +1465,5 @@ type ConsoleScreenBufferInfo struct {
Window SmallRect
MaximumWindowSize Coord
}
+
+const UNIX_PATH_MAX = 108 // defined in afunix.h
diff --git a/src/cmd/vendor/golang.org/x/sys/windows/types_windows_arm.go b/src/cmd/vendor/golang.org/x/sys/windows/types_windows_arm.go
new file mode 100644
index 0000000000..74571e3600
--- /dev/null
+++ b/src/cmd/vendor/golang.org/x/sys/windows/types_windows_arm.go
@@ -0,0 +1,22 @@
+// Copyright 2018 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 windows
+
+type WSAData struct {
+ Version uint16
+ HighVersion uint16
+ Description [WSADESCRIPTION_LEN + 1]byte
+ SystemStatus [WSASYS_STATUS_LEN + 1]byte
+ MaxSockets uint16
+ MaxUdpDg uint16
+ VendorInfo *byte
+}
+
+type Servent struct {
+ Name *byte
+ Aliases **byte
+ Port uint16
+ Proto *byte
+}
diff --git a/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go
index 318c61634e..fc56aec035 100644
--- a/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go
+++ b/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go
@@ -1,4 +1,4 @@
-// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT
+// Code generated by 'go generate'; DO NOT EDIT.
package windows
diff --git a/src/cmd/vendor/vendor.json b/src/cmd/vendor/vendor.json
index 8009661879..6e077e4ae1 100644
--- a/src/cmd/vendor/vendor.json
+++ b/src/cmd/vendor/vendor.json
@@ -131,40 +131,40 @@
"revisionTime": "2018-06-27T13:57:12Z"
},
{
- "checksumSHA1": "y0x0I9zDxnxn9nCxwP/MdPyq1E8=",
+ "checksumSHA1": "s+lofQ+SCdhmy0cQp9FpdQncuuI=",
"path": "golang.org/x/sys/windows",
- "revision": "c11f84a56e43e20a78cee75a7c034031ecf57d1f",
- "revisionTime": "2018-05-25T13:55:20Z"
+ "revision": "90868a75fefd03942536221d7c0e2f84ec62a668",
+ "revisionTime": "2018-08-01T20:46:00Z"
},
{
- "checksumSHA1": "BnZkq/3Ejb7961bDhybRraW6jzI=",
+ "checksumSHA1": "yEg3f1MGwuyDh5NrNEGkWKlTyqY=",
"path": "golang.org/x/sys/windows/registry",
- "revision": "c11f84a56e43e20a78cee75a7c034031ecf57d1f",
- "revisionTime": "2018-05-25T13:55:20Z"
+ "revision": "90868a75fefd03942536221d7c0e2f84ec62a668",
+ "revisionTime": "2018-08-01T20:46:00Z"
},
{
- "checksumSHA1": "dQbFeoiAxfB3WFFVcAdeSwSgeDk=",
+ "checksumSHA1": "ZDwqsuoZqQq/XMQ0R0dJ4oK41lU=",
"path": "golang.org/x/sys/windows/svc",
- "revision": "c11f84a56e43e20a78cee75a7c034031ecf57d1f",
- "revisionTime": "2018-05-25T13:55:20Z"
+ "revision": "90868a75fefd03942536221d7c0e2f84ec62a668",
+ "revisionTime": "2018-08-01T20:46:00Z"
},
{
"checksumSHA1": "e9KJPWrdqg5PMkbE2w60Io8rY4M=",
"path": "golang.org/x/sys/windows/svc/debug",
- "revision": "c11f84a56e43e20a78cee75a7c034031ecf57d1f",
- "revisionTime": "2018-05-25T13:55:20Z"
+ "revision": "90868a75fefd03942536221d7c0e2f84ec62a668",
+ "revisionTime": "2018-08-01T20:46:00Z"
},
{
"checksumSHA1": "dz53pQfqAnXG8HdJj+nazXN9YRw=",
"path": "golang.org/x/sys/windows/svc/eventlog",
- "revision": "c11f84a56e43e20a78cee75a7c034031ecf57d1f",
- "revisionTime": "2018-05-25T13:55:20Z"
+ "revision": "90868a75fefd03942536221d7c0e2f84ec62a668",
+ "revisionTime": "2018-08-01T20:46:00Z"
},
{
- "checksumSHA1": "wz+0tf0Z7cVBaz/35P1m1cAiI7k=",
+ "checksumSHA1": "vV6Mr/b+1GaHiHLnq2zEejQJVec=",
"path": "golang.org/x/sys/windows/svc/mgr",
- "revision": "c11f84a56e43e20a78cee75a7c034031ecf57d1f",
- "revisionTime": "2018-05-25T13:55:20Z"
+ "revision": "90868a75fefd03942536221d7c0e2f84ec62a668",
+ "revisionTime": "2018-08-01T20:46:00Z"
}
],
"rootPath": "/cmd"
diff --git a/src/cmd/vet/all/main.go b/src/cmd/vet/all/main.go
index e7fe4edc2a..7e4a68101f 100644
--- a/src/cmd/vet/all/main.go
+++ b/src/cmd/vet/all/main.go
@@ -192,9 +192,9 @@ func vetPlatforms(pp []platform) {
}
func (p platform) vet() {
- if p.os == "linux" && p.arch == "riscv64" {
- // TODO(tklauser): enable as soon as the riscv64 port has fully landed
- fmt.Println("skipping linux/riscv64")
+ if p.os == "linux" && (p.arch == "riscv64" || p.arch == "sparc64") {
+ // TODO(tklauser): enable as soon as these ports have fully landed
+ fmt.Printf("skipping %s/%s\n", p.os, p.arch)
return
}
@@ -204,6 +204,12 @@ func (p platform) vet() {
return
}
+ if p.os == "aix" && p.arch == "ppc64" {
+ // TODO(aix): enable as soon as the aix/ppc64 port has fully landed
+ fmt.Println("skipping aix/ppc64")
+ return
+ }
+
var buf bytes.Buffer
fmt.Fprintf(&buf, "go run main.go -p %s\n", p)
diff --git a/src/cmd/vet/all/whitelist/all.txt b/src/cmd/vet/all/whitelist/all.txt
index b974d21c6a..5425f84fc6 100644
--- a/src/cmd/vet/all/whitelist/all.txt
+++ b/src/cmd/vet/all/whitelist/all.txt
@@ -24,6 +24,7 @@ runtime/asm_ARCHSUFF.s: [GOARCH] gcWriteBarrier: function gcWriteBarrier missing
// in bad situations that vet can also detect statically.
encoding/json/decode_test.go: struct field m has json tag but is not exported
encoding/json/decode_test.go: struct field m2 has json tag but is not exported
+encoding/json/decode_test.go: struct field s has json tag but is not exported
encoding/json/tagkey_test.go: struct field tag `:"BadFormat"` not compatible with reflect.StructTag.Get: bad syntax for struct tag key
runtime/testdata/testprog/deadlock.go: unreachable code
runtime/testdata/testprog/deadlock.go: unreachable code
diff --git a/src/cmd/vet/all/whitelist/windows_386.txt b/src/cmd/vet/all/whitelist/windows_386.txt
index 788684a49d..d910022ef6 100644
--- a/src/cmd/vet/all/whitelist/windows_386.txt
+++ b/src/cmd/vet/all/whitelist/windows_386.txt
@@ -3,7 +3,6 @@
runtime/sys_windows_386.s: [386] profileloop: use of 4(SP) points beyond argument frame
runtime/sys_windows_386.s: [386] ctrlhandler: 4(SP) should be _type+0(FP)
runtime/sys_windows_386.s: [386] setldt: function setldt missing Go declaration
-runtime/zcallback_windows.s: [386] callbackasm: function callbackasm missing Go declaration
runtime/sys_windows_386.s: [386] callbackasm1+0: function callbackasm1+0 missing Go declaration
runtime/sys_windows_386.s: [386] tstart: function tstart missing Go declaration
runtime/sys_windows_386.s: [386] tstart_stdcall: RET without writing to 4-byte ret+4(FP)
diff --git a/src/cmd/vet/all/whitelist/windows_amd64.txt b/src/cmd/vet/all/whitelist/windows_amd64.txt
index 3be4602579..676e6baf71 100644
--- a/src/cmd/vet/all/whitelist/windows_amd64.txt
+++ b/src/cmd/vet/all/whitelist/windows_amd64.txt
@@ -6,4 +6,3 @@ runtime/sys_windows_amd64.s: [amd64] callbackasm1: function callbackasm1 missing
runtime/sys_windows_amd64.s: [amd64] tstart_stdcall: RET without writing to 4-byte ret+8(FP)
runtime/sys_windows_amd64.s: [amd64] settls: function settls missing Go declaration
runtime/sys_windows_amd64.s: [amd64] cannot check cross-package assembly function: now is in package time
-runtime/zcallback_windows.s: [amd64] callbackasm: function callbackasm missing Go declaration
diff --git a/src/cmd/vet/main.go b/src/cmd/vet/main.go
index c50d4885a0..6e885121c8 100644
--- a/src/cmd/vet/main.go
+++ b/src/cmd/vet/main.go
@@ -273,7 +273,7 @@ func main() {
// Accept space-separated tags because that matches
// the go command's other subcommands.
// Accept commas because go tool vet traditionally has.
- tagList = strings.Fields(strings.Replace(*tags, ",", " ", -1))
+ tagList = strings.Fields(strings.ReplaceAll(*tags, ",", " "))
initPrintFlags()
initUnusedFlags()
@@ -467,6 +467,7 @@ type Package struct {
path string
defs map[*ast.Ident]types.Object
uses map[*ast.Ident]types.Object
+ implicits map[ast.Node]types.Object
selectors map[*ast.SelectorExpr]*types.Selection
types map[ast.Expr]types.TypeAndValue
spans map[types.Object]Span
diff --git a/src/cmd/vet/shadow.go b/src/cmd/vet/shadow.go
index 29c952fd88..47a48834bf 100644
--- a/src/cmd/vet/shadow.go
+++ b/src/cmd/vet/shadow.go
@@ -86,14 +86,11 @@ func (s Span) contains(pos token.Pos) bool {
return s.min <= pos && pos < s.max
}
-// growSpan expands the span for the object to contain the instance represented
-// by the identifier.
-func (pkg *Package) growSpan(ident *ast.Ident, obj types.Object) {
+// growSpan expands the span for the object to contain the source range [pos, end).
+func (pkg *Package) growSpan(obj types.Object, pos, end token.Pos) {
if *strictShadowing {
return // No need
}
- pos := ident.Pos()
- end := ident.End()
span, ok := pkg.spans[obj]
if ok {
if span.min > pos {
@@ -232,7 +229,7 @@ func checkShadowing(f *File, ident *ast.Ident) {
// the shadowing identifier.
span, ok := f.pkg.spans[shadowed]
if !ok {
- f.Badf(ident.Pos(), "internal error: no range for %q", ident.Name)
+ f.Badf(shadowed.Pos(), "internal error: no range for %q", shadowed.Name())
return
}
if !span.contains(ident.Pos()) {
diff --git a/src/cmd/vet/testdata/shadow.go b/src/cmd/vet/testdata/shadow.go
index c55cb2772a..d10fde2b81 100644
--- a/src/cmd/vet/testdata/shadow.go
+++ b/src/cmd/vet/testdata/shadow.go
@@ -57,3 +57,35 @@ func ShadowRead(f *os.File, buf []byte) (err error) {
func one() int {
return 1
}
+
+// Must not complain with an internal error for the
+// implicitly declared type switch variable v.
+func issue26725(x interface{}) int {
+ switch v := x.(type) {
+ case int, int32:
+ if v, ok := x.(int); ok {
+ return v
+ }
+ case int64:
+ return int(v)
+ }
+ return 0
+}
+
+// Verify that implicitly declared variables from
+// type switches are considered in shadowing analysis.
+func shadowTypeSwitch(a interface{}) {
+ switch t := a.(type) {
+ case int:
+ {
+ t := 0 // ERROR "declaration of .t. shadows declaration at shadow.go:78"
+ _ = t
+ }
+ _ = t
+ case uint:
+ {
+ t := uint(0) // OK because t is not mentioned later in this function
+ _ = t
+ }
+ }
+}
diff --git a/src/cmd/vet/types.go b/src/cmd/vet/types.go
index 5f8e481e01..3ff4b5966d 100644
--- a/src/cmd/vet/types.go
+++ b/src/cmd/vet/types.go
@@ -73,6 +73,7 @@ func (pkg *Package) check(fs *token.FileSet, astFiles []*ast.File) []error {
}
pkg.defs = make(map[*ast.Ident]types.Object)
pkg.uses = make(map[*ast.Ident]types.Object)
+ pkg.implicits = make(map[ast.Node]types.Object)
pkg.selectors = make(map[*ast.SelectorExpr]*types.Selection)
pkg.spans = make(map[types.Object]Span)
pkg.types = make(map[ast.Expr]types.TypeAndValue)
@@ -95,6 +96,7 @@ func (pkg *Package) check(fs *token.FileSet, astFiles []*ast.File) []error {
Types: pkg.types,
Defs: pkg.defs,
Uses: pkg.uses,
+ Implicits: pkg.implicits,
}
typesPkg, err := config.Check(pkg.path, fs, astFiles, info)
if len(allErrors) == 0 && err != nil {
@@ -103,10 +105,28 @@ func (pkg *Package) check(fs *token.FileSet, astFiles []*ast.File) []error {
pkg.typesPkg = typesPkg
// update spans
for id, obj := range pkg.defs {
- pkg.growSpan(id, obj)
+ // Ignore identifiers that don't denote objects
+ // (package names, symbolic variables such as t
+ // in t := x.(type) of type switch headers).
+ if obj != nil {
+ pkg.growSpan(obj, id.Pos(), id.End())
+ }
}
for id, obj := range pkg.uses {
- pkg.growSpan(id, obj)
+ pkg.growSpan(obj, id.Pos(), id.End())
+ }
+ for node, obj := range pkg.implicits {
+ // A type switch with a short variable declaration
+ // such as t := x.(type) doesn't declare the symbolic
+ // variable (t in the example) at the switch header;
+ // instead a new variable t (with specific type) is
+ // declared implicitly for each case. Such variables
+ // are found in the types.Info.Implicits (not Defs)
+ // map. Add them here, assuming they are declared at
+ // the type cases' colon ":".
+ if cc, ok := node.(*ast.CaseClause); ok {
+ pkg.growSpan(obj, cc.Colon, cc.Colon)
+ }
}
return allErrors
}
diff --git a/src/cmd/vet/vet_test.go b/src/cmd/vet/vet_test.go
index 90665d77bc..df84d6cc98 100644
--- a/src/cmd/vet/vet_test.go
+++ b/src/cmd/vet/vet_test.go
@@ -243,7 +243,7 @@ func errorCheck(outStr string, wantAuto bool, fullshort ...string) (err error) {
for i := range out {
for j := 0; j < len(fullshort); j += 2 {
full, short := fullshort[j], fullshort[j+1]
- out[i] = strings.Replace(out[i], full, short, -1)
+ out[i] = strings.ReplaceAll(out[i], full, short)
}
}
diff --git a/src/compress/bzip2/bzip2_test.go b/src/compress/bzip2/bzip2_test.go
index 3848603e0d..c432bb5226 100644
--- a/src/compress/bzip2/bzip2_test.go
+++ b/src/compress/bzip2/bzip2_test.go
@@ -214,7 +214,7 @@ func TestZeroRead(t *testing.T) {
var (
digits = mustLoadFile("testdata/e.txt.bz2")
- twain = mustLoadFile("testdata/Mark.Twain-Tom.Sawyer.txt.bz2")
+ newton = mustLoadFile("testdata/Isaac.Newton-Opticks.txt.bz2")
random = mustLoadFile("testdata/random.data.bz2")
)
@@ -236,5 +236,5 @@ func benchmarkDecode(b *testing.B, compressed []byte) {
}
func BenchmarkDecodeDigits(b *testing.B) { benchmarkDecode(b, digits) }
-func BenchmarkDecodeTwain(b *testing.B) { benchmarkDecode(b, twain) }
+func BenchmarkDecodeNewton(b *testing.B) { benchmarkDecode(b, newton) }
func BenchmarkDecodeRand(b *testing.B) { benchmarkDecode(b, random) }
diff --git a/src/compress/bzip2/testdata/Isaac.Newton-Opticks.txt.bz2 b/src/compress/bzip2/testdata/Isaac.Newton-Opticks.txt.bz2
new file mode 100644
index 0000000000..6c56de3bc2
--- /dev/null
+++ b/src/compress/bzip2/testdata/Isaac.Newton-Opticks.txt.bz2
Binary files differ
diff --git a/src/compress/bzip2/testdata/Mark.Twain-Tom.Sawyer.txt.bz2 b/src/compress/bzip2/testdata/Mark.Twain-Tom.Sawyer.txt.bz2
deleted file mode 100644
index eac2b0571b..0000000000
--- a/src/compress/bzip2/testdata/Mark.Twain-Tom.Sawyer.txt.bz2
+++ /dev/null
Binary files differ
diff --git a/src/compress/flate/deflate_test.go b/src/compress/flate/deflate_test.go
index fbea761721..831be2198c 100644
--- a/src/compress/flate/deflate_test.go
+++ b/src/compress/flate/deflate_test.go
@@ -371,9 +371,9 @@ var deflateInflateStringTests = []deflateInflateStringTest{
[...]int{100018, 50650, 50960, 51150, 50930, 50790, 50790, 50790, 50790, 50790, 43683},
},
{
- "../testdata/Mark.Twain-Tom.Sawyer.txt",
- "Mark.Twain-Tom.Sawyer",
- [...]int{407330, 187598, 180361, 172974, 169160, 163476, 160936, 160506, 160295, 160295, 233460},
+ "../../testdata/Isaac.Newton-Opticks.txt",
+ "Isaac.Newton-Opticks",
+ [...]int{567248, 218338, 198211, 193152, 181100, 175427, 175427, 173597, 173422, 173422, 325240},
},
}
@@ -654,7 +654,7 @@ func (w *failWriter) Write(b []byte) (int, error) {
func TestWriterPersistentError(t *testing.T) {
t.Parallel()
- d, err := ioutil.ReadFile("../testdata/Mark.Twain-Tom.Sawyer.txt")
+ d, err := ioutil.ReadFile("../../testdata/Isaac.Newton-Opticks.txt")
if err != nil {
t.Fatalf("ReadFile: %v", err)
}
diff --git a/src/compress/flate/reader_test.go b/src/compress/flate/reader_test.go
index b0a16ce18b..9d2943a540 100644
--- a/src/compress/flate/reader_test.go
+++ b/src/compress/flate/reader_test.go
@@ -27,8 +27,8 @@ var suites = []struct{ name, file string }{
// does not repeat, but there are only 10 possible digits, so it should be
// reasonably compressible.
{"Digits", "../testdata/e.txt"},
- // Twain is Mark Twain's classic English novel.
- {"Twain", "../testdata/Mark.Twain-Tom.Sawyer.txt"},
+ // Newton is Isaac Newtons's educational text on Opticks.
+ {"Newton", "../../testdata/Isaac.Newton-Opticks.txt"},
}
func BenchmarkDecode(b *testing.B) {
diff --git a/src/compress/testdata/Mark.Twain-Tom.Sawyer.txt b/src/compress/testdata/Mark.Twain-Tom.Sawyer.txt
deleted file mode 100644
index c9106fd522..0000000000
--- a/src/compress/testdata/Mark.Twain-Tom.Sawyer.txt
+++ /dev/null
@@ -1,8465 +0,0 @@
-Produced by David Widger. The previous edition was updated by Jose
-Menendez.
-
-
-
-
-
- THE ADVENTURES OF TOM SAWYER
- BY
- MARK TWAIN
- (Samuel Langhorne Clemens)
-
-
-
-
- P R E F A C E
-
-MOST of the adventures recorded in this book really occurred; one or
-two were experiences of my own, the rest those of boys who were
-schoolmates of mine. Huck Finn is drawn from life; Tom Sawyer also, but
-not from an individual--he is a combination of the characteristics of
-three boys whom I knew, and therefore belongs to the composite order of
-architecture.
-
-The odd superstitions touched upon were all prevalent among children
-and slaves in the West at the period of this story--that is to say,
-thirty or forty years ago.
-
-Although my book is intended mainly for the entertainment of boys and
-girls, I hope it will not be shunned by men and women on that account,
-for part of my plan has been to try to pleasantly remind adults of what
-they once were themselves, and of how they felt and thought and talked,
-and what queer enterprises they sometimes engaged in.
-
- THE AUTHOR.
-
-HARTFORD, 1876.
-
-
-
- T O M S A W Y E R
-
-
-
-CHAPTER I
-
-"TOM!"
-
-No answer.
-
-"TOM!"
-
-No answer.
-
-"What's gone with that boy, I wonder? You TOM!"
-
-No answer.
-
-The old lady pulled her spectacles down and looked over them about the
-room; then she put them up and looked out under them. She seldom or
-never looked THROUGH them for so small a thing as a boy; they were her
-state pair, the pride of her heart, and were built for "style," not
-service--she could have seen through a pair of stove-lids just as well.
-She looked perplexed for a moment, and then said, not fiercely, but
-still loud enough for the furniture to hear:
-
-"Well, I lay if I get hold of you I'll--"
-
-She did not finish, for by this time she was bending down and punching
-under the bed with the broom, and so she needed breath to punctuate the
-punches with. She resurrected nothing but the cat.
-
-"I never did see the beat of that boy!"
-
-She went to the open door and stood in it and looked out among the
-tomato vines and "jimpson" weeds that constituted the garden. No Tom.
-So she lifted up her voice at an angle calculated for distance and
-shouted:
-
-"Y-o-u-u TOM!"
-
-There was a slight noise behind her and she turned just in time to
-seize a small boy by the slack of his roundabout and arrest his flight.
-
-"There! I might 'a' thought of that closet. What you been doing in
-there?"
-
-"Nothing."
-
-"Nothing! Look at your hands. And look at your mouth. What IS that
-truck?"
-
-"I don't know, aunt."
-
-"Well, I know. It's jam--that's what it is. Forty times I've said if
-you didn't let that jam alone I'd skin you. Hand me that switch."
-
-The switch hovered in the air--the peril was desperate--
-
-"My! Look behind you, aunt!"
-
-The old lady whirled round, and snatched her skirts out of danger. The
-lad fled on the instant, scrambled up the high board-fence, and
-disappeared over it.
-
-His aunt Polly stood surprised a moment, and then broke into a gentle
-laugh.
-
-"Hang the boy, can't I never learn anything? Ain't he played me tricks
-enough like that for me to be looking out for him by this time? But old
-fools is the biggest fools there is. Can't learn an old dog new tricks,
-as the saying is. But my goodness, he never plays them alike, two days,
-and how is a body to know what's coming? He 'pears to know just how
-long he can torment me before I get my dander up, and he knows if he
-can make out to put me off for a minute or make me laugh, it's all down
-again and I can't hit him a lick. I ain't doing my duty by that boy,
-and that's the Lord's truth, goodness knows. Spare the rod and spile
-the child, as the Good Book says. I'm a laying up sin and suffering for
-us both, I know. He's full of the Old Scratch, but laws-a-me! he's my
-own dead sister's boy, poor thing, and I ain't got the heart to lash
-him, somehow. Every time I let him off, my conscience does hurt me so,
-and every time I hit him my old heart most breaks. Well-a-well, man
-that is born of woman is of few days and full of trouble, as the
-Scripture says, and I reckon it's so. He'll play hookey this evening, *
-and [* Southwestern for "afternoon"] I'll just be obleeged to make him
-work, to-morrow, to punish him. It's mighty hard to make him work
-Saturdays, when all the boys is having holiday, but he hates work more
-than he hates anything else, and I've GOT to do some of my duty by him,
-or I'll be the ruination of the child."
-
-Tom did play hookey, and he had a very good time. He got back home
-barely in season to help Jim, the small colored boy, saw next-day's
-wood and split the kindlings before supper--at least he was there in
-time to tell his adventures to Jim while Jim did three-fourths of the
-work. Tom's younger brother (or rather half-brother) Sid was already
-through with his part of the work (picking up chips), for he was a
-quiet boy, and had no adventurous, troublesome ways.
-
-While Tom was eating his supper, and stealing sugar as opportunity
-offered, Aunt Polly asked him questions that were full of guile, and
-very deep--for she wanted to trap him into damaging revealments. Like
-many other simple-hearted souls, it was her pet vanity to believe she
-was endowed with a talent for dark and mysterious diplomacy, and she
-loved to contemplate her most transparent devices as marvels of low
-cunning. Said she:
-
-"Tom, it was middling warm in school, warn't it?"
-
-"Yes'm."
-
-"Powerful warm, warn't it?"
-
-"Yes'm."
-
-"Didn't you want to go in a-swimming, Tom?"
-
-A bit of a scare shot through Tom--a touch of uncomfortable suspicion.
-He searched Aunt Polly's face, but it told him nothing. So he said:
-
-"No'm--well, not very much."
-
-The old lady reached out her hand and felt Tom's shirt, and said:
-
-"But you ain't too warm now, though." And it flattered her to reflect
-that she had discovered that the shirt was dry without anybody knowing
-that that was what she had in her mind. But in spite of her, Tom knew
-where the wind lay, now. So he forestalled what might be the next move:
-
-"Some of us pumped on our heads--mine's damp yet. See?"
-
-Aunt Polly was vexed to think she had overlooked that bit of
-circumstantial evidence, and missed a trick. Then she had a new
-inspiration:
-
-"Tom, you didn't have to undo your shirt collar where I sewed it, to
-pump on your head, did you? Unbutton your jacket!"
-
-The trouble vanished out of Tom's face. He opened his jacket. His
-shirt collar was securely sewed.
-
-"Bother! Well, go 'long with you. I'd made sure you'd played hookey
-and been a-swimming. But I forgive ye, Tom. I reckon you're a kind of a
-singed cat, as the saying is--better'n you look. THIS time."
-
-She was half sorry her sagacity had miscarried, and half glad that Tom
-had stumbled into obedient conduct for once.
-
-But Sidney said:
-
-"Well, now, if I didn't think you sewed his collar with white thread,
-but it's black."
-
-"Why, I did sew it with white! Tom!"
-
-But Tom did not wait for the rest. As he went out at the door he said:
-
-"Siddy, I'll lick you for that."
-
-In a safe place Tom examined two large needles which were thrust into
-the lapels of his jacket, and had thread bound about them--one needle
-carried white thread and the other black. He said:
-
-"She'd never noticed if it hadn't been for Sid. Confound it! sometimes
-she sews it with white, and sometimes she sews it with black. I wish to
-geeminy she'd stick to one or t'other--I can't keep the run of 'em. But
-I bet you I'll lam Sid for that. I'll learn him!"
-
-He was not the Model Boy of the village. He knew the model boy very
-well though--and loathed him.
-
-Within two minutes, or even less, he had forgotten all his troubles.
-Not because his troubles were one whit less heavy and bitter to him
-than a man's are to a man, but because a new and powerful interest bore
-them down and drove them out of his mind for the time--just as men's
-misfortunes are forgotten in the excitement of new enterprises. This
-new interest was a valued novelty in whistling, which he had just
-acquired from a negro, and he was suffering to practise it undisturbed.
-It consisted in a peculiar bird-like turn, a sort of liquid warble,
-produced by touching the tongue to the roof of the mouth at short
-intervals in the midst of the music--the reader probably remembers how
-to do it, if he has ever been a boy. Diligence and attention soon gave
-him the knack of it, and he strode down the street with his mouth full
-of harmony and his soul full of gratitude. He felt much as an
-astronomer feels who has discovered a new planet--no doubt, as far as
-strong, deep, unalloyed pleasure is concerned, the advantage was with
-the boy, not the astronomer.
-
-The summer evenings were long. It was not dark, yet. Presently Tom
-checked his whistle. A stranger was before him--a boy a shade larger
-than himself. A new-comer of any age or either sex was an impressive
-curiosity in the poor little shabby village of St. Petersburg. This boy
-was well dressed, too--well dressed on a week-day. This was simply
-astounding. His cap was a dainty thing, his close-buttoned blue cloth
-roundabout was new and natty, and so were his pantaloons. He had shoes
-on--and it was only Friday. He even wore a necktie, a bright bit of
-ribbon. He had a citified air about him that ate into Tom's vitals. The
-more Tom stared at the splendid marvel, the higher he turned up his
-nose at his finery and the shabbier and shabbier his own outfit seemed
-to him to grow. Neither boy spoke. If one moved, the other moved--but
-only sidewise, in a circle; they kept face to face and eye to eye all
-the time. Finally Tom said:
-
-"I can lick you!"
-
-"I'd like to see you try it."
-
-"Well, I can do it."
-
-"No you can't, either."
-
-"Yes I can."
-
-"No you can't."
-
-"I can."
-
-"You can't."
-
-"Can!"
-
-"Can't!"
-
-An uncomfortable pause. Then Tom said:
-
-"What's your name?"
-
-"'Tisn't any of your business, maybe."
-
-"Well I 'low I'll MAKE it my business."
-
-"Well why don't you?"
-
-"If you say much, I will."
-
-"Much--much--MUCH. There now."
-
-"Oh, you think you're mighty smart, DON'T you? I could lick you with
-one hand tied behind me, if I wanted to."
-
-"Well why don't you DO it? You SAY you can do it."
-
-"Well I WILL, if you fool with me."
-
-"Oh yes--I've seen whole families in the same fix."
-
-"Smarty! You think you're SOME, now, DON'T you? Oh, what a hat!"
-
-"You can lump that hat if you don't like it. I dare you to knock it
-off--and anybody that'll take a dare will suck eggs."
-
-"You're a liar!"
-
-"You're another."
-
-"You're a fighting liar and dasn't take it up."
-
-"Aw--take a walk!"
-
-"Say--if you give me much more of your sass I'll take and bounce a
-rock off'n your head."
-
-"Oh, of COURSE you will."
-
-"Well I WILL."
-
-"Well why don't you DO it then? What do you keep SAYING you will for?
-Why don't you DO it? It's because you're afraid."
-
-"I AIN'T afraid."
-
-"You are."
-
-"I ain't."
-
-"You are."
-
-Another pause, and more eying and sidling around each other. Presently
-they were shoulder to shoulder. Tom said:
-
-"Get away from here!"
-
-"Go away yourself!"
-
-"I won't."
-
-"I won't either."
-
-So they stood, each with a foot placed at an angle as a brace, and
-both shoving with might and main, and glowering at each other with
-hate. But neither could get an advantage. After struggling till both
-were hot and flushed, each relaxed his strain with watchful caution,
-and Tom said:
-
-"You're a coward and a pup. I'll tell my big brother on you, and he
-can thrash you with his little finger, and I'll make him do it, too."
-
-"What do I care for your big brother? I've got a brother that's bigger
-than he is--and what's more, he can throw him over that fence, too."
-[Both brothers were imaginary.]
-
-"That's a lie."
-
-"YOUR saying so don't make it so."
-
-Tom drew a line in the dust with his big toe, and said:
-
-"I dare you to step over that, and I'll lick you till you can't stand
-up. Anybody that'll take a dare will steal sheep."
-
-The new boy stepped over promptly, and said:
-
-"Now you said you'd do it, now let's see you do it."
-
-"Don't you crowd me now; you better look out."
-
-"Well, you SAID you'd do it--why don't you do it?"
-
-"By jingo! for two cents I WILL do it."
-
-The new boy took two broad coppers out of his pocket and held them out
-with derision. Tom struck them to the ground. In an instant both boys
-were rolling and tumbling in the dirt, gripped together like cats; and
-for the space of a minute they tugged and tore at each other's hair and
-clothes, punched and scratched each other's nose, and covered
-themselves with dust and glory. Presently the confusion took form, and
-through the fog of battle Tom appeared, seated astride the new boy, and
-pounding him with his fists. "Holler 'nuff!" said he.
-
-The boy only struggled to free himself. He was crying--mainly from rage.
-
-"Holler 'nuff!"--and the pounding went on.
-
-At last the stranger got out a smothered "'Nuff!" and Tom let him up
-and said:
-
-"Now that'll learn you. Better look out who you're fooling with next
-time."
-
-The new boy went off brushing the dust from his clothes, sobbing,
-snuffling, and occasionally looking back and shaking his head and
-threatening what he would do to Tom the "next time he caught him out."
-To which Tom responded with jeers, and started off in high feather, and
-as soon as his back was turned the new boy snatched up a stone, threw
-it and hit him between the shoulders and then turned tail and ran like
-an antelope. Tom chased the traitor home, and thus found out where he
-lived. He then held a position at the gate for some time, daring the
-enemy to come outside, but the enemy only made faces at him through the
-window and declined. At last the enemy's mother appeared, and called
-Tom a bad, vicious, vulgar child, and ordered him away. So he went
-away; but he said he "'lowed" to "lay" for that boy.
-
-He got home pretty late that night, and when he climbed cautiously in
-at the window, he uncovered an ambuscade, in the person of his aunt;
-and when she saw the state his clothes were in her resolution to turn
-his Saturday holiday into captivity at hard labor became adamantine in
-its firmness.
-
-
-
-CHAPTER II
-
-SATURDAY morning was come, and all the summer world was bright and
-fresh, and brimming with life. There was a song in every heart; and if
-the heart was young the music issued at the lips. There was cheer in
-every face and a spring in every step. The locust-trees were in bloom
-and the fragrance of the blossoms filled the air. Cardiff Hill, beyond
-the village and above it, was green with vegetation and it lay just far
-enough away to seem a Delectable Land, dreamy, reposeful, and inviting.
-
-Tom appeared on the sidewalk with a bucket of whitewash and a
-long-handled brush. He surveyed the fence, and all gladness left him and
-a deep melancholy settled down upon his spirit. Thirty yards of board
-fence nine feet high. Life to him seemed hollow, and existence but a
-burden. Sighing, he dipped his brush and passed it along the topmost
-plank; repeated the operation; did it again; compared the insignificant
-whitewashed streak with the far-reaching continent of unwhitewashed
-fence, and sat down on a tree-box discouraged. Jim came skipping out at
-the gate with a tin pail, and singing Buffalo Gals. Bringing water from
-the town pump had always been hateful work in Tom's eyes, before, but
-now it did not strike him so. He remembered that there was company at
-the pump. White, mulatto, and negro boys and girls were always there
-waiting their turns, resting, trading playthings, quarrelling,
-fighting, skylarking. And he remembered that although the pump was only
-a hundred and fifty yards off, Jim never got back with a bucket of
-water under an hour--and even then somebody generally had to go after
-him. Tom said:
-
-"Say, Jim, I'll fetch the water if you'll whitewash some."
-
-Jim shook his head and said:
-
-"Can't, Mars Tom. Ole missis, she tole me I got to go an' git dis
-water an' not stop foolin' roun' wid anybody. She say she spec' Mars
-Tom gwine to ax me to whitewash, an' so she tole me go 'long an' 'tend
-to my own business--she 'lowed SHE'D 'tend to de whitewashin'."
-
-"Oh, never you mind what she said, Jim. That's the way she always
-talks. Gimme the bucket--I won't be gone only a a minute. SHE won't
-ever know."
-
-"Oh, I dasn't, Mars Tom. Ole missis she'd take an' tar de head off'n
-me. 'Deed she would."
-
-"SHE! She never licks anybody--whacks 'em over the head with her
-thimble--and who cares for that, I'd like to know. She talks awful, but
-talk don't hurt--anyways it don't if she don't cry. Jim, I'll give you
-a marvel. I'll give you a white alley!"
-
-Jim began to waver.
-
-"White alley, Jim! And it's a bully taw."
-
-"My! Dat's a mighty gay marvel, I tell you! But Mars Tom I's powerful
-'fraid ole missis--"
-
-"And besides, if you will I'll show you my sore toe."
-
-Jim was only human--this attraction was too much for him. He put down
-his pail, took the white alley, and bent over the toe with absorbing
-interest while the bandage was being unwound. In another moment he was
-flying down the street with his pail and a tingling rear, Tom was
-whitewashing with vigor, and Aunt Polly was retiring from the field
-with a slipper in her hand and triumph in her eye.
-
-But Tom's energy did not last. He began to think of the fun he had
-planned for this day, and his sorrows multiplied. Soon the free boys
-would come tripping along on all sorts of delicious expeditions, and
-they would make a world of fun of him for having to work--the very
-thought of it burnt him like fire. He got out his worldly wealth and
-examined it--bits of toys, marbles, and trash; enough to buy an
-exchange of WORK, maybe, but not half enough to buy so much as half an
-hour of pure freedom. So he returned his straitened means to his
-pocket, and gave up the idea of trying to buy the boys. At this dark
-and hopeless moment an inspiration burst upon him! Nothing less than a
-great, magnificent inspiration.
-
-He took up his brush and went tranquilly to work. Ben Rogers hove in
-sight presently--the very boy, of all boys, whose ridicule he had been
-dreading. Ben's gait was the hop-skip-and-jump--proof enough that his
-heart was light and his anticipations high. He was eating an apple, and
-giving a long, melodious whoop, at intervals, followed by a deep-toned
-ding-dong-dong, ding-dong-dong, for he was personating a steamboat. As
-he drew near, he slackened speed, took the middle of the street, leaned
-far over to starboard and rounded to ponderously and with laborious
-pomp and circumstance--for he was personating the Big Missouri, and
-considered himself to be drawing nine feet of water. He was boat and
-captain and engine-bells combined, so he had to imagine himself
-standing on his own hurricane-deck giving the orders and executing them:
-
-"Stop her, sir! Ting-a-ling-ling!" The headway ran almost out, and he
-drew up slowly toward the sidewalk.
-
-"Ship up to back! Ting-a-ling-ling!" His arms straightened and
-stiffened down his sides.
-
-"Set her back on the stabboard! Ting-a-ling-ling! Chow! ch-chow-wow!
-Chow!" His right hand, meantime, describing stately circles--for it was
-representing a forty-foot wheel.
-
-"Let her go back on the labboard! Ting-a-lingling! Chow-ch-chow-chow!"
-The left hand began to describe circles.
-
-"Stop the stabboard! Ting-a-ling-ling! Stop the labboard! Come ahead
-on the stabboard! Stop her! Let your outside turn over slow!
-Ting-a-ling-ling! Chow-ow-ow! Get out that head-line! LIVELY now!
-Come--out with your spring-line--what're you about there! Take a turn
-round that stump with the bight of it! Stand by that stage, now--let her
-go! Done with the engines, sir! Ting-a-ling-ling! SH'T! S'H'T! SH'T!"
-(trying the gauge-cocks).
-
-Tom went on whitewashing--paid no attention to the steamboat. Ben
-stared a moment and then said: "Hi-YI! YOU'RE up a stump, ain't you!"
-
-No answer. Tom surveyed his last touch with the eye of an artist, then
-he gave his brush another gentle sweep and surveyed the result, as
-before. Ben ranged up alongside of him. Tom's mouth watered for the
-apple, but he stuck to his work. Ben said:
-
-"Hello, old chap, you got to work, hey?"
-
-Tom wheeled suddenly and said:
-
-"Why, it's you, Ben! I warn't noticing."
-
-"Say--I'm going in a-swimming, I am. Don't you wish you could? But of
-course you'd druther WORK--wouldn't you? Course you would!"
-
-Tom contemplated the boy a bit, and said:
-
-"What do you call work?"
-
-"Why, ain't THAT work?"
-
-Tom resumed his whitewashing, and answered carelessly:
-
-"Well, maybe it is, and maybe it ain't. All I know, is, it suits Tom
-Sawyer."
-
-"Oh come, now, you don't mean to let on that you LIKE it?"
-
-The brush continued to move.
-
-"Like it? Well, I don't see why I oughtn't to like it. Does a boy get
-a chance to whitewash a fence every day?"
-
-That put the thing in a new light. Ben stopped nibbling his apple. Tom
-swept his brush daintily back and forth--stepped back to note the
-effect--added a touch here and there--criticised the effect again--Ben
-watching every move and getting more and more interested, more and more
-absorbed. Presently he said:
-
-"Say, Tom, let ME whitewash a little."
-
-Tom considered, was about to consent; but he altered his mind:
-
-"No--no--I reckon it wouldn't hardly do, Ben. You see, Aunt Polly's
-awful particular about this fence--right here on the street, you know
---but if it was the back fence I wouldn't mind and SHE wouldn't. Yes,
-she's awful particular about this fence; it's got to be done very
-careful; I reckon there ain't one boy in a thousand, maybe two
-thousand, that can do it the way it's got to be done."
-
-"No--is that so? Oh come, now--lemme just try. Only just a little--I'd
-let YOU, if you was me, Tom."
-
-"Ben, I'd like to, honest injun; but Aunt Polly--well, Jim wanted to
-do it, but she wouldn't let him; Sid wanted to do it, and she wouldn't
-let Sid. Now don't you see how I'm fixed? If you was to tackle this
-fence and anything was to happen to it--"
-
-"Oh, shucks, I'll be just as careful. Now lemme try. Say--I'll give
-you the core of my apple."
-
-"Well, here--No, Ben, now don't. I'm afeard--"
-
-"I'll give you ALL of it!"
-
-Tom gave up the brush with reluctance in his face, but alacrity in his
-heart. And while the late steamer Big Missouri worked and sweated in
-the sun, the retired artist sat on a barrel in the shade close by,
-dangled his legs, munched his apple, and planned the slaughter of more
-innocents. There was no lack of material; boys happened along every
-little while; they came to jeer, but remained to whitewash. By the time
-Ben was fagged out, Tom had traded the next chance to Billy Fisher for
-a kite, in good repair; and when he played out, Johnny Miller bought in
-for a dead rat and a string to swing it with--and so on, and so on,
-hour after hour. And when the middle of the afternoon came, from being
-a poor poverty-stricken boy in the morning, Tom was literally rolling
-in wealth. He had besides the things before mentioned, twelve marbles,
-part of a jews-harp, a piece of blue bottle-glass to look through, a
-spool cannon, a key that wouldn't unlock anything, a fragment of chalk,
-a glass stopper of a decanter, a tin soldier, a couple of tadpoles, six
-fire-crackers, a kitten with only one eye, a brass doorknob, a
-dog-collar--but no dog--the handle of a knife, four pieces of
-orange-peel, and a dilapidated old window sash.
-
-He had had a nice, good, idle time all the while--plenty of company
---and the fence had three coats of whitewash on it! If he hadn't run out
-of whitewash he would have bankrupted every boy in the village.
-
-Tom said to himself that it was not such a hollow world, after all. He
-had discovered a great law of human action, without knowing it--namely,
-that in order to make a man or a boy covet a thing, it is only
-necessary to make the thing difficult to attain. If he had been a great
-and wise philosopher, like the writer of this book, he would now have
-comprehended that Work consists of whatever a body is OBLIGED to do,
-and that Play consists of whatever a body is not obliged to do. And
-this would help him to understand why constructing artificial flowers
-or performing on a tread-mill is work, while rolling ten-pins or
-climbing Mont Blanc is only amusement. There are wealthy gentlemen in
-England who drive four-horse passenger-coaches twenty or thirty miles
-on a daily line, in the summer, because the privilege costs them
-considerable money; but if they were offered wages for the service,
-that would turn it into work and then they would resign.
-
-The boy mused awhile over the substantial change which had taken place
-in his worldly circumstances, and then wended toward headquarters to
-report.
-
-
-
-CHAPTER III
-
-TOM presented himself before Aunt Polly, who was sitting by an open
-window in a pleasant rearward apartment, which was bedroom,
-breakfast-room, dining-room, and library, combined. The balmy summer
-air, the restful quiet, the odor of the flowers, and the drowsing murmur
-of the bees had had their effect, and she was nodding over her knitting
---for she had no company but the cat, and it was asleep in her lap. Her
-spectacles were propped up on her gray head for safety. She had thought
-that of course Tom had deserted long ago, and she wondered at seeing him
-place himself in her power again in this intrepid way. He said: "Mayn't
-I go and play now, aunt?"
-
-"What, a'ready? How much have you done?"
-
-"It's all done, aunt."
-
-"Tom, don't lie to me--I can't bear it."
-
-"I ain't, aunt; it IS all done."
-
-Aunt Polly placed small trust in such evidence. She went out to see
-for herself; and she would have been content to find twenty per cent.
-of Tom's statement true. When she found the entire fence whitewashed,
-and not only whitewashed but elaborately coated and recoated, and even
-a streak added to the ground, her astonishment was almost unspeakable.
-She said:
-
-"Well, I never! There's no getting round it, you can work when you're
-a mind to, Tom." And then she diluted the compliment by adding, "But
-it's powerful seldom you're a mind to, I'm bound to say. Well, go 'long
-and play; but mind you get back some time in a week, or I'll tan you."
-
-She was so overcome by the splendor of his achievement that she took
-him into the closet and selected a choice apple and delivered it to
-him, along with an improving lecture upon the added value and flavor a
-treat took to itself when it came without sin through virtuous effort.
-And while she closed with a happy Scriptural flourish, he "hooked" a
-doughnut.
-
-Then he skipped out, and saw Sid just starting up the outside stairway
-that led to the back rooms on the second floor. Clods were handy and
-the air was full of them in a twinkling. They raged around Sid like a
-hail-storm; and before Aunt Polly could collect her surprised faculties
-and sally to the rescue, six or seven clods had taken personal effect,
-and Tom was over the fence and gone. There was a gate, but as a general
-thing he was too crowded for time to make use of it. His soul was at
-peace, now that he had settled with Sid for calling attention to his
-black thread and getting him into trouble.
-
-Tom skirted the block, and came round into a muddy alley that led by
-the back of his aunt's cow-stable. He presently got safely beyond the
-reach of capture and punishment, and hastened toward the public square
-of the village, where two "military" companies of boys had met for
-conflict, according to previous appointment. Tom was General of one of
-these armies, Joe Harper (a bosom friend) General of the other. These
-two great commanders did not condescend to fight in person--that being
-better suited to the still smaller fry--but sat together on an eminence
-and conducted the field operations by orders delivered through
-aides-de-camp. Tom's army won a great victory, after a long and
-hard-fought battle. Then the dead were counted, prisoners exchanged,
-the terms of the next disagreement agreed upon, and the day for the
-necessary battle appointed; after which the armies fell into line and
-marched away, and Tom turned homeward alone.
-
-As he was passing by the house where Jeff Thatcher lived, he saw a new
-girl in the garden--a lovely little blue-eyed creature with yellow hair
-plaited into two long-tails, white summer frock and embroidered
-pantalettes. The fresh-crowned hero fell without firing a shot. A
-certain Amy Lawrence vanished out of his heart and left not even a
-memory of herself behind. He had thought he loved her to distraction;
-he had regarded his passion as adoration; and behold it was only a poor
-little evanescent partiality. He had been months winning her; she had
-confessed hardly a week ago; he had been the happiest and the proudest
-boy in the world only seven short days, and here in one instant of time
-she had gone out of his heart like a casual stranger whose visit is
-done.
-
-He worshipped this new angel with furtive eye, till he saw that she
-had discovered him; then he pretended he did not know she was present,
-and began to "show off" in all sorts of absurd boyish ways, in order to
-win her admiration. He kept up this grotesque foolishness for some
-time; but by-and-by, while he was in the midst of some dangerous
-gymnastic performances, he glanced aside and saw that the little girl
-was wending her way toward the house. Tom came up to the fence and
-leaned on it, grieving, and hoping she would tarry yet awhile longer.
-She halted a moment on the steps and then moved toward the door. Tom
-heaved a great sigh as she put her foot on the threshold. But his face
-lit up, right away, for she tossed a pansy over the fence a moment
-before she disappeared.
-
-The boy ran around and stopped within a foot or two of the flower, and
-then shaded his eyes with his hand and began to look down street as if
-he had discovered something of interest going on in that direction.
-Presently he picked up a straw and began trying to balance it on his
-nose, with his head tilted far back; and as he moved from side to side,
-in his efforts, he edged nearer and nearer toward the pansy; finally
-his bare foot rested upon it, his pliant toes closed upon it, and he
-hopped away with the treasure and disappeared round the corner. But
-only for a minute--only while he could button the flower inside his
-jacket, next his heart--or next his stomach, possibly, for he was not
-much posted in anatomy, and not hypercritical, anyway.
-
-He returned, now, and hung about the fence till nightfall, "showing
-off," as before; but the girl never exhibited herself again, though Tom
-comforted himself a little with the hope that she had been near some
-window, meantime, and been aware of his attentions. Finally he strode
-home reluctantly, with his poor head full of visions.
-
-All through supper his spirits were so high that his aunt wondered
-"what had got into the child." He took a good scolding about clodding
-Sid, and did not seem to mind it in the least. He tried to steal sugar
-under his aunt's very nose, and got his knuckles rapped for it. He said:
-
-"Aunt, you don't whack Sid when he takes it."
-
-"Well, Sid don't torment a body the way you do. You'd be always into
-that sugar if I warn't watching you."
-
-Presently she stepped into the kitchen, and Sid, happy in his
-immunity, reached for the sugar-bowl--a sort of glorying over Tom which
-was wellnigh unbearable. But Sid's fingers slipped and the bowl dropped
-and broke. Tom was in ecstasies. In such ecstasies that he even
-controlled his tongue and was silent. He said to himself that he would
-not speak a word, even when his aunt came in, but would sit perfectly
-still till she asked who did the mischief; and then he would tell, and
-there would be nothing so good in the world as to see that pet model
-"catch it." He was so brimful of exultation that he could hardly hold
-himself when the old lady came back and stood above the wreck
-discharging lightnings of wrath from over her spectacles. He said to
-himself, "Now it's coming!" And the next instant he was sprawling on
-the floor! The potent palm was uplifted to strike again when Tom cried
-out:
-
-"Hold on, now, what 'er you belting ME for?--Sid broke it!"
-
-Aunt Polly paused, perplexed, and Tom looked for healing pity. But
-when she got her tongue again, she only said:
-
-"Umf! Well, you didn't get a lick amiss, I reckon. You been into some
-other audacious mischief when I wasn't around, like enough."
-
-Then her conscience reproached her, and she yearned to say something
-kind and loving; but she judged that this would be construed into a
-confession that she had been in the wrong, and discipline forbade that.
-So she kept silence, and went about her affairs with a troubled heart.
-Tom sulked in a corner and exalted his woes. He knew that in her heart
-his aunt was on her knees to him, and he was morosely gratified by the
-consciousness of it. He would hang out no signals, he would take notice
-of none. He knew that a yearning glance fell upon him, now and then,
-through a film of tears, but he refused recognition of it. He pictured
-himself lying sick unto death and his aunt bending over him beseeching
-one little forgiving word, but he would turn his face to the wall, and
-die with that word unsaid. Ah, how would she feel then? And he pictured
-himself brought home from the river, dead, with his curls all wet, and
-his sore heart at rest. How she would throw herself upon him, and how
-her tears would fall like rain, and her lips pray God to give her back
-her boy and she would never, never abuse him any more! But he would lie
-there cold and white and make no sign--a poor little sufferer, whose
-griefs were at an end. He so worked upon his feelings with the pathos
-of these dreams, that he had to keep swallowing, he was so like to
-choke; and his eyes swam in a blur of water, which overflowed when he
-winked, and ran down and trickled from the end of his nose. And such a
-luxury to him was this petting of his sorrows, that he could not bear
-to have any worldly cheeriness or any grating delight intrude upon it;
-it was too sacred for such contact; and so, presently, when his cousin
-Mary danced in, all alive with the joy of seeing home again after an
-age-long visit of one week to the country, he got up and moved in
-clouds and darkness out at one door as she brought song and sunshine in
-at the other.
-
-He wandered far from the accustomed haunts of boys, and sought
-desolate places that were in harmony with his spirit. A log raft in the
-river invited him, and he seated himself on its outer edge and
-contemplated the dreary vastness of the stream, wishing, the while,
-that he could only be drowned, all at once and unconsciously, without
-undergoing the uncomfortable routine devised by nature. Then he thought
-of his flower. He got it out, rumpled and wilted, and it mightily
-increased his dismal felicity. He wondered if she would pity him if she
-knew? Would she cry, and wish that she had a right to put her arms
-around his neck and comfort him? Or would she turn coldly away like all
-the hollow world? This picture brought such an agony of pleasurable
-suffering that he worked it over and over again in his mind and set it
-up in new and varied lights, till he wore it threadbare. At last he
-rose up sighing and departed in the darkness.
-
-About half-past nine or ten o'clock he came along the deserted street
-to where the Adored Unknown lived; he paused a moment; no sound fell
-upon his listening ear; a candle was casting a dull glow upon the
-curtain of a second-story window. Was the sacred presence there? He
-climbed the fence, threaded his stealthy way through the plants, till
-he stood under that window; he looked up at it long, and with emotion;
-then he laid him down on the ground under it, disposing himself upon
-his back, with his hands clasped upon his breast and holding his poor
-wilted flower. And thus he would die--out in the cold world, with no
-shelter over his homeless head, no friendly hand to wipe the
-death-damps from his brow, no loving face to bend pityingly over him
-when the great agony came. And thus SHE would see him when she looked
-out upon the glad morning, and oh! would she drop one little tear upon
-his poor, lifeless form, would she heave one little sigh to see a bright
-young life so rudely blighted, so untimely cut down?
-
-The window went up, a maid-servant's discordant voice profaned the
-holy calm, and a deluge of water drenched the prone martyr's remains!
-
-The strangling hero sprang up with a relieving snort. There was a whiz
-as of a missile in the air, mingled with the murmur of a curse, a sound
-as of shivering glass followed, and a small, vague form went over the
-fence and shot away in the gloom.
-
-Not long after, as Tom, all undressed for bed, was surveying his
-drenched garments by the light of a tallow dip, Sid woke up; but if he
-had any dim idea of making any "references to allusions," he thought
-better of it and held his peace, for there was danger in Tom's eye.
-
-Tom turned in without the added vexation of prayers, and Sid made
-mental note of the omission.
-
-
-
-CHAPTER IV
-
-THE sun rose upon a tranquil world, and beamed down upon the peaceful
-village like a benediction. Breakfast over, Aunt Polly had family
-worship: it began with a prayer built from the ground up of solid
-courses of Scriptural quotations, welded together with a thin mortar of
-originality; and from the summit of this she delivered a grim chapter
-of the Mosaic Law, as from Sinai.
-
-Then Tom girded up his loins, so to speak, and went to work to "get
-his verses." Sid had learned his lesson days before. Tom bent all his
-energies to the memorizing of five verses, and he chose part of the
-Sermon on the Mount, because he could find no verses that were shorter.
-At the end of half an hour Tom had a vague general idea of his lesson,
-but no more, for his mind was traversing the whole field of human
-thought, and his hands were busy with distracting recreations. Mary
-took his book to hear him recite, and he tried to find his way through
-the fog:
-
-"Blessed are the--a--a--"
-
-"Poor"--
-
-"Yes--poor; blessed are the poor--a--a--"
-
-"In spirit--"
-
-"In spirit; blessed are the poor in spirit, for they--they--"
-
-"THEIRS--"
-
-"For THEIRS. Blessed are the poor in spirit, for theirs is the kingdom
-of heaven. Blessed are they that mourn, for they--they--"
-
-"Sh--"
-
-"For they--a--"
-
-"S, H, A--"
-
-"For they S, H--Oh, I don't know what it is!"
-
-"SHALL!"
-
-"Oh, SHALL! for they shall--for they shall--a--a--shall mourn--a--a--
-blessed are they that shall--they that--a--they that shall mourn, for
-they shall--a--shall WHAT? Why don't you tell me, Mary?--what do you
-want to be so mean for?"
-
-"Oh, Tom, you poor thick-headed thing, I'm not teasing you. I wouldn't
-do that. You must go and learn it again. Don't you be discouraged, Tom,
-you'll manage it--and if you do, I'll give you something ever so nice.
-There, now, that's a good boy."
-
-"All right! What is it, Mary, tell me what it is."
-
-"Never you mind, Tom. You know if I say it's nice, it is nice."
-
-"You bet you that's so, Mary. All right, I'll tackle it again."
-
-And he did "tackle it again"--and under the double pressure of
-curiosity and prospective gain he did it with such spirit that he
-accomplished a shining success. Mary gave him a brand-new "Barlow"
-knife worth twelve and a half cents; and the convulsion of delight that
-swept his system shook him to his foundations. True, the knife would
-not cut anything, but it was a "sure-enough" Barlow, and there was
-inconceivable grandeur in that--though where the Western boys ever got
-the idea that such a weapon could possibly be counterfeited to its
-injury is an imposing mystery and will always remain so, perhaps. Tom
-contrived to scarify the cupboard with it, and was arranging to begin
-on the bureau, when he was called off to dress for Sunday-school.
-
-Mary gave him a tin basin of water and a piece of soap, and he went
-outside the door and set the basin on a little bench there; then he
-dipped the soap in the water and laid it down; turned up his sleeves;
-poured out the water on the ground, gently, and then entered the
-kitchen and began to wipe his face diligently on the towel behind the
-door. But Mary removed the towel and said:
-
-"Now ain't you ashamed, Tom. You mustn't be so bad. Water won't hurt
-you."
-
-Tom was a trifle disconcerted. The basin was refilled, and this time
-he stood over it a little while, gathering resolution; took in a big
-breath and began. When he entered the kitchen presently, with both eyes
-shut and groping for the towel with his hands, an honorable testimony
-of suds and water was dripping from his face. But when he emerged from
-the towel, he was not yet satisfactory, for the clean territory stopped
-short at his chin and his jaws, like a mask; below and beyond this line
-there was a dark expanse of unirrigated soil that spread downward in
-front and backward around his neck. Mary took him in hand, and when she
-was done with him he was a man and a brother, without distinction of
-color, and his saturated hair was neatly brushed, and its short curls
-wrought into a dainty and symmetrical general effect. [He privately
-smoothed out the curls, with labor and difficulty, and plastered his
-hair close down to his head; for he held curls to be effeminate, and
-his own filled his life with bitterness.] Then Mary got out a suit of
-his clothing that had been used only on Sundays during two years--they
-were simply called his "other clothes"--and so by that we know the
-size of his wardrobe. The girl "put him to rights" after he had dressed
-himself; she buttoned his neat roundabout up to his chin, turned his
-vast shirt collar down over his shoulders, brushed him off and crowned
-him with his speckled straw hat. He now looked exceedingly improved and
-uncomfortable. He was fully as uncomfortable as he looked; for there
-was a restraint about whole clothes and cleanliness that galled him. He
-hoped that Mary would forget his shoes, but the hope was blighted; she
-coated them thoroughly with tallow, as was the custom, and brought them
-out. He lost his temper and said he was always being made to do
-everything he didn't want to do. But Mary said, persuasively:
-
-"Please, Tom--that's a good boy."
-
-So he got into the shoes snarling. Mary was soon ready, and the three
-children set out for Sunday-school--a place that Tom hated with his
-whole heart; but Sid and Mary were fond of it.
-
-Sabbath-school hours were from nine to half-past ten; and then church
-service. Two of the children always remained for the sermon
-voluntarily, and the other always remained too--for stronger reasons.
-The church's high-backed, uncushioned pews would seat about three
-hundred persons; the edifice was but a small, plain affair, with a sort
-of pine board tree-box on top of it for a steeple. At the door Tom
-dropped back a step and accosted a Sunday-dressed comrade:
-
-"Say, Billy, got a yaller ticket?"
-
-"Yes."
-
-"What'll you take for her?"
-
-"What'll you give?"
-
-"Piece of lickrish and a fish-hook."
-
-"Less see 'em."
-
-Tom exhibited. They were satisfactory, and the property changed hands.
-Then Tom traded a couple of white alleys for three red tickets, and
-some small trifle or other for a couple of blue ones. He waylaid other
-boys as they came, and went on buying tickets of various colors ten or
-fifteen minutes longer. He entered the church, now, with a swarm of
-clean and noisy boys and girls, proceeded to his seat and started a
-quarrel with the first boy that came handy. The teacher, a grave,
-elderly man, interfered; then turned his back a moment and Tom pulled a
-boy's hair in the next bench, and was absorbed in his book when the boy
-turned around; stuck a pin in another boy, presently, in order to hear
-him say "Ouch!" and got a new reprimand from his teacher. Tom's whole
-class were of a pattern--restless, noisy, and troublesome. When they
-came to recite their lessons, not one of them knew his verses
-perfectly, but had to be prompted all along. However, they worried
-through, and each got his reward--in small blue tickets, each with a
-passage of Scripture on it; each blue ticket was pay for two verses of
-the recitation. Ten blue tickets equalled a red one, and could be
-exchanged for it; ten red tickets equalled a yellow one; for ten yellow
-tickets the superintendent gave a very plainly bound Bible (worth forty
-cents in those easy times) to the pupil. How many of my readers would
-have the industry and application to memorize two thousand verses, even
-for a Dore Bible? And yet Mary had acquired two Bibles in this way--it
-was the patient work of two years--and a boy of German parentage had
-won four or five. He once recited three thousand verses without
-stopping; but the strain upon his mental faculties was too great, and
-he was little better than an idiot from that day forth--a grievous
-misfortune for the school, for on great occasions, before company, the
-superintendent (as Tom expressed it) had always made this boy come out
-and "spread himself." Only the older pupils managed to keep their
-tickets and stick to their tedious work long enough to get a Bible, and
-so the delivery of one of these prizes was a rare and noteworthy
-circumstance; the successful pupil was so great and conspicuous for
-that day that on the spot every scholar's heart was fired with a fresh
-ambition that often lasted a couple of weeks. It is possible that Tom's
-mental stomach had never really hungered for one of those prizes, but
-unquestionably his entire being had for many a day longed for the glory
-and the eclat that came with it.
-
-In due course the superintendent stood up in front of the pulpit, with
-a closed hymn-book in his hand and his forefinger inserted between its
-leaves, and commanded attention. When a Sunday-school superintendent
-makes his customary little speech, a hymn-book in the hand is as
-necessary as is the inevitable sheet of music in the hand of a singer
-who stands forward on the platform and sings a solo at a concert
---though why, is a mystery: for neither the hymn-book nor the sheet of
-music is ever referred to by the sufferer. This superintendent was a
-slim creature of thirty-five, with a sandy goatee and short sandy hair;
-he wore a stiff standing-collar whose upper edge almost reached his
-ears and whose sharp points curved forward abreast the corners of his
-mouth--a fence that compelled a straight lookout ahead, and a turning
-of the whole body when a side view was required; his chin was propped
-on a spreading cravat which was as broad and as long as a bank-note,
-and had fringed ends; his boot toes were turned sharply up, in the
-fashion of the day, like sleigh-runners--an effect patiently and
-laboriously produced by the young men by sitting with their toes
-pressed against a wall for hours together. Mr. Walters was very earnest
-of mien, and very sincere and honest at heart; and he held sacred
-things and places in such reverence, and so separated them from worldly
-matters, that unconsciously to himself his Sunday-school voice had
-acquired a peculiar intonation which was wholly absent on week-days. He
-began after this fashion:
-
-"Now, children, I want you all to sit up just as straight and pretty
-as you can and give me all your attention for a minute or two. There
---that is it. That is the way good little boys and girls should do. I see
-one little girl who is looking out of the window--I am afraid she
-thinks I am out there somewhere--perhaps up in one of the trees making
-a speech to the little birds. [Applausive titter.] I want to tell you
-how good it makes me feel to see so many bright, clean little faces
-assembled in a place like this, learning to do right and be good." And
-so forth and so on. It is not necessary to set down the rest of the
-oration. It was of a pattern which does not vary, and so it is familiar
-to us all.
-
-The latter third of the speech was marred by the resumption of fights
-and other recreations among certain of the bad boys, and by fidgetings
-and whisperings that extended far and wide, washing even to the bases
-of isolated and incorruptible rocks like Sid and Mary. But now every
-sound ceased suddenly, with the subsidence of Mr. Walters' voice, and
-the conclusion of the speech was received with a burst of silent
-gratitude.
-
-A good part of the whispering had been occasioned by an event which
-was more or less rare--the entrance of visitors: lawyer Thatcher,
-accompanied by a very feeble and aged man; a fine, portly, middle-aged
-gentleman with iron-gray hair; and a dignified lady who was doubtless
-the latter's wife. The lady was leading a child. Tom had been restless
-and full of chafings and repinings; conscience-smitten, too--he could
-not meet Amy Lawrence's eye, he could not brook her loving gaze. But
-when he saw this small new-comer his soul was all ablaze with bliss in
-a moment. The next moment he was "showing off" with all his might
---cuffing boys, pulling hair, making faces--in a word, using every art
-that seemed likely to fascinate a girl and win her applause. His
-exaltation had but one alloy--the memory of his humiliation in this
-angel's garden--and that record in sand was fast washing out, under
-the waves of happiness that were sweeping over it now.
-
-The visitors were given the highest seat of honor, and as soon as Mr.
-Walters' speech was finished, he introduced them to the school. The
-middle-aged man turned out to be a prodigious personage--no less a one
-than the county judge--altogether the most august creation these
-children had ever looked upon--and they wondered what kind of material
-he was made of--and they half wanted to hear him roar, and were half
-afraid he might, too. He was from Constantinople, twelve miles away--so
-he had travelled, and seen the world--these very eyes had looked upon
-the county court-house--which was said to have a tin roof. The awe
-which these reflections inspired was attested by the impressive silence
-and the ranks of staring eyes. This was the great Judge Thatcher,
-brother of their own lawyer. Jeff Thatcher immediately went forward, to
-be familiar with the great man and be envied by the school. It would
-have been music to his soul to hear the whisperings:
-
-"Look at him, Jim! He's a going up there. Say--look! he's a going to
-shake hands with him--he IS shaking hands with him! By jings, don't you
-wish you was Jeff?"
-
-Mr. Walters fell to "showing off," with all sorts of official
-bustlings and activities, giving orders, delivering judgments,
-discharging directions here, there, everywhere that he could find a
-target. The librarian "showed off"--running hither and thither with his
-arms full of books and making a deal of the splutter and fuss that
-insect authority delights in. The young lady teachers "showed off"
---bending sweetly over pupils that were lately being boxed, lifting
-pretty warning fingers at bad little boys and patting good ones
-lovingly. The young gentlemen teachers "showed off" with small
-scoldings and other little displays of authority and fine attention to
-discipline--and most of the teachers, of both sexes, found business up
-at the library, by the pulpit; and it was business that frequently had
-to be done over again two or three times (with much seeming vexation).
-The little girls "showed off" in various ways, and the little boys
-"showed off" with such diligence that the air was thick with paper wads
-and the murmur of scufflings. And above it all the great man sat and
-beamed a majestic judicial smile upon all the house, and warmed himself
-in the sun of his own grandeur--for he was "showing off," too.
-
-There was only one thing wanting to make Mr. Walters' ecstasy
-complete, and that was a chance to deliver a Bible-prize and exhibit a
-prodigy. Several pupils had a few yellow tickets, but none had enough
---he had been around among the star pupils inquiring. He would have given
-worlds, now, to have that German lad back again with a sound mind.
-
-And now at this moment, when hope was dead, Tom Sawyer came forward
-with nine yellow tickets, nine red tickets, and ten blue ones, and
-demanded a Bible. This was a thunderbolt out of a clear sky. Walters
-was not expecting an application from this source for the next ten
-years. But there was no getting around it--here were the certified
-checks, and they were good for their face. Tom was therefore elevated
-to a place with the Judge and the other elect, and the great news was
-announced from headquarters. It was the most stunning surprise of the
-decade, and so profound was the sensation that it lifted the new hero
-up to the judicial one's altitude, and the school had two marvels to
-gaze upon in place of one. The boys were all eaten up with envy--but
-those that suffered the bitterest pangs were those who perceived too
-late that they themselves had contributed to this hated splendor by
-trading tickets to Tom for the wealth he had amassed in selling
-whitewashing privileges. These despised themselves, as being the dupes
-of a wily fraud, a guileful snake in the grass.
-
-The prize was delivered to Tom with as much effusion as the
-superintendent could pump up under the circumstances; but it lacked
-somewhat of the true gush, for the poor fellow's instinct taught him
-that there was a mystery here that could not well bear the light,
-perhaps; it was simply preposterous that this boy had warehoused two
-thousand sheaves of Scriptural wisdom on his premises--a dozen would
-strain his capacity, without a doubt.
-
-Amy Lawrence was proud and glad, and she tried to make Tom see it in
-her face--but he wouldn't look. She wondered; then she was just a grain
-troubled; next a dim suspicion came and went--came again; she watched;
-a furtive glance told her worlds--and then her heart broke, and she was
-jealous, and angry, and the tears came and she hated everybody. Tom
-most of all (she thought).
-
-Tom was introduced to the Judge; but his tongue was tied, his breath
-would hardly come, his heart quaked--partly because of the awful
-greatness of the man, but mainly because he was her parent. He would
-have liked to fall down and worship him, if it were in the dark. The
-Judge put his hand on Tom's head and called him a fine little man, and
-asked him what his name was. The boy stammered, gasped, and got it out:
-
-"Tom."
-
-"Oh, no, not Tom--it is--"
-
-"Thomas."
-
-"Ah, that's it. I thought there was more to it, maybe. That's very
-well. But you've another one I daresay, and you'll tell it to me, won't
-you?"
-
-"Tell the gentleman your other name, Thomas," said Walters, "and say
-sir. You mustn't forget your manners."
-
-"Thomas Sawyer--sir."
-
-"That's it! That's a good boy. Fine boy. Fine, manly little fellow.
-Two thousand verses is a great many--very, very great many. And you
-never can be sorry for the trouble you took to learn them; for
-knowledge is worth more than anything there is in the world; it's what
-makes great men and good men; you'll be a great man and a good man
-yourself, some day, Thomas, and then you'll look back and say, It's all
-owing to the precious Sunday-school privileges of my boyhood--it's all
-owing to my dear teachers that taught me to learn--it's all owing to
-the good superintendent, who encouraged me, and watched over me, and
-gave me a beautiful Bible--a splendid elegant Bible--to keep and have
-it all for my own, always--it's all owing to right bringing up! That is
-what you will say, Thomas--and you wouldn't take any money for those
-two thousand verses--no indeed you wouldn't. And now you wouldn't mind
-telling me and this lady some of the things you've learned--no, I know
-you wouldn't--for we are proud of little boys that learn. Now, no
-doubt you know the names of all the twelve disciples. Won't you tell us
-the names of the first two that were appointed?"
-
-Tom was tugging at a button-hole and looking sheepish. He blushed,
-now, and his eyes fell. Mr. Walters' heart sank within him. He said to
-himself, it is not possible that the boy can answer the simplest
-question--why DID the Judge ask him? Yet he felt obliged to speak up
-and say:
-
-"Answer the gentleman, Thomas--don't be afraid."
-
-Tom still hung fire.
-
-"Now I know you'll tell me," said the lady. "The names of the first
-two disciples were--"
-
-"DAVID AND GOLIAH!"
-
-Let us draw the curtain of charity over the rest of the scene.
-
-
-
-CHAPTER V
-
-ABOUT half-past ten the cracked bell of the small church began to
-ring, and presently the people began to gather for the morning sermon.
-The Sunday-school children distributed themselves about the house and
-occupied pews with their parents, so as to be under supervision. Aunt
-Polly came, and Tom and Sid and Mary sat with her--Tom being placed
-next the aisle, in order that he might be as far away from the open
-window and the seductive outside summer scenes as possible. The crowd
-filed up the aisles: the aged and needy postmaster, who had seen better
-days; the mayor and his wife--for they had a mayor there, among other
-unnecessaries; the justice of the peace; the widow Douglass, fair,
-smart, and forty, a generous, good-hearted soul and well-to-do, her
-hill mansion the only palace in the town, and the most hospitable and
-much the most lavish in the matter of festivities that St. Petersburg
-could boast; the bent and venerable Major and Mrs. Ward; lawyer
-Riverson, the new notable from a distance; next the belle of the
-village, followed by a troop of lawn-clad and ribbon-decked young
-heart-breakers; then all the young clerks in town in a body--for they
-had stood in the vestibule sucking their cane-heads, a circling wall of
-oiled and simpering admirers, till the last girl had run their gantlet;
-and last of all came the Model Boy, Willie Mufferson, taking as heedful
-care of his mother as if she were cut glass. He always brought his
-mother to church, and was the pride of all the matrons. The boys all
-hated him, he was so good. And besides, he had been "thrown up to them"
-so much. His white handkerchief was hanging out of his pocket behind, as
-usual on Sundays--accidentally. Tom had no handkerchief, and he looked
-upon boys who had as snobs.
-
-The congregation being fully assembled, now, the bell rang once more,
-to warn laggards and stragglers, and then a solemn hush fell upon the
-church which was only broken by the tittering and whispering of the
-choir in the gallery. The choir always tittered and whispered all
-through service. There was once a church choir that was not ill-bred,
-but I have forgotten where it was, now. It was a great many years ago,
-and I can scarcely remember anything about it, but I think it was in
-some foreign country.
-
-The minister gave out the hymn, and read it through with a relish, in
-a peculiar style which was much admired in that part of the country.
-His voice began on a medium key and climbed steadily up till it reached
-a certain point, where it bore with strong emphasis upon the topmost
-word and then plunged down as if from a spring-board:
-
- Shall I be car-ri-ed toe the skies, on flow'ry BEDS of ease,
-
- Whilst others fight to win the prize, and sail thro' BLOODY seas?
-
-He was regarded as a wonderful reader. At church "sociables" he was
-always called upon to read poetry; and when he was through, the ladies
-would lift up their hands and let them fall helplessly in their laps,
-and "wall" their eyes, and shake their heads, as much as to say, "Words
-cannot express it; it is too beautiful, TOO beautiful for this mortal
-earth."
-
-After the hymn had been sung, the Rev. Mr. Sprague turned himself into
-a bulletin-board, and read off "notices" of meetings and societies and
-things till it seemed that the list would stretch out to the crack of
-doom--a queer custom which is still kept up in America, even in cities,
-away here in this age of abundant newspapers. Often, the less there is
-to justify a traditional custom, the harder it is to get rid of it.
-
-And now the minister prayed. A good, generous prayer it was, and went
-into details: it pleaded for the church, and the little children of the
-church; for the other churches of the village; for the village itself;
-for the county; for the State; for the State officers; for the United
-States; for the churches of the United States; for Congress; for the
-President; for the officers of the Government; for poor sailors, tossed
-by stormy seas; for the oppressed millions groaning under the heel of
-European monarchies and Oriental despotisms; for such as have the light
-and the good tidings, and yet have not eyes to see nor ears to hear
-withal; for the heathen in the far islands of the sea; and closed with
-a supplication that the words he was about to speak might find grace
-and favor, and be as seed sown in fertile ground, yielding in time a
-grateful harvest of good. Amen.
-
-There was a rustling of dresses, and the standing congregation sat
-down. The boy whose history this book relates did not enjoy the prayer,
-he only endured it--if he even did that much. He was restive all
-through it; he kept tally of the details of the prayer, unconsciously
---for he was not listening, but he knew the ground of old, and the
-clergyman's regular route over it--and when a little trifle of new
-matter was interlarded, his ear detected it and his whole nature
-resented it; he considered additions unfair, and scoundrelly. In the
-midst of the prayer a fly had lit on the back of the pew in front of
-him and tortured his spirit by calmly rubbing its hands together,
-embracing its head with its arms, and polishing it so vigorously that
-it seemed to almost part company with the body, and the slender thread
-of a neck was exposed to view; scraping its wings with its hind legs
-and smoothing them to its body as if they had been coat-tails; going
-through its whole toilet as tranquilly as if it knew it was perfectly
-safe. As indeed it was; for as sorely as Tom's hands itched to grab for
-it they did not dare--he believed his soul would be instantly destroyed
-if he did such a thing while the prayer was going on. But with the
-closing sentence his hand began to curve and steal forward; and the
-instant the "Amen" was out the fly was a prisoner of war. His aunt
-detected the act and made him let it go.
-
-The minister gave out his text and droned along monotonously through
-an argument that was so prosy that many a head by and by began to nod
---and yet it was an argument that dealt in limitless fire and brimstone
-and thinned the predestined elect down to a company so small as to be
-hardly worth the saving. Tom counted the pages of the sermon; after
-church he always knew how many pages there had been, but he seldom knew
-anything else about the discourse. However, this time he was really
-interested for a little while. The minister made a grand and moving
-picture of the assembling together of the world's hosts at the
-millennium when the lion and the lamb should lie down together and a
-little child should lead them. But the pathos, the lesson, the moral of
-the great spectacle were lost upon the boy; he only thought of the
-conspicuousness of the principal character before the on-looking
-nations; his face lit with the thought, and he said to himself that he
-wished he could be that child, if it was a tame lion.
-
-Now he lapsed into suffering again, as the dry argument was resumed.
-Presently he bethought him of a treasure he had and got it out. It was
-a large black beetle with formidable jaws--a "pinchbug," he called it.
-It was in a percussion-cap box. The first thing the beetle did was to
-take him by the finger. A natural fillip followed, the beetle went
-floundering into the aisle and lit on its back, and the hurt finger
-went into the boy's mouth. The beetle lay there working its helpless
-legs, unable to turn over. Tom eyed it, and longed for it; but it was
-safe out of his reach. Other people uninterested in the sermon found
-relief in the beetle, and they eyed it too. Presently a vagrant poodle
-dog came idling along, sad at heart, lazy with the summer softness and
-the quiet, weary of captivity, sighing for change. He spied the beetle;
-the drooping tail lifted and wagged. He surveyed the prize; walked
-around it; smelt at it from a safe distance; walked around it again;
-grew bolder, and took a closer smell; then lifted his lip and made a
-gingerly snatch at it, just missing it; made another, and another;
-began to enjoy the diversion; subsided to his stomach with the beetle
-between his paws, and continued his experiments; grew weary at last,
-and then indifferent and absent-minded. His head nodded, and little by
-little his chin descended and touched the enemy, who seized it. There
-was a sharp yelp, a flirt of the poodle's head, and the beetle fell a
-couple of yards away, and lit on its back once more. The neighboring
-spectators shook with a gentle inward joy, several faces went behind
-fans and handkerchiefs, and Tom was entirely happy. The dog looked
-foolish, and probably felt so; but there was resentment in his heart,
-too, and a craving for revenge. So he went to the beetle and began a
-wary attack on it again; jumping at it from every point of a circle,
-lighting with his fore-paws within an inch of the creature, making even
-closer snatches at it with his teeth, and jerking his head till his
-ears flapped again. But he grew tired once more, after a while; tried
-to amuse himself with a fly but found no relief; followed an ant
-around, with his nose close to the floor, and quickly wearied of that;
-yawned, sighed, forgot the beetle entirely, and sat down on it. Then
-there was a wild yelp of agony and the poodle went sailing up the
-aisle; the yelps continued, and so did the dog; he crossed the house in
-front of the altar; he flew down the other aisle; he crossed before the
-doors; he clamored up the home-stretch; his anguish grew with his
-progress, till presently he was but a woolly comet moving in its orbit
-with the gleam and the speed of light. At last the frantic sufferer
-sheered from its course, and sprang into its master's lap; he flung it
-out of the window, and the voice of distress quickly thinned away and
-died in the distance.
-
-By this time the whole church was red-faced and suffocating with
-suppressed laughter, and the sermon had come to a dead standstill. The
-discourse was resumed presently, but it went lame and halting, all
-possibility of impressiveness being at an end; for even the gravest
-sentiments were constantly being received with a smothered burst of
-unholy mirth, under cover of some remote pew-back, as if the poor
-parson had said a rarely facetious thing. It was a genuine relief to
-the whole congregation when the ordeal was over and the benediction
-pronounced.
-
-Tom Sawyer went home quite cheerful, thinking to himself that there
-was some satisfaction about divine service when there was a bit of
-variety in it. He had but one marring thought; he was willing that the
-dog should play with his pinchbug, but he did not think it was upright
-in him to carry it off.
-
-
-
-CHAPTER VI
-
-MONDAY morning found Tom Sawyer miserable. Monday morning always found
-him so--because it began another week's slow suffering in school. He
-generally began that day with wishing he had had no intervening
-holiday, it made the going into captivity and fetters again so much
-more odious.
-
-Tom lay thinking. Presently it occurred to him that he wished he was
-sick; then he could stay home from school. Here was a vague
-possibility. He canvassed his system. No ailment was found, and he
-investigated again. This time he thought he could detect colicky
-symptoms, and he began to encourage them with considerable hope. But
-they soon grew feeble, and presently died wholly away. He reflected
-further. Suddenly he discovered something. One of his upper front teeth
-was loose. This was lucky; he was about to begin to groan, as a
-"starter," as he called it, when it occurred to him that if he came
-into court with that argument, his aunt would pull it out, and that
-would hurt. So he thought he would hold the tooth in reserve for the
-present, and seek further. Nothing offered for some little time, and
-then he remembered hearing the doctor tell about a certain thing that
-laid up a patient for two or three weeks and threatened to make him
-lose a finger. So the boy eagerly drew his sore toe from under the
-sheet and held it up for inspection. But now he did not know the
-necessary symptoms. However, it seemed well worth while to chance it,
-so he fell to groaning with considerable spirit.
-
-But Sid slept on unconscious.
-
-Tom groaned louder, and fancied that he began to feel pain in the toe.
-
-No result from Sid.
-
-Tom was panting with his exertions by this time. He took a rest and
-then swelled himself up and fetched a succession of admirable groans.
-
-Sid snored on.
-
-Tom was aggravated. He said, "Sid, Sid!" and shook him. This course
-worked well, and Tom began to groan again. Sid yawned, stretched, then
-brought himself up on his elbow with a snort, and began to stare at
-Tom. Tom went on groaning. Sid said:
-
-"Tom! Say, Tom!" [No response.] "Here, Tom! TOM! What is the matter,
-Tom?" And he shook him and looked in his face anxiously.
-
-Tom moaned out:
-
-"Oh, don't, Sid. Don't joggle me."
-
-"Why, what's the matter, Tom? I must call auntie."
-
-"No--never mind. It'll be over by and by, maybe. Don't call anybody."
-
-"But I must! DON'T groan so, Tom, it's awful. How long you been this
-way?"
-
-"Hours. Ouch! Oh, don't stir so, Sid, you'll kill me."
-
-"Tom, why didn't you wake me sooner? Oh, Tom, DON'T! It makes my
-flesh crawl to hear you. Tom, what is the matter?"
-
-"I forgive you everything, Sid. [Groan.] Everything you've ever done
-to me. When I'm gone--"
-
-"Oh, Tom, you ain't dying, are you? Don't, Tom--oh, don't. Maybe--"
-
-"I forgive everybody, Sid. [Groan.] Tell 'em so, Sid. And Sid, you
-give my window-sash and my cat with one eye to that new girl that's
-come to town, and tell her--"
-
-But Sid had snatched his clothes and gone. Tom was suffering in
-reality, now, so handsomely was his imagination working, and so his
-groans had gathered quite a genuine tone.
-
-Sid flew down-stairs and said:
-
-"Oh, Aunt Polly, come! Tom's dying!"
-
-"Dying!"
-
-"Yes'm. Don't wait--come quick!"
-
-"Rubbage! I don't believe it!"
-
-But she fled up-stairs, nevertheless, with Sid and Mary at her heels.
-And her face grew white, too, and her lip trembled. When she reached
-the bedside she gasped out:
-
-"You, Tom! Tom, what's the matter with you?"
-
-"Oh, auntie, I'm--"
-
-"What's the matter with you--what is the matter with you, child?"
-
-"Oh, auntie, my sore toe's mortified!"
-
-The old lady sank down into a chair and laughed a little, then cried a
-little, then did both together. This restored her and she said:
-
-"Tom, what a turn you did give me. Now you shut up that nonsense and
-climb out of this."
-
-The groans ceased and the pain vanished from the toe. The boy felt a
-little foolish, and he said:
-
-"Aunt Polly, it SEEMED mortified, and it hurt so I never minded my
-tooth at all."
-
-"Your tooth, indeed! What's the matter with your tooth?"
-
-"One of them's loose, and it aches perfectly awful."
-
-"There, there, now, don't begin that groaning again. Open your mouth.
-Well--your tooth IS loose, but you're not going to die about that.
-Mary, get me a silk thread, and a chunk of fire out of the kitchen."
-
-Tom said:
-
-"Oh, please, auntie, don't pull it out. It don't hurt any more. I wish
-I may never stir if it does. Please don't, auntie. I don't want to stay
-home from school."
-
-"Oh, you don't, don't you? So all this row was because you thought
-you'd get to stay home from school and go a-fishing? Tom, Tom, I love
-you so, and you seem to try every way you can to break my old heart
-with your outrageousness." By this time the dental instruments were
-ready. The old lady made one end of the silk thread fast to Tom's tooth
-with a loop and tied the other to the bedpost. Then she seized the
-chunk of fire and suddenly thrust it almost into the boy's face. The
-tooth hung dangling by the bedpost, now.
-
-But all trials bring their compensations. As Tom wended to school
-after breakfast, he was the envy of every boy he met because the gap in
-his upper row of teeth enabled him to expectorate in a new and
-admirable way. He gathered quite a following of lads interested in the
-exhibition; and one that had cut his finger and had been a centre of
-fascination and homage up to this time, now found himself suddenly
-without an adherent, and shorn of his glory. His heart was heavy, and
-he said with a disdain which he did not feel that it wasn't anything to
-spit like Tom Sawyer; but another boy said, "Sour grapes!" and he
-wandered away a dismantled hero.
-
-Shortly Tom came upon the juvenile pariah of the village, Huckleberry
-Finn, son of the town drunkard. Huckleberry was cordially hated and
-dreaded by all the mothers of the town, because he was idle and lawless
-and vulgar and bad--and because all their children admired him so, and
-delighted in his forbidden society, and wished they dared to be like
-him. Tom was like the rest of the respectable boys, in that he envied
-Huckleberry his gaudy outcast condition, and was under strict orders
-not to play with him. So he played with him every time he got a chance.
-Huckleberry was always dressed in the cast-off clothes of full-grown
-men, and they were in perennial bloom and fluttering with rags. His hat
-was a vast ruin with a wide crescent lopped out of its brim; his coat,
-when he wore one, hung nearly to his heels and had the rearward buttons
-far down the back; but one suspender supported his trousers; the seat
-of the trousers bagged low and contained nothing, the fringed legs
-dragged in the dirt when not rolled up.
-
-Huckleberry came and went, at his own free will. He slept on doorsteps
-in fine weather and in empty hogsheads in wet; he did not have to go to
-school or to church, or call any being master or obey anybody; he could
-go fishing or swimming when and where he chose, and stay as long as it
-suited him; nobody forbade him to fight; he could sit up as late as he
-pleased; he was always the first boy that went barefoot in the spring
-and the last to resume leather in the fall; he never had to wash, nor
-put on clean clothes; he could swear wonderfully. In a word, everything
-that goes to make life precious that boy had. So thought every
-harassed, hampered, respectable boy in St. Petersburg.
-
-Tom hailed the romantic outcast:
-
-"Hello, Huckleberry!"
-
-"Hello yourself, and see how you like it."
-
-"What's that you got?"
-
-"Dead cat."
-
-"Lemme see him, Huck. My, he's pretty stiff. Where'd you get him?"
-
-"Bought him off'n a boy."
-
-"What did you give?"
-
-"I give a blue ticket and a bladder that I got at the slaughter-house."
-
-"Where'd you get the blue ticket?"
-
-"Bought it off'n Ben Rogers two weeks ago for a hoop-stick."
-
-"Say--what is dead cats good for, Huck?"
-
-"Good for? Cure warts with."
-
-"No! Is that so? I know something that's better."
-
-"I bet you don't. What is it?"
-
-"Why, spunk-water."
-
-"Spunk-water! I wouldn't give a dern for spunk-water."
-
-"You wouldn't, wouldn't you? D'you ever try it?"
-
-"No, I hain't. But Bob Tanner did."
-
-"Who told you so!"
-
-"Why, he told Jeff Thatcher, and Jeff told Johnny Baker, and Johnny
-told Jim Hollis, and Jim told Ben Rogers, and Ben told a nigger, and
-the nigger told me. There now!"
-
-"Well, what of it? They'll all lie. Leastways all but the nigger. I
-don't know HIM. But I never see a nigger that WOULDN'T lie. Shucks! Now
-you tell me how Bob Tanner done it, Huck."
-
-"Why, he took and dipped his hand in a rotten stump where the
-rain-water was."
-
-"In the daytime?"
-
-"Certainly."
-
-"With his face to the stump?"
-
-"Yes. Least I reckon so."
-
-"Did he say anything?"
-
-"I don't reckon he did. I don't know."
-
-"Aha! Talk about trying to cure warts with spunk-water such a blame
-fool way as that! Why, that ain't a-going to do any good. You got to go
-all by yourself, to the middle of the woods, where you know there's a
-spunk-water stump, and just as it's midnight you back up against the
-stump and jam your hand in and say:
-
- 'Barley-corn, barley-corn, injun-meal shorts,
- Spunk-water, spunk-water, swaller these warts,'
-
-and then walk away quick, eleven steps, with your eyes shut, and then
-turn around three times and walk home without speaking to anybody.
-Because if you speak the charm's busted."
-
-"Well, that sounds like a good way; but that ain't the way Bob Tanner
-done."
-
-"No, sir, you can bet he didn't, becuz he's the wartiest boy in this
-town; and he wouldn't have a wart on him if he'd knowed how to work
-spunk-water. I've took off thousands of warts off of my hands that way,
-Huck. I play with frogs so much that I've always got considerable many
-warts. Sometimes I take 'em off with a bean."
-
-"Yes, bean's good. I've done that."
-
-"Have you? What's your way?"
-
-"You take and split the bean, and cut the wart so as to get some
-blood, and then you put the blood on one piece of the bean and take and
-dig a hole and bury it 'bout midnight at the crossroads in the dark of
-the moon, and then you burn up the rest of the bean. You see that piece
-that's got the blood on it will keep drawing and drawing, trying to
-fetch the other piece to it, and so that helps the blood to draw the
-wart, and pretty soon off she comes."
-
-"Yes, that's it, Huck--that's it; though when you're burying it if you
-say 'Down bean; off wart; come no more to bother me!' it's better.
-That's the way Joe Harper does, and he's been nearly to Coonville and
-most everywheres. But say--how do you cure 'em with dead cats?"
-
-"Why, you take your cat and go and get in the graveyard 'long about
-midnight when somebody that was wicked has been buried; and when it's
-midnight a devil will come, or maybe two or three, but you can't see
-'em, you can only hear something like the wind, or maybe hear 'em talk;
-and when they're taking that feller away, you heave your cat after 'em
-and say, 'Devil follow corpse, cat follow devil, warts follow cat, I'm
-done with ye!' That'll fetch ANY wart."
-
-"Sounds right. D'you ever try it, Huck?"
-
-"No, but old Mother Hopkins told me."
-
-"Well, I reckon it's so, then. Becuz they say she's a witch."
-
-"Say! Why, Tom, I KNOW she is. She witched pap. Pap says so his own
-self. He come along one day, and he see she was a-witching him, so he
-took up a rock, and if she hadn't dodged, he'd a got her. Well, that
-very night he rolled off'n a shed wher' he was a layin drunk, and broke
-his arm."
-
-"Why, that's awful. How did he know she was a-witching him?"
-
-"Lord, pap can tell, easy. Pap says when they keep looking at you
-right stiddy, they're a-witching you. Specially if they mumble. Becuz
-when they mumble they're saying the Lord's Prayer backards."
-
-"Say, Hucky, when you going to try the cat?"
-
-"To-night. I reckon they'll come after old Hoss Williams to-night."
-
-"But they buried him Saturday. Didn't they get him Saturday night?"
-
-"Why, how you talk! How could their charms work till midnight?--and
-THEN it's Sunday. Devils don't slosh around much of a Sunday, I don't
-reckon."
-
-"I never thought of that. That's so. Lemme go with you?"
-
-"Of course--if you ain't afeard."
-
-"Afeard! 'Tain't likely. Will you meow?"
-
-"Yes--and you meow back, if you get a chance. Last time, you kep' me
-a-meowing around till old Hays went to throwing rocks at me and says
-'Dern that cat!' and so I hove a brick through his window--but don't
-you tell."
-
-"I won't. I couldn't meow that night, becuz auntie was watching me,
-but I'll meow this time. Say--what's that?"
-
-"Nothing but a tick."
-
-"Where'd you get him?"
-
-"Out in the woods."
-
-"What'll you take for him?"
-
-"I don't know. I don't want to sell him."
-
-"All right. It's a mighty small tick, anyway."
-
-"Oh, anybody can run a tick down that don't belong to them. I'm
-satisfied with it. It's a good enough tick for me."
-
-"Sho, there's ticks a plenty. I could have a thousand of 'em if I
-wanted to."
-
-"Well, why don't you? Becuz you know mighty well you can't. This is a
-pretty early tick, I reckon. It's the first one I've seen this year."
-
-"Say, Huck--I'll give you my tooth for him."
-
-"Less see it."
-
-Tom got out a bit of paper and carefully unrolled it. Huckleberry
-viewed it wistfully. The temptation was very strong. At last he said:
-
-"Is it genuwyne?"
-
-Tom lifted his lip and showed the vacancy.
-
-"Well, all right," said Huckleberry, "it's a trade."
-
-Tom enclosed the tick in the percussion-cap box that had lately been
-the pinchbug's prison, and the boys separated, each feeling wealthier
-than before.
-
-When Tom reached the little isolated frame schoolhouse, he strode in
-briskly, with the manner of one who had come with all honest speed.
-He hung his hat on a peg and flung himself into his seat with
-business-like alacrity. The master, throned on high in his great
-splint-bottom arm-chair, was dozing, lulled by the drowsy hum of study.
-The interruption roused him.
-
-"Thomas Sawyer!"
-
-Tom knew that when his name was pronounced in full, it meant trouble.
-
-"Sir!"
-
-"Come up here. Now, sir, why are you late again, as usual?"
-
-Tom was about to take refuge in a lie, when he saw two long tails of
-yellow hair hanging down a back that he recognized by the electric
-sympathy of love; and by that form was THE ONLY VACANT PLACE on the
-girls' side of the schoolhouse. He instantly said:
-
-"I STOPPED TO TALK WITH HUCKLEBERRY FINN!"
-
-The master's pulse stood still, and he stared helplessly. The buzz of
-study ceased. The pupils wondered if this foolhardy boy had lost his
-mind. The master said:
-
-"You--you did what?"
-
-"Stopped to talk with Huckleberry Finn."
-
-There was no mistaking the words.
-
-"Thomas Sawyer, this is the most astounding confession I have ever
-listened to. No mere ferule will answer for this offence. Take off your
-jacket."
-
-The master's arm performed until it was tired and the stock of
-switches notably diminished. Then the order followed:
-
-"Now, sir, go and sit with the girls! And let this be a warning to you."
-
-The titter that rippled around the room appeared to abash the boy, but
-in reality that result was caused rather more by his worshipful awe of
-his unknown idol and the dread pleasure that lay in his high good
-fortune. He sat down upon the end of the pine bench and the girl
-hitched herself away from him with a toss of her head. Nudges and winks
-and whispers traversed the room, but Tom sat still, with his arms upon
-the long, low desk before him, and seemed to study his book.
-
-By and by attention ceased from him, and the accustomed school murmur
-rose upon the dull air once more. Presently the boy began to steal
-furtive glances at the girl. She observed it, "made a mouth" at him and
-gave him the back of her head for the space of a minute. When she
-cautiously faced around again, a peach lay before her. She thrust it
-away. Tom gently put it back. She thrust it away again, but with less
-animosity. Tom patiently returned it to its place. Then she let it
-remain. Tom scrawled on his slate, "Please take it--I got more." The
-girl glanced at the words, but made no sign. Now the boy began to draw
-something on the slate, hiding his work with his left hand. For a time
-the girl refused to notice; but her human curiosity presently began to
-manifest itself by hardly perceptible signs. The boy worked on,
-apparently unconscious. The girl made a sort of noncommittal attempt to
-see, but the boy did not betray that he was aware of it. At last she
-gave in and hesitatingly whispered:
-
-"Let me see it."
-
-Tom partly uncovered a dismal caricature of a house with two gable
-ends to it and a corkscrew of smoke issuing from the chimney. Then the
-girl's interest began to fasten itself upon the work and she forgot
-everything else. When it was finished, she gazed a moment, then
-whispered:
-
-"It's nice--make a man."
-
-The artist erected a man in the front yard, that resembled a derrick.
-He could have stepped over the house; but the girl was not
-hypercritical; she was satisfied with the monster, and whispered:
-
-"It's a beautiful man--now make me coming along."
-
-Tom drew an hour-glass with a full moon and straw limbs to it and
-armed the spreading fingers with a portentous fan. The girl said:
-
-"It's ever so nice--I wish I could draw."
-
-"It's easy," whispered Tom, "I'll learn you."
-
-"Oh, will you? When?"
-
-"At noon. Do you go home to dinner?"
-
-"I'll stay if you will."
-
-"Good--that's a whack. What's your name?"
-
-"Becky Thatcher. What's yours? Oh, I know. It's Thomas Sawyer."
-
-"That's the name they lick me by. I'm Tom when I'm good. You call me
-Tom, will you?"
-
-"Yes."
-
-Now Tom began to scrawl something on the slate, hiding the words from
-the girl. But she was not backward this time. She begged to see. Tom
-said:
-
-"Oh, it ain't anything."
-
-"Yes it is."
-
-"No it ain't. You don't want to see."
-
-"Yes I do, indeed I do. Please let me."
-
-"You'll tell."
-
-"No I won't--deed and deed and double deed won't."
-
-"You won't tell anybody at all? Ever, as long as you live?"
-
-"No, I won't ever tell ANYbody. Now let me."
-
-"Oh, YOU don't want to see!"
-
-"Now that you treat me so, I WILL see." And she put her small hand
-upon his and a little scuffle ensued, Tom pretending to resist in
-earnest but letting his hand slip by degrees till these words were
-revealed: "I LOVE YOU."
-
-"Oh, you bad thing!" And she hit his hand a smart rap, but reddened
-and looked pleased, nevertheless.
-
-Just at this juncture the boy felt a slow, fateful grip closing on his
-ear, and a steady lifting impulse. In that wise he was borne across the
-house and deposited in his own seat, under a peppering fire of giggles
-from the whole school. Then the master stood over him during a few
-awful moments, and finally moved away to his throne without saying a
-word. But although Tom's ear tingled, his heart was jubilant.
-
-As the school quieted down Tom made an honest effort to study, but the
-turmoil within him was too great. In turn he took his place in the
-reading class and made a botch of it; then in the geography class and
-turned lakes into mountains, mountains into rivers, and rivers into
-continents, till chaos was come again; then in the spelling class, and
-got "turned down," by a succession of mere baby words, till he brought
-up at the foot and yielded up the pewter medal which he had worn with
-ostentation for months.
-
-
-
-CHAPTER VII
-
-THE harder Tom tried to fasten his mind on his book, the more his
-ideas wandered. So at last, with a sigh and a yawn, he gave it up. It
-seemed to him that the noon recess would never come. The air was
-utterly dead. There was not a breath stirring. It was the sleepiest of
-sleepy days. The drowsing murmur of the five and twenty studying
-scholars soothed the soul like the spell that is in the murmur of bees.
-Away off in the flaming sunshine, Cardiff Hill lifted its soft green
-sides through a shimmering veil of heat, tinted with the purple of
-distance; a few birds floated on lazy wing high in the air; no other
-living thing was visible but some cows, and they were asleep. Tom's
-heart ached to be free, or else to have something of interest to do to
-pass the dreary time. His hand wandered into his pocket and his face
-lit up with a glow of gratitude that was prayer, though he did not know
-it. Then furtively the percussion-cap box came out. He released the
-tick and put him on the long flat desk. The creature probably glowed
-with a gratitude that amounted to prayer, too, at this moment, but it
-was premature: for when he started thankfully to travel off, Tom turned
-him aside with a pin and made him take a new direction.
-
-Tom's bosom friend sat next him, suffering just as Tom had been, and
-now he was deeply and gratefully interested in this entertainment in an
-instant. This bosom friend was Joe Harper. The two boys were sworn
-friends all the week, and embattled enemies on Saturdays. Joe took a
-pin out of his lapel and began to assist in exercising the prisoner.
-The sport grew in interest momently. Soon Tom said that they were
-interfering with each other, and neither getting the fullest benefit of
-the tick. So he put Joe's slate on the desk and drew a line down the
-middle of it from top to bottom.
-
-"Now," said he, "as long as he is on your side you can stir him up and
-I'll let him alone; but if you let him get away and get on my side,
-you're to leave him alone as long as I can keep him from crossing over."
-
-"All right, go ahead; start him up."
-
-The tick escaped from Tom, presently, and crossed the equator. Joe
-harassed him awhile, and then he got away and crossed back again. This
-change of base occurred often. While one boy was worrying the tick with
-absorbing interest, the other would look on with interest as strong,
-the two heads bowed together over the slate, and the two souls dead to
-all things else. At last luck seemed to settle and abide with Joe. The
-tick tried this, that, and the other course, and got as excited and as
-anxious as the boys themselves, but time and again just as he would
-have victory in his very grasp, so to speak, and Tom's fingers would be
-twitching to begin, Joe's pin would deftly head him off, and keep
-possession. At last Tom could stand it no longer. The temptation was
-too strong. So he reached out and lent a hand with his pin. Joe was
-angry in a moment. Said he:
-
-"Tom, you let him alone."
-
-"I only just want to stir him up a little, Joe."
-
-"No, sir, it ain't fair; you just let him alone."
-
-"Blame it, I ain't going to stir him much."
-
-"Let him alone, I tell you."
-
-"I won't!"
-
-"You shall--he's on my side of the line."
-
-"Look here, Joe Harper, whose is that tick?"
-
-"I don't care whose tick he is--he's on my side of the line, and you
-sha'n't touch him."
-
-"Well, I'll just bet I will, though. He's my tick and I'll do what I
-blame please with him, or die!"
-
-A tremendous whack came down on Tom's shoulders, and its duplicate on
-Joe's; and for the space of two minutes the dust continued to fly from
-the two jackets and the whole school to enjoy it. The boys had been too
-absorbed to notice the hush that had stolen upon the school awhile
-before when the master came tiptoeing down the room and stood over
-them. He had contemplated a good part of the performance before he
-contributed his bit of variety to it.
-
-When school broke up at noon, Tom flew to Becky Thatcher, and
-whispered in her ear:
-
-"Put on your bonnet and let on you're going home; and when you get to
-the corner, give the rest of 'em the slip, and turn down through the
-lane and come back. I'll go the other way and come it over 'em the same
-way."
-
-So the one went off with one group of scholars, and the other with
-another. In a little while the two met at the bottom of the lane, and
-when they reached the school they had it all to themselves. Then they
-sat together, with a slate before them, and Tom gave Becky the pencil
-and held her hand in his, guiding it, and so created another surprising
-house. When the interest in art began to wane, the two fell to talking.
-Tom was swimming in bliss. He said:
-
-"Do you love rats?"
-
-"No! I hate them!"
-
-"Well, I do, too--LIVE ones. But I mean dead ones, to swing round your
-head with a string."
-
-"No, I don't care for rats much, anyway. What I like is chewing-gum."
-
-"Oh, I should say so! I wish I had some now."
-
-"Do you? I've got some. I'll let you chew it awhile, but you must give
-it back to me."
-
-That was agreeable, so they chewed it turn about, and dangled their
-legs against the bench in excess of contentment.
-
-"Was you ever at a circus?" said Tom.
-
-"Yes, and my pa's going to take me again some time, if I'm good."
-
-"I been to the circus three or four times--lots of times. Church ain't
-shucks to a circus. There's things going on at a circus all the time.
-I'm going to be a clown in a circus when I grow up."
-
-"Oh, are you! That will be nice. They're so lovely, all spotted up."
-
-"Yes, that's so. And they get slathers of money--most a dollar a day,
-Ben Rogers says. Say, Becky, was you ever engaged?"
-
-"What's that?"
-
-"Why, engaged to be married."
-
-"No."
-
-"Would you like to?"
-
-"I reckon so. I don't know. What is it like?"
-
-"Like? Why it ain't like anything. You only just tell a boy you won't
-ever have anybody but him, ever ever ever, and then you kiss and that's
-all. Anybody can do it."
-
-"Kiss? What do you kiss for?"
-
-"Why, that, you know, is to--well, they always do that."
-
-"Everybody?"
-
-"Why, yes, everybody that's in love with each other. Do you remember
-what I wrote on the slate?"
-
-"Ye--yes."
-
-"What was it?"
-
-"I sha'n't tell you."
-
-"Shall I tell YOU?"
-
-"Ye--yes--but some other time."
-
-"No, now."
-
-"No, not now--to-morrow."
-
-"Oh, no, NOW. Please, Becky--I'll whisper it, I'll whisper it ever so
-easy."
-
-Becky hesitating, Tom took silence for consent, and passed his arm
-about her waist and whispered the tale ever so softly, with his mouth
-close to her ear. And then he added:
-
-"Now you whisper it to me--just the same."
-
-She resisted, for a while, and then said:
-
-"You turn your face away so you can't see, and then I will. But you
-mustn't ever tell anybody--WILL you, Tom? Now you won't, WILL you?"
-
-"No, indeed, indeed I won't. Now, Becky."
-
-He turned his face away. She bent timidly around till her breath
-stirred his curls and whispered, "I--love--you!"
-
-Then she sprang away and ran around and around the desks and benches,
-with Tom after her, and took refuge in a corner at last, with her
-little white apron to her face. Tom clasped her about her neck and
-pleaded:
-
-"Now, Becky, it's all done--all over but the kiss. Don't you be afraid
-of that--it ain't anything at all. Please, Becky." And he tugged at her
-apron and the hands.
-
-By and by she gave up, and let her hands drop; her face, all glowing
-with the struggle, came up and submitted. Tom kissed the red lips and
-said:
-
-"Now it's all done, Becky. And always after this, you know, you ain't
-ever to love anybody but me, and you ain't ever to marry anybody but
-me, ever never and forever. Will you?"
-
-"No, I'll never love anybody but you, Tom, and I'll never marry
-anybody but you--and you ain't to ever marry anybody but me, either."
-
-"Certainly. Of course. That's PART of it. And always coming to school
-or when we're going home, you're to walk with me, when there ain't
-anybody looking--and you choose me and I choose you at parties, because
-that's the way you do when you're engaged."
-
-"It's so nice. I never heard of it before."
-
-"Oh, it's ever so gay! Why, me and Amy Lawrence--"
-
-The big eyes told Tom his blunder and he stopped, confused.
-
-"Oh, Tom! Then I ain't the first you've ever been engaged to!"
-
-The child began to cry. Tom said:
-
-"Oh, don't cry, Becky, I don't care for her any more."
-
-"Yes, you do, Tom--you know you do."
-
-Tom tried to put his arm about her neck, but she pushed him away and
-turned her face to the wall, and went on crying. Tom tried again, with
-soothing words in his mouth, and was repulsed again. Then his pride was
-up, and he strode away and went outside. He stood about, restless and
-uneasy, for a while, glancing at the door, every now and then, hoping
-she would repent and come to find him. But she did not. Then he began
-to feel badly and fear that he was in the wrong. It was a hard struggle
-with him to make new advances, now, but he nerved himself to it and
-entered. She was still standing back there in the corner, sobbing, with
-her face to the wall. Tom's heart smote him. He went to her and stood a
-moment, not knowing exactly how to proceed. Then he said hesitatingly:
-
-"Becky, I--I don't care for anybody but you."
-
-No reply--but sobs.
-
-"Becky"--pleadingly. "Becky, won't you say something?"
-
-More sobs.
-
-Tom got out his chiefest jewel, a brass knob from the top of an
-andiron, and passed it around her so that she could see it, and said:
-
-"Please, Becky, won't you take it?"
-
-She struck it to the floor. Then Tom marched out of the house and over
-the hills and far away, to return to school no more that day. Presently
-Becky began to suspect. She ran to the door; he was not in sight; she
-flew around to the play-yard; he was not there. Then she called:
-
-"Tom! Come back, Tom!"
-
-She listened intently, but there was no answer. She had no companions
-but silence and loneliness. So she sat down to cry again and upbraid
-herself; and by this time the scholars began to gather again, and she
-had to hide her griefs and still her broken heart and take up the cross
-of a long, dreary, aching afternoon, with none among the strangers
-about her to exchange sorrows with.
-
-
-
-CHAPTER VIII
-
-TOM dodged hither and thither through lanes until he was well out of
-the track of returning scholars, and then fell into a moody jog. He
-crossed a small "branch" two or three times, because of a prevailing
-juvenile superstition that to cross water baffled pursuit. Half an hour
-later he was disappearing behind the Douglas mansion on the summit of
-Cardiff Hill, and the schoolhouse was hardly distinguishable away off
-in the valley behind him. He entered a dense wood, picked his pathless
-way to the centre of it, and sat down on a mossy spot under a spreading
-oak. There was not even a zephyr stirring; the dead noonday heat had
-even stilled the songs of the birds; nature lay in a trance that was
-broken by no sound but the occasional far-off hammering of a
-woodpecker, and this seemed to render the pervading silence and sense
-of loneliness the more profound. The boy's soul was steeped in
-melancholy; his feelings were in happy accord with his surroundings. He
-sat long with his elbows on his knees and his chin in his hands,
-meditating. It seemed to him that life was but a trouble, at best, and
-he more than half envied Jimmy Hodges, so lately released; it must be
-very peaceful, he thought, to lie and slumber and dream forever and
-ever, with the wind whispering through the trees and caressing the
-grass and the flowers over the grave, and nothing to bother and grieve
-about, ever any more. If he only had a clean Sunday-school record he
-could be willing to go, and be done with it all. Now as to this girl.
-What had he done? Nothing. He had meant the best in the world, and been
-treated like a dog--like a very dog. She would be sorry some day--maybe
-when it was too late. Ah, if he could only die TEMPORARILY!
-
-But the elastic heart of youth cannot be compressed into one
-constrained shape long at a time. Tom presently began to drift
-insensibly back into the concerns of this life again. What if he turned
-his back, now, and disappeared mysteriously? What if he went away--ever
-so far away, into unknown countries beyond the seas--and never came
-back any more! How would she feel then! The idea of being a clown
-recurred to him now, only to fill him with disgust. For frivolity and
-jokes and spotted tights were an offense, when they intruded themselves
-upon a spirit that was exalted into the vague august realm of the
-romantic. No, he would be a soldier, and return after long years, all
-war-worn and illustrious. No--better still, he would join the Indians,
-and hunt buffaloes and go on the warpath in the mountain ranges and the
-trackless great plains of the Far West, and away in the future come
-back a great chief, bristling with feathers, hideous with paint, and
-prance into Sunday-school, some drowsy summer morning, with a
-bloodcurdling war-whoop, and sear the eyeballs of all his companions
-with unappeasable envy. But no, there was something gaudier even than
-this. He would be a pirate! That was it! NOW his future lay plain
-before him, and glowing with unimaginable splendor. How his name would
-fill the world, and make people shudder! How gloriously he would go
-plowing the dancing seas, in his long, low, black-hulled racer, the
-Spirit of the Storm, with his grisly flag flying at the fore! And at
-the zenith of his fame, how he would suddenly appear at the old village
-and stalk into church, brown and weather-beaten, in his black velvet
-doublet and trunks, his great jack-boots, his crimson sash, his belt
-bristling with horse-pistols, his crime-rusted cutlass at his side, his
-slouch hat with waving plumes, his black flag unfurled, with the skull
-and crossbones on it, and hear with swelling ecstasy the whisperings,
-"It's Tom Sawyer the Pirate!--the Black Avenger of the Spanish Main!"
-
-Yes, it was settled; his career was determined. He would run away from
-home and enter upon it. He would start the very next morning. Therefore
-he must now begin to get ready. He would collect his resources
-together. He went to a rotten log near at hand and began to dig under
-one end of it with his Barlow knife. He soon struck wood that sounded
-hollow. He put his hand there and uttered this incantation impressively:
-
-"What hasn't come here, come! What's here, stay here!"
-
-Then he scraped away the dirt, and exposed a pine shingle. He took it
-up and disclosed a shapely little treasure-house whose bottom and sides
-were of shingles. In it lay a marble. Tom's astonishment was boundless!
-He scratched his head with a perplexed air, and said:
-
-"Well, that beats anything!"
-
-Then he tossed the marble away pettishly, and stood cogitating. The
-truth was, that a superstition of his had failed, here, which he and
-all his comrades had always looked upon as infallible. If you buried a
-marble with certain necessary incantations, and left it alone a
-fortnight, and then opened the place with the incantation he had just
-used, you would find that all the marbles you had ever lost had
-gathered themselves together there, meantime, no matter how widely they
-had been separated. But now, this thing had actually and unquestionably
-failed. Tom's whole structure of faith was shaken to its foundations.
-He had many a time heard of this thing succeeding but never of its
-failing before. It did not occur to him that he had tried it several
-times before, himself, but could never find the hiding-places
-afterward. He puzzled over the matter some time, and finally decided
-that some witch had interfered and broken the charm. He thought he
-would satisfy himself on that point; so he searched around till he
-found a small sandy spot with a little funnel-shaped depression in it.
-He laid himself down and put his mouth close to this depression and
-called--
-
-"Doodle-bug, doodle-bug, tell me what I want to know! Doodle-bug,
-doodle-bug, tell me what I want to know!"
-
-The sand began to work, and presently a small black bug appeared for a
-second and then darted under again in a fright.
-
-"He dasn't tell! So it WAS a witch that done it. I just knowed it."
-
-He well knew the futility of trying to contend against witches, so he
-gave up discouraged. But it occurred to him that he might as well have
-the marble he had just thrown away, and therefore he went and made a
-patient search for it. But he could not find it. Now he went back to
-his treasure-house and carefully placed himself just as he had been
-standing when he tossed the marble away; then he took another marble
-from his pocket and tossed it in the same way, saying:
-
-"Brother, go find your brother!"
-
-He watched where it stopped, and went there and looked. But it must
-have fallen short or gone too far; so he tried twice more. The last
-repetition was successful. The two marbles lay within a foot of each
-other.
-
-Just here the blast of a toy tin trumpet came faintly down the green
-aisles of the forest. Tom flung off his jacket and trousers, turned a
-suspender into a belt, raked away some brush behind the rotten log,
-disclosing a rude bow and arrow, a lath sword and a tin trumpet, and in
-a moment had seized these things and bounded away, barelegged, with
-fluttering shirt. He presently halted under a great elm, blew an
-answering blast, and then began to tiptoe and look warily out, this way
-and that. He said cautiously--to an imaginary company:
-
-"Hold, my merry men! Keep hid till I blow."
-
-Now appeared Joe Harper, as airily clad and elaborately armed as Tom.
-Tom called:
-
-"Hold! Who comes here into Sherwood Forest without my pass?"
-
-"Guy of Guisborne wants no man's pass. Who art thou that--that--"
-
-"Dares to hold such language," said Tom, prompting--for they talked
-"by the book," from memory.
-
-"Who art thou that dares to hold such language?"
-
-"I, indeed! I am Robin Hood, as thy caitiff carcase soon shall know."
-
-"Then art thou indeed that famous outlaw? Right gladly will I dispute
-with thee the passes of the merry wood. Have at thee!"
-
-They took their lath swords, dumped their other traps on the ground,
-struck a fencing attitude, foot to foot, and began a grave, careful
-combat, "two up and two down." Presently Tom said:
-
-"Now, if you've got the hang, go it lively!"
-
-So they "went it lively," panting and perspiring with the work. By and
-by Tom shouted:
-
-"Fall! fall! Why don't you fall?"
-
-"I sha'n't! Why don't you fall yourself? You're getting the worst of
-it."
-
-"Why, that ain't anything. I can't fall; that ain't the way it is in
-the book. The book says, 'Then with one back-handed stroke he slew poor
-Guy of Guisborne.' You're to turn around and let me hit you in the
-back."
-
-There was no getting around the authorities, so Joe turned, received
-the whack and fell.
-
-"Now," said Joe, getting up, "you got to let me kill YOU. That's fair."
-
-"Why, I can't do that, it ain't in the book."
-
-"Well, it's blamed mean--that's all."
-
-"Well, say, Joe, you can be Friar Tuck or Much the miller's son, and
-lam me with a quarter-staff; or I'll be the Sheriff of Nottingham and
-you be Robin Hood a little while and kill me."
-
-This was satisfactory, and so these adventures were carried out. Then
-Tom became Robin Hood again, and was allowed by the treacherous nun to
-bleed his strength away through his neglected wound. And at last Joe,
-representing a whole tribe of weeping outlaws, dragged him sadly forth,
-gave his bow into his feeble hands, and Tom said, "Where this arrow
-falls, there bury poor Robin Hood under the greenwood tree." Then he
-shot the arrow and fell back and would have died, but he lit on a
-nettle and sprang up too gaily for a corpse.
-
-The boys dressed themselves, hid their accoutrements, and went off
-grieving that there were no outlaws any more, and wondering what modern
-civilization could claim to have done to compensate for their loss.
-They said they would rather be outlaws a year in Sherwood Forest than
-President of the United States forever.
-
-
-
-CHAPTER IX
-
-AT half-past nine, that night, Tom and Sid were sent to bed, as usual.
-They said their prayers, and Sid was soon asleep. Tom lay awake and
-waited, in restless impatience. When it seemed to him that it must be
-nearly daylight, he heard the clock strike ten! This was despair. He
-would have tossed and fidgeted, as his nerves demanded, but he was
-afraid he might wake Sid. So he lay still, and stared up into the dark.
-Everything was dismally still. By and by, out of the stillness, little,
-scarcely perceptible noises began to emphasize themselves. The ticking
-of the clock began to bring itself into notice. Old beams began to
-crack mysteriously. The stairs creaked faintly. Evidently spirits were
-abroad. A measured, muffled snore issued from Aunt Polly's chamber. And
-now the tiresome chirping of a cricket that no human ingenuity could
-locate, began. Next the ghastly ticking of a deathwatch in the wall at
-the bed's head made Tom shudder--it meant that somebody's days were
-numbered. Then the howl of a far-off dog rose on the night air, and was
-answered by a fainter howl from a remoter distance. Tom was in an
-agony. At last he was satisfied that time had ceased and eternity
-begun; he began to doze, in spite of himself; the clock chimed eleven,
-but he did not hear it. And then there came, mingling with his
-half-formed dreams, a most melancholy caterwauling. The raising of a
-neighboring window disturbed him. A cry of "Scat! you devil!" and the
-crash of an empty bottle against the back of his aunt's woodshed
-brought him wide awake, and a single minute later he was dressed and
-out of the window and creeping along the roof of the "ell" on all
-fours. He "meow'd" with caution once or twice, as he went; then jumped
-to the roof of the woodshed and thence to the ground. Huckleberry Finn
-was there, with his dead cat. The boys moved off and disappeared in the
-gloom. At the end of half an hour they were wading through the tall
-grass of the graveyard.
-
-It was a graveyard of the old-fashioned Western kind. It was on a
-hill, about a mile and a half from the village. It had a crazy board
-fence around it, which leaned inward in places, and outward the rest of
-the time, but stood upright nowhere. Grass and weeds grew rank over the
-whole cemetery. All the old graves were sunken in, there was not a
-tombstone on the place; round-topped, worm-eaten boards staggered over
-the graves, leaning for support and finding none. "Sacred to the memory
-of" So-and-So had been painted on them once, but it could no longer
-have been read, on the most of them, now, even if there had been light.
-
-A faint wind moaned through the trees, and Tom feared it might be the
-spirits of the dead, complaining at being disturbed. The boys talked
-little, and only under their breath, for the time and the place and the
-pervading solemnity and silence oppressed their spirits. They found the
-sharp new heap they were seeking, and ensconced themselves within the
-protection of three great elms that grew in a bunch within a few feet
-of the grave.
-
-Then they waited in silence for what seemed a long time. The hooting
-of a distant owl was all the sound that troubled the dead stillness.
-Tom's reflections grew oppressive. He must force some talk. So he said
-in a whisper:
-
-"Hucky, do you believe the dead people like it for us to be here?"
-
-Huckleberry whispered:
-
-"I wisht I knowed. It's awful solemn like, AIN'T it?"
-
-"I bet it is."
-
-There was a considerable pause, while the boys canvassed this matter
-inwardly. Then Tom whispered:
-
-"Say, Hucky--do you reckon Hoss Williams hears us talking?"
-
-"O' course he does. Least his sperrit does."
-
-Tom, after a pause:
-
-"I wish I'd said Mister Williams. But I never meant any harm.
-Everybody calls him Hoss."
-
-"A body can't be too partic'lar how they talk 'bout these-yer dead
-people, Tom."
-
-This was a damper, and conversation died again.
-
-Presently Tom seized his comrade's arm and said:
-
-"Sh!"
-
-"What is it, Tom?" And the two clung together with beating hearts.
-
-"Sh! There 'tis again! Didn't you hear it?"
-
-"I--"
-
-"There! Now you hear it."
-
-"Lord, Tom, they're coming! They're coming, sure. What'll we do?"
-
-"I dono. Think they'll see us?"
-
-"Oh, Tom, they can see in the dark, same as cats. I wisht I hadn't
-come."
-
-"Oh, don't be afeard. I don't believe they'll bother us. We ain't
-doing any harm. If we keep perfectly still, maybe they won't notice us
-at all."
-
-"I'll try to, Tom, but, Lord, I'm all of a shiver."
-
-"Listen!"
-
-The boys bent their heads together and scarcely breathed. A muffled
-sound of voices floated up from the far end of the graveyard.
-
-"Look! See there!" whispered Tom. "What is it?"
-
-"It's devil-fire. Oh, Tom, this is awful."
-
-Some vague figures approached through the gloom, swinging an
-old-fashioned tin lantern that freckled the ground with innumerable
-little spangles of light. Presently Huckleberry whispered with a
-shudder:
-
-"It's the devils sure enough. Three of 'em! Lordy, Tom, we're goners!
-Can you pray?"
-
-"I'll try, but don't you be afeard. They ain't going to hurt us. 'Now
-I lay me down to sleep, I--'"
-
-"Sh!"
-
-"What is it, Huck?"
-
-"They're HUMANS! One of 'em is, anyway. One of 'em's old Muff Potter's
-voice."
-
-"No--'tain't so, is it?"
-
-"I bet I know it. Don't you stir nor budge. He ain't sharp enough to
-notice us. Drunk, the same as usual, likely--blamed old rip!"
-
-"All right, I'll keep still. Now they're stuck. Can't find it. Here
-they come again. Now they're hot. Cold again. Hot again. Red hot!
-They're p'inted right, this time. Say, Huck, I know another o' them
-voices; it's Injun Joe."
-
-"That's so--that murderin' half-breed! I'd druther they was devils a
-dern sight. What kin they be up to?"
-
-The whisper died wholly out, now, for the three men had reached the
-grave and stood within a few feet of the boys' hiding-place.
-
-"Here it is," said the third voice; and the owner of it held the
-lantern up and revealed the face of young Doctor Robinson.
-
-Potter and Injun Joe were carrying a handbarrow with a rope and a
-couple of shovels on it. They cast down their load and began to open
-the grave. The doctor put the lantern at the head of the grave and came
-and sat down with his back against one of the elm trees. He was so
-close the boys could have touched him.
-
-"Hurry, men!" he said, in a low voice; "the moon might come out at any
-moment."
-
-They growled a response and went on digging. For some time there was
-no noise but the grating sound of the spades discharging their freight
-of mould and gravel. It was very monotonous. Finally a spade struck
-upon the coffin with a dull woody accent, and within another minute or
-two the men had hoisted it out on the ground. They pried off the lid
-with their shovels, got out the body and dumped it rudely on the
-ground. The moon drifted from behind the clouds and exposed the pallid
-face. The barrow was got ready and the corpse placed on it, covered
-with a blanket, and bound to its place with the rope. Potter took out a
-large spring-knife and cut off the dangling end of the rope and then
-said:
-
-"Now the cussed thing's ready, Sawbones, and you'll just out with
-another five, or here she stays."
-
-"That's the talk!" said Injun Joe.
-
-"Look here, what does this mean?" said the doctor. "You required your
-pay in advance, and I've paid you."
-
-"Yes, and you done more than that," said Injun Joe, approaching the
-doctor, who was now standing. "Five years ago you drove me away from
-your father's kitchen one night, when I come to ask for something to
-eat, and you said I warn't there for any good; and when I swore I'd get
-even with you if it took a hundred years, your father had me jailed for
-a vagrant. Did you think I'd forget? The Injun blood ain't in me for
-nothing. And now I've GOT you, and you got to SETTLE, you know!"
-
-He was threatening the doctor, with his fist in his face, by this
-time. The doctor struck out suddenly and stretched the ruffian on the
-ground. Potter dropped his knife, and exclaimed:
-
-"Here, now, don't you hit my pard!" and the next moment he had
-grappled with the doctor and the two were struggling with might and
-main, trampling the grass and tearing the ground with their heels.
-Injun Joe sprang to his feet, his eyes flaming with passion, snatched
-up Potter's knife, and went creeping, catlike and stooping, round and
-round about the combatants, seeking an opportunity. All at once the
-doctor flung himself free, seized the heavy headboard of Williams'
-grave and felled Potter to the earth with it--and in the same instant
-the half-breed saw his chance and drove the knife to the hilt in the
-young man's breast. He reeled and fell partly upon Potter, flooding him
-with his blood, and in the same moment the clouds blotted out the
-dreadful spectacle and the two frightened boys went speeding away in
-the dark.
-
-Presently, when the moon emerged again, Injun Joe was standing over
-the two forms, contemplating them. The doctor murmured inarticulately,
-gave a long gasp or two and was still. The half-breed muttered:
-
-"THAT score is settled--damn you."
-
-Then he robbed the body. After which he put the fatal knife in
-Potter's open right hand, and sat down on the dismantled coffin. Three
---four--five minutes passed, and then Potter began to stir and moan. His
-hand closed upon the knife; he raised it, glanced at it, and let it
-fall, with a shudder. Then he sat up, pushing the body from him, and
-gazed at it, and then around him, confusedly. His eyes met Joe's.
-
-"Lord, how is this, Joe?" he said.
-
-"It's a dirty business," said Joe, without moving.
-
-"What did you do it for?"
-
-"I! I never done it!"
-
-"Look here! That kind of talk won't wash."
-
-Potter trembled and grew white.
-
-"I thought I'd got sober. I'd no business to drink to-night. But it's
-in my head yet--worse'n when we started here. I'm all in a muddle;
-can't recollect anything of it, hardly. Tell me, Joe--HONEST, now, old
-feller--did I do it? Joe, I never meant to--'pon my soul and honor, I
-never meant to, Joe. Tell me how it was, Joe. Oh, it's awful--and him
-so young and promising."
-
-"Why, you two was scuffling, and he fetched you one with the headboard
-and you fell flat; and then up you come, all reeling and staggering
-like, and snatched the knife and jammed it into him, just as he fetched
-you another awful clip--and here you've laid, as dead as a wedge til
-now."
-
-"Oh, I didn't know what I was a-doing. I wish I may die this minute if
-I did. It was all on account of the whiskey and the excitement, I
-reckon. I never used a weepon in my life before, Joe. I've fought, but
-never with weepons. They'll all say that. Joe, don't tell! Say you
-won't tell, Joe--that's a good feller. I always liked you, Joe, and
-stood up for you, too. Don't you remember? You WON'T tell, WILL you,
-Joe?" And the poor creature dropped on his knees before the stolid
-murderer, and clasped his appealing hands.
-
-"No, you've always been fair and square with me, Muff Potter, and I
-won't go back on you. There, now, that's as fair as a man can say."
-
-"Oh, Joe, you're an angel. I'll bless you for this the longest day I
-live." And Potter began to cry.
-
-"Come, now, that's enough of that. This ain't any time for blubbering.
-You be off yonder way and I'll go this. Move, now, and don't leave any
-tracks behind you."
-
-Potter started on a trot that quickly increased to a run. The
-half-breed stood looking after him. He muttered:
-
-"If he's as much stunned with the lick and fuddled with the rum as he
-had the look of being, he won't think of the knife till he's gone so
-far he'll be afraid to come back after it to such a place by himself
---chicken-heart!"
-
-Two or three minutes later the murdered man, the blanketed corpse, the
-lidless coffin, and the open grave were under no inspection but the
-moon's. The stillness was complete again, too.
-
-
-
-CHAPTER X
-
-THE two boys flew on and on, toward the village, speechless with
-horror. They glanced backward over their shoulders from time to time,
-apprehensively, as if they feared they might be followed. Every stump
-that started up in their path seemed a man and an enemy, and made them
-catch their breath; and as they sped by some outlying cottages that lay
-near the village, the barking of the aroused watch-dogs seemed to give
-wings to their feet.
-
-"If we can only get to the old tannery before we break down!"
-whispered Tom, in short catches between breaths. "I can't stand it much
-longer."
-
-Huckleberry's hard pantings were his only reply, and the boys fixed
-their eyes on the goal of their hopes and bent to their work to win it.
-They gained steadily on it, and at last, breast to breast, they burst
-through the open door and fell grateful and exhausted in the sheltering
-shadows beyond. By and by their pulses slowed down, and Tom whispered:
-
-"Huckleberry, what do you reckon'll come of this?"
-
-"If Doctor Robinson dies, I reckon hanging'll come of it."
-
-"Do you though?"
-
-"Why, I KNOW it, Tom."
-
-Tom thought a while, then he said:
-
-"Who'll tell? We?"
-
-"What are you talking about? S'pose something happened and Injun Joe
-DIDN'T hang? Why, he'd kill us some time or other, just as dead sure as
-we're a laying here."
-
-"That's just what I was thinking to myself, Huck."
-
-"If anybody tells, let Muff Potter do it, if he's fool enough. He's
-generally drunk enough."
-
-Tom said nothing--went on thinking. Presently he whispered:
-
-"Huck, Muff Potter don't know it. How can he tell?"
-
-"What's the reason he don't know it?"
-
-"Because he'd just got that whack when Injun Joe done it. D'you reckon
-he could see anything? D'you reckon he knowed anything?"
-
-"By hokey, that's so, Tom!"
-
-"And besides, look-a-here--maybe that whack done for HIM!"
-
-"No, 'taint likely, Tom. He had liquor in him; I could see that; and
-besides, he always has. Well, when pap's full, you might take and belt
-him over the head with a church and you couldn't phase him. He says so,
-his own self. So it's the same with Muff Potter, of course. But if a
-man was dead sober, I reckon maybe that whack might fetch him; I dono."
-
-After another reflective silence, Tom said:
-
-"Hucky, you sure you can keep mum?"
-
-"Tom, we GOT to keep mum. You know that. That Injun devil wouldn't
-make any more of drownding us than a couple of cats, if we was to
-squeak 'bout this and they didn't hang him. Now, look-a-here, Tom, less
-take and swear to one another--that's what we got to do--swear to keep
-mum."
-
-"I'm agreed. It's the best thing. Would you just hold hands and swear
-that we--"
-
-"Oh no, that wouldn't do for this. That's good enough for little
-rubbishy common things--specially with gals, cuz THEY go back on you
-anyway, and blab if they get in a huff--but there orter be writing
-'bout a big thing like this. And blood."
-
-Tom's whole being applauded this idea. It was deep, and dark, and
-awful; the hour, the circumstances, the surroundings, were in keeping
-with it. He picked up a clean pine shingle that lay in the moonlight,
-took a little fragment of "red keel" out of his pocket, got the moon on
-his work, and painfully scrawled these lines, emphasizing each slow
-down-stroke by clamping his tongue between his teeth, and letting up
-the pressure on the up-strokes. [See next page.]
-
- "Huck Finn and
- Tom Sawyer swears
- they will keep mum
- about This and They
- wish They may Drop
- down dead in Their
- Tracks if They ever
- Tell and Rot."
-
-Huckleberry was filled with admiration of Tom's facility in writing,
-and the sublimity of his language. He at once took a pin from his lapel
-and was going to prick his flesh, but Tom said:
-
-"Hold on! Don't do that. A pin's brass. It might have verdigrease on
-it."
-
-"What's verdigrease?"
-
-"It's p'ison. That's what it is. You just swaller some of it once
---you'll see."
-
-So Tom unwound the thread from one of his needles, and each boy
-pricked the ball of his thumb and squeezed out a drop of blood. In
-time, after many squeezes, Tom managed to sign his initials, using the
-ball of his little finger for a pen. Then he showed Huckleberry how to
-make an H and an F, and the oath was complete. They buried the shingle
-close to the wall, with some dismal ceremonies and incantations, and
-the fetters that bound their tongues were considered to be locked and
-the key thrown away.
-
-A figure crept stealthily through a break in the other end of the
-ruined building, now, but they did not notice it.
-
-"Tom," whispered Huckleberry, "does this keep us from EVER telling
---ALWAYS?"
-
-"Of course it does. It don't make any difference WHAT happens, we got
-to keep mum. We'd drop down dead--don't YOU know that?"
-
-"Yes, I reckon that's so."
-
-They continued to whisper for some little time. Presently a dog set up
-a long, lugubrious howl just outside--within ten feet of them. The boys
-clasped each other suddenly, in an agony of fright.
-
-"Which of us does he mean?" gasped Huckleberry.
-
-"I dono--peep through the crack. Quick!"
-
-"No, YOU, Tom!"
-
-"I can't--I can't DO it, Huck!"
-
-"Please, Tom. There 'tis again!"
-
-"Oh, lordy, I'm thankful!" whispered Tom. "I know his voice. It's Bull
-Harbison." *
-
-[* If Mr. Harbison owned a slave named Bull, Tom would have spoken of
-him as "Harbison's Bull," but a son or a dog of that name was "Bull
-Harbison."]
-
-"Oh, that's good--I tell you, Tom, I was most scared to death; I'd a
-bet anything it was a STRAY dog."
-
-The dog howled again. The boys' hearts sank once more.
-
-"Oh, my! that ain't no Bull Harbison!" whispered Huckleberry. "DO, Tom!"
-
-Tom, quaking with fear, yielded, and put his eye to the crack. His
-whisper was hardly audible when he said:
-
-"Oh, Huck, IT S A STRAY DOG!"
-
-"Quick, Tom, quick! Who does he mean?"
-
-"Huck, he must mean us both--we're right together."
-
-"Oh, Tom, I reckon we're goners. I reckon there ain't no mistake 'bout
-where I'LL go to. I been so wicked."
-
-"Dad fetch it! This comes of playing hookey and doing everything a
-feller's told NOT to do. I might a been good, like Sid, if I'd a tried
---but no, I wouldn't, of course. But if ever I get off this time, I lay
-I'll just WALLER in Sunday-schools!" And Tom began to snuffle a little.
-
-"YOU bad!" and Huckleberry began to snuffle too. "Consound it, Tom
-Sawyer, you're just old pie, 'longside o' what I am. Oh, LORDY, lordy,
-lordy, I wisht I only had half your chance."
-
-Tom choked off and whispered:
-
-"Look, Hucky, look! He's got his BACK to us!"
-
-Hucky looked, with joy in his heart.
-
-"Well, he has, by jingoes! Did he before?"
-
-"Yes, he did. But I, like a fool, never thought. Oh, this is bully,
-you know. NOW who can he mean?"
-
-The howling stopped. Tom pricked up his ears.
-
-"Sh! What's that?" he whispered.
-
-"Sounds like--like hogs grunting. No--it's somebody snoring, Tom."
-
-"That IS it! Where 'bouts is it, Huck?"
-
-"I bleeve it's down at 'tother end. Sounds so, anyway. Pap used to
-sleep there, sometimes, 'long with the hogs, but laws bless you, he
-just lifts things when HE snores. Besides, I reckon he ain't ever
-coming back to this town any more."
-
-The spirit of adventure rose in the boys' souls once more.
-
-"Hucky, do you das't to go if I lead?"
-
-"I don't like to, much. Tom, s'pose it's Injun Joe!"
-
-Tom quailed. But presently the temptation rose up strong again and the
-boys agreed to try, with the understanding that they would take to
-their heels if the snoring stopped. So they went tiptoeing stealthily
-down, the one behind the other. When they had got to within five steps
-of the snorer, Tom stepped on a stick, and it broke with a sharp snap.
-The man moaned, writhed a little, and his face came into the moonlight.
-It was Muff Potter. The boys' hearts had stood still, and their hopes
-too, when the man moved, but their fears passed away now. They tiptoed
-out, through the broken weather-boarding, and stopped at a little
-distance to exchange a parting word. That long, lugubrious howl rose on
-the night air again! They turned and saw the strange dog standing
-within a few feet of where Potter was lying, and FACING Potter, with
-his nose pointing heavenward.
-
-"Oh, geeminy, it's HIM!" exclaimed both boys, in a breath.
-
-"Say, Tom--they say a stray dog come howling around Johnny Miller's
-house, 'bout midnight, as much as two weeks ago; and a whippoorwill
-come in and lit on the banisters and sung, the very same evening; and
-there ain't anybody dead there yet."
-
-"Well, I know that. And suppose there ain't. Didn't Gracie Miller fall
-in the kitchen fire and burn herself terrible the very next Saturday?"
-
-"Yes, but she ain't DEAD. And what's more, she's getting better, too."
-
-"All right, you wait and see. She's a goner, just as dead sure as Muff
-Potter's a goner. That's what the niggers say, and they know all about
-these kind of things, Huck."
-
-Then they separated, cogitating. When Tom crept in at his bedroom
-window the night was almost spent. He undressed with excessive caution,
-and fell asleep congratulating himself that nobody knew of his
-escapade. He was not aware that the gently-snoring Sid was awake, and
-had been so for an hour.
-
-When Tom awoke, Sid was dressed and gone. There was a late look in the
-light, a late sense in the atmosphere. He was startled. Why had he not
-been called--persecuted till he was up, as usual? The thought filled
-him with bodings. Within five minutes he was dressed and down-stairs,
-feeling sore and drowsy. The family were still at table, but they had
-finished breakfast. There was no voice of rebuke; but there were
-averted eyes; there was a silence and an air of solemnity that struck a
-chill to the culprit's heart. He sat down and tried to seem gay, but it
-was up-hill work; it roused no smile, no response, and he lapsed into
-silence and let his heart sink down to the depths.
-
-After breakfast his aunt took him aside, and Tom almost brightened in
-the hope that he was going to be flogged; but it was not so. His aunt
-wept over him and asked him how he could go and break her old heart so;
-and finally told him to go on, and ruin himself and bring her gray
-hairs with sorrow to the grave, for it was no use for her to try any
-more. This was worse than a thousand whippings, and Tom's heart was
-sorer now than his body. He cried, he pleaded for forgiveness, promised
-to reform over and over again, and then received his dismissal, feeling
-that he had won but an imperfect forgiveness and established but a
-feeble confidence.
-
-He left the presence too miserable to even feel revengeful toward Sid;
-and so the latter's prompt retreat through the back gate was
-unnecessary. He moped to school gloomy and sad, and took his flogging,
-along with Joe Harper, for playing hookey the day before, with the air
-of one whose heart was busy with heavier woes and wholly dead to
-trifles. Then he betook himself to his seat, rested his elbows on his
-desk and his jaws in his hands, and stared at the wall with the stony
-stare of suffering that has reached the limit and can no further go.
-His elbow was pressing against some hard substance. After a long time
-he slowly and sadly changed his position, and took up this object with
-a sigh. It was in a paper. He unrolled it. A long, lingering, colossal
-sigh followed, and his heart broke. It was his brass andiron knob!
-
-This final feather broke the camel's back.
-
-
-
-CHAPTER XI
-
-CLOSE upon the hour of noon the whole village was suddenly electrified
-with the ghastly news. No need of the as yet undreamed-of telegraph;
-the tale flew from man to man, from group to group, from house to
-house, with little less than telegraphic speed. Of course the
-schoolmaster gave holiday for that afternoon; the town would have
-thought strangely of him if he had not.
-
-A gory knife had been found close to the murdered man, and it had been
-recognized by somebody as belonging to Muff Potter--so the story ran.
-And it was said that a belated citizen had come upon Potter washing
-himself in the "branch" about one or two o'clock in the morning, and
-that Potter had at once sneaked off--suspicious circumstances,
-especially the washing which was not a habit with Potter. It was also
-said that the town had been ransacked for this "murderer" (the public
-are not slow in the matter of sifting evidence and arriving at a
-verdict), but that he could not be found. Horsemen had departed down
-all the roads in every direction, and the Sheriff "was confident" that
-he would be captured before night.
-
-All the town was drifting toward the graveyard. Tom's heartbreak
-vanished and he joined the procession, not because he would not a
-thousand times rather go anywhere else, but because an awful,
-unaccountable fascination drew him on. Arrived at the dreadful place,
-he wormed his small body through the crowd and saw the dismal
-spectacle. It seemed to him an age since he was there before. Somebody
-pinched his arm. He turned, and his eyes met Huckleberry's. Then both
-looked elsewhere at once, and wondered if anybody had noticed anything
-in their mutual glance. But everybody was talking, and intent upon the
-grisly spectacle before them.
-
-"Poor fellow!" "Poor young fellow!" "This ought to be a lesson to
-grave robbers!" "Muff Potter'll hang for this if they catch him!" This
-was the drift of remark; and the minister said, "It was a judgment; His
-hand is here."
-
-Now Tom shivered from head to heel; for his eye fell upon the stolid
-face of Injun Joe. At this moment the crowd began to sway and struggle,
-and voices shouted, "It's him! it's him! he's coming himself!"
-
-"Who? Who?" from twenty voices.
-
-"Muff Potter!"
-
-"Hallo, he's stopped!--Look out, he's turning! Don't let him get away!"
-
-People in the branches of the trees over Tom's head said he wasn't
-trying to get away--he only looked doubtful and perplexed.
-
-"Infernal impudence!" said a bystander; "wanted to come and take a
-quiet look at his work, I reckon--didn't expect any company."
-
-The crowd fell apart, now, and the Sheriff came through,
-ostentatiously leading Potter by the arm. The poor fellow's face was
-haggard, and his eyes showed the fear that was upon him. When he stood
-before the murdered man, he shook as with a palsy, and he put his face
-in his hands and burst into tears.
-
-"I didn't do it, friends," he sobbed; "'pon my word and honor I never
-done it."
-
-"Who's accused you?" shouted a voice.
-
-This shot seemed to carry home. Potter lifted his face and looked
-around him with a pathetic hopelessness in his eyes. He saw Injun Joe,
-and exclaimed:
-
-"Oh, Injun Joe, you promised me you'd never--"
-
-"Is that your knife?" and it was thrust before him by the Sheriff.
-
-Potter would have fallen if they had not caught him and eased him to
-the ground. Then he said:
-
-"Something told me 't if I didn't come back and get--" He shuddered;
-then waved his nerveless hand with a vanquished gesture and said, "Tell
-'em, Joe, tell 'em--it ain't any use any more."
-
-Then Huckleberry and Tom stood dumb and staring, and heard the
-stony-hearted liar reel off his serene statement, they expecting every
-moment that the clear sky would deliver God's lightnings upon his head,
-and wondering to see how long the stroke was delayed. And when he had
-finished and still stood alive and whole, their wavering impulse to
-break their oath and save the poor betrayed prisoner's life faded and
-vanished away, for plainly this miscreant had sold himself to Satan and
-it would be fatal to meddle with the property of such a power as that.
-
-"Why didn't you leave? What did you want to come here for?" somebody
-said.
-
-"I couldn't help it--I couldn't help it," Potter moaned. "I wanted to
-run away, but I couldn't seem to come anywhere but here." And he fell
-to sobbing again.
-
-Injun Joe repeated his statement, just as calmly, a few minutes
-afterward on the inquest, under oath; and the boys, seeing that the
-lightnings were still withheld, were confirmed in their belief that Joe
-had sold himself to the devil. He was now become, to them, the most
-balefully interesting object they had ever looked upon, and they could
-not take their fascinated eyes from his face.
-
-They inwardly resolved to watch him nights, when opportunity should
-offer, in the hope of getting a glimpse of his dread master.
-
-Injun Joe helped to raise the body of the murdered man and put it in a
-wagon for removal; and it was whispered through the shuddering crowd
-that the wound bled a little! The boys thought that this happy
-circumstance would turn suspicion in the right direction; but they were
-disappointed, for more than one villager remarked:
-
-"It was within three feet of Muff Potter when it done it."
-
-Tom's fearful secret and gnawing conscience disturbed his sleep for as
-much as a week after this; and at breakfast one morning Sid said:
-
-"Tom, you pitch around and talk in your sleep so much that you keep me
-awake half the time."
-
-Tom blanched and dropped his eyes.
-
-"It's a bad sign," said Aunt Polly, gravely. "What you got on your
-mind, Tom?"
-
-"Nothing. Nothing 't I know of." But the boy's hand shook so that he
-spilled his coffee.
-
-"And you do talk such stuff," Sid said. "Last night you said, 'It's
-blood, it's blood, that's what it is!' You said that over and over. And
-you said, 'Don't torment me so--I'll tell!' Tell WHAT? What is it
-you'll tell?"
-
-Everything was swimming before Tom. There is no telling what might
-have happened, now, but luckily the concern passed out of Aunt Polly's
-face and she came to Tom's relief without knowing it. She said:
-
-"Sho! It's that dreadful murder. I dream about it most every night
-myself. Sometimes I dream it's me that done it."
-
-Mary said she had been affected much the same way. Sid seemed
-satisfied. Tom got out of the presence as quick as he plausibly could,
-and after that he complained of toothache for a week, and tied up his
-jaws every night. He never knew that Sid lay nightly watching, and
-frequently slipped the bandage free and then leaned on his elbow
-listening a good while at a time, and afterward slipped the bandage
-back to its place again. Tom's distress of mind wore off gradually and
-the toothache grew irksome and was discarded. If Sid really managed to
-make anything out of Tom's disjointed mutterings, he kept it to himself.
-
-It seemed to Tom that his schoolmates never would get done holding
-inquests on dead cats, and thus keeping his trouble present to his
-mind. Sid noticed that Tom never was coroner at one of these inquiries,
-though it had been his habit to take the lead in all new enterprises;
-he noticed, too, that Tom never acted as a witness--and that was
-strange; and Sid did not overlook the fact that Tom even showed a
-marked aversion to these inquests, and always avoided them when he
-could. Sid marvelled, but said nothing. However, even inquests went out
-of vogue at last, and ceased to torture Tom's conscience.
-
-Every day or two, during this time of sorrow, Tom watched his
-opportunity and went to the little grated jail-window and smuggled such
-small comforts through to the "murderer" as he could get hold of. The
-jail was a trifling little brick den that stood in a marsh at the edge
-of the village, and no guards were afforded for it; indeed, it was
-seldom occupied. These offerings greatly helped to ease Tom's
-conscience.
-
-The villagers had a strong desire to tar-and-feather Injun Joe and
-ride him on a rail, for body-snatching, but so formidable was his
-character that nobody could be found who was willing to take the lead
-in the matter, so it was dropped. He had been careful to begin both of
-his inquest-statements with the fight, without confessing the
-grave-robbery that preceded it; therefore it was deemed wisest not
-to try the case in the courts at present.
-
-
-
-CHAPTER XII
-
-ONE of the reasons why Tom's mind had drifted away from its secret
-troubles was, that it had found a new and weighty matter to interest
-itself about. Becky Thatcher had stopped coming to school. Tom had
-struggled with his pride a few days, and tried to "whistle her down the
-wind," but failed. He began to find himself hanging around her father's
-house, nights, and feeling very miserable. She was ill. What if she
-should die! There was distraction in the thought. He no longer took an
-interest in war, nor even in piracy. The charm of life was gone; there
-was nothing but dreariness left. He put his hoop away, and his bat;
-there was no joy in them any more. His aunt was concerned. She began to
-try all manner of remedies on him. She was one of those people who are
-infatuated with patent medicines and all new-fangled methods of
-producing health or mending it. She was an inveterate experimenter in
-these things. When something fresh in this line came out she was in a
-fever, right away, to try it; not on herself, for she was never ailing,
-but on anybody else that came handy. She was a subscriber for all the
-"Health" periodicals and phrenological frauds; and the solemn ignorance
-they were inflated with was breath to her nostrils. All the "rot" they
-contained about ventilation, and how to go to bed, and how to get up,
-and what to eat, and what to drink, and how much exercise to take, and
-what frame of mind to keep one's self in, and what sort of clothing to
-wear, was all gospel to her, and she never observed that her
-health-journals of the current month customarily upset everything they
-had recommended the month before. She was as simple-hearted and honest
-as the day was long, and so she was an easy victim. She gathered
-together her quack periodicals and her quack medicines, and thus armed
-with death, went about on her pale horse, metaphorically speaking, with
-"hell following after." But she never suspected that she was not an
-angel of healing and the balm of Gilead in disguise, to the suffering
-neighbors.
-
-The water treatment was new, now, and Tom's low condition was a
-windfall to her. She had him out at daylight every morning, stood him
-up in the woodshed and drowned him with a deluge of cold water; then
-she scrubbed him down with a towel like a file, and so brought him to;
-then she rolled him up in a wet sheet and put him away under blankets
-till she sweated his soul clean and "the yellow stains of it came
-through his pores"--as Tom said.
-
-Yet notwithstanding all this, the boy grew more and more melancholy
-and pale and dejected. She added hot baths, sitz baths, shower baths,
-and plunges. The boy remained as dismal as a hearse. She began to
-assist the water with a slim oatmeal diet and blister-plasters. She
-calculated his capacity as she would a jug's, and filled him up every
-day with quack cure-alls.
-
-Tom had become indifferent to persecution by this time. This phase
-filled the old lady's heart with consternation. This indifference must
-be broken up at any cost. Now she heard of Pain-killer for the first
-time. She ordered a lot at once. She tasted it and was filled with
-gratitude. It was simply fire in a liquid form. She dropped the water
-treatment and everything else, and pinned her faith to Pain-killer. She
-gave Tom a teaspoonful and watched with the deepest anxiety for the
-result. Her troubles were instantly at rest, her soul at peace again;
-for the "indifference" was broken up. The boy could not have shown a
-wilder, heartier interest, if she had built a fire under him.
-
-Tom felt that it was time to wake up; this sort of life might be
-romantic enough, in his blighted condition, but it was getting to have
-too little sentiment and too much distracting variety about it. So he
-thought over various plans for relief, and finally hit pon that of
-professing to be fond of Pain-killer. He asked for it so often that he
-became a nuisance, and his aunt ended by telling him to help himself
-and quit bothering her. If it had been Sid, she would have had no
-misgivings to alloy her delight; but since it was Tom, she watched the
-bottle clandestinely. She found that the medicine did really diminish,
-but it did not occur to her that the boy was mending the health of a
-crack in the sitting-room floor with it.
-
-One day Tom was in the act of dosing the crack when his aunt's yellow
-cat came along, purring, eying the teaspoon avariciously, and begging
-for a taste. Tom said:
-
-"Don't ask for it unless you want it, Peter."
-
-But Peter signified that he did want it.
-
-"You better make sure."
-
-Peter was sure.
-
-"Now you've asked for it, and I'll give it to you, because there ain't
-anything mean about me; but if you find you don't like it, you mustn't
-blame anybody but your own self."
-
-Peter was agreeable. So Tom pried his mouth open and poured down the
-Pain-killer. Peter sprang a couple of yards in the air, and then
-delivered a war-whoop and set off round and round the room, banging
-against furniture, upsetting flower-pots, and making general havoc.
-Next he rose on his hind feet and pranced around, in a frenzy of
-enjoyment, with his head over his shoulder and his voice proclaiming
-his unappeasable happiness. Then he went tearing around the house again
-spreading chaos and destruction in his path. Aunt Polly entered in time
-to see him throw a few double summersets, deliver a final mighty
-hurrah, and sail through the open window, carrying the rest of the
-flower-pots with him. The old lady stood petrified with astonishment,
-peering over her glasses; Tom lay on the floor expiring with laughter.
-
-"Tom, what on earth ails that cat?"
-
-"I don't know, aunt," gasped the boy.
-
-"Why, I never see anything like it. What did make him act so?"
-
-"Deed I don't know, Aunt Polly; cats always act so when they're having
-a good time."
-
-"They do, do they?" There was something in the tone that made Tom
-apprehensive.
-
-"Yes'm. That is, I believe they do."
-
-"You DO?"
-
-"Yes'm."
-
-The old lady was bending down, Tom watching, with interest emphasized
-by anxiety. Too late he divined her "drift." The handle of the telltale
-teaspoon was visible under the bed-valance. Aunt Polly took it, held it
-up. Tom winced, and dropped his eyes. Aunt Polly raised him by the
-usual handle--his ear--and cracked his head soundly with her thimble.
-
-"Now, sir, what did you want to treat that poor dumb beast so, for?"
-
-"I done it out of pity for him--because he hadn't any aunt."
-
-"Hadn't any aunt!--you numskull. What has that got to do with it?"
-
-"Heaps. Because if he'd had one she'd a burnt him out herself! She'd a
-roasted his bowels out of him 'thout any more feeling than if he was a
-human!"
-
-Aunt Polly felt a sudden pang of remorse. This was putting the thing
-in a new light; what was cruelty to a cat MIGHT be cruelty to a boy,
-too. She began to soften; she felt sorry. Her eyes watered a little,
-and she put her hand on Tom's head and said gently:
-
-"I was meaning for the best, Tom. And, Tom, it DID do you good."
-
-Tom looked up in her face with just a perceptible twinkle peeping
-through his gravity.
-
-"I know you was meaning for the best, aunty, and so was I with Peter.
-It done HIM good, too. I never see him get around so since--"
-
-"Oh, go 'long with you, Tom, before you aggravate me again. And you
-try and see if you can't be a good boy, for once, and you needn't take
-any more medicine."
-
-Tom reached school ahead of time. It was noticed that this strange
-thing had been occurring every day latterly. And now, as usual of late,
-he hung about the gate of the schoolyard instead of playing with his
-comrades. He was sick, he said, and he looked it. He tried to seem to
-be looking everywhere but whither he really was looking--down the road.
-Presently Jeff Thatcher hove in sight, and Tom's face lighted; he gazed
-a moment, and then turned sorrowfully away. When Jeff arrived, Tom
-accosted him; and "led up" warily to opportunities for remark about
-Becky, but the giddy lad never could see the bait. Tom watched and
-watched, hoping whenever a frisking frock came in sight, and hating the
-owner of it as soon as he saw she was not the right one. At last frocks
-ceased to appear, and he dropped hopelessly into the dumps; he entered
-the empty schoolhouse and sat down to suffer. Then one more frock
-passed in at the gate, and Tom's heart gave a great bound. The next
-instant he was out, and "going on" like an Indian; yelling, laughing,
-chasing boys, jumping over the fence at risk of life and limb, throwing
-handsprings, standing on his head--doing all the heroic things he could
-conceive of, and keeping a furtive eye out, all the while, to see if
-Becky Thatcher was noticing. But she seemed to be unconscious of it
-all; she never looked. Could it be possible that she was not aware that
-he was there? He carried his exploits to her immediate vicinity; came
-war-whooping around, snatched a boy's cap, hurled it to the roof of the
-schoolhouse, broke through a group of boys, tumbling them in every
-direction, and fell sprawling, himself, under Becky's nose, almost
-upsetting her--and she turned, with her nose in the air, and he heard
-her say: "Mf! some people think they're mighty smart--always showing
-off!"
-
-Tom's cheeks burned. He gathered himself up and sneaked off, crushed
-and crestfallen.
-
-
-
-CHAPTER XIII
-
-TOM'S mind was made up now. He was gloomy and desperate. He was a
-forsaken, friendless boy, he said; nobody loved him; when they found
-out what they had driven him to, perhaps they would be sorry; he had
-tried to do right and get along, but they would not let him; since
-nothing would do them but to be rid of him, let it be so; and let them
-blame HIM for the consequences--why shouldn't they? What right had the
-friendless to complain? Yes, they had forced him to it at last: he
-would lead a life of crime. There was no choice.
-
-By this time he was far down Meadow Lane, and the bell for school to
-"take up" tinkled faintly upon his ear. He sobbed, now, to think he
-should never, never hear that old familiar sound any more--it was very
-hard, but it was forced on him; since he was driven out into the cold
-world, he must submit--but he forgave them. Then the sobs came thick
-and fast.
-
-Just at this point he met his soul's sworn comrade, Joe Harper
---hard-eyed, and with evidently a great and dismal purpose in his heart.
-Plainly here were "two souls with but a single thought." Tom, wiping
-his eyes with his sleeve, began to blubber out something about a
-resolution to escape from hard usage and lack of sympathy at home by
-roaming abroad into the great world never to return; and ended by
-hoping that Joe would not forget him.
-
-But it transpired that this was a request which Joe had just been
-going to make of Tom, and had come to hunt him up for that purpose. His
-mother had whipped him for drinking some cream which he had never
-tasted and knew nothing about; it was plain that she was tired of him
-and wished him to go; if she felt that way, there was nothing for him
-to do but succumb; he hoped she would be happy, and never regret having
-driven her poor boy out into the unfeeling world to suffer and die.
-
-As the two boys walked sorrowing along, they made a new compact to
-stand by each other and be brothers and never separate till death
-relieved them of their troubles. Then they began to lay their plans.
-Joe was for being a hermit, and living on crusts in a remote cave, and
-dying, some time, of cold and want and grief; but after listening to
-Tom, he conceded that there were some conspicuous advantages about a
-life of crime, and so he consented to be a pirate.
-
-Three miles below St. Petersburg, at a point where the Mississippi
-River was a trifle over a mile wide, there was a long, narrow, wooded
-island, with a shallow bar at the head of it, and this offered well as
-a rendezvous. It was not inhabited; it lay far over toward the further
-shore, abreast a dense and almost wholly unpeopled forest. So Jackson's
-Island was chosen. Who were to be the subjects of their piracies was a
-matter that did not occur to them. Then they hunted up Huckleberry
-Finn, and he joined them promptly, for all careers were one to him; he
-was indifferent. They presently separated to meet at a lonely spot on
-the river-bank two miles above the village at the favorite hour--which
-was midnight. There was a small log raft there which they meant to
-capture. Each would bring hooks and lines, and such provision as he
-could steal in the most dark and mysterious way--as became outlaws. And
-before the afternoon was done, they had all managed to enjoy the sweet
-glory of spreading the fact that pretty soon the town would "hear
-something." All who got this vague hint were cautioned to "be mum and
-wait."
-
-About midnight Tom arrived with a boiled ham and a few trifles,
-and stopped in a dense undergrowth on a small bluff overlooking the
-meeting-place. It was starlight, and very still. The mighty river lay
-like an ocean at rest. Tom listened a moment, but no sound disturbed the
-quiet. Then he gave a low, distinct whistle. It was answered from under
-the bluff. Tom whistled twice more; these signals were answered in the
-same way. Then a guarded voice said:
-
-"Who goes there?"
-
-"Tom Sawyer, the Black Avenger of the Spanish Main. Name your names."
-
-"Huck Finn the Red-Handed, and Joe Harper the Terror of the Seas." Tom
-had furnished these titles, from his favorite literature.
-
-"'Tis well. Give the countersign."
-
-Two hoarse whispers delivered the same awful word simultaneously to
-the brooding night:
-
-"BLOOD!"
-
-Then Tom tumbled his ham over the bluff and let himself down after it,
-tearing both skin and clothes to some extent in the effort. There was
-an easy, comfortable path along the shore under the bluff, but it
-lacked the advantages of difficulty and danger so valued by a pirate.
-
-The Terror of the Seas had brought a side of bacon, and had about worn
-himself out with getting it there. Finn the Red-Handed had stolen a
-skillet and a quantity of half-cured leaf tobacco, and had also brought
-a few corn-cobs to make pipes with. But none of the pirates smoked or
-"chewed" but himself. The Black Avenger of the Spanish Main said it
-would never do to start without some fire. That was a wise thought;
-matches were hardly known there in that day. They saw a fire
-smouldering upon a great raft a hundred yards above, and they went
-stealthily thither and helped themselves to a chunk. They made an
-imposing adventure of it, saying, "Hist!" every now and then, and
-suddenly halting with finger on lip; moving with hands on imaginary
-dagger-hilts; and giving orders in dismal whispers that if "the foe"
-stirred, to "let him have it to the hilt," because "dead men tell no
-tales." They knew well enough that the raftsmen were all down at the
-village laying in stores or having a spree, but still that was no
-excuse for their conducting this thing in an unpiratical way.
-
-They shoved off, presently, Tom in command, Huck at the after oar and
-Joe at the forward. Tom stood amidships, gloomy-browed, and with folded
-arms, and gave his orders in a low, stern whisper:
-
-"Luff, and bring her to the wind!"
-
-"Aye-aye, sir!"
-
-"Steady, steady-y-y-y!"
-
-"Steady it is, sir!"
-
-"Let her go off a point!"
-
-"Point it is, sir!"
-
-As the boys steadily and monotonously drove the raft toward mid-stream
-it was no doubt understood that these orders were given only for
-"style," and were not intended to mean anything in particular.
-
-"What sail's she carrying?"
-
-"Courses, tops'ls, and flying-jib, sir."
-
-"Send the r'yals up! Lay out aloft, there, half a dozen of ye
---foretopmaststuns'l! Lively, now!"
-
-"Aye-aye, sir!"
-
-"Shake out that maintogalans'l! Sheets and braces! NOW my hearties!"
-
-"Aye-aye, sir!"
-
-"Hellum-a-lee--hard a port! Stand by to meet her when she comes! Port,
-port! NOW, men! With a will! Stead-y-y-y!"
-
-"Steady it is, sir!"
-
-The raft drew beyond the middle of the river; the boys pointed her
-head right, and then lay on their oars. The river was not high, so
-there was not more than a two or three mile current. Hardly a word was
-said during the next three-quarters of an hour. Now the raft was
-passing before the distant town. Two or three glimmering lights showed
-where it lay, peacefully sleeping, beyond the vague vast sweep of
-star-gemmed water, unconscious of the tremendous event that was happening.
-The Black Avenger stood still with folded arms, "looking his last" upon
-the scene of his former joys and his later sufferings, and wishing
-"she" could see him now, abroad on the wild sea, facing peril and death
-with dauntless heart, going to his doom with a grim smile on his lips.
-It was but a small strain on his imagination to remove Jackson's Island
-beyond eyeshot of the village, and so he "looked his last" with a
-broken and satisfied heart. The other pirates were looking their last,
-too; and they all looked so long that they came near letting the
-current drift them out of the range of the island. But they discovered
-the danger in time, and made shift to avert it. About two o'clock in
-the morning the raft grounded on the bar two hundred yards above the
-head of the island, and they waded back and forth until they had landed
-their freight. Part of the little raft's belongings consisted of an old
-sail, and this they spread over a nook in the bushes for a tent to
-shelter their provisions; but they themselves would sleep in the open
-air in good weather, as became outlaws.
-
-They built a fire against the side of a great log twenty or thirty
-steps within the sombre depths of the forest, and then cooked some
-bacon in the frying-pan for supper, and used up half of the corn "pone"
-stock they had brought. It seemed glorious sport to be feasting in that
-wild, free way in the virgin forest of an unexplored and uninhabited
-island, far from the haunts of men, and they said they never would
-return to civilization. The climbing fire lit up their faces and threw
-its ruddy glare upon the pillared tree-trunks of their forest temple,
-and upon the varnished foliage and festooning vines.
-
-When the last crisp slice of bacon was gone, and the last allowance of
-corn pone devoured, the boys stretched themselves out on the grass,
-filled with contentment. They could have found a cooler place, but they
-would not deny themselves such a romantic feature as the roasting
-camp-fire.
-
-"AIN'T it gay?" said Joe.
-
-"It's NUTS!" said Tom. "What would the boys say if they could see us?"
-
-"Say? Well, they'd just die to be here--hey, Hucky!"
-
-"I reckon so," said Huckleberry; "anyways, I'm suited. I don't want
-nothing better'n this. I don't ever get enough to eat, gen'ally--and
-here they can't come and pick at a feller and bullyrag him so."
-
-"It's just the life for me," said Tom. "You don't have to get up,
-mornings, and you don't have to go to school, and wash, and all that
-blame foolishness. You see a pirate don't have to do ANYTHING, Joe,
-when he's ashore, but a hermit HE has to be praying considerable, and
-then he don't have any fun, anyway, all by himself that way."
-
-"Oh yes, that's so," said Joe, "but I hadn't thought much about it,
-you know. I'd a good deal rather be a pirate, now that I've tried it."
-
-"You see," said Tom, "people don't go much on hermits, nowadays, like
-they used to in old times, but a pirate's always respected. And a
-hermit's got to sleep on the hardest place he can find, and put
-sackcloth and ashes on his head, and stand out in the rain, and--"
-
-"What does he put sackcloth and ashes on his head for?" inquired Huck.
-
-"I dono. But they've GOT to do it. Hermits always do. You'd have to do
-that if you was a hermit."
-
-"Dern'd if I would," said Huck.
-
-"Well, what would you do?"
-
-"I dono. But I wouldn't do that."
-
-"Why, Huck, you'd HAVE to. How'd you get around it?"
-
-"Why, I just wouldn't stand it. I'd run away."
-
-"Run away! Well, you WOULD be a nice old slouch of a hermit. You'd be
-a disgrace."
-
-The Red-Handed made no response, being better employed. He had
-finished gouging out a cob, and now he fitted a weed stem to it, loaded
-it with tobacco, and was pressing a coal to the charge and blowing a
-cloud of fragrant smoke--he was in the full bloom of luxurious
-contentment. The other pirates envied him this majestic vice, and
-secretly resolved to acquire it shortly. Presently Huck said:
-
-"What does pirates have to do?"
-
-Tom said:
-
-"Oh, they have just a bully time--take ships and burn them, and get
-the money and bury it in awful places in their island where there's
-ghosts and things to watch it, and kill everybody in the ships--make
-'em walk a plank."
-
-"And they carry the women to the island," said Joe; "they don't kill
-the women."
-
-"No," assented Tom, "they don't kill the women--they're too noble. And
-the women's always beautiful, too.
-
-"And don't they wear the bulliest clothes! Oh no! All gold and silver
-and di'monds," said Joe, with enthusiasm.
-
-"Who?" said Huck.
-
-"Why, the pirates."
-
-Huck scanned his own clothing forlornly.
-
-"I reckon I ain't dressed fitten for a pirate," said he, with a
-regretful pathos in his voice; "but I ain't got none but these."
-
-But the other boys told him the fine clothes would come fast enough,
-after they should have begun their adventures. They made him understand
-that his poor rags would do to begin with, though it was customary for
-wealthy pirates to start with a proper wardrobe.
-
-Gradually their talk died out and drowsiness began to steal upon the
-eyelids of the little waifs. The pipe dropped from the fingers of the
-Red-Handed, and he slept the sleep of the conscience-free and the
-weary. The Terror of the Seas and the Black Avenger of the Spanish Main
-had more difficulty in getting to sleep. They said their prayers
-inwardly, and lying down, since there was nobody there with authority
-to make them kneel and recite aloud; in truth, they had a mind not to
-say them at all, but they were afraid to proceed to such lengths as
-that, lest they might call down a sudden and special thunderbolt from
-heaven. Then at once they reached and hovered upon the imminent verge
-of sleep--but an intruder came, now, that would not "down." It was
-conscience. They began to feel a vague fear that they had been doing
-wrong to run away; and next they thought of the stolen meat, and then
-the real torture came. They tried to argue it away by reminding
-conscience that they had purloined sweetmeats and apples scores of
-times; but conscience was not to be appeased by such thin
-plausibilities; it seemed to them, in the end, that there was no
-getting around the stubborn fact that taking sweetmeats was only
-"hooking," while taking bacon and hams and such valuables was plain
-simple stealing--and there was a command against that in the Bible. So
-they inwardly resolved that so long as they remained in the business,
-their piracies should not again be sullied with the crime of stealing.
-Then conscience granted a truce, and these curiously inconsistent
-pirates fell peacefully to sleep.
-
-
-
-CHAPTER XIV
-
-WHEN Tom awoke in the morning, he wondered where he was. He sat up and
-rubbed his eyes and looked around. Then he comprehended. It was the
-cool gray dawn, and there was a delicious sense of repose and peace in
-the deep pervading calm and silence of the woods. Not a leaf stirred;
-not a sound obtruded upon great Nature's meditation. Beaded dewdrops
-stood upon the leaves and grasses. A white layer of ashes covered the
-fire, and a thin blue breath of smoke rose straight into the air. Joe
-and Huck still slept.
-
-Now, far away in the woods a bird called; another answered; presently
-the hammering of a woodpecker was heard. Gradually the cool dim gray of
-the morning whitened, and as gradually sounds multiplied and life
-manifested itself. The marvel of Nature shaking off sleep and going to
-work unfolded itself to the musing boy. A little green worm came
-crawling over a dewy leaf, lifting two-thirds of his body into the air
-from time to time and "sniffing around," then proceeding again--for he
-was measuring, Tom said; and when the worm approached him, of its own
-accord, he sat as still as a stone, with his hopes rising and falling,
-by turns, as the creature still came toward him or seemed inclined to
-go elsewhere; and when at last it considered a painful moment with its
-curved body in the air and then came decisively down upon Tom's leg and
-began a journey over him, his whole heart was glad--for that meant that
-he was going to have a new suit of clothes--without the shadow of a
-doubt a gaudy piratical uniform. Now a procession of ants appeared,
-from nowhere in particular, and went about their labors; one struggled
-manfully by with a dead spider five times as big as itself in its arms,
-and lugged it straight up a tree-trunk. A brown spotted lady-bug
-climbed the dizzy height of a grass blade, and Tom bent down close to
-it and said, "Lady-bug, lady-bug, fly away home, your house is on fire,
-your children's alone," and she took wing and went off to see about it
---which did not surprise the boy, for he knew of old that this insect was
-credulous about conflagrations, and he had practised upon its
-simplicity more than once. A tumblebug came next, heaving sturdily at
-its ball, and Tom touched the creature, to see it shut its legs against
-its body and pretend to be dead. The birds were fairly rioting by this
-time. A catbird, the Northern mocker, lit in a tree over Tom's head,
-and trilled out her imitations of her neighbors in a rapture of
-enjoyment; then a shrill jay swept down, a flash of blue flame, and
-stopped on a twig almost within the boy's reach, cocked his head to one
-side and eyed the strangers with a consuming curiosity; a gray squirrel
-and a big fellow of the "fox" kind came skurrying along, sitting up at
-intervals to inspect and chatter at the boys, for the wild things had
-probably never seen a human being before and scarcely knew whether to
-be afraid or not. All Nature was wide awake and stirring, now; long
-lances of sunlight pierced down through the dense foliage far and near,
-and a few butterflies came fluttering upon the scene.
-
-Tom stirred up the other pirates and they all clattered away with a
-shout, and in a minute or two were stripped and chasing after and
-tumbling over each other in the shallow limpid water of the white
-sandbar. They felt no longing for the little village sleeping in the
-distance beyond the majestic waste of water. A vagrant current or a
-slight rise in the river had carried off their raft, but this only
-gratified them, since its going was something like burning the bridge
-between them and civilization.
-
-They came back to camp wonderfully refreshed, glad-hearted, and
-ravenous; and they soon had the camp-fire blazing up again. Huck found
-a spring of clear cold water close by, and the boys made cups of broad
-oak or hickory leaves, and felt that water, sweetened with such a
-wildwood charm as that, would be a good enough substitute for coffee.
-While Joe was slicing bacon for breakfast, Tom and Huck asked him to
-hold on a minute; they stepped to a promising nook in the river-bank
-and threw in their lines; almost immediately they had reward. Joe had
-not had time to get impatient before they were back again with some
-handsome bass, a couple of sun-perch and a small catfish--provisions
-enough for quite a family. They fried the fish with the bacon, and were
-astonished; for no fish had ever seemed so delicious before. They did
-not know that the quicker a fresh-water fish is on the fire after he is
-caught the better he is; and they reflected little upon what a sauce
-open-air sleeping, open-air exercise, bathing, and a large ingredient
-of hunger make, too.
-
-They lay around in the shade, after breakfast, while Huck had a smoke,
-and then went off through the woods on an exploring expedition. They
-tramped gayly along, over decaying logs, through tangled underbrush,
-among solemn monarchs of the forest, hung from their crowns to the
-ground with a drooping regalia of grape-vines. Now and then they came
-upon snug nooks carpeted with grass and jeweled with flowers.
-
-They found plenty of things to be delighted with, but nothing to be
-astonished at. They discovered that the island was about three miles
-long and a quarter of a mile wide, and that the shore it lay closest to
-was only separated from it by a narrow channel hardly two hundred yards
-wide. They took a swim about every hour, so it was close upon the
-middle of the afternoon when they got back to camp. They were too
-hungry to stop to fish, but they fared sumptuously upon cold ham, and
-then threw themselves down in the shade to talk. But the talk soon
-began to drag, and then died. The stillness, the solemnity that brooded
-in the woods, and the sense of loneliness, began to tell upon the
-spirits of the boys. They fell to thinking. A sort of undefined longing
-crept upon them. This took dim shape, presently--it was budding
-homesickness. Even Finn the Red-Handed was dreaming of his doorsteps
-and empty hogsheads. But they were all ashamed of their weakness, and
-none was brave enough to speak his thought.
-
-For some time, now, the boys had been dully conscious of a peculiar
-sound in the distance, just as one sometimes is of the ticking of a
-clock which he takes no distinct note of. But now this mysterious sound
-became more pronounced, and forced a recognition. The boys started,
-glanced at each other, and then each assumed a listening attitude.
-There was a long silence, profound and unbroken; then a deep, sullen
-boom came floating down out of the distance.
-
-"What is it!" exclaimed Joe, under his breath.
-
-"I wonder," said Tom in a whisper.
-
-"'Tain't thunder," said Huckleberry, in an awed tone, "becuz thunder--"
-
-"Hark!" said Tom. "Listen--don't talk."
-
-They waited a time that seemed an age, and then the same muffled boom
-troubled the solemn hush.
-
-"Let's go and see."
-
-They sprang to their feet and hurried to the shore toward the town.
-They parted the bushes on the bank and peered out over the water. The
-little steam ferryboat was about a mile below the village, drifting
-with the current. Her broad deck seemed crowded with people. There were
-a great many skiffs rowing about or floating with the stream in the
-neighborhood of the ferryboat, but the boys could not determine what
-the men in them were doing. Presently a great jet of white smoke burst
-from the ferryboat's side, and as it expanded and rose in a lazy cloud,
-that same dull throb of sound was borne to the listeners again.
-
-"I know now!" exclaimed Tom; "somebody's drownded!"
-
-"That's it!" said Huck; "they done that last summer, when Bill Turner
-got drownded; they shoot a cannon over the water, and that makes him
-come up to the top. Yes, and they take loaves of bread and put
-quicksilver in 'em and set 'em afloat, and wherever there's anybody
-that's drownded, they'll float right there and stop."
-
-"Yes, I've heard about that," said Joe. "I wonder what makes the bread
-do that."
-
-"Oh, it ain't the bread, so much," said Tom; "I reckon it's mostly
-what they SAY over it before they start it out."
-
-"But they don't say anything over it," said Huck. "I've seen 'em and
-they don't."
-
-"Well, that's funny," said Tom. "But maybe they say it to themselves.
-Of COURSE they do. Anybody might know that."
-
-The other boys agreed that there was reason in what Tom said, because
-an ignorant lump of bread, uninstructed by an incantation, could not be
-expected to act very intelligently when set upon an errand of such
-gravity.
-
-"By jings, I wish I was over there, now," said Joe.
-
-"I do too" said Huck "I'd give heaps to know who it is."
-
-The boys still listened and watched. Presently a revealing thought
-flashed through Tom's mind, and he exclaimed:
-
-"Boys, I know who's drownded--it's us!"
-
-They felt like heroes in an instant. Here was a gorgeous triumph; they
-were missed; they were mourned; hearts were breaking on their account;
-tears were being shed; accusing memories of unkindness to these poor
-lost lads were rising up, and unavailing regrets and remorse were being
-indulged; and best of all, the departed were the talk of the whole
-town, and the envy of all the boys, as far as this dazzling notoriety
-was concerned. This was fine. It was worth while to be a pirate, after
-all.
-
-As twilight drew on, the ferryboat went back to her accustomed
-business and the skiffs disappeared. The pirates returned to camp. They
-were jubilant with vanity over their new grandeur and the illustrious
-trouble they were making. They caught fish, cooked supper and ate it,
-and then fell to guessing at what the village was thinking and saying
-about them; and the pictures they drew of the public distress on their
-account were gratifying to look upon--from their point of view. But
-when the shadows of night closed them in, they gradually ceased to
-talk, and sat gazing into the fire, with their minds evidently
-wandering elsewhere. The excitement was gone, now, and Tom and Joe
-could not keep back thoughts of certain persons at home who were not
-enjoying this fine frolic as much as they were. Misgivings came; they
-grew troubled and unhappy; a sigh or two escaped, unawares. By and by
-Joe timidly ventured upon a roundabout "feeler" as to how the others
-might look upon a return to civilization--not right now, but--
-
-Tom withered him with derision! Huck, being uncommitted as yet, joined
-in with Tom, and the waverer quickly "explained," and was glad to get
-out of the scrape with as little taint of chicken-hearted homesickness
-clinging to his garments as he could. Mutiny was effectually laid to
-rest for the moment.
-
-As the night deepened, Huck began to nod, and presently to snore. Joe
-followed next. Tom lay upon his elbow motionless, for some time,
-watching the two intently. At last he got up cautiously, on his knees,
-and went searching among the grass and the flickering reflections flung
-by the camp-fire. He picked up and inspected several large
-semi-cylinders of the thin white bark of a sycamore, and finally chose
-two which seemed to suit him. Then he knelt by the fire and painfully
-wrote something upon each of these with his "red keel"; one he rolled up
-and put in his jacket pocket, and the other he put in Joe's hat and
-removed it to a little distance from the owner. And he also put into the
-hat certain schoolboy treasures of almost inestimable value--among them
-a lump of chalk, an India-rubber ball, three fishhooks, and one of that
-kind of marbles known as a "sure 'nough crystal." Then he tiptoed his
-way cautiously among the trees till he felt that he was out of hearing,
-and straightway broke into a keen run in the direction of the sandbar.
-
-
-
-CHAPTER XV
-
-A FEW minutes later Tom was in the shoal water of the bar, wading
-toward the Illinois shore. Before the depth reached his middle he was
-half-way over; the current would permit no more wading, now, so he
-struck out confidently to swim the remaining hundred yards. He swam
-quartering upstream, but still was swept downward rather faster than he
-had expected. However, he reached the shore finally, and drifted along
-till he found a low place and drew himself out. He put his hand on his
-jacket pocket, found his piece of bark safe, and then struck through
-the woods, following the shore, with streaming garments. Shortly before
-ten o'clock he came out into an open place opposite the village, and
-saw the ferryboat lying in the shadow of the trees and the high bank.
-Everything was quiet under the blinking stars. He crept down the bank,
-watching with all his eyes, slipped into the water, swam three or four
-strokes and climbed into the skiff that did "yawl" duty at the boat's
-stern. He laid himself down under the thwarts and waited, panting.
-
-Presently the cracked bell tapped and a voice gave the order to "cast
-off." A minute or two later the skiff's head was standing high up,
-against the boat's swell, and the voyage was begun. Tom felt happy in
-his success, for he knew it was the boat's last trip for the night. At
-the end of a long twelve or fifteen minutes the wheels stopped, and Tom
-slipped overboard and swam ashore in the dusk, landing fifty yards
-downstream, out of danger of possible stragglers.
-
-He flew along unfrequented alleys, and shortly found himself at his
-aunt's back fence. He climbed over, approached the "ell," and looked in
-at the sitting-room window, for a light was burning there. There sat
-Aunt Polly, Sid, Mary, and Joe Harper's mother, grouped together,
-talking. They were by the bed, and the bed was between them and the
-door. Tom went to the door and began to softly lift the latch; then he
-pressed gently and the door yielded a crack; he continued pushing
-cautiously, and quaking every time it creaked, till he judged he might
-squeeze through on his knees; so he put his head through and began,
-warily.
-
-"What makes the candle blow so?" said Aunt Polly. Tom hurried up.
-"Why, that door's open, I believe. Why, of course it is. No end of
-strange things now. Go 'long and shut it, Sid."
-
-Tom disappeared under the bed just in time. He lay and "breathed"
-himself for a time, and then crept to where he could almost touch his
-aunt's foot.
-
-"But as I was saying," said Aunt Polly, "he warn't BAD, so to say
---only mischEEvous. Only just giddy, and harum-scarum, you know. He
-warn't any more responsible than a colt. HE never meant any harm, and
-he was the best-hearted boy that ever was"--and she began to cry.
-
-"It was just so with my Joe--always full of his devilment, and up to
-every kind of mischief, but he was just as unselfish and kind as he
-could be--and laws bless me, to think I went and whipped him for taking
-that cream, never once recollecting that I throwed it out myself
-because it was sour, and I never to see him again in this world, never,
-never, never, poor abused boy!" And Mrs. Harper sobbed as if her heart
-would break.
-
-"I hope Tom's better off where he is," said Sid, "but if he'd been
-better in some ways--"
-
-"SID!" Tom felt the glare of the old lady's eye, though he could not
-see it. "Not a word against my Tom, now that he's gone! God'll take
-care of HIM--never you trouble YOURself, sir! Oh, Mrs. Harper, I don't
-know how to give him up! I don't know how to give him up! He was such a
-comfort to me, although he tormented my old heart out of me, 'most."
-
-"The Lord giveth and the Lord hath taken away--Blessed be the name of
-the Lord! But it's so hard--Oh, it's so hard! Only last Saturday my
-Joe busted a firecracker right under my nose and I knocked him
-sprawling. Little did I know then, how soon--Oh, if it was to do over
-again I'd hug him and bless him for it."
-
-"Yes, yes, yes, I know just how you feel, Mrs. Harper, I know just
-exactly how you feel. No longer ago than yesterday noon, my Tom took
-and filled the cat full of Pain-killer, and I did think the cretur
-would tear the house down. And God forgive me, I cracked Tom's head
-with my thimble, poor boy, poor dead boy. But he's out of all his
-troubles now. And the last words I ever heard him say was to reproach--"
-
-But this memory was too much for the old lady, and she broke entirely
-down. Tom was snuffling, now, himself--and more in pity of himself than
-anybody else. He could hear Mary crying, and putting in a kindly word
-for him from time to time. He began to have a nobler opinion of himself
-than ever before. Still, he was sufficiently touched by his aunt's
-grief to long to rush out from under the bed and overwhelm her with
-joy--and the theatrical gorgeousness of the thing appealed strongly to
-his nature, too, but he resisted and lay still.
-
-He went on listening, and gathered by odds and ends that it was
-conjectured at first that the boys had got drowned while taking a swim;
-then the small raft had been missed; next, certain boys said the
-missing lads had promised that the village should "hear something"
-soon; the wise-heads had "put this and that together" and decided that
-the lads had gone off on that raft and would turn up at the next town
-below, presently; but toward noon the raft had been found, lodged
-against the Missouri shore some five or six miles below the village
---and then hope perished; they must be drowned, else hunger would have
-driven them home by nightfall if not sooner. It was believed that the
-search for the bodies had been a fruitless effort merely because the
-drowning must have occurred in mid-channel, since the boys, being good
-swimmers, would otherwise have escaped to shore. This was Wednesday
-night. If the bodies continued missing until Sunday, all hope would be
-given over, and the funerals would be preached on that morning. Tom
-shuddered.
-
-Mrs. Harper gave a sobbing good-night and turned to go. Then with a
-mutual impulse the two bereaved women flung themselves into each
-other's arms and had a good, consoling cry, and then parted. Aunt Polly
-was tender far beyond her wont, in her good-night to Sid and Mary. Sid
-snuffled a bit and Mary went off crying with all her heart.
-
-Aunt Polly knelt down and prayed for Tom so touchingly, so
-appealingly, and with such measureless love in her words and her old
-trembling voice, that he was weltering in tears again, long before she
-was through.
-
-He had to keep still long after she went to bed, for she kept making
-broken-hearted ejaculations from time to time, tossing unrestfully, and
-turning over. But at last she was still, only moaning a little in her
-sleep. Now the boy stole out, rose gradually by the bedside, shaded the
-candle-light with his hand, and stood regarding her. His heart was full
-of pity for her. He took out his sycamore scroll and placed it by the
-candle. But something occurred to him, and he lingered considering. His
-face lighted with a happy solution of his thought; he put the bark
-hastily in his pocket. Then he bent over and kissed the faded lips, and
-straightway made his stealthy exit, latching the door behind him.
-
-He threaded his way back to the ferry landing, found nobody at large
-there, and walked boldly on board the boat, for he knew she was
-tenantless except that there was a watchman, who always turned in and
-slept like a graven image. He untied the skiff at the stern, slipped
-into it, and was soon rowing cautiously upstream. When he had pulled a
-mile above the village, he started quartering across and bent himself
-stoutly to his work. He hit the landing on the other side neatly, for
-this was a familiar bit of work to him. He was moved to capture the
-skiff, arguing that it might be considered a ship and therefore
-legitimate prey for a pirate, but he knew a thorough search would be
-made for it and that might end in revelations. So he stepped ashore and
-entered the woods.
-
-He sat down and took a long rest, torturing himself meanwhile to keep
-awake, and then started warily down the home-stretch. The night was far
-spent. It was broad daylight before he found himself fairly abreast the
-island bar. He rested again until the sun was well up and gilding the
-great river with its splendor, and then he plunged into the stream. A
-little later he paused, dripping, upon the threshold of the camp, and
-heard Joe say:
-
-"No, Tom's true-blue, Huck, and he'll come back. He won't desert. He
-knows that would be a disgrace to a pirate, and Tom's too proud for
-that sort of thing. He's up to something or other. Now I wonder what?"
-
-"Well, the things is ours, anyway, ain't they?"
-
-"Pretty near, but not yet, Huck. The writing says they are if he ain't
-back here to breakfast."
-
-"Which he is!" exclaimed Tom, with fine dramatic effect, stepping
-grandly into camp.
-
-A sumptuous breakfast of bacon and fish was shortly provided, and as
-the boys set to work upon it, Tom recounted (and adorned) his
-adventures. They were a vain and boastful company of heroes when the
-tale was done. Then Tom hid himself away in a shady nook to sleep till
-noon, and the other pirates got ready to fish and explore.
-
-
-
-CHAPTER XVI
-
-AFTER dinner all the gang turned out to hunt for turtle eggs on the
-bar. They went about poking sticks into the sand, and when they found a
-soft place they went down on their knees and dug with their hands.
-Sometimes they would take fifty or sixty eggs out of one hole. They
-were perfectly round white things a trifle smaller than an English
-walnut. They had a famous fried-egg feast that night, and another on
-Friday morning.
-
-After breakfast they went whooping and prancing out on the bar, and
-chased each other round and round, shedding clothes as they went, until
-they were naked, and then continued the frolic far away up the shoal
-water of the bar, against the stiff current, which latter tripped their
-legs from under them from time to time and greatly increased the fun.
-And now and then they stooped in a group and splashed water in each
-other's faces with their palms, gradually approaching each other, with
-averted faces to avoid the strangling sprays, and finally gripping and
-struggling till the best man ducked his neighbor, and then they all
-went under in a tangle of white legs and arms and came up blowing,
-sputtering, laughing, and gasping for breath at one and the same time.
-
-When they were well exhausted, they would run out and sprawl on the
-dry, hot sand, and lie there and cover themselves up with it, and by
-and by break for the water again and go through the original
-performance once more. Finally it occurred to them that their naked
-skin represented flesh-colored "tights" very fairly; so they drew a
-ring in the sand and had a circus--with three clowns in it, for none
-would yield this proudest post to his neighbor.
-
-Next they got their marbles and played "knucks" and "ring-taw" and
-"keeps" till that amusement grew stale. Then Joe and Huck had another
-swim, but Tom would not venture, because he found that in kicking off
-his trousers he had kicked his string of rattlesnake rattles off his
-ankle, and he wondered how he had escaped cramp so long without the
-protection of this mysterious charm. He did not venture again until he
-had found it, and by that time the other boys were tired and ready to
-rest. They gradually wandered apart, dropped into the "dumps," and fell
-to gazing longingly across the wide river to where the village lay
-drowsing in the sun. Tom found himself writing "BECKY" in the sand with
-his big toe; he scratched it out, and was angry with himself for his
-weakness. But he wrote it again, nevertheless; he could not help it. He
-erased it once more and then took himself out of temptation by driving
-the other boys together and joining them.
-
-But Joe's spirits had gone down almost beyond resurrection. He was so
-homesick that he could hardly endure the misery of it. The tears lay
-very near the surface. Huck was melancholy, too. Tom was downhearted,
-but tried hard not to show it. He had a secret which he was not ready
-to tell, yet, but if this mutinous depression was not broken up soon,
-he would have to bring it out. He said, with a great show of
-cheerfulness:
-
-"I bet there's been pirates on this island before, boys. We'll explore
-it again. They've hid treasures here somewhere. How'd you feel to light
-on a rotten chest full of gold and silver--hey?"
-
-But it roused only faint enthusiasm, which faded out, with no reply.
-Tom tried one or two other seductions; but they failed, too. It was
-discouraging work. Joe sat poking up the sand with a stick and looking
-very gloomy. Finally he said:
-
-"Oh, boys, let's give it up. I want to go home. It's so lonesome."
-
-"Oh no, Joe, you'll feel better by and by," said Tom. "Just think of
-the fishing that's here."
-
-"I don't care for fishing. I want to go home."
-
-"But, Joe, there ain't such another swimming-place anywhere."
-
-"Swimming's no good. I don't seem to care for it, somehow, when there
-ain't anybody to say I sha'n't go in. I mean to go home."
-
-"Oh, shucks! Baby! You want to see your mother, I reckon."
-
-"Yes, I DO want to see my mother--and you would, too, if you had one.
-I ain't any more baby than you are." And Joe snuffled a little.
-
-"Well, we'll let the cry-baby go home to his mother, won't we, Huck?
-Poor thing--does it want to see its mother? And so it shall. You like
-it here, don't you, Huck? We'll stay, won't we?"
-
-Huck said, "Y-e-s"--without any heart in it.
-
-"I'll never speak to you again as long as I live," said Joe, rising.
-"There now!" And he moved moodily away and began to dress himself.
-
-"Who cares!" said Tom. "Nobody wants you to. Go 'long home and get
-laughed at. Oh, you're a nice pirate. Huck and me ain't cry-babies.
-We'll stay, won't we, Huck? Let him go if he wants to. I reckon we can
-get along without him, per'aps."
-
-But Tom was uneasy, nevertheless, and was alarmed to see Joe go
-sullenly on with his dressing. And then it was discomforting to see
-Huck eying Joe's preparations so wistfully, and keeping up such an
-ominous silence. Presently, without a parting word, Joe began to wade
-off toward the Illinois shore. Tom's heart began to sink. He glanced at
-Huck. Huck could not bear the look, and dropped his eyes. Then he said:
-
-"I want to go, too, Tom. It was getting so lonesome anyway, and now
-it'll be worse. Let's us go, too, Tom."
-
-"I won't! You can all go, if you want to. I mean to stay."
-
-"Tom, I better go."
-
-"Well, go 'long--who's hendering you."
-
-Huck began to pick up his scattered clothes. He said:
-
-"Tom, I wisht you'd come, too. Now you think it over. We'll wait for
-you when we get to shore."
-
-"Well, you'll wait a blame long time, that's all."
-
-Huck started sorrowfully away, and Tom stood looking after him, with a
-strong desire tugging at his heart to yield his pride and go along too.
-He hoped the boys would stop, but they still waded slowly on. It
-suddenly dawned on Tom that it was become very lonely and still. He
-made one final struggle with his pride, and then darted after his
-comrades, yelling:
-
-"Wait! Wait! I want to tell you something!"
-
-They presently stopped and turned around. When he got to where they
-were, he began unfolding his secret, and they listened moodily till at
-last they saw the "point" he was driving at, and then they set up a
-war-whoop of applause and said it was "splendid!" and said if he had
-told them at first, they wouldn't have started away. He made a plausible
-excuse; but his real reason had been the fear that not even the secret
-would keep them with him any very great length of time, and so he had
-meant to hold it in reserve as a last seduction.
-
-The lads came gayly back and went at their sports again with a will,
-chattering all the time about Tom's stupendous plan and admiring the
-genius of it. After a dainty egg and fish dinner, Tom said he wanted to
-learn to smoke, now. Joe caught at the idea and said he would like to
-try, too. So Huck made pipes and filled them. These novices had never
-smoked anything before but cigars made of grape-vine, and they "bit"
-the tongue, and were not considered manly anyway.
-
-Now they stretched themselves out on their elbows and began to puff,
-charily, and with slender confidence. The smoke had an unpleasant
-taste, and they gagged a little, but Tom said:
-
-"Why, it's just as easy! If I'd a knowed this was all, I'd a learnt
-long ago."
-
-"So would I," said Joe. "It's just nothing."
-
-"Why, many a time I've looked at people smoking, and thought well I
-wish I could do that; but I never thought I could," said Tom.
-
-"That's just the way with me, hain't it, Huck? You've heard me talk
-just that way--haven't you, Huck? I'll leave it to Huck if I haven't."
-
-"Yes--heaps of times," said Huck.
-
-"Well, I have too," said Tom; "oh, hundreds of times. Once down by the
-slaughter-house. Don't you remember, Huck? Bob Tanner was there, and
-Johnny Miller, and Jeff Thatcher, when I said it. Don't you remember,
-Huck, 'bout me saying that?"
-
-"Yes, that's so," said Huck. "That was the day after I lost a white
-alley. No, 'twas the day before."
-
-"There--I told you so," said Tom. "Huck recollects it."
-
-"I bleeve I could smoke this pipe all day," said Joe. "I don't feel
-sick."
-
-"Neither do I," said Tom. "I could smoke it all day. But I bet you
-Jeff Thatcher couldn't."
-
-"Jeff Thatcher! Why, he'd keel over just with two draws. Just let him
-try it once. HE'D see!"
-
-"I bet he would. And Johnny Miller--I wish could see Johnny Miller
-tackle it once."
-
-"Oh, don't I!" said Joe. "Why, I bet you Johnny Miller couldn't any
-more do this than nothing. Just one little snifter would fetch HIM."
-
-"'Deed it would, Joe. Say--I wish the boys could see us now."
-
-"So do I."
-
-"Say--boys, don't say anything about it, and some time when they're
-around, I'll come up to you and say, 'Joe, got a pipe? I want a smoke.'
-And you'll say, kind of careless like, as if it warn't anything, you'll
-say, 'Yes, I got my OLD pipe, and another one, but my tobacker ain't
-very good.' And I'll say, 'Oh, that's all right, if it's STRONG
-enough.' And then you'll out with the pipes, and we'll light up just as
-ca'm, and then just see 'em look!"
-
-"By jings, that'll be gay, Tom! I wish it was NOW!"
-
-"So do I! And when we tell 'em we learned when we was off pirating,
-won't they wish they'd been along?"
-
-"Oh, I reckon not! I'll just BET they will!"
-
-So the talk ran on. But presently it began to flag a trifle, and grow
-disjointed. The silences widened; the expectoration marvellously
-increased. Every pore inside the boys' cheeks became a spouting
-fountain; they could scarcely bail out the cellars under their tongues
-fast enough to prevent an inundation; little overflowings down their
-throats occurred in spite of all they could do, and sudden retchings
-followed every time. Both boys were looking very pale and miserable,
-now. Joe's pipe dropped from his nerveless fingers. Tom's followed.
-Both fountains were going furiously and both pumps bailing with might
-and main. Joe said feebly:
-
-"I've lost my knife. I reckon I better go and find it."
-
-Tom said, with quivering lips and halting utterance:
-
-"I'll help you. You go over that way and I'll hunt around by the
-spring. No, you needn't come, Huck--we can find it."
-
-So Huck sat down again, and waited an hour. Then he found it lonesome,
-and went to find his comrades. They were wide apart in the woods, both
-very pale, both fast asleep. But something informed him that if they
-had had any trouble they had got rid of it.
-
-They were not talkative at supper that night. They had a humble look,
-and when Huck prepared his pipe after the meal and was going to prepare
-theirs, they said no, they were not feeling very well--something they
-ate at dinner had disagreed with them.
-
-About midnight Joe awoke, and called the boys. There was a brooding
-oppressiveness in the air that seemed to bode something. The boys
-huddled themselves together and sought the friendly companionship of
-the fire, though the dull dead heat of the breathless atmosphere was
-stifling. They sat still, intent and waiting. The solemn hush
-continued. Beyond the light of the fire everything was swallowed up in
-the blackness of darkness. Presently there came a quivering glow that
-vaguely revealed the foliage for a moment and then vanished. By and by
-another came, a little stronger. Then another. Then a faint moan came
-sighing through the branches of the forest and the boys felt a fleeting
-breath upon their cheeks, and shuddered with the fancy that the Spirit
-of the Night had gone by. There was a pause. Now a weird flash turned
-night into day and showed every little grass-blade, separate and
-distinct, that grew about their feet. And it showed three white,
-startled faces, too. A deep peal of thunder went rolling and tumbling
-down the heavens and lost itself in sullen rumblings in the distance. A
-sweep of chilly air passed by, rustling all the leaves and snowing the
-flaky ashes broadcast about the fire. Another fierce glare lit up the
-forest and an instant crash followed that seemed to rend the tree-tops
-right over the boys' heads. They clung together in terror, in the thick
-gloom that followed. A few big rain-drops fell pattering upon the
-leaves.
-
-"Quick! boys, go for the tent!" exclaimed Tom.
-
-They sprang away, stumbling over roots and among vines in the dark, no
-two plunging in the same direction. A furious blast roared through the
-trees, making everything sing as it went. One blinding flash after
-another came, and peal on peal of deafening thunder. And now a
-drenching rain poured down and the rising hurricane drove it in sheets
-along the ground. The boys cried out to each other, but the roaring
-wind and the booming thunder-blasts drowned their voices utterly.
-However, one by one they straggled in at last and took shelter under
-the tent, cold, scared, and streaming with water; but to have company
-in misery seemed something to be grateful for. They could not talk, the
-old sail flapped so furiously, even if the other noises would have
-allowed them. The tempest rose higher and higher, and presently the
-sail tore loose from its fastenings and went winging away on the blast.
-The boys seized each others' hands and fled, with many tumblings and
-bruises, to the shelter of a great oak that stood upon the river-bank.
-Now the battle was at its highest. Under the ceaseless conflagration of
-lightning that flamed in the skies, everything below stood out in
-clean-cut and shadowless distinctness: the bending trees, the billowy
-river, white with foam, the driving spray of spume-flakes, the dim
-outlines of the high bluffs on the other side, glimpsed through the
-drifting cloud-rack and the slanting veil of rain. Every little while
-some giant tree yielded the fight and fell crashing through the younger
-growth; and the unflagging thunder-peals came now in ear-splitting
-explosive bursts, keen and sharp, and unspeakably appalling. The storm
-culminated in one matchless effort that seemed likely to tear the island
-to pieces, burn it up, drown it to the tree-tops, blow it away, and
-deafen every creature in it, all at one and the same moment. It was a
-wild night for homeless young heads to be out in.
-
-But at last the battle was done, and the forces retired with weaker
-and weaker threatenings and grumblings, and peace resumed her sway. The
-boys went back to camp, a good deal awed; but they found there was
-still something to be thankful for, because the great sycamore, the
-shelter of their beds, was a ruin, now, blasted by the lightnings, and
-they were not under it when the catastrophe happened.
-
-Everything in camp was drenched, the camp-fire as well; for they were
-but heedless lads, like their generation, and had made no provision
-against rain. Here was matter for dismay, for they were soaked through
-and chilled. They were eloquent in their distress; but they presently
-discovered that the fire had eaten so far up under the great log it had
-been built against (where it curved upward and separated itself from
-the ground), that a handbreadth or so of it had escaped wetting; so
-they patiently wrought until, with shreds and bark gathered from the
-under sides of sheltered logs, they coaxed the fire to burn again. Then
-they piled on great dead boughs till they had a roaring furnace, and
-were glad-hearted once more. They dried their boiled ham and had a
-feast, and after that they sat by the fire and expanded and glorified
-their midnight adventure until morning, for there was not a dry spot to
-sleep on, anywhere around.
-
-As the sun began to steal in upon the boys, drowsiness came over them,
-and they went out on the sandbar and lay down to sleep. They got
-scorched out by and by, and drearily set about getting breakfast. After
-the meal they felt rusty, and stiff-jointed, and a little homesick once
-more. Tom saw the signs, and fell to cheering up the pirates as well as
-he could. But they cared nothing for marbles, or circus, or swimming,
-or anything. He reminded them of the imposing secret, and raised a ray
-of cheer. While it lasted, he got them interested in a new device. This
-was to knock off being pirates, for a while, and be Indians for a
-change. They were attracted by this idea; so it was not long before
-they were stripped, and striped from head to heel with black mud, like
-so many zebras--all of them chiefs, of course--and then they went
-tearing through the woods to attack an English settlement.
-
-By and by they separated into three hostile tribes, and darted upon
-each other from ambush with dreadful war-whoops, and killed and scalped
-each other by thousands. It was a gory day. Consequently it was an
-extremely satisfactory one.
-
-They assembled in camp toward supper-time, hungry and happy; but now a
-difficulty arose--hostile Indians could not break the bread of
-hospitality together without first making peace, and this was a simple
-impossibility without smoking a pipe of peace. There was no other
-process that ever they had heard of. Two of the savages almost wished
-they had remained pirates. However, there was no other way; so with
-such show of cheerfulness as they could muster they called for the pipe
-and took their whiff as it passed, in due form.
-
-And behold, they were glad they had gone into savagery, for they had
-gained something; they found that they could now smoke a little without
-having to go and hunt for a lost knife; they did not get sick enough to
-be seriously uncomfortable. They were not likely to fool away this high
-promise for lack of effort. No, they practised cautiously, after
-supper, with right fair success, and so they spent a jubilant evening.
-They were prouder and happier in their new acquirement than they would
-have been in the scalping and skinning of the Six Nations. We will
-leave them to smoke and chatter and brag, since we have no further use
-for them at present.
-
-
-
-CHAPTER XVII
-
-BUT there was no hilarity in the little town that same tranquil
-Saturday afternoon. The Harpers, and Aunt Polly's family, were being
-put into mourning, with great grief and many tears. An unusual quiet
-possessed the village, although it was ordinarily quiet enough, in all
-conscience. The villagers conducted their concerns with an absent air,
-and talked little; but they sighed often. The Saturday holiday seemed a
-burden to the children. They had no heart in their sports, and
-gradually gave them up.
-
-In the afternoon Becky Thatcher found herself moping about the
-deserted schoolhouse yard, and feeling very melancholy. But she found
-nothing there to comfort her. She soliloquized:
-
-"Oh, if I only had a brass andiron-knob again! But I haven't got
-anything now to remember him by." And she choked back a little sob.
-
-Presently she stopped, and said to herself:
-
-"It was right here. Oh, if it was to do over again, I wouldn't say
-that--I wouldn't say it for the whole world. But he's gone now; I'll
-never, never, never see him any more."
-
-This thought broke her down, and she wandered away, with tears rolling
-down her cheeks. Then quite a group of boys and girls--playmates of
-Tom's and Joe's--came by, and stood looking over the paling fence and
-talking in reverent tones of how Tom did so-and-so the last time they
-saw him, and how Joe said this and that small trifle (pregnant with
-awful prophecy, as they could easily see now!)--and each speaker
-pointed out the exact spot where the lost lads stood at the time, and
-then added something like "and I was a-standing just so--just as I am
-now, and as if you was him--I was as close as that--and he smiled, just
-this way--and then something seemed to go all over me, like--awful, you
-know--and I never thought what it meant, of course, but I can see now!"
-
-Then there was a dispute about who saw the dead boys last in life, and
-many claimed that dismal distinction, and offered evidences, more or
-less tampered with by the witness; and when it was ultimately decided
-who DID see the departed last, and exchanged the last words with them,
-the lucky parties took upon themselves a sort of sacred importance, and
-were gaped at and envied by all the rest. One poor chap, who had no
-other grandeur to offer, said with tolerably manifest pride in the
-remembrance:
-
-"Well, Tom Sawyer he licked me once."
-
-But that bid for glory was a failure. Most of the boys could say that,
-and so that cheapened the distinction too much. The group loitered
-away, still recalling memories of the lost heroes, in awed voices.
-
-When the Sunday-school hour was finished, the next morning, the bell
-began to toll, instead of ringing in the usual way. It was a very still
-Sabbath, and the mournful sound seemed in keeping with the musing hush
-that lay upon nature. The villagers began to gather, loitering a moment
-in the vestibule to converse in whispers about the sad event. But there
-was no whispering in the house; only the funereal rustling of dresses
-as the women gathered to their seats disturbed the silence there. None
-could remember when the little church had been so full before. There
-was finally a waiting pause, an expectant dumbness, and then Aunt Polly
-entered, followed by Sid and Mary, and they by the Harper family, all
-in deep black, and the whole congregation, the old minister as well,
-rose reverently and stood until the mourners were seated in the front
-pew. There was another communing silence, broken at intervals by
-muffled sobs, and then the minister spread his hands abroad and prayed.
-A moving hymn was sung, and the text followed: "I am the Resurrection
-and the Life."
-
-As the service proceeded, the clergyman drew such pictures of the
-graces, the winning ways, and the rare promise of the lost lads that
-every soul there, thinking he recognized these pictures, felt a pang in
-remembering that he had persistently blinded himself to them always
-before, and had as persistently seen only faults and flaws in the poor
-boys. The minister related many a touching incident in the lives of the
-departed, too, which illustrated their sweet, generous natures, and the
-people could easily see, now, how noble and beautiful those episodes
-were, and remembered with grief that at the time they occurred they had
-seemed rank rascalities, well deserving of the cowhide. The
-congregation became more and more moved, as the pathetic tale went on,
-till at last the whole company broke down and joined the weeping
-mourners in a chorus of anguished sobs, the preacher himself giving way
-to his feelings, and crying in the pulpit.
-
-There was a rustle in the gallery, which nobody noticed; a moment
-later the church door creaked; the minister raised his streaming eyes
-above his handkerchief, and stood transfixed! First one and then
-another pair of eyes followed the minister's, and then almost with one
-impulse the congregation rose and stared while the three dead boys came
-marching up the aisle, Tom in the lead, Joe next, and Huck, a ruin of
-drooping rags, sneaking sheepishly in the rear! They had been hid in
-the unused gallery listening to their own funeral sermon!
-
-Aunt Polly, Mary, and the Harpers threw themselves upon their restored
-ones, smothered them with kisses and poured out thanksgivings, while
-poor Huck stood abashed and uncomfortable, not knowing exactly what to
-do or where to hide from so many unwelcoming eyes. He wavered, and
-started to slink away, but Tom seized him and said:
-
-"Aunt Polly, it ain't fair. Somebody's got to be glad to see Huck."
-
-"And so they shall. I'm glad to see him, poor motherless thing!" And
-the loving attentions Aunt Polly lavished upon him were the one thing
-capable of making him more uncomfortable than he was before.
-
-Suddenly the minister shouted at the top of his voice: "Praise God
-from whom all blessings flow--SING!--and put your hearts in it!"
-
-And they did. Old Hundred swelled up with a triumphant burst, and
-while it shook the rafters Tom Sawyer the Pirate looked around upon the
-envying juveniles about him and confessed in his heart that this was
-the proudest moment of his life.
-
-As the "sold" congregation trooped out they said they would almost be
-willing to be made ridiculous again to hear Old Hundred sung like that
-once more.
-
-Tom got more cuffs and kisses that day--according to Aunt Polly's
-varying moods--than he had earned before in a year; and he hardly knew
-which expressed the most gratefulness to God and affection for himself.
-
-
-
-CHAPTER XVIII
-
-THAT was Tom's great secret--the scheme to return home with his
-brother pirates and attend their own funerals. They had paddled over to
-the Missouri shore on a log, at dusk on Saturday, landing five or six
-miles below the village; they had slept in the woods at the edge of the
-town till nearly daylight, and had then crept through back lanes and
-alleys and finished their sleep in the gallery of the church among a
-chaos of invalided benches.
-
-At breakfast, Monday morning, Aunt Polly and Mary were very loving to
-Tom, and very attentive to his wants. There was an unusual amount of
-talk. In the course of it Aunt Polly said:
-
-"Well, I don't say it wasn't a fine joke, Tom, to keep everybody
-suffering 'most a week so you boys had a good time, but it is a pity
-you could be so hard-hearted as to let me suffer so. If you could come
-over on a log to go to your funeral, you could have come over and give
-me a hint some way that you warn't dead, but only run off."
-
-"Yes, you could have done that, Tom," said Mary; "and I believe you
-would if you had thought of it."
-
-"Would you, Tom?" said Aunt Polly, her face lighting wistfully. "Say,
-now, would you, if you'd thought of it?"
-
-"I--well, I don't know. 'Twould 'a' spoiled everything."
-
-"Tom, I hoped you loved me that much," said Aunt Polly, with a grieved
-tone that discomforted the boy. "It would have been something if you'd
-cared enough to THINK of it, even if you didn't DO it."
-
-"Now, auntie, that ain't any harm," pleaded Mary; "it's only Tom's
-giddy way--he is always in such a rush that he never thinks of
-anything."
-
-"More's the pity. Sid would have thought. And Sid would have come and
-DONE it, too. Tom, you'll look back, some day, when it's too late, and
-wish you'd cared a little more for me when it would have cost you so
-little."
-
-"Now, auntie, you know I do care for you," said Tom.
-
-"I'd know it better if you acted more like it."
-
-"I wish now I'd thought," said Tom, with a repentant tone; "but I
-dreamt about you, anyway. That's something, ain't it?"
-
-"It ain't much--a cat does that much--but it's better than nothing.
-What did you dream?"
-
-"Why, Wednesday night I dreamt that you was sitting over there by the
-bed, and Sid was sitting by the woodbox, and Mary next to him."
-
-"Well, so we did. So we always do. I'm glad your dreams could take
-even that much trouble about us."
-
-"And I dreamt that Joe Harper's mother was here."
-
-"Why, she was here! Did you dream any more?"
-
-"Oh, lots. But it's so dim, now."
-
-"Well, try to recollect--can't you?"
-
-"Somehow it seems to me that the wind--the wind blowed the--the--"
-
-"Try harder, Tom! The wind did blow something. Come!"
-
-Tom pressed his fingers on his forehead an anxious minute, and then
-said:
-
-"I've got it now! I've got it now! It blowed the candle!"
-
-"Mercy on us! Go on, Tom--go on!"
-
-"And it seems to me that you said, 'Why, I believe that that door--'"
-
-"Go ON, Tom!"
-
-"Just let me study a moment--just a moment. Oh, yes--you said you
-believed the door was open."
-
-"As I'm sitting here, I did! Didn't I, Mary! Go on!"
-
-"And then--and then--well I won't be certain, but it seems like as if
-you made Sid go and--and--"
-
-"Well? Well? What did I make him do, Tom? What did I make him do?"
-
-"You made him--you--Oh, you made him shut it."
-
-"Well, for the land's sake! I never heard the beat of that in all my
-days! Don't tell ME there ain't anything in dreams, any more. Sereny
-Harper shall know of this before I'm an hour older. I'd like to see her
-get around THIS with her rubbage 'bout superstition. Go on, Tom!"
-
-"Oh, it's all getting just as bright as day, now. Next you said I
-warn't BAD, only mischeevous and harum-scarum, and not any more
-responsible than--than--I think it was a colt, or something."
-
-"And so it was! Well, goodness gracious! Go on, Tom!"
-
-"And then you began to cry."
-
-"So I did. So I did. Not the first time, neither. And then--"
-
-"Then Mrs. Harper she began to cry, and said Joe was just the same,
-and she wished she hadn't whipped him for taking cream when she'd
-throwed it out her own self--"
-
-"Tom! The sperrit was upon you! You was a prophesying--that's what you
-was doing! Land alive, go on, Tom!"
-
-"Then Sid he said--he said--"
-
-"I don't think I said anything," said Sid.
-
-"Yes you did, Sid," said Mary.
-
-"Shut your heads and let Tom go on! What did he say, Tom?"
-
-"He said--I THINK he said he hoped I was better off where I was gone
-to, but if I'd been better sometimes--"
-
-"THERE, d'you hear that! It was his very words!"
-
-"And you shut him up sharp."
-
-"I lay I did! There must 'a' been an angel there. There WAS an angel
-there, somewheres!"
-
-"And Mrs. Harper told about Joe scaring her with a firecracker, and
-you told about Peter and the Painkiller--"
-
-"Just as true as I live!"
-
-"And then there was a whole lot of talk 'bout dragging the river for
-us, and 'bout having the funeral Sunday, and then you and old Miss
-Harper hugged and cried, and she went."
-
-"It happened just so! It happened just so, as sure as I'm a-sitting in
-these very tracks. Tom, you couldn't told it more like if you'd 'a'
-seen it! And then what? Go on, Tom!"
-
-"Then I thought you prayed for me--and I could see you and hear every
-word you said. And you went to bed, and I was so sorry that I took and
-wrote on a piece of sycamore bark, 'We ain't dead--we are only off
-being pirates,' and put it on the table by the candle; and then you
-looked so good, laying there asleep, that I thought I went and leaned
-over and kissed you on the lips."
-
-"Did you, Tom, DID you! I just forgive you everything for that!" And
-she seized the boy in a crushing embrace that made him feel like the
-guiltiest of villains.
-
-"It was very kind, even though it was only a--dream," Sid soliloquized
-just audibly.
-
-"Shut up, Sid! A body does just the same in a dream as he'd do if he
-was awake. Here's a big Milum apple I've been saving for you, Tom, if
-you was ever found again--now go 'long to school. I'm thankful to the
-good God and Father of us all I've got you back, that's long-suffering
-and merciful to them that believe on Him and keep His word, though
-goodness knows I'm unworthy of it, but if only the worthy ones got His
-blessings and had His hand to help them over the rough places, there's
-few enough would smile here or ever enter into His rest when the long
-night comes. Go 'long Sid, Mary, Tom--take yourselves off--you've
-hendered me long enough."
-
-The children left for school, and the old lady to call on Mrs. Harper
-and vanquish her realism with Tom's marvellous dream. Sid had better
-judgment than to utter the thought that was in his mind as he left the
-house. It was this: "Pretty thin--as long a dream as that, without any
-mistakes in it!"
-
-What a hero Tom was become, now! He did not go skipping and prancing,
-but moved with a dignified swagger as became a pirate who felt that the
-public eye was on him. And indeed it was; he tried not to seem to see
-the looks or hear the remarks as he passed along, but they were food
-and drink to him. Smaller boys than himself flocked at his heels, as
-proud to be seen with him, and tolerated by him, as if he had been the
-drummer at the head of a procession or the elephant leading a menagerie
-into town. Boys of his own size pretended not to know he had been away
-at all; but they were consuming with envy, nevertheless. They would
-have given anything to have that swarthy suntanned skin of his, and his
-glittering notoriety; and Tom would not have parted with either for a
-circus.
-
-At school the children made so much of him and of Joe, and delivered
-such eloquent admiration from their eyes, that the two heroes were not
-long in becoming insufferably "stuck-up." They began to tell their
-adventures to hungry listeners--but they only began; it was not a thing
-likely to have an end, with imaginations like theirs to furnish
-material. And finally, when they got out their pipes and went serenely
-puffing around, the very summit of glory was reached.
-
-Tom decided that he could be independent of Becky Thatcher now. Glory
-was sufficient. He would live for glory. Now that he was distinguished,
-maybe she would be wanting to "make up." Well, let her--she should see
-that he could be as indifferent as some other people. Presently she
-arrived. Tom pretended not to see her. He moved away and joined a group
-of boys and girls and began to talk. Soon he observed that she was
-tripping gayly back and forth with flushed face and dancing eyes,
-pretending to be busy chasing schoolmates, and screaming with laughter
-when she made a capture; but he noticed that she always made her
-captures in his vicinity, and that she seemed to cast a conscious eye
-in his direction at such times, too. It gratified all the vicious
-vanity that was in him; and so, instead of winning him, it only "set
-him up" the more and made him the more diligent to avoid betraying that
-he knew she was about. Presently she gave over skylarking, and moved
-irresolutely about, sighing once or twice and glancing furtively and
-wistfully toward Tom. Then she observed that now Tom was talking more
-particularly to Amy Lawrence than to any one else. She felt a sharp
-pang and grew disturbed and uneasy at once. She tried to go away, but
-her feet were treacherous, and carried her to the group instead. She
-said to a girl almost at Tom's elbow--with sham vivacity:
-
-"Why, Mary Austin! you bad girl, why didn't you come to Sunday-school?"
-
-"I did come--didn't you see me?"
-
-"Why, no! Did you? Where did you sit?"
-
-"I was in Miss Peters' class, where I always go. I saw YOU."
-
-"Did you? Why, it's funny I didn't see you. I wanted to tell you about
-the picnic."
-
-"Oh, that's jolly. Who's going to give it?"
-
-"My ma's going to let me have one."
-
-"Oh, goody; I hope she'll let ME come."
-
-"Well, she will. The picnic's for me. She'll let anybody come that I
-want, and I want you."
-
-"That's ever so nice. When is it going to be?"
-
-"By and by. Maybe about vacation."
-
-"Oh, won't it be fun! You going to have all the girls and boys?"
-
-"Yes, every one that's friends to me--or wants to be"; and she glanced
-ever so furtively at Tom, but he talked right along to Amy Lawrence
-about the terrible storm on the island, and how the lightning tore the
-great sycamore tree "all to flinders" while he was "standing within
-three feet of it."
-
-"Oh, may I come?" said Grace Miller.
-
-"Yes."
-
-"And me?" said Sally Rogers.
-
-"Yes."
-
-"And me, too?" said Susy Harper. "And Joe?"
-
-"Yes."
-
-And so on, with clapping of joyful hands till all the group had begged
-for invitations but Tom and Amy. Then Tom turned coolly away, still
-talking, and took Amy with him. Becky's lips trembled and the tears
-came to her eyes; she hid these signs with a forced gayety and went on
-chattering, but the life had gone out of the picnic, now, and out of
-everything else; she got away as soon as she could and hid herself and
-had what her sex call "a good cry." Then she sat moody, with wounded
-pride, till the bell rang. She roused up, now, with a vindictive cast
-in her eye, and gave her plaited tails a shake and said she knew what
-SHE'D do.
-
-At recess Tom continued his flirtation with Amy with jubilant
-self-satisfaction. And he kept drifting about to find Becky and lacerate
-her with the performance. At last he spied her, but there was a sudden
-falling of his mercury. She was sitting cosily on a little bench behind
-the schoolhouse looking at a picture-book with Alfred Temple--and so
-absorbed were they, and their heads so close together over the book,
-that they did not seem to be conscious of anything in the world besides.
-Jealousy ran red-hot through Tom's veins. He began to hate himself for
-throwing away the chance Becky had offered for a reconciliation. He
-called himself a fool, and all the hard names he could think of. He
-wanted to cry with vexation. Amy chatted happily along, as they walked,
-for her heart was singing, but Tom's tongue had lost its function. He
-did not hear what Amy was saying, and whenever she paused expectantly he
-could only stammer an awkward assent, which was as often misplaced as
-otherwise. He kept drifting to the rear of the schoolhouse, again and
-again, to sear his eyeballs with the hateful spectacle there. He could
-not help it. And it maddened him to see, as he thought he saw, that
-Becky Thatcher never once suspected that he was even in the land of the
-living. But she did see, nevertheless; and she knew she was winning her
-fight, too, and was glad to see him suffer as she had suffered.
-
-Amy's happy prattle became intolerable. Tom hinted at things he had to
-attend to; things that must be done; and time was fleeting. But in
-vain--the girl chirped on. Tom thought, "Oh, hang her, ain't I ever
-going to get rid of her?" At last he must be attending to those
-things--and she said artlessly that she would be "around" when school
-let out. And he hastened away, hating her for it.
-
-"Any other boy!" Tom thought, grating his teeth. "Any boy in the whole
-town but that Saint Louis smarty that thinks he dresses so fine and is
-aristocracy! Oh, all right, I licked you the first day you ever saw
-this town, mister, and I'll lick you again! You just wait till I catch
-you out! I'll just take and--"
-
-And he went through the motions of thrashing an imaginary boy
---pummelling the air, and kicking and gouging. "Oh, you do, do you? You
-holler 'nough, do you? Now, then, let that learn you!" And so the
-imaginary flogging was finished to his satisfaction.
-
-Tom fled home at noon. His conscience could not endure any more of
-Amy's grateful happiness, and his jealousy could bear no more of the
-other distress. Becky resumed her picture inspections with Alfred, but
-as the minutes dragged along and no Tom came to suffer, her triumph
-began to cloud and she lost interest; gravity and absent-mindedness
-followed, and then melancholy; two or three times she pricked up her
-ear at a footstep, but it was a false hope; no Tom came. At last she
-grew entirely miserable and wished she hadn't carried it so far. When
-poor Alfred, seeing that he was losing her, he did not know how, kept
-exclaiming: "Oh, here's a jolly one! look at this!" she lost patience
-at last, and said, "Oh, don't bother me! I don't care for them!" and
-burst into tears, and got up and walked away.
-
-Alfred dropped alongside and was going to try to comfort her, but she
-said:
-
-"Go away and leave me alone, can't you! I hate you!"
-
-So the boy halted, wondering what he could have done--for she had said
-she would look at pictures all through the nooning--and she walked on,
-crying. Then Alfred went musing into the deserted schoolhouse. He was
-humiliated and angry. He easily guessed his way to the truth--the girl
-had simply made a convenience of him to vent her spite upon Tom Sawyer.
-He was far from hating Tom the less when this thought occurred to him.
-He wished there was some way to get that boy into trouble without much
-risk to himself. Tom's spelling-book fell under his eye. Here was his
-opportunity. He gratefully opened to the lesson for the afternoon and
-poured ink upon the page.
-
-Becky, glancing in at a window behind him at the moment, saw the act,
-and moved on, without discovering herself. She started homeward, now,
-intending to find Tom and tell him; Tom would be thankful and their
-troubles would be healed. Before she was half way home, however, she
-had changed her mind. The thought of Tom's treatment of her when she
-was talking about her picnic came scorching back and filled her with
-shame. She resolved to let him get whipped on the damaged
-spelling-book's account, and to hate him forever, into the bargain.
-
-
-
-CHAPTER XIX
-
-TOM arrived at home in a dreary mood, and the first thing his aunt
-said to him showed him that he had brought his sorrows to an
-unpromising market:
-
-"Tom, I've a notion to skin you alive!"
-
-"Auntie, what have I done?"
-
-"Well, you've done enough. Here I go over to Sereny Harper, like an
-old softy, expecting I'm going to make her believe all that rubbage
-about that dream, when lo and behold you she'd found out from Joe that
-you was over here and heard all the talk we had that night. Tom, I
-don't know what is to become of a boy that will act like that. It makes
-me feel so bad to think you could let me go to Sereny Harper and make
-such a fool of myself and never say a word."
-
-This was a new aspect of the thing. His smartness of the morning had
-seemed to Tom a good joke before, and very ingenious. It merely looked
-mean and shabby now. He hung his head and could not think of anything
-to say for a moment. Then he said:
-
-"Auntie, I wish I hadn't done it--but I didn't think."
-
-"Oh, child, you never think. You never think of anything but your own
-selfishness. You could think to come all the way over here from
-Jackson's Island in the night to laugh at our troubles, and you could
-think to fool me with a lie about a dream; but you couldn't ever think
-to pity us and save us from sorrow."
-
-"Auntie, I know now it was mean, but I didn't mean to be mean. I
-didn't, honest. And besides, I didn't come over here to laugh at you
-that night."
-
-"What did you come for, then?"
-
-"It was to tell you not to be uneasy about us, because we hadn't got
-drownded."
-
-"Tom, Tom, I would be the thankfullest soul in this world if I could
-believe you ever had as good a thought as that, but you know you never
-did--and I know it, Tom."
-
-"Indeed and 'deed I did, auntie--I wish I may never stir if I didn't."
-
-"Oh, Tom, don't lie--don't do it. It only makes things a hundred times
-worse."
-
-"It ain't a lie, auntie; it's the truth. I wanted to keep you from
-grieving--that was all that made me come."
-
-"I'd give the whole world to believe that--it would cover up a power
-of sins, Tom. I'd 'most be glad you'd run off and acted so bad. But it
-ain't reasonable; because, why didn't you tell me, child?"
-
-"Why, you see, when you got to talking about the funeral, I just got
-all full of the idea of our coming and hiding in the church, and I
-couldn't somehow bear to spoil it. So I just put the bark back in my
-pocket and kept mum."
-
-"What bark?"
-
-"The bark I had wrote on to tell you we'd gone pirating. I wish, now,
-you'd waked up when I kissed you--I do, honest."
-
-The hard lines in his aunt's face relaxed and a sudden tenderness
-dawned in her eyes.
-
-"DID you kiss me, Tom?"
-
-"Why, yes, I did."
-
-"Are you sure you did, Tom?"
-
-"Why, yes, I did, auntie--certain sure."
-
-"What did you kiss me for, Tom?"
-
-"Because I loved you so, and you laid there moaning and I was so sorry."
-
-The words sounded like truth. The old lady could not hide a tremor in
-her voice when she said:
-
-"Kiss me again, Tom!--and be off with you to school, now, and don't
-bother me any more."
-
-The moment he was gone, she ran to a closet and got out the ruin of a
-jacket which Tom had gone pirating in. Then she stopped, with it in her
-hand, and said to herself:
-
-"No, I don't dare. Poor boy, I reckon he's lied about it--but it's a
-blessed, blessed lie, there's such a comfort come from it. I hope the
-Lord--I KNOW the Lord will forgive him, because it was such
-goodheartedness in him to tell it. But I don't want to find out it's a
-lie. I won't look."
-
-She put the jacket away, and stood by musing a minute. Twice she put
-out her hand to take the garment again, and twice she refrained. Once
-more she ventured, and this time she fortified herself with the
-thought: "It's a good lie--it's a good lie--I won't let it grieve me."
-So she sought the jacket pocket. A moment later she was reading Tom's
-piece of bark through flowing tears and saying: "I could forgive the
-boy, now, if he'd committed a million sins!"
-
-
-
-CHAPTER XX
-
-THERE was something about Aunt Polly's manner, when she kissed Tom,
-that swept away his low spirits and made him lighthearted and happy
-again. He started to school and had the luck of coming upon Becky
-Thatcher at the head of Meadow Lane. His mood always determined his
-manner. Without a moment's hesitation he ran to her and said:
-
-"I acted mighty mean to-day, Becky, and I'm so sorry. I won't ever,
-ever do that way again, as long as ever I live--please make up, won't
-you?"
-
-The girl stopped and looked him scornfully in the face:
-
-"I'll thank you to keep yourself TO yourself, Mr. Thomas Sawyer. I'll
-never speak to you again."
-
-She tossed her head and passed on. Tom was so stunned that he had not
-even presence of mind enough to say "Who cares, Miss Smarty?" until the
-right time to say it had gone by. So he said nothing. But he was in a
-fine rage, nevertheless. He moped into the schoolyard wishing she were
-a boy, and imagining how he would trounce her if she were. He presently
-encountered her and delivered a stinging remark as he passed. She
-hurled one in return, and the angry breach was complete. It seemed to
-Becky, in her hot resentment, that she could hardly wait for school to
-"take in," she was so impatient to see Tom flogged for the injured
-spelling-book. If she had had any lingering notion of exposing Alfred
-Temple, Tom's offensive fling had driven it entirely away.
-
-Poor girl, she did not know how fast she was nearing trouble herself.
-The master, Mr. Dobbins, had reached middle age with an unsatisfied
-ambition. The darling of his desires was, to be a doctor, but poverty
-had decreed that he should be nothing higher than a village
-schoolmaster. Every day he took a mysterious book out of his desk and
-absorbed himself in it at times when no classes were reciting. He kept
-that book under lock and key. There was not an urchin in school but was
-perishing to have a glimpse of it, but the chance never came. Every boy
-and girl had a theory about the nature of that book; but no two
-theories were alike, and there was no way of getting at the facts in
-the case. Now, as Becky was passing by the desk, which stood near the
-door, she noticed that the key was in the lock! It was a precious
-moment. She glanced around; found herself alone, and the next instant
-she had the book in her hands. The title-page--Professor Somebody's
-ANATOMY--carried no information to her mind; so she began to turn the
-leaves. She came at once upon a handsomely engraved and colored
-frontispiece--a human figure, stark naked. At that moment a shadow fell
-on the page and Tom Sawyer stepped in at the door and caught a glimpse
-of the picture. Becky snatched at the book to close it, and had the
-hard luck to tear the pictured page half down the middle. She thrust
-the volume into the desk, turned the key, and burst out crying with
-shame and vexation.
-
-"Tom Sawyer, you are just as mean as you can be, to sneak up on a
-person and look at what they're looking at."
-
-"How could I know you was looking at anything?"
-
-"You ought to be ashamed of yourself, Tom Sawyer; you know you're
-going to tell on me, and oh, what shall I do, what shall I do! I'll be
-whipped, and I never was whipped in school."
-
-Then she stamped her little foot and said:
-
-"BE so mean if you want to! I know something that's going to happen.
-You just wait and you'll see! Hateful, hateful, hateful!"--and she
-flung out of the house with a new explosion of crying.
-
-Tom stood still, rather flustered by this onslaught. Presently he said
-to himself:
-
-"What a curious kind of a fool a girl is! Never been licked in school!
-Shucks! What's a licking! That's just like a girl--they're so
-thin-skinned and chicken-hearted. Well, of course I ain't going to tell
-old Dobbins on this little fool, because there's other ways of getting
-even on her, that ain't so mean; but what of it? Old Dobbins will ask
-who it was tore his book. Nobody'll answer. Then he'll do just the way
-he always does--ask first one and then t'other, and when he comes to the
-right girl he'll know it, without any telling. Girls' faces always tell
-on them. They ain't got any backbone. She'll get licked. Well, it's a
-kind of a tight place for Becky Thatcher, because there ain't any way
-out of it." Tom conned the thing a moment longer, and then added: "All
-right, though; she'd like to see me in just such a fix--let her sweat it
-out!"
-
-Tom joined the mob of skylarking scholars outside. In a few moments
-the master arrived and school "took in." Tom did not feel a strong
-interest in his studies. Every time he stole a glance at the girls'
-side of the room Becky's face troubled him. Considering all things, he
-did not want to pity her, and yet it was all he could do to help it. He
-could get up no exultation that was really worthy the name. Presently
-the spelling-book discovery was made, and Tom's mind was entirely full
-of his own matters for a while after that. Becky roused up from her
-lethargy of distress and showed good interest in the proceedings. She
-did not expect that Tom could get out of his trouble by denying that he
-spilt the ink on the book himself; and she was right. The denial only
-seemed to make the thing worse for Tom. Becky supposed she would be
-glad of that, and she tried to believe she was glad of it, but she
-found she was not certain. When the worst came to the worst, she had an
-impulse to get up and tell on Alfred Temple, but she made an effort and
-forced herself to keep still--because, said she to herself, "he'll tell
-about me tearing the picture sure. I wouldn't say a word, not to save
-his life!"
-
-Tom took his whipping and went back to his seat not at all
-broken-hearted, for he thought it was possible that he had unknowingly
-upset the ink on the spelling-book himself, in some skylarking bout--he
-had denied it for form's sake and because it was custom, and had stuck
-to the denial from principle.
-
-A whole hour drifted by, the master sat nodding in his throne, the air
-was drowsy with the hum of study. By and by, Mr. Dobbins straightened
-himself up, yawned, then unlocked his desk, and reached for his book,
-but seemed undecided whether to take it out or leave it. Most of the
-pupils glanced up languidly, but there were two among them that watched
-his movements with intent eyes. Mr. Dobbins fingered his book absently
-for a while, then took it out and settled himself in his chair to read!
-Tom shot a glance at Becky. He had seen a hunted and helpless rabbit
-look as she did, with a gun levelled at its head. Instantly he forgot
-his quarrel with her. Quick--something must be done! done in a flash,
-too! But the very imminence of the emergency paralyzed his invention.
-Good!--he had an inspiration! He would run and snatch the book, spring
-through the door and fly. But his resolution shook for one little
-instant, and the chance was lost--the master opened the volume. If Tom
-only had the wasted opportunity back again! Too late. There was no help
-for Becky now, he said. The next moment the master faced the school.
-Every eye sank under his gaze. There was that in it which smote even
-the innocent with fear. There was silence while one might count ten
---the master was gathering his wrath. Then he spoke: "Who tore this book?"
-
-There was not a sound. One could have heard a pin drop. The stillness
-continued; the master searched face after face for signs of guilt.
-
-"Benjamin Rogers, did you tear this book?"
-
-A denial. Another pause.
-
-"Joseph Harper, did you?"
-
-Another denial. Tom's uneasiness grew more and more intense under the
-slow torture of these proceedings. The master scanned the ranks of
-boys--considered a while, then turned to the girls:
-
-"Amy Lawrence?"
-
-A shake of the head.
-
-"Gracie Miller?"
-
-The same sign.
-
-"Susan Harper, did you do this?"
-
-Another negative. The next girl was Becky Thatcher. Tom was trembling
-from head to foot with excitement and a sense of the hopelessness of
-the situation.
-
-"Rebecca Thatcher" [Tom glanced at her face--it was white with terror]
---"did you tear--no, look me in the face" [her hands rose in appeal]
---"did you tear this book?"
-
-A thought shot like lightning through Tom's brain. He sprang to his
-feet and shouted--"I done it!"
-
-The school stared in perplexity at this incredible folly. Tom stood a
-moment, to gather his dismembered faculties; and when he stepped
-forward to go to his punishment the surprise, the gratitude, the
-adoration that shone upon him out of poor Becky's eyes seemed pay
-enough for a hundred floggings. Inspired by the splendor of his own
-act, he took without an outcry the most merciless flaying that even Mr.
-Dobbins had ever administered; and also received with indifference the
-added cruelty of a command to remain two hours after school should be
-dismissed--for he knew who would wait for him outside till his
-captivity was done, and not count the tedious time as loss, either.
-
-Tom went to bed that night planning vengeance against Alfred Temple;
-for with shame and repentance Becky had told him all, not forgetting
-her own treachery; but even the longing for vengeance had to give way,
-soon, to pleasanter musings, and he fell asleep at last with Becky's
-latest words lingering dreamily in his ear--
-
-"Tom, how COULD you be so noble!"
-
-
-
-CHAPTER XXI
-
-VACATION was approaching. The schoolmaster, always severe, grew
-severer and more exacting than ever, for he wanted the school to make a
-good showing on "Examination" day. His rod and his ferule were seldom
-idle now--at least among the smaller pupils. Only the biggest boys, and
-young ladies of eighteen and twenty, escaped lashing. Mr. Dobbins'
-lashings were very vigorous ones, too; for although he carried, under
-his wig, a perfectly bald and shiny head, he had only reached middle
-age, and there was no sign of feebleness in his muscle. As the great
-day approached, all the tyranny that was in him came to the surface; he
-seemed to take a vindictive pleasure in punishing the least
-shortcomings. The consequence was, that the smaller boys spent their
-days in terror and suffering and their nights in plotting revenge. They
-threw away no opportunity to do the master a mischief. But he kept
-ahead all the time. The retribution that followed every vengeful
-success was so sweeping and majestic that the boys always retired from
-the field badly worsted. At last they conspired together and hit upon a
-plan that promised a dazzling victory. They swore in the sign-painter's
-boy, told him the scheme, and asked his help. He had his own reasons
-for being delighted, for the master boarded in his father's family and
-had given the boy ample cause to hate him. The master's wife would go
-on a visit to the country in a few days, and there would be nothing to
-interfere with the plan; the master always prepared himself for great
-occasions by getting pretty well fuddled, and the sign-painter's boy
-said that when the dominie had reached the proper condition on
-Examination Evening he would "manage the thing" while he napped in his
-chair; then he would have him awakened at the right time and hurried
-away to school.
-
-In the fulness of time the interesting occasion arrived. At eight in
-the evening the schoolhouse was brilliantly lighted, and adorned with
-wreaths and festoons of foliage and flowers. The master sat throned in
-his great chair upon a raised platform, with his blackboard behind him.
-He was looking tolerably mellow. Three rows of benches on each side and
-six rows in front of him were occupied by the dignitaries of the town
-and by the parents of the pupils. To his left, back of the rows of
-citizens, was a spacious temporary platform upon which were seated the
-scholars who were to take part in the exercises of the evening; rows of
-small boys, washed and dressed to an intolerable state of discomfort;
-rows of gawky big boys; snowbanks of girls and young ladies clad in
-lawn and muslin and conspicuously conscious of their bare arms, their
-grandmothers' ancient trinkets, their bits of pink and blue ribbon and
-the flowers in their hair. All the rest of the house was filled with
-non-participating scholars.
-
-The exercises began. A very little boy stood up and sheepishly
-recited, "You'd scarce expect one of my age to speak in public on the
-stage," etc.--accompanying himself with the painfully exact and
-spasmodic gestures which a machine might have used--supposing the
-machine to be a trifle out of order. But he got through safely, though
-cruelly scared, and got a fine round of applause when he made his
-manufactured bow and retired.
-
-A little shamefaced girl lisped, "Mary had a little lamb," etc.,
-performed a compassion-inspiring curtsy, got her meed of applause, and
-sat down flushed and happy.
-
-Tom Sawyer stepped forward with conceited confidence and soared into
-the unquenchable and indestructible "Give me liberty or give me death"
-speech, with fine fury and frantic gesticulation, and broke down in the
-middle of it. A ghastly stage-fright seized him, his legs quaked under
-him and he was like to choke. True, he had the manifest sympathy of the
-house but he had the house's silence, too, which was even worse than
-its sympathy. The master frowned, and this completed the disaster. Tom
-struggled awhile and then retired, utterly defeated. There was a weak
-attempt at applause, but it died early.
-
-"The Boy Stood on the Burning Deck" followed; also "The Assyrian Came
-Down," and other declamatory gems. Then there were reading exercises,
-and a spelling fight. The meagre Latin class recited with honor. The
-prime feature of the evening was in order, now--original "compositions"
-by the young ladies. Each in her turn stepped forward to the edge of
-the platform, cleared her throat, held up her manuscript (tied with
-dainty ribbon), and proceeded to read, with labored attention to
-"expression" and punctuation. The themes were the same that had been
-illuminated upon similar occasions by their mothers before them, their
-grandmothers, and doubtless all their ancestors in the female line
-clear back to the Crusades. "Friendship" was one; "Memories of Other
-Days"; "Religion in History"; "Dream Land"; "The Advantages of
-Culture"; "Forms of Political Government Compared and Contrasted";
-"Melancholy"; "Filial Love"; "Heart Longings," etc., etc.
-
-A prevalent feature in these compositions was a nursed and petted
-melancholy; another was a wasteful and opulent gush of "fine language";
-another was a tendency to lug in by the ears particularly prized words
-and phrases until they were worn entirely out; and a peculiarity that
-conspicuously marked and marred them was the inveterate and intolerable
-sermon that wagged its crippled tail at the end of each and every one
-of them. No matter what the subject might be, a brain-racking effort
-was made to squirm it into some aspect or other that the moral and
-religious mind could contemplate with edification. The glaring
-insincerity of these sermons was not sufficient to compass the
-banishment of the fashion from the schools, and it is not sufficient
-to-day; it never will be sufficient while the world stands, perhaps.
-There is no school in all our land where the young ladies do not feel
-obliged to close their compositions with a sermon; and you will find
-that the sermon of the most frivolous and the least religious girl in
-the school is always the longest and the most relentlessly pious. But
-enough of this. Homely truth is unpalatable.
-
-Let us return to the "Examination." The first composition that was
-read was one entitled "Is this, then, Life?" Perhaps the reader can
-endure an extract from it:
-
- "In the common walks of life, with what delightful
- emotions does the youthful mind look forward to some
- anticipated scene of festivity! Imagination is busy
- sketching rose-tinted pictures of joy. In fancy, the
- voluptuous votary of fashion sees herself amid the
- festive throng, 'the observed of all observers.' Her
- graceful form, arrayed in snowy robes, is whirling
- through the mazes of the joyous dance; her eye is
- brightest, her step is lightest in the gay assembly.
-
- "In such delicious fancies time quickly glides by,
- and the welcome hour arrives for her entrance into
- the Elysian world, of which she has had such bright
- dreams. How fairy-like does everything appear to
- her enchanted vision! Each new scene is more charming
- than the last. But after a while she finds that
- beneath this goodly exterior, all is vanity, the
- flattery which once charmed her soul, now grates
- harshly upon her ear; the ball-room has lost its
- charms; and with wasted health and imbittered heart,
- she turns away with the conviction that earthly
- pleasures cannot satisfy the longings of the soul!"
-
-And so forth and so on. There was a buzz of gratification from time to
-time during the reading, accompanied by whispered ejaculations of "How
-sweet!" "How eloquent!" "So true!" etc., and after the thing had closed
-with a peculiarly afflicting sermon the applause was enthusiastic.
-
-Then arose a slim, melancholy girl, whose face had the "interesting"
-paleness that comes of pills and indigestion, and read a "poem." Two
-stanzas of it will do:
-
- "A MISSOURI MAIDEN'S FAREWELL TO ALABAMA
-
- "Alabama, good-bye! I love thee well!
- But yet for a while do I leave thee now!
- Sad, yes, sad thoughts of thee my heart doth swell,
- And burning recollections throng my brow!
- For I have wandered through thy flowery woods;
- Have roamed and read near Tallapoosa's stream;
- Have listened to Tallassee's warring floods,
- And wooed on Coosa's side Aurora's beam.
-
- "Yet shame I not to bear an o'er-full heart,
- Nor blush to turn behind my tearful eyes;
- 'Tis from no stranger land I now must part,
- 'Tis to no strangers left I yield these sighs.
- Welcome and home were mine within this State,
- Whose vales I leave--whose spires fade fast from me
- And cold must be mine eyes, and heart, and tete,
- When, dear Alabama! they turn cold on thee!"
-
-There were very few there who knew what "tete" meant, but the poem was
-very satisfactory, nevertheless.
-
-Next appeared a dark-complexioned, black-eyed, black-haired young
-lady, who paused an impressive moment, assumed a tragic expression, and
-began to read in a measured, solemn tone:
-
- "A VISION
-
- "Dark and tempestuous was night. Around the
- throne on high not a single star quivered; but
- the deep intonations of the heavy thunder
- constantly vibrated upon the ear; whilst the
- terrific lightning revelled in angry mood
- through the cloudy chambers of heaven, seeming
- to scorn the power exerted over its terror by
- the illustrious Franklin! Even the boisterous
- winds unanimously came forth from their mystic
- homes, and blustered about as if to enhance by
- their aid the wildness of the scene.
-
- "At such a time, so dark, so dreary, for human
- sympathy my very spirit sighed; but instead thereof,
-
- "'My dearest friend, my counsellor, my comforter
- and guide--My joy in grief, my second bliss
- in joy,' came to my side. She moved like one of
- those bright beings pictured in the sunny walks
- of fancy's Eden by the romantic and young, a
- queen of beauty unadorned save by her own
- transcendent loveliness. So soft was her step, it
- failed to make even a sound, and but for the
- magical thrill imparted by her genial touch, as
- other unobtrusive beauties, she would have glided
- away un-perceived--unsought. A strange sadness
- rested upon her features, like icy tears upon
- the robe of December, as she pointed to the
- contending elements without, and bade me contemplate
- the two beings presented."
-
-This nightmare occupied some ten pages of manuscript and wound up with
-a sermon so destructive of all hope to non-Presbyterians that it took
-the first prize. This composition was considered to be the very finest
-effort of the evening. The mayor of the village, in delivering the
-prize to the author of it, made a warm speech in which he said that it
-was by far the most "eloquent" thing he had ever listened to, and that
-Daniel Webster himself might well be proud of it.
-
-It may be remarked, in passing, that the number of compositions in
-which the word "beauteous" was over-fondled, and human experience
-referred to as "life's page," was up to the usual average.
-
-Now the master, mellow almost to the verge of geniality, put his chair
-aside, turned his back to the audience, and began to draw a map of
-America on the blackboard, to exercise the geography class upon. But he
-made a sad business of it with his unsteady hand, and a smothered
-titter rippled over the house. He knew what the matter was, and set
-himself to right it. He sponged out lines and remade them; but he only
-distorted them more than ever, and the tittering was more pronounced.
-He threw his entire attention upon his work, now, as if determined not
-to be put down by the mirth. He felt that all eyes were fastened upon
-him; he imagined he was succeeding, and yet the tittering continued; it
-even manifestly increased. And well it might. There was a garret above,
-pierced with a scuttle over his head; and down through this scuttle
-came a cat, suspended around the haunches by a string; she had a rag
-tied about her head and jaws to keep her from mewing; as she slowly
-descended she curved upward and clawed at the string, she swung
-downward and clawed at the intangible air. The tittering rose higher
-and higher--the cat was within six inches of the absorbed teacher's
-head--down, down, a little lower, and she grabbed his wig with her
-desperate claws, clung to it, and was snatched up into the garret in an
-instant with her trophy still in her possession! And how the light did
-blaze abroad from the master's bald pate--for the sign-painter's boy
-had GILDED it!
-
-That broke up the meeting. The boys were avenged. Vacation had come.
-
- NOTE:--The pretended "compositions" quoted in
- this chapter are taken without alteration from a
- volume entitled "Prose and Poetry, by a Western
- Lady"--but they are exactly and precisely after
- the schoolgirl pattern, and hence are much
- happier than any mere imitations could be.
-
-
-
-CHAPTER XXII
-
-TOM joined the new order of Cadets of Temperance, being attracted by
-the showy character of their "regalia." He promised to abstain from
-smoking, chewing, and profanity as long as he remained a member. Now he
-found out a new thing--namely, that to promise not to do a thing is the
-surest way in the world to make a body want to go and do that very
-thing. Tom soon found himself tormented with a desire to drink and
-swear; the desire grew to be so intense that nothing but the hope of a
-chance to display himself in his red sash kept him from withdrawing
-from the order. Fourth of July was coming; but he soon gave that up
---gave it up before he had worn his shackles over forty-eight hours--and
-fixed his hopes upon old Judge Frazer, justice of the peace, who was
-apparently on his deathbed and would have a big public funeral, since
-he was so high an official. During three days Tom was deeply concerned
-about the Judge's condition and hungry for news of it. Sometimes his
-hopes ran high--so high that he would venture to get out his regalia
-and practise before the looking-glass. But the Judge had a most
-discouraging way of fluctuating. At last he was pronounced upon the
-mend--and then convalescent. Tom was disgusted; and felt a sense of
-injury, too. He handed in his resignation at once--and that night the
-Judge suffered a relapse and died. Tom resolved that he would never
-trust a man like that again.
-
-The funeral was a fine thing. The Cadets paraded in a style calculated
-to kill the late member with envy. Tom was a free boy again, however
---there was something in that. He could drink and swear, now--but found
-to his surprise that he did not want to. The simple fact that he could,
-took the desire away, and the charm of it.
-
-Tom presently wondered to find that his coveted vacation was beginning
-to hang a little heavily on his hands.
-
-He attempted a diary--but nothing happened during three days, and so
-he abandoned it.
-
-The first of all the negro minstrel shows came to town, and made a
-sensation. Tom and Joe Harper got up a band of performers and were
-happy for two days.
-
-Even the Glorious Fourth was in some sense a failure, for it rained
-hard, there was no procession in consequence, and the greatest man in
-the world (as Tom supposed), Mr. Benton, an actual United States
-Senator, proved an overwhelming disappointment--for he was not
-twenty-five feet high, nor even anywhere in the neighborhood of it.
-
-A circus came. The boys played circus for three days afterward in
-tents made of rag carpeting--admission, three pins for boys, two for
-girls--and then circusing was abandoned.
-
-A phrenologist and a mesmerizer came--and went again and left the
-village duller and drearier than ever.
-
-There were some boys-and-girls' parties, but they were so few and so
-delightful that they only made the aching voids between ache the harder.
-
-Becky Thatcher was gone to her Constantinople home to stay with her
-parents during vacation--so there was no bright side to life anywhere.
-
-The dreadful secret of the murder was a chronic misery. It was a very
-cancer for permanency and pain.
-
-Then came the measles.
-
-During two long weeks Tom lay a prisoner, dead to the world and its
-happenings. He was very ill, he was interested in nothing. When he got
-upon his feet at last and moved feebly down-town, a melancholy change
-had come over everything and every creature. There had been a
-"revival," and everybody had "got religion," not only the adults, but
-even the boys and girls. Tom went about, hoping against hope for the
-sight of one blessed sinful face, but disappointment crossed him
-everywhere. He found Joe Harper studying a Testament, and turned sadly
-away from the depressing spectacle. He sought Ben Rogers, and found him
-visiting the poor with a basket of tracts. He hunted up Jim Hollis, who
-called his attention to the precious blessing of his late measles as a
-warning. Every boy he encountered added another ton to his depression;
-and when, in desperation, he flew for refuge at last to the bosom of
-Huckleberry Finn and was received with a Scriptural quotation, his
-heart broke and he crept home and to bed realizing that he alone of all
-the town was lost, forever and forever.
-
-And that night there came on a terrific storm, with driving rain,
-awful claps of thunder and blinding sheets of lightning. He covered his
-head with the bedclothes and waited in a horror of suspense for his
-doom; for he had not the shadow of a doubt that all this hubbub was
-about him. He believed he had taxed the forbearance of the powers above
-to the extremity of endurance and that this was the result. It might
-have seemed to him a waste of pomp and ammunition to kill a bug with a
-battery of artillery, but there seemed nothing incongruous about the
-getting up such an expensive thunderstorm as this to knock the turf
-from under an insect like himself.
-
-By and by the tempest spent itself and died without accomplishing its
-object. The boy's first impulse was to be grateful, and reform. His
-second was to wait--for there might not be any more storms.
-
-The next day the doctors were back; Tom had relapsed. The three weeks
-he spent on his back this time seemed an entire age. When he got abroad
-at last he was hardly grateful that he had been spared, remembering how
-lonely was his estate, how companionless and forlorn he was. He drifted
-listlessly down the street and found Jim Hollis acting as judge in a
-juvenile court that was trying a cat for murder, in the presence of her
-victim, a bird. He found Joe Harper and Huck Finn up an alley eating a
-stolen melon. Poor lads! they--like Tom--had suffered a relapse.
-
-
-
-CHAPTER XXIII
-
-AT last the sleepy atmosphere was stirred--and vigorously: the murder
-trial came on in the court. It became the absorbing topic of village
-talk immediately. Tom could not get away from it. Every reference to
-the murder sent a shudder to his heart, for his troubled conscience and
-fears almost persuaded him that these remarks were put forth in his
-hearing as "feelers"; he did not see how he could be suspected of
-knowing anything about the murder, but still he could not be
-comfortable in the midst of this gossip. It kept him in a cold shiver
-all the time. He took Huck to a lonely place to have a talk with him.
-It would be some relief to unseal his tongue for a little while; to
-divide his burden of distress with another sufferer. Moreover, he
-wanted to assure himself that Huck had remained discreet.
-
-"Huck, have you ever told anybody about--that?"
-
-"'Bout what?"
-
-"You know what."
-
-"Oh--'course I haven't."
-
-"Never a word?"
-
-"Never a solitary word, so help me. What makes you ask?"
-
-"Well, I was afeard."
-
-"Why, Tom Sawyer, we wouldn't be alive two days if that got found out.
-YOU know that."
-
-Tom felt more comfortable. After a pause:
-
-"Huck, they couldn't anybody get you to tell, could they?"
-
-"Get me to tell? Why, if I wanted that half-breed devil to drownd me
-they could get me to tell. They ain't no different way."
-
-"Well, that's all right, then. I reckon we're safe as long as we keep
-mum. But let's swear again, anyway. It's more surer."
-
-"I'm agreed."
-
-So they swore again with dread solemnities.
-
-"What is the talk around, Huck? I've heard a power of it."
-
-"Talk? Well, it's just Muff Potter, Muff Potter, Muff Potter all the
-time. It keeps me in a sweat, constant, so's I want to hide som'ers."
-
-"That's just the same way they go on round me. I reckon he's a goner.
-Don't you feel sorry for him, sometimes?"
-
-"Most always--most always. He ain't no account; but then he hain't
-ever done anything to hurt anybody. Just fishes a little, to get money
-to get drunk on--and loafs around considerable; but lord, we all do
-that--leastways most of us--preachers and such like. But he's kind of
-good--he give me half a fish, once, when there warn't enough for two;
-and lots of times he's kind of stood by me when I was out of luck."
-
-"Well, he's mended kites for me, Huck, and knitted hooks on to my
-line. I wish we could get him out of there."
-
-"My! we couldn't get him out, Tom. And besides, 'twouldn't do any
-good; they'd ketch him again."
-
-"Yes--so they would. But I hate to hear 'em abuse him so like the
-dickens when he never done--that."
-
-"I do too, Tom. Lord, I hear 'em say he's the bloodiest looking
-villain in this country, and they wonder he wasn't ever hung before."
-
-"Yes, they talk like that, all the time. I've heard 'em say that if he
-was to get free they'd lynch him."
-
-"And they'd do it, too."
-
-The boys had a long talk, but it brought them little comfort. As the
-twilight drew on, they found themselves hanging about the neighborhood
-of the little isolated jail, perhaps with an undefined hope that
-something would happen that might clear away their difficulties. But
-nothing happened; there seemed to be no angels or fairies interested in
-this luckless captive.
-
-The boys did as they had often done before--went to the cell grating
-and gave Potter some tobacco and matches. He was on the ground floor
-and there were no guards.
-
-His gratitude for their gifts had always smote their consciences
-before--it cut deeper than ever, this time. They felt cowardly and
-treacherous to the last degree when Potter said:
-
-"You've been mighty good to me, boys--better'n anybody else in this
-town. And I don't forget it, I don't. Often I says to myself, says I,
-'I used to mend all the boys' kites and things, and show 'em where the
-good fishin' places was, and befriend 'em what I could, and now they've
-all forgot old Muff when he's in trouble; but Tom don't, and Huck
-don't--THEY don't forget him, says I, 'and I don't forget them.' Well,
-boys, I done an awful thing--drunk and crazy at the time--that's the
-only way I account for it--and now I got to swing for it, and it's
-right. Right, and BEST, too, I reckon--hope so, anyway. Well, we won't
-talk about that. I don't want to make YOU feel bad; you've befriended
-me. But what I want to say, is, don't YOU ever get drunk--then you won't
-ever get here. Stand a litter furder west--so--that's it; it's a prime
-comfort to see faces that's friendly when a body's in such a muck of
-trouble, and there don't none come here but yourn. Good friendly
-faces--good friendly faces. Git up on one another's backs and let me
-touch 'em. That's it. Shake hands--yourn'll come through the bars, but
-mine's too big. Little hands, and weak--but they've helped Muff Potter
-a power, and they'd help him more if they could."
-
-Tom went home miserable, and his dreams that night were full of
-horrors. The next day and the day after, he hung about the court-room,
-drawn by an almost irresistible impulse to go in, but forcing himself
-to stay out. Huck was having the same experience. They studiously
-avoided each other. Each wandered away, from time to time, but the same
-dismal fascination always brought them back presently. Tom kept his
-ears open when idlers sauntered out of the court-room, but invariably
-heard distressing news--the toils were closing more and more
-relentlessly around poor Potter. At the end of the second day the
-village talk was to the effect that Injun Joe's evidence stood firm and
-unshaken, and that there was not the slightest question as to what the
-jury's verdict would be.
-
-Tom was out late, that night, and came to bed through the window. He
-was in a tremendous state of excitement. It was hours before he got to
-sleep. All the village flocked to the court-house the next morning, for
-this was to be the great day. Both sexes were about equally represented
-in the packed audience. After a long wait the jury filed in and took
-their places; shortly afterward, Potter, pale and haggard, timid and
-hopeless, was brought in, with chains upon him, and seated where all
-the curious eyes could stare at him; no less conspicuous was Injun Joe,
-stolid as ever. There was another pause, and then the judge arrived and
-the sheriff proclaimed the opening of the court. The usual whisperings
-among the lawyers and gathering together of papers followed. These
-details and accompanying delays worked up an atmosphere of preparation
-that was as impressive as it was fascinating.
-
-Now a witness was called who testified that he found Muff Potter
-washing in the brook, at an early hour of the morning that the murder
-was discovered, and that he immediately sneaked away. After some
-further questioning, counsel for the prosecution said:
-
-"Take the witness."
-
-The prisoner raised his eyes for a moment, but dropped them again when
-his own counsel said:
-
-"I have no questions to ask him."
-
-The next witness proved the finding of the knife near the corpse.
-Counsel for the prosecution said:
-
-"Take the witness."
-
-"I have no questions to ask him," Potter's lawyer replied.
-
-A third witness swore he had often seen the knife in Potter's
-possession.
-
-"Take the witness."
-
-Counsel for Potter declined to question him. The faces of the audience
-began to betray annoyance. Did this attorney mean to throw away his
-client's life without an effort?
-
-Several witnesses deposed concerning Potter's guilty behavior when
-brought to the scene of the murder. They were allowed to leave the
-stand without being cross-questioned.
-
-Every detail of the damaging circumstances that occurred in the
-graveyard upon that morning which all present remembered so well was
-brought out by credible witnesses, but none of them were cross-examined
-by Potter's lawyer. The perplexity and dissatisfaction of the house
-expressed itself in murmurs and provoked a reproof from the bench.
-Counsel for the prosecution now said:
-
-"By the oaths of citizens whose simple word is above suspicion, we
-have fastened this awful crime, beyond all possibility of question,
-upon the unhappy prisoner at the bar. We rest our case here."
-
-A groan escaped from poor Potter, and he put his face in his hands and
-rocked his body softly to and fro, while a painful silence reigned in
-the court-room. Many men were moved, and many women's compassion
-testified itself in tears. Counsel for the defence rose and said:
-
-"Your honor, in our remarks at the opening of this trial, we
-foreshadowed our purpose to prove that our client did this fearful deed
-while under the influence of a blind and irresponsible delirium
-produced by drink. We have changed our mind. We shall not offer that
-plea." [Then to the clerk:] "Call Thomas Sawyer!"
-
-A puzzled amazement awoke in every face in the house, not even
-excepting Potter's. Every eye fastened itself with wondering interest
-upon Tom as he rose and took his place upon the stand. The boy looked
-wild enough, for he was badly scared. The oath was administered.
-
-"Thomas Sawyer, where were you on the seventeenth of June, about the
-hour of midnight?"
-
-Tom glanced at Injun Joe's iron face and his tongue failed him. The
-audience listened breathless, but the words refused to come. After a
-few moments, however, the boy got a little of his strength back, and
-managed to put enough of it into his voice to make part of the house
-hear:
-
-"In the graveyard!"
-
-"A little bit louder, please. Don't be afraid. You were--"
-
-"In the graveyard."
-
-A contemptuous smile flitted across Injun Joe's face.
-
-"Were you anywhere near Horse Williams' grave?"
-
-"Yes, sir."
-
-"Speak up--just a trifle louder. How near were you?"
-
-"Near as I am to you."
-
-"Were you hidden, or not?"
-
-"I was hid."
-
-"Where?"
-
-"Behind the elms that's on the edge of the grave."
-
-Injun Joe gave a barely perceptible start.
-
-"Any one with you?"
-
-"Yes, sir. I went there with--"
-
-"Wait--wait a moment. Never mind mentioning your companion's name. We
-will produce him at the proper time. Did you carry anything there with
-you."
-
-Tom hesitated and looked confused.
-
-"Speak out, my boy--don't be diffident. The truth is always
-respectable. What did you take there?"
-
-"Only a--a--dead cat."
-
-There was a ripple of mirth, which the court checked.
-
-"We will produce the skeleton of that cat. Now, my boy, tell us
-everything that occurred--tell it in your own way--don't skip anything,
-and don't be afraid."
-
-Tom began--hesitatingly at first, but as he warmed to his subject his
-words flowed more and more easily; in a little while every sound ceased
-but his own voice; every eye fixed itself upon him; with parted lips
-and bated breath the audience hung upon his words, taking no note of
-time, rapt in the ghastly fascinations of the tale. The strain upon
-pent emotion reached its climax when the boy said:
-
-"--and as the doctor fetched the board around and Muff Potter fell,
-Injun Joe jumped with the knife and--"
-
-Crash! Quick as lightning the half-breed sprang for a window, tore his
-way through all opposers, and was gone!
-
-
-
-CHAPTER XXIV
-
-TOM was a glittering hero once more--the pet of the old, the envy of
-the young. His name even went into immortal print, for the village
-paper magnified him. There were some that believed he would be
-President, yet, if he escaped hanging.
-
-As usual, the fickle, unreasoning world took Muff Potter to its bosom
-and fondled him as lavishly as it had abused him before. But that sort
-of conduct is to the world's credit; therefore it is not well to find
-fault with it.
-
-Tom's days were days of splendor and exultation to him, but his nights
-were seasons of horror. Injun Joe infested all his dreams, and always
-with doom in his eye. Hardly any temptation could persuade the boy to
-stir abroad after nightfall. Poor Huck was in the same state of
-wretchedness and terror, for Tom had told the whole story to the lawyer
-the night before the great day of the trial, and Huck was sore afraid
-that his share in the business might leak out, yet, notwithstanding
-Injun Joe's flight had saved him the suffering of testifying in court.
-The poor fellow had got the attorney to promise secrecy, but what of
-that? Since Tom's harassed conscience had managed to drive him to the
-lawyer's house by night and wring a dread tale from lips that had been
-sealed with the dismalest and most formidable of oaths, Huck's
-confidence in the human race was well-nigh obliterated.
-
-Daily Muff Potter's gratitude made Tom glad he had spoken; but nightly
-he wished he had sealed up his tongue.
-
-Half the time Tom was afraid Injun Joe would never be captured; the
-other half he was afraid he would be. He felt sure he never could draw
-a safe breath again until that man was dead and he had seen the corpse.
-
-Rewards had been offered, the country had been scoured, but no Injun
-Joe was found. One of those omniscient and awe-inspiring marvels, a
-detective, came up from St. Louis, moused around, shook his head,
-looked wise, and made that sort of astounding success which members of
-that craft usually achieve. That is to say, he "found a clew." But you
-can't hang a "clew" for murder, and so after that detective had got
-through and gone home, Tom felt just as insecure as he was before.
-
-The slow days drifted on, and each left behind it a slightly lightened
-weight of apprehension.
-
-
-
-CHAPTER XXV
-
-THERE comes a time in every rightly-constructed boy's life when he has
-a raging desire to go somewhere and dig for hidden treasure. This
-desire suddenly came upon Tom one day. He sallied out to find Joe
-Harper, but failed of success. Next he sought Ben Rogers; he had gone
-fishing. Presently he stumbled upon Huck Finn the Red-Handed. Huck
-would answer. Tom took him to a private place and opened the matter to
-him confidentially. Huck was willing. Huck was always willing to take a
-hand in any enterprise that offered entertainment and required no
-capital, for he had a troublesome superabundance of that sort of time
-which is not money. "Where'll we dig?" said Huck.
-
-"Oh, most anywhere."
-
-"Why, is it hid all around?"
-
-"No, indeed it ain't. It's hid in mighty particular places, Huck
---sometimes on islands, sometimes in rotten chests under the end of a
-limb of an old dead tree, just where the shadow falls at midnight; but
-mostly under the floor in ha'nted houses."
-
-"Who hides it?"
-
-"Why, robbers, of course--who'd you reckon? Sunday-school
-sup'rintendents?"
-
-"I don't know. If 'twas mine I wouldn't hide it; I'd spend it and have
-a good time."
-
-"So would I. But robbers don't do that way. They always hide it and
-leave it there."
-
-"Don't they come after it any more?"
-
-"No, they think they will, but they generally forget the marks, or
-else they die. Anyway, it lays there a long time and gets rusty; and by
-and by somebody finds an old yellow paper that tells how to find the
-marks--a paper that's got to be ciphered over about a week because it's
-mostly signs and hy'roglyphics."
-
-"Hyro--which?"
-
-"Hy'roglyphics--pictures and things, you know, that don't seem to mean
-anything."
-
-"Have you got one of them papers, Tom?"
-
-"No."
-
-"Well then, how you going to find the marks?"
-
-"I don't want any marks. They always bury it under a ha'nted house or
-on an island, or under a dead tree that's got one limb sticking out.
-Well, we've tried Jackson's Island a little, and we can try it again
-some time; and there's the old ha'nted house up the Still-House branch,
-and there's lots of dead-limb trees--dead loads of 'em."
-
-"Is it under all of them?"
-
-"How you talk! No!"
-
-"Then how you going to know which one to go for?"
-
-"Go for all of 'em!"
-
-"Why, Tom, it'll take all summer."
-
-"Well, what of that? Suppose you find a brass pot with a hundred
-dollars in it, all rusty and gray, or rotten chest full of di'monds.
-How's that?"
-
-Huck's eyes glowed.
-
-"That's bully. Plenty bully enough for me. Just you gimme the hundred
-dollars and I don't want no di'monds."
-
-"All right. But I bet you I ain't going to throw off on di'monds. Some
-of 'em's worth twenty dollars apiece--there ain't any, hardly, but's
-worth six bits or a dollar."
-
-"No! Is that so?"
-
-"Cert'nly--anybody'll tell you so. Hain't you ever seen one, Huck?"
-
-"Not as I remember."
-
-"Oh, kings have slathers of them."
-
-"Well, I don' know no kings, Tom."
-
-"I reckon you don't. But if you was to go to Europe you'd see a raft
-of 'em hopping around."
-
-"Do they hop?"
-
-"Hop?--your granny! No!"
-
-"Well, what did you say they did, for?"
-
-"Shucks, I only meant you'd SEE 'em--not hopping, of course--what do
-they want to hop for?--but I mean you'd just see 'em--scattered around,
-you know, in a kind of a general way. Like that old humpbacked Richard."
-
-"Richard? What's his other name?"
-
-"He didn't have any other name. Kings don't have any but a given name."
-
-"No?"
-
-"But they don't."
-
-"Well, if they like it, Tom, all right; but I don't want to be a king
-and have only just a given name, like a nigger. But say--where you
-going to dig first?"
-
-"Well, I don't know. S'pose we tackle that old dead-limb tree on the
-hill t'other side of Still-House branch?"
-
-"I'm agreed."
-
-So they got a crippled pick and a shovel, and set out on their
-three-mile tramp. They arrived hot and panting, and threw themselves
-down in the shade of a neighboring elm to rest and have a smoke.
-
-"I like this," said Tom.
-
-"So do I."
-
-"Say, Huck, if we find a treasure here, what you going to do with your
-share?"
-
-"Well, I'll have pie and a glass of soda every day, and I'll go to
-every circus that comes along. I bet I'll have a gay time."
-
-"Well, ain't you going to save any of it?"
-
-"Save it? What for?"
-
-"Why, so as to have something to live on, by and by."
-
-"Oh, that ain't any use. Pap would come back to thish-yer town some
-day and get his claws on it if I didn't hurry up, and I tell you he'd
-clean it out pretty quick. What you going to do with yourn, Tom?"
-
-"I'm going to buy a new drum, and a sure-'nough sword, and a red
-necktie and a bull pup, and get married."
-
-"Married!"
-
-"That's it."
-
-"Tom, you--why, you ain't in your right mind."
-
-"Wait--you'll see."
-
-"Well, that's the foolishest thing you could do. Look at pap and my
-mother. Fight! Why, they used to fight all the time. I remember, mighty
-well."
-
-"That ain't anything. The girl I'm going to marry won't fight."
-
-"Tom, I reckon they're all alike. They'll all comb a body. Now you
-better think 'bout this awhile. I tell you you better. What's the name
-of the gal?"
-
-"It ain't a gal at all--it's a girl."
-
-"It's all the same, I reckon; some says gal, some says girl--both's
-right, like enough. Anyway, what's her name, Tom?"
-
-"I'll tell you some time--not now."
-
-"All right--that'll do. Only if you get married I'll be more lonesomer
-than ever."
-
-"No you won't. You'll come and live with me. Now stir out of this and
-we'll go to digging."
-
-They worked and sweated for half an hour. No result. They toiled
-another half-hour. Still no result. Huck said:
-
-"Do they always bury it as deep as this?"
-
-"Sometimes--not always. Not generally. I reckon we haven't got the
-right place."
-
-So they chose a new spot and began again. The labor dragged a little,
-but still they made progress. They pegged away in silence for some
-time. Finally Huck leaned on his shovel, swabbed the beaded drops from
-his brow with his sleeve, and said:
-
-"Where you going to dig next, after we get this one?"
-
-"I reckon maybe we'll tackle the old tree that's over yonder on
-Cardiff Hill back of the widow's."
-
-"I reckon that'll be a good one. But won't the widow take it away from
-us, Tom? It's on her land."
-
-"SHE take it away! Maybe she'd like to try it once. Whoever finds one
-of these hid treasures, it belongs to him. It don't make any difference
-whose land it's on."
-
-That was satisfactory. The work went on. By and by Huck said:
-
-"Blame it, we must be in the wrong place again. What do you think?"
-
-"It is mighty curious, Huck. I don't understand it. Sometimes witches
-interfere. I reckon maybe that's what's the trouble now."
-
-"Shucks! Witches ain't got no power in the daytime."
-
-"Well, that's so. I didn't think of that. Oh, I know what the matter
-is! What a blamed lot of fools we are! You got to find out where the
-shadow of the limb falls at midnight, and that's where you dig!"
-
-"Then consound it, we've fooled away all this work for nothing. Now
-hang it all, we got to come back in the night. It's an awful long way.
-Can you get out?"
-
-"I bet I will. We've got to do it to-night, too, because if somebody
-sees these holes they'll know in a minute what's here and they'll go
-for it."
-
-"Well, I'll come around and maow to-night."
-
-"All right. Let's hide the tools in the bushes."
-
-The boys were there that night, about the appointed time. They sat in
-the shadow waiting. It was a lonely place, and an hour made solemn by
-old traditions. Spirits whispered in the rustling leaves, ghosts lurked
-in the murky nooks, the deep baying of a hound floated up out of the
-distance, an owl answered with his sepulchral note. The boys were
-subdued by these solemnities, and talked little. By and by they judged
-that twelve had come; they marked where the shadow fell, and began to
-dig. Their hopes commenced to rise. Their interest grew stronger, and
-their industry kept pace with it. The hole deepened and still deepened,
-but every time their hearts jumped to hear the pick strike upon
-something, they only suffered a new disappointment. It was only a stone
-or a chunk. At last Tom said:
-
-"It ain't any use, Huck, we're wrong again."
-
-"Well, but we CAN'T be wrong. We spotted the shadder to a dot."
-
-"I know it, but then there's another thing."
-
-"What's that?".
-
-"Why, we only guessed at the time. Like enough it was too late or too
-early."
-
-Huck dropped his shovel.
-
-"That's it," said he. "That's the very trouble. We got to give this
-one up. We can't ever tell the right time, and besides this kind of
-thing's too awful, here this time of night with witches and ghosts
-a-fluttering around so. I feel as if something's behind me all the time;
-and I'm afeard to turn around, becuz maybe there's others in front
-a-waiting for a chance. I been creeping all over, ever since I got here."
-
-"Well, I've been pretty much so, too, Huck. They most always put in a
-dead man when they bury a treasure under a tree, to look out for it."
-
-"Lordy!"
-
-"Yes, they do. I've always heard that."
-
-"Tom, I don't like to fool around much where there's dead people. A
-body's bound to get into trouble with 'em, sure."
-
-"I don't like to stir 'em up, either. S'pose this one here was to
-stick his skull out and say something!"
-
-"Don't Tom! It's awful."
-
-"Well, it just is. Huck, I don't feel comfortable a bit."
-
-"Say, Tom, let's give this place up, and try somewheres else."
-
-"All right, I reckon we better."
-
-"What'll it be?"
-
-Tom considered awhile; and then said:
-
-"The ha'nted house. That's it!"
-
-"Blame it, I don't like ha'nted houses, Tom. Why, they're a dern sight
-worse'n dead people. Dead people might talk, maybe, but they don't come
-sliding around in a shroud, when you ain't noticing, and peep over your
-shoulder all of a sudden and grit their teeth, the way a ghost does. I
-couldn't stand such a thing as that, Tom--nobody could."
-
-"Yes, but, Huck, ghosts don't travel around only at night. They won't
-hender us from digging there in the daytime."
-
-"Well, that's so. But you know mighty well people don't go about that
-ha'nted house in the day nor the night."
-
-"Well, that's mostly because they don't like to go where a man's been
-murdered, anyway--but nothing's ever been seen around that house except
-in the night--just some blue lights slipping by the windows--no regular
-ghosts."
-
-"Well, where you see one of them blue lights flickering around, Tom,
-you can bet there's a ghost mighty close behind it. It stands to
-reason. Becuz you know that they don't anybody but ghosts use 'em."
-
-"Yes, that's so. But anyway they don't come around in the daytime, so
-what's the use of our being afeard?"
-
-"Well, all right. We'll tackle the ha'nted house if you say so--but I
-reckon it's taking chances."
-
-They had started down the hill by this time. There in the middle of
-the moonlit valley below them stood the "ha'nted" house, utterly
-isolated, its fences gone long ago, rank weeds smothering the very
-doorsteps, the chimney crumbled to ruin, the window-sashes vacant, a
-corner of the roof caved in. The boys gazed awhile, half expecting to
-see a blue light flit past a window; then talking in a low tone, as
-befitted the time and the circumstances, they struck far off to the
-right, to give the haunted house a wide berth, and took their way
-homeward through the woods that adorned the rearward side of Cardiff
-Hill.
-
-
-
-CHAPTER XXVI
-
-ABOUT noon the next day the boys arrived at the dead tree; they had
-come for their tools. Tom was impatient to go to the haunted house;
-Huck was measurably so, also--but suddenly said:
-
-"Lookyhere, Tom, do you know what day it is?"
-
-Tom mentally ran over the days of the week, and then quickly lifted
-his eyes with a startled look in them--
-
-"My! I never once thought of it, Huck!"
-
-"Well, I didn't neither, but all at once it popped onto me that it was
-Friday."
-
-"Blame it, a body can't be too careful, Huck. We might 'a' got into an
-awful scrape, tackling such a thing on a Friday."
-
-"MIGHT! Better say we WOULD! There's some lucky days, maybe, but
-Friday ain't."
-
-"Any fool knows that. I don't reckon YOU was the first that found it
-out, Huck."
-
-"Well, I never said I was, did I? And Friday ain't all, neither. I had
-a rotten bad dream last night--dreampt about rats."
-
-"No! Sure sign of trouble. Did they fight?"
-
-"No."
-
-"Well, that's good, Huck. When they don't fight it's only a sign that
-there's trouble around, you know. All we got to do is to look mighty
-sharp and keep out of it. We'll drop this thing for to-day, and play.
-Do you know Robin Hood, Huck?"
-
-"No. Who's Robin Hood?"
-
-"Why, he was one of the greatest men that was ever in England--and the
-best. He was a robber."
-
-"Cracky, I wisht I was. Who did he rob?"
-
-"Only sheriffs and bishops and rich people and kings, and such like.
-But he never bothered the poor. He loved 'em. He always divided up with
-'em perfectly square."
-
-"Well, he must 'a' been a brick."
-
-"I bet you he was, Huck. Oh, he was the noblest man that ever was.
-They ain't any such men now, I can tell you. He could lick any man in
-England, with one hand tied behind him; and he could take his yew bow
-and plug a ten-cent piece every time, a mile and a half."
-
-"What's a YEW bow?"
-
-"I don't know. It's some kind of a bow, of course. And if he hit that
-dime only on the edge he would set down and cry--and curse. But we'll
-play Robin Hood--it's nobby fun. I'll learn you."
-
-"I'm agreed."
-
-So they played Robin Hood all the afternoon, now and then casting a
-yearning eye down upon the haunted house and passing a remark about the
-morrow's prospects and possibilities there. As the sun began to sink
-into the west they took their way homeward athwart the long shadows of
-the trees and soon were buried from sight in the forests of Cardiff
-Hill.
-
-On Saturday, shortly after noon, the boys were at the dead tree again.
-They had a smoke and a chat in the shade, and then dug a little in
-their last hole, not with great hope, but merely because Tom said there
-were so many cases where people had given up a treasure after getting
-down within six inches of it, and then somebody else had come along and
-turned it up with a single thrust of a shovel. The thing failed this
-time, however, so the boys shouldered their tools and went away feeling
-that they had not trifled with fortune, but had fulfilled all the
-requirements that belong to the business of treasure-hunting.
-
-When they reached the haunted house there was something so weird and
-grisly about the dead silence that reigned there under the baking sun,
-and something so depressing about the loneliness and desolation of the
-place, that they were afraid, for a moment, to venture in. Then they
-crept to the door and took a trembling peep. They saw a weed-grown,
-floorless room, unplastered, an ancient fireplace, vacant windows, a
-ruinous staircase; and here, there, and everywhere hung ragged and
-abandoned cobwebs. They presently entered, softly, with quickened
-pulses, talking in whispers, ears alert to catch the slightest sound,
-and muscles tense and ready for instant retreat.
-
-In a little while familiarity modified their fears and they gave the
-place a critical and interested examination, rather admiring their own
-boldness, and wondering at it, too. Next they wanted to look up-stairs.
-This was something like cutting off retreat, but they got to daring
-each other, and of course there could be but one result--they threw
-their tools into a corner and made the ascent. Up there were the same
-signs of decay. In one corner they found a closet that promised
-mystery, but the promise was a fraud--there was nothing in it. Their
-courage was up now and well in hand. They were about to go down and
-begin work when--
-
-"Sh!" said Tom.
-
-"What is it?" whispered Huck, blanching with fright.
-
-"Sh!... There!... Hear it?"
-
-"Yes!... Oh, my! Let's run!"
-
-"Keep still! Don't you budge! They're coming right toward the door."
-
-The boys stretched themselves upon the floor with their eyes to
-knot-holes in the planking, and lay waiting, in a misery of fear.
-
-"They've stopped.... No--coming.... Here they are. Don't whisper
-another word, Huck. My goodness, I wish I was out of this!"
-
-Two men entered. Each boy said to himself: "There's the old deaf and
-dumb Spaniard that's been about town once or twice lately--never saw
-t'other man before."
-
-"T'other" was a ragged, unkempt creature, with nothing very pleasant
-in his face. The Spaniard was wrapped in a serape; he had bushy white
-whiskers; long white hair flowed from under his sombrero, and he wore
-green goggles. When they came in, "t'other" was talking in a low voice;
-they sat down on the ground, facing the door, with their backs to the
-wall, and the speaker continued his remarks. His manner became less
-guarded and his words more distinct as he proceeded:
-
-"No," said he, "I've thought it all over, and I don't like it. It's
-dangerous."
-
-"Dangerous!" grunted the "deaf and dumb" Spaniard--to the vast
-surprise of the boys. "Milksop!"
-
-This voice made the boys gasp and quake. It was Injun Joe's! There was
-silence for some time. Then Joe said:
-
-"What's any more dangerous than that job up yonder--but nothing's come
-of it."
-
-"That's different. Away up the river so, and not another house about.
-'Twon't ever be known that we tried, anyway, long as we didn't succeed."
-
-"Well, what's more dangerous than coming here in the daytime!--anybody
-would suspicion us that saw us."
-
-"I know that. But there warn't any other place as handy after that
-fool of a job. I want to quit this shanty. I wanted to yesterday, only
-it warn't any use trying to stir out of here, with those infernal boys
-playing over there on the hill right in full view."
-
-"Those infernal boys" quaked again under the inspiration of this
-remark, and thought how lucky it was that they had remembered it was
-Friday and concluded to wait a day. They wished in their hearts they
-had waited a year.
-
-The two men got out some food and made a luncheon. After a long and
-thoughtful silence, Injun Joe said:
-
-"Look here, lad--you go back up the river where you belong. Wait there
-till you hear from me. I'll take the chances on dropping into this town
-just once more, for a look. We'll do that 'dangerous' job after I've
-spied around a little and think things look well for it. Then for
-Texas! We'll leg it together!"
-
-This was satisfactory. Both men presently fell to yawning, and Injun
-Joe said:
-
-"I'm dead for sleep! It's your turn to watch."
-
-He curled down in the weeds and soon began to snore. His comrade
-stirred him once or twice and he became quiet. Presently the watcher
-began to nod; his head drooped lower and lower, both men began to snore
-now.
-
-The boys drew a long, grateful breath. Tom whispered:
-
-"Now's our chance--come!"
-
-Huck said:
-
-"I can't--I'd die if they was to wake."
-
-Tom urged--Huck held back. At last Tom rose slowly and softly, and
-started alone. But the first step he made wrung such a hideous creak
-from the crazy floor that he sank down almost dead with fright. He
-never made a second attempt. The boys lay there counting the dragging
-moments till it seemed to them that time must be done and eternity
-growing gray; and then they were grateful to note that at last the sun
-was setting.
-
-Now one snore ceased. Injun Joe sat up, stared around--smiled grimly
-upon his comrade, whose head was drooping upon his knees--stirred him
-up with his foot and said:
-
-"Here! YOU'RE a watchman, ain't you! All right, though--nothing's
-happened."
-
-"My! have I been asleep?"
-
-"Oh, partly, partly. Nearly time for us to be moving, pard. What'll we
-do with what little swag we've got left?"
-
-"I don't know--leave it here as we've always done, I reckon. No use to
-take it away till we start south. Six hundred and fifty in silver's
-something to carry."
-
-"Well--all right--it won't matter to come here once more."
-
-"No--but I'd say come in the night as we used to do--it's better."
-
-"Yes: but look here; it may be a good while before I get the right
-chance at that job; accidents might happen; 'tain't in such a very good
-place; we'll just regularly bury it--and bury it deep."
-
-"Good idea," said the comrade, who walked across the room, knelt down,
-raised one of the rearward hearth-stones and took out a bag that
-jingled pleasantly. He subtracted from it twenty or thirty dollars for
-himself and as much for Injun Joe, and passed the bag to the latter,
-who was on his knees in the corner, now, digging with his bowie-knife.
-
-The boys forgot all their fears, all their miseries in an instant.
-With gloating eyes they watched every movement. Luck!--the splendor of
-it was beyond all imagination! Six hundred dollars was money enough to
-make half a dozen boys rich! Here was treasure-hunting under the
-happiest auspices--there would not be any bothersome uncertainty as to
-where to dig. They nudged each other every moment--eloquent nudges and
-easily understood, for they simply meant--"Oh, but ain't you glad NOW
-we're here!"
-
-Joe's knife struck upon something.
-
-"Hello!" said he.
-
-"What is it?" said his comrade.
-
-"Half-rotten plank--no, it's a box, I believe. Here--bear a hand and
-we'll see what it's here for. Never mind, I've broke a hole."
-
-He reached his hand in and drew it out--
-
-"Man, it's money!"
-
-The two men examined the handful of coins. They were gold. The boys
-above were as excited as themselves, and as delighted.
-
-Joe's comrade said:
-
-"We'll make quick work of this. There's an old rusty pick over amongst
-the weeds in the corner the other side of the fireplace--I saw it a
-minute ago."
-
-He ran and brought the boys' pick and shovel. Injun Joe took the pick,
-looked it over critically, shook his head, muttered something to
-himself, and then began to use it. The box was soon unearthed. It was
-not very large; it was iron bound and had been very strong before the
-slow years had injured it. The men contemplated the treasure awhile in
-blissful silence.
-
-"Pard, there's thousands of dollars here," said Injun Joe.
-
-"'Twas always said that Murrel's gang used to be around here one
-summer," the stranger observed.
-
-"I know it," said Injun Joe; "and this looks like it, I should say."
-
-"Now you won't need to do that job."
-
-The half-breed frowned. Said he:
-
-"You don't know me. Least you don't know all about that thing. 'Tain't
-robbery altogether--it's REVENGE!" and a wicked light flamed in his
-eyes. "I'll need your help in it. When it's finished--then Texas. Go
-home to your Nance and your kids, and stand by till you hear from me."
-
-"Well--if you say so; what'll we do with this--bury it again?"
-
-"Yes. [Ravishing delight overhead.] NO! by the great Sachem, no!
-[Profound distress overhead.] I'd nearly forgot. That pick had fresh
-earth on it! [The boys were sick with terror in a moment.] What
-business has a pick and a shovel here? What business with fresh earth
-on them? Who brought them here--and where are they gone? Have you heard
-anybody?--seen anybody? What! bury it again and leave them to come and
-see the ground disturbed? Not exactly--not exactly. We'll take it to my
-den."
-
-"Why, of course! Might have thought of that before. You mean Number
-One?"
-
-"No--Number Two--under the cross. The other place is bad--too common."
-
-"All right. It's nearly dark enough to start."
-
-Injun Joe got up and went about from window to window cautiously
-peeping out. Presently he said:
-
-"Who could have brought those tools here? Do you reckon they can be
-up-stairs?"
-
-The boys' breath forsook them. Injun Joe put his hand on his knife,
-halted a moment, undecided, and then turned toward the stairway. The
-boys thought of the closet, but their strength was gone. The steps came
-creaking up the stairs--the intolerable distress of the situation woke
-the stricken resolution of the lads--they were about to spring for the
-closet, when there was a crash of rotten timbers and Injun Joe landed
-on the ground amid the debris of the ruined stairway. He gathered
-himself up cursing, and his comrade said:
-
-"Now what's the use of all that? If it's anybody, and they're up
-there, let them STAY there--who cares? If they want to jump down, now,
-and get into trouble, who objects? It will be dark in fifteen minutes
---and then let them follow us if they want to. I'm willing. In my
-opinion, whoever hove those things in here caught a sight of us and
-took us for ghosts or devils or something. I'll bet they're running
-yet."
-
-Joe grumbled awhile; then he agreed with his friend that what daylight
-was left ought to be economized in getting things ready for leaving.
-Shortly afterward they slipped out of the house in the deepening
-twilight, and moved toward the river with their precious box.
-
-Tom and Huck rose up, weak but vastly relieved, and stared after them
-through the chinks between the logs of the house. Follow? Not they.
-They were content to reach ground again without broken necks, and take
-the townward track over the hill. They did not talk much. They were too
-much absorbed in hating themselves--hating the ill luck that made them
-take the spade and the pick there. But for that, Injun Joe never would
-have suspected. He would have hidden the silver with the gold to wait
-there till his "revenge" was satisfied, and then he would have had the
-misfortune to find that money turn up missing. Bitter, bitter luck that
-the tools were ever brought there!
-
-They resolved to keep a lookout for that Spaniard when he should come
-to town spying out for chances to do his revengeful job, and follow him
-to "Number Two," wherever that might be. Then a ghastly thought
-occurred to Tom.
-
-"Revenge? What if he means US, Huck!"
-
-"Oh, don't!" said Huck, nearly fainting.
-
-They talked it all over, and as they entered town they agreed to
-believe that he might possibly mean somebody else--at least that he
-might at least mean nobody but Tom, since only Tom had testified.
-
-Very, very small comfort it was to Tom to be alone in danger! Company
-would be a palpable improvement, he thought.
-
-
-
-CHAPTER XXVII
-
-THE adventure of the day mightily tormented Tom's dreams that night.
-Four times he had his hands on that rich treasure and four times it
-wasted to nothingness in his fingers as sleep forsook him and
-wakefulness brought back the hard reality of his misfortune. As he lay
-in the early morning recalling the incidents of his great adventure, he
-noticed that they seemed curiously subdued and far away--somewhat as if
-they had happened in another world, or in a time long gone by. Then it
-occurred to him that the great adventure itself must be a dream! There
-was one very strong argument in favor of this idea--namely, that the
-quantity of coin he had seen was too vast to be real. He had never seen
-as much as fifty dollars in one mass before, and he was like all boys
-of his age and station in life, in that he imagined that all references
-to "hundreds" and "thousands" were mere fanciful forms of speech, and
-that no such sums really existed in the world. He never had supposed
-for a moment that so large a sum as a hundred dollars was to be found
-in actual money in any one's possession. If his notions of hidden
-treasure had been analyzed, they would have been found to consist of a
-handful of real dimes and a bushel of vague, splendid, ungraspable
-dollars.
-
-But the incidents of his adventure grew sensibly sharper and clearer
-under the attrition of thinking them over, and so he presently found
-himself leaning to the impression that the thing might not have been a
-dream, after all. This uncertainty must be swept away. He would snatch
-a hurried breakfast and go and find Huck. Huck was sitting on the
-gunwale of a flatboat, listlessly dangling his feet in the water and
-looking very melancholy. Tom concluded to let Huck lead up to the
-subject. If he did not do it, then the adventure would be proved to
-have been only a dream.
-
-"Hello, Huck!"
-
-"Hello, yourself."
-
-Silence, for a minute.
-
-"Tom, if we'd 'a' left the blame tools at the dead tree, we'd 'a' got
-the money. Oh, ain't it awful!"
-
-"'Tain't a dream, then, 'tain't a dream! Somehow I most wish it was.
-Dog'd if I don't, Huck."
-
-"What ain't a dream?"
-
-"Oh, that thing yesterday. I been half thinking it was."
-
-"Dream! If them stairs hadn't broke down you'd 'a' seen how much dream
-it was! I've had dreams enough all night--with that patch-eyed Spanish
-devil going for me all through 'em--rot him!"
-
-"No, not rot him. FIND him! Track the money!"
-
-"Tom, we'll never find him. A feller don't have only one chance for
-such a pile--and that one's lost. I'd feel mighty shaky if I was to see
-him, anyway."
-
-"Well, so'd I; but I'd like to see him, anyway--and track him out--to
-his Number Two."
-
-"Number Two--yes, that's it. I been thinking 'bout that. But I can't
-make nothing out of it. What do you reckon it is?"
-
-"I dono. It's too deep. Say, Huck--maybe it's the number of a house!"
-
-"Goody!... No, Tom, that ain't it. If it is, it ain't in this
-one-horse town. They ain't no numbers here."
-
-"Well, that's so. Lemme think a minute. Here--it's the number of a
-room--in a tavern, you know!"
-
-"Oh, that's the trick! They ain't only two taverns. We can find out
-quick."
-
-"You stay here, Huck, till I come."
-
-Tom was off at once. He did not care to have Huck's company in public
-places. He was gone half an hour. He found that in the best tavern, No.
-2 had long been occupied by a young lawyer, and was still so occupied.
-In the less ostentatious house, No. 2 was a mystery. The
-tavern-keeper's young son said it was kept locked all the time, and he
-never saw anybody go into it or come out of it except at night; he did
-not know any particular reason for this state of things; had had some
-little curiosity, but it was rather feeble; had made the most of the
-mystery by entertaining himself with the idea that that room was
-"ha'nted"; had noticed that there was a light in there the night before.
-
-"That's what I've found out, Huck. I reckon that's the very No. 2
-we're after."
-
-"I reckon it is, Tom. Now what you going to do?"
-
-"Lemme think."
-
-Tom thought a long time. Then he said:
-
-"I'll tell you. The back door of that No. 2 is the door that comes out
-into that little close alley between the tavern and the old rattle trap
-of a brick store. Now you get hold of all the door-keys you can find,
-and I'll nip all of auntie's, and the first dark night we'll go there
-and try 'em. And mind you, keep a lookout for Injun Joe, because he
-said he was going to drop into town and spy around once more for a
-chance to get his revenge. If you see him, you just follow him; and if
-he don't go to that No. 2, that ain't the place."
-
-"Lordy, I don't want to foller him by myself!"
-
-"Why, it'll be night, sure. He mightn't ever see you--and if he did,
-maybe he'd never think anything."
-
-"Well, if it's pretty dark I reckon I'll track him. I dono--I dono.
-I'll try."
-
-"You bet I'll follow him, if it's dark, Huck. Why, he might 'a' found
-out he couldn't get his revenge, and be going right after that money."
-
-"It's so, Tom, it's so. I'll foller him; I will, by jingoes!"
-
-"Now you're TALKING! Don't you ever weaken, Huck, and I won't."
-
-
-
-CHAPTER XXVIII
-
-THAT night Tom and Huck were ready for their adventure. They hung
-about the neighborhood of the tavern until after nine, one watching the
-alley at a distance and the other the tavern door. Nobody entered the
-alley or left it; nobody resembling the Spaniard entered or left the
-tavern door. The night promised to be a fair one; so Tom went home with
-the understanding that if a considerable degree of darkness came on,
-Huck was to come and "maow," whereupon he would slip out and try the
-keys. But the night remained clear, and Huck closed his watch and
-retired to bed in an empty sugar hogshead about twelve.
-
-Tuesday the boys had the same ill luck. Also Wednesday. But Thursday
-night promised better. Tom slipped out in good season with his aunt's
-old tin lantern, and a large towel to blindfold it with. He hid the
-lantern in Huck's sugar hogshead and the watch began. An hour before
-midnight the tavern closed up and its lights (the only ones
-thereabouts) were put out. No Spaniard had been seen. Nobody had
-entered or left the alley. Everything was auspicious. The blackness of
-darkness reigned, the perfect stillness was interrupted only by
-occasional mutterings of distant thunder.
-
-Tom got his lantern, lit it in the hogshead, wrapped it closely in the
-towel, and the two adventurers crept in the gloom toward the tavern.
-Huck stood sentry and Tom felt his way into the alley. Then there was a
-season of waiting anxiety that weighed upon Huck's spirits like a
-mountain. He began to wish he could see a flash from the lantern--it
-would frighten him, but it would at least tell him that Tom was alive
-yet. It seemed hours since Tom had disappeared. Surely he must have
-fainted; maybe he was dead; maybe his heart had burst under terror and
-excitement. In his uneasiness Huck found himself drawing closer and
-closer to the alley; fearing all sorts of dreadful things, and
-momentarily expecting some catastrophe to happen that would take away
-his breath. There was not much to take away, for he seemed only able to
-inhale it by thimblefuls, and his heart would soon wear itself out, the
-way it was beating. Suddenly there was a flash of light and Tom came
-tearing by him: "Run!" said he; "run, for your life!"
-
-He needn't have repeated it; once was enough; Huck was making thirty
-or forty miles an hour before the repetition was uttered. The boys
-never stopped till they reached the shed of a deserted slaughter-house
-at the lower end of the village. Just as they got within its shelter
-the storm burst and the rain poured down. As soon as Tom got his breath
-he said:
-
-"Huck, it was awful! I tried two of the keys, just as soft as I could;
-but they seemed to make such a power of racket that I couldn't hardly
-get my breath I was so scared. They wouldn't turn in the lock, either.
-Well, without noticing what I was doing, I took hold of the knob, and
-open comes the door! It warn't locked! I hopped in, and shook off the
-towel, and, GREAT CAESAR'S GHOST!"
-
-"What!--what'd you see, Tom?"
-
-"Huck, I most stepped onto Injun Joe's hand!"
-
-"No!"
-
-"Yes! He was lying there, sound asleep on the floor, with his old
-patch on his eye and his arms spread out."
-
-"Lordy, what did you do? Did he wake up?"
-
-"No, never budged. Drunk, I reckon. I just grabbed that towel and
-started!"
-
-"I'd never 'a' thought of the towel, I bet!"
-
-"Well, I would. My aunt would make me mighty sick if I lost it."
-
-"Say, Tom, did you see that box?"
-
-"Huck, I didn't wait to look around. I didn't see the box, I didn't
-see the cross. I didn't see anything but a bottle and a tin cup on the
-floor by Injun Joe; yes, I saw two barrels and lots more bottles in the
-room. Don't you see, now, what's the matter with that ha'nted room?"
-
-"How?"
-
-"Why, it's ha'nted with whiskey! Maybe ALL the Temperance Taverns have
-got a ha'nted room, hey, Huck?"
-
-"Well, I reckon maybe that's so. Who'd 'a' thought such a thing? But
-say, Tom, now's a mighty good time to get that box, if Injun Joe's
-drunk."
-
-"It is, that! You try it!"
-
-Huck shuddered.
-
-"Well, no--I reckon not."
-
-"And I reckon not, Huck. Only one bottle alongside of Injun Joe ain't
-enough. If there'd been three, he'd be drunk enough and I'd do it."
-
-There was a long pause for reflection, and then Tom said:
-
-"Lookyhere, Huck, less not try that thing any more till we know Injun
-Joe's not in there. It's too scary. Now, if we watch every night, we'll
-be dead sure to see him go out, some time or other, and then we'll
-snatch that box quicker'n lightning."
-
-"Well, I'm agreed. I'll watch the whole night long, and I'll do it
-every night, too, if you'll do the other part of the job."
-
-"All right, I will. All you got to do is to trot up Hooper Street a
-block and maow--and if I'm asleep, you throw some gravel at the window
-and that'll fetch me."
-
-"Agreed, and good as wheat!"
-
-"Now, Huck, the storm's over, and I'll go home. It'll begin to be
-daylight in a couple of hours. You go back and watch that long, will
-you?"
-
-"I said I would, Tom, and I will. I'll ha'nt that tavern every night
-for a year! I'll sleep all day and I'll stand watch all night."
-
-"That's all right. Now, where you going to sleep?"
-
-"In Ben Rogers' hayloft. He lets me, and so does his pap's nigger man,
-Uncle Jake. I tote water for Uncle Jake whenever he wants me to, and
-any time I ask him he gives me a little something to eat if he can
-spare it. That's a mighty good nigger, Tom. He likes me, becuz I don't
-ever act as if I was above him. Sometime I've set right down and eat
-WITH him. But you needn't tell that. A body's got to do things when
-he's awful hungry he wouldn't want to do as a steady thing."
-
-"Well, if I don't want you in the daytime, I'll let you sleep. I won't
-come bothering around. Any time you see something's up, in the night,
-just skip right around and maow."
-
-
-
-CHAPTER XXIX
-
-THE first thing Tom heard on Friday morning was a glad piece of news
---Judge Thatcher's family had come back to town the night before. Both
-Injun Joe and the treasure sunk into secondary importance for a moment,
-and Becky took the chief place in the boy's interest. He saw her and
-they had an exhausting good time playing "hi-spy" and "gully-keeper"
-with a crowd of their school-mates. The day was completed and crowned
-in a peculiarly satisfactory way: Becky teased her mother to appoint
-the next day for the long-promised and long-delayed picnic, and she
-consented. The child's delight was boundless; and Tom's not more
-moderate. The invitations were sent out before sunset, and straightway
-the young folks of the village were thrown into a fever of preparation
-and pleasurable anticipation. Tom's excitement enabled him to keep
-awake until a pretty late hour, and he had good hopes of hearing Huck's
-"maow," and of having his treasure to astonish Becky and the picnickers
-with, next day; but he was disappointed. No signal came that night.
-
-Morning came, eventually, and by ten or eleven o'clock a giddy and
-rollicking company were gathered at Judge Thatcher's, and everything
-was ready for a start. It was not the custom for elderly people to mar
-the picnics with their presence. The children were considered safe
-enough under the wings of a few young ladies of eighteen and a few
-young gentlemen of twenty-three or thereabouts. The old steam ferryboat
-was chartered for the occasion; presently the gay throng filed up the
-main street laden with provision-baskets. Sid was sick and had to miss
-the fun; Mary remained at home to entertain him. The last thing Mrs.
-Thatcher said to Becky, was:
-
-"You'll not get back till late. Perhaps you'd better stay all night
-with some of the girls that live near the ferry-landing, child."
-
-"Then I'll stay with Susy Harper, mamma."
-
-"Very well. And mind and behave yourself and don't be any trouble."
-
-Presently, as they tripped along, Tom said to Becky:
-
-"Say--I'll tell you what we'll do. 'Stead of going to Joe Harper's
-we'll climb right up the hill and stop at the Widow Douglas'. She'll
-have ice-cream! She has it most every day--dead loads of it. And she'll
-be awful glad to have us."
-
-"Oh, that will be fun!"
-
-Then Becky reflected a moment and said:
-
-"But what will mamma say?"
-
-"How'll she ever know?"
-
-The girl turned the idea over in her mind, and said reluctantly:
-
-"I reckon it's wrong--but--"
-
-"But shucks! Your mother won't know, and so what's the harm? All she
-wants is that you'll be safe; and I bet you she'd 'a' said go there if
-she'd 'a' thought of it. I know she would!"
-
-The Widow Douglas' splendid hospitality was a tempting bait. It and
-Tom's persuasions presently carried the day. So it was decided to say
-nothing anybody about the night's programme. Presently it occurred to
-Tom that maybe Huck might come this very night and give the signal. The
-thought took a deal of the spirit out of his anticipations. Still he
-could not bear to give up the fun at Widow Douglas'. And why should he
-give it up, he reasoned--the signal did not come the night before, so
-why should it be any more likely to come to-night? The sure fun of the
-evening outweighed the uncertain treasure; and, boy-like, he determined
-to yield to the stronger inclination and not allow himself to think of
-the box of money another time that day.
-
-Three miles below town the ferryboat stopped at the mouth of a woody
-hollow and tied up. The crowd swarmed ashore and soon the forest
-distances and craggy heights echoed far and near with shoutings and
-laughter. All the different ways of getting hot and tired were gone
-through with, and by-and-by the rovers straggled back to camp fortified
-with responsible appetites, and then the destruction of the good things
-began. After the feast there was a refreshing season of rest and chat
-in the shade of spreading oaks. By-and-by somebody shouted:
-
-"Who's ready for the cave?"
-
-Everybody was. Bundles of candles were procured, and straightway there
-was a general scamper up the hill. The mouth of the cave was up the
-hillside--an opening shaped like a letter A. Its massive oaken door
-stood unbarred. Within was a small chamber, chilly as an ice-house, and
-walled by Nature with solid limestone that was dewy with a cold sweat.
-It was romantic and mysterious to stand here in the deep gloom and look
-out upon the green valley shining in the sun. But the impressiveness of
-the situation quickly wore off, and the romping began again. The moment
-a candle was lighted there was a general rush upon the owner of it; a
-struggle and a gallant defence followed, but the candle was soon
-knocked down or blown out, and then there was a glad clamor of laughter
-and a new chase. But all things have an end. By-and-by the procession
-went filing down the steep descent of the main avenue, the flickering
-rank of lights dimly revealing the lofty walls of rock almost to their
-point of junction sixty feet overhead. This main avenue was not more
-than eight or ten feet wide. Every few steps other lofty and still
-narrower crevices branched from it on either hand--for McDougal's cave
-was but a vast labyrinth of crooked aisles that ran into each other and
-out again and led nowhere. It was said that one might wander days and
-nights together through its intricate tangle of rifts and chasms, and
-never find the end of the cave; and that he might go down, and down,
-and still down, into the earth, and it was just the same--labyrinth
-under labyrinth, and no end to any of them. No man "knew" the cave.
-That was an impossible thing. Most of the young men knew a portion of
-it, and it was not customary to venture much beyond this known portion.
-Tom Sawyer knew as much of the cave as any one.
-
-The procession moved along the main avenue some three-quarters of a
-mile, and then groups and couples began to slip aside into branch
-avenues, fly along the dismal corridors, and take each other by
-surprise at points where the corridors joined again. Parties were able
-to elude each other for the space of half an hour without going beyond
-the "known" ground.
-
-By-and-by, one group after another came straggling back to the mouth
-of the cave, panting, hilarious, smeared from head to foot with tallow
-drippings, daubed with clay, and entirely delighted with the success of
-the day. Then they were astonished to find that they had been taking no
-note of time and that night was about at hand. The clanging bell had
-been calling for half an hour. However, this sort of close to the day's
-adventures was romantic and therefore satisfactory. When the ferryboat
-with her wild freight pushed into the stream, nobody cared sixpence for
-the wasted time but the captain of the craft.
-
-Huck was already upon his watch when the ferryboat's lights went
-glinting past the wharf. He heard no noise on board, for the young
-people were as subdued and still as people usually are who are nearly
-tired to death. He wondered what boat it was, and why she did not stop
-at the wharf--and then he dropped her out of his mind and put his
-attention upon his business. The night was growing cloudy and dark. Ten
-o'clock came, and the noise of vehicles ceased, scattered lights began
-to wink out, all straggling foot-passengers disappeared, the village
-betook itself to its slumbers and left the small watcher alone with the
-silence and the ghosts. Eleven o'clock came, and the tavern lights were
-put out; darkness everywhere, now. Huck waited what seemed a weary long
-time, but nothing happened. His faith was weakening. Was there any use?
-Was there really any use? Why not give it up and turn in?
-
-A noise fell upon his ear. He was all attention in an instant. The
-alley door closed softly. He sprang to the corner of the brick store.
-The next moment two men brushed by him, and one seemed to have
-something under his arm. It must be that box! So they were going to
-remove the treasure. Why call Tom now? It would be absurd--the men
-would get away with the box and never be found again. No, he would
-stick to their wake and follow them; he would trust to the darkness for
-security from discovery. So communing with himself, Huck stepped out
-and glided along behind the men, cat-like, with bare feet, allowing
-them to keep just far enough ahead not to be invisible.
-
-They moved up the river street three blocks, then turned to the left
-up a cross-street. They went straight ahead, then, until they came to
-the path that led up Cardiff Hill; this they took. They passed by the
-old Welshman's house, half-way up the hill, without hesitating, and
-still climbed upward. Good, thought Huck, they will bury it in the old
-quarry. But they never stopped at the quarry. They passed on, up the
-summit. They plunged into the narrow path between the tall sumach
-bushes, and were at once hidden in the gloom. Huck closed up and
-shortened his distance, now, for they would never be able to see him.
-He trotted along awhile; then slackened his pace, fearing he was
-gaining too fast; moved on a piece, then stopped altogether; listened;
-no sound; none, save that he seemed to hear the beating of his own
-heart. The hooting of an owl came over the hill--ominous sound! But no
-footsteps. Heavens, was everything lost! He was about to spring with
-winged feet, when a man cleared his throat not four feet from him!
-Huck's heart shot into his throat, but he swallowed it again; and then
-he stood there shaking as if a dozen agues had taken charge of him at
-once, and so weak that he thought he must surely fall to the ground. He
-knew where he was. He knew he was within five steps of the stile
-leading into Widow Douglas' grounds. Very well, he thought, let them
-bury it there; it won't be hard to find.
-
-Now there was a voice--a very low voice--Injun Joe's:
-
-"Damn her, maybe she's got company--there's lights, late as it is."
-
-"I can't see any."
-
-This was that stranger's voice--the stranger of the haunted house. A
-deadly chill went to Huck's heart--this, then, was the "revenge" job!
-His thought was, to fly. Then he remembered that the Widow Douglas had
-been kind to him more than once, and maybe these men were going to
-murder her. He wished he dared venture to warn her; but he knew he
-didn't dare--they might come and catch him. He thought all this and
-more in the moment that elapsed between the stranger's remark and Injun
-Joe's next--which was--
-
-"Because the bush is in your way. Now--this way--now you see, don't
-you?"
-
-"Yes. Well, there IS company there, I reckon. Better give it up."
-
-"Give it up, and I just leaving this country forever! Give it up and
-maybe never have another chance. I tell you again, as I've told you
-before, I don't care for her swag--you may have it. But her husband was
-rough on me--many times he was rough on me--and mainly he was the
-justice of the peace that jugged me for a vagrant. And that ain't all.
-It ain't a millionth part of it! He had me HORSEWHIPPED!--horsewhipped
-in front of the jail, like a nigger!--with all the town looking on!
-HORSEWHIPPED!--do you understand? He took advantage of me and died. But
-I'll take it out of HER."
-
-"Oh, don't kill her! Don't do that!"
-
-"Kill? Who said anything about killing? I would kill HIM if he was
-here; but not her. When you want to get revenge on a woman you don't
-kill her--bosh! you go for her looks. You slit her nostrils--you notch
-her ears like a sow!"
-
-"By God, that's--"
-
-"Keep your opinion to yourself! It will be safest for you. I'll tie
-her to the bed. If she bleeds to death, is that my fault? I'll not cry,
-if she does. My friend, you'll help me in this thing--for MY sake
---that's why you're here--I mightn't be able alone. If you flinch, I'll
-kill you. Do you understand that? And if I have to kill you, I'll kill
-her--and then I reckon nobody'll ever know much about who done this
-business."
-
-"Well, if it's got to be done, let's get at it. The quicker the
-better--I'm all in a shiver."
-
-"Do it NOW? And company there? Look here--I'll get suspicious of you,
-first thing you know. No--we'll wait till the lights are out--there's
-no hurry."
-
-Huck felt that a silence was going to ensue--a thing still more awful
-than any amount of murderous talk; so he held his breath and stepped
-gingerly back; planted his foot carefully and firmly, after balancing,
-one-legged, in a precarious way and almost toppling over, first on one
-side and then on the other. He took another step back, with the same
-elaboration and the same risks; then another and another, and--a twig
-snapped under his foot! His breath stopped and he listened. There was
-no sound--the stillness was perfect. His gratitude was measureless. Now
-he turned in his tracks, between the walls of sumach bushes--turned
-himself as carefully as if he were a ship--and then stepped quickly but
-cautiously along. When he emerged at the quarry he felt secure, and so
-he picked up his nimble heels and flew. Down, down he sped, till he
-reached the Welshman's. He banged at the door, and presently the heads
-of the old man and his two stalwart sons were thrust from windows.
-
-"What's the row there? Who's banging? What do you want?"
-
-"Let me in--quick! I'll tell everything."
-
-"Why, who are you?"
-
-"Huckleberry Finn--quick, let me in!"
-
-"Huckleberry Finn, indeed! It ain't a name to open many doors, I
-judge! But let him in, lads, and let's see what's the trouble."
-
-"Please don't ever tell I told you," were Huck's first words when he
-got in. "Please don't--I'd be killed, sure--but the widow's been good
-friends to me sometimes, and I want to tell--I WILL tell if you'll
-promise you won't ever say it was me."
-
-"By George, he HAS got something to tell, or he wouldn't act so!"
-exclaimed the old man; "out with it and nobody here'll ever tell, lad."
-
-Three minutes later the old man and his sons, well armed, were up the
-hill, and just entering the sumach path on tiptoe, their weapons in
-their hands. Huck accompanied them no further. He hid behind a great
-bowlder and fell to listening. There was a lagging, anxious silence,
-and then all of a sudden there was an explosion of firearms and a cry.
-
-Huck waited for no particulars. He sprang away and sped down the hill
-as fast as his legs could carry him.
-
-
-
-CHAPTER XXX
-
-AS the earliest suspicion of dawn appeared on Sunday morning, Huck
-came groping up the hill and rapped gently at the old Welshman's door.
-The inmates were asleep, but it was a sleep that was set on a
-hair-trigger, on account of the exciting episode of the night. A call
-came from a window:
-
-"Who's there!"
-
-Huck's scared voice answered in a low tone:
-
-"Please let me in! It's only Huck Finn!"
-
-"It's a name that can open this door night or day, lad!--and welcome!"
-
-These were strange words to the vagabond boy's ears, and the
-pleasantest he had ever heard. He could not recollect that the closing
-word had ever been applied in his case before. The door was quickly
-unlocked, and he entered. Huck was given a seat and the old man and his
-brace of tall sons speedily dressed themselves.
-
-"Now, my boy, I hope you're good and hungry, because breakfast will be
-ready as soon as the sun's up, and we'll have a piping hot one, too
---make yourself easy about that! I and the boys hoped you'd turn up and
-stop here last night."
-
-"I was awful scared," said Huck, "and I run. I took out when the
-pistols went off, and I didn't stop for three mile. I've come now becuz
-I wanted to know about it, you know; and I come before daylight becuz I
-didn't want to run across them devils, even if they was dead."
-
-"Well, poor chap, you do look as if you'd had a hard night of it--but
-there's a bed here for you when you've had your breakfast. No, they
-ain't dead, lad--we are sorry enough for that. You see we knew right
-where to put our hands on them, by your description; so we crept along
-on tiptoe till we got within fifteen feet of them--dark as a cellar
-that sumach path was--and just then I found I was going to sneeze. It
-was the meanest kind of luck! I tried to keep it back, but no use
---'twas bound to come, and it did come! I was in the lead with my pistol
-raised, and when the sneeze started those scoundrels a-rustling to get
-out of the path, I sung out, 'Fire boys!' and blazed away at the place
-where the rustling was. So did the boys. But they were off in a jiffy,
-those villains, and we after them, down through the woods. I judge we
-never touched them. They fired a shot apiece as they started, but their
-bullets whizzed by and didn't do us any harm. As soon as we lost the
-sound of their feet we quit chasing, and went down and stirred up the
-constables. They got a posse together, and went off to guard the river
-bank, and as soon as it is light the sheriff and a gang are going to
-beat up the woods. My boys will be with them presently. I wish we had
-some sort of description of those rascals--'twould help a good deal.
-But you couldn't see what they were like, in the dark, lad, I suppose?"
-
-"Oh yes; I saw them down-town and follered them."
-
-"Splendid! Describe them--describe them, my boy!"
-
-"One's the old deaf and dumb Spaniard that's ben around here once or
-twice, and t'other's a mean-looking, ragged--"
-
-"That's enough, lad, we know the men! Happened on them in the woods
-back of the widow's one day, and they slunk away. Off with you, boys,
-and tell the sheriff--get your breakfast to-morrow morning!"
-
-The Welshman's sons departed at once. As they were leaving the room
-Huck sprang up and exclaimed:
-
-"Oh, please don't tell ANYbody it was me that blowed on them! Oh,
-please!"
-
-"All right if you say it, Huck, but you ought to have the credit of
-what you did."
-
-"Oh no, no! Please don't tell!"
-
-When the young men were gone, the old Welshman said:
-
-"They won't tell--and I won't. But why don't you want it known?"
-
-Huck would not explain, further than to say that he already knew too
-much about one of those men and would not have the man know that he
-knew anything against him for the whole world--he would be killed for
-knowing it, sure.
-
-The old man promised secrecy once more, and said:
-
-"How did you come to follow these fellows, lad? Were they looking
-suspicious?"
-
-Huck was silent while he framed a duly cautious reply. Then he said:
-
-"Well, you see, I'm a kind of a hard lot,--least everybody says so,
-and I don't see nothing agin it--and sometimes I can't sleep much, on
-account of thinking about it and sort of trying to strike out a new way
-of doing. That was the way of it last night. I couldn't sleep, and so I
-come along up-street 'bout midnight, a-turning it all over, and when I
-got to that old shackly brick store by the Temperance Tavern, I backed
-up agin the wall to have another think. Well, just then along comes
-these two chaps slipping along close by me, with something under their
-arm, and I reckoned they'd stole it. One was a-smoking, and t'other one
-wanted a light; so they stopped right before me and the cigars lit up
-their faces and I see that the big one was the deaf and dumb Spaniard,
-by his white whiskers and the patch on his eye, and t'other one was a
-rusty, ragged-looking devil."
-
-"Could you see the rags by the light of the cigars?"
-
-This staggered Huck for a moment. Then he said:
-
-"Well, I don't know--but somehow it seems as if I did."
-
-"Then they went on, and you--"
-
-"Follered 'em--yes. That was it. I wanted to see what was up--they
-sneaked along so. I dogged 'em to the widder's stile, and stood in the
-dark and heard the ragged one beg for the widder, and the Spaniard
-swear he'd spile her looks just as I told you and your two--"
-
-"What! The DEAF AND DUMB man said all that!"
-
-Huck had made another terrible mistake! He was trying his best to keep
-the old man from getting the faintest hint of who the Spaniard might
-be, and yet his tongue seemed determined to get him into trouble in
-spite of all he could do. He made several efforts to creep out of his
-scrape, but the old man's eye was upon him and he made blunder after
-blunder. Presently the Welshman said:
-
-"My boy, don't be afraid of me. I wouldn't hurt a hair of your head
-for all the world. No--I'd protect you--I'd protect you. This Spaniard
-is not deaf and dumb; you've let that slip without intending it; you
-can't cover that up now. You know something about that Spaniard that
-you want to keep dark. Now trust me--tell me what it is, and trust me
---I won't betray you."
-
-Huck looked into the old man's honest eyes a moment, then bent over
-and whispered in his ear:
-
-"'Tain't a Spaniard--it's Injun Joe!"
-
-The Welshman almost jumped out of his chair. In a moment he said:
-
-"It's all plain enough, now. When you talked about notching ears and
-slitting noses I judged that that was your own embellishment, because
-white men don't take that sort of revenge. But an Injun! That's a
-different matter altogether."
-
-During breakfast the talk went on, and in the course of it the old man
-said that the last thing which he and his sons had done, before going
-to bed, was to get a lantern and examine the stile and its vicinity for
-marks of blood. They found none, but captured a bulky bundle of--
-
-"Of WHAT?"
-
-If the words had been lightning they could not have leaped with a more
-stunning suddenness from Huck's blanched lips. His eyes were staring
-wide, now, and his breath suspended--waiting for the answer. The
-Welshman started--stared in return--three seconds--five seconds--ten
---then replied:
-
-"Of burglar's tools. Why, what's the MATTER with you?"
-
-Huck sank back, panting gently, but deeply, unutterably grateful. The
-Welshman eyed him gravely, curiously--and presently said:
-
-"Yes, burglar's tools. That appears to relieve you a good deal. But
-what did give you that turn? What were YOU expecting we'd found?"
-
-Huck was in a close place--the inquiring eye was upon him--he would
-have given anything for material for a plausible answer--nothing
-suggested itself--the inquiring eye was boring deeper and deeper--a
-senseless reply offered--there was no time to weigh it, so at a venture
-he uttered it--feebly:
-
-"Sunday-school books, maybe."
-
-Poor Huck was too distressed to smile, but the old man laughed loud
-and joyously, shook up the details of his anatomy from head to foot,
-and ended by saying that such a laugh was money in a-man's pocket,
-because it cut down the doctor's bill like everything. Then he added:
-
-"Poor old chap, you're white and jaded--you ain't well a bit--no
-wonder you're a little flighty and off your balance. But you'll come
-out of it. Rest and sleep will fetch you out all right, I hope."
-
-Huck was irritated to think he had been such a goose and betrayed such
-a suspicious excitement, for he had dropped the idea that the parcel
-brought from the tavern was the treasure, as soon as he had heard the
-talk at the widow's stile. He had only thought it was not the treasure,
-however--he had not known that it wasn't--and so the suggestion of a
-captured bundle was too much for his self-possession. But on the whole
-he felt glad the little episode had happened, for now he knew beyond
-all question that that bundle was not THE bundle, and so his mind was
-at rest and exceedingly comfortable. In fact, everything seemed to be
-drifting just in the right direction, now; the treasure must be still
-in No. 2, the men would be captured and jailed that day, and he and Tom
-could seize the gold that night without any trouble or any fear of
-interruption.
-
-Just as breakfast was completed there was a knock at the door. Huck
-jumped for a hiding-place, for he had no mind to be connected even
-remotely with the late event. The Welshman admitted several ladies and
-gentlemen, among them the Widow Douglas, and noticed that groups of
-citizens were climbing up the hill--to stare at the stile. So the news
-had spread. The Welshman had to tell the story of the night to the
-visitors. The widow's gratitude for her preservation was outspoken.
-
-"Don't say a word about it, madam. There's another that you're more
-beholden to than you are to me and my boys, maybe, but he don't allow
-me to tell his name. We wouldn't have been there but for him."
-
-Of course this excited a curiosity so vast that it almost belittled
-the main matter--but the Welshman allowed it to eat into the vitals of
-his visitors, and through them be transmitted to the whole town, for he
-refused to part with his secret. When all else had been learned, the
-widow said:
-
-"I went to sleep reading in bed and slept straight through all that
-noise. Why didn't you come and wake me?"
-
-"We judged it warn't worth while. Those fellows warn't likely to come
-again--they hadn't any tools left to work with, and what was the use of
-waking you up and scaring you to death? My three negro men stood guard
-at your house all the rest of the night. They've just come back."
-
-More visitors came, and the story had to be told and retold for a
-couple of hours more.
-
-There was no Sabbath-school during day-school vacation, but everybody
-was early at church. The stirring event was well canvassed. News came
-that not a sign of the two villains had been yet discovered. When the
-sermon was finished, Judge Thatcher's wife dropped alongside of Mrs.
-Harper as she moved down the aisle with the crowd and said:
-
-"Is my Becky going to sleep all day? I just expected she would be
-tired to death."
-
-"Your Becky?"
-
-"Yes," with a startled look--"didn't she stay with you last night?"
-
-"Why, no."
-
-Mrs. Thatcher turned pale, and sank into a pew, just as Aunt Polly,
-talking briskly with a friend, passed by. Aunt Polly said:
-
-"Good-morning, Mrs. Thatcher. Good-morning, Mrs. Harper. I've got a
-boy that's turned up missing. I reckon my Tom stayed at your house last
-night--one of you. And now he's afraid to come to church. I've got to
-settle with him."
-
-Mrs. Thatcher shook her head feebly and turned paler than ever.
-
-"He didn't stay with us," said Mrs. Harper, beginning to look uneasy.
-A marked anxiety came into Aunt Polly's face.
-
-"Joe Harper, have you seen my Tom this morning?"
-
-"No'm."
-
-"When did you see him last?"
-
-Joe tried to remember, but was not sure he could say. The people had
-stopped moving out of church. Whispers passed along, and a boding
-uneasiness took possession of every countenance. Children were
-anxiously questioned, and young teachers. They all said they had not
-noticed whether Tom and Becky were on board the ferryboat on the
-homeward trip; it was dark; no one thought of inquiring if any one was
-missing. One young man finally blurted out his fear that they were
-still in the cave! Mrs. Thatcher swooned away. Aunt Polly fell to
-crying and wringing her hands.
-
-The alarm swept from lip to lip, from group to group, from street to
-street, and within five minutes the bells were wildly clanging and the
-whole town was up! The Cardiff Hill episode sank into instant
-insignificance, the burglars were forgotten, horses were saddled,
-skiffs were manned, the ferryboat ordered out, and before the horror
-was half an hour old, two hundred men were pouring down highroad and
-river toward the cave.
-
-All the long afternoon the village seemed empty and dead. Many women
-visited Aunt Polly and Mrs. Thatcher and tried to comfort them. They
-cried with them, too, and that was still better than words. All the
-tedious night the town waited for news; but when the morning dawned at
-last, all the word that came was, "Send more candles--and send food."
-Mrs. Thatcher was almost crazed; and Aunt Polly, also. Judge Thatcher
-sent messages of hope and encouragement from the cave, but they
-conveyed no real cheer.
-
-The old Welshman came home toward daylight, spattered with
-candle-grease, smeared with clay, and almost worn out. He found Huck
-still in the bed that had been provided for him, and delirious with
-fever. The physicians were all at the cave, so the Widow Douglas came
-and took charge of the patient. She said she would do her best by him,
-because, whether he was good, bad, or indifferent, he was the Lord's,
-and nothing that was the Lord's was a thing to be neglected. The
-Welshman said Huck had good spots in him, and the widow said:
-
-"You can depend on it. That's the Lord's mark. He don't leave it off.
-He never does. Puts it somewhere on every creature that comes from his
-hands."
-
-Early in the forenoon parties of jaded men began to straggle into the
-village, but the strongest of the citizens continued searching. All the
-news that could be gained was that remotenesses of the cavern were
-being ransacked that had never been visited before; that every corner
-and crevice was going to be thoroughly searched; that wherever one
-wandered through the maze of passages, lights were to be seen flitting
-hither and thither in the distance, and shoutings and pistol-shots sent
-their hollow reverberations to the ear down the sombre aisles. In one
-place, far from the section usually traversed by tourists, the names
-"BECKY & TOM" had been found traced upon the rocky wall with
-candle-smoke, and near at hand a grease-soiled bit of ribbon. Mrs.
-Thatcher recognized the ribbon and cried over it. She said it was the
-last relic she should ever have of her child; and that no other memorial
-of her could ever be so precious, because this one parted latest from
-the living body before the awful death came. Some said that now and
-then, in the cave, a far-away speck of light would glimmer, and then a
-glorious shout would burst forth and a score of men go trooping down the
-echoing aisle--and then a sickening disappointment always followed; the
-children were not there; it was only a searcher's light.
-
-Three dreadful days and nights dragged their tedious hours along, and
-the village sank into a hopeless stupor. No one had heart for anything.
-The accidental discovery, just made, that the proprietor of the
-Temperance Tavern kept liquor on his premises, scarcely fluttered the
-public pulse, tremendous as the fact was. In a lucid interval, Huck
-feebly led up to the subject of taverns, and finally asked--dimly
-dreading the worst--if anything had been discovered at the Temperance
-Tavern since he had been ill.
-
-"Yes," said the widow.
-
-Huck started up in bed, wild-eyed:
-
-"What? What was it?"
-
-"Liquor!--and the place has been shut up. Lie down, child--what a turn
-you did give me!"
-
-"Only tell me just one thing--only just one--please! Was it Tom Sawyer
-that found it?"
-
-The widow burst into tears. "Hush, hush, child, hush! I've told you
-before, you must NOT talk. You are very, very sick!"
-
-Then nothing but liquor had been found; there would have been a great
-powwow if it had been the gold. So the treasure was gone forever--gone
-forever! But what could she be crying about? Curious that she should
-cry.
-
-These thoughts worked their dim way through Huck's mind, and under the
-weariness they gave him he fell asleep. The widow said to herself:
-
-"There--he's asleep, poor wreck. Tom Sawyer find it! Pity but somebody
-could find Tom Sawyer! Ah, there ain't many left, now, that's got hope
-enough, or strength enough, either, to go on searching."
-
-
-
-CHAPTER XXXI
-
-NOW to return to Tom and Becky's share in the picnic. They tripped
-along the murky aisles with the rest of the company, visiting the
-familiar wonders of the cave--wonders dubbed with rather
-over-descriptive names, such as "The Drawing-Room," "The Cathedral,"
-"Aladdin's Palace," and so on. Presently the hide-and-seek frolicking
-began, and Tom and Becky engaged in it with zeal until the exertion
-began to grow a trifle wearisome; then they wandered down a sinuous
-avenue holding their candles aloft and reading the tangled web-work of
-names, dates, post-office addresses, and mottoes with which the rocky
-walls had been frescoed (in candle-smoke). Still drifting along and
-talking, they scarcely noticed that they were now in a part of the cave
-whose walls were not frescoed. They smoked their own names under an
-overhanging shelf and moved on. Presently they came to a place where a
-little stream of water, trickling over a ledge and carrying a limestone
-sediment with it, had, in the slow-dragging ages, formed a laced and
-ruffled Niagara in gleaming and imperishable stone. Tom squeezed his
-small body behind it in order to illuminate it for Becky's
-gratification. He found that it curtained a sort of steep natural
-stairway which was enclosed between narrow walls, and at once the
-ambition to be a discoverer seized him. Becky responded to his call,
-and they made a smoke-mark for future guidance, and started upon their
-quest. They wound this way and that, far down into the secret depths of
-the cave, made another mark, and branched off in search of novelties to
-tell the upper world about. In one place they found a spacious cavern,
-from whose ceiling depended a multitude of shining stalactites of the
-length and circumference of a man's leg; they walked all about it,
-wondering and admiring, and presently left it by one of the numerous
-passages that opened into it. This shortly brought them to a bewitching
-spring, whose basin was incrusted with a frostwork of glittering
-crystals; it was in the midst of a cavern whose walls were supported by
-many fantastic pillars which had been formed by the joining of great
-stalactites and stalagmites together, the result of the ceaseless
-water-drip of centuries. Under the roof vast knots of bats had packed
-themselves together, thousands in a bunch; the lights disturbed the
-creatures and they came flocking down by hundreds, squeaking and
-darting furiously at the candles. Tom knew their ways and the danger of
-this sort of conduct. He seized Becky's hand and hurried her into the
-first corridor that offered; and none too soon, for a bat struck
-Becky's light out with its wing while she was passing out of the
-cavern. The bats chased the children a good distance; but the fugitives
-plunged into every new passage that offered, and at last got rid of the
-perilous things. Tom found a subterranean lake, shortly, which
-stretched its dim length away until its shape was lost in the shadows.
-He wanted to explore its borders, but concluded that it would be best
-to sit down and rest awhile, first. Now, for the first time, the deep
-stillness of the place laid a clammy hand upon the spirits of the
-children. Becky said:
-
-"Why, I didn't notice, but it seems ever so long since I heard any of
-the others."
-
-"Come to think, Becky, we are away down below them--and I don't know
-how far away north, or south, or east, or whichever it is. We couldn't
-hear them here."
-
-Becky grew apprehensive.
-
-"I wonder how long we've been down here, Tom? We better start back."
-
-"Yes, I reckon we better. P'raps we better."
-
-"Can you find the way, Tom? It's all a mixed-up crookedness to me."
-
-"I reckon I could find it--but then the bats. If they put our candles
-out it will be an awful fix. Let's try some other way, so as not to go
-through there."
-
-"Well. But I hope we won't get lost. It would be so awful!" and the
-girl shuddered at the thought of the dreadful possibilities.
-
-They started through a corridor, and traversed it in silence a long
-way, glancing at each new opening, to see if there was anything
-familiar about the look of it; but they were all strange. Every time
-Tom made an examination, Becky would watch his face for an encouraging
-sign, and he would say cheerily:
-
-"Oh, it's all right. This ain't the one, but we'll come to it right
-away!"
-
-But he felt less and less hopeful with each failure, and presently
-began to turn off into diverging avenues at sheer random, in desperate
-hope of finding the one that was wanted. He still said it was "all
-right," but there was such a leaden dread at his heart that the words
-had lost their ring and sounded just as if he had said, "All is lost!"
-Becky clung to his side in an anguish of fear, and tried hard to keep
-back the tears, but they would come. At last she said:
-
-"Oh, Tom, never mind the bats, let's go back that way! We seem to get
-worse and worse off all the time."
-
-"Listen!" said he.
-
-Profound silence; silence so deep that even their breathings were
-conspicuous in the hush. Tom shouted. The call went echoing down the
-empty aisles and died out in the distance in a faint sound that
-resembled a ripple of mocking laughter.
-
-"Oh, don't do it again, Tom, it is too horrid," said Becky.
-
-"It is horrid, but I better, Becky; they might hear us, you know," and
-he shouted again.
-
-The "might" was even a chillier horror than the ghostly laughter, it
-so confessed a perishing hope. The children stood still and listened;
-but there was no result. Tom turned upon the back track at once, and
-hurried his steps. It was but a little while before a certain
-indecision in his manner revealed another fearful fact to Becky--he
-could not find his way back!
-
-"Oh, Tom, you didn't make any marks!"
-
-"Becky, I was such a fool! Such a fool! I never thought we might want
-to come back! No--I can't find the way. It's all mixed up."
-
-"Tom, Tom, we're lost! we're lost! We never can get out of this awful
-place! Oh, why DID we ever leave the others!"
-
-She sank to the ground and burst into such a frenzy of crying that Tom
-was appalled with the idea that she might die, or lose her reason. He
-sat down by her and put his arms around her; she buried her face in his
-bosom, she clung to him, she poured out her terrors, her unavailing
-regrets, and the far echoes turned them all to jeering laughter. Tom
-begged her to pluck up hope again, and she said she could not. He fell
-to blaming and abusing himself for getting her into this miserable
-situation; this had a better effect. She said she would try to hope
-again, she would get up and follow wherever he might lead if only he
-would not talk like that any more. For he was no more to blame than
-she, she said.
-
-So they moved on again--aimlessly--simply at random--all they could do
-was to move, keep moving. For a little while, hope made a show of
-reviving--not with any reason to back it, but only because it is its
-nature to revive when the spring has not been taken out of it by age
-and familiarity with failure.
-
-By-and-by Tom took Becky's candle and blew it out. This economy meant
-so much! Words were not needed. Becky understood, and her hope died
-again. She knew that Tom had a whole candle and three or four pieces in
-his pockets--yet he must economize.
-
-By-and-by, fatigue began to assert its claims; the children tried to
-pay attention, for it was dreadful to think of sitting down when time
-was grown to be so precious, moving, in some direction, in any
-direction, was at least progress and might bear fruit; but to sit down
-was to invite death and shorten its pursuit.
-
-At last Becky's frail limbs refused to carry her farther. She sat
-down. Tom rested with her, and they talked of home, and the friends
-there, and the comfortable beds and, above all, the light! Becky cried,
-and Tom tried to think of some way of comforting her, but all his
-encouragements were grown threadbare with use, and sounded like
-sarcasms. Fatigue bore so heavily upon Becky that she drowsed off to
-sleep. Tom was grateful. He sat looking into her drawn face and saw it
-grow smooth and natural under the influence of pleasant dreams; and
-by-and-by a smile dawned and rested there. The peaceful face reflected
-somewhat of peace and healing into his own spirit, and his thoughts
-wandered away to bygone times and dreamy memories. While he was deep in
-his musings, Becky woke up with a breezy little laugh--but it was
-stricken dead upon her lips, and a groan followed it.
-
-"Oh, how COULD I sleep! I wish I never, never had waked! No! No, I
-don't, Tom! Don't look so! I won't say it again."
-
-"I'm glad you've slept, Becky; you'll feel rested, now, and we'll find
-the way out."
-
-"We can try, Tom; but I've seen such a beautiful country in my dream.
-I reckon we are going there."
-
-"Maybe not, maybe not. Cheer up, Becky, and let's go on trying."
-
-They rose up and wandered along, hand in hand and hopeless. They tried
-to estimate how long they had been in the cave, but all they knew was
-that it seemed days and weeks, and yet it was plain that this could not
-be, for their candles were not gone yet. A long time after this--they
-could not tell how long--Tom said they must go softly and listen for
-dripping water--they must find a spring. They found one presently, and
-Tom said it was time to rest again. Both were cruelly tired, yet Becky
-said she thought she could go a little farther. She was surprised to
-hear Tom dissent. She could not understand it. They sat down, and Tom
-fastened his candle to the wall in front of them with some clay.
-Thought was soon busy; nothing was said for some time. Then Becky broke
-the silence:
-
-"Tom, I am so hungry!"
-
-Tom took something out of his pocket.
-
-"Do you remember this?" said he.
-
-Becky almost smiled.
-
-"It's our wedding-cake, Tom."
-
-"Yes--I wish it was as big as a barrel, for it's all we've got."
-
-"I saved it from the picnic for us to dream on, Tom, the way grown-up
-people do with wedding-cake--but it'll be our--"
-
-She dropped the sentence where it was. Tom divided the cake and Becky
-ate with good appetite, while Tom nibbled at his moiety. There was
-abundance of cold water to finish the feast with. By-and-by Becky
-suggested that they move on again. Tom was silent a moment. Then he
-said:
-
-"Becky, can you bear it if I tell you something?"
-
-Becky's face paled, but she thought she could.
-
-"Well, then, Becky, we must stay here, where there's water to drink.
-That little piece is our last candle!"
-
-Becky gave loose to tears and wailings. Tom did what he could to
-comfort her, but with little effect. At length Becky said:
-
-"Tom!"
-
-"Well, Becky?"
-
-"They'll miss us and hunt for us!"
-
-"Yes, they will! Certainly they will!"
-
-"Maybe they're hunting for us now, Tom."
-
-"Why, I reckon maybe they are. I hope they are."
-
-"When would they miss us, Tom?"
-
-"When they get back to the boat, I reckon."
-
-"Tom, it might be dark then--would they notice we hadn't come?"
-
-"I don't know. But anyway, your mother would miss you as soon as they
-got home."
-
-A frightened look in Becky's face brought Tom to his senses and he saw
-that he had made a blunder. Becky was not to have gone home that night!
-The children became silent and thoughtful. In a moment a new burst of
-grief from Becky showed Tom that the thing in his mind had struck hers
-also--that the Sabbath morning might be half spent before Mrs. Thatcher
-discovered that Becky was not at Mrs. Harper's.
-
-The children fastened their eyes upon their bit of candle and watched
-it melt slowly and pitilessly away; saw the half inch of wick stand
-alone at last; saw the feeble flame rise and fall, climb the thin
-column of smoke, linger at its top a moment, and then--the horror of
-utter darkness reigned!
-
-How long afterward it was that Becky came to a slow consciousness that
-she was crying in Tom's arms, neither could tell. All that they knew
-was, that after what seemed a mighty stretch of time, both awoke out of
-a dead stupor of sleep and resumed their miseries once more. Tom said
-it might be Sunday, now--maybe Monday. He tried to get Becky to talk,
-but her sorrows were too oppressive, all her hopes were gone. Tom said
-that they must have been missed long ago, and no doubt the search was
-going on. He would shout and maybe some one would come. He tried it;
-but in the darkness the distant echoes sounded so hideously that he
-tried it no more.
-
-The hours wasted away, and hunger came to torment the captives again.
-A portion of Tom's half of the cake was left; they divided and ate it.
-But they seemed hungrier than before. The poor morsel of food only
-whetted desire.
-
-By-and-by Tom said:
-
-"SH! Did you hear that?"
-
-Both held their breath and listened. There was a sound like the
-faintest, far-off shout. Instantly Tom answered it, and leading Becky
-by the hand, started groping down the corridor in its direction.
-Presently he listened again; again the sound was heard, and apparently
-a little nearer.
-
-"It's them!" said Tom; "they're coming! Come along, Becky--we're all
-right now!"
-
-The joy of the prisoners was almost overwhelming. Their speed was
-slow, however, because pitfalls were somewhat common, and had to be
-guarded against. They shortly came to one and had to stop. It might be
-three feet deep, it might be a hundred--there was no passing it at any
-rate. Tom got down on his breast and reached as far down as he could.
-No bottom. They must stay there and wait until the searchers came. They
-listened; evidently the distant shoutings were growing more distant! a
-moment or two more and they had gone altogether. The heart-sinking
-misery of it! Tom whooped until he was hoarse, but it was of no use. He
-talked hopefully to Becky; but an age of anxious waiting passed and no
-sounds came again.
-
-The children groped their way back to the spring. The weary time
-dragged on; they slept again, and awoke famished and woe-stricken. Tom
-believed it must be Tuesday by this time.
-
-Now an idea struck him. There were some side passages near at hand. It
-would be better to explore some of these than bear the weight of the
-heavy time in idleness. He took a kite-line from his pocket, tied it to
-a projection, and he and Becky started, Tom in the lead, unwinding the
-line as he groped along. At the end of twenty steps the corridor ended
-in a "jumping-off place." Tom got down on his knees and felt below, and
-then as far around the corner as he could reach with his hands
-conveniently; he made an effort to stretch yet a little farther to the
-right, and at that moment, not twenty yards away, a human hand, holding
-a candle, appeared from behind a rock! Tom lifted up a glorious shout,
-and instantly that hand was followed by the body it belonged to--Injun
-Joe's! Tom was paralyzed; he could not move. He was vastly gratified
-the next moment, to see the "Spaniard" take to his heels and get
-himself out of sight. Tom wondered that Joe had not recognized his
-voice and come over and killed him for testifying in court. But the
-echoes must have disguised the voice. Without doubt, that was it, he
-reasoned. Tom's fright weakened every muscle in his body. He said to
-himself that if he had strength enough to get back to the spring he
-would stay there, and nothing should tempt him to run the risk of
-meeting Injun Joe again. He was careful to keep from Becky what it was
-he had seen. He told her he had only shouted "for luck."
-
-But hunger and wretchedness rise superior to fears in the long run.
-Another tedious wait at the spring and another long sleep brought
-changes. The children awoke tortured with a raging hunger. Tom believed
-that it must be Wednesday or Thursday or even Friday or Saturday, now,
-and that the search had been given over. He proposed to explore another
-passage. He felt willing to risk Injun Joe and all other terrors. But
-Becky was very weak. She had sunk into a dreary apathy and would not be
-roused. She said she would wait, now, where she was, and die--it would
-not be long. She told Tom to go with the kite-line and explore if he
-chose; but she implored him to come back every little while and speak
-to her; and she made him promise that when the awful time came, he
-would stay by her and hold her hand until all was over.
-
-Tom kissed her, with a choking sensation in his throat, and made a
-show of being confident of finding the searchers or an escape from the
-cave; then he took the kite-line in his hand and went groping down one
-of the passages on his hands and knees, distressed with hunger and sick
-with bodings of coming doom.
-
-
-
-CHAPTER XXXII
-
-TUESDAY afternoon came, and waned to the twilight. The village of St.
-Petersburg still mourned. The lost children had not been found. Public
-prayers had been offered up for them, and many and many a private
-prayer that had the petitioner's whole heart in it; but still no good
-news came from the cave. The majority of the searchers had given up the
-quest and gone back to their daily avocations, saying that it was plain
-the children could never be found. Mrs. Thatcher was very ill, and a
-great part of the time delirious. People said it was heartbreaking to
-hear her call her child, and raise her head and listen a whole minute
-at a time, then lay it wearily down again with a moan. Aunt Polly had
-drooped into a settled melancholy, and her gray hair had grown almost
-white. The village went to its rest on Tuesday night, sad and forlorn.
-
-Away in the middle of the night a wild peal burst from the village
-bells, and in a moment the streets were swarming with frantic half-clad
-people, who shouted, "Turn out! turn out! they're found! they're
-found!" Tin pans and horns were added to the din, the population massed
-itself and moved toward the river, met the children coming in an open
-carriage drawn by shouting citizens, thronged around it, joined its
-homeward march, and swept magnificently up the main street roaring
-huzzah after huzzah!
-
-The village was illuminated; nobody went to bed again; it was the
-greatest night the little town had ever seen. During the first half-hour
-a procession of villagers filed through Judge Thatcher's house, seized
-the saved ones and kissed them, squeezed Mrs. Thatcher's hand, tried to
-speak but couldn't--and drifted out raining tears all over the place.
-
-Aunt Polly's happiness was complete, and Mrs. Thatcher's nearly so. It
-would be complete, however, as soon as the messenger dispatched with
-the great news to the cave should get the word to her husband. Tom lay
-upon a sofa with an eager auditory about him and told the history of
-the wonderful adventure, putting in many striking additions to adorn it
-withal; and closed with a description of how he left Becky and went on
-an exploring expedition; how he followed two avenues as far as his
-kite-line would reach; how he followed a third to the fullest stretch of
-the kite-line, and was about to turn back when he glimpsed a far-off
-speck that looked like daylight; dropped the line and groped toward it,
-pushed his head and shoulders through a small hole, and saw the broad
-Mississippi rolling by! And if it had only happened to be night he would
-not have seen that speck of daylight and would not have explored that
-passage any more! He told how he went back for Becky and broke the good
-news and she told him not to fret her with such stuff, for she was
-tired, and knew she was going to die, and wanted to. He described how he
-labored with her and convinced her; and how she almost died for joy when
-she had groped to where she actually saw the blue speck of daylight; how
-he pushed his way out at the hole and then helped her out; how they sat
-there and cried for gladness; how some men came along in a skiff and Tom
-hailed them and told them their situation and their famished condition;
-how the men didn't believe the wild tale at first, "because," said they,
-"you are five miles down the river below the valley the cave is in"
---then took them aboard, rowed to a house, gave them supper, made them
-rest till two or three hours after dark and then brought them home.
-
-Before day-dawn, Judge Thatcher and the handful of searchers with him
-were tracked out, in the cave, by the twine clews they had strung
-behind them, and informed of the great news.
-
-Three days and nights of toil and hunger in the cave were not to be
-shaken off at once, as Tom and Becky soon discovered. They were
-bedridden all of Wednesday and Thursday, and seemed to grow more and
-more tired and worn, all the time. Tom got about, a little, on
-Thursday, was down-town Friday, and nearly as whole as ever Saturday;
-but Becky did not leave her room until Sunday, and then she looked as
-if she had passed through a wasting illness.
-
-Tom learned of Huck's sickness and went to see him on Friday, but
-could not be admitted to the bedroom; neither could he on Saturday or
-Sunday. He was admitted daily after that, but was warned to keep still
-about his adventure and introduce no exciting topic. The Widow Douglas
-stayed by to see that he obeyed. At home Tom learned of the Cardiff
-Hill event; also that the "ragged man's" body had eventually been found
-in the river near the ferry-landing; he had been drowned while trying
-to escape, perhaps.
-
-About a fortnight after Tom's rescue from the cave, he started off to
-visit Huck, who had grown plenty strong enough, now, to hear exciting
-talk, and Tom had some that would interest him, he thought. Judge
-Thatcher's house was on Tom's way, and he stopped to see Becky. The
-Judge and some friends set Tom to talking, and some one asked him
-ironically if he wouldn't like to go to the cave again. Tom said he
-thought he wouldn't mind it. The Judge said:
-
-"Well, there are others just like you, Tom, I've not the least doubt.
-But we have taken care of that. Nobody will get lost in that cave any
-more."
-
-"Why?"
-
-"Because I had its big door sheathed with boiler iron two weeks ago,
-and triple-locked--and I've got the keys."
-
-Tom turned as white as a sheet.
-
-"What's the matter, boy! Here, run, somebody! Fetch a glass of water!"
-
-The water was brought and thrown into Tom's face.
-
-"Ah, now you're all right. What was the matter with you, Tom?"
-
-"Oh, Judge, Injun Joe's in the cave!"
-
-
-
-CHAPTER XXXIII
-
-WITHIN a few minutes the news had spread, and a dozen skiff-loads of
-men were on their way to McDougal's cave, and the ferryboat, well
-filled with passengers, soon followed. Tom Sawyer was in the skiff that
-bore Judge Thatcher.
-
-When the cave door was unlocked, a sorrowful sight presented itself in
-the dim twilight of the place. Injun Joe lay stretched upon the ground,
-dead, with his face close to the crack of the door, as if his longing
-eyes had been fixed, to the latest moment, upon the light and the cheer
-of the free world outside. Tom was touched, for he knew by his own
-experience how this wretch had suffered. His pity was moved, but
-nevertheless he felt an abounding sense of relief and security, now,
-which revealed to him in a degree which he had not fully appreciated
-before how vast a weight of dread had been lying upon him since the day
-he lifted his voice against this bloody-minded outcast.
-
-Injun Joe's bowie-knife lay close by, its blade broken in two. The
-great foundation-beam of the door had been chipped and hacked through,
-with tedious labor; useless labor, too, it was, for the native rock
-formed a sill outside it, and upon that stubborn material the knife had
-wrought no effect; the only damage done was to the knife itself. But if
-there had been no stony obstruction there the labor would have been
-useless still, for if the beam had been wholly cut away Injun Joe could
-not have squeezed his body under the door, and he knew it. So he had
-only hacked that place in order to be doing something--in order to pass
-the weary time--in order to employ his tortured faculties. Ordinarily
-one could find half a dozen bits of candle stuck around in the crevices
-of this vestibule, left there by tourists; but there were none now. The
-prisoner had searched them out and eaten them. He had also contrived to
-catch a few bats, and these, also, he had eaten, leaving only their
-claws. The poor unfortunate had starved to death. In one place, near at
-hand, a stalagmite had been slowly growing up from the ground for ages,
-builded by the water-drip from a stalactite overhead. The captive had
-broken off the stalagmite, and upon the stump had placed a stone,
-wherein he had scooped a shallow hollow to catch the precious drop
-that fell once in every three minutes with the dreary regularity of a
-clock-tick--a dessertspoonful once in four and twenty hours. That drop
-was falling when the Pyramids were new; when Troy fell; when the
-foundations of Rome were laid; when Christ was crucified; when the
-Conqueror created the British empire; when Columbus sailed; when the
-massacre at Lexington was "news." It is falling now; it will still be
-falling when all these things shall have sunk down the afternoon of
-history, and the twilight of tradition, and been swallowed up in the
-thick night of oblivion. Has everything a purpose and a mission? Did
-this drop fall patiently during five thousand years to be ready for
-this flitting human insect's need? and has it another important object
-to accomplish ten thousand years to come? No matter. It is many and
-many a year since the hapless half-breed scooped out the stone to catch
-the priceless drops, but to this day the tourist stares longest at that
-pathetic stone and that slow-dropping water when he comes to see the
-wonders of McDougal's cave. Injun Joe's cup stands first in the list of
-the cavern's marvels; even "Aladdin's Palace" cannot rival it.
-
-Injun Joe was buried near the mouth of the cave; and people flocked
-there in boats and wagons from the towns and from all the farms and
-hamlets for seven miles around; they brought their children, and all
-sorts of provisions, and confessed that they had had almost as
-satisfactory a time at the funeral as they could have had at the
-hanging.
-
-This funeral stopped the further growth of one thing--the petition to
-the governor for Injun Joe's pardon. The petition had been largely
-signed; many tearful and eloquent meetings had been held, and a
-committee of sappy women been appointed to go in deep mourning and wail
-around the governor, and implore him to be a merciful ass and trample
-his duty under foot. Injun Joe was believed to have killed five
-citizens of the village, but what of that? If he had been Satan himself
-there would have been plenty of weaklings ready to scribble their names
-to a pardon-petition, and drip a tear on it from their permanently
-impaired and leaky water-works.
-
-The morning after the funeral Tom took Huck to a private place to have
-an important talk. Huck had learned all about Tom's adventure from the
-Welshman and the Widow Douglas, by this time, but Tom said he reckoned
-there was one thing they had not told him; that thing was what he
-wanted to talk about now. Huck's face saddened. He said:
-
-"I know what it is. You got into No. 2 and never found anything but
-whiskey. Nobody told me it was you; but I just knowed it must 'a' ben
-you, soon as I heard 'bout that whiskey business; and I knowed you
-hadn't got the money becuz you'd 'a' got at me some way or other and
-told me even if you was mum to everybody else. Tom, something's always
-told me we'd never get holt of that swag."
-
-"Why, Huck, I never told on that tavern-keeper. YOU know his tavern
-was all right the Saturday I went to the picnic. Don't you remember you
-was to watch there that night?"
-
-"Oh yes! Why, it seems 'bout a year ago. It was that very night that I
-follered Injun Joe to the widder's."
-
-"YOU followed him?"
-
-"Yes--but you keep mum. I reckon Injun Joe's left friends behind him,
-and I don't want 'em souring on me and doing me mean tricks. If it
-hadn't ben for me he'd be down in Texas now, all right."
-
-Then Huck told his entire adventure in confidence to Tom, who had only
-heard of the Welshman's part of it before.
-
-"Well," said Huck, presently, coming back to the main question,
-"whoever nipped the whiskey in No. 2, nipped the money, too, I reckon
---anyways it's a goner for us, Tom."
-
-"Huck, that money wasn't ever in No. 2!"
-
-"What!" Huck searched his comrade's face keenly. "Tom, have you got on
-the track of that money again?"
-
-"Huck, it's in the cave!"
-
-Huck's eyes blazed.
-
-"Say it again, Tom."
-
-"The money's in the cave!"
-
-"Tom--honest injun, now--is it fun, or earnest?"
-
-"Earnest, Huck--just as earnest as ever I was in my life. Will you go
-in there with me and help get it out?"
-
-"I bet I will! I will if it's where we can blaze our way to it and not
-get lost."
-
-"Huck, we can do that without the least little bit of trouble in the
-world."
-
-"Good as wheat! What makes you think the money's--"
-
-"Huck, you just wait till we get in there. If we don't find it I'll
-agree to give you my drum and every thing I've got in the world. I
-will, by jings."
-
-"All right--it's a whiz. When do you say?"
-
-"Right now, if you say it. Are you strong enough?"
-
-"Is it far in the cave? I ben on my pins a little, three or four days,
-now, but I can't walk more'n a mile, Tom--least I don't think I could."
-
-"It's about five mile into there the way anybody but me would go,
-Huck, but there's a mighty short cut that they don't anybody but me
-know about. Huck, I'll take you right to it in a skiff. I'll float the
-skiff down there, and I'll pull it back again all by myself. You
-needn't ever turn your hand over."
-
-"Less start right off, Tom."
-
-"All right. We want some bread and meat, and our pipes, and a little
-bag or two, and two or three kite-strings, and some of these
-new-fangled things they call lucifer matches. I tell you, many's
-the time I wished I had some when I was in there before."
-
-A trifle after noon the boys borrowed a small skiff from a citizen who
-was absent, and got under way at once. When they were several miles
-below "Cave Hollow," Tom said:
-
-"Now you see this bluff here looks all alike all the way down from the
-cave hollow--no houses, no wood-yards, bushes all alike. But do you see
-that white place up yonder where there's been a landslide? Well, that's
-one of my marks. We'll get ashore, now."
-
-They landed.
-
-"Now, Huck, where we're a-standing you could touch that hole I got out
-of with a fishing-pole. See if you can find it."
-
-Huck searched all the place about, and found nothing. Tom proudly
-marched into a thick clump of sumach bushes and said:
-
-"Here you are! Look at it, Huck; it's the snuggest hole in this
-country. You just keep mum about it. All along I've been wanting to be
-a robber, but I knew I'd got to have a thing like this, and where to
-run across it was the bother. We've got it now, and we'll keep it
-quiet, only we'll let Joe Harper and Ben Rogers in--because of course
-there's got to be a Gang, or else there wouldn't be any style about it.
-Tom Sawyer's Gang--it sounds splendid, don't it, Huck?"
-
-"Well, it just does, Tom. And who'll we rob?"
-
-"Oh, most anybody. Waylay people--that's mostly the way."
-
-"And kill them?"
-
-"No, not always. Hive them in the cave till they raise a ransom."
-
-"What's a ransom?"
-
-"Money. You make them raise all they can, off'n their friends; and
-after you've kept them a year, if it ain't raised then you kill them.
-That's the general way. Only you don't kill the women. You shut up the
-women, but you don't kill them. They're always beautiful and rich, and
-awfully scared. You take their watches and things, but you always take
-your hat off and talk polite. They ain't anybody as polite as robbers
---you'll see that in any book. Well, the women get to loving you, and
-after they've been in the cave a week or two weeks they stop crying and
-after that you couldn't get them to leave. If you drove them out they'd
-turn right around and come back. It's so in all the books."
-
-"Why, it's real bully, Tom. I believe it's better'n to be a pirate."
-
-"Yes, it's better in some ways, because it's close to home and
-circuses and all that."
-
-By this time everything was ready and the boys entered the hole, Tom
-in the lead. They toiled their way to the farther end of the tunnel,
-then made their spliced kite-strings fast and moved on. A few steps
-brought them to the spring, and Tom felt a shudder quiver all through
-him. He showed Huck the fragment of candle-wick perched on a lump of
-clay against the wall, and described how he and Becky had watched the
-flame struggle and expire.
-
-The boys began to quiet down to whispers, now, for the stillness and
-gloom of the place oppressed their spirits. They went on, and presently
-entered and followed Tom's other corridor until they reached the
-"jumping-off place." The candles revealed the fact that it was not
-really a precipice, but only a steep clay hill twenty or thirty feet
-high. Tom whispered:
-
-"Now I'll show you something, Huck."
-
-He held his candle aloft and said:
-
-"Look as far around the corner as you can. Do you see that? There--on
-the big rock over yonder--done with candle-smoke."
-
-"Tom, it's a CROSS!"
-
-"NOW where's your Number Two? 'UNDER THE CROSS,' hey? Right yonder's
-where I saw Injun Joe poke up his candle, Huck!"
-
-Huck stared at the mystic sign awhile, and then said with a shaky voice:
-
-"Tom, less git out of here!"
-
-"What! and leave the treasure?"
-
-"Yes--leave it. Injun Joe's ghost is round about there, certain."
-
-"No it ain't, Huck, no it ain't. It would ha'nt the place where he
-died--away out at the mouth of the cave--five mile from here."
-
-"No, Tom, it wouldn't. It would hang round the money. I know the ways
-of ghosts, and so do you."
-
-Tom began to fear that Huck was right. Misgivings gathered in his
-mind. But presently an idea occurred to him--
-
-"Lookyhere, Huck, what fools we're making of ourselves! Injun Joe's
-ghost ain't a going to come around where there's a cross!"
-
-The point was well taken. It had its effect.
-
-"Tom, I didn't think of that. But that's so. It's luck for us, that
-cross is. I reckon we'll climb down there and have a hunt for that box."
-
-Tom went first, cutting rude steps in the clay hill as he descended.
-Huck followed. Four avenues opened out of the small cavern which the
-great rock stood in. The boys examined three of them with no result.
-They found a small recess in the one nearest the base of the rock, with
-a pallet of blankets spread down in it; also an old suspender, some
-bacon rind, and the well-gnawed bones of two or three fowls. But there
-was no money-box. The lads searched and researched this place, but in
-vain. Tom said:
-
-"He said UNDER the cross. Well, this comes nearest to being under the
-cross. It can't be under the rock itself, because that sets solid on
-the ground."
-
-They searched everywhere once more, and then sat down discouraged.
-Huck could suggest nothing. By-and-by Tom said:
-
-"Lookyhere, Huck, there's footprints and some candle-grease on the
-clay about one side of this rock, but not on the other sides. Now,
-what's that for? I bet you the money IS under the rock. I'm going to
-dig in the clay."
-
-"That ain't no bad notion, Tom!" said Huck with animation.
-
-Tom's "real Barlow" was out at once, and he had not dug four inches
-before he struck wood.
-
-"Hey, Huck!--you hear that?"
-
-Huck began to dig and scratch now. Some boards were soon uncovered and
-removed. They had concealed a natural chasm which led under the rock.
-Tom got into this and held his candle as far under the rock as he
-could, but said he could not see to the end of the rift. He proposed to
-explore. He stooped and passed under; the narrow way descended
-gradually. He followed its winding course, first to the right, then to
-the left, Huck at his heels. Tom turned a short curve, by-and-by, and
-exclaimed:
-
-"My goodness, Huck, lookyhere!"
-
-It was the treasure-box, sure enough, occupying a snug little cavern,
-along with an empty powder-keg, a couple of guns in leather cases, two
-or three pairs of old moccasins, a leather belt, and some other rubbish
-well soaked with the water-drip.
-
-"Got it at last!" said Huck, ploughing among the tarnished coins with
-his hand. "My, but we're rich, Tom!"
-
-"Huck, I always reckoned we'd get it. It's just too good to believe,
-but we HAVE got it, sure! Say--let's not fool around here. Let's snake
-it out. Lemme see if I can lift the box."
-
-It weighed about fifty pounds. Tom could lift it, after an awkward
-fashion, but could not carry it conveniently.
-
-"I thought so," he said; "THEY carried it like it was heavy, that day
-at the ha'nted house. I noticed that. I reckon I was right to think of
-fetching the little bags along."
-
-The money was soon in the bags and the boys took it up to the cross
-rock.
-
-"Now less fetch the guns and things," said Huck.
-
-"No, Huck--leave them there. They're just the tricks to have when we
-go to robbing. We'll keep them there all the time, and we'll hold our
-orgies there, too. It's an awful snug place for orgies."
-
-"What orgies?"
-
-"I dono. But robbers always have orgies, and of course we've got to
-have them, too. Come along, Huck, we've been in here a long time. It's
-getting late, I reckon. I'm hungry, too. We'll eat and smoke when we
-get to the skiff."
-
-They presently emerged into the clump of sumach bushes, looked warily
-out, found the coast clear, and were soon lunching and smoking in the
-skiff. As the sun dipped toward the horizon they pushed out and got
-under way. Tom skimmed up the shore through the long twilight, chatting
-cheerily with Huck, and landed shortly after dark.
-
-"Now, Huck," said Tom, "we'll hide the money in the loft of the
-widow's woodshed, and I'll come up in the morning and we'll count it
-and divide, and then we'll hunt up a place out in the woods for it
-where it will be safe. Just you lay quiet here and watch the stuff till
-I run and hook Benny Taylor's little wagon; I won't be gone a minute."
-
-He disappeared, and presently returned with the wagon, put the two
-small sacks into it, threw some old rags on top of them, and started
-off, dragging his cargo behind him. When the boys reached the
-Welshman's house, they stopped to rest. Just as they were about to move
-on, the Welshman stepped out and said:
-
-"Hallo, who's that?"
-
-"Huck and Tom Sawyer."
-
-"Good! Come along with me, boys, you are keeping everybody waiting.
-Here--hurry up, trot ahead--I'll haul the wagon for you. Why, it's not
-as light as it might be. Got bricks in it?--or old metal?"
-
-"Old metal," said Tom.
-
-"I judged so; the boys in this town will take more trouble and fool
-away more time hunting up six bits' worth of old iron to sell to the
-foundry than they would to make twice the money at regular work. But
-that's human nature--hurry along, hurry along!"
-
-The boys wanted to know what the hurry was about.
-
-"Never mind; you'll see, when we get to the Widow Douglas'."
-
-Huck said with some apprehension--for he was long used to being
-falsely accused:
-
-"Mr. Jones, we haven't been doing nothing."
-
-The Welshman laughed.
-
-"Well, I don't know, Huck, my boy. I don't know about that. Ain't you
-and the widow good friends?"
-
-"Yes. Well, she's ben good friends to me, anyway."
-
-"All right, then. What do you want to be afraid for?"
-
-This question was not entirely answered in Huck's slow mind before he
-found himself pushed, along with Tom, into Mrs. Douglas' drawing-room.
-Mr. Jones left the wagon near the door and followed.
-
-The place was grandly lighted, and everybody that was of any
-consequence in the village was there. The Thatchers were there, the
-Harpers, the Rogerses, Aunt Polly, Sid, Mary, the minister, the editor,
-and a great many more, and all dressed in their best. The widow
-received the boys as heartily as any one could well receive two such
-looking beings. They were covered with clay and candle-grease. Aunt
-Polly blushed crimson with humiliation, and frowned and shook her head
-at Tom. Nobody suffered half as much as the two boys did, however. Mr.
-Jones said:
-
-"Tom wasn't at home, yet, so I gave him up; but I stumbled on him and
-Huck right at my door, and so I just brought them along in a hurry."
-
-"And you did just right," said the widow. "Come with me, boys."
-
-She took them to a bedchamber and said:
-
-"Now wash and dress yourselves. Here are two new suits of clothes
---shirts, socks, everything complete. They're Huck's--no, no thanks,
-Huck--Mr. Jones bought one and I the other. But they'll fit both of you.
-Get into them. We'll wait--come down when you are slicked up enough."
-
-Then she left.
-
-
-
-CHAPTER XXXIV
-
-HUCK said: "Tom, we can slope, if we can find a rope. The window ain't
-high from the ground."
-
-"Shucks! what do you want to slope for?"
-
-"Well, I ain't used to that kind of a crowd. I can't stand it. I ain't
-going down there, Tom."
-
-"Oh, bother! It ain't anything. I don't mind it a bit. I'll take care
-of you."
-
-Sid appeared.
-
-"Tom," said he, "auntie has been waiting for you all the afternoon.
-Mary got your Sunday clothes ready, and everybody's been fretting about
-you. Say--ain't this grease and clay, on your clothes?"
-
-"Now, Mr. Siddy, you jist 'tend to your own business. What's all this
-blow-out about, anyway?"
-
-"It's one of the widow's parties that she's always having. This time
-it's for the Welshman and his sons, on account of that scrape they
-helped her out of the other night. And say--I can tell you something,
-if you want to know."
-
-"Well, what?"
-
-"Why, old Mr. Jones is going to try to spring something on the people
-here to-night, but I overheard him tell auntie to-day about it, as a
-secret, but I reckon it's not much of a secret now. Everybody knows
---the widow, too, for all she tries to let on she don't. Mr. Jones was
-bound Huck should be here--couldn't get along with his grand secret
-without Huck, you know!"
-
-"Secret about what, Sid?"
-
-"About Huck tracking the robbers to the widow's. I reckon Mr. Jones
-was going to make a grand time over his surprise, but I bet you it will
-drop pretty flat."
-
-Sid chuckled in a very contented and satisfied way.
-
-"Sid, was it you that told?"
-
-"Oh, never mind who it was. SOMEBODY told--that's enough."
-
-"Sid, there's only one person in this town mean enough to do that, and
-that's you. If you had been in Huck's place you'd 'a' sneaked down the
-hill and never told anybody on the robbers. You can't do any but mean
-things, and you can't bear to see anybody praised for doing good ones.
-There--no thanks, as the widow says"--and Tom cuffed Sid's ears and
-helped him to the door with several kicks. "Now go and tell auntie if
-you dare--and to-morrow you'll catch it!"
-
-Some minutes later the widow's guests were at the supper-table, and a
-dozen children were propped up at little side-tables in the same room,
-after the fashion of that country and that day. At the proper time Mr.
-Jones made his little speech, in which he thanked the widow for the
-honor she was doing himself and his sons, but said that there was
-another person whose modesty--
-
-And so forth and so on. He sprung his secret about Huck's share in the
-adventure in the finest dramatic manner he was master of, but the
-surprise it occasioned was largely counterfeit and not as clamorous and
-effusive as it might have been under happier circumstances. However,
-the widow made a pretty fair show of astonishment, and heaped so many
-compliments and so much gratitude upon Huck that he almost forgot the
-nearly intolerable discomfort of his new clothes in the entirely
-intolerable discomfort of being set up as a target for everybody's gaze
-and everybody's laudations.
-
-The widow said she meant to give Huck a home under her roof and have
-him educated; and that when she could spare the money she would start
-him in business in a modest way. Tom's chance was come. He said:
-
-"Huck don't need it. Huck's rich."
-
-Nothing but a heavy strain upon the good manners of the company kept
-back the due and proper complimentary laugh at this pleasant joke. But
-the silence was a little awkward. Tom broke it:
-
-"Huck's got money. Maybe you don't believe it, but he's got lots of
-it. Oh, you needn't smile--I reckon I can show you. You just wait a
-minute."
-
-Tom ran out of doors. The company looked at each other with a
-perplexed interest--and inquiringly at Huck, who was tongue-tied.
-
-"Sid, what ails Tom?" said Aunt Polly. "He--well, there ain't ever any
-making of that boy out. I never--"
-
-Tom entered, struggling with the weight of his sacks, and Aunt Polly
-did not finish her sentence. Tom poured the mass of yellow coin upon
-the table and said:
-
-"There--what did I tell you? Half of it's Huck's and half of it's mine!"
-
-The spectacle took the general breath away. All gazed, nobody spoke
-for a moment. Then there was a unanimous call for an explanation. Tom
-said he could furnish it, and he did. The tale was long, but brimful of
-interest. There was scarcely an interruption from any one to break the
-charm of its flow. When he had finished, Mr. Jones said:
-
-"I thought I had fixed up a little surprise for this occasion, but it
-don't amount to anything now. This one makes it sing mighty small, I'm
-willing to allow."
-
-The money was counted. The sum amounted to a little over twelve
-thousand dollars. It was more than any one present had ever seen at one
-time before, though several persons were there who were worth
-considerably more than that in property.
-
-
-
-CHAPTER XXXV
-
-THE reader may rest satisfied that Tom's and Huck's windfall made a
-mighty stir in the poor little village of St. Petersburg. So vast a
-sum, all in actual cash, seemed next to incredible. It was talked
-about, gloated over, glorified, until the reason of many of the
-citizens tottered under the strain of the unhealthy excitement. Every
-"haunted" house in St. Petersburg and the neighboring villages was
-dissected, plank by plank, and its foundations dug up and ransacked for
-hidden treasure--and not by boys, but men--pretty grave, unromantic
-men, too, some of them. Wherever Tom and Huck appeared they were
-courted, admired, stared at. The boys were not able to remember that
-their remarks had possessed weight before; but now their sayings were
-treasured and repeated; everything they did seemed somehow to be
-regarded as remarkable; they had evidently lost the power of doing and
-saying commonplace things; moreover, their past history was raked up
-and discovered to bear marks of conspicuous originality. The village
-paper published biographical sketches of the boys.
-
-The Widow Douglas put Huck's money out at six per cent., and Judge
-Thatcher did the same with Tom's at Aunt Polly's request. Each lad had
-an income, now, that was simply prodigious--a dollar for every week-day
-in the year and half of the Sundays. It was just what the minister got
---no, it was what he was promised--he generally couldn't collect it. A
-dollar and a quarter a week would board, lodge, and school a boy in
-those old simple days--and clothe him and wash him, too, for that
-matter.
-
-Judge Thatcher had conceived a great opinion of Tom. He said that no
-commonplace boy would ever have got his daughter out of the cave. When
-Becky told her father, in strict confidence, how Tom had taken her
-whipping at school, the Judge was visibly moved; and when she pleaded
-grace for the mighty lie which Tom had told in order to shift that
-whipping from her shoulders to his own, the Judge said with a fine
-outburst that it was a noble, a generous, a magnanimous lie--a lie that
-was worthy to hold up its head and march down through history breast to
-breast with George Washington's lauded Truth about the hatchet! Becky
-thought her father had never looked so tall and so superb as when he
-walked the floor and stamped his foot and said that. She went straight
-off and told Tom about it.
-
-Judge Thatcher hoped to see Tom a great lawyer or a great soldier some
-day. He said he meant to look to it that Tom should be admitted to the
-National Military Academy and afterward trained in the best law school
-in the country, in order that he might be ready for either career or
-both.
-
-Huck Finn's wealth and the fact that he was now under the Widow
-Douglas' protection introduced him into society--no, dragged him into
-it, hurled him into it--and his sufferings were almost more than he
-could bear. The widow's servants kept him clean and neat, combed and
-brushed, and they bedded him nightly in unsympathetic sheets that had
-not one little spot or stain which he could press to his heart and know
-for a friend. He had to eat with a knife and fork; he had to use
-napkin, cup, and plate; he had to learn his book, he had to go to
-church; he had to talk so properly that speech was become insipid in
-his mouth; whithersoever he turned, the bars and shackles of
-civilization shut him in and bound him hand and foot.
-
-He bravely bore his miseries three weeks, and then one day turned up
-missing. For forty-eight hours the widow hunted for him everywhere in
-great distress. The public were profoundly concerned; they searched
-high and low, they dragged the river for his body. Early the third
-morning Tom Sawyer wisely went poking among some old empty hogsheads
-down behind the abandoned slaughter-house, and in one of them he found
-the refugee. Huck had slept there; he had just breakfasted upon some
-stolen odds and ends of food, and was lying off, now, in comfort, with
-his pipe. He was unkempt, uncombed, and clad in the same old ruin of
-rags that had made him picturesque in the days when he was free and
-happy. Tom routed him out, told him the trouble he had been causing,
-and urged him to go home. Huck's face lost its tranquil content, and
-took a melancholy cast. He said:
-
-"Don't talk about it, Tom. I've tried it, and it don't work; it don't
-work, Tom. It ain't for me; I ain't used to it. The widder's good to
-me, and friendly; but I can't stand them ways. She makes me get up just
-at the same time every morning; she makes me wash, they comb me all to
-thunder; she won't let me sleep in the woodshed; I got to wear them
-blamed clothes that just smothers me, Tom; they don't seem to any air
-git through 'em, somehow; and they're so rotten nice that I can't set
-down, nor lay down, nor roll around anywher's; I hain't slid on a
-cellar-door for--well, it 'pears to be years; I got to go to church and
-sweat and sweat--I hate them ornery sermons! I can't ketch a fly in
-there, I can't chaw. I got to wear shoes all Sunday. The widder eats by
-a bell; she goes to bed by a bell; she gits up by a bell--everything's
-so awful reg'lar a body can't stand it."
-
-"Well, everybody does that way, Huck."
-
-"Tom, it don't make no difference. I ain't everybody, and I can't
-STAND it. It's awful to be tied up so. And grub comes too easy--I don't
-take no interest in vittles, that way. I got to ask to go a-fishing; I
-got to ask to go in a-swimming--dern'd if I hain't got to ask to do
-everything. Well, I'd got to talk so nice it wasn't no comfort--I'd got
-to go up in the attic and rip out awhile, every day, to git a taste in
-my mouth, or I'd a died, Tom. The widder wouldn't let me smoke; she
-wouldn't let me yell, she wouldn't let me gape, nor stretch, nor
-scratch, before folks--" [Then with a spasm of special irritation and
-injury]--"And dad fetch it, she prayed all the time! I never see such a
-woman! I HAD to shove, Tom--I just had to. And besides, that school's
-going to open, and I'd a had to go to it--well, I wouldn't stand THAT,
-Tom. Looky here, Tom, being rich ain't what it's cracked up to be. It's
-just worry and worry, and sweat and sweat, and a-wishing you was dead
-all the time. Now these clothes suits me, and this bar'l suits me, and
-I ain't ever going to shake 'em any more. Tom, I wouldn't ever got into
-all this trouble if it hadn't 'a' ben for that money; now you just take
-my sheer of it along with your'n, and gimme a ten-center sometimes--not
-many times, becuz I don't give a dern for a thing 'thout it's tollable
-hard to git--and you go and beg off for me with the widder."
-
-"Oh, Huck, you know I can't do that. 'Tain't fair; and besides if
-you'll try this thing just a while longer you'll come to like it."
-
-"Like it! Yes--the way I'd like a hot stove if I was to set on it long
-enough. No, Tom, I won't be rich, and I won't live in them cussed
-smothery houses. I like the woods, and the river, and hogsheads, and
-I'll stick to 'em, too. Blame it all! just as we'd got guns, and a
-cave, and all just fixed to rob, here this dern foolishness has got to
-come up and spile it all!"
-
-Tom saw his opportunity--
-
-"Lookyhere, Huck, being rich ain't going to keep me back from turning
-robber."
-
-"No! Oh, good-licks; are you in real dead-wood earnest, Tom?"
-
-"Just as dead earnest as I'm sitting here. But Huck, we can't let you
-into the gang if you ain't respectable, you know."
-
-Huck's joy was quenched.
-
-"Can't let me in, Tom? Didn't you let me go for a pirate?"
-
-"Yes, but that's different. A robber is more high-toned than what a
-pirate is--as a general thing. In most countries they're awful high up
-in the nobility--dukes and such."
-
-"Now, Tom, hain't you always ben friendly to me? You wouldn't shet me
-out, would you, Tom? You wouldn't do that, now, WOULD you, Tom?"
-
-"Huck, I wouldn't want to, and I DON'T want to--but what would people
-say? Why, they'd say, 'Mph! Tom Sawyer's Gang! pretty low characters in
-it!' They'd mean you, Huck. You wouldn't like that, and I wouldn't."
-
-Huck was silent for some time, engaged in a mental struggle. Finally
-he said:
-
-"Well, I'll go back to the widder for a month and tackle it and see if
-I can come to stand it, if you'll let me b'long to the gang, Tom."
-
-"All right, Huck, it's a whiz! Come along, old chap, and I'll ask the
-widow to let up on you a little, Huck."
-
-"Will you, Tom--now will you? That's good. If she'll let up on some of
-the roughest things, I'll smoke private and cuss private, and crowd
-through or bust. When you going to start the gang and turn robbers?"
-
-"Oh, right off. We'll get the boys together and have the initiation
-to-night, maybe."
-
-"Have the which?"
-
-"Have the initiation."
-
-"What's that?"
-
-"It's to swear to stand by one another, and never tell the gang's
-secrets, even if you're chopped all to flinders, and kill anybody and
-all his family that hurts one of the gang."
-
-"That's gay--that's mighty gay, Tom, I tell you."
-
-"Well, I bet it is. And all that swearing's got to be done at
-midnight, in the lonesomest, awfulest place you can find--a ha'nted
-house is the best, but they're all ripped up now."
-
-"Well, midnight's good, anyway, Tom."
-
-"Yes, so it is. And you've got to swear on a coffin, and sign it with
-blood."
-
-"Now, that's something LIKE! Why, it's a million times bullier than
-pirating. I'll stick to the widder till I rot, Tom; and if I git to be
-a reg'lar ripper of a robber, and everybody talking 'bout it, I reckon
-she'll be proud she snaked me in out of the wet."
-
-
-
-CONCLUSION
-
-SO endeth this chronicle. It being strictly a history of a BOY, it
-must stop here; the story could not go much further without becoming
-the history of a MAN. When one writes a novel about grown people, he
-knows exactly where to stop--that is, with a marriage; but when he
-writes of juveniles, he must stop where he best can.
-
-Most of the characters that perform in this book still live, and are
-prosperous and happy. Some day it may seem worth while to take up the
-story of the younger ones again and see what sort of men and women they
-turned out to be; therefore it will be wisest not to reveal any of that
-part of their lives at present.
diff --git a/src/compress/zlib/writer.go b/src/compress/zlib/writer.go
index a7b219467e..9986e3834d 100644
--- a/src/compress/zlib/writer.go
+++ b/src/compress/zlib/writer.go
@@ -6,6 +6,7 @@ package zlib
import (
"compress/flate"
+ "encoding/binary"
"fmt"
"hash"
"hash/adler32"
@@ -120,11 +121,7 @@ func (z *Writer) writeHeader() (err error) {
}
if z.dict != nil {
// The next four bytes are the Adler-32 checksum of the dictionary.
- checksum := adler32.Checksum(z.dict)
- z.scratch[0] = uint8(checksum >> 24)
- z.scratch[1] = uint8(checksum >> 16)
- z.scratch[2] = uint8(checksum >> 8)
- z.scratch[3] = uint8(checksum >> 0)
+ binary.BigEndian.PutUint32(z.scratch[:], adler32.Checksum(z.dict))
if _, err = z.w.Write(z.scratch[0:4]); err != nil {
return err
}
@@ -190,10 +187,7 @@ func (z *Writer) Close() error {
}
checksum := z.digest.Sum32()
// ZLIB (RFC 1950) is big-endian, unlike GZIP (RFC 1952).
- z.scratch[0] = uint8(checksum >> 24)
- z.scratch[1] = uint8(checksum >> 16)
- z.scratch[2] = uint8(checksum >> 8)
- z.scratch[3] = uint8(checksum >> 0)
+ binary.BigEndian.PutUint32(z.scratch[:], checksum)
_, z.err = z.w.Write(z.scratch[0:4])
return z.err
}
diff --git a/src/context/context.go b/src/context/context.go
index 85f8acf8fa..21a40d5947 100644
--- a/src/context/context.go
+++ b/src/context/context.go
@@ -393,7 +393,7 @@ func WithDeadline(parent Context, d time.Time) (Context, CancelFunc) {
dur := time.Until(d)
if dur <= 0 {
c.cancel(true, DeadlineExceeded) // deadline has already passed
- return c, func() { c.cancel(true, Canceled) }
+ return c, func() { c.cancel(false, Canceled) }
}
c.mu.Lock()
defer c.mu.Unlock()
diff --git a/src/crypto/cipher/benchmark_test.go b/src/crypto/cipher/benchmark_test.go
index 1a3f1bdfac..90d0cd7138 100644
--- a/src/crypto/cipher/benchmark_test.go
+++ b/src/crypto/cipher/benchmark_test.go
@@ -81,70 +81,49 @@ func BenchmarkAESGCMOpen8K(b *testing.B) {
benchmarkAESGCMOpen(b, make([]byte, 8*1024))
}
-// If we test exactly 1K blocks, we would generate exact multiples of
-// the cipher's block size, and the cipher stream fragments would
-// always be wordsize aligned, whereas non-aligned is a more typical
-// use-case.
-const almost1K = 1024 - 5
-
-func BenchmarkAESCFBEncrypt1K(b *testing.B) {
- buf := make([]byte, almost1K)
+func benchmarkAESStream(b *testing.B, mode func(cipher.Block, []byte) cipher.Stream, buf []byte) {
b.SetBytes(int64(len(buf)))
var key [16]byte
var iv [16]byte
aes, _ := aes.NewCipher(key[:])
- ctr := cipher.NewCFBEncrypter(aes, iv[:])
+ stream := mode(aes, iv[:])
b.ResetTimer()
for i := 0; i < b.N; i++ {
- ctr.XORKeyStream(buf, buf)
+ stream.XORKeyStream(buf, buf)
}
}
-func BenchmarkAESCFBDecrypt1K(b *testing.B) {
- buf := make([]byte, almost1K)
- b.SetBytes(int64(len(buf)))
-
- var key [16]byte
- var iv [16]byte
- aes, _ := aes.NewCipher(key[:])
- ctr := cipher.NewCFBDecrypter(aes, iv[:])
+// If we test exactly 1K blocks, we would generate exact multiples of
+// the cipher's block size, and the cipher stream fragments would
+// always be wordsize aligned, whereas non-aligned is a more typical
+// use-case.
+const almost1K = 1024 - 5
+const almost8K = 8*1024 - 5
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- ctr.XORKeyStream(buf, buf)
- }
+func BenchmarkAESCFBEncrypt1K(b *testing.B) {
+ benchmarkAESStream(b, cipher.NewCFBEncrypter, make([]byte, almost1K))
}
-func BenchmarkAESOFB1K(b *testing.B) {
- buf := make([]byte, almost1K)
- b.SetBytes(int64(len(buf)))
+func BenchmarkAESCFBDecrypt1K(b *testing.B) {
+ benchmarkAESStream(b, cipher.NewCFBDecrypter, make([]byte, almost1K))
+}
- var key [16]byte
- var iv [16]byte
- aes, _ := aes.NewCipher(key[:])
- ctr := cipher.NewOFB(aes, iv[:])
+func BenchmarkAESCFBDecrypt8K(b *testing.B) {
+ benchmarkAESStream(b, cipher.NewCFBDecrypter, make([]byte, almost8K))
+}
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- ctr.XORKeyStream(buf, buf)
- }
+func BenchmarkAESOFB1K(b *testing.B) {
+ benchmarkAESStream(b, cipher.NewOFB, make([]byte, almost1K))
}
func BenchmarkAESCTR1K(b *testing.B) {
- buf := make([]byte, almost1K)
- b.SetBytes(int64(len(buf)))
-
- var key [16]byte
- var iv [16]byte
- aes, _ := aes.NewCipher(key[:])
- ctr := cipher.NewCTR(aes, iv[:])
+ benchmarkAESStream(b, cipher.NewCTR, make([]byte, almost1K))
+}
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- ctr.XORKeyStream(buf, buf)
- }
+func BenchmarkAESCTR8K(b *testing.B) {
+ benchmarkAESStream(b, cipher.NewCTR, make([]byte, almost8K))
}
func BenchmarkAESCBCEncrypt1K(b *testing.B) {
diff --git a/src/crypto/md5/md5block_386.s b/src/crypto/md5/md5block_386.s
index 8e426d148f..30d4209a62 100644
--- a/src/crypto/md5/md5block_386.s
+++ b/src/crypto/md5/md5block_386.s
@@ -122,7 +122,7 @@ loop:
ROUND2(DX,AX,BX,CX, 7,0xfcefa3f8, 9);
ROUND2(CX,DX,AX,BX,12,0x676f02d9,14);
ROUND2(BX,CX,DX,AX, 0,0x8d2a4c8a,20);
-
+
MOVL (5*4)(SI), DI
MOVL CX, BP
diff --git a/src/crypto/md5/md5block_amd64.s b/src/crypto/md5/md5block_amd64.s
index a3ae7d97b2..90d932b146 100644
--- a/src/crypto/md5/md5block_amd64.s
+++ b/src/crypto/md5/md5block_amd64.s
@@ -99,7 +99,7 @@ loop:
ROUND2(DX,AX,BX,CX, 7,0xfcefa3f8, 9);
ROUND2(CX,DX,AX,BX,12,0x676f02d9,14);
ROUND2(BX,CX,DX,AX, 0,0x8d2a4c8a,20);
-
+
MOVL (5*4)(SI), R8
MOVL CX, R9
@@ -144,7 +144,7 @@ loop:
ROLL $shift, a; \
XORL c, R9; \
ADDL b, a
-
+
ROUND4(AX,BX,CX,DX, 7,0xf4292244, 6);
ROUND4(DX,AX,BX,CX,14,0x432aff97,10);
ROUND4(CX,DX,AX,BX, 5,0xab9423a7,15);
diff --git a/src/crypto/md5/md5block_amd64p32.s b/src/crypto/md5/md5block_amd64p32.s
index ee05f8613b..7295942dc8 100644
--- a/src/crypto/md5/md5block_amd64p32.s
+++ b/src/crypto/md5/md5block_amd64p32.s
@@ -103,7 +103,7 @@ loop:
ROUND2(DX,AX,BX,CX, 7,0xfcefa3f8, 9);
ROUND2(CX,DX,AX,BX,12,0x676f02d9,14);
ROUND2(BX,CX,DX,AX, 0,0x8d2a4c8a,20);
-
+
MOVL (5*4)(SI), R8
MOVL CX, R9
@@ -148,7 +148,7 @@ loop:
ROLL $shift, a; \
XORL c, R9; \
ADDL b, a
-
+
ROUND4(AX,BX,CX,DX, 7,0xf4292244, 6);
ROUND4(DX,AX,BX,CX,14,0x432aff97,10);
ROUND4(CX,DX,AX,BX, 5,0xab9423a7,15);
diff --git a/src/crypto/rand/rand.go b/src/crypto/rand/rand.go
index 952d20aa16..a5ccd19de3 100644
--- a/src/crypto/rand/rand.go
+++ b/src/crypto/rand/rand.go
@@ -23,3 +23,7 @@ var Reader io.Reader
func Read(b []byte) (n int, err error) {
return io.ReadFull(Reader, b)
}
+
+func warnBlocked() {
+ println("crypto/rand: blocked for 60 seconds waiting to read random data from the kernel")
+}
diff --git a/src/crypto/rand/rand_unix.go b/src/crypto/rand/rand_unix.go
index 13c874a961..272b83d52b 100644
--- a/src/crypto/rand/rand_unix.go
+++ b/src/crypto/rand/rand_unix.go
@@ -19,6 +19,7 @@ import (
"os"
"runtime"
"sync"
+ "sync/atomic"
"time"
)
@@ -44,6 +45,7 @@ type devReader struct {
name string
f io.Reader
mu sync.Mutex
+ used int32 // atomic; whether this devReader has been used
}
// altGetRandom if non-nil specifies an OS-specific function to get
@@ -52,6 +54,12 @@ var altGetRandom func([]byte) (ok bool)
func (r *devReader) Read(b []byte) (n int, err error) {
boring.Unreachable()
+ if atomic.CompareAndSwapInt32(&r.used, 0, 1) {
+ // First use of randomness. Start timer to warn about
+ // being blocked on entropy not being available.
+ t := time.AfterFunc(60*time.Second, warnBlocked)
+ defer t.Stop()
+ }
if altGetRandom != nil && r.name == urandomDevice && altGetRandom(b) {
return len(b), nil
}
diff --git a/src/crypto/rand/rand_windows.go b/src/crypto/rand/rand_windows.go
index 4d7511a840..78a4ed6d67 100644
--- a/src/crypto/rand/rand_windows.go
+++ b/src/crypto/rand/rand_windows.go
@@ -10,7 +10,9 @@ package rand
import (
"os"
"sync"
+ "sync/atomic"
"syscall"
+ "time"
)
// Implemented by using Windows CryptoAPI 2.0.
@@ -19,11 +21,18 @@ func init() { Reader = &rngReader{} }
// A rngReader satisfies reads by reading from the Windows CryptGenRandom API.
type rngReader struct {
+ used int32 // atomic; whether this rngReader has been used
prov syscall.Handle
mu sync.Mutex
}
func (r *rngReader) Read(b []byte) (n int, err error) {
+ if atomic.CompareAndSwapInt32(&r.used, 0, 1) {
+ // First use of randomness. Start timer to warn about
+ // being blocked on entropy not being available.
+ t := time.AfterFunc(60*time.Second, warnBlocked)
+ defer t.Stop()
+ }
r.mu.Lock()
if r.prov == 0 {
const provType = syscall.PROV_RSA_FULL
diff --git a/src/crypto/rsa/pss_test.go b/src/crypto/rsa/pss_test.go
index 4ce5ad8684..32f6f0c3aa 100644
--- a/src/crypto/rsa/pss_test.go
+++ b/src/crypto/rsa/pss_test.go
@@ -102,7 +102,7 @@ func TestPSSGolden(t *testing.T) {
switch {
case len(line) == 0:
if len(partialValue) > 0 {
- values <- strings.Replace(partialValue, " ", "", -1)
+ values <- strings.ReplaceAll(partialValue, " ", "")
partialValue = ""
lastWasValue = true
}
diff --git a/src/crypto/sha1/sha1block_386.s b/src/crypto/sha1/sha1block_386.s
index 0a7e45a79c..34d023d424 100644
--- a/src/crypto/sha1/sha1block_386.s
+++ b/src/crypto/sha1/sha1block_386.s
@@ -105,7 +105,7 @@ TEXT ·block(SB),NOSPLIT,$92-16
MOVL p_len+8(FP), DX
SHRL $6, DX
SHLL $6, DX
-
+
LEAL (SI)(DX*1), DI
MOVL (0*4)(BP), AX
MOVL (1*4)(BP), BX
@@ -148,7 +148,7 @@ loop:
ROUND1x(DX, BP, AX, BX, CX, 17)
ROUND1x(CX, DX, BP, AX, BX, 18)
ROUND1x(BX, CX, DX, BP, AX, 19)
-
+
ROUND2(AX, BX, CX, DX, BP, 20)
ROUND2(BP, AX, BX, CX, DX, 21)
ROUND2(DX, BP, AX, BX, CX, 22)
@@ -169,7 +169,7 @@ loop:
ROUND2(DX, BP, AX, BX, CX, 37)
ROUND2(CX, DX, BP, AX, BX, 38)
ROUND2(BX, CX, DX, BP, AX, 39)
-
+
ROUND3(AX, BX, CX, DX, BP, 40)
ROUND3(BP, AX, BX, CX, DX, 41)
ROUND3(DX, BP, AX, BX, CX, 42)
@@ -190,7 +190,7 @@ loop:
ROUND3(DX, BP, AX, BX, CX, 57)
ROUND3(CX, DX, BP, AX, BX, 58)
ROUND3(BX, CX, DX, BP, AX, 59)
-
+
ROUND4(AX, BX, CX, DX, BP, 60)
ROUND4(BP, AX, BX, CX, DX, 61)
ROUND4(DX, BP, AX, BX, CX, 62)
diff --git a/src/crypto/sha1/sha1block_amd64.s b/src/crypto/sha1/sha1block_amd64.s
index 135f113898..42f03fb268 100644
--- a/src/crypto/sha1/sha1block_amd64.s
+++ b/src/crypto/sha1/sha1block_amd64.s
@@ -60,7 +60,7 @@
MOVL b, R9; \
ANDL c, R9; \
ORL R8, R9
-
+
#define FUNC4 FUNC2
#define MIX(a, b, c, d, e, const) \
@@ -102,7 +102,7 @@ TEXT ·blockAMD64(SB),NOSPLIT,$64-32
MOVQ p_len+16(FP), DX
SHRQ $6, DX
SHLQ $6, DX
-
+
LEAQ (SI)(DX*1), DI
MOVL (0*4)(BP), AX
MOVL (1*4)(BP), BX
@@ -141,7 +141,7 @@ loop:
ROUND1x(DX, BP, AX, BX, CX, 17)
ROUND1x(CX, DX, BP, AX, BX, 18)
ROUND1x(BX, CX, DX, BP, AX, 19)
-
+
ROUND2(AX, BX, CX, DX, BP, 20)
ROUND2(BP, AX, BX, CX, DX, 21)
ROUND2(DX, BP, AX, BX, CX, 22)
@@ -162,7 +162,7 @@ loop:
ROUND2(DX, BP, AX, BX, CX, 37)
ROUND2(CX, DX, BP, AX, BX, 38)
ROUND2(BX, CX, DX, BP, AX, 39)
-
+
ROUND3(AX, BX, CX, DX, BP, 40)
ROUND3(BP, AX, BX, CX, DX, 41)
ROUND3(DX, BP, AX, BX, CX, 42)
@@ -183,7 +183,7 @@ loop:
ROUND3(DX, BP, AX, BX, CX, 57)
ROUND3(CX, DX, BP, AX, BX, 58)
ROUND3(BX, CX, DX, BP, AX, 59)
-
+
ROUND4(AX, BX, CX, DX, BP, 60)
ROUND4(BP, AX, BX, CX, DX, 61)
ROUND4(DX, BP, AX, BX, CX, 62)
diff --git a/src/crypto/sha1/sha1block_amd64p32.s b/src/crypto/sha1/sha1block_amd64p32.s
index e5404e8997..32058ba01d 100644
--- a/src/crypto/sha1/sha1block_amd64p32.s
+++ b/src/crypto/sha1/sha1block_amd64p32.s
@@ -55,7 +55,7 @@
MOVL b, R9; \
ANDL c, R9; \
ORL R8, R9
-
+
#define FUNC4 FUNC2
#define MIX(a, b, c, d, e, const) \
@@ -97,7 +97,7 @@ TEXT ·block(SB),NOSPLIT,$64-16
MOVL p_len+8(FP), DX
SHRQ $6, DX
SHLQ $6, DX
-
+
LEAQ (SI)(DX*1), DI
MOVL (0*4)(R14), AX
MOVL (1*4)(R14), BX
@@ -131,7 +131,7 @@ loop:
ROUND1x(DX, BP, AX, BX, CX, 17)
ROUND1x(CX, DX, BP, AX, BX, 18)
ROUND1x(BX, CX, DX, BP, AX, 19)
-
+
ROUND2(AX, BX, CX, DX, BP, 20)
ROUND2(BP, AX, BX, CX, DX, 21)
ROUND2(DX, BP, AX, BX, CX, 22)
@@ -152,7 +152,7 @@ loop:
ROUND2(DX, BP, AX, BX, CX, 37)
ROUND2(CX, DX, BP, AX, BX, 38)
ROUND2(BX, CX, DX, BP, AX, 39)
-
+
ROUND3(AX, BX, CX, DX, BP, 40)
ROUND3(BP, AX, BX, CX, DX, 41)
ROUND3(DX, BP, AX, BX, CX, 42)
@@ -173,7 +173,7 @@ loop:
ROUND3(DX, BP, AX, BX, CX, 57)
ROUND3(CX, DX, BP, AX, BX, 58)
ROUND3(BX, CX, DX, BP, AX, 59)
-
+
ROUND4(AX, BX, CX, DX, BP, 60)
ROUND4(BP, AX, BX, CX, DX, 61)
ROUND4(DX, BP, AX, BX, CX, 62)
diff --git a/src/crypto/sha1/sha1block_arm.s b/src/crypto/sha1/sha1block_arm.s
index 055edc9f3f..2236533ab4 100644
--- a/src/crypto/sha1/sha1block_arm.s
+++ b/src/crypto/sha1/sha1block_arm.s
@@ -63,10 +63,10 @@
ORR Rt1<<24, Rt0, Rt0 ; \
MOVW.P Rt0, 4(Rw) ; \
ADD Rt0, Re, Re
-
+
// tmp := w[(i-3)&0xf] ^ w[(i-8)&0xf] ^ w[(i-14)&0xf] ^ w[(i)&0xf]
// w[i&0xf] = tmp<<1 | tmp>>(32-1)
- // e += w[i&0xf]
+ // e += w[i&0xf]
#define SHUFFLE(Re) \
MOVW (-16*4)(Rw), Rt0 ; \
MOVW (-14*4)(Rw), Rt1 ; \
@@ -167,7 +167,7 @@ loop1: ROUND1(Ra, Rb, Rc, Rd, Re)
ROUND1x(Rd, Re, Ra, Rb, Rc)
ROUND1x(Rc, Rd, Re, Ra, Rb)
ROUND1x(Rb, Rc, Rd, Re, Ra)
-
+
MOVW $0x6ED9EBA1, Rconst
MOVW $4, Rctr
loop2: ROUND2(Ra, Rb, Rc, Rd, Re)
@@ -177,7 +177,7 @@ loop2: ROUND2(Ra, Rb, Rc, Rd, Re)
ROUND2(Rb, Rc, Rd, Re, Ra)
SUB.S $1, Rctr
BNE loop2
-
+
MOVW $0x8F1BBCDC, Rconst
MOVW $4, Rctr
loop3: ROUND3(Ra, Rb, Rc, Rd, Re)
@@ -187,7 +187,7 @@ loop3: ROUND3(Ra, Rb, Rc, Rd, Re)
ROUND3(Rb, Rc, Rd, Re, Ra)
SUB.S $1, Rctr
BNE loop3
-
+
MOVW $0xCA62C1D6, Rconst
MOVW $4, Rctr
loop4: ROUND4(Ra, Rb, Rc, Rd, Re)
diff --git a/src/crypto/x509/cert_pool.go b/src/crypto/x509/cert_pool.go
index 86aba6710d..7cc1dd4eb6 100644
--- a/src/crypto/x509/cert_pool.go
+++ b/src/crypto/x509/cert_pool.go
@@ -50,7 +50,7 @@ func (s *CertPool) copy() *CertPool {
// Any mutations to the returned pool are not written to disk and do
// not affect any other pool returned by SystemCertPool.
//
-// New changes in the the system cert pool might not be reflected
+// New changes in the system cert pool might not be reflected
// in subsequent calls.
func SystemCertPool() (*CertPool, error) {
if runtime.GOOS == "windows" {
diff --git a/src/crypto/x509/root_darwin_arm_gen.go b/src/crypto/x509/root_darwin_arm_gen.go
index b5580d6f02..bc44124a78 100644
--- a/src/crypto/x509/root_darwin_arm_gen.go
+++ b/src/crypto/x509/root_darwin_arm_gen.go
@@ -154,9 +154,9 @@ func fetchCertIDs() ([]certID, error) {
values := regexp.MustCompile("(?s)<td>(.*?)</td>").FindAllStringSubmatch(row, -1)
name := values[cols["Certificate name"]][1]
fingerprint := values[cols["Fingerprint (SHA-256)"]][1]
- fingerprint = strings.Replace(fingerprint, "<br>", "", -1)
- fingerprint = strings.Replace(fingerprint, "\n", "", -1)
- fingerprint = strings.Replace(fingerprint, " ", "", -1)
+ fingerprint = strings.ReplaceAll(fingerprint, "<br>", "")
+ fingerprint = strings.ReplaceAll(fingerprint, "\n", "")
+ fingerprint = strings.ReplaceAll(fingerprint, " ", "")
fingerprint = strings.ToLower(fingerprint)
ids = append(ids, certID{
diff --git a/src/crypto/x509/verify.go b/src/crypto/x509/verify.go
index 94b68a4607..b545f2b2dc 100644
--- a/src/crypto/x509/verify.go
+++ b/src/crypto/x509/verify.go
@@ -906,8 +906,8 @@ func validHostname(host string) bool {
if c == '-' && j != 0 {
continue
}
- if c == '_' {
- // _ is not a valid character in hostnames, but it's commonly
+ if c == '_' || c == ':' {
+ // Not valid characters in hostnames, but commonly
// found in deployments outside the WebPKI.
continue
}
diff --git a/src/crypto/x509/verify_test.go b/src/crypto/x509/verify_test.go
index 7684145839..0e24d3b5da 100644
--- a/src/crypto/x509/verify_test.go
+++ b/src/crypto/x509/verify_test.go
@@ -1881,6 +1881,7 @@ func TestValidHostname(t *testing.T) {
{"foo.*.example.com", false},
{"exa_mple.com", true},
{"foo,bar", false},
+ {"project-dev:us-central1:main", true},
}
for _, tt := range tests {
if got := validHostname(tt.host); got != tt.want {
diff --git a/src/database/sql/driver/driver.go b/src/database/sql/driver/driver.go
index 1e54b4cf2c..70b3ddc470 100644
--- a/src/database/sql/driver/driver.go
+++ b/src/database/sql/driver/driver.go
@@ -469,7 +469,7 @@ type RowsAffected int64
var _ Result = RowsAffected(0)
func (RowsAffected) LastInsertId() (int64, error) {
- return 0, errors.New("no LastInsertId available")
+ return 0, errors.New("LastInsertId is not supported by this driver")
}
func (v RowsAffected) RowsAffected() (int64, error) {
diff --git a/src/database/sql/sql.go b/src/database/sql/sql.go
index 7537f87d47..7c8d46b100 100644
--- a/src/database/sql/sql.go
+++ b/src/database/sql/sql.go
@@ -1322,11 +1322,13 @@ func (db *DB) putConnDBLocked(dc *driverConn, err error) bool {
err: err,
}
return true
- } else if err == nil && !db.closed && db.maxIdleConnsLocked() > len(db.freeConn) {
- db.freeConn = append(db.freeConn, dc)
+ } else if err == nil && !db.closed {
+ if db.maxIdleConnsLocked() > len(db.freeConn) {
+ db.freeConn = append(db.freeConn, dc)
+ db.startCleanerLocked()
+ return true
+ }
db.maxIdleClosed++
- db.startCleanerLocked()
- return true
}
return false
}
diff --git a/src/database/sql/sql_test.go b/src/database/sql/sql_test.go
index f194744aef..e52091c3af 100644
--- a/src/database/sql/sql_test.go
+++ b/src/database/sql/sql_test.go
@@ -3415,6 +3415,58 @@ func TestConnectionLeak(t *testing.T) {
wg.Wait()
}
+func TestStatsMaxIdleClosedZero(t *testing.T) {
+ db := newTestDB(t, "people")
+ defer closeDB(t, db)
+
+ db.SetMaxOpenConns(1)
+ db.SetMaxIdleConns(1)
+ db.SetConnMaxLifetime(0)
+
+ preMaxIdleClosed := db.Stats().MaxIdleClosed
+
+ for i := 0; i < 10; i++ {
+ rows, err := db.Query("SELECT|people|name|")
+ if err != nil {
+ t.Fatal(err)
+ }
+ rows.Close()
+ }
+
+ st := db.Stats()
+ maxIdleClosed := st.MaxIdleClosed - preMaxIdleClosed
+ t.Logf("MaxIdleClosed: %d", maxIdleClosed)
+ if maxIdleClosed != 0 {
+ t.Fatal("expected 0 max idle closed conns, got: ", maxIdleClosed)
+ }
+}
+
+func TestStatsMaxIdleClosedTen(t *testing.T) {
+ db := newTestDB(t, "people")
+ defer closeDB(t, db)
+
+ db.SetMaxOpenConns(1)
+ db.SetMaxIdleConns(0)
+ db.SetConnMaxLifetime(0)
+
+ preMaxIdleClosed := db.Stats().MaxIdleClosed
+
+ for i := 0; i < 10; i++ {
+ rows, err := db.Query("SELECT|people|name|")
+ if err != nil {
+ t.Fatal(err)
+ }
+ rows.Close()
+ }
+
+ st := db.Stats()
+ maxIdleClosed := st.MaxIdleClosed - preMaxIdleClosed
+ t.Logf("MaxIdleClosed: %d", maxIdleClosed)
+ if maxIdleClosed != 10 {
+ t.Fatal("expected 0 max idle closed conns, got: ", maxIdleClosed)
+ }
+}
+
type nvcDriver struct {
fakeDriver
skipNamedValueCheck bool
diff --git a/src/debug/elf/elf.go b/src/debug/elf/elf.go
index 07c03e7999..96a67ce732 100644
--- a/src/debug/elf/elf.go
+++ b/src/debug/elf/elf.go
@@ -2424,6 +2424,7 @@ const (
R_RISCV_SET8 R_RISCV = 54 /* Local label subtraction */
R_RISCV_SET16 R_RISCV = 55 /* Local label subtraction */
R_RISCV_SET32 R_RISCV = 56 /* Local label subtraction */
+ R_RISCV_32_PCREL R_RISCV = 57 /* 32-bit PC relative */
)
var rriscvStrings = []intName{
@@ -2480,6 +2481,7 @@ var rriscvStrings = []intName{
{54, "R_RISCV_SET8"},
{55, "R_RISCV_SET16"},
{56, "R_RISCV_SET32"},
+ {57, "R_RISCV_32_PCREL"},
}
func (i R_RISCV) String() string { return stringName(uint32(i), rriscvStrings, false) }
diff --git a/src/encoding/base32/base32_test.go b/src/encoding/base32/base32_test.go
index c5506ed4de..b74054ba40 100644
--- a/src/encoding/base32/base32_test.go
+++ b/src/encoding/base32/base32_test.go
@@ -425,7 +425,7 @@ IZJAOZSWY2LUEBSXG43FEBRWS3DMOVWSAZDPNRXXEZJAMV2SAZTVM5UWC5BANZ2WY3DBBJYGC4TJMF
NZ2CYIDTOVXHIIDJNYFGG5LMOBQSA4LVNEQG6ZTGNFRWSYJAMRSXGZLSOVXHIIDNN5WGY2LUEBQW42
LNEBUWIIDFON2CA3DBMJXXE5LNFY==
====`
- encodedShort := strings.Replace(encoded, "\n", "", -1)
+ encodedShort := strings.ReplaceAll(encoded, "\n", "")
dec := NewDecoder(StdEncoding, strings.NewReader(encoded))
res1, err := ioutil.ReadAll(dec)
@@ -465,7 +465,7 @@ func TestWithCustomPadding(t *testing.T) {
for _, testcase := range pairs {
defaultPadding := StdEncoding.EncodeToString([]byte(testcase.decoded))
customPadding := StdEncoding.WithPadding('@').EncodeToString([]byte(testcase.decoded))
- expected := strings.Replace(defaultPadding, "=", "@", -1)
+ expected := strings.ReplaceAll(defaultPadding, "=", "@")
if expected != customPadding {
t.Errorf("Expected custom %s, got %s", expected, customPadding)
@@ -675,7 +675,7 @@ func TestWithoutPaddingClose(t *testing.T) {
expected := testpair.encoded
if encoding.padChar == NoPadding {
- expected = strings.Replace(expected, "=", "", -1)
+ expected = strings.ReplaceAll(expected, "=", "")
}
res := buf.String()
@@ -697,7 +697,7 @@ func TestDecodeReadAll(t *testing.T) {
for encIndex, encoding := range encodings {
encoded := pair.encoded
if encoding.padChar == NoPadding {
- encoded = strings.Replace(encoded, "=", "", -1)
+ encoded = strings.ReplaceAll(encoded, "=", "")
}
decReader, err := ioutil.ReadAll(NewDecoder(encoding, strings.NewReader(encoded)))
@@ -723,7 +723,7 @@ func TestDecodeSmallBuffer(t *testing.T) {
for encIndex, encoding := range encodings {
encoded := pair.encoded
if encoding.padChar == NoPadding {
- encoded = strings.Replace(encoded, "=", "", -1)
+ encoded = strings.ReplaceAll(encoded, "=", "")
}
decoder := NewDecoder(encoding, strings.NewReader(encoded))
diff --git a/src/encoding/base64/base64_test.go b/src/encoding/base64/base64_test.go
index f019654f5b..f7f312ca39 100644
--- a/src/encoding/base64/base64_test.go
+++ b/src/encoding/base64/base64_test.go
@@ -53,8 +53,8 @@ func stdRef(ref string) string {
// Convert a reference string to URL-encoding
func urlRef(ref string) string {
- ref = strings.Replace(ref, "+", "-", -1)
- ref = strings.Replace(ref, "/", "_", -1)
+ ref = strings.ReplaceAll(ref, "+", "-")
+ ref = strings.ReplaceAll(ref, "/", "_")
return ref
}
@@ -72,7 +72,7 @@ func rawURLRef(ref string) string {
var funnyEncoding = NewEncoding(encodeStd).WithPadding(rune('@'))
func funnyRef(ref string) string {
- return strings.Replace(ref, "=", "@", -1)
+ return strings.ReplaceAll(ref, "=", "@")
}
type encodingTest struct {
@@ -418,7 +418,7 @@ j+mSARB/17pKVXYWHXjsj7yIex0PadzXMO1zT5KHoNA3HT8ietoGhgjsfA+CSnvvqh/jJtqsrwOv
2b6NGNzXfTYexzJ+nU7/ALkf4P8Awv6P9KvTQQ4AgyDqCF85Pho3CTB7eHwXoH+LT65uZbX9X+o2
bqbPb06551Y4
`
- encodedShort := strings.Replace(encoded, "\n", "", -1)
+ encodedShort := strings.ReplaceAll(encoded, "\n", "")
dec := NewDecoder(StdEncoding, strings.NewReader(encoded))
res1, err := ioutil.ReadAll(dec)
diff --git a/src/encoding/json/decode.go b/src/encoding/json/decode.go
index 82dc78083a..cab4616ba3 100644
--- a/src/encoding/json/decode.go
+++ b/src/encoding/json/decode.go
@@ -11,7 +11,6 @@ import (
"bytes"
"encoding"
"encoding/base64"
- "errors"
"fmt"
"reflect"
"strconv"
@@ -280,10 +279,10 @@ func (d *decodeState) readIndex() int {
return d.off - 1
}
-// errPhase is used for errors that should not happen unless
-// there is a bug in the JSON decoder or something is editing
-// the data slice while the decoder executes.
-var errPhase = errors.New("JSON decoder out of sync - data changing underfoot?")
+// phasePanicMsg is used as a panic message when we end up with something that
+// shouldn't happen. It can indicate a bug in the JSON decoder, or that
+// something is editing the data slice while the decoder executes.
+const phasePanicMsg = "JSON decoder out of sync - data changing underfoot?"
func (d *decodeState) init(data []byte) *decodeState {
d.data = data
@@ -365,7 +364,7 @@ func (d *decodeState) scanWhile(op int) {
func (d *decodeState) value(v reflect.Value) error {
switch d.opcode {
default:
- return errPhase
+ panic(phasePanicMsg)
case scanBeginArray:
if v.IsValid() {
@@ -407,26 +406,23 @@ type unquotedValue struct{}
// quoted string literal or literal null into an interface value.
// If it finds anything other than a quoted string literal or null,
// valueQuoted returns unquotedValue{}.
-func (d *decodeState) valueQuoted() (interface{}, error) {
+func (d *decodeState) valueQuoted() interface{} {
switch d.opcode {
default:
- return nil, errPhase
+ panic(phasePanicMsg)
case scanBeginArray, scanBeginObject:
d.skip()
d.scanNext()
case scanBeginLiteral:
- v, err := d.literalInterface()
- if err != nil {
- return nil, err
- }
+ v := d.literalInterface()
switch v.(type) {
case nil, string:
- return v, nil
+ return v
}
}
- return unquotedValue{}, nil
+ return unquotedValue{}
}
// indirect walks down v allocating pointers as needed,
@@ -520,10 +516,7 @@ func (d *decodeState) array(v reflect.Value) error {
case reflect.Interface:
if v.NumMethod() == 0 {
// Decoding into nil interface? Switch to non-reflect code.
- ai, err := d.arrayInterface()
- if err != nil {
- return err
- }
+ ai := d.arrayInterface()
v.Set(reflect.ValueOf(ai))
return nil
}
@@ -533,8 +526,7 @@ func (d *decodeState) array(v reflect.Value) error {
d.saveError(&UnmarshalTypeError{Value: "array", Type: v.Type(), Offset: int64(d.off)})
d.skip()
return nil
- case reflect.Array:
- case reflect.Slice:
+ case reflect.Array, reflect.Slice:
break
}
@@ -584,7 +576,7 @@ func (d *decodeState) array(v reflect.Value) error {
break
}
if d.opcode != scanArrayValue {
- return errPhase
+ panic(phasePanicMsg)
}
}
@@ -628,10 +620,7 @@ func (d *decodeState) object(v reflect.Value) error {
// Decoding into nil interface? Switch to non-reflect code.
if v.Kind() == reflect.Interface && v.NumMethod() == 0 {
- oi, err := d.objectInterface()
- if err != nil {
- return err
- }
+ oi := d.objectInterface()
v.Set(reflect.ValueOf(oi))
return nil
}
@@ -680,7 +669,7 @@ func (d *decodeState) object(v reflect.Value) error {
break
}
if d.opcode != scanBeginLiteral {
- return errPhase
+ panic(phasePanicMsg)
}
// Read key.
@@ -689,7 +678,7 @@ func (d *decodeState) object(v reflect.Value) error {
item := d.data[start:d.readIndex()]
key, ok := unquoteBytes(item)
if !ok {
- return errPhase
+ panic(phasePanicMsg)
}
// Figure out field corresponding to key.
@@ -753,16 +742,12 @@ func (d *decodeState) object(v reflect.Value) error {
d.scanWhile(scanSkipSpace)
}
if d.opcode != scanObjectKey {
- return errPhase
+ panic(phasePanicMsg)
}
d.scanWhile(scanSkipSpace)
if destring {
- q, err := d.valueQuoted()
- if err != nil {
- return err
- }
- switch qv := q.(type) {
+ switch qv := d.valueQuoted().(type) {
case nil:
if err := d.literalStore(nullLiteral, subv, false); err != nil {
return err
@@ -827,7 +812,7 @@ func (d *decodeState) object(v reflect.Value) error {
break
}
if d.opcode != scanObjectValue {
- return errPhase
+ panic(phasePanicMsg)
}
d.errorContext = originalErrorContext
@@ -871,18 +856,16 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
if item[0] != '"' {
if fromQuoted {
d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
- } else {
- var val string
- switch item[0] {
- case 'n':
- val = "null"
- case 't', 'f':
- val = "bool"
- default:
- val = "number"
- }
- d.saveError(&UnmarshalTypeError{Value: val, Type: v.Type(), Offset: int64(d.readIndex())})
+ return nil
+ }
+ val := "number"
+ switch item[0] {
+ case 'n':
+ val = "null"
+ case 't', 'f':
+ val = "bool"
}
+ d.saveError(&UnmarshalTypeError{Value: val, Type: v.Type(), Offset: int64(d.readIndex())})
return nil
}
s, ok := unquoteBytes(item)
@@ -890,7 +873,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
if fromQuoted {
return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())
}
- return errPhase
+ panic(phasePanicMsg)
}
return ut.UnmarshalText(s)
}
@@ -941,7 +924,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
if fromQuoted {
return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())
}
- return errPhase
+ panic(phasePanicMsg)
}
switch v.Kind() {
default:
@@ -973,7 +956,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
if fromQuoted {
return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())
}
- return errPhase
+ panic(phasePanicMsg)
}
s := string(item)
switch v.Kind() {
@@ -1034,24 +1017,24 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
// but they avoid the weight of reflection in this common case.
// valueInterface is like value but returns interface{}
-func (d *decodeState) valueInterface() (val interface{}, err error) {
+func (d *decodeState) valueInterface() (val interface{}) {
switch d.opcode {
default:
- err = errPhase
+ panic(phasePanicMsg)
case scanBeginArray:
- val, err = d.arrayInterface()
+ val = d.arrayInterface()
d.scanNext()
case scanBeginObject:
- val, err = d.objectInterface()
+ val = d.objectInterface()
d.scanNext()
case scanBeginLiteral:
- val, err = d.literalInterface()
+ val = d.literalInterface()
}
return
}
// arrayInterface is like array but returns []interface{}.
-func (d *decodeState) arrayInterface() ([]interface{}, error) {
+func (d *decodeState) arrayInterface() []interface{} {
var v = make([]interface{}, 0)
for {
// Look ahead for ] - can only happen on first iteration.
@@ -1060,11 +1043,7 @@ func (d *decodeState) arrayInterface() ([]interface{}, error) {
break
}
- vi, err := d.valueInterface()
- if err != nil {
- return nil, err
- }
- v = append(v, vi)
+ v = append(v, d.valueInterface())
// Next token must be , or ].
if d.opcode == scanSkipSpace {
@@ -1074,14 +1053,14 @@ func (d *decodeState) arrayInterface() ([]interface{}, error) {
break
}
if d.opcode != scanArrayValue {
- return nil, errPhase
+ panic(phasePanicMsg)
}
}
- return v, nil
+ return v
}
// objectInterface is like object but returns map[string]interface{}.
-func (d *decodeState) objectInterface() (map[string]interface{}, error) {
+func (d *decodeState) objectInterface() map[string]interface{} {
m := make(map[string]interface{})
for {
// Read opening " of string key or closing }.
@@ -1091,7 +1070,7 @@ func (d *decodeState) objectInterface() (map[string]interface{}, error) {
break
}
if d.opcode != scanBeginLiteral {
- return nil, errPhase
+ panic(phasePanicMsg)
}
// Read string key.
@@ -1100,7 +1079,7 @@ func (d *decodeState) objectInterface() (map[string]interface{}, error) {
item := d.data[start:d.readIndex()]
key, ok := unquote(item)
if !ok {
- return nil, errPhase
+ panic(phasePanicMsg)
}
// Read : before value.
@@ -1108,16 +1087,12 @@ func (d *decodeState) objectInterface() (map[string]interface{}, error) {
d.scanWhile(scanSkipSpace)
}
if d.opcode != scanObjectKey {
- return nil, errPhase
+ panic(phasePanicMsg)
}
d.scanWhile(scanSkipSpace)
// Read value.
- vi, err := d.valueInterface()
- if err != nil {
- return nil, err
- }
- m[key] = vi
+ m[key] = d.valueInterface()
// Next token must be , or }.
if d.opcode == scanSkipSpace {
@@ -1127,16 +1102,16 @@ func (d *decodeState) objectInterface() (map[string]interface{}, error) {
break
}
if d.opcode != scanObjectValue {
- return nil, errPhase
+ panic(phasePanicMsg)
}
}
- return m, nil
+ return m
}
// literalInterface consumes and returns a literal from d.data[d.off-1:] and
// it reads the following byte ahead. The first byte of the literal has been
// read already (that's how the caller knows it's a literal).
-func (d *decodeState) literalInterface() (interface{}, error) {
+func (d *decodeState) literalInterface() interface{} {
// All bytes inside literal return scanContinue op code.
start := d.readIndex()
d.scanWhile(scanContinue)
@@ -1145,27 +1120,27 @@ func (d *decodeState) literalInterface() (interface{}, error) {
switch c := item[0]; c {
case 'n': // null
- return nil, nil
+ return nil
case 't', 'f': // true, false
- return c == 't', nil
+ return c == 't'
case '"': // string
s, ok := unquote(item)
if !ok {
- return nil, errPhase
+ panic(phasePanicMsg)
}
- return s, nil
+ return s
default: // number
if c != '-' && (c < '0' || c > '9') {
- return nil, errPhase
+ panic(phasePanicMsg)
}
n, err := d.convertNumber(string(item))
if err != nil {
d.saveError(err)
}
- return n, nil
+ return n
}
}
diff --git a/src/encoding/json/decode_test.go b/src/encoding/json/decode_test.go
index defa97e40f..5fbe67a706 100644
--- a/src/encoding/json/decode_test.go
+++ b/src/encoding/json/decode_test.go
@@ -445,6 +445,7 @@ var unmarshalTests = []unmarshalTest{
{in: `{"X": "foo", "Y"}`, err: &SyntaxError{"invalid character '}' after object key", 17}},
{in: `[1, 2, 3+]`, err: &SyntaxError{"invalid character '+' after array element", 9}},
{in: `{"X":12x}`, err: &SyntaxError{"invalid character 'x' after object key:value pair", 8}, useNumber: true},
+ {in: `[2, 3`, err: &SyntaxError{msg: "unexpected end of JSON input", Offset: 5}},
// raw value errors
{in: "\x01 42", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}},
@@ -460,6 +461,7 @@ var unmarshalTests = []unmarshalTest{
{in: `[1, 2, 3]`, ptr: new([3]int), out: [3]int{1, 2, 3}},
{in: `[1, 2, 3]`, ptr: new([1]int), out: [1]int{1}},
{in: `[1, 2, 3]`, ptr: new([5]int), out: [5]int{1, 2, 3, 0, 0}},
+ {in: `[1, 2, 3]`, ptr: new(MustNotUnmarshalJSON), err: errors.New("MustNotUnmarshalJSON was used")},
// empty array to interface test
{in: `[]`, ptr: new([]interface{}), out: []interface{}{}},
@@ -826,6 +828,7 @@ var unmarshalTests = []unmarshalTest{
{in: `{"B": "False"}`, ptr: new(B), err: errors.New(`json: invalid use of ,string struct tag, trying to unmarshal "False" into bool`)},
{in: `{"B": "null"}`, ptr: new(B), out: B{false}},
{in: `{"B": "nul"}`, ptr: new(B), err: errors.New(`json: invalid use of ,string struct tag, trying to unmarshal "nul" into bool`)},
+ {in: `{"B": [2, 3]}`, ptr: new(B), err: errors.New(`json: invalid use of ,string struct tag, trying to unmarshal unquoted value into bool`)},
// additional tests for disallowUnknownFields
{
@@ -894,6 +897,18 @@ var unmarshalTests = []unmarshalTest{
ptr: new(mapStringToStringData),
err: &UnmarshalTypeError{Value: "number", Type: reflect.TypeOf(""), Offset: 21, Struct: "mapStringToStringData", Field: "data"},
},
+
+ // trying to decode JSON arrays or objects via TextUnmarshaler
+ {
+ in: `[1, 2, 3]`,
+ ptr: new(MustNotUnmarshalText),
+ err: &UnmarshalTypeError{Value: "array", Type: reflect.TypeOf(&MustNotUnmarshalText{}), Offset: 1},
+ },
+ {
+ in: `{"foo": "bar"}`,
+ ptr: new(MustNotUnmarshalText),
+ err: &UnmarshalTypeError{Value: "object", Type: reflect.TypeOf(&MustNotUnmarshalText{}), Offset: 1},
+ },
}
func TestMarshal(t *testing.T) {
@@ -1955,10 +1970,12 @@ type unexportedFields struct {
Name string
m map[string]interface{} `json:"-"`
m2 map[string]interface{} `json:"abcd"`
+
+ s []int `json:"-"`
}
func TestUnmarshalUnexported(t *testing.T) {
- input := `{"Name": "Bob", "m": {"x": 123}, "m2": {"y": 456}, "abcd": {"z": 789}}`
+ input := `{"Name": "Bob", "m": {"x": 123}, "m2": {"y": 456}, "abcd": {"z": 789}, "s": [2, 3]}`
want := &unexportedFields{Name: "Bob"}
out := &unexportedFields{}
diff --git a/src/flag/flag.go b/src/flag/flag.go
index 2cd7829c1a..ae84e1f775 100644
--- a/src/flag/flag.go
+++ b/src/flag/flag.go
@@ -472,7 +472,7 @@ func (f *FlagSet) PrintDefaults() {
// for both 4- and 8-space tab stops.
s += "\n \t"
}
- s += strings.Replace(usage, "\n", "\n \t", -1)
+ s += strings.ReplaceAll(usage, "\n", "\n \t")
if !isZeroValue(flag, flag.DefValue) {
if _, ok := flag.Value.(*stringValue); ok {
diff --git a/src/fmt/example_test.go b/src/fmt/example_test.go
index 1479b761b6..ecf3391ce7 100644
--- a/src/fmt/example_test.go
+++ b/src/fmt/example_test.go
@@ -7,8 +7,10 @@ package fmt_test
import (
"fmt"
"io"
+ "math"
"os"
"strings"
+ "time"
)
// The Errorf function lets us use formatting features
@@ -17,6 +19,7 @@ func ExampleErrorf() {
const name, id = "bueller", 17
err := fmt.Errorf("user %q (id %d) not found", name, id)
fmt.Println(err.Error())
+
// Output: user "bueller" (id 17) not found
}
@@ -29,7 +32,7 @@ func ExampleFscanf() {
r := strings.NewReader("5 true gophers")
n, err := fmt.Fscanf(r, "%d %t %s", &i, &b, &s)
if err != nil {
- panic(err)
+ fmt.Fprintf(os.Stderr, "Fscanf: %v\n", err)
}
fmt.Println(i, b, s)
fmt.Println(n)
@@ -38,47 +41,6 @@ func ExampleFscanf() {
// 3
}
-func ExampleSprintf() {
- i := 30
- s := "Aug"
- sf := fmt.Sprintf("Today is %d %s", i, s)
- fmt.Println(sf)
- fmt.Println(len(sf))
- // Output:
- // Today is 30 Aug
- // 15
-}
-
-func ExamplePrintln() {
- n, err := fmt.Println("there", "are", 99, "gophers")
- if err != nil {
- panic(err)
- }
- fmt.Print(n)
- // Output:
- // there are 99 gophers
- // 21
-}
-
-func ExampleSprintln() {
- s := "Aug"
- sl := fmt.Sprintln("Today is 30", s)
- fmt.Printf("%q", sl)
- // Output:
- // "Today is 30 Aug\n"
-}
-
-func ExampleFprintln() {
- n, err := fmt.Fprintln(os.Stdout, "there", "are", 99, "gophers")
- if err != nil {
- panic(err)
- }
- fmt.Print(n)
- // Output:
- // there are 99 gophers
- // 21
-}
-
func ExampleFscanln() {
s := `dmr 1771 1.61803398875
ken 271828 3.14159`
@@ -100,3 +62,292 @@ func ExampleFscanln() {
// 3: dmr, 1771, 1.618034
// 3: ken, 271828, 3.141590
}
+
+func ExamplePrint() {
+ const name, age = "Kim", 22
+ fmt.Print(name, " is ", age, " years old.\n")
+
+ // It is conventional not to worry about any
+ // error returned by Print.
+
+ // Output:
+ // Kim is 22 years old.
+}
+
+func ExamplePrintln() {
+ const name, age = "Kim", 22
+ fmt.Println(name, "is", age, "years old.")
+
+ // It is conventional not to worry about any
+ // error returned by Println.
+
+ // Output:
+ // Kim is 22 years old.
+}
+
+func ExamplePrintf() {
+ const name, age = "Kim", 22
+ fmt.Printf("%s is %d years old.\n", name, age)
+
+ // It is conventional not to worry about any
+ // error returned by Printf.
+
+ // Output:
+ // Kim is 22 years old.
+}
+
+func ExampleSprint() {
+ const name, age = "Kim", 22
+ s := fmt.Sprint(name, " is ", age, " years old.\n")
+
+ io.WriteString(os.Stdout, s) // Ignoring error for simplicity.
+
+ // Output:
+ // Kim is 22 years old.
+}
+
+func ExampleSprintln() {
+ const name, age = "Kim", 22
+ s := fmt.Sprintln(name, "is", age, "years old.")
+
+ io.WriteString(os.Stdout, s) // Ignoring error for simplicity.
+
+ // Output:
+ // Kim is 22 years old.
+}
+
+func ExampleSprintf() {
+ const name, age = "Kim", 22
+ s := fmt.Sprintf("%s is %d years old.\n", name, age)
+
+ io.WriteString(os.Stdout, s) // Ignoring error for simplicity.
+
+ // Output:
+ // Kim is 22 years old.
+}
+
+func ExampleFprint() {
+ const name, age = "Kim", 22
+ n, err := fmt.Fprint(os.Stdout, name, " is ", age, " years old.\n")
+
+ // The n and err return values from Fprint are
+ // those returned by the underlying io.Writer.
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Fprint: %v\n", err)
+ }
+ fmt.Print(n, " bytes written.\n")
+
+ // Output:
+ // Kim is 22 years old.
+ // 21 bytes written.
+}
+
+func ExampleFprintln() {
+ const name, age = "Kim", 22
+ n, err := fmt.Fprintln(os.Stdout, name, "is", age, "years old.")
+
+ // The n and err return values from Fprintln are
+ // those returned by the underlying io.Writer.
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Fprintln: %v\n", err)
+ }
+ fmt.Println(n, "bytes written.")
+
+ // Output:
+ // Kim is 22 years old.
+ // 21 bytes written.
+}
+
+func ExampleFprintf() {
+ const name, age = "Kim", 22
+ n, err := fmt.Fprintf(os.Stdout, "%s is %d years old.\n", name, age)
+
+ // The n and err return values from Fprintf are
+ // those returned by the underlying io.Writer.
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Fprintf: %v\n", err)
+ }
+ fmt.Printf("%d bytes written.\n", n)
+
+ // Output:
+ // Kim is 22 years old.
+ // 21 bytes written.
+}
+
+// Print, Println, and Printf lay out their arguments differently. In this example
+// we can compare their behaviors. Println always adds blanks between the items it
+// prints, while Print adds blanks only between non-string arguments and Printf
+// does exactly what it is told.
+// Sprint, Sprintln, Sprintf, Fprint, Fprintln, and Fprintf behave the same as
+// their corresponding Print, Println, and Printf functions shown here.
+func Example_printers() {
+ a, b := 3.0, 4.0
+ h := math.Hypot(a, b)
+
+ // Print inserts blanks between arguments when neither is a string.
+ // It does not add a newline to the output, so we add one explicitly.
+ fmt.Print("The vector (", a, b, ") has length ", h, ".\n")
+
+ // Println always inserts spaces between its arguments,
+ // so it cannot be used to produce the same output as Print in this case;
+ // its output has extra spaces.
+ // Also, Println always adds a newline to the output.
+ fmt.Println("The vector (", a, b, ") has length", h, ".")
+
+ // Printf provides complete control but is more complex to use.
+ // It does not add a newline to the output, so we add one explicitly
+ // at the end of the format specifier string.
+ fmt.Printf("The vector (%g %g) has length %g.\n", a, b, h)
+
+ // Output:
+ // The vector (3 4) has length 5.
+ // The vector ( 3 4 ) has length 5 .
+ // The vector (3 4) has length 5.
+}
+
+// These examples demonstrate the basics of printing using a format string. Printf,
+// Sprintf, and Fprintf all take a format string that specifies how to format the
+// subsequent arguments. For example, %d (we call that a 'verb') says to print the
+// corresponding argument, which must be an integer (or something containing an
+// integer, such as a slice of ints) in decimal. The verb %v ('v' for 'value')
+// always formats the argument in its default form, just how Print or Println would
+// show it. The special verb %T ('T' for 'Type') prints the type of the argument
+// rather than its value. The examples are not exhaustive; see the package comment
+// for all the details.
+func Example_formats() {
+ // A basic set of examples showing that %v is the default format, in this
+ // case decimal for integers, which can be explicitly requested with %d;
+ // the output is just what Println generates.
+ integer := 23
+ // Each of these prints "23" (without the quotes).
+ fmt.Println(integer)
+ fmt.Printf("%v\n", integer)
+ fmt.Printf("%d\n", integer)
+
+ // The special verb %T shows the type of an item rather than its value.
+ fmt.Printf("%T %T\n", integer, &integer)
+ // Result: int *int
+
+ // Println(x) is the same as Printf("%v\n", x) so we will use only Printf
+ // in the following examples. Each one demonstrates how to format values of
+ // a particular type, such as integers or strings. We start each format
+ // string with %v to show the default output and follow that with one or
+ // more custom formats.
+
+ // Booleans print as "true" or "false" with %v or %t.
+ truth := true
+ fmt.Printf("%v %t\n", truth, truth)
+ // Result: true true
+
+ // Integers print as decimals with %v and %d,
+ // or in hex with %x, octal with %o, or binary with %b.
+ answer := 42
+ fmt.Printf("%v %d %x %o %b\n", answer, answer, answer, answer, answer)
+ // Result: 42 42 2a 52 101010
+
+ // Floats have multiple formats: %v and %g print a compact representation,
+ // while %f prints a decimal point and %e uses exponential notation. The
+ // format %6.2f used here shows how to set the width and precision to
+ // control the appearance of a floating-point value. In this instance, 6 is
+ // the total width of the printed text for the value (note the extra spaces
+ // in the output) and 2 is the number of decimal places to show.
+ pi := math.Pi
+ fmt.Printf("%v %g %.2f (%6.2f) %e\n", pi, pi, pi, pi, pi)
+ // Result: 3.141592653589793 3.141592653589793 3.14 ( 3.14) 3.141593e+00
+
+ // Complex numbers format as parenthesized pairs of floats, with an 'i'
+ // after the imaginary part.
+ point := 110.7 + 22.5i
+ fmt.Printf("%v %g %.2f %.2e\n", point, point, point, point)
+ // Result: (110.7+22.5i) (110.7+22.5i) (110.70+22.50i) (1.11e+02+2.25e+01i)
+
+ // Runes are integers but when printed with %c show the character with that
+ // Unicode value. The %q verb shows them as quoted characters, %U as a
+ // hex Unicode code point, and %#U as both a code point and a quoted
+ // printable form if the rune is printable.
+ smile := '😀'
+ fmt.Printf("%v %d %c %q %U %#U\n", smile, smile, smile, smile, smile, smile)
+ // Result: 128512 128512 😀 '😀' U+1F600 U+1F600 '😀'
+
+ // Strings are formatted with %v and %s as-is, with %q as quoted strings,
+ // and %#q as backquoted strings.
+ placeholders := `foo "bar"`
+ fmt.Printf("%v %s %q %#q\n", placeholders, placeholders, placeholders, placeholders)
+ // Result: foo "bar" foo "bar" "foo \"bar\"" `foo "bar"`
+
+ // Maps formatted with %v show keys and values in their default formats.
+ // The %#v form (the # is called a "flag" in this context) shows the map in
+ // the Go source format.
+ isLegume := map[string]bool{
+ "peanut": true,
+ // TODO: Include this line when maps are printed in deterministic order.
+ // See Issue #21095
+ // "dachshund": false,
+ }
+ fmt.Printf("%v %#v\n", isLegume, isLegume)
+ // Result: map[peanut:true] map[string]bool{"peanut":true}
+
+ // Structs formatted with %v show field values in their default formats.
+ // The %+v form shows the fields by name, while %#v formats the struct in
+ // Go source format.
+ person := struct {
+ Name string
+ Age int
+ }{"Kim", 22}
+ fmt.Printf("%v %+v %#v\n", person, person, person)
+ // Result: {Kim 22} {Name:Kim Age:22} struct { Name string; Age int }{Name:"Kim", Age:22}
+
+ // The default format for a pointer shows the underlying value preceded by
+ // an ampersand. The %p verb prints the pointer value in hex. We use a
+ // typed nil for the argument to %p here because the value of any non-nil
+ // pointer would change from run to run; run the commented-out Printf
+ // call yourself to see.
+ pointer := &person
+ fmt.Printf("%v %p\n", pointer, (*int)(nil))
+ // Result: &{Kim 22} 0x0
+ // fmt.Printf("%v %p\n", pointer, pointer)
+ // Result: &{Kim 22} 0x010203 // See comment above.
+
+ // Arrays and slices are formatted by applying the format to each element.
+ greats := [5]string{"Katano", "Kobayashi", "Kurosawa", "Miyazaki", "Ozu"}
+ fmt.Printf("%v %q\n", greats, greats)
+ // Result: [Katano Kobayashi Kurosawa Miyazaki Ozu] ["Katano" "Kobayashi" "Kurosawa" "Miyazaki" "Ozu"]
+
+ kGreats := greats[:3]
+ fmt.Printf("%v %q %#v\n", kGreats, kGreats, kGreats)
+ // Result: [Katano Kobayashi Kurosawa] ["Katano" "Kobayashi" "Kurosawa"] []string{"Katano", "Kobayashi", "Kurosawa"}
+
+ // Byte slices are special. Integer verbs like %d print the elements in
+ // that format. The %s and %q forms treat the slice like a string. The %x
+ // verb has a special form with the space flag that puts a space between
+ // the bytes.
+ cmd := []byte("a⌘")
+ fmt.Printf("%v %d %s %q %x % x\n", cmd, cmd, cmd, cmd, cmd, cmd)
+ // Result: [97 226 140 152] [97 226 140 152] a⌘ "a⌘" 61e28c98 61 e2 8c 98
+
+ // Types that implement Stringer are printed the same as strings. Because
+ // Stringers return a string, we can print them using a string-specific
+ // verb such as %q.
+ now := time.Unix(123456789, 0).UTC() // time.Time implements fmt.Stringer.
+ fmt.Printf("%v %q\n", now, now)
+ // Result: 1973-11-29 21:33:09 +0000 UTC "1973-11-29 21:33:09 +0000 UTC"
+
+ // Output:
+ // 23
+ // 23
+ // 23
+ // int *int
+ // true true
+ // 42 42 2a 52 101010
+ // 3.141592653589793 3.141592653589793 3.14 ( 3.14) 3.141593e+00
+ // (110.7+22.5i) (110.7+22.5i) (110.70+22.50i) (1.11e+02+2.25e+01i)
+ // 128512 128512 😀 '😀' U+1F600 U+1F600 '😀'
+ // foo "bar" foo "bar" "foo \"bar\"" `foo "bar"`
+ // map[peanut:true] map[string]bool{"peanut":true}
+ // {Kim 22} {Name:Kim Age:22} struct { Name string; Age int }{Name:"Kim", Age:22}
+ // &{Kim 22} 0x0
+ // [Katano Kobayashi Kurosawa Miyazaki Ozu] ["Katano" "Kobayashi" "Kurosawa" "Miyazaki" "Ozu"]
+ // [Katano Kobayashi Kurosawa] ["Katano" "Kobayashi" "Kurosawa"] []string{"Katano", "Kobayashi", "Kurosawa"}
+ // [97 226 140 152] [97 226 140 152] a⌘ "a⌘" 61e28c98 61 e2 8c 98
+ // 1973-11-29 21:33:09 +0000 UTC "1973-11-29 21:33:09 +0000 UTC"
+}
diff --git a/src/fmt/fmt_test.go b/src/fmt/fmt_test.go
index 9581becd32..d63271a805 100644
--- a/src/fmt/fmt_test.go
+++ b/src/fmt/fmt_test.go
@@ -131,15 +131,10 @@ func (byteFormatter) Format(f State, _ rune) {
var byteFormatterSlice = []byteFormatter{'h', 'e', 'l', 'l', 'o'}
-// Copy of io.stringWriter interface used by writeStringFormatter for type assertion.
-type stringWriter interface {
- WriteString(s string) (n int, err error)
-}
-
type writeStringFormatter string
func (sf writeStringFormatter) Format(f State, c rune) {
- if sw, ok := f.(stringWriter); ok {
+ if sw, ok := f.(io.StringWriter); ok {
sw.WriteString("***" + string(sf) + "***")
}
}
diff --git a/src/fmt/print.go b/src/fmt/print.go
index c9d694b07d..32743d0712 100644
--- a/src/fmt/print.go
+++ b/src/fmt/print.go
@@ -139,6 +139,16 @@ func newPrinter() *pp {
// free saves used pp structs in ppFree; avoids an allocation per invocation.
func (p *pp) free() {
+ // Proper usage of a sync.Pool requires each entry to have approximately
+ // the same memory cost. To obtain this property when the stored type
+ // contains a variably-sized buffer, we add a hard limit on the maximum buffer
+ // to place back in the pool.
+ //
+ // See https://golang.org/issue/23199
+ if cap(p.buf) > 64<<10 {
+ return
+ }
+
p.buf = p.buf[:0]
p.arg = nil
p.value = reflect.Value{}
diff --git a/src/go/build/build.go b/src/go/build/build.go
index b68a712a7d..fc8d37789f 100644
--- a/src/go/build/build.go
+++ b/src/go/build/build.go
@@ -12,6 +12,7 @@ import (
"go/doc"
"go/parser"
"go/token"
+ "internal/goroot"
"io"
"io/ioutil"
"log"
@@ -543,7 +544,7 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa
inTestdata := func(sub string) bool {
return strings.Contains(sub, "/testdata/") || strings.HasSuffix(sub, "/testdata") || strings.HasPrefix(sub, "testdata/") || sub == "testdata"
}
- if ctxt.GOROOT != "" && ctxt.Compiler != "gccgo" {
+ if ctxt.GOROOT != "" {
root := ctxt.joinPath(ctxt.GOROOT, "src")
if sub, ok := ctxt.hasSubdir(root, p.Dir); ok && !inTestdata(sub) {
p.Goroot = true
@@ -656,7 +657,7 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa
}
tried.goroot = dir
}
- if ctxt.Compiler == "gccgo" && isStandardPackage(path) {
+ if ctxt.Compiler == "gccgo" && goroot.IsStandardPackage(ctxt.GOROOT, ctxt.Compiler, path) {
p.Dir = ctxt.joinPath(ctxt.GOROOT, "src", path)
p.Goroot = true
p.Root = ctxt.GOROOT
@@ -714,6 +715,11 @@ Found:
// non-nil *Package returned when an error occurs.
// We need to do this before we return early on FindOnly flag.
if IsLocalImport(path) && !ctxt.isDir(p.Dir) {
+ if ctxt.Compiler == "gccgo" && p.Goroot {
+ // gccgo has no sources for GOROOT packages.
+ return p, nil
+ }
+
// package was not found
return p, fmt.Errorf("cannot find package %q in:\n\t%s", path, p.Dir)
}
diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go
index f0e584585b..c15706fb6b 100644
--- a/src/go/build/deps_test.go
+++ b/src/go/build/deps_test.go
@@ -265,7 +265,7 @@ var pkgDeps = map[string][]string{
"encoding/pem": {"L4"},
"encoding/xml": {"L4", "encoding"},
"flag": {"L4", "OS"},
- "go/build": {"L4", "OS", "GOPARSER"},
+ "go/build": {"L4", "OS", "GOPARSER", "internal/goroot"},
"html": {"L4"},
"image/draw": {"L4", "image/internal/imageutil"},
"image/gif": {"L4", "compress/lzw", "image/color/palette", "image/draw"},
@@ -273,6 +273,7 @@ var pkgDeps = map[string][]string{
"image/jpeg": {"L4", "image/internal/imageutil"},
"image/png": {"L4", "compress/zlib"},
"index/suffixarray": {"L4", "regexp"},
+ "internal/goroot": {"L4", "OS"},
"internal/singleflight": {"sync"},
"internal/trace": {"L4", "OS"},
"math/big": {"L4"},
diff --git a/src/go/build/doc.go b/src/go/build/doc.go
index 69613e359c..d803b8967b 100644
--- a/src/go/build/doc.go
+++ b/src/go/build/doc.go
@@ -110,6 +110,9 @@
// - "go1.11", from Go version 1.11 onward
// - any additional words listed in ctxt.BuildTags
//
+// There are no build tags for beta or minor releases. Programs that need the
+// minor release number can call runtime.Version.
+//
// If a file's name, after stripping the extension and a possible _test suffix,
// matches any of the following patterns:
// *_GOOS
diff --git a/src/go/build/gc.go b/src/go/build/gc.go
index e2be2cbb1d..3025cd5681 100644
--- a/src/go/build/gc.go
+++ b/src/go/build/gc.go
@@ -7,131 +7,11 @@
package build
import (
- "os"
- "os/exec"
"path/filepath"
"runtime"
- "strings"
- "sync"
)
// getToolDir returns the default value of ToolDir.
func getToolDir() string {
return filepath.Join(runtime.GOROOT(), "pkg/tool/"+runtime.GOOS+"_"+runtime.GOARCH)
}
-
-// isStandardPackage is not used for the gc toolchain.
-// However, this function may be called when using `go build -compiler=gccgo`.
-func isStandardPackage(path string) bool {
- return gccgoSearch.isStandard(path)
-}
-
-// gccgoSearch holds the gccgo search directories.
-type gccgoDirs struct {
- once sync.Once
- dirs []string
-}
-
-// gccgoSearch is used to check whether a gccgo package exists in the
-// standard library.
-var gccgoSearch gccgoDirs
-
-// init finds the gccgo search directories. If this fails it leaves dirs == nil.
-func (gd *gccgoDirs) init() {
- gccgo := os.Getenv("GCCGO")
- if gccgo == "" {
- gccgo = "gccgo"
- }
- bin, err := exec.LookPath(gccgo)
- if err != nil {
- return
- }
-
- allDirs, err := exec.Command(bin, "-print-search-dirs").Output()
- if err != nil {
- return
- }
- versionB, err := exec.Command(bin, "-dumpversion").Output()
- if err != nil {
- return
- }
- version := strings.TrimSpace(string(versionB))
- machineB, err := exec.Command(bin, "-dumpmachine").Output()
- if err != nil {
- return
- }
- machine := strings.TrimSpace(string(machineB))
-
- dirsEntries := strings.Split(string(allDirs), "\n")
- const prefix = "libraries: ="
- var dirs []string
- for _, dirEntry := range dirsEntries {
- if strings.HasPrefix(dirEntry, prefix) {
- dirs = filepath.SplitList(strings.TrimPrefix(dirEntry, prefix))
- break
- }
- }
- if len(dirs) == 0 {
- return
- }
-
- var lastDirs []string
- for _, dir := range dirs {
- goDir := filepath.Join(dir, "go", version)
- if fi, err := os.Stat(goDir); err == nil && fi.IsDir() {
- gd.dirs = append(gd.dirs, goDir)
- goDir = filepath.Join(goDir, machine)
- if fi, err = os.Stat(goDir); err == nil && fi.IsDir() {
- gd.dirs = append(gd.dirs, goDir)
- }
- }
- if fi, err := os.Stat(dir); err == nil && fi.IsDir() {
- lastDirs = append(lastDirs, dir)
- }
- }
- gd.dirs = append(gd.dirs, lastDirs...)
-}
-
-// isStandard returns whether path is a standard library for gccgo.
-func (gd *gccgoDirs) isStandard(path string) bool {
- // Quick check: if the first path component has a '.', it's not
- // in the standard library. This skips most GOPATH directories.
- i := strings.Index(path, "/")
- if i < 0 {
- i = len(path)
- }
- if strings.Contains(path[:i], ".") {
- return false
- }
-
- if path == "unsafe" {
- // Special case.
- return true
- }
-
- gd.once.Do(gd.init)
- if gd.dirs == nil {
- // We couldn't find the gccgo search directories.
- // Best guess, since the first component did not contain
- // '.', is that this is a standard library package.
- return true
- }
-
- for _, dir := range gd.dirs {
- full := filepath.Join(dir, path)
- pkgdir, pkg := filepath.Split(full)
- for _, p := range [...]string{
- full,
- full + ".gox",
- pkgdir + "lib" + pkg + ".so",
- pkgdir + "lib" + pkg + ".a",
- full + ".o",
- } {
- if fi, err := os.Stat(p); err == nil && !fi.IsDir() {
- return true
- }
- }
- }
-
- return false
-}
diff --git a/src/go/build/gccgo.go b/src/go/build/gccgo.go
index 59e089d69d..c6aac9aa1b 100644
--- a/src/go/build/gccgo.go
+++ b/src/go/build/gccgo.go
@@ -12,9 +12,3 @@ import "runtime"
func getToolDir() string {
return envOr("GCCGOTOOLDIR", runtime.GCCGOTOOLDIR)
}
-
-// isStandardPackage returns whether path names a standard library package.
-// This uses a list generated at build time.
-func isStandardPackage(path string) bool {
- return stdpkg[path]
-}
diff --git a/src/go/build/syslist.go b/src/go/build/syslist.go
index d7938fad54..597212b6d0 100644
--- a/src/go/build/syslist.go
+++ b/src/go/build/syslist.go
@@ -4,5 +4,5 @@
package build
-const goosList = "android darwin dragonfly freebsd js linux nacl netbsd openbsd plan9 solaris windows zos "
+const goosList = "aix android darwin dragonfly freebsd js linux nacl netbsd openbsd plan9 solaris windows zos "
const goarchList = "386 amd64 amd64p32 arm armbe arm64 arm64be ppc64 ppc64le mips mipsle mips64 mips64le mips64p32 mips64p32le ppc riscv riscv64 s390 s390x sparc sparc64 wasm "
diff --git a/src/go/constant/value_test.go b/src/go/constant/value_test.go
index e6fca76e18..68b87eaa55 100644
--- a/src/go/constant/value_test.go
+++ b/src/go/constant/value_test.go
@@ -296,7 +296,7 @@ func val(lit string) Value {
switch first, last := lit[0], lit[len(lit)-1]; {
case first == '"' || first == '`':
tok = token.STRING
- lit = strings.Replace(lit, "_", " ", -1)
+ lit = strings.ReplaceAll(lit, "_", " ")
case first == '\'':
tok = token.CHAR
case last == 'i':
diff --git a/src/go/doc/doc_test.go b/src/go/doc/doc_test.go
index 902a79f63f..0b2d2b63cc 100644
--- a/src/go/doc/doc_test.go
+++ b/src/go/doc/doc_test.go
@@ -40,7 +40,7 @@ func readTemplate(filename string) *template.Template {
func nodeFmt(node interface{}, fset *token.FileSet) string {
var buf bytes.Buffer
printer.Fprint(&buf, fset, node)
- return strings.Replace(strings.TrimSpace(buf.String()), "\n", "\n\t", -1)
+ return strings.ReplaceAll(strings.TrimSpace(buf.String()), "\n", "\n\t")
}
func synopsisFmt(s string) string {
@@ -53,7 +53,7 @@ func synopsisFmt(s string) string {
}
s = strings.TrimSpace(s) + " ..."
}
- return "// " + strings.Replace(s, "\n", " ", -1)
+ return "// " + strings.ReplaceAll(s, "\n", " ")
}
func indentFmt(indent, s string) string {
@@ -62,7 +62,7 @@ func indentFmt(indent, s string) string {
end = "\n"
s = s[:len(s)-1]
}
- return indent + strings.Replace(s, "\n", "\n"+indent, -1) + end
+ return indent + strings.ReplaceAll(s, "\n", "\n"+indent) + end
}
func isGoFile(fi os.FileInfo) bool {
diff --git a/src/go/internal/gccgoimporter/importer_test.go b/src/go/internal/gccgoimporter/importer_test.go
index 5a699687bd..15494fd6b3 100644
--- a/src/go/internal/gccgoimporter/importer_test.go
+++ b/src/go/internal/gccgoimporter/importer_test.go
@@ -102,8 +102,10 @@ var importerTests = [...]importerTest{
{pkgpath: "unicode", name: "MaxRune", want: "const MaxRune untyped rune", wantval: "1114111"},
{pkgpath: "imports", wantinits: []string{"imports..import", "fmt..import", "math..import"}},
{pkgpath: "importsar", name: "Hello", want: "var Hello string"},
- {pkgpath: "alias", name: "IntAlias2", want: "type IntAlias2 = Int"},
+ {pkgpath: "aliases", name: "A14", want: "type A14 = func(int, T0) chan T2"},
+ {pkgpath: "aliases", name: "C0", want: "type C0 struct{f1 C1; f2 C1}"},
{pkgpath: "escapeinfo", name: "NewT", want: "func NewT(data []byte) *T"},
+ {pkgpath: "issue27856", name: "M", want: "type M struct{E F}"},
}
func TestGoxImporter(t *testing.T) {
diff --git a/src/go/internal/gccgoimporter/parser.go b/src/go/internal/gccgoimporter/parser.go
index 9f8c19b638..9a94c3369e 100644
--- a/src/go/internal/gccgoimporter/parser.go
+++ b/src/go/internal/gccgoimporter/parser.go
@@ -26,7 +26,7 @@ type parser struct {
pkgname string // name of imported package
pkg *types.Package // reference to imported package
imports map[string]*types.Package // package path -> package object
- typeMap map[int]types.Type // type number -> type
+ typeList []types.Type // type number -> type
initdata InitData // package init priority data
}
@@ -38,7 +38,7 @@ func (p *parser) init(filename string, src io.Reader, imports map[string]*types.
p.scanner.Filename = filename // for good error messages
p.next()
p.imports = imports
- p.typeMap = make(map[int]types.Type)
+ p.typeList = make([]types.Type, 1 /* type numbers start at 1 */, 16)
}
type importError struct {
@@ -378,52 +378,80 @@ func (p *parser) parseConst(pkg *types.Package) *types.Const {
return types.NewConst(token.NoPos, pkg, name, typ, val)
}
+// reserved is a singleton type used to fill type map slots that have
+// been reserved (i.e., for which a type number has been parsed) but
+// which don't have their actual type yet. When the type map is updated,
+// the actual type must replace a reserved entry (or we have an internal
+// error). Used for self-verification only - not required for correctness.
+var reserved = new(struct{ types.Type })
+
+// reserve reserves the type map entry n for future use.
+func (p *parser) reserve(n int) {
+ if n != len(p.typeList) {
+ p.errorf("invalid type number %d (out of sync)", n)
+ }
+ p.typeList = append(p.typeList, reserved)
+}
+
+// update sets the type map entries for the given type numbers nlist to t.
+func (p *parser) update(t types.Type, nlist []int) {
+ for _, n := range nlist {
+ if p.typeList[n] != reserved {
+ p.errorf("typeMap[%d] not reserved", n)
+ }
+ p.typeList[n] = t
+ }
+}
+
// NamedType = TypeName [ "=" ] Type { Method } .
// TypeName = ExportedName .
// Method = "func" "(" Param ")" Name ParamList ResultList ";" .
-func (p *parser) parseNamedType(n int) types.Type {
+func (p *parser) parseNamedType(nlist []int) types.Type {
pkg, name := p.parseExportedName()
scope := pkg.Scope()
+ obj := scope.Lookup(name)
+ if obj != nil && obj.Type() == nil {
+ p.errorf("%v has nil type", obj)
+ }
+ // type alias
if p.tok == '=' {
- // type alias
p.next()
- typ := p.parseType(pkg)
- if obj := scope.Lookup(name); obj != nil {
- typ = obj.Type() // use previously imported type
- if typ == nil {
- p.errorf("%v (type alias) used in cycle", obj)
- }
- } else {
- obj = types.NewTypeName(token.NoPos, pkg, name, typ)
- scope.Insert(obj)
+ if obj != nil {
+ // use the previously imported (canonical) type
+ t := obj.Type()
+ p.update(t, nlist)
+ p.parseType(pkg) // discard
+ return t
}
- p.typeMap[n] = typ
- return typ
+ t := p.parseType(pkg, nlist...)
+ obj = types.NewTypeName(token.NoPos, pkg, name, t)
+ scope.Insert(obj)
+ return t
}
- // named type
- obj := scope.Lookup(name)
+ // defined type
if obj == nil {
- // a named type may be referred to before the underlying type
- // is known - set it up
+ // A named type may be referred to before the underlying type
+ // is known - set it up.
tname := types.NewTypeName(token.NoPos, pkg, name, nil)
types.NewNamed(tname, nil, nil)
scope.Insert(tname)
obj = tname
}
- typ := obj.Type()
- p.typeMap[n] = typ
+ // use the previously imported (canonical), or newly created type
+ t := obj.Type()
+ p.update(t, nlist)
- nt, ok := typ.(*types.Named)
+ nt, ok := t.(*types.Named)
if !ok {
// This can happen for unsafe.Pointer, which is a TypeName holding a Basic type.
pt := p.parseType(pkg)
- if pt != typ {
+ if pt != t {
p.error("unexpected underlying type for non-named TypeName")
}
- return typ
+ return t
}
underlying := p.parseType(pkg)
@@ -449,41 +477,70 @@ func (p *parser) parseNamedType(n int) types.Type {
return nt
}
-func (p *parser) parseInt() int64 {
+func (p *parser) parseInt64() int64 {
lit := p.expect(scanner.Int)
- n, err := strconv.ParseInt(lit, 10, 0)
+ n, err := strconv.ParseInt(lit, 10, 64)
if err != nil {
p.error(err)
}
return n
}
+func (p *parser) parseInt() int {
+ lit := p.expect(scanner.Int)
+ n, err := strconv.ParseInt(lit, 10, 0 /* int */)
+ if err != nil {
+ p.error(err)
+ }
+ return int(n)
+}
+
// ArrayOrSliceType = "[" [ int ] "]" Type .
-func (p *parser) parseArrayOrSliceType(pkg *types.Package) types.Type {
+func (p *parser) parseArrayOrSliceType(pkg *types.Package, nlist []int) types.Type {
p.expect('[')
if p.tok == ']' {
p.next()
- return types.NewSlice(p.parseType(pkg))
+
+ t := new(types.Slice)
+ p.update(t, nlist)
+
+ *t = *types.NewSlice(p.parseType(pkg))
+ return t
}
- n := p.parseInt()
+ t := new(types.Array)
+ p.update(t, nlist)
+
+ len := p.parseInt64()
p.expect(']')
- return types.NewArray(p.parseType(pkg), n)
+
+ *t = *types.NewArray(p.parseType(pkg), len)
+ return t
}
// MapType = "map" "[" Type "]" Type .
-func (p *parser) parseMapType(pkg *types.Package) types.Type {
+func (p *parser) parseMapType(pkg *types.Package, nlist []int) types.Type {
p.expectKeyword("map")
+
+ t := new(types.Map)
+ p.update(t, nlist)
+
p.expect('[')
key := p.parseType(pkg)
p.expect(']')
elem := p.parseType(pkg)
- return types.NewMap(key, elem)
+
+ *t = *types.NewMap(key, elem)
+ return t
}
// ChanType = "chan" ["<-" | "-<"] Type .
-func (p *parser) parseChanType(pkg *types.Package) types.Type {
+func (p *parser) parseChanType(pkg *types.Package, nlist []int) types.Type {
p.expectKeyword("chan")
+
+ t := new(types.Chan)
+ p.update(t, nlist)
+
dir := types.SendRecv
switch p.tok {
case '-':
@@ -500,13 +557,17 @@ func (p *parser) parseChanType(pkg *types.Package) types.Type {
}
}
- return types.NewChan(dir, p.parseType(pkg))
+ *t = *types.NewChan(dir, p.parseType(pkg))
+ return t
}
// StructType = "struct" "{" { Field } "}" .
-func (p *parser) parseStructType(pkg *types.Package) types.Type {
+func (p *parser) parseStructType(pkg *types.Package, nlist []int) types.Type {
p.expectKeyword("struct")
+ t := new(types.Struct)
+ p.update(t, nlist)
+
var fields []*types.Var
var tags []string
@@ -519,7 +580,8 @@ func (p *parser) parseStructType(pkg *types.Package) types.Type {
}
p.expect('}')
- return types.NewStruct(fields, tags)
+ *t = *types.NewStruct(fields, tags)
+ return t
}
// ParamList = "(" [ { Parameter "," } Parameter ] ")" .
@@ -562,10 +624,15 @@ func (p *parser) parseResultList(pkg *types.Package) *types.Tuple {
}
// FunctionType = ParamList ResultList .
-func (p *parser) parseFunctionType(pkg *types.Package) *types.Signature {
+func (p *parser) parseFunctionType(pkg *types.Package, nlist []int) *types.Signature {
+ t := new(types.Signature)
+ p.update(t, nlist)
+
params, isVariadic := p.parseParamList(pkg)
results := p.parseResultList(pkg)
- return types.NewSignature(nil, params, results, isVariadic)
+
+ *t = *types.NewSignature(nil, params, results, isVariadic)
+ return t
}
// Func = Name FunctionType .
@@ -577,13 +644,16 @@ func (p *parser) parseFunc(pkg *types.Package) *types.Func {
p.discardDirectiveWhileParsingTypes(pkg)
return nil
}
- return types.NewFunc(token.NoPos, pkg, name, p.parseFunctionType(pkg))
+ return types.NewFunc(token.NoPos, pkg, name, p.parseFunctionType(pkg, nil))
}
// InterfaceType = "interface" "{" { ("?" Type | Func) ";" } "}" .
-func (p *parser) parseInterfaceType(pkg *types.Package) types.Type {
+func (p *parser) parseInterfaceType(pkg *types.Package, nlist []int) types.Type {
p.expectKeyword("interface")
+ t := new(types.Interface)
+ p.update(t, nlist)
+
var methods []*types.Func
var embeddeds []types.Type
@@ -600,53 +670,61 @@ func (p *parser) parseInterfaceType(pkg *types.Package) types.Type {
}
p.expect('}')
- return types.NewInterfaceType(methods, embeddeds)
+ *t = *types.NewInterfaceType(methods, embeddeds)
+ return t
}
// PointerType = "*" ("any" | Type) .
-func (p *parser) parsePointerType(pkg *types.Package) types.Type {
+func (p *parser) parsePointerType(pkg *types.Package, nlist []int) types.Type {
p.expect('*')
if p.tok == scanner.Ident {
p.expectKeyword("any")
- return types.Typ[types.UnsafePointer]
+ t := types.Typ[types.UnsafePointer]
+ p.update(t, nlist)
+ return t
}
- return types.NewPointer(p.parseType(pkg))
+
+ t := new(types.Pointer)
+ p.update(t, nlist)
+
+ *t = *types.NewPointer(p.parseType(pkg))
+
+ return t
}
-// TypeDefinition = NamedType | MapType | ChanType | StructType | InterfaceType | PointerType | ArrayOrSliceType | FunctionType .
-func (p *parser) parseTypeDefinition(pkg *types.Package, n int) types.Type {
- var t types.Type
+// TypeSpec = NamedType | MapType | ChanType | StructType | InterfaceType | PointerType | ArrayOrSliceType | FunctionType .
+func (p *parser) parseTypeSpec(pkg *types.Package, nlist []int) types.Type {
switch p.tok {
case scanner.String:
- t = p.parseNamedType(n)
+ return p.parseNamedType(nlist)
case scanner.Ident:
switch p.lit {
case "map":
- t = p.parseMapType(pkg)
+ return p.parseMapType(pkg, nlist)
case "chan":
- t = p.parseChanType(pkg)
+ return p.parseChanType(pkg, nlist)
case "struct":
- t = p.parseStructType(pkg)
+ return p.parseStructType(pkg, nlist)
case "interface":
- t = p.parseInterfaceType(pkg)
+ return p.parseInterfaceType(pkg, nlist)
}
case '*':
- t = p.parsePointerType(pkg)
+ return p.parsePointerType(pkg, nlist)
case '[':
- t = p.parseArrayOrSliceType(pkg)
+ return p.parseArrayOrSliceType(pkg, nlist)
case '(':
- t = p.parseFunctionType(pkg)
+ return p.parseFunctionType(pkg, nlist)
}
- p.typeMap[n] = t
- return t
+ p.errorf("expected type name or literal, got %s", scanner.TokenString(p.tok))
+ return nil
}
const (
@@ -700,29 +778,36 @@ func lookupBuiltinType(typ int) types.Type {
}[typ]
}
-// Type = "<" "type" ( "-" int | int [ TypeDefinition ] ) ">" .
-func (p *parser) parseType(pkg *types.Package) (t types.Type) {
+// Type = "<" "type" ( "-" int | int [ TypeSpec ] ) ">" .
+//
+// parseType updates the type map to t for all type numbers n.
+//
+func (p *parser) parseType(pkg *types.Package, n ...int) (t types.Type) {
p.expect('<')
p.expectKeyword("type")
switch p.tok {
case scanner.Int:
- n := p.parseInt()
-
+ n1 := p.parseInt()
if p.tok == '>' {
- t = p.typeMap[int(n)]
+ t = p.typeList[n1]
+ if t == reserved {
+ p.errorf("invalid type cycle, type %d not yet defined", n1)
+ }
+ p.update(t, n)
} else {
- t = p.parseTypeDefinition(pkg, int(n))
+ p.reserve(n1)
+ t = p.parseTypeSpec(pkg, append(n, n1))
}
case '-':
p.next()
- n := p.parseInt()
- t = lookupBuiltinType(int(n))
+ n1 := p.parseInt()
+ t = lookupBuiltinType(n1)
+ p.update(t, n)
default:
p.errorf("expected type number, got %s (%q)", scanner.TokenString(p.tok), p.lit)
- return nil
}
p.expect('>')
@@ -735,7 +820,7 @@ func (p *parser) parsePackageInit() PackageInit {
initfunc := p.parseUnquotedString()
priority := -1
if p.version == "v1" {
- priority = int(p.parseInt())
+ priority = p.parseInt()
}
return PackageInit{Name: name, InitFunc: initfunc, Priority: priority}
}
@@ -781,7 +866,7 @@ func (p *parser) parseInitDataDirective() {
case "priority":
p.next()
- p.initdata.Priority = int(p.parseInt())
+ p.initdata.Priority = p.parseInt()
p.expect(';')
case "init":
@@ -795,8 +880,8 @@ func (p *parser) parseInitDataDirective() {
p.next()
// The graph data is thrown away for now.
for p.tok != ';' && p.tok != scanner.EOF {
- p.parseInt()
- p.parseInt()
+ p.parseInt64()
+ p.parseInt64()
}
p.expect(';')
@@ -898,7 +983,7 @@ func (p *parser) parsePackage() *types.Package {
for p.tok != scanner.EOF {
p.parseDirective()
}
- for _, typ := range p.typeMap {
+ for _, typ := range p.typeList {
if it, ok := typ.(*types.Interface); ok {
it.Complete()
}
diff --git a/src/go/internal/gccgoimporter/testdata/alias.gox b/src/go/internal/gccgoimporter/testdata/alias.gox
deleted file mode 100644
index ced7d84c4f..0000000000
--- a/src/go/internal/gccgoimporter/testdata/alias.gox
+++ /dev/null
@@ -1,4 +0,0 @@
-v1;
-package alias;
-pkgpath alias;
-type <type 115 "I1" <type 116 interface { M1 (? <type 117 "IntAlias2" = <type 118 "IntAlias" = <type 119 "Int" <type -11>>>>) < type 114>; M2 () <type 1>; }>>;
diff --git a/src/go/internal/gccgoimporter/testdata/aliases.go b/src/go/internal/gccgoimporter/testdata/aliases.go
new file mode 100644
index 0000000000..cfb59b3e31
--- /dev/null
+++ b/src/go/internal/gccgoimporter/testdata/aliases.go
@@ -0,0 +1,65 @@
+package aliases
+
+type (
+ T0 [10]int
+ T1 []byte
+ T2 struct {
+ x int
+ }
+ T3 interface {
+ m() T2
+ }
+ T4 func(int, T0) chan T2
+)
+
+// basic aliases
+type (
+ Ai = int
+ A0 = T0
+ A1 = T1
+ A2 = T2
+ A3 = T3
+ A4 = T4
+
+ A10 = [10]int
+ A11 = []byte
+ A12 = struct {
+ x int
+ }
+ A13 = interface {
+ m() A2
+ }
+ A14 = func(int, A0) chan A2
+)
+
+// alias receiver types
+func (T0) m1() {}
+func (A0) m2() {}
+
+// alias receiver types (long type declaration chains)
+type (
+ V0 = V1
+ V1 = (V2)
+ V2 = (V3)
+ V3 = T0
+)
+
+func (V1) n() {}
+
+// cycles
+type C0 struct {
+ f1 C1
+ f2 C2
+}
+
+type (
+ C1 *C0
+ C2 = C1
+)
+
+type (
+ C5 struct {
+ f *C6
+ }
+ C6 = C5
+)
diff --git a/src/go/internal/gccgoimporter/testdata/aliases.gox b/src/go/internal/gccgoimporter/testdata/aliases.gox
new file mode 100644
index 0000000000..2428c06874
--- /dev/null
+++ b/src/go/internal/gccgoimporter/testdata/aliases.gox
@@ -0,0 +1,33 @@
+v2;
+package aliases;
+prefix go;
+package aliases go.aliases go.aliases;
+type <type 1 "A0" = <type 2 "T0" <type 3 [10 ] <type -11>>
+ func (? <esc:0x1> <type 2>) .go.aliases.m1 ();
+ func (? <esc:0x1> <type 1>) .go.aliases.m2 ();
+ func (? <esc:0x1> <type 4 "V1" = <type 5 "V2" = <type 6 "V3" = <type 2>>>>) .go.aliases.n ();
+>>;
+type <type 7 "A1" = <type 8 "T1" <type 9 [] <type -20>>>>;
+type <type 10 "A10" = <type 11 [10 ] <type -11>>>;
+type <type 12 "A11" = <type 13 [] <type -20>>>;
+type <type 14 "A12" = <type 15 struct { .go.aliases.x <type -11>; }>>;
+type <type 16 "A13" = <type 17 interface { .go.aliases.m () <type 18 "A2" = <type 19 "T2" <type 20 struct { .go.aliases.x <type -11>; }>>>; }>>;
+type <type 21 "A14" = <type 22 (? <type -11>, ? <type 1>) <type 23 chan <type 18>>>>;
+type <type 18>;
+type <type 24 "A3" = <type 25 "T3" <type 26 interface { .go.aliases.m () <type 19>; }>>>;
+type <type 27 "A4" = <type 28 "T4" <type 29 (? <type -11>, ? <type 2>) <type 30 chan <type 19>>>>>;
+type <type 31 "Ai" = <type -11>>;
+type <type 32 "C0" <type 33 struct { .go.aliases.f1 <type 34 "C1" <type 35 *<type 32>>>; .go.aliases.f2 <type 36 "C2" = <type 34>>; }>>;
+type <type 34>;
+type <type 36>;
+type <type 37 "C5" <type 38 struct { .go.aliases.f <type 39 *<type 40 "C6" = <type 37>>>; }>>;
+type <type 40>;
+type <type 2>;
+type <type 8>;
+type <type 19>;
+type <type 25>;
+type <type 28>;
+type <type 41 "V0" = <type 4>>;
+type <type 4>;
+type <type 5>;
+type <type 6>;
diff --git a/src/go/internal/gccgoimporter/testdata/issue27856.go b/src/go/internal/gccgoimporter/testdata/issue27856.go
new file mode 100644
index 0000000000..bf361e1cd8
--- /dev/null
+++ b/src/go/internal/gccgoimporter/testdata/issue27856.go
@@ -0,0 +1,9 @@
+package lib
+
+type M struct {
+ E E
+}
+type F struct {
+ _ *M
+}
+type E = F
diff --git a/src/go/internal/gccgoimporter/testdata/issue27856.gox b/src/go/internal/gccgoimporter/testdata/issue27856.gox
new file mode 100644
index 0000000000..6665e64021
--- /dev/null
+++ b/src/go/internal/gccgoimporter/testdata/issue27856.gox
@@ -0,0 +1,9 @@
+v2;
+package main;
+pkgpath main;
+import runtime runtime "runtime";
+init runtime runtime..import sys runtime_internal_sys..import;
+init_graph 0 1;
+type <type 1 "E" = <type 2 "F" <type 3 struct { .main._ <type 4 *<type 5 "M" <type 6 struct { E <type 1>; }>>>; }>>>;
+type <type 2>;
+type <type 5>;
diff --git a/src/go/printer/example_test.go b/src/go/printer/example_test.go
index e570040ba1..30816931a8 100644
--- a/src/go/printer/example_test.go
+++ b/src/go/printer/example_test.go
@@ -48,7 +48,7 @@ func ExampleFprint() {
// and trim leading and trailing white space.
s := buf.String()
s = s[1 : len(s)-1]
- s = strings.TrimSpace(strings.Replace(s, "\n\t", "\n", -1))
+ s = strings.TrimSpace(strings.ReplaceAll(s, "\n\t", "\n"))
// Print the cleaned-up body text to stdout.
fmt.Println(s)
@@ -61,7 +61,7 @@ func ExampleFprint() {
//
// s := buf.String()
// s = s[1 : len(s)-1]
- // s = strings.TrimSpace(strings.Replace(s, "\n\t", "\n", -1))
+ // s = strings.TrimSpace(strings.ReplaceAll(s, "\n\t", "\n"))
//
// fmt.Println(s)
}
diff --git a/src/go/token/position.go b/src/go/token/position.go
index 241133fe26..3f5a390078 100644
--- a/src/go/token/position.go
+++ b/src/go/token/position.go
@@ -146,7 +146,7 @@ func (f *File) AddLine(offset int) {
// MergeLine will panic if given an invalid line number.
//
func (f *File) MergeLine(line int) {
- if line <= 0 {
+ if line < 1 {
panic("illegal line number (line numbering starts at 1)")
}
f.mutex.Lock()
@@ -209,6 +209,21 @@ func (f *File) SetLinesForContent(content []byte) {
f.mutex.Unlock()
}
+// LineStart returns the Pos value of the start of the specified line.
+// It ignores any alternative positions set using AddLineColumnInfo.
+// LineStart panics if the 1-based line number is invalid.
+func (f *File) LineStart(line int) Pos {
+ if line < 1 {
+ panic("illegal line number (line numbering starts at 1)")
+ }
+ f.mutex.Lock()
+ defer f.mutex.Unlock()
+ if line > len(f.lines) {
+ panic("illegal line number")
+ }
+ return Pos(f.base + f.lines[line-1])
+}
+
// A lineInfo object describes alternative file, line, and column
// number information (such as provided via a //line directive)
// for a given file offset.
diff --git a/src/go/token/position_test.go b/src/go/token/position_test.go
index 63984bc872..7d465dffa6 100644
--- a/src/go/token/position_test.go
+++ b/src/go/token/position_test.go
@@ -324,3 +324,18 @@ done
checkPos(t, "3. Position", got3, want)
}
}
+
+func TestLineStart(t *testing.T) {
+ const src = "one\ntwo\nthree\n"
+ fset := NewFileSet()
+ f := fset.AddFile("input", -1, len(src))
+ f.SetLinesForContent([]byte(src))
+
+ for line := 1; line <= 3; line++ {
+ pos := f.LineStart(line)
+ position := fset.Position(pos)
+ if position.Line != line || position.Column != 1 {
+ t.Errorf("LineStart(%d) returned wrong pos %d: %s", line, pos, position)
+ }
+ }
+}
diff --git a/src/go/types/api.go b/src/go/types/api.go
index fcefddf488..b1fcb2d10b 100644
--- a/src/go/types/api.go
+++ b/src/go/types/api.go
@@ -180,7 +180,7 @@ type Info struct {
//
// *ast.ImportSpec *PkgName for imports without renames
// *ast.CaseClause type-specific *Var for each type switch case clause (incl. default)
- // *ast.Field anonymous parameter *Var
+ // *ast.Field anonymous parameter *Var (incl. unnamed results)
//
Implicits map[ast.Node]Object
@@ -240,7 +240,7 @@ func (info *Info) TypeOf(e ast.Expr) Type {
// or nil if not found.
//
// If id is an embedded struct field, ObjectOf returns the field (*Var)
-// it uses, not the type (*TypeName) it defines.
+// it defines, not the type (*TypeName) it uses.
//
// Precondition: the Uses and Defs maps are populated.
//
diff --git a/src/go/types/decl.go b/src/go/types/decl.go
index d37a460a4e..0ff1fb058b 100644
--- a/src/go/types/decl.go
+++ b/src/go/types/decl.go
@@ -65,7 +65,7 @@ func objPathString(path []Object) string {
}
// objDecl type-checks the declaration of obj in its respective (file) context.
-// See check.typ for the details on def and path.
+// For the meaning of def, see Checker.definedType, in typexpr.go.
func (check *Checker) objDecl(obj Object, def *Named) {
if trace {
check.trace(obj.Pos(), "-- checking %s %s (objPath = %s)", obj.color(), obj, objPathString(check.objPath))
@@ -140,20 +140,12 @@ func (check *Checker) objDecl(obj Object, def *Named) {
// order code.
switch obj := obj.(type) {
case *Const:
- if check.typeCycle(obj) {
- obj.typ = Typ[Invalid]
- break
- }
- if obj.typ == nil {
+ if check.typeCycle(obj) || obj.typ == nil {
obj.typ = Typ[Invalid]
}
case *Var:
- if check.typeCycle(obj) {
- obj.typ = Typ[Invalid]
- break
- }
- if obj.typ == nil {
+ if check.typeCycle(obj) || obj.typ == nil {
obj.typ = Typ[Invalid]
}
diff --git a/src/go/types/example_test.go b/src/go/types/example_test.go
index 2a2fb3fc59..492127bbab 100644
--- a/src/go/types/example_test.go
+++ b/src/go/types/example_test.go
@@ -51,6 +51,7 @@ type Celsius float64
func (c Celsius) String() string { return fmt.Sprintf("%g°C", c) }
func FToC(f float64) Celsius { return Celsius(f - 32 / 9 * 5) }
const Boiling Celsius = 100
+func Unused() { {}; {{ var x int; _ = x }} } // make sure empty block scopes get printed
`},
} {
f, err := parser.ParseFile(fset, file.name, file.input, 0)
@@ -81,23 +82,33 @@ const Boiling Celsius = 100
// . const temperature.Boiling temperature.Celsius
// . type temperature.Celsius float64
// . func temperature.FToC(f float64) temperature.Celsius
+ // . func temperature.Unused()
// . func temperature.main()
- //
// . main.go scope {
// . . package fmt
- //
// . . function scope {
// . . . var freezing temperature.Celsius
- // . . }. }
+ // . . }
+ // . }
// . celsius.go scope {
// . . package fmt
- //
// . . function scope {
// . . . var c temperature.Celsius
// . . }
// . . function scope {
// . . . var f float64
- // . . }. }}
+ // . . }
+ // . . function scope {
+ // . . . block scope {
+ // . . . }
+ // . . . block scope {
+ // . . . . block scope {
+ // . . . . . var x int
+ // . . . . }
+ // . . . }
+ // . . }
+ // . }
+ // }
}
// ExampleMethodSet prints the method sets of various types.
diff --git a/src/go/types/expr.go b/src/go/types/expr.go
index c65c9e7681..fc4de98eb7 100644
--- a/src/go/types/expr.go
+++ b/src/go/types/expr.go
@@ -1010,7 +1010,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
goto Error // error was reported before
case *ast.Ident:
- check.ident(x, e, nil)
+ check.ident(x, e, nil, false)
case *ast.Ellipsis:
// ellipses are handled explicitly where they are legal
diff --git a/src/go/types/scope.go b/src/go/types/scope.go
index 39e42d758a..839a60db2e 100644
--- a/src/go/types/scope.go
+++ b/src/go/types/scope.go
@@ -161,13 +161,8 @@ func (s *Scope) WriteTo(w io.Writer, n int, recurse bool) {
const ind = ". "
indn := strings.Repeat(ind, n)
- fmt.Fprintf(w, "%s%s scope %p {", indn, s.comment, s)
- if len(s.elems) == 0 {
- fmt.Fprintf(w, "}\n")
- return
- }
+ fmt.Fprintf(w, "%s%s scope %p {\n", indn, s.comment, s)
- fmt.Fprintln(w)
indn1 := indn + ind
for _, name := range s.Names() {
fmt.Fprintf(w, "%s%s\n", indn1, s.elems[name])
@@ -175,12 +170,11 @@ func (s *Scope) WriteTo(w io.Writer, n int, recurse bool) {
if recurse {
for _, s := range s.children {
- fmt.Fprintln(w)
s.WriteTo(w, n+1, recurse)
}
}
- fmt.Fprintf(w, "%s}", indn)
+ fmt.Fprintf(w, "%s}\n", indn)
}
// String returns a string representation of the scope, for debugging.
diff --git a/src/go/types/sizes.go b/src/go/types/sizes.go
index 7b5410167f..f890c30377 100644
--- a/src/go/types/sizes.go
+++ b/src/go/types/sizes.go
@@ -169,6 +169,7 @@ var gcArchSizes = map[string]*StdSizes{
"ppc64le": {8, 8},
"riscv64": {8, 8},
"s390x": {8, 8},
+ "sparc64": {8, 8},
"wasm": {8, 8},
// When adding more architectures here,
// update the doc string of SizesFor below.
@@ -179,7 +180,7 @@ var gcArchSizes = map[string]*StdSizes{
//
// Supported architectures for compiler "gc":
// "386", "arm", "arm64", "amd64", "amd64p32", "mips", "mipsle",
-// "mips64", "mips64le", "ppc64", "ppc64le", "riscv64", "s390x", "wasm".
+// "mips64", "mips64le", "ppc64", "ppc64le", "riscv64", "s390x", "sparc64", "wasm".
func SizesFor(compiler, arch string) Sizes {
if compiler != "gc" {
return nil
diff --git a/src/go/types/testdata/cycles5.src b/src/go/types/testdata/cycles5.src
index 9c2822e738..aa6528a631 100644
--- a/src/go/types/testdata/cycles5.src
+++ b/src/go/types/testdata/cycles5.src
@@ -162,20 +162,29 @@ func makeArray() (res T12) { return }
var r /* ERROR cycle */ = newReader()
func newReader() r
-// variations of the theme of #8699 amd #20770
+// variations of the theme of #8699 and #20770
var arr /* ERROR cycle */ = f()
func f() [len(arr)]int
-// TODO(gri) here we should only get one error
-func ff /* ERROR cycle */ (ff /* ERROR not a type */ )
+// issue #25790
+func ff(ff /* ERROR not a type */ )
+func gg((gg /* ERROR not a type */ ))
type T13 /* ERROR cycle */ [len(b13)]int
var b13 T13
-func g /* ERROR cycle */ () [unsafe.Sizeof(x)]int
-var x = g
+func g1() [unsafe.Sizeof(g1)]int
+func g2() [unsafe.Sizeof(x2)]int
+var x2 = g2
-func h /* ERROR cycle */ () [h /* ERROR no value */ ()[0]]int { panic(0) }
+// verify that we get the correct sizes for the functions above
+// (note: assert is statically evaluated in go/types test mode)
+func init() {
+ assert(unsafe.Sizeof(g1) == 8)
+ assert(unsafe.Sizeof(x2) == 8)
+}
+
+func h() [h /* ERROR no value */ ()[0]]int { panic(0) }
var c14 /* ERROR cycle */ T14
type T14 [uintptr(unsafe.Sizeof(&c14))]byte
diff --git a/src/go/types/testdata/decls0.src b/src/go/types/testdata/decls0.src
index 162dfeda04..e75216172b 100644
--- a/src/go/types/testdata/decls0.src
+++ b/src/go/types/testdata/decls0.src
@@ -183,11 +183,11 @@ type (
)
// cycles in function/method declarations
-// (test cases for issue 5217 and variants)
-func f1 /* ERROR cycle */ (x f1 /* ERROR "not a type" */ ) {}
-func f2 /* ERROR cycle */ (x *f2 /* ERROR "not a type" */ ) {}
-func f3 /* ERROR cycle */ () (x f3 /* ERROR "not a type" */ ) { return }
-func f4 /* ERROR cycle */ () (x *f4 /* ERROR "not a type" */ ) { return }
+// (test cases for issues #5217, #25790 and variants)
+func f1(x f1 /* ERROR "not a type" */ ) {}
+func f2(x *f2 /* ERROR "not a type" */ ) {}
+func f3() (x f3 /* ERROR "not a type" */ ) { return }
+func f4() (x *f4 /* ERROR "not a type" */ ) { return }
func (S0) m1(x S0.m1 /* ERROR "field or method" */ ) {}
func (S0) m2(x *S0.m2 /* ERROR "field or method" */ ) {}
diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go
index 83848099c2..12c5c7b0a5 100644
--- a/src/go/types/typexpr.go
+++ b/src/go/types/typexpr.go
@@ -16,9 +16,10 @@ import (
// ident type-checks identifier e and initializes x with the value or type of e.
// If an error occurred, x.mode is set to invalid.
-// For the meaning of def, see check.typExpr, below.
+// For the meaning of def, see Checker.definedType, below.
+// If wantType is set, the identifier e is expected to denote a type.
//
-func (check *Checker) ident(x *operand, e *ast.Ident, def *Named) {
+func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, wantType bool) {
x.mode = invalid
x.expr = e
@@ -35,8 +36,19 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *Named) {
}
check.recordUse(e, obj)
- check.objDecl(obj, def)
+ // Type-check the object.
+ // Only call Checker.objDecl if the object doesn't have a type yet
+ // (in which case we must actually determine it) or the object is a
+ // TypeName and we also want a type (in which case we might detect
+ // a cycle which needs to be reported). Otherwise we can skip the
+ // call and avoid a possible cycle error in favor of the more
+ // informative "not a type/value" error that this function's caller
+ // will issue (see issue #25790).
typ := obj.Type()
+ if _, gotType := obj.(*TypeName); typ == nil || gotType && wantType {
+ check.objDecl(obj, def)
+ typ = obj.Type() // type must have been assigned by Checker.objDecl
+ }
assert(typ != nil)
// The object may be dot-imported: If so, remove its package from
@@ -215,7 +227,7 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type {
case *ast.Ident:
var x operand
- check.ident(&x, e, def)
+ check.ident(&x, e, def, true)
switch x.mode {
case typexpr:
diff --git a/src/html/template/js.go b/src/html/template/js.go
index 33a18b4186..2291f47c33 100644
--- a/src/html/template/js.go
+++ b/src/html/template/js.go
@@ -172,7 +172,7 @@ func jsValEscaper(args ...interface{}) string {
// turning into
// x//* error marshaling y:
// second line of error message */null
- return fmt.Sprintf(" /* %s */null ", strings.Replace(err.Error(), "*/", "* /", -1))
+ return fmt.Sprintf(" /* %s */null ", strings.ReplaceAll(err.Error(), "*/", "* /"))
}
// TODO: maybe post-process output to prevent it from containing
diff --git a/src/html/template/url.go b/src/html/template/url.go
index f0516300de..8a4f727e50 100644
--- a/src/html/template/url.go
+++ b/src/html/template/url.go
@@ -156,7 +156,7 @@ func srcsetFilterAndEscaper(args ...interface{}) string {
s = b.String()
}
// Additionally, commas separate one source from another.
- return strings.Replace(s, ",", "%2c", -1)
+ return strings.ReplaceAll(s, ",", "%2c")
}
var b bytes.Buffer
diff --git a/src/image/draw/draw.go b/src/image/draw/draw.go
index 977d7c5221..3ff1828dc0 100644
--- a/src/image/draw/draw.go
+++ b/src/image/draw/draw.go
@@ -309,23 +309,20 @@ func drawCopyOver(dst *image.RGBA, r image.Rectangle, src *image.RGBA, sp image.
dpix := dst.Pix[d0:]
spix := src.Pix[s0:]
for i := i0; i != i1; i += idelta {
- sr := uint32(spix[i+0]) * 0x101
- sg := uint32(spix[i+1]) * 0x101
- sb := uint32(spix[i+2]) * 0x101
- sa := uint32(spix[i+3]) * 0x101
-
- dr := &dpix[i+0]
- dg := &dpix[i+1]
- db := &dpix[i+2]
- da := &dpix[i+3]
+ s := spix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
+ sr := uint32(s[0]) * 0x101
+ sg := uint32(s[1]) * 0x101
+ sb := uint32(s[2]) * 0x101
+ sa := uint32(s[3]) * 0x101
// The 0x101 is here for the same reason as in drawRGBA.
a := (m - sa) * 0x101
- *dr = uint8((uint32(*dr)*a/m + sr) >> 8)
- *dg = uint8((uint32(*dg)*a/m + sg) >> 8)
- *db = uint8((uint32(*db)*a/m + sb) >> 8)
- *da = uint8((uint32(*da)*a/m + sa) >> 8)
+ d := dpix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
+ d[0] = uint8((uint32(d[0])*a/m + sr) >> 8)
+ d[1] = uint8((uint32(d[1])*a/m + sg) >> 8)
+ d[2] = uint8((uint32(d[2])*a/m + sb) >> 8)
+ d[3] = uint8((uint32(d[3])*a/m + sa) >> 8)
}
d0 += ddelta
s0 += sdelta
@@ -372,23 +369,25 @@ func drawNRGBAOver(dst *image.RGBA, r image.Rectangle, src *image.NRGBA, sp imag
for i, si := i0, si0; i < i1; i, si = i+4, si+4 {
// Convert from non-premultiplied color to pre-multiplied color.
- sa := uint32(spix[si+3]) * 0x101
- sr := uint32(spix[si+0]) * sa / 0xff
- sg := uint32(spix[si+1]) * sa / 0xff
- sb := uint32(spix[si+2]) * sa / 0xff
+ s := spix[si : si+4 : si+4] // Small cap improves performance, see https://golang.org/issue/27857
+ sa := uint32(s[3]) * 0x101
+ sr := uint32(s[0]) * sa / 0xff
+ sg := uint32(s[1]) * sa / 0xff
+ sb := uint32(s[2]) * sa / 0xff
- dr := uint32(dpix[i+0])
- dg := uint32(dpix[i+1])
- db := uint32(dpix[i+2])
- da := uint32(dpix[i+3])
+ d := dpix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
+ dr := uint32(d[0])
+ dg := uint32(d[1])
+ db := uint32(d[2])
+ da := uint32(d[3])
// The 0x101 is here for the same reason as in drawRGBA.
a := (m - sa) * 0x101
- dpix[i+0] = uint8((dr*a/m + sr) >> 8)
- dpix[i+1] = uint8((dg*a/m + sg) >> 8)
- dpix[i+2] = uint8((db*a/m + sb) >> 8)
- dpix[i+3] = uint8((da*a/m + sa) >> 8)
+ d[0] = uint8((dr*a/m + sr) >> 8)
+ d[1] = uint8((dg*a/m + sg) >> 8)
+ d[2] = uint8((db*a/m + sb) >> 8)
+ d[3] = uint8((da*a/m + sa) >> 8)
}
}
}
@@ -407,15 +406,17 @@ func drawNRGBASrc(dst *image.RGBA, r image.Rectangle, src *image.NRGBA, sp image
for i, si := i0, si0; i < i1; i, si = i+4, si+4 {
// Convert from non-premultiplied color to pre-multiplied color.
- sa := uint32(spix[si+3]) * 0x101
- sr := uint32(spix[si+0]) * sa / 0xff
- sg := uint32(spix[si+1]) * sa / 0xff
- sb := uint32(spix[si+2]) * sa / 0xff
+ s := spix[si : si+4 : si+4] // Small cap improves performance, see https://golang.org/issue/27857
+ sa := uint32(s[3]) * 0x101
+ sr := uint32(s[0]) * sa / 0xff
+ sg := uint32(s[1]) * sa / 0xff
+ sb := uint32(s[2]) * sa / 0xff
- dpix[i+0] = uint8(sr >> 8)
- dpix[i+1] = uint8(sg >> 8)
- dpix[i+2] = uint8(sb >> 8)
- dpix[i+3] = uint8(sa >> 8)
+ d := dpix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
+ d[0] = uint8(sr >> 8)
+ d[1] = uint8(sg >> 8)
+ d[2] = uint8(sb >> 8)
+ d[3] = uint8(sa >> 8)
}
}
}
@@ -434,10 +435,11 @@ func drawGray(dst *image.RGBA, r image.Rectangle, src *image.Gray, sp image.Poin
for i, si := i0, si0; i < i1; i, si = i+4, si+1 {
p := spix[si]
- dpix[i+0] = p
- dpix[i+1] = p
- dpix[i+2] = p
- dpix[i+3] = 255
+ d := dpix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
+ d[0] = p
+ d[1] = p
+ d[2] = p
+ d[3] = 255
}
}
}
@@ -455,9 +457,10 @@ func drawCMYK(dst *image.RGBA, r image.Rectangle, src *image.CMYK, sp image.Poin
spix := src.Pix[sy*src.Stride:]
for i, si := i0, si0; i < i1; i, si = i+4, si+4 {
- dpix[i+0], dpix[i+1], dpix[i+2] =
- color.CMYKToRGB(spix[si+0], spix[si+1], spix[si+2], spix[si+3])
- dpix[i+3] = 255
+ s := spix[si : si+4 : si+4] // Small cap improves performance, see https://golang.org/issue/27857
+ d := dpix[i : i+4 : i+4]
+ d[0], d[1], d[2] = color.CMYKToRGB(s[0], s[1], s[2], s[3])
+ d[3] = 255
}
}
}
@@ -475,18 +478,14 @@ func drawGlyphOver(dst *image.RGBA, r image.Rectangle, src *image.Uniform, mask
}
ma |= ma << 8
- dr := &dst.Pix[i+0]
- dg := &dst.Pix[i+1]
- db := &dst.Pix[i+2]
- da := &dst.Pix[i+3]
-
// The 0x101 is here for the same reason as in drawRGBA.
a := (m - (sa * ma / m)) * 0x101
- *dr = uint8((uint32(*dr)*a + sr*ma) / m >> 8)
- *dg = uint8((uint32(*dg)*a + sg*ma) / m >> 8)
- *db = uint8((uint32(*db)*a + sb*ma) / m >> 8)
- *da = uint8((uint32(*da)*a + sa*ma) / m >> 8)
+ d := dst.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
+ d[0] = uint8((uint32(d[0])*a + sr*ma) / m >> 8)
+ d[1] = uint8((uint32(d[1])*a + sg*ma) / m >> 8)
+ d[2] = uint8((uint32(d[2])*a + sb*ma) / m >> 8)
+ d[3] = uint8((uint32(d[3])*a + sa*ma) / m >> 8)
}
i0 += dst.Stride
i1 += dst.Stride
@@ -518,11 +517,12 @@ func drawRGBA(dst *image.RGBA, r image.Rectangle, src image.Image, sp image.Poin
_, _, _, ma = mask.At(mx, my).RGBA()
}
sr, sg, sb, sa := src.At(sx, sy).RGBA()
+ d := dst.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
if op == Over {
- dr := uint32(dst.Pix[i+0])
- dg := uint32(dst.Pix[i+1])
- db := uint32(dst.Pix[i+2])
- da := uint32(dst.Pix[i+3])
+ dr := uint32(d[0])
+ dg := uint32(d[1])
+ db := uint32(d[2])
+ da := uint32(d[3])
// dr, dg, db and da are all 8-bit color at the moment, ranging in [0,255].
// We work in 16-bit color, and so would normally do:
@@ -532,16 +532,16 @@ func drawRGBA(dst *image.RGBA, r image.Rectangle, src image.Image, sp image.Poin
// This yields the same result, but is fewer arithmetic operations.
a := (m - (sa * ma / m)) * 0x101
- dst.Pix[i+0] = uint8((dr*a + sr*ma) / m >> 8)
- dst.Pix[i+1] = uint8((dg*a + sg*ma) / m >> 8)
- dst.Pix[i+2] = uint8((db*a + sb*ma) / m >> 8)
- dst.Pix[i+3] = uint8((da*a + sa*ma) / m >> 8)
+ d[0] = uint8((dr*a + sr*ma) / m >> 8)
+ d[1] = uint8((dg*a + sg*ma) / m >> 8)
+ d[2] = uint8((db*a + sb*ma) / m >> 8)
+ d[3] = uint8((da*a + sa*ma) / m >> 8)
} else {
- dst.Pix[i+0] = uint8(sr * ma / m >> 8)
- dst.Pix[i+1] = uint8(sg * ma / m >> 8)
- dst.Pix[i+2] = uint8(sb * ma / m >> 8)
- dst.Pix[i+3] = uint8(sa * ma / m >> 8)
+ d[0] = uint8(sr * ma / m >> 8)
+ d[1] = uint8(sg * ma / m >> 8)
+ d[2] = uint8(sb * ma / m >> 8)
+ d[3] = uint8(sa * ma / m >> 8)
}
}
i0 += dy * dst.Stride
diff --git a/src/image/format.go b/src/image/format.go
index 3668de4e68..a53b8f9b55 100644
--- a/src/image/format.go
+++ b/src/image/format.go
@@ -8,6 +8,8 @@ import (
"bufio"
"errors"
"io"
+ "sync"
+ "sync/atomic"
)
// ErrFormat indicates that decoding encountered an unknown format.
@@ -21,7 +23,10 @@ type format struct {
}
// Formats is the list of registered formats.
-var formats []format
+var (
+ formatsMu sync.Mutex
+ atomicFormats atomic.Value
+)
// RegisterFormat registers an image format for use by Decode.
// Name is the name of the format, like "jpeg" or "png".
@@ -30,7 +35,10 @@ var formats []format
// Decode is the function that decodes the encoded image.
// DecodeConfig is the function that decodes just its configuration.
func RegisterFormat(name, magic string, decode func(io.Reader) (Image, error), decodeConfig func(io.Reader) (Config, error)) {
- formats = append(formats, format{name, magic, decode, decodeConfig})
+ formatsMu.Lock()
+ formats, _ := atomicFormats.Load().([]format)
+ atomicFormats.Store(append(formats, format{name, magic, decode, decodeConfig}))
+ formatsMu.Unlock()
}
// A reader is an io.Reader that can also peek ahead.
@@ -62,6 +70,7 @@ func match(magic string, b []byte) bool {
// Sniff determines the format of r's data.
func sniff(r reader) format {
+ formats, _ := atomicFormats.Load().([]format)
for _, f := range formats {
b, err := r.Peek(len(f.magic))
if err == nil && match(f.magic, b) {
diff --git a/src/image/image.go b/src/image/image.go
index bebb9f70fa..ffd6de7383 100644
--- a/src/image/image.go
+++ b/src/image/image.go
@@ -80,7 +80,8 @@ func (p *RGBA) RGBAAt(x, y int) color.RGBA {
return color.RGBA{}
}
i := p.PixOffset(x, y)
- return color.RGBA{p.Pix[i+0], p.Pix[i+1], p.Pix[i+2], p.Pix[i+3]}
+ s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
+ return color.RGBA{s[0], s[1], s[2], s[3]}
}
// PixOffset returns the index of the first element of Pix that corresponds to
@@ -95,10 +96,11 @@ func (p *RGBA) Set(x, y int, c color.Color) {
}
i := p.PixOffset(x, y)
c1 := color.RGBAModel.Convert(c).(color.RGBA)
- p.Pix[i+0] = c1.R
- p.Pix[i+1] = c1.G
- p.Pix[i+2] = c1.B
- p.Pix[i+3] = c1.A
+ s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
+ s[0] = c1.R
+ s[1] = c1.G
+ s[2] = c1.B
+ s[3] = c1.A
}
func (p *RGBA) SetRGBA(x, y int, c color.RGBA) {
@@ -106,10 +108,11 @@ func (p *RGBA) SetRGBA(x, y int, c color.RGBA) {
return
}
i := p.PixOffset(x, y)
- p.Pix[i+0] = c.R
- p.Pix[i+1] = c.G
- p.Pix[i+2] = c.B
- p.Pix[i+3] = c.A
+ s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
+ s[0] = c.R
+ s[1] = c.G
+ s[2] = c.B
+ s[3] = c.A
}
// SubImage returns an image representing the portion of the image p visible
@@ -179,11 +182,12 @@ func (p *RGBA64) RGBA64At(x, y int) color.RGBA64 {
return color.RGBA64{}
}
i := p.PixOffset(x, y)
+ s := p.Pix[i : i+8 : i+8] // Small cap improves performance, see https://golang.org/issue/27857
return color.RGBA64{
- uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1]),
- uint16(p.Pix[i+2])<<8 | uint16(p.Pix[i+3]),
- uint16(p.Pix[i+4])<<8 | uint16(p.Pix[i+5]),
- uint16(p.Pix[i+6])<<8 | uint16(p.Pix[i+7]),
+ uint16(s[0])<<8 | uint16(s[1]),
+ uint16(s[2])<<8 | uint16(s[3]),
+ uint16(s[4])<<8 | uint16(s[5]),
+ uint16(s[6])<<8 | uint16(s[7]),
}
}
@@ -199,14 +203,15 @@ func (p *RGBA64) Set(x, y int, c color.Color) {
}
i := p.PixOffset(x, y)
c1 := color.RGBA64Model.Convert(c).(color.RGBA64)
- p.Pix[i+0] = uint8(c1.R >> 8)
- p.Pix[i+1] = uint8(c1.R)
- p.Pix[i+2] = uint8(c1.G >> 8)
- p.Pix[i+3] = uint8(c1.G)
- p.Pix[i+4] = uint8(c1.B >> 8)
- p.Pix[i+5] = uint8(c1.B)
- p.Pix[i+6] = uint8(c1.A >> 8)
- p.Pix[i+7] = uint8(c1.A)
+ s := p.Pix[i : i+8 : i+8] // Small cap improves performance, see https://golang.org/issue/27857
+ s[0] = uint8(c1.R >> 8)
+ s[1] = uint8(c1.R)
+ s[2] = uint8(c1.G >> 8)
+ s[3] = uint8(c1.G)
+ s[4] = uint8(c1.B >> 8)
+ s[5] = uint8(c1.B)
+ s[6] = uint8(c1.A >> 8)
+ s[7] = uint8(c1.A)
}
func (p *RGBA64) SetRGBA64(x, y int, c color.RGBA64) {
@@ -214,14 +219,15 @@ func (p *RGBA64) SetRGBA64(x, y int, c color.RGBA64) {
return
}
i := p.PixOffset(x, y)
- p.Pix[i+0] = uint8(c.R >> 8)
- p.Pix[i+1] = uint8(c.R)
- p.Pix[i+2] = uint8(c.G >> 8)
- p.Pix[i+3] = uint8(c.G)
- p.Pix[i+4] = uint8(c.B >> 8)
- p.Pix[i+5] = uint8(c.B)
- p.Pix[i+6] = uint8(c.A >> 8)
- p.Pix[i+7] = uint8(c.A)
+ s := p.Pix[i : i+8 : i+8] // Small cap improves performance, see https://golang.org/issue/27857
+ s[0] = uint8(c.R >> 8)
+ s[1] = uint8(c.R)
+ s[2] = uint8(c.G >> 8)
+ s[3] = uint8(c.G)
+ s[4] = uint8(c.B >> 8)
+ s[5] = uint8(c.B)
+ s[6] = uint8(c.A >> 8)
+ s[7] = uint8(c.A)
}
// SubImage returns an image representing the portion of the image p visible
@@ -291,7 +297,8 @@ func (p *NRGBA) NRGBAAt(x, y int) color.NRGBA {
return color.NRGBA{}
}
i := p.PixOffset(x, y)
- return color.NRGBA{p.Pix[i+0], p.Pix[i+1], p.Pix[i+2], p.Pix[i+3]}
+ s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
+ return color.NRGBA{s[0], s[1], s[2], s[3]}
}
// PixOffset returns the index of the first element of Pix that corresponds to
@@ -306,10 +313,11 @@ func (p *NRGBA) Set(x, y int, c color.Color) {
}
i := p.PixOffset(x, y)
c1 := color.NRGBAModel.Convert(c).(color.NRGBA)
- p.Pix[i+0] = c1.R
- p.Pix[i+1] = c1.G
- p.Pix[i+2] = c1.B
- p.Pix[i+3] = c1.A
+ s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
+ s[0] = c1.R
+ s[1] = c1.G
+ s[2] = c1.B
+ s[3] = c1.A
}
func (p *NRGBA) SetNRGBA(x, y int, c color.NRGBA) {
@@ -317,10 +325,11 @@ func (p *NRGBA) SetNRGBA(x, y int, c color.NRGBA) {
return
}
i := p.PixOffset(x, y)
- p.Pix[i+0] = c.R
- p.Pix[i+1] = c.G
- p.Pix[i+2] = c.B
- p.Pix[i+3] = c.A
+ s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
+ s[0] = c.R
+ s[1] = c.G
+ s[2] = c.B
+ s[3] = c.A
}
// SubImage returns an image representing the portion of the image p visible
@@ -390,11 +399,12 @@ func (p *NRGBA64) NRGBA64At(x, y int) color.NRGBA64 {
return color.NRGBA64{}
}
i := p.PixOffset(x, y)
+ s := p.Pix[i : i+8 : i+8] // Small cap improves performance, see https://golang.org/issue/27857
return color.NRGBA64{
- uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1]),
- uint16(p.Pix[i+2])<<8 | uint16(p.Pix[i+3]),
- uint16(p.Pix[i+4])<<8 | uint16(p.Pix[i+5]),
- uint16(p.Pix[i+6])<<8 | uint16(p.Pix[i+7]),
+ uint16(s[0])<<8 | uint16(s[1]),
+ uint16(s[2])<<8 | uint16(s[3]),
+ uint16(s[4])<<8 | uint16(s[5]),
+ uint16(s[6])<<8 | uint16(s[7]),
}
}
@@ -410,14 +420,15 @@ func (p *NRGBA64) Set(x, y int, c color.Color) {
}
i := p.PixOffset(x, y)
c1 := color.NRGBA64Model.Convert(c).(color.NRGBA64)
- p.Pix[i+0] = uint8(c1.R >> 8)
- p.Pix[i+1] = uint8(c1.R)
- p.Pix[i+2] = uint8(c1.G >> 8)
- p.Pix[i+3] = uint8(c1.G)
- p.Pix[i+4] = uint8(c1.B >> 8)
- p.Pix[i+5] = uint8(c1.B)
- p.Pix[i+6] = uint8(c1.A >> 8)
- p.Pix[i+7] = uint8(c1.A)
+ s := p.Pix[i : i+8 : i+8] // Small cap improves performance, see https://golang.org/issue/27857
+ s[0] = uint8(c1.R >> 8)
+ s[1] = uint8(c1.R)
+ s[2] = uint8(c1.G >> 8)
+ s[3] = uint8(c1.G)
+ s[4] = uint8(c1.B >> 8)
+ s[5] = uint8(c1.B)
+ s[6] = uint8(c1.A >> 8)
+ s[7] = uint8(c1.A)
}
func (p *NRGBA64) SetNRGBA64(x, y int, c color.NRGBA64) {
@@ -425,14 +436,15 @@ func (p *NRGBA64) SetNRGBA64(x, y int, c color.NRGBA64) {
return
}
i := p.PixOffset(x, y)
- p.Pix[i+0] = uint8(c.R >> 8)
- p.Pix[i+1] = uint8(c.R)
- p.Pix[i+2] = uint8(c.G >> 8)
- p.Pix[i+3] = uint8(c.G)
- p.Pix[i+4] = uint8(c.B >> 8)
- p.Pix[i+5] = uint8(c.B)
- p.Pix[i+6] = uint8(c.A >> 8)
- p.Pix[i+7] = uint8(c.A)
+ s := p.Pix[i : i+8 : i+8] // Small cap improves performance, see https://golang.org/issue/27857
+ s[0] = uint8(c.R >> 8)
+ s[1] = uint8(c.R)
+ s[2] = uint8(c.G >> 8)
+ s[3] = uint8(c.G)
+ s[4] = uint8(c.B >> 8)
+ s[5] = uint8(c.B)
+ s[6] = uint8(c.A >> 8)
+ s[7] = uint8(c.A)
}
// SubImage returns an image representing the portion of the image p visible
@@ -850,7 +862,8 @@ func (p *CMYK) CMYKAt(x, y int) color.CMYK {
return color.CMYK{}
}
i := p.PixOffset(x, y)
- return color.CMYK{p.Pix[i+0], p.Pix[i+1], p.Pix[i+2], p.Pix[i+3]}
+ s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
+ return color.CMYK{s[0], s[1], s[2], s[3]}
}
// PixOffset returns the index of the first element of Pix that corresponds to
@@ -865,10 +878,11 @@ func (p *CMYK) Set(x, y int, c color.Color) {
}
i := p.PixOffset(x, y)
c1 := color.CMYKModel.Convert(c).(color.CMYK)
- p.Pix[i+0] = c1.C
- p.Pix[i+1] = c1.M
- p.Pix[i+2] = c1.Y
- p.Pix[i+3] = c1.K
+ s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
+ s[0] = c1.C
+ s[1] = c1.M
+ s[2] = c1.Y
+ s[3] = c1.K
}
func (p *CMYK) SetCMYK(x, y int, c color.CMYK) {
@@ -876,10 +890,11 @@ func (p *CMYK) SetCMYK(x, y int, c color.CMYK) {
return
}
i := p.PixOffset(x, y)
- p.Pix[i+0] = c.C
- p.Pix[i+1] = c.M
- p.Pix[i+2] = c.Y
- p.Pix[i+3] = c.K
+ s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
+ s[0] = c.C
+ s[1] = c.M
+ s[2] = c.Y
+ s[3] = c.K
}
// SubImage returns an image representing the portion of the image p visible
diff --git a/src/image/image_test.go b/src/image/image_test.go
index 08ba61ea0c..dfd8eb35a8 100644
--- a/src/image/image_test.go
+++ b/src/image/image_test.go
@@ -22,22 +22,29 @@ func cmp(cm color.Model, c0, c1 color.Color) bool {
return r0 == r1 && g0 == g1 && b0 == b1 && a0 == a1
}
-func TestImage(t *testing.T) {
- testImage := []image{
- NewRGBA(Rect(0, 0, 10, 10)),
- NewRGBA64(Rect(0, 0, 10, 10)),
- NewNRGBA(Rect(0, 0, 10, 10)),
- NewNRGBA64(Rect(0, 0, 10, 10)),
- NewAlpha(Rect(0, 0, 10, 10)),
- NewAlpha16(Rect(0, 0, 10, 10)),
- NewGray(Rect(0, 0, 10, 10)),
- NewGray16(Rect(0, 0, 10, 10)),
- NewPaletted(Rect(0, 0, 10, 10), color.Palette{
+var testImages = []struct {
+ name string
+ image func() image
+}{
+ {"rgba", func() image { return NewRGBA(Rect(0, 0, 10, 10)) }},
+ {"rgba64", func() image { return NewRGBA64(Rect(0, 0, 10, 10)) }},
+ {"nrgba", func() image { return NewNRGBA(Rect(0, 0, 10, 10)) }},
+ {"nrgba64", func() image { return NewNRGBA64(Rect(0, 0, 10, 10)) }},
+ {"alpha", func() image { return NewAlpha(Rect(0, 0, 10, 10)) }},
+ {"alpha16", func() image { return NewAlpha16(Rect(0, 0, 10, 10)) }},
+ {"gray", func() image { return NewGray(Rect(0, 0, 10, 10)) }},
+ {"gray16", func() image { return NewGray16(Rect(0, 0, 10, 10)) }},
+ {"paletted", func() image {
+ return NewPaletted(Rect(0, 0, 10, 10), color.Palette{
Transparent,
Opaque,
- }),
- }
- for _, m := range testImage {
+ })
+ }},
+}
+
+func TestImage(t *testing.T) {
+ for _, tc := range testImages {
+ m := tc.image()
if !Rect(0, 0, 10, 10).Eq(m.Bounds()) {
t.Errorf("%T: want bounds %v, got %v", m, Rect(0, 0, 10, 10), m.Bounds())
continue
@@ -111,3 +118,182 @@ func Test16BitsPerColorChannel(t *testing.T) {
}
}
}
+
+func BenchmarkAt(b *testing.B) {
+ for _, tc := range testImages {
+ b.Run(tc.name, func(b *testing.B) {
+ m := tc.image()
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ m.At(4, 5)
+ }
+ })
+ }
+}
+
+func BenchmarkSet(b *testing.B) {
+ c := color.Gray{0xff}
+ for _, tc := range testImages {
+ b.Run(tc.name, func(b *testing.B) {
+ m := tc.image()
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ m.Set(4, 5, c)
+ }
+ })
+ }
+}
+
+func BenchmarkRGBAAt(b *testing.B) {
+ m := NewRGBA(Rect(0, 0, 10, 10))
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ m.RGBAAt(4, 5)
+ }
+}
+
+func BenchmarkRGBASetRGBA(b *testing.B) {
+ m := NewRGBA(Rect(0, 0, 10, 10))
+ c := color.RGBA{0xff, 0xff, 0xff, 0x13}
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ m.SetRGBA(4, 5, c)
+ }
+}
+
+func BenchmarkRGBA64At(b *testing.B) {
+ m := NewRGBA64(Rect(0, 0, 10, 10))
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ m.RGBA64At(4, 5)
+ }
+}
+
+func BenchmarkRGBA64SetRGBA64(b *testing.B) {
+ m := NewRGBA64(Rect(0, 0, 10, 10))
+ c := color.RGBA64{0xffff, 0xffff, 0xffff, 0x1357}
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ m.SetRGBA64(4, 5, c)
+ }
+}
+
+func BenchmarkNRGBAAt(b *testing.B) {
+ m := NewNRGBA(Rect(0, 0, 10, 10))
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ m.NRGBAAt(4, 5)
+ }
+}
+
+func BenchmarkNRGBASetNRGBA(b *testing.B) {
+ m := NewNRGBA(Rect(0, 0, 10, 10))
+ c := color.NRGBA{0xff, 0xff, 0xff, 0x13}
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ m.SetNRGBA(4, 5, c)
+ }
+}
+
+func BenchmarkNRGBA64At(b *testing.B) {
+ m := NewNRGBA64(Rect(0, 0, 10, 10))
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ m.NRGBA64At(4, 5)
+ }
+}
+
+func BenchmarkNRGBA64SetNRGBA64(b *testing.B) {
+ m := NewNRGBA64(Rect(0, 0, 10, 10))
+ c := color.NRGBA64{0xffff, 0xffff, 0xffff, 0x1357}
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ m.SetNRGBA64(4, 5, c)
+ }
+}
+
+func BenchmarkAlphaAt(b *testing.B) {
+ m := NewAlpha(Rect(0, 0, 10, 10))
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ m.AlphaAt(4, 5)
+ }
+}
+
+func BenchmarkAlphaSetAlpha(b *testing.B) {
+ m := NewAlpha(Rect(0, 0, 10, 10))
+ c := color.Alpha{0x13}
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ m.SetAlpha(4, 5, c)
+ }
+}
+
+func BenchmarkAlpha16At(b *testing.B) {
+ m := NewAlpha16(Rect(0, 0, 10, 10))
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ m.Alpha16At(4, 5)
+ }
+}
+
+func BenchmarkAlphaSetAlpha16(b *testing.B) {
+ m := NewAlpha16(Rect(0, 0, 10, 10))
+ c := color.Alpha16{0x13}
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ m.SetAlpha16(4, 5, c)
+ }
+}
+
+func BenchmarkGrayAt(b *testing.B) {
+ m := NewGray(Rect(0, 0, 10, 10))
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ m.GrayAt(4, 5)
+ }
+}
+
+func BenchmarkGraySetGray(b *testing.B) {
+ m := NewGray(Rect(0, 0, 10, 10))
+ c := color.Gray{0x13}
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ m.SetGray(4, 5, c)
+ }
+}
+
+func BenchmarkGray16At(b *testing.B) {
+ m := NewGray16(Rect(0, 0, 10, 10))
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ m.Gray16At(4, 5)
+ }
+}
+
+func BenchmarkGraySetGray16(b *testing.B) {
+ m := NewGray16(Rect(0, 0, 10, 10))
+ c := color.Gray16{0x13}
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ m.SetGray16(4, 5, c)
+ }
+}
diff --git a/src/image/png/reader_test.go b/src/image/png/reader_test.go
index 66bcfcb437..33dcd3debc 100644
--- a/src/image/png/reader_test.go
+++ b/src/image/png/reader_test.go
@@ -364,10 +364,6 @@ func TestReader(t *testing.T) {
}
defer sf.Close()
sb := bufio.NewScanner(sf)
- if err != nil {
- t.Error(fn, err)
- continue
- }
// Compare the two, in SNG format, line by line.
for {
diff --git a/src/image/png/writer.go b/src/image/png/writer.go
index 49f1ad2e7f..c03335120e 100644
--- a/src/image/png/writer.go
+++ b/src/image/png/writer.go
@@ -7,6 +7,7 @@ package png
import (
"bufio"
"compress/zlib"
+ "encoding/binary"
"hash/crc32"
"image"
"image/color"
@@ -62,14 +63,6 @@ const (
// compression level, although that is not implemented yet.
)
-// Big-endian.
-func writeUint32(b []uint8, u uint32) {
- b[0] = uint8(u >> 24)
- b[1] = uint8(u >> 16)
- b[2] = uint8(u >> 8)
- b[3] = uint8(u >> 0)
-}
-
type opaquer interface {
Opaque() bool
}
@@ -108,7 +101,7 @@ func (e *encoder) writeChunk(b []byte, name string) {
e.err = UnsupportedError(name + " chunk is too large: " + strconv.Itoa(len(b)))
return
}
- writeUint32(e.header[:4], n)
+ binary.BigEndian.PutUint32(e.header[:4], n)
e.header[4] = name[0]
e.header[5] = name[1]
e.header[6] = name[2]
@@ -116,7 +109,7 @@ func (e *encoder) writeChunk(b []byte, name string) {
crc := crc32.NewIEEE()
crc.Write(e.header[4:8])
crc.Write(b)
- writeUint32(e.footer[:4], crc.Sum32())
+ binary.BigEndian.PutUint32(e.footer[:4], crc.Sum32())
_, e.err = e.w.Write(e.header[:8])
if e.err != nil {
@@ -131,8 +124,8 @@ func (e *encoder) writeChunk(b []byte, name string) {
func (e *encoder) writeIHDR() {
b := e.m.Bounds()
- writeUint32(e.tmp[0:4], uint32(b.Dx()))
- writeUint32(e.tmp[4:8], uint32(b.Dy()))
+ binary.BigEndian.PutUint32(e.tmp[0:4], uint32(b.Dx()))
+ binary.BigEndian.PutUint32(e.tmp[4:8], uint32(b.Dy()))
// Set bit depth and color type.
switch e.cb {
case cbG8:
@@ -144,6 +137,15 @@ func (e *encoder) writeIHDR() {
case cbP8:
e.tmp[8] = 8
e.tmp[9] = ctPaletted
+ case cbP4:
+ e.tmp[8] = 4
+ e.tmp[9] = ctPaletted
+ case cbP2:
+ e.tmp[8] = 2
+ e.tmp[9] = ctPaletted
+ case cbP1:
+ e.tmp[8] = 1
+ e.tmp[9] = ctPaletted
case cbTCA8:
e.tmp[8] = 8
e.tmp[9] = ctTrueColorAlpha
@@ -312,31 +314,38 @@ func (e *encoder) writeImage(w io.Writer, m image.Image, cb int, level int) erro
}
defer e.zw.Close()
- bpp := 0 // Bytes per pixel.
+ bitsPerPixel := 0
switch cb {
case cbG8:
- bpp = 1
+ bitsPerPixel = 8
case cbTC8:
- bpp = 3
+ bitsPerPixel = 24
case cbP8:
- bpp = 1
+ bitsPerPixel = 8
+ case cbP4:
+ bitsPerPixel = 4
+ case cbP2:
+ bitsPerPixel = 2
+ case cbP1:
+ bitsPerPixel = 1
case cbTCA8:
- bpp = 4
+ bitsPerPixel = 32
case cbTC16:
- bpp = 6
+ bitsPerPixel = 48
case cbTCA16:
- bpp = 8
+ bitsPerPixel = 64
case cbG16:
- bpp = 2
+ bitsPerPixel = 16
}
+
// cr[*] and pr are the bytes for the current and previous row.
// cr[0] is unfiltered (or equivalently, filtered with the ftNone filter).
// cr[ft], for non-zero filter types ft, are buffers for transforming cr[0] under the
// other PNG filter types. These buffers are allocated once and re-used for each row.
// The +1 is for the per-row filter type, which is at cr[*][0].
b := m.Bounds()
- sz := 1 + bpp*b.Dx()
+ sz := 1 + (bitsPerPixel*b.Dx()+7)/8
for i := range e.cr {
if cap(e.cr[i]) < sz {
e.cr[i] = make([]uint8, sz)
@@ -412,6 +421,30 @@ func (e *encoder) writeImage(w io.Writer, m image.Image, cb int, level int) erro
i += 1
}
}
+
+ case cbP4, cbP2, cbP1:
+ pi := m.(image.PalettedImage)
+
+ var a uint8
+ var c int
+ for x := b.Min.X; x < b.Max.X; x++ {
+ a = a<<uint(bitsPerPixel) | pi.ColorIndexAt(x, y)
+ c++
+ if c == 8/bitsPerPixel {
+ cr[0][i] = a
+ i += 1
+ a = 0
+ c = 0
+ }
+ }
+ if c != 0 {
+ for c != 8/bitsPerPixel {
+ a = a << uint(bitsPerPixel)
+ c++
+ }
+ cr[0][i] = a
+ }
+
case cbTCA8:
if nrgba != nil {
offset := (y - b.Min.Y) * nrgba.Stride
@@ -467,7 +500,10 @@ func (e *encoder) writeImage(w io.Writer, m image.Image, cb int, level int) erro
// "filters are rarely useful on palette images" and will result
// in larger files (see http://www.libpng.org/pub/png/book/chapter09.html).
f := ftNone
- if level != zlib.NoCompression && cb != cbP8 {
+ if level != zlib.NoCompression && cb != cbP8 && cb != cbP4 && cb != cbP2 && cb != cbP1 {
+ // Since we skip paletted images we don't have to worry about
+ // bitsPerPixel not being a multiple of 8
+ bpp := bitsPerPixel / 8
f = filter(&cr, pr, bpp)
}
@@ -558,7 +594,15 @@ func (enc *Encoder) Encode(w io.Writer, m image.Image) error {
pal, _ = m.ColorModel().(color.Palette)
}
if pal != nil {
- e.cb = cbP8
+ if len(pal) <= 2 {
+ e.cb = cbP1
+ } else if len(pal) <= 4 {
+ e.cb = cbP2
+ } else if len(pal) <= 16 {
+ e.cb = cbP4
+ } else {
+ e.cb = cbP8
+ }
} else {
switch m.ColorModel() {
case color.GrayModel:
diff --git a/src/image/png/writer_test.go b/src/image/png/writer_test.go
index 1107ea0e7f..5d131ff823 100644
--- a/src/image/png/writer_test.go
+++ b/src/image/png/writer_test.go
@@ -6,9 +6,12 @@ package png
import (
"bytes"
+ "compress/zlib"
+ "encoding/binary"
"fmt"
"image"
"image/color"
+ "io"
"io/ioutil"
"testing"
)
@@ -61,12 +64,12 @@ func TestWriter(t *testing.T) {
m1, err := readPNG(qfn)
if err != nil {
t.Error(fn, err)
- return
+ continue
}
m2, err := encodeDecode(m1)
if err != nil {
t.Error(fn, err)
- return
+ continue
}
// Compare the two.
err = diff(m0, m2)
@@ -77,6 +80,111 @@ func TestWriter(t *testing.T) {
}
}
+func TestWriterPaletted(t *testing.T) {
+ const width, height = 32, 16
+
+ testCases := []struct {
+ plen int
+ bitdepth uint8
+ datalen int
+ }{
+
+ {
+ plen: 256,
+ bitdepth: 8,
+ datalen: (1 + width) * height,
+ },
+
+ {
+ plen: 128,
+ bitdepth: 8,
+ datalen: (1 + width) * height,
+ },
+
+ {
+ plen: 16,
+ bitdepth: 4,
+ datalen: (1 + width/2) * height,
+ },
+
+ {
+ plen: 4,
+ bitdepth: 2,
+ datalen: (1 + width/4) * height,
+ },
+
+ {
+ plen: 2,
+ bitdepth: 1,
+ datalen: (1 + width/8) * height,
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(fmt.Sprintf("plen-%d", tc.plen), func(t *testing.T) {
+ // Create a paletted image with the correct palette length
+ palette := make(color.Palette, tc.plen)
+ for i := range palette {
+ palette[i] = color.NRGBA{
+ R: uint8(i),
+ G: uint8(i),
+ B: uint8(i),
+ A: 255,
+ }
+ }
+ m0 := image.NewPaletted(image.Rect(0, 0, width, height), palette)
+
+ i := 0
+ for y := 0; y < height; y++ {
+ for x := 0; x < width; x++ {
+ m0.SetColorIndex(x, y, uint8(i%tc.plen))
+ i++
+ }
+ }
+
+ // Encode the image
+ var b bytes.Buffer
+ if err := Encode(&b, m0); err != nil {
+ t.Error(err)
+ return
+ }
+ const chunkFieldsLength = 12 // 4 bytes for length, name and crc
+ data := b.Bytes()
+ i = len(pngHeader)
+
+ for i < len(data)-chunkFieldsLength {
+ length := binary.BigEndian.Uint32(data[i : i+4])
+ name := string(data[i+4 : i+8])
+
+ switch name {
+ case "IHDR":
+ bitdepth := data[i+8+8]
+ if bitdepth != tc.bitdepth {
+ t.Errorf("got bitdepth %d, want %d", bitdepth, tc.bitdepth)
+ }
+ case "IDAT":
+ // Uncompress the image data
+ r, err := zlib.NewReader(bytes.NewReader(data[i+8 : i+8+int(length)]))
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ n, err := io.Copy(ioutil.Discard, r)
+ if err != nil {
+ t.Errorf("got error while reading image data: %v", err)
+ }
+ if n != int64(tc.datalen) {
+ t.Errorf("got uncompressed data length %d, want %d", n, tc.datalen)
+ }
+ }
+
+ i += chunkFieldsLength + int(length)
+ }
+ })
+
+ }
+}
+
func TestWriterLevels(t *testing.T) {
m := image.NewNRGBA(image.Rect(0, 0, 100, 100))
diff --git a/src/internal/bytealg/compare_amd64.s b/src/internal/bytealg/compare_amd64.s
index 05bef4aad9..25effbc56f 100644
--- a/src/internal/bytealg/compare_amd64.s
+++ b/src/internal/bytealg/compare_amd64.s
@@ -63,7 +63,7 @@ loop:
ADDQ $16, DI
SUBQ $16, R8
JMP loop
-
+
diff64:
ADDQ $48, SI
ADDQ $48, DI
diff --git a/src/internal/bytealg/compare_amd64p32.s b/src/internal/bytealg/compare_amd64p32.s
index 85ba6fa9ac..4687fd8a04 100644
--- a/src/internal/bytealg/compare_amd64p32.s
+++ b/src/internal/bytealg/compare_amd64p32.s
@@ -62,7 +62,7 @@ loop:
ADDQ $16, DI
SUBQ $16, R8
JMP loop
-
+
// AX = bit mask of differences
diff16:
BSFQ AX, BX // index of first byte that differs
diff --git a/src/internal/bytealg/count_generic.go b/src/internal/bytealg/count_generic.go
index a763b3bc61..e24b2b7fa0 100644
--- a/src/internal/bytealg/count_generic.go
+++ b/src/internal/bytealg/count_generic.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build !amd64,!arm64
+// +build !amd64,!arm64,!ppc64le,!ppc64
package bytealg
diff --git a/src/internal/bytealg/count_native.go b/src/internal/bytealg/count_native.go
index a62c4cb5c0..e6a91b3c0e 100644
--- a/src/internal/bytealg/count_native.go
+++ b/src/internal/bytealg/count_native.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build amd64 arm64
+// +build amd64 arm64 ppc64le ppc64
package bytealg
diff --git a/src/internal/bytealg/count_ppc64x.s b/src/internal/bytealg/count_ppc64x.s
new file mode 100644
index 0000000000..7abdce1954
--- /dev/null
+++ b/src/internal/bytealg/count_ppc64x.s
@@ -0,0 +1,97 @@
+// Copyright 2018 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 ppc64le ppc64
+
+#include "go_asm.h"
+#include "textflag.h"
+
+TEXT ·Count(SB), NOSPLIT|NOFRAME, $0-40
+ MOVD b_base+0(FP), R3 // R3 = byte array pointer
+ MOVD b_len+8(FP), R4 // R4 = length
+ MOVBZ c+24(FP), R5 // R5 = byte
+ MOVD $ret+32(FP), R14 // R14 = &ret
+ BR countbytebody<>(SB)
+
+TEXT ·CountString(SB), NOSPLIT|NOFRAME, $0-32
+ MOVD s_base+0(FP), R3 // R3 = string
+ MOVD s_len+8(FP), R4 // R4 = length
+ MOVBZ c+16(FP), R5 // R5 = byte
+ MOVD $ret+24(FP), R14 // R14 = &ret
+ BR countbytebody<>(SB)
+
+// R3: addr of string
+// R4: len of string
+// R5: byte to count
+// R14: addr for return value
+// endianness shouldn't matter since we are just counting and order
+// is irrelevant
+TEXT countbytebody<>(SB), NOSPLIT|NOFRAME, $0-0
+ DCBT (R3) // Prepare cache line.
+ MOVD R0, R18 // byte count
+ MOVD R3, R19 // Save base address for calculating the index later.
+ MOVD R4, R16
+
+ MOVD R5, R6
+ RLDIMI $8, R6, $48, R6
+ RLDIMI $16, R6, $32, R6
+ RLDIMI $32, R6, $0, R6 // fill reg with the byte to count
+
+ VSPLTISW $3, V4 // used for shift
+ MTVRD R6, V1 // move compare byte
+ VSPLTB $7, V1, V1 // replicate byte across V1
+
+ CMPU R4, $32 // Check if it's a small string (<32 bytes)
+ BLT tail // Jump to the small string case
+ XXLXOR VS37, VS37, VS37 // clear V5 (aka VS37) to use as accumulator
+
+cmploop:
+ LXVW4X (R3), VS32 // load bytes from string
+
+ // when the bytes match, the corresonding byte contains all 1s
+ VCMPEQUB V1, V0, V2 // compare bytes
+ VPOPCNTD V2, V3 // each double word contains its count
+ VADDUDM V3, V5, V5 // accumulate bit count in each double word
+ ADD $16, R3, R3 // increment pointer
+ SUB $16, R16, R16 // remaining bytes
+ CMP R16, $16 // at least 16 remaining?
+ BGE cmploop
+ VSRD V5, V4, V5 // shift by 3 to convert bits to bytes
+ VSLDOI $8, V5, V5, V6 // get the double word values from vector
+ MFVSRD V5, R9
+ MFVSRD V6, R10
+ ADD R9, R10, R9
+ ADD R9, R18, R18
+
+tail:
+ CMP R16, $8 // 8 bytes left?
+ BLT small
+
+ MOVD (R3), R12 // load 8 bytes
+ CMPB R12, R6, R17 // compare bytes
+ POPCNTD R17, R15 // bit count
+ SRD $3, R15, R15 // byte count
+ ADD R15, R18, R18 // add to byte count
+
+next1:
+ ADD $8, R3, R3
+ SUB $8, R16, R16 // remaining bytes
+ BR tail
+
+small:
+ CMP $0, R16 // any remaining
+ BEQ done
+ MOVBZ (R3), R12 // check each remaining byte
+ CMP R12, R5
+ BNE next2
+ ADD $1, R18
+
+next2:
+ SUB $1, R16
+ ADD $1, R3 // inc address
+ BR small
+
+done:
+ MOVD R18, (R14) // return count
+ RET
diff --git a/src/internal/bytealg/equal_amd64.s b/src/internal/bytealg/equal_amd64.s
index 5263d3040d..b695d9cf42 100644
--- a/src/internal/bytealg/equal_amd64.s
+++ b/src/internal/bytealg/equal_amd64.s
@@ -79,7 +79,7 @@ TEXT memeqbody<>(SB),NOSPLIT,$0-0
JB bigloop
CMPB internal∕cpu·X86+const_offsetX86HasAVX2(SB), $1
JE hugeloop_avx2
-
+
// 64 bytes at a time using xmm registers
hugeloop:
CMPQ BX, $64
diff --git a/src/internal/bytealg/equal_amd64p32.s b/src/internal/bytealg/equal_amd64p32.s
index c841f98b2f..9be4274c11 100644
--- a/src/internal/bytealg/equal_amd64p32.s
+++ b/src/internal/bytealg/equal_amd64p32.s
@@ -80,7 +80,7 @@ TEXT memeqbody<>(SB),NOSPLIT,$0-0
CMPQ BX, $8
JB small
-
+
// 64 bytes at a time using xmm registers
hugeloop:
CMPQ BX, $64
diff --git a/src/internal/bytealg/equal_arm.s b/src/internal/bytealg/equal_arm.s
index 6b0d7deed9..e8a92b3cf2 100644
--- a/src/internal/bytealg/equal_arm.s
+++ b/src/internal/bytealg/equal_arm.s
@@ -9,7 +9,7 @@
TEXT ·Equal(SB),NOSPLIT,$0-25
MOVW a_len+4(FP), R1
MOVW b_len+16(FP), R3
-
+
CMP R1, R3 // unequal lengths are not equal
B.NE notequal
diff --git a/src/internal/bytealg/equal_arm64.s b/src/internal/bytealg/equal_arm64.s
index 30abd980c5..dd4840dae1 100644
--- a/src/internal/bytealg/equal_arm64.s
+++ b/src/internal/bytealg/equal_arm64.s
@@ -67,6 +67,7 @@ TEXT runtime·memequal_varlen(SB),NOSPLIT,$40-17
CMP R3, R4
BEQ eq
MOVD 8(R26), R5 // compiler stores size at offset 8 in the closure
+ CBZ R5, eq
MOVD R3, 8(RSP)
MOVD R4, 16(RSP)
MOVD R5, 24(RSP)
@@ -119,30 +120,41 @@ chunk16:
CBZ R3, tail
ADD R3, R0, R6 // end of chunks
chunk16_loop:
- VLD1.P (R0), [V0.D2]
- VLD1.P (R2), [V1.D2]
- VCMEQ V0.D2, V1.D2, V2.D2
+ LDP.P 16(R0), (R4, R5)
+ LDP.P 16(R2), (R7, R9)
+ EOR R4, R7
+ CBNZ R7, not_equal
+ EOR R5, R9
+ CBNZ R9, not_equal
CMP R0, R6
- VMOV V2.D[0], R4
- VMOV V2.D[1], R5
- CBZ R4, not_equal
- CBZ R5, not_equal
BNE chunk16_loop
AND $0xf, R1, R1
CBZ R1, equal
tail:
// special compare of tail with length < 16
TBZ $3, R1, lt_8
- MOVD.P 8(R0), R4
- MOVD.P 8(R2), R5
- CMP R4, R5
- BNE not_equal
+ MOVD (R0), R4
+ MOVD (R2), R5
+ EOR R4, R5
+ CBNZ R5, not_equal
+ SUB $8, R1, R6 // offset of the last 8 bytes
+ MOVD (R0)(R6), R4
+ MOVD (R2)(R6), R5
+ EOR R4, R5
+ CBNZ R5, not_equal
+ B equal
lt_8:
TBZ $2, R1, lt_4
- MOVWU.P 4(R0), R4
- MOVWU.P 4(R2), R5
- CMP R4, R5
- BNE not_equal
+ MOVWU (R0), R4
+ MOVWU (R2), R5
+ EOR R4, R5
+ CBNZ R5, not_equal
+ SUB $4, R1, R6 // offset of the last 4 bytes
+ MOVWU (R0)(R6), R4
+ MOVWU (R2)(R6), R5
+ EOR R4, R5
+ CBNZ R5, not_equal
+ B equal
lt_4:
TBZ $1, R1, lt_2
MOVHU.P 2(R0), R4
@@ -150,7 +162,7 @@ lt_4:
CMP R4, R5
BNE not_equal
lt_2:
- TBZ $0, R1, equal
+ TBZ $0, R1, equal
one:
MOVBU (R0), R4
MOVBU (R2), R5
diff --git a/src/internal/bytealg/indexbyte_ppc64x.s b/src/internal/bytealg/indexbyte_ppc64x.s
index ccf897d99c..61b33bc9cb 100644
--- a/src/internal/bytealg/indexbyte_ppc64x.s
+++ b/src/internal/bytealg/indexbyte_ppc64x.s
@@ -38,14 +38,14 @@ TEXT strings·IndexByte(SB),NOSPLIT|NOFRAME,$0-32
BR indexbytebody<>(SB)
TEXT indexbytebody<>(SB),NOSPLIT|NOFRAME,$0-0
- DCBT (R3) // Prepare cache line.
MOVD R3,R17 // Save base address for calculating the index later.
RLDICR $0,R3,$60,R8 // Align address to doubleword boundary in R8.
RLDIMI $8,R5,$48,R5 // Replicating the byte across the register.
ADD R4,R3,R7 // Last acceptable address in R7.
+ DCBT (R8) // Prepare cache line.
RLDIMI $16,R5,$32,R5
- CMPU R4,$32 // Check if it's a small string (<32 bytes). Those will be processed differently.
+ CMPU R4,$32 // Check if it's a small string (≤32 bytes). Those will be processed differently.
MOVD $-1,R9
WORD $0x54661EB8 // Calculate padding in R6 (rlwinm r6,r3,3,26,28).
RLDIMI $32,R5,$0,R5
@@ -56,7 +56,7 @@ TEXT indexbytebody<>(SB),NOSPLIT|NOFRAME,$0-0
#else
SRD R6,R9,R9 // Same for Big Endian
#endif
- BLE small_string // Jump to the small string case if it's <32 bytes.
+ BLE small_string // Jump to the small string case if it's ≤32 bytes.
// If we are 64-byte aligned, branch to qw_align just to get the auxiliary values
// in V0, V1 and V10, then branch to the preloop.
@@ -97,7 +97,7 @@ qw_align:
LVSL (R0+R0),V11
VSLB V11,V10,V10
VSPLTB $7,V1,V1 // Replicate byte across V1
- CMPU R4, $64 // If len <= 64, don't use the vectorized loop
+ CMPU R4, $64 // If len ≤ 64, don't use the vectorized loop
BLE tail
// We will load 4 quardwords per iteration in the loop, so check for
@@ -131,7 +131,7 @@ qw_align:
// 64-byte aligned. Prepare for the main loop.
preloop:
CMPU R4,$64
- BLE tail // If len <= 64, don't use the vectorized loop
+ BLE tail // If len ≤ 64, don't use the vectorized loop
// We are now aligned to a 64-byte boundary. We will load 4 quadwords
// per loop iteration. The last doubleword is in R10, so our loop counter
@@ -140,30 +140,34 @@ preloop:
SRD $6,R6,R9 // Loop counter in R9
MOVD R9,CTR
+ ADD $-64,R8,R8 // Adjust index for loop entry
MOVD $16,R11 // Load offsets for the vector loads
MOVD $32,R9
MOVD $48,R7
// Main loop we will load 64 bytes per iteration
loop:
+ ADD $64,R8,R8 // Fuse addi+lvx for performance
LVX (R8+R0),V2 // Load 4 16-byte vectors
- LVX (R11+R8),V3
- LVX (R9+R8),V4
- LVX (R7+R8),V5
+ LVX (R8+R11),V3
VCMPEQUB V1,V2,V6 // Look for byte in each vector
VCMPEQUB V1,V3,V7
+
+ LVX (R8+R9),V4
+ LVX (R8+R7),V5
VCMPEQUB V1,V4,V8
VCMPEQUB V1,V5,V9
+
VOR V6,V7,V11 // Compress the result in a single vector
VOR V8,V9,V12
- VOR V11,V12,V11
- VCMPEQUBCC V0,V11,V11 // Check for byte
+ VOR V11,V12,V13
+ VCMPEQUBCC V0,V13,V14 // Check for byte
BGE CR6,found
- ADD $64,R8,R8
BC 16,0,loop // bdnz loop
- // Handle the tailing bytes or R4 <= 64
+ // Handle the tailing bytes or R4 ≤ 64
RLDICL $0,R6,$58,R4
+ ADD $64,R8,R8
tail:
CMPU R4,$0
BEQ notfound
diff --git a/src/internal/goroot/gc.go b/src/internal/goroot/gc.go
new file mode 100644
index 0000000000..b9da9a5301
--- /dev/null
+++ b/src/internal/goroot/gc.go
@@ -0,0 +1,140 @@
+// Copyright 2018 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 gc
+
+package goroot
+
+import (
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strings"
+ "sync"
+)
+
+// IsStandardPackage returns whether path is a standard package,
+// given goroot and compiler.
+func IsStandardPackage(goroot, compiler, path string) bool {
+ switch compiler {
+ case "gc":
+ dir := filepath.Join(goroot, "src", path)
+ _, err := os.Stat(dir)
+ return err == nil
+ case "gccgo":
+ return gccgoSearch.isStandard(path)
+ default:
+ panic("unknown compiler " + compiler)
+ }
+}
+
+// gccgoSearch holds the gccgo search directories.
+type gccgoDirs struct {
+ once sync.Once
+ dirs []string
+}
+
+// gccgoSearch is used to check whether a gccgo package exists in the
+// standard library.
+var gccgoSearch gccgoDirs
+
+// init finds the gccgo search directories. If this fails it leaves dirs == nil.
+func (gd *gccgoDirs) init() {
+ gccgo := os.Getenv("GCCGO")
+ if gccgo == "" {
+ gccgo = "gccgo"
+ }
+ bin, err := exec.LookPath(gccgo)
+ if err != nil {
+ return
+ }
+
+ allDirs, err := exec.Command(bin, "-print-search-dirs").Output()
+ if err != nil {
+ return
+ }
+ versionB, err := exec.Command(bin, "-dumpversion").Output()
+ if err != nil {
+ return
+ }
+ version := strings.TrimSpace(string(versionB))
+ machineB, err := exec.Command(bin, "-dumpmachine").Output()
+ if err != nil {
+ return
+ }
+ machine := strings.TrimSpace(string(machineB))
+
+ dirsEntries := strings.Split(string(allDirs), "\n")
+ const prefix = "libraries: ="
+ var dirs []string
+ for _, dirEntry := range dirsEntries {
+ if strings.HasPrefix(dirEntry, prefix) {
+ dirs = filepath.SplitList(strings.TrimPrefix(dirEntry, prefix))
+ break
+ }
+ }
+ if len(dirs) == 0 {
+ return
+ }
+
+ var lastDirs []string
+ for _, dir := range dirs {
+ goDir := filepath.Join(dir, "go", version)
+ if fi, err := os.Stat(goDir); err == nil && fi.IsDir() {
+ gd.dirs = append(gd.dirs, goDir)
+ goDir = filepath.Join(goDir, machine)
+ if fi, err = os.Stat(goDir); err == nil && fi.IsDir() {
+ gd.dirs = append(gd.dirs, goDir)
+ }
+ }
+ if fi, err := os.Stat(dir); err == nil && fi.IsDir() {
+ lastDirs = append(lastDirs, dir)
+ }
+ }
+ gd.dirs = append(gd.dirs, lastDirs...)
+}
+
+// isStandard returns whether path is a standard library for gccgo.
+func (gd *gccgoDirs) isStandard(path string) bool {
+ // Quick check: if the first path component has a '.', it's not
+ // in the standard library. This skips most GOPATH directories.
+ i := strings.Index(path, "/")
+ if i < 0 {
+ i = len(path)
+ }
+ if strings.Contains(path[:i], ".") {
+ return false
+ }
+
+ if path == "unsafe" {
+ // Special case.
+ return true
+ }
+
+ gd.once.Do(gd.init)
+ if gd.dirs == nil {
+ // We couldn't find the gccgo search directories.
+ // Best guess, since the first component did not contain
+ // '.', is that this is a standard library package.
+ return true
+ }
+
+ for _, dir := range gd.dirs {
+ full := filepath.Join(dir, path)
+ pkgdir, pkg := filepath.Split(full)
+ for _, p := range [...]string{
+ full,
+ full + ".gox",
+ pkgdir + "lib" + pkg + ".so",
+ pkgdir + "lib" + pkg + ".a",
+ full + ".o",
+ } {
+ if fi, err := os.Stat(p); err == nil && !fi.IsDir() {
+ return true
+ }
+ }
+ }
+
+ return false
+}
diff --git a/src/internal/goroot/gccgo.go b/src/internal/goroot/gccgo.go
new file mode 100644
index 0000000000..098e77d893
--- /dev/null
+++ b/src/internal/goroot/gccgo.go
@@ -0,0 +1,27 @@
+// Copyright 2018 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 gccgo
+
+package goroot
+
+import (
+ "os"
+ "path/filepath"
+)
+
+// IsStandardPackage returns whether path is a standard package,
+// given goroot and compiler.
+func IsStandardPackage(goroot, compiler, path string) bool {
+ switch compiler {
+ case "gc":
+ dir := filepath.Join(goroot, "src", path)
+ _, err := os.Stat(dir)
+ return err == nil
+ case "gccgo":
+ return stdpkg[path]
+ default:
+ panic("unknown compiler " + compiler)
+ }
+}
diff --git a/src/internal/poll/export_posix_test.go b/src/internal/poll/export_posix_test.go
index 73b2c11e1e..6b9bb8b7d0 100644
--- a/src/internal/poll/export_posix_test.go
+++ b/src/internal/poll/export_posix_test.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
+// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
// Export guts for testing on posix.
// Since testing imports os and os imports internal/poll,
diff --git a/src/internal/poll/fd_poll_runtime.go b/src/internal/poll/fd_poll_runtime.go
index 87a01a8b69..b91cbe40e4 100644
--- a/src/internal/poll/fd_poll_runtime.go
+++ b/src/internal/poll/fd_poll_runtime.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin dragonfly freebsd linux netbsd openbsd windows solaris
+// +build aix darwin dragonfly freebsd linux netbsd openbsd windows solaris
package poll
diff --git a/src/internal/poll/fd_posix.go b/src/internal/poll/fd_posix.go
index f899a74876..b43ad51799 100644
--- a/src/internal/poll/fd_posix.go
+++ b/src/internal/poll/fd_posix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris windows
+// +build aix darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris windows
package poll
diff --git a/src/internal/poll/fd_posix_test.go b/src/internal/poll/fd_posix_test.go
index cbe015edbd..246d4989e1 100644
--- a/src/internal/poll/fd_posix_test.go
+++ b/src/internal/poll/fd_posix_test.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
+// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
package poll_test
diff --git a/src/internal/poll/fd_unix.go b/src/internal/poll/fd_unix.go
index b311049ad7..21966ad466 100644
--- a/src/internal/poll/fd_unix.go
+++ b/src/internal/poll/fd_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris
+// +build aix darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris
package poll
diff --git a/src/internal/poll/fd_windows.go b/src/internal/poll/fd_windows.go
index b08cec2625..19d9a12dad 100644
--- a/src/internal/poll/fd_windows.go
+++ b/src/internal/poll/fd_windows.go
@@ -116,11 +116,17 @@ func (o *operation) InitBufs(buf *[][]byte) {
o.bufs = o.bufs[:0]
}
for _, b := range *buf {
- var p *byte
+ if len(b) == 0 {
+ o.bufs = append(o.bufs, syscall.WSABuf{})
+ continue
+ }
+ for len(b) > maxRW {
+ o.bufs = append(o.bufs, syscall.WSABuf{Len: maxRW, Buf: &b[0]})
+ b = b[maxRW:]
+ }
if len(b) > 0 {
- p = &b[0]
+ o.bufs = append(o.bufs, syscall.WSABuf{Len: uint32(len(b)), Buf: &b[0]})
}
- o.bufs = append(o.bufs, syscall.WSABuf{Len: uint32(len(b)), Buf: p})
}
}
@@ -461,6 +467,11 @@ func (fd *FD) Shutdown(how int) error {
return syscall.Shutdown(fd.Sysfd, how)
}
+// Windows ReadFile and WSARecv use DWORD (uint32) parameter to pass buffer length.
+// This prevents us reading blocks larger than 4GB.
+// See golang.org/issue/26923.
+const maxRW = 1 << 30 // 1GB is large enough and keeps subsequent reads aligned
+
// Read implements io.Reader.
func (fd *FD) Read(buf []byte) (int, error) {
if err := fd.readLock(); err != nil {
@@ -468,6 +479,10 @@ func (fd *FD) Read(buf []byte) (int, error) {
}
defer fd.readUnlock()
+ if len(buf) > maxRW {
+ buf = buf[:maxRW]
+ }
+
var n int
var err error
if fd.isFile || fd.isDir || fd.isConsole {
@@ -581,6 +596,10 @@ func (fd *FD) Pread(b []byte, off int64) (int, error) {
}
defer fd.decref()
+ if len(b) > maxRW {
+ b = b[:maxRW]
+ }
+
fd.l.Lock()
defer fd.l.Unlock()
curoffset, e := syscall.Seek(fd.Sysfd, 0, io.SeekCurrent)
@@ -611,6 +630,9 @@ func (fd *FD) ReadFrom(buf []byte) (int, syscall.Sockaddr, error) {
if len(buf) == 0 {
return 0, nil, nil
}
+ if len(buf) > maxRW {
+ buf = buf[:maxRW]
+ }
if err := fd.readLock(); err != nil {
return 0, nil, err
}
@@ -639,30 +661,42 @@ func (fd *FD) Write(buf []byte) (int, error) {
}
defer fd.writeUnlock()
- var n int
- var err error
- if fd.isFile || fd.isDir || fd.isConsole {
- fd.l.Lock()
- defer fd.l.Unlock()
- if fd.isConsole {
- n, err = fd.writeConsole(buf)
+ ntotal := 0
+ for len(buf) > 0 {
+ b := buf
+ if len(b) > maxRW {
+ b = b[:maxRW]
+ }
+ var n int
+ var err error
+ if fd.isFile || fd.isDir || fd.isConsole {
+ fd.l.Lock()
+ defer fd.l.Unlock()
+ if fd.isConsole {
+ n, err = fd.writeConsole(b)
+ } else {
+ n, err = syscall.Write(fd.Sysfd, b)
+ }
+ if err != nil {
+ n = 0
+ }
} else {
- n, err = syscall.Write(fd.Sysfd, buf)
+ if race.Enabled {
+ race.ReleaseMerge(unsafe.Pointer(&ioSync))
+ }
+ o := &fd.wop
+ o.InitBuf(b)
+ n, err = wsrv.ExecIO(o, func(o *operation) error {
+ return syscall.WSASend(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, &o.o, nil)
+ })
}
+ ntotal += n
if err != nil {
- n = 0
- }
- } else {
- if race.Enabled {
- race.ReleaseMerge(unsafe.Pointer(&ioSync))
+ return ntotal, err
}
- o := &fd.wop
- o.InitBuf(buf)
- n, err = wsrv.ExecIO(o, func(o *operation) error {
- return syscall.WSASend(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, &o.o, nil)
- })
+ buf = buf[n:]
}
- return n, err
+ return ntotal, nil
}
// writeConsole writes len(b) bytes to the console File.
@@ -709,7 +743,7 @@ func (fd *FD) writeConsole(b []byte) (int, error) {
}
// Pwrite emulates the Unix pwrite system call.
-func (fd *FD) Pwrite(b []byte, off int64) (int, error) {
+func (fd *FD) Pwrite(buf []byte, off int64) (int, error) {
// Call incref, not writeLock, because since pwrite specifies the
// offset it is independent from other writes.
if err := fd.incref(); err != nil {
@@ -724,16 +758,27 @@ func (fd *FD) Pwrite(b []byte, off int64) (int, error) {
return 0, e
}
defer syscall.Seek(fd.Sysfd, curoffset, io.SeekStart)
- o := syscall.Overlapped{
- OffsetHigh: uint32(off >> 32),
- Offset: uint32(off),
- }
- var done uint32
- e = syscall.WriteFile(fd.Sysfd, b, &done, &o)
- if e != nil {
- return 0, e
+
+ ntotal := 0
+ for len(buf) > 0 {
+ b := buf
+ if len(b) > maxRW {
+ b = b[:maxRW]
+ }
+ var n uint32
+ o := syscall.Overlapped{
+ OffsetHigh: uint32(off >> 32),
+ Offset: uint32(off),
+ }
+ e = syscall.WriteFile(fd.Sysfd, b, &n, &o)
+ ntotal += int(n)
+ if e != nil {
+ return ntotal, e
+ }
+ buf = buf[n:]
+ off += int64(n)
}
- return int(done), nil
+ return ntotal, nil
}
// Writev emulates the Unix writev system call.
@@ -765,13 +810,37 @@ func (fd *FD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) {
return 0, err
}
defer fd.writeUnlock()
- o := &fd.wop
- o.InitBuf(buf)
- o.sa = sa
- n, err := wsrv.ExecIO(o, func(o *operation) error {
- return syscall.WSASendto(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, o.sa, &o.o, nil)
- })
- return n, err
+
+ if len(buf) == 0 {
+ // handle zero-byte payload
+ o := &fd.wop
+ o.InitBuf(buf)
+ o.sa = sa
+ n, err := wsrv.ExecIO(o, func(o *operation) error {
+ return syscall.WSASendto(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, o.sa, &o.o, nil)
+ })
+ return n, err
+ }
+
+ ntotal := 0
+ for len(buf) > 0 {
+ b := buf
+ if len(b) > maxRW {
+ b = b[:maxRW]
+ }
+ o := &fd.wop
+ o.InitBuf(b)
+ o.sa = sa
+ n, err := wsrv.ExecIO(o, func(o *operation) error {
+ return syscall.WSASendto(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, o.sa, &o.o, nil)
+ })
+ ntotal += int(n)
+ if err != nil {
+ return ntotal, err
+ }
+ buf = buf[n:]
+ }
+ return ntotal, nil
}
// Call ConnectEx. This doesn't need any locking, since it is only
@@ -986,6 +1055,10 @@ func (fd *FD) ReadMsg(p []byte, oob []byte) (int, int, int, syscall.Sockaddr, er
}
defer fd.readUnlock()
+ if len(p) > maxRW {
+ p = p[:maxRW]
+ }
+
o := &fd.rop
o.InitMsg(p, oob)
o.rsa = new(syscall.RawSockaddrAny)
@@ -1004,6 +1077,10 @@ func (fd *FD) ReadMsg(p []byte, oob []byte) (int, int, int, syscall.Sockaddr, er
// WriteMsg wraps the WSASendMsg network call.
func (fd *FD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (int, int, error) {
+ if len(p) > maxRW {
+ return 0, 0, errors.New("packet is too large (only 1GB is allowed)")
+ }
+
if err := fd.writeLock(); err != nil {
return 0, 0, err
}
diff --git a/src/internal/poll/hook_unix.go b/src/internal/poll/hook_unix.go
index c2ad17eb1a..a7512b1255 100644
--- a/src/internal/poll/hook_unix.go
+++ b/src/internal/poll/hook_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris
+// +build aix darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris
package poll
diff --git a/src/internal/poll/sockopt.go b/src/internal/poll/sockopt.go
index f86ce707a1..bb5ea02c0a 100644
--- a/src/internal/poll/sockopt.go
+++ b/src/internal/poll/sockopt.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
+// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows
package poll
diff --git a/src/internal/poll/sockopt_unix.go b/src/internal/poll/sockopt_unix.go
index b33644db76..bd942c2934 100644
--- a/src/internal/poll/sockopt_unix.go
+++ b/src/internal/poll/sockopt_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
package poll
diff --git a/src/internal/poll/sockoptip.go b/src/internal/poll/sockoptip.go
index 1ee490c257..c55a1e3c5b 100644
--- a/src/internal/poll/sockoptip.go
+++ b/src/internal/poll/sockoptip.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
+// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows
package poll
diff --git a/src/internal/poll/splice_linux.go b/src/internal/poll/splice_linux.go
index aa237e587a..4f97298417 100644
--- a/src/internal/poll/splice_linux.go
+++ b/src/internal/poll/splice_linux.go
@@ -32,8 +32,6 @@ func Splice(dst, src *FD, remain int64) (written int64, handled bool, sc string,
return 0, false, sc, err
}
defer destroyTempPipe(prfd, pwfd)
- // From here on, the operation should be considered handled,
- // even if Splice doesn't transfer any data.
var inPipe, n int
for err == nil && remain > 0 {
max := maxSpliceSize
@@ -41,9 +39,18 @@ func Splice(dst, src *FD, remain int64) (written int64, handled bool, sc string,
max = int(remain)
}
inPipe, err = spliceDrain(pwfd, src, max)
+ // The operation is considered handled if splice returns no
+ // error, or an error other than EINVAL. An EINVAL means the
+ // kernel does not support splice for the socket type of src.
+ // The failed syscall does not consume any data so it is safe
+ // to fall back to a generic copy.
+ //
// spliceDrain should never return EAGAIN, so if err != nil,
- // Splice cannot continue. If inPipe == 0 && err == nil,
- // src is at EOF, and the transfer is complete.
+ // Splice cannot continue.
+ //
+ // If inPipe == 0 && err == nil, src is at EOF, and the
+ // transfer is complete.
+ handled = handled || (err != syscall.EINVAL)
if err != nil || (inPipe == 0 && err == nil) {
break
}
@@ -54,7 +61,7 @@ func Splice(dst, src *FD, remain int64) (written int64, handled bool, sc string,
}
}
if err != nil {
- return written, true, "splice", err
+ return written, handled, "splice", err
}
return written, true, "", nil
}
diff --git a/src/internal/poll/sys_cloexec.go b/src/internal/poll/sys_cloexec.go
index 7bafa0d81a..64e46127d4 100644
--- a/src/internal/poll/sys_cloexec.go
+++ b/src/internal/poll/sys_cloexec.go
@@ -5,7 +5,7 @@
// This file implements sysSocket and accept for platforms that do not
// provide a fast path for setting SetNonblock and CloseOnExec.
-// +build darwin js,wasm nacl solaris
+// +build aix darwin js,wasm nacl solaris
package poll
diff --git a/src/internal/syscall/unix/nonblocking.go b/src/internal/syscall/unix/nonblocking.go
index 1db3394432..233b6689d1 100644
--- a/src/internal/syscall/unix/nonblocking.go
+++ b/src/internal/syscall/unix/nonblocking.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
package unix
diff --git a/src/io/io.go b/src/io/io.go
index 72b75813a5..2010770e6a 100644
--- a/src/io/io.go
+++ b/src/io/io.go
@@ -278,16 +278,16 @@ type RuneScanner interface {
UnreadRune() error
}
-// stringWriter is the interface that wraps the WriteString method.
-type stringWriter interface {
+// StringWriter is the interface that wraps the WriteString method.
+type StringWriter interface {
WriteString(s string) (n int, err error)
}
// WriteString writes the contents of the string s to w, which accepts a slice of bytes.
-// If w implements a WriteString method, it is invoked directly.
+// If w implements StringWriter, its WriteString method is invoked directly.
// Otherwise, w.Write is called exactly once.
func WriteString(w Writer, s string) (n int, err error) {
- if sw, ok := w.(stringWriter); ok {
+ if sw, ok := w.(StringWriter); ok {
return sw.WriteString(s)
}
return w.Write([]byte(s))
diff --git a/src/io/multi.go b/src/io/multi.go
index 65f99099ca..24ee71e4ca 100644
--- a/src/io/multi.go
+++ b/src/io/multi.go
@@ -69,12 +69,12 @@ func (t *multiWriter) Write(p []byte) (n int, err error) {
return len(p), nil
}
-var _ stringWriter = (*multiWriter)(nil)
+var _ StringWriter = (*multiWriter)(nil)
func (t *multiWriter) WriteString(s string) (n int, err error) {
var p []byte // lazily initialized if/when needed
for _, w := range t.writers {
- if sw, ok := w.(stringWriter); ok {
+ if sw, ok := w.(StringWriter); ok {
n, err = sw.WriteString(s)
} else {
if p == nil {
diff --git a/src/math/all_test.go b/src/math/all_test.go
index 00f2058ea6..6a6d8bf6d0 100644
--- a/src/math/all_test.go
+++ b/src/math/all_test.go
@@ -3635,3 +3635,41 @@ func BenchmarkYn(b *testing.B) {
}
GlobalF = x
}
+
+func BenchmarkFloat64bits(b *testing.B) {
+ y := uint64(0)
+ for i := 0; i < b.N; i++ {
+ y = Float64bits(roundNeg)
+ }
+ GlobalI = int(y)
+}
+
+var roundUint64 = uint64(5)
+
+func BenchmarkFloat64frombits(b *testing.B) {
+ x := 0.0
+ for i := 0; i < b.N; i++ {
+ x = Float64frombits(roundUint64)
+ }
+ GlobalF = x
+}
+
+var roundFloat32 = float32(-2.5)
+
+func BenchmarkFloat32bits(b *testing.B) {
+ y := uint32(0)
+ for i := 0; i < b.N; i++ {
+ y = Float32bits(roundFloat32)
+ }
+ GlobalI = int(y)
+}
+
+var roundUint32 = uint32(5)
+
+func BenchmarkFloat32frombits(b *testing.B) {
+ x := float32(0.0)
+ for i := 0; i < b.N; i++ {
+ x = Float32frombits(roundUint32)
+ }
+ GlobalF = float64(x)
+}
diff --git a/src/math/big/arith_386.s b/src/math/big/arith_386.s
index 6c080f074a..864fbc554e 100644
--- a/src/math/big/arith_386.s
+++ b/src/math/big/arith_386.s
@@ -183,7 +183,7 @@ L9: MOVL AX, DX // w = w1
SHRL CX, DX:AX // w>>s | w1<<ŝ
MOVL DX, (DI)(BX*4) // z[i] = w>>s | w1<<ŝ
ADDL $1, BX // i++
-
+
E9: CMPL BX, BP
JL L9 // i < n-1
diff --git a/src/math/big/arith_amd64.s b/src/math/big/arith_amd64.s
index 1b950a4a25..e9c8887523 100644
--- a/src/math/big/arith_amd64.s
+++ b/src/math/big/arith_amd64.s
@@ -324,10 +324,10 @@ TEXT ·mulAddVWW(SB),NOSPLIT,$0
MOVQ r+56(FP), CX // c = r
MOVQ z_len+8(FP), R11
MOVQ $0, BX // i = 0
-
+
CMPQ R11, $4
JL E5
-
+
U5: // i+4 <= n
// regular loop body unrolled 4x
MOVQ (0*8)(R8)(BX*8), AX
@@ -355,7 +355,7 @@ U5: // i+4 <= n
MOVQ AX, (3*8)(R10)(BX*8)
MOVQ DX, CX
ADDQ $4, BX // i += 4
-
+
LEAQ 4(BX), DX
CMPQ DX, R11
JLE U5
diff --git a/src/math/big/arith_arm.s b/src/math/big/arith_arm.s
index ba65fd2b1f..33aa36f709 100644
--- a/src/math/big/arith_arm.s
+++ b/src/math/big/arith_arm.s
@@ -123,7 +123,7 @@ TEXT ·shlVU(SB),NOSPLIT,$0
MOVW z_len+4(FP), R5
TEQ $0, R5
BEQ X7
-
+
MOVW z+0(FP), R1
MOVW x+12(FP), R2
ADD R5<<2, R2, R2
@@ -135,7 +135,7 @@ TEXT ·shlVU(SB),NOSPLIT,$0
MOVW $32, R4
SUB R3, R4
MOVW $0, R7
-
+
MOVW.W -4(R2), R6
MOVW R6<<R3, R7
MOVW R6>>R4, R6
diff --git a/src/math/big/arith_s390x.s b/src/math/big/arith_s390x.s
index 4520d161d7..9156d9debe 100644
--- a/src/math/big/arith_s390x.s
+++ b/src/math/big/arith_s390x.s
@@ -54,7 +54,7 @@ TEXT ·divWW(SB),NOSPLIT,$0
TEXT ·addVV(SB),NOSPLIT,$0
MOVD addvectorfacility+0x00(SB),R1
BR (R1)
-
+
TEXT ·addVV_check(SB),NOSPLIT, $0
MOVB ·hasVX(SB), R1
CMPBEQ R1, $1, vectorimpl // vectorfacility = 1, vector supported
@@ -89,7 +89,7 @@ TEXT ·addVV_vec(SB),NOSPLIT,$0
BLT v1
SUB $12, R3 // n -= 16
BLT A1 // if n < 0 goto A1
-
+
MOVD R8, R5
MOVD R9, R6
MOVD R2, R7
@@ -291,7 +291,7 @@ E1n: NEG R4, R4
TEXT ·subVV(SB),NOSPLIT,$0
MOVD subvectorfacility+0x00(SB),R1
BR (R1)
-
+
TEXT ·subVV_check(SB),NOSPLIT,$0
MOVB ·hasVX(SB), R1
CMPBEQ R1, $1, vectorimpl // vectorfacility = 1, vector supported
@@ -321,7 +321,7 @@ TEXT ·subVV_vec(SB),NOSPLIT,$0
MOVD $0, R4 // c = 0
MOVD $0, R0 // make sure it's zero
MOVD $0, R10 // i = 0
-
+
// s/JL/JMP/ below to disable the unrolled loop
SUB $4, R3 // n -= 4
BLT v1 // if n < 0 goto v1
@@ -413,7 +413,7 @@ UU1: VLM 0(R5), V1, V4 // 64-bytes into V1..V8
A1: ADD $12, R3 // n += 16
BLT v1 // if n < 0 goto v1
-
+
U1: // n >= 0
// regular loop body unrolled 4x
MOVD 0(R8)(R10*1), R5
@@ -532,7 +532,7 @@ E1: NEG R4, R4
TEXT ·addVW(SB),NOSPLIT,$0
MOVD addwvectorfacility+0x00(SB),R1
BR (R1)
-
+
TEXT ·addVW_check(SB),NOSPLIT,$0
MOVB ·hasVX(SB), R1
CMPBEQ R1, $1, vectorimpl // vectorfacility = 1, vector supported
@@ -742,7 +742,7 @@ E4: MOVD R4, c+56(FP) // return c
TEXT ·subVW(SB),NOSPLIT,$0
MOVD subwvectorfacility+0x00(SB),R1
BR (R1)
-
+
TEXT ·subVW_check(SB),NOSPLIT,$0
MOVB ·hasVX(SB), R1
CMPBEQ R1, $1, vectorimpl // vectorfacility = 1, vector supported
diff --git a/src/math/bits/bits.go b/src/math/bits/bits.go
index 989baacc13..58cf52d2a7 100644
--- a/src/math/bits/bits.go
+++ b/src/math/bits/bits.go
@@ -328,3 +328,197 @@ func Len64(x uint64) (n int) {
}
return n + int(len8tab[x])
}
+
+// --- Add with carry ---
+
+// Add returns the sum with carry of x, y and carry: sum = x + y + carry.
+// The carry input must be 0 or 1; otherwise the behavior is undefined.
+// The carryOut output is guaranteed to be 0 or 1.
+func Add(x, y, carry uint) (sum, carryOut uint) {
+ yc := y + carry
+ sum = x + yc
+ if sum < x || yc < y {
+ carryOut = 1
+ }
+ return
+}
+
+// Add32 returns the sum with carry of x, y and carry: sum = x + y + carry.
+// The carry input must be 0 or 1; otherwise the behavior is undefined.
+// The carryOut output is guaranteed to be 0 or 1.
+func Add32(x, y, carry uint32) (sum, carryOut uint32) {
+ yc := y + carry
+ sum = x + yc
+ if sum < x || yc < y {
+ carryOut = 1
+ }
+ return
+}
+
+// Add64 returns the sum with carry of x, y and carry: sum = x + y + carry.
+// The carry input must be 0 or 1; otherwise the behavior is undefined.
+// The carryOut output is guaranteed to be 0 or 1.
+func Add64(x, y, carry uint64) (sum, carryOut uint64) {
+ yc := y + carry
+ sum = x + yc
+ if sum < x || yc < y {
+ carryOut = 1
+ }
+ return
+}
+
+// --- Subtract with borrow ---
+
+// Sub returns the difference of x, y and borrow: diff = x - y - borrow.
+// The borrow input must be 0 or 1; otherwise the behavior is undefined.
+// The borrowOut output is guaranteed to be 0 or 1.
+func Sub(x, y, borrow uint) (diff, borrowOut uint) {
+ yb := y + borrow
+ diff = x - yb
+ if diff > x || yb < y {
+ borrowOut = 1
+ }
+ return
+}
+
+// Sub32 returns the difference of x, y and borrow, diff = x - y - borrow.
+// The borrow input must be 0 or 1; otherwise the behavior is undefined.
+// The borrowOut output is guaranteed to be 0 or 1.
+func Sub32(x, y, borrow uint32) (diff, borrowOut uint32) {
+ yb := y + borrow
+ diff = x - yb
+ if diff > x || yb < y {
+ borrowOut = 1
+ }
+ return
+}
+
+// Sub64 returns the difference of x, y and borrow: diff = x - y - borrow.
+// The borrow input must be 0 or 1; otherwise the behavior is undefined.
+// The borrowOut output is guaranteed to be 0 or 1.
+func Sub64(x, y, borrow uint64) (diff, borrowOut uint64) {
+ yb := y + borrow
+ diff = x - yb
+ if diff > x || yb < y {
+ borrowOut = 1
+ }
+ return
+}
+
+// --- Full-width multiply ---
+
+// Mul returns the full-width product of x and y: (hi, lo) = x * y
+// with the product bits' upper half returned in hi and the lower
+// half returned in lo.
+func Mul(x, y uint) (hi, lo uint) {
+ if UintSize == 32 {
+ h, l := Mul32(uint32(x), uint32(y))
+ return uint(h), uint(l)
+ }
+ h, l := Mul64(uint64(x), uint64(y))
+ return uint(h), uint(l)
+}
+
+// Mul32 returns the 64-bit product of x and y: (hi, lo) = x * y
+// with the product bits' upper half returned in hi and the lower
+// half returned in lo.
+func Mul32(x, y uint32) (hi, lo uint32) {
+ tmp := uint64(x) * uint64(y)
+ hi, lo = uint32(tmp>>32), uint32(tmp)
+ return
+}
+
+// Mul64 returns the 128-bit product of x and y: (hi, lo) = x * y
+// with the product bits' upper half returned in hi and the lower
+// half returned in lo.
+func Mul64(x, y uint64) (hi, lo uint64) {
+ const mask32 = 1<<32 - 1
+ x0 := x & mask32
+ x1 := x >> 32
+ y0 := y & mask32
+ y1 := y >> 32
+ w0 := x0 * y0
+ t := x1*y0 + w0>>32
+ w1 := t & mask32
+ w2 := t >> 32
+ w1 += x0 * y1
+ hi = x1*y1 + w2 + w1>>32
+ lo = x * y
+ return
+}
+
+// --- Full-width divide ---
+
+// Div returns the quotient and remainder of (hi, lo) divided by y:
+// quo = (hi, lo)/y, rem = (hi, lo)%y with the dividend bits' upper
+// half in parameter hi and the lower half in parameter lo.
+// hi must be < y otherwise the behavior is undefined (the quotient
+// won't fit into quo).
+func Div(hi, lo, y uint) (quo, rem uint) {
+ if UintSize == 32 {
+ q, r := Div32(uint32(hi), uint32(lo), uint32(y))
+ return uint(q), uint(r)
+ }
+ q, r := Div64(uint64(hi), uint64(lo), uint64(y))
+ return uint(q), uint(r)
+}
+
+// Div32 returns the quotient and remainder of (hi, lo) divided by y:
+// quo = (hi, lo)/y, rem = (hi, lo)%y with the dividend bits' upper
+// half in parameter hi and the lower half in parameter lo.
+// hi must be < y otherwise the behavior is undefined (the quotient
+// won't fit into quo).
+func Div32(hi, lo, y uint32) (quo, rem uint32) {
+ z := uint64(hi)<<32 | uint64(lo)
+ quo, rem = uint32(z/uint64(y)), uint32(z%uint64(y))
+ return
+}
+
+// Div64 returns the quotient and remainder of (hi, lo) divided by y:
+// quo = (hi, lo)/y, rem = (hi, lo)%y with the dividend bits' upper
+// half in parameter hi and the lower half in parameter lo.
+// hi must be < y otherwise the behavior is undefined (the quotient
+// won't fit into quo).
+func Div64(hi, lo, y uint64) (quo, rem uint64) {
+ const (
+ two32 = 1 << 32
+ mask32 = two32 - 1
+ )
+ if hi >= y {
+ return 1<<64 - 1, 1<<64 - 1
+ }
+
+ s := uint(LeadingZeros64(y))
+ y <<= s
+
+ yn1 := y >> 32
+ yn0 := y & mask32
+ un32 := hi<<s | lo>>(64-s)
+ un10 := lo << s
+ un1 := un10 >> 32
+ un0 := un10 & mask32
+ q1 := un32 / yn1
+ rhat := un32 - q1*yn1
+
+ for q1 >= two32 || q1*yn0 > two32*rhat+un1 {
+ q1--
+ rhat += yn1
+ if rhat >= two32 {
+ break
+ }
+ }
+
+ un21 := un32*two32 + un1 - q1*y
+ q0 := un21 / yn1
+ rhat = un21 - q0*yn1
+
+ for q0 >= two32 || q0*yn0 > two32*rhat+un0 {
+ q0--
+ rhat += yn1
+ if rhat >= two32 {
+ break
+ }
+ }
+
+ return q1*two32 + q0, (un21*two32 + un0 - q0*y) >> s
+}
diff --git a/src/math/bits/bits_test.go b/src/math/bits/bits_test.go
index 5c34f6dbf7..bd6b618f35 100644
--- a/src/math/bits/bits_test.go
+++ b/src/math/bits/bits_test.go
@@ -705,6 +705,272 @@ func TestLen(t *testing.T) {
}
}
+const (
+ _M = 1<<UintSize - 1
+ _M32 = 1<<32 - 1
+ _M64 = 1<<64 - 1
+)
+
+func TestAddSubUint(t *testing.T) {
+ test := func(msg string, f func(x, y, c uint) (z, cout uint), x, y, c, z, cout uint) {
+ z1, cout1 := f(x, y, c)
+ if z1 != z || cout1 != cout {
+ t.Errorf("%s: got z:cout = %#x:%#x; want %#x:%#x", msg, z1, cout1, z, cout)
+ }
+ }
+ for _, a := range []struct{ x, y, c, z, cout uint }{
+ {0, 0, 0, 0, 0},
+ {0, 1, 0, 1, 0},
+ {0, 0, 1, 1, 0},
+ {0, 1, 1, 2, 0},
+ {12345, 67890, 0, 80235, 0},
+ {12345, 67890, 1, 80236, 0},
+ {_M, 1, 0, 0, 1},
+ {_M, 0, 1, 0, 1},
+ {_M, 1, 1, 1, 1},
+ {_M, _M, 0, _M - 1, 1},
+ {_M, _M, 1, _M, 1},
+ } {
+ test("Add", Add, a.x, a.y, a.c, a.z, a.cout)
+ test("Add symmetric", Add, a.y, a.x, a.c, a.z, a.cout)
+ test("Sub", Sub, a.z, a.x, a.c, a.y, a.cout)
+ test("Sub symmetric", Sub, a.z, a.y, a.c, a.x, a.cout)
+ }
+}
+
+func TestAddSubUint32(t *testing.T) {
+ test := func(msg string, f func(x, y, c uint32) (z, cout uint32), x, y, c, z, cout uint32) {
+ z1, cout1 := f(x, y, c)
+ if z1 != z || cout1 != cout {
+ t.Errorf("%s: got z:cout = %#x:%#x; want %#x:%#x", msg, z1, cout1, z, cout)
+ }
+ }
+ for _, a := range []struct{ x, y, c, z, cout uint32 }{
+ {0, 0, 0, 0, 0},
+ {0, 1, 0, 1, 0},
+ {0, 0, 1, 1, 0},
+ {0, 1, 1, 2, 0},
+ {12345, 67890, 0, 80235, 0},
+ {12345, 67890, 1, 80236, 0},
+ {_M32, 1, 0, 0, 1},
+ {_M32, 0, 1, 0, 1},
+ {_M32, 1, 1, 1, 1},
+ {_M32, _M32, 0, _M32 - 1, 1},
+ {_M32, _M32, 1, _M32, 1},
+ } {
+ test("Add32", Add32, a.x, a.y, a.c, a.z, a.cout)
+ test("Add32 symmetric", Add32, a.y, a.x, a.c, a.z, a.cout)
+ test("Sub32", Sub32, a.z, a.x, a.c, a.y, a.cout)
+ test("Sub32 symmetric", Sub32, a.z, a.y, a.c, a.x, a.cout)
+ }
+}
+
+func TestAddSubUint64(t *testing.T) {
+ test := func(msg string, f func(x, y, c uint64) (z, cout uint64), x, y, c, z, cout uint64) {
+ z1, cout1 := f(x, y, c)
+ if z1 != z || cout1 != cout {
+ t.Errorf("%s: got z:cout = %#x:%#x; want %#x:%#x", msg, z1, cout1, z, cout)
+ }
+ }
+ for _, a := range []struct{ x, y, c, z, cout uint64 }{
+ {0, 0, 0, 0, 0},
+ {0, 1, 0, 1, 0},
+ {0, 0, 1, 1, 0},
+ {0, 1, 1, 2, 0},
+ {12345, 67890, 0, 80235, 0},
+ {12345, 67890, 1, 80236, 0},
+ {_M64, 1, 0, 0, 1},
+ {_M64, 0, 1, 0, 1},
+ {_M64, 1, 1, 1, 1},
+ {_M64, _M64, 0, _M64 - 1, 1},
+ {_M64, _M64, 1, _M64, 1},
+ } {
+ test("Add64", Add64, a.x, a.y, a.c, a.z, a.cout)
+ test("Add64 symmetric", Add64, a.y, a.x, a.c, a.z, a.cout)
+ test("Sub64", Sub64, a.z, a.x, a.c, a.y, a.cout)
+ test("Sub64 symmetric", Sub64, a.z, a.y, a.c, a.x, a.cout)
+ }
+}
+
+func TestMulDiv(t *testing.T) {
+ testMul := func(msg string, f func(x, y uint) (hi, lo uint), x, y, hi, lo uint) {
+ hi1, lo1 := f(x, y)
+ if hi1 != hi || lo1 != lo {
+ t.Errorf("%s: got hi:lo = %#x:%#x; want %#x:%#x", msg, hi1, lo1, hi, lo)
+ }
+ }
+ testDiv := func(msg string, f func(hi, lo, y uint) (q, r uint), hi, lo, y, q, r uint) {
+ q1, r1 := f(hi, lo, y)
+ if q1 != q || r1 != r {
+ t.Errorf("%s: got q:r = %#x:%#x; want %#x:%#x", msg, q1, r1, q, r)
+ }
+ }
+ for _, a := range []struct {
+ x, y uint
+ hi, lo, r uint
+ }{
+ {1 << (UintSize - 1), 2, 1, 0, 1},
+ {_M, _M, _M - 1, 1, 42},
+ } {
+ testMul("Mul", Mul, a.x, a.y, a.hi, a.lo)
+ testMul("Mul symmetric", Mul, a.y, a.x, a.hi, a.lo)
+ testDiv("Div", Div, a.hi, a.lo+a.r, a.y, a.x, a.r)
+ testDiv("Div symmetric", Div, a.hi, a.lo+a.r, a.x, a.y, a.r)
+ }
+}
+
+func TestMulDiv32(t *testing.T) {
+ testMul := func(msg string, f func(x, y uint32) (hi, lo uint32), x, y, hi, lo uint32) {
+ hi1, lo1 := f(x, y)
+ if hi1 != hi || lo1 != lo {
+ t.Errorf("%s: got hi:lo = %#x:%#x; want %#x:%#x", msg, hi1, lo1, hi, lo)
+ }
+ }
+ testDiv := func(msg string, f func(hi, lo, y uint32) (q, r uint32), hi, lo, y, q, r uint32) {
+ q1, r1 := f(hi, lo, y)
+ if q1 != q || r1 != r {
+ t.Errorf("%s: got q:r = %#x:%#x; want %#x:%#x", msg, q1, r1, q, r)
+ }
+ }
+ for _, a := range []struct {
+ x, y uint32
+ hi, lo, r uint32
+ }{
+ {1 << 31, 2, 1, 0, 1},
+ {0xc47dfa8c, 50911, 0x98a4, 0x998587f4, 13},
+ {_M32, _M32, _M32 - 1, 1, 42},
+ } {
+ testMul("Mul32", Mul32, a.x, a.y, a.hi, a.lo)
+ testMul("Mul32 symmetric", Mul32, a.y, a.x, a.hi, a.lo)
+ testDiv("Div32", Div32, a.hi, a.lo+a.r, a.y, a.x, a.r)
+ testDiv("Div32 symmetric", Div32, a.hi, a.lo+a.r, a.x, a.y, a.r)
+ }
+}
+
+func TestMulDiv64(t *testing.T) {
+ testMul := func(msg string, f func(x, y uint64) (hi, lo uint64), x, y, hi, lo uint64) {
+ hi1, lo1 := f(x, y)
+ if hi1 != hi || lo1 != lo {
+ t.Errorf("%s: got hi:lo = %#x:%#x; want %#x:%#x", msg, hi1, lo1, hi, lo)
+ }
+ }
+ testDiv := func(msg string, f func(hi, lo, y uint64) (q, r uint64), hi, lo, y, q, r uint64) {
+ q1, r1 := f(hi, lo, y)
+ if q1 != q || r1 != r {
+ t.Errorf("%s: got q:r = %#x:%#x; want %#x:%#x", msg, q1, r1, q, r)
+ }
+ }
+ for _, a := range []struct {
+ x, y uint64
+ hi, lo, r uint64
+ }{
+ {1 << 63, 2, 1, 0, 1},
+ {0x3626229738a3b9, 0xd8988a9f1cc4a61, 0x2dd0712657fe8, 0x9dd6a3364c358319, 13},
+ {_M64, _M64, _M64 - 1, 1, 42},
+ } {
+ testMul("Mul64", Mul64, a.x, a.y, a.hi, a.lo)
+ testMul("Mul64 symmetric", Mul64, a.y, a.x, a.hi, a.lo)
+ testDiv("Div64", Div64, a.hi, a.lo+a.r, a.y, a.x, a.r)
+ testDiv("Div64 symmetric", Div64, a.hi, a.lo+a.r, a.x, a.y, a.r)
+ }
+}
+
+func BenchmarkAdd(b *testing.B) {
+ var z, c uint
+ for i := 0; i < b.N; i++ {
+ z, c = Add(uint(Input), uint(i), c)
+ }
+ Output = int(z + c)
+}
+
+func BenchmarkAdd32(b *testing.B) {
+ var z, c uint32
+ for i := 0; i < b.N; i++ {
+ z, c = Add32(uint32(Input), uint32(i), c)
+ }
+ Output = int(z + c)
+}
+
+func BenchmarkAdd64(b *testing.B) {
+ var z, c uint64
+ for i := 0; i < b.N; i++ {
+ z, c = Add64(uint64(Input), uint64(i), c)
+ }
+ Output = int(z + c)
+}
+
+func BenchmarkSub(b *testing.B) {
+ var z, c uint
+ for i := 0; i < b.N; i++ {
+ z, c = Sub(uint(Input), uint(i), c)
+ }
+ Output = int(z + c)
+}
+
+func BenchmarkSub32(b *testing.B) {
+ var z, c uint32
+ for i := 0; i < b.N; i++ {
+ z, c = Sub32(uint32(Input), uint32(i), c)
+ }
+ Output = int(z + c)
+}
+
+func BenchmarkSub64(b *testing.B) {
+ var z, c uint64
+ for i := 0; i < b.N; i++ {
+ z, c = Add64(uint64(Input), uint64(i), c)
+ }
+ Output = int(z + c)
+}
+
+func BenchmarkMul(b *testing.B) {
+ var hi, lo uint
+ for i := 0; i < b.N; i++ {
+ hi, lo = Mul(uint(Input), uint(i))
+ }
+ Output = int(hi + lo)
+}
+
+func BenchmarkMul32(b *testing.B) {
+ var hi, lo uint32
+ for i := 0; i < b.N; i++ {
+ hi, lo = Mul32(uint32(Input), uint32(i))
+ }
+ Output = int(hi + lo)
+}
+
+func BenchmarkMul64(b *testing.B) {
+ var hi, lo uint64
+ for i := 0; i < b.N; i++ {
+ hi, lo = Mul64(uint64(Input), uint64(i))
+ }
+ Output = int(hi + lo)
+}
+
+func BenchmarkDiv(b *testing.B) {
+ var q, r uint
+ for i := 0; i < b.N; i++ {
+ q, r = Div(1, uint(i), uint(Input))
+ }
+ Output = int(q + r)
+}
+
+func BenchmarkDiv32(b *testing.B) {
+ var q, r uint32
+ for i := 0; i < b.N; i++ {
+ q, r = Div32(1, uint32(i), uint32(Input))
+ }
+ Output = int(q + r)
+}
+
+func BenchmarkDiv64(b *testing.B) {
+ var q, r uint64
+ for i := 0; i < b.N; i++ {
+ q, r = Div64(1, uint64(i), uint64(Input))
+ }
+ Output = int(q + r)
+}
+
// ----------------------------------------------------------------------------
// Testing support
diff --git a/src/math/expm1_386.s b/src/math/expm1_386.s
index c1392cd52b..d020296ca7 100644
--- a/src/math/expm1_386.s
+++ b/src/math/expm1_386.s
@@ -8,7 +8,7 @@
TEXT ·Expm1(SB),NOSPLIT,$0
FLDLN2 // F0=log(2) = 1/log2(e) ~ 0.693147
FMOVD x+0(FP), F0 // F0=x, F1=1/log2(e)
- FABS // F0=|x|, F1=1/log2(e)
+ FABS // F0=|x|, F1=1/log2(e)
FUCOMPP F0, F1 // compare F0 to F1
FSTSW AX
SAHF
@@ -36,7 +36,7 @@ use_exp:
FSCALE // F0=e**x, F1=int(x*log2(e))
FMOVDP F0, F1 // F0=e**x
FLD1 // F0=1, F1=e**x
- FSUBDP F0, F1 // F0=e**x-1
+ FSUBDP F0, F1 // F0=e**x-1
FMOVDP F0, ret+8(FP)
RET
not_finite:
diff --git a/src/math/sin_386.s b/src/math/sin_386.s
index 9d605a1e38..45d12e00c8 100644
--- a/src/math/sin_386.s
+++ b/src/math/sin_386.s
@@ -24,7 +24,7 @@ TEXT ·Cos(SB),NOSPLIT,$0
FCOS // F0=cos(reduced_x)
FMOVDP F0, ret+8(FP)
RET
-
+
// func Sin(x float64) float64
TEXT ·Sin(SB),NOSPLIT,$0
FMOVD x+0(FP), F0 // F0=x
diff --git a/src/math/sqrt_386.s b/src/math/sqrt_386.s
index 402d152785..5a5c33a79a 100644
--- a/src/math/sqrt_386.s
+++ b/src/math/sqrt_386.s
@@ -4,7 +4,7 @@
#include "textflag.h"
-// func Sqrt(x float64) float64
+// func Sqrt(x float64) float64
TEXT ·Sqrt(SB),NOSPLIT,$0
FMOVD x+0(FP),F0
FSQRT
diff --git a/src/math/sqrt_arm.s b/src/math/sqrt_arm.s
index deb6712553..ffc7d1026d 100644
--- a/src/math/sqrt_arm.s
+++ b/src/math/sqrt_arm.s
@@ -4,7 +4,7 @@
#include "textflag.h"
-// func Sqrt(x float64) float64
+// func Sqrt(x float64) float64
TEXT ·Sqrt(SB),NOSPLIT,$0
MOVB runtime·goarm(SB), R11
CMP $5, R11
diff --git a/src/mime/mediatype.go b/src/mime/mediatype.go
index ea2bbac189..3d480a9d7e 100644
--- a/src/mime/mediatype.go
+++ b/src/mime/mediatype.go
@@ -280,7 +280,7 @@ func consumeValue(v string) (value, rest string) {
// and intended as a literal backslash. This makes Go servers deal better
// with MSIE without affecting the way they handle conforming MIME
// generators.
- if r == '\\' && i+1 < len(v) && !isTokenChar(rune(v[i+1])) {
+ if r == '\\' && i+1 < len(v) && isTSpecial(rune(v[i+1])) {
buffer.WriteByte(v[i+1])
i++
continue
diff --git a/src/mime/mediatype_test.go b/src/mime/mediatype_test.go
index 88d742f0aa..35b311a4a5 100644
--- a/src/mime/mediatype_test.go
+++ b/src/mime/mediatype_test.go
@@ -40,6 +40,8 @@ func TestConsumeValue(t *testing.T) {
{`"\\" rest`, "\\", " rest"},
{`"My \" value"end`, "My \" value", "end"},
{`"\" rest`, "", `"\" rest`},
+ {`"C:\dev\go\robots.txt"`, `C:\dev\go\robots.txt`, ""},
+ {`"C:\新建文件件\中文第二次测试.mp4"`, `C:\新建文件件\中文第二次测试.mp4`, ""},
}
for _, test := range tests {
value, rest := consumeValue(test[0])
@@ -393,6 +395,7 @@ func TestParseMediaType(t *testing.T) {
// Microsoft browers in intranet mode do not think they need to escape \ in file name.
{`form-data; name="file"; filename="C:\dev\go\robots.txt"`, "form-data", m("name", "file", "filename", `C:\dev\go\robots.txt`)},
+ {`form-data; name="file"; filename="C:\新建文件件\中文第二次测试.mp4"`, "form-data", m("name", "file", "filename", `C:\新建文件件\中文第二次测试.mp4`)},
}
for _, test := range tests {
mt, params, err := ParseMediaType(test.in)
diff --git a/src/mime/multipart/formdata_test.go b/src/mime/multipart/formdata_test.go
index 2d6a830cb6..105a82c417 100644
--- a/src/mime/multipart/formdata_test.go
+++ b/src/mime/multipart/formdata_test.go
@@ -13,7 +13,7 @@ import (
)
func TestReadForm(t *testing.T) {
- b := strings.NewReader(strings.Replace(message, "\n", "\r\n", -1))
+ b := strings.NewReader(strings.ReplaceAll(message, "\n", "\r\n"))
r := NewReader(b, boundary)
f, err := r.ReadForm(25)
if err != nil {
@@ -39,7 +39,7 @@ func TestReadForm(t *testing.T) {
}
func TestReadFormWithNamelessFile(t *testing.T) {
- b := strings.NewReader(strings.Replace(messageWithFileWithoutName, "\n", "\r\n", -1))
+ b := strings.NewReader(strings.ReplaceAll(messageWithFileWithoutName, "\n", "\r\n"))
r := NewReader(b, boundary)
f, err := r.ReadForm(25)
if err != nil {
@@ -54,7 +54,7 @@ func TestReadFormWithNamelessFile(t *testing.T) {
func TestReadFormWithTextContentType(t *testing.T) {
// From https://github.com/golang/go/issues/24041
- b := strings.NewReader(strings.Replace(messageWithTextContentType, "\n", "\r\n", -1))
+ b := strings.NewReader(strings.ReplaceAll(messageWithTextContentType, "\n", "\r\n"))
r := NewReader(b, boundary)
f, err := r.ReadForm(25)
if err != nil {
@@ -184,7 +184,7 @@ Content-Disposition: form-data; name="largetext"
--MyBoundary--
`
- testBody := strings.Replace(message, "\n", "\r\n", -1)
+ testBody := strings.ReplaceAll(message, "\n", "\r\n")
testCases := []struct {
name string
maxMemory int64
diff --git a/src/mime/multipart/multipart_test.go b/src/mime/multipart/multipart_test.go
index abe1cc8e77..7bf606765c 100644
--- a/src/mime/multipart/multipart_test.go
+++ b/src/mime/multipart/multipart_test.go
@@ -105,7 +105,7 @@ never read data
useless trailer
`
- testBody = strings.Replace(testBody, "\n", sep, -1)
+ testBody = strings.ReplaceAll(testBody, "\n", sep)
return strings.Replace(testBody, "[longline]", longLine, 1)
}
@@ -151,7 +151,7 @@ func testMultipart(t *testing.T, r io.Reader, onlyNewlines bool) {
adjustNewlines := func(s string) string {
if onlyNewlines {
- return strings.Replace(s, "\r\n", "\n", -1)
+ return strings.ReplaceAll(s, "\r\n", "\n")
}
return s
}
@@ -299,7 +299,7 @@ foo-bar: baz
Oh no, premature EOF!
`
- body := strings.Replace(testBody, "\n", "\r\n", -1)
+ body := strings.ReplaceAll(testBody, "\n", "\r\n")
bodyReader := strings.NewReader(body)
r := NewReader(bodyReader, "MyBoundary")
diff --git a/src/net/dnsclient.go b/src/net/dnsclient.go
index e3524280b6..2c47bc4130 100644
--- a/src/net/dnsclient.go
+++ b/src/net/dnsclient.go
@@ -75,7 +75,7 @@ func isDomainName(s string) bool {
}
last := byte('.')
- ok := false // Ok once we've seen a letter.
+ nonNumeric := false // true once we've seen a letter or hyphen
partlen := 0
for i := 0; i < len(s); i++ {
c := s[i]
@@ -83,7 +83,7 @@ func isDomainName(s string) bool {
default:
return false
case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || c == '_':
- ok = true
+ nonNumeric = true
partlen++
case '0' <= c && c <= '9':
// fine
@@ -94,6 +94,7 @@ func isDomainName(s string) bool {
return false
}
partlen++
+ nonNumeric = true
case c == '.':
// Byte before dot cannot be dot, dash.
if last == '.' || last == '-' {
@@ -110,7 +111,7 @@ func isDomainName(s string) bool {
return false
}
- return ok
+ return nonNumeric
}
// absDomainName returns an absolute domain name which ends with a
diff --git a/src/net/dnsclient_unix.go b/src/net/dnsclient_unix.go
index 2fee3346e9..9a0b1d69a8 100644
--- a/src/net/dnsclient_unix.go
+++ b/src/net/dnsclient_unix.go
@@ -27,6 +27,20 @@ import (
"golang_org/x/net/dns/dnsmessage"
)
+var (
+ errLameReferral = errors.New("lame referral")
+ errCannotUnmarshalDNSMessage = errors.New("cannot unmarshal DNS message")
+ errCannotMarshalDNSMessage = errors.New("cannot marshal DNS message")
+ errServerMisbehaving = errors.New("server misbehaving")
+ errInvalidDNSResponse = errors.New("invalid DNS response")
+ errNoAnswerFromDNSServer = errors.New("no answer from DNS server")
+
+ // errServerTemporarlyMisbehaving is like errServerMisbehaving, except
+ // that when it gets translated to a DNSError, the IsTemporary field
+ // gets set to true.
+ errServerTemporarlyMisbehaving = errors.New("server misbehaving")
+)
+
func newRequest(q dnsmessage.Question) (id uint16, udpReq, tcpReq []byte, err error) {
id = uint16(rand.Int()) ^ uint16(time.Now().UnixNano())
b := dnsmessage.NewBuilder(make([]byte, 2, 514), dnsmessage.Header{ID: id, RecursionDesired: true})
@@ -105,14 +119,14 @@ func dnsStreamRoundTrip(c Conn, id uint16, query dnsmessage.Question, b []byte)
var p dnsmessage.Parser
h, err := p.Start(b[:n])
if err != nil {
- return dnsmessage.Parser{}, dnsmessage.Header{}, errors.New("cannot unmarshal DNS message")
+ return dnsmessage.Parser{}, dnsmessage.Header{}, errCannotUnmarshalDNSMessage
}
q, err := p.Question()
if err != nil {
- return dnsmessage.Parser{}, dnsmessage.Header{}, errors.New("cannot unmarshal DNS message")
+ return dnsmessage.Parser{}, dnsmessage.Header{}, errCannotUnmarshalDNSMessage
}
if !checkResponse(id, query, h, q) {
- return dnsmessage.Parser{}, dnsmessage.Header{}, errors.New("invalid DNS response")
+ return dnsmessage.Parser{}, dnsmessage.Header{}, errInvalidDNSResponse
}
return p, h, nil
}
@@ -122,7 +136,7 @@ func (r *Resolver) exchange(ctx context.Context, server string, q dnsmessage.Que
q.Class = dnsmessage.ClassINET
id, udpReq, tcpReq, err := newRequest(q)
if err != nil {
- return dnsmessage.Parser{}, dnsmessage.Header{}, errors.New("cannot marshal DNS message")
+ return dnsmessage.Parser{}, dnsmessage.Header{}, errCannotMarshalDNSMessage
}
for _, network := range []string{"udp", "tcp"} {
ctx, cancel := context.WithDeadline(ctx, time.Now().Add(timeout))
@@ -147,31 +161,31 @@ func (r *Resolver) exchange(ctx context.Context, server string, q dnsmessage.Que
return dnsmessage.Parser{}, dnsmessage.Header{}, mapErr(err)
}
if err := p.SkipQuestion(); err != dnsmessage.ErrSectionDone {
- return dnsmessage.Parser{}, dnsmessage.Header{}, errors.New("invalid DNS response")
+ return dnsmessage.Parser{}, dnsmessage.Header{}, errInvalidDNSResponse
}
if h.Truncated { // see RFC 5966
continue
}
return p, h, nil
}
- return dnsmessage.Parser{}, dnsmessage.Header{}, errors.New("no answer from DNS server")
+ return dnsmessage.Parser{}, dnsmessage.Header{}, errNoAnswerFromDNSServer
}
// checkHeader performs basic sanity checks on the header.
func checkHeader(p *dnsmessage.Parser, h dnsmessage.Header, name, server string) error {
+ if h.RCode == dnsmessage.RCodeNameError {
+ return errNoSuchHost
+ }
+
_, err := p.AnswerHeader()
if err != nil && err != dnsmessage.ErrSectionDone {
- return &DNSError{
- Err: "cannot unmarshal DNS message",
- Name: name,
- Server: server,
- }
+ return errCannotUnmarshalDNSMessage
}
// libresolv continues to the next server when it receives
// an invalid referral response. See golang.org/issue/15434.
if h.RCode == dnsmessage.RCodeSuccess && !h.Authoritative && !h.RecursionAvailable && err == dnsmessage.ErrSectionDone {
- return &DNSError{Err: "lame referral", Name: name, Server: server}
+ return errLameReferral
}
if h.RCode != dnsmessage.RCodeSuccess && h.RCode != dnsmessage.RCodeNameError {
@@ -180,11 +194,10 @@ func checkHeader(p *dnsmessage.Parser, h dnsmessage.Header, name, server string)
// a name error and we didn't get success,
// the server is behaving incorrectly or
// having temporary trouble.
- err := &DNSError{Err: "server misbehaving", Name: name, Server: server}
if h.RCode == dnsmessage.RCodeServerFailure {
- err.IsTemporary = true
+ return errServerTemporarlyMisbehaving
}
- return err
+ return errServerMisbehaving
}
return nil
@@ -194,28 +207,16 @@ func skipToAnswer(p *dnsmessage.Parser, qtype dnsmessage.Type, name, server stri
for {
h, err := p.AnswerHeader()
if err == dnsmessage.ErrSectionDone {
- return &DNSError{
- Err: errNoSuchHost.Error(),
- Name: name,
- Server: server,
- }
+ return errNoSuchHost
}
if err != nil {
- return &DNSError{
- Err: "cannot unmarshal DNS message",
- Name: name,
- Server: server,
- }
+ return errCannotUnmarshalDNSMessage
}
if h.Type == qtype {
return nil
}
if err := p.SkipAnswer(); err != nil {
- return &DNSError{
- Err: "cannot unmarshal DNS message",
- Name: name,
- Server: server,
- }
+ return errCannotUnmarshalDNSMessage
}
}
}
@@ -229,7 +230,7 @@ func (r *Resolver) tryOneName(ctx context.Context, cfg *dnsConfig, name string,
n, err := dnsmessage.NewName(name)
if err != nil {
- return dnsmessage.Parser{}, "", errors.New("cannot marshal DNS message")
+ return dnsmessage.Parser{}, "", errCannotMarshalDNSMessage
}
q := dnsmessage.Question{
Name: n,
@@ -243,38 +244,62 @@ func (r *Resolver) tryOneName(ctx context.Context, cfg *dnsConfig, name string,
p, h, err := r.exchange(ctx, server, q, cfg.timeout)
if err != nil {
- lastErr = &DNSError{
+ dnsErr := &DNSError{
Err: err.Error(),
Name: name,
Server: server,
}
if nerr, ok := err.(Error); ok && nerr.Timeout() {
- lastErr.(*DNSError).IsTimeout = true
+ dnsErr.IsTimeout = true
}
// Set IsTemporary for socket-level errors. Note that this flag
// may also be used to indicate a SERVFAIL response.
if _, ok := err.(*OpError); ok {
- lastErr.(*DNSError).IsTemporary = true
+ dnsErr.IsTemporary = true
}
+ lastErr = dnsErr
continue
}
- // The name does not exist, so trying another server won't help.
- //
- // TODO: indicate this in a more obvious way, such as a field on DNSError?
- if h.RCode == dnsmessage.RCodeNameError {
- return dnsmessage.Parser{}, "", &DNSError{Err: errNoSuchHost.Error(), Name: name, Server: server}
- }
-
- lastErr = checkHeader(&p, h, name, server)
- if lastErr != nil {
+ if err := checkHeader(&p, h, name, server); err != nil {
+ dnsErr := &DNSError{
+ Err: err.Error(),
+ Name: name,
+ Server: server,
+ }
+ if err == errServerTemporarlyMisbehaving {
+ dnsErr.IsTemporary = true
+ }
+ if err == errNoSuchHost {
+ // The name does not exist, so trying
+ // another server won't help.
+ //
+ // TODO: indicate this in a more
+ // obvious way, such as a field on
+ // DNSError?
+ return p, server, dnsErr
+ }
+ lastErr = dnsErr
continue
}
- lastErr = skipToAnswer(&p, qtype, name, server)
- if lastErr == nil {
+ err = skipToAnswer(&p, qtype, name, server)
+ if err == nil {
return p, server, nil
}
+ lastErr = &DNSError{
+ Err: err.Error(),
+ Name: name,
+ Server: server,
+ }
+ if err == errNoSuchHost {
+ // The name does not exist, so trying another
+ // server won't help.
+ //
+ // TODO: indicate this in a more obvious way,
+ // such as a field on DNSError?
+ return p, server, lastErr
+ }
}
}
return dnsmessage.Parser{}, "", lastErr
diff --git a/src/net/dnsclient_unix_test.go b/src/net/dnsclient_unix_test.go
index bb014b903a..9482fc466f 100644
--- a/src/net/dnsclient_unix_test.go
+++ b/src/net/dnsclient_unix_test.go
@@ -1427,28 +1427,35 @@ func TestDNSGoroutineRace(t *testing.T) {
}
}
+func lookupWithFake(fake fakeDNSServer, name string, typ dnsmessage.Type) error {
+ r := Resolver{PreferGo: true, Dial: fake.DialContext}
+
+ resolvConf.mu.RLock()
+ conf := resolvConf.dnsConfig
+ resolvConf.mu.RUnlock()
+
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ _, _, err := r.tryOneName(ctx, conf, name, typ)
+ return err
+}
+
// Issue 8434: verify that Temporary returns true on an error when rcode
// is SERVFAIL
func TestIssue8434(t *testing.T) {
- msg := dnsmessage.Message{
- Header: dnsmessage.Header{
- RCode: dnsmessage.RCodeServerFailure,
+ err := lookupWithFake(fakeDNSServer{
+ rh: func(n, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) {
+ return dnsmessage.Message{
+ Header: dnsmessage.Header{
+ ID: q.ID,
+ Response: true,
+ RCode: dnsmessage.RCodeServerFailure,
+ },
+ Questions: q.Questions,
+ }, nil
},
- }
- b, err := msg.Pack()
- if err != nil {
- t.Fatal("Pack failed:", err)
- }
- var p dnsmessage.Parser
- h, err := p.Start(b)
- if err != nil {
- t.Fatal("Start failed:", err)
- }
- if err := p.SkipAllQuestions(); err != nil {
- t.Fatal("SkipAllQuestions failed:", err)
- }
-
- err = checkHeader(&p, h, "golang.org", "foo:53")
+ }, "golang.org.", dnsmessage.TypeALL)
if err == nil {
t.Fatal("expected an error")
}
@@ -1464,50 +1471,76 @@ func TestIssue8434(t *testing.T) {
}
}
-// Issue 12778: verify that NXDOMAIN without RA bit errors as
-// "no such host" and not "server misbehaving"
+// TestNoSuchHost verifies that tryOneName works correctly when the domain does
+// not exist.
+//
+// Issue 12778: verify that NXDOMAIN without RA bit errors as "no such host"
+// and not "server misbehaving"
//
// Issue 25336: verify that NXDOMAIN errors fail fast.
-func TestIssue12778(t *testing.T) {
- lookups := 0
- fake := fakeDNSServer{
- rh: func(n, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) {
- lookups++
- return dnsmessage.Message{
- Header: dnsmessage.Header{
- ID: q.ID,
- Response: true,
- RCode: dnsmessage.RCodeNameError,
- RecursionAvailable: false,
- },
- Questions: q.Questions,
- }, nil
+//
+// Issue 27525: verify that empty answers fail fast.
+func TestNoSuchHost(t *testing.T) {
+ tests := []struct {
+ name string
+ f func(string, string, dnsmessage.Message, time.Time) (dnsmessage.Message, error)
+ }{
+ {
+ "NXDOMAIN",
+ func(n, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) {
+ return dnsmessage.Message{
+ Header: dnsmessage.Header{
+ ID: q.ID,
+ Response: true,
+ RCode: dnsmessage.RCodeNameError,
+ RecursionAvailable: false,
+ },
+ Questions: q.Questions,
+ }, nil
+ },
+ },
+ {
+ "no answers",
+ func(n, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) {
+ return dnsmessage.Message{
+ Header: dnsmessage.Header{
+ ID: q.ID,
+ Response: true,
+ RCode: dnsmessage.RCodeSuccess,
+ RecursionAvailable: false,
+ Authoritative: true,
+ },
+ Questions: q.Questions,
+ }, nil
+ },
},
}
- r := Resolver{PreferGo: true, Dial: fake.DialContext}
-
- resolvConf.mu.RLock()
- conf := resolvConf.dnsConfig
- resolvConf.mu.RUnlock()
-
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
- _, _, err := r.tryOneName(ctx, conf, ".", dnsmessage.TypeALL)
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ lookups := 0
+ err := lookupWithFake(fakeDNSServer{
+ rh: func(n, s string, q dnsmessage.Message, d time.Time) (dnsmessage.Message, error) {
+ lookups++
+ return test.f(n, s, q, d)
+ },
+ }, ".", dnsmessage.TypeALL)
- if lookups != 1 {
- t.Errorf("got %d lookups, wanted 1", lookups)
- }
+ if lookups != 1 {
+ t.Errorf("got %d lookups, wanted 1", lookups)
+ }
- if err == nil {
- t.Fatal("expected an error")
- }
- de, ok := err.(*DNSError)
- if !ok {
- t.Fatalf("err = %#v; wanted a *net.DNSError", err)
- }
- if de.Err != errNoSuchHost.Error() {
- t.Fatalf("Err = %#v; wanted %q", de.Err, errNoSuchHost.Error())
+ if err == nil {
+ t.Fatal("expected an error")
+ }
+ de, ok := err.(*DNSError)
+ if !ok {
+ t.Fatalf("err = %#v; wanted a *net.DNSError", err)
+ }
+ if de.Err != errNoSuchHost.Error() {
+ t.Fatalf("Err = %#v; wanted %q", de.Err, errNoSuchHost.Error())
+ }
+ })
}
}
@@ -1535,3 +1568,56 @@ func TestDNSDialTCP(t *testing.T) {
t.Fatal("exhange failed:", err)
}
}
+
+// Issue 27763: verify that two strings in one TXT record are concatenated.
+func TestTXTRecordTwoStrings(t *testing.T) {
+ fake := fakeDNSServer{
+ rh: func(n, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) {
+ r := dnsmessage.Message{
+ Header: dnsmessage.Header{
+ ID: q.Header.ID,
+ Response: true,
+ RCode: dnsmessage.RCodeSuccess,
+ },
+ Questions: q.Questions,
+ Answers: []dnsmessage.Resource{
+ {
+ Header: dnsmessage.ResourceHeader{
+ Name: q.Questions[0].Name,
+ Type: dnsmessage.TypeA,
+ Class: dnsmessage.ClassINET,
+ },
+ Body: &dnsmessage.TXTResource{
+ TXT: []string{"string1 ", "string2"},
+ },
+ },
+ {
+ Header: dnsmessage.ResourceHeader{
+ Name: q.Questions[0].Name,
+ Type: dnsmessage.TypeA,
+ Class: dnsmessage.ClassINET,
+ },
+ Body: &dnsmessage.TXTResource{
+ TXT: []string{"onestring"},
+ },
+ },
+ },
+ }
+ return r, nil
+ },
+ }
+ r := Resolver{PreferGo: true, Dial: fake.DialContext}
+ txt, err := r.lookupTXT(context.Background(), "golang.org")
+ if err != nil {
+ t.Fatal("LookupTXT failed:", err)
+ }
+ if want := 2; len(txt) != want {
+ t.Fatalf("len(txt), got %d, want %d", len(txt), want)
+ }
+ if want := "string1 string2"; txt[0] != want {
+ t.Errorf("txt[0], got %q, want %q", txt[0], want)
+ }
+ if want := "onestring"; txt[1] != want {
+ t.Errorf("txt[1], got %q, want %q", txt[1], want)
+ }
+}
diff --git a/src/net/dnsname_test.go b/src/net/dnsname_test.go
index 806d8756cb..2964982311 100644
--- a/src/net/dnsname_test.go
+++ b/src/net/dnsname_test.go
@@ -22,6 +22,7 @@ var dnsNameTests = []dnsNameTest{
{"foo.com", true},
{"1foo.com", true},
{"26.0.0.73.com", true},
+ {"10-0-0-1", true},
{"fo-o.com", true},
{"fo1o.com", true},
{"foo1.com", true},
diff --git a/src/net/http/cgi/child.go b/src/net/http/cgi/child.go
index da12ac3498..10325c2eb5 100644
--- a/src/net/http/cgi/child.go
+++ b/src/net/http/cgi/child.go
@@ -86,7 +86,7 @@ func RequestFromMap(params map[string]string) (*http.Request, error) {
if !strings.HasPrefix(k, "HTTP_") || k == "HTTP_HOST" {
continue
}
- r.Header.Add(strings.Replace(k[5:], "_", "-", -1), v)
+ r.Header.Add(strings.ReplaceAll(k[5:], "_", "-"), v)
}
// TODO: cookies. parsing them isn't exported, though.
diff --git a/src/net/http/client.go b/src/net/http/client.go
index a15b3ba276..ea6c071911 100644
--- a/src/net/http/client.go
+++ b/src/net/http/client.go
@@ -238,7 +238,7 @@ func send(ireq *Request, rt RoundTripper, deadline time.Time) (resp *Response, d
username := u.Username()
password, _ := u.Password()
forkReq()
- req.Header = cloneHeader(ireq.Header)
+ req.Header = ireq.Header.clone()
req.Header.Set("Authorization", "Basic "+basicAuth(username, password))
}
diff --git a/src/net/http/clientserver_test.go b/src/net/http/clientserver_test.go
index 9a05b648e3..465bae1478 100644
--- a/src/net/http/clientserver_test.go
+++ b/src/net/http/clientserver_test.go
@@ -252,7 +252,7 @@ type slurpResult struct {
func (sr slurpResult) String() string { return fmt.Sprintf("body %q; err %v", sr.body, sr.err) }
func (tt h12Compare) normalizeRes(t *testing.T, res *Response, wantProto string) {
- if res.Proto == wantProto {
+ if res.Proto == wantProto || res.Proto == "HTTP/IGNORE" {
res.Proto, res.ProtoMajor, res.ProtoMinor = "", 0, 0
} else {
t.Errorf("got %q response; want %q", res.Proto, wantProto)
@@ -1474,11 +1474,11 @@ func testWriteHeaderAfterWrite(t *testing.T, h2, hijack bool) {
return
}
gotLog := strings.TrimSpace(errorLog.String())
- wantLog := "http: multiple response.WriteHeader calls"
+ wantLog := "http: superfluous response.WriteHeader call from net/http_test.testWriteHeaderAfterWrite.func1 (clientserver_test.go:"
if hijack {
- wantLog = "http: response.WriteHeader on hijacked connection"
+ wantLog = "http: response.WriteHeader on hijacked connection from net/http_test.testWriteHeaderAfterWrite.func1 (clientserver_test.go:"
}
- if gotLog != wantLog {
+ if !strings.HasPrefix(gotLog, wantLog) {
t.Errorf("stderr output = %q; want %q", gotLog, wantLog)
}
}
@@ -1546,3 +1546,25 @@ func TestBidiStreamReverseProxy(t *testing.T) {
}
}
+
+// Always use HTTP/1.1 for WebSocket upgrades.
+func TestH12_WebSocketUpgrade(t *testing.T) {
+ h12Compare{
+ Handler: func(w ResponseWriter, r *Request) {
+ h := w.Header()
+ h.Set("Foo", "bar")
+ },
+ ReqFunc: func(c *Client, url string) (*Response, error) {
+ req, _ := NewRequest("GET", url, nil)
+ req.Header.Set("Connection", "Upgrade")
+ req.Header.Set("Upgrade", "WebSocket")
+ return c.Do(req)
+ },
+ EarlyCheckResponse: func(proto string, res *Response) {
+ if res.Proto != "HTTP/1.1" {
+ t.Errorf("%s: expected HTTP/1.1, got %q", proto, res.Proto)
+ }
+ res.Proto = "HTTP/IGNORE" // skip later checks that Proto must be 1.1 vs 2.0
+ },
+ }.run(t)
+}
diff --git a/src/net/http/cookie.go b/src/net/http/cookie.go
index 382398756b..289c3c37b1 100644
--- a/src/net/http/cookie.go
+++ b/src/net/http/cookie.go
@@ -36,9 +36,9 @@ type Cookie struct {
Unparsed []string // Raw text of unparsed attribute-value pairs
}
-// SameSite allows a server define a cookie attribute making it impossible for
+// SameSite allows a server to define a cookie attribute making it impossible for
// the browser to send this cookie along with cross-site requests. The main
-// goal is mitigate the risk of cross-origin information leakage, and provides
+// goal is to mitigate the risk of cross-origin information leakage, and provides
// some protection against cross-site request forgery attacks.
//
// See https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site-00 for details.
diff --git a/src/net/http/example_handle_test.go b/src/net/http/example_handle_test.go
new file mode 100644
index 0000000000..10a62f64c2
--- /dev/null
+++ b/src/net/http/example_handle_test.go
@@ -0,0 +1,29 @@
+// Copyright 2018 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 http_test
+
+import (
+ "fmt"
+ "log"
+ "net/http"
+ "sync"
+)
+
+type countHandler struct {
+ mu sync.Mutex // guards n
+ n int
+}
+
+func (h *countHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ h.mu.Lock()
+ defer h.mu.Unlock()
+ h.n++
+ fmt.Fprintf(w, "count is %d\n", h.n)
+}
+
+func ExampleHandle() {
+ http.Handle("/count", new(countHandler))
+ log.Fatal(http.ListenAndServe(":8080", nil))
+}
diff --git a/src/net/http/example_test.go b/src/net/http/example_test.go
index f5c47d0bd4..2a09f5f6c6 100644
--- a/src/net/http/example_test.go
+++ b/src/net/http/example_test.go
@@ -173,3 +173,21 @@ func ExampleHandleFunc() {
log.Fatal(http.ListenAndServe(":8080", nil))
}
+
+func newPeopleHandler() http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ fmt.Fprintln(w, "This is the people handler.")
+ })
+}
+
+func ExampleNotFoundHandler() {
+ mux := http.NewServeMux()
+
+ // Create sample handler to returns 404
+ mux.Handle("/resources", http.NotFoundHandler())
+
+ // Create sample handler that returns 200
+ mux.Handle("/resources/people/", newPeopleHandler())
+
+ log.Fatal(http.ListenAndServe(":8080", mux))
+}
diff --git a/src/net/http/export_test.go b/src/net/http/export_test.go
index bc0db53a2c..716e8ecac7 100644
--- a/src/net/http/export_test.go
+++ b/src/net/http/export_test.go
@@ -155,7 +155,7 @@ func (t *Transport) IdleConnStrsForTesting_h2() []string {
func (t *Transport) IdleConnCountForTesting(scheme, addr string) int {
t.idleMu.Lock()
defer t.idleMu.Unlock()
- key := connectMethodKey{"", scheme, addr}
+ key := connectMethodKey{"", scheme, addr, false}
cacheKey := key.String()
for k, conns := range t.idleConn {
if k.String() == cacheKey {
@@ -178,12 +178,12 @@ func (t *Transport) IsIdleForTesting() bool {
}
func (t *Transport) RequestIdleConnChForTesting() {
- t.getIdleConnCh(connectMethod{nil, "http", "example.com"})
+ t.getIdleConnCh(connectMethod{nil, "http", "example.com", false})
}
func (t *Transport) PutIdleTestConn(scheme, addr string) bool {
c, _ := net.Pipe()
- key := connectMethodKey{"", scheme, addr}
+ key := connectMethodKey{"", scheme, addr, false}
select {
case <-t.incHostConnCount(key):
default:
diff --git a/src/net/http/header.go b/src/net/http/header.go
index b28144d8c1..611ee04705 100644
--- a/src/net/http/header.go
+++ b/src/net/http/header.go
@@ -19,23 +19,27 @@ type Header map[string][]string
// Add adds the key, value pair to the header.
// It appends to any existing values associated with key.
+// The key is case insensitive; it is canonicalized by
+// textproto.CanonicalMIMEHeaderKey.
func (h Header) Add(key, value string) {
textproto.MIMEHeader(h).Add(key, value)
}
-// Set sets the header entries associated with key to
-// the single element value. It replaces any existing
-// values associated with key.
+// Set sets the header entries associated with key to the
+// single element value. It replaces any existing values
+// associated with key. The key is case insensitive; it is
+// canonicalized by textproto.CanonicalMIMEHeaderKey.
+// To use non-canonical keys, assign to the map directly.
func (h Header) Set(key, value string) {
textproto.MIMEHeader(h).Set(key, value)
}
-// Get gets the first value associated with the given key.
-// It is case insensitive; textproto.CanonicalMIMEHeaderKey is used
-// to canonicalize the provided key.
-// If there are no values associated with the key, Get returns "".
-// To access multiple values of a key, or to use non-canonical keys,
-// access the map directly.
+// Get gets the first value associated with the given key. If
+// there are no values associated with the key, Get returns "".
+// It is case insensitive; textproto.CanonicalMIMEHeaderKey is
+// used to canonicalize the provided key. To access multiple
+// values of a key, or to use non-canonical keys, access the
+// map directly.
func (h Header) Get(key string) string {
return textproto.MIMEHeader(h).Get(key)
}
@@ -49,6 +53,8 @@ func (h Header) get(key string) string {
}
// Del deletes the values associated with key.
+// The key is case insensitive; it is canonicalized by
+// textproto.CanonicalMIMEHeaderKey.
func (h Header) Del(key string) {
textproto.MIMEHeader(h).Del(key)
}
@@ -93,10 +99,6 @@ func ParseTime(text string) (t time.Time, err error) {
var headerNewlineToSpace = strings.NewReplacer("\n", " ", "\r", " ")
-type writeStringer interface {
- WriteString(string) (int, error)
-}
-
// stringWriter implements WriteString on a Writer.
type stringWriter struct {
w io.Writer
@@ -152,7 +154,7 @@ func (h Header) WriteSubset(w io.Writer, exclude map[string]bool) error {
}
func (h Header) writeSubset(w io.Writer, exclude map[string]bool, trace *httptrace.ClientTrace) error {
- ws, ok := w.(writeStringer)
+ ws, ok := w.(io.StringWriter)
if !ok {
ws = stringWriter{w}
}
@@ -229,13 +231,3 @@ func hasToken(v, token string) bool {
func isTokenBoundary(b byte) bool {
return b == ' ' || b == ',' || b == '\t'
}
-
-func cloneHeader(h Header) Header {
- h2 := make(Header, len(h))
- for k, vv := range h {
- vv2 := make([]string, len(vv))
- copy(vv2, vv)
- h2[k] = vv2
- }
- return h2
-}
diff --git a/src/net/http/http.go b/src/net/http/http.go
index ce0eceb1de..30d1a52b63 100644
--- a/src/net/http/http.go
+++ b/src/net/http/http.go
@@ -135,6 +135,10 @@ type Pusher interface {
// data that may trigger a request for URL X. This avoids a race where the
// client issues requests for X before receiving the PUSH_PROMISE for X.
//
+ // Push will run in a separate goroutine making the order of arrival
+ // non-deterministic. Any required synchronization needs to be implemented
+ // by the caller.
+ //
// Push returns ErrNotSupported if the client has disabled push or if push
// is not supported on the underlying connection.
Push(target string, opts *PushOptions) error
diff --git a/src/net/http/httputil/dump_test.go b/src/net/http/httputil/dump_test.go
index 5703a7fb86..63312dd885 100644
--- a/src/net/http/httputil/dump_test.go
+++ b/src/net/http/httputil/dump_test.go
@@ -370,7 +370,7 @@ func TestDumpResponse(t *testing.T) {
}
got := string(gotb)
got = strings.TrimSpace(got)
- got = strings.Replace(got, "\r", "", -1)
+ got = strings.ReplaceAll(got, "\r", "")
if got != tt.want {
t.Errorf("%d.\nDumpResponse got:\n%s\n\nWant:\n%s\n", i, got, tt.want)
diff --git a/src/net/http/proxy_test.go b/src/net/http/proxy_test.go
index eef0ca82f8..feb7047a58 100644
--- a/src/net/http/proxy_test.go
+++ b/src/net/http/proxy_test.go
@@ -35,7 +35,7 @@ func TestCacheKeys(t *testing.T) {
}
proxy = u
}
- cm := connectMethod{proxy, tt.scheme, tt.addr}
+ cm := connectMethod{proxy, tt.scheme, tt.addr, false}
if got := cm.key().String(); got != tt.key {
t.Fatalf("{%q, %q, %q} cache key = %q; want %q", tt.proxy, tt.scheme, tt.addr, got, tt.key)
}
diff --git a/src/net/http/readrequest_test.go b/src/net/http/readrequest_test.go
index 18eed345a8..517a8189e1 100644
--- a/src/net/http/readrequest_test.go
+++ b/src/net/http/readrequest_test.go
@@ -438,7 +438,7 @@ func TestReadRequest(t *testing.T) {
// reqBytes treats req as a request (with \n delimiters) and returns it with \r\n delimiters,
// ending in \r\n\r\n
func reqBytes(req string) []byte {
- return []byte(strings.Replace(strings.TrimSpace(req), "\n", "\r\n", -1) + "\r\n\r\n")
+ return []byte(strings.ReplaceAll(strings.TrimSpace(req), "\n", "\r\n") + "\r\n\r\n")
}
var badRequestTests = []struct {
diff --git a/src/net/http/request.go b/src/net/http/request.go
index a40b0a3cb8..967de7917f 100644
--- a/src/net/http/request.go
+++ b/src/net/http/request.go
@@ -105,7 +105,7 @@ var reqWriteExcludeHeader = map[string]bool{
// documentation for Request.Write and RoundTripper.
type Request struct {
// Method specifies the HTTP method (GET, POST, PUT, etc.).
- // For client requests an empty string means GET.
+ // For client requests, an empty string means GET.
//
// Go's HTTP client does not support sending a request with
// the CONNECT method. See the documentation on Transport for
@@ -115,7 +115,7 @@ type Request struct {
// URL specifies either the URI being requested (for server
// requests) or the URL to access (for client requests).
//
- // For server requests the URL is parsed from the URI
+ // For server requests, the URL is parsed from the URI
// supplied on the Request-Line as stored in RequestURI. For
// most requests, fields other than Path and RawQuery will be
// empty. (See RFC 7230, Section 5.3)
@@ -128,7 +128,7 @@ type Request struct {
// The protocol version for incoming server requests.
//
- // For client requests these fields are ignored. The HTTP
+ // For client requests, these fields are ignored. The HTTP
// client code always uses either HTTP/1.1 or HTTP/2.
// See the docs on Transport for details.
Proto string // "HTTP/1.0"
@@ -170,11 +170,11 @@ type Request struct {
// Body is the request's body.
//
- // For client requests a nil body means the request has no
+ // For client requests, a nil body means the request has no
// body, such as a GET request. The HTTP Client's Transport
// is responsible for calling the Close method.
//
- // For server requests the Request Body is always non-nil
+ // For server requests, the Request Body is always non-nil
// but will return EOF immediately when no body is present.
// The Server will close the request body. The ServeHTTP
// Handler does not need to.
@@ -185,13 +185,14 @@ type Request struct {
// reading the body more than once. Use of GetBody still
// requires setting Body.
//
- // For server requests it is unused.
+ // For server requests, it is unused.
GetBody func() (io.ReadCloser, error)
// ContentLength records the length of the associated content.
// The value -1 indicates that the length is unknown.
// Values >= 0 indicate that the given number of bytes may
// be read from Body.
+ //
// For client requests, a value of 0 with a non-nil Body is
// also treated as unknown.
ContentLength int64
@@ -215,7 +216,7 @@ type Request struct {
// Transport.DisableKeepAlives were set.
Close bool
- // For server requests Host specifies the host on which the URL
+ // For server requests, Host specifies the host on which the URL
// is sought. Per RFC 7230, section 5.4, this is either the value
// of the "Host" header or the host name given in the URL itself.
// It may be of the form "host:port". For international domain
@@ -228,7 +229,7 @@ type Request struct {
// ServeMux supports patterns registered to particular host
// names and thus protects its registered Handlers.
//
- // For client requests Host optionally overrides the Host
+ // For client requests, Host optionally overrides the Host
// header to send. If empty, the Request.Write method uses
// the value of URL.Host. Host may contain an international
// domain name.
@@ -255,14 +256,14 @@ type Request struct {
// Trailer specifies additional headers that are sent after the request
// body.
//
- // For server requests the Trailer map initially contains only the
+ // For server requests, the Trailer map initially contains only the
// trailer keys, with nil values. (The client declares which trailers it
// will later send.) While the handler is reading from Body, it must
// not reference Trailer. After reading from Body returns EOF, Trailer
// can be read again and will contain non-nil values, if they were sent
// by the client.
//
- // For client requests Trailer must be initialized to a map containing
+ // For client requests, Trailer must be initialized to a map containing
// the trailer keys to later send. The values may be nil or their final
// values. The ContentLength must be 0 or -1, to send a chunked request.
// After the HTTP request is sent the map values can be updated while
@@ -1370,3 +1371,10 @@ func requestMethodUsuallyLacksBody(method string) bool {
}
return false
}
+
+// requiresHTTP1 reports whether this request requires being sent on
+// an HTTP/1 connection.
+func (r *Request) requiresHTTP1() bool {
+ return hasToken(r.Header.Get("Connection"), "upgrade") &&
+ strings.EqualFold(r.Header.Get("Upgrade"), "websocket")
+}
diff --git a/src/net/http/request_test.go b/src/net/http/request_test.go
index 7a83ae5b1c..e8005571df 100644
--- a/src/net/http/request_test.go
+++ b/src/net/http/request_test.go
@@ -878,7 +878,7 @@ func testMissingFile(t *testing.T, req *Request) {
}
func newTestMultipartRequest(t *testing.T) *Request {
- b := strings.NewReader(strings.Replace(message, "\n", "\r\n", -1))
+ b := strings.NewReader(strings.ReplaceAll(message, "\n", "\r\n"))
req, err := NewRequest("POST", "/", b)
if err != nil {
t.Fatal("NewRequest:", err)
@@ -970,8 +970,8 @@ Content-Disposition: form-data; name="textb"
`
func benchmarkReadRequest(b *testing.B, request string) {
- request = request + "\n" // final \n
- request = strings.Replace(request, "\n", "\r\n", -1) // expand \n to \r\n
+ request = request + "\n" // final \n
+ request = strings.ReplaceAll(request, "\n", "\r\n") // expand \n to \r\n
b.SetBytes(int64(len(request)))
r := bufio.NewReader(&infiniteReader{buf: []byte(request)})
b.ReportAllocs()
diff --git a/src/net/http/roundtrip_js.go b/src/net/http/roundtrip_js.go
index 16b7b891c8..38e4f5573e 100644
--- a/src/net/http/roundtrip_js.go
+++ b/src/net/http/roundtrip_js.go
@@ -116,7 +116,9 @@ func (t *Transport) RoundTrip(req *Request) (*Response, error) {
b := result.Get("body")
var body io.ReadCloser
- if b != js.Undefined() {
+ // The body is undefined when the browser does not support streaming response bodies (Firefox),
+ // and null in certain error cases, i.e. when the request is blocked because of CORS settings.
+ if b != js.Undefined() && b != js.Null() {
body = &streamReader{stream: b.Call("getReader")}
} else {
// Fall back to using ArrayBuffer
diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go
index 8dae95678d..a282c4bc17 100644
--- a/src/net/http/serve_test.go
+++ b/src/net/http/serve_test.go
@@ -130,7 +130,7 @@ func (c *testConn) Close() error {
// reqBytes treats req as a request (with \n delimiters) and returns it with \r\n delimiters,
// ending in \r\n\r\n
func reqBytes(req string) []byte {
- return []byte(strings.Replace(strings.TrimSpace(req), "\n", "\r\n", -1) + "\r\n\r\n")
+ return []byte(strings.ReplaceAll(strings.TrimSpace(req), "\n", "\r\n") + "\r\n\r\n")
}
type handlerTest struct {
@@ -4028,21 +4028,18 @@ func TestRequestBodyCloseDoesntBlock(t *testing.T) {
}
}
-// test that ResponseWriter implements io.stringWriter.
+// test that ResponseWriter implements io.StringWriter.
func TestResponseWriterWriteString(t *testing.T) {
okc := make(chan bool, 1)
ht := newHandlerTest(HandlerFunc(func(w ResponseWriter, r *Request) {
- type stringWriter interface {
- WriteString(s string) (n int, err error)
- }
- _, ok := w.(stringWriter)
+ _, ok := w.(io.StringWriter)
okc <- ok
}))
ht.rawResponse("GET / HTTP/1.0")
select {
case ok := <-okc:
if !ok {
- t.Error("ResponseWriter did not implement io.stringWriter")
+ t.Error("ResponseWriter did not implement io.StringWriter")
}
default:
t.Error("handler was never called")
diff --git a/src/net/http/server.go b/src/net/http/server.go
index 449cfe5121..4227343fbe 100644
--- a/src/net/http/server.go
+++ b/src/net/http/server.go
@@ -1093,13 +1093,34 @@ func checkWriteHeaderCode(code int) {
}
}
+// relevantCaller searches the call stack for the first function outside of net/http.
+// The purpose of this function is to provide more helpful error messages.
+func relevantCaller() runtime.Frame {
+ pc := make([]uintptr, 16)
+ n := runtime.Callers(1, pc)
+ frames := runtime.CallersFrames(pc[:n])
+ var frame runtime.Frame
+ for {
+ frame, more := frames.Next()
+ if !strings.HasPrefix(frame.Function, "net/http.") {
+ return frame
+ }
+ if !more {
+ break
+ }
+ }
+ return frame
+}
+
func (w *response) WriteHeader(code int) {
if w.conn.hijacked() {
- w.conn.server.logf("http: response.WriteHeader on hijacked connection")
+ caller := relevantCaller()
+ w.conn.server.logf("http: response.WriteHeader on hijacked connection from %s (%s:%d)", caller.Function, path.Base(caller.File), caller.Line)
return
}
if w.wroteHeader {
- w.conn.server.logf("http: multiple response.WriteHeader calls")
+ caller := relevantCaller()
+ w.conn.server.logf("http: superfluous response.WriteHeader call from %s (%s:%d)", caller.Function, path.Base(caller.File), caller.Line)
return
}
checkWriteHeaderCode(code)
@@ -1529,7 +1550,8 @@ func (w *response) WriteString(data string) (n int, err error) {
func (w *response) write(lenData int, dataB []byte, dataS string) (n int, err error) {
if w.conn.hijacked() {
if lenData > 0 {
- w.conn.server.logf("http: response.Write on hijacked connection")
+ caller := relevantCaller()
+ w.conn.server.logf("http: response.Write on hijacked connection from %s (%s:%d)", caller.Function, path.Base(caller.File), caller.Line)
}
return 0, ErrHijacked
}
diff --git a/src/net/http/transport.go b/src/net/http/transport.go
index ffe4cdc0d6..b298ec6d7d 100644
--- a/src/net/http/transport.go
+++ b/src/net/http/transport.go
@@ -278,7 +278,7 @@ func (t *Transport) onceSetNextProtoDefaults() {
// If they've already configured http2 with
// golang.org/x/net/http2 instead of the bundled copy, try to
- // get at its http2.Transport value (via the the "https"
+ // get at its http2.Transport value (via the "https"
// altproto map) so we can call CloseIdleConnections on it if
// requested. (Issue 22891)
altProto, _ := t.altProto.Load().(map[string]RoundTripper)
@@ -286,6 +286,7 @@ func (t *Transport) onceSetNextProtoDefaults() {
if v := rv.Field(0); v.CanInterface() {
if h2i, ok := v.Interface().(h2Transport); ok {
t.h2transport = h2i
+ return
}
}
}
@@ -381,6 +382,19 @@ func (tr *transportRequest) setError(err error) {
tr.mu.Unlock()
}
+// useRegisteredProtocol reports whether an alternate protocol (as reqistered
+// with Transport.RegisterProtocol) should be respected for this request.
+func (t *Transport) useRegisteredProtocol(req *Request) bool {
+ if req.URL.Scheme == "https" && req.requiresHTTP1() {
+ // If this request requires HTTP/1, don't use the
+ // "https" alternate protocol, which is used by the
+ // HTTP/2 code to take over requests if there's an
+ // existing cached HTTP/2 connection.
+ return false
+ }
+ return true
+}
+
// roundTrip implements a RoundTripper over HTTP.
func (t *Transport) roundTrip(req *Request) (*Response, error) {
t.nextProtoOnce.Do(t.onceSetNextProtoDefaults)
@@ -410,10 +424,12 @@ func (t *Transport) roundTrip(req *Request) (*Response, error) {
}
}
- altProto, _ := t.altProto.Load().(map[string]RoundTripper)
- if altRT := altProto[scheme]; altRT != nil {
- if resp, err := altRT.RoundTrip(req); err != ErrSkipAltProtocol {
- return resp, err
+ if t.useRegisteredProtocol(req) {
+ altProto, _ := t.altProto.Load().(map[string]RoundTripper)
+ if altRT := altProto[scheme]; altRT != nil {
+ if resp, err := altRT.RoundTrip(req); err != ErrSkipAltProtocol {
+ return resp, err
+ }
}
}
if !isHTTP {
@@ -477,9 +493,8 @@ func (t *Transport) roundTrip(req *Request) (*Response, error) {
}
testHookRoundTripRetried()
- // Rewind the body if we're able to. (HTTP/2 does this itself so we only
- // need to do it for HTTP/1.1 connections.)
- if req.GetBody != nil && pconn.alt == nil {
+ // Rewind the body if we're able to.
+ if req.GetBody != nil {
newReq := *req
var err error
newReq.Body, err = req.GetBody()
@@ -653,6 +668,7 @@ func (t *Transport) connectMethodForRequest(treq *transportRequest) (cm connectM
}
}
}
+ cm.onlyH1 = treq.requiresHTTP1()
return cm, err
}
@@ -1155,6 +1171,9 @@ func (pconn *persistConn) addTLS(name string, trace *httptrace.ClientTrace) erro
if cfg.ServerName == "" {
cfg.ServerName = name
}
+ if pconn.cacheKey.onlyH1 {
+ cfg.NextProtos = nil
+ }
plainConn := pconn.conn
tlsConn := tls.Client(plainConn, cfg)
errc := make(chan error, 2)
@@ -1361,10 +1380,11 @@ func (w persistConnWriter) Write(p []byte) (n int, err error) {
//
// A connect method may be of the following types:
//
-// Cache key form Description
-// ----------------- -------------------------
+// connectMethod.key().String() Description
+// ------------------------------ -------------------------
// |http|foo.com http directly to server, no proxy
// |https|foo.com https directly to server, no proxy
+// |https,h1|foo.com https directly to server w/o HTTP/2, no proxy
// http://proxy.com|https|foo.com http to proxy, then CONNECT to foo.com
// http://proxy.com|http http to proxy, http to anywhere after that
// socks5://proxy.com|http|foo.com socks5 to proxy, then http to foo.com
@@ -1379,6 +1399,7 @@ type connectMethod struct {
// then targetAddr is not included in the connect method key, because the socket can
// be reused for different targetAddr values.
targetAddr string
+ onlyH1 bool // whether to disable HTTP/2 and force HTTP/1
}
func (cm *connectMethod) key() connectMethodKey {
@@ -1394,6 +1415,7 @@ func (cm *connectMethod) key() connectMethodKey {
proxy: proxyStr,
scheme: cm.targetScheme,
addr: targetAddr,
+ onlyH1: cm.onlyH1,
}
}
@@ -1428,11 +1450,16 @@ func (cm *connectMethod) tlsHost() string {
// a URL.
type connectMethodKey struct {
proxy, scheme, addr string
+ onlyH1 bool
}
func (k connectMethodKey) String() string {
// Only used by tests.
- return fmt.Sprintf("%s|%s|%s", k.proxy, k.scheme, k.addr)
+ var h1 string
+ if k.onlyH1 {
+ h1 = ",h1"
+ }
+ return fmt.Sprintf("%s|%s%s|%s", k.proxy, k.scheme, h1, k.addr)
}
// persistConn wraps a connection, usually a persistent one
diff --git a/src/net/http/transport_internal_test.go b/src/net/http/transport_internal_test.go
index a5f29c97a9..92729e65b2 100644
--- a/src/net/http/transport_internal_test.go
+++ b/src/net/http/transport_internal_test.go
@@ -7,8 +7,13 @@
package http
import (
+ "bytes"
+ "crypto/tls"
"errors"
+ "io"
+ "io/ioutil"
"net"
+ "net/http/internal"
"strings"
"testing"
)
@@ -178,3 +183,81 @@ func TestTransportShouldRetryRequest(t *testing.T) {
}
}
}
+
+type roundTripFunc func(r *Request) (*Response, error)
+
+func (f roundTripFunc) RoundTrip(r *Request) (*Response, error) {
+ return f(r)
+}
+
+// Issue 25009
+func TestTransportBodyAltRewind(t *testing.T) {
+ cert, err := tls.X509KeyPair(internal.LocalhostCert, internal.LocalhostKey)
+ if err != nil {
+ t.Fatal(err)
+ }
+ ln := newLocalListener(t)
+ defer ln.Close()
+
+ go func() {
+ tln := tls.NewListener(ln, &tls.Config{
+ NextProtos: []string{"foo"},
+ Certificates: []tls.Certificate{cert},
+ })
+ for i := 0; i < 2; i++ {
+ sc, err := tln.Accept()
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if err := sc.(*tls.Conn).Handshake(); err != nil {
+ t.Error(err)
+ return
+ }
+ sc.Close()
+ }
+ }()
+
+ addr := ln.Addr().String()
+ req, _ := NewRequest("POST", "https://example.org/", bytes.NewBufferString("request"))
+ roundTripped := false
+ tr := &Transport{
+ DisableKeepAlives: true,
+ TLSNextProto: map[string]func(string, *tls.Conn) RoundTripper{
+ "foo": func(authority string, c *tls.Conn) RoundTripper {
+ return roundTripFunc(func(r *Request) (*Response, error) {
+ n, _ := io.Copy(ioutil.Discard, r.Body)
+ if n == 0 {
+ t.Error("body length is zero")
+ }
+ if roundTripped {
+ return &Response{
+ Body: NoBody,
+ StatusCode: 200,
+ }, nil
+ }
+ roundTripped = true
+ return nil, http2noCachedConnError{}
+ })
+ },
+ },
+ DialTLS: func(_, _ string) (net.Conn, error) {
+ tc, err := tls.Dial("tcp", addr, &tls.Config{
+ InsecureSkipVerify: true,
+ NextProtos: []string{"foo"},
+ })
+ if err != nil {
+ return nil, err
+ }
+ if err := tc.Handshake(); err != nil {
+ return nil, err
+ }
+ return tc, nil
+ },
+ }
+ c := &Client{Transport: tr}
+ _, err = c.Do(req)
+ if err != nil {
+ t.Error(err)
+ }
+}
diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go
index 327b3b4996..739fe5f597 100644
--- a/src/net/http/transport_test.go
+++ b/src/net/http/transport_test.go
@@ -4753,7 +4753,7 @@ func TestClientTimeoutKillsConn_BeforeHeaders(t *testing.T) {
}
case <-time.After(timeout * 10):
// If we didn't get into the Handler in 50ms, that probably means
- // the builder was just slow and the the Get failed in that time
+ // the builder was just slow and the Get failed in that time
// but never made it to the server. That's fine. We'll usually
// test the part above on faster machines.
t.Skip("skipping test on slow builder")
@@ -4764,7 +4764,7 @@ func TestClientTimeoutKillsConn_BeforeHeaders(t *testing.T) {
// conn is closed so that it's not reused.
//
// This is the test variant that has the server send response headers
-// first, and time out during the the write of the response body.
+// first, and time out during the write of the response body.
func TestClientTimeoutKillsConn_AfterHeaders(t *testing.T) {
setParallel(t)
defer afterTest(t)
diff --git a/src/net/lookup_unix.go b/src/net/lookup_unix.go
index 04f443bb1a..1266680706 100644
--- a/src/net/lookup_unix.go
+++ b/src/net/lookup_unix.go
@@ -300,11 +300,21 @@ func (r *Resolver) lookupTXT(ctx context.Context, name string) ([]string, error)
Server: server,
}
}
+ // Multiple strings in one TXT record need to be
+ // concatenated without separator to be consistent
+ // with previous Go resolver.
+ n := 0
+ for _, s := range txt.TXT {
+ n += len(s)
+ }
+ txtJoin := make([]byte, 0, n)
+ for _, s := range txt.TXT {
+ txtJoin = append(txtJoin, s...)
+ }
if len(txts) == 0 {
- txts = txt.TXT
- } else {
- txts = append(txts, txt.TXT...)
+ txts = make([]string, 0, 1)
}
+ txts = append(txts, string(txtJoin))
}
return txts, nil
}
diff --git a/src/net/lookup_windows_test.go b/src/net/lookup_windows_test.go
index cebb2d0558..d3748f28c3 100644
--- a/src/net/lookup_windows_test.go
+++ b/src/net/lookup_windows_test.go
@@ -150,7 +150,7 @@ func nslookup(qtype, name string) (string, error) {
if err := cmd.Run(); err != nil {
return "", err
}
- r := strings.Replace(out.String(), "\r\n", "\n", -1)
+ r := strings.ReplaceAll(out.String(), "\r\n", "\n")
// nslookup stderr output contains also debug information such as
// "Non-authoritative answer" and it doesn't return the correct errcode
if strings.Contains(err.String(), "can't find") {
diff --git a/src/net/mail/message_test.go b/src/net/mail/message_test.go
index b19da52c42..14ac9192a4 100644
--- a/src/net/mail/message_test.go
+++ b/src/net/mail/message_test.go
@@ -668,9 +668,9 @@ func TestAddressParser(t *testing.T) {
switch charset {
case "iso-8859-15":
- in = bytes.Replace(in, []byte("\xf6"), []byte("ö"), -1)
+ in = bytes.ReplaceAll(in, []byte("\xf6"), []byte("ö"))
case "windows-1252":
- in = bytes.Replace(in, []byte("\xe9"), []byte("é"), -1)
+ in = bytes.ReplaceAll(in, []byte("\xe9"), []byte("é"))
}
return bytes.NewReader(in), nil
diff --git a/src/net/net_windows_test.go b/src/net/net_windows_test.go
index 8dfd312980..8aa719f433 100644
--- a/src/net/net_windows_test.go
+++ b/src/net/net_windows_test.go
@@ -571,7 +571,7 @@ func TestInterfaceHardwareAddrWithGetmac(t *testing.T) {
// skip these
return
}
- addr = strings.Replace(addr, "-", ":", -1)
+ addr = strings.ReplaceAll(addr, "-", ":")
cname := getValue("Connection Name")
want[cname] = addr
group = make(map[string]string)
diff --git a/src/net/sendfile_test.go b/src/net/sendfile_test.go
index 3b982774b0..f133744a66 100644
--- a/src/net/sendfile_test.go
+++ b/src/net/sendfile_test.go
@@ -17,9 +17,9 @@ import (
)
const (
- twain = "testdata/Mark.Twain-Tom.Sawyer.txt"
- twainLen = 387851
- twainSHA256 = "461eb7cb2d57d293fc680c836464c9125e4382be3596f7d415093ae9db8fcb0e"
+ newton = "../testdata/Isaac.Newton-Opticks.txt"
+ newtonLen = 567198
+ newtonSHA256 = "d4a9ac22462b35e7821a4f2706c211093da678620a8f9997989ee7cf8d507bbd"
)
func TestSendfile(t *testing.T) {
@@ -43,7 +43,7 @@ func TestSendfile(t *testing.T) {
defer close(errc)
defer conn.Close()
- f, err := os.Open(twain)
+ f, err := os.Open(newton)
if err != nil {
errc <- err
return
@@ -58,8 +58,8 @@ func TestSendfile(t *testing.T) {
return
}
- if sbytes != twainLen {
- errc <- fmt.Errorf("sent %d bytes; expected %d", sbytes, twainLen)
+ if sbytes != newtonLen {
+ errc <- fmt.Errorf("sent %d bytes; expected %d", sbytes, newtonLen)
return
}
}()
@@ -79,11 +79,11 @@ func TestSendfile(t *testing.T) {
t.Error(err)
}
- if rbytes != twainLen {
- t.Errorf("received %d bytes; expected %d", rbytes, twainLen)
+ if rbytes != newtonLen {
+ t.Errorf("received %d bytes; expected %d", rbytes, newtonLen)
}
- if res := hex.EncodeToString(h.Sum(nil)); res != twainSHA256 {
+ if res := hex.EncodeToString(h.Sum(nil)); res != newtonSHA256 {
t.Error("retrieved data hash did not match")
}
@@ -113,7 +113,7 @@ func TestSendfileParts(t *testing.T) {
defer close(errc)
defer conn.Close()
- f, err := os.Open(twain)
+ f, err := os.Open(newton)
if err != nil {
errc <- err
return
@@ -174,7 +174,7 @@ func TestSendfileSeeked(t *testing.T) {
defer close(errc)
defer conn.Close()
- f, err := os.Open(twain)
+ f, err := os.Open(newton)
if err != nil {
errc <- err
return
diff --git a/src/net/splice_linux.go b/src/net/splice_linux.go
index 8a4d55af62..69c3f65770 100644
--- a/src/net/splice_linux.go
+++ b/src/net/splice_linux.go
@@ -11,7 +11,7 @@ import (
// splice transfers data from r to c using the splice system call to minimize
// copies from and to userspace. c must be a TCP connection. Currently, splice
-// is only enabled if r is a TCP or Unix connection.
+// is only enabled if r is a TCP or a stream-oriented Unix connection.
//
// If splice returns handled == false, it has performed no work.
func splice(c *netFD, r io.Reader) (written int64, err error, handled bool) {
@@ -28,6 +28,9 @@ func splice(c *netFD, r io.Reader) (written int64, err error, handled bool) {
if tc, ok := r.(*TCPConn); ok {
s = tc.fd
} else if uc, ok := r.(*UnixConn); ok {
+ if uc.fd.net != "unix" {
+ return 0, nil, false
+ }
s = uc.fd
} else {
return 0, nil, false
diff --git a/src/net/splice_test.go b/src/net/splice_test.go
index 93e8b1f8cc..4c300172c5 100644
--- a/src/net/splice_test.go
+++ b/src/net/splice_test.go
@@ -24,6 +24,8 @@ func TestSplice(t *testing.T) {
t.Skip("skipping unix-to-tcp tests")
}
t.Run("unix-to-tcp", func(t *testing.T) { testSplice(t, "unix", "tcp") })
+ t.Run("no-unixpacket", testSpliceNoUnixpacket)
+ t.Run("no-unixgram", testSpliceNoUnixgram)
}
func testSplice(t *testing.T, upNet, downNet string) {
@@ -208,6 +210,56 @@ func testSpliceIssue25985(t *testing.T, upNet, downNet string) {
wg.Wait()
}
+func testSpliceNoUnixpacket(t *testing.T) {
+ clientUp, serverUp, err := spliceTestSocketPair("unixpacket")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer clientUp.Close()
+ defer serverUp.Close()
+ clientDown, serverDown, err := spliceTestSocketPair("tcp")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer clientDown.Close()
+ defer serverDown.Close()
+ // If splice called poll.Splice here, we'd get err == syscall.EINVAL
+ // and handled == false. If poll.Splice gets an EINVAL on the first
+ // try, it assumes the kernel it's running on doesn't support splice
+ // for unix sockets and returns handled == false. This works for our
+ // purposes by somewhat of an accident, but is not entirely correct.
+ //
+ // What we want is err == nil and handled == false, i.e. we never
+ // called poll.Splice, because we know the unix socket's network.
+ _, err, handled := splice(serverDown.(*TCPConn).fd, serverUp)
+ if err != nil || handled != false {
+ t.Fatalf("got err = %v, handled = %t, want nil error, handled == false", err, handled)
+ }
+}
+
+func testSpliceNoUnixgram(t *testing.T) {
+ addr, err := ResolveUnixAddr("unixgram", testUnixAddr())
+ if err != nil {
+ t.Fatal(err)
+ }
+ up, err := ListenUnixgram("unixgram", addr)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer up.Close()
+ clientDown, serverDown, err := spliceTestSocketPair("tcp")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer clientDown.Close()
+ defer serverDown.Close()
+ // Analogous to testSpliceNoUnixpacket.
+ _, err, handled := splice(serverDown.(*TCPConn).fd, up)
+ if err != nil || handled != false {
+ t.Fatalf("got err = %v, handled = %t, want nil error, handled == false", err, handled)
+ }
+}
+
func BenchmarkSplice(b *testing.B) {
testHookUninstaller.Do(uninstallTestHooks)
diff --git a/src/net/testdata/Mark.Twain-Tom.Sawyer.txt b/src/net/testdata/Mark.Twain-Tom.Sawyer.txt
deleted file mode 100644
index c9106fd522..0000000000
--- a/src/net/testdata/Mark.Twain-Tom.Sawyer.txt
+++ /dev/null
@@ -1,8465 +0,0 @@
-Produced by David Widger. The previous edition was updated by Jose
-Menendez.
-
-
-
-
-
- THE ADVENTURES OF TOM SAWYER
- BY
- MARK TWAIN
- (Samuel Langhorne Clemens)
-
-
-
-
- P R E F A C E
-
-MOST of the adventures recorded in this book really occurred; one or
-two were experiences of my own, the rest those of boys who were
-schoolmates of mine. Huck Finn is drawn from life; Tom Sawyer also, but
-not from an individual--he is a combination of the characteristics of
-three boys whom I knew, and therefore belongs to the composite order of
-architecture.
-
-The odd superstitions touched upon were all prevalent among children
-and slaves in the West at the period of this story--that is to say,
-thirty or forty years ago.
-
-Although my book is intended mainly for the entertainment of boys and
-girls, I hope it will not be shunned by men and women on that account,
-for part of my plan has been to try to pleasantly remind adults of what
-they once were themselves, and of how they felt and thought and talked,
-and what queer enterprises they sometimes engaged in.
-
- THE AUTHOR.
-
-HARTFORD, 1876.
-
-
-
- T O M S A W Y E R
-
-
-
-CHAPTER I
-
-"TOM!"
-
-No answer.
-
-"TOM!"
-
-No answer.
-
-"What's gone with that boy, I wonder? You TOM!"
-
-No answer.
-
-The old lady pulled her spectacles down and looked over them about the
-room; then she put them up and looked out under them. She seldom or
-never looked THROUGH them for so small a thing as a boy; they were her
-state pair, the pride of her heart, and were built for "style," not
-service--she could have seen through a pair of stove-lids just as well.
-She looked perplexed for a moment, and then said, not fiercely, but
-still loud enough for the furniture to hear:
-
-"Well, I lay if I get hold of you I'll--"
-
-She did not finish, for by this time she was bending down and punching
-under the bed with the broom, and so she needed breath to punctuate the
-punches with. She resurrected nothing but the cat.
-
-"I never did see the beat of that boy!"
-
-She went to the open door and stood in it and looked out among the
-tomato vines and "jimpson" weeds that constituted the garden. No Tom.
-So she lifted up her voice at an angle calculated for distance and
-shouted:
-
-"Y-o-u-u TOM!"
-
-There was a slight noise behind her and she turned just in time to
-seize a small boy by the slack of his roundabout and arrest his flight.
-
-"There! I might 'a' thought of that closet. What you been doing in
-there?"
-
-"Nothing."
-
-"Nothing! Look at your hands. And look at your mouth. What IS that
-truck?"
-
-"I don't know, aunt."
-
-"Well, I know. It's jam--that's what it is. Forty times I've said if
-you didn't let that jam alone I'd skin you. Hand me that switch."
-
-The switch hovered in the air--the peril was desperate--
-
-"My! Look behind you, aunt!"
-
-The old lady whirled round, and snatched her skirts out of danger. The
-lad fled on the instant, scrambled up the high board-fence, and
-disappeared over it.
-
-His aunt Polly stood surprised a moment, and then broke into a gentle
-laugh.
-
-"Hang the boy, can't I never learn anything? Ain't he played me tricks
-enough like that for me to be looking out for him by this time? But old
-fools is the biggest fools there is. Can't learn an old dog new tricks,
-as the saying is. But my goodness, he never plays them alike, two days,
-and how is a body to know what's coming? He 'pears to know just how
-long he can torment me before I get my dander up, and he knows if he
-can make out to put me off for a minute or make me laugh, it's all down
-again and I can't hit him a lick. I ain't doing my duty by that boy,
-and that's the Lord's truth, goodness knows. Spare the rod and spile
-the child, as the Good Book says. I'm a laying up sin and suffering for
-us both, I know. He's full of the Old Scratch, but laws-a-me! he's my
-own dead sister's boy, poor thing, and I ain't got the heart to lash
-him, somehow. Every time I let him off, my conscience does hurt me so,
-and every time I hit him my old heart most breaks. Well-a-well, man
-that is born of woman is of few days and full of trouble, as the
-Scripture says, and I reckon it's so. He'll play hookey this evening, *
-and [* Southwestern for "afternoon"] I'll just be obleeged to make him
-work, to-morrow, to punish him. It's mighty hard to make him work
-Saturdays, when all the boys is having holiday, but he hates work more
-than he hates anything else, and I've GOT to do some of my duty by him,
-or I'll be the ruination of the child."
-
-Tom did play hookey, and he had a very good time. He got back home
-barely in season to help Jim, the small colored boy, saw next-day's
-wood and split the kindlings before supper--at least he was there in
-time to tell his adventures to Jim while Jim did three-fourths of the
-work. Tom's younger brother (or rather half-brother) Sid was already
-through with his part of the work (picking up chips), for he was a
-quiet boy, and had no adventurous, troublesome ways.
-
-While Tom was eating his supper, and stealing sugar as opportunity
-offered, Aunt Polly asked him questions that were full of guile, and
-very deep--for she wanted to trap him into damaging revealments. Like
-many other simple-hearted souls, it was her pet vanity to believe she
-was endowed with a talent for dark and mysterious diplomacy, and she
-loved to contemplate her most transparent devices as marvels of low
-cunning. Said she:
-
-"Tom, it was middling warm in school, warn't it?"
-
-"Yes'm."
-
-"Powerful warm, warn't it?"
-
-"Yes'm."
-
-"Didn't you want to go in a-swimming, Tom?"
-
-A bit of a scare shot through Tom--a touch of uncomfortable suspicion.
-He searched Aunt Polly's face, but it told him nothing. So he said:
-
-"No'm--well, not very much."
-
-The old lady reached out her hand and felt Tom's shirt, and said:
-
-"But you ain't too warm now, though." And it flattered her to reflect
-that she had discovered that the shirt was dry without anybody knowing
-that that was what she had in her mind. But in spite of her, Tom knew
-where the wind lay, now. So he forestalled what might be the next move:
-
-"Some of us pumped on our heads--mine's damp yet. See?"
-
-Aunt Polly was vexed to think she had overlooked that bit of
-circumstantial evidence, and missed a trick. Then she had a new
-inspiration:
-
-"Tom, you didn't have to undo your shirt collar where I sewed it, to
-pump on your head, did you? Unbutton your jacket!"
-
-The trouble vanished out of Tom's face. He opened his jacket. His
-shirt collar was securely sewed.
-
-"Bother! Well, go 'long with you. I'd made sure you'd played hookey
-and been a-swimming. But I forgive ye, Tom. I reckon you're a kind of a
-singed cat, as the saying is--better'n you look. THIS time."
-
-She was half sorry her sagacity had miscarried, and half glad that Tom
-had stumbled into obedient conduct for once.
-
-But Sidney said:
-
-"Well, now, if I didn't think you sewed his collar with white thread,
-but it's black."
-
-"Why, I did sew it with white! Tom!"
-
-But Tom did not wait for the rest. As he went out at the door he said:
-
-"Siddy, I'll lick you for that."
-
-In a safe place Tom examined two large needles which were thrust into
-the lapels of his jacket, and had thread bound about them--one needle
-carried white thread and the other black. He said:
-
-"She'd never noticed if it hadn't been for Sid. Confound it! sometimes
-she sews it with white, and sometimes she sews it with black. I wish to
-geeminy she'd stick to one or t'other--I can't keep the run of 'em. But
-I bet you I'll lam Sid for that. I'll learn him!"
-
-He was not the Model Boy of the village. He knew the model boy very
-well though--and loathed him.
-
-Within two minutes, or even less, he had forgotten all his troubles.
-Not because his troubles were one whit less heavy and bitter to him
-than a man's are to a man, but because a new and powerful interest bore
-them down and drove them out of his mind for the time--just as men's
-misfortunes are forgotten in the excitement of new enterprises. This
-new interest was a valued novelty in whistling, which he had just
-acquired from a negro, and he was suffering to practise it undisturbed.
-It consisted in a peculiar bird-like turn, a sort of liquid warble,
-produced by touching the tongue to the roof of the mouth at short
-intervals in the midst of the music--the reader probably remembers how
-to do it, if he has ever been a boy. Diligence and attention soon gave
-him the knack of it, and he strode down the street with his mouth full
-of harmony and his soul full of gratitude. He felt much as an
-astronomer feels who has discovered a new planet--no doubt, as far as
-strong, deep, unalloyed pleasure is concerned, the advantage was with
-the boy, not the astronomer.
-
-The summer evenings were long. It was not dark, yet. Presently Tom
-checked his whistle. A stranger was before him--a boy a shade larger
-than himself. A new-comer of any age or either sex was an impressive
-curiosity in the poor little shabby village of St. Petersburg. This boy
-was well dressed, too--well dressed on a week-day. This was simply
-astounding. His cap was a dainty thing, his close-buttoned blue cloth
-roundabout was new and natty, and so were his pantaloons. He had shoes
-on--and it was only Friday. He even wore a necktie, a bright bit of
-ribbon. He had a citified air about him that ate into Tom's vitals. The
-more Tom stared at the splendid marvel, the higher he turned up his
-nose at his finery and the shabbier and shabbier his own outfit seemed
-to him to grow. Neither boy spoke. If one moved, the other moved--but
-only sidewise, in a circle; they kept face to face and eye to eye all
-the time. Finally Tom said:
-
-"I can lick you!"
-
-"I'd like to see you try it."
-
-"Well, I can do it."
-
-"No you can't, either."
-
-"Yes I can."
-
-"No you can't."
-
-"I can."
-
-"You can't."
-
-"Can!"
-
-"Can't!"
-
-An uncomfortable pause. Then Tom said:
-
-"What's your name?"
-
-"'Tisn't any of your business, maybe."
-
-"Well I 'low I'll MAKE it my business."
-
-"Well why don't you?"
-
-"If you say much, I will."
-
-"Much--much--MUCH. There now."
-
-"Oh, you think you're mighty smart, DON'T you? I could lick you with
-one hand tied behind me, if I wanted to."
-
-"Well why don't you DO it? You SAY you can do it."
-
-"Well I WILL, if you fool with me."
-
-"Oh yes--I've seen whole families in the same fix."
-
-"Smarty! You think you're SOME, now, DON'T you? Oh, what a hat!"
-
-"You can lump that hat if you don't like it. I dare you to knock it
-off--and anybody that'll take a dare will suck eggs."
-
-"You're a liar!"
-
-"You're another."
-
-"You're a fighting liar and dasn't take it up."
-
-"Aw--take a walk!"
-
-"Say--if you give me much more of your sass I'll take and bounce a
-rock off'n your head."
-
-"Oh, of COURSE you will."
-
-"Well I WILL."
-
-"Well why don't you DO it then? What do you keep SAYING you will for?
-Why don't you DO it? It's because you're afraid."
-
-"I AIN'T afraid."
-
-"You are."
-
-"I ain't."
-
-"You are."
-
-Another pause, and more eying and sidling around each other. Presently
-they were shoulder to shoulder. Tom said:
-
-"Get away from here!"
-
-"Go away yourself!"
-
-"I won't."
-
-"I won't either."
-
-So they stood, each with a foot placed at an angle as a brace, and
-both shoving with might and main, and glowering at each other with
-hate. But neither could get an advantage. After struggling till both
-were hot and flushed, each relaxed his strain with watchful caution,
-and Tom said:
-
-"You're a coward and a pup. I'll tell my big brother on you, and he
-can thrash you with his little finger, and I'll make him do it, too."
-
-"What do I care for your big brother? I've got a brother that's bigger
-than he is--and what's more, he can throw him over that fence, too."
-[Both brothers were imaginary.]
-
-"That's a lie."
-
-"YOUR saying so don't make it so."
-
-Tom drew a line in the dust with his big toe, and said:
-
-"I dare you to step over that, and I'll lick you till you can't stand
-up. Anybody that'll take a dare will steal sheep."
-
-The new boy stepped over promptly, and said:
-
-"Now you said you'd do it, now let's see you do it."
-
-"Don't you crowd me now; you better look out."
-
-"Well, you SAID you'd do it--why don't you do it?"
-
-"By jingo! for two cents I WILL do it."
-
-The new boy took two broad coppers out of his pocket and held them out
-with derision. Tom struck them to the ground. In an instant both boys
-were rolling and tumbling in the dirt, gripped together like cats; and
-for the space of a minute they tugged and tore at each other's hair and
-clothes, punched and scratched each other's nose, and covered
-themselves with dust and glory. Presently the confusion took form, and
-through the fog of battle Tom appeared, seated astride the new boy, and
-pounding him with his fists. "Holler 'nuff!" said he.
-
-The boy only struggled to free himself. He was crying--mainly from rage.
-
-"Holler 'nuff!"--and the pounding went on.
-
-At last the stranger got out a smothered "'Nuff!" and Tom let him up
-and said:
-
-"Now that'll learn you. Better look out who you're fooling with next
-time."
-
-The new boy went off brushing the dust from his clothes, sobbing,
-snuffling, and occasionally looking back and shaking his head and
-threatening what he would do to Tom the "next time he caught him out."
-To which Tom responded with jeers, and started off in high feather, and
-as soon as his back was turned the new boy snatched up a stone, threw
-it and hit him between the shoulders and then turned tail and ran like
-an antelope. Tom chased the traitor home, and thus found out where he
-lived. He then held a position at the gate for some time, daring the
-enemy to come outside, but the enemy only made faces at him through the
-window and declined. At last the enemy's mother appeared, and called
-Tom a bad, vicious, vulgar child, and ordered him away. So he went
-away; but he said he "'lowed" to "lay" for that boy.
-
-He got home pretty late that night, and when he climbed cautiously in
-at the window, he uncovered an ambuscade, in the person of his aunt;
-and when she saw the state his clothes were in her resolution to turn
-his Saturday holiday into captivity at hard labor became adamantine in
-its firmness.
-
-
-
-CHAPTER II
-
-SATURDAY morning was come, and all the summer world was bright and
-fresh, and brimming with life. There was a song in every heart; and if
-the heart was young the music issued at the lips. There was cheer in
-every face and a spring in every step. The locust-trees were in bloom
-and the fragrance of the blossoms filled the air. Cardiff Hill, beyond
-the village and above it, was green with vegetation and it lay just far
-enough away to seem a Delectable Land, dreamy, reposeful, and inviting.
-
-Tom appeared on the sidewalk with a bucket of whitewash and a
-long-handled brush. He surveyed the fence, and all gladness left him and
-a deep melancholy settled down upon his spirit. Thirty yards of board
-fence nine feet high. Life to him seemed hollow, and existence but a
-burden. Sighing, he dipped his brush and passed it along the topmost
-plank; repeated the operation; did it again; compared the insignificant
-whitewashed streak with the far-reaching continent of unwhitewashed
-fence, and sat down on a tree-box discouraged. Jim came skipping out at
-the gate with a tin pail, and singing Buffalo Gals. Bringing water from
-the town pump had always been hateful work in Tom's eyes, before, but
-now it did not strike him so. He remembered that there was company at
-the pump. White, mulatto, and negro boys and girls were always there
-waiting their turns, resting, trading playthings, quarrelling,
-fighting, skylarking. And he remembered that although the pump was only
-a hundred and fifty yards off, Jim never got back with a bucket of
-water under an hour--and even then somebody generally had to go after
-him. Tom said:
-
-"Say, Jim, I'll fetch the water if you'll whitewash some."
-
-Jim shook his head and said:
-
-"Can't, Mars Tom. Ole missis, she tole me I got to go an' git dis
-water an' not stop foolin' roun' wid anybody. She say she spec' Mars
-Tom gwine to ax me to whitewash, an' so she tole me go 'long an' 'tend
-to my own business--she 'lowed SHE'D 'tend to de whitewashin'."
-
-"Oh, never you mind what she said, Jim. That's the way she always
-talks. Gimme the bucket--I won't be gone only a a minute. SHE won't
-ever know."
-
-"Oh, I dasn't, Mars Tom. Ole missis she'd take an' tar de head off'n
-me. 'Deed she would."
-
-"SHE! She never licks anybody--whacks 'em over the head with her
-thimble--and who cares for that, I'd like to know. She talks awful, but
-talk don't hurt--anyways it don't if she don't cry. Jim, I'll give you
-a marvel. I'll give you a white alley!"
-
-Jim began to waver.
-
-"White alley, Jim! And it's a bully taw."
-
-"My! Dat's a mighty gay marvel, I tell you! But Mars Tom I's powerful
-'fraid ole missis--"
-
-"And besides, if you will I'll show you my sore toe."
-
-Jim was only human--this attraction was too much for him. He put down
-his pail, took the white alley, and bent over the toe with absorbing
-interest while the bandage was being unwound. In another moment he was
-flying down the street with his pail and a tingling rear, Tom was
-whitewashing with vigor, and Aunt Polly was retiring from the field
-with a slipper in her hand and triumph in her eye.
-
-But Tom's energy did not last. He began to think of the fun he had
-planned for this day, and his sorrows multiplied. Soon the free boys
-would come tripping along on all sorts of delicious expeditions, and
-they would make a world of fun of him for having to work--the very
-thought of it burnt him like fire. He got out his worldly wealth and
-examined it--bits of toys, marbles, and trash; enough to buy an
-exchange of WORK, maybe, but not half enough to buy so much as half an
-hour of pure freedom. So he returned his straitened means to his
-pocket, and gave up the idea of trying to buy the boys. At this dark
-and hopeless moment an inspiration burst upon him! Nothing less than a
-great, magnificent inspiration.
-
-He took up his brush and went tranquilly to work. Ben Rogers hove in
-sight presently--the very boy, of all boys, whose ridicule he had been
-dreading. Ben's gait was the hop-skip-and-jump--proof enough that his
-heart was light and his anticipations high. He was eating an apple, and
-giving a long, melodious whoop, at intervals, followed by a deep-toned
-ding-dong-dong, ding-dong-dong, for he was personating a steamboat. As
-he drew near, he slackened speed, took the middle of the street, leaned
-far over to starboard and rounded to ponderously and with laborious
-pomp and circumstance--for he was personating the Big Missouri, and
-considered himself to be drawing nine feet of water. He was boat and
-captain and engine-bells combined, so he had to imagine himself
-standing on his own hurricane-deck giving the orders and executing them:
-
-"Stop her, sir! Ting-a-ling-ling!" The headway ran almost out, and he
-drew up slowly toward the sidewalk.
-
-"Ship up to back! Ting-a-ling-ling!" His arms straightened and
-stiffened down his sides.
-
-"Set her back on the stabboard! Ting-a-ling-ling! Chow! ch-chow-wow!
-Chow!" His right hand, meantime, describing stately circles--for it was
-representing a forty-foot wheel.
-
-"Let her go back on the labboard! Ting-a-lingling! Chow-ch-chow-chow!"
-The left hand began to describe circles.
-
-"Stop the stabboard! Ting-a-ling-ling! Stop the labboard! Come ahead
-on the stabboard! Stop her! Let your outside turn over slow!
-Ting-a-ling-ling! Chow-ow-ow! Get out that head-line! LIVELY now!
-Come--out with your spring-line--what're you about there! Take a turn
-round that stump with the bight of it! Stand by that stage, now--let her
-go! Done with the engines, sir! Ting-a-ling-ling! SH'T! S'H'T! SH'T!"
-(trying the gauge-cocks).
-
-Tom went on whitewashing--paid no attention to the steamboat. Ben
-stared a moment and then said: "Hi-YI! YOU'RE up a stump, ain't you!"
-
-No answer. Tom surveyed his last touch with the eye of an artist, then
-he gave his brush another gentle sweep and surveyed the result, as
-before. Ben ranged up alongside of him. Tom's mouth watered for the
-apple, but he stuck to his work. Ben said:
-
-"Hello, old chap, you got to work, hey?"
-
-Tom wheeled suddenly and said:
-
-"Why, it's you, Ben! I warn't noticing."
-
-"Say--I'm going in a-swimming, I am. Don't you wish you could? But of
-course you'd druther WORK--wouldn't you? Course you would!"
-
-Tom contemplated the boy a bit, and said:
-
-"What do you call work?"
-
-"Why, ain't THAT work?"
-
-Tom resumed his whitewashing, and answered carelessly:
-
-"Well, maybe it is, and maybe it ain't. All I know, is, it suits Tom
-Sawyer."
-
-"Oh come, now, you don't mean to let on that you LIKE it?"
-
-The brush continued to move.
-
-"Like it? Well, I don't see why I oughtn't to like it. Does a boy get
-a chance to whitewash a fence every day?"
-
-That put the thing in a new light. Ben stopped nibbling his apple. Tom
-swept his brush daintily back and forth--stepped back to note the
-effect--added a touch here and there--criticised the effect again--Ben
-watching every move and getting more and more interested, more and more
-absorbed. Presently he said:
-
-"Say, Tom, let ME whitewash a little."
-
-Tom considered, was about to consent; but he altered his mind:
-
-"No--no--I reckon it wouldn't hardly do, Ben. You see, Aunt Polly's
-awful particular about this fence--right here on the street, you know
---but if it was the back fence I wouldn't mind and SHE wouldn't. Yes,
-she's awful particular about this fence; it's got to be done very
-careful; I reckon there ain't one boy in a thousand, maybe two
-thousand, that can do it the way it's got to be done."
-
-"No--is that so? Oh come, now--lemme just try. Only just a little--I'd
-let YOU, if you was me, Tom."
-
-"Ben, I'd like to, honest injun; but Aunt Polly--well, Jim wanted to
-do it, but she wouldn't let him; Sid wanted to do it, and she wouldn't
-let Sid. Now don't you see how I'm fixed? If you was to tackle this
-fence and anything was to happen to it--"
-
-"Oh, shucks, I'll be just as careful. Now lemme try. Say--I'll give
-you the core of my apple."
-
-"Well, here--No, Ben, now don't. I'm afeard--"
-
-"I'll give you ALL of it!"
-
-Tom gave up the brush with reluctance in his face, but alacrity in his
-heart. And while the late steamer Big Missouri worked and sweated in
-the sun, the retired artist sat on a barrel in the shade close by,
-dangled his legs, munched his apple, and planned the slaughter of more
-innocents. There was no lack of material; boys happened along every
-little while; they came to jeer, but remained to whitewash. By the time
-Ben was fagged out, Tom had traded the next chance to Billy Fisher for
-a kite, in good repair; and when he played out, Johnny Miller bought in
-for a dead rat and a string to swing it with--and so on, and so on,
-hour after hour. And when the middle of the afternoon came, from being
-a poor poverty-stricken boy in the morning, Tom was literally rolling
-in wealth. He had besides the things before mentioned, twelve marbles,
-part of a jews-harp, a piece of blue bottle-glass to look through, a
-spool cannon, a key that wouldn't unlock anything, a fragment of chalk,
-a glass stopper of a decanter, a tin soldier, a couple of tadpoles, six
-fire-crackers, a kitten with only one eye, a brass doorknob, a
-dog-collar--but no dog--the handle of a knife, four pieces of
-orange-peel, and a dilapidated old window sash.
-
-He had had a nice, good, idle time all the while--plenty of company
---and the fence had three coats of whitewash on it! If he hadn't run out
-of whitewash he would have bankrupted every boy in the village.
-
-Tom said to himself that it was not such a hollow world, after all. He
-had discovered a great law of human action, without knowing it--namely,
-that in order to make a man or a boy covet a thing, it is only
-necessary to make the thing difficult to attain. If he had been a great
-and wise philosopher, like the writer of this book, he would now have
-comprehended that Work consists of whatever a body is OBLIGED to do,
-and that Play consists of whatever a body is not obliged to do. And
-this would help him to understand why constructing artificial flowers
-or performing on a tread-mill is work, while rolling ten-pins or
-climbing Mont Blanc is only amusement. There are wealthy gentlemen in
-England who drive four-horse passenger-coaches twenty or thirty miles
-on a daily line, in the summer, because the privilege costs them
-considerable money; but if they were offered wages for the service,
-that would turn it into work and then they would resign.
-
-The boy mused awhile over the substantial change which had taken place
-in his worldly circumstances, and then wended toward headquarters to
-report.
-
-
-
-CHAPTER III
-
-TOM presented himself before Aunt Polly, who was sitting by an open
-window in a pleasant rearward apartment, which was bedroom,
-breakfast-room, dining-room, and library, combined. The balmy summer
-air, the restful quiet, the odor of the flowers, and the drowsing murmur
-of the bees had had their effect, and she was nodding over her knitting
---for she had no company but the cat, and it was asleep in her lap. Her
-spectacles were propped up on her gray head for safety. She had thought
-that of course Tom had deserted long ago, and she wondered at seeing him
-place himself in her power again in this intrepid way. He said: "Mayn't
-I go and play now, aunt?"
-
-"What, a'ready? How much have you done?"
-
-"It's all done, aunt."
-
-"Tom, don't lie to me--I can't bear it."
-
-"I ain't, aunt; it IS all done."
-
-Aunt Polly placed small trust in such evidence. She went out to see
-for herself; and she would have been content to find twenty per cent.
-of Tom's statement true. When she found the entire fence whitewashed,
-and not only whitewashed but elaborately coated and recoated, and even
-a streak added to the ground, her astonishment was almost unspeakable.
-She said:
-
-"Well, I never! There's no getting round it, you can work when you're
-a mind to, Tom." And then she diluted the compliment by adding, "But
-it's powerful seldom you're a mind to, I'm bound to say. Well, go 'long
-and play; but mind you get back some time in a week, or I'll tan you."
-
-She was so overcome by the splendor of his achievement that she took
-him into the closet and selected a choice apple and delivered it to
-him, along with an improving lecture upon the added value and flavor a
-treat took to itself when it came without sin through virtuous effort.
-And while she closed with a happy Scriptural flourish, he "hooked" a
-doughnut.
-
-Then he skipped out, and saw Sid just starting up the outside stairway
-that led to the back rooms on the second floor. Clods were handy and
-the air was full of them in a twinkling. They raged around Sid like a
-hail-storm; and before Aunt Polly could collect her surprised faculties
-and sally to the rescue, six or seven clods had taken personal effect,
-and Tom was over the fence and gone. There was a gate, but as a general
-thing he was too crowded for time to make use of it. His soul was at
-peace, now that he had settled with Sid for calling attention to his
-black thread and getting him into trouble.
-
-Tom skirted the block, and came round into a muddy alley that led by
-the back of his aunt's cow-stable. He presently got safely beyond the
-reach of capture and punishment, and hastened toward the public square
-of the village, where two "military" companies of boys had met for
-conflict, according to previous appointment. Tom was General of one of
-these armies, Joe Harper (a bosom friend) General of the other. These
-two great commanders did not condescend to fight in person--that being
-better suited to the still smaller fry--but sat together on an eminence
-and conducted the field operations by orders delivered through
-aides-de-camp. Tom's army won a great victory, after a long and
-hard-fought battle. Then the dead were counted, prisoners exchanged,
-the terms of the next disagreement agreed upon, and the day for the
-necessary battle appointed; after which the armies fell into line and
-marched away, and Tom turned homeward alone.
-
-As he was passing by the house where Jeff Thatcher lived, he saw a new
-girl in the garden--a lovely little blue-eyed creature with yellow hair
-plaited into two long-tails, white summer frock and embroidered
-pantalettes. The fresh-crowned hero fell without firing a shot. A
-certain Amy Lawrence vanished out of his heart and left not even a
-memory of herself behind. He had thought he loved her to distraction;
-he had regarded his passion as adoration; and behold it was only a poor
-little evanescent partiality. He had been months winning her; she had
-confessed hardly a week ago; he had been the happiest and the proudest
-boy in the world only seven short days, and here in one instant of time
-she had gone out of his heart like a casual stranger whose visit is
-done.
-
-He worshipped this new angel with furtive eye, till he saw that she
-had discovered him; then he pretended he did not know she was present,
-and began to "show off" in all sorts of absurd boyish ways, in order to
-win her admiration. He kept up this grotesque foolishness for some
-time; but by-and-by, while he was in the midst of some dangerous
-gymnastic performances, he glanced aside and saw that the little girl
-was wending her way toward the house. Tom came up to the fence and
-leaned on it, grieving, and hoping she would tarry yet awhile longer.
-She halted a moment on the steps and then moved toward the door. Tom
-heaved a great sigh as she put her foot on the threshold. But his face
-lit up, right away, for she tossed a pansy over the fence a moment
-before she disappeared.
-
-The boy ran around and stopped within a foot or two of the flower, and
-then shaded his eyes with his hand and began to look down street as if
-he had discovered something of interest going on in that direction.
-Presently he picked up a straw and began trying to balance it on his
-nose, with his head tilted far back; and as he moved from side to side,
-in his efforts, he edged nearer and nearer toward the pansy; finally
-his bare foot rested upon it, his pliant toes closed upon it, and he
-hopped away with the treasure and disappeared round the corner. But
-only for a minute--only while he could button the flower inside his
-jacket, next his heart--or next his stomach, possibly, for he was not
-much posted in anatomy, and not hypercritical, anyway.
-
-He returned, now, and hung about the fence till nightfall, "showing
-off," as before; but the girl never exhibited herself again, though Tom
-comforted himself a little with the hope that she had been near some
-window, meantime, and been aware of his attentions. Finally he strode
-home reluctantly, with his poor head full of visions.
-
-All through supper his spirits were so high that his aunt wondered
-"what had got into the child." He took a good scolding about clodding
-Sid, and did not seem to mind it in the least. He tried to steal sugar
-under his aunt's very nose, and got his knuckles rapped for it. He said:
-
-"Aunt, you don't whack Sid when he takes it."
-
-"Well, Sid don't torment a body the way you do. You'd be always into
-that sugar if I warn't watching you."
-
-Presently she stepped into the kitchen, and Sid, happy in his
-immunity, reached for the sugar-bowl--a sort of glorying over Tom which
-was wellnigh unbearable. But Sid's fingers slipped and the bowl dropped
-and broke. Tom was in ecstasies. In such ecstasies that he even
-controlled his tongue and was silent. He said to himself that he would
-not speak a word, even when his aunt came in, but would sit perfectly
-still till she asked who did the mischief; and then he would tell, and
-there would be nothing so good in the world as to see that pet model
-"catch it." He was so brimful of exultation that he could hardly hold
-himself when the old lady came back and stood above the wreck
-discharging lightnings of wrath from over her spectacles. He said to
-himself, "Now it's coming!" And the next instant he was sprawling on
-the floor! The potent palm was uplifted to strike again when Tom cried
-out:
-
-"Hold on, now, what 'er you belting ME for?--Sid broke it!"
-
-Aunt Polly paused, perplexed, and Tom looked for healing pity. But
-when she got her tongue again, she only said:
-
-"Umf! Well, you didn't get a lick amiss, I reckon. You been into some
-other audacious mischief when I wasn't around, like enough."
-
-Then her conscience reproached her, and she yearned to say something
-kind and loving; but she judged that this would be construed into a
-confession that she had been in the wrong, and discipline forbade that.
-So she kept silence, and went about her affairs with a troubled heart.
-Tom sulked in a corner and exalted his woes. He knew that in her heart
-his aunt was on her knees to him, and he was morosely gratified by the
-consciousness of it. He would hang out no signals, he would take notice
-of none. He knew that a yearning glance fell upon him, now and then,
-through a film of tears, but he refused recognition of it. He pictured
-himself lying sick unto death and his aunt bending over him beseeching
-one little forgiving word, but he would turn his face to the wall, and
-die with that word unsaid. Ah, how would she feel then? And he pictured
-himself brought home from the river, dead, with his curls all wet, and
-his sore heart at rest. How she would throw herself upon him, and how
-her tears would fall like rain, and her lips pray God to give her back
-her boy and she would never, never abuse him any more! But he would lie
-there cold and white and make no sign--a poor little sufferer, whose
-griefs were at an end. He so worked upon his feelings with the pathos
-of these dreams, that he had to keep swallowing, he was so like to
-choke; and his eyes swam in a blur of water, which overflowed when he
-winked, and ran down and trickled from the end of his nose. And such a
-luxury to him was this petting of his sorrows, that he could not bear
-to have any worldly cheeriness or any grating delight intrude upon it;
-it was too sacred for such contact; and so, presently, when his cousin
-Mary danced in, all alive with the joy of seeing home again after an
-age-long visit of one week to the country, he got up and moved in
-clouds and darkness out at one door as she brought song and sunshine in
-at the other.
-
-He wandered far from the accustomed haunts of boys, and sought
-desolate places that were in harmony with his spirit. A log raft in the
-river invited him, and he seated himself on its outer edge and
-contemplated the dreary vastness of the stream, wishing, the while,
-that he could only be drowned, all at once and unconsciously, without
-undergoing the uncomfortable routine devised by nature. Then he thought
-of his flower. He got it out, rumpled and wilted, and it mightily
-increased his dismal felicity. He wondered if she would pity him if she
-knew? Would she cry, and wish that she had a right to put her arms
-around his neck and comfort him? Or would she turn coldly away like all
-the hollow world? This picture brought such an agony of pleasurable
-suffering that he worked it over and over again in his mind and set it
-up in new and varied lights, till he wore it threadbare. At last he
-rose up sighing and departed in the darkness.
-
-About half-past nine or ten o'clock he came along the deserted street
-to where the Adored Unknown lived; he paused a moment; no sound fell
-upon his listening ear; a candle was casting a dull glow upon the
-curtain of a second-story window. Was the sacred presence there? He
-climbed the fence, threaded his stealthy way through the plants, till
-he stood under that window; he looked up at it long, and with emotion;
-then he laid him down on the ground under it, disposing himself upon
-his back, with his hands clasped upon his breast and holding his poor
-wilted flower. And thus he would die--out in the cold world, with no
-shelter over his homeless head, no friendly hand to wipe the
-death-damps from his brow, no loving face to bend pityingly over him
-when the great agony came. And thus SHE would see him when she looked
-out upon the glad morning, and oh! would she drop one little tear upon
-his poor, lifeless form, would she heave one little sigh to see a bright
-young life so rudely blighted, so untimely cut down?
-
-The window went up, a maid-servant's discordant voice profaned the
-holy calm, and a deluge of water drenched the prone martyr's remains!
-
-The strangling hero sprang up with a relieving snort. There was a whiz
-as of a missile in the air, mingled with the murmur of a curse, a sound
-as of shivering glass followed, and a small, vague form went over the
-fence and shot away in the gloom.
-
-Not long after, as Tom, all undressed for bed, was surveying his
-drenched garments by the light of a tallow dip, Sid woke up; but if he
-had any dim idea of making any "references to allusions," he thought
-better of it and held his peace, for there was danger in Tom's eye.
-
-Tom turned in without the added vexation of prayers, and Sid made
-mental note of the omission.
-
-
-
-CHAPTER IV
-
-THE sun rose upon a tranquil world, and beamed down upon the peaceful
-village like a benediction. Breakfast over, Aunt Polly had family
-worship: it began with a prayer built from the ground up of solid
-courses of Scriptural quotations, welded together with a thin mortar of
-originality; and from the summit of this she delivered a grim chapter
-of the Mosaic Law, as from Sinai.
-
-Then Tom girded up his loins, so to speak, and went to work to "get
-his verses." Sid had learned his lesson days before. Tom bent all his
-energies to the memorizing of five verses, and he chose part of the
-Sermon on the Mount, because he could find no verses that were shorter.
-At the end of half an hour Tom had a vague general idea of his lesson,
-but no more, for his mind was traversing the whole field of human
-thought, and his hands were busy with distracting recreations. Mary
-took his book to hear him recite, and he tried to find his way through
-the fog:
-
-"Blessed are the--a--a--"
-
-"Poor"--
-
-"Yes--poor; blessed are the poor--a--a--"
-
-"In spirit--"
-
-"In spirit; blessed are the poor in spirit, for they--they--"
-
-"THEIRS--"
-
-"For THEIRS. Blessed are the poor in spirit, for theirs is the kingdom
-of heaven. Blessed are they that mourn, for they--they--"
-
-"Sh--"
-
-"For they--a--"
-
-"S, H, A--"
-
-"For they S, H--Oh, I don't know what it is!"
-
-"SHALL!"
-
-"Oh, SHALL! for they shall--for they shall--a--a--shall mourn--a--a--
-blessed are they that shall--they that--a--they that shall mourn, for
-they shall--a--shall WHAT? Why don't you tell me, Mary?--what do you
-want to be so mean for?"
-
-"Oh, Tom, you poor thick-headed thing, I'm not teasing you. I wouldn't
-do that. You must go and learn it again. Don't you be discouraged, Tom,
-you'll manage it--and if you do, I'll give you something ever so nice.
-There, now, that's a good boy."
-
-"All right! What is it, Mary, tell me what it is."
-
-"Never you mind, Tom. You know if I say it's nice, it is nice."
-
-"You bet you that's so, Mary. All right, I'll tackle it again."
-
-And he did "tackle it again"--and under the double pressure of
-curiosity and prospective gain he did it with such spirit that he
-accomplished a shining success. Mary gave him a brand-new "Barlow"
-knife worth twelve and a half cents; and the convulsion of delight that
-swept his system shook him to his foundations. True, the knife would
-not cut anything, but it was a "sure-enough" Barlow, and there was
-inconceivable grandeur in that--though where the Western boys ever got
-the idea that such a weapon could possibly be counterfeited to its
-injury is an imposing mystery and will always remain so, perhaps. Tom
-contrived to scarify the cupboard with it, and was arranging to begin
-on the bureau, when he was called off to dress for Sunday-school.
-
-Mary gave him a tin basin of water and a piece of soap, and he went
-outside the door and set the basin on a little bench there; then he
-dipped the soap in the water and laid it down; turned up his sleeves;
-poured out the water on the ground, gently, and then entered the
-kitchen and began to wipe his face diligently on the towel behind the
-door. But Mary removed the towel and said:
-
-"Now ain't you ashamed, Tom. You mustn't be so bad. Water won't hurt
-you."
-
-Tom was a trifle disconcerted. The basin was refilled, and this time
-he stood over it a little while, gathering resolution; took in a big
-breath and began. When he entered the kitchen presently, with both eyes
-shut and groping for the towel with his hands, an honorable testimony
-of suds and water was dripping from his face. But when he emerged from
-the towel, he was not yet satisfactory, for the clean territory stopped
-short at his chin and his jaws, like a mask; below and beyond this line
-there was a dark expanse of unirrigated soil that spread downward in
-front and backward around his neck. Mary took him in hand, and when she
-was done with him he was a man and a brother, without distinction of
-color, and his saturated hair was neatly brushed, and its short curls
-wrought into a dainty and symmetrical general effect. [He privately
-smoothed out the curls, with labor and difficulty, and plastered his
-hair close down to his head; for he held curls to be effeminate, and
-his own filled his life with bitterness.] Then Mary got out a suit of
-his clothing that had been used only on Sundays during two years--they
-were simply called his "other clothes"--and so by that we know the
-size of his wardrobe. The girl "put him to rights" after he had dressed
-himself; she buttoned his neat roundabout up to his chin, turned his
-vast shirt collar down over his shoulders, brushed him off and crowned
-him with his speckled straw hat. He now looked exceedingly improved and
-uncomfortable. He was fully as uncomfortable as he looked; for there
-was a restraint about whole clothes and cleanliness that galled him. He
-hoped that Mary would forget his shoes, but the hope was blighted; she
-coated them thoroughly with tallow, as was the custom, and brought them
-out. He lost his temper and said he was always being made to do
-everything he didn't want to do. But Mary said, persuasively:
-
-"Please, Tom--that's a good boy."
-
-So he got into the shoes snarling. Mary was soon ready, and the three
-children set out for Sunday-school--a place that Tom hated with his
-whole heart; but Sid and Mary were fond of it.
-
-Sabbath-school hours were from nine to half-past ten; and then church
-service. Two of the children always remained for the sermon
-voluntarily, and the other always remained too--for stronger reasons.
-The church's high-backed, uncushioned pews would seat about three
-hundred persons; the edifice was but a small, plain affair, with a sort
-of pine board tree-box on top of it for a steeple. At the door Tom
-dropped back a step and accosted a Sunday-dressed comrade:
-
-"Say, Billy, got a yaller ticket?"
-
-"Yes."
-
-"What'll you take for her?"
-
-"What'll you give?"
-
-"Piece of lickrish and a fish-hook."
-
-"Less see 'em."
-
-Tom exhibited. They were satisfactory, and the property changed hands.
-Then Tom traded a couple of white alleys for three red tickets, and
-some small trifle or other for a couple of blue ones. He waylaid other
-boys as they came, and went on buying tickets of various colors ten or
-fifteen minutes longer. He entered the church, now, with a swarm of
-clean and noisy boys and girls, proceeded to his seat and started a
-quarrel with the first boy that came handy. The teacher, a grave,
-elderly man, interfered; then turned his back a moment and Tom pulled a
-boy's hair in the next bench, and was absorbed in his book when the boy
-turned around; stuck a pin in another boy, presently, in order to hear
-him say "Ouch!" and got a new reprimand from his teacher. Tom's whole
-class were of a pattern--restless, noisy, and troublesome. When they
-came to recite their lessons, not one of them knew his verses
-perfectly, but had to be prompted all along. However, they worried
-through, and each got his reward--in small blue tickets, each with a
-passage of Scripture on it; each blue ticket was pay for two verses of
-the recitation. Ten blue tickets equalled a red one, and could be
-exchanged for it; ten red tickets equalled a yellow one; for ten yellow
-tickets the superintendent gave a very plainly bound Bible (worth forty
-cents in those easy times) to the pupil. How many of my readers would
-have the industry and application to memorize two thousand verses, even
-for a Dore Bible? And yet Mary had acquired two Bibles in this way--it
-was the patient work of two years--and a boy of German parentage had
-won four or five. He once recited three thousand verses without
-stopping; but the strain upon his mental faculties was too great, and
-he was little better than an idiot from that day forth--a grievous
-misfortune for the school, for on great occasions, before company, the
-superintendent (as Tom expressed it) had always made this boy come out
-and "spread himself." Only the older pupils managed to keep their
-tickets and stick to their tedious work long enough to get a Bible, and
-so the delivery of one of these prizes was a rare and noteworthy
-circumstance; the successful pupil was so great and conspicuous for
-that day that on the spot every scholar's heart was fired with a fresh
-ambition that often lasted a couple of weeks. It is possible that Tom's
-mental stomach had never really hungered for one of those prizes, but
-unquestionably his entire being had for many a day longed for the glory
-and the eclat that came with it.
-
-In due course the superintendent stood up in front of the pulpit, with
-a closed hymn-book in his hand and his forefinger inserted between its
-leaves, and commanded attention. When a Sunday-school superintendent
-makes his customary little speech, a hymn-book in the hand is as
-necessary as is the inevitable sheet of music in the hand of a singer
-who stands forward on the platform and sings a solo at a concert
---though why, is a mystery: for neither the hymn-book nor the sheet of
-music is ever referred to by the sufferer. This superintendent was a
-slim creature of thirty-five, with a sandy goatee and short sandy hair;
-he wore a stiff standing-collar whose upper edge almost reached his
-ears and whose sharp points curved forward abreast the corners of his
-mouth--a fence that compelled a straight lookout ahead, and a turning
-of the whole body when a side view was required; his chin was propped
-on a spreading cravat which was as broad and as long as a bank-note,
-and had fringed ends; his boot toes were turned sharply up, in the
-fashion of the day, like sleigh-runners--an effect patiently and
-laboriously produced by the young men by sitting with their toes
-pressed against a wall for hours together. Mr. Walters was very earnest
-of mien, and very sincere and honest at heart; and he held sacred
-things and places in such reverence, and so separated them from worldly
-matters, that unconsciously to himself his Sunday-school voice had
-acquired a peculiar intonation which was wholly absent on week-days. He
-began after this fashion:
-
-"Now, children, I want you all to sit up just as straight and pretty
-as you can and give me all your attention for a minute or two. There
---that is it. That is the way good little boys and girls should do. I see
-one little girl who is looking out of the window--I am afraid she
-thinks I am out there somewhere--perhaps up in one of the trees making
-a speech to the little birds. [Applausive titter.] I want to tell you
-how good it makes me feel to see so many bright, clean little faces
-assembled in a place like this, learning to do right and be good." And
-so forth and so on. It is not necessary to set down the rest of the
-oration. It was of a pattern which does not vary, and so it is familiar
-to us all.
-
-The latter third of the speech was marred by the resumption of fights
-and other recreations among certain of the bad boys, and by fidgetings
-and whisperings that extended far and wide, washing even to the bases
-of isolated and incorruptible rocks like Sid and Mary. But now every
-sound ceased suddenly, with the subsidence of Mr. Walters' voice, and
-the conclusion of the speech was received with a burst of silent
-gratitude.
-
-A good part of the whispering had been occasioned by an event which
-was more or less rare--the entrance of visitors: lawyer Thatcher,
-accompanied by a very feeble and aged man; a fine, portly, middle-aged
-gentleman with iron-gray hair; and a dignified lady who was doubtless
-the latter's wife. The lady was leading a child. Tom had been restless
-and full of chafings and repinings; conscience-smitten, too--he could
-not meet Amy Lawrence's eye, he could not brook her loving gaze. But
-when he saw this small new-comer his soul was all ablaze with bliss in
-a moment. The next moment he was "showing off" with all his might
---cuffing boys, pulling hair, making faces--in a word, using every art
-that seemed likely to fascinate a girl and win her applause. His
-exaltation had but one alloy--the memory of his humiliation in this
-angel's garden--and that record in sand was fast washing out, under
-the waves of happiness that were sweeping over it now.
-
-The visitors were given the highest seat of honor, and as soon as Mr.
-Walters' speech was finished, he introduced them to the school. The
-middle-aged man turned out to be a prodigious personage--no less a one
-than the county judge--altogether the most august creation these
-children had ever looked upon--and they wondered what kind of material
-he was made of--and they half wanted to hear him roar, and were half
-afraid he might, too. He was from Constantinople, twelve miles away--so
-he had travelled, and seen the world--these very eyes had looked upon
-the county court-house--which was said to have a tin roof. The awe
-which these reflections inspired was attested by the impressive silence
-and the ranks of staring eyes. This was the great Judge Thatcher,
-brother of their own lawyer. Jeff Thatcher immediately went forward, to
-be familiar with the great man and be envied by the school. It would
-have been music to his soul to hear the whisperings:
-
-"Look at him, Jim! He's a going up there. Say--look! he's a going to
-shake hands with him--he IS shaking hands with him! By jings, don't you
-wish you was Jeff?"
-
-Mr. Walters fell to "showing off," with all sorts of official
-bustlings and activities, giving orders, delivering judgments,
-discharging directions here, there, everywhere that he could find a
-target. The librarian "showed off"--running hither and thither with his
-arms full of books and making a deal of the splutter and fuss that
-insect authority delights in. The young lady teachers "showed off"
---bending sweetly over pupils that were lately being boxed, lifting
-pretty warning fingers at bad little boys and patting good ones
-lovingly. The young gentlemen teachers "showed off" with small
-scoldings and other little displays of authority and fine attention to
-discipline--and most of the teachers, of both sexes, found business up
-at the library, by the pulpit; and it was business that frequently had
-to be done over again two or three times (with much seeming vexation).
-The little girls "showed off" in various ways, and the little boys
-"showed off" with such diligence that the air was thick with paper wads
-and the murmur of scufflings. And above it all the great man sat and
-beamed a majestic judicial smile upon all the house, and warmed himself
-in the sun of his own grandeur--for he was "showing off," too.
-
-There was only one thing wanting to make Mr. Walters' ecstasy
-complete, and that was a chance to deliver a Bible-prize and exhibit a
-prodigy. Several pupils had a few yellow tickets, but none had enough
---he had been around among the star pupils inquiring. He would have given
-worlds, now, to have that German lad back again with a sound mind.
-
-And now at this moment, when hope was dead, Tom Sawyer came forward
-with nine yellow tickets, nine red tickets, and ten blue ones, and
-demanded a Bible. This was a thunderbolt out of a clear sky. Walters
-was not expecting an application from this source for the next ten
-years. But there was no getting around it--here were the certified
-checks, and they were good for their face. Tom was therefore elevated
-to a place with the Judge and the other elect, and the great news was
-announced from headquarters. It was the most stunning surprise of the
-decade, and so profound was the sensation that it lifted the new hero
-up to the judicial one's altitude, and the school had two marvels to
-gaze upon in place of one. The boys were all eaten up with envy--but
-those that suffered the bitterest pangs were those who perceived too
-late that they themselves had contributed to this hated splendor by
-trading tickets to Tom for the wealth he had amassed in selling
-whitewashing privileges. These despised themselves, as being the dupes
-of a wily fraud, a guileful snake in the grass.
-
-The prize was delivered to Tom with as much effusion as the
-superintendent could pump up under the circumstances; but it lacked
-somewhat of the true gush, for the poor fellow's instinct taught him
-that there was a mystery here that could not well bear the light,
-perhaps; it was simply preposterous that this boy had warehoused two
-thousand sheaves of Scriptural wisdom on his premises--a dozen would
-strain his capacity, without a doubt.
-
-Amy Lawrence was proud and glad, and she tried to make Tom see it in
-her face--but he wouldn't look. She wondered; then she was just a grain
-troubled; next a dim suspicion came and went--came again; she watched;
-a furtive glance told her worlds--and then her heart broke, and she was
-jealous, and angry, and the tears came and she hated everybody. Tom
-most of all (she thought).
-
-Tom was introduced to the Judge; but his tongue was tied, his breath
-would hardly come, his heart quaked--partly because of the awful
-greatness of the man, but mainly because he was her parent. He would
-have liked to fall down and worship him, if it were in the dark. The
-Judge put his hand on Tom's head and called him a fine little man, and
-asked him what his name was. The boy stammered, gasped, and got it out:
-
-"Tom."
-
-"Oh, no, not Tom--it is--"
-
-"Thomas."
-
-"Ah, that's it. I thought there was more to it, maybe. That's very
-well. But you've another one I daresay, and you'll tell it to me, won't
-you?"
-
-"Tell the gentleman your other name, Thomas," said Walters, "and say
-sir. You mustn't forget your manners."
-
-"Thomas Sawyer--sir."
-
-"That's it! That's a good boy. Fine boy. Fine, manly little fellow.
-Two thousand verses is a great many--very, very great many. And you
-never can be sorry for the trouble you took to learn them; for
-knowledge is worth more than anything there is in the world; it's what
-makes great men and good men; you'll be a great man and a good man
-yourself, some day, Thomas, and then you'll look back and say, It's all
-owing to the precious Sunday-school privileges of my boyhood--it's all
-owing to my dear teachers that taught me to learn--it's all owing to
-the good superintendent, who encouraged me, and watched over me, and
-gave me a beautiful Bible--a splendid elegant Bible--to keep and have
-it all for my own, always--it's all owing to right bringing up! That is
-what you will say, Thomas--and you wouldn't take any money for those
-two thousand verses--no indeed you wouldn't. And now you wouldn't mind
-telling me and this lady some of the things you've learned--no, I know
-you wouldn't--for we are proud of little boys that learn. Now, no
-doubt you know the names of all the twelve disciples. Won't you tell us
-the names of the first two that were appointed?"
-
-Tom was tugging at a button-hole and looking sheepish. He blushed,
-now, and his eyes fell. Mr. Walters' heart sank within him. He said to
-himself, it is not possible that the boy can answer the simplest
-question--why DID the Judge ask him? Yet he felt obliged to speak up
-and say:
-
-"Answer the gentleman, Thomas--don't be afraid."
-
-Tom still hung fire.
-
-"Now I know you'll tell me," said the lady. "The names of the first
-two disciples were--"
-
-"DAVID AND GOLIAH!"
-
-Let us draw the curtain of charity over the rest of the scene.
-
-
-
-CHAPTER V
-
-ABOUT half-past ten the cracked bell of the small church began to
-ring, and presently the people began to gather for the morning sermon.
-The Sunday-school children distributed themselves about the house and
-occupied pews with their parents, so as to be under supervision. Aunt
-Polly came, and Tom and Sid and Mary sat with her--Tom being placed
-next the aisle, in order that he might be as far away from the open
-window and the seductive outside summer scenes as possible. The crowd
-filed up the aisles: the aged and needy postmaster, who had seen better
-days; the mayor and his wife--for they had a mayor there, among other
-unnecessaries; the justice of the peace; the widow Douglass, fair,
-smart, and forty, a generous, good-hearted soul and well-to-do, her
-hill mansion the only palace in the town, and the most hospitable and
-much the most lavish in the matter of festivities that St. Petersburg
-could boast; the bent and venerable Major and Mrs. Ward; lawyer
-Riverson, the new notable from a distance; next the belle of the
-village, followed by a troop of lawn-clad and ribbon-decked young
-heart-breakers; then all the young clerks in town in a body--for they
-had stood in the vestibule sucking their cane-heads, a circling wall of
-oiled and simpering admirers, till the last girl had run their gantlet;
-and last of all came the Model Boy, Willie Mufferson, taking as heedful
-care of his mother as if she were cut glass. He always brought his
-mother to church, and was the pride of all the matrons. The boys all
-hated him, he was so good. And besides, he had been "thrown up to them"
-so much. His white handkerchief was hanging out of his pocket behind, as
-usual on Sundays--accidentally. Tom had no handkerchief, and he looked
-upon boys who had as snobs.
-
-The congregation being fully assembled, now, the bell rang once more,
-to warn laggards and stragglers, and then a solemn hush fell upon the
-church which was only broken by the tittering and whispering of the
-choir in the gallery. The choir always tittered and whispered all
-through service. There was once a church choir that was not ill-bred,
-but I have forgotten where it was, now. It was a great many years ago,
-and I can scarcely remember anything about it, but I think it was in
-some foreign country.
-
-The minister gave out the hymn, and read it through with a relish, in
-a peculiar style which was much admired in that part of the country.
-His voice began on a medium key and climbed steadily up till it reached
-a certain point, where it bore with strong emphasis upon the topmost
-word and then plunged down as if from a spring-board:
-
- Shall I be car-ri-ed toe the skies, on flow'ry BEDS of ease,
-
- Whilst others fight to win the prize, and sail thro' BLOODY seas?
-
-He was regarded as a wonderful reader. At church "sociables" he was
-always called upon to read poetry; and when he was through, the ladies
-would lift up their hands and let them fall helplessly in their laps,
-and "wall" their eyes, and shake their heads, as much as to say, "Words
-cannot express it; it is too beautiful, TOO beautiful for this mortal
-earth."
-
-After the hymn had been sung, the Rev. Mr. Sprague turned himself into
-a bulletin-board, and read off "notices" of meetings and societies and
-things till it seemed that the list would stretch out to the crack of
-doom--a queer custom which is still kept up in America, even in cities,
-away here in this age of abundant newspapers. Often, the less there is
-to justify a traditional custom, the harder it is to get rid of it.
-
-And now the minister prayed. A good, generous prayer it was, and went
-into details: it pleaded for the church, and the little children of the
-church; for the other churches of the village; for the village itself;
-for the county; for the State; for the State officers; for the United
-States; for the churches of the United States; for Congress; for the
-President; for the officers of the Government; for poor sailors, tossed
-by stormy seas; for the oppressed millions groaning under the heel of
-European monarchies and Oriental despotisms; for such as have the light
-and the good tidings, and yet have not eyes to see nor ears to hear
-withal; for the heathen in the far islands of the sea; and closed with
-a supplication that the words he was about to speak might find grace
-and favor, and be as seed sown in fertile ground, yielding in time a
-grateful harvest of good. Amen.
-
-There was a rustling of dresses, and the standing congregation sat
-down. The boy whose history this book relates did not enjoy the prayer,
-he only endured it--if he even did that much. He was restive all
-through it; he kept tally of the details of the prayer, unconsciously
---for he was not listening, but he knew the ground of old, and the
-clergyman's regular route over it--and when a little trifle of new
-matter was interlarded, his ear detected it and his whole nature
-resented it; he considered additions unfair, and scoundrelly. In the
-midst of the prayer a fly had lit on the back of the pew in front of
-him and tortured his spirit by calmly rubbing its hands together,
-embracing its head with its arms, and polishing it so vigorously that
-it seemed to almost part company with the body, and the slender thread
-of a neck was exposed to view; scraping its wings with its hind legs
-and smoothing them to its body as if they had been coat-tails; going
-through its whole toilet as tranquilly as if it knew it was perfectly
-safe. As indeed it was; for as sorely as Tom's hands itched to grab for
-it they did not dare--he believed his soul would be instantly destroyed
-if he did such a thing while the prayer was going on. But with the
-closing sentence his hand began to curve and steal forward; and the
-instant the "Amen" was out the fly was a prisoner of war. His aunt
-detected the act and made him let it go.
-
-The minister gave out his text and droned along monotonously through
-an argument that was so prosy that many a head by and by began to nod
---and yet it was an argument that dealt in limitless fire and brimstone
-and thinned the predestined elect down to a company so small as to be
-hardly worth the saving. Tom counted the pages of the sermon; after
-church he always knew how many pages there had been, but he seldom knew
-anything else about the discourse. However, this time he was really
-interested for a little while. The minister made a grand and moving
-picture of the assembling together of the world's hosts at the
-millennium when the lion and the lamb should lie down together and a
-little child should lead them. But the pathos, the lesson, the moral of
-the great spectacle were lost upon the boy; he only thought of the
-conspicuousness of the principal character before the on-looking
-nations; his face lit with the thought, and he said to himself that he
-wished he could be that child, if it was a tame lion.
-
-Now he lapsed into suffering again, as the dry argument was resumed.
-Presently he bethought him of a treasure he had and got it out. It was
-a large black beetle with formidable jaws--a "pinchbug," he called it.
-It was in a percussion-cap box. The first thing the beetle did was to
-take him by the finger. A natural fillip followed, the beetle went
-floundering into the aisle and lit on its back, and the hurt finger
-went into the boy's mouth. The beetle lay there working its helpless
-legs, unable to turn over. Tom eyed it, and longed for it; but it was
-safe out of his reach. Other people uninterested in the sermon found
-relief in the beetle, and they eyed it too. Presently a vagrant poodle
-dog came idling along, sad at heart, lazy with the summer softness and
-the quiet, weary of captivity, sighing for change. He spied the beetle;
-the drooping tail lifted and wagged. He surveyed the prize; walked
-around it; smelt at it from a safe distance; walked around it again;
-grew bolder, and took a closer smell; then lifted his lip and made a
-gingerly snatch at it, just missing it; made another, and another;
-began to enjoy the diversion; subsided to his stomach with the beetle
-between his paws, and continued his experiments; grew weary at last,
-and then indifferent and absent-minded. His head nodded, and little by
-little his chin descended and touched the enemy, who seized it. There
-was a sharp yelp, a flirt of the poodle's head, and the beetle fell a
-couple of yards away, and lit on its back once more. The neighboring
-spectators shook with a gentle inward joy, several faces went behind
-fans and handkerchiefs, and Tom was entirely happy. The dog looked
-foolish, and probably felt so; but there was resentment in his heart,
-too, and a craving for revenge. So he went to the beetle and began a
-wary attack on it again; jumping at it from every point of a circle,
-lighting with his fore-paws within an inch of the creature, making even
-closer snatches at it with his teeth, and jerking his head till his
-ears flapped again. But he grew tired once more, after a while; tried
-to amuse himself with a fly but found no relief; followed an ant
-around, with his nose close to the floor, and quickly wearied of that;
-yawned, sighed, forgot the beetle entirely, and sat down on it. Then
-there was a wild yelp of agony and the poodle went sailing up the
-aisle; the yelps continued, and so did the dog; he crossed the house in
-front of the altar; he flew down the other aisle; he crossed before the
-doors; he clamored up the home-stretch; his anguish grew with his
-progress, till presently he was but a woolly comet moving in its orbit
-with the gleam and the speed of light. At last the frantic sufferer
-sheered from its course, and sprang into its master's lap; he flung it
-out of the window, and the voice of distress quickly thinned away and
-died in the distance.
-
-By this time the whole church was red-faced and suffocating with
-suppressed laughter, and the sermon had come to a dead standstill. The
-discourse was resumed presently, but it went lame and halting, all
-possibility of impressiveness being at an end; for even the gravest
-sentiments were constantly being received with a smothered burst of
-unholy mirth, under cover of some remote pew-back, as if the poor
-parson had said a rarely facetious thing. It was a genuine relief to
-the whole congregation when the ordeal was over and the benediction
-pronounced.
-
-Tom Sawyer went home quite cheerful, thinking to himself that there
-was some satisfaction about divine service when there was a bit of
-variety in it. He had but one marring thought; he was willing that the
-dog should play with his pinchbug, but he did not think it was upright
-in him to carry it off.
-
-
-
-CHAPTER VI
-
-MONDAY morning found Tom Sawyer miserable. Monday morning always found
-him so--because it began another week's slow suffering in school. He
-generally began that day with wishing he had had no intervening
-holiday, it made the going into captivity and fetters again so much
-more odious.
-
-Tom lay thinking. Presently it occurred to him that he wished he was
-sick; then he could stay home from school. Here was a vague
-possibility. He canvassed his system. No ailment was found, and he
-investigated again. This time he thought he could detect colicky
-symptoms, and he began to encourage them with considerable hope. But
-they soon grew feeble, and presently died wholly away. He reflected
-further. Suddenly he discovered something. One of his upper front teeth
-was loose. This was lucky; he was about to begin to groan, as a
-"starter," as he called it, when it occurred to him that if he came
-into court with that argument, his aunt would pull it out, and that
-would hurt. So he thought he would hold the tooth in reserve for the
-present, and seek further. Nothing offered for some little time, and
-then he remembered hearing the doctor tell about a certain thing that
-laid up a patient for two or three weeks and threatened to make him
-lose a finger. So the boy eagerly drew his sore toe from under the
-sheet and held it up for inspection. But now he did not know the
-necessary symptoms. However, it seemed well worth while to chance it,
-so he fell to groaning with considerable spirit.
-
-But Sid slept on unconscious.
-
-Tom groaned louder, and fancied that he began to feel pain in the toe.
-
-No result from Sid.
-
-Tom was panting with his exertions by this time. He took a rest and
-then swelled himself up and fetched a succession of admirable groans.
-
-Sid snored on.
-
-Tom was aggravated. He said, "Sid, Sid!" and shook him. This course
-worked well, and Tom began to groan again. Sid yawned, stretched, then
-brought himself up on his elbow with a snort, and began to stare at
-Tom. Tom went on groaning. Sid said:
-
-"Tom! Say, Tom!" [No response.] "Here, Tom! TOM! What is the matter,
-Tom?" And he shook him and looked in his face anxiously.
-
-Tom moaned out:
-
-"Oh, don't, Sid. Don't joggle me."
-
-"Why, what's the matter, Tom? I must call auntie."
-
-"No--never mind. It'll be over by and by, maybe. Don't call anybody."
-
-"But I must! DON'T groan so, Tom, it's awful. How long you been this
-way?"
-
-"Hours. Ouch! Oh, don't stir so, Sid, you'll kill me."
-
-"Tom, why didn't you wake me sooner? Oh, Tom, DON'T! It makes my
-flesh crawl to hear you. Tom, what is the matter?"
-
-"I forgive you everything, Sid. [Groan.] Everything you've ever done
-to me. When I'm gone--"
-
-"Oh, Tom, you ain't dying, are you? Don't, Tom--oh, don't. Maybe--"
-
-"I forgive everybody, Sid. [Groan.] Tell 'em so, Sid. And Sid, you
-give my window-sash and my cat with one eye to that new girl that's
-come to town, and tell her--"
-
-But Sid had snatched his clothes and gone. Tom was suffering in
-reality, now, so handsomely was his imagination working, and so his
-groans had gathered quite a genuine tone.
-
-Sid flew down-stairs and said:
-
-"Oh, Aunt Polly, come! Tom's dying!"
-
-"Dying!"
-
-"Yes'm. Don't wait--come quick!"
-
-"Rubbage! I don't believe it!"
-
-But she fled up-stairs, nevertheless, with Sid and Mary at her heels.
-And her face grew white, too, and her lip trembled. When she reached
-the bedside she gasped out:
-
-"You, Tom! Tom, what's the matter with you?"
-
-"Oh, auntie, I'm--"
-
-"What's the matter with you--what is the matter with you, child?"
-
-"Oh, auntie, my sore toe's mortified!"
-
-The old lady sank down into a chair and laughed a little, then cried a
-little, then did both together. This restored her and she said:
-
-"Tom, what a turn you did give me. Now you shut up that nonsense and
-climb out of this."
-
-The groans ceased and the pain vanished from the toe. The boy felt a
-little foolish, and he said:
-
-"Aunt Polly, it SEEMED mortified, and it hurt so I never minded my
-tooth at all."
-
-"Your tooth, indeed! What's the matter with your tooth?"
-
-"One of them's loose, and it aches perfectly awful."
-
-"There, there, now, don't begin that groaning again. Open your mouth.
-Well--your tooth IS loose, but you're not going to die about that.
-Mary, get me a silk thread, and a chunk of fire out of the kitchen."
-
-Tom said:
-
-"Oh, please, auntie, don't pull it out. It don't hurt any more. I wish
-I may never stir if it does. Please don't, auntie. I don't want to stay
-home from school."
-
-"Oh, you don't, don't you? So all this row was because you thought
-you'd get to stay home from school and go a-fishing? Tom, Tom, I love
-you so, and you seem to try every way you can to break my old heart
-with your outrageousness." By this time the dental instruments were
-ready. The old lady made one end of the silk thread fast to Tom's tooth
-with a loop and tied the other to the bedpost. Then she seized the
-chunk of fire and suddenly thrust it almost into the boy's face. The
-tooth hung dangling by the bedpost, now.
-
-But all trials bring their compensations. As Tom wended to school
-after breakfast, he was the envy of every boy he met because the gap in
-his upper row of teeth enabled him to expectorate in a new and
-admirable way. He gathered quite a following of lads interested in the
-exhibition; and one that had cut his finger and had been a centre of
-fascination and homage up to this time, now found himself suddenly
-without an adherent, and shorn of his glory. His heart was heavy, and
-he said with a disdain which he did not feel that it wasn't anything to
-spit like Tom Sawyer; but another boy said, "Sour grapes!" and he
-wandered away a dismantled hero.
-
-Shortly Tom came upon the juvenile pariah of the village, Huckleberry
-Finn, son of the town drunkard. Huckleberry was cordially hated and
-dreaded by all the mothers of the town, because he was idle and lawless
-and vulgar and bad--and because all their children admired him so, and
-delighted in his forbidden society, and wished they dared to be like
-him. Tom was like the rest of the respectable boys, in that he envied
-Huckleberry his gaudy outcast condition, and was under strict orders
-not to play with him. So he played with him every time he got a chance.
-Huckleberry was always dressed in the cast-off clothes of full-grown
-men, and they were in perennial bloom and fluttering with rags. His hat
-was a vast ruin with a wide crescent lopped out of its brim; his coat,
-when he wore one, hung nearly to his heels and had the rearward buttons
-far down the back; but one suspender supported his trousers; the seat
-of the trousers bagged low and contained nothing, the fringed legs
-dragged in the dirt when not rolled up.
-
-Huckleberry came and went, at his own free will. He slept on doorsteps
-in fine weather and in empty hogsheads in wet; he did not have to go to
-school or to church, or call any being master or obey anybody; he could
-go fishing or swimming when and where he chose, and stay as long as it
-suited him; nobody forbade him to fight; he could sit up as late as he
-pleased; he was always the first boy that went barefoot in the spring
-and the last to resume leather in the fall; he never had to wash, nor
-put on clean clothes; he could swear wonderfully. In a word, everything
-that goes to make life precious that boy had. So thought every
-harassed, hampered, respectable boy in St. Petersburg.
-
-Tom hailed the romantic outcast:
-
-"Hello, Huckleberry!"
-
-"Hello yourself, and see how you like it."
-
-"What's that you got?"
-
-"Dead cat."
-
-"Lemme see him, Huck. My, he's pretty stiff. Where'd you get him?"
-
-"Bought him off'n a boy."
-
-"What did you give?"
-
-"I give a blue ticket and a bladder that I got at the slaughter-house."
-
-"Where'd you get the blue ticket?"
-
-"Bought it off'n Ben Rogers two weeks ago for a hoop-stick."
-
-"Say--what is dead cats good for, Huck?"
-
-"Good for? Cure warts with."
-
-"No! Is that so? I know something that's better."
-
-"I bet you don't. What is it?"
-
-"Why, spunk-water."
-
-"Spunk-water! I wouldn't give a dern for spunk-water."
-
-"You wouldn't, wouldn't you? D'you ever try it?"
-
-"No, I hain't. But Bob Tanner did."
-
-"Who told you so!"
-
-"Why, he told Jeff Thatcher, and Jeff told Johnny Baker, and Johnny
-told Jim Hollis, and Jim told Ben Rogers, and Ben told a nigger, and
-the nigger told me. There now!"
-
-"Well, what of it? They'll all lie. Leastways all but the nigger. I
-don't know HIM. But I never see a nigger that WOULDN'T lie. Shucks! Now
-you tell me how Bob Tanner done it, Huck."
-
-"Why, he took and dipped his hand in a rotten stump where the
-rain-water was."
-
-"In the daytime?"
-
-"Certainly."
-
-"With his face to the stump?"
-
-"Yes. Least I reckon so."
-
-"Did he say anything?"
-
-"I don't reckon he did. I don't know."
-
-"Aha! Talk about trying to cure warts with spunk-water such a blame
-fool way as that! Why, that ain't a-going to do any good. You got to go
-all by yourself, to the middle of the woods, where you know there's a
-spunk-water stump, and just as it's midnight you back up against the
-stump and jam your hand in and say:
-
- 'Barley-corn, barley-corn, injun-meal shorts,
- Spunk-water, spunk-water, swaller these warts,'
-
-and then walk away quick, eleven steps, with your eyes shut, and then
-turn around three times and walk home without speaking to anybody.
-Because if you speak the charm's busted."
-
-"Well, that sounds like a good way; but that ain't the way Bob Tanner
-done."
-
-"No, sir, you can bet he didn't, becuz he's the wartiest boy in this
-town; and he wouldn't have a wart on him if he'd knowed how to work
-spunk-water. I've took off thousands of warts off of my hands that way,
-Huck. I play with frogs so much that I've always got considerable many
-warts. Sometimes I take 'em off with a bean."
-
-"Yes, bean's good. I've done that."
-
-"Have you? What's your way?"
-
-"You take and split the bean, and cut the wart so as to get some
-blood, and then you put the blood on one piece of the bean and take and
-dig a hole and bury it 'bout midnight at the crossroads in the dark of
-the moon, and then you burn up the rest of the bean. You see that piece
-that's got the blood on it will keep drawing and drawing, trying to
-fetch the other piece to it, and so that helps the blood to draw the
-wart, and pretty soon off she comes."
-
-"Yes, that's it, Huck--that's it; though when you're burying it if you
-say 'Down bean; off wart; come no more to bother me!' it's better.
-That's the way Joe Harper does, and he's been nearly to Coonville and
-most everywheres. But say--how do you cure 'em with dead cats?"
-
-"Why, you take your cat and go and get in the graveyard 'long about
-midnight when somebody that was wicked has been buried; and when it's
-midnight a devil will come, or maybe two or three, but you can't see
-'em, you can only hear something like the wind, or maybe hear 'em talk;
-and when they're taking that feller away, you heave your cat after 'em
-and say, 'Devil follow corpse, cat follow devil, warts follow cat, I'm
-done with ye!' That'll fetch ANY wart."
-
-"Sounds right. D'you ever try it, Huck?"
-
-"No, but old Mother Hopkins told me."
-
-"Well, I reckon it's so, then. Becuz they say she's a witch."
-
-"Say! Why, Tom, I KNOW she is. She witched pap. Pap says so his own
-self. He come along one day, and he see she was a-witching him, so he
-took up a rock, and if she hadn't dodged, he'd a got her. Well, that
-very night he rolled off'n a shed wher' he was a layin drunk, and broke
-his arm."
-
-"Why, that's awful. How did he know she was a-witching him?"
-
-"Lord, pap can tell, easy. Pap says when they keep looking at you
-right stiddy, they're a-witching you. Specially if they mumble. Becuz
-when they mumble they're saying the Lord's Prayer backards."
-
-"Say, Hucky, when you going to try the cat?"
-
-"To-night. I reckon they'll come after old Hoss Williams to-night."
-
-"But they buried him Saturday. Didn't they get him Saturday night?"
-
-"Why, how you talk! How could their charms work till midnight?--and
-THEN it's Sunday. Devils don't slosh around much of a Sunday, I don't
-reckon."
-
-"I never thought of that. That's so. Lemme go with you?"
-
-"Of course--if you ain't afeard."
-
-"Afeard! 'Tain't likely. Will you meow?"
-
-"Yes--and you meow back, if you get a chance. Last time, you kep' me
-a-meowing around till old Hays went to throwing rocks at me and says
-'Dern that cat!' and so I hove a brick through his window--but don't
-you tell."
-
-"I won't. I couldn't meow that night, becuz auntie was watching me,
-but I'll meow this time. Say--what's that?"
-
-"Nothing but a tick."
-
-"Where'd you get him?"
-
-"Out in the woods."
-
-"What'll you take for him?"
-
-"I don't know. I don't want to sell him."
-
-"All right. It's a mighty small tick, anyway."
-
-"Oh, anybody can run a tick down that don't belong to them. I'm
-satisfied with it. It's a good enough tick for me."
-
-"Sho, there's ticks a plenty. I could have a thousand of 'em if I
-wanted to."
-
-"Well, why don't you? Becuz you know mighty well you can't. This is a
-pretty early tick, I reckon. It's the first one I've seen this year."
-
-"Say, Huck--I'll give you my tooth for him."
-
-"Less see it."
-
-Tom got out a bit of paper and carefully unrolled it. Huckleberry
-viewed it wistfully. The temptation was very strong. At last he said:
-
-"Is it genuwyne?"
-
-Tom lifted his lip and showed the vacancy.
-
-"Well, all right," said Huckleberry, "it's a trade."
-
-Tom enclosed the tick in the percussion-cap box that had lately been
-the pinchbug's prison, and the boys separated, each feeling wealthier
-than before.
-
-When Tom reached the little isolated frame schoolhouse, he strode in
-briskly, with the manner of one who had come with all honest speed.
-He hung his hat on a peg and flung himself into his seat with
-business-like alacrity. The master, throned on high in his great
-splint-bottom arm-chair, was dozing, lulled by the drowsy hum of study.
-The interruption roused him.
-
-"Thomas Sawyer!"
-
-Tom knew that when his name was pronounced in full, it meant trouble.
-
-"Sir!"
-
-"Come up here. Now, sir, why are you late again, as usual?"
-
-Tom was about to take refuge in a lie, when he saw two long tails of
-yellow hair hanging down a back that he recognized by the electric
-sympathy of love; and by that form was THE ONLY VACANT PLACE on the
-girls' side of the schoolhouse. He instantly said:
-
-"I STOPPED TO TALK WITH HUCKLEBERRY FINN!"
-
-The master's pulse stood still, and he stared helplessly. The buzz of
-study ceased. The pupils wondered if this foolhardy boy had lost his
-mind. The master said:
-
-"You--you did what?"
-
-"Stopped to talk with Huckleberry Finn."
-
-There was no mistaking the words.
-
-"Thomas Sawyer, this is the most astounding confession I have ever
-listened to. No mere ferule will answer for this offence. Take off your
-jacket."
-
-The master's arm performed until it was tired and the stock of
-switches notably diminished. Then the order followed:
-
-"Now, sir, go and sit with the girls! And let this be a warning to you."
-
-The titter that rippled around the room appeared to abash the boy, but
-in reality that result was caused rather more by his worshipful awe of
-his unknown idol and the dread pleasure that lay in his high good
-fortune. He sat down upon the end of the pine bench and the girl
-hitched herself away from him with a toss of her head. Nudges and winks
-and whispers traversed the room, but Tom sat still, with his arms upon
-the long, low desk before him, and seemed to study his book.
-
-By and by attention ceased from him, and the accustomed school murmur
-rose upon the dull air once more. Presently the boy began to steal
-furtive glances at the girl. She observed it, "made a mouth" at him and
-gave him the back of her head for the space of a minute. When she
-cautiously faced around again, a peach lay before her. She thrust it
-away. Tom gently put it back. She thrust it away again, but with less
-animosity. Tom patiently returned it to its place. Then she let it
-remain. Tom scrawled on his slate, "Please take it--I got more." The
-girl glanced at the words, but made no sign. Now the boy began to draw
-something on the slate, hiding his work with his left hand. For a time
-the girl refused to notice; but her human curiosity presently began to
-manifest itself by hardly perceptible signs. The boy worked on,
-apparently unconscious. The girl made a sort of noncommittal attempt to
-see, but the boy did not betray that he was aware of it. At last she
-gave in and hesitatingly whispered:
-
-"Let me see it."
-
-Tom partly uncovered a dismal caricature of a house with two gable
-ends to it and a corkscrew of smoke issuing from the chimney. Then the
-girl's interest began to fasten itself upon the work and she forgot
-everything else. When it was finished, she gazed a moment, then
-whispered:
-
-"It's nice--make a man."
-
-The artist erected a man in the front yard, that resembled a derrick.
-He could have stepped over the house; but the girl was not
-hypercritical; she was satisfied with the monster, and whispered:
-
-"It's a beautiful man--now make me coming along."
-
-Tom drew an hour-glass with a full moon and straw limbs to it and
-armed the spreading fingers with a portentous fan. The girl said:
-
-"It's ever so nice--I wish I could draw."
-
-"It's easy," whispered Tom, "I'll learn you."
-
-"Oh, will you? When?"
-
-"At noon. Do you go home to dinner?"
-
-"I'll stay if you will."
-
-"Good--that's a whack. What's your name?"
-
-"Becky Thatcher. What's yours? Oh, I know. It's Thomas Sawyer."
-
-"That's the name they lick me by. I'm Tom when I'm good. You call me
-Tom, will you?"
-
-"Yes."
-
-Now Tom began to scrawl something on the slate, hiding the words from
-the girl. But she was not backward this time. She begged to see. Tom
-said:
-
-"Oh, it ain't anything."
-
-"Yes it is."
-
-"No it ain't. You don't want to see."
-
-"Yes I do, indeed I do. Please let me."
-
-"You'll tell."
-
-"No I won't--deed and deed and double deed won't."
-
-"You won't tell anybody at all? Ever, as long as you live?"
-
-"No, I won't ever tell ANYbody. Now let me."
-
-"Oh, YOU don't want to see!"
-
-"Now that you treat me so, I WILL see." And she put her small hand
-upon his and a little scuffle ensued, Tom pretending to resist in
-earnest but letting his hand slip by degrees till these words were
-revealed: "I LOVE YOU."
-
-"Oh, you bad thing!" And she hit his hand a smart rap, but reddened
-and looked pleased, nevertheless.
-
-Just at this juncture the boy felt a slow, fateful grip closing on his
-ear, and a steady lifting impulse. In that wise he was borne across the
-house and deposited in his own seat, under a peppering fire of giggles
-from the whole school. Then the master stood over him during a few
-awful moments, and finally moved away to his throne without saying a
-word. But although Tom's ear tingled, his heart was jubilant.
-
-As the school quieted down Tom made an honest effort to study, but the
-turmoil within him was too great. In turn he took his place in the
-reading class and made a botch of it; then in the geography class and
-turned lakes into mountains, mountains into rivers, and rivers into
-continents, till chaos was come again; then in the spelling class, and
-got "turned down," by a succession of mere baby words, till he brought
-up at the foot and yielded up the pewter medal which he had worn with
-ostentation for months.
-
-
-
-CHAPTER VII
-
-THE harder Tom tried to fasten his mind on his book, the more his
-ideas wandered. So at last, with a sigh and a yawn, he gave it up. It
-seemed to him that the noon recess would never come. The air was
-utterly dead. There was not a breath stirring. It was the sleepiest of
-sleepy days. The drowsing murmur of the five and twenty studying
-scholars soothed the soul like the spell that is in the murmur of bees.
-Away off in the flaming sunshine, Cardiff Hill lifted its soft green
-sides through a shimmering veil of heat, tinted with the purple of
-distance; a few birds floated on lazy wing high in the air; no other
-living thing was visible but some cows, and they were asleep. Tom's
-heart ached to be free, or else to have something of interest to do to
-pass the dreary time. His hand wandered into his pocket and his face
-lit up with a glow of gratitude that was prayer, though he did not know
-it. Then furtively the percussion-cap box came out. He released the
-tick and put him on the long flat desk. The creature probably glowed
-with a gratitude that amounted to prayer, too, at this moment, but it
-was premature: for when he started thankfully to travel off, Tom turned
-him aside with a pin and made him take a new direction.
-
-Tom's bosom friend sat next him, suffering just as Tom had been, and
-now he was deeply and gratefully interested in this entertainment in an
-instant. This bosom friend was Joe Harper. The two boys were sworn
-friends all the week, and embattled enemies on Saturdays. Joe took a
-pin out of his lapel and began to assist in exercising the prisoner.
-The sport grew in interest momently. Soon Tom said that they were
-interfering with each other, and neither getting the fullest benefit of
-the tick. So he put Joe's slate on the desk and drew a line down the
-middle of it from top to bottom.
-
-"Now," said he, "as long as he is on your side you can stir him up and
-I'll let him alone; but if you let him get away and get on my side,
-you're to leave him alone as long as I can keep him from crossing over."
-
-"All right, go ahead; start him up."
-
-The tick escaped from Tom, presently, and crossed the equator. Joe
-harassed him awhile, and then he got away and crossed back again. This
-change of base occurred often. While one boy was worrying the tick with
-absorbing interest, the other would look on with interest as strong,
-the two heads bowed together over the slate, and the two souls dead to
-all things else. At last luck seemed to settle and abide with Joe. The
-tick tried this, that, and the other course, and got as excited and as
-anxious as the boys themselves, but time and again just as he would
-have victory in his very grasp, so to speak, and Tom's fingers would be
-twitching to begin, Joe's pin would deftly head him off, and keep
-possession. At last Tom could stand it no longer. The temptation was
-too strong. So he reached out and lent a hand with his pin. Joe was
-angry in a moment. Said he:
-
-"Tom, you let him alone."
-
-"I only just want to stir him up a little, Joe."
-
-"No, sir, it ain't fair; you just let him alone."
-
-"Blame it, I ain't going to stir him much."
-
-"Let him alone, I tell you."
-
-"I won't!"
-
-"You shall--he's on my side of the line."
-
-"Look here, Joe Harper, whose is that tick?"
-
-"I don't care whose tick he is--he's on my side of the line, and you
-sha'n't touch him."
-
-"Well, I'll just bet I will, though. He's my tick and I'll do what I
-blame please with him, or die!"
-
-A tremendous whack came down on Tom's shoulders, and its duplicate on
-Joe's; and for the space of two minutes the dust continued to fly from
-the two jackets and the whole school to enjoy it. The boys had been too
-absorbed to notice the hush that had stolen upon the school awhile
-before when the master came tiptoeing down the room and stood over
-them. He had contemplated a good part of the performance before he
-contributed his bit of variety to it.
-
-When school broke up at noon, Tom flew to Becky Thatcher, and
-whispered in her ear:
-
-"Put on your bonnet and let on you're going home; and when you get to
-the corner, give the rest of 'em the slip, and turn down through the
-lane and come back. I'll go the other way and come it over 'em the same
-way."
-
-So the one went off with one group of scholars, and the other with
-another. In a little while the two met at the bottom of the lane, and
-when they reached the school they had it all to themselves. Then they
-sat together, with a slate before them, and Tom gave Becky the pencil
-and held her hand in his, guiding it, and so created another surprising
-house. When the interest in art began to wane, the two fell to talking.
-Tom was swimming in bliss. He said:
-
-"Do you love rats?"
-
-"No! I hate them!"
-
-"Well, I do, too--LIVE ones. But I mean dead ones, to swing round your
-head with a string."
-
-"No, I don't care for rats much, anyway. What I like is chewing-gum."
-
-"Oh, I should say so! I wish I had some now."
-
-"Do you? I've got some. I'll let you chew it awhile, but you must give
-it back to me."
-
-That was agreeable, so they chewed it turn about, and dangled their
-legs against the bench in excess of contentment.
-
-"Was you ever at a circus?" said Tom.
-
-"Yes, and my pa's going to take me again some time, if I'm good."
-
-"I been to the circus three or four times--lots of times. Church ain't
-shucks to a circus. There's things going on at a circus all the time.
-I'm going to be a clown in a circus when I grow up."
-
-"Oh, are you! That will be nice. They're so lovely, all spotted up."
-
-"Yes, that's so. And they get slathers of money--most a dollar a day,
-Ben Rogers says. Say, Becky, was you ever engaged?"
-
-"What's that?"
-
-"Why, engaged to be married."
-
-"No."
-
-"Would you like to?"
-
-"I reckon so. I don't know. What is it like?"
-
-"Like? Why it ain't like anything. You only just tell a boy you won't
-ever have anybody but him, ever ever ever, and then you kiss and that's
-all. Anybody can do it."
-
-"Kiss? What do you kiss for?"
-
-"Why, that, you know, is to--well, they always do that."
-
-"Everybody?"
-
-"Why, yes, everybody that's in love with each other. Do you remember
-what I wrote on the slate?"
-
-"Ye--yes."
-
-"What was it?"
-
-"I sha'n't tell you."
-
-"Shall I tell YOU?"
-
-"Ye--yes--but some other time."
-
-"No, now."
-
-"No, not now--to-morrow."
-
-"Oh, no, NOW. Please, Becky--I'll whisper it, I'll whisper it ever so
-easy."
-
-Becky hesitating, Tom took silence for consent, and passed his arm
-about her waist and whispered the tale ever so softly, with his mouth
-close to her ear. And then he added:
-
-"Now you whisper it to me--just the same."
-
-She resisted, for a while, and then said:
-
-"You turn your face away so you can't see, and then I will. But you
-mustn't ever tell anybody--WILL you, Tom? Now you won't, WILL you?"
-
-"No, indeed, indeed I won't. Now, Becky."
-
-He turned his face away. She bent timidly around till her breath
-stirred his curls and whispered, "I--love--you!"
-
-Then she sprang away and ran around and around the desks and benches,
-with Tom after her, and took refuge in a corner at last, with her
-little white apron to her face. Tom clasped her about her neck and
-pleaded:
-
-"Now, Becky, it's all done--all over but the kiss. Don't you be afraid
-of that--it ain't anything at all. Please, Becky." And he tugged at her
-apron and the hands.
-
-By and by she gave up, and let her hands drop; her face, all glowing
-with the struggle, came up and submitted. Tom kissed the red lips and
-said:
-
-"Now it's all done, Becky. And always after this, you know, you ain't
-ever to love anybody but me, and you ain't ever to marry anybody but
-me, ever never and forever. Will you?"
-
-"No, I'll never love anybody but you, Tom, and I'll never marry
-anybody but you--and you ain't to ever marry anybody but me, either."
-
-"Certainly. Of course. That's PART of it. And always coming to school
-or when we're going home, you're to walk with me, when there ain't
-anybody looking--and you choose me and I choose you at parties, because
-that's the way you do when you're engaged."
-
-"It's so nice. I never heard of it before."
-
-"Oh, it's ever so gay! Why, me and Amy Lawrence--"
-
-The big eyes told Tom his blunder and he stopped, confused.
-
-"Oh, Tom! Then I ain't the first you've ever been engaged to!"
-
-The child began to cry. Tom said:
-
-"Oh, don't cry, Becky, I don't care for her any more."
-
-"Yes, you do, Tom--you know you do."
-
-Tom tried to put his arm about her neck, but she pushed him away and
-turned her face to the wall, and went on crying. Tom tried again, with
-soothing words in his mouth, and was repulsed again. Then his pride was
-up, and he strode away and went outside. He stood about, restless and
-uneasy, for a while, glancing at the door, every now and then, hoping
-she would repent and come to find him. But she did not. Then he began
-to feel badly and fear that he was in the wrong. It was a hard struggle
-with him to make new advances, now, but he nerved himself to it and
-entered. She was still standing back there in the corner, sobbing, with
-her face to the wall. Tom's heart smote him. He went to her and stood a
-moment, not knowing exactly how to proceed. Then he said hesitatingly:
-
-"Becky, I--I don't care for anybody but you."
-
-No reply--but sobs.
-
-"Becky"--pleadingly. "Becky, won't you say something?"
-
-More sobs.
-
-Tom got out his chiefest jewel, a brass knob from the top of an
-andiron, and passed it around her so that she could see it, and said:
-
-"Please, Becky, won't you take it?"
-
-She struck it to the floor. Then Tom marched out of the house and over
-the hills and far away, to return to school no more that day. Presently
-Becky began to suspect. She ran to the door; he was not in sight; she
-flew around to the play-yard; he was not there. Then she called:
-
-"Tom! Come back, Tom!"
-
-She listened intently, but there was no answer. She had no companions
-but silence and loneliness. So she sat down to cry again and upbraid
-herself; and by this time the scholars began to gather again, and she
-had to hide her griefs and still her broken heart and take up the cross
-of a long, dreary, aching afternoon, with none among the strangers
-about her to exchange sorrows with.
-
-
-
-CHAPTER VIII
-
-TOM dodged hither and thither through lanes until he was well out of
-the track of returning scholars, and then fell into a moody jog. He
-crossed a small "branch" two or three times, because of a prevailing
-juvenile superstition that to cross water baffled pursuit. Half an hour
-later he was disappearing behind the Douglas mansion on the summit of
-Cardiff Hill, and the schoolhouse was hardly distinguishable away off
-in the valley behind him. He entered a dense wood, picked his pathless
-way to the centre of it, and sat down on a mossy spot under a spreading
-oak. There was not even a zephyr stirring; the dead noonday heat had
-even stilled the songs of the birds; nature lay in a trance that was
-broken by no sound but the occasional far-off hammering of a
-woodpecker, and this seemed to render the pervading silence and sense
-of loneliness the more profound. The boy's soul was steeped in
-melancholy; his feelings were in happy accord with his surroundings. He
-sat long with his elbows on his knees and his chin in his hands,
-meditating. It seemed to him that life was but a trouble, at best, and
-he more than half envied Jimmy Hodges, so lately released; it must be
-very peaceful, he thought, to lie and slumber and dream forever and
-ever, with the wind whispering through the trees and caressing the
-grass and the flowers over the grave, and nothing to bother and grieve
-about, ever any more. If he only had a clean Sunday-school record he
-could be willing to go, and be done with it all. Now as to this girl.
-What had he done? Nothing. He had meant the best in the world, and been
-treated like a dog--like a very dog. She would be sorry some day--maybe
-when it was too late. Ah, if he could only die TEMPORARILY!
-
-But the elastic heart of youth cannot be compressed into one
-constrained shape long at a time. Tom presently began to drift
-insensibly back into the concerns of this life again. What if he turned
-his back, now, and disappeared mysteriously? What if he went away--ever
-so far away, into unknown countries beyond the seas--and never came
-back any more! How would she feel then! The idea of being a clown
-recurred to him now, only to fill him with disgust. For frivolity and
-jokes and spotted tights were an offense, when they intruded themselves
-upon a spirit that was exalted into the vague august realm of the
-romantic. No, he would be a soldier, and return after long years, all
-war-worn and illustrious. No--better still, he would join the Indians,
-and hunt buffaloes and go on the warpath in the mountain ranges and the
-trackless great plains of the Far West, and away in the future come
-back a great chief, bristling with feathers, hideous with paint, and
-prance into Sunday-school, some drowsy summer morning, with a
-bloodcurdling war-whoop, and sear the eyeballs of all his companions
-with unappeasable envy. But no, there was something gaudier even than
-this. He would be a pirate! That was it! NOW his future lay plain
-before him, and glowing with unimaginable splendor. How his name would
-fill the world, and make people shudder! How gloriously he would go
-plowing the dancing seas, in his long, low, black-hulled racer, the
-Spirit of the Storm, with his grisly flag flying at the fore! And at
-the zenith of his fame, how he would suddenly appear at the old village
-and stalk into church, brown and weather-beaten, in his black velvet
-doublet and trunks, his great jack-boots, his crimson sash, his belt
-bristling with horse-pistols, his crime-rusted cutlass at his side, his
-slouch hat with waving plumes, his black flag unfurled, with the skull
-and crossbones on it, and hear with swelling ecstasy the whisperings,
-"It's Tom Sawyer the Pirate!--the Black Avenger of the Spanish Main!"
-
-Yes, it was settled; his career was determined. He would run away from
-home and enter upon it. He would start the very next morning. Therefore
-he must now begin to get ready. He would collect his resources
-together. He went to a rotten log near at hand and began to dig under
-one end of it with his Barlow knife. He soon struck wood that sounded
-hollow. He put his hand there and uttered this incantation impressively:
-
-"What hasn't come here, come! What's here, stay here!"
-
-Then he scraped away the dirt, and exposed a pine shingle. He took it
-up and disclosed a shapely little treasure-house whose bottom and sides
-were of shingles. In it lay a marble. Tom's astonishment was boundless!
-He scratched his head with a perplexed air, and said:
-
-"Well, that beats anything!"
-
-Then he tossed the marble away pettishly, and stood cogitating. The
-truth was, that a superstition of his had failed, here, which he and
-all his comrades had always looked upon as infallible. If you buried a
-marble with certain necessary incantations, and left it alone a
-fortnight, and then opened the place with the incantation he had just
-used, you would find that all the marbles you had ever lost had
-gathered themselves together there, meantime, no matter how widely they
-had been separated. But now, this thing had actually and unquestionably
-failed. Tom's whole structure of faith was shaken to its foundations.
-He had many a time heard of this thing succeeding but never of its
-failing before. It did not occur to him that he had tried it several
-times before, himself, but could never find the hiding-places
-afterward. He puzzled over the matter some time, and finally decided
-that some witch had interfered and broken the charm. He thought he
-would satisfy himself on that point; so he searched around till he
-found a small sandy spot with a little funnel-shaped depression in it.
-He laid himself down and put his mouth close to this depression and
-called--
-
-"Doodle-bug, doodle-bug, tell me what I want to know! Doodle-bug,
-doodle-bug, tell me what I want to know!"
-
-The sand began to work, and presently a small black bug appeared for a
-second and then darted under again in a fright.
-
-"He dasn't tell! So it WAS a witch that done it. I just knowed it."
-
-He well knew the futility of trying to contend against witches, so he
-gave up discouraged. But it occurred to him that he might as well have
-the marble he had just thrown away, and therefore he went and made a
-patient search for it. But he could not find it. Now he went back to
-his treasure-house and carefully placed himself just as he had been
-standing when he tossed the marble away; then he took another marble
-from his pocket and tossed it in the same way, saying:
-
-"Brother, go find your brother!"
-
-He watched where it stopped, and went there and looked. But it must
-have fallen short or gone too far; so he tried twice more. The last
-repetition was successful. The two marbles lay within a foot of each
-other.
-
-Just here the blast of a toy tin trumpet came faintly down the green
-aisles of the forest. Tom flung off his jacket and trousers, turned a
-suspender into a belt, raked away some brush behind the rotten log,
-disclosing a rude bow and arrow, a lath sword and a tin trumpet, and in
-a moment had seized these things and bounded away, barelegged, with
-fluttering shirt. He presently halted under a great elm, blew an
-answering blast, and then began to tiptoe and look warily out, this way
-and that. He said cautiously--to an imaginary company:
-
-"Hold, my merry men! Keep hid till I blow."
-
-Now appeared Joe Harper, as airily clad and elaborately armed as Tom.
-Tom called:
-
-"Hold! Who comes here into Sherwood Forest without my pass?"
-
-"Guy of Guisborne wants no man's pass. Who art thou that--that--"
-
-"Dares to hold such language," said Tom, prompting--for they talked
-"by the book," from memory.
-
-"Who art thou that dares to hold such language?"
-
-"I, indeed! I am Robin Hood, as thy caitiff carcase soon shall know."
-
-"Then art thou indeed that famous outlaw? Right gladly will I dispute
-with thee the passes of the merry wood. Have at thee!"
-
-They took their lath swords, dumped their other traps on the ground,
-struck a fencing attitude, foot to foot, and began a grave, careful
-combat, "two up and two down." Presently Tom said:
-
-"Now, if you've got the hang, go it lively!"
-
-So they "went it lively," panting and perspiring with the work. By and
-by Tom shouted:
-
-"Fall! fall! Why don't you fall?"
-
-"I sha'n't! Why don't you fall yourself? You're getting the worst of
-it."
-
-"Why, that ain't anything. I can't fall; that ain't the way it is in
-the book. The book says, 'Then with one back-handed stroke he slew poor
-Guy of Guisborne.' You're to turn around and let me hit you in the
-back."
-
-There was no getting around the authorities, so Joe turned, received
-the whack and fell.
-
-"Now," said Joe, getting up, "you got to let me kill YOU. That's fair."
-
-"Why, I can't do that, it ain't in the book."
-
-"Well, it's blamed mean--that's all."
-
-"Well, say, Joe, you can be Friar Tuck or Much the miller's son, and
-lam me with a quarter-staff; or I'll be the Sheriff of Nottingham and
-you be Robin Hood a little while and kill me."
-
-This was satisfactory, and so these adventures were carried out. Then
-Tom became Robin Hood again, and was allowed by the treacherous nun to
-bleed his strength away through his neglected wound. And at last Joe,
-representing a whole tribe of weeping outlaws, dragged him sadly forth,
-gave his bow into his feeble hands, and Tom said, "Where this arrow
-falls, there bury poor Robin Hood under the greenwood tree." Then he
-shot the arrow and fell back and would have died, but he lit on a
-nettle and sprang up too gaily for a corpse.
-
-The boys dressed themselves, hid their accoutrements, and went off
-grieving that there were no outlaws any more, and wondering what modern
-civilization could claim to have done to compensate for their loss.
-They said they would rather be outlaws a year in Sherwood Forest than
-President of the United States forever.
-
-
-
-CHAPTER IX
-
-AT half-past nine, that night, Tom and Sid were sent to bed, as usual.
-They said their prayers, and Sid was soon asleep. Tom lay awake and
-waited, in restless impatience. When it seemed to him that it must be
-nearly daylight, he heard the clock strike ten! This was despair. He
-would have tossed and fidgeted, as his nerves demanded, but he was
-afraid he might wake Sid. So he lay still, and stared up into the dark.
-Everything was dismally still. By and by, out of the stillness, little,
-scarcely perceptible noises began to emphasize themselves. The ticking
-of the clock began to bring itself into notice. Old beams began to
-crack mysteriously. The stairs creaked faintly. Evidently spirits were
-abroad. A measured, muffled snore issued from Aunt Polly's chamber. And
-now the tiresome chirping of a cricket that no human ingenuity could
-locate, began. Next the ghastly ticking of a deathwatch in the wall at
-the bed's head made Tom shudder--it meant that somebody's days were
-numbered. Then the howl of a far-off dog rose on the night air, and was
-answered by a fainter howl from a remoter distance. Tom was in an
-agony. At last he was satisfied that time had ceased and eternity
-begun; he began to doze, in spite of himself; the clock chimed eleven,
-but he did not hear it. And then there came, mingling with his
-half-formed dreams, a most melancholy caterwauling. The raising of a
-neighboring window disturbed him. A cry of "Scat! you devil!" and the
-crash of an empty bottle against the back of his aunt's woodshed
-brought him wide awake, and a single minute later he was dressed and
-out of the window and creeping along the roof of the "ell" on all
-fours. He "meow'd" with caution once or twice, as he went; then jumped
-to the roof of the woodshed and thence to the ground. Huckleberry Finn
-was there, with his dead cat. The boys moved off and disappeared in the
-gloom. At the end of half an hour they were wading through the tall
-grass of the graveyard.
-
-It was a graveyard of the old-fashioned Western kind. It was on a
-hill, about a mile and a half from the village. It had a crazy board
-fence around it, which leaned inward in places, and outward the rest of
-the time, but stood upright nowhere. Grass and weeds grew rank over the
-whole cemetery. All the old graves were sunken in, there was not a
-tombstone on the place; round-topped, worm-eaten boards staggered over
-the graves, leaning for support and finding none. "Sacred to the memory
-of" So-and-So had been painted on them once, but it could no longer
-have been read, on the most of them, now, even if there had been light.
-
-A faint wind moaned through the trees, and Tom feared it might be the
-spirits of the dead, complaining at being disturbed. The boys talked
-little, and only under their breath, for the time and the place and the
-pervading solemnity and silence oppressed their spirits. They found the
-sharp new heap they were seeking, and ensconced themselves within the
-protection of three great elms that grew in a bunch within a few feet
-of the grave.
-
-Then they waited in silence for what seemed a long time. The hooting
-of a distant owl was all the sound that troubled the dead stillness.
-Tom's reflections grew oppressive. He must force some talk. So he said
-in a whisper:
-
-"Hucky, do you believe the dead people like it for us to be here?"
-
-Huckleberry whispered:
-
-"I wisht I knowed. It's awful solemn like, AIN'T it?"
-
-"I bet it is."
-
-There was a considerable pause, while the boys canvassed this matter
-inwardly. Then Tom whispered:
-
-"Say, Hucky--do you reckon Hoss Williams hears us talking?"
-
-"O' course he does. Least his sperrit does."
-
-Tom, after a pause:
-
-"I wish I'd said Mister Williams. But I never meant any harm.
-Everybody calls him Hoss."
-
-"A body can't be too partic'lar how they talk 'bout these-yer dead
-people, Tom."
-
-This was a damper, and conversation died again.
-
-Presently Tom seized his comrade's arm and said:
-
-"Sh!"
-
-"What is it, Tom?" And the two clung together with beating hearts.
-
-"Sh! There 'tis again! Didn't you hear it?"
-
-"I--"
-
-"There! Now you hear it."
-
-"Lord, Tom, they're coming! They're coming, sure. What'll we do?"
-
-"I dono. Think they'll see us?"
-
-"Oh, Tom, they can see in the dark, same as cats. I wisht I hadn't
-come."
-
-"Oh, don't be afeard. I don't believe they'll bother us. We ain't
-doing any harm. If we keep perfectly still, maybe they won't notice us
-at all."
-
-"I'll try to, Tom, but, Lord, I'm all of a shiver."
-
-"Listen!"
-
-The boys bent their heads together and scarcely breathed. A muffled
-sound of voices floated up from the far end of the graveyard.
-
-"Look! See there!" whispered Tom. "What is it?"
-
-"It's devil-fire. Oh, Tom, this is awful."
-
-Some vague figures approached through the gloom, swinging an
-old-fashioned tin lantern that freckled the ground with innumerable
-little spangles of light. Presently Huckleberry whispered with a
-shudder:
-
-"It's the devils sure enough. Three of 'em! Lordy, Tom, we're goners!
-Can you pray?"
-
-"I'll try, but don't you be afeard. They ain't going to hurt us. 'Now
-I lay me down to sleep, I--'"
-
-"Sh!"
-
-"What is it, Huck?"
-
-"They're HUMANS! One of 'em is, anyway. One of 'em's old Muff Potter's
-voice."
-
-"No--'tain't so, is it?"
-
-"I bet I know it. Don't you stir nor budge. He ain't sharp enough to
-notice us. Drunk, the same as usual, likely--blamed old rip!"
-
-"All right, I'll keep still. Now they're stuck. Can't find it. Here
-they come again. Now they're hot. Cold again. Hot again. Red hot!
-They're p'inted right, this time. Say, Huck, I know another o' them
-voices; it's Injun Joe."
-
-"That's so--that murderin' half-breed! I'd druther they was devils a
-dern sight. What kin they be up to?"
-
-The whisper died wholly out, now, for the three men had reached the
-grave and stood within a few feet of the boys' hiding-place.
-
-"Here it is," said the third voice; and the owner of it held the
-lantern up and revealed the face of young Doctor Robinson.
-
-Potter and Injun Joe were carrying a handbarrow with a rope and a
-couple of shovels on it. They cast down their load and began to open
-the grave. The doctor put the lantern at the head of the grave and came
-and sat down with his back against one of the elm trees. He was so
-close the boys could have touched him.
-
-"Hurry, men!" he said, in a low voice; "the moon might come out at any
-moment."
-
-They growled a response and went on digging. For some time there was
-no noise but the grating sound of the spades discharging their freight
-of mould and gravel. It was very monotonous. Finally a spade struck
-upon the coffin with a dull woody accent, and within another minute or
-two the men had hoisted it out on the ground. They pried off the lid
-with their shovels, got out the body and dumped it rudely on the
-ground. The moon drifted from behind the clouds and exposed the pallid
-face. The barrow was got ready and the corpse placed on it, covered
-with a blanket, and bound to its place with the rope. Potter took out a
-large spring-knife and cut off the dangling end of the rope and then
-said:
-
-"Now the cussed thing's ready, Sawbones, and you'll just out with
-another five, or here she stays."
-
-"That's the talk!" said Injun Joe.
-
-"Look here, what does this mean?" said the doctor. "You required your
-pay in advance, and I've paid you."
-
-"Yes, and you done more than that," said Injun Joe, approaching the
-doctor, who was now standing. "Five years ago you drove me away from
-your father's kitchen one night, when I come to ask for something to
-eat, and you said I warn't there for any good; and when I swore I'd get
-even with you if it took a hundred years, your father had me jailed for
-a vagrant. Did you think I'd forget? The Injun blood ain't in me for
-nothing. And now I've GOT you, and you got to SETTLE, you know!"
-
-He was threatening the doctor, with his fist in his face, by this
-time. The doctor struck out suddenly and stretched the ruffian on the
-ground. Potter dropped his knife, and exclaimed:
-
-"Here, now, don't you hit my pard!" and the next moment he had
-grappled with the doctor and the two were struggling with might and
-main, trampling the grass and tearing the ground with their heels.
-Injun Joe sprang to his feet, his eyes flaming with passion, snatched
-up Potter's knife, and went creeping, catlike and stooping, round and
-round about the combatants, seeking an opportunity. All at once the
-doctor flung himself free, seized the heavy headboard of Williams'
-grave and felled Potter to the earth with it--and in the same instant
-the half-breed saw his chance and drove the knife to the hilt in the
-young man's breast. He reeled and fell partly upon Potter, flooding him
-with his blood, and in the same moment the clouds blotted out the
-dreadful spectacle and the two frightened boys went speeding away in
-the dark.
-
-Presently, when the moon emerged again, Injun Joe was standing over
-the two forms, contemplating them. The doctor murmured inarticulately,
-gave a long gasp or two and was still. The half-breed muttered:
-
-"THAT score is settled--damn you."
-
-Then he robbed the body. After which he put the fatal knife in
-Potter's open right hand, and sat down on the dismantled coffin. Three
---four--five minutes passed, and then Potter began to stir and moan. His
-hand closed upon the knife; he raised it, glanced at it, and let it
-fall, with a shudder. Then he sat up, pushing the body from him, and
-gazed at it, and then around him, confusedly. His eyes met Joe's.
-
-"Lord, how is this, Joe?" he said.
-
-"It's a dirty business," said Joe, without moving.
-
-"What did you do it for?"
-
-"I! I never done it!"
-
-"Look here! That kind of talk won't wash."
-
-Potter trembled and grew white.
-
-"I thought I'd got sober. I'd no business to drink to-night. But it's
-in my head yet--worse'n when we started here. I'm all in a muddle;
-can't recollect anything of it, hardly. Tell me, Joe--HONEST, now, old
-feller--did I do it? Joe, I never meant to--'pon my soul and honor, I
-never meant to, Joe. Tell me how it was, Joe. Oh, it's awful--and him
-so young and promising."
-
-"Why, you two was scuffling, and he fetched you one with the headboard
-and you fell flat; and then up you come, all reeling and staggering
-like, and snatched the knife and jammed it into him, just as he fetched
-you another awful clip--and here you've laid, as dead as a wedge til
-now."
-
-"Oh, I didn't know what I was a-doing. I wish I may die this minute if
-I did. It was all on account of the whiskey and the excitement, I
-reckon. I never used a weepon in my life before, Joe. I've fought, but
-never with weepons. They'll all say that. Joe, don't tell! Say you
-won't tell, Joe--that's a good feller. I always liked you, Joe, and
-stood up for you, too. Don't you remember? You WON'T tell, WILL you,
-Joe?" And the poor creature dropped on his knees before the stolid
-murderer, and clasped his appealing hands.
-
-"No, you've always been fair and square with me, Muff Potter, and I
-won't go back on you. There, now, that's as fair as a man can say."
-
-"Oh, Joe, you're an angel. I'll bless you for this the longest day I
-live." And Potter began to cry.
-
-"Come, now, that's enough of that. This ain't any time for blubbering.
-You be off yonder way and I'll go this. Move, now, and don't leave any
-tracks behind you."
-
-Potter started on a trot that quickly increased to a run. The
-half-breed stood looking after him. He muttered:
-
-"If he's as much stunned with the lick and fuddled with the rum as he
-had the look of being, he won't think of the knife till he's gone so
-far he'll be afraid to come back after it to such a place by himself
---chicken-heart!"
-
-Two or three minutes later the murdered man, the blanketed corpse, the
-lidless coffin, and the open grave were under no inspection but the
-moon's. The stillness was complete again, too.
-
-
-
-CHAPTER X
-
-THE two boys flew on and on, toward the village, speechless with
-horror. They glanced backward over their shoulders from time to time,
-apprehensively, as if they feared they might be followed. Every stump
-that started up in their path seemed a man and an enemy, and made them
-catch their breath; and as they sped by some outlying cottages that lay
-near the village, the barking of the aroused watch-dogs seemed to give
-wings to their feet.
-
-"If we can only get to the old tannery before we break down!"
-whispered Tom, in short catches between breaths. "I can't stand it much
-longer."
-
-Huckleberry's hard pantings were his only reply, and the boys fixed
-their eyes on the goal of their hopes and bent to their work to win it.
-They gained steadily on it, and at last, breast to breast, they burst
-through the open door and fell grateful and exhausted in the sheltering
-shadows beyond. By and by their pulses slowed down, and Tom whispered:
-
-"Huckleberry, what do you reckon'll come of this?"
-
-"If Doctor Robinson dies, I reckon hanging'll come of it."
-
-"Do you though?"
-
-"Why, I KNOW it, Tom."
-
-Tom thought a while, then he said:
-
-"Who'll tell? We?"
-
-"What are you talking about? S'pose something happened and Injun Joe
-DIDN'T hang? Why, he'd kill us some time or other, just as dead sure as
-we're a laying here."
-
-"That's just what I was thinking to myself, Huck."
-
-"If anybody tells, let Muff Potter do it, if he's fool enough. He's
-generally drunk enough."
-
-Tom said nothing--went on thinking. Presently he whispered:
-
-"Huck, Muff Potter don't know it. How can he tell?"
-
-"What's the reason he don't know it?"
-
-"Because he'd just got that whack when Injun Joe done it. D'you reckon
-he could see anything? D'you reckon he knowed anything?"
-
-"By hokey, that's so, Tom!"
-
-"And besides, look-a-here--maybe that whack done for HIM!"
-
-"No, 'taint likely, Tom. He had liquor in him; I could see that; and
-besides, he always has. Well, when pap's full, you might take and belt
-him over the head with a church and you couldn't phase him. He says so,
-his own self. So it's the same with Muff Potter, of course. But if a
-man was dead sober, I reckon maybe that whack might fetch him; I dono."
-
-After another reflective silence, Tom said:
-
-"Hucky, you sure you can keep mum?"
-
-"Tom, we GOT to keep mum. You know that. That Injun devil wouldn't
-make any more of drownding us than a couple of cats, if we was to
-squeak 'bout this and they didn't hang him. Now, look-a-here, Tom, less
-take and swear to one another--that's what we got to do--swear to keep
-mum."
-
-"I'm agreed. It's the best thing. Would you just hold hands and swear
-that we--"
-
-"Oh no, that wouldn't do for this. That's good enough for little
-rubbishy common things--specially with gals, cuz THEY go back on you
-anyway, and blab if they get in a huff--but there orter be writing
-'bout a big thing like this. And blood."
-
-Tom's whole being applauded this idea. It was deep, and dark, and
-awful; the hour, the circumstances, the surroundings, were in keeping
-with it. He picked up a clean pine shingle that lay in the moonlight,
-took a little fragment of "red keel" out of his pocket, got the moon on
-his work, and painfully scrawled these lines, emphasizing each slow
-down-stroke by clamping his tongue between his teeth, and letting up
-the pressure on the up-strokes. [See next page.]
-
- "Huck Finn and
- Tom Sawyer swears
- they will keep mum
- about This and They
- wish They may Drop
- down dead in Their
- Tracks if They ever
- Tell and Rot."
-
-Huckleberry was filled with admiration of Tom's facility in writing,
-and the sublimity of his language. He at once took a pin from his lapel
-and was going to prick his flesh, but Tom said:
-
-"Hold on! Don't do that. A pin's brass. It might have verdigrease on
-it."
-
-"What's verdigrease?"
-
-"It's p'ison. That's what it is. You just swaller some of it once
---you'll see."
-
-So Tom unwound the thread from one of his needles, and each boy
-pricked the ball of his thumb and squeezed out a drop of blood. In
-time, after many squeezes, Tom managed to sign his initials, using the
-ball of his little finger for a pen. Then he showed Huckleberry how to
-make an H and an F, and the oath was complete. They buried the shingle
-close to the wall, with some dismal ceremonies and incantations, and
-the fetters that bound their tongues were considered to be locked and
-the key thrown away.
-
-A figure crept stealthily through a break in the other end of the
-ruined building, now, but they did not notice it.
-
-"Tom," whispered Huckleberry, "does this keep us from EVER telling
---ALWAYS?"
-
-"Of course it does. It don't make any difference WHAT happens, we got
-to keep mum. We'd drop down dead--don't YOU know that?"
-
-"Yes, I reckon that's so."
-
-They continued to whisper for some little time. Presently a dog set up
-a long, lugubrious howl just outside--within ten feet of them. The boys
-clasped each other suddenly, in an agony of fright.
-
-"Which of us does he mean?" gasped Huckleberry.
-
-"I dono--peep through the crack. Quick!"
-
-"No, YOU, Tom!"
-
-"I can't--I can't DO it, Huck!"
-
-"Please, Tom. There 'tis again!"
-
-"Oh, lordy, I'm thankful!" whispered Tom. "I know his voice. It's Bull
-Harbison." *
-
-[* If Mr. Harbison owned a slave named Bull, Tom would have spoken of
-him as "Harbison's Bull," but a son or a dog of that name was "Bull
-Harbison."]
-
-"Oh, that's good--I tell you, Tom, I was most scared to death; I'd a
-bet anything it was a STRAY dog."
-
-The dog howled again. The boys' hearts sank once more.
-
-"Oh, my! that ain't no Bull Harbison!" whispered Huckleberry. "DO, Tom!"
-
-Tom, quaking with fear, yielded, and put his eye to the crack. His
-whisper was hardly audible when he said:
-
-"Oh, Huck, IT S A STRAY DOG!"
-
-"Quick, Tom, quick! Who does he mean?"
-
-"Huck, he must mean us both--we're right together."
-
-"Oh, Tom, I reckon we're goners. I reckon there ain't no mistake 'bout
-where I'LL go to. I been so wicked."
-
-"Dad fetch it! This comes of playing hookey and doing everything a
-feller's told NOT to do. I might a been good, like Sid, if I'd a tried
---but no, I wouldn't, of course. But if ever I get off this time, I lay
-I'll just WALLER in Sunday-schools!" And Tom began to snuffle a little.
-
-"YOU bad!" and Huckleberry began to snuffle too. "Consound it, Tom
-Sawyer, you're just old pie, 'longside o' what I am. Oh, LORDY, lordy,
-lordy, I wisht I only had half your chance."
-
-Tom choked off and whispered:
-
-"Look, Hucky, look! He's got his BACK to us!"
-
-Hucky looked, with joy in his heart.
-
-"Well, he has, by jingoes! Did he before?"
-
-"Yes, he did. But I, like a fool, never thought. Oh, this is bully,
-you know. NOW who can he mean?"
-
-The howling stopped. Tom pricked up his ears.
-
-"Sh! What's that?" he whispered.
-
-"Sounds like--like hogs grunting. No--it's somebody snoring, Tom."
-
-"That IS it! Where 'bouts is it, Huck?"
-
-"I bleeve it's down at 'tother end. Sounds so, anyway. Pap used to
-sleep there, sometimes, 'long with the hogs, but laws bless you, he
-just lifts things when HE snores. Besides, I reckon he ain't ever
-coming back to this town any more."
-
-The spirit of adventure rose in the boys' souls once more.
-
-"Hucky, do you das't to go if I lead?"
-
-"I don't like to, much. Tom, s'pose it's Injun Joe!"
-
-Tom quailed. But presently the temptation rose up strong again and the
-boys agreed to try, with the understanding that they would take to
-their heels if the snoring stopped. So they went tiptoeing stealthily
-down, the one behind the other. When they had got to within five steps
-of the snorer, Tom stepped on a stick, and it broke with a sharp snap.
-The man moaned, writhed a little, and his face came into the moonlight.
-It was Muff Potter. The boys' hearts had stood still, and their hopes
-too, when the man moved, but their fears passed away now. They tiptoed
-out, through the broken weather-boarding, and stopped at a little
-distance to exchange a parting word. That long, lugubrious howl rose on
-the night air again! They turned and saw the strange dog standing
-within a few feet of where Potter was lying, and FACING Potter, with
-his nose pointing heavenward.
-
-"Oh, geeminy, it's HIM!" exclaimed both boys, in a breath.
-
-"Say, Tom--they say a stray dog come howling around Johnny Miller's
-house, 'bout midnight, as much as two weeks ago; and a whippoorwill
-come in and lit on the banisters and sung, the very same evening; and
-there ain't anybody dead there yet."
-
-"Well, I know that. And suppose there ain't. Didn't Gracie Miller fall
-in the kitchen fire and burn herself terrible the very next Saturday?"
-
-"Yes, but she ain't DEAD. And what's more, she's getting better, too."
-
-"All right, you wait and see. She's a goner, just as dead sure as Muff
-Potter's a goner. That's what the niggers say, and they know all about
-these kind of things, Huck."
-
-Then they separated, cogitating. When Tom crept in at his bedroom
-window the night was almost spent. He undressed with excessive caution,
-and fell asleep congratulating himself that nobody knew of his
-escapade. He was not aware that the gently-snoring Sid was awake, and
-had been so for an hour.
-
-When Tom awoke, Sid was dressed and gone. There was a late look in the
-light, a late sense in the atmosphere. He was startled. Why had he not
-been called--persecuted till he was up, as usual? The thought filled
-him with bodings. Within five minutes he was dressed and down-stairs,
-feeling sore and drowsy. The family were still at table, but they had
-finished breakfast. There was no voice of rebuke; but there were
-averted eyes; there was a silence and an air of solemnity that struck a
-chill to the culprit's heart. He sat down and tried to seem gay, but it
-was up-hill work; it roused no smile, no response, and he lapsed into
-silence and let his heart sink down to the depths.
-
-After breakfast his aunt took him aside, and Tom almost brightened in
-the hope that he was going to be flogged; but it was not so. His aunt
-wept over him and asked him how he could go and break her old heart so;
-and finally told him to go on, and ruin himself and bring her gray
-hairs with sorrow to the grave, for it was no use for her to try any
-more. This was worse than a thousand whippings, and Tom's heart was
-sorer now than his body. He cried, he pleaded for forgiveness, promised
-to reform over and over again, and then received his dismissal, feeling
-that he had won but an imperfect forgiveness and established but a
-feeble confidence.
-
-He left the presence too miserable to even feel revengeful toward Sid;
-and so the latter's prompt retreat through the back gate was
-unnecessary. He moped to school gloomy and sad, and took his flogging,
-along with Joe Harper, for playing hookey the day before, with the air
-of one whose heart was busy with heavier woes and wholly dead to
-trifles. Then he betook himself to his seat, rested his elbows on his
-desk and his jaws in his hands, and stared at the wall with the stony
-stare of suffering that has reached the limit and can no further go.
-His elbow was pressing against some hard substance. After a long time
-he slowly and sadly changed his position, and took up this object with
-a sigh. It was in a paper. He unrolled it. A long, lingering, colossal
-sigh followed, and his heart broke. It was his brass andiron knob!
-
-This final feather broke the camel's back.
-
-
-
-CHAPTER XI
-
-CLOSE upon the hour of noon the whole village was suddenly electrified
-with the ghastly news. No need of the as yet undreamed-of telegraph;
-the tale flew from man to man, from group to group, from house to
-house, with little less than telegraphic speed. Of course the
-schoolmaster gave holiday for that afternoon; the town would have
-thought strangely of him if he had not.
-
-A gory knife had been found close to the murdered man, and it had been
-recognized by somebody as belonging to Muff Potter--so the story ran.
-And it was said that a belated citizen had come upon Potter washing
-himself in the "branch" about one or two o'clock in the morning, and
-that Potter had at once sneaked off--suspicious circumstances,
-especially the washing which was not a habit with Potter. It was also
-said that the town had been ransacked for this "murderer" (the public
-are not slow in the matter of sifting evidence and arriving at a
-verdict), but that he could not be found. Horsemen had departed down
-all the roads in every direction, and the Sheriff "was confident" that
-he would be captured before night.
-
-All the town was drifting toward the graveyard. Tom's heartbreak
-vanished and he joined the procession, not because he would not a
-thousand times rather go anywhere else, but because an awful,
-unaccountable fascination drew him on. Arrived at the dreadful place,
-he wormed his small body through the crowd and saw the dismal
-spectacle. It seemed to him an age since he was there before. Somebody
-pinched his arm. He turned, and his eyes met Huckleberry's. Then both
-looked elsewhere at once, and wondered if anybody had noticed anything
-in their mutual glance. But everybody was talking, and intent upon the
-grisly spectacle before them.
-
-"Poor fellow!" "Poor young fellow!" "This ought to be a lesson to
-grave robbers!" "Muff Potter'll hang for this if they catch him!" This
-was the drift of remark; and the minister said, "It was a judgment; His
-hand is here."
-
-Now Tom shivered from head to heel; for his eye fell upon the stolid
-face of Injun Joe. At this moment the crowd began to sway and struggle,
-and voices shouted, "It's him! it's him! he's coming himself!"
-
-"Who? Who?" from twenty voices.
-
-"Muff Potter!"
-
-"Hallo, he's stopped!--Look out, he's turning! Don't let him get away!"
-
-People in the branches of the trees over Tom's head said he wasn't
-trying to get away--he only looked doubtful and perplexed.
-
-"Infernal impudence!" said a bystander; "wanted to come and take a
-quiet look at his work, I reckon--didn't expect any company."
-
-The crowd fell apart, now, and the Sheriff came through,
-ostentatiously leading Potter by the arm. The poor fellow's face was
-haggard, and his eyes showed the fear that was upon him. When he stood
-before the murdered man, he shook as with a palsy, and he put his face
-in his hands and burst into tears.
-
-"I didn't do it, friends," he sobbed; "'pon my word and honor I never
-done it."
-
-"Who's accused you?" shouted a voice.
-
-This shot seemed to carry home. Potter lifted his face and looked
-around him with a pathetic hopelessness in his eyes. He saw Injun Joe,
-and exclaimed:
-
-"Oh, Injun Joe, you promised me you'd never--"
-
-"Is that your knife?" and it was thrust before him by the Sheriff.
-
-Potter would have fallen if they had not caught him and eased him to
-the ground. Then he said:
-
-"Something told me 't if I didn't come back and get--" He shuddered;
-then waved his nerveless hand with a vanquished gesture and said, "Tell
-'em, Joe, tell 'em--it ain't any use any more."
-
-Then Huckleberry and Tom stood dumb and staring, and heard the
-stony-hearted liar reel off his serene statement, they expecting every
-moment that the clear sky would deliver God's lightnings upon his head,
-and wondering to see how long the stroke was delayed. And when he had
-finished and still stood alive and whole, their wavering impulse to
-break their oath and save the poor betrayed prisoner's life faded and
-vanished away, for plainly this miscreant had sold himself to Satan and
-it would be fatal to meddle with the property of such a power as that.
-
-"Why didn't you leave? What did you want to come here for?" somebody
-said.
-
-"I couldn't help it--I couldn't help it," Potter moaned. "I wanted to
-run away, but I couldn't seem to come anywhere but here." And he fell
-to sobbing again.
-
-Injun Joe repeated his statement, just as calmly, a few minutes
-afterward on the inquest, under oath; and the boys, seeing that the
-lightnings were still withheld, were confirmed in their belief that Joe
-had sold himself to the devil. He was now become, to them, the most
-balefully interesting object they had ever looked upon, and they could
-not take their fascinated eyes from his face.
-
-They inwardly resolved to watch him nights, when opportunity should
-offer, in the hope of getting a glimpse of his dread master.
-
-Injun Joe helped to raise the body of the murdered man and put it in a
-wagon for removal; and it was whispered through the shuddering crowd
-that the wound bled a little! The boys thought that this happy
-circumstance would turn suspicion in the right direction; but they were
-disappointed, for more than one villager remarked:
-
-"It was within three feet of Muff Potter when it done it."
-
-Tom's fearful secret and gnawing conscience disturbed his sleep for as
-much as a week after this; and at breakfast one morning Sid said:
-
-"Tom, you pitch around and talk in your sleep so much that you keep me
-awake half the time."
-
-Tom blanched and dropped his eyes.
-
-"It's a bad sign," said Aunt Polly, gravely. "What you got on your
-mind, Tom?"
-
-"Nothing. Nothing 't I know of." But the boy's hand shook so that he
-spilled his coffee.
-
-"And you do talk such stuff," Sid said. "Last night you said, 'It's
-blood, it's blood, that's what it is!' You said that over and over. And
-you said, 'Don't torment me so--I'll tell!' Tell WHAT? What is it
-you'll tell?"
-
-Everything was swimming before Tom. There is no telling what might
-have happened, now, but luckily the concern passed out of Aunt Polly's
-face and she came to Tom's relief without knowing it. She said:
-
-"Sho! It's that dreadful murder. I dream about it most every night
-myself. Sometimes I dream it's me that done it."
-
-Mary said she had been affected much the same way. Sid seemed
-satisfied. Tom got out of the presence as quick as he plausibly could,
-and after that he complained of toothache for a week, and tied up his
-jaws every night. He never knew that Sid lay nightly watching, and
-frequently slipped the bandage free and then leaned on his elbow
-listening a good while at a time, and afterward slipped the bandage
-back to its place again. Tom's distress of mind wore off gradually and
-the toothache grew irksome and was discarded. If Sid really managed to
-make anything out of Tom's disjointed mutterings, he kept it to himself.
-
-It seemed to Tom that his schoolmates never would get done holding
-inquests on dead cats, and thus keeping his trouble present to his
-mind. Sid noticed that Tom never was coroner at one of these inquiries,
-though it had been his habit to take the lead in all new enterprises;
-he noticed, too, that Tom never acted as a witness--and that was
-strange; and Sid did not overlook the fact that Tom even showed a
-marked aversion to these inquests, and always avoided them when he
-could. Sid marvelled, but said nothing. However, even inquests went out
-of vogue at last, and ceased to torture Tom's conscience.
-
-Every day or two, during this time of sorrow, Tom watched his
-opportunity and went to the little grated jail-window and smuggled such
-small comforts through to the "murderer" as he could get hold of. The
-jail was a trifling little brick den that stood in a marsh at the edge
-of the village, and no guards were afforded for it; indeed, it was
-seldom occupied. These offerings greatly helped to ease Tom's
-conscience.
-
-The villagers had a strong desire to tar-and-feather Injun Joe and
-ride him on a rail, for body-snatching, but so formidable was his
-character that nobody could be found who was willing to take the lead
-in the matter, so it was dropped. He had been careful to begin both of
-his inquest-statements with the fight, without confessing the
-grave-robbery that preceded it; therefore it was deemed wisest not
-to try the case in the courts at present.
-
-
-
-CHAPTER XII
-
-ONE of the reasons why Tom's mind had drifted away from its secret
-troubles was, that it had found a new and weighty matter to interest
-itself about. Becky Thatcher had stopped coming to school. Tom had
-struggled with his pride a few days, and tried to "whistle her down the
-wind," but failed. He began to find himself hanging around her father's
-house, nights, and feeling very miserable. She was ill. What if she
-should die! There was distraction in the thought. He no longer took an
-interest in war, nor even in piracy. The charm of life was gone; there
-was nothing but dreariness left. He put his hoop away, and his bat;
-there was no joy in them any more. His aunt was concerned. She began to
-try all manner of remedies on him. She was one of those people who are
-infatuated with patent medicines and all new-fangled methods of
-producing health or mending it. She was an inveterate experimenter in
-these things. When something fresh in this line came out she was in a
-fever, right away, to try it; not on herself, for she was never ailing,
-but on anybody else that came handy. She was a subscriber for all the
-"Health" periodicals and phrenological frauds; and the solemn ignorance
-they were inflated with was breath to her nostrils. All the "rot" they
-contained about ventilation, and how to go to bed, and how to get up,
-and what to eat, and what to drink, and how much exercise to take, and
-what frame of mind to keep one's self in, and what sort of clothing to
-wear, was all gospel to her, and she never observed that her
-health-journals of the current month customarily upset everything they
-had recommended the month before. She was as simple-hearted and honest
-as the day was long, and so she was an easy victim. She gathered
-together her quack periodicals and her quack medicines, and thus armed
-with death, went about on her pale horse, metaphorically speaking, with
-"hell following after." But she never suspected that she was not an
-angel of healing and the balm of Gilead in disguise, to the suffering
-neighbors.
-
-The water treatment was new, now, and Tom's low condition was a
-windfall to her. She had him out at daylight every morning, stood him
-up in the woodshed and drowned him with a deluge of cold water; then
-she scrubbed him down with a towel like a file, and so brought him to;
-then she rolled him up in a wet sheet and put him away under blankets
-till she sweated his soul clean and "the yellow stains of it came
-through his pores"--as Tom said.
-
-Yet notwithstanding all this, the boy grew more and more melancholy
-and pale and dejected. She added hot baths, sitz baths, shower baths,
-and plunges. The boy remained as dismal as a hearse. She began to
-assist the water with a slim oatmeal diet and blister-plasters. She
-calculated his capacity as she would a jug's, and filled him up every
-day with quack cure-alls.
-
-Tom had become indifferent to persecution by this time. This phase
-filled the old lady's heart with consternation. This indifference must
-be broken up at any cost. Now she heard of Pain-killer for the first
-time. She ordered a lot at once. She tasted it and was filled with
-gratitude. It was simply fire in a liquid form. She dropped the water
-treatment and everything else, and pinned her faith to Pain-killer. She
-gave Tom a teaspoonful and watched with the deepest anxiety for the
-result. Her troubles were instantly at rest, her soul at peace again;
-for the "indifference" was broken up. The boy could not have shown a
-wilder, heartier interest, if she had built a fire under him.
-
-Tom felt that it was time to wake up; this sort of life might be
-romantic enough, in his blighted condition, but it was getting to have
-too little sentiment and too much distracting variety about it. So he
-thought over various plans for relief, and finally hit pon that of
-professing to be fond of Pain-killer. He asked for it so often that he
-became a nuisance, and his aunt ended by telling him to help himself
-and quit bothering her. If it had been Sid, she would have had no
-misgivings to alloy her delight; but since it was Tom, she watched the
-bottle clandestinely. She found that the medicine did really diminish,
-but it did not occur to her that the boy was mending the health of a
-crack in the sitting-room floor with it.
-
-One day Tom was in the act of dosing the crack when his aunt's yellow
-cat came along, purring, eying the teaspoon avariciously, and begging
-for a taste. Tom said:
-
-"Don't ask for it unless you want it, Peter."
-
-But Peter signified that he did want it.
-
-"You better make sure."
-
-Peter was sure.
-
-"Now you've asked for it, and I'll give it to you, because there ain't
-anything mean about me; but if you find you don't like it, you mustn't
-blame anybody but your own self."
-
-Peter was agreeable. So Tom pried his mouth open and poured down the
-Pain-killer. Peter sprang a couple of yards in the air, and then
-delivered a war-whoop and set off round and round the room, banging
-against furniture, upsetting flower-pots, and making general havoc.
-Next he rose on his hind feet and pranced around, in a frenzy of
-enjoyment, with his head over his shoulder and his voice proclaiming
-his unappeasable happiness. Then he went tearing around the house again
-spreading chaos and destruction in his path. Aunt Polly entered in time
-to see him throw a few double summersets, deliver a final mighty
-hurrah, and sail through the open window, carrying the rest of the
-flower-pots with him. The old lady stood petrified with astonishment,
-peering over her glasses; Tom lay on the floor expiring with laughter.
-
-"Tom, what on earth ails that cat?"
-
-"I don't know, aunt," gasped the boy.
-
-"Why, I never see anything like it. What did make him act so?"
-
-"Deed I don't know, Aunt Polly; cats always act so when they're having
-a good time."
-
-"They do, do they?" There was something in the tone that made Tom
-apprehensive.
-
-"Yes'm. That is, I believe they do."
-
-"You DO?"
-
-"Yes'm."
-
-The old lady was bending down, Tom watching, with interest emphasized
-by anxiety. Too late he divined her "drift." The handle of the telltale
-teaspoon was visible under the bed-valance. Aunt Polly took it, held it
-up. Tom winced, and dropped his eyes. Aunt Polly raised him by the
-usual handle--his ear--and cracked his head soundly with her thimble.
-
-"Now, sir, what did you want to treat that poor dumb beast so, for?"
-
-"I done it out of pity for him--because he hadn't any aunt."
-
-"Hadn't any aunt!--you numskull. What has that got to do with it?"
-
-"Heaps. Because if he'd had one she'd a burnt him out herself! She'd a
-roasted his bowels out of him 'thout any more feeling than if he was a
-human!"
-
-Aunt Polly felt a sudden pang of remorse. This was putting the thing
-in a new light; what was cruelty to a cat MIGHT be cruelty to a boy,
-too. She began to soften; she felt sorry. Her eyes watered a little,
-and she put her hand on Tom's head and said gently:
-
-"I was meaning for the best, Tom. And, Tom, it DID do you good."
-
-Tom looked up in her face with just a perceptible twinkle peeping
-through his gravity.
-
-"I know you was meaning for the best, aunty, and so was I with Peter.
-It done HIM good, too. I never see him get around so since--"
-
-"Oh, go 'long with you, Tom, before you aggravate me again. And you
-try and see if you can't be a good boy, for once, and you needn't take
-any more medicine."
-
-Tom reached school ahead of time. It was noticed that this strange
-thing had been occurring every day latterly. And now, as usual of late,
-he hung about the gate of the schoolyard instead of playing with his
-comrades. He was sick, he said, and he looked it. He tried to seem to
-be looking everywhere but whither he really was looking--down the road.
-Presently Jeff Thatcher hove in sight, and Tom's face lighted; he gazed
-a moment, and then turned sorrowfully away. When Jeff arrived, Tom
-accosted him; and "led up" warily to opportunities for remark about
-Becky, but the giddy lad never could see the bait. Tom watched and
-watched, hoping whenever a frisking frock came in sight, and hating the
-owner of it as soon as he saw she was not the right one. At last frocks
-ceased to appear, and he dropped hopelessly into the dumps; he entered
-the empty schoolhouse and sat down to suffer. Then one more frock
-passed in at the gate, and Tom's heart gave a great bound. The next
-instant he was out, and "going on" like an Indian; yelling, laughing,
-chasing boys, jumping over the fence at risk of life and limb, throwing
-handsprings, standing on his head--doing all the heroic things he could
-conceive of, and keeping a furtive eye out, all the while, to see if
-Becky Thatcher was noticing. But she seemed to be unconscious of it
-all; she never looked. Could it be possible that she was not aware that
-he was there? He carried his exploits to her immediate vicinity; came
-war-whooping around, snatched a boy's cap, hurled it to the roof of the
-schoolhouse, broke through a group of boys, tumbling them in every
-direction, and fell sprawling, himself, under Becky's nose, almost
-upsetting her--and she turned, with her nose in the air, and he heard
-her say: "Mf! some people think they're mighty smart--always showing
-off!"
-
-Tom's cheeks burned. He gathered himself up and sneaked off, crushed
-and crestfallen.
-
-
-
-CHAPTER XIII
-
-TOM'S mind was made up now. He was gloomy and desperate. He was a
-forsaken, friendless boy, he said; nobody loved him; when they found
-out what they had driven him to, perhaps they would be sorry; he had
-tried to do right and get along, but they would not let him; since
-nothing would do them but to be rid of him, let it be so; and let them
-blame HIM for the consequences--why shouldn't they? What right had the
-friendless to complain? Yes, they had forced him to it at last: he
-would lead a life of crime. There was no choice.
-
-By this time he was far down Meadow Lane, and the bell for school to
-"take up" tinkled faintly upon his ear. He sobbed, now, to think he
-should never, never hear that old familiar sound any more--it was very
-hard, but it was forced on him; since he was driven out into the cold
-world, he must submit--but he forgave them. Then the sobs came thick
-and fast.
-
-Just at this point he met his soul's sworn comrade, Joe Harper
---hard-eyed, and with evidently a great and dismal purpose in his heart.
-Plainly here were "two souls with but a single thought." Tom, wiping
-his eyes with his sleeve, began to blubber out something about a
-resolution to escape from hard usage and lack of sympathy at home by
-roaming abroad into the great world never to return; and ended by
-hoping that Joe would not forget him.
-
-But it transpired that this was a request which Joe had just been
-going to make of Tom, and had come to hunt him up for that purpose. His
-mother had whipped him for drinking some cream which he had never
-tasted and knew nothing about; it was plain that she was tired of him
-and wished him to go; if she felt that way, there was nothing for him
-to do but succumb; he hoped she would be happy, and never regret having
-driven her poor boy out into the unfeeling world to suffer and die.
-
-As the two boys walked sorrowing along, they made a new compact to
-stand by each other and be brothers and never separate till death
-relieved them of their troubles. Then they began to lay their plans.
-Joe was for being a hermit, and living on crusts in a remote cave, and
-dying, some time, of cold and want and grief; but after listening to
-Tom, he conceded that there were some conspicuous advantages about a
-life of crime, and so he consented to be a pirate.
-
-Three miles below St. Petersburg, at a point where the Mississippi
-River was a trifle over a mile wide, there was a long, narrow, wooded
-island, with a shallow bar at the head of it, and this offered well as
-a rendezvous. It was not inhabited; it lay far over toward the further
-shore, abreast a dense and almost wholly unpeopled forest. So Jackson's
-Island was chosen. Who were to be the subjects of their piracies was a
-matter that did not occur to them. Then they hunted up Huckleberry
-Finn, and he joined them promptly, for all careers were one to him; he
-was indifferent. They presently separated to meet at a lonely spot on
-the river-bank two miles above the village at the favorite hour--which
-was midnight. There was a small log raft there which they meant to
-capture. Each would bring hooks and lines, and such provision as he
-could steal in the most dark and mysterious way--as became outlaws. And
-before the afternoon was done, they had all managed to enjoy the sweet
-glory of spreading the fact that pretty soon the town would "hear
-something." All who got this vague hint were cautioned to "be mum and
-wait."
-
-About midnight Tom arrived with a boiled ham and a few trifles,
-and stopped in a dense undergrowth on a small bluff overlooking the
-meeting-place. It was starlight, and very still. The mighty river lay
-like an ocean at rest. Tom listened a moment, but no sound disturbed the
-quiet. Then he gave a low, distinct whistle. It was answered from under
-the bluff. Tom whistled twice more; these signals were answered in the
-same way. Then a guarded voice said:
-
-"Who goes there?"
-
-"Tom Sawyer, the Black Avenger of the Spanish Main. Name your names."
-
-"Huck Finn the Red-Handed, and Joe Harper the Terror of the Seas." Tom
-had furnished these titles, from his favorite literature.
-
-"'Tis well. Give the countersign."
-
-Two hoarse whispers delivered the same awful word simultaneously to
-the brooding night:
-
-"BLOOD!"
-
-Then Tom tumbled his ham over the bluff and let himself down after it,
-tearing both skin and clothes to some extent in the effort. There was
-an easy, comfortable path along the shore under the bluff, but it
-lacked the advantages of difficulty and danger so valued by a pirate.
-
-The Terror of the Seas had brought a side of bacon, and had about worn
-himself out with getting it there. Finn the Red-Handed had stolen a
-skillet and a quantity of half-cured leaf tobacco, and had also brought
-a few corn-cobs to make pipes with. But none of the pirates smoked or
-"chewed" but himself. The Black Avenger of the Spanish Main said it
-would never do to start without some fire. That was a wise thought;
-matches were hardly known there in that day. They saw a fire
-smouldering upon a great raft a hundred yards above, and they went
-stealthily thither and helped themselves to a chunk. They made an
-imposing adventure of it, saying, "Hist!" every now and then, and
-suddenly halting with finger on lip; moving with hands on imaginary
-dagger-hilts; and giving orders in dismal whispers that if "the foe"
-stirred, to "let him have it to the hilt," because "dead men tell no
-tales." They knew well enough that the raftsmen were all down at the
-village laying in stores or having a spree, but still that was no
-excuse for their conducting this thing in an unpiratical way.
-
-They shoved off, presently, Tom in command, Huck at the after oar and
-Joe at the forward. Tom stood amidships, gloomy-browed, and with folded
-arms, and gave his orders in a low, stern whisper:
-
-"Luff, and bring her to the wind!"
-
-"Aye-aye, sir!"
-
-"Steady, steady-y-y-y!"
-
-"Steady it is, sir!"
-
-"Let her go off a point!"
-
-"Point it is, sir!"
-
-As the boys steadily and monotonously drove the raft toward mid-stream
-it was no doubt understood that these orders were given only for
-"style," and were not intended to mean anything in particular.
-
-"What sail's she carrying?"
-
-"Courses, tops'ls, and flying-jib, sir."
-
-"Send the r'yals up! Lay out aloft, there, half a dozen of ye
---foretopmaststuns'l! Lively, now!"
-
-"Aye-aye, sir!"
-
-"Shake out that maintogalans'l! Sheets and braces! NOW my hearties!"
-
-"Aye-aye, sir!"
-
-"Hellum-a-lee--hard a port! Stand by to meet her when she comes! Port,
-port! NOW, men! With a will! Stead-y-y-y!"
-
-"Steady it is, sir!"
-
-The raft drew beyond the middle of the river; the boys pointed her
-head right, and then lay on their oars. The river was not high, so
-there was not more than a two or three mile current. Hardly a word was
-said during the next three-quarters of an hour. Now the raft was
-passing before the distant town. Two or three glimmering lights showed
-where it lay, peacefully sleeping, beyond the vague vast sweep of
-star-gemmed water, unconscious of the tremendous event that was happening.
-The Black Avenger stood still with folded arms, "looking his last" upon
-the scene of his former joys and his later sufferings, and wishing
-"she" could see him now, abroad on the wild sea, facing peril and death
-with dauntless heart, going to his doom with a grim smile on his lips.
-It was but a small strain on his imagination to remove Jackson's Island
-beyond eyeshot of the village, and so he "looked his last" with a
-broken and satisfied heart. The other pirates were looking their last,
-too; and they all looked so long that they came near letting the
-current drift them out of the range of the island. But they discovered
-the danger in time, and made shift to avert it. About two o'clock in
-the morning the raft grounded on the bar two hundred yards above the
-head of the island, and they waded back and forth until they had landed
-their freight. Part of the little raft's belongings consisted of an old
-sail, and this they spread over a nook in the bushes for a tent to
-shelter their provisions; but they themselves would sleep in the open
-air in good weather, as became outlaws.
-
-They built a fire against the side of a great log twenty or thirty
-steps within the sombre depths of the forest, and then cooked some
-bacon in the frying-pan for supper, and used up half of the corn "pone"
-stock they had brought. It seemed glorious sport to be feasting in that
-wild, free way in the virgin forest of an unexplored and uninhabited
-island, far from the haunts of men, and they said they never would
-return to civilization. The climbing fire lit up their faces and threw
-its ruddy glare upon the pillared tree-trunks of their forest temple,
-and upon the varnished foliage and festooning vines.
-
-When the last crisp slice of bacon was gone, and the last allowance of
-corn pone devoured, the boys stretched themselves out on the grass,
-filled with contentment. They could have found a cooler place, but they
-would not deny themselves such a romantic feature as the roasting
-camp-fire.
-
-"AIN'T it gay?" said Joe.
-
-"It's NUTS!" said Tom. "What would the boys say if they could see us?"
-
-"Say? Well, they'd just die to be here--hey, Hucky!"
-
-"I reckon so," said Huckleberry; "anyways, I'm suited. I don't want
-nothing better'n this. I don't ever get enough to eat, gen'ally--and
-here they can't come and pick at a feller and bullyrag him so."
-
-"It's just the life for me," said Tom. "You don't have to get up,
-mornings, and you don't have to go to school, and wash, and all that
-blame foolishness. You see a pirate don't have to do ANYTHING, Joe,
-when he's ashore, but a hermit HE has to be praying considerable, and
-then he don't have any fun, anyway, all by himself that way."
-
-"Oh yes, that's so," said Joe, "but I hadn't thought much about it,
-you know. I'd a good deal rather be a pirate, now that I've tried it."
-
-"You see," said Tom, "people don't go much on hermits, nowadays, like
-they used to in old times, but a pirate's always respected. And a
-hermit's got to sleep on the hardest place he can find, and put
-sackcloth and ashes on his head, and stand out in the rain, and--"
-
-"What does he put sackcloth and ashes on his head for?" inquired Huck.
-
-"I dono. But they've GOT to do it. Hermits always do. You'd have to do
-that if you was a hermit."
-
-"Dern'd if I would," said Huck.
-
-"Well, what would you do?"
-
-"I dono. But I wouldn't do that."
-
-"Why, Huck, you'd HAVE to. How'd you get around it?"
-
-"Why, I just wouldn't stand it. I'd run away."
-
-"Run away! Well, you WOULD be a nice old slouch of a hermit. You'd be
-a disgrace."
-
-The Red-Handed made no response, being better employed. He had
-finished gouging out a cob, and now he fitted a weed stem to it, loaded
-it with tobacco, and was pressing a coal to the charge and blowing a
-cloud of fragrant smoke--he was in the full bloom of luxurious
-contentment. The other pirates envied him this majestic vice, and
-secretly resolved to acquire it shortly. Presently Huck said:
-
-"What does pirates have to do?"
-
-Tom said:
-
-"Oh, they have just a bully time--take ships and burn them, and get
-the money and bury it in awful places in their island where there's
-ghosts and things to watch it, and kill everybody in the ships--make
-'em walk a plank."
-
-"And they carry the women to the island," said Joe; "they don't kill
-the women."
-
-"No," assented Tom, "they don't kill the women--they're too noble. And
-the women's always beautiful, too.
-
-"And don't they wear the bulliest clothes! Oh no! All gold and silver
-and di'monds," said Joe, with enthusiasm.
-
-"Who?" said Huck.
-
-"Why, the pirates."
-
-Huck scanned his own clothing forlornly.
-
-"I reckon I ain't dressed fitten for a pirate," said he, with a
-regretful pathos in his voice; "but I ain't got none but these."
-
-But the other boys told him the fine clothes would come fast enough,
-after they should have begun their adventures. They made him understand
-that his poor rags would do to begin with, though it was customary for
-wealthy pirates to start with a proper wardrobe.
-
-Gradually their talk died out and drowsiness began to steal upon the
-eyelids of the little waifs. The pipe dropped from the fingers of the
-Red-Handed, and he slept the sleep of the conscience-free and the
-weary. The Terror of the Seas and the Black Avenger of the Spanish Main
-had more difficulty in getting to sleep. They said their prayers
-inwardly, and lying down, since there was nobody there with authority
-to make them kneel and recite aloud; in truth, they had a mind not to
-say them at all, but they were afraid to proceed to such lengths as
-that, lest they might call down a sudden and special thunderbolt from
-heaven. Then at once they reached and hovered upon the imminent verge
-of sleep--but an intruder came, now, that would not "down." It was
-conscience. They began to feel a vague fear that they had been doing
-wrong to run away; and next they thought of the stolen meat, and then
-the real torture came. They tried to argue it away by reminding
-conscience that they had purloined sweetmeats and apples scores of
-times; but conscience was not to be appeased by such thin
-plausibilities; it seemed to them, in the end, that there was no
-getting around the stubborn fact that taking sweetmeats was only
-"hooking," while taking bacon and hams and such valuables was plain
-simple stealing--and there was a command against that in the Bible. So
-they inwardly resolved that so long as they remained in the business,
-their piracies should not again be sullied with the crime of stealing.
-Then conscience granted a truce, and these curiously inconsistent
-pirates fell peacefully to sleep.
-
-
-
-CHAPTER XIV
-
-WHEN Tom awoke in the morning, he wondered where he was. He sat up and
-rubbed his eyes and looked around. Then he comprehended. It was the
-cool gray dawn, and there was a delicious sense of repose and peace in
-the deep pervading calm and silence of the woods. Not a leaf stirred;
-not a sound obtruded upon great Nature's meditation. Beaded dewdrops
-stood upon the leaves and grasses. A white layer of ashes covered the
-fire, and a thin blue breath of smoke rose straight into the air. Joe
-and Huck still slept.
-
-Now, far away in the woods a bird called; another answered; presently
-the hammering of a woodpecker was heard. Gradually the cool dim gray of
-the morning whitened, and as gradually sounds multiplied and life
-manifested itself. The marvel of Nature shaking off sleep and going to
-work unfolded itself to the musing boy. A little green worm came
-crawling over a dewy leaf, lifting two-thirds of his body into the air
-from time to time and "sniffing around," then proceeding again--for he
-was measuring, Tom said; and when the worm approached him, of its own
-accord, he sat as still as a stone, with his hopes rising and falling,
-by turns, as the creature still came toward him or seemed inclined to
-go elsewhere; and when at last it considered a painful moment with its
-curved body in the air and then came decisively down upon Tom's leg and
-began a journey over him, his whole heart was glad--for that meant that
-he was going to have a new suit of clothes--without the shadow of a
-doubt a gaudy piratical uniform. Now a procession of ants appeared,
-from nowhere in particular, and went about their labors; one struggled
-manfully by with a dead spider five times as big as itself in its arms,
-and lugged it straight up a tree-trunk. A brown spotted lady-bug
-climbed the dizzy height of a grass blade, and Tom bent down close to
-it and said, "Lady-bug, lady-bug, fly away home, your house is on fire,
-your children's alone," and she took wing and went off to see about it
---which did not surprise the boy, for he knew of old that this insect was
-credulous about conflagrations, and he had practised upon its
-simplicity more than once. A tumblebug came next, heaving sturdily at
-its ball, and Tom touched the creature, to see it shut its legs against
-its body and pretend to be dead. The birds were fairly rioting by this
-time. A catbird, the Northern mocker, lit in a tree over Tom's head,
-and trilled out her imitations of her neighbors in a rapture of
-enjoyment; then a shrill jay swept down, a flash of blue flame, and
-stopped on a twig almost within the boy's reach, cocked his head to one
-side and eyed the strangers with a consuming curiosity; a gray squirrel
-and a big fellow of the "fox" kind came skurrying along, sitting up at
-intervals to inspect and chatter at the boys, for the wild things had
-probably never seen a human being before and scarcely knew whether to
-be afraid or not. All Nature was wide awake and stirring, now; long
-lances of sunlight pierced down through the dense foliage far and near,
-and a few butterflies came fluttering upon the scene.
-
-Tom stirred up the other pirates and they all clattered away with a
-shout, and in a minute or two were stripped and chasing after and
-tumbling over each other in the shallow limpid water of the white
-sandbar. They felt no longing for the little village sleeping in the
-distance beyond the majestic waste of water. A vagrant current or a
-slight rise in the river had carried off their raft, but this only
-gratified them, since its going was something like burning the bridge
-between them and civilization.
-
-They came back to camp wonderfully refreshed, glad-hearted, and
-ravenous; and they soon had the camp-fire blazing up again. Huck found
-a spring of clear cold water close by, and the boys made cups of broad
-oak or hickory leaves, and felt that water, sweetened with such a
-wildwood charm as that, would be a good enough substitute for coffee.
-While Joe was slicing bacon for breakfast, Tom and Huck asked him to
-hold on a minute; they stepped to a promising nook in the river-bank
-and threw in their lines; almost immediately they had reward. Joe had
-not had time to get impatient before they were back again with some
-handsome bass, a couple of sun-perch and a small catfish--provisions
-enough for quite a family. They fried the fish with the bacon, and were
-astonished; for no fish had ever seemed so delicious before. They did
-not know that the quicker a fresh-water fish is on the fire after he is
-caught the better he is; and they reflected little upon what a sauce
-open-air sleeping, open-air exercise, bathing, and a large ingredient
-of hunger make, too.
-
-They lay around in the shade, after breakfast, while Huck had a smoke,
-and then went off through the woods on an exploring expedition. They
-tramped gayly along, over decaying logs, through tangled underbrush,
-among solemn monarchs of the forest, hung from their crowns to the
-ground with a drooping regalia of grape-vines. Now and then they came
-upon snug nooks carpeted with grass and jeweled with flowers.
-
-They found plenty of things to be delighted with, but nothing to be
-astonished at. They discovered that the island was about three miles
-long and a quarter of a mile wide, and that the shore it lay closest to
-was only separated from it by a narrow channel hardly two hundred yards
-wide. They took a swim about every hour, so it was close upon the
-middle of the afternoon when they got back to camp. They were too
-hungry to stop to fish, but they fared sumptuously upon cold ham, and
-then threw themselves down in the shade to talk. But the talk soon
-began to drag, and then died. The stillness, the solemnity that brooded
-in the woods, and the sense of loneliness, began to tell upon the
-spirits of the boys. They fell to thinking. A sort of undefined longing
-crept upon them. This took dim shape, presently--it was budding
-homesickness. Even Finn the Red-Handed was dreaming of his doorsteps
-and empty hogsheads. But they were all ashamed of their weakness, and
-none was brave enough to speak his thought.
-
-For some time, now, the boys had been dully conscious of a peculiar
-sound in the distance, just as one sometimes is of the ticking of a
-clock which he takes no distinct note of. But now this mysterious sound
-became more pronounced, and forced a recognition. The boys started,
-glanced at each other, and then each assumed a listening attitude.
-There was a long silence, profound and unbroken; then a deep, sullen
-boom came floating down out of the distance.
-
-"What is it!" exclaimed Joe, under his breath.
-
-"I wonder," said Tom in a whisper.
-
-"'Tain't thunder," said Huckleberry, in an awed tone, "becuz thunder--"
-
-"Hark!" said Tom. "Listen--don't talk."
-
-They waited a time that seemed an age, and then the same muffled boom
-troubled the solemn hush.
-
-"Let's go and see."
-
-They sprang to their feet and hurried to the shore toward the town.
-They parted the bushes on the bank and peered out over the water. The
-little steam ferryboat was about a mile below the village, drifting
-with the current. Her broad deck seemed crowded with people. There were
-a great many skiffs rowing about or floating with the stream in the
-neighborhood of the ferryboat, but the boys could not determine what
-the men in them were doing. Presently a great jet of white smoke burst
-from the ferryboat's side, and as it expanded and rose in a lazy cloud,
-that same dull throb of sound was borne to the listeners again.
-
-"I know now!" exclaimed Tom; "somebody's drownded!"
-
-"That's it!" said Huck; "they done that last summer, when Bill Turner
-got drownded; they shoot a cannon over the water, and that makes him
-come up to the top. Yes, and they take loaves of bread and put
-quicksilver in 'em and set 'em afloat, and wherever there's anybody
-that's drownded, they'll float right there and stop."
-
-"Yes, I've heard about that," said Joe. "I wonder what makes the bread
-do that."
-
-"Oh, it ain't the bread, so much," said Tom; "I reckon it's mostly
-what they SAY over it before they start it out."
-
-"But they don't say anything over it," said Huck. "I've seen 'em and
-they don't."
-
-"Well, that's funny," said Tom. "But maybe they say it to themselves.
-Of COURSE they do. Anybody might know that."
-
-The other boys agreed that there was reason in what Tom said, because
-an ignorant lump of bread, uninstructed by an incantation, could not be
-expected to act very intelligently when set upon an errand of such
-gravity.
-
-"By jings, I wish I was over there, now," said Joe.
-
-"I do too" said Huck "I'd give heaps to know who it is."
-
-The boys still listened and watched. Presently a revealing thought
-flashed through Tom's mind, and he exclaimed:
-
-"Boys, I know who's drownded--it's us!"
-
-They felt like heroes in an instant. Here was a gorgeous triumph; they
-were missed; they were mourned; hearts were breaking on their account;
-tears were being shed; accusing memories of unkindness to these poor
-lost lads were rising up, and unavailing regrets and remorse were being
-indulged; and best of all, the departed were the talk of the whole
-town, and the envy of all the boys, as far as this dazzling notoriety
-was concerned. This was fine. It was worth while to be a pirate, after
-all.
-
-As twilight drew on, the ferryboat went back to her accustomed
-business and the skiffs disappeared. The pirates returned to camp. They
-were jubilant with vanity over their new grandeur and the illustrious
-trouble they were making. They caught fish, cooked supper and ate it,
-and then fell to guessing at what the village was thinking and saying
-about them; and the pictures they drew of the public distress on their
-account were gratifying to look upon--from their point of view. But
-when the shadows of night closed them in, they gradually ceased to
-talk, and sat gazing into the fire, with their minds evidently
-wandering elsewhere. The excitement was gone, now, and Tom and Joe
-could not keep back thoughts of certain persons at home who were not
-enjoying this fine frolic as much as they were. Misgivings came; they
-grew troubled and unhappy; a sigh or two escaped, unawares. By and by
-Joe timidly ventured upon a roundabout "feeler" as to how the others
-might look upon a return to civilization--not right now, but--
-
-Tom withered him with derision! Huck, being uncommitted as yet, joined
-in with Tom, and the waverer quickly "explained," and was glad to get
-out of the scrape with as little taint of chicken-hearted homesickness
-clinging to his garments as he could. Mutiny was effectually laid to
-rest for the moment.
-
-As the night deepened, Huck began to nod, and presently to snore. Joe
-followed next. Tom lay upon his elbow motionless, for some time,
-watching the two intently. At last he got up cautiously, on his knees,
-and went searching among the grass and the flickering reflections flung
-by the camp-fire. He picked up and inspected several large
-semi-cylinders of the thin white bark of a sycamore, and finally chose
-two which seemed to suit him. Then he knelt by the fire and painfully
-wrote something upon each of these with his "red keel"; one he rolled up
-and put in his jacket pocket, and the other he put in Joe's hat and
-removed it to a little distance from the owner. And he also put into the
-hat certain schoolboy treasures of almost inestimable value--among them
-a lump of chalk, an India-rubber ball, three fishhooks, and one of that
-kind of marbles known as a "sure 'nough crystal." Then he tiptoed his
-way cautiously among the trees till he felt that he was out of hearing,
-and straightway broke into a keen run in the direction of the sandbar.
-
-
-
-CHAPTER XV
-
-A FEW minutes later Tom was in the shoal water of the bar, wading
-toward the Illinois shore. Before the depth reached his middle he was
-half-way over; the current would permit no more wading, now, so he
-struck out confidently to swim the remaining hundred yards. He swam
-quartering upstream, but still was swept downward rather faster than he
-had expected. However, he reached the shore finally, and drifted along
-till he found a low place and drew himself out. He put his hand on his
-jacket pocket, found his piece of bark safe, and then struck through
-the woods, following the shore, with streaming garments. Shortly before
-ten o'clock he came out into an open place opposite the village, and
-saw the ferryboat lying in the shadow of the trees and the high bank.
-Everything was quiet under the blinking stars. He crept down the bank,
-watching with all his eyes, slipped into the water, swam three or four
-strokes and climbed into the skiff that did "yawl" duty at the boat's
-stern. He laid himself down under the thwarts and waited, panting.
-
-Presently the cracked bell tapped and a voice gave the order to "cast
-off." A minute or two later the skiff's head was standing high up,
-against the boat's swell, and the voyage was begun. Tom felt happy in
-his success, for he knew it was the boat's last trip for the night. At
-the end of a long twelve or fifteen minutes the wheels stopped, and Tom
-slipped overboard and swam ashore in the dusk, landing fifty yards
-downstream, out of danger of possible stragglers.
-
-He flew along unfrequented alleys, and shortly found himself at his
-aunt's back fence. He climbed over, approached the "ell," and looked in
-at the sitting-room window, for a light was burning there. There sat
-Aunt Polly, Sid, Mary, and Joe Harper's mother, grouped together,
-talking. They were by the bed, and the bed was between them and the
-door. Tom went to the door and began to softly lift the latch; then he
-pressed gently and the door yielded a crack; he continued pushing
-cautiously, and quaking every time it creaked, till he judged he might
-squeeze through on his knees; so he put his head through and began,
-warily.
-
-"What makes the candle blow so?" said Aunt Polly. Tom hurried up.
-"Why, that door's open, I believe. Why, of course it is. No end of
-strange things now. Go 'long and shut it, Sid."
-
-Tom disappeared under the bed just in time. He lay and "breathed"
-himself for a time, and then crept to where he could almost touch his
-aunt's foot.
-
-"But as I was saying," said Aunt Polly, "he warn't BAD, so to say
---only mischEEvous. Only just giddy, and harum-scarum, you know. He
-warn't any more responsible than a colt. HE never meant any harm, and
-he was the best-hearted boy that ever was"--and she began to cry.
-
-"It was just so with my Joe--always full of his devilment, and up to
-every kind of mischief, but he was just as unselfish and kind as he
-could be--and laws bless me, to think I went and whipped him for taking
-that cream, never once recollecting that I throwed it out myself
-because it was sour, and I never to see him again in this world, never,
-never, never, poor abused boy!" And Mrs. Harper sobbed as if her heart
-would break.
-
-"I hope Tom's better off where he is," said Sid, "but if he'd been
-better in some ways--"
-
-"SID!" Tom felt the glare of the old lady's eye, though he could not
-see it. "Not a word against my Tom, now that he's gone! God'll take
-care of HIM--never you trouble YOURself, sir! Oh, Mrs. Harper, I don't
-know how to give him up! I don't know how to give him up! He was such a
-comfort to me, although he tormented my old heart out of me, 'most."
-
-"The Lord giveth and the Lord hath taken away--Blessed be the name of
-the Lord! But it's so hard--Oh, it's so hard! Only last Saturday my
-Joe busted a firecracker right under my nose and I knocked him
-sprawling. Little did I know then, how soon--Oh, if it was to do over
-again I'd hug him and bless him for it."
-
-"Yes, yes, yes, I know just how you feel, Mrs. Harper, I know just
-exactly how you feel. No longer ago than yesterday noon, my Tom took
-and filled the cat full of Pain-killer, and I did think the cretur
-would tear the house down. And God forgive me, I cracked Tom's head
-with my thimble, poor boy, poor dead boy. But he's out of all his
-troubles now. And the last words I ever heard him say was to reproach--"
-
-But this memory was too much for the old lady, and she broke entirely
-down. Tom was snuffling, now, himself--and more in pity of himself than
-anybody else. He could hear Mary crying, and putting in a kindly word
-for him from time to time. He began to have a nobler opinion of himself
-than ever before. Still, he was sufficiently touched by his aunt's
-grief to long to rush out from under the bed and overwhelm her with
-joy--and the theatrical gorgeousness of the thing appealed strongly to
-his nature, too, but he resisted and lay still.
-
-He went on listening, and gathered by odds and ends that it was
-conjectured at first that the boys had got drowned while taking a swim;
-then the small raft had been missed; next, certain boys said the
-missing lads had promised that the village should "hear something"
-soon; the wise-heads had "put this and that together" and decided that
-the lads had gone off on that raft and would turn up at the next town
-below, presently; but toward noon the raft had been found, lodged
-against the Missouri shore some five or six miles below the village
---and then hope perished; they must be drowned, else hunger would have
-driven them home by nightfall if not sooner. It was believed that the
-search for the bodies had been a fruitless effort merely because the
-drowning must have occurred in mid-channel, since the boys, being good
-swimmers, would otherwise have escaped to shore. This was Wednesday
-night. If the bodies continued missing until Sunday, all hope would be
-given over, and the funerals would be preached on that morning. Tom
-shuddered.
-
-Mrs. Harper gave a sobbing good-night and turned to go. Then with a
-mutual impulse the two bereaved women flung themselves into each
-other's arms and had a good, consoling cry, and then parted. Aunt Polly
-was tender far beyond her wont, in her good-night to Sid and Mary. Sid
-snuffled a bit and Mary went off crying with all her heart.
-
-Aunt Polly knelt down and prayed for Tom so touchingly, so
-appealingly, and with such measureless love in her words and her old
-trembling voice, that he was weltering in tears again, long before she
-was through.
-
-He had to keep still long after she went to bed, for she kept making
-broken-hearted ejaculations from time to time, tossing unrestfully, and
-turning over. But at last she was still, only moaning a little in her
-sleep. Now the boy stole out, rose gradually by the bedside, shaded the
-candle-light with his hand, and stood regarding her. His heart was full
-of pity for her. He took out his sycamore scroll and placed it by the
-candle. But something occurred to him, and he lingered considering. His
-face lighted with a happy solution of his thought; he put the bark
-hastily in his pocket. Then he bent over and kissed the faded lips, and
-straightway made his stealthy exit, latching the door behind him.
-
-He threaded his way back to the ferry landing, found nobody at large
-there, and walked boldly on board the boat, for he knew she was
-tenantless except that there was a watchman, who always turned in and
-slept like a graven image. He untied the skiff at the stern, slipped
-into it, and was soon rowing cautiously upstream. When he had pulled a
-mile above the village, he started quartering across and bent himself
-stoutly to his work. He hit the landing on the other side neatly, for
-this was a familiar bit of work to him. He was moved to capture the
-skiff, arguing that it might be considered a ship and therefore
-legitimate prey for a pirate, but he knew a thorough search would be
-made for it and that might end in revelations. So he stepped ashore and
-entered the woods.
-
-He sat down and took a long rest, torturing himself meanwhile to keep
-awake, and then started warily down the home-stretch. The night was far
-spent. It was broad daylight before he found himself fairly abreast the
-island bar. He rested again until the sun was well up and gilding the
-great river with its splendor, and then he plunged into the stream. A
-little later he paused, dripping, upon the threshold of the camp, and
-heard Joe say:
-
-"No, Tom's true-blue, Huck, and he'll come back. He won't desert. He
-knows that would be a disgrace to a pirate, and Tom's too proud for
-that sort of thing. He's up to something or other. Now I wonder what?"
-
-"Well, the things is ours, anyway, ain't they?"
-
-"Pretty near, but not yet, Huck. The writing says they are if he ain't
-back here to breakfast."
-
-"Which he is!" exclaimed Tom, with fine dramatic effect, stepping
-grandly into camp.
-
-A sumptuous breakfast of bacon and fish was shortly provided, and as
-the boys set to work upon it, Tom recounted (and adorned) his
-adventures. They were a vain and boastful company of heroes when the
-tale was done. Then Tom hid himself away in a shady nook to sleep till
-noon, and the other pirates got ready to fish and explore.
-
-
-
-CHAPTER XVI
-
-AFTER dinner all the gang turned out to hunt for turtle eggs on the
-bar. They went about poking sticks into the sand, and when they found a
-soft place they went down on their knees and dug with their hands.
-Sometimes they would take fifty or sixty eggs out of one hole. They
-were perfectly round white things a trifle smaller than an English
-walnut. They had a famous fried-egg feast that night, and another on
-Friday morning.
-
-After breakfast they went whooping and prancing out on the bar, and
-chased each other round and round, shedding clothes as they went, until
-they were naked, and then continued the frolic far away up the shoal
-water of the bar, against the stiff current, which latter tripped their
-legs from under them from time to time and greatly increased the fun.
-And now and then they stooped in a group and splashed water in each
-other's faces with their palms, gradually approaching each other, with
-averted faces to avoid the strangling sprays, and finally gripping and
-struggling till the best man ducked his neighbor, and then they all
-went under in a tangle of white legs and arms and came up blowing,
-sputtering, laughing, and gasping for breath at one and the same time.
-
-When they were well exhausted, they would run out and sprawl on the
-dry, hot sand, and lie there and cover themselves up with it, and by
-and by break for the water again and go through the original
-performance once more. Finally it occurred to them that their naked
-skin represented flesh-colored "tights" very fairly; so they drew a
-ring in the sand and had a circus--with three clowns in it, for none
-would yield this proudest post to his neighbor.
-
-Next they got their marbles and played "knucks" and "ring-taw" and
-"keeps" till that amusement grew stale. Then Joe and Huck had another
-swim, but Tom would not venture, because he found that in kicking off
-his trousers he had kicked his string of rattlesnake rattles off his
-ankle, and he wondered how he had escaped cramp so long without the
-protection of this mysterious charm. He did not venture again until he
-had found it, and by that time the other boys were tired and ready to
-rest. They gradually wandered apart, dropped into the "dumps," and fell
-to gazing longingly across the wide river to where the village lay
-drowsing in the sun. Tom found himself writing "BECKY" in the sand with
-his big toe; he scratched it out, and was angry with himself for his
-weakness. But he wrote it again, nevertheless; he could not help it. He
-erased it once more and then took himself out of temptation by driving
-the other boys together and joining them.
-
-But Joe's spirits had gone down almost beyond resurrection. He was so
-homesick that he could hardly endure the misery of it. The tears lay
-very near the surface. Huck was melancholy, too. Tom was downhearted,
-but tried hard not to show it. He had a secret which he was not ready
-to tell, yet, but if this mutinous depression was not broken up soon,
-he would have to bring it out. He said, with a great show of
-cheerfulness:
-
-"I bet there's been pirates on this island before, boys. We'll explore
-it again. They've hid treasures here somewhere. How'd you feel to light
-on a rotten chest full of gold and silver--hey?"
-
-But it roused only faint enthusiasm, which faded out, with no reply.
-Tom tried one or two other seductions; but they failed, too. It was
-discouraging work. Joe sat poking up the sand with a stick and looking
-very gloomy. Finally he said:
-
-"Oh, boys, let's give it up. I want to go home. It's so lonesome."
-
-"Oh no, Joe, you'll feel better by and by," said Tom. "Just think of
-the fishing that's here."
-
-"I don't care for fishing. I want to go home."
-
-"But, Joe, there ain't such another swimming-place anywhere."
-
-"Swimming's no good. I don't seem to care for it, somehow, when there
-ain't anybody to say I sha'n't go in. I mean to go home."
-
-"Oh, shucks! Baby! You want to see your mother, I reckon."
-
-"Yes, I DO want to see my mother--and you would, too, if you had one.
-I ain't any more baby than you are." And Joe snuffled a little.
-
-"Well, we'll let the cry-baby go home to his mother, won't we, Huck?
-Poor thing--does it want to see its mother? And so it shall. You like
-it here, don't you, Huck? We'll stay, won't we?"
-
-Huck said, "Y-e-s"--without any heart in it.
-
-"I'll never speak to you again as long as I live," said Joe, rising.
-"There now!" And he moved moodily away and began to dress himself.
-
-"Who cares!" said Tom. "Nobody wants you to. Go 'long home and get
-laughed at. Oh, you're a nice pirate. Huck and me ain't cry-babies.
-We'll stay, won't we, Huck? Let him go if he wants to. I reckon we can
-get along without him, per'aps."
-
-But Tom was uneasy, nevertheless, and was alarmed to see Joe go
-sullenly on with his dressing. And then it was discomforting to see
-Huck eying Joe's preparations so wistfully, and keeping up such an
-ominous silence. Presently, without a parting word, Joe began to wade
-off toward the Illinois shore. Tom's heart began to sink. He glanced at
-Huck. Huck could not bear the look, and dropped his eyes. Then he said:
-
-"I want to go, too, Tom. It was getting so lonesome anyway, and now
-it'll be worse. Let's us go, too, Tom."
-
-"I won't! You can all go, if you want to. I mean to stay."
-
-"Tom, I better go."
-
-"Well, go 'long--who's hendering you."
-
-Huck began to pick up his scattered clothes. He said:
-
-"Tom, I wisht you'd come, too. Now you think it over. We'll wait for
-you when we get to shore."
-
-"Well, you'll wait a blame long time, that's all."
-
-Huck started sorrowfully away, and Tom stood looking after him, with a
-strong desire tugging at his heart to yield his pride and go along too.
-He hoped the boys would stop, but they still waded slowly on. It
-suddenly dawned on Tom that it was become very lonely and still. He
-made one final struggle with his pride, and then darted after his
-comrades, yelling:
-
-"Wait! Wait! I want to tell you something!"
-
-They presently stopped and turned around. When he got to where they
-were, he began unfolding his secret, and they listened moodily till at
-last they saw the "point" he was driving at, and then they set up a
-war-whoop of applause and said it was "splendid!" and said if he had
-told them at first, they wouldn't have started away. He made a plausible
-excuse; but his real reason had been the fear that not even the secret
-would keep them with him any very great length of time, and so he had
-meant to hold it in reserve as a last seduction.
-
-The lads came gayly back and went at their sports again with a will,
-chattering all the time about Tom's stupendous plan and admiring the
-genius of it. After a dainty egg and fish dinner, Tom said he wanted to
-learn to smoke, now. Joe caught at the idea and said he would like to
-try, too. So Huck made pipes and filled them. These novices had never
-smoked anything before but cigars made of grape-vine, and they "bit"
-the tongue, and were not considered manly anyway.
-
-Now they stretched themselves out on their elbows and began to puff,
-charily, and with slender confidence. The smoke had an unpleasant
-taste, and they gagged a little, but Tom said:
-
-"Why, it's just as easy! If I'd a knowed this was all, I'd a learnt
-long ago."
-
-"So would I," said Joe. "It's just nothing."
-
-"Why, many a time I've looked at people smoking, and thought well I
-wish I could do that; but I never thought I could," said Tom.
-
-"That's just the way with me, hain't it, Huck? You've heard me talk
-just that way--haven't you, Huck? I'll leave it to Huck if I haven't."
-
-"Yes--heaps of times," said Huck.
-
-"Well, I have too," said Tom; "oh, hundreds of times. Once down by the
-slaughter-house. Don't you remember, Huck? Bob Tanner was there, and
-Johnny Miller, and Jeff Thatcher, when I said it. Don't you remember,
-Huck, 'bout me saying that?"
-
-"Yes, that's so," said Huck. "That was the day after I lost a white
-alley. No, 'twas the day before."
-
-"There--I told you so," said Tom. "Huck recollects it."
-
-"I bleeve I could smoke this pipe all day," said Joe. "I don't feel
-sick."
-
-"Neither do I," said Tom. "I could smoke it all day. But I bet you
-Jeff Thatcher couldn't."
-
-"Jeff Thatcher! Why, he'd keel over just with two draws. Just let him
-try it once. HE'D see!"
-
-"I bet he would. And Johnny Miller--I wish could see Johnny Miller
-tackle it once."
-
-"Oh, don't I!" said Joe. "Why, I bet you Johnny Miller couldn't any
-more do this than nothing. Just one little snifter would fetch HIM."
-
-"'Deed it would, Joe. Say--I wish the boys could see us now."
-
-"So do I."
-
-"Say--boys, don't say anything about it, and some time when they're
-around, I'll come up to you and say, 'Joe, got a pipe? I want a smoke.'
-And you'll say, kind of careless like, as if it warn't anything, you'll
-say, 'Yes, I got my OLD pipe, and another one, but my tobacker ain't
-very good.' And I'll say, 'Oh, that's all right, if it's STRONG
-enough.' And then you'll out with the pipes, and we'll light up just as
-ca'm, and then just see 'em look!"
-
-"By jings, that'll be gay, Tom! I wish it was NOW!"
-
-"So do I! And when we tell 'em we learned when we was off pirating,
-won't they wish they'd been along?"
-
-"Oh, I reckon not! I'll just BET they will!"
-
-So the talk ran on. But presently it began to flag a trifle, and grow
-disjointed. The silences widened; the expectoration marvellously
-increased. Every pore inside the boys' cheeks became a spouting
-fountain; they could scarcely bail out the cellars under their tongues
-fast enough to prevent an inundation; little overflowings down their
-throats occurred in spite of all they could do, and sudden retchings
-followed every time. Both boys were looking very pale and miserable,
-now. Joe's pipe dropped from his nerveless fingers. Tom's followed.
-Both fountains were going furiously and both pumps bailing with might
-and main. Joe said feebly:
-
-"I've lost my knife. I reckon I better go and find it."
-
-Tom said, with quivering lips and halting utterance:
-
-"I'll help you. You go over that way and I'll hunt around by the
-spring. No, you needn't come, Huck--we can find it."
-
-So Huck sat down again, and waited an hour. Then he found it lonesome,
-and went to find his comrades. They were wide apart in the woods, both
-very pale, both fast asleep. But something informed him that if they
-had had any trouble they had got rid of it.
-
-They were not talkative at supper that night. They had a humble look,
-and when Huck prepared his pipe after the meal and was going to prepare
-theirs, they said no, they were not feeling very well--something they
-ate at dinner had disagreed with them.
-
-About midnight Joe awoke, and called the boys. There was a brooding
-oppressiveness in the air that seemed to bode something. The boys
-huddled themselves together and sought the friendly companionship of
-the fire, though the dull dead heat of the breathless atmosphere was
-stifling. They sat still, intent and waiting. The solemn hush
-continued. Beyond the light of the fire everything was swallowed up in
-the blackness of darkness. Presently there came a quivering glow that
-vaguely revealed the foliage for a moment and then vanished. By and by
-another came, a little stronger. Then another. Then a faint moan came
-sighing through the branches of the forest and the boys felt a fleeting
-breath upon their cheeks, and shuddered with the fancy that the Spirit
-of the Night had gone by. There was a pause. Now a weird flash turned
-night into day and showed every little grass-blade, separate and
-distinct, that grew about their feet. And it showed three white,
-startled faces, too. A deep peal of thunder went rolling and tumbling
-down the heavens and lost itself in sullen rumblings in the distance. A
-sweep of chilly air passed by, rustling all the leaves and snowing the
-flaky ashes broadcast about the fire. Another fierce glare lit up the
-forest and an instant crash followed that seemed to rend the tree-tops
-right over the boys' heads. They clung together in terror, in the thick
-gloom that followed. A few big rain-drops fell pattering upon the
-leaves.
-
-"Quick! boys, go for the tent!" exclaimed Tom.
-
-They sprang away, stumbling over roots and among vines in the dark, no
-two plunging in the same direction. A furious blast roared through the
-trees, making everything sing as it went. One blinding flash after
-another came, and peal on peal of deafening thunder. And now a
-drenching rain poured down and the rising hurricane drove it in sheets
-along the ground. The boys cried out to each other, but the roaring
-wind and the booming thunder-blasts drowned their voices utterly.
-However, one by one they straggled in at last and took shelter under
-the tent, cold, scared, and streaming with water; but to have company
-in misery seemed something to be grateful for. They could not talk, the
-old sail flapped so furiously, even if the other noises would have
-allowed them. The tempest rose higher and higher, and presently the
-sail tore loose from its fastenings and went winging away on the blast.
-The boys seized each others' hands and fled, with many tumblings and
-bruises, to the shelter of a great oak that stood upon the river-bank.
-Now the battle was at its highest. Under the ceaseless conflagration of
-lightning that flamed in the skies, everything below stood out in
-clean-cut and shadowless distinctness: the bending trees, the billowy
-river, white with foam, the driving spray of spume-flakes, the dim
-outlines of the high bluffs on the other side, glimpsed through the
-drifting cloud-rack and the slanting veil of rain. Every little while
-some giant tree yielded the fight and fell crashing through the younger
-growth; and the unflagging thunder-peals came now in ear-splitting
-explosive bursts, keen and sharp, and unspeakably appalling. The storm
-culminated in one matchless effort that seemed likely to tear the island
-to pieces, burn it up, drown it to the tree-tops, blow it away, and
-deafen every creature in it, all at one and the same moment. It was a
-wild night for homeless young heads to be out in.
-
-But at last the battle was done, and the forces retired with weaker
-and weaker threatenings and grumblings, and peace resumed her sway. The
-boys went back to camp, a good deal awed; but they found there was
-still something to be thankful for, because the great sycamore, the
-shelter of their beds, was a ruin, now, blasted by the lightnings, and
-they were not under it when the catastrophe happened.
-
-Everything in camp was drenched, the camp-fire as well; for they were
-but heedless lads, like their generation, and had made no provision
-against rain. Here was matter for dismay, for they were soaked through
-and chilled. They were eloquent in their distress; but they presently
-discovered that the fire had eaten so far up under the great log it had
-been built against (where it curved upward and separated itself from
-the ground), that a handbreadth or so of it had escaped wetting; so
-they patiently wrought until, with shreds and bark gathered from the
-under sides of sheltered logs, they coaxed the fire to burn again. Then
-they piled on great dead boughs till they had a roaring furnace, and
-were glad-hearted once more. They dried their boiled ham and had a
-feast, and after that they sat by the fire and expanded and glorified
-their midnight adventure until morning, for there was not a dry spot to
-sleep on, anywhere around.
-
-As the sun began to steal in upon the boys, drowsiness came over them,
-and they went out on the sandbar and lay down to sleep. They got
-scorched out by and by, and drearily set about getting breakfast. After
-the meal they felt rusty, and stiff-jointed, and a little homesick once
-more. Tom saw the signs, and fell to cheering up the pirates as well as
-he could. But they cared nothing for marbles, or circus, or swimming,
-or anything. He reminded them of the imposing secret, and raised a ray
-of cheer. While it lasted, he got them interested in a new device. This
-was to knock off being pirates, for a while, and be Indians for a
-change. They were attracted by this idea; so it was not long before
-they were stripped, and striped from head to heel with black mud, like
-so many zebras--all of them chiefs, of course--and then they went
-tearing through the woods to attack an English settlement.
-
-By and by they separated into three hostile tribes, and darted upon
-each other from ambush with dreadful war-whoops, and killed and scalped
-each other by thousands. It was a gory day. Consequently it was an
-extremely satisfactory one.
-
-They assembled in camp toward supper-time, hungry and happy; but now a
-difficulty arose--hostile Indians could not break the bread of
-hospitality together without first making peace, and this was a simple
-impossibility without smoking a pipe of peace. There was no other
-process that ever they had heard of. Two of the savages almost wished
-they had remained pirates. However, there was no other way; so with
-such show of cheerfulness as they could muster they called for the pipe
-and took their whiff as it passed, in due form.
-
-And behold, they were glad they had gone into savagery, for they had
-gained something; they found that they could now smoke a little without
-having to go and hunt for a lost knife; they did not get sick enough to
-be seriously uncomfortable. They were not likely to fool away this high
-promise for lack of effort. No, they practised cautiously, after
-supper, with right fair success, and so they spent a jubilant evening.
-They were prouder and happier in their new acquirement than they would
-have been in the scalping and skinning of the Six Nations. We will
-leave them to smoke and chatter and brag, since we have no further use
-for them at present.
-
-
-
-CHAPTER XVII
-
-BUT there was no hilarity in the little town that same tranquil
-Saturday afternoon. The Harpers, and Aunt Polly's family, were being
-put into mourning, with great grief and many tears. An unusual quiet
-possessed the village, although it was ordinarily quiet enough, in all
-conscience. The villagers conducted their concerns with an absent air,
-and talked little; but they sighed often. The Saturday holiday seemed a
-burden to the children. They had no heart in their sports, and
-gradually gave them up.
-
-In the afternoon Becky Thatcher found herself moping about the
-deserted schoolhouse yard, and feeling very melancholy. But she found
-nothing there to comfort her. She soliloquized:
-
-"Oh, if I only had a brass andiron-knob again! But I haven't got
-anything now to remember him by." And she choked back a little sob.
-
-Presently she stopped, and said to herself:
-
-"It was right here. Oh, if it was to do over again, I wouldn't say
-that--I wouldn't say it for the whole world. But he's gone now; I'll
-never, never, never see him any more."
-
-This thought broke her down, and she wandered away, with tears rolling
-down her cheeks. Then quite a group of boys and girls--playmates of
-Tom's and Joe's--came by, and stood looking over the paling fence and
-talking in reverent tones of how Tom did so-and-so the last time they
-saw him, and how Joe said this and that small trifle (pregnant with
-awful prophecy, as they could easily see now!)--and each speaker
-pointed out the exact spot where the lost lads stood at the time, and
-then added something like "and I was a-standing just so--just as I am
-now, and as if you was him--I was as close as that--and he smiled, just
-this way--and then something seemed to go all over me, like--awful, you
-know--and I never thought what it meant, of course, but I can see now!"
-
-Then there was a dispute about who saw the dead boys last in life, and
-many claimed that dismal distinction, and offered evidences, more or
-less tampered with by the witness; and when it was ultimately decided
-who DID see the departed last, and exchanged the last words with them,
-the lucky parties took upon themselves a sort of sacred importance, and
-were gaped at and envied by all the rest. One poor chap, who had no
-other grandeur to offer, said with tolerably manifest pride in the
-remembrance:
-
-"Well, Tom Sawyer he licked me once."
-
-But that bid for glory was a failure. Most of the boys could say that,
-and so that cheapened the distinction too much. The group loitered
-away, still recalling memories of the lost heroes, in awed voices.
-
-When the Sunday-school hour was finished, the next morning, the bell
-began to toll, instead of ringing in the usual way. It was a very still
-Sabbath, and the mournful sound seemed in keeping with the musing hush
-that lay upon nature. The villagers began to gather, loitering a moment
-in the vestibule to converse in whispers about the sad event. But there
-was no whispering in the house; only the funereal rustling of dresses
-as the women gathered to their seats disturbed the silence there. None
-could remember when the little church had been so full before. There
-was finally a waiting pause, an expectant dumbness, and then Aunt Polly
-entered, followed by Sid and Mary, and they by the Harper family, all
-in deep black, and the whole congregation, the old minister as well,
-rose reverently and stood until the mourners were seated in the front
-pew. There was another communing silence, broken at intervals by
-muffled sobs, and then the minister spread his hands abroad and prayed.
-A moving hymn was sung, and the text followed: "I am the Resurrection
-and the Life."
-
-As the service proceeded, the clergyman drew such pictures of the
-graces, the winning ways, and the rare promise of the lost lads that
-every soul there, thinking he recognized these pictures, felt a pang in
-remembering that he had persistently blinded himself to them always
-before, and had as persistently seen only faults and flaws in the poor
-boys. The minister related many a touching incident in the lives of the
-departed, too, which illustrated their sweet, generous natures, and the
-people could easily see, now, how noble and beautiful those episodes
-were, and remembered with grief that at the time they occurred they had
-seemed rank rascalities, well deserving of the cowhide. The
-congregation became more and more moved, as the pathetic tale went on,
-till at last the whole company broke down and joined the weeping
-mourners in a chorus of anguished sobs, the preacher himself giving way
-to his feelings, and crying in the pulpit.
-
-There was a rustle in the gallery, which nobody noticed; a moment
-later the church door creaked; the minister raised his streaming eyes
-above his handkerchief, and stood transfixed! First one and then
-another pair of eyes followed the minister's, and then almost with one
-impulse the congregation rose and stared while the three dead boys came
-marching up the aisle, Tom in the lead, Joe next, and Huck, a ruin of
-drooping rags, sneaking sheepishly in the rear! They had been hid in
-the unused gallery listening to their own funeral sermon!
-
-Aunt Polly, Mary, and the Harpers threw themselves upon their restored
-ones, smothered them with kisses and poured out thanksgivings, while
-poor Huck stood abashed and uncomfortable, not knowing exactly what to
-do or where to hide from so many unwelcoming eyes. He wavered, and
-started to slink away, but Tom seized him and said:
-
-"Aunt Polly, it ain't fair. Somebody's got to be glad to see Huck."
-
-"And so they shall. I'm glad to see him, poor motherless thing!" And
-the loving attentions Aunt Polly lavished upon him were the one thing
-capable of making him more uncomfortable than he was before.
-
-Suddenly the minister shouted at the top of his voice: "Praise God
-from whom all blessings flow--SING!--and put your hearts in it!"
-
-And they did. Old Hundred swelled up with a triumphant burst, and
-while it shook the rafters Tom Sawyer the Pirate looked around upon the
-envying juveniles about him and confessed in his heart that this was
-the proudest moment of his life.
-
-As the "sold" congregation trooped out they said they would almost be
-willing to be made ridiculous again to hear Old Hundred sung like that
-once more.
-
-Tom got more cuffs and kisses that day--according to Aunt Polly's
-varying moods--than he had earned before in a year; and he hardly knew
-which expressed the most gratefulness to God and affection for himself.
-
-
-
-CHAPTER XVIII
-
-THAT was Tom's great secret--the scheme to return home with his
-brother pirates and attend their own funerals. They had paddled over to
-the Missouri shore on a log, at dusk on Saturday, landing five or six
-miles below the village; they had slept in the woods at the edge of the
-town till nearly daylight, and had then crept through back lanes and
-alleys and finished their sleep in the gallery of the church among a
-chaos of invalided benches.
-
-At breakfast, Monday morning, Aunt Polly and Mary were very loving to
-Tom, and very attentive to his wants. There was an unusual amount of
-talk. In the course of it Aunt Polly said:
-
-"Well, I don't say it wasn't a fine joke, Tom, to keep everybody
-suffering 'most a week so you boys had a good time, but it is a pity
-you could be so hard-hearted as to let me suffer so. If you could come
-over on a log to go to your funeral, you could have come over and give
-me a hint some way that you warn't dead, but only run off."
-
-"Yes, you could have done that, Tom," said Mary; "and I believe you
-would if you had thought of it."
-
-"Would you, Tom?" said Aunt Polly, her face lighting wistfully. "Say,
-now, would you, if you'd thought of it?"
-
-"I--well, I don't know. 'Twould 'a' spoiled everything."
-
-"Tom, I hoped you loved me that much," said Aunt Polly, with a grieved
-tone that discomforted the boy. "It would have been something if you'd
-cared enough to THINK of it, even if you didn't DO it."
-
-"Now, auntie, that ain't any harm," pleaded Mary; "it's only Tom's
-giddy way--he is always in such a rush that he never thinks of
-anything."
-
-"More's the pity. Sid would have thought. And Sid would have come and
-DONE it, too. Tom, you'll look back, some day, when it's too late, and
-wish you'd cared a little more for me when it would have cost you so
-little."
-
-"Now, auntie, you know I do care for you," said Tom.
-
-"I'd know it better if you acted more like it."
-
-"I wish now I'd thought," said Tom, with a repentant tone; "but I
-dreamt about you, anyway. That's something, ain't it?"
-
-"It ain't much--a cat does that much--but it's better than nothing.
-What did you dream?"
-
-"Why, Wednesday night I dreamt that you was sitting over there by the
-bed, and Sid was sitting by the woodbox, and Mary next to him."
-
-"Well, so we did. So we always do. I'm glad your dreams could take
-even that much trouble about us."
-
-"And I dreamt that Joe Harper's mother was here."
-
-"Why, she was here! Did you dream any more?"
-
-"Oh, lots. But it's so dim, now."
-
-"Well, try to recollect--can't you?"
-
-"Somehow it seems to me that the wind--the wind blowed the--the--"
-
-"Try harder, Tom! The wind did blow something. Come!"
-
-Tom pressed his fingers on his forehead an anxious minute, and then
-said:
-
-"I've got it now! I've got it now! It blowed the candle!"
-
-"Mercy on us! Go on, Tom--go on!"
-
-"And it seems to me that you said, 'Why, I believe that that door--'"
-
-"Go ON, Tom!"
-
-"Just let me study a moment--just a moment. Oh, yes--you said you
-believed the door was open."
-
-"As I'm sitting here, I did! Didn't I, Mary! Go on!"
-
-"And then--and then--well I won't be certain, but it seems like as if
-you made Sid go and--and--"
-
-"Well? Well? What did I make him do, Tom? What did I make him do?"
-
-"You made him--you--Oh, you made him shut it."
-
-"Well, for the land's sake! I never heard the beat of that in all my
-days! Don't tell ME there ain't anything in dreams, any more. Sereny
-Harper shall know of this before I'm an hour older. I'd like to see her
-get around THIS with her rubbage 'bout superstition. Go on, Tom!"
-
-"Oh, it's all getting just as bright as day, now. Next you said I
-warn't BAD, only mischeevous and harum-scarum, and not any more
-responsible than--than--I think it was a colt, or something."
-
-"And so it was! Well, goodness gracious! Go on, Tom!"
-
-"And then you began to cry."
-
-"So I did. So I did. Not the first time, neither. And then--"
-
-"Then Mrs. Harper she began to cry, and said Joe was just the same,
-and she wished she hadn't whipped him for taking cream when she'd
-throwed it out her own self--"
-
-"Tom! The sperrit was upon you! You was a prophesying--that's what you
-was doing! Land alive, go on, Tom!"
-
-"Then Sid he said--he said--"
-
-"I don't think I said anything," said Sid.
-
-"Yes you did, Sid," said Mary.
-
-"Shut your heads and let Tom go on! What did he say, Tom?"
-
-"He said--I THINK he said he hoped I was better off where I was gone
-to, but if I'd been better sometimes--"
-
-"THERE, d'you hear that! It was his very words!"
-
-"And you shut him up sharp."
-
-"I lay I did! There must 'a' been an angel there. There WAS an angel
-there, somewheres!"
-
-"And Mrs. Harper told about Joe scaring her with a firecracker, and
-you told about Peter and the Painkiller--"
-
-"Just as true as I live!"
-
-"And then there was a whole lot of talk 'bout dragging the river for
-us, and 'bout having the funeral Sunday, and then you and old Miss
-Harper hugged and cried, and she went."
-
-"It happened just so! It happened just so, as sure as I'm a-sitting in
-these very tracks. Tom, you couldn't told it more like if you'd 'a'
-seen it! And then what? Go on, Tom!"
-
-"Then I thought you prayed for me--and I could see you and hear every
-word you said. And you went to bed, and I was so sorry that I took and
-wrote on a piece of sycamore bark, 'We ain't dead--we are only off
-being pirates,' and put it on the table by the candle; and then you
-looked so good, laying there asleep, that I thought I went and leaned
-over and kissed you on the lips."
-
-"Did you, Tom, DID you! I just forgive you everything for that!" And
-she seized the boy in a crushing embrace that made him feel like the
-guiltiest of villains.
-
-"It was very kind, even though it was only a--dream," Sid soliloquized
-just audibly.
-
-"Shut up, Sid! A body does just the same in a dream as he'd do if he
-was awake. Here's a big Milum apple I've been saving for you, Tom, if
-you was ever found again--now go 'long to school. I'm thankful to the
-good God and Father of us all I've got you back, that's long-suffering
-and merciful to them that believe on Him and keep His word, though
-goodness knows I'm unworthy of it, but if only the worthy ones got His
-blessings and had His hand to help them over the rough places, there's
-few enough would smile here or ever enter into His rest when the long
-night comes. Go 'long Sid, Mary, Tom--take yourselves off--you've
-hendered me long enough."
-
-The children left for school, and the old lady to call on Mrs. Harper
-and vanquish her realism with Tom's marvellous dream. Sid had better
-judgment than to utter the thought that was in his mind as he left the
-house. It was this: "Pretty thin--as long a dream as that, without any
-mistakes in it!"
-
-What a hero Tom was become, now! He did not go skipping and prancing,
-but moved with a dignified swagger as became a pirate who felt that the
-public eye was on him. And indeed it was; he tried not to seem to see
-the looks or hear the remarks as he passed along, but they were food
-and drink to him. Smaller boys than himself flocked at his heels, as
-proud to be seen with him, and tolerated by him, as if he had been the
-drummer at the head of a procession or the elephant leading a menagerie
-into town. Boys of his own size pretended not to know he had been away
-at all; but they were consuming with envy, nevertheless. They would
-have given anything to have that swarthy suntanned skin of his, and his
-glittering notoriety; and Tom would not have parted with either for a
-circus.
-
-At school the children made so much of him and of Joe, and delivered
-such eloquent admiration from their eyes, that the two heroes were not
-long in becoming insufferably "stuck-up." They began to tell their
-adventures to hungry listeners--but they only began; it was not a thing
-likely to have an end, with imaginations like theirs to furnish
-material. And finally, when they got out their pipes and went serenely
-puffing around, the very summit of glory was reached.
-
-Tom decided that he could be independent of Becky Thatcher now. Glory
-was sufficient. He would live for glory. Now that he was distinguished,
-maybe she would be wanting to "make up." Well, let her--she should see
-that he could be as indifferent as some other people. Presently she
-arrived. Tom pretended not to see her. He moved away and joined a group
-of boys and girls and began to talk. Soon he observed that she was
-tripping gayly back and forth with flushed face and dancing eyes,
-pretending to be busy chasing schoolmates, and screaming with laughter
-when she made a capture; but he noticed that she always made her
-captures in his vicinity, and that she seemed to cast a conscious eye
-in his direction at such times, too. It gratified all the vicious
-vanity that was in him; and so, instead of winning him, it only "set
-him up" the more and made him the more diligent to avoid betraying that
-he knew she was about. Presently she gave over skylarking, and moved
-irresolutely about, sighing once or twice and glancing furtively and
-wistfully toward Tom. Then she observed that now Tom was talking more
-particularly to Amy Lawrence than to any one else. She felt a sharp
-pang and grew disturbed and uneasy at once. She tried to go away, but
-her feet were treacherous, and carried her to the group instead. She
-said to a girl almost at Tom's elbow--with sham vivacity:
-
-"Why, Mary Austin! you bad girl, why didn't you come to Sunday-school?"
-
-"I did come--didn't you see me?"
-
-"Why, no! Did you? Where did you sit?"
-
-"I was in Miss Peters' class, where I always go. I saw YOU."
-
-"Did you? Why, it's funny I didn't see you. I wanted to tell you about
-the picnic."
-
-"Oh, that's jolly. Who's going to give it?"
-
-"My ma's going to let me have one."
-
-"Oh, goody; I hope she'll let ME come."
-
-"Well, she will. The picnic's for me. She'll let anybody come that I
-want, and I want you."
-
-"That's ever so nice. When is it going to be?"
-
-"By and by. Maybe about vacation."
-
-"Oh, won't it be fun! You going to have all the girls and boys?"
-
-"Yes, every one that's friends to me--or wants to be"; and she glanced
-ever so furtively at Tom, but he talked right along to Amy Lawrence
-about the terrible storm on the island, and how the lightning tore the
-great sycamore tree "all to flinders" while he was "standing within
-three feet of it."
-
-"Oh, may I come?" said Grace Miller.
-
-"Yes."
-
-"And me?" said Sally Rogers.
-
-"Yes."
-
-"And me, too?" said Susy Harper. "And Joe?"
-
-"Yes."
-
-And so on, with clapping of joyful hands till all the group had begged
-for invitations but Tom and Amy. Then Tom turned coolly away, still
-talking, and took Amy with him. Becky's lips trembled and the tears
-came to her eyes; she hid these signs with a forced gayety and went on
-chattering, but the life had gone out of the picnic, now, and out of
-everything else; she got away as soon as she could and hid herself and
-had what her sex call "a good cry." Then she sat moody, with wounded
-pride, till the bell rang. She roused up, now, with a vindictive cast
-in her eye, and gave her plaited tails a shake and said she knew what
-SHE'D do.
-
-At recess Tom continued his flirtation with Amy with jubilant
-self-satisfaction. And he kept drifting about to find Becky and lacerate
-her with the performance. At last he spied her, but there was a sudden
-falling of his mercury. She was sitting cosily on a little bench behind
-the schoolhouse looking at a picture-book with Alfred Temple--and so
-absorbed were they, and their heads so close together over the book,
-that they did not seem to be conscious of anything in the world besides.
-Jealousy ran red-hot through Tom's veins. He began to hate himself for
-throwing away the chance Becky had offered for a reconciliation. He
-called himself a fool, and all the hard names he could think of. He
-wanted to cry with vexation. Amy chatted happily along, as they walked,
-for her heart was singing, but Tom's tongue had lost its function. He
-did not hear what Amy was saying, and whenever she paused expectantly he
-could only stammer an awkward assent, which was as often misplaced as
-otherwise. He kept drifting to the rear of the schoolhouse, again and
-again, to sear his eyeballs with the hateful spectacle there. He could
-not help it. And it maddened him to see, as he thought he saw, that
-Becky Thatcher never once suspected that he was even in the land of the
-living. But she did see, nevertheless; and she knew she was winning her
-fight, too, and was glad to see him suffer as she had suffered.
-
-Amy's happy prattle became intolerable. Tom hinted at things he had to
-attend to; things that must be done; and time was fleeting. But in
-vain--the girl chirped on. Tom thought, "Oh, hang her, ain't I ever
-going to get rid of her?" At last he must be attending to those
-things--and she said artlessly that she would be "around" when school
-let out. And he hastened away, hating her for it.
-
-"Any other boy!" Tom thought, grating his teeth. "Any boy in the whole
-town but that Saint Louis smarty that thinks he dresses so fine and is
-aristocracy! Oh, all right, I licked you the first day you ever saw
-this town, mister, and I'll lick you again! You just wait till I catch
-you out! I'll just take and--"
-
-And he went through the motions of thrashing an imaginary boy
---pummelling the air, and kicking and gouging. "Oh, you do, do you? You
-holler 'nough, do you? Now, then, let that learn you!" And so the
-imaginary flogging was finished to his satisfaction.
-
-Tom fled home at noon. His conscience could not endure any more of
-Amy's grateful happiness, and his jealousy could bear no more of the
-other distress. Becky resumed her picture inspections with Alfred, but
-as the minutes dragged along and no Tom came to suffer, her triumph
-began to cloud and she lost interest; gravity and absent-mindedness
-followed, and then melancholy; two or three times she pricked up her
-ear at a footstep, but it was a false hope; no Tom came. At last she
-grew entirely miserable and wished she hadn't carried it so far. When
-poor Alfred, seeing that he was losing her, he did not know how, kept
-exclaiming: "Oh, here's a jolly one! look at this!" she lost patience
-at last, and said, "Oh, don't bother me! I don't care for them!" and
-burst into tears, and got up and walked away.
-
-Alfred dropped alongside and was going to try to comfort her, but she
-said:
-
-"Go away and leave me alone, can't you! I hate you!"
-
-So the boy halted, wondering what he could have done--for she had said
-she would look at pictures all through the nooning--and she walked on,
-crying. Then Alfred went musing into the deserted schoolhouse. He was
-humiliated and angry. He easily guessed his way to the truth--the girl
-had simply made a convenience of him to vent her spite upon Tom Sawyer.
-He was far from hating Tom the less when this thought occurred to him.
-He wished there was some way to get that boy into trouble without much
-risk to himself. Tom's spelling-book fell under his eye. Here was his
-opportunity. He gratefully opened to the lesson for the afternoon and
-poured ink upon the page.
-
-Becky, glancing in at a window behind him at the moment, saw the act,
-and moved on, without discovering herself. She started homeward, now,
-intending to find Tom and tell him; Tom would be thankful and their
-troubles would be healed. Before she was half way home, however, she
-had changed her mind. The thought of Tom's treatment of her when she
-was talking about her picnic came scorching back and filled her with
-shame. She resolved to let him get whipped on the damaged
-spelling-book's account, and to hate him forever, into the bargain.
-
-
-
-CHAPTER XIX
-
-TOM arrived at home in a dreary mood, and the first thing his aunt
-said to him showed him that he had brought his sorrows to an
-unpromising market:
-
-"Tom, I've a notion to skin you alive!"
-
-"Auntie, what have I done?"
-
-"Well, you've done enough. Here I go over to Sereny Harper, like an
-old softy, expecting I'm going to make her believe all that rubbage
-about that dream, when lo and behold you she'd found out from Joe that
-you was over here and heard all the talk we had that night. Tom, I
-don't know what is to become of a boy that will act like that. It makes
-me feel so bad to think you could let me go to Sereny Harper and make
-such a fool of myself and never say a word."
-
-This was a new aspect of the thing. His smartness of the morning had
-seemed to Tom a good joke before, and very ingenious. It merely looked
-mean and shabby now. He hung his head and could not think of anything
-to say for a moment. Then he said:
-
-"Auntie, I wish I hadn't done it--but I didn't think."
-
-"Oh, child, you never think. You never think of anything but your own
-selfishness. You could think to come all the way over here from
-Jackson's Island in the night to laugh at our troubles, and you could
-think to fool me with a lie about a dream; but you couldn't ever think
-to pity us and save us from sorrow."
-
-"Auntie, I know now it was mean, but I didn't mean to be mean. I
-didn't, honest. And besides, I didn't come over here to laugh at you
-that night."
-
-"What did you come for, then?"
-
-"It was to tell you not to be uneasy about us, because we hadn't got
-drownded."
-
-"Tom, Tom, I would be the thankfullest soul in this world if I could
-believe you ever had as good a thought as that, but you know you never
-did--and I know it, Tom."
-
-"Indeed and 'deed I did, auntie--I wish I may never stir if I didn't."
-
-"Oh, Tom, don't lie--don't do it. It only makes things a hundred times
-worse."
-
-"It ain't a lie, auntie; it's the truth. I wanted to keep you from
-grieving--that was all that made me come."
-
-"I'd give the whole world to believe that--it would cover up a power
-of sins, Tom. I'd 'most be glad you'd run off and acted so bad. But it
-ain't reasonable; because, why didn't you tell me, child?"
-
-"Why, you see, when you got to talking about the funeral, I just got
-all full of the idea of our coming and hiding in the church, and I
-couldn't somehow bear to spoil it. So I just put the bark back in my
-pocket and kept mum."
-
-"What bark?"
-
-"The bark I had wrote on to tell you we'd gone pirating. I wish, now,
-you'd waked up when I kissed you--I do, honest."
-
-The hard lines in his aunt's face relaxed and a sudden tenderness
-dawned in her eyes.
-
-"DID you kiss me, Tom?"
-
-"Why, yes, I did."
-
-"Are you sure you did, Tom?"
-
-"Why, yes, I did, auntie--certain sure."
-
-"What did you kiss me for, Tom?"
-
-"Because I loved you so, and you laid there moaning and I was so sorry."
-
-The words sounded like truth. The old lady could not hide a tremor in
-her voice when she said:
-
-"Kiss me again, Tom!--and be off with you to school, now, and don't
-bother me any more."
-
-The moment he was gone, she ran to a closet and got out the ruin of a
-jacket which Tom had gone pirating in. Then she stopped, with it in her
-hand, and said to herself:
-
-"No, I don't dare. Poor boy, I reckon he's lied about it--but it's a
-blessed, blessed lie, there's such a comfort come from it. I hope the
-Lord--I KNOW the Lord will forgive him, because it was such
-goodheartedness in him to tell it. But I don't want to find out it's a
-lie. I won't look."
-
-She put the jacket away, and stood by musing a minute. Twice she put
-out her hand to take the garment again, and twice she refrained. Once
-more she ventured, and this time she fortified herself with the
-thought: "It's a good lie--it's a good lie--I won't let it grieve me."
-So she sought the jacket pocket. A moment later she was reading Tom's
-piece of bark through flowing tears and saying: "I could forgive the
-boy, now, if he'd committed a million sins!"
-
-
-
-CHAPTER XX
-
-THERE was something about Aunt Polly's manner, when she kissed Tom,
-that swept away his low spirits and made him lighthearted and happy
-again. He started to school and had the luck of coming upon Becky
-Thatcher at the head of Meadow Lane. His mood always determined his
-manner. Without a moment's hesitation he ran to her and said:
-
-"I acted mighty mean to-day, Becky, and I'm so sorry. I won't ever,
-ever do that way again, as long as ever I live--please make up, won't
-you?"
-
-The girl stopped and looked him scornfully in the face:
-
-"I'll thank you to keep yourself TO yourself, Mr. Thomas Sawyer. I'll
-never speak to you again."
-
-She tossed her head and passed on. Tom was so stunned that he had not
-even presence of mind enough to say "Who cares, Miss Smarty?" until the
-right time to say it had gone by. So he said nothing. But he was in a
-fine rage, nevertheless. He moped into the schoolyard wishing she were
-a boy, and imagining how he would trounce her if she were. He presently
-encountered her and delivered a stinging remark as he passed. She
-hurled one in return, and the angry breach was complete. It seemed to
-Becky, in her hot resentment, that she could hardly wait for school to
-"take in," she was so impatient to see Tom flogged for the injured
-spelling-book. If she had had any lingering notion of exposing Alfred
-Temple, Tom's offensive fling had driven it entirely away.
-
-Poor girl, she did not know how fast she was nearing trouble herself.
-The master, Mr. Dobbins, had reached middle age with an unsatisfied
-ambition. The darling of his desires was, to be a doctor, but poverty
-had decreed that he should be nothing higher than a village
-schoolmaster. Every day he took a mysterious book out of his desk and
-absorbed himself in it at times when no classes were reciting. He kept
-that book under lock and key. There was not an urchin in school but was
-perishing to have a glimpse of it, but the chance never came. Every boy
-and girl had a theory about the nature of that book; but no two
-theories were alike, and there was no way of getting at the facts in
-the case. Now, as Becky was passing by the desk, which stood near the
-door, she noticed that the key was in the lock! It was a precious
-moment. She glanced around; found herself alone, and the next instant
-she had the book in her hands. The title-page--Professor Somebody's
-ANATOMY--carried no information to her mind; so she began to turn the
-leaves. She came at once upon a handsomely engraved and colored
-frontispiece--a human figure, stark naked. At that moment a shadow fell
-on the page and Tom Sawyer stepped in at the door and caught a glimpse
-of the picture. Becky snatched at the book to close it, and had the
-hard luck to tear the pictured page half down the middle. She thrust
-the volume into the desk, turned the key, and burst out crying with
-shame and vexation.
-
-"Tom Sawyer, you are just as mean as you can be, to sneak up on a
-person and look at what they're looking at."
-
-"How could I know you was looking at anything?"
-
-"You ought to be ashamed of yourself, Tom Sawyer; you know you're
-going to tell on me, and oh, what shall I do, what shall I do! I'll be
-whipped, and I never was whipped in school."
-
-Then she stamped her little foot and said:
-
-"BE so mean if you want to! I know something that's going to happen.
-You just wait and you'll see! Hateful, hateful, hateful!"--and she
-flung out of the house with a new explosion of crying.
-
-Tom stood still, rather flustered by this onslaught. Presently he said
-to himself:
-
-"What a curious kind of a fool a girl is! Never been licked in school!
-Shucks! What's a licking! That's just like a girl--they're so
-thin-skinned and chicken-hearted. Well, of course I ain't going to tell
-old Dobbins on this little fool, because there's other ways of getting
-even on her, that ain't so mean; but what of it? Old Dobbins will ask
-who it was tore his book. Nobody'll answer. Then he'll do just the way
-he always does--ask first one and then t'other, and when he comes to the
-right girl he'll know it, without any telling. Girls' faces always tell
-on them. They ain't got any backbone. She'll get licked. Well, it's a
-kind of a tight place for Becky Thatcher, because there ain't any way
-out of it." Tom conned the thing a moment longer, and then added: "All
-right, though; she'd like to see me in just such a fix--let her sweat it
-out!"
-
-Tom joined the mob of skylarking scholars outside. In a few moments
-the master arrived and school "took in." Tom did not feel a strong
-interest in his studies. Every time he stole a glance at the girls'
-side of the room Becky's face troubled him. Considering all things, he
-did not want to pity her, and yet it was all he could do to help it. He
-could get up no exultation that was really worthy the name. Presently
-the spelling-book discovery was made, and Tom's mind was entirely full
-of his own matters for a while after that. Becky roused up from her
-lethargy of distress and showed good interest in the proceedings. She
-did not expect that Tom could get out of his trouble by denying that he
-spilt the ink on the book himself; and she was right. The denial only
-seemed to make the thing worse for Tom. Becky supposed she would be
-glad of that, and she tried to believe she was glad of it, but she
-found she was not certain. When the worst came to the worst, she had an
-impulse to get up and tell on Alfred Temple, but she made an effort and
-forced herself to keep still--because, said she to herself, "he'll tell
-about me tearing the picture sure. I wouldn't say a word, not to save
-his life!"
-
-Tom took his whipping and went back to his seat not at all
-broken-hearted, for he thought it was possible that he had unknowingly
-upset the ink on the spelling-book himself, in some skylarking bout--he
-had denied it for form's sake and because it was custom, and had stuck
-to the denial from principle.
-
-A whole hour drifted by, the master sat nodding in his throne, the air
-was drowsy with the hum of study. By and by, Mr. Dobbins straightened
-himself up, yawned, then unlocked his desk, and reached for his book,
-but seemed undecided whether to take it out or leave it. Most of the
-pupils glanced up languidly, but there were two among them that watched
-his movements with intent eyes. Mr. Dobbins fingered his book absently
-for a while, then took it out and settled himself in his chair to read!
-Tom shot a glance at Becky. He had seen a hunted and helpless rabbit
-look as she did, with a gun levelled at its head. Instantly he forgot
-his quarrel with her. Quick--something must be done! done in a flash,
-too! But the very imminence of the emergency paralyzed his invention.
-Good!--he had an inspiration! He would run and snatch the book, spring
-through the door and fly. But his resolution shook for one little
-instant, and the chance was lost--the master opened the volume. If Tom
-only had the wasted opportunity back again! Too late. There was no help
-for Becky now, he said. The next moment the master faced the school.
-Every eye sank under his gaze. There was that in it which smote even
-the innocent with fear. There was silence while one might count ten
---the master was gathering his wrath. Then he spoke: "Who tore this book?"
-
-There was not a sound. One could have heard a pin drop. The stillness
-continued; the master searched face after face for signs of guilt.
-
-"Benjamin Rogers, did you tear this book?"
-
-A denial. Another pause.
-
-"Joseph Harper, did you?"
-
-Another denial. Tom's uneasiness grew more and more intense under the
-slow torture of these proceedings. The master scanned the ranks of
-boys--considered a while, then turned to the girls:
-
-"Amy Lawrence?"
-
-A shake of the head.
-
-"Gracie Miller?"
-
-The same sign.
-
-"Susan Harper, did you do this?"
-
-Another negative. The next girl was Becky Thatcher. Tom was trembling
-from head to foot with excitement and a sense of the hopelessness of
-the situation.
-
-"Rebecca Thatcher" [Tom glanced at her face--it was white with terror]
---"did you tear--no, look me in the face" [her hands rose in appeal]
---"did you tear this book?"
-
-A thought shot like lightning through Tom's brain. He sprang to his
-feet and shouted--"I done it!"
-
-The school stared in perplexity at this incredible folly. Tom stood a
-moment, to gather his dismembered faculties; and when he stepped
-forward to go to his punishment the surprise, the gratitude, the
-adoration that shone upon him out of poor Becky's eyes seemed pay
-enough for a hundred floggings. Inspired by the splendor of his own
-act, he took without an outcry the most merciless flaying that even Mr.
-Dobbins had ever administered; and also received with indifference the
-added cruelty of a command to remain two hours after school should be
-dismissed--for he knew who would wait for him outside till his
-captivity was done, and not count the tedious time as loss, either.
-
-Tom went to bed that night planning vengeance against Alfred Temple;
-for with shame and repentance Becky had told him all, not forgetting
-her own treachery; but even the longing for vengeance had to give way,
-soon, to pleasanter musings, and he fell asleep at last with Becky's
-latest words lingering dreamily in his ear--
-
-"Tom, how COULD you be so noble!"
-
-
-
-CHAPTER XXI
-
-VACATION was approaching. The schoolmaster, always severe, grew
-severer and more exacting than ever, for he wanted the school to make a
-good showing on "Examination" day. His rod and his ferule were seldom
-idle now--at least among the smaller pupils. Only the biggest boys, and
-young ladies of eighteen and twenty, escaped lashing. Mr. Dobbins'
-lashings were very vigorous ones, too; for although he carried, under
-his wig, a perfectly bald and shiny head, he had only reached middle
-age, and there was no sign of feebleness in his muscle. As the great
-day approached, all the tyranny that was in him came to the surface; he
-seemed to take a vindictive pleasure in punishing the least
-shortcomings. The consequence was, that the smaller boys spent their
-days in terror and suffering and their nights in plotting revenge. They
-threw away no opportunity to do the master a mischief. But he kept
-ahead all the time. The retribution that followed every vengeful
-success was so sweeping and majestic that the boys always retired from
-the field badly worsted. At last they conspired together and hit upon a
-plan that promised a dazzling victory. They swore in the sign-painter's
-boy, told him the scheme, and asked his help. He had his own reasons
-for being delighted, for the master boarded in his father's family and
-had given the boy ample cause to hate him. The master's wife would go
-on a visit to the country in a few days, and there would be nothing to
-interfere with the plan; the master always prepared himself for great
-occasions by getting pretty well fuddled, and the sign-painter's boy
-said that when the dominie had reached the proper condition on
-Examination Evening he would "manage the thing" while he napped in his
-chair; then he would have him awakened at the right time and hurried
-away to school.
-
-In the fulness of time the interesting occasion arrived. At eight in
-the evening the schoolhouse was brilliantly lighted, and adorned with
-wreaths and festoons of foliage and flowers. The master sat throned in
-his great chair upon a raised platform, with his blackboard behind him.
-He was looking tolerably mellow. Three rows of benches on each side and
-six rows in front of him were occupied by the dignitaries of the town
-and by the parents of the pupils. To his left, back of the rows of
-citizens, was a spacious temporary platform upon which were seated the
-scholars who were to take part in the exercises of the evening; rows of
-small boys, washed and dressed to an intolerable state of discomfort;
-rows of gawky big boys; snowbanks of girls and young ladies clad in
-lawn and muslin and conspicuously conscious of their bare arms, their
-grandmothers' ancient trinkets, their bits of pink and blue ribbon and
-the flowers in their hair. All the rest of the house was filled with
-non-participating scholars.
-
-The exercises began. A very little boy stood up and sheepishly
-recited, "You'd scarce expect one of my age to speak in public on the
-stage," etc.--accompanying himself with the painfully exact and
-spasmodic gestures which a machine might have used--supposing the
-machine to be a trifle out of order. But he got through safely, though
-cruelly scared, and got a fine round of applause when he made his
-manufactured bow and retired.
-
-A little shamefaced girl lisped, "Mary had a little lamb," etc.,
-performed a compassion-inspiring curtsy, got her meed of applause, and
-sat down flushed and happy.
-
-Tom Sawyer stepped forward with conceited confidence and soared into
-the unquenchable and indestructible "Give me liberty or give me death"
-speech, with fine fury and frantic gesticulation, and broke down in the
-middle of it. A ghastly stage-fright seized him, his legs quaked under
-him and he was like to choke. True, he had the manifest sympathy of the
-house but he had the house's silence, too, which was even worse than
-its sympathy. The master frowned, and this completed the disaster. Tom
-struggled awhile and then retired, utterly defeated. There was a weak
-attempt at applause, but it died early.
-
-"The Boy Stood on the Burning Deck" followed; also "The Assyrian Came
-Down," and other declamatory gems. Then there were reading exercises,
-and a spelling fight. The meagre Latin class recited with honor. The
-prime feature of the evening was in order, now--original "compositions"
-by the young ladies. Each in her turn stepped forward to the edge of
-the platform, cleared her throat, held up her manuscript (tied with
-dainty ribbon), and proceeded to read, with labored attention to
-"expression" and punctuation. The themes were the same that had been
-illuminated upon similar occasions by their mothers before them, their
-grandmothers, and doubtless all their ancestors in the female line
-clear back to the Crusades. "Friendship" was one; "Memories of Other
-Days"; "Religion in History"; "Dream Land"; "The Advantages of
-Culture"; "Forms of Political Government Compared and Contrasted";
-"Melancholy"; "Filial Love"; "Heart Longings," etc., etc.
-
-A prevalent feature in these compositions was a nursed and petted
-melancholy; another was a wasteful and opulent gush of "fine language";
-another was a tendency to lug in by the ears particularly prized words
-and phrases until they were worn entirely out; and a peculiarity that
-conspicuously marked and marred them was the inveterate and intolerable
-sermon that wagged its crippled tail at the end of each and every one
-of them. No matter what the subject might be, a brain-racking effort
-was made to squirm it into some aspect or other that the moral and
-religious mind could contemplate with edification. The glaring
-insincerity of these sermons was not sufficient to compass the
-banishment of the fashion from the schools, and it is not sufficient
-to-day; it never will be sufficient while the world stands, perhaps.
-There is no school in all our land where the young ladies do not feel
-obliged to close their compositions with a sermon; and you will find
-that the sermon of the most frivolous and the least religious girl in
-the school is always the longest and the most relentlessly pious. But
-enough of this. Homely truth is unpalatable.
-
-Let us return to the "Examination." The first composition that was
-read was one entitled "Is this, then, Life?" Perhaps the reader can
-endure an extract from it:
-
- "In the common walks of life, with what delightful
- emotions does the youthful mind look forward to some
- anticipated scene of festivity! Imagination is busy
- sketching rose-tinted pictures of joy. In fancy, the
- voluptuous votary of fashion sees herself amid the
- festive throng, 'the observed of all observers.' Her
- graceful form, arrayed in snowy robes, is whirling
- through the mazes of the joyous dance; her eye is
- brightest, her step is lightest in the gay assembly.
-
- "In such delicious fancies time quickly glides by,
- and the welcome hour arrives for her entrance into
- the Elysian world, of which she has had such bright
- dreams. How fairy-like does everything appear to
- her enchanted vision! Each new scene is more charming
- than the last. But after a while she finds that
- beneath this goodly exterior, all is vanity, the
- flattery which once charmed her soul, now grates
- harshly upon her ear; the ball-room has lost its
- charms; and with wasted health and imbittered heart,
- she turns away with the conviction that earthly
- pleasures cannot satisfy the longings of the soul!"
-
-And so forth and so on. There was a buzz of gratification from time to
-time during the reading, accompanied by whispered ejaculations of "How
-sweet!" "How eloquent!" "So true!" etc., and after the thing had closed
-with a peculiarly afflicting sermon the applause was enthusiastic.
-
-Then arose a slim, melancholy girl, whose face had the "interesting"
-paleness that comes of pills and indigestion, and read a "poem." Two
-stanzas of it will do:
-
- "A MISSOURI MAIDEN'S FAREWELL TO ALABAMA
-
- "Alabama, good-bye! I love thee well!
- But yet for a while do I leave thee now!
- Sad, yes, sad thoughts of thee my heart doth swell,
- And burning recollections throng my brow!
- For I have wandered through thy flowery woods;
- Have roamed and read near Tallapoosa's stream;
- Have listened to Tallassee's warring floods,
- And wooed on Coosa's side Aurora's beam.
-
- "Yet shame I not to bear an o'er-full heart,
- Nor blush to turn behind my tearful eyes;
- 'Tis from no stranger land I now must part,
- 'Tis to no strangers left I yield these sighs.
- Welcome and home were mine within this State,
- Whose vales I leave--whose spires fade fast from me
- And cold must be mine eyes, and heart, and tete,
- When, dear Alabama! they turn cold on thee!"
-
-There were very few there who knew what "tete" meant, but the poem was
-very satisfactory, nevertheless.
-
-Next appeared a dark-complexioned, black-eyed, black-haired young
-lady, who paused an impressive moment, assumed a tragic expression, and
-began to read in a measured, solemn tone:
-
- "A VISION
-
- "Dark and tempestuous was night. Around the
- throne on high not a single star quivered; but
- the deep intonations of the heavy thunder
- constantly vibrated upon the ear; whilst the
- terrific lightning revelled in angry mood
- through the cloudy chambers of heaven, seeming
- to scorn the power exerted over its terror by
- the illustrious Franklin! Even the boisterous
- winds unanimously came forth from their mystic
- homes, and blustered about as if to enhance by
- their aid the wildness of the scene.
-
- "At such a time, so dark, so dreary, for human
- sympathy my very spirit sighed; but instead thereof,
-
- "'My dearest friend, my counsellor, my comforter
- and guide--My joy in grief, my second bliss
- in joy,' came to my side. She moved like one of
- those bright beings pictured in the sunny walks
- of fancy's Eden by the romantic and young, a
- queen of beauty unadorned save by her own
- transcendent loveliness. So soft was her step, it
- failed to make even a sound, and but for the
- magical thrill imparted by her genial touch, as
- other unobtrusive beauties, she would have glided
- away un-perceived--unsought. A strange sadness
- rested upon her features, like icy tears upon
- the robe of December, as she pointed to the
- contending elements without, and bade me contemplate
- the two beings presented."
-
-This nightmare occupied some ten pages of manuscript and wound up with
-a sermon so destructive of all hope to non-Presbyterians that it took
-the first prize. This composition was considered to be the very finest
-effort of the evening. The mayor of the village, in delivering the
-prize to the author of it, made a warm speech in which he said that it
-was by far the most "eloquent" thing he had ever listened to, and that
-Daniel Webster himself might well be proud of it.
-
-It may be remarked, in passing, that the number of compositions in
-which the word "beauteous" was over-fondled, and human experience
-referred to as "life's page," was up to the usual average.
-
-Now the master, mellow almost to the verge of geniality, put his chair
-aside, turned his back to the audience, and began to draw a map of
-America on the blackboard, to exercise the geography class upon. But he
-made a sad business of it with his unsteady hand, and a smothered
-titter rippled over the house. He knew what the matter was, and set
-himself to right it. He sponged out lines and remade them; but he only
-distorted them more than ever, and the tittering was more pronounced.
-He threw his entire attention upon his work, now, as if determined not
-to be put down by the mirth. He felt that all eyes were fastened upon
-him; he imagined he was succeeding, and yet the tittering continued; it
-even manifestly increased. And well it might. There was a garret above,
-pierced with a scuttle over his head; and down through this scuttle
-came a cat, suspended around the haunches by a string; she had a rag
-tied about her head and jaws to keep her from mewing; as she slowly
-descended she curved upward and clawed at the string, she swung
-downward and clawed at the intangible air. The tittering rose higher
-and higher--the cat was within six inches of the absorbed teacher's
-head--down, down, a little lower, and she grabbed his wig with her
-desperate claws, clung to it, and was snatched up into the garret in an
-instant with her trophy still in her possession! And how the light did
-blaze abroad from the master's bald pate--for the sign-painter's boy
-had GILDED it!
-
-That broke up the meeting. The boys were avenged. Vacation had come.
-
- NOTE:--The pretended "compositions" quoted in
- this chapter are taken without alteration from a
- volume entitled "Prose and Poetry, by a Western
- Lady"--but they are exactly and precisely after
- the schoolgirl pattern, and hence are much
- happier than any mere imitations could be.
-
-
-
-CHAPTER XXII
-
-TOM joined the new order of Cadets of Temperance, being attracted by
-the showy character of their "regalia." He promised to abstain from
-smoking, chewing, and profanity as long as he remained a member. Now he
-found out a new thing--namely, that to promise not to do a thing is the
-surest way in the world to make a body want to go and do that very
-thing. Tom soon found himself tormented with a desire to drink and
-swear; the desire grew to be so intense that nothing but the hope of a
-chance to display himself in his red sash kept him from withdrawing
-from the order. Fourth of July was coming; but he soon gave that up
---gave it up before he had worn his shackles over forty-eight hours--and
-fixed his hopes upon old Judge Frazer, justice of the peace, who was
-apparently on his deathbed and would have a big public funeral, since
-he was so high an official. During three days Tom was deeply concerned
-about the Judge's condition and hungry for news of it. Sometimes his
-hopes ran high--so high that he would venture to get out his regalia
-and practise before the looking-glass. But the Judge had a most
-discouraging way of fluctuating. At last he was pronounced upon the
-mend--and then convalescent. Tom was disgusted; and felt a sense of
-injury, too. He handed in his resignation at once--and that night the
-Judge suffered a relapse and died. Tom resolved that he would never
-trust a man like that again.
-
-The funeral was a fine thing. The Cadets paraded in a style calculated
-to kill the late member with envy. Tom was a free boy again, however
---there was something in that. He could drink and swear, now--but found
-to his surprise that he did not want to. The simple fact that he could,
-took the desire away, and the charm of it.
-
-Tom presently wondered to find that his coveted vacation was beginning
-to hang a little heavily on his hands.
-
-He attempted a diary--but nothing happened during three days, and so
-he abandoned it.
-
-The first of all the negro minstrel shows came to town, and made a
-sensation. Tom and Joe Harper got up a band of performers and were
-happy for two days.
-
-Even the Glorious Fourth was in some sense a failure, for it rained
-hard, there was no procession in consequence, and the greatest man in
-the world (as Tom supposed), Mr. Benton, an actual United States
-Senator, proved an overwhelming disappointment--for he was not
-twenty-five feet high, nor even anywhere in the neighborhood of it.
-
-A circus came. The boys played circus for three days afterward in
-tents made of rag carpeting--admission, three pins for boys, two for
-girls--and then circusing was abandoned.
-
-A phrenologist and a mesmerizer came--and went again and left the
-village duller and drearier than ever.
-
-There were some boys-and-girls' parties, but they were so few and so
-delightful that they only made the aching voids between ache the harder.
-
-Becky Thatcher was gone to her Constantinople home to stay with her
-parents during vacation--so there was no bright side to life anywhere.
-
-The dreadful secret of the murder was a chronic misery. It was a very
-cancer for permanency and pain.
-
-Then came the measles.
-
-During two long weeks Tom lay a prisoner, dead to the world and its
-happenings. He was very ill, he was interested in nothing. When he got
-upon his feet at last and moved feebly down-town, a melancholy change
-had come over everything and every creature. There had been a
-"revival," and everybody had "got religion," not only the adults, but
-even the boys and girls. Tom went about, hoping against hope for the
-sight of one blessed sinful face, but disappointment crossed him
-everywhere. He found Joe Harper studying a Testament, and turned sadly
-away from the depressing spectacle. He sought Ben Rogers, and found him
-visiting the poor with a basket of tracts. He hunted up Jim Hollis, who
-called his attention to the precious blessing of his late measles as a
-warning. Every boy he encountered added another ton to his depression;
-and when, in desperation, he flew for refuge at last to the bosom of
-Huckleberry Finn and was received with a Scriptural quotation, his
-heart broke and he crept home and to bed realizing that he alone of all
-the town was lost, forever and forever.
-
-And that night there came on a terrific storm, with driving rain,
-awful claps of thunder and blinding sheets of lightning. He covered his
-head with the bedclothes and waited in a horror of suspense for his
-doom; for he had not the shadow of a doubt that all this hubbub was
-about him. He believed he had taxed the forbearance of the powers above
-to the extremity of endurance and that this was the result. It might
-have seemed to him a waste of pomp and ammunition to kill a bug with a
-battery of artillery, but there seemed nothing incongruous about the
-getting up such an expensive thunderstorm as this to knock the turf
-from under an insect like himself.
-
-By and by the tempest spent itself and died without accomplishing its
-object. The boy's first impulse was to be grateful, and reform. His
-second was to wait--for there might not be any more storms.
-
-The next day the doctors were back; Tom had relapsed. The three weeks
-he spent on his back this time seemed an entire age. When he got abroad
-at last he was hardly grateful that he had been spared, remembering how
-lonely was his estate, how companionless and forlorn he was. He drifted
-listlessly down the street and found Jim Hollis acting as judge in a
-juvenile court that was trying a cat for murder, in the presence of her
-victim, a bird. He found Joe Harper and Huck Finn up an alley eating a
-stolen melon. Poor lads! they--like Tom--had suffered a relapse.
-
-
-
-CHAPTER XXIII
-
-AT last the sleepy atmosphere was stirred--and vigorously: the murder
-trial came on in the court. It became the absorbing topic of village
-talk immediately. Tom could not get away from it. Every reference to
-the murder sent a shudder to his heart, for his troubled conscience and
-fears almost persuaded him that these remarks were put forth in his
-hearing as "feelers"; he did not see how he could be suspected of
-knowing anything about the murder, but still he could not be
-comfortable in the midst of this gossip. It kept him in a cold shiver
-all the time. He took Huck to a lonely place to have a talk with him.
-It would be some relief to unseal his tongue for a little while; to
-divide his burden of distress with another sufferer. Moreover, he
-wanted to assure himself that Huck had remained discreet.
-
-"Huck, have you ever told anybody about--that?"
-
-"'Bout what?"
-
-"You know what."
-
-"Oh--'course I haven't."
-
-"Never a word?"
-
-"Never a solitary word, so help me. What makes you ask?"
-
-"Well, I was afeard."
-
-"Why, Tom Sawyer, we wouldn't be alive two days if that got found out.
-YOU know that."
-
-Tom felt more comfortable. After a pause:
-
-"Huck, they couldn't anybody get you to tell, could they?"
-
-"Get me to tell? Why, if I wanted that half-breed devil to drownd me
-they could get me to tell. They ain't no different way."
-
-"Well, that's all right, then. I reckon we're safe as long as we keep
-mum. But let's swear again, anyway. It's more surer."
-
-"I'm agreed."
-
-So they swore again with dread solemnities.
-
-"What is the talk around, Huck? I've heard a power of it."
-
-"Talk? Well, it's just Muff Potter, Muff Potter, Muff Potter all the
-time. It keeps me in a sweat, constant, so's I want to hide som'ers."
-
-"That's just the same way they go on round me. I reckon he's a goner.
-Don't you feel sorry for him, sometimes?"
-
-"Most always--most always. He ain't no account; but then he hain't
-ever done anything to hurt anybody. Just fishes a little, to get money
-to get drunk on--and loafs around considerable; but lord, we all do
-that--leastways most of us--preachers and such like. But he's kind of
-good--he give me half a fish, once, when there warn't enough for two;
-and lots of times he's kind of stood by me when I was out of luck."
-
-"Well, he's mended kites for me, Huck, and knitted hooks on to my
-line. I wish we could get him out of there."
-
-"My! we couldn't get him out, Tom. And besides, 'twouldn't do any
-good; they'd ketch him again."
-
-"Yes--so they would. But I hate to hear 'em abuse him so like the
-dickens when he never done--that."
-
-"I do too, Tom. Lord, I hear 'em say he's the bloodiest looking
-villain in this country, and they wonder he wasn't ever hung before."
-
-"Yes, they talk like that, all the time. I've heard 'em say that if he
-was to get free they'd lynch him."
-
-"And they'd do it, too."
-
-The boys had a long talk, but it brought them little comfort. As the
-twilight drew on, they found themselves hanging about the neighborhood
-of the little isolated jail, perhaps with an undefined hope that
-something would happen that might clear away their difficulties. But
-nothing happened; there seemed to be no angels or fairies interested in
-this luckless captive.
-
-The boys did as they had often done before--went to the cell grating
-and gave Potter some tobacco and matches. He was on the ground floor
-and there were no guards.
-
-His gratitude for their gifts had always smote their consciences
-before--it cut deeper than ever, this time. They felt cowardly and
-treacherous to the last degree when Potter said:
-
-"You've been mighty good to me, boys--better'n anybody else in this
-town. And I don't forget it, I don't. Often I says to myself, says I,
-'I used to mend all the boys' kites and things, and show 'em where the
-good fishin' places was, and befriend 'em what I could, and now they've
-all forgot old Muff when he's in trouble; but Tom don't, and Huck
-don't--THEY don't forget him, says I, 'and I don't forget them.' Well,
-boys, I done an awful thing--drunk and crazy at the time--that's the
-only way I account for it--and now I got to swing for it, and it's
-right. Right, and BEST, too, I reckon--hope so, anyway. Well, we won't
-talk about that. I don't want to make YOU feel bad; you've befriended
-me. But what I want to say, is, don't YOU ever get drunk--then you won't
-ever get here. Stand a litter furder west--so--that's it; it's a prime
-comfort to see faces that's friendly when a body's in such a muck of
-trouble, and there don't none come here but yourn. Good friendly
-faces--good friendly faces. Git up on one another's backs and let me
-touch 'em. That's it. Shake hands--yourn'll come through the bars, but
-mine's too big. Little hands, and weak--but they've helped Muff Potter
-a power, and they'd help him more if they could."
-
-Tom went home miserable, and his dreams that night were full of
-horrors. The next day and the day after, he hung about the court-room,
-drawn by an almost irresistible impulse to go in, but forcing himself
-to stay out. Huck was having the same experience. They studiously
-avoided each other. Each wandered away, from time to time, but the same
-dismal fascination always brought them back presently. Tom kept his
-ears open when idlers sauntered out of the court-room, but invariably
-heard distressing news--the toils were closing more and more
-relentlessly around poor Potter. At the end of the second day the
-village talk was to the effect that Injun Joe's evidence stood firm and
-unshaken, and that there was not the slightest question as to what the
-jury's verdict would be.
-
-Tom was out late, that night, and came to bed through the window. He
-was in a tremendous state of excitement. It was hours before he got to
-sleep. All the village flocked to the court-house the next morning, for
-this was to be the great day. Both sexes were about equally represented
-in the packed audience. After a long wait the jury filed in and took
-their places; shortly afterward, Potter, pale and haggard, timid and
-hopeless, was brought in, with chains upon him, and seated where all
-the curious eyes could stare at him; no less conspicuous was Injun Joe,
-stolid as ever. There was another pause, and then the judge arrived and
-the sheriff proclaimed the opening of the court. The usual whisperings
-among the lawyers and gathering together of papers followed. These
-details and accompanying delays worked up an atmosphere of preparation
-that was as impressive as it was fascinating.
-
-Now a witness was called who testified that he found Muff Potter
-washing in the brook, at an early hour of the morning that the murder
-was discovered, and that he immediately sneaked away. After some
-further questioning, counsel for the prosecution said:
-
-"Take the witness."
-
-The prisoner raised his eyes for a moment, but dropped them again when
-his own counsel said:
-
-"I have no questions to ask him."
-
-The next witness proved the finding of the knife near the corpse.
-Counsel for the prosecution said:
-
-"Take the witness."
-
-"I have no questions to ask him," Potter's lawyer replied.
-
-A third witness swore he had often seen the knife in Potter's
-possession.
-
-"Take the witness."
-
-Counsel for Potter declined to question him. The faces of the audience
-began to betray annoyance. Did this attorney mean to throw away his
-client's life without an effort?
-
-Several witnesses deposed concerning Potter's guilty behavior when
-brought to the scene of the murder. They were allowed to leave the
-stand without being cross-questioned.
-
-Every detail of the damaging circumstances that occurred in the
-graveyard upon that morning which all present remembered so well was
-brought out by credible witnesses, but none of them were cross-examined
-by Potter's lawyer. The perplexity and dissatisfaction of the house
-expressed itself in murmurs and provoked a reproof from the bench.
-Counsel for the prosecution now said:
-
-"By the oaths of citizens whose simple word is above suspicion, we
-have fastened this awful crime, beyond all possibility of question,
-upon the unhappy prisoner at the bar. We rest our case here."
-
-A groan escaped from poor Potter, and he put his face in his hands and
-rocked his body softly to and fro, while a painful silence reigned in
-the court-room. Many men were moved, and many women's compassion
-testified itself in tears. Counsel for the defence rose and said:
-
-"Your honor, in our remarks at the opening of this trial, we
-foreshadowed our purpose to prove that our client did this fearful deed
-while under the influence of a blind and irresponsible delirium
-produced by drink. We have changed our mind. We shall not offer that
-plea." [Then to the clerk:] "Call Thomas Sawyer!"
-
-A puzzled amazement awoke in every face in the house, not even
-excepting Potter's. Every eye fastened itself with wondering interest
-upon Tom as he rose and took his place upon the stand. The boy looked
-wild enough, for he was badly scared. The oath was administered.
-
-"Thomas Sawyer, where were you on the seventeenth of June, about the
-hour of midnight?"
-
-Tom glanced at Injun Joe's iron face and his tongue failed him. The
-audience listened breathless, but the words refused to come. After a
-few moments, however, the boy got a little of his strength back, and
-managed to put enough of it into his voice to make part of the house
-hear:
-
-"In the graveyard!"
-
-"A little bit louder, please. Don't be afraid. You were--"
-
-"In the graveyard."
-
-A contemptuous smile flitted across Injun Joe's face.
-
-"Were you anywhere near Horse Williams' grave?"
-
-"Yes, sir."
-
-"Speak up--just a trifle louder. How near were you?"
-
-"Near as I am to you."
-
-"Were you hidden, or not?"
-
-"I was hid."
-
-"Where?"
-
-"Behind the elms that's on the edge of the grave."
-
-Injun Joe gave a barely perceptible start.
-
-"Any one with you?"
-
-"Yes, sir. I went there with--"
-
-"Wait--wait a moment. Never mind mentioning your companion's name. We
-will produce him at the proper time. Did you carry anything there with
-you."
-
-Tom hesitated and looked confused.
-
-"Speak out, my boy--don't be diffident. The truth is always
-respectable. What did you take there?"
-
-"Only a--a--dead cat."
-
-There was a ripple of mirth, which the court checked.
-
-"We will produce the skeleton of that cat. Now, my boy, tell us
-everything that occurred--tell it in your own way--don't skip anything,
-and don't be afraid."
-
-Tom began--hesitatingly at first, but as he warmed to his subject his
-words flowed more and more easily; in a little while every sound ceased
-but his own voice; every eye fixed itself upon him; with parted lips
-and bated breath the audience hung upon his words, taking no note of
-time, rapt in the ghastly fascinations of the tale. The strain upon
-pent emotion reached its climax when the boy said:
-
-"--and as the doctor fetched the board around and Muff Potter fell,
-Injun Joe jumped with the knife and--"
-
-Crash! Quick as lightning the half-breed sprang for a window, tore his
-way through all opposers, and was gone!
-
-
-
-CHAPTER XXIV
-
-TOM was a glittering hero once more--the pet of the old, the envy of
-the young. His name even went into immortal print, for the village
-paper magnified him. There were some that believed he would be
-President, yet, if he escaped hanging.
-
-As usual, the fickle, unreasoning world took Muff Potter to its bosom
-and fondled him as lavishly as it had abused him before. But that sort
-of conduct is to the world's credit; therefore it is not well to find
-fault with it.
-
-Tom's days were days of splendor and exultation to him, but his nights
-were seasons of horror. Injun Joe infested all his dreams, and always
-with doom in his eye. Hardly any temptation could persuade the boy to
-stir abroad after nightfall. Poor Huck was in the same state of
-wretchedness and terror, for Tom had told the whole story to the lawyer
-the night before the great day of the trial, and Huck was sore afraid
-that his share in the business might leak out, yet, notwithstanding
-Injun Joe's flight had saved him the suffering of testifying in court.
-The poor fellow had got the attorney to promise secrecy, but what of
-that? Since Tom's harassed conscience had managed to drive him to the
-lawyer's house by night and wring a dread tale from lips that had been
-sealed with the dismalest and most formidable of oaths, Huck's
-confidence in the human race was well-nigh obliterated.
-
-Daily Muff Potter's gratitude made Tom glad he had spoken; but nightly
-he wished he had sealed up his tongue.
-
-Half the time Tom was afraid Injun Joe would never be captured; the
-other half he was afraid he would be. He felt sure he never could draw
-a safe breath again until that man was dead and he had seen the corpse.
-
-Rewards had been offered, the country had been scoured, but no Injun
-Joe was found. One of those omniscient and awe-inspiring marvels, a
-detective, came up from St. Louis, moused around, shook his head,
-looked wise, and made that sort of astounding success which members of
-that craft usually achieve. That is to say, he "found a clew." But you
-can't hang a "clew" for murder, and so after that detective had got
-through and gone home, Tom felt just as insecure as he was before.
-
-The slow days drifted on, and each left behind it a slightly lightened
-weight of apprehension.
-
-
-
-CHAPTER XXV
-
-THERE comes a time in every rightly-constructed boy's life when he has
-a raging desire to go somewhere and dig for hidden treasure. This
-desire suddenly came upon Tom one day. He sallied out to find Joe
-Harper, but failed of success. Next he sought Ben Rogers; he had gone
-fishing. Presently he stumbled upon Huck Finn the Red-Handed. Huck
-would answer. Tom took him to a private place and opened the matter to
-him confidentially. Huck was willing. Huck was always willing to take a
-hand in any enterprise that offered entertainment and required no
-capital, for he had a troublesome superabundance of that sort of time
-which is not money. "Where'll we dig?" said Huck.
-
-"Oh, most anywhere."
-
-"Why, is it hid all around?"
-
-"No, indeed it ain't. It's hid in mighty particular places, Huck
---sometimes on islands, sometimes in rotten chests under the end of a
-limb of an old dead tree, just where the shadow falls at midnight; but
-mostly under the floor in ha'nted houses."
-
-"Who hides it?"
-
-"Why, robbers, of course--who'd you reckon? Sunday-school
-sup'rintendents?"
-
-"I don't know. If 'twas mine I wouldn't hide it; I'd spend it and have
-a good time."
-
-"So would I. But robbers don't do that way. They always hide it and
-leave it there."
-
-"Don't they come after it any more?"
-
-"No, they think they will, but they generally forget the marks, or
-else they die. Anyway, it lays there a long time and gets rusty; and by
-and by somebody finds an old yellow paper that tells how to find the
-marks--a paper that's got to be ciphered over about a week because it's
-mostly signs and hy'roglyphics."
-
-"Hyro--which?"
-
-"Hy'roglyphics--pictures and things, you know, that don't seem to mean
-anything."
-
-"Have you got one of them papers, Tom?"
-
-"No."
-
-"Well then, how you going to find the marks?"
-
-"I don't want any marks. They always bury it under a ha'nted house or
-on an island, or under a dead tree that's got one limb sticking out.
-Well, we've tried Jackson's Island a little, and we can try it again
-some time; and there's the old ha'nted house up the Still-House branch,
-and there's lots of dead-limb trees--dead loads of 'em."
-
-"Is it under all of them?"
-
-"How you talk! No!"
-
-"Then how you going to know which one to go for?"
-
-"Go for all of 'em!"
-
-"Why, Tom, it'll take all summer."
-
-"Well, what of that? Suppose you find a brass pot with a hundred
-dollars in it, all rusty and gray, or rotten chest full of di'monds.
-How's that?"
-
-Huck's eyes glowed.
-
-"That's bully. Plenty bully enough for me. Just you gimme the hundred
-dollars and I don't want no di'monds."
-
-"All right. But I bet you I ain't going to throw off on di'monds. Some
-of 'em's worth twenty dollars apiece--there ain't any, hardly, but's
-worth six bits or a dollar."
-
-"No! Is that so?"
-
-"Cert'nly--anybody'll tell you so. Hain't you ever seen one, Huck?"
-
-"Not as I remember."
-
-"Oh, kings have slathers of them."
-
-"Well, I don' know no kings, Tom."
-
-"I reckon you don't. But if you was to go to Europe you'd see a raft
-of 'em hopping around."
-
-"Do they hop?"
-
-"Hop?--your granny! No!"
-
-"Well, what did you say they did, for?"
-
-"Shucks, I only meant you'd SEE 'em--not hopping, of course--what do
-they want to hop for?--but I mean you'd just see 'em--scattered around,
-you know, in a kind of a general way. Like that old humpbacked Richard."
-
-"Richard? What's his other name?"
-
-"He didn't have any other name. Kings don't have any but a given name."
-
-"No?"
-
-"But they don't."
-
-"Well, if they like it, Tom, all right; but I don't want to be a king
-and have only just a given name, like a nigger. But say--where you
-going to dig first?"
-
-"Well, I don't know. S'pose we tackle that old dead-limb tree on the
-hill t'other side of Still-House branch?"
-
-"I'm agreed."
-
-So they got a crippled pick and a shovel, and set out on their
-three-mile tramp. They arrived hot and panting, and threw themselves
-down in the shade of a neighboring elm to rest and have a smoke.
-
-"I like this," said Tom.
-
-"So do I."
-
-"Say, Huck, if we find a treasure here, what you going to do with your
-share?"
-
-"Well, I'll have pie and a glass of soda every day, and I'll go to
-every circus that comes along. I bet I'll have a gay time."
-
-"Well, ain't you going to save any of it?"
-
-"Save it? What for?"
-
-"Why, so as to have something to live on, by and by."
-
-"Oh, that ain't any use. Pap would come back to thish-yer town some
-day and get his claws on it if I didn't hurry up, and I tell you he'd
-clean it out pretty quick. What you going to do with yourn, Tom?"
-
-"I'm going to buy a new drum, and a sure-'nough sword, and a red
-necktie and a bull pup, and get married."
-
-"Married!"
-
-"That's it."
-
-"Tom, you--why, you ain't in your right mind."
-
-"Wait--you'll see."
-
-"Well, that's the foolishest thing you could do. Look at pap and my
-mother. Fight! Why, they used to fight all the time. I remember, mighty
-well."
-
-"That ain't anything. The girl I'm going to marry won't fight."
-
-"Tom, I reckon they're all alike. They'll all comb a body. Now you
-better think 'bout this awhile. I tell you you better. What's the name
-of the gal?"
-
-"It ain't a gal at all--it's a girl."
-
-"It's all the same, I reckon; some says gal, some says girl--both's
-right, like enough. Anyway, what's her name, Tom?"
-
-"I'll tell you some time--not now."
-
-"All right--that'll do. Only if you get married I'll be more lonesomer
-than ever."
-
-"No you won't. You'll come and live with me. Now stir out of this and
-we'll go to digging."
-
-They worked and sweated for half an hour. No result. They toiled
-another half-hour. Still no result. Huck said:
-
-"Do they always bury it as deep as this?"
-
-"Sometimes--not always. Not generally. I reckon we haven't got the
-right place."
-
-So they chose a new spot and began again. The labor dragged a little,
-but still they made progress. They pegged away in silence for some
-time. Finally Huck leaned on his shovel, swabbed the beaded drops from
-his brow with his sleeve, and said:
-
-"Where you going to dig next, after we get this one?"
-
-"I reckon maybe we'll tackle the old tree that's over yonder on
-Cardiff Hill back of the widow's."
-
-"I reckon that'll be a good one. But won't the widow take it away from
-us, Tom? It's on her land."
-
-"SHE take it away! Maybe she'd like to try it once. Whoever finds one
-of these hid treasures, it belongs to him. It don't make any difference
-whose land it's on."
-
-That was satisfactory. The work went on. By and by Huck said:
-
-"Blame it, we must be in the wrong place again. What do you think?"
-
-"It is mighty curious, Huck. I don't understand it. Sometimes witches
-interfere. I reckon maybe that's what's the trouble now."
-
-"Shucks! Witches ain't got no power in the daytime."
-
-"Well, that's so. I didn't think of that. Oh, I know what the matter
-is! What a blamed lot of fools we are! You got to find out where the
-shadow of the limb falls at midnight, and that's where you dig!"
-
-"Then consound it, we've fooled away all this work for nothing. Now
-hang it all, we got to come back in the night. It's an awful long way.
-Can you get out?"
-
-"I bet I will. We've got to do it to-night, too, because if somebody
-sees these holes they'll know in a minute what's here and they'll go
-for it."
-
-"Well, I'll come around and maow to-night."
-
-"All right. Let's hide the tools in the bushes."
-
-The boys were there that night, about the appointed time. They sat in
-the shadow waiting. It was a lonely place, and an hour made solemn by
-old traditions. Spirits whispered in the rustling leaves, ghosts lurked
-in the murky nooks, the deep baying of a hound floated up out of the
-distance, an owl answered with his sepulchral note. The boys were
-subdued by these solemnities, and talked little. By and by they judged
-that twelve had come; they marked where the shadow fell, and began to
-dig. Their hopes commenced to rise. Their interest grew stronger, and
-their industry kept pace with it. The hole deepened and still deepened,
-but every time their hearts jumped to hear the pick strike upon
-something, they only suffered a new disappointment. It was only a stone
-or a chunk. At last Tom said:
-
-"It ain't any use, Huck, we're wrong again."
-
-"Well, but we CAN'T be wrong. We spotted the shadder to a dot."
-
-"I know it, but then there's another thing."
-
-"What's that?".
-
-"Why, we only guessed at the time. Like enough it was too late or too
-early."
-
-Huck dropped his shovel.
-
-"That's it," said he. "That's the very trouble. We got to give this
-one up. We can't ever tell the right time, and besides this kind of
-thing's too awful, here this time of night with witches and ghosts
-a-fluttering around so. I feel as if something's behind me all the time;
-and I'm afeard to turn around, becuz maybe there's others in front
-a-waiting for a chance. I been creeping all over, ever since I got here."
-
-"Well, I've been pretty much so, too, Huck. They most always put in a
-dead man when they bury a treasure under a tree, to look out for it."
-
-"Lordy!"
-
-"Yes, they do. I've always heard that."
-
-"Tom, I don't like to fool around much where there's dead people. A
-body's bound to get into trouble with 'em, sure."
-
-"I don't like to stir 'em up, either. S'pose this one here was to
-stick his skull out and say something!"
-
-"Don't Tom! It's awful."
-
-"Well, it just is. Huck, I don't feel comfortable a bit."
-
-"Say, Tom, let's give this place up, and try somewheres else."
-
-"All right, I reckon we better."
-
-"What'll it be?"
-
-Tom considered awhile; and then said:
-
-"The ha'nted house. That's it!"
-
-"Blame it, I don't like ha'nted houses, Tom. Why, they're a dern sight
-worse'n dead people. Dead people might talk, maybe, but they don't come
-sliding around in a shroud, when you ain't noticing, and peep over your
-shoulder all of a sudden and grit their teeth, the way a ghost does. I
-couldn't stand such a thing as that, Tom--nobody could."
-
-"Yes, but, Huck, ghosts don't travel around only at night. They won't
-hender us from digging there in the daytime."
-
-"Well, that's so. But you know mighty well people don't go about that
-ha'nted house in the day nor the night."
-
-"Well, that's mostly because they don't like to go where a man's been
-murdered, anyway--but nothing's ever been seen around that house except
-in the night--just some blue lights slipping by the windows--no regular
-ghosts."
-
-"Well, where you see one of them blue lights flickering around, Tom,
-you can bet there's a ghost mighty close behind it. It stands to
-reason. Becuz you know that they don't anybody but ghosts use 'em."
-
-"Yes, that's so. But anyway they don't come around in the daytime, so
-what's the use of our being afeard?"
-
-"Well, all right. We'll tackle the ha'nted house if you say so--but I
-reckon it's taking chances."
-
-They had started down the hill by this time. There in the middle of
-the moonlit valley below them stood the "ha'nted" house, utterly
-isolated, its fences gone long ago, rank weeds smothering the very
-doorsteps, the chimney crumbled to ruin, the window-sashes vacant, a
-corner of the roof caved in. The boys gazed awhile, half expecting to
-see a blue light flit past a window; then talking in a low tone, as
-befitted the time and the circumstances, they struck far off to the
-right, to give the haunted house a wide berth, and took their way
-homeward through the woods that adorned the rearward side of Cardiff
-Hill.
-
-
-
-CHAPTER XXVI
-
-ABOUT noon the next day the boys arrived at the dead tree; they had
-come for their tools. Tom was impatient to go to the haunted house;
-Huck was measurably so, also--but suddenly said:
-
-"Lookyhere, Tom, do you know what day it is?"
-
-Tom mentally ran over the days of the week, and then quickly lifted
-his eyes with a startled look in them--
-
-"My! I never once thought of it, Huck!"
-
-"Well, I didn't neither, but all at once it popped onto me that it was
-Friday."
-
-"Blame it, a body can't be too careful, Huck. We might 'a' got into an
-awful scrape, tackling such a thing on a Friday."
-
-"MIGHT! Better say we WOULD! There's some lucky days, maybe, but
-Friday ain't."
-
-"Any fool knows that. I don't reckon YOU was the first that found it
-out, Huck."
-
-"Well, I never said I was, did I? And Friday ain't all, neither. I had
-a rotten bad dream last night--dreampt about rats."
-
-"No! Sure sign of trouble. Did they fight?"
-
-"No."
-
-"Well, that's good, Huck. When they don't fight it's only a sign that
-there's trouble around, you know. All we got to do is to look mighty
-sharp and keep out of it. We'll drop this thing for to-day, and play.
-Do you know Robin Hood, Huck?"
-
-"No. Who's Robin Hood?"
-
-"Why, he was one of the greatest men that was ever in England--and the
-best. He was a robber."
-
-"Cracky, I wisht I was. Who did he rob?"
-
-"Only sheriffs and bishops and rich people and kings, and such like.
-But he never bothered the poor. He loved 'em. He always divided up with
-'em perfectly square."
-
-"Well, he must 'a' been a brick."
-
-"I bet you he was, Huck. Oh, he was the noblest man that ever was.
-They ain't any such men now, I can tell you. He could lick any man in
-England, with one hand tied behind him; and he could take his yew bow
-and plug a ten-cent piece every time, a mile and a half."
-
-"What's a YEW bow?"
-
-"I don't know. It's some kind of a bow, of course. And if he hit that
-dime only on the edge he would set down and cry--and curse. But we'll
-play Robin Hood--it's nobby fun. I'll learn you."
-
-"I'm agreed."
-
-So they played Robin Hood all the afternoon, now and then casting a
-yearning eye down upon the haunted house and passing a remark about the
-morrow's prospects and possibilities there. As the sun began to sink
-into the west they took their way homeward athwart the long shadows of
-the trees and soon were buried from sight in the forests of Cardiff
-Hill.
-
-On Saturday, shortly after noon, the boys were at the dead tree again.
-They had a smoke and a chat in the shade, and then dug a little in
-their last hole, not with great hope, but merely because Tom said there
-were so many cases where people had given up a treasure after getting
-down within six inches of it, and then somebody else had come along and
-turned it up with a single thrust of a shovel. The thing failed this
-time, however, so the boys shouldered their tools and went away feeling
-that they had not trifled with fortune, but had fulfilled all the
-requirements that belong to the business of treasure-hunting.
-
-When they reached the haunted house there was something so weird and
-grisly about the dead silence that reigned there under the baking sun,
-and something so depressing about the loneliness and desolation of the
-place, that they were afraid, for a moment, to venture in. Then they
-crept to the door and took a trembling peep. They saw a weed-grown,
-floorless room, unplastered, an ancient fireplace, vacant windows, a
-ruinous staircase; and here, there, and everywhere hung ragged and
-abandoned cobwebs. They presently entered, softly, with quickened
-pulses, talking in whispers, ears alert to catch the slightest sound,
-and muscles tense and ready for instant retreat.
-
-In a little while familiarity modified their fears and they gave the
-place a critical and interested examination, rather admiring their own
-boldness, and wondering at it, too. Next they wanted to look up-stairs.
-This was something like cutting off retreat, but they got to daring
-each other, and of course there could be but one result--they threw
-their tools into a corner and made the ascent. Up there were the same
-signs of decay. In one corner they found a closet that promised
-mystery, but the promise was a fraud--there was nothing in it. Their
-courage was up now and well in hand. They were about to go down and
-begin work when--
-
-"Sh!" said Tom.
-
-"What is it?" whispered Huck, blanching with fright.
-
-"Sh!... There!... Hear it?"
-
-"Yes!... Oh, my! Let's run!"
-
-"Keep still! Don't you budge! They're coming right toward the door."
-
-The boys stretched themselves upon the floor with their eyes to
-knot-holes in the planking, and lay waiting, in a misery of fear.
-
-"They've stopped.... No--coming.... Here they are. Don't whisper
-another word, Huck. My goodness, I wish I was out of this!"
-
-Two men entered. Each boy said to himself: "There's the old deaf and
-dumb Spaniard that's been about town once or twice lately--never saw
-t'other man before."
-
-"T'other" was a ragged, unkempt creature, with nothing very pleasant
-in his face. The Spaniard was wrapped in a serape; he had bushy white
-whiskers; long white hair flowed from under his sombrero, and he wore
-green goggles. When they came in, "t'other" was talking in a low voice;
-they sat down on the ground, facing the door, with their backs to the
-wall, and the speaker continued his remarks. His manner became less
-guarded and his words more distinct as he proceeded:
-
-"No," said he, "I've thought it all over, and I don't like it. It's
-dangerous."
-
-"Dangerous!" grunted the "deaf and dumb" Spaniard--to the vast
-surprise of the boys. "Milksop!"
-
-This voice made the boys gasp and quake. It was Injun Joe's! There was
-silence for some time. Then Joe said:
-
-"What's any more dangerous than that job up yonder--but nothing's come
-of it."
-
-"That's different. Away up the river so, and not another house about.
-'Twon't ever be known that we tried, anyway, long as we didn't succeed."
-
-"Well, what's more dangerous than coming here in the daytime!--anybody
-would suspicion us that saw us."
-
-"I know that. But there warn't any other place as handy after that
-fool of a job. I want to quit this shanty. I wanted to yesterday, only
-it warn't any use trying to stir out of here, with those infernal boys
-playing over there on the hill right in full view."
-
-"Those infernal boys" quaked again under the inspiration of this
-remark, and thought how lucky it was that they had remembered it was
-Friday and concluded to wait a day. They wished in their hearts they
-had waited a year.
-
-The two men got out some food and made a luncheon. After a long and
-thoughtful silence, Injun Joe said:
-
-"Look here, lad--you go back up the river where you belong. Wait there
-till you hear from me. I'll take the chances on dropping into this town
-just once more, for a look. We'll do that 'dangerous' job after I've
-spied around a little and think things look well for it. Then for
-Texas! We'll leg it together!"
-
-This was satisfactory. Both men presently fell to yawning, and Injun
-Joe said:
-
-"I'm dead for sleep! It's your turn to watch."
-
-He curled down in the weeds and soon began to snore. His comrade
-stirred him once or twice and he became quiet. Presently the watcher
-began to nod; his head drooped lower and lower, both men began to snore
-now.
-
-The boys drew a long, grateful breath. Tom whispered:
-
-"Now's our chance--come!"
-
-Huck said:
-
-"I can't--I'd die if they was to wake."
-
-Tom urged--Huck held back. At last Tom rose slowly and softly, and
-started alone. But the first step he made wrung such a hideous creak
-from the crazy floor that he sank down almost dead with fright. He
-never made a second attempt. The boys lay there counting the dragging
-moments till it seemed to them that time must be done and eternity
-growing gray; and then they were grateful to note that at last the sun
-was setting.
-
-Now one snore ceased. Injun Joe sat up, stared around--smiled grimly
-upon his comrade, whose head was drooping upon his knees--stirred him
-up with his foot and said:
-
-"Here! YOU'RE a watchman, ain't you! All right, though--nothing's
-happened."
-
-"My! have I been asleep?"
-
-"Oh, partly, partly. Nearly time for us to be moving, pard. What'll we
-do with what little swag we've got left?"
-
-"I don't know--leave it here as we've always done, I reckon. No use to
-take it away till we start south. Six hundred and fifty in silver's
-something to carry."
-
-"Well--all right--it won't matter to come here once more."
-
-"No--but I'd say come in the night as we used to do--it's better."
-
-"Yes: but look here; it may be a good while before I get the right
-chance at that job; accidents might happen; 'tain't in such a very good
-place; we'll just regularly bury it--and bury it deep."
-
-"Good idea," said the comrade, who walked across the room, knelt down,
-raised one of the rearward hearth-stones and took out a bag that
-jingled pleasantly. He subtracted from it twenty or thirty dollars for
-himself and as much for Injun Joe, and passed the bag to the latter,
-who was on his knees in the corner, now, digging with his bowie-knife.
-
-The boys forgot all their fears, all their miseries in an instant.
-With gloating eyes they watched every movement. Luck!--the splendor of
-it was beyond all imagination! Six hundred dollars was money enough to
-make half a dozen boys rich! Here was treasure-hunting under the
-happiest auspices--there would not be any bothersome uncertainty as to
-where to dig. They nudged each other every moment--eloquent nudges and
-easily understood, for they simply meant--"Oh, but ain't you glad NOW
-we're here!"
-
-Joe's knife struck upon something.
-
-"Hello!" said he.
-
-"What is it?" said his comrade.
-
-"Half-rotten plank--no, it's a box, I believe. Here--bear a hand and
-we'll see what it's here for. Never mind, I've broke a hole."
-
-He reached his hand in and drew it out--
-
-"Man, it's money!"
-
-The two men examined the handful of coins. They were gold. The boys
-above were as excited as themselves, and as delighted.
-
-Joe's comrade said:
-
-"We'll make quick work of this. There's an old rusty pick over amongst
-the weeds in the corner the other side of the fireplace--I saw it a
-minute ago."
-
-He ran and brought the boys' pick and shovel. Injun Joe took the pick,
-looked it over critically, shook his head, muttered something to
-himself, and then began to use it. The box was soon unearthed. It was
-not very large; it was iron bound and had been very strong before the
-slow years had injured it. The men contemplated the treasure awhile in
-blissful silence.
-
-"Pard, there's thousands of dollars here," said Injun Joe.
-
-"'Twas always said that Murrel's gang used to be around here one
-summer," the stranger observed.
-
-"I know it," said Injun Joe; "and this looks like it, I should say."
-
-"Now you won't need to do that job."
-
-The half-breed frowned. Said he:
-
-"You don't know me. Least you don't know all about that thing. 'Tain't
-robbery altogether--it's REVENGE!" and a wicked light flamed in his
-eyes. "I'll need your help in it. When it's finished--then Texas. Go
-home to your Nance and your kids, and stand by till you hear from me."
-
-"Well--if you say so; what'll we do with this--bury it again?"
-
-"Yes. [Ravishing delight overhead.] NO! by the great Sachem, no!
-[Profound distress overhead.] I'd nearly forgot. That pick had fresh
-earth on it! [The boys were sick with terror in a moment.] What
-business has a pick and a shovel here? What business with fresh earth
-on them? Who brought them here--and where are they gone? Have you heard
-anybody?--seen anybody? What! bury it again and leave them to come and
-see the ground disturbed? Not exactly--not exactly. We'll take it to my
-den."
-
-"Why, of course! Might have thought of that before. You mean Number
-One?"
-
-"No--Number Two--under the cross. The other place is bad--too common."
-
-"All right. It's nearly dark enough to start."
-
-Injun Joe got up and went about from window to window cautiously
-peeping out. Presently he said:
-
-"Who could have brought those tools here? Do you reckon they can be
-up-stairs?"
-
-The boys' breath forsook them. Injun Joe put his hand on his knife,
-halted a moment, undecided, and then turned toward the stairway. The
-boys thought of the closet, but their strength was gone. The steps came
-creaking up the stairs--the intolerable distress of the situation woke
-the stricken resolution of the lads--they were about to spring for the
-closet, when there was a crash of rotten timbers and Injun Joe landed
-on the ground amid the debris of the ruined stairway. He gathered
-himself up cursing, and his comrade said:
-
-"Now what's the use of all that? If it's anybody, and they're up
-there, let them STAY there--who cares? If they want to jump down, now,
-and get into trouble, who objects? It will be dark in fifteen minutes
---and then let them follow us if they want to. I'm willing. In my
-opinion, whoever hove those things in here caught a sight of us and
-took us for ghosts or devils or something. I'll bet they're running
-yet."
-
-Joe grumbled awhile; then he agreed with his friend that what daylight
-was left ought to be economized in getting things ready for leaving.
-Shortly afterward they slipped out of the house in the deepening
-twilight, and moved toward the river with their precious box.
-
-Tom and Huck rose up, weak but vastly relieved, and stared after them
-through the chinks between the logs of the house. Follow? Not they.
-They were content to reach ground again without broken necks, and take
-the townward track over the hill. They did not talk much. They were too
-much absorbed in hating themselves--hating the ill luck that made them
-take the spade and the pick there. But for that, Injun Joe never would
-have suspected. He would have hidden the silver with the gold to wait
-there till his "revenge" was satisfied, and then he would have had the
-misfortune to find that money turn up missing. Bitter, bitter luck that
-the tools were ever brought there!
-
-They resolved to keep a lookout for that Spaniard when he should come
-to town spying out for chances to do his revengeful job, and follow him
-to "Number Two," wherever that might be. Then a ghastly thought
-occurred to Tom.
-
-"Revenge? What if he means US, Huck!"
-
-"Oh, don't!" said Huck, nearly fainting.
-
-They talked it all over, and as they entered town they agreed to
-believe that he might possibly mean somebody else--at least that he
-might at least mean nobody but Tom, since only Tom had testified.
-
-Very, very small comfort it was to Tom to be alone in danger! Company
-would be a palpable improvement, he thought.
-
-
-
-CHAPTER XXVII
-
-THE adventure of the day mightily tormented Tom's dreams that night.
-Four times he had his hands on that rich treasure and four times it
-wasted to nothingness in his fingers as sleep forsook him and
-wakefulness brought back the hard reality of his misfortune. As he lay
-in the early morning recalling the incidents of his great adventure, he
-noticed that they seemed curiously subdued and far away--somewhat as if
-they had happened in another world, or in a time long gone by. Then it
-occurred to him that the great adventure itself must be a dream! There
-was one very strong argument in favor of this idea--namely, that the
-quantity of coin he had seen was too vast to be real. He had never seen
-as much as fifty dollars in one mass before, and he was like all boys
-of his age and station in life, in that he imagined that all references
-to "hundreds" and "thousands" were mere fanciful forms of speech, and
-that no such sums really existed in the world. He never had supposed
-for a moment that so large a sum as a hundred dollars was to be found
-in actual money in any one's possession. If his notions of hidden
-treasure had been analyzed, they would have been found to consist of a
-handful of real dimes and a bushel of vague, splendid, ungraspable
-dollars.
-
-But the incidents of his adventure grew sensibly sharper and clearer
-under the attrition of thinking them over, and so he presently found
-himself leaning to the impression that the thing might not have been a
-dream, after all. This uncertainty must be swept away. He would snatch
-a hurried breakfast and go and find Huck. Huck was sitting on the
-gunwale of a flatboat, listlessly dangling his feet in the water and
-looking very melancholy. Tom concluded to let Huck lead up to the
-subject. If he did not do it, then the adventure would be proved to
-have been only a dream.
-
-"Hello, Huck!"
-
-"Hello, yourself."
-
-Silence, for a minute.
-
-"Tom, if we'd 'a' left the blame tools at the dead tree, we'd 'a' got
-the money. Oh, ain't it awful!"
-
-"'Tain't a dream, then, 'tain't a dream! Somehow I most wish it was.
-Dog'd if I don't, Huck."
-
-"What ain't a dream?"
-
-"Oh, that thing yesterday. I been half thinking it was."
-
-"Dream! If them stairs hadn't broke down you'd 'a' seen how much dream
-it was! I've had dreams enough all night--with that patch-eyed Spanish
-devil going for me all through 'em--rot him!"
-
-"No, not rot him. FIND him! Track the money!"
-
-"Tom, we'll never find him. A feller don't have only one chance for
-such a pile--and that one's lost. I'd feel mighty shaky if I was to see
-him, anyway."
-
-"Well, so'd I; but I'd like to see him, anyway--and track him out--to
-his Number Two."
-
-"Number Two--yes, that's it. I been thinking 'bout that. But I can't
-make nothing out of it. What do you reckon it is?"
-
-"I dono. It's too deep. Say, Huck--maybe it's the number of a house!"
-
-"Goody!... No, Tom, that ain't it. If it is, it ain't in this
-one-horse town. They ain't no numbers here."
-
-"Well, that's so. Lemme think a minute. Here--it's the number of a
-room--in a tavern, you know!"
-
-"Oh, that's the trick! They ain't only two taverns. We can find out
-quick."
-
-"You stay here, Huck, till I come."
-
-Tom was off at once. He did not care to have Huck's company in public
-places. He was gone half an hour. He found that in the best tavern, No.
-2 had long been occupied by a young lawyer, and was still so occupied.
-In the less ostentatious house, No. 2 was a mystery. The
-tavern-keeper's young son said it was kept locked all the time, and he
-never saw anybody go into it or come out of it except at night; he did
-not know any particular reason for this state of things; had had some
-little curiosity, but it was rather feeble; had made the most of the
-mystery by entertaining himself with the idea that that room was
-"ha'nted"; had noticed that there was a light in there the night before.
-
-"That's what I've found out, Huck. I reckon that's the very No. 2
-we're after."
-
-"I reckon it is, Tom. Now what you going to do?"
-
-"Lemme think."
-
-Tom thought a long time. Then he said:
-
-"I'll tell you. The back door of that No. 2 is the door that comes out
-into that little close alley between the tavern and the old rattle trap
-of a brick store. Now you get hold of all the door-keys you can find,
-and I'll nip all of auntie's, and the first dark night we'll go there
-and try 'em. And mind you, keep a lookout for Injun Joe, because he
-said he was going to drop into town and spy around once more for a
-chance to get his revenge. If you see him, you just follow him; and if
-he don't go to that No. 2, that ain't the place."
-
-"Lordy, I don't want to foller him by myself!"
-
-"Why, it'll be night, sure. He mightn't ever see you--and if he did,
-maybe he'd never think anything."
-
-"Well, if it's pretty dark I reckon I'll track him. I dono--I dono.
-I'll try."
-
-"You bet I'll follow him, if it's dark, Huck. Why, he might 'a' found
-out he couldn't get his revenge, and be going right after that money."
-
-"It's so, Tom, it's so. I'll foller him; I will, by jingoes!"
-
-"Now you're TALKING! Don't you ever weaken, Huck, and I won't."
-
-
-
-CHAPTER XXVIII
-
-THAT night Tom and Huck were ready for their adventure. They hung
-about the neighborhood of the tavern until after nine, one watching the
-alley at a distance and the other the tavern door. Nobody entered the
-alley or left it; nobody resembling the Spaniard entered or left the
-tavern door. The night promised to be a fair one; so Tom went home with
-the understanding that if a considerable degree of darkness came on,
-Huck was to come and "maow," whereupon he would slip out and try the
-keys. But the night remained clear, and Huck closed his watch and
-retired to bed in an empty sugar hogshead about twelve.
-
-Tuesday the boys had the same ill luck. Also Wednesday. But Thursday
-night promised better. Tom slipped out in good season with his aunt's
-old tin lantern, and a large towel to blindfold it with. He hid the
-lantern in Huck's sugar hogshead and the watch began. An hour before
-midnight the tavern closed up and its lights (the only ones
-thereabouts) were put out. No Spaniard had been seen. Nobody had
-entered or left the alley. Everything was auspicious. The blackness of
-darkness reigned, the perfect stillness was interrupted only by
-occasional mutterings of distant thunder.
-
-Tom got his lantern, lit it in the hogshead, wrapped it closely in the
-towel, and the two adventurers crept in the gloom toward the tavern.
-Huck stood sentry and Tom felt his way into the alley. Then there was a
-season of waiting anxiety that weighed upon Huck's spirits like a
-mountain. He began to wish he could see a flash from the lantern--it
-would frighten him, but it would at least tell him that Tom was alive
-yet. It seemed hours since Tom had disappeared. Surely he must have
-fainted; maybe he was dead; maybe his heart had burst under terror and
-excitement. In his uneasiness Huck found himself drawing closer and
-closer to the alley; fearing all sorts of dreadful things, and
-momentarily expecting some catastrophe to happen that would take away
-his breath. There was not much to take away, for he seemed only able to
-inhale it by thimblefuls, and his heart would soon wear itself out, the
-way it was beating. Suddenly there was a flash of light and Tom came
-tearing by him: "Run!" said he; "run, for your life!"
-
-He needn't have repeated it; once was enough; Huck was making thirty
-or forty miles an hour before the repetition was uttered. The boys
-never stopped till they reached the shed of a deserted slaughter-house
-at the lower end of the village. Just as they got within its shelter
-the storm burst and the rain poured down. As soon as Tom got his breath
-he said:
-
-"Huck, it was awful! I tried two of the keys, just as soft as I could;
-but they seemed to make such a power of racket that I couldn't hardly
-get my breath I was so scared. They wouldn't turn in the lock, either.
-Well, without noticing what I was doing, I took hold of the knob, and
-open comes the door! It warn't locked! I hopped in, and shook off the
-towel, and, GREAT CAESAR'S GHOST!"
-
-"What!--what'd you see, Tom?"
-
-"Huck, I most stepped onto Injun Joe's hand!"
-
-"No!"
-
-"Yes! He was lying there, sound asleep on the floor, with his old
-patch on his eye and his arms spread out."
-
-"Lordy, what did you do? Did he wake up?"
-
-"No, never budged. Drunk, I reckon. I just grabbed that towel and
-started!"
-
-"I'd never 'a' thought of the towel, I bet!"
-
-"Well, I would. My aunt would make me mighty sick if I lost it."
-
-"Say, Tom, did you see that box?"
-
-"Huck, I didn't wait to look around. I didn't see the box, I didn't
-see the cross. I didn't see anything but a bottle and a tin cup on the
-floor by Injun Joe; yes, I saw two barrels and lots more bottles in the
-room. Don't you see, now, what's the matter with that ha'nted room?"
-
-"How?"
-
-"Why, it's ha'nted with whiskey! Maybe ALL the Temperance Taverns have
-got a ha'nted room, hey, Huck?"
-
-"Well, I reckon maybe that's so. Who'd 'a' thought such a thing? But
-say, Tom, now's a mighty good time to get that box, if Injun Joe's
-drunk."
-
-"It is, that! You try it!"
-
-Huck shuddered.
-
-"Well, no--I reckon not."
-
-"And I reckon not, Huck. Only one bottle alongside of Injun Joe ain't
-enough. If there'd been three, he'd be drunk enough and I'd do it."
-
-There was a long pause for reflection, and then Tom said:
-
-"Lookyhere, Huck, less not try that thing any more till we know Injun
-Joe's not in there. It's too scary. Now, if we watch every night, we'll
-be dead sure to see him go out, some time or other, and then we'll
-snatch that box quicker'n lightning."
-
-"Well, I'm agreed. I'll watch the whole night long, and I'll do it
-every night, too, if you'll do the other part of the job."
-
-"All right, I will. All you got to do is to trot up Hooper Street a
-block and maow--and if I'm asleep, you throw some gravel at the window
-and that'll fetch me."
-
-"Agreed, and good as wheat!"
-
-"Now, Huck, the storm's over, and I'll go home. It'll begin to be
-daylight in a couple of hours. You go back and watch that long, will
-you?"
-
-"I said I would, Tom, and I will. I'll ha'nt that tavern every night
-for a year! I'll sleep all day and I'll stand watch all night."
-
-"That's all right. Now, where you going to sleep?"
-
-"In Ben Rogers' hayloft. He lets me, and so does his pap's nigger man,
-Uncle Jake. I tote water for Uncle Jake whenever he wants me to, and
-any time I ask him he gives me a little something to eat if he can
-spare it. That's a mighty good nigger, Tom. He likes me, becuz I don't
-ever act as if I was above him. Sometime I've set right down and eat
-WITH him. But you needn't tell that. A body's got to do things when
-he's awful hungry he wouldn't want to do as a steady thing."
-
-"Well, if I don't want you in the daytime, I'll let you sleep. I won't
-come bothering around. Any time you see something's up, in the night,
-just skip right around and maow."
-
-
-
-CHAPTER XXIX
-
-THE first thing Tom heard on Friday morning was a glad piece of news
---Judge Thatcher's family had come back to town the night before. Both
-Injun Joe and the treasure sunk into secondary importance for a moment,
-and Becky took the chief place in the boy's interest. He saw her and
-they had an exhausting good time playing "hi-spy" and "gully-keeper"
-with a crowd of their school-mates. The day was completed and crowned
-in a peculiarly satisfactory way: Becky teased her mother to appoint
-the next day for the long-promised and long-delayed picnic, and she
-consented. The child's delight was boundless; and Tom's not more
-moderate. The invitations were sent out before sunset, and straightway
-the young folks of the village were thrown into a fever of preparation
-and pleasurable anticipation. Tom's excitement enabled him to keep
-awake until a pretty late hour, and he had good hopes of hearing Huck's
-"maow," and of having his treasure to astonish Becky and the picnickers
-with, next day; but he was disappointed. No signal came that night.
-
-Morning came, eventually, and by ten or eleven o'clock a giddy and
-rollicking company were gathered at Judge Thatcher's, and everything
-was ready for a start. It was not the custom for elderly people to mar
-the picnics with their presence. The children were considered safe
-enough under the wings of a few young ladies of eighteen and a few
-young gentlemen of twenty-three or thereabouts. The old steam ferryboat
-was chartered for the occasion; presently the gay throng filed up the
-main street laden with provision-baskets. Sid was sick and had to miss
-the fun; Mary remained at home to entertain him. The last thing Mrs.
-Thatcher said to Becky, was:
-
-"You'll not get back till late. Perhaps you'd better stay all night
-with some of the girls that live near the ferry-landing, child."
-
-"Then I'll stay with Susy Harper, mamma."
-
-"Very well. And mind and behave yourself and don't be any trouble."
-
-Presently, as they tripped along, Tom said to Becky:
-
-"Say--I'll tell you what we'll do. 'Stead of going to Joe Harper's
-we'll climb right up the hill and stop at the Widow Douglas'. She'll
-have ice-cream! She has it most every day--dead loads of it. And she'll
-be awful glad to have us."
-
-"Oh, that will be fun!"
-
-Then Becky reflected a moment and said:
-
-"But what will mamma say?"
-
-"How'll she ever know?"
-
-The girl turned the idea over in her mind, and said reluctantly:
-
-"I reckon it's wrong--but--"
-
-"But shucks! Your mother won't know, and so what's the harm? All she
-wants is that you'll be safe; and I bet you she'd 'a' said go there if
-she'd 'a' thought of it. I know she would!"
-
-The Widow Douglas' splendid hospitality was a tempting bait. It and
-Tom's persuasions presently carried the day. So it was decided to say
-nothing anybody about the night's programme. Presently it occurred to
-Tom that maybe Huck might come this very night and give the signal. The
-thought took a deal of the spirit out of his anticipations. Still he
-could not bear to give up the fun at Widow Douglas'. And why should he
-give it up, he reasoned--the signal did not come the night before, so
-why should it be any more likely to come to-night? The sure fun of the
-evening outweighed the uncertain treasure; and, boy-like, he determined
-to yield to the stronger inclination and not allow himself to think of
-the box of money another time that day.
-
-Three miles below town the ferryboat stopped at the mouth of a woody
-hollow and tied up. The crowd swarmed ashore and soon the forest
-distances and craggy heights echoed far and near with shoutings and
-laughter. All the different ways of getting hot and tired were gone
-through with, and by-and-by the rovers straggled back to camp fortified
-with responsible appetites, and then the destruction of the good things
-began. After the feast there was a refreshing season of rest and chat
-in the shade of spreading oaks. By-and-by somebody shouted:
-
-"Who's ready for the cave?"
-
-Everybody was. Bundles of candles were procured, and straightway there
-was a general scamper up the hill. The mouth of the cave was up the
-hillside--an opening shaped like a letter A. Its massive oaken door
-stood unbarred. Within was a small chamber, chilly as an ice-house, and
-walled by Nature with solid limestone that was dewy with a cold sweat.
-It was romantic and mysterious to stand here in the deep gloom and look
-out upon the green valley shining in the sun. But the impressiveness of
-the situation quickly wore off, and the romping began again. The moment
-a candle was lighted there was a general rush upon the owner of it; a
-struggle and a gallant defence followed, but the candle was soon
-knocked down or blown out, and then there was a glad clamor of laughter
-and a new chase. But all things have an end. By-and-by the procession
-went filing down the steep descent of the main avenue, the flickering
-rank of lights dimly revealing the lofty walls of rock almost to their
-point of junction sixty feet overhead. This main avenue was not more
-than eight or ten feet wide. Every few steps other lofty and still
-narrower crevices branched from it on either hand--for McDougal's cave
-was but a vast labyrinth of crooked aisles that ran into each other and
-out again and led nowhere. It was said that one might wander days and
-nights together through its intricate tangle of rifts and chasms, and
-never find the end of the cave; and that he might go down, and down,
-and still down, into the earth, and it was just the same--labyrinth
-under labyrinth, and no end to any of them. No man "knew" the cave.
-That was an impossible thing. Most of the young men knew a portion of
-it, and it was not customary to venture much beyond this known portion.
-Tom Sawyer knew as much of the cave as any one.
-
-The procession moved along the main avenue some three-quarters of a
-mile, and then groups and couples began to slip aside into branch
-avenues, fly along the dismal corridors, and take each other by
-surprise at points where the corridors joined again. Parties were able
-to elude each other for the space of half an hour without going beyond
-the "known" ground.
-
-By-and-by, one group after another came straggling back to the mouth
-of the cave, panting, hilarious, smeared from head to foot with tallow
-drippings, daubed with clay, and entirely delighted with the success of
-the day. Then they were astonished to find that they had been taking no
-note of time and that night was about at hand. The clanging bell had
-been calling for half an hour. However, this sort of close to the day's
-adventures was romantic and therefore satisfactory. When the ferryboat
-with her wild freight pushed into the stream, nobody cared sixpence for
-the wasted time but the captain of the craft.
-
-Huck was already upon his watch when the ferryboat's lights went
-glinting past the wharf. He heard no noise on board, for the young
-people were as subdued and still as people usually are who are nearly
-tired to death. He wondered what boat it was, and why she did not stop
-at the wharf--and then he dropped her out of his mind and put his
-attention upon his business. The night was growing cloudy and dark. Ten
-o'clock came, and the noise of vehicles ceased, scattered lights began
-to wink out, all straggling foot-passengers disappeared, the village
-betook itself to its slumbers and left the small watcher alone with the
-silence and the ghosts. Eleven o'clock came, and the tavern lights were
-put out; darkness everywhere, now. Huck waited what seemed a weary long
-time, but nothing happened. His faith was weakening. Was there any use?
-Was there really any use? Why not give it up and turn in?
-
-A noise fell upon his ear. He was all attention in an instant. The
-alley door closed softly. He sprang to the corner of the brick store.
-The next moment two men brushed by him, and one seemed to have
-something under his arm. It must be that box! So they were going to
-remove the treasure. Why call Tom now? It would be absurd--the men
-would get away with the box and never be found again. No, he would
-stick to their wake and follow them; he would trust to the darkness for
-security from discovery. So communing with himself, Huck stepped out
-and glided along behind the men, cat-like, with bare feet, allowing
-them to keep just far enough ahead not to be invisible.
-
-They moved up the river street three blocks, then turned to the left
-up a cross-street. They went straight ahead, then, until they came to
-the path that led up Cardiff Hill; this they took. They passed by the
-old Welshman's house, half-way up the hill, without hesitating, and
-still climbed upward. Good, thought Huck, they will bury it in the old
-quarry. But they never stopped at the quarry. They passed on, up the
-summit. They plunged into the narrow path between the tall sumach
-bushes, and were at once hidden in the gloom. Huck closed up and
-shortened his distance, now, for they would never be able to see him.
-He trotted along awhile; then slackened his pace, fearing he was
-gaining too fast; moved on a piece, then stopped altogether; listened;
-no sound; none, save that he seemed to hear the beating of his own
-heart. The hooting of an owl came over the hill--ominous sound! But no
-footsteps. Heavens, was everything lost! He was about to spring with
-winged feet, when a man cleared his throat not four feet from him!
-Huck's heart shot into his throat, but he swallowed it again; and then
-he stood there shaking as if a dozen agues had taken charge of him at
-once, and so weak that he thought he must surely fall to the ground. He
-knew where he was. He knew he was within five steps of the stile
-leading into Widow Douglas' grounds. Very well, he thought, let them
-bury it there; it won't be hard to find.
-
-Now there was a voice--a very low voice--Injun Joe's:
-
-"Damn her, maybe she's got company--there's lights, late as it is."
-
-"I can't see any."
-
-This was that stranger's voice--the stranger of the haunted house. A
-deadly chill went to Huck's heart--this, then, was the "revenge" job!
-His thought was, to fly. Then he remembered that the Widow Douglas had
-been kind to him more than once, and maybe these men were going to
-murder her. He wished he dared venture to warn her; but he knew he
-didn't dare--they might come and catch him. He thought all this and
-more in the moment that elapsed between the stranger's remark and Injun
-Joe's next--which was--
-
-"Because the bush is in your way. Now--this way--now you see, don't
-you?"
-
-"Yes. Well, there IS company there, I reckon. Better give it up."
-
-"Give it up, and I just leaving this country forever! Give it up and
-maybe never have another chance. I tell you again, as I've told you
-before, I don't care for her swag--you may have it. But her husband was
-rough on me--many times he was rough on me--and mainly he was the
-justice of the peace that jugged me for a vagrant. And that ain't all.
-It ain't a millionth part of it! He had me HORSEWHIPPED!--horsewhipped
-in front of the jail, like a nigger!--with all the town looking on!
-HORSEWHIPPED!--do you understand? He took advantage of me and died. But
-I'll take it out of HER."
-
-"Oh, don't kill her! Don't do that!"
-
-"Kill? Who said anything about killing? I would kill HIM if he was
-here; but not her. When you want to get revenge on a woman you don't
-kill her--bosh! you go for her looks. You slit her nostrils--you notch
-her ears like a sow!"
-
-"By God, that's--"
-
-"Keep your opinion to yourself! It will be safest for you. I'll tie
-her to the bed. If she bleeds to death, is that my fault? I'll not cry,
-if she does. My friend, you'll help me in this thing--for MY sake
---that's why you're here--I mightn't be able alone. If you flinch, I'll
-kill you. Do you understand that? And if I have to kill you, I'll kill
-her--and then I reckon nobody'll ever know much about who done this
-business."
-
-"Well, if it's got to be done, let's get at it. The quicker the
-better--I'm all in a shiver."
-
-"Do it NOW? And company there? Look here--I'll get suspicious of you,
-first thing you know. No--we'll wait till the lights are out--there's
-no hurry."
-
-Huck felt that a silence was going to ensue--a thing still more awful
-than any amount of murderous talk; so he held his breath and stepped
-gingerly back; planted his foot carefully and firmly, after balancing,
-one-legged, in a precarious way and almost toppling over, first on one
-side and then on the other. He took another step back, with the same
-elaboration and the same risks; then another and another, and--a twig
-snapped under his foot! His breath stopped and he listened. There was
-no sound--the stillness was perfect. His gratitude was measureless. Now
-he turned in his tracks, between the walls of sumach bushes--turned
-himself as carefully as if he were a ship--and then stepped quickly but
-cautiously along. When he emerged at the quarry he felt secure, and so
-he picked up his nimble heels and flew. Down, down he sped, till he
-reached the Welshman's. He banged at the door, and presently the heads
-of the old man and his two stalwart sons were thrust from windows.
-
-"What's the row there? Who's banging? What do you want?"
-
-"Let me in--quick! I'll tell everything."
-
-"Why, who are you?"
-
-"Huckleberry Finn--quick, let me in!"
-
-"Huckleberry Finn, indeed! It ain't a name to open many doors, I
-judge! But let him in, lads, and let's see what's the trouble."
-
-"Please don't ever tell I told you," were Huck's first words when he
-got in. "Please don't--I'd be killed, sure--but the widow's been good
-friends to me sometimes, and I want to tell--I WILL tell if you'll
-promise you won't ever say it was me."
-
-"By George, he HAS got something to tell, or he wouldn't act so!"
-exclaimed the old man; "out with it and nobody here'll ever tell, lad."
-
-Three minutes later the old man and his sons, well armed, were up the
-hill, and just entering the sumach path on tiptoe, their weapons in
-their hands. Huck accompanied them no further. He hid behind a great
-bowlder and fell to listening. There was a lagging, anxious silence,
-and then all of a sudden there was an explosion of firearms and a cry.
-
-Huck waited for no particulars. He sprang away and sped down the hill
-as fast as his legs could carry him.
-
-
-
-CHAPTER XXX
-
-AS the earliest suspicion of dawn appeared on Sunday morning, Huck
-came groping up the hill and rapped gently at the old Welshman's door.
-The inmates were asleep, but it was a sleep that was set on a
-hair-trigger, on account of the exciting episode of the night. A call
-came from a window:
-
-"Who's there!"
-
-Huck's scared voice answered in a low tone:
-
-"Please let me in! It's only Huck Finn!"
-
-"It's a name that can open this door night or day, lad!--and welcome!"
-
-These were strange words to the vagabond boy's ears, and the
-pleasantest he had ever heard. He could not recollect that the closing
-word had ever been applied in his case before. The door was quickly
-unlocked, and he entered. Huck was given a seat and the old man and his
-brace of tall sons speedily dressed themselves.
-
-"Now, my boy, I hope you're good and hungry, because breakfast will be
-ready as soon as the sun's up, and we'll have a piping hot one, too
---make yourself easy about that! I and the boys hoped you'd turn up and
-stop here last night."
-
-"I was awful scared," said Huck, "and I run. I took out when the
-pistols went off, and I didn't stop for three mile. I've come now becuz
-I wanted to know about it, you know; and I come before daylight becuz I
-didn't want to run across them devils, even if they was dead."
-
-"Well, poor chap, you do look as if you'd had a hard night of it--but
-there's a bed here for you when you've had your breakfast. No, they
-ain't dead, lad--we are sorry enough for that. You see we knew right
-where to put our hands on them, by your description; so we crept along
-on tiptoe till we got within fifteen feet of them--dark as a cellar
-that sumach path was--and just then I found I was going to sneeze. It
-was the meanest kind of luck! I tried to keep it back, but no use
---'twas bound to come, and it did come! I was in the lead with my pistol
-raised, and when the sneeze started those scoundrels a-rustling to get
-out of the path, I sung out, 'Fire boys!' and blazed away at the place
-where the rustling was. So did the boys. But they were off in a jiffy,
-those villains, and we after them, down through the woods. I judge we
-never touched them. They fired a shot apiece as they started, but their
-bullets whizzed by and didn't do us any harm. As soon as we lost the
-sound of their feet we quit chasing, and went down and stirred up the
-constables. They got a posse together, and went off to guard the river
-bank, and as soon as it is light the sheriff and a gang are going to
-beat up the woods. My boys will be with them presently. I wish we had
-some sort of description of those rascals--'twould help a good deal.
-But you couldn't see what they were like, in the dark, lad, I suppose?"
-
-"Oh yes; I saw them down-town and follered them."
-
-"Splendid! Describe them--describe them, my boy!"
-
-"One's the old deaf and dumb Spaniard that's ben around here once or
-twice, and t'other's a mean-looking, ragged--"
-
-"That's enough, lad, we know the men! Happened on them in the woods
-back of the widow's one day, and they slunk away. Off with you, boys,
-and tell the sheriff--get your breakfast to-morrow morning!"
-
-The Welshman's sons departed at once. As they were leaving the room
-Huck sprang up and exclaimed:
-
-"Oh, please don't tell ANYbody it was me that blowed on them! Oh,
-please!"
-
-"All right if you say it, Huck, but you ought to have the credit of
-what you did."
-
-"Oh no, no! Please don't tell!"
-
-When the young men were gone, the old Welshman said:
-
-"They won't tell--and I won't. But why don't you want it known?"
-
-Huck would not explain, further than to say that he already knew too
-much about one of those men and would not have the man know that he
-knew anything against him for the whole world--he would be killed for
-knowing it, sure.
-
-The old man promised secrecy once more, and said:
-
-"How did you come to follow these fellows, lad? Were they looking
-suspicious?"
-
-Huck was silent while he framed a duly cautious reply. Then he said:
-
-"Well, you see, I'm a kind of a hard lot,--least everybody says so,
-and I don't see nothing agin it--and sometimes I can't sleep much, on
-account of thinking about it and sort of trying to strike out a new way
-of doing. That was the way of it last night. I couldn't sleep, and so I
-come along up-street 'bout midnight, a-turning it all over, and when I
-got to that old shackly brick store by the Temperance Tavern, I backed
-up agin the wall to have another think. Well, just then along comes
-these two chaps slipping along close by me, with something under their
-arm, and I reckoned they'd stole it. One was a-smoking, and t'other one
-wanted a light; so they stopped right before me and the cigars lit up
-their faces and I see that the big one was the deaf and dumb Spaniard,
-by his white whiskers and the patch on his eye, and t'other one was a
-rusty, ragged-looking devil."
-
-"Could you see the rags by the light of the cigars?"
-
-This staggered Huck for a moment. Then he said:
-
-"Well, I don't know--but somehow it seems as if I did."
-
-"Then they went on, and you--"
-
-"Follered 'em--yes. That was it. I wanted to see what was up--they
-sneaked along so. I dogged 'em to the widder's stile, and stood in the
-dark and heard the ragged one beg for the widder, and the Spaniard
-swear he'd spile her looks just as I told you and your two--"
-
-"What! The DEAF AND DUMB man said all that!"
-
-Huck had made another terrible mistake! He was trying his best to keep
-the old man from getting the faintest hint of who the Spaniard might
-be, and yet his tongue seemed determined to get him into trouble in
-spite of all he could do. He made several efforts to creep out of his
-scrape, but the old man's eye was upon him and he made blunder after
-blunder. Presently the Welshman said:
-
-"My boy, don't be afraid of me. I wouldn't hurt a hair of your head
-for all the world. No--I'd protect you--I'd protect you. This Spaniard
-is not deaf and dumb; you've let that slip without intending it; you
-can't cover that up now. You know something about that Spaniard that
-you want to keep dark. Now trust me--tell me what it is, and trust me
---I won't betray you."
-
-Huck looked into the old man's honest eyes a moment, then bent over
-and whispered in his ear:
-
-"'Tain't a Spaniard--it's Injun Joe!"
-
-The Welshman almost jumped out of his chair. In a moment he said:
-
-"It's all plain enough, now. When you talked about notching ears and
-slitting noses I judged that that was your own embellishment, because
-white men don't take that sort of revenge. But an Injun! That's a
-different matter altogether."
-
-During breakfast the talk went on, and in the course of it the old man
-said that the last thing which he and his sons had done, before going
-to bed, was to get a lantern and examine the stile and its vicinity for
-marks of blood. They found none, but captured a bulky bundle of--
-
-"Of WHAT?"
-
-If the words had been lightning they could not have leaped with a more
-stunning suddenness from Huck's blanched lips. His eyes were staring
-wide, now, and his breath suspended--waiting for the answer. The
-Welshman started--stared in return--three seconds--five seconds--ten
---then replied:
-
-"Of burglar's tools. Why, what's the MATTER with you?"
-
-Huck sank back, panting gently, but deeply, unutterably grateful. The
-Welshman eyed him gravely, curiously--and presently said:
-
-"Yes, burglar's tools. That appears to relieve you a good deal. But
-what did give you that turn? What were YOU expecting we'd found?"
-
-Huck was in a close place--the inquiring eye was upon him--he would
-have given anything for material for a plausible answer--nothing
-suggested itself--the inquiring eye was boring deeper and deeper--a
-senseless reply offered--there was no time to weigh it, so at a venture
-he uttered it--feebly:
-
-"Sunday-school books, maybe."
-
-Poor Huck was too distressed to smile, but the old man laughed loud
-and joyously, shook up the details of his anatomy from head to foot,
-and ended by saying that such a laugh was money in a-man's pocket,
-because it cut down the doctor's bill like everything. Then he added:
-
-"Poor old chap, you're white and jaded--you ain't well a bit--no
-wonder you're a little flighty and off your balance. But you'll come
-out of it. Rest and sleep will fetch you out all right, I hope."
-
-Huck was irritated to think he had been such a goose and betrayed such
-a suspicious excitement, for he had dropped the idea that the parcel
-brought from the tavern was the treasure, as soon as he had heard the
-talk at the widow's stile. He had only thought it was not the treasure,
-however--he had not known that it wasn't--and so the suggestion of a
-captured bundle was too much for his self-possession. But on the whole
-he felt glad the little episode had happened, for now he knew beyond
-all question that that bundle was not THE bundle, and so his mind was
-at rest and exceedingly comfortable. In fact, everything seemed to be
-drifting just in the right direction, now; the treasure must be still
-in No. 2, the men would be captured and jailed that day, and he and Tom
-could seize the gold that night without any trouble or any fear of
-interruption.
-
-Just as breakfast was completed there was a knock at the door. Huck
-jumped for a hiding-place, for he had no mind to be connected even
-remotely with the late event. The Welshman admitted several ladies and
-gentlemen, among them the Widow Douglas, and noticed that groups of
-citizens were climbing up the hill--to stare at the stile. So the news
-had spread. The Welshman had to tell the story of the night to the
-visitors. The widow's gratitude for her preservation was outspoken.
-
-"Don't say a word about it, madam. There's another that you're more
-beholden to than you are to me and my boys, maybe, but he don't allow
-me to tell his name. We wouldn't have been there but for him."
-
-Of course this excited a curiosity so vast that it almost belittled
-the main matter--but the Welshman allowed it to eat into the vitals of
-his visitors, and through them be transmitted to the whole town, for he
-refused to part with his secret. When all else had been learned, the
-widow said:
-
-"I went to sleep reading in bed and slept straight through all that
-noise. Why didn't you come and wake me?"
-
-"We judged it warn't worth while. Those fellows warn't likely to come
-again--they hadn't any tools left to work with, and what was the use of
-waking you up and scaring you to death? My three negro men stood guard
-at your house all the rest of the night. They've just come back."
-
-More visitors came, and the story had to be told and retold for a
-couple of hours more.
-
-There was no Sabbath-school during day-school vacation, but everybody
-was early at church. The stirring event was well canvassed. News came
-that not a sign of the two villains had been yet discovered. When the
-sermon was finished, Judge Thatcher's wife dropped alongside of Mrs.
-Harper as she moved down the aisle with the crowd and said:
-
-"Is my Becky going to sleep all day? I just expected she would be
-tired to death."
-
-"Your Becky?"
-
-"Yes," with a startled look--"didn't she stay with you last night?"
-
-"Why, no."
-
-Mrs. Thatcher turned pale, and sank into a pew, just as Aunt Polly,
-talking briskly with a friend, passed by. Aunt Polly said:
-
-"Good-morning, Mrs. Thatcher. Good-morning, Mrs. Harper. I've got a
-boy that's turned up missing. I reckon my Tom stayed at your house last
-night--one of you. And now he's afraid to come to church. I've got to
-settle with him."
-
-Mrs. Thatcher shook her head feebly and turned paler than ever.
-
-"He didn't stay with us," said Mrs. Harper, beginning to look uneasy.
-A marked anxiety came into Aunt Polly's face.
-
-"Joe Harper, have you seen my Tom this morning?"
-
-"No'm."
-
-"When did you see him last?"
-
-Joe tried to remember, but was not sure he could say. The people had
-stopped moving out of church. Whispers passed along, and a boding
-uneasiness took possession of every countenance. Children were
-anxiously questioned, and young teachers. They all said they had not
-noticed whether Tom and Becky were on board the ferryboat on the
-homeward trip; it was dark; no one thought of inquiring if any one was
-missing. One young man finally blurted out his fear that they were
-still in the cave! Mrs. Thatcher swooned away. Aunt Polly fell to
-crying and wringing her hands.
-
-The alarm swept from lip to lip, from group to group, from street to
-street, and within five minutes the bells were wildly clanging and the
-whole town was up! The Cardiff Hill episode sank into instant
-insignificance, the burglars were forgotten, horses were saddled,
-skiffs were manned, the ferryboat ordered out, and before the horror
-was half an hour old, two hundred men were pouring down highroad and
-river toward the cave.
-
-All the long afternoon the village seemed empty and dead. Many women
-visited Aunt Polly and Mrs. Thatcher and tried to comfort them. They
-cried with them, too, and that was still better than words. All the
-tedious night the town waited for news; but when the morning dawned at
-last, all the word that came was, "Send more candles--and send food."
-Mrs. Thatcher was almost crazed; and Aunt Polly, also. Judge Thatcher
-sent messages of hope and encouragement from the cave, but they
-conveyed no real cheer.
-
-The old Welshman came home toward daylight, spattered with
-candle-grease, smeared with clay, and almost worn out. He found Huck
-still in the bed that had been provided for him, and delirious with
-fever. The physicians were all at the cave, so the Widow Douglas came
-and took charge of the patient. She said she would do her best by him,
-because, whether he was good, bad, or indifferent, he was the Lord's,
-and nothing that was the Lord's was a thing to be neglected. The
-Welshman said Huck had good spots in him, and the widow said:
-
-"You can depend on it. That's the Lord's mark. He don't leave it off.
-He never does. Puts it somewhere on every creature that comes from his
-hands."
-
-Early in the forenoon parties of jaded men began to straggle into the
-village, but the strongest of the citizens continued searching. All the
-news that could be gained was that remotenesses of the cavern were
-being ransacked that had never been visited before; that every corner
-and crevice was going to be thoroughly searched; that wherever one
-wandered through the maze of passages, lights were to be seen flitting
-hither and thither in the distance, and shoutings and pistol-shots sent
-their hollow reverberations to the ear down the sombre aisles. In one
-place, far from the section usually traversed by tourists, the names
-"BECKY & TOM" had been found traced upon the rocky wall with
-candle-smoke, and near at hand a grease-soiled bit of ribbon. Mrs.
-Thatcher recognized the ribbon and cried over it. She said it was the
-last relic she should ever have of her child; and that no other memorial
-of her could ever be so precious, because this one parted latest from
-the living body before the awful death came. Some said that now and
-then, in the cave, a far-away speck of light would glimmer, and then a
-glorious shout would burst forth and a score of men go trooping down the
-echoing aisle--and then a sickening disappointment always followed; the
-children were not there; it was only a searcher's light.
-
-Three dreadful days and nights dragged their tedious hours along, and
-the village sank into a hopeless stupor. No one had heart for anything.
-The accidental discovery, just made, that the proprietor of the
-Temperance Tavern kept liquor on his premises, scarcely fluttered the
-public pulse, tremendous as the fact was. In a lucid interval, Huck
-feebly led up to the subject of taverns, and finally asked--dimly
-dreading the worst--if anything had been discovered at the Temperance
-Tavern since he had been ill.
-
-"Yes," said the widow.
-
-Huck started up in bed, wild-eyed:
-
-"What? What was it?"
-
-"Liquor!--and the place has been shut up. Lie down, child--what a turn
-you did give me!"
-
-"Only tell me just one thing--only just one--please! Was it Tom Sawyer
-that found it?"
-
-The widow burst into tears. "Hush, hush, child, hush! I've told you
-before, you must NOT talk. You are very, very sick!"
-
-Then nothing but liquor had been found; there would have been a great
-powwow if it had been the gold. So the treasure was gone forever--gone
-forever! But what could she be crying about? Curious that she should
-cry.
-
-These thoughts worked their dim way through Huck's mind, and under the
-weariness they gave him he fell asleep. The widow said to herself:
-
-"There--he's asleep, poor wreck. Tom Sawyer find it! Pity but somebody
-could find Tom Sawyer! Ah, there ain't many left, now, that's got hope
-enough, or strength enough, either, to go on searching."
-
-
-
-CHAPTER XXXI
-
-NOW to return to Tom and Becky's share in the picnic. They tripped
-along the murky aisles with the rest of the company, visiting the
-familiar wonders of the cave--wonders dubbed with rather
-over-descriptive names, such as "The Drawing-Room," "The Cathedral,"
-"Aladdin's Palace," and so on. Presently the hide-and-seek frolicking
-began, and Tom and Becky engaged in it with zeal until the exertion
-began to grow a trifle wearisome; then they wandered down a sinuous
-avenue holding their candles aloft and reading the tangled web-work of
-names, dates, post-office addresses, and mottoes with which the rocky
-walls had been frescoed (in candle-smoke). Still drifting along and
-talking, they scarcely noticed that they were now in a part of the cave
-whose walls were not frescoed. They smoked their own names under an
-overhanging shelf and moved on. Presently they came to a place where a
-little stream of water, trickling over a ledge and carrying a limestone
-sediment with it, had, in the slow-dragging ages, formed a laced and
-ruffled Niagara in gleaming and imperishable stone. Tom squeezed his
-small body behind it in order to illuminate it for Becky's
-gratification. He found that it curtained a sort of steep natural
-stairway which was enclosed between narrow walls, and at once the
-ambition to be a discoverer seized him. Becky responded to his call,
-and they made a smoke-mark for future guidance, and started upon their
-quest. They wound this way and that, far down into the secret depths of
-the cave, made another mark, and branched off in search of novelties to
-tell the upper world about. In one place they found a spacious cavern,
-from whose ceiling depended a multitude of shining stalactites of the
-length and circumference of a man's leg; they walked all about it,
-wondering and admiring, and presently left it by one of the numerous
-passages that opened into it. This shortly brought them to a bewitching
-spring, whose basin was incrusted with a frostwork of glittering
-crystals; it was in the midst of a cavern whose walls were supported by
-many fantastic pillars which had been formed by the joining of great
-stalactites and stalagmites together, the result of the ceaseless
-water-drip of centuries. Under the roof vast knots of bats had packed
-themselves together, thousands in a bunch; the lights disturbed the
-creatures and they came flocking down by hundreds, squeaking and
-darting furiously at the candles. Tom knew their ways and the danger of
-this sort of conduct. He seized Becky's hand and hurried her into the
-first corridor that offered; and none too soon, for a bat struck
-Becky's light out with its wing while she was passing out of the
-cavern. The bats chased the children a good distance; but the fugitives
-plunged into every new passage that offered, and at last got rid of the
-perilous things. Tom found a subterranean lake, shortly, which
-stretched its dim length away until its shape was lost in the shadows.
-He wanted to explore its borders, but concluded that it would be best
-to sit down and rest awhile, first. Now, for the first time, the deep
-stillness of the place laid a clammy hand upon the spirits of the
-children. Becky said:
-
-"Why, I didn't notice, but it seems ever so long since I heard any of
-the others."
-
-"Come to think, Becky, we are away down below them--and I don't know
-how far away north, or south, or east, or whichever it is. We couldn't
-hear them here."
-
-Becky grew apprehensive.
-
-"I wonder how long we've been down here, Tom? We better start back."
-
-"Yes, I reckon we better. P'raps we better."
-
-"Can you find the way, Tom? It's all a mixed-up crookedness to me."
-
-"I reckon I could find it--but then the bats. If they put our candles
-out it will be an awful fix. Let's try some other way, so as not to go
-through there."
-
-"Well. But I hope we won't get lost. It would be so awful!" and the
-girl shuddered at the thought of the dreadful possibilities.
-
-They started through a corridor, and traversed it in silence a long
-way, glancing at each new opening, to see if there was anything
-familiar about the look of it; but they were all strange. Every time
-Tom made an examination, Becky would watch his face for an encouraging
-sign, and he would say cheerily:
-
-"Oh, it's all right. This ain't the one, but we'll come to it right
-away!"
-
-But he felt less and less hopeful with each failure, and presently
-began to turn off into diverging avenues at sheer random, in desperate
-hope of finding the one that was wanted. He still said it was "all
-right," but there was such a leaden dread at his heart that the words
-had lost their ring and sounded just as if he had said, "All is lost!"
-Becky clung to his side in an anguish of fear, and tried hard to keep
-back the tears, but they would come. At last she said:
-
-"Oh, Tom, never mind the bats, let's go back that way! We seem to get
-worse and worse off all the time."
-
-"Listen!" said he.
-
-Profound silence; silence so deep that even their breathings were
-conspicuous in the hush. Tom shouted. The call went echoing down the
-empty aisles and died out in the distance in a faint sound that
-resembled a ripple of mocking laughter.
-
-"Oh, don't do it again, Tom, it is too horrid," said Becky.
-
-"It is horrid, but I better, Becky; they might hear us, you know," and
-he shouted again.
-
-The "might" was even a chillier horror than the ghostly laughter, it
-so confessed a perishing hope. The children stood still and listened;
-but there was no result. Tom turned upon the back track at once, and
-hurried his steps. It was but a little while before a certain
-indecision in his manner revealed another fearful fact to Becky--he
-could not find his way back!
-
-"Oh, Tom, you didn't make any marks!"
-
-"Becky, I was such a fool! Such a fool! I never thought we might want
-to come back! No--I can't find the way. It's all mixed up."
-
-"Tom, Tom, we're lost! we're lost! We never can get out of this awful
-place! Oh, why DID we ever leave the others!"
-
-She sank to the ground and burst into such a frenzy of crying that Tom
-was appalled with the idea that she might die, or lose her reason. He
-sat down by her and put his arms around her; she buried her face in his
-bosom, she clung to him, she poured out her terrors, her unavailing
-regrets, and the far echoes turned them all to jeering laughter. Tom
-begged her to pluck up hope again, and she said she could not. He fell
-to blaming and abusing himself for getting her into this miserable
-situation; this had a better effect. She said she would try to hope
-again, she would get up and follow wherever he might lead if only he
-would not talk like that any more. For he was no more to blame than
-she, she said.
-
-So they moved on again--aimlessly--simply at random--all they could do
-was to move, keep moving. For a little while, hope made a show of
-reviving--not with any reason to back it, but only because it is its
-nature to revive when the spring has not been taken out of it by age
-and familiarity with failure.
-
-By-and-by Tom took Becky's candle and blew it out. This economy meant
-so much! Words were not needed. Becky understood, and her hope died
-again. She knew that Tom had a whole candle and three or four pieces in
-his pockets--yet he must economize.
-
-By-and-by, fatigue began to assert its claims; the children tried to
-pay attention, for it was dreadful to think of sitting down when time
-was grown to be so precious, moving, in some direction, in any
-direction, was at least progress and might bear fruit; but to sit down
-was to invite death and shorten its pursuit.
-
-At last Becky's frail limbs refused to carry her farther. She sat
-down. Tom rested with her, and they talked of home, and the friends
-there, and the comfortable beds and, above all, the light! Becky cried,
-and Tom tried to think of some way of comforting her, but all his
-encouragements were grown threadbare with use, and sounded like
-sarcasms. Fatigue bore so heavily upon Becky that she drowsed off to
-sleep. Tom was grateful. He sat looking into her drawn face and saw it
-grow smooth and natural under the influence of pleasant dreams; and
-by-and-by a smile dawned and rested there. The peaceful face reflected
-somewhat of peace and healing into his own spirit, and his thoughts
-wandered away to bygone times and dreamy memories. While he was deep in
-his musings, Becky woke up with a breezy little laugh--but it was
-stricken dead upon her lips, and a groan followed it.
-
-"Oh, how COULD I sleep! I wish I never, never had waked! No! No, I
-don't, Tom! Don't look so! I won't say it again."
-
-"I'm glad you've slept, Becky; you'll feel rested, now, and we'll find
-the way out."
-
-"We can try, Tom; but I've seen such a beautiful country in my dream.
-I reckon we are going there."
-
-"Maybe not, maybe not. Cheer up, Becky, and let's go on trying."
-
-They rose up and wandered along, hand in hand and hopeless. They tried
-to estimate how long they had been in the cave, but all they knew was
-that it seemed days and weeks, and yet it was plain that this could not
-be, for their candles were not gone yet. A long time after this--they
-could not tell how long--Tom said they must go softly and listen for
-dripping water--they must find a spring. They found one presently, and
-Tom said it was time to rest again. Both were cruelly tired, yet Becky
-said she thought she could go a little farther. She was surprised to
-hear Tom dissent. She could not understand it. They sat down, and Tom
-fastened his candle to the wall in front of them with some clay.
-Thought was soon busy; nothing was said for some time. Then Becky broke
-the silence:
-
-"Tom, I am so hungry!"
-
-Tom took something out of his pocket.
-
-"Do you remember this?" said he.
-
-Becky almost smiled.
-
-"It's our wedding-cake, Tom."
-
-"Yes--I wish it was as big as a barrel, for it's all we've got."
-
-"I saved it from the picnic for us to dream on, Tom, the way grown-up
-people do with wedding-cake--but it'll be our--"
-
-She dropped the sentence where it was. Tom divided the cake and Becky
-ate with good appetite, while Tom nibbled at his moiety. There was
-abundance of cold water to finish the feast with. By-and-by Becky
-suggested that they move on again. Tom was silent a moment. Then he
-said:
-
-"Becky, can you bear it if I tell you something?"
-
-Becky's face paled, but she thought she could.
-
-"Well, then, Becky, we must stay here, where there's water to drink.
-That little piece is our last candle!"
-
-Becky gave loose to tears and wailings. Tom did what he could to
-comfort her, but with little effect. At length Becky said:
-
-"Tom!"
-
-"Well, Becky?"
-
-"They'll miss us and hunt for us!"
-
-"Yes, they will! Certainly they will!"
-
-"Maybe they're hunting for us now, Tom."
-
-"Why, I reckon maybe they are. I hope they are."
-
-"When would they miss us, Tom?"
-
-"When they get back to the boat, I reckon."
-
-"Tom, it might be dark then--would they notice we hadn't come?"
-
-"I don't know. But anyway, your mother would miss you as soon as they
-got home."
-
-A frightened look in Becky's face brought Tom to his senses and he saw
-that he had made a blunder. Becky was not to have gone home that night!
-The children became silent and thoughtful. In a moment a new burst of
-grief from Becky showed Tom that the thing in his mind had struck hers
-also--that the Sabbath morning might be half spent before Mrs. Thatcher
-discovered that Becky was not at Mrs. Harper's.
-
-The children fastened their eyes upon their bit of candle and watched
-it melt slowly and pitilessly away; saw the half inch of wick stand
-alone at last; saw the feeble flame rise and fall, climb the thin
-column of smoke, linger at its top a moment, and then--the horror of
-utter darkness reigned!
-
-How long afterward it was that Becky came to a slow consciousness that
-she was crying in Tom's arms, neither could tell. All that they knew
-was, that after what seemed a mighty stretch of time, both awoke out of
-a dead stupor of sleep and resumed their miseries once more. Tom said
-it might be Sunday, now--maybe Monday. He tried to get Becky to talk,
-but her sorrows were too oppressive, all her hopes were gone. Tom said
-that they must have been missed long ago, and no doubt the search was
-going on. He would shout and maybe some one would come. He tried it;
-but in the darkness the distant echoes sounded so hideously that he
-tried it no more.
-
-The hours wasted away, and hunger came to torment the captives again.
-A portion of Tom's half of the cake was left; they divided and ate it.
-But they seemed hungrier than before. The poor morsel of food only
-whetted desire.
-
-By-and-by Tom said:
-
-"SH! Did you hear that?"
-
-Both held their breath and listened. There was a sound like the
-faintest, far-off shout. Instantly Tom answered it, and leading Becky
-by the hand, started groping down the corridor in its direction.
-Presently he listened again; again the sound was heard, and apparently
-a little nearer.
-
-"It's them!" said Tom; "they're coming! Come along, Becky--we're all
-right now!"
-
-The joy of the prisoners was almost overwhelming. Their speed was
-slow, however, because pitfalls were somewhat common, and had to be
-guarded against. They shortly came to one and had to stop. It might be
-three feet deep, it might be a hundred--there was no passing it at any
-rate. Tom got down on his breast and reached as far down as he could.
-No bottom. They must stay there and wait until the searchers came. They
-listened; evidently the distant shoutings were growing more distant! a
-moment or two more and they had gone altogether. The heart-sinking
-misery of it! Tom whooped until he was hoarse, but it was of no use. He
-talked hopefully to Becky; but an age of anxious waiting passed and no
-sounds came again.
-
-The children groped their way back to the spring. The weary time
-dragged on; they slept again, and awoke famished and woe-stricken. Tom
-believed it must be Tuesday by this time.
-
-Now an idea struck him. There were some side passages near at hand. It
-would be better to explore some of these than bear the weight of the
-heavy time in idleness. He took a kite-line from his pocket, tied it to
-a projection, and he and Becky started, Tom in the lead, unwinding the
-line as he groped along. At the end of twenty steps the corridor ended
-in a "jumping-off place." Tom got down on his knees and felt below, and
-then as far around the corner as he could reach with his hands
-conveniently; he made an effort to stretch yet a little farther to the
-right, and at that moment, not twenty yards away, a human hand, holding
-a candle, appeared from behind a rock! Tom lifted up a glorious shout,
-and instantly that hand was followed by the body it belonged to--Injun
-Joe's! Tom was paralyzed; he could not move. He was vastly gratified
-the next moment, to see the "Spaniard" take to his heels and get
-himself out of sight. Tom wondered that Joe had not recognized his
-voice and come over and killed him for testifying in court. But the
-echoes must have disguised the voice. Without doubt, that was it, he
-reasoned. Tom's fright weakened every muscle in his body. He said to
-himself that if he had strength enough to get back to the spring he
-would stay there, and nothing should tempt him to run the risk of
-meeting Injun Joe again. He was careful to keep from Becky what it was
-he had seen. He told her he had only shouted "for luck."
-
-But hunger and wretchedness rise superior to fears in the long run.
-Another tedious wait at the spring and another long sleep brought
-changes. The children awoke tortured with a raging hunger. Tom believed
-that it must be Wednesday or Thursday or even Friday or Saturday, now,
-and that the search had been given over. He proposed to explore another
-passage. He felt willing to risk Injun Joe and all other terrors. But
-Becky was very weak. She had sunk into a dreary apathy and would not be
-roused. She said she would wait, now, where she was, and die--it would
-not be long. She told Tom to go with the kite-line and explore if he
-chose; but she implored him to come back every little while and speak
-to her; and she made him promise that when the awful time came, he
-would stay by her and hold her hand until all was over.
-
-Tom kissed her, with a choking sensation in his throat, and made a
-show of being confident of finding the searchers or an escape from the
-cave; then he took the kite-line in his hand and went groping down one
-of the passages on his hands and knees, distressed with hunger and sick
-with bodings of coming doom.
-
-
-
-CHAPTER XXXII
-
-TUESDAY afternoon came, and waned to the twilight. The village of St.
-Petersburg still mourned. The lost children had not been found. Public
-prayers had been offered up for them, and many and many a private
-prayer that had the petitioner's whole heart in it; but still no good
-news came from the cave. The majority of the searchers had given up the
-quest and gone back to their daily avocations, saying that it was plain
-the children could never be found. Mrs. Thatcher was very ill, and a
-great part of the time delirious. People said it was heartbreaking to
-hear her call her child, and raise her head and listen a whole minute
-at a time, then lay it wearily down again with a moan. Aunt Polly had
-drooped into a settled melancholy, and her gray hair had grown almost
-white. The village went to its rest on Tuesday night, sad and forlorn.
-
-Away in the middle of the night a wild peal burst from the village
-bells, and in a moment the streets were swarming with frantic half-clad
-people, who shouted, "Turn out! turn out! they're found! they're
-found!" Tin pans and horns were added to the din, the population massed
-itself and moved toward the river, met the children coming in an open
-carriage drawn by shouting citizens, thronged around it, joined its
-homeward march, and swept magnificently up the main street roaring
-huzzah after huzzah!
-
-The village was illuminated; nobody went to bed again; it was the
-greatest night the little town had ever seen. During the first half-hour
-a procession of villagers filed through Judge Thatcher's house, seized
-the saved ones and kissed them, squeezed Mrs. Thatcher's hand, tried to
-speak but couldn't--and drifted out raining tears all over the place.
-
-Aunt Polly's happiness was complete, and Mrs. Thatcher's nearly so. It
-would be complete, however, as soon as the messenger dispatched with
-the great news to the cave should get the word to her husband. Tom lay
-upon a sofa with an eager auditory about him and told the history of
-the wonderful adventure, putting in many striking additions to adorn it
-withal; and closed with a description of how he left Becky and went on
-an exploring expedition; how he followed two avenues as far as his
-kite-line would reach; how he followed a third to the fullest stretch of
-the kite-line, and was about to turn back when he glimpsed a far-off
-speck that looked like daylight; dropped the line and groped toward it,
-pushed his head and shoulders through a small hole, and saw the broad
-Mississippi rolling by! And if it had only happened to be night he would
-not have seen that speck of daylight and would not have explored that
-passage any more! He told how he went back for Becky and broke the good
-news and she told him not to fret her with such stuff, for she was
-tired, and knew she was going to die, and wanted to. He described how he
-labored with her and convinced her; and how she almost died for joy when
-she had groped to where she actually saw the blue speck of daylight; how
-he pushed his way out at the hole and then helped her out; how they sat
-there and cried for gladness; how some men came along in a skiff and Tom
-hailed them and told them their situation and their famished condition;
-how the men didn't believe the wild tale at first, "because," said they,
-"you are five miles down the river below the valley the cave is in"
---then took them aboard, rowed to a house, gave them supper, made them
-rest till two or three hours after dark and then brought them home.
-
-Before day-dawn, Judge Thatcher and the handful of searchers with him
-were tracked out, in the cave, by the twine clews they had strung
-behind them, and informed of the great news.
-
-Three days and nights of toil and hunger in the cave were not to be
-shaken off at once, as Tom and Becky soon discovered. They were
-bedridden all of Wednesday and Thursday, and seemed to grow more and
-more tired and worn, all the time. Tom got about, a little, on
-Thursday, was down-town Friday, and nearly as whole as ever Saturday;
-but Becky did not leave her room until Sunday, and then she looked as
-if she had passed through a wasting illness.
-
-Tom learned of Huck's sickness and went to see him on Friday, but
-could not be admitted to the bedroom; neither could he on Saturday or
-Sunday. He was admitted daily after that, but was warned to keep still
-about his adventure and introduce no exciting topic. The Widow Douglas
-stayed by to see that he obeyed. At home Tom learned of the Cardiff
-Hill event; also that the "ragged man's" body had eventually been found
-in the river near the ferry-landing; he had been drowned while trying
-to escape, perhaps.
-
-About a fortnight after Tom's rescue from the cave, he started off to
-visit Huck, who had grown plenty strong enough, now, to hear exciting
-talk, and Tom had some that would interest him, he thought. Judge
-Thatcher's house was on Tom's way, and he stopped to see Becky. The
-Judge and some friends set Tom to talking, and some one asked him
-ironically if he wouldn't like to go to the cave again. Tom said he
-thought he wouldn't mind it. The Judge said:
-
-"Well, there are others just like you, Tom, I've not the least doubt.
-But we have taken care of that. Nobody will get lost in that cave any
-more."
-
-"Why?"
-
-"Because I had its big door sheathed with boiler iron two weeks ago,
-and triple-locked--and I've got the keys."
-
-Tom turned as white as a sheet.
-
-"What's the matter, boy! Here, run, somebody! Fetch a glass of water!"
-
-The water was brought and thrown into Tom's face.
-
-"Ah, now you're all right. What was the matter with you, Tom?"
-
-"Oh, Judge, Injun Joe's in the cave!"
-
-
-
-CHAPTER XXXIII
-
-WITHIN a few minutes the news had spread, and a dozen skiff-loads of
-men were on their way to McDougal's cave, and the ferryboat, well
-filled with passengers, soon followed. Tom Sawyer was in the skiff that
-bore Judge Thatcher.
-
-When the cave door was unlocked, a sorrowful sight presented itself in
-the dim twilight of the place. Injun Joe lay stretched upon the ground,
-dead, with his face close to the crack of the door, as if his longing
-eyes had been fixed, to the latest moment, upon the light and the cheer
-of the free world outside. Tom was touched, for he knew by his own
-experience how this wretch had suffered. His pity was moved, but
-nevertheless he felt an abounding sense of relief and security, now,
-which revealed to him in a degree which he had not fully appreciated
-before how vast a weight of dread had been lying upon him since the day
-he lifted his voice against this bloody-minded outcast.
-
-Injun Joe's bowie-knife lay close by, its blade broken in two. The
-great foundation-beam of the door had been chipped and hacked through,
-with tedious labor; useless labor, too, it was, for the native rock
-formed a sill outside it, and upon that stubborn material the knife had
-wrought no effect; the only damage done was to the knife itself. But if
-there had been no stony obstruction there the labor would have been
-useless still, for if the beam had been wholly cut away Injun Joe could
-not have squeezed his body under the door, and he knew it. So he had
-only hacked that place in order to be doing something--in order to pass
-the weary time--in order to employ his tortured faculties. Ordinarily
-one could find half a dozen bits of candle stuck around in the crevices
-of this vestibule, left there by tourists; but there were none now. The
-prisoner had searched them out and eaten them. He had also contrived to
-catch a few bats, and these, also, he had eaten, leaving only their
-claws. The poor unfortunate had starved to death. In one place, near at
-hand, a stalagmite had been slowly growing up from the ground for ages,
-builded by the water-drip from a stalactite overhead. The captive had
-broken off the stalagmite, and upon the stump had placed a stone,
-wherein he had scooped a shallow hollow to catch the precious drop
-that fell once in every three minutes with the dreary regularity of a
-clock-tick--a dessertspoonful once in four and twenty hours. That drop
-was falling when the Pyramids were new; when Troy fell; when the
-foundations of Rome were laid; when Christ was crucified; when the
-Conqueror created the British empire; when Columbus sailed; when the
-massacre at Lexington was "news." It is falling now; it will still be
-falling when all these things shall have sunk down the afternoon of
-history, and the twilight of tradition, and been swallowed up in the
-thick night of oblivion. Has everything a purpose and a mission? Did
-this drop fall patiently during five thousand years to be ready for
-this flitting human insect's need? and has it another important object
-to accomplish ten thousand years to come? No matter. It is many and
-many a year since the hapless half-breed scooped out the stone to catch
-the priceless drops, but to this day the tourist stares longest at that
-pathetic stone and that slow-dropping water when he comes to see the
-wonders of McDougal's cave. Injun Joe's cup stands first in the list of
-the cavern's marvels; even "Aladdin's Palace" cannot rival it.
-
-Injun Joe was buried near the mouth of the cave; and people flocked
-there in boats and wagons from the towns and from all the farms and
-hamlets for seven miles around; they brought their children, and all
-sorts of provisions, and confessed that they had had almost as
-satisfactory a time at the funeral as they could have had at the
-hanging.
-
-This funeral stopped the further growth of one thing--the petition to
-the governor for Injun Joe's pardon. The petition had been largely
-signed; many tearful and eloquent meetings had been held, and a
-committee of sappy women been appointed to go in deep mourning and wail
-around the governor, and implore him to be a merciful ass and trample
-his duty under foot. Injun Joe was believed to have killed five
-citizens of the village, but what of that? If he had been Satan himself
-there would have been plenty of weaklings ready to scribble their names
-to a pardon-petition, and drip a tear on it from their permanently
-impaired and leaky water-works.
-
-The morning after the funeral Tom took Huck to a private place to have
-an important talk. Huck had learned all about Tom's adventure from the
-Welshman and the Widow Douglas, by this time, but Tom said he reckoned
-there was one thing they had not told him; that thing was what he
-wanted to talk about now. Huck's face saddened. He said:
-
-"I know what it is. You got into No. 2 and never found anything but
-whiskey. Nobody told me it was you; but I just knowed it must 'a' ben
-you, soon as I heard 'bout that whiskey business; and I knowed you
-hadn't got the money becuz you'd 'a' got at me some way or other and
-told me even if you was mum to everybody else. Tom, something's always
-told me we'd never get holt of that swag."
-
-"Why, Huck, I never told on that tavern-keeper. YOU know his tavern
-was all right the Saturday I went to the picnic. Don't you remember you
-was to watch there that night?"
-
-"Oh yes! Why, it seems 'bout a year ago. It was that very night that I
-follered Injun Joe to the widder's."
-
-"YOU followed him?"
-
-"Yes--but you keep mum. I reckon Injun Joe's left friends behind him,
-and I don't want 'em souring on me and doing me mean tricks. If it
-hadn't ben for me he'd be down in Texas now, all right."
-
-Then Huck told his entire adventure in confidence to Tom, who had only
-heard of the Welshman's part of it before.
-
-"Well," said Huck, presently, coming back to the main question,
-"whoever nipped the whiskey in No. 2, nipped the money, too, I reckon
---anyways it's a goner for us, Tom."
-
-"Huck, that money wasn't ever in No. 2!"
-
-"What!" Huck searched his comrade's face keenly. "Tom, have you got on
-the track of that money again?"
-
-"Huck, it's in the cave!"
-
-Huck's eyes blazed.
-
-"Say it again, Tom."
-
-"The money's in the cave!"
-
-"Tom--honest injun, now--is it fun, or earnest?"
-
-"Earnest, Huck--just as earnest as ever I was in my life. Will you go
-in there with me and help get it out?"
-
-"I bet I will! I will if it's where we can blaze our way to it and not
-get lost."
-
-"Huck, we can do that without the least little bit of trouble in the
-world."
-
-"Good as wheat! What makes you think the money's--"
-
-"Huck, you just wait till we get in there. If we don't find it I'll
-agree to give you my drum and every thing I've got in the world. I
-will, by jings."
-
-"All right--it's a whiz. When do you say?"
-
-"Right now, if you say it. Are you strong enough?"
-
-"Is it far in the cave? I ben on my pins a little, three or four days,
-now, but I can't walk more'n a mile, Tom--least I don't think I could."
-
-"It's about five mile into there the way anybody but me would go,
-Huck, but there's a mighty short cut that they don't anybody but me
-know about. Huck, I'll take you right to it in a skiff. I'll float the
-skiff down there, and I'll pull it back again all by myself. You
-needn't ever turn your hand over."
-
-"Less start right off, Tom."
-
-"All right. We want some bread and meat, and our pipes, and a little
-bag or two, and two or three kite-strings, and some of these
-new-fangled things they call lucifer matches. I tell you, many's
-the time I wished I had some when I was in there before."
-
-A trifle after noon the boys borrowed a small skiff from a citizen who
-was absent, and got under way at once. When they were several miles
-below "Cave Hollow," Tom said:
-
-"Now you see this bluff here looks all alike all the way down from the
-cave hollow--no houses, no wood-yards, bushes all alike. But do you see
-that white place up yonder where there's been a landslide? Well, that's
-one of my marks. We'll get ashore, now."
-
-They landed.
-
-"Now, Huck, where we're a-standing you could touch that hole I got out
-of with a fishing-pole. See if you can find it."
-
-Huck searched all the place about, and found nothing. Tom proudly
-marched into a thick clump of sumach bushes and said:
-
-"Here you are! Look at it, Huck; it's the snuggest hole in this
-country. You just keep mum about it. All along I've been wanting to be
-a robber, but I knew I'd got to have a thing like this, and where to
-run across it was the bother. We've got it now, and we'll keep it
-quiet, only we'll let Joe Harper and Ben Rogers in--because of course
-there's got to be a Gang, or else there wouldn't be any style about it.
-Tom Sawyer's Gang--it sounds splendid, don't it, Huck?"
-
-"Well, it just does, Tom. And who'll we rob?"
-
-"Oh, most anybody. Waylay people--that's mostly the way."
-
-"And kill them?"
-
-"No, not always. Hive them in the cave till they raise a ransom."
-
-"What's a ransom?"
-
-"Money. You make them raise all they can, off'n their friends; and
-after you've kept them a year, if it ain't raised then you kill them.
-That's the general way. Only you don't kill the women. You shut up the
-women, but you don't kill them. They're always beautiful and rich, and
-awfully scared. You take their watches and things, but you always take
-your hat off and talk polite. They ain't anybody as polite as robbers
---you'll see that in any book. Well, the women get to loving you, and
-after they've been in the cave a week or two weeks they stop crying and
-after that you couldn't get them to leave. If you drove them out they'd
-turn right around and come back. It's so in all the books."
-
-"Why, it's real bully, Tom. I believe it's better'n to be a pirate."
-
-"Yes, it's better in some ways, because it's close to home and
-circuses and all that."
-
-By this time everything was ready and the boys entered the hole, Tom
-in the lead. They toiled their way to the farther end of the tunnel,
-then made their spliced kite-strings fast and moved on. A few steps
-brought them to the spring, and Tom felt a shudder quiver all through
-him. He showed Huck the fragment of candle-wick perched on a lump of
-clay against the wall, and described how he and Becky had watched the
-flame struggle and expire.
-
-The boys began to quiet down to whispers, now, for the stillness and
-gloom of the place oppressed their spirits. They went on, and presently
-entered and followed Tom's other corridor until they reached the
-"jumping-off place." The candles revealed the fact that it was not
-really a precipice, but only a steep clay hill twenty or thirty feet
-high. Tom whispered:
-
-"Now I'll show you something, Huck."
-
-He held his candle aloft and said:
-
-"Look as far around the corner as you can. Do you see that? There--on
-the big rock over yonder--done with candle-smoke."
-
-"Tom, it's a CROSS!"
-
-"NOW where's your Number Two? 'UNDER THE CROSS,' hey? Right yonder's
-where I saw Injun Joe poke up his candle, Huck!"
-
-Huck stared at the mystic sign awhile, and then said with a shaky voice:
-
-"Tom, less git out of here!"
-
-"What! and leave the treasure?"
-
-"Yes--leave it. Injun Joe's ghost is round about there, certain."
-
-"No it ain't, Huck, no it ain't. It would ha'nt the place where he
-died--away out at the mouth of the cave--five mile from here."
-
-"No, Tom, it wouldn't. It would hang round the money. I know the ways
-of ghosts, and so do you."
-
-Tom began to fear that Huck was right. Misgivings gathered in his
-mind. But presently an idea occurred to him--
-
-"Lookyhere, Huck, what fools we're making of ourselves! Injun Joe's
-ghost ain't a going to come around where there's a cross!"
-
-The point was well taken. It had its effect.
-
-"Tom, I didn't think of that. But that's so. It's luck for us, that
-cross is. I reckon we'll climb down there and have a hunt for that box."
-
-Tom went first, cutting rude steps in the clay hill as he descended.
-Huck followed. Four avenues opened out of the small cavern which the
-great rock stood in. The boys examined three of them with no result.
-They found a small recess in the one nearest the base of the rock, with
-a pallet of blankets spread down in it; also an old suspender, some
-bacon rind, and the well-gnawed bones of two or three fowls. But there
-was no money-box. The lads searched and researched this place, but in
-vain. Tom said:
-
-"He said UNDER the cross. Well, this comes nearest to being under the
-cross. It can't be under the rock itself, because that sets solid on
-the ground."
-
-They searched everywhere once more, and then sat down discouraged.
-Huck could suggest nothing. By-and-by Tom said:
-
-"Lookyhere, Huck, there's footprints and some candle-grease on the
-clay about one side of this rock, but not on the other sides. Now,
-what's that for? I bet you the money IS under the rock. I'm going to
-dig in the clay."
-
-"That ain't no bad notion, Tom!" said Huck with animation.
-
-Tom's "real Barlow" was out at once, and he had not dug four inches
-before he struck wood.
-
-"Hey, Huck!--you hear that?"
-
-Huck began to dig and scratch now. Some boards were soon uncovered and
-removed. They had concealed a natural chasm which led under the rock.
-Tom got into this and held his candle as far under the rock as he
-could, but said he could not see to the end of the rift. He proposed to
-explore. He stooped and passed under; the narrow way descended
-gradually. He followed its winding course, first to the right, then to
-the left, Huck at his heels. Tom turned a short curve, by-and-by, and
-exclaimed:
-
-"My goodness, Huck, lookyhere!"
-
-It was the treasure-box, sure enough, occupying a snug little cavern,
-along with an empty powder-keg, a couple of guns in leather cases, two
-or three pairs of old moccasins, a leather belt, and some other rubbish
-well soaked with the water-drip.
-
-"Got it at last!" said Huck, ploughing among the tarnished coins with
-his hand. "My, but we're rich, Tom!"
-
-"Huck, I always reckoned we'd get it. It's just too good to believe,
-but we HAVE got it, sure! Say--let's not fool around here. Let's snake
-it out. Lemme see if I can lift the box."
-
-It weighed about fifty pounds. Tom could lift it, after an awkward
-fashion, but could not carry it conveniently.
-
-"I thought so," he said; "THEY carried it like it was heavy, that day
-at the ha'nted house. I noticed that. I reckon I was right to think of
-fetching the little bags along."
-
-The money was soon in the bags and the boys took it up to the cross
-rock.
-
-"Now less fetch the guns and things," said Huck.
-
-"No, Huck--leave them there. They're just the tricks to have when we
-go to robbing. We'll keep them there all the time, and we'll hold our
-orgies there, too. It's an awful snug place for orgies."
-
-"What orgies?"
-
-"I dono. But robbers always have orgies, and of course we've got to
-have them, too. Come along, Huck, we've been in here a long time. It's
-getting late, I reckon. I'm hungry, too. We'll eat and smoke when we
-get to the skiff."
-
-They presently emerged into the clump of sumach bushes, looked warily
-out, found the coast clear, and were soon lunching and smoking in the
-skiff. As the sun dipped toward the horizon they pushed out and got
-under way. Tom skimmed up the shore through the long twilight, chatting
-cheerily with Huck, and landed shortly after dark.
-
-"Now, Huck," said Tom, "we'll hide the money in the loft of the
-widow's woodshed, and I'll come up in the morning and we'll count it
-and divide, and then we'll hunt up a place out in the woods for it
-where it will be safe. Just you lay quiet here and watch the stuff till
-I run and hook Benny Taylor's little wagon; I won't be gone a minute."
-
-He disappeared, and presently returned with the wagon, put the two
-small sacks into it, threw some old rags on top of them, and started
-off, dragging his cargo behind him. When the boys reached the
-Welshman's house, they stopped to rest. Just as they were about to move
-on, the Welshman stepped out and said:
-
-"Hallo, who's that?"
-
-"Huck and Tom Sawyer."
-
-"Good! Come along with me, boys, you are keeping everybody waiting.
-Here--hurry up, trot ahead--I'll haul the wagon for you. Why, it's not
-as light as it might be. Got bricks in it?--or old metal?"
-
-"Old metal," said Tom.
-
-"I judged so; the boys in this town will take more trouble and fool
-away more time hunting up six bits' worth of old iron to sell to the
-foundry than they would to make twice the money at regular work. But
-that's human nature--hurry along, hurry along!"
-
-The boys wanted to know what the hurry was about.
-
-"Never mind; you'll see, when we get to the Widow Douglas'."
-
-Huck said with some apprehension--for he was long used to being
-falsely accused:
-
-"Mr. Jones, we haven't been doing nothing."
-
-The Welshman laughed.
-
-"Well, I don't know, Huck, my boy. I don't know about that. Ain't you
-and the widow good friends?"
-
-"Yes. Well, she's ben good friends to me, anyway."
-
-"All right, then. What do you want to be afraid for?"
-
-This question was not entirely answered in Huck's slow mind before he
-found himself pushed, along with Tom, into Mrs. Douglas' drawing-room.
-Mr. Jones left the wagon near the door and followed.
-
-The place was grandly lighted, and everybody that was of any
-consequence in the village was there. The Thatchers were there, the
-Harpers, the Rogerses, Aunt Polly, Sid, Mary, the minister, the editor,
-and a great many more, and all dressed in their best. The widow
-received the boys as heartily as any one could well receive two such
-looking beings. They were covered with clay and candle-grease. Aunt
-Polly blushed crimson with humiliation, and frowned and shook her head
-at Tom. Nobody suffered half as much as the two boys did, however. Mr.
-Jones said:
-
-"Tom wasn't at home, yet, so I gave him up; but I stumbled on him and
-Huck right at my door, and so I just brought them along in a hurry."
-
-"And you did just right," said the widow. "Come with me, boys."
-
-She took them to a bedchamber and said:
-
-"Now wash and dress yourselves. Here are two new suits of clothes
---shirts, socks, everything complete. They're Huck's--no, no thanks,
-Huck--Mr. Jones bought one and I the other. But they'll fit both of you.
-Get into them. We'll wait--come down when you are slicked up enough."
-
-Then she left.
-
-
-
-CHAPTER XXXIV
-
-HUCK said: "Tom, we can slope, if we can find a rope. The window ain't
-high from the ground."
-
-"Shucks! what do you want to slope for?"
-
-"Well, I ain't used to that kind of a crowd. I can't stand it. I ain't
-going down there, Tom."
-
-"Oh, bother! It ain't anything. I don't mind it a bit. I'll take care
-of you."
-
-Sid appeared.
-
-"Tom," said he, "auntie has been waiting for you all the afternoon.
-Mary got your Sunday clothes ready, and everybody's been fretting about
-you. Say--ain't this grease and clay, on your clothes?"
-
-"Now, Mr. Siddy, you jist 'tend to your own business. What's all this
-blow-out about, anyway?"
-
-"It's one of the widow's parties that she's always having. This time
-it's for the Welshman and his sons, on account of that scrape they
-helped her out of the other night. And say--I can tell you something,
-if you want to know."
-
-"Well, what?"
-
-"Why, old Mr. Jones is going to try to spring something on the people
-here to-night, but I overheard him tell auntie to-day about it, as a
-secret, but I reckon it's not much of a secret now. Everybody knows
---the widow, too, for all she tries to let on she don't. Mr. Jones was
-bound Huck should be here--couldn't get along with his grand secret
-without Huck, you know!"
-
-"Secret about what, Sid?"
-
-"About Huck tracking the robbers to the widow's. I reckon Mr. Jones
-was going to make a grand time over his surprise, but I bet you it will
-drop pretty flat."
-
-Sid chuckled in a very contented and satisfied way.
-
-"Sid, was it you that told?"
-
-"Oh, never mind who it was. SOMEBODY told--that's enough."
-
-"Sid, there's only one person in this town mean enough to do that, and
-that's you. If you had been in Huck's place you'd 'a' sneaked down the
-hill and never told anybody on the robbers. You can't do any but mean
-things, and you can't bear to see anybody praised for doing good ones.
-There--no thanks, as the widow says"--and Tom cuffed Sid's ears and
-helped him to the door with several kicks. "Now go and tell auntie if
-you dare--and to-morrow you'll catch it!"
-
-Some minutes later the widow's guests were at the supper-table, and a
-dozen children were propped up at little side-tables in the same room,
-after the fashion of that country and that day. At the proper time Mr.
-Jones made his little speech, in which he thanked the widow for the
-honor she was doing himself and his sons, but said that there was
-another person whose modesty--
-
-And so forth and so on. He sprung his secret about Huck's share in the
-adventure in the finest dramatic manner he was master of, but the
-surprise it occasioned was largely counterfeit and not as clamorous and
-effusive as it might have been under happier circumstances. However,
-the widow made a pretty fair show of astonishment, and heaped so many
-compliments and so much gratitude upon Huck that he almost forgot the
-nearly intolerable discomfort of his new clothes in the entirely
-intolerable discomfort of being set up as a target for everybody's gaze
-and everybody's laudations.
-
-The widow said she meant to give Huck a home under her roof and have
-him educated; and that when she could spare the money she would start
-him in business in a modest way. Tom's chance was come. He said:
-
-"Huck don't need it. Huck's rich."
-
-Nothing but a heavy strain upon the good manners of the company kept
-back the due and proper complimentary laugh at this pleasant joke. But
-the silence was a little awkward. Tom broke it:
-
-"Huck's got money. Maybe you don't believe it, but he's got lots of
-it. Oh, you needn't smile--I reckon I can show you. You just wait a
-minute."
-
-Tom ran out of doors. The company looked at each other with a
-perplexed interest--and inquiringly at Huck, who was tongue-tied.
-
-"Sid, what ails Tom?" said Aunt Polly. "He--well, there ain't ever any
-making of that boy out. I never--"
-
-Tom entered, struggling with the weight of his sacks, and Aunt Polly
-did not finish her sentence. Tom poured the mass of yellow coin upon
-the table and said:
-
-"There--what did I tell you? Half of it's Huck's and half of it's mine!"
-
-The spectacle took the general breath away. All gazed, nobody spoke
-for a moment. Then there was a unanimous call for an explanation. Tom
-said he could furnish it, and he did. The tale was long, but brimful of
-interest. There was scarcely an interruption from any one to break the
-charm of its flow. When he had finished, Mr. Jones said:
-
-"I thought I had fixed up a little surprise for this occasion, but it
-don't amount to anything now. This one makes it sing mighty small, I'm
-willing to allow."
-
-The money was counted. The sum amounted to a little over twelve
-thousand dollars. It was more than any one present had ever seen at one
-time before, though several persons were there who were worth
-considerably more than that in property.
-
-
-
-CHAPTER XXXV
-
-THE reader may rest satisfied that Tom's and Huck's windfall made a
-mighty stir in the poor little village of St. Petersburg. So vast a
-sum, all in actual cash, seemed next to incredible. It was talked
-about, gloated over, glorified, until the reason of many of the
-citizens tottered under the strain of the unhealthy excitement. Every
-"haunted" house in St. Petersburg and the neighboring villages was
-dissected, plank by plank, and its foundations dug up and ransacked for
-hidden treasure--and not by boys, but men--pretty grave, unromantic
-men, too, some of them. Wherever Tom and Huck appeared they were
-courted, admired, stared at. The boys were not able to remember that
-their remarks had possessed weight before; but now their sayings were
-treasured and repeated; everything they did seemed somehow to be
-regarded as remarkable; they had evidently lost the power of doing and
-saying commonplace things; moreover, their past history was raked up
-and discovered to bear marks of conspicuous originality. The village
-paper published biographical sketches of the boys.
-
-The Widow Douglas put Huck's money out at six per cent., and Judge
-Thatcher did the same with Tom's at Aunt Polly's request. Each lad had
-an income, now, that was simply prodigious--a dollar for every week-day
-in the year and half of the Sundays. It was just what the minister got
---no, it was what he was promised--he generally couldn't collect it. A
-dollar and a quarter a week would board, lodge, and school a boy in
-those old simple days--and clothe him and wash him, too, for that
-matter.
-
-Judge Thatcher had conceived a great opinion of Tom. He said that no
-commonplace boy would ever have got his daughter out of the cave. When
-Becky told her father, in strict confidence, how Tom had taken her
-whipping at school, the Judge was visibly moved; and when she pleaded
-grace for the mighty lie which Tom had told in order to shift that
-whipping from her shoulders to his own, the Judge said with a fine
-outburst that it was a noble, a generous, a magnanimous lie--a lie that
-was worthy to hold up its head and march down through history breast to
-breast with George Washington's lauded Truth about the hatchet! Becky
-thought her father had never looked so tall and so superb as when he
-walked the floor and stamped his foot and said that. She went straight
-off and told Tom about it.
-
-Judge Thatcher hoped to see Tom a great lawyer or a great soldier some
-day. He said he meant to look to it that Tom should be admitted to the
-National Military Academy and afterward trained in the best law school
-in the country, in order that he might be ready for either career or
-both.
-
-Huck Finn's wealth and the fact that he was now under the Widow
-Douglas' protection introduced him into society--no, dragged him into
-it, hurled him into it--and his sufferings were almost more than he
-could bear. The widow's servants kept him clean and neat, combed and
-brushed, and they bedded him nightly in unsympathetic sheets that had
-not one little spot or stain which he could press to his heart and know
-for a friend. He had to eat with a knife and fork; he had to use
-napkin, cup, and plate; he had to learn his book, he had to go to
-church; he had to talk so properly that speech was become insipid in
-his mouth; whithersoever he turned, the bars and shackles of
-civilization shut him in and bound him hand and foot.
-
-He bravely bore his miseries three weeks, and then one day turned up
-missing. For forty-eight hours the widow hunted for him everywhere in
-great distress. The public were profoundly concerned; they searched
-high and low, they dragged the river for his body. Early the third
-morning Tom Sawyer wisely went poking among some old empty hogsheads
-down behind the abandoned slaughter-house, and in one of them he found
-the refugee. Huck had slept there; he had just breakfasted upon some
-stolen odds and ends of food, and was lying off, now, in comfort, with
-his pipe. He was unkempt, uncombed, and clad in the same old ruin of
-rags that had made him picturesque in the days when he was free and
-happy. Tom routed him out, told him the trouble he had been causing,
-and urged him to go home. Huck's face lost its tranquil content, and
-took a melancholy cast. He said:
-
-"Don't talk about it, Tom. I've tried it, and it don't work; it don't
-work, Tom. It ain't for me; I ain't used to it. The widder's good to
-me, and friendly; but I can't stand them ways. She makes me get up just
-at the same time every morning; she makes me wash, they comb me all to
-thunder; she won't let me sleep in the woodshed; I got to wear them
-blamed clothes that just smothers me, Tom; they don't seem to any air
-git through 'em, somehow; and they're so rotten nice that I can't set
-down, nor lay down, nor roll around anywher's; I hain't slid on a
-cellar-door for--well, it 'pears to be years; I got to go to church and
-sweat and sweat--I hate them ornery sermons! I can't ketch a fly in
-there, I can't chaw. I got to wear shoes all Sunday. The widder eats by
-a bell; she goes to bed by a bell; she gits up by a bell--everything's
-so awful reg'lar a body can't stand it."
-
-"Well, everybody does that way, Huck."
-
-"Tom, it don't make no difference. I ain't everybody, and I can't
-STAND it. It's awful to be tied up so. And grub comes too easy--I don't
-take no interest in vittles, that way. I got to ask to go a-fishing; I
-got to ask to go in a-swimming--dern'd if I hain't got to ask to do
-everything. Well, I'd got to talk so nice it wasn't no comfort--I'd got
-to go up in the attic and rip out awhile, every day, to git a taste in
-my mouth, or I'd a died, Tom. The widder wouldn't let me smoke; she
-wouldn't let me yell, she wouldn't let me gape, nor stretch, nor
-scratch, before folks--" [Then with a spasm of special irritation and
-injury]--"And dad fetch it, she prayed all the time! I never see such a
-woman! I HAD to shove, Tom--I just had to. And besides, that school's
-going to open, and I'd a had to go to it--well, I wouldn't stand THAT,
-Tom. Looky here, Tom, being rich ain't what it's cracked up to be. It's
-just worry and worry, and sweat and sweat, and a-wishing you was dead
-all the time. Now these clothes suits me, and this bar'l suits me, and
-I ain't ever going to shake 'em any more. Tom, I wouldn't ever got into
-all this trouble if it hadn't 'a' ben for that money; now you just take
-my sheer of it along with your'n, and gimme a ten-center sometimes--not
-many times, becuz I don't give a dern for a thing 'thout it's tollable
-hard to git--and you go and beg off for me with the widder."
-
-"Oh, Huck, you know I can't do that. 'Tain't fair; and besides if
-you'll try this thing just a while longer you'll come to like it."
-
-"Like it! Yes--the way I'd like a hot stove if I was to set on it long
-enough. No, Tom, I won't be rich, and I won't live in them cussed
-smothery houses. I like the woods, and the river, and hogsheads, and
-I'll stick to 'em, too. Blame it all! just as we'd got guns, and a
-cave, and all just fixed to rob, here this dern foolishness has got to
-come up and spile it all!"
-
-Tom saw his opportunity--
-
-"Lookyhere, Huck, being rich ain't going to keep me back from turning
-robber."
-
-"No! Oh, good-licks; are you in real dead-wood earnest, Tom?"
-
-"Just as dead earnest as I'm sitting here. But Huck, we can't let you
-into the gang if you ain't respectable, you know."
-
-Huck's joy was quenched.
-
-"Can't let me in, Tom? Didn't you let me go for a pirate?"
-
-"Yes, but that's different. A robber is more high-toned than what a
-pirate is--as a general thing. In most countries they're awful high up
-in the nobility--dukes and such."
-
-"Now, Tom, hain't you always ben friendly to me? You wouldn't shet me
-out, would you, Tom? You wouldn't do that, now, WOULD you, Tom?"
-
-"Huck, I wouldn't want to, and I DON'T want to--but what would people
-say? Why, they'd say, 'Mph! Tom Sawyer's Gang! pretty low characters in
-it!' They'd mean you, Huck. You wouldn't like that, and I wouldn't."
-
-Huck was silent for some time, engaged in a mental struggle. Finally
-he said:
-
-"Well, I'll go back to the widder for a month and tackle it and see if
-I can come to stand it, if you'll let me b'long to the gang, Tom."
-
-"All right, Huck, it's a whiz! Come along, old chap, and I'll ask the
-widow to let up on you a little, Huck."
-
-"Will you, Tom--now will you? That's good. If she'll let up on some of
-the roughest things, I'll smoke private and cuss private, and crowd
-through or bust. When you going to start the gang and turn robbers?"
-
-"Oh, right off. We'll get the boys together and have the initiation
-to-night, maybe."
-
-"Have the which?"
-
-"Have the initiation."
-
-"What's that?"
-
-"It's to swear to stand by one another, and never tell the gang's
-secrets, even if you're chopped all to flinders, and kill anybody and
-all his family that hurts one of the gang."
-
-"That's gay--that's mighty gay, Tom, I tell you."
-
-"Well, I bet it is. And all that swearing's got to be done at
-midnight, in the lonesomest, awfulest place you can find--a ha'nted
-house is the best, but they're all ripped up now."
-
-"Well, midnight's good, anyway, Tom."
-
-"Yes, so it is. And you've got to swear on a coffin, and sign it with
-blood."
-
-"Now, that's something LIKE! Why, it's a million times bullier than
-pirating. I'll stick to the widder till I rot, Tom; and if I git to be
-a reg'lar ripper of a robber, and everybody talking 'bout it, I reckon
-she'll be proud she snaked me in out of the wet."
-
-
-
-CONCLUSION
-
-SO endeth this chronicle. It being strictly a history of a BOY, it
-must stop here; the story could not go much further without becoming
-the history of a MAN. When one writes a novel about grown people, he
-knows exactly where to stop--that is, with a marriage; but when he
-writes of juveniles, he must stop where he best can.
-
-Most of the characters that perform in this book still live, and are
-prosperous and happy. Some day it may seem worth while to take up the
-story of the younger ones again and see what sort of men and women they
-turned out to be; therefore it will be wisest not to reveal any of that
-part of their lives at present.
diff --git a/src/net/textproto/reader_test.go b/src/net/textproto/reader_test.go
index 7cff7b4579..f85fbdc36d 100644
--- a/src/net/textproto/reader_test.go
+++ b/src/net/textproto/reader_test.go
@@ -382,31 +382,25 @@ Non-Interned: test
func BenchmarkReadMIMEHeader(b *testing.B) {
b.ReportAllocs()
- var buf bytes.Buffer
- br := bufio.NewReader(&buf)
- r := NewReader(br)
- for i := 0; i < b.N; i++ {
- var want int
- var find string
- if (i & 1) == 1 {
- buf.WriteString(clientHeaders)
- want = 10
- find = "Cookie"
- } else {
- buf.WriteString(serverHeaders)
- want = 9
- find = "Via"
- }
- h, err := r.ReadMIMEHeader()
- if err != nil {
- b.Fatal(err)
- }
- if len(h) != want {
- b.Fatalf("wrong number of headers: got %d, want %d", len(h), want)
- }
- if _, ok := h[find]; !ok {
- b.Fatalf("did not find key %s", find)
- }
+ for _, set := range []struct {
+ name string
+ headers string
+ }{
+ {"client_headers", clientHeaders},
+ {"server_headers", serverHeaders},
+ } {
+ b.Run(set.name, func(b *testing.B) {
+ var buf bytes.Buffer
+ br := bufio.NewReader(&buf)
+ r := NewReader(br)
+
+ for i := 0; i < b.N; i++ {
+ buf.WriteString(set.headers)
+ if _, err := r.ReadMIMEHeader(); err != nil {
+ b.Fatal(err)
+ }
+ }
+ })
}
}
diff --git a/src/net/unixsock_windows_test.go b/src/net/unixsock_windows_test.go
index a1da5d4062..d856e3fd81 100644
--- a/src/net/unixsock_windows_test.go
+++ b/src/net/unixsock_windows_test.go
@@ -10,6 +10,7 @@ import (
"internal/syscall/windows/registry"
"os"
"reflect"
+ "runtime"
"strconv"
"testing"
)
@@ -33,6 +34,9 @@ func isBuild17063() bool {
}
func TestUnixConnLocalWindows(t *testing.T) {
+ if runtime.GOARCH == "386" {
+ t.Skip("not supported on windows/386, see golang.org/issue/27943")
+ }
if !isBuild17063() {
t.Skip("unix test")
}
diff --git a/src/net/url/example_test.go b/src/net/url/example_test.go
index d8eb6dcd20..ad67f5328a 100644
--- a/src/net/url/example_test.go
+++ b/src/net/url/example_test.go
@@ -219,5 +219,5 @@ func toJSON(m interface{}) string {
if err != nil {
log.Fatal(err)
}
- return strings.Replace(string(js), ",", ", ", -1)
+ return strings.ReplaceAll(string(js), ",", ", ")
}
diff --git a/src/net/url/url.go b/src/net/url/url.go
index 4943ea6d67..702f9124bf 100644
--- a/src/net/url/url.go
+++ b/src/net/url/url.go
@@ -304,7 +304,26 @@ func escape(s string, mode encoding) string {
return s
}
- t := make([]byte, len(s)+2*hexCount)
+ var buf [64]byte
+ var t []byte
+
+ required := len(s) + 2*hexCount
+ if required <= len(buf) {
+ t = buf[:required]
+ } else {
+ t = make([]byte, required)
+ }
+
+ if hexCount == 0 {
+ copy(t, s)
+ for i := 0; i < len(s); i++ {
+ if s[i] == ' ' {
+ t[i] = '+'
+ }
+ }
+ return string(t)
+ }
+
j := 0
for i := 0; i < len(s); i++ {
switch c := s[i]; {
@@ -515,13 +534,7 @@ func parse(rawurl string, viaRequest bool) (*URL, error) {
url.ForceQuery = true
rest = rest[:len(rest)-1]
} else {
- var q string
- rest, q = split(rest, "?", true)
- if validQuery(q) {
- url.RawQuery = q
- } else {
- url.RawQuery = QueryEscape(q)
- }
+ rest, url.RawQuery = split(rest, "?", true)
}
if !strings.HasPrefix(rest, "/") {
@@ -1120,46 +1133,3 @@ func validUserinfo(s string) bool {
}
return true
}
-
-// validQuery reports whether s is a valid query string per RFC 3986
-// Section 3.4:
-// query = *( pchar / "/" / "?" )
-// pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
-// unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
-// sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
-// / "*" / "+" / "," / ";" / "="
-func validQuery(s string) bool {
- pctEnc := 0
-
- for _, r := range s {
- if pctEnc > 0 {
- if uint32(r) > 255 || !ishex(byte(r)) {
- return false
- }
- pctEnc--
- continue
- } else if r == '%' {
- pctEnc = 2
- continue
- }
-
- if 'A' <= r && r <= 'Z' {
- continue
- }
- if 'a' <= r && r <= 'z' {
- continue
- }
- if '0' <= r && r <= '9' {
- continue
- }
- switch r {
- case '-', '.', '_', '~', '!', '$', '&', '\'', '(', ')',
- '*', '+', ',', ';', '=', ':', '@', '/', '?':
- continue
- default:
- return false
- }
- }
-
- return true
-}
diff --git a/src/net/url/url_test.go b/src/net/url/url_test.go
index 19d4d636d6..7c4ada245a 100644
--- a/src/net/url/url_test.go
+++ b/src/net/url/url_test.go
@@ -590,16 +590,6 @@ var urltests = []URLTest{
},
"mailto:?subject=hi",
},
- {
- "https://example.com/search?q=Фотки собак&source=lnms",
- &URL{
- Scheme: "https",
- Host: "example.com",
- Path: "/search",
- RawQuery: "q%3D%D0%A4%D0%BE%D1%82%D0%BA%D0%B8+%D1%81%D0%BE%D0%B1%D0%B0%D0%BA%26source%3Dlnms",
- },
- "https://example.com/search?q%3D%D0%A4%D0%BE%D1%82%D0%BA%D0%B8+%D1%81%D0%BE%D0%B1%D0%B0%D0%BA%26source%3Dlnms",
- },
}
// more useful string for debugging than fmt's struct printer
@@ -858,18 +848,18 @@ func TestUnescape(t *testing.T) {
in := tt.in
out := tt.out
if strings.Contains(tt.in, "+") {
- in = strings.Replace(tt.in, "+", "%20", -1)
+ in = strings.ReplaceAll(tt.in, "+", "%20")
actual, err := PathUnescape(in)
if actual != tt.out || (err != nil) != (tt.err != nil) {
t.Errorf("PathUnescape(%q) = %q, %s; want %q, %s", in, actual, err, tt.out, tt.err)
}
if tt.err == nil {
- s, err := QueryUnescape(strings.Replace(tt.in, "+", "XXX", -1))
+ s, err := QueryUnescape(strings.ReplaceAll(tt.in, "+", "XXX"))
if err != nil {
continue
}
in = tt.in
- out = strings.Replace(s, "XXX", "+", -1)
+ out = strings.ReplaceAll(s, "XXX", "+")
}
}
@@ -1449,7 +1439,6 @@ func TestParseErrors(t *testing.T) {
{"cache_object:foo", true},
{"cache_object:foo/bar", true},
{"cache_object/:foo/bar", false},
- {"https://example.com/search?q=Фотки собак&source=lnms", false},
}
for _, tt := range tests {
u, err := Parse(tt.in)
@@ -1754,3 +1743,106 @@ func TestInvalidUserPassword(t *testing.T) {
t.Errorf("error = %q; want substring %q", got, wantsub)
}
}
+
+var escapeBenchmarks = []struct {
+ unescaped string
+ query string
+ path string
+}{
+ {
+ unescaped: "one two",
+ query: "one+two",
+ path: "one%20two",
+ },
+ {
+ unescaped: "Фотки собак",
+ query: "%D0%A4%D0%BE%D1%82%D0%BA%D0%B8+%D1%81%D0%BE%D0%B1%D0%B0%D0%BA",
+ path: "%D0%A4%D0%BE%D1%82%D0%BA%D0%B8%20%D1%81%D0%BE%D0%B1%D0%B0%D0%BA",
+ },
+
+ {
+ unescaped: "shortrun(break)shortrun",
+ query: "shortrun%28break%29shortrun",
+ path: "shortrun%28break%29shortrun",
+ },
+
+ {
+ unescaped: "longerrunofcharacters(break)anotherlongerrunofcharacters",
+ query: "longerrunofcharacters%28break%29anotherlongerrunofcharacters",
+ path: "longerrunofcharacters%28break%29anotherlongerrunofcharacters",
+ },
+
+ {
+ unescaped: strings.Repeat("padded/with+various%characters?that=need$some@escaping+paddedsowebreak/256bytes", 4),
+ query: strings.Repeat("padded%2Fwith%2Bvarious%25characters%3Fthat%3Dneed%24some%40escaping%2Bpaddedsowebreak%2F256bytes", 4),
+ path: strings.Repeat("padded%2Fwith+various%25characters%3Fthat=need$some@escaping+paddedsowebreak%2F256bytes", 4),
+ },
+}
+
+func BenchmarkQueryEscape(b *testing.B) {
+ for _, tc := range escapeBenchmarks {
+ b.Run("", func(b *testing.B) {
+ b.ReportAllocs()
+ var g string
+ for i := 0; i < b.N; i++ {
+ g = QueryEscape(tc.unescaped)
+ }
+ b.StopTimer()
+ if g != tc.query {
+ b.Errorf("QueryEscape(%q) == %q, want %q", tc.unescaped, g, tc.query)
+ }
+
+ })
+ }
+}
+
+func BenchmarkPathEscape(b *testing.B) {
+ for _, tc := range escapeBenchmarks {
+ b.Run("", func(b *testing.B) {
+ b.ReportAllocs()
+ var g string
+ for i := 0; i < b.N; i++ {
+ g = PathEscape(tc.unescaped)
+ }
+ b.StopTimer()
+ if g != tc.path {
+ b.Errorf("PathEscape(%q) == %q, want %q", tc.unescaped, g, tc.path)
+ }
+
+ })
+ }
+}
+
+func BenchmarkQueryUnescape(b *testing.B) {
+ for _, tc := range escapeBenchmarks {
+ b.Run("", func(b *testing.B) {
+ b.ReportAllocs()
+ var g string
+ for i := 0; i < b.N; i++ {
+ g, _ = QueryUnescape(tc.query)
+ }
+ b.StopTimer()
+ if g != tc.unescaped {
+ b.Errorf("QueryUnescape(%q) == %q, want %q", tc.query, g, tc.unescaped)
+ }
+
+ })
+ }
+}
+
+func BenchmarkPathUnescape(b *testing.B) {
+ for _, tc := range escapeBenchmarks {
+ b.Run("", func(b *testing.B) {
+ b.ReportAllocs()
+ var g string
+ for i := 0; i < b.N; i++ {
+ g, _ = PathUnescape(tc.path)
+ }
+ b.StopTimer()
+ if g != tc.unescaped {
+ b.Errorf("PathUnescape(%q) == %q, want %q", tc.path, g, tc.unescaped)
+ }
+
+ })
+ }
+}
diff --git a/src/os/example_test.go b/src/os/example_test.go
index 95a4a67817..5c96ebb417 100644
--- a/src/os/example_test.go
+++ b/src/os/example_test.go
@@ -76,32 +76,29 @@ func ExampleIsNotExist() {
// file does not exist
}
-func init() {
- os.Setenv("USER", "gopher")
- os.Setenv("HOME", "/usr/gopher")
- os.Unsetenv("GOPATH")
-}
-
func ExampleExpand() {
mapper := func(placeholderName string) string {
switch placeholderName {
case "DAY_PART":
return "morning"
- case "USER":
+ case "NAME":
return "Gopher"
}
return ""
}
- fmt.Println(os.Expand("Good ${DAY_PART}, $USER!", mapper))
+ fmt.Println(os.Expand("Good ${DAY_PART}, $NAME!", mapper))
// Output:
// Good morning, Gopher!
}
func ExampleExpandEnv() {
- fmt.Println(os.ExpandEnv("$USER lives in ${HOME}."))
+ os.Setenv("NAME", "gopher")
+ os.Setenv("BURROW", "/usr/gopher")
+
+ fmt.Println(os.ExpandEnv("$NAME lives in ${BURROW}."))
// Output:
// gopher lives in /usr/gopher.
@@ -117,16 +114,24 @@ func ExampleLookupEnv() {
}
}
- show("USER")
- show("GOPATH")
+ os.Setenv("SOME_KEY", "value")
+ os.Setenv("EMPTY_KEY", "")
+
+ show("SOME_KEY")
+ show("EMPTY_KEY")
+ show("MISSING_KEY")
// Output:
- // USER=gopher
- // GOPATH not set
+ // SOME_KEY=value
+ // EMPTY_KEY=
+ // MISSING_KEY not set
}
func ExampleGetenv() {
- fmt.Printf("%s lives in %s.\n", os.Getenv("USER"), os.Getenv("HOME"))
+ os.Setenv("NAME", "gopher")
+ os.Setenv("BURROW", "/usr/gopher")
+
+ fmt.Printf("%s lives in %s.\n", os.Getenv("NAME"), os.Getenv("BURROW"))
// Output:
// gopher lives in /usr/gopher.
diff --git a/src/os/file.go b/src/os/file.go
index cba70d78fb..eb2277dece 100644
--- a/src/os/file.go
+++ b/src/os/file.go
@@ -381,6 +381,24 @@ func UserCacheDir() (string, error) {
return dir, nil
}
+// UserHomeDir returns the current user's home directory.
+//
+// On Unix, including macOS, it returns the $HOME environment variable.
+// On Windows, it returns the concatenation of %HOMEDRIVE% and %HOMEPATH%.
+// On Plan 9, it returns the $home environment variable.
+func UserHomeDir() string {
+ if runtime.GOOS == "windows" {
+ return Getenv("HOMEDRIVE") + Getenv("HOMEPATH")
+ }
+ if runtime.GOOS == "plan9" {
+ return Getenv("home")
+ }
+ if runtime.GOOS == "nacl" {
+ return "/"
+ }
+ return Getenv("HOME")
+}
+
// Chmod changes the mode of the named file to mode.
// If the file is a symbolic link, it changes the mode of the link's target.
// If there is an error, it will be of type *PathError.
diff --git a/src/os/os_test.go b/src/os/os_test.go
index 894105a886..08853691a9 100644
--- a/src/os/os_test.go
+++ b/src/os/os_test.go
@@ -2333,3 +2333,17 @@ func TestDoubleCloseError(t *testing.T) {
t.Logf("second close returned expected error %q", err)
}
}
+
+func TestUserHomeDir(t *testing.T) {
+ dir := UserHomeDir()
+ if dir == "" {
+ t.Fatal("UserHomeDir returned an empty string")
+ }
+ fi, err := Stat(dir)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !fi.IsDir() {
+ t.Fatalf("dir %s is not directory; type = %v", dir, fi.Mode())
+ }
+}
diff --git a/src/os/os_unix_test.go b/src/os/os_unix_test.go
index 54f121ef4c..1077d78613 100644
--- a/src/os/os_unix_test.go
+++ b/src/os/os_unix_test.go
@@ -234,7 +234,7 @@ func newFileTest(t *testing.T, blocking bool) {
}
defer syscall.Close(p[1])
- // Set the the read-side to non-blocking.
+ // Set the read-side to non-blocking.
if !blocking {
if err := syscall.SetNonblock(p[0], true); err != nil {
syscall.Close(p[0])
diff --git a/src/os/os_windows_test.go b/src/os/os_windows_test.go
index 8984dd2c66..c555369488 100644
--- a/src/os/os_windows_test.go
+++ b/src/os/os_windows_test.go
@@ -895,16 +895,6 @@ func main() {
}
}
-func testIsDir(t *testing.T, path string, fi os.FileInfo) {
- t.Helper()
- if !fi.IsDir() {
- t.Errorf("%q should be a directory", path)
- }
- if fi.Mode()&os.ModeSymlink != 0 {
- t.Errorf("%q should not be a symlink", path)
- }
-}
-
func findOneDriveDir() (string, error) {
// as per https://stackoverflow.com/questions/42519624/how-to-determine-location-of-onedrive-on-windows-7-and-8-in-c
const onedrivekey = `SOFTWARE\Microsoft\OneDrive`
@@ -927,57 +917,7 @@ func TestOneDrive(t *testing.T) {
if err != nil {
t.Skipf("Skipping, because we did not find OneDrive directory: %v", err)
}
-
- // test os.Stat
- fi, err := os.Stat(dir)
- if err != nil {
- t.Fatal(err)
- }
- testIsDir(t, dir, fi)
-
- // test os.Lstat
- fi, err = os.Lstat(dir)
- if err != nil {
- t.Fatal(err)
- }
- testIsDir(t, dir, fi)
-
- // test os.File.Stat
- f, err := os.Open(dir)
- if err != nil {
- t.Fatal(err)
- }
- defer f.Close()
-
- fi, err = f.Stat()
- if err != nil {
- t.Fatal(err)
- }
- testIsDir(t, dir, fi)
-
- // test os.FileInfo returned by os.Readdir
- parent, err := os.Open(filepath.Dir(dir))
- if err != nil {
- t.Fatal(err)
- }
- defer parent.Close()
-
- fis, err := parent.Readdir(-1)
- if err != nil {
- t.Fatal(err)
- }
- fi = nil
- base := filepath.Base(dir)
- for _, fi2 := range fis {
- if fi2.Name() == base {
- fi = fi2
- break
- }
- }
- if fi == nil {
- t.Errorf("failed to find %q in its parent", dir)
- }
- testIsDir(t, dir, fi)
+ testDirStats(t, dir)
}
func TestWindowsDevNullFile(t *testing.T) {
diff --git a/src/os/path_windows_test.go b/src/os/path_windows_test.go
index 00a3e63bf3..f1745ad132 100644
--- a/src/os/path_windows_test.go
+++ b/src/os/path_windows_test.go
@@ -38,10 +38,10 @@ func TestFixLongPath(t *testing.T) {
{`\\?\c:\long\foo.txt`, `\\?\c:\long\foo.txt`},
{`\\?\c:\long/foo.txt`, `\\?\c:\long/foo.txt`},
} {
- in := strings.Replace(test.in, "long", veryLong, -1)
- want := strings.Replace(test.want, "long", veryLong, -1)
+ in := strings.ReplaceAll(test.in, "long", veryLong)
+ want := strings.ReplaceAll(test.want, "long", veryLong)
if got := os.FixLongPath(in); got != want {
- got = strings.Replace(got, veryLong, "long", -1)
+ got = strings.ReplaceAll(got, veryLong, "long")
t.Errorf("fixLongPath(%q) = %q; want %q", test.in, got, test.want)
}
}
diff --git a/src/os/stat_test.go b/src/os/stat_test.go
new file mode 100644
index 0000000000..d59edeb547
--- /dev/null
+++ b/src/os/stat_test.go
@@ -0,0 +1,276 @@
+// Copyright 2018 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 os_test
+
+import (
+ "internal/testenv"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "runtime"
+ "testing"
+)
+
+// testStatAndLstat verifies that all os.Stat, os.Lstat os.File.Stat and os.Readdir work.
+func testStatAndLstat(t *testing.T, path string, isLink bool, statCheck, lstatCheck func(*testing.T, string, os.FileInfo)) {
+ // test os.Stat
+ sfi, err := os.Stat(path)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ statCheck(t, path, sfi)
+
+ // test os.Lstat
+ lsfi, err := os.Lstat(path)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ lstatCheck(t, path, lsfi)
+
+ if isLink {
+ if os.SameFile(sfi, lsfi) {
+ t.Errorf("stat and lstat of %q should not be the same", path)
+ }
+ } else {
+ if !os.SameFile(sfi, lsfi) {
+ t.Errorf("stat and lstat of %q should be the same", path)
+ }
+ }
+
+ // test os.File.Stat
+ f, err := os.Open(path)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ defer f.Close()
+
+ sfi2, err := f.Stat()
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ statCheck(t, path, sfi2)
+
+ if !os.SameFile(sfi, sfi2) {
+ t.Errorf("stat of open %q file and stat of %q should be the same", path, path)
+ }
+
+ if isLink {
+ if os.SameFile(sfi2, lsfi) {
+ t.Errorf("stat of opened %q file and lstat of %q should not be the same", path, path)
+ }
+ } else {
+ if !os.SameFile(sfi2, lsfi) {
+ t.Errorf("stat of opened %q file and lstat of %q should be the same", path, path)
+ }
+ }
+
+ // test os.FileInfo returned by os.Readdir
+ if len(path) > 0 && os.IsPathSeparator(path[len(path)-1]) {
+ // skip os.Readdir test of directories with slash at the end
+ return
+ }
+ parentdir := filepath.Dir(path)
+ parent, err := os.Open(parentdir)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ defer parent.Close()
+
+ fis, err := parent.Readdir(-1)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ var lsfi2 os.FileInfo
+ base := filepath.Base(path)
+ for _, fi2 := range fis {
+ if fi2.Name() == base {
+ lsfi2 = fi2
+ break
+ }
+ }
+ if lsfi2 == nil {
+ t.Errorf("failed to find %q in its parent", path)
+ return
+ }
+ lstatCheck(t, path, lsfi2)
+
+ if !os.SameFile(lsfi, lsfi2) {
+ t.Errorf("lstat of %q file in %q directory and %q should be the same", lsfi2.Name(), parentdir, path)
+ }
+}
+
+// testIsDir verifies that fi refers to directory.
+func testIsDir(t *testing.T, path string, fi os.FileInfo) {
+ t.Helper()
+ if !fi.IsDir() {
+ t.Errorf("%q should be a directory", path)
+ }
+ if fi.Mode()&os.ModeSymlink != 0 {
+ t.Errorf("%q should not be a symlink", path)
+ }
+}
+
+// testIsSymlink verifies that fi refers to symlink.
+func testIsSymlink(t *testing.T, path string, fi os.FileInfo) {
+ t.Helper()
+ if fi.IsDir() {
+ t.Errorf("%q should not be a directory", path)
+ }
+ if fi.Mode()&os.ModeSymlink == 0 {
+ t.Errorf("%q should be a symlink", path)
+ }
+}
+
+// testIsFile verifies that fi refers to file.
+func testIsFile(t *testing.T, path string, fi os.FileInfo) {
+ t.Helper()
+ if fi.IsDir() {
+ t.Errorf("%q should not be a directory", path)
+ }
+ if fi.Mode()&os.ModeSymlink != 0 {
+ t.Errorf("%q should not be a symlink", path)
+ }
+}
+
+func testDirStats(t *testing.T, path string) {
+ testStatAndLstat(t, path, false, testIsDir, testIsDir)
+}
+
+func testFileStats(t *testing.T, path string) {
+ testStatAndLstat(t, path, false, testIsFile, testIsFile)
+}
+
+func testSymlinkStats(t *testing.T, path string, isdir bool) {
+ if isdir {
+ testStatAndLstat(t, path, true, testIsDir, testIsSymlink)
+ } else {
+ testStatAndLstat(t, path, true, testIsFile, testIsSymlink)
+ }
+}
+
+func testSymlinkSameFile(t *testing.T, path, link string) {
+ pathfi, err := os.Stat(path)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+
+ linkfi, err := os.Stat(link)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if !os.SameFile(pathfi, linkfi) {
+ t.Errorf("os.Stat(%q) and os.Stat(%q) are not the same file", path, link)
+ }
+
+ linkfi, err = os.Lstat(link)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if os.SameFile(pathfi, linkfi) {
+ t.Errorf("os.Stat(%q) and os.Lstat(%q) are the same file", path, link)
+ }
+}
+
+func TestDirAndSymlinkStats(t *testing.T) {
+ testenv.MustHaveSymlink(t)
+
+ tmpdir, err := ioutil.TempDir("", "TestDirAndSymlinkStats")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(tmpdir)
+
+ dir := filepath.Join(tmpdir, "dir")
+ err = os.Mkdir(dir, 0777)
+ if err != nil {
+ t.Fatal(err)
+ }
+ testDirStats(t, dir)
+
+ dirlink := filepath.Join(tmpdir, "link")
+ err = os.Symlink(dir, dirlink)
+ if err != nil {
+ t.Fatal(err)
+ }
+ testSymlinkStats(t, dirlink, true)
+ testSymlinkSameFile(t, dir, dirlink)
+}
+
+func TestFileAndSymlinkStats(t *testing.T) {
+ testenv.MustHaveSymlink(t)
+
+ tmpdir, err := ioutil.TempDir("", "TestFileAndSymlinkStats")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(tmpdir)
+
+ file := filepath.Join(tmpdir, "file")
+ err = ioutil.WriteFile(file, []byte(""), 0644)
+ if err != nil {
+ t.Fatal(err)
+ }
+ testFileStats(t, file)
+
+ filelink := filepath.Join(tmpdir, "link")
+ err = os.Symlink(file, filelink)
+ if err != nil {
+ t.Fatal(err)
+ }
+ testSymlinkStats(t, filelink, false)
+ testSymlinkSameFile(t, file, filelink)
+}
+
+// see issue 27225 for details
+func TestSymlinkWithTrailingSlash(t *testing.T) {
+ if runtime.GOOS == "windows" {
+ t.Skip("skipping on windows; issue 27225")
+ }
+
+ testenv.MustHaveSymlink(t)
+
+ tmpdir, err := ioutil.TempDir("", "TestSymlinkWithTrailingSlash")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(tmpdir)
+
+ dir := filepath.Join(tmpdir, "dir")
+ err = os.Mkdir(dir, 0777)
+ if err != nil {
+ t.Fatal(err)
+ }
+ dirlink := filepath.Join(tmpdir, "link")
+ err = os.Symlink(dir, dirlink)
+ if err != nil {
+ t.Fatal(err)
+ }
+ dirlinkWithSlash := dirlink + string(os.PathSeparator)
+
+ testDirStats(t, dirlinkWithSlash)
+
+ fi1, err := os.Stat(dir)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ fi2, err := os.Stat(dirlinkWithSlash)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if !os.SameFile(fi1, fi2) {
+ t.Errorf("os.Stat(%q) and os.Stat(%q) are not the same file", dir, dirlinkWithSlash)
+ }
+}
diff --git a/src/os/types.go b/src/os/types.go
index b0b7d8d94d..4b6c084838 100644
--- a/src/os/types.go
+++ b/src/os/types.go
@@ -57,7 +57,7 @@ const (
ModeIrregular // ?: non-regular file; nothing else is known about this file
// Mask for the type bits. For regular files, none will be set.
- ModeType = ModeDir | ModeSymlink | ModeNamedPipe | ModeSocket | ModeDevice | ModeIrregular
+ ModeType = ModeDir | ModeSymlink | ModeNamedPipe | ModeSocket | ModeDevice | ModeCharDevice | ModeIrregular
ModePerm FileMode = 0777 // Unix permission bits
)
diff --git a/src/os/types_windows.go b/src/os/types_windows.go
index f3297c0338..7ebeec50ef 100644
--- a/src/os/types_windows.go
+++ b/src/os/types_windows.go
@@ -211,7 +211,13 @@ func (fs *fileStat) loadFileId() error {
if err != nil {
return err
}
- h, err := syscall.CreateFile(pathp, 0, 0, nil, syscall.OPEN_EXISTING, syscall.FILE_FLAG_BACKUP_SEMANTICS, 0)
+ attrs := uint32(syscall.FILE_FLAG_BACKUP_SEMANTICS)
+ if fs.isSymlink() {
+ // Use FILE_FLAG_OPEN_REPARSE_POINT, otherwise CreateFile will follow symlink.
+ // See https://docs.microsoft.com/en-us/windows/desktop/FileIO/symbolic-link-effects-on-file-systems-functions#createfile-and-createfiletransacted
+ attrs |= syscall.FILE_FLAG_OPEN_REPARSE_POINT
+ }
+ h, err := syscall.CreateFile(pathp, 0, 0, nil, syscall.OPEN_EXISTING, attrs, 0)
if err != nil {
return err
}
diff --git a/src/os/user/lookup.go b/src/os/user/lookup.go
index 2243a25788..b36b7c01c0 100644
--- a/src/os/user/lookup.go
+++ b/src/os/user/lookup.go
@@ -7,6 +7,10 @@ package user
import "sync"
// Current returns the current user.
+//
+// The first call will cache the current user information.
+// Subsequent calls will return the cached value and will not reflect
+// changes to the current user.
func Current() (*User, error) {
cache.Do(func() { cache.u, cache.err = current() })
if cache.err != nil {
diff --git a/src/os/user/lookup_stubs.go b/src/os/user/lookup_stubs.go
index f7d138ff46..9fc03c65d9 100644
--- a/src/os/user/lookup_stubs.go
+++ b/src/os/user/lookup_stubs.go
@@ -19,8 +19,15 @@ func init() {
}
func current() (*User, error) {
- u := &User{
- Uid: currentUID(),
+ uid := currentUID()
+ // $USER and /etc/passwd may disagree; prefer the latter if we can get it.
+ // See issue 27524 for more information.
+ u, err := lookupUserId(uid)
+ if err == nil {
+ return u, nil
+ }
+ u = &User{
+ Uid: uid,
Gid: currentGID(),
Username: os.Getenv("USER"),
Name: "", // ignored
diff --git a/src/os/user/user_test.go b/src/os/user/user_test.go
index 8fd760e649..2563077eb2 100644
--- a/src/os/user/user_test.go
+++ b/src/os/user/user_test.go
@@ -5,33 +5,18 @@
package user
import (
- "internal/testenv"
- "os"
"runtime"
"testing"
)
func checkUser(t *testing.T) {
+ t.Helper()
if !userImplemented {
t.Skip("user: not implemented; skipping tests")
}
}
func TestCurrent(t *testing.T) {
- // The Go builders (in particular the ones using containers)
- // often have minimal environments without $HOME or $USER set,
- // which breaks Current which relies on those working as a
- // fallback.
- // TODO: we should fix that (Issue 24884) and remove these
- // workarounds.
- if testenv.Builder() != "" && runtime.GOOS != "windows" && runtime.GOOS != "plan9" {
- if os.Getenv("HOME") == "" {
- os.Setenv("HOME", "/tmp")
- }
- if os.Getenv("USER") == "" {
- os.Setenv("USER", "gobuilder")
- }
- }
u, err := Current()
if err != nil {
t.Fatalf("Current: %v (got %#v)", err, u)
@@ -108,6 +93,7 @@ func TestLookupId(t *testing.T) {
}
func checkGroup(t *testing.T) {
+ t.Helper()
if !groupImplemented {
t.Skip("user: group not implemented; skipping test")
}
diff --git a/src/path/filepath/path.go b/src/path/filepath/path.go
index 1508137a33..bbb90306a7 100644
--- a/src/path/filepath/path.go
+++ b/src/path/filepath/path.go
@@ -96,14 +96,19 @@ func Clean(path string) string {
}
return originalPath + "."
}
+
+ n := len(path)
+ if volLen > 2 && n == 1 && os.IsPathSeparator(path[0]) {
+ // UNC volume name with trailing slash.
+ return FromSlash(originalPath[:volLen])
+ }
rooted := os.IsPathSeparator(path[0])
// Invariants:
// reading from path; r is index of next byte to process.
- // writing to buf; w is index of next byte to write.
- // dotdot is index in buf where .. must stop, either because
+ // writing to out; w is index of next byte to write.
+ // dotdot is index in out where .. must stop, either because
// it is the leading slash or it is a leading ../../.. prefix.
- n := len(path)
out := lazybuf{path: path, volAndPath: originalPath, volLen: volLen}
r, dotdot := 0, 0
if rooted {
@@ -166,7 +171,7 @@ func ToSlash(path string) string {
if Separator == '/' {
return path
}
- return strings.Replace(path, string(Separator), "/", -1)
+ return strings.ReplaceAll(path, string(Separator), "/")
}
// FromSlash returns the result of replacing each slash ('/') character
@@ -176,7 +181,7 @@ func FromSlash(path string) string {
if Separator == '/' {
return path
}
- return strings.Replace(path, "/", string(Separator), -1)
+ return strings.ReplaceAll(path, "/", string(Separator))
}
// SplitList splits a list of paths joined by the OS-specific ListSeparator,
diff --git a/src/path/filepath/path_test.go b/src/path/filepath/path_test.go
index e50ee97bcb..eddae4755b 100644
--- a/src/path/filepath/path_test.go
+++ b/src/path/filepath/path_test.go
@@ -92,6 +92,9 @@ var wincleantests = []PathTest{
{`//host/share/foo/../baz`, `\\host\share\baz`},
{`\\a\b\..\c`, `\\a\b\c`},
{`\\a\b`, `\\a\b`},
+ {`\\a\b\`, `\\a\b`},
+ {`\\folder\share\foo`, `\\folder\share\foo`},
+ {`\\folder\share\foo\`, `\\folder\share\foo`},
}
func TestClean(t *testing.T) {
@@ -771,6 +774,18 @@ var EvalSymlinksTestDirs = []EvalSymlinksTest{
{"test/link1", "../test"},
{"test/link2", "dir"},
{"test/linkabs", "/"},
+ {"test/link4", "../test2"},
+ {"test2", "test/dir"},
+ // Issue 23444.
+ {"src", ""},
+ {"src/pool", ""},
+ {"src/pool/test", ""},
+ {"src/versions", ""},
+ {"src/versions/current", "../../version"},
+ {"src/versions/v1", ""},
+ {"src/versions/v1/modules", ""},
+ {"src/versions/v1/modules/test", "../../../pool/test"},
+ {"version", "src/versions/v1"},
}
var EvalSymlinksTests = []EvalSymlinksTest{
@@ -784,6 +799,8 @@ var EvalSymlinksTests = []EvalSymlinksTest{
{"test/dir/link3", "."},
{"test/link2/link3/test", "test"},
{"test/linkabs", "/"},
+ {"test/link4/..", "test"},
+ {"src/versions/current/modules/test", "src/pool/test"},
}
// simpleJoin builds a file name from the directory and path.
@@ -1048,7 +1065,7 @@ func TestAbs(t *testing.T) {
}
for _, path := range absTests {
- path = strings.Replace(path, "$", root, -1)
+ path = strings.ReplaceAll(path, "$", root)
info, err := os.Stat(path)
if err != nil {
t.Errorf("%s: %s", path, err)
diff --git a/src/path/filepath/path_windows.go b/src/path/filepath/path_windows.go
index 519b6ebc32..6a144d9e0b 100644
--- a/src/path/filepath/path_windows.go
+++ b/src/path/filepath/path_windows.go
@@ -100,7 +100,7 @@ func splitList(path string) []string {
// Remove quotes.
for i, s := range list {
- list[i] = strings.Replace(s, `"`, ``, -1)
+ list[i] = strings.ReplaceAll(s, `"`, ``)
}
return list
diff --git a/src/path/filepath/path_windows_test.go b/src/path/filepath/path_windows_test.go
index e36a3c9b64..63eab18116 100644
--- a/src/path/filepath/path_windows_test.go
+++ b/src/path/filepath/path_windows_test.go
@@ -431,7 +431,7 @@ func TestToNorm(t *testing.T) {
t.Fatal(err)
}
- err = os.MkdirAll(strings.Replace(testPath, "{{tmp}}", ctmp, -1), 0777)
+ err = os.MkdirAll(strings.ReplaceAll(testPath, "{{tmp}}", ctmp), 0777)
if err != nil {
t.Fatal(err)
}
diff --git a/src/path/filepath/symlink.go b/src/path/filepath/symlink.go
index 824aee4e49..98a92357be 100644
--- a/src/path/filepath/symlink.go
+++ b/src/path/filepath/symlink.go
@@ -10,109 +10,126 @@ import (
"runtime"
)
-// isRoot returns true if path is root of file system
-// (`/` on unix and `/`, `\`, `c:\` or `c:/` on windows).
-func isRoot(path string) bool {
- if runtime.GOOS != "windows" {
- return path == "/"
- }
- switch len(path) {
- case 1:
- return os.IsPathSeparator(path[0])
- case 3:
- return path[1] == ':' && os.IsPathSeparator(path[2])
+func walkSymlinks(path string) (string, error) {
+ volLen := volumeNameLen(path)
+ if volLen < len(path) && os.IsPathSeparator(path[volLen]) {
+ volLen++
}
- return false
-}
+ vol := path[:volLen]
+ dest := vol
+ linksWalked := 0
+ for start, end := volLen, volLen; start < len(path); start = end {
+ for start < len(path) && os.IsPathSeparator(path[start]) {
+ start++
+ }
+ end = start
+ for end < len(path) && !os.IsPathSeparator(path[end]) {
+ end++
+ }
-// isDriveLetter returns true if path is Windows drive letter (like "c:").
-func isDriveLetter(path string) bool {
- if runtime.GOOS != "windows" {
- return false
- }
- return len(path) == 2 && path[1] == ':'
-}
+ // On Windows, "." can be a symlink.
+ // We look it up, and use the value if it is absolute.
+ // If not, we just return ".".
+ isWindowsDot := runtime.GOOS == "windows" && path[volumeNameLen(path):] == "."
-func walkLink(path string, linksWalked *int) (newpath string, islink bool, err error) {
- if *linksWalked > 255 {
- return "", false, errors.New("EvalSymlinks: too many links")
- }
- fi, err := os.Lstat(path)
- if err != nil {
- return "", false, err
- }
- if fi.Mode()&os.ModeSymlink == 0 {
- return path, false, nil
- }
- newpath, err = os.Readlink(path)
- if err != nil {
- return "", false, err
- }
- *linksWalked++
- return newpath, true, nil
-}
-
-func walkLinks(path string, linksWalked *int) (string, error) {
- switch dir, file := Split(path); {
- case dir == "":
- newpath, _, err := walkLink(file, linksWalked)
- return newpath, err
- case file == "":
- if isDriveLetter(dir) {
- return dir, nil
- }
- if os.IsPathSeparator(dir[len(dir)-1]) {
- if isRoot(dir) {
- return dir, nil
+ // The next path component is in path[start:end].
+ if end == start {
+ // No more path components.
+ break
+ } else if path[start:end] == "." && !isWindowsDot {
+ // Ignore path component ".".
+ continue
+ } else if path[start:end] == ".." {
+ // Back up to previous component if possible.
+ // Note that volLen includes any leading slash.
+ var r int
+ for r = len(dest) - 1; r >= volLen; r-- {
+ if os.IsPathSeparator(dest[r]) {
+ break
+ }
+ }
+ if r < volLen {
+ if len(dest) > volLen {
+ dest += string(os.PathSeparator)
+ }
+ dest += ".."
+ } else {
+ dest = dest[:r]
}
- return walkLinks(dir[:len(dir)-1], linksWalked)
+ continue
}
- newpath, _, err := walkLink(dir, linksWalked)
- return newpath, err
- default:
- newdir, err := walkLinks(dir, linksWalked)
- if err != nil {
- return "", err
+
+ // Ordinary path component. Add it to result.
+
+ if len(dest) > volumeNameLen(dest) && !os.IsPathSeparator(dest[len(dest)-1]) {
+ dest += string(os.PathSeparator)
}
- newpath, islink, err := walkLink(Join(newdir, file), linksWalked)
+
+ dest += path[start:end]
+
+ // Resolve symlink.
+
+ fi, err := os.Lstat(dest)
if err != nil {
return "", err
}
- if !islink {
- return newpath, nil
+
+ if fi.Mode()&os.ModeSymlink == 0 {
+ if !fi.Mode().IsDir() && end < len(path) {
+ return "", os.ErrNotExist
+ }
+ continue
}
- if IsAbs(newpath) || os.IsPathSeparator(newpath[0]) {
- return newpath, nil
+
+ // Found symlink.
+
+ linksWalked++
+ if linksWalked > 255 {
+ return "", errors.New("EvalSymlinks: too many links")
}
- return Join(newdir, newpath), nil
- }
-}
-func walkSymlinks(path string) (string, error) {
- if path == "" {
- return path, nil
- }
- var linksWalked int // to protect against cycles
- for {
- i := linksWalked
- newpath, err := walkLinks(path, &linksWalked)
+ link, err := os.Readlink(dest)
if err != nil {
return "", err
}
- if runtime.GOOS == "windows" {
- // walkLinks(".", ...) always returns "." on unix.
- // But on windows it returns symlink target, if current
- // directory is a symlink. Stop the walk, if symlink
- // target is not absolute path, and return "."
- // to the caller (just like unix does).
- // Same for "C:.".
- if path[volumeNameLen(path):] == "." && !IsAbs(newpath) {
- return path, nil
- }
+
+ if isWindowsDot && !IsAbs(link) {
+ // On Windows, if "." is a relative symlink,
+ // just return ".".
+ break
}
- if i == linksWalked {
- return Clean(newpath), nil
+
+ path = link + path[end:]
+
+ v := volumeNameLen(link)
+ if v > 0 {
+ // Symlink to drive name is an absolute path.
+ if v < len(link) && os.IsPathSeparator(link[v]) {
+ v++
+ }
+ vol = link[:v]
+ dest = vol
+ end = len(vol)
+ } else if len(link) > 0 && os.IsPathSeparator(link[0]) {
+ // Symlink to absolute path.
+ dest = link[:1]
+ end = 1
+ } else {
+ // Symlink to relative path; replace last
+ // path component in dest.
+ var r int
+ for r = len(dest) - 1; r >= volLen; r-- {
+ if os.IsPathSeparator(dest[r]) {
+ break
+ }
+ }
+ if r < volLen {
+ dest = vol
+ } else {
+ dest = dest[:r]
+ }
+ end = 0
}
- path = newpath
}
+ return Clean(dest), nil
}
diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go
index c616b37008..c463b61c57 100644
--- a/src/reflect/all_test.go
+++ b/src/reflect/all_test.go
@@ -5844,7 +5844,7 @@ func clobber() {
type funcLayoutTest struct {
rcvr, t Type
size, argsize, retOffset uintptr
- stack []byte // pointer bitmap: 1 is pointer, 0 is scalar (or uninitialized)
+ stack []byte // pointer bitmap: 1 is pointer, 0 is scalar
gc []byte
}
@@ -5866,7 +5866,7 @@ func init() {
6 * PtrSize,
4 * PtrSize,
4 * PtrSize,
- []byte{1, 0, 1},
+ []byte{1, 0, 1, 0, 1},
[]byte{1, 0, 1, 0, 1},
})
@@ -5988,7 +5988,8 @@ func TestFuncLayout(t *testing.T) {
func verifyGCBits(t *testing.T, typ Type, bits []byte) {
heapBits := GCBits(New(typ).Interface())
if !bytes.Equal(heapBits, bits) {
- t.Errorf("heapBits incorrect for %v\nhave %v\nwant %v", typ, heapBits, bits)
+ _, _, line, _ := runtime.Caller(1)
+ t.Errorf("line %d: heapBits incorrect for %v\nhave %v\nwant %v", line, typ, heapBits, bits)
}
}
diff --git a/src/reflect/asm_386.s b/src/reflect/asm_386.s
index d827360006..e79beb6dc9 100644
--- a/src/reflect/asm_386.s
+++ b/src/reflect/asm_386.s
@@ -9,11 +9,14 @@
// See the comment on the declaration of makeFuncStub in makefunc.go
// for more details.
// No argsize here, gc generates argsize info at call site.
-TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$8
+TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
NO_LOCAL_POINTERS
MOVL DX, 0(SP)
LEAL argframe+0(FP), CX
MOVL CX, 4(SP)
+ MOVB $0, 12(SP)
+ LEAL 12(SP), AX
+ MOVL AX, 8(SP)
CALL ·callReflect(SB)
RET
@@ -21,10 +24,13 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$8
// See the comment on the declaration of methodValueCall in makefunc.go
// for more details.
// No argsize here, gc generates argsize info at call site.
-TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$8
+TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$16
NO_LOCAL_POINTERS
MOVL DX, 0(SP)
LEAL argframe+0(FP), CX
MOVL CX, 4(SP)
+ MOVB $0, 12(SP)
+ LEAL 12(SP), AX
+ MOVL AX, 8(SP)
CALL ·callMethod(SB)
RET
diff --git a/src/reflect/asm_amd64.s b/src/reflect/asm_amd64.s
index 1272c489de..fb28ab87f1 100644
--- a/src/reflect/asm_amd64.s
+++ b/src/reflect/asm_amd64.s
@@ -9,11 +9,14 @@
// See the comment on the declaration of makeFuncStub in makefunc.go
// for more details.
// No arg size here; runtime pulls arg map out of the func value.
-TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
+TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$32
NO_LOCAL_POINTERS
MOVQ DX, 0(SP)
LEAQ argframe+0(FP), CX
MOVQ CX, 8(SP)
+ MOVB $0, 24(SP)
+ LEAQ 24(SP), AX
+ MOVQ AX, 16(SP)
CALL ·callReflect(SB)
RET
@@ -21,10 +24,13 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
// See the comment on the declaration of methodValueCall in makefunc.go
// for more details.
// No arg size here; runtime pulls arg map out of the func value.
-TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$16
+TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$32
NO_LOCAL_POINTERS
MOVQ DX, 0(SP)
LEAQ argframe+0(FP), CX
MOVQ CX, 8(SP)
+ MOVB $0, 24(SP)
+ LEAQ 24(SP), AX
+ MOVQ AX, 16(SP)
CALL ·callMethod(SB)
RET
diff --git a/src/reflect/asm_amd64p32.s b/src/reflect/asm_amd64p32.s
index d827360006..e79beb6dc9 100644
--- a/src/reflect/asm_amd64p32.s
+++ b/src/reflect/asm_amd64p32.s
@@ -9,11 +9,14 @@
// See the comment on the declaration of makeFuncStub in makefunc.go
// for more details.
// No argsize here, gc generates argsize info at call site.
-TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$8
+TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
NO_LOCAL_POINTERS
MOVL DX, 0(SP)
LEAL argframe+0(FP), CX
MOVL CX, 4(SP)
+ MOVB $0, 12(SP)
+ LEAL 12(SP), AX
+ MOVL AX, 8(SP)
CALL ·callReflect(SB)
RET
@@ -21,10 +24,13 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$8
// See the comment on the declaration of methodValueCall in makefunc.go
// for more details.
// No argsize here, gc generates argsize info at call site.
-TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$8
+TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$16
NO_LOCAL_POINTERS
MOVL DX, 0(SP)
LEAL argframe+0(FP), CX
MOVL CX, 4(SP)
+ MOVB $0, 12(SP)
+ LEAL 12(SP), AX
+ MOVL AX, 8(SP)
CALL ·callMethod(SB)
RET
diff --git a/src/reflect/asm_arm.s b/src/reflect/asm_arm.s
index b721ed28c6..cd50d33918 100644
--- a/src/reflect/asm_arm.s
+++ b/src/reflect/asm_arm.s
@@ -9,11 +9,15 @@
// See the comment on the declaration of makeFuncStub in makefunc.go
// for more details.
// No argsize here, gc generates argsize info at call site.
-TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$8
+TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
NO_LOCAL_POINTERS
MOVW R7, 4(R13)
MOVW $argframe+0(FP), R1
MOVW R1, 8(R13)
+ MOVW $0, R1
+ MOVB R1, 16(R13)
+ ADD $16, R13, R1
+ MOVW R1, 12(R13)
BL ·callReflect(SB)
RET
@@ -21,10 +25,14 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$8
// See the comment on the declaration of methodValueCall in makefunc.go
// for more details.
// No argsize here, gc generates argsize info at call site.
-TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$8
+TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$16
NO_LOCAL_POINTERS
MOVW R7, 4(R13)
MOVW $argframe+0(FP), R1
MOVW R1, 8(R13)
+ MOVW $0, R1
+ MOVB R1, 16(R13)
+ ADD $16, R13, R1
+ MOVW R1, 12(R13)
BL ·callMethod(SB)
RET
diff --git a/src/reflect/asm_arm64.s b/src/reflect/asm_arm64.s
index d1563709f2..28bb86c2a4 100644
--- a/src/reflect/asm_arm64.s
+++ b/src/reflect/asm_arm64.s
@@ -9,11 +9,14 @@
// See the comment on the declaration of makeFuncStub in makefunc.go
// for more details.
// No arg size here, runtime pulls arg map out of the func value.
-TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$24
+TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$40
NO_LOCAL_POINTERS
MOVD R26, 8(RSP)
MOVD $argframe+0(FP), R3
MOVD R3, 16(RSP)
+ MOVB $0, 32(RSP)
+ ADD $32, RSP, R3
+ MOVD R3, 24(RSP)
BL ·callReflect(SB)
RET
@@ -21,10 +24,13 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$24
// See the comment on the declaration of methodValueCall in makefunc.go
// for more details.
// No arg size here; runtime pulls arg map out of the func value.
-TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$24
+TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$40
NO_LOCAL_POINTERS
MOVD R26, 8(RSP)
MOVD $argframe+0(FP), R3
MOVD R3, 16(RSP)
+ MOVB $0, 32(RSP)
+ ADD $32, RSP, R3
+ MOVD R3, 24(RSP)
BL ·callMethod(SB)
RET
diff --git a/src/reflect/asm_mips64x.s b/src/reflect/asm_mips64x.s
index 98afb52f6a..6f76685567 100644
--- a/src/reflect/asm_mips64x.s
+++ b/src/reflect/asm_mips64x.s
@@ -13,11 +13,14 @@
// See the comment on the declaration of makeFuncStub in makefunc.go
// for more details.
// No arg size here, runtime pulls arg map out of the func value.
-TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
+TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$32
NO_LOCAL_POINTERS
MOVV REGCTXT, 8(R29)
MOVV $argframe+0(FP), R1
MOVV R1, 16(R29)
+ MOVB R0, 32(R29)
+ ADDV $32, R29, R1
+ MOVV R1, 24(R29)
JAL ·callReflect(SB)
RET
@@ -25,10 +28,13 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
// See the comment on the declaration of methodValueCall in makefunc.go
// for more details.
// No arg size here; runtime pulls arg map out of the func value.
-TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$16
+TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$32
NO_LOCAL_POINTERS
MOVV REGCTXT, 8(R29)
MOVV $argframe+0(FP), R1
MOVV R1, 16(R29)
+ MOVB R0, 32(R29)
+ ADDV $32, R29, R1
+ MOVV R1, 24(R29)
JAL ·callMethod(SB)
RET
diff --git a/src/reflect/asm_mipsx.s b/src/reflect/asm_mipsx.s
index b6df4e636e..5a5c53ef9f 100644
--- a/src/reflect/asm_mipsx.s
+++ b/src/reflect/asm_mipsx.s
@@ -13,11 +13,14 @@
// See the comment on the declaration of makeFuncStub in makefunc.go
// for more details.
// No arg size here, runtime pulls arg map out of the func value.
-TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$8
+TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
NO_LOCAL_POINTERS
MOVW REGCTXT, 4(R29)
MOVW $argframe+0(FP), R1
MOVW R1, 8(R29)
+ MOVB R0, 16(R29)
+ ADD $16, R29, R1
+ MOVW R1, 12(R29)
JAL ·callReflect(SB)
RET
@@ -25,10 +28,13 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$8
// See the comment on the declaration of methodValueCall in makefunc.go
// for more details.
// No arg size here; runtime pulls arg map out of the func value.
-TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$8
+TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$16
NO_LOCAL_POINTERS
MOVW REGCTXT, 4(R29)
MOVW $argframe+0(FP), R1
MOVW R1, 8(R29)
+ MOVB R0, 16(R29)
+ ADD $16, R29, R1
+ MOVW R1, 12(R29)
JAL ·callMethod(SB)
RET
diff --git a/src/reflect/asm_ppc64x.s b/src/reflect/asm_ppc64x.s
index 42f57743e6..4609f6bb75 100644
--- a/src/reflect/asm_ppc64x.s
+++ b/src/reflect/asm_ppc64x.s
@@ -12,11 +12,14 @@
// See the comment on the declaration of makeFuncStub in makefunc.go
// for more details.
// No arg size here, runtime pulls arg map out of the func value.
-TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
+TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$32
NO_LOCAL_POINTERS
MOVD R11, FIXED_FRAME+0(R1)
MOVD $argframe+0(FP), R3
MOVD R3, FIXED_FRAME+8(R1)
+ MOVB R0, FIXED_FRAME+24(R1)
+ ADD $FIXED_FRAME+24, R1, R3
+ MOVD R3, FIXED_FRAME+16(R1)
BL ·callReflect(SB)
RET
@@ -24,10 +27,13 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
// See the comment on the declaration of methodValueCall in makefunc.go
// for more details.
// No arg size here; runtime pulls arg map out of the func value.
-TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$16
+TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$32
NO_LOCAL_POINTERS
MOVD R11, FIXED_FRAME+0(R1)
MOVD $argframe+0(FP), R3
MOVD R3, FIXED_FRAME+8(R1)
+ MOVB R0, FIXED_FRAME+24(R1)
+ ADD $FIXED_FRAME+24, R1, R3
+ MOVD R3, FIXED_FRAME+16(R1)
BL ·callMethod(SB)
RET
diff --git a/src/reflect/asm_s390x.s b/src/reflect/asm_s390x.s
index e6b86cfaa9..cb7954c900 100644
--- a/src/reflect/asm_s390x.s
+++ b/src/reflect/asm_s390x.s
@@ -9,11 +9,14 @@
// See the comment on the declaration of makeFuncStub in makefunc.go
// for more details.
// No arg size here, runtime pulls arg map out of the func value.
-TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
+TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$32
NO_LOCAL_POINTERS
MOVD R12, 8(R15)
MOVD $argframe+0(FP), R3
MOVD R3, 16(R15)
+ MOVB $0, 32(R15)
+ ADD $32, R15, R3
+ MOVD R3, 24(R15)
BL ·callReflect(SB)
RET
@@ -21,10 +24,13 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
// See the comment on the declaration of methodValueCall in makefunc.go
// for more details.
// No arg size here; runtime pulls arg map out of the func value.
-TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$16
+TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$32
NO_LOCAL_POINTERS
MOVD R12, 8(R15)
MOVD $argframe+0(FP), R3
MOVD R3, 16(R15)
+ MOVB $0, 32(R15)
+ ADD $32, R15, R3
+ MOVD R3, 24(R15)
BL ·callMethod(SB)
RET
diff --git a/src/reflect/asm_wasm.s b/src/reflect/asm_wasm.s
index 0f9b5aa130..627e295769 100644
--- a/src/reflect/asm_wasm.s
+++ b/src/reflect/asm_wasm.s
@@ -9,7 +9,7 @@
// See the comment on the declaration of makeFuncStub in makefunc.go
// for more details.
// No arg size here; runtime pulls arg map out of the func value.
-TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
+TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$32
NO_LOCAL_POINTERS
MOVD CTXT, 0(SP)
@@ -21,6 +21,9 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
I64Add
I64Store $8
+ MOVB $0, 24(SP)
+ MOVD $24(SP), 16(SP)
+
CALL ·callReflect(SB)
RET
@@ -28,7 +31,7 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
// See the comment on the declaration of methodValueCall in makefunc.go
// for more details.
// No arg size here; runtime pulls arg map out of the func value.
-TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$16
+TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$32
NO_LOCAL_POINTERS
MOVD CTXT, 0(SP)
@@ -40,5 +43,8 @@ TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$16
I64Add
I64Store $8
+ MOVB $0, 24(SP)
+ MOVD $24(SP), 16(SP)
+
CALL ·callMethod(SB)
RET
diff --git a/src/reflect/example_test.go b/src/reflect/example_test.go
index f959b95846..23c08e4950 100644
--- a/src/reflect/example_test.go
+++ b/src/reflect/example_test.go
@@ -13,6 +13,24 @@ import (
"reflect"
)
+func ExampleKind() {
+ for _, v := range []interface{}{"hi", 42, func() {}} {
+ switch v := reflect.ValueOf(v); v.Kind() {
+ case reflect.String:
+ fmt.Println(v.String())
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ fmt.Println(v.Int())
+ default:
+ fmt.Printf("unhandled kind %s", v.Kind())
+ }
+ }
+
+ // Output:
+ // hi
+ // 42
+ // unhandled kind func
+}
+
func ExampleMakeFunc() {
// swap is the implementation passed to MakeFunc.
// It must work in terms of reflect.Values so that it is possible
diff --git a/src/reflect/export_test.go b/src/reflect/export_test.go
index 14a6981fde..3c47d6712f 100644
--- a/src/reflect/export_test.go
+++ b/src/reflect/export_test.go
@@ -25,9 +25,9 @@ func FuncLayout(t Type, rcvr Type) (frametype Type, argSize, retOffset uintptr,
var ft *rtype
var s *bitVector
if rcvr != nil {
- ft, argSize, retOffset, s, _ = funcLayout(t.(*rtype), rcvr.(*rtype))
+ ft, argSize, retOffset, s, _ = funcLayout((*funcType)(unsafe.Pointer(t.(*rtype))), rcvr.(*rtype))
} else {
- ft, argSize, retOffset, s, _ = funcLayout(t.(*rtype), nil)
+ ft, argSize, retOffset, s, _ = funcLayout((*funcType)(unsafe.Pointer(t.(*rtype))), nil)
}
frametype = ft
for i := uint32(0); i < s.n; i++ {
diff --git a/src/reflect/makefunc.go b/src/reflect/makefunc.go
index 885966db6f..67dc4859b9 100644
--- a/src/reflect/makefunc.go
+++ b/src/reflect/makefunc.go
@@ -12,14 +12,15 @@ import (
// makeFuncImpl is the closure value implementing the function
// returned by MakeFunc.
-// The first two words of this type must be kept in sync with
+// The first three words of this type must be kept in sync with
// methodValue and runtime.reflectMethodValue.
// Any changes should be reflected in all three.
type makeFuncImpl struct {
- code uintptr
- stack *bitVector
- typ *funcType
- fn func([]Value) []Value
+ code uintptr
+ stack *bitVector // ptrmap for both args and results
+ argLen uintptr // just args
+ ftyp *funcType
+ fn func([]Value) []Value
}
// MakeFunc returns a new function of the given Type
@@ -59,9 +60,9 @@ func MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value {
code := **(**uintptr)(unsafe.Pointer(&dummy))
// makeFuncImpl contains a stack map for use by the runtime
- _, _, _, stack, _ := funcLayout(t, nil)
+ _, argLen, _, stack, _ := funcLayout(ftyp, nil)
- impl := &makeFuncImpl{code: code, stack: stack, typ: ftyp, fn: fn}
+ impl := &makeFuncImpl{code: code, stack: stack, argLen: argLen, ftyp: ftyp, fn: fn}
return Value{t, unsafe.Pointer(impl), flag(Func)}
}
@@ -73,12 +74,13 @@ func MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value {
// word in the passed-in argument frame.
func makeFuncStub()
-// The first two words of this type must be kept in sync with
+// The first 3 words of this type must be kept in sync with
// makeFuncImpl and runtime.reflectMethodValue.
// Any changes should be reflected in all three.
type methodValue struct {
fn uintptr
- stack *bitVector
+ stack *bitVector // ptrmap for both args and results
+ argLen uintptr // just args
method int
rcvr Value
}
@@ -101,7 +103,7 @@ func makeMethodValue(op string, v Value) Value {
rcvr := Value{v.typ, v.ptr, fl}
// v.Type returns the actual type of the method value.
- funcType := v.Type().(*rtype)
+ ftyp := (*funcType)(unsafe.Pointer(v.Type().(*rtype)))
// Indirect Go func value (dummy) to obtain
// actual code address. (A Go func value is a pointer
@@ -110,11 +112,12 @@ func makeMethodValue(op string, v Value) Value {
code := **(**uintptr)(unsafe.Pointer(&dummy))
// methodValue contains a stack map for use by the runtime
- _, _, _, stack, _ := funcLayout(funcType, nil)
+ _, argLen, _, stack, _ := funcLayout(ftyp, nil)
fv := &methodValue{
fn: code,
stack: stack,
+ argLen: argLen,
method: int(v.flag) >> flagMethodShift,
rcvr: rcvr,
}
@@ -124,7 +127,7 @@ func makeMethodValue(op string, v Value) Value {
// but we want Interface() and other operations to fail early.
methodReceiver(op, fv.rcvr, fv.method)
- return Value{funcType, unsafe.Pointer(fv), v.flag&flagRO | flag(Func)}
+ return Value{&ftyp.rtype, unsafe.Pointer(fv), v.flag&flagRO | flag(Func)}
}
// methodValueCall is an assembly function that is the code half of
diff --git a/src/reflect/type.go b/src/reflect/type.go
index 58cfc0e884..d8971d620e 100644
--- a/src/reflect/type.go
+++ b/src/reflect/type.go
@@ -3022,8 +3022,8 @@ func toType(t *rtype) Type {
}
type layoutKey struct {
- t *rtype // function signature
- rcvr *rtype // receiver type, or nil if none
+ ftyp *funcType // function signature
+ rcvr *rtype // receiver type, or nil if none
}
type layoutType struct {
@@ -3042,7 +3042,7 @@ var layoutCache sync.Map // map[layoutKey]layoutType
// The returned type exists only for GC, so we only fill out GC relevant info.
// Currently, that's just size and the GC program. We also fill in
// the name for possible debugging use.
-func funcLayout(t *rtype, rcvr *rtype) (frametype *rtype, argSize, retOffset uintptr, stk *bitVector, framePool *sync.Pool) {
+func funcLayout(t *funcType, rcvr *rtype) (frametype *rtype, argSize, retOffset uintptr, stk *bitVector, framePool *sync.Pool) {
if t.Kind() != Func {
panic("reflect: funcLayout of non-func type")
}
@@ -3055,8 +3055,6 @@ func funcLayout(t *rtype, rcvr *rtype) (frametype *rtype, argSize, retOffset uin
return lt.t, lt.argSize, lt.retOffset, lt.stack, lt.framePool
}
- tt := (*funcType)(unsafe.Pointer(t))
-
// compute gc program & stack bitmap for arguments
ptrmap := new(bitVector)
var offset uintptr
@@ -3066,22 +3064,23 @@ func funcLayout(t *rtype, rcvr *rtype) (frametype *rtype, argSize, retOffset uin
// space no matter how big they actually are.
if ifaceIndir(rcvr) || rcvr.pointers() {
ptrmap.append(1)
+ } else {
+ ptrmap.append(0)
}
offset += ptrSize
}
- for _, arg := range tt.in() {
+ for _, arg := range t.in() {
offset += -offset & uintptr(arg.align-1)
addTypeBits(ptrmap, offset, arg)
offset += arg.size
}
- argN := ptrmap.n
argSize = offset
if runtime.GOARCH == "amd64p32" {
offset += -offset & (8 - 1)
}
offset += -offset & (ptrSize - 1)
retOffset = offset
- for _, res := range tt.out() {
+ for _, res := range t.out() {
offset += -offset & uintptr(res.align-1)
addTypeBits(ptrmap, offset, res)
offset += res.size
@@ -3102,7 +3101,6 @@ func funcLayout(t *rtype, rcvr *rtype) (frametype *rtype, argSize, retOffset uin
} else {
x.kind |= kindNoPointers
}
- ptrmap.n = argN
var s string
if rcvr != nil {
diff --git a/src/reflect/value.go b/src/reflect/value.go
index 1c3e590377..6d2862dbab 100644
--- a/src/reflect/value.go
+++ b/src/reflect/value.go
@@ -325,7 +325,7 @@ var callGC bool // for testing; see TestCallMethodJump
func (v Value) call(op string, in []Value) []Value {
// Get function pointer, type.
- t := v.typ
+ t := (*funcType)(unsafe.Pointer(v.typ))
var (
fn unsafe.Pointer
rcvr Value
@@ -453,15 +453,14 @@ func (v Value) call(op string, in []Value) []Value {
var ret []Value
if nout == 0 {
- // This is untyped because the frame is really a
- // stack, even though it's a heap object.
- memclrNoHeapPointers(args, frametype.size)
+ typedmemclr(frametype, args)
framePool.Put(args)
} else {
// Zero the now unused input area of args,
// because the Values returned by this function contain pointers to the args object,
// and will thus keep the args object alive indefinitely.
- memclrNoHeapPointers(args, retOffset)
+ typedmemclrpartial(frametype, args, 0, retOffset)
+
// Wrap Values around return values in args.
ret = make([]Value, nout)
off = retOffset
@@ -472,6 +471,10 @@ func (v Value) call(op string, in []Value) []Value {
if tv.Size() != 0 {
fl := flagIndir | flag(tv.Kind())
ret[i] = Value{tv.common(), add(args, off, "tv.Size() != 0"), fl}
+ // Note: this does introduce false sharing between results -
+ // if any result is live, they are all live.
+ // (And the space for the args is live as well, but as we've
+ // cleared that space it isn't as big a deal.)
} else {
// For zero-sized return value, args+off may point to the next object.
// In this case, return the zero value instead.
@@ -496,8 +499,13 @@ func (v Value) call(op string, in []Value) []Value {
// NOTE: This function must be marked as a "wrapper" in the generated code,
// so that the linker can make it work correctly for panic and recover.
// The gc compilers know to do that for the name "reflect.callReflect".
-func callReflect(ctxt *makeFuncImpl, frame unsafe.Pointer) {
- ftyp := ctxt.typ
+//
+// ctxt is the "closure" generated by MakeFunc.
+// frame is a pointer to the arguments to that closure on the stack.
+// retValid points to a boolean which should be set when the results
+// section of frame is set.
+func callReflect(ctxt *makeFuncImpl, frame unsafe.Pointer, retValid *bool) {
+ ftyp := ctxt.ftyp
f := ctxt.fn
// Copy argument frame into Values.
@@ -562,6 +570,16 @@ func callReflect(ctxt *makeFuncImpl, frame unsafe.Pointer) {
}
}
+ // Announce that the return values are valid.
+ // After this point the runtime can depend on the return values being valid.
+ *retValid = true
+
+ // We have to make sure that the out slice lives at least until
+ // the runtime knows the return values are valid. Otherwise, the
+ // return values might not be scanned by anyone during a GC.
+ // (out would be dead, and the return slots not yet alive.)
+ runtime.KeepAlive(out)
+
// runtime.getArgInfo expects to be able to find ctxt on the
// stack when it finds our caller, makeFuncStub. Make sure it
// doesn't get garbage collected.
@@ -575,7 +593,7 @@ func callReflect(ctxt *makeFuncImpl, frame unsafe.Pointer) {
// The return value rcvrtype gives the method's actual receiver type.
// The return value t gives the method type signature (without the receiver).
// The return value fn is a pointer to the method code.
-func methodReceiver(op string, v Value, methodIndex int) (rcvrtype, t *rtype, fn unsafe.Pointer) {
+func methodReceiver(op string, v Value, methodIndex int) (rcvrtype *rtype, t *funcType, fn unsafe.Pointer) {
i := methodIndex
if v.typ.Kind() == Interface {
tt := (*interfaceType)(unsafe.Pointer(v.typ))
@@ -592,7 +610,7 @@ func methodReceiver(op string, v Value, methodIndex int) (rcvrtype, t *rtype, fn
}
rcvrtype = iface.itab.typ
fn = unsafe.Pointer(&iface.itab.fun[i])
- t = tt.typeOff(m.typ)
+ t = (*funcType)(unsafe.Pointer(tt.typeOff(m.typ)))
} else {
rcvrtype = v.typ
ms := v.typ.exportedMethods()
@@ -605,7 +623,7 @@ func methodReceiver(op string, v Value, methodIndex int) (rcvrtype, t *rtype, fn
}
ifn := v.typ.textOff(m.ifn)
fn = unsafe.Pointer(&ifn)
- t = v.typ.typeOff(m.mtyp)
+ t = (*funcType)(unsafe.Pointer(v.typ.typeOff(m.mtyp)))
}
return
}
@@ -644,23 +662,31 @@ func align(x, n uintptr) uintptr {
// NOTE: This function must be marked as a "wrapper" in the generated code,
// so that the linker can make it work correctly for panic and recover.
// The gc compilers know to do that for the name "reflect.callMethod".
-func callMethod(ctxt *methodValue, frame unsafe.Pointer) {
+//
+// ctxt is the "closure" generated by makeVethodValue.
+// frame is a pointer to the arguments to that closure on the stack.
+// retValid points to a boolean which should be set when the results
+// section of frame is set.
+func callMethod(ctxt *methodValue, frame unsafe.Pointer, retValid *bool) {
rcvr := ctxt.rcvr
rcvrtype, t, fn := methodReceiver("call", rcvr, ctxt.method)
frametype, argSize, retOffset, _, framePool := funcLayout(t, rcvrtype)
// Make a new frame that is one word bigger so we can store the receiver.
- args := framePool.Get().(unsafe.Pointer)
+ // This space is used for both arguments and return values.
+ scratch := framePool.Get().(unsafe.Pointer)
// Copy in receiver and rest of args.
// Avoid constructing out-of-bounds pointers if there are no args.
- storeRcvr(rcvr, args)
+ storeRcvr(rcvr, scratch)
if argSize-ptrSize > 0 {
- typedmemmovepartial(frametype, add(args, ptrSize, "argSize > ptrSize"), frame, ptrSize, argSize-ptrSize)
+ typedmemmovepartial(frametype, add(scratch, ptrSize, "argSize > ptrSize"), frame, ptrSize, argSize-ptrSize)
}
// Call.
- call(frametype, fn, args, uint32(frametype.size), uint32(retOffset))
+ // Call copies the arguments from scratch to the stack, calls fn,
+ // and then copies the results back into scratch.
+ call(frametype, fn, scratch, uint32(frametype.size), uint32(retOffset))
// Copy return values. On amd64p32, the beginning of return values
// is 64-bit aligned, so the caller's frame layout (which doesn't have
@@ -673,17 +699,21 @@ func callMethod(ctxt *methodValue, frame unsafe.Pointer) {
if runtime.GOARCH == "amd64p32" {
callerRetOffset = align(argSize-ptrSize, 8)
}
- typedmemmovepartial(frametype,
- add(frame, callerRetOffset, "frametype.size > retOffset"),
- add(args, retOffset, "frametype.size > retOffset"),
- retOffset,
+ // This copies to the stack. Write barriers are not needed.
+ memmove(add(frame, callerRetOffset, "frametype.size > retOffset"),
+ add(scratch, retOffset, "frametype.size > retOffset"),
frametype.size-retOffset)
}
- // This is untyped because the frame is really a stack, even
- // though it's a heap object.
- memclrNoHeapPointers(args, frametype.size)
- framePool.Put(args)
+ // Tell the runtime it can now depend on the return values
+ // being properly initialized.
+ *retValid = true
+
+ // Clear the scratch space and put it back in the pool.
+ // This must happen after the statement above, so that the return
+ // values will always be scanned by someone.
+ typedmemclr(frametype, scratch)
+ framePool.Put(scratch)
// See the comment in callReflect.
runtime.KeepAlive(ctxt)
@@ -2641,6 +2671,10 @@ func call(argtype *rtype, fn, arg unsafe.Pointer, n uint32, retoffset uint32)
func ifaceE2I(t *rtype, src interface{}, dst unsafe.Pointer)
+// memmove copies size bytes to dst from src. No write barriers are used.
+//go:noescape
+func memmove(dst, src unsafe.Pointer, size uintptr)
+
// typedmemmove copies a value of type t to dst from src.
//go:noescape
func typedmemmove(t *rtype, dst, src unsafe.Pointer)
@@ -2650,14 +2684,20 @@ func typedmemmove(t *rtype, dst, src unsafe.Pointer)
//go:noescape
func typedmemmovepartial(t *rtype, dst, src unsafe.Pointer, off, size uintptr)
+// typedmemclr zeros the value at ptr of type t.
+//go:noescape
+func typedmemclr(t *rtype, ptr unsafe.Pointer)
+
+// typedmemclrpartial is like typedmemclr but assumes that
+// dst points off bytes into the value and only clears size bytes.
+//go:noescape
+func typedmemclrpartial(t *rtype, ptr unsafe.Pointer, off, size uintptr)
+
// typedslicecopy copies a slice of elemType values from src to dst,
// returning the number of elements copied.
//go:noescape
func typedslicecopy(elemType *rtype, dst, src sliceHeader) int
-//go:noescape
-func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
-
// Dummy annotation marking that the value x escapes,
// for use in cases where the reflect code is so clever that
// the compiler cannot follow.
diff --git a/src/regexp/regexp.go b/src/regexp/regexp.go
index 61ed9c5059..89bb975ac1 100644
--- a/src/regexp/regexp.go
+++ b/src/regexp/regexp.go
@@ -469,7 +469,7 @@ func MatchString(pattern string, s string) (matched bool, err error) {
return re.MatchString(s), nil
}
-// MatchString reports whether the byte slice b
+// Match reports whether the byte slice b
// contains any match of the regular expression pattern.
// More complicated queries need to use Compile and the full Regexp interface.
func Match(pattern string, b []byte) (matched bool, err error) {
diff --git a/src/runtime/asm_386.s b/src/runtime/asm_386.s
index 7761415ecd..5bc2063bed 100644
--- a/src/runtime/asm_386.s
+++ b/src/runtime/asm_386.s
@@ -107,7 +107,7 @@ TEXT runtime·rt0_go(SB),NOSPLIT,$0
MOVL BX, g_stackguard1(BP)
MOVL BX, (g_stack+stack_lo)(BP)
MOVL SP, (g_stack+stack_hi)(BP)
-
+
// find out information about the processor we're on
#ifdef GOOS_nacl // NaCl doesn't like PUSHFL/POPFL
JMP has_cpuid
@@ -827,7 +827,7 @@ havem:
MOVL (g_sched+gobuf_sp)(SI), SP
MOVL 0(SP), AX
MOVL AX, (g_sched+gobuf_sp)(SI)
-
+
// If the m on entry was nil, we called needm above to borrow an m
// for the duration of the call. Since the call is over, return it with dropm.
CMPL DX, $0
@@ -942,7 +942,7 @@ TEXT runtime·aeshashbody(SB),NOSPLIT,$0-0
CMPL BX, $64
JBE aes33to64
JMP aes65plus
-
+
aes0to15:
TESTL BX, BX
JE aes0
@@ -957,7 +957,7 @@ aes0to15:
ADDL BX, BX
PAND masks<>(SB)(BX*8), X1
-final1:
+final1:
AESENC X0, X1 // scramble input, xor in seed
AESENC X1, X1 // scramble combo 2 times
AESENC X1, X1
@@ -987,7 +987,7 @@ aes17to32:
// make second starting seed
PXOR runtime·aeskeysched+16(SB), X1
AESENC X1, X1
-
+
// load data to be hashed
MOVOU (AX), X2
MOVOU -16(AX)(BX*1), X3
@@ -1015,22 +1015,22 @@ aes33to64:
AESENC X1, X1
AESENC X2, X2
AESENC X3, X3
-
+
MOVOU (AX), X4
MOVOU 16(AX), X5
MOVOU -32(AX)(BX*1), X6
MOVOU -16(AX)(BX*1), X7
-
+
AESENC X0, X4
AESENC X1, X5
AESENC X2, X6
AESENC X3, X7
-
+
AESENC X4, X4
AESENC X5, X5
AESENC X6, X6
AESENC X7, X7
-
+
AESENC X4, X4
AESENC X5, X5
AESENC X6, X6
@@ -1052,7 +1052,7 @@ aes65plus:
AESENC X1, X1
AESENC X2, X2
AESENC X3, X3
-
+
// start with last (possibly overlapping) block
MOVOU -64(AX)(BX*1), X4
MOVOU -48(AX)(BX*1), X5
@@ -1068,7 +1068,7 @@ aes65plus:
// compute number of remaining 64-byte blocks
DECL BX
SHRL $6, BX
-
+
aesloop:
// scramble state, xor in a block
MOVOU (AX), X0
@@ -1095,7 +1095,7 @@ aesloop:
AESENC X5, X5
AESENC X6, X6
AESENC X7, X7
-
+
AESENC X4, X4
AESENC X5, X5
AESENC X6, X6
@@ -1132,77 +1132,77 @@ DATA masks<>+0x00(SB)/4, $0x00000000
DATA masks<>+0x04(SB)/4, $0x00000000
DATA masks<>+0x08(SB)/4, $0x00000000
DATA masks<>+0x0c(SB)/4, $0x00000000
-
+
DATA masks<>+0x10(SB)/4, $0x000000ff
DATA masks<>+0x14(SB)/4, $0x00000000
DATA masks<>+0x18(SB)/4, $0x00000000
DATA masks<>+0x1c(SB)/4, $0x00000000
-
+
DATA masks<>+0x20(SB)/4, $0x0000ffff
DATA masks<>+0x24(SB)/4, $0x00000000
DATA masks<>+0x28(SB)/4, $0x00000000
DATA masks<>+0x2c(SB)/4, $0x00000000
-
+
DATA masks<>+0x30(SB)/4, $0x00ffffff
DATA masks<>+0x34(SB)/4, $0x00000000
DATA masks<>+0x38(SB)/4, $0x00000000
DATA masks<>+0x3c(SB)/4, $0x00000000
-
+
DATA masks<>+0x40(SB)/4, $0xffffffff
DATA masks<>+0x44(SB)/4, $0x00000000
DATA masks<>+0x48(SB)/4, $0x00000000
DATA masks<>+0x4c(SB)/4, $0x00000000
-
+
DATA masks<>+0x50(SB)/4, $0xffffffff
DATA masks<>+0x54(SB)/4, $0x000000ff
DATA masks<>+0x58(SB)/4, $0x00000000
DATA masks<>+0x5c(SB)/4, $0x00000000
-
+
DATA masks<>+0x60(SB)/4, $0xffffffff
DATA masks<>+0x64(SB)/4, $0x0000ffff
DATA masks<>+0x68(SB)/4, $0x00000000
DATA masks<>+0x6c(SB)/4, $0x00000000
-
+
DATA masks<>+0x70(SB)/4, $0xffffffff
DATA masks<>+0x74(SB)/4, $0x00ffffff
DATA masks<>+0x78(SB)/4, $0x00000000
DATA masks<>+0x7c(SB)/4, $0x00000000
-
+
DATA masks<>+0x80(SB)/4, $0xffffffff
DATA masks<>+0x84(SB)/4, $0xffffffff
DATA masks<>+0x88(SB)/4, $0x00000000
DATA masks<>+0x8c(SB)/4, $0x00000000
-
+
DATA masks<>+0x90(SB)/4, $0xffffffff
DATA masks<>+0x94(SB)/4, $0xffffffff
DATA masks<>+0x98(SB)/4, $0x000000ff
DATA masks<>+0x9c(SB)/4, $0x00000000
-
+
DATA masks<>+0xa0(SB)/4, $0xffffffff
DATA masks<>+0xa4(SB)/4, $0xffffffff
DATA masks<>+0xa8(SB)/4, $0x0000ffff
DATA masks<>+0xac(SB)/4, $0x00000000
-
+
DATA masks<>+0xb0(SB)/4, $0xffffffff
DATA masks<>+0xb4(SB)/4, $0xffffffff
DATA masks<>+0xb8(SB)/4, $0x00ffffff
DATA masks<>+0xbc(SB)/4, $0x00000000
-
+
DATA masks<>+0xc0(SB)/4, $0xffffffff
DATA masks<>+0xc4(SB)/4, $0xffffffff
DATA masks<>+0xc8(SB)/4, $0xffffffff
DATA masks<>+0xcc(SB)/4, $0x00000000
-
+
DATA masks<>+0xd0(SB)/4, $0xffffffff
DATA masks<>+0xd4(SB)/4, $0xffffffff
DATA masks<>+0xd8(SB)/4, $0xffffffff
DATA masks<>+0xdc(SB)/4, $0x000000ff
-
+
DATA masks<>+0xe0(SB)/4, $0xffffffff
DATA masks<>+0xe4(SB)/4, $0xffffffff
DATA masks<>+0xe8(SB)/4, $0xffffffff
DATA masks<>+0xec(SB)/4, $0x0000ffff
-
+
DATA masks<>+0xf0(SB)/4, $0xffffffff
DATA masks<>+0xf4(SB)/4, $0xffffffff
DATA masks<>+0xf8(SB)/4, $0xffffffff
@@ -1217,77 +1217,77 @@ DATA shifts<>+0x00(SB)/4, $0x00000000
DATA shifts<>+0x04(SB)/4, $0x00000000
DATA shifts<>+0x08(SB)/4, $0x00000000
DATA shifts<>+0x0c(SB)/4, $0x00000000
-
+
DATA shifts<>+0x10(SB)/4, $0xffffff0f
DATA shifts<>+0x14(SB)/4, $0xffffffff
DATA shifts<>+0x18(SB)/4, $0xffffffff
DATA shifts<>+0x1c(SB)/4, $0xffffffff
-
+
DATA shifts<>+0x20(SB)/4, $0xffff0f0e
DATA shifts<>+0x24(SB)/4, $0xffffffff
DATA shifts<>+0x28(SB)/4, $0xffffffff
DATA shifts<>+0x2c(SB)/4, $0xffffffff
-
+
DATA shifts<>+0x30(SB)/4, $0xff0f0e0d
DATA shifts<>+0x34(SB)/4, $0xffffffff
DATA shifts<>+0x38(SB)/4, $0xffffffff
DATA shifts<>+0x3c(SB)/4, $0xffffffff
-
+
DATA shifts<>+0x40(SB)/4, $0x0f0e0d0c
DATA shifts<>+0x44(SB)/4, $0xffffffff
DATA shifts<>+0x48(SB)/4, $0xffffffff
DATA shifts<>+0x4c(SB)/4, $0xffffffff
-
+
DATA shifts<>+0x50(SB)/4, $0x0e0d0c0b
DATA shifts<>+0x54(SB)/4, $0xffffff0f
DATA shifts<>+0x58(SB)/4, $0xffffffff
DATA shifts<>+0x5c(SB)/4, $0xffffffff
-
+
DATA shifts<>+0x60(SB)/4, $0x0d0c0b0a
DATA shifts<>+0x64(SB)/4, $0xffff0f0e
DATA shifts<>+0x68(SB)/4, $0xffffffff
DATA shifts<>+0x6c(SB)/4, $0xffffffff
-
+
DATA shifts<>+0x70(SB)/4, $0x0c0b0a09
DATA shifts<>+0x74(SB)/4, $0xff0f0e0d
DATA shifts<>+0x78(SB)/4, $0xffffffff
DATA shifts<>+0x7c(SB)/4, $0xffffffff
-
+
DATA shifts<>+0x80(SB)/4, $0x0b0a0908
DATA shifts<>+0x84(SB)/4, $0x0f0e0d0c
DATA shifts<>+0x88(SB)/4, $0xffffffff
DATA shifts<>+0x8c(SB)/4, $0xffffffff
-
+
DATA shifts<>+0x90(SB)/4, $0x0a090807
DATA shifts<>+0x94(SB)/4, $0x0e0d0c0b
DATA shifts<>+0x98(SB)/4, $0xffffff0f
DATA shifts<>+0x9c(SB)/4, $0xffffffff
-
+
DATA shifts<>+0xa0(SB)/4, $0x09080706
DATA shifts<>+0xa4(SB)/4, $0x0d0c0b0a
DATA shifts<>+0xa8(SB)/4, $0xffff0f0e
DATA shifts<>+0xac(SB)/4, $0xffffffff
-
+
DATA shifts<>+0xb0(SB)/4, $0x08070605
DATA shifts<>+0xb4(SB)/4, $0x0c0b0a09
DATA shifts<>+0xb8(SB)/4, $0xff0f0e0d
DATA shifts<>+0xbc(SB)/4, $0xffffffff
-
+
DATA shifts<>+0xc0(SB)/4, $0x07060504
DATA shifts<>+0xc4(SB)/4, $0x0b0a0908
DATA shifts<>+0xc8(SB)/4, $0x0f0e0d0c
DATA shifts<>+0xcc(SB)/4, $0xffffffff
-
+
DATA shifts<>+0xd0(SB)/4, $0x06050403
DATA shifts<>+0xd4(SB)/4, $0x0a090807
DATA shifts<>+0xd8(SB)/4, $0x0e0d0c0b
DATA shifts<>+0xdc(SB)/4, $0xffffff0f
-
+
DATA shifts<>+0xe0(SB)/4, $0x05040302
DATA shifts<>+0xe4(SB)/4, $0x09080706
DATA shifts<>+0xe8(SB)/4, $0x0d0c0b0a
DATA shifts<>+0xec(SB)/4, $0xffff0f0e
-
+
DATA shifts<>+0xf0(SB)/4, $0x04030201
DATA shifts<>+0xf4(SB)/4, $0x08070605
DATA shifts<>+0xf8(SB)/4, $0x0c0b0a09
diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s
index 2a15910aea..ab891154c8 100644
--- a/src/runtime/asm_amd64.s
+++ b/src/runtime/asm_amd64.s
@@ -92,7 +92,7 @@ TEXT runtime·rt0_go(SB),NOSPLIT,$0
ANDQ $~15, SP
MOVQ AX, 16(SP)
MOVQ BX, 24(SP)
-
+
// create istack out of the given (operating system) stack.
// _cgo_init may update stackguard.
MOVQ $runtime·g0(SB), DI
@@ -273,7 +273,7 @@ TEXT runtime·gogo(SB), NOSPLIT, $16-8
// to keep running g.
TEXT runtime·mcall(SB), NOSPLIT, $0-8
MOVQ fn+0(FP), DI
-
+
get_tls(CX)
MOVQ g(CX), AX // save state in g->sched
MOVQ 0(SP), BX // caller's PC
@@ -617,7 +617,7 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-20
MOVQ m_gsignal(R8), SI
CMPQ SI, DI
JEQ nosave
-
+
// Switch to system stack.
MOVQ m_g0(R8), SI
CALL gosave<>(SB)
@@ -717,7 +717,7 @@ needm:
get_tls(CX)
MOVQ g(CX), BX
MOVQ g_m(BX), BX
-
+
// Set m->sched.sp = SP, so that if a panic happens
// during the function we are about to execute, it will
// have a valid SP to run on the g0 stack.
@@ -801,7 +801,7 @@ havem:
MOVQ (g_sched+gobuf_sp)(SI), SP
MOVQ 0(SP), AX
MOVQ AX, (g_sched+gobuf_sp)(SI)
-
+
// If the m on entry was nil, we called needm above to borrow an m
// for the duration of the call. Since the call is over, return it with dropm.
CMPQ R8, $0
@@ -953,7 +953,7 @@ aes17to32:
// make second starting seed
PXOR runtime·aeskeysched+16(SB), X1
AESENC X1, X1
-
+
// load data to be hashed
MOVOU (AX), X2
MOVOU -16(AX)(CX*1), X3
@@ -985,7 +985,7 @@ aes33to64:
AESENC X1, X1
AESENC X2, X2
AESENC X3, X3
-
+
MOVOU (AX), X4
MOVOU 16(AX), X5
MOVOU -32(AX)(CX*1), X6
@@ -995,17 +995,17 @@ aes33to64:
PXOR X1, X5
PXOR X2, X6
PXOR X3, X7
-
+
AESENC X4, X4
AESENC X5, X5
AESENC X6, X6
AESENC X7, X7
-
+
AESENC X4, X4
AESENC X5, X5
AESENC X6, X6
AESENC X7, X7
-
+
AESENC X4, X4
AESENC X5, X5
AESENC X6, X6
@@ -1121,7 +1121,7 @@ aes129plus:
AESENC X5, X5
AESENC X6, X6
AESENC X7, X7
-
+
// start with last (possibly overlapping) block
MOVOU -128(AX)(CX*1), X8
MOVOU -112(AX)(CX*1), X9
@@ -1141,11 +1141,11 @@ aes129plus:
PXOR X5, X13
PXOR X6, X14
PXOR X7, X15
-
+
// compute number of remaining 128-byte blocks
DECQ CX
SHRQ $7, CX
-
+
aesloop:
// scramble state
AESENC X8, X8
diff --git a/src/runtime/asm_amd64p32.s b/src/runtime/asm_amd64p32.s
index 49958d0c88..7f194d2403 100644
--- a/src/runtime/asm_amd64p32.s
+++ b/src/runtime/asm_amd64p32.s
@@ -18,7 +18,7 @@ TEXT runtime·rt0_go(SB),NOSPLIT,$0
MOVL AX, 16(SP)
MOVL BX, 24(SP)
-
+
// create istack out of the given (operating system) stack.
MOVL $runtime·g0(SB), DI
LEAL (-64*1024+104)(SP), BX
@@ -150,7 +150,7 @@ TEXT runtime·gogo(SB), NOSPLIT, $8-4
// to keep running g.
TEXT runtime·mcall(SB), NOSPLIT, $0-4
MOVL fn+0(FP), DI
-
+
get_tls(CX)
MOVL g(CX), AX // save state in g->sched
MOVL 0(SP), BX // caller's PC
diff --git a/src/runtime/asm_arm.s b/src/runtime/asm_arm.s
index 6722ba760f..174dc46389 100644
--- a/src/runtime/asm_arm.s
+++ b/src/runtime/asm_arm.s
@@ -514,7 +514,7 @@ TEXT callRet<>(SB), NOSPLIT, $16-0
MOVW R1, 12(R13)
MOVW R2, 16(R13)
BL runtime·reflectcallmove(SB)
- RET
+ RET
CALLFN(·call16, 16)
CALLFN(·call32, 32)
@@ -673,7 +673,7 @@ TEXT runtime·cgocallback(SB),NOSPLIT,$16-16
// See cgocall.go for more details.
TEXT ·cgocallback_gofunc(SB),NOSPLIT,$8-16
NO_LOCAL_POINTERS
-
+
// Load m and g from thread-local storage.
MOVB runtime·iscgo(SB), R0
CMP $0, R0
@@ -784,6 +784,9 @@ TEXT setg<>(SB),NOSPLIT|NOFRAME,$0-0
MOVW R0, g
// Save g to thread-local storage.
+#ifdef GOOS_windows
+ B runtime·save_g(SB)
+#else
MOVB runtime·iscgo(SB), R0
CMP $0, R0
B.EQ 2(PC)
@@ -791,6 +794,7 @@ TEXT setg<>(SB),NOSPLIT|NOFRAME,$0-0
MOVW g, R0
RET
+#endif
TEXT runtime·emptyfunc(SB),0,$0-0
RET
@@ -851,12 +855,12 @@ TEXT _cgo_topofstack(SB),NOSPLIT,$8
// callee-save in the gcc calling convention, so save them here.
MOVW R11, saveR11-4(SP)
MOVW g, saveG-8(SP)
-
+
BL runtime·load_g(SB)
MOVW g_m(g), R0
MOVW m_curg(R0), R0
MOVW (g_stack+stack_hi)(R0), R0
-
+
MOVW saveG-8(SP), g
MOVW saveR11-4(SP), R11
RET
diff --git a/src/runtime/asm_ppc64x.s b/src/runtime/asm_ppc64x.s
index 57877c0194..b180cb06ab 100644
--- a/src/runtime/asm_ppc64x.s
+++ b/src/runtime/asm_ppc64x.s
@@ -390,15 +390,36 @@ TEXT NAME(SB), WRAPPER, $MAXSIZE-24; \
/* copy arguments to stack */ \
MOVD arg+16(FP), R3; \
MOVWZ argsize+24(FP), R4; \
- MOVD R1, R5; \
- ADD $(FIXED_FRAME-1), R5; \
- SUB $1, R3; \
- ADD R5, R4; \
- CMP R5, R4; \
- BEQ 4(PC); \
- MOVBZU 1(R3), R6; \
- MOVBZU R6, 1(R5); \
- BR -4(PC); \
+ MOVD R1, R5; \
+ CMP R4, $8; \
+ BLT tailsetup; \
+ /* copy 8 at a time if possible */ \
+ ADD $(FIXED_FRAME-8), R5; \
+ SUB $8, R3; \
+top: \
+ MOVDU 8(R3), R7; \
+ MOVDU R7, 8(R5); \
+ SUB $8, R4; \
+ CMP R4, $8; \
+ BGE top; \
+ /* handle remaining bytes */ \
+ CMP $0, R4; \
+ BEQ callfn; \
+ ADD $7, R3; \
+ ADD $7, R5; \
+ BR tail; \
+tailsetup: \
+ CMP $0, R4; \
+ BEQ callfn; \
+ ADD $(FIXED_FRAME-1), R5; \
+ SUB $1, R3; \
+tail: \
+ MOVBU 1(R3), R6; \
+ MOVBU R6, 1(R5); \
+ SUB $1, R4; \
+ CMP $0, R4; \
+ BGT tail; \
+callfn: \
/* call function */ \
MOVD f+8(FP), R11; \
MOVD (R11), R12; \
diff --git a/src/runtime/cgo/asm_amd64.s b/src/runtime/cgo/asm_amd64.s
index 0e33fc4796..06c538b9bc 100644
--- a/src/runtime/cgo/asm_amd64.s
+++ b/src/runtime/cgo/asm_amd64.s
@@ -36,9 +36,9 @@ TEXT crosscall2(SB),NOSPLIT,$0x110-0 /* also need to save xmm6 - xmm15 */
MOVQ DX, 0x0(SP) /* arg */
MOVQ R8, 0x8(SP) /* argsize (includes padding) */
MOVQ R9, 0x10(SP) /* ctxt */
-
+
CALL CX /* fn */
-
+
MOVQ 0x48(SP), DI
MOVQ 0x50(SP), SI
MOVUPS 0x60(SP), X6
@@ -64,5 +64,5 @@ TEXT crosscall2(SB),NOSPLIT,$0x110-0 /* also need to save xmm6 - xmm15 */
MOVQ 0x30(SP), R13
MOVQ 0x38(SP), R14
MOVQ 0x40(SP), R15
-
+
RET
diff --git a/src/runtime/cgo/asm_arm.s b/src/runtime/cgo/asm_arm.s
index 36dab286ae..60132c14a8 100644
--- a/src/runtime/cgo/asm_arm.s
+++ b/src/runtime/cgo/asm_arm.s
@@ -8,7 +8,7 @@
// func crosscall2(fn func(a unsafe.Pointer, n int32, ctxt uintptr), a unsafe.Pointer, n int32, ctxt uintptr)
// Saves C callee-saved registers and calls fn with three arguments.
TEXT crosscall2(SB),NOSPLIT|NOFRAME,$0
- /*
+ /*
* We still need to save all callee save register as before, and then
* push 3 args for fn (R1, R2, R3).
* Also note that at procedure entry in gc world, 4(R13) will be the
diff --git a/src/runtime/cgo/signal_darwin_arm64.s b/src/runtime/cgo/signal_darwin_arm64.s
index 60443b64c8..1ae00d13f3 100644
--- a/src/runtime/cgo/signal_darwin_arm64.s
+++ b/src/runtime/cgo/signal_darwin_arm64.s
@@ -37,7 +37,7 @@ ongothread:
// Build a 32-byte stack frame for us for this call.
// Saved LR (none available) is at the bottom,
- // then the PC argument for setsigsegv,
+ // then the PC argument for setsigsegv,
// then a copy of the LR for us to restore.
MOVD.W $0, -32(RSP)
MOVD R1, 8(RSP)
diff --git a/src/runtime/cgocheck.go b/src/runtime/cgocheck.go
index 73cb6ecae2..ac57e0344e 100644
--- a/src/runtime/cgocheck.go
+++ b/src/runtime/cgocheck.go
@@ -126,7 +126,7 @@ func cgoCheckTypedBlock(typ *_type, src unsafe.Pointer, off, size uintptr) {
}
s := spanOfUnchecked(uintptr(src))
- if s.state == _MSpanManual {
+ if s.state == mSpanManual {
// There are no heap bits for value stored on the stack.
// For a channel receive src might be on the stack of some
// other goroutine, so we can't unwind the stack even if
diff --git a/src/runtime/chan.go b/src/runtime/chan.go
index 615643e6a6..5cf0b86f58 100644
--- a/src/runtime/chan.go
+++ b/src/runtime/chan.go
@@ -92,7 +92,7 @@ func makechan(t *chantype, size int) *hchan {
// Queue or element size is zero.
c = (*hchan)(mallocgc(hchanSize, nil, true))
// Race detector uses this location for synchronization.
- c.buf = unsafe.Pointer(c)
+ c.buf = c.raceaddr()
case elem.kind&kindNoPointers != 0:
// Elements do not contain pointers.
// Allocate hchan and buf in one call.
@@ -151,7 +151,7 @@ func chansend(c *hchan, ep unsafe.Pointer, block bool, callerpc uintptr) bool {
}
if raceenabled {
- racereadpc(unsafe.Pointer(c), callerpc, funcPC(chansend))
+ racereadpc(c.raceaddr(), callerpc, funcPC(chansend))
}
// Fast path: check for failed non-blocking operation without acquiring the lock.
@@ -232,6 +232,11 @@ func chansend(c *hchan, ep unsafe.Pointer, block bool, callerpc uintptr) bool {
gp.param = nil
c.sendq.enqueue(mysg)
goparkunlock(&c.lock, waitReasonChanSend, traceEvGoBlockSend, 3)
+ // Ensure the value being sent is kept alive until the
+ // receiver copies it out. The sudog has a pointer to the
+ // stack object, but sudogs aren't considered as roots of the
+ // stack tracer.
+ KeepAlive(ep)
// someone woke us up.
if mysg != gp.waiting {
@@ -337,8 +342,8 @@ func closechan(c *hchan) {
if raceenabled {
callerpc := getcallerpc()
- racewritepc(unsafe.Pointer(c), callerpc, funcPC(closechan))
- racerelease(unsafe.Pointer(c))
+ racewritepc(c.raceaddr(), callerpc, funcPC(closechan))
+ racerelease(c.raceaddr())
}
c.closed = 1
@@ -361,7 +366,7 @@ func closechan(c *hchan) {
gp := sg.g
gp.param = nil
if raceenabled {
- raceacquireg(gp, unsafe.Pointer(c))
+ raceacquireg(gp, c.raceaddr())
}
glist.push(gp)
}
@@ -379,7 +384,7 @@ func closechan(c *hchan) {
gp := sg.g
gp.param = nil
if raceenabled {
- raceacquireg(gp, unsafe.Pointer(c))
+ raceacquireg(gp, c.raceaddr())
}
glist.push(gp)
}
@@ -454,7 +459,7 @@ func chanrecv(c *hchan, ep unsafe.Pointer, block bool) (selected, received bool)
if c.closed != 0 && c.qcount == 0 {
if raceenabled {
- raceacquire(unsafe.Pointer(c))
+ raceacquire(c.raceaddr())
}
unlock(&c.lock)
if ep != nil {
@@ -732,6 +737,15 @@ func (q *waitq) dequeue() *sudog {
}
}
+func (c *hchan) raceaddr() unsafe.Pointer {
+ // Treat read-like and write-like operations on the channel to
+ // happen at this address. Avoid using the address of qcount
+ // or dataqsiz, because the len() and cap() builtins read
+ // those addresses, and we don't want them racing with
+ // operations like close().
+ return unsafe.Pointer(&c.buf)
+}
+
func racesync(c *hchan, sg *sudog) {
racerelease(chanbuf(c, 0))
raceacquireg(sg.g, chanbuf(c, 0))
diff --git a/src/runtime/crash_test.go b/src/runtime/crash_test.go
index 2766b8850a..6835cacb3f 100644
--- a/src/runtime/crash_test.go
+++ b/src/runtime/crash_test.go
@@ -686,7 +686,7 @@ func init() {
func TestRuntimePanic(t *testing.T) {
testenv.MustHaveExec(t)
- cmd := exec.Command(os.Args[0], "-test.run=TestRuntimePanic")
+ cmd := testenv.CleanCmdEnv(exec.Command(os.Args[0], "-test.run=TestRuntimePanic"))
cmd.Env = append(cmd.Env, "GO_TEST_RUNTIME_PANIC=1")
out, err := cmd.CombinedOutput()
t.Logf("%s", out)
diff --git a/src/runtime/crash_unix_test.go b/src/runtime/crash_unix_test.go
index af9e6430da..1384e00210 100644
--- a/src/runtime/crash_unix_test.go
+++ b/src/runtime/crash_unix_test.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
package runtime_test
diff --git a/src/runtime/debug_test.go b/src/runtime/debug_test.go
index a34f4c77f7..37dcafd145 100644
--- a/src/runtime/debug_test.go
+++ b/src/runtime/debug_test.go
@@ -17,6 +17,8 @@ package runtime_test
import (
"fmt"
+ "io/ioutil"
+ "regexp"
"runtime"
"runtime/debug"
"sync/atomic"
@@ -25,6 +27,11 @@ import (
)
func startDebugCallWorker(t *testing.T) (g *runtime.G, after func()) {
+ // This can deadlock if run under a debugger because it
+ // depends on catching SIGTRAP, which is usually swallowed by
+ // a debugger.
+ skipUnderDebugger(t)
+
// This can deadlock if there aren't enough threads or if a GC
// tries to interrupt an atomic loop (see issue #10958).
ogomaxprocs := runtime.GOMAXPROCS(2)
@@ -73,6 +80,28 @@ func debugCallTKill(tid int) error {
return syscall.Tgkill(syscall.Getpid(), tid, syscall.SIGTRAP)
}
+// skipUnderDebugger skips the current test when running under a
+// debugger (specifically if this process has a tracer). This is
+// Linux-specific.
+func skipUnderDebugger(t *testing.T) {
+ pid := syscall.Getpid()
+ status, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/status", pid))
+ if err != nil {
+ t.Logf("couldn't get proc tracer: %s", err)
+ return
+ }
+ re := regexp.MustCompile(`TracerPid:\s+([0-9]+)`)
+ sub := re.FindSubmatch(status)
+ if sub == nil {
+ t.Logf("couldn't find proc tracer PID")
+ return
+ }
+ if string(sub[1]) == "0" {
+ return
+ }
+ t.Skip("test will deadlock under a debugger")
+}
+
func TestDebugCall(t *testing.T) {
g, after := startDebugCallWorker(t)
defer after()
@@ -160,6 +189,8 @@ func debugCallUnsafePointWorker(gpp **runtime.G, ready, stop *uint32) {
}
func TestDebugCallUnsafePoint(t *testing.T) {
+ skipUnderDebugger(t)
+
// This can deadlock if there aren't enough threads or if a GC
// tries to interrupt an atomic loop (see issue #10958).
defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2))
@@ -181,6 +212,8 @@ func TestDebugCallUnsafePoint(t *testing.T) {
}
func TestDebugCallPanic(t *testing.T) {
+ skipUnderDebugger(t)
+
// This can deadlock if there aren't enough threads.
defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2))
diff --git a/src/runtime/defs2_linux.go b/src/runtime/defs2_linux.go
index c10dfb8624..b08c0dafe1 100644
--- a/src/runtime/defs2_linux.go
+++ b/src/runtime/defs2_linux.go
@@ -58,7 +58,10 @@ const (
MAP_PRIVATE = C.MAP_PRIVATE
MAP_FIXED = C.MAP_FIXED
- MADV_DONTNEED = C.MADV_DONTNEED
+ MADV_DONTNEED = C.MADV_DONTNEED
+ MADV_FREE = C.MADV_FREE
+ MADV_HUGEPAGE = C.MADV_HUGEPAGE
+ MADV_NOHUGEPAGE = C.MADV_HNOUGEPAGE
SA_RESTART = C.SA_RESTART
SA_ONSTACK = C.SA_ONSTACK
diff --git a/src/runtime/defs_aix.go b/src/runtime/defs_aix.go
new file mode 100644
index 0000000000..812c7fcfa2
--- /dev/null
+++ b/src/runtime/defs_aix.go
@@ -0,0 +1,170 @@
+// Copyright 2018 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
+
+/*
+Input to cgo -godefs
+GOARCH=ppc64 go tool cgo -godefs defs_aix.go > defs_aix_ppc64_tmp.go
+
+This is only an helper to create defs_aix_ppc64.go
+Go runtime functions require the "linux" name of fields (ss_sp, si_addr, etc)
+However, AIX structures don't provide such names and must be modified.
+
+TODO(aix): create a script to automatise defs_aix creation.
+
+Modifications made:
+ - sigset replaced by a [4]uint64 array
+ - add sigset_all variable
+ - siginfo.si_addr uintptr instead of *byte
+ - add (*timeval) set_usec
+ - stackt.ss_sp uintptr instead of *byte
+ - stackt.ss_size uintptr instead of uint64
+ - sigcontext.sc_jmpbuf context64 instead of jumbuf
+ - ucontext.__extctx is a uintptr because we don't need extctx struct
+ - ucontext.uc_mcontext: replace jumbuf structure by context64 structure
+ - sigaction.sa_handler represents union field as both are uintptr
+ - tstate.* replace *byte by uintptr
+
+
+*/
+
+package runtime
+
+/*
+
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/time.h>
+#include <sys/signal.h>
+#include <sys/mman.h>
+#include <sys/thread.h>
+#include <sys/resource.h>
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <semaphore.h>
+*/
+import "C"
+
+const (
+ _EPERM = C.EPERM
+ _ENOENT = C.ENOENT
+ _EINTR = C.EINTR
+ _EAGAIN = C.EAGAIN
+ _ENOMEM = C.ENOMEM
+ _EACCES = C.EACCES
+ _EFAULT = C.EFAULT
+ _EINVAL = C.EINVAL
+ _ETIMEDOUT = C.ETIMEDOUT
+
+ _PROT_NONE = C.PROT_NONE
+ _PROT_READ = C.PROT_READ
+ _PROT_WRITE = C.PROT_WRITE
+ _PROT_EXEC = C.PROT_EXEC
+
+ _MAP_ANONYMOUS = C.MAP_ANONYMOUS
+ _MAP_PRIVATE = C.MAP_PRIVATE
+ _MAP_FIXED = C.MAP_FIXED
+ _MADV_DONTNEED = C.MADV_DONTNEED
+
+ _SIGHUP = C.SIGHUP
+ _SIGINT = C.SIGINT
+ _SIGQUIT = C.SIGQUIT
+ _SIGILL = C.SIGILL
+ _SIGTRAP = C.SIGTRAP
+ _SIGABRT = C.SIGABRT
+ _SIGBUS = C.SIGBUS
+ _SIGFPE = C.SIGFPE
+ _SIGKILL = C.SIGKILL
+ _SIGUSR1 = C.SIGUSR1
+ _SIGSEGV = C.SIGSEGV
+ _SIGUSR2 = C.SIGUSR2
+ _SIGPIPE = C.SIGPIPE
+ _SIGALRM = C.SIGALRM
+ _SIGCHLD = C.SIGCHLD
+ _SIGCONT = C.SIGCONT
+ _SIGSTOP = C.SIGSTOP
+ _SIGTSTP = C.SIGTSTP
+ _SIGTTIN = C.SIGTTIN
+ _SIGTTOU = C.SIGTTOU
+ _SIGURG = C.SIGURG
+ _SIGXCPU = C.SIGXCPU
+ _SIGXFSZ = C.SIGXFSZ
+ _SIGVTALRM = C.SIGVTALRM
+ _SIGPROF = C.SIGPROF
+ _SIGWINCH = C.SIGWINCH
+ _SIGIO = C.SIGIO
+ _SIGPWR = C.SIGPWR
+ _SIGSYS = C.SIGSYS
+ _SIGTERM = C.SIGTERM
+ _SIGEMT = C.SIGEMT
+ _SIGWAITING = C.SIGWAITING
+
+ _FPE_INTDIV = C.FPE_INTDIV
+ _FPE_INTOVF = C.FPE_INTOVF
+ _FPE_FLTDIV = C.FPE_FLTDIV
+ _FPE_FLTOVF = C.FPE_FLTOVF
+ _FPE_FLTUND = C.FPE_FLTUND
+ _FPE_FLTRES = C.FPE_FLTRES
+ _FPE_FLTINV = C.FPE_FLTINV
+ _FPE_FLTSUB = C.FPE_FLTSUB
+
+ _BUS_ADRALN = C.BUS_ADRALN
+ _BUS_ADRERR = C.BUS_ADRERR
+ _BUS_OBJERR = C.BUS_OBJERR
+
+ _SEGV_MAPERR = C.SEGV_MAPERR
+ _SEGV_ACCERR = C.SEGV_ACCERR
+
+ _ITIMER_REAL = C.ITIMER_REAL
+ _ITIMER_VIRTUAL = C.ITIMER_VIRTUAL
+ _ITIMER_PROF = C.ITIMER_PROF
+
+ _O_RDONLY = C.O_RDONLY
+
+ _SS_DISABLE = C.SS_DISABLE
+ _SI_USER = C.SI_USER
+ _SIG_BLOCK = C.SIG_BLOCK
+ _SIG_UNBLOCK = C.SIG_UNBLOCK
+ _SIG_SETMASK = C.SIG_SETMASK
+
+ _SA_SIGINFO = C.SA_SIGINFO
+ _SA_RESTART = C.SA_RESTART
+ _SA_ONSTACK = C.SA_ONSTACK
+
+ _PTHREAD_CREATE_DETACHED = C.PTHREAD_CREATE_DETACHED
+
+ __SC_PAGE_SIZE = C._SC_PAGE_SIZE
+ __SC_NPROCESSORS_ONLN = C._SC_NPROCESSORS_ONLN
+
+ _F_SETFD = C.F_SETFD
+ _F_SETFL = C.F_SETFL
+ _F_GETFD = C.F_GETFD
+ _F_GETFL = C.F_GETFL
+ _FD_CLOEXEC = C.FD_CLOEXEC
+)
+
+type sigset C.sigset_t
+type siginfo C.siginfo_t
+type timespec C.struct_timespec
+type timestruc C.struct_timestruc_t
+type timeval C.struct_timeval
+type itimerval C.struct_itimerval
+
+type stackt C.stack_t
+type sigcontext C.struct_sigcontext
+type ucontext C.ucontext_t
+type _Ctype_struct___extctx uint64 // ucontext use a pointer to this structure but it shouldn't be used
+type jmpbuf C.struct___jmpbuf
+type context64 C.struct___context64
+type sigactiont C.struct_sigaction
+type tstate C.struct_tstate
+type rusage C.struct_rusage
+
+type pthread C.pthread_t
+type pthread_attr C.pthread_attr_t
+
+type semt C.sem_t
diff --git a/src/runtime/defs_aix_ppc64.go b/src/runtime/defs_aix_ppc64.go
new file mode 100644
index 0000000000..e7480d06ba
--- /dev/null
+++ b/src/runtime/defs_aix_ppc64.go
@@ -0,0 +1,203 @@
+// Copyright 2018 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 aix
+
+package runtime
+
+const (
+ _EPERM = 0x1
+ _ENOENT = 0x2
+ _EINTR = 0x4
+ _EAGAIN = 0xb
+ _ENOMEM = 0xc
+ _EACCES = 0xd
+ _EFAULT = 0xe
+ _EINVAL = 0x16
+ _ETIMEDOUT = 0x4e
+
+ _PROT_NONE = 0x0
+ _PROT_READ = 0x1
+ _PROT_WRITE = 0x2
+ _PROT_EXEC = 0x4
+
+ _MAP_ANONYMOUS = 0x10
+ _MAP_PRIVATE = 0x2
+ _MAP_FIXED = 0x100
+ _MADV_DONTNEED = 0x4
+
+ _SIGHUP = 0x1
+ _SIGINT = 0x2
+ _SIGQUIT = 0x3
+ _SIGILL = 0x4
+ _SIGTRAP = 0x5
+ _SIGABRT = 0x6
+ _SIGBUS = 0xa
+ _SIGFPE = 0x8
+ _SIGKILL = 0x9
+ _SIGUSR1 = 0x1e
+ _SIGSEGV = 0xb
+ _SIGUSR2 = 0x1f
+ _SIGPIPE = 0xd
+ _SIGALRM = 0xe
+ _SIGCHLD = 0x14
+ _SIGCONT = 0x13
+ _SIGSTOP = 0x11
+ _SIGTSTP = 0x12
+ _SIGTTIN = 0x15
+ _SIGTTOU = 0x16
+ _SIGURG = 0x10
+ _SIGXCPU = 0x18
+ _SIGXFSZ = 0x19
+ _SIGVTALRM = 0x22
+ _SIGPROF = 0x20
+ _SIGWINCH = 0x1c
+ _SIGIO = 0x17
+ _SIGPWR = 0x1d
+ _SIGSYS = 0xc
+ _SIGTERM = 0xf
+ _SIGEMT = 0x7
+ _SIGWAITING = 0x27
+
+ _FPE_INTDIV = 0x14
+ _FPE_INTOVF = 0x15
+ _FPE_FLTDIV = 0x16
+ _FPE_FLTOVF = 0x17
+ _FPE_FLTUND = 0x18
+ _FPE_FLTRES = 0x19
+ _FPE_FLTINV = 0x1a
+ _FPE_FLTSUB = 0x1b
+
+ _BUS_ADRALN = 0x1
+ _BUS_ADRERR = 0x2
+ _BUS_OBJERR = 0x3
+ _
+ _SEGV_MAPERR = 0x32
+ _SEGV_ACCERR = 0x33
+
+ _ITIMER_REAL = 0x0
+ _ITIMER_VIRTUAL = 0x1
+ _ITIMER_PROF = 0x2
+
+ _O_RDONLY = 0x0
+
+ _SS_DISABLE = 0x2
+ _SI_USER = 0x0
+ _SIG_BLOCK = 0x0
+ _SIG_UNBLOCK = 0x1
+ _SIG_SETMASK = 0x2
+
+ _SA_SIGINFO = 0x100
+ _SA_RESTART = 0x8
+ _SA_ONSTACK = 0x1
+
+ _PTHREAD_CREATE_DETACHED = 0x1
+
+ __SC_PAGE_SIZE = 0x30
+ __SC_NPROCESSORS_ONLN = 0x48
+
+ _F_SETFD = 0x2
+ _F_SETFL = 0x4
+ _F_GETFD = 0x1
+ _F_GETFL = 0x3
+ _FD_CLOEXEC = 0x1
+)
+
+type sigset [4]uint64
+
+var sigset_all = sigset{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)}
+
+type siginfo struct {
+ si_signo int32
+ si_errno int32
+ si_code int32
+ si_pid int32
+ si_uid uint32
+ si_status int32
+ si_addr uintptr
+ si_band int64
+ si_value [2]int32 // [8]byte
+ __si_flags int32
+ __pad [3]int32
+}
+
+type timespec struct {
+ tv_sec int64
+ tv_nsec int64
+}
+type timeval struct {
+ tv_sec int64
+ tv_usec int32
+ pad_cgo_0 [4]byte
+}
+
+func (tv *timeval) set_usec(x int32) {
+ tv.tv_usec = x
+}
+
+type itimerval struct {
+ it_interval timeval
+ it_value timeval
+}
+
+type stackt struct {
+ ss_sp uintptr
+ ss_size uintptr
+ ss_flags int32
+ __pad [4]int32
+ pas_cgo_0 [4]byte
+}
+
+type sigcontext struct {
+ sc_onstack int32
+ pad_cgo_0 [4]byte
+ sc_mask sigset
+ sc_uerror int32
+ sc_jmpbuf context64
+}
+
+type ucontext struct {
+ __sc_onstack int32
+ pad_cgo_0 [4]byte
+ uc_sigmask sigset
+ __sc_error int32
+ pad_cgo_1 [4]byte
+ uc_mcontext context64
+ uc_link *ucontext
+ uc_stack stackt
+ __extctx uintptr // pointer to struct __extctx but we don't use it
+ __extctx_magic int32
+ __pad int32
+}
+
+type context64 struct {
+ gpr [32]uint64
+ msr uint64
+ iar uint64
+ lr uint64
+ ctr uint64
+ cr uint32
+ xer uint32
+ fpscr uint32
+ fpscrx uint32
+ except [1]uint64
+ fpr [32]float64
+ fpeu uint8
+ fpinfo uint8
+ fpscr24_31 uint8
+ pad [1]uint8
+ excp_type int32
+}
+
+type sigactiont struct {
+ sa_handler uintptr // a union of two pointer
+ sa_mask sigset
+ sa_flags int32
+ pad_cgo_0 [4]byte
+}
+
+type pthread uint32
+type pthread_attr *byte
+
+type semt int32
diff --git a/src/runtime/defs_linux.go b/src/runtime/defs_linux.go
index 553366a50b..2d810136d9 100644
--- a/src/runtime/defs_linux.go
+++ b/src/runtime/defs_linux.go
@@ -47,7 +47,10 @@ const (
MAP_PRIVATE = C.MAP_PRIVATE
MAP_FIXED = C.MAP_FIXED
- MADV_DONTNEED = C.MADV_DONTNEED
+ MADV_DONTNEED = C.MADV_DONTNEED
+ MADV_FREE = C.MADV_FREE
+ MADV_HUGEPAGE = C.MADV_HUGEPAGE
+ MADV_NOHUGEPAGE = C.MADV_HNOUGEPAGE
SA_RESTART = C.SA_RESTART
SA_ONSTACK = C.SA_ONSTACK
diff --git a/src/runtime/defs_linux_386.go b/src/runtime/defs_linux_386.go
index a7e435f854..0ebac17aef 100644
--- a/src/runtime/defs_linux_386.go
+++ b/src/runtime/defs_linux_386.go
@@ -18,6 +18,7 @@ const (
_MAP_FIXED = 0x10
_MADV_DONTNEED = 0x4
+ _MADV_FREE = 0x8
_MADV_HUGEPAGE = 0xe
_MADV_NOHUGEPAGE = 0xf
diff --git a/src/runtime/defs_linux_amd64.go b/src/runtime/defs_linux_amd64.go
index e8c6a212db..c0a0ef0dd4 100644
--- a/src/runtime/defs_linux_amd64.go
+++ b/src/runtime/defs_linux_amd64.go
@@ -18,6 +18,7 @@ const (
_MAP_FIXED = 0x10
_MADV_DONTNEED = 0x4
+ _MADV_FREE = 0x8
_MADV_HUGEPAGE = 0xe
_MADV_NOHUGEPAGE = 0xf
diff --git a/src/runtime/defs_linux_arm.go b/src/runtime/defs_linux_arm.go
index 62ec8fab5e..43946bb79c 100644
--- a/src/runtime/defs_linux_arm.go
+++ b/src/runtime/defs_linux_arm.go
@@ -16,6 +16,7 @@ const (
_MAP_FIXED = 0x10
_MADV_DONTNEED = 0x4
+ _MADV_FREE = 0x8
_MADV_HUGEPAGE = 0xe
_MADV_NOHUGEPAGE = 0xf
diff --git a/src/runtime/defs_linux_arm64.go b/src/runtime/defs_linux_arm64.go
index c295bc0257..c2cc281ab4 100644
--- a/src/runtime/defs_linux_arm64.go
+++ b/src/runtime/defs_linux_arm64.go
@@ -18,6 +18,7 @@ const (
_MAP_FIXED = 0x10
_MADV_DONTNEED = 0x4
+ _MADV_FREE = 0x8
_MADV_HUGEPAGE = 0xe
_MADV_NOHUGEPAGE = 0xf
diff --git a/src/runtime/defs_linux_mips64x.go b/src/runtime/defs_linux_mips64x.go
index df11cb0965..9dacd5d1e9 100644
--- a/src/runtime/defs_linux_mips64x.go
+++ b/src/runtime/defs_linux_mips64x.go
@@ -18,6 +18,7 @@ const (
_MAP_FIXED = 0x10
_MADV_DONTNEED = 0x4
+ _MADV_FREE = 0x8
_MADV_HUGEPAGE = 0xe
_MADV_NOHUGEPAGE = 0xf
diff --git a/src/runtime/defs_linux_mipsx.go b/src/runtime/defs_linux_mipsx.go
index 702fbb51c8..9532ac54ee 100644
--- a/src/runtime/defs_linux_mipsx.go
+++ b/src/runtime/defs_linux_mipsx.go
@@ -22,6 +22,7 @@ const (
_MAP_FIXED = 0x10
_MADV_DONTNEED = 0x4
+ _MADV_FREE = 0x8
_MADV_HUGEPAGE = 0xe
_MADV_NOHUGEPAGE = 0xf
diff --git a/src/runtime/defs_linux_ppc64.go b/src/runtime/defs_linux_ppc64.go
index 45363d1285..5a4326da07 100644
--- a/src/runtime/defs_linux_ppc64.go
+++ b/src/runtime/defs_linux_ppc64.go
@@ -18,6 +18,7 @@ const (
_MAP_FIXED = 0x10
_MADV_DONTNEED = 0x4
+ _MADV_FREE = 0x8
_MADV_HUGEPAGE = 0xe
_MADV_NOHUGEPAGE = 0xf
diff --git a/src/runtime/defs_linux_ppc64le.go b/src/runtime/defs_linux_ppc64le.go
index 45363d1285..5a4326da07 100644
--- a/src/runtime/defs_linux_ppc64le.go
+++ b/src/runtime/defs_linux_ppc64le.go
@@ -18,6 +18,7 @@ const (
_MAP_FIXED = 0x10
_MADV_DONTNEED = 0x4
+ _MADV_FREE = 0x8
_MADV_HUGEPAGE = 0xe
_MADV_NOHUGEPAGE = 0xf
diff --git a/src/runtime/defs_linux_s390x.go b/src/runtime/defs_linux_s390x.go
index ab90723f75..a6cc9c48e9 100644
--- a/src/runtime/defs_linux_s390x.go
+++ b/src/runtime/defs_linux_s390x.go
@@ -19,6 +19,7 @@ const (
_MAP_FIXED = 0x10
_MADV_DONTNEED = 0x4
+ _MADV_FREE = 0x8
_MADV_HUGEPAGE = 0xe
_MADV_NOHUGEPAGE = 0xf
diff --git a/src/runtime/defs_windows_386.go b/src/runtime/defs_windows_386.go
index 589a7884cd..38b30b70e3 100644
--- a/src/runtime/defs_windows_386.go
+++ b/src/runtime/defs_windows_386.go
@@ -104,6 +104,9 @@ type context struct {
func (c *context) ip() uintptr { return uintptr(c.eip) }
func (c *context) sp() uintptr { return uintptr(c.esp) }
+// 386 does not have link register, so this returns 0.
+func (c *context) lr() uintptr { return 0 }
+
func (c *context) setip(x uintptr) { c.eip = uint32(x) }
func (c *context) setsp(x uintptr) { c.esp = uint32(x) }
diff --git a/src/runtime/defs_windows_amd64.go b/src/runtime/defs_windows_amd64.go
index 1e173e934d..37508c09be 100644
--- a/src/runtime/defs_windows_amd64.go
+++ b/src/runtime/defs_windows_amd64.go
@@ -119,6 +119,9 @@ type context struct {
func (c *context) ip() uintptr { return uintptr(c.rip) }
func (c *context) sp() uintptr { return uintptr(c.rsp) }
+// Amd64 does not have link register, so this returns 0.
+func (c *context) lr() uintptr { return 0 }
+
func (c *context) setip(x uintptr) { c.rip = uint64(x) }
func (c *context) setsp(x uintptr) { c.rsp = uint64(x) }
diff --git a/src/runtime/defs_windows_arm.go b/src/runtime/defs_windows_arm.go
new file mode 100644
index 0000000000..1140f61651
--- /dev/null
+++ b/src/runtime/defs_windows_arm.go
@@ -0,0 +1,149 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+const (
+ _PROT_NONE = 0
+ _PROT_READ = 1
+ _PROT_WRITE = 2
+ _PROT_EXEC = 4
+
+ _MAP_ANON = 1
+ _MAP_PRIVATE = 2
+
+ _DUPLICATE_SAME_ACCESS = 0x2
+ _THREAD_PRIORITY_HIGHEST = 0x2
+
+ _SIGINT = 0x2
+ _CTRL_C_EVENT = 0x0
+ _CTRL_BREAK_EVENT = 0x1
+
+ _CONTEXT_CONTROL = 0x10001
+ _CONTEXT_FULL = 0x10007
+
+ _EXCEPTION_ACCESS_VIOLATION = 0xc0000005
+ _EXCEPTION_BREAKPOINT = 0x80000003
+ _EXCEPTION_FLT_DENORMAL_OPERAND = 0xc000008d
+ _EXCEPTION_FLT_DIVIDE_BY_ZERO = 0xc000008e
+ _EXCEPTION_FLT_INEXACT_RESULT = 0xc000008f
+ _EXCEPTION_FLT_OVERFLOW = 0xc0000091
+ _EXCEPTION_FLT_UNDERFLOW = 0xc0000093
+ _EXCEPTION_INT_DIVIDE_BY_ZERO = 0xc0000094
+ _EXCEPTION_INT_OVERFLOW = 0xc0000095
+
+ _INFINITE = 0xffffffff
+ _WAIT_TIMEOUT = 0x102
+
+ _EXCEPTION_CONTINUE_EXECUTION = -0x1
+ _EXCEPTION_CONTINUE_SEARCH = 0x0
+)
+
+type systeminfo struct {
+ anon0 [4]byte
+ dwpagesize uint32
+ lpminimumapplicationaddress *byte
+ lpmaximumapplicationaddress *byte
+ dwactiveprocessormask uint32
+ dwnumberofprocessors uint32
+ dwprocessortype uint32
+ dwallocationgranularity uint32
+ wprocessorlevel uint16
+ wprocessorrevision uint16
+}
+
+type exceptionrecord struct {
+ exceptioncode uint32
+ exceptionflags uint32
+ exceptionrecord *exceptionrecord
+ exceptionaddress *byte
+ numberparameters uint32
+ exceptioninformation [15]uint32
+}
+
+type neon128 struct {
+ low uint64
+ high int64
+}
+
+type context struct {
+ contextflags uint32
+ r0 uint32
+ r1 uint32
+ r2 uint32
+ r3 uint32
+ r4 uint32
+ r5 uint32
+ r6 uint32
+ r7 uint32
+ r8 uint32
+ r9 uint32
+ r10 uint32
+ r11 uint32
+ r12 uint32
+
+ spr uint32
+ lrr uint32
+ pc uint32
+ cpsr uint32
+
+ fpscr uint32
+ padding uint32
+
+ floatNeon [16]neon128
+
+ bvr [8]uint32
+ bcr [8]uint32
+ wvr [1]uint32
+ wcr [1]uint32
+ padding2 [2]uint32
+}
+
+func (c *context) ip() uintptr { return uintptr(c.pc) }
+func (c *context) sp() uintptr { return uintptr(c.spr) }
+func (c *context) lr() uintptr { return uintptr(c.lrr) }
+
+func (c *context) setip(x uintptr) { c.pc = uint32(x) }
+func (c *context) setsp(x uintptr) { c.spr = uint32(x) }
+
+func dumpregs(r *context) {
+ print("r0 ", hex(r.r0), "\n")
+ print("r1 ", hex(r.r1), "\n")
+ print("r2 ", hex(r.r2), "\n")
+ print("r3 ", hex(r.r3), "\n")
+ print("r4 ", hex(r.r4), "\n")
+ print("r5 ", hex(r.r5), "\n")
+ print("r6 ", hex(r.r6), "\n")
+ print("r7 ", hex(r.r7), "\n")
+ print("r8 ", hex(r.r8), "\n")
+ print("r9 ", hex(r.r9), "\n")
+ print("r10 ", hex(r.r10), "\n")
+ print("r11 ", hex(r.r11), "\n")
+ print("r12 ", hex(r.r12), "\n")
+ print("sp ", hex(r.spr), "\n")
+ print("lr ", hex(r.lrr), "\n")
+ print("pc ", hex(r.pc), "\n")
+ print("cpsr ", hex(r.cpsr), "\n")
+}
+
+type overlapped struct {
+ internal uint32
+ internalhigh uint32
+ anon0 [8]byte
+ hevent *byte
+}
+
+type memoryBasicInformation struct {
+ baseAddress uintptr
+ allocationBase uintptr
+ allocationProtect uint32
+ regionSize uintptr
+ state uint32
+ protect uint32
+ type_ uint32
+}
+
+func stackcheck() {
+ // TODO: not implemented on ARM
+}
diff --git a/src/runtime/env_posix.go b/src/runtime/env_posix.go
index 032e7122ce..a2daeb7f27 100644
--- a/src/runtime/env_posix.go
+++ b/src/runtime/env_posix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris windows
+// +build aix darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris windows
package runtime
diff --git a/src/runtime/export_unix_test.go b/src/runtime/export_unix_test.go
index 54d577072e..eecdfb7eb2 100644
--- a/src/runtime/export_unix_test.go
+++ b/src/runtime/export_unix_test.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
package runtime
diff --git a/src/runtime/extern.go b/src/runtime/extern.go
index 1773c8fe7e..640688e004 100644
--- a/src/runtime/extern.go
+++ b/src/runtime/extern.go
@@ -50,19 +50,13 @@ It is a comma-separated list of name=val pairs setting these named variables:
gcshrinkstackoff: setting gcshrinkstackoff=1 disables moving goroutines
onto smaller stacks. In this mode, a goroutine's stack can only grow.
- gcrescanstacks: setting gcrescanstacks=1 enables stack
- re-scanning during the STW mark termination phase. This is
- helpful for debugging if objects are being prematurely
- garbage collected.
-
gcstoptheworld: setting gcstoptheworld=1 disables concurrent garbage collection,
making every garbage collection a stop-the-world event. Setting gcstoptheworld=2
also disables concurrent sweeping after the garbage collection finishes.
gctrace: setting gctrace=1 causes the garbage collector to emit a single line to standard
error at each collection, summarizing the amount of memory collected and the
- length of the pause. Setting gctrace=2 emits the same summary but also
- repeats each collection. The format of this line is subject to change.
+ length of the pause. The format of this line is subject to change.
Currently, it is:
gc # @#s #%: #+#+# ms clock, #+#/#/#+# ms cpu, #->#-># MB, # MB goal, # P
where the fields are as follows:
diff --git a/src/runtime/funcdata.h b/src/runtime/funcdata.h
index e6e0306e65..1ee67c8683 100644
--- a/src/runtime/funcdata.h
+++ b/src/runtime/funcdata.h
@@ -16,6 +16,7 @@
#define FUNCDATA_LocalsPointerMaps 1
#define FUNCDATA_InlTree 2
#define FUNCDATA_RegPointerMaps 3
+#define FUNCDATA_StackObjects 4
// Pseudo-assembly statements.
diff --git a/src/runtime/gc_test.go b/src/runtime/gc_test.go
index 0da19cdf34..51e8ea4d31 100644
--- a/src/runtime/gc_test.go
+++ b/src/runtime/gc_test.go
@@ -24,6 +24,9 @@ func TestGcSys(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("skipping test; GOOS=windows http://golang.org/issue/27156")
}
+ if runtime.GOOS == "linux" && runtime.GOARCH == "arm64" {
+ t.Skip("skipping test; GOOS=linux GOARCH=arm64 https://github.com/golang/go/issues/27636")
+ }
got := runTestProg(t, "testprog", "GCSys")
want := "OK\n"
if got != want {
@@ -571,8 +574,8 @@ func BenchmarkWriteBarrier(b *testing.B) {
n := &node{mkTree(level - 1), mkTree(level - 1)}
if level == 10 {
// Seed GC with enough early pointers so it
- // doesn't accidentally switch to mark 2 when
- // it only has the top of the tree.
+ // doesn't start termination barriers when it
+ // only has the top of the tree.
wbRoots = append(wbRoots, n)
}
return n
diff --git a/src/runtime/gcinfo_test.go b/src/runtime/gcinfo_test.go
index 7dd1a5607c..0741f6361c 100644
--- a/src/runtime/gcinfo_test.go
+++ b/src/runtime/gcinfo_test.go
@@ -35,14 +35,46 @@ func TestGCInfo(t *testing.T) {
verifyGCInfo(t, "data eface", &dataEface, infoEface)
verifyGCInfo(t, "data iface", &dataIface, infoIface)
- verifyGCInfo(t, "stack Ptr", new(Ptr), infoPtr)
- verifyGCInfo(t, "stack ScalarPtr", new(ScalarPtr), infoScalarPtr)
- verifyGCInfo(t, "stack PtrScalar", new(PtrScalar), infoPtrScalar)
- verifyGCInfo(t, "stack BigStruct", new(BigStruct), infoBigStruct())
- verifyGCInfo(t, "stack string", new(string), infoString)
- verifyGCInfo(t, "stack slice", new([]string), infoSlice)
- verifyGCInfo(t, "stack eface", new(interface{}), infoEface)
- verifyGCInfo(t, "stack iface", new(Iface), infoIface)
+ {
+ var x Ptr
+ verifyGCInfo(t, "stack Ptr", &x, infoPtr)
+ runtime.KeepAlive(x)
+ }
+ {
+ var x ScalarPtr
+ verifyGCInfo(t, "stack ScalarPtr", &x, infoScalarPtr)
+ runtime.KeepAlive(x)
+ }
+ {
+ var x PtrScalar
+ verifyGCInfo(t, "stack PtrScalar", &x, infoPtrScalar)
+ runtime.KeepAlive(x)
+ }
+ {
+ var x BigStruct
+ verifyGCInfo(t, "stack BigStruct", &x, infoBigStruct())
+ runtime.KeepAlive(x)
+ }
+ {
+ var x string
+ verifyGCInfo(t, "stack string", &x, infoString)
+ runtime.KeepAlive(x)
+ }
+ {
+ var x []string
+ verifyGCInfo(t, "stack slice", &x, infoSlice)
+ runtime.KeepAlive(x)
+ }
+ {
+ var x interface{}
+ verifyGCInfo(t, "stack eface", &x, infoEface)
+ runtime.KeepAlive(x)
+ }
+ {
+ var x Iface
+ verifyGCInfo(t, "stack iface", &x, infoIface)
+ runtime.KeepAlive(x)
+ }
for i := 0; i < 10; i++ {
verifyGCInfo(t, "heap Ptr", escape(new(Ptr)), trimDead(padDead(infoPtr)))
diff --git a/src/runtime/heapdump.go b/src/runtime/heapdump.go
index 0fc02a8e80..eadbcaeee1 100644
--- a/src/runtime/heapdump.go
+++ b/src/runtime/heapdump.go
@@ -346,7 +346,7 @@ func dumpgoroutine(gp *g) {
dumpint(uint64(gp.goid))
dumpint(uint64(gp.gopc))
dumpint(uint64(readgstatus(gp)))
- dumpbool(isSystemGoroutine(gp))
+ dumpbool(isSystemGoroutine(gp, false))
dumpbool(false) // isbackground
dumpint(uint64(gp.waitsince))
dumpstr(gp.waitreason.String())
@@ -430,7 +430,7 @@ func dumproots() {
// MSpan.types
for _, s := range mheap_.allspans {
- if s.state == _MSpanInUse {
+ if s.state == mSpanInUse {
// Finalizers
for sp := s.specials; sp != nil; sp = sp.next {
if sp.kind != _KindSpecialFinalizer {
@@ -453,7 +453,7 @@ var freemark [_PageSize / 8]bool
func dumpobjs() {
for _, s := range mheap_.allspans {
- if s.state != _MSpanInUse {
+ if s.state != mSpanInUse {
continue
}
p := s.base()
@@ -616,7 +616,7 @@ func dumpmemprof_callback(b *bucket, nstk uintptr, pstk *uintptr, size, allocs,
func dumpmemprof() {
iterate_memprof(dumpmemprof_callback)
for _, s := range mheap_.allspans {
- if s.state != _MSpanInUse {
+ if s.state != mSpanInUse {
continue
}
for sp := s.specials; sp != nil; sp = sp.next {
@@ -637,7 +637,7 @@ var dumphdr = []byte("go1.7 heap dump\n")
func mdump() {
// make sure we're done sweeping
for _, s := range mheap_.allspans {
- if s.state == _MSpanInUse {
+ if s.state == mSpanInUse {
s.ensureSwept()
}
}
diff --git a/src/runtime/internal/sys/zgoos_aix.go b/src/runtime/internal/sys/zgoos_aix.go
new file mode 100644
index 0000000000..9ce5b3434f
--- /dev/null
+++ b/src/runtime/internal/sys/zgoos_aix.go
@@ -0,0 +1,21 @@
+// Code generated by gengoos.go using 'go generate'. DO NOT EDIT.
+
+// +build aix
+
+package sys
+
+const GOOS = `aix`
+
+const GoosAndroid = 0
+const GoosAix = 1
+const GoosDarwin = 0
+const GoosDragonfly = 0
+const GoosFreebsd = 0
+const GoosLinux = 0
+const GoosNacl = 0
+const GoosNetbsd = 0
+const GoosOpenbsd = 0
+const GoosPlan9 = 0
+const GoosSolaris = 0
+const GoosWindows = 0
+const GoosZos = 0
diff --git a/src/runtime/internal/sys/zgoos_android.go b/src/runtime/internal/sys/zgoos_android.go
index bfdc37792e..36a5768ab6 100644
--- a/src/runtime/internal/sys/zgoos_android.go
+++ b/src/runtime/internal/sys/zgoos_android.go
@@ -7,6 +7,7 @@ package sys
const GOOS = `android`
const GoosAndroid = 1
+const GoosAix = 0
const GoosDarwin = 0
const GoosDragonfly = 0
const GoosFreebsd = 0
diff --git a/src/runtime/internal/sys/zgoos_darwin.go b/src/runtime/internal/sys/zgoos_darwin.go
index 1c4667f6de..10c0e88e9a 100644
--- a/src/runtime/internal/sys/zgoos_darwin.go
+++ b/src/runtime/internal/sys/zgoos_darwin.go
@@ -7,6 +7,7 @@ package sys
const GOOS = `darwin`
const GoosAndroid = 0
+const GoosAix = 0
const GoosDarwin = 1
const GoosDragonfly = 0
const GoosFreebsd = 0
diff --git a/src/runtime/internal/sys/zgoos_dragonfly.go b/src/runtime/internal/sys/zgoos_dragonfly.go
index 728bf6abe8..5cb47cb84e 100644
--- a/src/runtime/internal/sys/zgoos_dragonfly.go
+++ b/src/runtime/internal/sys/zgoos_dragonfly.go
@@ -7,6 +7,7 @@ package sys
const GOOS = `dragonfly`
const GoosAndroid = 0
+const GoosAix = 0
const GoosDarwin = 0
const GoosDragonfly = 1
const GoosFreebsd = 0
diff --git a/src/runtime/internal/sys/zgoos_freebsd.go b/src/runtime/internal/sys/zgoos_freebsd.go
index a8d659169b..470406ce5f 100644
--- a/src/runtime/internal/sys/zgoos_freebsd.go
+++ b/src/runtime/internal/sys/zgoos_freebsd.go
@@ -7,6 +7,7 @@ package sys
const GOOS = `freebsd`
const GoosAndroid = 0
+const GoosAix = 0
const GoosDarwin = 0
const GoosDragonfly = 0
const GoosFreebsd = 1
diff --git a/src/runtime/internal/sys/zgoos_linux.go b/src/runtime/internal/sys/zgoos_linux.go
index 289400c612..76235b748c 100644
--- a/src/runtime/internal/sys/zgoos_linux.go
+++ b/src/runtime/internal/sys/zgoos_linux.go
@@ -8,6 +8,7 @@ package sys
const GOOS = `linux`
const GoosAndroid = 0
+const GoosAix = 0
const GoosDarwin = 0
const GoosDragonfly = 0
const GoosFreebsd = 0
diff --git a/src/runtime/internal/sys/zgoos_nacl.go b/src/runtime/internal/sys/zgoos_nacl.go
index 3fedb0a2c3..6d28b59667 100644
--- a/src/runtime/internal/sys/zgoos_nacl.go
+++ b/src/runtime/internal/sys/zgoos_nacl.go
@@ -7,6 +7,7 @@ package sys
const GOOS = `nacl`
const GoosAndroid = 0
+const GoosAix = 0
const GoosDarwin = 0
const GoosDragonfly = 0
const GoosFreebsd = 0
diff --git a/src/runtime/internal/sys/zgoos_netbsd.go b/src/runtime/internal/sys/zgoos_netbsd.go
index 3346e3711c..ef8d938ddb 100644
--- a/src/runtime/internal/sys/zgoos_netbsd.go
+++ b/src/runtime/internal/sys/zgoos_netbsd.go
@@ -7,6 +7,7 @@ package sys
const GOOS = `netbsd`
const GoosAndroid = 0
+const GoosAix = 0
const GoosDarwin = 0
const GoosDragonfly = 0
const GoosFreebsd = 0
diff --git a/src/runtime/internal/sys/zgoos_openbsd.go b/src/runtime/internal/sys/zgoos_openbsd.go
index 13c0323249..2e43847396 100644
--- a/src/runtime/internal/sys/zgoos_openbsd.go
+++ b/src/runtime/internal/sys/zgoos_openbsd.go
@@ -7,6 +7,7 @@ package sys
const GOOS = `openbsd`
const GoosAndroid = 0
+const GoosAix = 0
const GoosDarwin = 0
const GoosDragonfly = 0
const GoosFreebsd = 0
diff --git a/src/runtime/internal/sys/zgoos_plan9.go b/src/runtime/internal/sys/zgoos_plan9.go
index 6b2e977b5e..ed598dcaac 100644
--- a/src/runtime/internal/sys/zgoos_plan9.go
+++ b/src/runtime/internal/sys/zgoos_plan9.go
@@ -7,6 +7,7 @@ package sys
const GOOS = `plan9`
const GoosAndroid = 0
+const GoosAix = 0
const GoosDarwin = 0
const GoosDragonfly = 0
const GoosFreebsd = 0
diff --git a/src/runtime/internal/sys/zgoos_solaris.go b/src/runtime/internal/sys/zgoos_solaris.go
index cbf70f079a..fe690df6c2 100644
--- a/src/runtime/internal/sys/zgoos_solaris.go
+++ b/src/runtime/internal/sys/zgoos_solaris.go
@@ -7,6 +7,7 @@ package sys
const GOOS = `solaris`
const GoosAndroid = 0
+const GoosAix = 0
const GoosDarwin = 0
const GoosDragonfly = 0
const GoosFreebsd = 0
diff --git a/src/runtime/internal/sys/zgoos_windows.go b/src/runtime/internal/sys/zgoos_windows.go
index 70839ca793..ea7c43bdf4 100644
--- a/src/runtime/internal/sys/zgoos_windows.go
+++ b/src/runtime/internal/sys/zgoos_windows.go
@@ -7,6 +7,7 @@ package sys
const GOOS = `windows`
const GoosAndroid = 0
+const GoosAix = 0
const GoosDarwin = 0
const GoosDragonfly = 0
const GoosFreebsd = 0
diff --git a/src/runtime/internal/sys/zgoos_zos.go b/src/runtime/internal/sys/zgoos_zos.go
index ecf449f703..d4027cf876 100644
--- a/src/runtime/internal/sys/zgoos_zos.go
+++ b/src/runtime/internal/sys/zgoos_zos.go
@@ -7,6 +7,7 @@ package sys
const GOOS = `zos`
const GoosAndroid = 0
+const GoosAix = 0
const GoosDarwin = 0
const GoosDragonfly = 0
const GoosFreebsd = 0
diff --git a/src/runtime/lock_sema.go b/src/runtime/lock_sema.go
index 6e01d70f75..d21a055685 100644
--- a/src/runtime/lock_sema.go
+++ b/src/runtime/lock_sema.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin nacl netbsd openbsd plan9 solaris windows
+// +build aix darwin nacl netbsd openbsd plan9 solaris windows
package runtime
diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go
index 07e0a67240..c3fe1169dc 100644
--- a/src/runtime/malloc.go
+++ b/src/runtime/malloc.go
@@ -124,8 +124,6 @@ const (
// have the most objects per span.
maxObjsPerSpan = pageSize / 8
- mSpanInUse = _MSpanInUse
-
concurrentSweep = _ConcurrentSweep
_PageSize = 1 << _PageShift
@@ -328,27 +326,27 @@ var physPageSize uintptr
// may use larger alignment, so the caller must be careful to realign the
// memory obtained by sysAlloc.
//
-// SysUnused notifies the operating system that the contents
+// sysUnused notifies the operating system that the contents
// of the memory region are no longer needed and can be reused
// for other purposes.
-// SysUsed notifies the operating system that the contents
+// sysUsed notifies the operating system that the contents
// of the memory region are needed again.
//
-// SysFree returns it unconditionally; this is only used if
+// sysFree returns it unconditionally; this is only used if
// an out-of-memory error has been detected midway through
-// an allocation. It is okay if SysFree is a no-op.
+// an allocation. It is okay if sysFree is a no-op.
//
-// SysReserve reserves address space without allocating memory.
+// sysReserve reserves address space without allocating memory.
// If the pointer passed to it is non-nil, the caller wants the
-// reservation there, but SysReserve can still choose another
+// reservation there, but sysReserve can still choose another
// location if that one is unavailable.
-// NOTE: SysReserve returns OS-aligned memory, but the heap allocator
+// NOTE: sysReserve returns OS-aligned memory, but the heap allocator
// may use larger alignment, so the caller must be careful to realign the
// memory obtained by sysAlloc.
//
-// SysMap maps previously reserved address space for use.
+// sysMap maps previously reserved address space for use.
//
-// SysFault marks a (already sysAlloc'd) region to fault
+// sysFault marks a (already sysAlloc'd) region to fault
// if accessed. Used only for debugging the runtime.
func mallocinit() {
@@ -735,6 +733,9 @@ func nextFreeFast(s *mspan) gclinkptr {
// weight allocation. If it is a heavy weight allocation the caller must
// determine whether a new GC cycle needs to be started or if the GC is active
// whether this goroutine needs to assist the GC.
+//
+// Must run in a non-preemptible context since otherwise the owner of
+// c could change.
func (c *mcache) nextFree(spc spanClass) (v gclinkptr, s *mspan, shouldhelpgc bool) {
s = c.alloc[spc]
shouldhelpgc = false
@@ -745,9 +746,7 @@ func (c *mcache) nextFree(spc spanClass) (v gclinkptr, s *mspan, shouldhelpgc bo
println("runtime: s.allocCount=", s.allocCount, "s.nelems=", s.nelems)
throw("s.allocCount != s.nelems && freeIndex == s.nelems")
}
- systemstack(func() {
- c.refill(spc)
- })
+ c.refill(spc)
shouldhelpgc = true
s = c.alloc[spc]
@@ -993,7 +992,7 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
if shouldhelpgc {
if t := (gcTrigger{kind: gcTriggerHeap}); t.test() {
- gcStart(gcBackgroundMode, t)
+ gcStart(t)
}
}
diff --git a/src/runtime/mbarrier.go b/src/runtime/mbarrier.go
index 5142f4327a..6da8cf2ccb 100644
--- a/src/runtime/mbarrier.go
+++ b/src/runtime/mbarrier.go
@@ -318,6 +318,19 @@ func typedmemclr(typ *_type, ptr unsafe.Pointer) {
memclrNoHeapPointers(ptr, typ.size)
}
+//go:linkname reflect_typedmemclr reflect.typedmemclr
+func reflect_typedmemclr(typ *_type, ptr unsafe.Pointer) {
+ typedmemclr(typ, ptr)
+}
+
+//go:linkname reflect_typedmemclrpartial reflect.typedmemclrpartial
+func reflect_typedmemclrpartial(typ *_type, ptr unsafe.Pointer, off, size uintptr) {
+ if typ.kind&kindNoPointers == 0 {
+ bulkBarrierPreWrite(uintptr(ptr), 0, size)
+ }
+ memclrNoHeapPointers(ptr, size)
+}
+
// memclrHasPointers clears n bytes of typed memory starting at ptr.
// The caller must ensure that the type of the object at ptr has
// pointers, usually by checking typ.kind&kindNoPointers. However, ptr
diff --git a/src/runtime/mbitmap.go b/src/runtime/mbitmap.go
index e217e7695f..87fa027b4e 100644
--- a/src/runtime/mbitmap.go
+++ b/src/runtime/mbitmap.go
@@ -365,7 +365,7 @@ func findObject(p, refBase, refOff uintptr) (base uintptr, s *mspan, objIndex ui
s = spanOf(p)
// If p is a bad pointer, it may not be in s's bounds.
if s == nil || p < s.base() || p >= s.limit || s.state != mSpanInUse {
- if s == nil || s.state == _MSpanManual {
+ if s == nil || s.state == mSpanManual {
// If s is nil, the virtual address has never been part of the heap.
// This pointer may be to some mmap'd region, so we allow it.
// Pointers into stacks are also ok, the runtime manages these explicitly.
@@ -611,7 +611,7 @@ func bulkBarrierPreWrite(dst, src, size uintptr) {
}
}
return
- } else if s.state != _MSpanInUse || dst < s.base() || s.limit <= dst {
+ } else if s.state != mSpanInUse || dst < s.base() || s.limit <= dst {
// dst was heap memory at some point, but isn't now.
// It can't be a global. It must be either our stack,
// or in the case of direct channel sends, it could be
@@ -1911,6 +1911,20 @@ Run:
return totalBits
}
+// materializeGCProg allocates space for the (1-bit) pointer bitmask
+// for an object of size ptrdata. Then it fills that space with the
+// pointer bitmask specified by the program prog.
+// The bitmask starts at s.startAddr.
+// The result must be deallocated with dematerializeGCProg.
+func materializeGCProg(ptrdata uintptr, prog *byte) *mspan {
+ s := mheap_.allocManual((ptrdata/(8*sys.PtrSize)+pageSize-1)/pageSize, &memstats.gc_sys)
+ runGCProg(addb(prog, 4), nil, (*byte)(unsafe.Pointer(s.startAddr)), 1)
+ return s
+}
+func dematerializeGCProg(s *mspan) {
+ mheap_.freeManual(s, &memstats.gc_sys)
+}
+
func dumpGCProg(p *byte) {
nptr := 0
for {
@@ -1980,7 +1994,9 @@ func reflect_gcbits(x interface{}) []byte {
return ret
}
-// Returns GC type info for object p for testing.
+// Returns GC type info for the pointer stored in ep for testing.
+// If ep points to the stack, only static live information will be returned
+// (i.e. not for objects which are only dynamically live stack objects).
func getgcmask(ep interface{}) (mask []byte) {
e := *efaceOf(&ep)
p := e.data
@@ -2037,7 +2053,7 @@ func getgcmask(ep interface{}) (mask []byte) {
_g_ := getg()
gentraceback(_g_.m.curg.sched.pc, _g_.m.curg.sched.sp, 0, _g_.m.curg, 0, nil, 1000, getgcmaskcb, noescape(unsafe.Pointer(&frame)), 0)
if frame.fn.valid() {
- locals, _ := getStackMap(&frame, nil, false)
+ locals, _, _ := getStackMap(&frame, nil, false)
if locals.n == 0 {
return
}
diff --git a/src/runtime/mcache.go b/src/runtime/mcache.go
index d0b007f915..e20e92cdf4 100644
--- a/src/runtime/mcache.go
+++ b/src/runtime/mcache.go
@@ -4,7 +4,10 @@
package runtime
-import "unsafe"
+import (
+ "runtime/internal/atomic"
+ "unsafe"
+)
// Per-thread (in Go, per-P) cache for small objects.
// No locking needed because it is per-thread (per-P).
@@ -42,6 +45,12 @@ type mcache struct {
local_largefree uintptr // bytes freed for large objects (>maxsmallsize)
local_nlargefree uintptr // number of frees for large objects (>maxsmallsize)
local_nsmallfree [_NumSizeClasses]uintptr // number of frees for small objects (<=maxsmallsize)
+
+ // flushGen indicates the sweepgen during which this mcache
+ // was last flushed. If flushGen != mheap_.sweepgen, the spans
+ // in this mcache are stale and need to the flushed so they
+ // can be swept. This is done in acquirep.
+ flushGen uint32
}
// A gclink is a node in a linked list of blocks, like mlink,
@@ -76,6 +85,7 @@ var emptymspan mspan
func allocmcache() *mcache {
lock(&mheap_.lock)
c := (*mcache)(mheap_.cachealloc.alloc())
+ c.flushGen = mheap_.sweepgen
unlock(&mheap_.lock)
for i := range c.alloc {
c.alloc[i] = &emptymspan
@@ -101,21 +111,24 @@ func freemcache(c *mcache) {
})
}
-// Gets a span that has a free object in it and assigns it
-// to be the cached span for the given sizeclass. Returns this span.
+// refill acquires a new span of span class spc for c. This span will
+// have at least one free object. The current span in c must be full.
+//
+// Must run in a non-preemptible context since otherwise the owner of
+// c could change.
func (c *mcache) refill(spc spanClass) {
- _g_ := getg()
-
- _g_.m.locks++
// Return the current cached span to the central lists.
s := c.alloc[spc]
if uintptr(s.allocCount) != s.nelems {
throw("refill of span with free space remaining")
}
-
if s != &emptymspan {
- s.incache = false
+ // Mark this span as no longer cached.
+ if s.sweepgen != mheap_.sweepgen+3 {
+ throw("bad sweepgen in refill")
+ }
+ atomic.Store(&s.sweepgen, mheap_.sweepgen)
}
// Get a new cached span from the central lists.
@@ -128,8 +141,11 @@ func (c *mcache) refill(spc spanClass) {
throw("span has no free space")
}
+ // Indicate that this span is cached and prevent asynchronous
+ // sweeping in the next sweep phase.
+ s.sweepgen = mheap_.sweepgen + 3
+
c.alloc[spc] = s
- _g_.m.locks--
}
func (c *mcache) releaseAll() {
@@ -144,3 +160,26 @@ func (c *mcache) releaseAll() {
c.tiny = 0
c.tinyoffset = 0
}
+
+// prepareForSweep flushes c if the system has entered a new sweep phase
+// since c was populated. This must happen between the sweep phase
+// starting and the first allocation from c.
+func (c *mcache) prepareForSweep() {
+ // Alternatively, instead of making sure we do this on every P
+ // between starting the world and allocating on that P, we
+ // could leave allocate-black on, allow allocation to continue
+ // as usual, use a ragged barrier at the beginning of sweep to
+ // ensure all cached spans are swept, and then disable
+ // allocate-black. However, with this approach it's difficult
+ // to avoid spilling mark bits into the *next* GC cycle.
+ sg := mheap_.sweepgen
+ if c.flushGen == sg {
+ return
+ } else if c.flushGen != sg-2 {
+ println("bad flushGen", c.flushGen, "in prepareForSweep; sweepgen", sg)
+ throw("bad flushGen")
+ }
+ c.releaseAll()
+ stackcache_clear(c)
+ atomic.Store(&c.flushGen, mheap_.sweepgen) // Synchronizes with gcStart
+}
diff --git a/src/runtime/mcentral.go b/src/runtime/mcentral.go
index c1e0b472bc..9ca8e5d222 100644
--- a/src/runtime/mcentral.go
+++ b/src/runtime/mcentral.go
@@ -135,7 +135,6 @@ havespan:
// heap_live changed.
gcController.revise()
}
- s.incache = true
freeByteBase := s.freeindex &^ (64 - 1)
whichByte := freeByteBase / 8
// Init alloc bits cache.
@@ -150,28 +149,54 @@ havespan:
// Return span from an MCache.
func (c *mcentral) uncacheSpan(s *mspan) {
- lock(&c.lock)
-
- s.incache = false
-
if s.allocCount == 0 {
throw("uncaching span but s.allocCount == 0")
}
cap := int32((s.npages << _PageShift) / s.elemsize)
n := cap - int32(s.allocCount)
+
+ // cacheSpan updated alloc assuming all objects on s were
+ // going to be allocated. Adjust for any that weren't. We must
+ // do this before potentially sweeping the span.
if n > 0 {
+ atomic.Xadd64(&c.nmalloc, -int64(n))
+ }
+
+ sg := mheap_.sweepgen
+ stale := s.sweepgen == sg+1
+ if stale {
+ // Span was cached before sweep began. It's our
+ // responsibility to sweep it.
+ //
+ // Set sweepgen to indicate it's not cached but needs
+ // sweeping. sweep will set s.sweepgen to indicate s
+ // is swept.
+ s.sweepgen = sg - 1
+ s.sweep(true)
+ // sweep may have freed objects, so recompute n.
+ n = cap - int32(s.allocCount)
+ } else {
+ // Indicate that s is no longer cached.
+ s.sweepgen = sg
+ }
+
+ if n > 0 {
+ lock(&c.lock)
c.empty.remove(s)
c.nonempty.insert(s)
- // mCentral_CacheSpan conservatively counted
- // unallocated slots in heap_live. Undo this.
- atomic.Xadd64(&memstats.heap_live, -int64(n)*int64(s.elemsize))
- // cacheSpan updated alloc assuming all objects on s
- // were going to be allocated. Adjust for any that
- // weren't.
- atomic.Xadd64(&c.nmalloc, -int64(n))
+ if !stale {
+ // mCentral_CacheSpan conservatively counted
+ // unallocated slots in heap_live. Undo this.
+ //
+ // If this span was cached before sweep, then
+ // heap_live was totally recomputed since
+ // caching this span, so we don't do this for
+ // stale spans.
+ atomic.Xadd64(&memstats.heap_live, -int64(n)*int64(s.elemsize))
+ }
+ unlock(&c.lock)
}
- unlock(&c.lock)
}
// freeSpan updates c and s after sweeping s.
@@ -183,13 +208,13 @@ func (c *mcentral) uncacheSpan(s *mspan) {
// If preserve=true, it does not move s (the caller
// must take care of it).
func (c *mcentral) freeSpan(s *mspan, preserve bool, wasempty bool) bool {
- if s.incache {
+ if sg := mheap_.sweepgen; s.sweepgen == sg+1 || s.sweepgen == sg+3 {
throw("freeSpan given cached span")
}
s.needzero = 1
if preserve {
- // preserve is set only when called from MCentral_CacheSpan above,
+ // preserve is set only when called from (un)cacheSpan above,
// the span must be in the empty list.
if !s.inList() {
throw("can't preserve unlinked span")
diff --git a/src/runtime/mem_darwin.go b/src/runtime/mem_aix.go
index 75c59f9cdd..f11f0aba52 100644
--- a/src/runtime/mem_darwin.go
+++ b/src/runtime/mem_aix.go
@@ -1,26 +1,36 @@
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package runtime
-import "unsafe"
+import (
+ "unsafe"
+)
-// Don't split the stack as this function may be invoked without a valid G,
-// which prevents us from allocating more stack.
+// Don't split the stack as this method may be invoked without a valid G, which
+// prevents us from allocating more stack.
//go:nosplit
func sysAlloc(n uintptr, sysStat *uint64) unsafe.Pointer {
- v, err := mmap(nil, n, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_PRIVATE, -1, 0)
+ p, err := mmap(nil, n, _PROT_READ|_PROT_WRITE, _MAP_ANONYMOUS|_MAP_PRIVATE, -1, 0)
if err != 0 {
+ if err == _EACCES {
+ print("runtime: mmap: access denied\n")
+ exit(2)
+ }
+ if err == _EAGAIN {
+ print("runtime: mmap: too much locked memory (check 'ulimit -l').\n")
+ exit(2)
+ }
+ //println("sysAlloc failed: ", err)
return nil
}
mSysStatInc(sysStat, n)
- return v
+ return p
}
func sysUnused(v unsafe.Pointer, n uintptr) {
- // Linux's MADV_DONTNEED is like BSD's MADV_FREE.
- madvise(v, n, _MADV_FREE)
+ madvise(v, n, _MADV_DONTNEED)
}
func sysUsed(v unsafe.Pointer, n uintptr) {
@@ -32,27 +42,29 @@ func sysUsed(v unsafe.Pointer, n uintptr) {
func sysFree(v unsafe.Pointer, n uintptr, sysStat *uint64) {
mSysStatDec(sysStat, n)
munmap(v, n)
+
}
func sysFault(v unsafe.Pointer, n uintptr) {
- mmap(v, n, _PROT_NONE, _MAP_ANON|_MAP_PRIVATE|_MAP_FIXED, -1, 0)
+ mmap(v, n, _PROT_NONE, _MAP_ANONYMOUS|_MAP_PRIVATE|_MAP_FIXED, -1, 0)
}
func sysReserve(v unsafe.Pointer, n uintptr) unsafe.Pointer {
- p, err := mmap(v, n, _PROT_NONE, _MAP_ANON|_MAP_PRIVATE, -1, 0)
+ p, err := mmap(v, n, _PROT_NONE, _MAP_ANONYMOUS|_MAP_PRIVATE, -1, 0)
if err != 0 {
return nil
}
return p
}
-const (
- _ENOMEM = 12
-)
-
func sysMap(v unsafe.Pointer, n uintptr, sysStat *uint64) {
mSysStatInc(sysStat, n)
- p, err := mmap(v, n, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_FIXED|_MAP_PRIVATE, -1, 0)
+
+ // AIX does not allow mapping a range that is already mapped.
+ // So always unmap first even if it is already unmapped.
+ munmap(v, n)
+ p, err := mmap(v, n, _PROT_READ|_PROT_WRITE, _MAP_ANONYMOUS|_MAP_FIXED|_MAP_PRIVATE, -1, 0)
+
if err == _ENOMEM {
throw("runtime: out of memory")
}
diff --git a/src/runtime/mem_bsd.go b/src/runtime/mem_bsd.go
index cc70e806ea..13065b61d4 100644
--- a/src/runtime/mem_bsd.go
+++ b/src/runtime/mem_bsd.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build dragonfly freebsd nacl netbsd openbsd solaris
+// +build darwin dragonfly freebsd nacl netbsd openbsd solaris
package runtime
diff --git a/src/runtime/mem_linux.go b/src/runtime/mem_linux.go
index 7aa48170a1..845f72ded2 100644
--- a/src/runtime/mem_linux.go
+++ b/src/runtime/mem_linux.go
@@ -5,6 +5,7 @@
package runtime
import (
+ "runtime/internal/atomic"
"runtime/internal/sys"
"unsafe"
)
@@ -34,10 +35,12 @@ func sysAlloc(n uintptr, sysStat *uint64) unsafe.Pointer {
return p
}
+var adviseUnused = uint32(_MADV_FREE)
+
func sysUnused(v unsafe.Pointer, n uintptr) {
// By default, Linux's "transparent huge page" support will
// merge pages into a huge page if there's even a single
- // present regular page, undoing the effects of the DONTNEED
+ // present regular page, undoing the effects of madvise(adviseUnused)
// below. On amd64, that means khugepaged can turn a single
// 4KB page to 2MB, bloating the process's RSS by as much as
// 512X. (See issue #8832 and Linux kernel bug
@@ -102,7 +105,13 @@ func sysUnused(v unsafe.Pointer, n uintptr) {
throw("unaligned sysUnused")
}
- madvise(v, n, _MADV_DONTNEED)
+ advise := atomic.Load(&adviseUnused)
+ if errno := madvise(v, n, int32(advise)); advise == _MADV_FREE && errno != 0 {
+ // MADV_FREE was added in Linux 4.5. Fall back to MADV_DONTNEED if it is
+ // not supported.
+ atomic.Store(&adviseUnused, _MADV_DONTNEED)
+ madvise(v, n, _MADV_DONTNEED)
+ }
}
func sysUsed(v unsafe.Pointer, n uintptr) {
diff --git a/src/runtime/memmove_amd64p32.s b/src/runtime/memmove_amd64p32.s
index 8e9fdd14c5..114077311c 100644
--- a/src/runtime/memmove_amd64p32.s
+++ b/src/runtime/memmove_amd64p32.s
@@ -34,7 +34,7 @@ back:
ADDL BX, DI
ADDL BX, SI
STD
-
+
MOVL BX, CX
SHRL $2, CX
ANDL $3, BX
diff --git a/src/runtime/memmove_arm.s b/src/runtime/memmove_arm.s
index 324b21bf7a..8352fb7860 100644
--- a/src/runtime/memmove_arm.s
+++ b/src/runtime/memmove_arm.s
@@ -138,7 +138,7 @@ _f32loop:
CMP TMP, TS
BHS _f4tail
- MOVM.IA.W (FROM), [R1-R8]
+ MOVM.IA.W (FROM), [R1-R8]
MOVM.IA.W [R1-R8], (TS)
B _f32loop
diff --git a/src/runtime/memmove_plan9_386.s b/src/runtime/memmove_plan9_386.s
index 7ff01940a2..65dec93f6b 100644
--- a/src/runtime/memmove_plan9_386.s
+++ b/src/runtime/memmove_plan9_386.s
@@ -56,7 +56,7 @@ tail:
/*
* forward copy loop
*/
-forward:
+forward:
MOVL BX, CX
SHRL $2, CX
ANDL $3, BX
diff --git a/src/runtime/memmove_plan9_amd64.s b/src/runtime/memmove_plan9_amd64.s
index f18b59f3d2..b729c7c0e7 100644
--- a/src/runtime/memmove_plan9_amd64.s
+++ b/src/runtime/memmove_plan9_amd64.s
@@ -73,7 +73,7 @@ back:
ADDQ BX, CX
CMPQ CX, DI
JLS forward
-
+
/*
* whole thing backwards has
* adjusted addresses
diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go
index c95b5ed37f..9dfee5a4dc 100644
--- a/src/runtime/mgc.go
+++ b/src/runtime/mgc.go
@@ -28,8 +28,7 @@
// b. Sweep any unswept spans. There will only be unswept spans if
// this GC cycle was forced before the expected time.
//
-// 2. GC performs the "mark 1" sub-phase. In this sub-phase, Ps are
-// allowed to locally cache parts of the work queue.
+// 2. GC performs the mark phase.
//
// a. Prepare for the mark phase by setting gcphase to _GCmark
// (from _GCoff), enabling the write barrier, enabling mutator
@@ -54,28 +53,21 @@
// object to black and shading all pointers found in the object
// (which in turn may add those pointers to the work queue).
//
-// 3. Once the global work queue is empty (but local work queue caches
-// may still contain work), GC performs the "mark 2" sub-phase.
+// e. Because GC work is spread across local caches, GC uses a
+// distributed termination algorithm to detect when there are no
+// more root marking jobs or grey objects (see gcMarkDone). At this
+// point, GC transitions to mark termination.
//
-// a. GC stops all workers, disables local work queue caches,
-// flushes each P's local work queue cache to the global work queue
-// cache, and reenables workers.
-//
-// b. GC again drains the work queue, as in 2d above.
-//
-// 4. Once the work queue is empty, GC performs mark termination.
+// 3. GC performs mark termination.
//
// a. Stop the world.
//
// b. Set gcphase to _GCmarktermination, and disable workers and
// assists.
//
-// c. Drain any remaining work from the work queue (typically there
-// will be none).
+// c. Perform housekeeping like flushing mcaches.
//
-// d. Perform other housekeeping like flushing mcaches.
-//
-// 5. GC performs the sweep phase.
+// 4. GC performs the sweep phase.
//
// a. Prepare for the sweep phase by setting gcphase to _GCoff,
// setting up sweep state and disabling the write barrier.
@@ -86,7 +78,7 @@
// c. GC does concurrent sweeping in the background and in response
// to allocation. See description below.
//
-// 6. When sufficient allocation has taken place, replay the sequence
+// 5. When sufficient allocation has taken place, replay the sequence
// starting with 1 above. See discussion of GC rate below.
// Concurrent sweep.
@@ -261,21 +253,6 @@ var writeBarrier struct {
// gcphase == _GCmark.
var gcBlackenEnabled uint32
-// gcBlackenPromptly indicates that optimizations that may
-// hide work from the global work queue should be disabled.
-//
-// If gcBlackenPromptly is true, per-P gcWork caches should
-// be flushed immediately and new objects should be allocated black.
-//
-// There is a tension between allocating objects white and
-// allocating them black. If white and the objects die before being
-// marked they can be collected during this GC cycle. On the other
-// hand allocating them black will reduce _GCmarktermination latency
-// since more work is done in the mark phase. This tension is resolved
-// by allocating white until the mark phase is approaching its end and
-// then allocating black for the remainder of the mark phase.
-var gcBlackenPromptly bool
-
const (
_GCoff = iota // GC not running; sweeping in background, write barrier disabled
_GCmark // GC marking roots and workbufs: allocate black, write barrier ENABLED
@@ -478,6 +455,12 @@ func (c *gcControllerState) startCycle() {
c.fractionalUtilizationGoal = 0
}
+ // In STW mode, we just want dedicated workers.
+ if debug.gcstoptheworld > 0 {
+ c.dedicatedMarkWorkersNeeded = int64(gomaxprocs)
+ c.fractionalUtilizationGoal = 0
+ }
+
// Clear per-P state
for _, p := range allp {
p.gcAssistTime = 0
@@ -955,32 +938,15 @@ var work struct {
markrootNext uint32 // next markroot job
markrootJobs uint32 // number of markroot jobs
- nproc uint32
- tstart int64
- nwait uint32
- ndone uint32
- alldone note
-
- // helperDrainBlock indicates that GC mark termination helpers
- // should pass gcDrainBlock to gcDrain to block in the
- // getfull() barrier. Otherwise, they should pass gcDrainNoBlock.
- //
- // TODO: This is a temporary fallback to work around races
- // that cause early mark termination.
- helperDrainBlock bool
+ nproc uint32
+ tstart int64
+ nwait uint32
+ ndone uint32
// Number of roots of various root types. Set by gcMarkRootPrepare.
nFlushCacheRoots int
nDataRoots, nBSSRoots, nSpanRoots, nStackRoots int
- // markrootDone indicates that roots have been marked at least
- // once during the current GC cycle. This is checked by root
- // marking operations that have to happen only during the
- // first root marking pass, whether that's during the
- // concurrent mark phase in current GC or mark termination in
- // STW GC.
- markrootDone bool
-
// Each type of GC state transition is protected by a lock.
// Since multiple threads can simultaneously detect the state
// transition condition, any thread that detects a transition
@@ -996,8 +962,7 @@ var work struct {
// startSema protects the transition from "off" to mark or
// mark termination.
startSema uint32
- // markDoneSema protects transitions from mark 1 to mark 2 and
- // from mark 2 to mark termination.
+ // markDoneSema protects transitions from mark to mark termination.
markDoneSema uint32
bgMarkReady note // signal background mark worker has started
@@ -1087,7 +1052,7 @@ func GC() {
// We're now in sweep N or later. Trigger GC cycle N+1, which
// will first finish sweep N if necessary and then enter sweep
// termination N+1.
- gcStart(gcBackgroundMode, gcTrigger{kind: gcTriggerCycle, n: n + 1})
+ gcStart(gcTrigger{kind: gcTriggerCycle, n: n + 1})
// Wait for mark termination N+1 to complete.
gcWaitOnMark(n + 1)
@@ -1225,13 +1190,13 @@ func (t gcTrigger) test() bool {
return true
}
-// gcStart transitions the GC from _GCoff to _GCmark (if
-// !mode.stwMark) or _GCmarktermination (if mode.stwMark) by
-// performing sweep termination and GC initialization.
+// gcStart starts the GC. It transitions from _GCoff to _GCmark (if
+// debug.gcstoptheworld == 0) or performs all of GC (if
+// debug.gcstoptheworld != 0).
//
// This may return without performing this transition in some cases,
// such as when called on a system stack or with locks held.
-func gcStart(mode gcMode, trigger gcTrigger) {
+func gcStart(trigger gcTrigger) {
// Since this is called from malloc and malloc is called in
// the guts of a number of libraries that might be holding
// locks, don't attempt to start GC in non-preemptible or
@@ -1274,12 +1239,11 @@ func gcStart(mode gcMode, trigger gcTrigger) {
// We do this after re-checking the transition condition so
// that multiple goroutines that detect the heap trigger don't
// start multiple STW GCs.
- if mode == gcBackgroundMode {
- if debug.gcstoptheworld == 1 {
- mode = gcForceMode
- } else if debug.gcstoptheworld == 2 {
- mode = gcForceBlockMode
- }
+ mode := gcBackgroundMode
+ if debug.gcstoptheworld == 1 {
+ mode = gcForceMode
+ } else if debug.gcstoptheworld == 2 {
+ mode = gcForceBlockMode
}
// Ok, we're doing it! Stop everybody else
@@ -1289,10 +1253,16 @@ func gcStart(mode gcMode, trigger gcTrigger) {
traceGCStart()
}
- if mode == gcBackgroundMode {
- gcBgMarkStartWorkers()
+ // Check that all Ps have finished deferred mcache flushes.
+ for _, p := range allp {
+ if fg := atomic.Load(&p.mcache.flushGen); fg != mheap_.sweepgen {
+ println("runtime: p", p.id, "flushGen", fg, "!= sweepgen", mheap_.sweepgen)
+ throw("p mcache not flushed")
+ }
}
+ gcBgMarkStartWorkers()
+
gcResetMarkState()
work.stwprocs, work.maxprocs = gomaxprocs, gomaxprocs
@@ -1321,199 +1291,192 @@ func gcStart(mode gcMode, trigger gcTrigger) {
clearpools()
work.cycles++
- if mode == gcBackgroundMode { // Do as much work concurrently as possible
- gcController.startCycle()
- work.heapGoal = memstats.next_gc
- // Enter concurrent mark phase and enable
- // write barriers.
- //
- // Because the world is stopped, all Ps will
- // observe that write barriers are enabled by
- // the time we start the world and begin
- // scanning.
- //
- // Write barriers must be enabled before assists are
- // enabled because they must be enabled before
- // any non-leaf heap objects are marked. Since
- // allocations are blocked until assists can
- // happen, we want enable assists as early as
- // possible.
- setGCPhase(_GCmark)
+ gcController.startCycle()
+ work.heapGoal = memstats.next_gc
- gcBgMarkPrepare() // Must happen before assist enable.
- gcMarkRootPrepare()
+ // In STW mode, disable scheduling of user Gs. This may also
+ // disable scheduling of this goroutine, so it may block as
+ // soon as we start the world again.
+ if mode != gcBackgroundMode {
+ schedEnableUser(false)
+ }
- // Mark all active tinyalloc blocks. Since we're
- // allocating from these, they need to be black like
- // other allocations. The alternative is to blacken
- // the tiny block on every allocation from it, which
- // would slow down the tiny allocator.
- gcMarkTinyAllocs()
+ // Enter concurrent mark phase and enable
+ // write barriers.
+ //
+ // Because the world is stopped, all Ps will
+ // observe that write barriers are enabled by
+ // the time we start the world and begin
+ // scanning.
+ //
+ // Write barriers must be enabled before assists are
+ // enabled because they must be enabled before
+ // any non-leaf heap objects are marked. Since
+ // allocations are blocked until assists can
+ // happen, we want enable assists as early as
+ // possible.
+ setGCPhase(_GCmark)
- // At this point all Ps have enabled the write
- // barrier, thus maintaining the no white to
- // black invariant. Enable mutator assists to
- // put back-pressure on fast allocating
- // mutators.
- atomic.Store(&gcBlackenEnabled, 1)
+ gcBgMarkPrepare() // Must happen before assist enable.
+ gcMarkRootPrepare()
- // Assists and workers can start the moment we start
- // the world.
- gcController.markStartTime = now
+ // Mark all active tinyalloc blocks. Since we're
+ // allocating from these, they need to be black like
+ // other allocations. The alternative is to blacken
+ // the tiny block on every allocation from it, which
+ // would slow down the tiny allocator.
+ gcMarkTinyAllocs()
- // Concurrent mark.
- systemstack(func() {
- now = startTheWorldWithSema(trace.enabled)
- })
+ // At this point all Ps have enabled the write
+ // barrier, thus maintaining the no white to
+ // black invariant. Enable mutator assists to
+ // put back-pressure on fast allocating
+ // mutators.
+ atomic.Store(&gcBlackenEnabled, 1)
+
+ // Assists and workers can start the moment we start
+ // the world.
+ gcController.markStartTime = now
+
+ // Concurrent mark.
+ systemstack(func() {
+ now = startTheWorldWithSema(trace.enabled)
work.pauseNS += now - work.pauseStart
work.tMark = now
- } else {
- if trace.enabled {
- // Switch to mark termination STW.
- traceGCSTWDone()
- traceGCSTWStart(0)
- }
- t := nanotime()
- work.tMark, work.tMarkTerm = t, t
- work.heapGoal = work.heap0
-
- // Perform mark termination. This will restart the world.
- gcMarkTermination(memstats.triggerRatio)
+ })
+ // In STW mode, we could block the instant systemstack
+ // returns, so don't do anything important here. Make sure we
+ // block rather than returning to user code.
+ if mode != gcBackgroundMode {
+ Gosched()
}
semrelease(&work.startSema)
}
-// gcMarkDone transitions the GC from mark 1 to mark 2 and from mark 2
-// to mark termination.
+// gcMarkDoneFlushed counts the number of P's with flushed work.
//
-// This should be called when all mark work has been drained. In mark
-// 1, this includes all root marking jobs, global work buffers, and
-// active work buffers in assists and background workers; however,
-// work may still be cached in per-P work buffers. In mark 2, per-P
-// caches are disabled.
+// Ideally this would be a captured local in gcMarkDone, but forEachP
+// escapes its callback closure, so it can't capture anything.
+//
+// This is protected by markDoneSema.
+var gcMarkDoneFlushed uint32
+
+// gcMarkDone transitions the GC from mark to mark termination if all
+// reachable objects have been marked (that is, there are no grey
+// objects and can be no more in the future). Otherwise, it flushes
+// all local work to the global queues where it can be discovered by
+// other workers.
+//
+// This should be called when all local mark work has been drained and
+// there are no remaining workers. Specifically, when
+//
+// work.nwait == work.nproc && !gcMarkWorkAvailable(p)
//
// The calling context must be preemptible.
//
-// Note that it is explicitly okay to have write barriers in this
-// function because completion of concurrent mark is best-effort
-// anyway. Any work created by write barriers here will be cleaned up
-// by mark termination.
+// Flushing local work is important because idle Ps may have local
+// work queued. This is the only way to make that work visible and
+// drive GC to completion.
+//
+// It is explicitly okay to have write barriers in this function. If
+// it does transition to mark termination, then all reachable objects
+// have been marked, so the write barrier cannot shade any more
+// objects.
func gcMarkDone() {
-top:
+ // Ensure only one thread is running the ragged barrier at a
+ // time.
semacquire(&work.markDoneSema)
+top:
// Re-check transition condition under transition lock.
+ //
+ // It's critical that this checks the global work queues are
+ // empty before performing the ragged barrier. Otherwise,
+ // there could be global work that a P could take after the P
+ // has passed the ragged barrier.
if !(gcphase == _GCmark && work.nwait == work.nproc && !gcMarkWorkAvailable(nil)) {
semrelease(&work.markDoneSema)
return
}
- // Disallow starting new workers so that any remaining workers
- // in the current mark phase will drain out.
- //
- // TODO(austin): Should dedicated workers keep an eye on this
- // and exit gcDrain promptly?
- atomic.Xaddint64(&gcController.dedicatedMarkWorkersNeeded, -0xffffffff)
- prevFractionalGoal := gcController.fractionalUtilizationGoal
- gcController.fractionalUtilizationGoal = 0
-
- if !gcBlackenPromptly {
- // Transition from mark 1 to mark 2.
- //
- // The global work list is empty, but there can still be work
- // sitting in the per-P work caches.
- // Flush and disable work caches.
-
- // Disallow caching workbufs and indicate that we're in mark 2.
- gcBlackenPromptly = true
-
- // Prevent completion of mark 2 until we've flushed
- // cached workbufs.
- atomic.Xadd(&work.nwait, -1)
-
- // GC is set up for mark 2. Let Gs blocked on the
- // transition lock go while we flush caches.
- semrelease(&work.markDoneSema)
-
- systemstack(func() {
- // Flush all currently cached workbufs and
- // ensure all Ps see gcBlackenPromptly. This
- // also blocks until any remaining mark 1
- // workers have exited their loop so we can
- // start new mark 2 workers.
- forEachP(func(_p_ *p) {
- wbBufFlush1(_p_)
- _p_.gcw.dispose()
- })
+ // Flush all local buffers and collect flushedWork flags.
+ gcMarkDoneFlushed = 0
+ systemstack(func() {
+ forEachP(func(_p_ *p) {
+ // Flush the write barrier buffer, since this may add
+ // work to the gcWork.
+ wbBufFlush1(_p_)
+ // Flush the gcWork, since this may create global work
+ // and set the flushedWork flag.
+ //
+ // TODO(austin): Break up these workbufs to
+ // better distribute work.
+ _p_.gcw.dispose()
+ // Collect the flushedWork flag.
+ if _p_.gcw.flushedWork {
+ atomic.Xadd(&gcMarkDoneFlushed, 1)
+ _p_.gcw.flushedWork = false
+ }
})
+ })
- // Check that roots are marked. We should be able to
- // do this before the forEachP, but based on issue
- // #16083 there may be a (harmless) race where we can
- // enter mark 2 while some workers are still scanning
- // stacks. The forEachP ensures these scans are done.
- //
- // TODO(austin): Figure out the race and fix this
- // properly.
- gcMarkRootCheck()
-
- // Now we can start up mark 2 workers.
- atomic.Xaddint64(&gcController.dedicatedMarkWorkersNeeded, 0xffffffff)
- gcController.fractionalUtilizationGoal = prevFractionalGoal
+ if gcMarkDoneFlushed != 0 {
+ // More grey objects were discovered since the
+ // previous termination check, so there may be more
+ // work to do. Keep going. It's possible the
+ // transition condition became true again during the
+ // ragged barrier, so re-check it.
+ goto top
+ }
- incnwait := atomic.Xadd(&work.nwait, +1)
- if incnwait == work.nproc && !gcMarkWorkAvailable(nil) {
- // This loop will make progress because
- // gcBlackenPromptly is now true, so it won't
- // take this same "if" branch.
- goto top
- }
- } else {
- // Transition to mark termination.
- now := nanotime()
- work.tMarkTerm = now
- work.pauseStart = now
- getg().m.preemptoff = "gcing"
- if trace.enabled {
- traceGCSTWStart(0)
- }
- systemstack(stopTheWorldWithSema)
- // The gcphase is _GCmark, it will transition to _GCmarktermination
- // below. The important thing is that the wb remains active until
- // all marking is complete. This includes writes made by the GC.
+ // There was no global work, no local work, and no Ps
+ // communicated work since we took markDoneSema. Therefore
+ // there are no grey objects and no more objects can be
+ // shaded. Transition to mark termination.
+ now := nanotime()
+ work.tMarkTerm = now
+ work.pauseStart = now
+ getg().m.preemptoff = "gcing"
+ if trace.enabled {
+ traceGCSTWStart(0)
+ }
+ systemstack(stopTheWorldWithSema)
+ // The gcphase is _GCmark, it will transition to _GCmarktermination
+ // below. The important thing is that the wb remains active until
+ // all marking is complete. This includes writes made by the GC.
- // Record that one root marking pass has completed.
- work.markrootDone = true
+ // Disable assists and background workers. We must do
+ // this before waking blocked assists.
+ atomic.Store(&gcBlackenEnabled, 0)
- // Disable assists and background workers. We must do
- // this before waking blocked assists.
- atomic.Store(&gcBlackenEnabled, 0)
+ // Wake all blocked assists. These will run when we
+ // start the world again.
+ gcWakeAllAssists()
- // Wake all blocked assists. These will run when we
- // start the world again.
- gcWakeAllAssists()
+ // Likewise, release the transition lock. Blocked
+ // workers and assists will run when we start the
+ // world again.
+ semrelease(&work.markDoneSema)
- // Likewise, release the transition lock. Blocked
- // workers and assists will run when we start the
- // world again.
- semrelease(&work.markDoneSema)
+ // In STW mode, re-enable user goroutines. These will be
+ // queued to run after we start the world.
+ schedEnableUser(true)
- // endCycle depends on all gcWork cache stats being
- // flushed. This is ensured by mark 2.
- nextTriggerRatio := gcController.endCycle()
+ // endCycle depends on all gcWork cache stats being flushed.
+ // The termination algorithm above ensured that up to
+ // allocations since the ragged barrier.
+ nextTriggerRatio := gcController.endCycle()
- // Perform mark termination. This will restart the world.
- gcMarkTermination(nextTriggerRatio)
- }
+ // Perform mark termination. This will restart the world.
+ gcMarkTermination(nextTriggerRatio)
}
func gcMarkTermination(nextTriggerRatio float64) {
// World is stopped.
// Start marktermination which includes enabling the write barrier.
atomic.Store(&gcBlackenEnabled, 0)
- gcBlackenPromptly = false
setGCPhase(_GCmarktermination)
work.heap1 = memstats.heap_live
@@ -1546,35 +1509,22 @@ func gcMarkTermination(nextTriggerRatio float64) {
systemstack(func() {
work.heap2 = work.bytesMarked
if debug.gccheckmark > 0 {
- // Run a full stop-the-world mark using checkmark bits,
- // to check that we didn't forget to mark anything during
- // the concurrent mark process.
+ // Run a full non-parallel, stop-the-world
+ // mark using checkmark bits, to check that we
+ // didn't forget to mark anything during the
+ // concurrent mark process.
gcResetMarkState()
initCheckmarks()
- gcMark(startTime)
+ gcw := &getg().m.p.ptr().gcw
+ gcDrain(gcw, 0)
+ wbBufFlush1(getg().m.p.ptr())
+ gcw.dispose()
clearCheckmarks()
}
// marking is complete so we can turn the write barrier off
setGCPhase(_GCoff)
gcSweep(work.mode)
-
- if debug.gctrace > 1 {
- startTime = nanotime()
- // The g stacks have been scanned so
- // they have gcscanvalid==true and gcworkdone==true.
- // Reset these so that all stacks will be rescanned.
- gcResetMarkState()
- finishsweep_m()
-
- // Still in STW but gcphase is _GCoff, reset to _GCmarktermination
- // At this point all objects will be found during the gcMark which
- // does a complete STW mark and object scan.
- setGCPhase(_GCmarktermination)
- gcMark(startTime)
- setGCPhase(_GCoff) // marking is done, turn off wb.
- gcSweep(work.mode)
- }
})
_g_.m.traceback = 0
@@ -1652,6 +1602,16 @@ func gcMarkTermination(nextTriggerRatio float64) {
// Free stack spans. This must be done between GC cycles.
systemstack(freeStackSpans)
+ // Ensure all mcaches are flushed. Each P will flush its own
+ // mcache before allocating, but idle Ps may not. Since this
+ // is necessary to sweep all spans, we need to ensure all
+ // mcaches are flushed before we start the next GC cycle.
+ systemstack(func() {
+ forEachP(func(_p_ *p) {
+ _p_.mcache.prepareForSweep()
+ })
+ })
+
// Print gctrace before dropping worldsema. As soon as we drop
// worldsema another cycle could start and smash the stats
// we're trying to print.
@@ -1852,7 +1812,7 @@ func gcBgMarkWorker(_p_ *p) {
}
// Go back to draining, this time
// without preemption.
- gcDrain(&_p_.gcw, gcDrainNoBlock|gcDrainFlushBgCredit)
+ gcDrain(&_p_.gcw, gcDrainFlushBgCredit)
case gcMarkWorkerFractionalMode:
gcDrain(&_p_.gcw, gcDrainFractional|gcDrainUntilPreempt|gcDrainFlushBgCredit)
case gcMarkWorkerIdleMode:
@@ -1861,16 +1821,6 @@ func gcBgMarkWorker(_p_ *p) {
casgstatus(gp, _Gwaiting, _Grunning)
})
- // If we are nearing the end of mark, dispose
- // of the cache promptly. We must do this
- // before signaling that we're no longer
- // working so that other workers can't observe
- // no workers and no work while we have this
- // cached, and before we compute done.
- if gcBlackenPromptly {
- _p_.gcw.dispose()
- }
-
// Account for time.
duration := nanotime() - startTime
switch _p_.gcMarkWorkerMode {
@@ -1947,50 +1897,11 @@ func gcMark(start_time int64) {
}
work.tstart = start_time
- // Queue root marking jobs.
- gcMarkRootPrepare()
-
- work.nwait = 0
- work.ndone = 0
- work.nproc = uint32(gcprocs())
-
- if work.full == 0 && work.nDataRoots+work.nBSSRoots+work.nSpanRoots+work.nStackRoots == 0 {
- // There's no work on the work queue and no root jobs
- // that can produce work, so don't bother entering the
- // getfull() barrier.
- //
- // This will be the situation the vast majority of the
- // time after concurrent mark. However, we still need
- // a fallback for STW GC and because there are some
- // known races that occasionally leave work around for
- // mark termination.
- //
- // We're still hedging our bets here: if we do
- // accidentally produce some work, we'll still process
- // it, just not necessarily in parallel.
- //
- // TODO(austin): Fix the races and and remove
- // work draining from mark termination so we don't
- // need the fallback path.
- work.helperDrainBlock = false
- } else {
- work.helperDrainBlock = true
- }
-
- if work.nproc > 1 {
- noteclear(&work.alldone)
- helpgc(int32(work.nproc))
- }
-
- gchelperstart()
-
- gcw := &getg().m.p.ptr().gcw
- if work.helperDrainBlock {
- gcDrain(gcw, gcDrainBlock)
- } else {
- gcDrain(gcw, gcDrainNoBlock)
+ // Check that there's no marking work remaining.
+ if work.full != 0 || work.markrootNext < work.markrootJobs {
+ print("runtime: full=", hex(work.full), " next=", work.markrootNext, " jobs=", work.markrootJobs, " nDataRoots=", work.nDataRoots, " nBSSRoots=", work.nBSSRoots, " nSpanRoots=", work.nSpanRoots, " nStackRoots=", work.nStackRoots, "\n")
+ panic("non-empty mark queue after concurrent mark")
}
- gcw.dispose()
if debug.gccheckmark > 0 {
// This is expensive when there's a large number of
@@ -2001,23 +1912,35 @@ func gcMark(start_time int64) {
throw("work.full != 0")
}
- if work.nproc > 1 {
- notesleep(&work.alldone)
- }
-
- // Record that at least one root marking pass has completed.
- work.markrootDone = true
-
- // Double-check that all gcWork caches are empty. This should
- // be ensured by mark 2 before we enter mark termination.
+ // Clear out buffers and double-check that all gcWork caches
+ // are empty. This should be ensured by gcMarkDone before we
+ // enter mark termination.
+ //
+ // TODO: We could clear out buffers just before mark if this
+ // has a non-negligible impact on STW time.
for _, p := range allp {
+ // The write barrier may have buffered pointers since
+ // the gcMarkDone barrier. However, since the barrier
+ // ensured all reachable objects were marked, all of
+ // these must be pointers to black objects. Hence we
+ // can just discard the write barrier buffer.
+ if debug.gccheckmark > 0 {
+ // For debugging, flush the buffer and make
+ // sure it really was all marked.
+ wbBufFlush1(p)
+ } else {
+ p.wbBuf.reset()
+ }
+
gcw := &p.gcw
if !gcw.empty() {
throw("P has cached GC work at end of mark termination")
}
- if gcw.scanWork != 0 || gcw.bytesMarked != 0 {
- throw("P has unflushed stats at end of mark termination")
- }
+ // There may still be cached empty buffers, which we
+ // need to flush since we're going to free them. Also,
+ // there may be non-zero stats because we allocated
+ // black after the gcMarkDone barrier.
+ gcw.dispose()
}
cachestats()
@@ -2102,7 +2025,6 @@ func gcResetMarkState() {
work.bytesMarked = 0
work.initialHeapLive = atomic.Load64(&memstats.heap_live)
- work.markrootDone = false
}
// Hooks for other packages
@@ -2149,48 +2071,6 @@ func clearpools() {
unlock(&sched.deferlock)
}
-// gchelper runs mark termination tasks on Ps other than the P
-// coordinating mark termination.
-//
-// The caller is responsible for ensuring that this has a P to run on,
-// even though it's running during STW. Because of this, it's allowed
-// to have write barriers.
-//
-//go:yeswritebarrierrec
-func gchelper() {
- _g_ := getg()
- _g_.m.traceback = 2
- gchelperstart()
-
- // Parallel mark over GC roots and heap
- if gcphase == _GCmarktermination {
- gcw := &_g_.m.p.ptr().gcw
- if work.helperDrainBlock {
- gcDrain(gcw, gcDrainBlock) // blocks in getfull
- } else {
- gcDrain(gcw, gcDrainNoBlock)
- }
- gcw.dispose()
- }
-
- nproc := atomic.Load(&work.nproc) // work.nproc can change right after we increment work.ndone
- if atomic.Xadd(&work.ndone, +1) == nproc-1 {
- notewakeup(&work.alldone)
- }
- _g_.m.traceback = 0
-}
-
-func gchelperstart() {
- _g_ := getg()
-
- if _g_.m.helpgc < 0 || _g_.m.helpgc >= _MaxGcproc {
- throw("gchelperstart: bad m->helpgc")
- }
- if _g_ != _g_.m.g0 {
- throw("gchelper not running on g0 stack")
- }
-}
-
// Timing
// itoaDiv formats val/(10**dec) into buf.
diff --git a/src/runtime/mgcmark.go b/src/runtime/mgcmark.go
index 69ff895512..d4dcfb6cb9 100644
--- a/src/runtime/mgcmark.go
+++ b/src/runtime/mgcmark.go
@@ -52,11 +52,7 @@ const (
//
//go:nowritebarrier
func gcMarkRootPrepare() {
- if gcphase == _GCmarktermination {
- work.nFlushCacheRoots = int(gomaxprocs)
- } else {
- work.nFlushCacheRoots = 0
- }
+ work.nFlushCacheRoots = 0
// Compute how many data and BSS root blocks there are.
nBlocks := func(bytes uintptr) int {
@@ -66,62 +62,41 @@ func gcMarkRootPrepare() {
work.nDataRoots = 0
work.nBSSRoots = 0
- // Only scan globals once per cycle; preferably concurrently.
- if !work.markrootDone {
- for _, datap := range activeModules() {
- nDataRoots := nBlocks(datap.edata - datap.data)
- if nDataRoots > work.nDataRoots {
- work.nDataRoots = nDataRoots
- }
+ // Scan globals.
+ for _, datap := range activeModules() {
+ nDataRoots := nBlocks(datap.edata - datap.data)
+ if nDataRoots > work.nDataRoots {
+ work.nDataRoots = nDataRoots
}
+ }
- for _, datap := range activeModules() {
- nBSSRoots := nBlocks(datap.ebss - datap.bss)
- if nBSSRoots > work.nBSSRoots {
- work.nBSSRoots = nBSSRoots
- }
+ for _, datap := range activeModules() {
+ nBSSRoots := nBlocks(datap.ebss - datap.bss)
+ if nBSSRoots > work.nBSSRoots {
+ work.nBSSRoots = nBSSRoots
}
}
- if !work.markrootDone {
- // On the first markroot, we need to scan span roots.
- // In concurrent GC, this happens during concurrent
- // mark and we depend on addfinalizer to ensure the
- // above invariants for objects that get finalizers
- // after concurrent mark. In STW GC, this will happen
- // during mark termination.
- //
- // We're only interested in scanning the in-use spans,
- // which will all be swept at this point. More spans
- // may be added to this list during concurrent GC, but
- // we only care about spans that were allocated before
- // this mark phase.
- work.nSpanRoots = mheap_.sweepSpans[mheap_.sweepgen/2%2].numBlocks()
-
- // On the first markroot, we need to scan all Gs. Gs
- // may be created after this point, but it's okay that
- // we ignore them because they begin life without any
- // roots, so there's nothing to scan, and any roots
- // they create during the concurrent phase will be
- // scanned during mark termination. During mark
- // termination, allglen isn't changing, so we'll scan
- // all Gs.
- work.nStackRoots = int(atomic.Loaduintptr(&allglen))
- } else {
- // We've already scanned span roots and kept the scan
- // up-to-date during concurrent mark.
- work.nSpanRoots = 0
-
- // The hybrid barrier ensures that stacks can't
- // contain pointers to unmarked objects, so on the
- // second markroot, there's no need to scan stacks.
- work.nStackRoots = 0
+ // Scan span roots for finalizer specials.
+ //
+ // We depend on addfinalizer to mark objects that get
+ // finalizers after root marking.
+ //
+ // We're only interested in scanning the in-use spans,
+ // which will all be swept at this point. More spans
+ // may be added to this list during concurrent GC, but
+ // we only care about spans that were allocated before
+ // this mark phase.
+ work.nSpanRoots = mheap_.sweepSpans[mheap_.sweepgen/2%2].numBlocks()
- if debug.gcrescanstacks > 0 {
- // Scan stacks anyway for debugging.
- work.nStackRoots = int(atomic.Loaduintptr(&allglen))
- }
- }
+ // Scan stacks.
+ //
+ // Gs may be created after this point, but it's okay that we
+ // ignore them because they begin life without any roots, so
+ // there's nothing to scan, and any roots they create during
+ // the concurrent phase will be scanned during mark
+ // termination.
+ work.nStackRoots = int(atomic.Loaduintptr(&allglen))
work.markrootNext = 0
work.markrootJobs = uint32(fixedRootCount + work.nFlushCacheRoots + work.nDataRoots + work.nBSSRoots + work.nSpanRoots + work.nStackRoots)
@@ -138,19 +113,10 @@ func gcMarkRootCheck() {
lock(&allglock)
// Check that stacks have been scanned.
var gp *g
- if gcphase == _GCmarktermination && debug.gcrescanstacks > 0 {
- for i := 0; i < len(allgs); i++ {
- gp = allgs[i]
- if !(gp.gcscandone && gp.gcscanvalid) && readgstatus(gp) != _Gdead {
- goto fail
- }
- }
- } else {
- for i := 0; i < work.nStackRoots; i++ {
- gp = allgs[i]
- if !gp.gcscandone {
- goto fail
- }
+ for i := 0; i < work.nStackRoots; i++ {
+ gp = allgs[i]
+ if !gp.gcscandone {
+ goto fail
}
}
unlock(&allglock)
@@ -201,24 +167,15 @@ func markroot(gcw *gcWork, i uint32) {
}
case i == fixedRootFinalizers:
- // Only do this once per GC cycle since we don't call
- // queuefinalizer during marking.
- if work.markrootDone {
- break
- }
for fb := allfin; fb != nil; fb = fb.alllink {
cnt := uintptr(atomic.Load(&fb.cnt))
- scanblock(uintptr(unsafe.Pointer(&fb.fin[0])), cnt*unsafe.Sizeof(fb.fin[0]), &finptrmask[0], gcw)
+ scanblock(uintptr(unsafe.Pointer(&fb.fin[0])), cnt*unsafe.Sizeof(fb.fin[0]), &finptrmask[0], gcw, nil)
}
case i == fixedRootFreeGStacks:
- // Only do this once per GC cycle; preferably
- // concurrently.
- if !work.markrootDone {
- // Switch to the system stack so we can call
- // stackfree.
- systemstack(markrootFreeGStacks)
- }
+ // Switch to the system stack so we can call
+ // stackfree.
+ systemstack(markrootFreeGStacks)
case baseSpans <= i && i < baseStacks:
// mark MSpan.specials
@@ -291,7 +248,7 @@ func markrootBlock(b0, n0 uintptr, ptrmask0 *uint8, gcw *gcWork, shard int) {
}
// Scan this shard.
- scanblock(b, n, ptrmask, gcw)
+ scanblock(b, n, ptrmask, gcw, nil)
}
// markrootFreeGStacks frees stacks of dead Gs.
@@ -342,10 +299,6 @@ func markrootSpans(gcw *gcWork, shard int) {
// TODO(austin): There are several ideas for making this more
// efficient in issue #11485.
- if work.markrootDone {
- throw("markrootSpans during second markroot")
- }
-
sg := mheap_.sweepgen
spans := mheap_.sweepSpans[mheap_.sweepgen/2%2].block(shard)
// Note that work.spans may not include spans that were
@@ -358,7 +311,8 @@ func markrootSpans(gcw *gcWork, shard int) {
if s.state != mSpanInUse {
continue
}
- if !useCheckmark && s.sweepgen != sg {
+ // Check that this span was swept (it may be cached or uncached).
+ if !useCheckmark && !(s.sweepgen == sg || s.sweepgen == sg+3) {
// sweepgen was updated (+2) during non-checkmark GC pass
print("sweep ", s.sweepgen, " ", sg, "\n")
throw("gc: unswept span")
@@ -395,7 +349,7 @@ func markrootSpans(gcw *gcWork, shard int) {
scanobject(p, gcw)
// The special itself is a root.
- scanblock(uintptr(unsafe.Pointer(&spf.fn)), sys.PtrSize, &oneptrmask[0], gcw)
+ scanblock(uintptr(unsafe.Pointer(&spf.fn)), sys.PtrSize, &oneptrmask[0], gcw, nil)
}
unlock(&s.speciallock)
@@ -556,11 +510,6 @@ func gcAssistAlloc1(gp *g, scanWork int64) {
// will be more cache friendly.
gcw := &getg().m.p.ptr().gcw
workDone := gcDrainN(gcw, scanWork)
- // If we are near the end of the mark phase
- // dispose of the gcw.
- if gcBlackenPromptly {
- gcw.dispose()
- }
casgstatus(gp, _Gwaiting, _Grunning)
@@ -577,8 +526,7 @@ func gcAssistAlloc1(gp *g, scanWork int64) {
incnwait := atomic.Xadd(&work.nwait, +1)
if incnwait > work.nproc {
println("runtime: work.nwait=", incnwait,
- "work.nproc=", work.nproc,
- "gcBlackenPromptly=", gcBlackenPromptly)
+ "work.nproc=", work.nproc)
throw("work.nwait > work.nproc")
}
@@ -737,53 +685,140 @@ func scanstack(gp *g, gcw *gcWork) {
if gp == getg() {
throw("can't scan our own stack")
}
- mp := gp.m
- if mp != nil && mp.helpgc != 0 {
- throw("can't scan gchelper stack")
- }
- // Shrink the stack if not much of it is being used. During
- // concurrent GC, we can do this during concurrent mark.
- if !work.markrootDone {
- shrinkstack(gp)
+ // Shrink the stack if not much of it is being used.
+ shrinkstack(gp)
+
+ var state stackScanState
+ state.stack = gp.stack
+
+ if stackTraceDebug {
+ println("stack trace goroutine", gp.goid)
}
// Scan the saved context register. This is effectively a live
// register that gets moved back and forth between the
// register and sched.ctxt without a write barrier.
if gp.sched.ctxt != nil {
- scanblock(uintptr(unsafe.Pointer(&gp.sched.ctxt)), sys.PtrSize, &oneptrmask[0], gcw)
+ scanblock(uintptr(unsafe.Pointer(&gp.sched.ctxt)), sys.PtrSize, &oneptrmask[0], gcw, &state)
}
- // Scan the stack.
- var cache pcvalueCache
+ // Scan the stack. Accumulate a list of stack objects.
scanframe := func(frame *stkframe, unused unsafe.Pointer) bool {
- scanframeworker(frame, &cache, gcw)
+ scanframeworker(frame, &state, gcw)
return true
}
gentraceback(^uintptr(0), ^uintptr(0), 0, gp, 0, nil, 0x7fffffff, scanframe, nil, 0)
tracebackdefers(gp, scanframe, nil)
+
+ // Find and scan all reachable stack objects.
+ state.buildIndex()
+ for {
+ p := state.getPtr()
+ if p == 0 {
+ break
+ }
+ obj := state.findObject(p)
+ if obj == nil {
+ continue
+ }
+ t := obj.typ
+ if t == nil {
+ // We've already scanned this object.
+ continue
+ }
+ obj.setType(nil) // Don't scan it again.
+ if stackTraceDebug {
+ println(" live stkobj at", hex(state.stack.lo+uintptr(obj.off)), "of type", t.string())
+ }
+ gcdata := t.gcdata
+ var s *mspan
+ if t.kind&kindGCProg != 0 {
+ // This path is pretty unlikely, an object large enough
+ // to have a GC program allocated on the stack.
+ // We need some space to unpack the program into a straight
+ // bitmask, which we allocate/free here.
+ // TODO: it would be nice if there were a way to run a GC
+ // program without having to store all its bits. We'd have
+ // to change from a Lempel-Ziv style program to something else.
+ // Or we can forbid putting objects on stacks if they require
+ // a gc program (see issue 27447).
+ s = materializeGCProg(t.ptrdata, gcdata)
+ gcdata = (*byte)(unsafe.Pointer(s.startAddr))
+ }
+
+ scanblock(state.stack.lo+uintptr(obj.off), t.ptrdata, gcdata, gcw, &state)
+
+ if s != nil {
+ dematerializeGCProg(s)
+ }
+ }
+
+ // Deallocate object buffers.
+ // (Pointer buffers were all deallocated in the loop above.)
+ for state.head != nil {
+ x := state.head
+ state.head = x.next
+ if stackTraceDebug {
+ for _, obj := range x.obj[:x.nobj] {
+ if obj.typ == nil { // reachable
+ continue
+ }
+ println(" dead stkobj at", hex(gp.stack.lo+uintptr(obj.off)), "of type", obj.typ.string())
+ // Note: not necessarily really dead - only reachable-from-ptr dead.
+ }
+ }
+ x.nobj = 0
+ putempty((*workbuf)(unsafe.Pointer(x)))
+ }
+ if state.buf != nil || state.freeBuf != nil {
+ throw("remaining pointer buffers")
+ }
+
gp.gcscanvalid = true
}
// Scan a stack frame: local variables and function arguments/results.
//go:nowritebarrier
-func scanframeworker(frame *stkframe, cache *pcvalueCache, gcw *gcWork) {
+func scanframeworker(frame *stkframe, state *stackScanState, gcw *gcWork) {
if _DebugGC > 1 && frame.continpc != 0 {
print("scanframe ", funcname(frame.fn), "\n")
}
- locals, args := getStackMap(frame, cache, false)
+ locals, args, objs := getStackMap(frame, &state.cache, false)
// Scan local variables if stack frame has been allocated.
if locals.n > 0 {
size := uintptr(locals.n) * sys.PtrSize
- scanblock(frame.varp-size, size, locals.bytedata, gcw)
+ scanblock(frame.varp-size, size, locals.bytedata, gcw, state)
}
// Scan arguments.
if args.n > 0 {
- scanblock(frame.argp, uintptr(args.n)*sys.PtrSize, args.bytedata, gcw)
+ scanblock(frame.argp, uintptr(args.n)*sys.PtrSize, args.bytedata, gcw, state)
+ }
+
+ // Add all stack objects to the stack object list.
+ if frame.varp != 0 {
+ // varp is 0 for defers, where there are no locals.
+ // In that case, there can't be a pointer to its args, either.
+ // (And all args would be scanned above anyway.)
+ for _, obj := range objs {
+ off := obj.off
+ base := frame.varp // locals base pointer
+ if off >= 0 {
+ base = frame.argp // arguments and return values base pointer
+ }
+ ptr := base + uintptr(off)
+ if ptr < frame.sp {
+ // object hasn't been allocated in the frame yet.
+ continue
+ }
+ if stackTraceDebug {
+ println("stkobj at", hex(ptr), "of type", obj.typ.string())
+ }
+ state.addObject(ptr, obj.typ)
+ }
}
}
@@ -791,34 +826,26 @@ type gcDrainFlags int
const (
gcDrainUntilPreempt gcDrainFlags = 1 << iota
- gcDrainNoBlock
gcDrainFlushBgCredit
gcDrainIdle
gcDrainFractional
-
- // gcDrainBlock means neither gcDrainUntilPreempt or
- // gcDrainNoBlock. It is the default, but callers should use
- // the constant for documentation purposes.
- gcDrainBlock gcDrainFlags = 0
)
// gcDrain scans roots and objects in work buffers, blackening grey
-// objects until all roots and work buffers have been drained.
+// objects until it is unable to get more work. It may return before
+// GC is done; it's the caller's responsibility to balance work from
+// other Ps.
//
// If flags&gcDrainUntilPreempt != 0, gcDrain returns when g.preempt
-// is set. This implies gcDrainNoBlock.
+// is set.
//
// If flags&gcDrainIdle != 0, gcDrain returns when there is other work
-// to do. This implies gcDrainNoBlock.
+// to do.
//
// If flags&gcDrainFractional != 0, gcDrain self-preempts when
// pollFractionalWorkerExit() returns true. This implies
// gcDrainNoBlock.
//
-// If flags&gcDrainNoBlock != 0, gcDrain returns as soon as it is
-// unable to get more work. Otherwise, it will block until all
-// blocking calls are blocked in gcDrain.
-//
// If flags&gcDrainFlushBgCredit != 0, gcDrain flushes scan work
// credit to gcController.bgScanCredit every gcCreditSlack units of
// scan work.
@@ -831,7 +858,6 @@ func gcDrain(gcw *gcWork, flags gcDrainFlags) {
gp := getg().m.curg
preemptible := flags&gcDrainUntilPreempt != 0
- blocking := flags&(gcDrainUntilPreempt|gcDrainIdle|gcDrainFractional|gcDrainNoBlock) == 0
flushBgCredit := flags&gcDrainFlushBgCredit != 0
idle := flags&gcDrainIdle != 0
@@ -875,17 +901,19 @@ func gcDrain(gcw *gcWork, flags gcDrainFlags) {
gcw.balance()
}
- var b uintptr
- if blocking {
- b = gcw.get()
- } else {
- b = gcw.tryGetFast()
+ b := gcw.tryGetFast()
+ if b == 0 {
+ b = gcw.tryGet()
if b == 0 {
+ // Flush the write barrier
+ // buffer; this may create
+ // more work.
+ wbBufFlush(nil, 0)
b = gcw.tryGet()
}
}
if b == 0 {
- // work barrier reached or tryGet failed.
+ // Unable to get work.
break
}
scanobject(b, gcw)
@@ -911,10 +939,6 @@ func gcDrain(gcw *gcWork, flags gcDrainFlags) {
}
}
- // In blocking mode, write barriers are not allowed after this
- // point because we must preserve the condition that the work
- // buffers are empty.
-
done:
// Flush remaining scan work credit.
if gcw.scanWork > 0 {
@@ -963,6 +987,12 @@ func gcDrainN(gcw *gcWork, scanWork int64) int64 {
b := gcw.tryGetFast()
if b == 0 {
b = gcw.tryGet()
+ if b == 0 {
+ // Flush the write barrier buffer;
+ // this may create more work.
+ wbBufFlush(nil, 0)
+ b = gcw.tryGet()
+ }
}
if b == 0 {
@@ -1003,8 +1033,9 @@ func gcDrainN(gcw *gcWork, scanWork int64) int64 {
// This is used to scan non-heap roots, so it does not update
// gcw.bytesMarked or gcw.scanWork.
//
+// If stk != nil, possible stack pointers are also reported to stk.putPtr.
//go:nowritebarrier
-func scanblock(b0, n0 uintptr, ptrmask *uint8, gcw *gcWork) {
+func scanblock(b0, n0 uintptr, ptrmask *uint8, gcw *gcWork, stk *stackScanState) {
// Use local copies of original parameters, so that a stack trace
// due to one of the throws below shows the original block
// base and extent.
@@ -1021,10 +1052,12 @@ func scanblock(b0, n0 uintptr, ptrmask *uint8, gcw *gcWork) {
for j := 0; j < 8 && i < n; j++ {
if bits&1 != 0 {
// Same work as in scanobject; see comments there.
- obj := *(*uintptr)(unsafe.Pointer(b + i))
- if obj != 0 {
- if obj, span, objIndex := findObject(obj, b, i); obj != 0 {
+ p := *(*uintptr)(unsafe.Pointer(b + i))
+ if p != 0 {
+ if obj, span, objIndex := findObject(p, b, i); obj != 0 {
greyobject(obj, b, i, span, gcw, objIndex)
+ } else if stk != nil && p >= stk.stack.lo && p < stk.stack.hi {
+ stk.putPtr(p)
}
}
}
@@ -1142,11 +1175,6 @@ func shade(b uintptr) {
if obj, span, objIndex := findObject(b, 0, 0); obj != 0 {
gcw := &getg().m.p.ptr().gcw
greyobject(obj, 0, 0, span, gcw, objIndex)
- if gcphase == _GCmarktermination || gcBlackenPromptly {
- // Ps aren't allowed to cache work during mark
- // termination.
- gcw.dispose()
- }
}
}
@@ -1239,7 +1267,7 @@ func gcDumpObject(label string, obj, off uintptr) {
skipped := false
size := s.elemsize
- if s.state == _MSpanManual && size == 0 {
+ if s.state == mSpanManual && size == 0 {
// We're printing something from a stack frame. We
// don't know how big it is, so just show up to an
// including off.
@@ -1276,18 +1304,13 @@ func gcDumpObject(label string, obj, off uintptr) {
//go:nowritebarrier
//go:nosplit
func gcmarknewobject(obj, size, scanSize uintptr) {
- if useCheckmark && !gcBlackenPromptly { // The world should be stopped so this should not happen.
+ if useCheckmark { // The world should be stopped so this should not happen.
throw("gcmarknewobject called while doing checkmark")
}
markBitsForAddr(obj).setMarked()
gcw := &getg().m.p.ptr().gcw
gcw.bytesMarked += uint64(size)
gcw.scanWork += int64(scanSize)
- if gcBlackenPromptly {
- // There shouldn't be anything in the work queue, but
- // we still need to flush stats.
- gcw.dispose()
- }
}
// gcMarkTinyAllocs greys all active tiny alloc blocks.
@@ -1302,9 +1325,6 @@ func gcMarkTinyAllocs() {
_, span, objIndex := findObject(c.tiny, 0, 0)
gcw := &p.gcw
greyobject(c.tiny, 0, 0, span, gcw, objIndex)
- if gcBlackenPromptly {
- gcw.dispose()
- }
}
}
@@ -1335,7 +1355,7 @@ var useCheckmark = false
func initCheckmarks() {
useCheckmark = true
for _, s := range mheap_.allspans {
- if s.state == _MSpanInUse {
+ if s.state == mSpanInUse {
heapBitsForAddr(s.base()).initCheckmarkSpan(s.layout())
}
}
@@ -1344,7 +1364,7 @@ func initCheckmarks() {
func clearCheckmarks() {
useCheckmark = false
for _, s := range mheap_.allspans {
- if s.state == _MSpanInUse {
+ if s.state == mSpanInUse {
heapBitsForAddr(s.base()).clearCheckmarkSpan(s.layout())
}
}
diff --git a/src/runtime/mgcstack.go b/src/runtime/mgcstack.go
new file mode 100644
index 0000000000..86e60d4381
--- /dev/null
+++ b/src/runtime/mgcstack.go
@@ -0,0 +1,330 @@
+// Copyright 2018 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.
+
+// Garbage collector: stack objects and stack tracing
+// See the design doc at https://docs.google.com/document/d/1un-Jn47yByHL7I0aVIP_uVCMxjdM5mpelJhiKlIqxkE/edit?usp=sharing
+// Also see issue 22350.
+
+// Stack tracing solves the problem of determining which parts of the
+// stack are live and should be scanned. It runs as part of scanning
+// a single goroutine stack.
+//
+// Normally determining which parts of the stack are live is easy to
+// do statically, as user code has explicit references (reads and
+// writes) to stack variables. The compiler can do a simple dataflow
+// analysis to determine liveness of stack variables at every point in
+// the code. See cmd/compile/internal/gc/plive.go for that analysis.
+//
+// However, when we take the address of a stack variable, determining
+// whether that variable is still live is less clear. We can still
+// look for static accesses, but accesses through a pointer to the
+// variable are difficult in general to track statically. That pointer
+// can be passed among functions on the stack, conditionally retained,
+// etc.
+//
+// Instead, we will track pointers to stack variables dynamically.
+// All pointers to stack-allocated variables will themselves be on the
+// stack somewhere (or in associated locations, like defer records), so
+// we can find them all efficiently.
+//
+// Stack tracing is organized as a mini garbage collection tracing
+// pass. The objects in this garbage collection are all the variables
+// on the stack whose address is taken, and which themselves contain a
+// pointer. We call these variables "stack objects".
+//
+// We begin by determining all the stack objects on the stack and all
+// the statically live pointers that may point into the stack. We then
+// process each pointer to see if it points to a stack object. If it
+// does, we scan that stack object. It may contain pointers into the
+// heap, in which case those pointers are passed to the main garbage
+// collection. It may also contain pointers into the stack, in which
+// case we add them to our set of stack pointers.
+//
+// Once we're done processing all the pointers (including the ones we
+// added during processing), we've found all the stack objects that
+// are live. Any dead stack objects are not scanned and their contents
+// will not keep heap objects live. Unlike the main garbage
+// collection, we can't sweep the dead stack objects; they live on in
+// a moribund state until the stack frame that contains them is
+// popped.
+//
+// A stack can look like this:
+//
+// +----------+
+// | foo() |
+// | +------+ |
+// | | A | | <---\
+// | +------+ | |
+// | | |
+// | +------+ | |
+// | | B | | |
+// | +------+ | |
+// | | |
+// +----------+ |
+// | bar() | |
+// | +------+ | |
+// | | C | | <-\ |
+// | +----|-+ | | |
+// | | | | |
+// | +----v-+ | | |
+// | | D ---------/
+// | +------+ | |
+// | | |
+// +----------+ |
+// | baz() | |
+// | +------+ | |
+// | | E -------/
+// | +------+ |
+// | ^ |
+// | F: --/ |
+// | |
+// +----------+
+//
+// foo() calls bar() calls baz(). Each has a frame on the stack.
+// foo() has stack objects A and B.
+// bar() has stack objects C and D, with C pointing to D and D pointing to A.
+// baz() has a stack object E pointing to C, and a local variable F pointing to E.
+//
+// Starting from the pointer in local variable F, we will eventually
+// scan all of E, C, D, and A (in that order). B is never scanned
+// because there is no live pointer to it. If B is also statically
+// dead (meaning that foo() never accesses B again after it calls
+// bar()), then B's pointers into the heap are not considered live.
+
+package runtime
+
+import (
+ "runtime/internal/sys"
+ "unsafe"
+)
+
+const stackTraceDebug = false
+
+// Buffer for pointers found during stack tracing.
+// Must be smaller than or equal to workbuf.
+//
+//go:notinheap
+type stackWorkBuf struct {
+ stackWorkBufHdr
+ obj [(_WorkbufSize - unsafe.Sizeof(stackWorkBufHdr{})) / sys.PtrSize]uintptr
+}
+
+// Header declaration must come after the buf declaration above, because of issue #14620.
+//
+//go:notinheap
+type stackWorkBufHdr struct {
+ workbufhdr
+ next *stackWorkBuf // linked list of workbufs
+ // Note: we could theoretically repurpose lfnode.next as this next pointer.
+ // It would save 1 word, but that probably isn't worth busting open
+ // the lfnode API.
+}
+
+// Buffer for stack objects found on a goroutine stack.
+// Must be smaller than or equal to workbuf.
+//
+//go:notinheap
+type stackObjectBuf struct {
+ stackObjectBufHdr
+ obj [(_WorkbufSize - unsafe.Sizeof(stackObjectBufHdr{})) / unsafe.Sizeof(stackObject{})]stackObject
+}
+
+//go:notinheap
+type stackObjectBufHdr struct {
+ workbufhdr
+ next *stackObjectBuf
+}
+
+func init() {
+ if unsafe.Sizeof(stackWorkBuf{}) > unsafe.Sizeof(workbuf{}) {
+ panic("stackWorkBuf too big")
+ }
+ if unsafe.Sizeof(stackObjectBuf{}) > unsafe.Sizeof(workbuf{}) {
+ panic("stackObjectBuf too big")
+ }
+}
+
+// A stackObject represents a variable on the stack that has had
+// its address taken.
+//
+//go:notinheap
+type stackObject struct {
+ off uint32 // offset above stack.lo
+ size uint32 // size of object
+ typ *_type // type info (for ptr/nonptr bits). nil if object has been scanned.
+ left *stackObject // objects with lower addresses
+ right *stackObject // objects with higher addresses
+}
+
+// obj.typ = typ, but with no write barrier.
+//go:nowritebarrier
+func (obj *stackObject) setType(typ *_type) {
+ // Types of stack objects are always in read-only memory, not the heap.
+ // So not using a write barrier is ok.
+ *(*uintptr)(unsafe.Pointer(&obj.typ)) = uintptr(unsafe.Pointer(typ))
+}
+
+// A stackScanState keeps track of the state used during the GC walk
+// of a goroutine.
+//
+//go:notinheap
+type stackScanState struct {
+ cache pcvalueCache
+
+ // stack limits
+ stack stack
+
+ // buf contains the set of possible pointers to stack objects.
+ // Organized as a LIFO linked list of buffers.
+ // All buffers except possibly the head buffer are full.
+ buf *stackWorkBuf
+ freeBuf *stackWorkBuf // keep around one free buffer for allocation hysteresis
+
+ // list of stack objects
+ // Objects are in increasing address order.
+ head *stackObjectBuf
+ tail *stackObjectBuf
+ nobjs int
+
+ // root of binary tree for fast object lookup by address
+ // Initialized by buildIndex.
+ root *stackObject
+}
+
+// Add p as a potential pointer to a stack object.
+// p must be a stack address.
+func (s *stackScanState) putPtr(p uintptr) {
+ if p < s.stack.lo || p >= s.stack.hi {
+ throw("address not a stack address")
+ }
+ buf := s.buf
+ if buf == nil {
+ // Initial setup.
+ buf = (*stackWorkBuf)(unsafe.Pointer(getempty()))
+ buf.nobj = 0
+ buf.next = nil
+ s.buf = buf
+ } else if buf.nobj == len(buf.obj) {
+ if s.freeBuf != nil {
+ buf = s.freeBuf
+ s.freeBuf = nil
+ } else {
+ buf = (*stackWorkBuf)(unsafe.Pointer(getempty()))
+ }
+ buf.nobj = 0
+ buf.next = s.buf
+ s.buf = buf
+ }
+ buf.obj[buf.nobj] = p
+ buf.nobj++
+}
+
+// Remove and return a potential pointer to a stack object.
+// Returns 0 if there are no more pointers available.
+func (s *stackScanState) getPtr() uintptr {
+ buf := s.buf
+ if buf == nil {
+ // Never had any data.
+ return 0
+ }
+ if buf.nobj == 0 {
+ if s.freeBuf != nil {
+ // Free old freeBuf.
+ putempty((*workbuf)(unsafe.Pointer(s.freeBuf)))
+ }
+ // Move buf to the freeBuf.
+ s.freeBuf = buf
+ buf = buf.next
+ s.buf = buf
+ if buf == nil {
+ // No more data.
+ putempty((*workbuf)(unsafe.Pointer(s.freeBuf)))
+ s.freeBuf = nil
+ return 0
+ }
+ }
+ buf.nobj--
+ return buf.obj[buf.nobj]
+}
+
+// addObject adds a stack object at addr of type typ to the set of stack objects.
+func (s *stackScanState) addObject(addr uintptr, typ *_type) {
+ x := s.tail
+ if x == nil {
+ // initial setup
+ x = (*stackObjectBuf)(unsafe.Pointer(getempty()))
+ x.next = nil
+ s.head = x
+ s.tail = x
+ }
+ if x.nobj > 0 && uint32(addr-s.stack.lo) < x.obj[x.nobj-1].off+x.obj[x.nobj-1].size {
+ throw("objects added out of order or overlapping")
+ }
+ if x.nobj == len(x.obj) {
+ // full buffer - allocate a new buffer, add to end of linked list
+ y := (*stackObjectBuf)(unsafe.Pointer(getempty()))
+ y.next = nil
+ x.next = y
+ s.tail = y
+ x = y
+ }
+ obj := &x.obj[x.nobj]
+ x.nobj++
+ obj.off = uint32(addr - s.stack.lo)
+ obj.size = uint32(typ.size)
+ obj.setType(typ)
+ // obj.left and obj.right will be initalized by buildIndex before use.
+ s.nobjs++
+}
+
+// buildIndex initializes s.root to a binary search tree.
+// It should be called after all addObject calls but before
+// any call of findObject.
+func (s *stackScanState) buildIndex() {
+ s.root, _, _ = binarySearchTree(s.head, 0, s.nobjs)
+}
+
+// Build a binary search tree with the n objects in the list
+// x.obj[idx], x.obj[idx+1], ..., x.next.obj[0], ...
+// Returns the root of that tree, and the buf+idx of the nth object after x.obj[idx].
+// (The first object that was not included in the binary search tree.)
+// If n == 0, returns nil, x.
+func binarySearchTree(x *stackObjectBuf, idx int, n int) (root *stackObject, restBuf *stackObjectBuf, restIdx int) {
+ if n == 0 {
+ return nil, x, idx
+ }
+ var left, right *stackObject
+ left, x, idx = binarySearchTree(x, idx, n/2)
+ root = &x.obj[idx]
+ idx++
+ if idx == len(x.obj) {
+ x = x.next
+ idx = 0
+ }
+ right, x, idx = binarySearchTree(x, idx, n-n/2-1)
+ root.left = left
+ root.right = right
+ return root, x, idx
+}
+
+// findObject returns the stack object containing address a, if any.
+// Must have called buildIndex previously.
+func (s *stackScanState) findObject(a uintptr) *stackObject {
+ off := uint32(a - s.stack.lo)
+ obj := s.root
+ for {
+ if obj == nil {
+ return nil
+ }
+ if off < obj.off {
+ obj = obj.left
+ continue
+ }
+ if off >= obj.off+obj.size {
+ obj = obj.right
+ continue
+ }
+ return obj
+ }
+}
diff --git a/src/runtime/mgcsweep.go b/src/runtime/mgcsweep.go
index c7baa455fe..00950aede2 100644
--- a/src/runtime/mgcsweep.go
+++ b/src/runtime/mgcsweep.go
@@ -88,10 +88,11 @@ func sweepone() uintptr {
}
atomic.Xadd(&mheap_.sweepers, +1)
- npages := ^uintptr(0)
+ // Find a span to sweep.
+ var s *mspan
sg := mheap_.sweepgen
for {
- s := mheap_.sweepSpans[1-sg/2%2].pop()
+ s = mheap_.sweepSpans[1-sg/2%2].pop()
if s == nil {
atomic.Store(&mheap_.sweepdone, 1)
break
@@ -106,9 +107,14 @@ func sweepone() uintptr {
}
continue
}
- if s.sweepgen != sg-2 || !atomic.Cas(&s.sweepgen, sg-2, sg-1) {
- continue
+ if s.sweepgen == sg-2 && atomic.Cas(&s.sweepgen, sg-2, sg-1) {
+ break
}
+ }
+
+ // Sweep the span we found.
+ npages := ^uintptr(0)
+ if s != nil {
npages = s.npages
if !s.sweep(false) {
// Span is still in-use, so this returned no
@@ -116,7 +122,6 @@ func sweepone() uintptr {
// move to the swept in-use list.
npages = 0
}
- break
}
// Decrement the number of active sweepers and if this is the
@@ -156,16 +161,21 @@ func (s *mspan) ensureSwept() {
}
sg := mheap_.sweepgen
- if atomic.Load(&s.sweepgen) == sg {
+ spangen := atomic.Load(&s.sweepgen)
+ if spangen == sg || spangen == sg+3 {
return
}
- // The caller must be sure that the span is a MSpanInUse span.
+ // The caller must be sure that the span is a mSpanInUse span.
if atomic.Cas(&s.sweepgen, sg-2, sg-1) {
s.sweep(false)
return
}
// unfortunate condition, and we don't have efficient means to wait
- for atomic.Load(&s.sweepgen) != sg {
+ for {
+ spangen := atomic.Load(&s.sweepgen)
+ if spangen == sg || spangen == sg+3 {
+ break
+ }
osyield()
}
}
@@ -339,18 +349,18 @@ func (s *mspan) sweep(preserve bool) bool {
// Free large span to heap
// NOTE(rsc,dvyukov): The original implementation of efence
- // in CL 22060046 used SysFree instead of SysFault, so that
+ // in CL 22060046 used sysFree instead of sysFault, so that
// the operating system would eventually give the memory
// back to us again, so that an efence program could run
// longer without running out of memory. Unfortunately,
- // calling SysFree here without any kind of adjustment of the
+ // calling sysFree here without any kind of adjustment of the
// heap data structures means that when the memory does
// come back to us, we have the wrong metadata for it, either in
// the MSpan structures or in the garbage collection bitmap.
- // Using SysFault here means that the program will run out of
+ // Using sysFault here means that the program will run out of
// memory fairly quickly in efence mode, but at least it won't
// have mysterious crashes due to confused memory reuse.
- // It should be possible to switch back to SysFree if we also
+ // It should be possible to switch back to sysFree if we also
// implement and then call some kind of MHeap_DeleteSpan.
if debug.efence > 0 {
s.limit = 0 // prevent mlookup from finding this span
diff --git a/src/runtime/mgcwork.go b/src/runtime/mgcwork.go
index 99771e2e57..c32c5eddd7 100644
--- a/src/runtime/mgcwork.go
+++ b/src/runtime/mgcwork.go
@@ -46,10 +46,7 @@ func init() {
//
// (preemption must be disabled)
// gcw := &getg().m.p.ptr().gcw
-// .. call gcw.put() to produce and gcw.get() to consume ..
-// if gcBlackenPromptly {
-// gcw.dispose()
-// }
+// .. call gcw.put() to produce and gcw.tryGet() to consume ..
//
// It's important that any use of gcWork during the mark phase prevent
// the garbage collector from transitioning to mark termination since
@@ -83,6 +80,12 @@ type gcWork struct {
// Scan work performed on this gcWork. This is aggregated into
// gcController by dispose and may also be flushed by callers.
scanWork int64
+
+ // flushedWork indicates that a non-empty work buffer was
+ // flushed to the global work list since the last gcMarkDone
+ // termination check. Specifically, this indicates that this
+ // gcWork may have communicated work to another gcWork.
+ flushedWork bool
}
// Most of the methods of gcWork are go:nowritebarrierrec because the
@@ -116,6 +119,7 @@ func (w *gcWork) put(obj uintptr) {
wbuf = w.wbuf1
if wbuf.nobj == len(wbuf.obj) {
putfull(wbuf)
+ w.flushedWork = true
wbuf = getempty()
w.wbuf1 = wbuf
flushed = true
@@ -169,6 +173,7 @@ func (w *gcWork) putBatch(obj []uintptr) {
for len(obj) > 0 {
for wbuf.nobj == len(wbuf.obj) {
putfull(wbuf)
+ w.flushedWork = true
w.wbuf1, w.wbuf2 = w.wbuf2, getempty()
wbuf = w.wbuf1
flushed = true
@@ -231,37 +236,6 @@ func (w *gcWork) tryGetFast() uintptr {
return wbuf.obj[wbuf.nobj]
}
-// get dequeues a pointer for the garbage collector to trace, blocking
-// if necessary to ensure all pointers from all queues and caches have
-// been retrieved. get returns 0 if there are no pointers remaining.
-//go:nowritebarrierrec
-func (w *gcWork) get() uintptr {
- wbuf := w.wbuf1
- if wbuf == nil {
- w.init()
- wbuf = w.wbuf1
- // wbuf is empty at this point.
- }
- if wbuf.nobj == 0 {
- w.wbuf1, w.wbuf2 = w.wbuf2, w.wbuf1
- wbuf = w.wbuf1
- if wbuf.nobj == 0 {
- owbuf := wbuf
- wbuf = getfull()
- if wbuf == nil {
- return 0
- }
- putempty(owbuf)
- w.wbuf1 = wbuf
- }
- }
-
- // TODO: This might be a good place to add prefetch code
-
- wbuf.nobj--
- return wbuf.obj[wbuf.nobj]
-}
-
// dispose returns any cached pointers to the global queue.
// The buffers are being put on the full queue so that the
// write barriers will not simply reacquire them before the
@@ -275,6 +249,7 @@ func (w *gcWork) dispose() {
putempty(wbuf)
} else {
putfull(wbuf)
+ w.flushedWork = true
}
w.wbuf1 = nil
@@ -283,6 +258,7 @@ func (w *gcWork) dispose() {
putempty(wbuf)
} else {
putfull(wbuf)
+ w.flushedWork = true
}
w.wbuf2 = nil
}
@@ -309,9 +285,11 @@ func (w *gcWork) balance() {
}
if wbuf := w.wbuf2; wbuf.nobj != 0 {
putfull(wbuf)
+ w.flushedWork = true
w.wbuf2 = getempty()
} else if wbuf := w.wbuf1; wbuf.nobj > 4 {
w.wbuf1 = handoff(wbuf)
+ w.flushedWork = true // handoff did putfull
} else {
return
}
@@ -440,61 +418,6 @@ func trygetfull() *workbuf {
return b
}
-// Get a full work buffer off the work.full list.
-// If nothing is available wait until all the other gc helpers have
-// finished and then return nil.
-// getfull acts as a barrier for work.nproc helpers. As long as one
-// gchelper is actively marking objects it
-// may create a workbuffer that the other helpers can work on.
-// The for loop either exits when a work buffer is found
-// or when _all_ of the work.nproc GC helpers are in the loop
-// looking for work and thus not capable of creating new work.
-// This is in fact the termination condition for the STW mark
-// phase.
-//go:nowritebarrier
-func getfull() *workbuf {
- b := (*workbuf)(work.full.pop())
- if b != nil {
- b.checknonempty()
- return b
- }
-
- incnwait := atomic.Xadd(&work.nwait, +1)
- if incnwait > work.nproc {
- println("runtime: work.nwait=", incnwait, "work.nproc=", work.nproc)
- throw("work.nwait > work.nproc")
- }
- for i := 0; ; i++ {
- if work.full != 0 {
- decnwait := atomic.Xadd(&work.nwait, -1)
- if decnwait == work.nproc {
- println("runtime: work.nwait=", decnwait, "work.nproc=", work.nproc)
- throw("work.nwait > work.nproc")
- }
- b = (*workbuf)(work.full.pop())
- if b != nil {
- b.checknonempty()
- return b
- }
- incnwait := atomic.Xadd(&work.nwait, +1)
- if incnwait > work.nproc {
- println("runtime: work.nwait=", incnwait, "work.nproc=", work.nproc)
- throw("work.nwait > work.nproc")
- }
- }
- if work.nwait == work.nproc && work.markrootNext >= work.markrootJobs {
- return nil
- }
- if i < 10 {
- procyield(20)
- } else if i < 20 {
- osyield()
- } else {
- usleep(100)
- }
- }
-}
-
//go:nowritebarrier
func handoff(b *workbuf) *workbuf {
// Make new buffer with half of b's pointers.
diff --git a/src/runtime/mheap.go b/src/runtime/mheap.go
index 00ecfa2d66..7a11bdc058 100644
--- a/src/runtime/mheap.go
+++ b/src/runtime/mheap.go
@@ -82,7 +82,7 @@ type mheap struct {
// accounting for current progress. If we could only adjust
// the slope, it would create a discontinuity in debt if any
// progress has already been made.
- pagesInUse uint64 // pages of spans in stats _MSpanInUse; R/W with mheap.lock
+ pagesInUse uint64 // pages of spans in stats mSpanInUse; R/W with mheap.lock
pagesSwept uint64 // pages swept this cycle; updated atomically
pagesSweptBasis uint64 // pagesSwept to use as the origin of the sweep ratio; updated atomically
sweepHeapLiveBasis uint64 // value of heap_live to use as the origin of sweep ratio; written with lock, read without
@@ -199,18 +199,18 @@ type arenaHint struct {
// An MSpan is a run of pages.
//
-// When a MSpan is in the heap free list, state == MSpanFree
+// When a MSpan is in the heap free list, state == mSpanFree
// and heapmap(s->start) == span, heapmap(s->start+s->npages-1) == span.
//
-// When a MSpan is allocated, state == MSpanInUse or MSpanManual
+// When a MSpan is allocated, state == mSpanInUse or mSpanManual
// and heapmap(i) == span for all s->start <= i < s->start+s->npages.
// Every MSpan is in one doubly-linked list,
// either one of the MHeap's free lists or one of the
// MCentral's span lists.
-// An MSpan representing actual memory has state _MSpanInUse,
-// _MSpanManual, or _MSpanFree. Transitions between these states are
+// An MSpan representing actual memory has state mSpanInUse,
+// mSpanManual, or mSpanFree. Transitions between these states are
// constrained as follows:
//
// * A span may transition from free to in-use or manual during any GC
@@ -226,19 +226,19 @@ type arenaHint struct {
type mSpanState uint8
const (
- _MSpanDead mSpanState = iota
- _MSpanInUse // allocated for garbage collected heap
- _MSpanManual // allocated for manual management (e.g., stack allocator)
- _MSpanFree
+ mSpanDead mSpanState = iota
+ mSpanInUse // allocated for garbage collected heap
+ mSpanManual // allocated for manual management (e.g., stack allocator)
+ mSpanFree
)
// mSpanStateNames are the names of the span states, indexed by
// mSpanState.
var mSpanStateNames = []string{
- "_MSpanDead",
- "_MSpanInUse",
- "_MSpanManual",
- "_MSpanFree",
+ "mSpanDead",
+ "mSpanInUse",
+ "mSpanManual",
+ "mSpanFree",
}
// mSpanList heads a linked list of spans.
@@ -258,7 +258,7 @@ type mspan struct {
startAddr uintptr // address of first byte of span aka s.base()
npages uintptr // number of pages in span
- manualFreeList gclinkptr // list of free objects in _MSpanManual spans
+ manualFreeList gclinkptr // list of free objects in mSpanManual spans
// freeindex is the slot index between 0 and nelems at which to begin scanning
// for the next free object in this span.
@@ -317,6 +317,8 @@ type mspan struct {
// if sweepgen == h->sweepgen - 2, the span needs sweeping
// if sweepgen == h->sweepgen - 1, the span is currently being swept
// if sweepgen == h->sweepgen, the span is swept and ready to use
+ // if sweepgen == h->sweepgen + 1, the span was cached before sweep began and is still cached, and needs sweeping
+ // if sweepgen == h->sweepgen + 3, the span was swept and then cached and is still cached
// h->sweepgen is incremented by 2 after every GC
sweepgen uint32
@@ -324,7 +326,6 @@ type mspan struct {
baseMask uint16 // if non-0, elemsize is a power of 2, & this will get object allocation base
allocCount uint16 // number of allocated objects
spanclass spanClass // size class and noscan (uint8)
- incache bool // being used by an mcache
state mSpanState // mspaninuse etc
needzero uint8 // needs to be zeroed before allocation
divShift uint8 // for divide by elemsize - divMagic.shift
@@ -458,7 +459,7 @@ func (i arenaIdx) l2() uint {
}
// inheap reports whether b is a pointer into a (potentially dead) heap object.
-// It returns false for pointers into _MSpanManual spans.
+// It returns false for pointers into mSpanManual spans.
// Non-preemptible because it is used by write barriers.
//go:nowritebarrier
//go:nosplit
@@ -477,7 +478,7 @@ func inHeapOrStack(b uintptr) bool {
return false
}
switch s.state {
- case mSpanInUse, _MSpanManual:
+ case mSpanInUse, mSpanManual:
return b < s.limit
default:
return false
@@ -696,7 +697,7 @@ func (h *mheap) alloc_m(npage uintptr, spanclass spanClass, large bool) *mspan {
// able to map interior pointer to containing span.
atomic.Store(&s.sweepgen, h.sweepgen)
h.sweepSpans[h.sweepgen/2%2].push(s) // Add to swept in-use list.
- s.state = _MSpanInUse
+ s.state = mSpanInUse
s.allocCount = 0
s.spanclass = spanclass
if sizeclass := spanclass.sizeclass(); sizeclass == 0 {
@@ -788,7 +789,7 @@ func (h *mheap) allocManual(npage uintptr, stat *uint64) *mspan {
lock(&h.lock)
s := h.allocSpanLocked(npage, stat)
if s != nil {
- s.state = _MSpanManual
+ s.state = mSpanManual
s.manualFreeList = 0
s.allocCount = 0
s.spanclass = 0
@@ -829,7 +830,7 @@ func (h *mheap) setSpans(base, npage uintptr, s *mspan) {
// Allocates a span of the given size. h must be locked.
// The returned span has been removed from the
-// free list, but its state is still MSpanFree.
+// free list, but its state is still mSpanFree.
func (h *mheap) allocSpanLocked(npage uintptr, stat *uint64) *mspan {
var list *mSpanList
var s *mspan
@@ -857,7 +858,7 @@ func (h *mheap) allocSpanLocked(npage uintptr, stat *uint64) *mspan {
HaveSpan:
// Mark span in use.
- if s.state != _MSpanFree {
+ if s.state != mSpanFree {
throw("MHeap_AllocLocked - MSpan not free")
}
if s.npages < npage {
@@ -878,10 +879,10 @@ HaveSpan:
h.setSpan(t.base(), t)
h.setSpan(t.base()+t.npages*pageSize-1, t)
t.needzero = s.needzero
- s.state = _MSpanManual // prevent coalescing with s
- t.state = _MSpanManual
+ s.state = mSpanManual // prevent coalescing with s
+ t.state = mSpanManual
h.freeSpanLocked(t, false, false, s.unusedsince)
- s.state = _MSpanFree
+ s.state = mSpanFree
}
s.unusedsince = 0
@@ -930,7 +931,7 @@ func (h *mheap) grow(npage uintptr) bool {
s.init(uintptr(v), size/pageSize)
h.setSpans(s.base(), s.npages, s)
atomic.Store(&s.sweepgen, h.sweepgen)
- s.state = _MSpanInUse
+ s.state = mSpanInUse
h.pagesInUse += uint64(s.npages)
h.freeSpanLocked(s, false, true, 0)
return true
@@ -986,11 +987,11 @@ func (h *mheap) freeManual(s *mspan, stat *uint64) {
// s must be on a busy list (h.busy or h.busylarge) or unlinked.
func (h *mheap) freeSpanLocked(s *mspan, acctinuse, acctidle bool, unusedsince int64) {
switch s.state {
- case _MSpanManual:
+ case mSpanManual:
if s.allocCount != 0 {
throw("MHeap_FreeSpanLocked - invalid stack free")
}
- case _MSpanInUse:
+ case mSpanInUse:
if s.allocCount != 0 || s.sweepgen != h.sweepgen {
print("MHeap_FreeSpanLocked - span ", s, " ptr ", hex(s.base()), " allocCount ", s.allocCount, " sweepgen ", s.sweepgen, "/", h.sweepgen, "\n")
throw("MHeap_FreeSpanLocked - invalid free")
@@ -1006,7 +1007,7 @@ func (h *mheap) freeSpanLocked(s *mspan, acctinuse, acctidle bool, unusedsince i
if acctidle {
memstats.heap_idle += uint64(s.npages << _PageShift)
}
- s.state = _MSpanFree
+ s.state = mSpanFree
if s.inList() {
h.busyList(s.npages).remove(s)
}
@@ -1020,7 +1021,7 @@ func (h *mheap) freeSpanLocked(s *mspan, acctinuse, acctidle bool, unusedsince i
s.npreleased = 0
// Coalesce with earlier, later spans.
- if before := spanOf(s.base() - 1); before != nil && before.state == _MSpanFree {
+ if before := spanOf(s.base() - 1); before != nil && before.state == mSpanFree {
// Now adjust s.
s.startAddr = before.startAddr
s.npages += before.npages
@@ -1035,12 +1036,12 @@ func (h *mheap) freeSpanLocked(s *mspan, acctinuse, acctidle bool, unusedsince i
} else {
h.freeList(before.npages).remove(before)
}
- before.state = _MSpanDead
+ before.state = mSpanDead
h.spanalloc.free(unsafe.Pointer(before))
}
// Now check to see if next (greater addresses) span is free and can be coalesced.
- if after := spanOf(s.base() + s.npages*pageSize); after != nil && after.state == _MSpanFree {
+ if after := spanOf(s.base() + s.npages*pageSize); after != nil && after.state == mSpanFree {
s.npages += after.npages
s.npreleased += after.npreleased
s.needzero |= after.needzero
@@ -1050,7 +1051,7 @@ func (h *mheap) freeSpanLocked(s *mspan, acctinuse, acctidle bool, unusedsince i
} else {
h.freeList(after.npages).remove(after)
}
- after.state = _MSpanDead
+ after.state = mSpanDead
h.spanalloc.free(unsafe.Pointer(after))
}
@@ -1185,9 +1186,8 @@ func (span *mspan) init(base uintptr, npages uintptr) {
span.npages = npages
span.allocCount = 0
span.spanclass = 0
- span.incache = false
span.elemsize = 0
- span.state = _MSpanDead
+ span.state = mSpanDead
span.unusedsince = 0
span.npreleased = 0
span.speciallock.key = 0
@@ -1437,10 +1437,7 @@ func addfinalizer(p unsafe.Pointer, f *funcval, nret uintptr, fint *_type, ot *p
scanobject(base, gcw)
// Mark the finalizer itself, since the
// special isn't part of the GC'd heap.
- scanblock(uintptr(unsafe.Pointer(&s.fn)), sys.PtrSize, &oneptrmask[0], gcw)
- if gcBlackenPromptly {
- gcw.dispose()
- }
+ scanblock(uintptr(unsafe.Pointer(&s.fn)), sys.PtrSize, &oneptrmask[0], gcw, nil)
releasem(mp)
}
return true
diff --git a/src/runtime/mmap.go b/src/runtime/mmap.go
index fe09e7029e..2868f3fd4e 100644
--- a/src/runtime/mmap.go
+++ b/src/runtime/mmap.go
@@ -10,6 +10,7 @@
// +build !linux !arm64
// +build !js
// +build !darwin
+// +build !aix
package runtime
diff --git a/src/runtime/mprof.go b/src/runtime/mprof.go
index 43e4810d97..2bd41b650f 100644
--- a/src/runtime/mprof.go
+++ b/src/runtime/mprof.go
@@ -723,7 +723,7 @@ func GoroutineProfile(p []StackRecord) (n int, ok bool) {
isOK := func(gp1 *g) bool {
// Checking isSystemGoroutine here makes GoroutineProfile
// consistent with both NumGoroutine and Stack.
- return gp1 != gp && readgstatus(gp1) != _Gdead && !isSystemGoroutine(gp1)
+ return gp1 != gp && readgstatus(gp1) != _Gdead && !isSystemGoroutine(gp1, false)
}
stopTheWorld("profile")
diff --git a/src/runtime/mstats.go b/src/runtime/mstats.go
index f67d05414d..1bd6566052 100644
--- a/src/runtime/mstats.go
+++ b/src/runtime/mstats.go
@@ -38,7 +38,7 @@ type mstats struct {
heap_alloc uint64 // bytes allocated and not yet freed (same as alloc above)
heap_sys uint64 // virtual address space obtained from system for GC'd heap
heap_idle uint64 // bytes in idle spans
- heap_inuse uint64 // bytes in _MSpanInUse spans
+ heap_inuse uint64 // bytes in mSpanInUse spans
heap_released uint64 // bytes released to the os
heap_objects uint64 // total number of allocated objects
diff --git a/src/runtime/mwbbuf.go b/src/runtime/mwbbuf.go
index 4df16d55b8..f35f7286ac 100644
--- a/src/runtime/mwbbuf.go
+++ b/src/runtime/mwbbuf.go
@@ -79,7 +79,7 @@ const (
func (b *wbBuf) reset() {
start := uintptr(unsafe.Pointer(&b.buf[0]))
b.next = start
- if gcBlackenPromptly || writeBarrier.cgo {
+ if writeBarrier.cgo {
// Effectively disable the buffer by forcing a flush
// on every barrier.
b.end = uintptr(unsafe.Pointer(&b.buf[wbBufEntryPointers]))
@@ -107,6 +107,11 @@ func (b *wbBuf) discard() {
b.next = uintptr(unsafe.Pointer(&b.buf[0]))
}
+// empty returns true if b contains no pointers.
+func (b *wbBuf) empty() bool {
+ return b.next == uintptr(unsafe.Pointer(&b.buf[0]))
+}
+
// putFast adds old and new to the write barrier buffer and returns
// false if a flush is necessary. Callers should use this as:
//
@@ -270,9 +275,4 @@ func wbBufFlush1(_p_ *p) {
// Enqueue the greyed objects.
gcw.putBatch(ptrs[:pos])
- if gcphase == _GCmarktermination || gcBlackenPromptly {
- // Ps aren't allowed to cache work during mark
- // termination.
- gcw.dispose()
- }
}
diff --git a/src/runtime/netpoll.go b/src/runtime/netpoll.go
index f9c422650a..da822a7308 100644
--- a/src/runtime/netpoll.go
+++ b/src/runtime/netpoll.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris windows
+// +build aix darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris windows
package runtime
@@ -166,8 +166,8 @@ func poll_runtime_pollWait(pd *pollDesc, mode int) int {
if err != 0 {
return err
}
- // As for now only Solaris uses level-triggered IO.
- if GOOS == "solaris" {
+ // As for now only Solaris and AIX use level-triggered IO.
+ if GOOS == "solaris" || GOOS == "aix" {
netpollarm(pd, mode)
}
for !netpollblock(pd, int32(mode), false) {
diff --git a/src/runtime/netpoll_aix.go b/src/runtime/netpoll_aix.go
new file mode 100644
index 0000000000..1e886dae94
--- /dev/null
+++ b/src/runtime/netpoll_aix.go
@@ -0,0 +1,247 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import "unsafe"
+
+// This is based on the former libgo/runtime/netpoll_select.c implementation
+// except that it uses poll instead of select and is written in Go.
+// It's also based on Solaris implementation for the arming mechanisms
+
+//go:cgo_import_dynamic libc_poll poll "libc.a/shr_64.o"
+//go:linkname libc_poll libc_poll
+
+var libc_poll libFunc
+
+//go:nosplit
+func poll(pfds *pollfd, npfds uintptr, timeout uintptr) (int32, int32) {
+ r, err := syscall3(&libc_poll, uintptr(unsafe.Pointer(pfds)), npfds, timeout)
+ return int32(r), int32(err)
+}
+
+//go:nosplit
+func fcntl(fd, cmd int32, arg uintptr) int32 {
+ r, _ := syscall3(&libc_fcntl, uintptr(fd), uintptr(cmd), arg)
+ return int32(r)
+}
+
+// pollfd represents the poll structure for AIX operating system.
+type pollfd struct {
+ fd int32
+ events int16
+ revents int16
+}
+
+const _POLLIN = 0x0001
+const _POLLOUT = 0x0002
+const _POLLHUP = 0x2000
+const _POLLERR = 0x4000
+const _O_NONBLOCK = 0x4
+
+var (
+ pfds []pollfd
+ pds []*pollDesc
+ mtxpoll mutex
+ mtxset mutex
+ rdwake int32
+ wrwake int32
+ pendingUpdates int32
+)
+
+const pollVerbose = false
+
+func netpollinit() {
+ var p [2]int32
+
+ // Create the pipe we use to wakeup poll.
+ if err := pipe(&p[0]); err < 0 {
+ throw("netpollinit: failed to create pipe")
+ }
+ rdwake = p[0]
+ wrwake = p[1]
+
+ fl := uintptr(fcntl(rdwake, _F_GETFL, 0))
+ fcntl(rdwake, _F_SETFL, fl|_O_NONBLOCK)
+ fcntl(rdwake, _F_SETFD, _FD_CLOEXEC)
+
+ fl = uintptr(fcntl(wrwake, _F_GETFL, 0))
+ fcntl(wrwake, _F_SETFL, fl|_O_NONBLOCK)
+ fcntl(wrwake, _F_SETFD, _FD_CLOEXEC)
+
+ // Pre-allocate array of pollfd structures for poll.
+ if pollVerbose {
+ println("*** allocating")
+ }
+ pfds = make([]pollfd, 1, 128)
+ if pollVerbose {
+ println("*** allocating done", &pfds[0])
+ }
+
+ // Poll the read side of the pipe.
+ pfds[0].fd = rdwake
+ pfds[0].events = _POLLIN
+
+ pds = make([]*pollDesc, 1, 128)
+ pds[0] = nil
+}
+
+func netpolldescriptor() uintptr {
+ // Both fd must be returned
+ if rdwake > 0xFFFF || wrwake > 0xFFFF {
+ throw("netpolldescriptor: invalid fd number")
+ }
+ return uintptr(rdwake<<16 | wrwake)
+}
+
+// netpollwakeup writes on wrwake to wakeup poll before any changes.
+func netpollwakeup() {
+ if pendingUpdates == 0 {
+ pendingUpdates = 1
+ if pollVerbose {
+ println("*** writing 1 byte")
+ }
+ b := [1]byte{0}
+ write(uintptr(wrwake), unsafe.Pointer(&b[0]), 1)
+ }
+}
+
+func netpollopen(fd uintptr, pd *pollDesc) int32 {
+ if pollVerbose {
+ println("*** netpollopen", fd)
+ }
+ lock(&mtxpoll)
+ netpollwakeup()
+
+ lock(&mtxset)
+ unlock(&mtxpoll)
+
+ pd.user = uint32(len(pfds))
+ pfds = append(pfds, pollfd{fd: int32(fd)})
+ pds = append(pds, pd)
+ unlock(&mtxset)
+ return 0
+}
+
+func netpollclose(fd uintptr) int32 {
+ if pollVerbose {
+ println("*** netpollclose", fd)
+ }
+ lock(&mtxpoll)
+ netpollwakeup()
+
+ lock(&mtxset)
+ unlock(&mtxpoll)
+
+ for i := 0; i < len(pfds); i++ {
+ if pfds[i].fd == int32(fd) {
+ pfds[i] = pfds[len(pfds)-1]
+ pfds = pfds[:len(pfds)-1]
+
+ pds[i] = pds[len(pds)-1]
+ pds[i].user = uint32(i)
+ pds = pds[:len(pds)-1]
+ break
+ }
+ }
+ unlock(&mtxset)
+ return 0
+}
+
+func netpollarm(pd *pollDesc, mode int) {
+ if pollVerbose {
+ println("*** netpollarm", pd.fd, mode)
+ }
+ lock(&mtxpoll)
+ netpollwakeup()
+
+ lock(&mtxset)
+ unlock(&mtxpoll)
+
+ switch mode {
+ case 'r':
+ pfds[pd.user].events |= _POLLIN
+ case 'w':
+ pfds[pd.user].events |= _POLLOUT
+ }
+ unlock(&mtxset)
+}
+
+//go:nowritebarrierrec
+func netpoll(block bool) gList {
+ timeout := ^uintptr(0)
+ if !block {
+ timeout = 0
+ return gList{}
+ }
+ if pollVerbose {
+ println("*** netpoll", block)
+ }
+retry:
+ lock(&mtxpoll)
+ lock(&mtxset)
+ pendingUpdates = 0
+ unlock(&mtxpoll)
+
+ if pollVerbose {
+ println("*** netpoll before poll")
+ }
+ n, e := poll(&pfds[0], uintptr(len(pfds)), timeout)
+ if pollVerbose {
+ println("*** netpoll after poll", n)
+ }
+ if n < 0 {
+ if e != _EINTR {
+ println("errno=", e, " len(pfds)=", len(pfds))
+ throw("poll failed")
+ }
+ if pollVerbose {
+ println("*** poll failed")
+ }
+ unlock(&mtxset)
+ goto retry
+ }
+ // Check if some descriptors need to be changed
+ if n != 0 && pfds[0].revents&(_POLLIN|_POLLHUP|_POLLERR) != 0 {
+ var b [1]byte
+ for read(rdwake, unsafe.Pointer(&b[0]), 1) == 1 {
+ if pollVerbose {
+ println("*** read 1 byte from pipe")
+ }
+ }
+ // Do not look at the other fds in this case as the mode may have changed
+ // XXX only additions of flags are made, so maybe it is ok
+ unlock(&mtxset)
+ goto retry
+ }
+ var toRun gList
+ for i := 0; i < len(pfds) && n > 0; i++ {
+ pfd := &pfds[i]
+
+ var mode int32
+ if pfd.revents&(_POLLIN|_POLLHUP|_POLLERR) != 0 {
+ mode += 'r'
+ pfd.events &= ^_POLLIN
+ }
+ if pfd.revents&(_POLLOUT|_POLLHUP|_POLLERR) != 0 {
+ mode += 'w'
+ pfd.events &= ^_POLLOUT
+ }
+ if mode != 0 {
+ if pollVerbose {
+ println("*** netpollready i=", i, "revents=", pfd.revents, "events=", pfd.events, "pd=", pds[i])
+ }
+ netpollready(&toRun, pds[i], mode)
+ n--
+ }
+ }
+ unlock(&mtxset)
+ if block && toRun.empty() {
+ goto retry
+ }
+ if pollVerbose {
+ println("*** netpoll returning end")
+ }
+ return toRun
+}
diff --git a/src/runtime/os2_aix.go b/src/runtime/os2_aix.go
new file mode 100644
index 0000000000..9e26ce23fc
--- /dev/null
+++ b/src/runtime/os2_aix.go
@@ -0,0 +1,479 @@
+// Copyright 2018 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.
+
+// This file contains main runtime AIX syscalls.
+// Pollset syscalls are in netpoll_aix.go.
+// The implementation is based on Solaris and Windows.
+// Each syscall is made by calling its libc symbol using asmcgocall and asmsyscall6
+// asssembly functions.
+
+package runtime
+
+import (
+ "unsafe"
+)
+
+// Symbols imported for __start function.
+
+//go:cgo_import_dynamic libc___n_pthreads __n_pthreads "libpthread.a/shr_xpg5_64.o"
+//go:cgo_import_dynamic libc___mod_init __mod_init "libc.a/shr_64.o"
+//go:linkname libc___n_pthreads libc___n_pthread
+//go:linkname libc___mod_init libc___mod_init
+
+var (
+ libc___n_pthread,
+ libc___mod_init libFunc
+)
+
+// Syscalls
+
+//go:cgo_import_dynamic libc__Errno _Errno "libc.a/shr_64.o"
+//go:cgo_import_dynamic libc_clock_gettime clock_gettime "libc.a/shr_64.o"
+//go:cgo_import_dynamic libc_close close "libc.a/shr_64.o"
+//go:cgo_import_dynamic libc_exit exit "libc.a/shr_64.o"
+//go:cgo_import_dynamic libc_getpid getpid "libc.a/shr_64.o"
+//go:cgo_import_dynamic libc_kill kill "libc.a/shr_64.o"
+//go:cgo_import_dynamic libc_madvise madvise "libc.a/shr_64.o"
+//go:cgo_import_dynamic libc_malloc malloc "libc.a/shr_64.o"
+//go:cgo_import_dynamic libc_mmap mmap "libc.a/shr_64.o"
+//go:cgo_import_dynamic libc_munmap munmap "libc.a/shr_64.o"
+//go:cgo_import_dynamic libc_open open "libc.a/shr_64.o"
+//go:cgo_import_dynamic libc_pipe pipe "libc.a/shr_64.o"
+//go:cgo_import_dynamic libc_raise raise "libc.a/shr_64.o"
+//go:cgo_import_dynamic libc_read read "libc.a/shr_64.o"
+//go:cgo_import_dynamic libc_sched_yield sched_yield "libc.a/shr_64.o"
+//go:cgo_import_dynamic libc_sem_init sem_init "libc.a/shr_64.o"
+//go:cgo_import_dynamic libc_sem_post sem_post "libc.a/shr_64.o"
+//go:cgo_import_dynamic libc_sem_timedwait sem_timedwait "libc.a/shr_64.o"
+//go:cgo_import_dynamic libc_sem_wait sem_wait "libc.a/shr_64.o"
+//go:cgo_import_dynamic libc_setitimer setitimer "libc.a/shr_64.o"
+//go:cgo_import_dynamic libc_sigaction sigaction "libc.a/shr_64.o"
+//go:cgo_import_dynamic libc_sigaltstack sigaltstack "libc.a/shr_64.o"
+//go:cgo_import_dynamic libc_sysconf sysconf "libc.a/shr_64.o"
+//go:cgo_import_dynamic libc_usleep usleep "libc.a/shr_64.o"
+//go:cgo_import_dynamic libc_write write "libc.a/shr_64.o"
+
+//go:cgo_import_dynamic libpthread___pth_init __pth_init "libpthread.a/shr_xpg5_64.o"
+//go:cgo_import_dynamic libpthread_attr_destroy pthread_attr_destroy "libpthread.a/shr_xpg5_64.o"
+//go:cgo_import_dynamic libpthread_attr_init pthread_attr_init "libpthread.a/shr_xpg5_64.o"
+//go:cgo_import_dynamic libpthread_attr_getstacksize pthread_attr_getstacksize "libpthread.a/shr_xpg5_64.o"
+//go:cgo_import_dynamic libpthread_attr_setstacksize pthread_attr_setstacksize "libpthread.a/shr_xpg5_64.o"
+//go:cgo_import_dynamic libpthread_attr_setdetachstate pthread_attr_setdetachstate "libpthread.a/shr_xpg5_64.o"
+//go:cgo_import_dynamic libpthread_attr_setstackaddr pthread_attr_setstackaddr "libpthread.a/shr_xpg5_64.o"
+//go:cgo_import_dynamic libpthread_create pthread_create "libpthread.a/shr_xpg5_64.o"
+//go:cgo_import_dynamic libpthread_sigthreadmask sigthreadmask "libpthread.a/shr_xpg5_64.o"
+
+//go:linkname libc__Errno libc__Errno
+//go:linkname libc_clock_gettime libc_clock_gettime
+//go:linkname libc_close libc_close
+//go:linkname libc_exit libc_exit
+//go:linkname libc_getpid libc_getpid
+//go:linkname libc_kill libc_kill
+//go:linkname libc_madvise libc_madvise
+//go:linkname libc_malloc libc_malloc
+//go:linkname libc_mmap libc_mmap
+//go:linkname libc_munmap libc_munmap
+//go:linkname libc_open libc_open
+//go:linkname libc_pipe libc_pipe
+//go:linkname libc_raise libc_raise
+//go:linkname libc_read libc_read
+//go:linkname libc_sched_yield libc_sched_yield
+//go:linkname libc_sem_init libc_sem_init
+//go:linkname libc_sem_post libc_sem_post
+//go:linkname libc_sem_timedwait libc_sem_timedwait
+//go:linkname libc_sem_wait libc_sem_wait
+//go:linkname libc_setitimer libc_setitimer
+//go:linkname libc_sigaction libc_sigaction
+//go:linkname libc_sigaltstack libc_sigaltstack
+//go:linkname libc_sysconf libc_sysconf
+//go:linkname libc_usleep libc_usleep
+//go:linkname libc_write libc_write
+
+//go:linkname libpthread___pth_init libpthread___pth_init
+//go:linkname libpthread_attr_destroy libpthread_attr_destroy
+//go:linkname libpthread_attr_init libpthread_attr_init
+//go:linkname libpthread_attr_getstacksize libpthread_attr_getstacksize
+//go:linkname libpthread_attr_setstacksize libpthread_attr_setstacksize
+//go:linkname libpthread_attr_setdetachstate libpthread_attr_setdetachstate
+//go:linkname libpthread_attr_setstackaddr libpthread_attr_setstackaddr
+//go:linkname libpthread_create libpthread_create
+//go:linkname libpthread_sigthreadmask libpthread_sigthreadmask
+
+var (
+ //libc
+ libc__Errno,
+ libc_clock_gettime,
+ libc_close,
+ libc_exit,
+ libc_getpid,
+ libc_kill,
+ libc_madvise,
+ libc_malloc,
+ libc_mmap,
+ libc_munmap,
+ libc_open,
+ libc_pipe,
+ libc_raise,
+ libc_read,
+ libc_sched_yield,
+ libc_sem_init,
+ libc_sem_post,
+ libc_sem_timedwait,
+ libc_sem_wait,
+ libc_setitimer,
+ libc_sigaction,
+ libc_sigaltstack,
+ libc_sysconf,
+ libc_usleep,
+ libc_write,
+ //libpthread
+ libpthread___pth_init,
+ libpthread_attr_destroy,
+ libpthread_attr_init,
+ libpthread_attr_getstacksize,
+ libpthread_attr_setstacksize,
+ libpthread_attr_setdetachstate,
+ libpthread_attr_setstackaddr,
+ libpthread_create,
+ libpthread_sigthreadmask libFunc
+)
+
+type libFunc uintptr
+
+// asmsyscall6 calls the libc symbol using a C convention.
+// It's defined in sys_aix_ppc64.go.
+var asmsyscall6 libFunc
+
+//go:nowritebarrier
+//go:nosplit
+func syscall0(fn *libFunc) (r, err uintptr) {
+ c := &getg().m.libcall
+ c.fn = uintptr(unsafe.Pointer(fn))
+ c.n = 0
+ c.args = uintptr(noescape(unsafe.Pointer(&fn))) // it's unused but must be non-nil, otherwise crashes
+
+ asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c))
+
+ return c.r1, c.err
+}
+
+//go:nowritebarrier
+//go:nosplit
+func syscall1(fn *libFunc, a0 uintptr) (r, err uintptr) {
+ c := &getg().m.libcall
+ c.fn = uintptr(unsafe.Pointer(fn))
+ c.n = 1
+ c.args = uintptr(noescape(unsafe.Pointer(&a0)))
+
+ asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c))
+
+ return c.r1, c.err
+}
+
+//go:nowritebarrier
+//go:nosplit
+func syscall2(fn *libFunc, a0, a1 uintptr) (r, err uintptr) {
+ c := &getg().m.libcall
+ c.fn = uintptr(unsafe.Pointer(fn))
+ c.n = 2
+ c.args = uintptr(noescape(unsafe.Pointer(&a0)))
+
+ asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c))
+
+ return c.r1, c.err
+}
+
+//go:nowritebarrier
+//go:nosplit
+func syscall3(fn *libFunc, a0, a1, a2 uintptr) (r, err uintptr) {
+ c := &getg().m.libcall
+ c.fn = uintptr(unsafe.Pointer(fn))
+ c.n = 3
+ c.args = uintptr(noescape(unsafe.Pointer(&a0)))
+
+ asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c))
+
+ return c.r1, c.err
+}
+
+//go:nowritebarrier
+//go:nosplit
+func syscall4(fn *libFunc, a0, a1, a2, a3 uintptr) (r, err uintptr) {
+ c := &getg().m.libcall
+ c.fn = uintptr(unsafe.Pointer(fn))
+ c.n = 4
+ c.args = uintptr(noescape(unsafe.Pointer(&a0)))
+
+ asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c))
+
+ return c.r1, c.err
+}
+
+//go:nowritebarrier
+//go:nosplit
+func syscall5(fn *libFunc, a0, a1, a2, a3, a4 uintptr) (r, err uintptr) {
+ c := &getg().m.libcall
+ c.fn = uintptr(unsafe.Pointer(fn))
+ c.n = 5
+ c.args = uintptr(noescape(unsafe.Pointer(&a0)))
+
+ asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c))
+
+ return c.r1, c.err
+}
+
+//go:nowritebarrier
+//go:nosplit
+func syscall6(fn *libFunc, a0, a1, a2, a3, a4, a5 uintptr) (r, err uintptr) {
+ c := &getg().m.libcall
+ c.fn = uintptr(unsafe.Pointer(fn))
+ c.n = 6
+ c.args = uintptr(noescape(unsafe.Pointer(&a0)))
+
+ asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c))
+
+ return c.r1, c.err
+}
+
+//go:nosplit
+func exit(code int32) {
+ syscall1(&libc_exit, uintptr(code))
+}
+
+//go:nosplit
+func write(fd uintptr, p unsafe.Pointer, n int32) int32 {
+ r, _ := syscall3(&libc_write, uintptr(fd), uintptr(p), uintptr(n))
+ return int32(r)
+
+}
+
+//go:nosplit
+func read(fd int32, p unsafe.Pointer, n int32) int32 {
+ r, _ := syscall3(&libc_read, uintptr(fd), uintptr(p), uintptr(n))
+ return int32(r)
+}
+
+//go:nosplit
+func open(name *byte, mode, perm int32) int32 {
+ r, _ := syscall3(&libc_open, uintptr(unsafe.Pointer(name)), uintptr(mode), uintptr(perm))
+ return int32(r)
+}
+
+//go:nosplit
+func closefd(fd int32) int32 {
+ r, _ := syscall1(&libc_close, uintptr(fd))
+ return int32(r)
+}
+
+//go:nosplit
+func pipe(fd *int32) int32 {
+ r, _ := syscall1(&libc_pipe, uintptr(unsafe.Pointer(fd)))
+ return int32(r)
+}
+
+// mmap calls the mmap system call.
+// We only pass the lower 32 bits of file offset to the
+// assembly routine; the higher bits (if required), should be provided
+// by the assembly routine as 0.
+// The err result is an OS error code such as ENOMEM.
+//go:nosplit
+func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) (p unsafe.Pointer, err int) {
+ r, err0 := syscall6(&libc_mmap, uintptr(addr), uintptr(n), uintptr(prot), uintptr(flags), uintptr(fd), uintptr(off))
+ return unsafe.Pointer(r), int(err0)
+}
+
+//go:nosplit
+func munmap(addr unsafe.Pointer, n uintptr) {
+ r, err := syscall2(&libc_munmap, uintptr(addr), uintptr(n))
+ if int32(r) == -1 {
+ println("syscall munmap failed: ", hex(err))
+ throw("syscall munmap")
+ }
+}
+
+//go:nosplit
+func madvise(addr unsafe.Pointer, n uintptr, flags int32) {
+ r, err := syscall3(&libc_madvise, uintptr(addr), uintptr(n), uintptr(flags))
+ if int32(r) == -1 {
+ println("syscall madvise failed: ", hex(err))
+ throw("syscall madvise")
+ }
+}
+
+//go:nosplit
+func sigaction(sig uintptr, new, old *sigactiont) {
+ r, err := syscall3(&libc_sigaction, sig, uintptr(unsafe.Pointer(new)), uintptr(unsafe.Pointer(old)))
+ if int32(r) == -1 {
+ println("Sigaction failed for sig: ", sig, " with error:", hex(err))
+ throw("syscall sigaction")
+ }
+}
+
+//go:nosplit
+func sigaltstack(new, old *stackt) {
+ r, err := syscall2(&libc_sigaltstack, uintptr(unsafe.Pointer(new)), uintptr(unsafe.Pointer(old)))
+ if int32(r) == -1 {
+ println("syscall sigaltstack failed: ", hex(err))
+ throw("syscall sigaltstack")
+ }
+}
+
+//go:nosplit
+func usleep(us uint32) {
+ r, err := syscall1(&libc_usleep, uintptr(us))
+ if int32(r) == -1 {
+ println("syscall usleep failed: ", hex(err))
+ throw("syscall usleep")
+ }
+}
+
+//go:nosplit
+func clock_gettime(clockid int32, tp *timespec) int32 {
+ r, _ := syscall2(&libc_clock_gettime, uintptr(clockid), uintptr(unsafe.Pointer(tp)))
+ return int32(r)
+}
+
+//go:nosplit
+func setitimer(mode int32, new, old *itimerval) {
+ r, err := syscall3(&libc_setitimer, uintptr(mode), uintptr(unsafe.Pointer(new)), uintptr(unsafe.Pointer(old)))
+ if int32(r) == -1 {
+ println("syscall setitimer failed: ", hex(err))
+ throw("syscall setitimer")
+ }
+}
+
+//go:nosplit
+func malloc(size uintptr) unsafe.Pointer {
+ r, _ := syscall1(&libc_malloc, size)
+ return unsafe.Pointer(r)
+}
+
+//go:nosplit
+func sem_init(sem *semt, pshared int32, value uint32) int32 {
+ r, _ := syscall3(&libc_sem_init, uintptr(unsafe.Pointer(sem)), uintptr(pshared), uintptr(value))
+ return int32(r)
+}
+
+//go:nosplit
+func sem_wait(sem *semt) (int32, int32) {
+ r, err := syscall1(&libc_sem_wait, uintptr(unsafe.Pointer(sem)))
+ return int32(r), int32(err)
+}
+
+//go:nosplit
+func sem_post(sem *semt) int32 {
+ r, _ := syscall1(&libc_sem_post, uintptr(unsafe.Pointer(sem)))
+ return int32(r)
+}
+
+//go:nosplit
+func sem_timedwait(sem *semt, timeout *timespec) (int32, int32) {
+ r, err := syscall2(&libc_sem_timedwait, uintptr(unsafe.Pointer(sem)), uintptr(unsafe.Pointer(timeout)))
+ return int32(r), int32(err)
+}
+
+//go:nosplit
+func raise(sig uint32) {
+ r, err := syscall1(&libc_raise, uintptr(sig))
+ if int32(r) == -1 {
+ println("syscall raise failed: ", hex(err))
+ throw("syscall raise")
+ }
+}
+
+//go:nosplit
+func raiseproc(sig uint32) {
+ pid, err := syscall0(&libc_getpid)
+ if int32(pid) == -1 {
+ println("syscall getpid failed: ", hex(err))
+ throw("syscall raiseproc")
+ }
+
+ syscall2(&libc_kill, pid, uintptr(sig))
+}
+
+func osyield1()
+
+//go:nosplit
+func osyield() {
+ _g_ := getg()
+
+ // Check the validity of m because we might be called in cgo callback
+ // path early enough where there isn't a m available yet.
+ if _g_ != nil && _g_.m != nil {
+ r, err := syscall0(&libc_sched_yield)
+ if int32(r) == -1 {
+ println("syscall osyield failed: ", hex(err))
+ throw("syscall osyield")
+ }
+ return
+ }
+ osyield1()
+}
+
+//go:nosplit
+func sysconf(name int32) uintptr {
+ r, _ := syscall1(&libc_sysconf, uintptr(name))
+ if int32(r) == -1 {
+ throw("syscall sysconf")
+ }
+ return r
+
+}
+
+// pthread functions returns its error code in the main return value
+// Therefore, err returns by syscall means nothing and must not be used
+
+//go:nosplit
+func pthread_attr_destroy(attr *pthread_attr) int32 {
+ r, _ := syscall1(&libpthread_attr_destroy, uintptr(unsafe.Pointer(attr)))
+ return int32(r)
+}
+
+//go:nosplit
+func pthread_attr_init(attr *pthread_attr) int32 {
+ r, _ := syscall1(&libpthread_attr_init, uintptr(unsafe.Pointer(attr)))
+ return int32(r)
+}
+
+//go:nosplit
+func pthread_attr_setdetachstate(attr *pthread_attr, state int32) int32 {
+ r, _ := syscall2(&libpthread_attr_setdetachstate, uintptr(unsafe.Pointer(attr)), uintptr(state))
+ return int32(r)
+}
+
+//go:nosplit
+func pthread_attr_setstackaddr(attr *pthread_attr, stk unsafe.Pointer) int32 {
+ r, _ := syscall2(&libpthread_attr_setstackaddr, uintptr(unsafe.Pointer(attr)), uintptr(stk))
+ return int32(r)
+}
+
+//go:nosplit
+func pthread_attr_getstacksize(attr *pthread_attr, size *uint64) int32 {
+ r, _ := syscall2(&libpthread_attr_getstacksize, uintptr(unsafe.Pointer(attr)), uintptr(unsafe.Pointer(size)))
+ return int32(r)
+}
+
+//go:nosplit
+func pthread_attr_setstacksize(attr *pthread_attr, size uint64) int32 {
+ r, _ := syscall2(&libpthread_attr_setstacksize, uintptr(unsafe.Pointer(attr)), uintptr(size))
+ return int32(r)
+}
+
+//go:nosplit
+func pthread_create(tid *pthread, attr *pthread_attr, fn *funcDescriptor, arg unsafe.Pointer) int32 {
+ r, _ := syscall4(&libpthread_create, uintptr(unsafe.Pointer(tid)), uintptr(unsafe.Pointer(attr)), uintptr(unsafe.Pointer(fn)), uintptr(arg))
+ return int32(r)
+}
+
+// On multi-thread program, sigprocmask must not be called.
+// It's replaced by sigthreadmask.
+//go:nosplit
+func sigprocmask(how int32, new, old *sigset) {
+ r, err := syscall3(&libpthread_sigthreadmask, uintptr(how), uintptr(unsafe.Pointer(new)), uintptr(unsafe.Pointer(old)))
+ if int32(r) != 0 {
+ println("syscall sigthreadmask failed: ", hex(err))
+ throw("syscall sigthreadmask")
+ }
+}
diff --git a/src/runtime/os_aix.go b/src/runtime/os_aix.go
new file mode 100644
index 0000000000..31590f22d8
--- /dev/null
+++ b/src/runtime/os_aix.go
@@ -0,0 +1,262 @@
+// Copyright 2018 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 aix
+
+package runtime
+
+import (
+ "unsafe"
+)
+
+const (
+ threadStackSize = 0x100000 // size of a thread stack allocated by OS
+)
+
+// funcDescriptor is a structure representing a function descriptor
+// A variable with this type is always created in assembler
+type funcDescriptor struct {
+ fn uintptr
+ toc uintptr
+ envPointer uintptr // unused in Golang
+}
+
+type mOS struct {
+ waitsema uintptr // semaphore for parking on locks
+ perrno uintptr // pointer to tls errno
+}
+
+//go:nosplit
+func semacreate(mp *m) {
+ if mp.waitsema != 0 {
+ return
+ }
+
+ var sem *semt
+
+ // Call libc's malloc rather than malloc. This will
+ // allocate space on the C heap. We can't call mallocgc
+ // here because it could cause a deadlock.
+ sem = (*semt)(malloc(unsafe.Sizeof(*sem)))
+ if sem_init(sem, 0, 0) != 0 {
+ throw("sem_init")
+ }
+ mp.waitsema = uintptr(unsafe.Pointer(sem))
+}
+
+//go:nosplit
+func semasleep(ns int64) int32 {
+ _m_ := getg().m
+ if ns >= 0 {
+ var ts timespec
+
+ if clock_gettime(_CLOCK_REALTIME, &ts) != 0 {
+ throw("clock_gettime")
+ }
+ ts.tv_sec += ns / 1e9
+ ts.tv_nsec += ns % 1e9
+ if ts.tv_nsec >= 1e9 {
+ ts.tv_sec++
+ ts.tv_nsec -= 1e9
+ }
+
+ if r, err := sem_timedwait((*semt)(unsafe.Pointer(_m_.waitsema)), &ts); r != 0 {
+ if err == _ETIMEDOUT || err == _EAGAIN || err == _EINTR {
+ return -1
+ }
+ println("sem_timedwait err ", err, " ts.tv_sec ", ts.tv_sec, " ts.tv_nsec ", ts.tv_nsec, " ns ", ns, " id ", _m_.id)
+ throw("sem_timedwait")
+ }
+ return 0
+ }
+ for {
+ r1, err := sem_wait((*semt)(unsafe.Pointer(_m_.waitsema)))
+ if r1 == 0 {
+ break
+ }
+ if err == _EINTR {
+ continue
+ }
+ throw("sem_wait")
+ }
+ return 0
+}
+
+//go:nosplit
+func semawakeup(mp *m) {
+ if sem_post((*semt)(unsafe.Pointer(mp.waitsema))) != 0 {
+ throw("sem_post")
+ }
+}
+
+func osinit() {
+ ncpu = int32(sysconf(__SC_NPROCESSORS_ONLN))
+ physPageSize = sysconf(__SC_PAGE_SIZE)
+}
+
+// Ms related functions
+func mpreinit(mp *m) {
+ mp.gsignal = malg(32 * 1024) // AIX wants >= 8K
+ mp.gsignal.m = mp
+}
+
+// errno address must be retrieved by calling _Errno libc function.
+// This will return a pointer to errno
+func miniterrno() {
+ mp := getg().m
+ r, _ := syscall0(&libc__Errno)
+ mp.perrno = r
+
+}
+
+func minit() {
+ miniterrno()
+ minitSignals()
+}
+
+func unminit() {
+ unminitSignals()
+}
+
+// tstart is a function descriptor to _tstart defined in assembly.
+var tstart funcDescriptor
+
+func newosproc(mp *m) {
+ var (
+ attr pthread_attr
+ oset sigset
+ tid pthread
+ )
+
+ if pthread_attr_init(&attr) != 0 {
+ throw("pthread_attr_init")
+ }
+
+ if pthread_attr_setstacksize(&attr, threadStackSize) != 0 {
+ throw("pthread_attr_getstacksize")
+ }
+
+ if pthread_attr_setdetachstate(&attr, _PTHREAD_CREATE_DETACHED) != 0 {
+ throw("pthread_attr_setdetachstate")
+ }
+
+ // Disable signals during create, so that the new thread starts
+ // with signals disabled. It will enable them in minit.
+ sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
+ var ret int32
+ for tries := 0; tries < 20; tries++ {
+ // pthread_create can fail with EAGAIN for no reasons
+ // but it will be ok if it retries.
+ ret = pthread_create(&tid, &attr, &tstart, unsafe.Pointer(mp))
+ if ret != _EAGAIN {
+ break
+ }
+ usleep(uint32(tries+1) * 1000) // Milliseconds.
+ }
+ sigprocmask(_SIG_SETMASK, &oset, nil)
+ if ret != 0 {
+ print("runtime: failed to create new OS thread (have ", mcount(), " already; errno=", ret, ")\n")
+ if ret == _EAGAIN {
+ println("runtime: may need to increase max user processes (ulimit -u)")
+ }
+ throw("newosproc")
+ }
+
+}
+
+func exitThread(wait *uint32) {
+ // We should never reach exitThread on AIX because we let
+ // libc clean up threads.
+ throw("exitThread")
+}
+
+var urandom_dev = []byte("/dev/urandom\x00")
+
+//go:nosplit
+func getRandomData(r []byte) {
+ fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0)
+ n := read(fd, unsafe.Pointer(&r[0]), int32(len(r)))
+ closefd(fd)
+ extendRandom(r, int(n))
+}
+
+func goenvs() {
+ goenvs_unix()
+}
+
+/* SIGNAL */
+
+const (
+ _NSIG = 256
+)
+
+// sigtramp is a function descriptor to _sigtramp defined in assembly
+var sigtramp funcDescriptor
+
+//go:nosplit
+//go:nowritebarrierrec
+func setsig(i uint32, fn uintptr) {
+ var sa sigactiont
+ sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART
+ sa.sa_mask = sigset_all
+ if fn == funcPC(sighandler) {
+ fn = uintptr(unsafe.Pointer(&sigtramp))
+ }
+ sa.sa_handler = fn
+ sigaction(uintptr(i), &sa, nil)
+
+}
+
+//go:nosplit
+//go:nowritebarrierrec
+func setsigstack(i uint32) {
+ throw("Not yet implemented\n")
+}
+
+//go:nosplit
+//go:nowritebarrierrec
+func getsig(i uint32) uintptr {
+ var sa sigactiont
+ sigaction(uintptr(i), nil, &sa)
+ return sa.sa_handler
+}
+
+// setSignaltstackSP sets the ss_sp field of a stackt.
+//go:nosplit
+func setSignalstackSP(s *stackt, sp uintptr) {
+ *(*uintptr)(unsafe.Pointer(&s.ss_sp)) = sp
+}
+
+func (c *sigctxt) fixsigcode(sig uint32) {
+}
+
+func sigaddset(mask *sigset, i int) {
+ (*mask)[(i-1)/64] |= 1 << ((uint32(i) - 1) & 63)
+}
+
+func sigdelset(mask *sigset, i int) {
+ (*mask)[(i-1)/64] &^= 1 << ((uint32(i) - 1) & 63)
+}
+
+const (
+ _CLOCK_REALTIME = 9
+ _CLOCK_MONOTONIC = 10
+)
+
+//go:nosplit
+func nanotime() int64 {
+ tp := &timespec{}
+ if clock_gettime(_CLOCK_REALTIME, tp) != 0 {
+ throw("syscall clock_gettime failed")
+ }
+ return tp.tv_sec*1000000000 + tp.tv_nsec
+}
+
+func walltime() (sec int64, nsec int32) {
+ ts := &timespec{}
+ if clock_gettime(_CLOCK_REALTIME, ts) != 0 {
+ throw("syscall clock_gettime failed")
+ }
+ return ts.tv_sec, int32(ts.tv_nsec)
+}
diff --git a/src/runtime/os_darwin.go b/src/runtime/os_darwin.go
index d2144edf2e..26b02820cd 100644
--- a/src/runtime/os_darwin.go
+++ b/src/runtime/os_darwin.go
@@ -34,6 +34,10 @@ func semacreate(mp *m) {
//go:nosplit
func semasleep(ns int64) int32 {
+ var start int64
+ if ns >= 0 {
+ start = nanotime()
+ }
mp := getg().m
pthread_mutex_lock(&mp.mutex)
for {
@@ -43,8 +47,13 @@ func semasleep(ns int64) int32 {
return 0
}
if ns >= 0 {
+ spent := nanotime() - start
+ if spent >= ns {
+ pthread_mutex_unlock(&mp.mutex)
+ return -1
+ }
var t timespec
- t.set_nsec(ns)
+ t.set_nsec(ns - spent)
err := pthread_cond_timedwait_relative_np(&mp.cond, &mp.mutex, &t)
if err == _ETIMEDOUT {
pthread_mutex_unlock(&mp.mutex)
diff --git a/src/runtime/os_nacl.go b/src/runtime/os_nacl.go
index 23ab03b953..ac7bf69582 100644
--- a/src/runtime/os_nacl.go
+++ b/src/runtime/os_nacl.go
@@ -197,23 +197,23 @@ func semacreate(mp *m) {
//go:nosplit
func semasleep(ns int64) int32 {
var ret int32
-
systemstack(func() {
_g_ := getg()
if nacl_mutex_lock(_g_.m.waitsemalock) < 0 {
throw("semasleep")
}
-
+ var ts timespec
+ if ns >= 0 {
+ end := ns + nanotime()
+ ts.tv_sec = end / 1e9
+ ts.tv_nsec = int32(end % 1e9)
+ }
for _g_.m.waitsemacount == 0 {
if ns < 0 {
if nacl_cond_wait(_g_.m.waitsema, _g_.m.waitsemalock) < 0 {
throw("semasleep")
}
} else {
- var ts timespec
- end := ns + nanotime()
- ts.tv_sec = end / 1e9
- ts.tv_nsec = int32(end % 1e9)
r := nacl_cond_timed_wait_abs(_g_.m.waitsema, _g_.m.waitsemalock, &ts)
if r == -_ETIMEDOUT {
nacl_mutex_unlock(_g_.m.waitsemalock)
diff --git a/src/runtime/os_netbsd.go b/src/runtime/os_netbsd.go
index a9bf407a36..7deab3ed03 100644
--- a/src/runtime/os_netbsd.go
+++ b/src/runtime/os_netbsd.go
@@ -126,15 +126,9 @@ func semacreate(mp *m) {
//go:nosplit
func semasleep(ns int64) int32 {
_g_ := getg()
-
- // Compute sleep deadline.
- var tsp *timespec
- var ts timespec
+ var deadline int64
if ns >= 0 {
- var nsec int32
- ts.set_sec(timediv(ns, 1000000000, &nsec))
- ts.set_nsec(nsec)
- tsp = &ts
+ deadline = nanotime() + ns
}
for {
@@ -147,18 +141,21 @@ func semasleep(ns int64) int32 {
}
// Sleep until unparked by semawakeup or timeout.
+ var tsp *timespec
+ var ts timespec
+ if ns >= 0 {
+ wait := deadline - nanotime()
+ if wait <= 0 {
+ return -1
+ }
+ var nsec int32
+ ts.set_sec(timediv(wait, 1000000000, &nsec))
+ ts.set_nsec(nsec)
+ tsp = &ts
+ }
ret := lwp_park(_CLOCK_MONOTONIC, _TIMER_RELTIME, tsp, 0, unsafe.Pointer(&_g_.m.waitsemacount), nil)
if ret == _ETIMEDOUT {
return -1
- } else if ret == _EINTR && ns >= 0 {
- // Avoid sleeping forever if we keep getting
- // interrupted (for example by the profiling
- // timer). It would be if tsp upon return had the
- // remaining time to sleep, but this is good enough.
- var nsec int32
- ns /= 2
- ts.set_sec(timediv(ns, 1000000000, &nsec))
- ts.set_nsec(nsec)
}
}
}
diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go
index 5607bf95c1..03dd95bf17 100644
--- a/src/runtime/os_windows.go
+++ b/src/runtime/os_windows.go
@@ -43,6 +43,7 @@ const (
//go:cgo_import_dynamic runtime._SetWaitableTimer SetWaitableTimer%6 "kernel32.dll"
//go:cgo_import_dynamic runtime._SuspendThread SuspendThread%1 "kernel32.dll"
//go:cgo_import_dynamic runtime._SwitchToThread SwitchToThread%0 "kernel32.dll"
+//go:cgo_import_dynamic runtime._TlsAlloc TlsAlloc%0 "kernel32.dll"
//go:cgo_import_dynamic runtime._VirtualAlloc VirtualAlloc%4 "kernel32.dll"
//go:cgo_import_dynamic runtime._VirtualFree VirtualFree%3 "kernel32.dll"
//go:cgo_import_dynamic runtime._VirtualQuery VirtualQuery%3 "kernel32.dll"
@@ -91,6 +92,7 @@ var (
_SetWaitableTimer,
_SuspendThread,
_SwitchToThread,
+ _TlsAlloc,
_VirtualAlloc,
_VirtualFree,
_VirtualQuery,
@@ -856,18 +858,38 @@ func profileloop()
var profiletimer uintptr
-func profilem(mp *m) {
+func profilem(mp *m, thread uintptr) {
var r *context
rbuf := make([]byte, unsafe.Sizeof(*r)+15)
- tls := &mp.tls[0]
- gp := *((**g)(unsafe.Pointer(tls)))
-
// align Context to 16 bytes
r = (*context)(unsafe.Pointer((uintptr(unsafe.Pointer(&rbuf[15]))) &^ 15))
r.contextflags = _CONTEXT_CONTROL
- stdcall2(_GetThreadContext, mp.thread, uintptr(unsafe.Pointer(r)))
- sigprof(r.ip(), r.sp(), 0, gp, mp)
+ stdcall2(_GetThreadContext, thread, uintptr(unsafe.Pointer(r)))
+
+ var gp *g
+ switch GOARCH {
+ default:
+ panic("unsupported architecture")
+ case "arm":
+ // TODO(jordanrh1): this is incorrect when Go is executing
+ // on the system or signal stacks because curg returns
+ // the current user g. The true g is stored in thread
+ // local storage, which we cannot access from another CPU.
+ // We cannot pull R10 from the thread context because
+ // it might be executing C code, in which case R10
+ // would not be g.
+ gp = mp.curg
+ case "386", "amd64":
+ tls := &mp.tls[0]
+ gp = *((**g)(unsafe.Pointer(tls)))
+ }
+
+ if gp == nil {
+ sigprofNonGoPC(r.ip())
+ } else {
+ sigprof(r.ip(), r.sp(), 0, gp, mp)
+ }
}
func profileloop1(param uintptr) uint32 {
@@ -884,9 +906,16 @@ func profileloop1(param uintptr) uint32 {
if thread == 0 || mp.profilehz == 0 || mp.blocked {
continue
}
- stdcall1(_SuspendThread, thread)
+ // mp may exit between the load above and the
+ // SuspendThread, so be careful.
+ if int32(stdcall1(_SuspendThread, thread)) == -1 {
+ // The thread no longer exists.
+ continue
+ }
if mp.profilehz != 0 && !mp.blocked {
- profilem(mp)
+ // Pass the thread handle in case mp
+ // was in the process of shutting down.
+ profilem(mp, thread)
}
stdcall1(_ResumeThread, thread)
}
diff --git a/src/runtime/os_windows_arm.go b/src/runtime/os_windows_arm.go
new file mode 100644
index 0000000000..3115f7241d
--- /dev/null
+++ b/src/runtime/os_windows_arm.go
@@ -0,0 +1,18 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+//go:nosplit
+func cputicks() int64 {
+ return nanotime()
+}
+
+func checkgoarm() {
+ if goarm < 7 {
+ print("Need atomic synchronization instructions, coprocessor ",
+ "access instructions. Recompile using GOARM=7.\n")
+ exit(1)
+ }
+}
diff --git a/src/runtime/pprof/internal/profile/profile.go b/src/runtime/pprof/internal/profile/profile.go
index 64c3e3f054..863bd403a4 100644
--- a/src/runtime/pprof/internal/profile/profile.go
+++ b/src/runtime/pprof/internal/profile/profile.go
@@ -200,7 +200,7 @@ var libRx = regexp.MustCompile(`([.]so$|[.]so[._][0-9]+)`)
// first.
func (p *Profile) setMain() {
for i := 0; i < len(p.Mapping); i++ {
- file := strings.TrimSpace(strings.Replace(p.Mapping[i].File, "(deleted)", "", -1))
+ file := strings.TrimSpace(strings.ReplaceAll(p.Mapping[i].File, "(deleted)", ""))
if len(file) == 0 {
continue
}
diff --git a/src/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go
index 126ba50054..593924183f 100644
--- a/src/runtime/pprof/pprof_test.go
+++ b/src/runtime/pprof/pprof_test.go
@@ -602,7 +602,7 @@ func TestBlockProfile(t *testing.T) {
}
for _, test := range tests {
- if !regexp.MustCompile(strings.Replace(test.re, "\t", "\t+", -1)).MatchString(prof) {
+ if !regexp.MustCompile(strings.ReplaceAll(test.re, "\t", "\t+")).MatchString(prof) {
t.Errorf("Bad %v entry, expect:\n%v\ngot:\n%v", test.name, test.re, prof)
}
}
diff --git a/src/runtime/pprof/proto.go b/src/runtime/pprof/proto.go
index cbd0b83376..bd5c8f7afc 100644
--- a/src/runtime/pprof/proto.go
+++ b/src/runtime/pprof/proto.go
@@ -524,6 +524,14 @@ func parseProcSelfMaps(data []byte, addMapping func(lo, hi, offset uint64, file,
continue
}
file := string(line)
+
+ // Trim deleted file marker.
+ deletedStr := " (deleted)"
+ deletedLen := len(deletedStr)
+ if len(file) >= deletedLen && file[len(file)-deletedLen:] == deletedStr {
+ file = file[:len(file)-deletedLen]
+ }
+
if len(inode) == 1 && inode[0] == '0' && file == "" {
// Huge-page text mappings list the initial fragment of
// mapped but unpopulated memory as being inode 0.
diff --git a/src/runtime/pprof/proto_test.go b/src/runtime/pprof/proto_test.go
index 76bd46da02..4452d51231 100644
--- a/src/runtime/pprof/proto_test.go
+++ b/src/runtime/pprof/proto_test.go
@@ -216,24 +216,89 @@ c000000000-c000036000 rw-p 00000000 00:00 0
07000000 07093000 06c00000 /path/to/gobench_server_main
`
+var profSelfMapsTestsWithDeleted = `
+00400000-0040b000 r-xp 00000000 fc:01 787766 /bin/cat (deleted)
+0060a000-0060b000 r--p 0000a000 fc:01 787766 /bin/cat (deleted)
+0060b000-0060c000 rw-p 0000b000 fc:01 787766 /bin/cat (deleted)
+014ab000-014cc000 rw-p 00000000 00:00 0 [heap]
+7f7d76af8000-7f7d7797c000 r--p 00000000 fc:01 1318064 /usr/lib/locale/locale-archive
+7f7d7797c000-7f7d77b36000 r-xp 00000000 fc:01 1180226 /lib/x86_64-linux-gnu/libc-2.19.so
+7f7d77b36000-7f7d77d36000 ---p 001ba000 fc:01 1180226 /lib/x86_64-linux-gnu/libc-2.19.so
+7f7d77d36000-7f7d77d3a000 r--p 001ba000 fc:01 1180226 /lib/x86_64-linux-gnu/libc-2.19.so
+7f7d77d3a000-7f7d77d3c000 rw-p 001be000 fc:01 1180226 /lib/x86_64-linux-gnu/libc-2.19.so
+7f7d77d3c000-7f7d77d41000 rw-p 00000000 00:00 0
+7f7d77d41000-7f7d77d64000 r-xp 00000000 fc:01 1180217 /lib/x86_64-linux-gnu/ld-2.19.so
+7f7d77f3f000-7f7d77f42000 rw-p 00000000 00:00 0
+7f7d77f61000-7f7d77f63000 rw-p 00000000 00:00 0
+7f7d77f63000-7f7d77f64000 r--p 00022000 fc:01 1180217 /lib/x86_64-linux-gnu/ld-2.19.so
+7f7d77f64000-7f7d77f65000 rw-p 00023000 fc:01 1180217 /lib/x86_64-linux-gnu/ld-2.19.so
+7f7d77f65000-7f7d77f66000 rw-p 00000000 00:00 0
+7ffc342a2000-7ffc342c3000 rw-p 00000000 00:00 0 [stack]
+7ffc34343000-7ffc34345000 r-xp 00000000 00:00 0 [vdso]
+ffffffffff600000-ffffffffff601000 r-xp 00000090 00:00 0 [vsyscall]
+->
+00400000 0040b000 00000000 /bin/cat
+7f7d7797c000 7f7d77b36000 00000000 /lib/x86_64-linux-gnu/libc-2.19.so
+7f7d77d41000 7f7d77d64000 00000000 /lib/x86_64-linux-gnu/ld-2.19.so
+7ffc34343000 7ffc34345000 00000000 [vdso]
+ffffffffff600000 ffffffffff601000 00000090 [vsyscall]
+
+00400000-0040b000 r-xp 00000000 fc:01 787766 /bin/cat with space
+0060a000-0060b000 r--p 0000a000 fc:01 787766 /bin/cat with space
+0060b000-0060c000 rw-p 0000b000 fc:01 787766 /bin/cat with space
+014ab000-014cc000 rw-p 00000000 00:00 0 [heap]
+7f7d76af8000-7f7d7797c000 r--p 00000000 fc:01 1318064 /usr/lib/locale/locale-archive
+7f7d7797c000-7f7d77b36000 r-xp 00000000 fc:01 1180226 /lib/x86_64-linux-gnu/libc-2.19.so
+7f7d77b36000-7f7d77d36000 ---p 001ba000 fc:01 1180226 /lib/x86_64-linux-gnu/libc-2.19.so
+7f7d77d36000-7f7d77d3a000 r--p 001ba000 fc:01 1180226 /lib/x86_64-linux-gnu/libc-2.19.so
+7f7d77d3a000-7f7d77d3c000 rw-p 001be000 fc:01 1180226 /lib/x86_64-linux-gnu/libc-2.19.so
+7f7d77d3c000-7f7d77d41000 rw-p 00000000 00:00 0
+7f7d77d41000-7f7d77d64000 r-xp 00000000 fc:01 1180217 /lib/x86_64-linux-gnu/ld-2.19.so
+7f7d77f3f000-7f7d77f42000 rw-p 00000000 00:00 0
+7f7d77f61000-7f7d77f63000 rw-p 00000000 00:00 0
+7f7d77f63000-7f7d77f64000 r--p 00022000 fc:01 1180217 /lib/x86_64-linux-gnu/ld-2.19.so
+7f7d77f64000-7f7d77f65000 rw-p 00023000 fc:01 1180217 /lib/x86_64-linux-gnu/ld-2.19.so
+7f7d77f65000-7f7d77f66000 rw-p 00000000 00:00 0
+7ffc342a2000-7ffc342c3000 rw-p 00000000 00:00 0 [stack]
+7ffc34343000-7ffc34345000 r-xp 00000000 00:00 0 [vdso]
+ffffffffff600000-ffffffffff601000 r-xp 00000090 00:00 0 [vsyscall]
+->
+00400000 0040b000 00000000 /bin/cat with space
+7f7d7797c000 7f7d77b36000 00000000 /lib/x86_64-linux-gnu/libc-2.19.so
+7f7d77d41000 7f7d77d64000 00000000 /lib/x86_64-linux-gnu/ld-2.19.so
+7ffc34343000 7ffc34345000 00000000 [vdso]
+ffffffffff600000 ffffffffff601000 00000090 [vsyscall]
+`
+
func TestProcSelfMaps(t *testing.T) {
- for tx, tt := range strings.Split(profSelfMapsTests, "\n\n") {
- i := strings.Index(tt, "->\n")
- if i < 0 {
- t.Fatal("malformed test case")
- }
- in, out := tt[:i], tt[i+len("->\n"):]
- if len(out) > 0 && out[len(out)-1] != '\n' {
- out += "\n"
- }
- var buf bytes.Buffer
- parseProcSelfMaps([]byte(in), func(lo, hi, offset uint64, file, buildID string) {
- fmt.Fprintf(&buf, "%08x %08x %08x %s\n", lo, hi, offset, file)
- })
- if buf.String() != out {
- t.Errorf("#%d: have:\n%s\nwant:\n%s\n%q\n%q", tx, buf.String(), out, buf.String(), out)
+
+ f := func(t *testing.T, input string) {
+ for tx, tt := range strings.Split(input, "\n\n") {
+ i := strings.Index(tt, "->\n")
+ if i < 0 {
+ t.Fatal("malformed test case")
+ }
+ in, out := tt[:i], tt[i+len("->\n"):]
+ if len(out) > 0 && out[len(out)-1] != '\n' {
+ out += "\n"
+ }
+ var buf bytes.Buffer
+ parseProcSelfMaps([]byte(in), func(lo, hi, offset uint64, file, buildID string) {
+ fmt.Fprintf(&buf, "%08x %08x %08x %s\n", lo, hi, offset, file)
+ })
+ if buf.String() != out {
+ t.Errorf("#%d: have:\n%s\nwant:\n%s\n%q\n%q", tx, buf.String(), out, buf.String(), out)
+ }
}
}
+
+ t.Run("Normal", func(t *testing.T) {
+ f(t, profSelfMapsTests)
+ })
+
+ t.Run("WithDeletedFile", func(t *testing.T) {
+ f(t, profSelfMapsTestsWithDeleted)
+ })
}
// TestMapping checkes the mapping section of CPU profiles
diff --git a/src/runtime/proc.go b/src/runtime/proc.go
index 73b4a1d9d6..acfdc8472e 100644
--- a/src/runtime/proc.go
+++ b/src/runtime/proc.go
@@ -254,7 +254,7 @@ func forcegchelper() {
println("GC forced")
}
// Time-triggered, fully concurrent.
- gcStart(gcBackgroundMode, gcTrigger{kind: gcTriggerTime, now: nanotime()})
+ gcStart(gcTrigger{kind: gcTriggerTime, now: nanotime()})
}
}
@@ -663,59 +663,6 @@ func ready(gp *g, traceskip int, next bool) {
}
}
-func gcprocs() int32 {
- // Figure out how many CPUs to use during GC.
- // Limited by gomaxprocs, number of actual CPUs, and MaxGcproc.
- lock(&sched.lock)
- n := gomaxprocs
- if n > ncpu {
- n = ncpu
- }
- if n > _MaxGcproc {
- n = _MaxGcproc
- }
- if n > sched.nmidle+1 { // one M is currently running
- n = sched.nmidle + 1
- }
- unlock(&sched.lock)
- return n
-}
-
-func needaddgcproc() bool {
- lock(&sched.lock)
- n := gomaxprocs
- if n > ncpu {
- n = ncpu
- }
- if n > _MaxGcproc {
- n = _MaxGcproc
- }
- n -= sched.nmidle + 1 // one M is currently running
- unlock(&sched.lock)
- return n > 0
-}
-
-func helpgc(nproc int32) {
- _g_ := getg()
- lock(&sched.lock)
- pos := 0
- for n := int32(1); n < nproc; n++ { // one M is currently running
- if allp[pos].mcache == _g_.m.mcache {
- pos++
- }
- mp := mget()
- if mp == nil {
- throw("gcprocs inconsistency")
- }
- mp.helpgc = n
- mp.p.set(allp[pos])
- mp.mcache = allp[pos].mcache
- pos++
- notewakeup(&mp.park)
- }
- unlock(&sched.lock)
-}
-
// freezeStopWait is a large value that freezetheworld sets
// sched.stopwait to in order to request that all Gs permanently stop.
const freezeStopWait = 0x7fffffff
@@ -1132,11 +1079,6 @@ func stopTheWorldWithSema() {
}
}
-func mhelpgc() {
- _g_ := getg()
- _g_.m.helpgc = -1
-}
-
func startTheWorldWithSema(emitTraceEvent bool) int64 {
_g_ := getg()
@@ -1145,7 +1087,6 @@ func startTheWorldWithSema(emitTraceEvent bool) int64 {
list := netpoll(false) // non-blocking
injectglist(&list)
}
- add := needaddgcproc()
lock(&sched.lock)
procs := gomaxprocs
@@ -1175,7 +1116,6 @@ func startTheWorldWithSema(emitTraceEvent bool) int64 {
} else {
// Start M to run P. Do not start another M below.
newm(nil, p)
- add = false
}
}
@@ -1192,16 +1132,6 @@ func startTheWorldWithSema(emitTraceEvent bool) int64 {
wakep()
}
- if add {
- // If GC could have used another helper proc, start one now,
- // in the hope that it will be available next time.
- // It would have been even better to start it before the collection,
- // but doing so requires allocating memory, so it's tricky to
- // coordinate. This lazy approach works out in practice:
- // we don't mind if the first couple gc rounds don't have quite
- // the maximum number of procs.
- newm(mhelpgc, nil)
- }
_g_.m.locks--
if _g_.m.locks == 0 && _g_.preempt { // restore the preemption request in case we've cleared it in newstack
_g_.stackguard0 = stackPreempt
@@ -1242,8 +1172,8 @@ func mstart() {
mstart1()
// Exit this thread.
- if GOOS == "windows" || GOOS == "solaris" || GOOS == "plan9" || GOOS == "darwin" {
- // Window, Solaris, Darwin and Plan 9 always system-allocate
+ if GOOS == "windows" || GOOS == "solaris" || GOOS == "plan9" || GOOS == "darwin" || GOOS == "aix" {
+ // Window, Solaris, Darwin, AIX and Plan 9 always system-allocate
// the stack, but put it in _g_.stack before mstart,
// so the logic above hasn't set osStack yet.
osStack = true
@@ -1276,10 +1206,7 @@ func mstart1() {
fn()
}
- if _g_.m.helpgc != 0 {
- _g_.m.helpgc = 0
- stopm()
- } else if _g_.m != &m0 {
+ if _g_.m != &m0 {
acquirep(_g_.m.nextp.ptr())
_g_.m.nextp = 0
}
@@ -2003,21 +1930,11 @@ func stopm() {
throw("stopm spinning")
}
-retry:
lock(&sched.lock)
mput(_g_.m)
unlock(&sched.lock)
notesleep(&_g_.m.park)
noteclear(&_g_.m.park)
- if _g_.m.helpgc != 0 {
- // helpgc() set _g_.m.p and _g_.m.mcache, so we have a P.
- gchelper()
- // Undo the effects of helpgc().
- _g_.m.helpgc = 0
- _g_.m.mcache = nil
- _g_.m.p = 0
- goto retry
- }
acquirep(_g_.m.nextp.ptr())
_g_.m.nextp = 0
}
@@ -2615,6 +2532,23 @@ top:
resetspinning()
}
+ if sched.disable.user && !schedEnabled(gp) {
+ // Scheduling of this goroutine is disabled. Put it on
+ // the list of pending runnable goroutines for when we
+ // re-enable user scheduling and look again.
+ lock(&sched.lock)
+ if schedEnabled(gp) {
+ // Something re-enabled scheduling while we
+ // were acquiring the lock.
+ unlock(&sched.lock)
+ } else {
+ sched.disable.runnable.pushBack(gp)
+ sched.disable.n++
+ unlock(&sched.lock)
+ goto top
+ }
+ }
+
if gp.lockedm != 0 {
// Hands off own p to the locked m,
// then blocks waiting for a new p.
@@ -2730,7 +2664,7 @@ func goexit0(gp *g) {
_g_ := getg()
casgstatus(gp, _Grunning, _Gdead)
- if isSystemGoroutine(gp) {
+ if isSystemGoroutine(gp, false) {
atomic.Xadd(&sched.ngsys, -1)
}
gp.m = nil
@@ -3033,6 +2967,12 @@ func exitsyscall() {
_g_.stackguard0 = _g_.stack.lo + _StackGuard
}
_g_.throwsplit = false
+
+ if sched.disable.user && !schedEnabled(_g_) {
+ // Scheduling of this goroutine is disabled.
+ Gosched()
+ }
+
return
}
@@ -3168,7 +3108,10 @@ func exitsyscall0(gp *g) {
casgstatus(gp, _Gsyscall, _Grunnable)
dropg()
lock(&sched.lock)
- _p_ := pidleget()
+ var _p_ *p
+ if schedEnabled(_g_) {
+ _p_ = pidleget()
+ }
if _p_ == nil {
globrunqput(gp)
} else if atomic.Load(&sched.sysmonwait) != 0 {
@@ -3381,7 +3324,7 @@ func newproc1(fn *funcval, argp *uint8, narg int32, callergp *g, callerpc uintpt
if _g_.m.curg != nil {
newg.labels = _g_.m.curg.labels
}
- if isSystemGoroutine(newg) {
+ if isSystemGoroutine(newg, false) {
atomic.Xadd(&sched.ngsys, +1)
}
newg.gcscanvalid = false
@@ -3831,7 +3774,7 @@ func sigprof(pc, sp, lr uintptr, gp *g, mp *m) {
pc = funcPC(_ExternalCode) + sys.PCQuantum
}
stk[0] = pc
- if mp.preemptoff != "" || mp.helpgc != 0 {
+ if mp.preemptoff != "" {
stk[1] = funcPC(_GC) + sys.PCQuantum
} else {
stk[1] = funcPC(_System) + sys.PCQuantum
@@ -4093,6 +4036,7 @@ func procresize(nprocs int32) *p {
if _g_.m.p != 0 && _g_.m.p.ptr().id < nprocs {
// continue to use the current P
_g_.m.p.ptr().status = _Prunning
+ _g_.m.p.ptr().mcache.prepareForSweep()
} else {
// release the current P and acquire allp[0]
if _g_.m.p != 0 {
@@ -4143,6 +4087,10 @@ func acquirep(_p_ *p) {
_g_ := getg()
_g_.m.mcache = _p_.mcache
+ // Perform deferred mcache flush before this P can allocate
+ // from a potentially stale mcache.
+ _p_.mcache.prepareForSweep()
+
if trace.enabled {
traceProcStart()
}
@@ -4244,7 +4192,7 @@ func checkdead() {
lock(&allglock)
for i := 0; i < len(allgs); i++ {
gp := allgs[i]
- if isSystemGoroutine(gp) {
+ if isSystemGoroutine(gp, false) {
continue
}
s := readgstatus(gp)
@@ -4603,7 +4551,7 @@ func schedtrace(detailed bool) {
if lockedg != nil {
id3 = lockedg.goid
}
- print(" M", mp.id, ": p=", id1, " curg=", id2, " mallocing=", mp.mallocing, " throwing=", mp.throwing, " preemptoff=", mp.preemptoff, ""+" locks=", mp.locks, " dying=", mp.dying, " helpgc=", mp.helpgc, " spinning=", mp.spinning, " blocked=", mp.blocked, " lockedg=", id3, "\n")
+ print(" M", mp.id, ": p=", id1, " curg=", id2, " mallocing=", mp.mallocing, " throwing=", mp.throwing, " preemptoff=", mp.preemptoff, ""+" locks=", mp.locks, " dying=", mp.dying, " spinning=", mp.spinning, " blocked=", mp.blocked, " lockedg=", id3, "\n")
}
lock(&allglock)
@@ -4625,6 +4573,40 @@ func schedtrace(detailed bool) {
unlock(&sched.lock)
}
+// schedEnableUser enables or disables the scheduling of user
+// goroutines.
+//
+// This does not stop already running user goroutines, so the caller
+// should first stop the world when disabling user goroutines.
+func schedEnableUser(enable bool) {
+ lock(&sched.lock)
+ if sched.disable.user == !enable {
+ unlock(&sched.lock)
+ return
+ }
+ sched.disable.user = !enable
+ if enable {
+ n := sched.disable.n
+ sched.disable.n = 0
+ globrunqputbatch(&sched.disable.runnable, n)
+ unlock(&sched.lock)
+ for ; n != 0 && sched.npidle != 0; n-- {
+ startm(nil, false)
+ }
+ } else {
+ unlock(&sched.lock)
+ }
+}
+
+// schedEnabled returns whether gp should be scheduled. It returns
+// false is scheduling of gp is disabled.
+func schedEnabled(gp *g) bool {
+ if sched.disable.user {
+ return isSystemGoroutine(gp, true)
+ }
+ return true
+}
+
// Put mp on midle list.
// Sched must be locked.
// May run during STW, so write barriers are not allowed.
diff --git a/src/runtime/race/testdata/chan_test.go b/src/runtime/race/testdata/chan_test.go
index 7f349c42ed..60e55ed66a 100644
--- a/src/runtime/race/testdata/chan_test.go
+++ b/src/runtime/race/testdata/chan_test.go
@@ -577,18 +577,32 @@ func TestRaceChanItselfCap(t *testing.T) {
<-compl
}
-func TestRaceChanCloseLen(t *testing.T) {
- v := 0
- _ = v
+func TestNoRaceChanCloseLen(t *testing.T) {
c := make(chan int, 10)
- c <- 0
+ r := make(chan int, 10)
+ go func() {
+ r <- len(c)
+ }()
go func() {
- v = 1
close(c)
+ r <- 0
}()
- time.Sleep(1e7)
- _ = len(c)
- v = 2
+ <-r
+ <-r
+}
+
+func TestNoRaceChanCloseCap(t *testing.T) {
+ c := make(chan int, 10)
+ r := make(chan int, 10)
+ go func() {
+ r <- cap(c)
+ }()
+ go func() {
+ close(c)
+ r <- 0
+ }()
+ <-r
+ <-r
}
func TestRaceChanCloseSend(t *testing.T) {
diff --git a/src/runtime/rt0_aix_ppc64.s b/src/runtime/rt0_aix_ppc64.s
new file mode 100644
index 0000000000..0e3d582809
--- /dev/null
+++ b/src/runtime/rt0_aix_ppc64.s
@@ -0,0 +1,40 @@
+// Copyright 2018 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 "textflag.h"
+
+// _rt0_ppc64_aix is a function descriptor of the entrypoint function
+// __start. This name is needed by cmd/link.
+DATA _rt0_ppc64_aix+0(SB)/8, $__start<>(SB)
+DATA _rt0_ppc64_aix+8(SB)/8, $TOC(SB)
+GLOBL _rt0_ppc64_aix(SB), NOPTR, $16
+
+
+// The starting function must return in the loader to
+// initialise some librairies, especially libthread which
+// creates the main thread and adds the TLS in R13
+// R19 contains a function descriptor to the loader function
+// which needs to be called.
+// This code is similar to the __start function in C
+TEXT __start<>(SB),NOSPLIT,$-8
+ XOR R0, R0
+ MOVD $libc___n_pthreads(SB), R4
+ MOVD 0(R4), R4
+ MOVD $libc___mod_init(SB), R5
+ MOVD 0(R5), R5
+ MOVD 0(R19), R0
+ MOVD R2, 40(R1)
+ MOVD 8(R19), R2
+ MOVD R18, R3
+ MOVD R0, CTR
+ BL (CTR) // Return to AIX loader
+
+ // Launch rt0_go
+ MOVD 40(R1), R2
+ MOVD R14, R3 // argc
+ MOVD R15, R4 // argv
+ MOVD $runtime·rt0_go(SB), R12
+ MOVD R12, CTR
+ BR (CTR)
+
diff --git a/src/runtime/rt0_linux_ppc64le.s b/src/runtime/rt0_linux_ppc64le.s
index 73b9ae392d..54ea9d58f7 100644
--- a/src/runtime/rt0_linux_ppc64le.s
+++ b/src/runtime/rt0_linux_ppc64le.s
@@ -12,7 +12,7 @@ TEXT _rt0_ppc64le_linux_lib(SB),NOSPLIT,$-8
MOVW CR, R0 // Save CR in caller's frame
MOVD R0, 8(R1)
MOVDU R1, -320(R1) // Allocate frame.
-
+
// Preserve callee-save registers.
MOVD R14, 24(R1)
MOVD R15, 32(R1)
diff --git a/src/runtime/rt0_nacl_amd64p32.s b/src/runtime/rt0_nacl_amd64p32.s
index 54e4b1de89..38583c58b2 100644
--- a/src/runtime/rt0_nacl_amd64p32.s
+++ b/src/runtime/rt0_nacl_amd64p32.s
@@ -11,7 +11,7 @@
// 8(DI) - argc
// 12(DI) - argv, then 0, then envv, then 0, then auxv
// NaCl entry here is almost the same, except that there
-// is no saved caller PC, so 0(FP) is -8(FP) and so on.
+// is no saved caller PC, so 0(FP) is -8(FP) and so on.
TEXT _rt0_amd64p32_nacl(SB),NOSPLIT,$16
MOVL DI, 0(SP)
CALL runtime·nacl_sysinfo(SB)
diff --git a/src/runtime/rt0_windows_arm.s b/src/runtime/rt0_windows_arm.s
new file mode 100644
index 0000000000..c5787d0dee
--- /dev/null
+++ b/src/runtime/rt0_windows_arm.s
@@ -0,0 +1,12 @@
+// Copyright 2018 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 "go_asm.h"
+#include "go_tls.h"
+#include "textflag.h"
+
+// This is the entry point for the program from the
+// kernel for an ordinary -buildmode=exe program.
+TEXT _rt0_arm_windows(SB),NOSPLIT|NOFRAME,$0
+ B ·rt0_go(SB)
diff --git a/src/runtime/runtime-gdb_test.go b/src/runtime/runtime-gdb_test.go
index d9c6f6d22a..0c24d3dce6 100644
--- a/src/runtime/runtime-gdb_test.go
+++ b/src/runtime/runtime-gdb_test.go
@@ -242,14 +242,14 @@ func testGdbPython(t *testing.T, cgo bool) {
t.Fatalf("info goroutines failed: %s", bl)
}
- printMapvarRe1 := regexp.MustCompile(`\Q = map[string]string = {["abc"] = "def", ["ghi"] = "jkl"}\E$`)
- printMapvarRe2 := regexp.MustCompile(`\Q = map[string]string = {["ghi"] = "jkl", ["abc"] = "def"}\E$`)
+ printMapvarRe1 := regexp.MustCompile(`^\$[0-9]+ = map\[string\]string = {\[(0x[0-9a-f]+\s+)?"abc"\] = (0x[0-9a-f]+\s+)?"def", \[(0x[0-9a-f]+\s+)?"ghi"\] = (0x[0-9a-f]+\s+)?"jkl"}$`)
+ printMapvarRe2 := regexp.MustCompile(`^\$[0-9]+ = map\[string\]string = {\[(0x[0-9a-f]+\s+)?"ghi"\] = (0x[0-9a-f]+\s+)?"jkl", \[(0x[0-9a-f]+\s+)?"abc"\] = (0x[0-9a-f]+\s+)?"def"}$`)
if bl := blocks["print mapvar"]; !printMapvarRe1.MatchString(bl) &&
!printMapvarRe2.MatchString(bl) {
t.Fatalf("print mapvar failed: %s", bl)
}
- strVarRe := regexp.MustCompile(`\Q = "abc"\E$`)
+ strVarRe := regexp.MustCompile(`^\$[0-9]+ = (0x[0-9a-f]+\s+)?"abc"$`)
if bl := blocks["print strvar"]; !strVarRe.MatchString(bl) {
t.Fatalf("print strvar failed: %s", bl)
}
@@ -263,8 +263,11 @@ func testGdbPython(t *testing.T, cgo bool) {
// aggregates from their fields and reverted their printing
// back to its original form.
- infoLocalsRe := regexp.MustCompile(`slicevar *= *\[\]string *= *{"def"}`)
- if bl := blocks["info locals"]; !infoLocalsRe.MatchString(bl) {
+ infoLocalsRe1 := regexp.MustCompile(`slicevar *= *\[\]string *= *{"def"}`)
+ // Format output from gdb v8.2
+ infoLocalsRe2 := regexp.MustCompile(`^slicevar = .*\nmapvar = .*\nstrvar = 0x[0-9a-f]+ "abc"`)
+ if bl := blocks["info locals"]; !infoLocalsRe1.MatchString(bl) &&
+ !infoLocalsRe2.MatchString(bl) {
t.Fatalf("info locals failed: %s", bl)
}
@@ -425,11 +428,11 @@ func TestGdbAutotmpTypes(t *testing.T) {
// Check that the backtrace matches the source code.
types := []string{
- "struct []main.astruct;",
- "struct bucket<string,main.astruct>;",
- "struct hash<string,main.astruct>;",
- "struct main.astruct;",
- "typedef struct hash<string,main.astruct> * map[string]main.astruct;",
+ "[]main.astruct;",
+ "bucket<string,main.astruct>;",
+ "hash<string,main.astruct>;",
+ "main.astruct;",
+ "hash<string,main.astruct> * map[string]main.astruct;",
}
for _, name := range types {
if !strings.Contains(sgot, name) {
@@ -484,13 +487,13 @@ func TestGdbConst(t *testing.T) {
"-ex", "print main.aConstant",
"-ex", "print main.largeConstant",
"-ex", "print main.minusOne",
- "-ex", "print 'runtime._MSpanInUse'",
+ "-ex", "print 'runtime.mSpanInUse'",
"-ex", "print 'runtime._PageSize'",
filepath.Join(dir, "a.exe"),
}
got, _ := exec.Command("gdb", args...).CombinedOutput()
- sgot := strings.Replace(string(got), "\r\n", "\n", -1)
+ sgot := strings.ReplaceAll(string(got), "\r\n", "\n")
t.Logf("output %q", sgot)
diff --git a/src/runtime/runtime1.go b/src/runtime/runtime1.go
index d5f78baded..8b8f4dcb1e 100644
--- a/src/runtime/runtime1.go
+++ b/src/runtime/runtime1.go
@@ -305,7 +305,6 @@ var debug struct {
gccheckmark int32
gcpacertrace int32
gcshrinkstackoff int32
- gcrescanstacks int32
gcstoptheworld int32
gctrace int32
invalidptr int32
@@ -323,7 +322,6 @@ var dbgvars = []dbgVar{
{"gccheckmark", &debug.gccheckmark},
{"gcpacertrace", &debug.gcpacertrace},
{"gcshrinkstackoff", &debug.gcshrinkstackoff},
- {"gcrescanstacks", &debug.gcrescanstacks},
{"gcstoptheworld", &debug.gcstoptheworld},
{"gctrace", &debug.gctrace},
{"invalidptr", &debug.invalidptr},
@@ -416,7 +414,9 @@ func timediv(v int64, div int32, rem *int32) int32 {
for bit := 30; bit >= 0; bit-- {
if v >= int64(div)<<uint(bit) {
v = v - (int64(div) << uint(bit))
- res += 1 << uint(bit)
+ // Before this for loop, res was 0, thus all these
+ // power of 2 increments are now just bitsets.
+ res |= 1 << uint(bit)
}
}
if v >= int64(div) {
diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go
index 259bb376ae..bbb66bb8fa 100644
--- a/src/runtime/runtime2.go
+++ b/src/runtime/runtime2.go
@@ -424,7 +424,6 @@ type m struct {
locks int32
dying int32
profilehz int32
- helpgc int32
spinning bool // m is out of work and is actively looking for work
blocked bool // m is blocked on a note
inwb bool // m is executing a write barrier
@@ -580,6 +579,18 @@ type schedt struct {
runq gQueue
runqsize int32
+ // disable controls selective disabling of the scheduler.
+ //
+ // Use schedEnableUser to control this.
+ //
+ // disable is protected by sched.lock.
+ disable struct {
+ // user disables scheduling of user goroutines.
+ user bool
+ runnable gQueue // pending runnable Gs
+ n int32 // length of runnable
+ }
+
// Global cache of dead G's.
gFree struct {
lock mutex
@@ -639,14 +650,16 @@ type _func struct {
entry uintptr // start pc
nameoff int32 // function name
- args int32 // in/out args size
- funcID funcID // set for certain special runtime functions
+ args int32 // in/out args size
+ deferreturn uint32 // offset of a deferreturn block from entry, if any.
pcsp int32
pcfile int32
pcln int32
npcdata int32
- nfuncdata int32
+ funcID funcID // set for certain special runtime functions
+ _ [2]int8 // unused
+ nfuncdata uint8 // must be last
}
// layout of Itab known to compilers
diff --git a/src/runtime/runtime_unix_test.go b/src/runtime/runtime_unix_test.go
index e91216365e..b0cbbbe3e6 100644
--- a/src/runtime/runtime_unix_test.go
+++ b/src/runtime/runtime_unix_test.go
@@ -6,7 +6,7 @@
// We need a fast system call to provoke the race,
// and Close(-1) is nearly universally fast.
-// +build darwin dragonfly freebsd linux netbsd openbsd plan9
+// +build aix darwin dragonfly freebsd linux netbsd openbsd plan9
package runtime_test
diff --git a/src/runtime/select.go b/src/runtime/select.go
index 3a3ac6b7ac..2729c2ecf9 100644
--- a/src/runtime/select.go
+++ b/src/runtime/select.go
@@ -245,7 +245,7 @@ loop:
case caseSend:
if raceenabled {
- racereadpc(unsafe.Pointer(c), cas.pc, chansendpc)
+ racereadpc(c.raceaddr(), cas.pc, chansendpc)
}
if c.closed != 0 {
goto sclose
@@ -462,7 +462,7 @@ rclose:
typedmemclr(c.elemtype, cas.elem)
}
if raceenabled {
- raceacquire(unsafe.Pointer(c))
+ raceacquire(c.raceaddr())
}
goto retc
diff --git a/src/runtime/semasleep_test.go b/src/runtime/semasleep_test.go
new file mode 100644
index 0000000000..5b2cc64483
--- /dev/null
+++ b/src/runtime/semasleep_test.go
@@ -0,0 +1,88 @@
+// Copyright 2018 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 !nacl,!plan9,!windows,!js
+
+package runtime_test
+
+import (
+ "internal/testenv"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "syscall"
+ "testing"
+ "time"
+)
+
+// Issue #27250. Spurious wakeups to pthread_cond_timedwait_relative_np
+// shouldn't cause semasleep to retry with the same timeout which would
+// cause indefinite spinning.
+func TestSpuriousWakeupsNeverHangSemasleep(t *testing.T) {
+ testenv.MustHaveGoBuild(t)
+ tempDir, err := ioutil.TempDir("", "issue-27250")
+ if err != nil {
+ t.Fatalf("Failed to create the temp directory: %v", err)
+ }
+ defer os.RemoveAll(tempDir)
+
+ repro := `
+ package main
+
+ import "time"
+
+ func main() {
+ <-time.After(1 * time.Second)
+ }
+ `
+ mainPath := filepath.Join(tempDir, "main.go")
+ if err := ioutil.WriteFile(mainPath, []byte(repro), 0644); err != nil {
+ t.Fatalf("Failed to create temp file for repro.go: %v", err)
+ }
+ binaryPath := filepath.Join(tempDir, "binary")
+
+ // Build the binary so that we can send the signal to its PID.
+ out, err := exec.Command(testenv.GoToolPath(t), "build", "-o", binaryPath, mainPath).CombinedOutput()
+ if err != nil {
+ t.Fatalf("Failed to compile the binary: err: %v\nOutput: %s\n", err, out)
+ }
+ if err := os.Chmod(binaryPath, 0755); err != nil {
+ t.Fatalf("Failed to chmod binary: %v", err)
+ }
+
+ // Now run the binary.
+ cmd := exec.Command(binaryPath)
+ if err := cmd.Start(); err != nil {
+ t.Fatalf("Failed to start command: %v", err)
+ }
+ doneCh := make(chan error, 1)
+ go func() {
+ doneCh <- cmd.Wait()
+ }()
+
+ // With the repro running, we can continuously send to it
+ // a non-terminal signal such as SIGIO, to spuriously
+ // wakeup pthread_cond_timedwait_relative_np.
+ unfixedTimer := time.NewTimer(2 * time.Second)
+ for {
+ select {
+ case <-time.After(200 * time.Millisecond):
+ // Send the pesky signal that toggles spinning
+ // indefinitely if #27520 is not fixed.
+ cmd.Process.Signal(syscall.SIGIO)
+
+ case <-unfixedTimer.C:
+ t.Error("Program failed to return on time and has to be killed, issue #27520 still exists")
+ cmd.Process.Signal(syscall.SIGKILL)
+ return
+
+ case err := <-doneCh:
+ if err != nil {
+ t.Fatalf("The program returned but unfortunately with an error: %v", err)
+ }
+ return
+ }
+ }
+}
diff --git a/src/runtime/signal_aix_ppc64.go b/src/runtime/signal_aix_ppc64.go
new file mode 100644
index 0000000000..c17563e2a5
--- /dev/null
+++ b/src/runtime/signal_aix_ppc64.go
@@ -0,0 +1,85 @@
+/// Copyright 2018 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 aix
+
+package runtime
+
+import (
+ "runtime/internal/sys"
+ "unsafe"
+)
+
+type sigctxt struct {
+ info *siginfo
+ ctxt unsafe.Pointer
+}
+
+//go:nosplit
+//go:nowritebarrierrec
+func (c *sigctxt) regs() *context64 { return &(*ucontext)(c.ctxt).uc_mcontext }
+
+func (c *sigctxt) r0() uint64 { return c.regs().gpr[0] }
+func (c *sigctxt) r1() uint64 { return c.regs().gpr[1] }
+func (c *sigctxt) r2() uint64 { return c.regs().gpr[2] }
+func (c *sigctxt) r3() uint64 { return c.regs().gpr[3] }
+func (c *sigctxt) r4() uint64 { return c.regs().gpr[4] }
+func (c *sigctxt) r5() uint64 { return c.regs().gpr[5] }
+func (c *sigctxt) r6() uint64 { return c.regs().gpr[6] }
+func (c *sigctxt) r7() uint64 { return c.regs().gpr[7] }
+func (c *sigctxt) r8() uint64 { return c.regs().gpr[8] }
+func (c *sigctxt) r9() uint64 { return c.regs().gpr[9] }
+func (c *sigctxt) r10() uint64 { return c.regs().gpr[10] }
+func (c *sigctxt) r11() uint64 { return c.regs().gpr[11] }
+func (c *sigctxt) r12() uint64 { return c.regs().gpr[12] }
+func (c *sigctxt) r13() uint64 { return c.regs().gpr[13] }
+func (c *sigctxt) r14() uint64 { return c.regs().gpr[14] }
+func (c *sigctxt) r15() uint64 { return c.regs().gpr[15] }
+func (c *sigctxt) r16() uint64 { return c.regs().gpr[16] }
+func (c *sigctxt) r17() uint64 { return c.regs().gpr[17] }
+func (c *sigctxt) r18() uint64 { return c.regs().gpr[18] }
+func (c *sigctxt) r19() uint64 { return c.regs().gpr[19] }
+func (c *sigctxt) r20() uint64 { return c.regs().gpr[20] }
+func (c *sigctxt) r21() uint64 { return c.regs().gpr[21] }
+func (c *sigctxt) r22() uint64 { return c.regs().gpr[22] }
+func (c *sigctxt) r23() uint64 { return c.regs().gpr[23] }
+func (c *sigctxt) r24() uint64 { return c.regs().gpr[24] }
+func (c *sigctxt) r25() uint64 { return c.regs().gpr[25] }
+func (c *sigctxt) r26() uint64 { return c.regs().gpr[26] }
+func (c *sigctxt) r27() uint64 { return c.regs().gpr[27] }
+func (c *sigctxt) r28() uint64 { return c.regs().gpr[28] }
+func (c *sigctxt) r29() uint64 { return c.regs().gpr[29] }
+func (c *sigctxt) r30() uint64 { return c.regs().gpr[30] }
+func (c *sigctxt) r31() uint64 { return c.regs().gpr[31] }
+func (c *sigctxt) sp() uint64 { return c.regs().gpr[1] }
+
+//go:nosplit
+//go:nowritebarrierrec
+func (c *sigctxt) pc() uint64 { return c.regs().iar }
+
+func (c *sigctxt) ctr() uint64 { return c.regs().ctr }
+func (c *sigctxt) link() uint64 { return c.regs().lr }
+func (c *sigctxt) xer() uint32 { return c.regs().xer }
+func (c *sigctxt) ccr() uint32 { return c.regs().cr }
+func (c *sigctxt) fpscr() uint32 { return c.regs().fpscr }
+func (c *sigctxt) fpscrx() uint32 { return c.regs().fpscrx }
+
+// TODO(aix): find trap equivalent
+func (c *sigctxt) trap() uint32 { return 0x0 }
+
+func (c *sigctxt) sigcode() uint32 { return uint32(c.info.si_code) }
+func (c *sigctxt) sigaddr() uint64 { return uint64(c.info.si_addr) }
+func (c *sigctxt) fault() uintptr { return uintptr(c.sigaddr()) }
+
+func (c *sigctxt) set_r0(x uint64) { c.regs().gpr[0] = x }
+func (c *sigctxt) set_r12(x uint64) { c.regs().gpr[12] = x }
+func (c *sigctxt) set_r30(x uint64) { c.regs().gpr[30] = x }
+func (c *sigctxt) set_pc(x uint64) { c.regs().iar = x }
+func (c *sigctxt) set_sp(x uint64) { c.regs().gpr[1] = x }
+func (c *sigctxt) set_link(x uint64) { c.regs().lr = x }
+
+func (c *sigctxt) set_sigcode(x uint32) { c.info.si_code = int32(x) }
+func (c *sigctxt) set_sigaddr(x uint64) {
+ *(*uintptr)(add(unsafe.Pointer(c.info), 2*sys.PtrSize)) = uintptr(x)
+}
diff --git a/src/runtime/signal_ppc64x.go b/src/runtime/signal_ppc64x.go
index 5a1a5cae60..cac1a23c9f 100644
--- a/src/runtime/signal_ppc64x.go
+++ b/src/runtime/signal_ppc64x.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build linux
+// +build aix linux
// +build ppc64 ppc64le
package runtime
diff --git a/src/runtime/signal_sighandler.go b/src/runtime/signal_sighandler.go
index 5a734f9050..6e71e41f52 100644
--- a/src/runtime/signal_sighandler.go
+++ b/src/runtime/signal_sighandler.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris
package runtime
diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go
index 6cd9f8ddb6..12a938c8c9 100644
--- a/src/runtime/signal_unix.go
+++ b/src/runtime/signal_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
package runtime
diff --git a/src/runtime/signal_windows.go b/src/runtime/signal_windows.go
index a63450038d..873ce66abe 100644
--- a/src/runtime/signal_windows.go
+++ b/src/runtime/signal_windows.go
@@ -27,7 +27,7 @@ func lastcontinuetramp()
func initExceptionHandler() {
stdcall2(_AddVectoredExceptionHandler, 1, funcPC(exceptiontramp))
- if _AddVectoredContinueHandler == nil || unsafe.Sizeof(&_AddVectoredContinueHandler) == 4 {
+ if _AddVectoredContinueHandler == nil || GOARCH == "386" {
// use SetUnhandledExceptionFilter for windows-386 or
// if VectoredContinueHandler is unavailable.
// note: SetUnhandledExceptionFilter handler won't be called, if debugging.
@@ -177,9 +177,15 @@ func lastcontinuehandler(info *exceptionrecord, r *context, gp *g) int32 {
}
print("\n")
+ // TODO(jordanrh1): This may be needed for 386/AMD64 as well.
+ if GOARCH == "arm" {
+ _g_.m.throwing = 1
+ _g_.m.caughtsig.set(gp)
+ }
+
level, _, docrash := gotraceback()
if level > 0 {
- tracebacktrap(r.ip(), r.sp(), 0, gp)
+ tracebacktrap(r.ip(), r.sp(), r.lr(), gp)
tracebackothers(gp)
dumpregs(r)
}
diff --git a/src/runtime/sigtab_aix.go b/src/runtime/sigtab_aix.go
new file mode 100644
index 0000000000..42e5606ab6
--- /dev/null
+++ b/src/runtime/sigtab_aix.go
@@ -0,0 +1,264 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+var sigtable = [...]sigTabT{
+ 0: {0, "SIGNONE: no trap"},
+ _SIGHUP: {_SigNotify + _SigKill, "SIGHUP: terminal line hangup"},
+ _SIGINT: {_SigNotify + _SigKill, "SIGINT: interrupt"},
+ _SIGQUIT: {_SigNotify + _SigThrow, "SIGQUIT: quit"},
+ _SIGILL: {_SigThrow + _SigUnblock, "SIGILL: illegal instruction"},
+ _SIGTRAP: {_SigThrow + _SigUnblock, "SIGTRAP: trace trap"},
+ _SIGABRT: {_SigNotify + _SigThrow, "SIGABRT: abort"},
+ _SIGBUS: {_SigPanic + _SigUnblock, "SIGBUS: bus error"},
+ _SIGFPE: {_SigPanic + _SigUnblock, "SIGFPE: floating-point exception"},
+ _SIGKILL: {0, "SIGKILL: kill"},
+ _SIGUSR1: {_SigNotify, "SIGUSR1: user-defined signal 1"},
+ _SIGSEGV: {_SigPanic + _SigUnblock, "SIGSEGV: segmentation violation"},
+ _SIGUSR2: {_SigNotify, "SIGUSR2: user-defined signal 2"},
+ _SIGPIPE: {_SigNotify, "SIGPIPE: write to broken pipe"},
+ _SIGALRM: {_SigNotify, "SIGALRM: alarm clock"},
+ _SIGTERM: {_SigNotify + _SigKill, "SIGTERM: termination"},
+ _SIGCHLD: {_SigNotify + _SigUnblock, "SIGCHLD: child status has changed"},
+ _SIGCONT: {_SigNotify + _SigDefault, "SIGCONT: continue"},
+ _SIGSTOP: {0, "SIGSTOP: stop"},
+ _SIGTSTP: {_SigNotify + _SigDefault, "SIGTSTP: keyboard stop"},
+ _SIGTTIN: {_SigNotify + _SigDefault, "SIGTTIN: background read from tty"},
+ _SIGTTOU: {_SigNotify + _SigDefault, "SIGTTOU: background write to tty"},
+ _SIGURG: {_SigNotify, "SIGURG: urgent condition on socket"},
+ _SIGXCPU: {_SigNotify, "SIGXCPU: cpu limit exceeded"},
+ _SIGXFSZ: {_SigNotify, "SIGXFSZ: file size limit exceeded"},
+ _SIGVTALRM: {_SigNotify, "SIGVTALRM: virtual alarm clock"},
+ _SIGPROF: {_SigNotify + _SigUnblock, "SIGPROF: profiling alarm clock"},
+ _SIGWINCH: {_SigNotify, "SIGWINCH: window size change"},
+ _SIGSYS: {_SigThrow, "SIGSYS: bad system call"},
+ _SIGIO: {_SigNotify, "SIGIO: i/o now possible"},
+ _SIGPWR: {_SigNotify, "SIGPWR: power failure restart"},
+ _SIGEMT: {_SigThrow, "SIGEMT: emulate instruction executed"},
+ _SIGWAITING: {0, "SIGWAITING: reserved signal no longer used by"},
+ 26: {_SigNotify, "signal 26"},
+ 27: {_SigNotify, "signal 27"},
+ 33: {_SigNotify, "signal 33"},
+ 35: {_SigNotify, "signal 35"},
+ 36: {_SigNotify, "signal 36"},
+ 37: {_SigNotify, "signal 37"},
+ 38: {_SigNotify, "signal 38"},
+ 40: {_SigNotify, "signal 40"},
+ 41: {_SigNotify, "signal 41"},
+ 42: {_SigNotify, "signal 42"},
+ 43: {_SigNotify, "signal 43"},
+ 44: {_SigNotify, "signal 44"},
+ 45: {_SigNotify, "signal 45"},
+ 46: {_SigNotify, "signal 46"},
+ 47: {_SigNotify, "signal 47"},
+ 48: {_SigNotify, "signal 48"},
+ 49: {_SigNotify, "signal 49"},
+ 50: {_SigNotify, "signal 50"},
+ 51: {_SigNotify, "signal 51"},
+ 52: {_SigNotify, "signal 52"},
+ 53: {_SigNotify, "signal 53"},
+ 54: {_SigNotify, "signal 54"},
+ 55: {_SigNotify, "signal 55"},
+ 56: {_SigNotify, "signal 56"},
+ 57: {_SigNotify, "signal 57"},
+ 58: {_SigNotify, "signal 58"},
+ 59: {_SigNotify, "signal 59"},
+ 60: {_SigNotify, "signal 60"},
+ 61: {_SigNotify, "signal 61"},
+ 62: {_SigNotify, "signal 62"},
+ 63: {_SigNotify, "signal 63"},
+ 64: {_SigNotify, "signal 64"},
+ 65: {_SigNotify, "signal 65"},
+ 66: {_SigNotify, "signal 66"},
+ 67: {_SigNotify, "signal 67"},
+ 68: {_SigNotify, "signal 68"},
+ 69: {_SigNotify, "signal 69"},
+ 70: {_SigNotify, "signal 70"},
+ 71: {_SigNotify, "signal 71"},
+ 72: {_SigNotify, "signal 72"},
+ 73: {_SigNotify, "signal 73"},
+ 74: {_SigNotify, "signal 74"},
+ 75: {_SigNotify, "signal 75"},
+ 76: {_SigNotify, "signal 76"},
+ 77: {_SigNotify, "signal 77"},
+ 78: {_SigNotify, "signal 78"},
+ 79: {_SigNotify, "signal 79"},
+ 80: {_SigNotify, "signal 80"},
+ 81: {_SigNotify, "signal 81"},
+ 82: {_SigNotify, "signal 82"},
+ 83: {_SigNotify, "signal 83"},
+ 84: {_SigNotify, "signal 84"},
+ 85: {_SigNotify, "signal 85"},
+ 86: {_SigNotify, "signal 86"},
+ 87: {_SigNotify, "signal 87"},
+ 88: {_SigNotify, "signal 88"},
+ 89: {_SigNotify, "signal 89"},
+ 90: {_SigNotify, "signal 90"},
+ 91: {_SigNotify, "signal 91"},
+ 92: {_SigNotify, "signal 92"},
+ 93: {_SigNotify, "signal 93"},
+ 94: {_SigNotify, "signal 94"},
+ 95: {_SigNotify, "signal 95"},
+ 96: {_SigNotify, "signal 96"},
+ 97: {_SigNotify, "signal 97"},
+ 98: {_SigNotify, "signal 98"},
+ 99: {_SigNotify, "signal 99"},
+ 100: {_SigNotify, "signal 100"},
+ 101: {_SigNotify, "signal 101"},
+ 102: {_SigNotify, "signal 102"},
+ 103: {_SigNotify, "signal 103"},
+ 104: {_SigNotify, "signal 104"},
+ 105: {_SigNotify, "signal 105"},
+ 106: {_SigNotify, "signal 106"},
+ 107: {_SigNotify, "signal 107"},
+ 108: {_SigNotify, "signal 108"},
+ 109: {_SigNotify, "signal 109"},
+ 110: {_SigNotify, "signal 110"},
+ 111: {_SigNotify, "signal 111"},
+ 112: {_SigNotify, "signal 112"},
+ 113: {_SigNotify, "signal 113"},
+ 114: {_SigNotify, "signal 114"},
+ 115: {_SigNotify, "signal 115"},
+ 116: {_SigNotify, "signal 116"},
+ 117: {_SigNotify, "signal 117"},
+ 118: {_SigNotify, "signal 118"},
+ 119: {_SigNotify, "signal 119"},
+ 120: {_SigNotify, "signal 120"},
+ 121: {_SigNotify, "signal 121"},
+ 122: {_SigNotify, "signal 122"},
+ 123: {_SigNotify, "signal 123"},
+ 124: {_SigNotify, "signal 124"},
+ 125: {_SigNotify, "signal 125"},
+ 126: {_SigNotify, "signal 126"},
+ 127: {_SigNotify, "signal 127"},
+ 128: {_SigNotify, "signal 128"},
+ 129: {_SigNotify, "signal 129"},
+ 130: {_SigNotify, "signal 130"},
+ 131: {_SigNotify, "signal 131"},
+ 132: {_SigNotify, "signal 132"},
+ 133: {_SigNotify, "signal 133"},
+ 134: {_SigNotify, "signal 134"},
+ 135: {_SigNotify, "signal 135"},
+ 136: {_SigNotify, "signal 136"},
+ 137: {_SigNotify, "signal 137"},
+ 138: {_SigNotify, "signal 138"},
+ 139: {_SigNotify, "signal 139"},
+ 140: {_SigNotify, "signal 140"},
+ 141: {_SigNotify, "signal 141"},
+ 142: {_SigNotify, "signal 142"},
+ 143: {_SigNotify, "signal 143"},
+ 144: {_SigNotify, "signal 144"},
+ 145: {_SigNotify, "signal 145"},
+ 146: {_SigNotify, "signal 146"},
+ 147: {_SigNotify, "signal 147"},
+ 148: {_SigNotify, "signal 148"},
+ 149: {_SigNotify, "signal 149"},
+ 150: {_SigNotify, "signal 150"},
+ 151: {_SigNotify, "signal 151"},
+ 152: {_SigNotify, "signal 152"},
+ 153: {_SigNotify, "signal 153"},
+ 154: {_SigNotify, "signal 154"},
+ 155: {_SigNotify, "signal 155"},
+ 156: {_SigNotify, "signal 156"},
+ 157: {_SigNotify, "signal 157"},
+ 158: {_SigNotify, "signal 158"},
+ 159: {_SigNotify, "signal 159"},
+ 160: {_SigNotify, "signal 160"},
+ 161: {_SigNotify, "signal 161"},
+ 162: {_SigNotify, "signal 162"},
+ 163: {_SigNotify, "signal 163"},
+ 164: {_SigNotify, "signal 164"},
+ 165: {_SigNotify, "signal 165"},
+ 166: {_SigNotify, "signal 166"},
+ 167: {_SigNotify, "signal 167"},
+ 168: {_SigNotify, "signal 168"},
+ 169: {_SigNotify, "signal 169"},
+ 170: {_SigNotify, "signal 170"},
+ 171: {_SigNotify, "signal 171"},
+ 172: {_SigNotify, "signal 172"},
+ 173: {_SigNotify, "signal 173"},
+ 174: {_SigNotify, "signal 174"},
+ 175: {_SigNotify, "signal 175"},
+ 176: {_SigNotify, "signal 176"},
+ 177: {_SigNotify, "signal 177"},
+ 178: {_SigNotify, "signal 178"},
+ 179: {_SigNotify, "signal 179"},
+ 180: {_SigNotify, "signal 180"},
+ 181: {_SigNotify, "signal 181"},
+ 182: {_SigNotify, "signal 182"},
+ 183: {_SigNotify, "signal 183"},
+ 184: {_SigNotify, "signal 184"},
+ 185: {_SigNotify, "signal 185"},
+ 186: {_SigNotify, "signal 186"},
+ 187: {_SigNotify, "signal 187"},
+ 188: {_SigNotify, "signal 188"},
+ 189: {_SigNotify, "signal 189"},
+ 190: {_SigNotify, "signal 190"},
+ 191: {_SigNotify, "signal 191"},
+ 192: {_SigNotify, "signal 192"},
+ 193: {_SigNotify, "signal 193"},
+ 194: {_SigNotify, "signal 194"},
+ 195: {_SigNotify, "signal 195"},
+ 196: {_SigNotify, "signal 196"},
+ 197: {_SigNotify, "signal 197"},
+ 198: {_SigNotify, "signal 198"},
+ 199: {_SigNotify, "signal 199"},
+ 200: {_SigNotify, "signal 200"},
+ 201: {_SigNotify, "signal 201"},
+ 202: {_SigNotify, "signal 202"},
+ 203: {_SigNotify, "signal 203"},
+ 204: {_SigNotify, "signal 204"},
+ 205: {_SigNotify, "signal 205"},
+ 206: {_SigNotify, "signal 206"},
+ 207: {_SigNotify, "signal 207"},
+ 208: {_SigNotify, "signal 208"},
+ 209: {_SigNotify, "signal 209"},
+ 210: {_SigNotify, "signal 210"},
+ 211: {_SigNotify, "signal 211"},
+ 212: {_SigNotify, "signal 212"},
+ 213: {_SigNotify, "signal 213"},
+ 214: {_SigNotify, "signal 214"},
+ 215: {_SigNotify, "signal 215"},
+ 216: {_SigNotify, "signal 216"},
+ 217: {_SigNotify, "signal 217"},
+ 218: {_SigNotify, "signal 218"},
+ 219: {_SigNotify, "signal 219"},
+ 220: {_SigNotify, "signal 220"},
+ 221: {_SigNotify, "signal 221"},
+ 222: {_SigNotify, "signal 222"},
+ 223: {_SigNotify, "signal 223"},
+ 224: {_SigNotify, "signal 224"},
+ 225: {_SigNotify, "signal 225"},
+ 226: {_SigNotify, "signal 226"},
+ 227: {_SigNotify, "signal 227"},
+ 228: {_SigNotify, "signal 228"},
+ 229: {_SigNotify, "signal 229"},
+ 230: {_SigNotify, "signal 230"},
+ 231: {_SigNotify, "signal 231"},
+ 232: {_SigNotify, "signal 232"},
+ 233: {_SigNotify, "signal 233"},
+ 234: {_SigNotify, "signal 234"},
+ 235: {_SigNotify, "signal 235"},
+ 236: {_SigNotify, "signal 236"},
+ 237: {_SigNotify, "signal 237"},
+ 238: {_SigNotify, "signal 238"},
+ 239: {_SigNotify, "signal 239"},
+ 240: {_SigNotify, "signal 240"},
+ 241: {_SigNotify, "signal 241"},
+ 242: {_SigNotify, "signal 242"},
+ 243: {_SigNotify, "signal 243"},
+ 244: {_SigNotify, "signal 244"},
+ 245: {_SigNotify, "signal 245"},
+ 246: {_SigNotify, "signal 246"},
+ 247: {_SigNotify, "signal 247"},
+ 248: {_SigNotify, "signal 248"},
+ 249: {_SigNotify, "signal 249"},
+ 250: {_SigNotify, "signal 250"},
+ 251: {_SigNotify, "signal 251"},
+ 252: {_SigNotify, "signal 252"},
+ 253: {_SigNotify, "signal 253"},
+ 254: {_SigNotify, "signal 254"},
+ 255: {_SigNotify, "signal 255"},
+}
diff --git a/src/runtime/stack.go b/src/runtime/stack.go
index c7bfc0434b..b815aa859e 100644
--- a/src/runtime/stack.go
+++ b/src/runtime/stack.go
@@ -211,7 +211,7 @@ func stackpoolalloc(order uint8) gclinkptr {
// Adds stack x to the free pool. Must be called with stackpoolmu held.
func stackpoolfree(x gclinkptr, order uint8) {
s := spanOfUnchecked(uintptr(x))
- if s.state != _MSpanManual {
+ if s.state != mSpanManual {
throw("freeing stack not in a stack span")
}
if s.manualFreeList.ptr() == nil {
@@ -350,7 +350,7 @@ func stackalloc(n uint32) stack {
}
var x gclinkptr
c := thisg.m.mcache
- if stackNoCache != 0 || c == nil || thisg.m.preemptoff != "" || thisg.m.helpgc != 0 {
+ if stackNoCache != 0 || c == nil || thisg.m.preemptoff != "" {
// c == nil can happen in the guts of exitsyscall or
// procresize. Just get a stack from the global pool.
// Also don't touch stackcache during gc
@@ -445,7 +445,7 @@ func stackfree(stk stack) {
}
x := gclinkptr(v)
c := gp.m.mcache
- if stackNoCache != 0 || c == nil || gp.m.preemptoff != "" || gp.m.helpgc != 0 {
+ if stackNoCache != 0 || c == nil || gp.m.preemptoff != "" {
lock(&stackpoolmu)
stackpoolfree(x, order)
unlock(&stackpoolmu)
@@ -459,7 +459,7 @@ func stackfree(stk stack) {
}
} else {
s := spanOfUnchecked(uintptr(v))
- if s.state != _MSpanManual {
+ if s.state != mSpanManual {
println(hex(s.base()), v)
throw("bad span state")
}
@@ -625,7 +625,7 @@ func adjustframe(frame *stkframe, arg unsafe.Pointer) bool {
return true
}
- locals, args := getStackMap(frame, &adjinfo.cache, true)
+ locals, args, objs := getStackMap(frame, &adjinfo.cache, true)
// Adjust local variables if stack frame has been allocated.
if locals.n > 0 {
@@ -663,6 +663,42 @@ func adjustframe(frame *stkframe, arg unsafe.Pointer) bool {
}
adjustpointers(unsafe.Pointer(frame.argp), &args, adjinfo, funcInfo{})
}
+
+ // Adjust pointers in all stack objects (whether they are live or not).
+ // See comments in mgcmark.go:scanframeworker.
+ if frame.varp != 0 {
+ for _, obj := range objs {
+ off := obj.off
+ base := frame.varp // locals base pointer
+ if off >= 0 {
+ base = frame.argp // arguments and return values base pointer
+ }
+ p := base + uintptr(off)
+ if p < frame.sp {
+ // Object hasn't been allocated in the frame yet.
+ // (Happens when the stack bounds check fails and
+ // we call into morestack.)
+ continue
+ }
+ t := obj.typ
+ gcdata := t.gcdata
+ var s *mspan
+ if t.kind&kindGCProg != 0 {
+ // See comments in mgcmark.go:scanstack
+ s = materializeGCProg(t.ptrdata, gcdata)
+ gcdata = (*byte)(unsafe.Pointer(s.startAddr))
+ }
+ for i := uintptr(0); i < t.ptrdata; i += sys.PtrSize {
+ if *addb(gcdata, i/(8*sys.PtrSize))>>(i/sys.PtrSize&7)&1 != 0 {
+ adjustpointer(adjinfo, unsafe.Pointer(p+i))
+ }
+ }
+ if s != nil {
+ dematerializeGCProg(s)
+ }
+ }
+ }
+
return true
}
@@ -981,9 +1017,6 @@ func newstack() {
// system stack.
gcw := &gp.m.p.ptr().gcw
scanstack(gp, gcw)
- if gcBlackenPromptly {
- gcw.dispose()
- }
gp.gcscandone = true
}
gp.preemptscan = false
@@ -1139,9 +1172,9 @@ func freeStackSpans() {
unlock(&stackLarge.lock)
}
-// getStackMap returns the locals and arguments live pointer maps for
-// frame.
-func getStackMap(frame *stkframe, cache *pcvalueCache, debug bool) (locals, args bitvector) {
+// getStackMap returns the locals and arguments live pointer maps, and
+// stack object list for frame.
+func getStackMap(frame *stkframe, cache *pcvalueCache, debug bool) (locals, args bitvector, objs []stackObjectRecord) {
targetpc := frame.continpc
if targetpc == 0 {
// Frame is dead. Return empty bitvectors.
@@ -1238,9 +1271,33 @@ func getStackMap(frame *stkframe, cache *pcvalueCache, debug bool) (locals, args
}
}
}
+
+ // stack objects.
+ p := funcdata(f, _FUNCDATA_StackObjects)
+ if p != nil {
+ n := *(*uintptr)(p)
+ p = add(p, sys.PtrSize)
+ *(*slice)(unsafe.Pointer(&objs)) = slice{array: noescape(p), len: int(n), cap: int(n)}
+ // Note: the noescape above is needed to keep
+ // getStackMap from from "leaking param content:
+ // frame". That leak propagates up to getgcmask, then
+ // GCMask, then verifyGCInfo, which converts the stack
+ // gcinfo tests into heap gcinfo tests :(
+ }
+
return
}
+// A stackObjectRecord is generated by the compiler for each stack object in a stack frame.
+// This record must match the generator code in cmd/compile/internal/gc/ssa.go:emitStackObjects.
+type stackObjectRecord struct {
+ // offset in frame
+ // if negative, offset from varp
+ // if non-negative, offset from argp
+ off int
+ typ *_type
+}
+
//go:nosplit
func morestackc() {
throw("attempt to execute system stack code on user stack")
diff --git a/src/runtime/stubs2.go b/src/runtime/stubs2.go
index 02249d0aad..57134f7354 100644
--- a/src/runtime/stubs2.go
+++ b/src/runtime/stubs2.go
@@ -8,6 +8,7 @@
// +build !nacl
// +build !js
// +build !darwin
+// +build !aix
package runtime
@@ -25,7 +26,8 @@ func write(fd uintptr, p unsafe.Pointer, n int32) int32
//go:noescape
func open(name *byte, mode, perm int32) int32
-func madvise(addr unsafe.Pointer, n uintptr, flags int32)
+// return value is only set on linux to be used in osinit()
+func madvise(addr unsafe.Pointer, n uintptr, flags int32) int32
// exitThread terminates the current thread, writing *wait = 0 when
// the stack is safe to reclaim.
diff --git a/src/runtime/stubs3.go b/src/runtime/stubs3.go
index 5c0786e411..a9ff689e79 100644
--- a/src/runtime/stubs3.go
+++ b/src/runtime/stubs3.go
@@ -8,6 +8,7 @@
// +build !nacl
// +build !freebsd
// +build !darwin
+// +build !aix
package runtime
diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go
index d90ab86ffa..1dc7ab740e 100644
--- a/src/runtime/symtab.go
+++ b/src/runtime/symtab.go
@@ -348,6 +348,7 @@ const (
_FUNCDATA_LocalsPointerMaps = 1
_FUNCDATA_InlTree = 2
_FUNCDATA_RegPointerMaps = 3
+ _FUNCDATA_StackObjects = 4
_ArgsSizeUnknown = -0x80000000
)
@@ -356,7 +357,7 @@ const (
// Note that in some situations involving plugins, there may be multiple
// copies of a particular special runtime function.
// Note: this list must match the list in cmd/internal/objabi/funcid.go.
-type funcID uint32
+type funcID uint8
const (
funcID_normal funcID = iota // not a special function
@@ -855,7 +856,7 @@ func pcdatavalue(f funcInfo, table int32, targetpc uintptr, cache *pcvalueCache)
return pcvalue(f, off, targetpc, cache, true)
}
-func funcdata(f funcInfo, i int32) unsafe.Pointer {
+func funcdata(f funcInfo, i uint8) unsafe.Pointer {
if i < 0 || i >= f.nfuncdata {
return nil
}
diff --git a/src/runtime/sys_aix_ppc64.s b/src/runtime/sys_aix_ppc64.s
new file mode 100644
index 0000000000..38e60f99eb
--- /dev/null
+++ b/src/runtime/sys_aix_ppc64.s
@@ -0,0 +1,201 @@
+// Copyright 2018 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 aix
+// +build ppc64 ppc64le
+
+//
+// System calls and other sys.stuff for ppc64, Aix
+//
+
+#include "go_asm.h"
+#include "go_tls.h"
+#include "textflag.h"
+#include "asm_ppc64x.h"
+
+// This function calls a C function with the function descriptor in R12
+TEXT runtime·callCfunction(SB), NOSPLIT|NOFRAME,$0
+ MOVD 0(R12), R12
+ MOVD R2, 40(R1)
+ MOVD 0(R12), R0
+ MOVD 8(R12), R2
+ MOVD R0, CTR
+ BR (CTR)
+
+
+// asmsyscall6 calls a library function with a function descriptor
+// stored in libcall_fn and store the results in libcall struture
+// Up to 6 arguments can be passed to this C function
+// Called by runtime.asmcgocall
+// It reserves a stack of 288 bytes for the C function.
+// NOT USING GO CALLING CONVENTION
+TEXT runtime·asmsyscall6(SB),NOSPLIT,$256
+ MOVD R3, 48(R1) // Save libcall for later
+ MOVD libcall_fn(R3), R12
+ MOVD libcall_args(R3), R9
+ MOVD 0(R9), R3
+ MOVD 8(R9), R4
+ MOVD 16(R9), R5
+ MOVD 24(R9), R6
+ MOVD 32(R9), R7
+ MOVD 40(R9), R8
+ BL runtime·callCfunction(SB)
+
+ // Restore R0 and TOC
+ XOR R0, R0
+ MOVD 40(R1), R2
+
+ // Store result in libcall
+ MOVD 48(R1), R5
+ MOVD R3, (libcall_r1)(R5)
+ MOVD $-1, R6
+ CMP R6, R3
+ BNE skiperrno
+
+ // Save errno in libcall
+ BL runtime·load_g(SB)
+ MOVD g_m(g), R4
+ MOVD (m_mOS + mOS_perrno)(R4), R9
+ MOVW 0(R9), R9
+ MOVD R9, (libcall_err)(R5)
+ RET
+skiperrno:
+ // Reset errno if no error has been returned
+ MOVD R0, (libcall_err)(R5)
+ RET
+
+
+TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
+ MOVW sig+8(FP), R3
+ MOVD info+16(FP), R4
+ MOVD ctx+24(FP), R5
+ MOVD fn+0(FP), R12
+ MOVD R12, CTR
+ BL (CTR)
+ RET
+
+
+// runtime.sigtramp is a function descriptor to the real sigtramp.
+DATA runtime·sigtramp+0(SB)/8, $runtime·_sigtramp(SB)
+DATA runtime·sigtramp+8(SB)/8, $TOC(SB)
+DATA runtime·sigtramp+16(SB)/8, $0
+GLOBL runtime·sigtramp(SB), NOPTR, $24
+
+// This funcion must not have any frame as we want to control how
+// every registers are used.
+TEXT runtime·_sigtramp(SB),NOSPLIT|NOFRAME,$0
+ MOVD LR, R0
+ MOVD R0, 16(R1)
+ // initialize essential registers (just in case)
+ BL runtime·reginit(SB)
+
+ // Note that we are executing on altsigstack here, so we have
+ // more stack available than NOSPLIT would have us believe.
+ // To defeat the linker, we make our own stack frame with
+ // more space.
+ SUB $128+FIXED_FRAME, R1
+
+ // Save registers
+ MOVD R31, 56(R1)
+ MOVD g, 64(R1)
+ MOVD R29, 72(R1)
+
+ BL runtime·load_g(SB)
+
+ // Save m->libcall. We need to do this because we
+ // might get interrupted by a signal in runtime·asmcgocall.
+
+ // save m->libcall
+ MOVD g_m(g), R6
+ MOVD (m_libcall+libcall_fn)(R6), R7
+ MOVD R7, 80(R1)
+ MOVD (m_libcall+libcall_args)(R6), R7
+ MOVD R7, 88(R1)
+ MOVD (m_libcall+libcall_n)(R6), R7
+ MOVD R7, 96(R1)
+ MOVD (m_libcall+libcall_r1)(R6), R7
+ MOVD R7, 104(R1)
+ MOVD (m_libcall+libcall_r2)(R6), R7
+ MOVD R7, 112(R1)
+
+ // save errno, it might be EINTR; stuff we do here might reset it.
+ MOVD (m_mOS+mOS_perrno)(R6), R8
+ MOVD 0(R8), R8
+ MOVD R8, 120(R1)
+
+ MOVW R3, FIXED_FRAME+0(R1)
+ MOVD R4, FIXED_FRAME+8(R1)
+ MOVD R5, FIXED_FRAME+16(R1)
+ MOVD $runtime·sigtrampgo(SB), R12
+ MOVD R12, CTR
+ BL (CTR)
+
+ MOVD g_m(g), R6
+ // restore libcall
+ MOVD 80(R1), R7
+ MOVD R7, (m_libcall+libcall_fn)(R6)
+ MOVD 88(R1), R7
+ MOVD R7, (m_libcall+libcall_args)(R6)
+ MOVD 96(R1), R7
+ MOVD R7, (m_libcall+libcall_n)(R6)
+ MOVD 104(R1), R7
+ MOVD R7, (m_libcall+libcall_r1)(R6)
+ MOVD 112(R1), R7
+ MOVD R7, (m_libcall+libcall_r2)(R6)
+
+ // restore errno
+ MOVD (m_mOS+mOS_perrno)(R6), R7
+ MOVD 120(R1), R8
+ MOVD R8, 0(R7)
+
+ // restore registers
+ MOVD 56(R1),R31
+ MOVD 64(R1),g
+ MOVD 72(R1),R29
+
+ // Don't use RET because we need to restore R31 !
+ ADD $128+FIXED_FRAME, R1
+ MOVD 16(R1), R0
+ MOVD R0, LR
+ BR (LR)
+
+// runtime.tstart is a function descriptor to the real tstart.
+DATA runtime·tstart+0(SB)/8, $runtime·_tstart(SB)
+DATA runtime·tstart+8(SB)/8, $TOC(SB)
+DATA runtime·tstart+16(SB)/8, $0
+GLOBL runtime·tstart(SB), NOPTR, $24
+
+TEXT runtime·_tstart(SB),NOSPLIT,$0
+ XOR R0, R0 // reset R0
+
+ // set g
+ MOVD m_g0(R3), g
+ BL runtime·save_g(SB)
+ MOVD R3, g_m(g)
+
+ // Layout new m scheduler stack on os stack.
+ MOVD R1, R3
+ MOVD R3, (g_stack+stack_hi)(g)
+ SUB $(const_threadStackSize), R3 // stack size
+ MOVD R3, (g_stack+stack_lo)(g)
+ ADD $const__StackGuard, R3
+ MOVD R3, g_stackguard0(g)
+ MOVD R3, g_stackguard1(g)
+
+ BL runtime·mstart(SB)
+
+ MOVD R0, R3
+ RET
+
+// Runs on OS stack, called from runtime·osyield.
+TEXT runtime·osyield1(SB),NOSPLIT,$0
+ MOVD $libc_sched_yield(SB), R12
+ MOVD 0(R12), R12
+ MOVD R2, 40(R1)
+ MOVD 0(R12), R0
+ MOVD 8(R12), R2
+ MOVD R0, CTR
+ BL (CTR)
+ MOVD 40(R1), R2
+ RET
diff --git a/src/runtime/sys_darwin.go b/src/runtime/sys_darwin.go
index 7efbef746c..9b0cc6f935 100644
--- a/src/runtime/sys_darwin.go
+++ b/src/runtime/sys_darwin.go
@@ -370,5 +370,5 @@ func closeonexec(fd int32) {
//go:cgo_import_dynamic libc_pthread_cond_signal pthread_cond_signal "/usr/lib/libSystem.B.dylib"
// Magic incantation to get libSystem actually dynamically linked.
-// TODO: Why does the code require this? See cmd/compile/internal/ld/go.go:210
+// TODO: Why does the code require this? See cmd/link/internal/ld/go.go
//go:cgo_import_dynamic _ _ "/usr/lib/libSystem.B.dylib"
diff --git a/src/runtime/sys_dragonfly_amd64.s b/src/runtime/sys_dragonfly_amd64.s
index f0eb5f4e21..b771850aaf 100644
--- a/src/runtime/sys_dragonfly_amd64.s
+++ b/src/runtime/sys_dragonfly_amd64.s
@@ -9,7 +9,7 @@
#include "go_asm.h"
#include "go_tls.h"
#include "textflag.h"
-
+
TEXT runtime·sys_umtx_sleep(SB),NOSPLIT,$0
MOVQ addr+0(FP), DI // arg 1 - ptr
MOVL val+8(FP), SI // arg 2 - value
@@ -260,9 +260,11 @@ TEXT runtime·madvise(SB),NOSPLIT,$0
MOVL flags+16(FP), DX
MOVQ $75, AX // madvise
SYSCALL
- // ignore failure - maybe pages are locked
+ JCC 2(PC)
+ MOVL $-1, AX
+ MOVL AX, ret+24(FP)
RET
-
+
TEXT runtime·sigaltstack(SB),NOSPLIT,$-8
MOVQ new+0(FP), DI
MOVQ old+8(FP), SI
diff --git a/src/runtime/sys_freebsd_386.s b/src/runtime/sys_freebsd_386.s
index b8f685a323..bc309ba453 100644
--- a/src/runtime/sys_freebsd_386.s
+++ b/src/runtime/sys_freebsd_386.s
@@ -9,7 +9,7 @@
#include "go_asm.h"
#include "go_tls.h"
#include "textflag.h"
-
+
TEXT runtime·sys_umtx_op(SB),NOSPLIT,$-4
MOVL $454, AX
INT $0x80
@@ -39,7 +39,7 @@ TEXT runtime·thr_start(SB),NOSPLIT,$0
POPAL
get_tls(CX)
MOVL BX, g(CX)
-
+
MOVL AX, g_m(BX)
CALL runtime·stackcheck(SB) // smashes AX
CALL runtime·mstart(SB)
@@ -163,7 +163,9 @@ TEXT runtime·munmap(SB),NOSPLIT,$-4
TEXT runtime·madvise(SB),NOSPLIT,$-4
MOVL $75, AX // madvise
INT $0x80
- // ignore failure - maybe pages are locked
+ JAE 2(PC)
+ MOVL $-1, AX
+ MOVL AX, ret+12(FP)
RET
TEXT runtime·setitimer(SB), NOSPLIT, $-4
diff --git a/src/runtime/sys_freebsd_amd64.s b/src/runtime/sys_freebsd_amd64.s
index be191a0784..55959b3e3a 100644
--- a/src/runtime/sys_freebsd_amd64.s
+++ b/src/runtime/sys_freebsd_amd64.s
@@ -337,9 +337,11 @@ TEXT runtime·madvise(SB),NOSPLIT,$0
MOVL flags+16(FP), DX
MOVQ $75, AX // madvise
SYSCALL
- // ignore failure - maybe pages are locked
+ JCC 2(PC)
+ MOVL $-1, AX
+ MOVL AX, ret+24(FP)
RET
-
+
TEXT runtime·sigaltstack(SB),NOSPLIT,$-8
MOVQ new+0(FP), DI
MOVQ old+8(FP), SI
diff --git a/src/runtime/sys_freebsd_arm.s b/src/runtime/sys_freebsd_arm.s
index 93bf569367..f347b9fa96 100644
--- a/src/runtime/sys_freebsd_arm.s
+++ b/src/runtime/sys_freebsd_arm.s
@@ -264,14 +264,15 @@ TEXT runtime·munmap(SB),NOSPLIT,$0
RET
TEXT runtime·madvise(SB),NOSPLIT,$0
- MOVW addr+0(FP), R0 // arg 1 addr
- MOVW n+4(FP), R1 // arg 2 len
- MOVW flags+8(FP), R2 // arg 3 flags
- MOVW $SYS_madvise, R7
- SWI $0
- // ignore failure - maybe pages are locked
+ MOVW addr+0(FP), R0 // arg 1 addr
+ MOVW n+4(FP), R1 // arg 2 len
+ MOVW flags+8(FP), R2 // arg 3 flags
+ MOVW $SYS_madvise, R7
+ SWI $0
+ MOVW.CS $-1, R0
+ MOVW R0, ret+12(FP)
RET
-
+
TEXT runtime·sigaltstack(SB),NOSPLIT|NOFRAME,$0
MOVW new+0(FP), R0
MOVW old+4(FP), R1
diff --git a/src/runtime/sys_linux_386.s b/src/runtime/sys_linux_386.s
index 8d5a4ff977..40b55a67eb 100644
--- a/src/runtime/sys_linux_386.s
+++ b/src/runtime/sys_linux_386.s
@@ -48,7 +48,6 @@
#define SYS_mincore 218
#define SYS_madvise 219
#define SYS_gettid 224
-#define SYS_tkill 238
#define SYS_futex 240
#define SYS_sched_getaffinity 242
#define SYS_set_thread_area 243
@@ -57,6 +56,7 @@
#define SYS_epoll_ctl 255
#define SYS_epoll_wait 256
#define SYS_clock_gettime 265
+#define SYS_tgkill 270
#define SYS_epoll_create1 329
TEXT runtime·exit(SB),NOSPLIT,$0
@@ -155,11 +155,14 @@ TEXT runtime·gettid(SB),NOSPLIT,$0-4
RET
TEXT runtime·raise(SB),NOSPLIT,$12
+ MOVL $SYS_getpid, AX
+ INVOKE_SYSCALL
+ MOVL AX, BX // arg 1 pid
MOVL $SYS_gettid, AX
INVOKE_SYSCALL
- MOVL AX, BX // arg 1 tid
- MOVL sig+0(FP), CX // arg 2 signal
- MOVL $SYS_tkill, AX
+ MOVL AX, CX // arg 2 tid
+ MOVL sig+0(FP), DX // arg 3 signal
+ MOVL $SYS_tgkill, AX
INVOKE_SYSCALL
RET
@@ -424,7 +427,7 @@ TEXT runtime·madvise(SB),NOSPLIT,$0
MOVL n+4(FP), CX
MOVL flags+8(FP), DX
INVOKE_SYSCALL
- // ignore failure - maybe pages are locked
+ MOVL AX, ret+12(FP)
RET
// int32 futex(int32 *uaddr, int32 op, int32 val,
diff --git a/src/runtime/sys_linux_amd64.s b/src/runtime/sys_linux_amd64.s
index 62d80247be..b709f77060 100644
--- a/src/runtime/sys_linux_amd64.s
+++ b/src/runtime/sys_linux_amd64.s
@@ -36,12 +36,12 @@
#define SYS_sigaltstack 131
#define SYS_arch_prctl 158
#define SYS_gettid 186
-#define SYS_tkill 200
#define SYS_futex 202
#define SYS_sched_getaffinity 204
#define SYS_epoll_create 213
#define SYS_exit_group 231
#define SYS_epoll_ctl 233
+#define SYS_tgkill 234
#define SYS_openat 257
#define SYS_faccessat 269
#define SYS_epoll_pwait 281
@@ -137,11 +137,15 @@ TEXT runtime·gettid(SB),NOSPLIT,$0-4
RET
TEXT runtime·raise(SB),NOSPLIT,$0
+ MOVL $SYS_getpid, AX
+ SYSCALL
+ MOVL AX, R12
MOVL $SYS_gettid, AX
SYSCALL
- MOVL AX, DI // arg 1 tid
- MOVL sig+0(FP), SI // arg 2
- MOVL $SYS_tkill, AX
+ MOVL AX, SI // arg 2 tid
+ MOVL R12, DI // arg 1 pid
+ MOVL sig+0(FP), DX // arg 3
+ MOVL $SYS_tgkill, AX
SYSCALL
RET
@@ -515,7 +519,7 @@ TEXT runtime·madvise(SB),NOSPLIT,$0
MOVL flags+16(FP), DX
MOVQ $SYS_madvise, AX
SYSCALL
- // ignore failure - maybe pages are locked
+ MOVL AX, ret+24(FP)
RET
// int64 futex(int32 *uaddr, int32 op, int32 val,
@@ -604,7 +608,7 @@ TEXT runtime·settls(SB),NOSPLIT,$32
// Same as in sys_darwin_386.s:/ugliness, different constant.
// DI currently holds m->tls, which must be fs:0x1d0.
// See cgo/gcc_android_amd64.c for the derivation of the constant.
- SUBQ $0x1d0, DI // In android, the tls base
+ SUBQ $0x1d0, DI // In android, the tls base
#else
ADDQ $8, DI // ELF wants to use -8(FS)
#endif
diff --git a/src/runtime/sys_linux_arm.s b/src/runtime/sys_linux_arm.s
index aa39732cfb..43a58335c8 100644
--- a/src/runtime/sys_linux_arm.s
+++ b/src/runtime/sys_linux_arm.s
@@ -36,7 +36,7 @@
#define SYS_setitimer (SYS_BASE + 104)
#define SYS_mincore (SYS_BASE + 219)
#define SYS_gettid (SYS_BASE + 224)
-#define SYS_tkill (SYS_BASE + 238)
+#define SYS_tgkill (SYS_BASE + 268)
#define SYS_sched_yield (SYS_BASE + 158)
#define SYS_nanosleep (SYS_BASE + 162)
#define SYS_sched_getaffinity (SYS_BASE + 242)
@@ -138,11 +138,15 @@ TEXT runtime·gettid(SB),NOSPLIT,$0-4
RET
TEXT runtime·raise(SB),NOSPLIT|NOFRAME,$0
+ MOVW $SYS_getpid, R7
+ SWI $0
+ MOVW R0, R4
MOVW $SYS_gettid, R7
SWI $0
- // arg 1 tid already in R0 from gettid
- MOVW sig+0(FP), R1 // arg 2 - signal
- MOVW $SYS_tkill, R7
+ MOVW R0, R1 // arg 2 tid
+ MOVW R4, R0 // arg 1 pid
+ MOVW sig+0(FP), R2 // arg 3
+ MOVW $SYS_tgkill, R7
SWI $0
RET
@@ -191,7 +195,7 @@ TEXT runtime·madvise(SB),NOSPLIT,$0
MOVW flags+8(FP), R2
MOVW $SYS_madvise, R7
SWI $0
- // ignore failure - maybe pages are locked
+ MOVW R0, ret+12(FP)
RET
TEXT runtime·setitimer(SB),NOSPLIT,$0
diff --git a/src/runtime/sys_linux_arm64.s b/src/runtime/sys_linux_arm64.s
index 1c8fce3db6..8b344be8f8 100644
--- a/src/runtime/sys_linux_arm64.s
+++ b/src/runtime/sys_linux_arm64.s
@@ -36,7 +36,7 @@
#define SYS_getpid 172
#define SYS_gettid 178
#define SYS_kill 129
-#define SYS_tkill 130
+#define SYS_tgkill 131
#define SYS_futex 98
#define SYS_sched_getaffinity 123
#define SYS_exit_group 94
@@ -143,11 +143,15 @@ TEXT runtime·gettid(SB),NOSPLIT,$0-4
RET
TEXT runtime·raise(SB),NOSPLIT|NOFRAME,$0
+ MOVD $SYS_getpid, R8
+ SVC
+ MOVW R0, R19
MOVD $SYS_gettid, R8
SVC
- MOVW R0, R0 // arg 1 tid
- MOVW sig+0(FP), R1 // arg 2
- MOVD $SYS_tkill, R8
+ MOVW R0, R1 // arg 2 tid
+ MOVW R19, R0 // arg 1 pid
+ MOVW sig+0(FP), R2 // arg 3
+ MOVD $SYS_tgkill, R8
SVC
RET
@@ -397,7 +401,7 @@ TEXT runtime·madvise(SB),NOSPLIT|NOFRAME,$0
MOVW flags+16(FP), R2
MOVD $SYS_madvise, R8
SVC
- // ignore failure - maybe pages are locked
+ MOVW R0, ret+24(FP)
RET
// int64 futex(int32 *uaddr, int32 op, int32 val,
diff --git a/src/runtime/sys_linux_mips64x.s b/src/runtime/sys_linux_mips64x.s
index 8e64f1c562..c45703d228 100644
--- a/src/runtime/sys_linux_mips64x.s
+++ b/src/runtime/sys_linux_mips64x.s
@@ -35,12 +35,12 @@
#define SYS_madvise 5027
#define SYS_mincore 5026
#define SYS_gettid 5178
-#define SYS_tkill 5192
#define SYS_futex 5194
#define SYS_sched_getaffinity 5196
#define SYS_exit_group 5205
#define SYS_epoll_create 5207
#define SYS_epoll_ctl 5208
+#define SYS_tgkill 5225
#define SYS_openat 5247
#define SYS_epoll_pwait 5272
#define SYS_clock_gettime 5222
@@ -137,11 +137,15 @@ TEXT runtime·gettid(SB),NOSPLIT,$0-4
RET
TEXT runtime·raise(SB),NOSPLIT|NOFRAME,$0
+ MOVV $SYS_getpid, R2
+ SYSCALL
+ MOVW R2, R16
MOVV $SYS_gettid, R2
SYSCALL
- MOVW R2, R4 // arg 1 tid
- MOVW sig+0(FP), R5 // arg 2
- MOVV $SYS_tkill, R2
+ MOVW R2, R5 // arg 2 tid
+ MOVW R16, R4 // arg 1 pid
+ MOVW sig+0(FP), R6 // arg 3
+ MOVV $SYS_tgkill, R2
SYSCALL
RET
@@ -287,7 +291,7 @@ TEXT runtime·madvise(SB),NOSPLIT|NOFRAME,$0
MOVW flags+16(FP), R6
MOVV $SYS_madvise, R2
SYSCALL
- // ignore failure - maybe pages are locked
+ MOVW R2, ret+24(FP)
RET
// int64 futex(int32 *uaddr, int32 op, int32 val,
diff --git a/src/runtime/sys_linux_mipsx.s b/src/runtime/sys_linux_mipsx.s
index a6bca3bebd..f362b0f3f1 100644
--- a/src/runtime/sys_linux_mipsx.s
+++ b/src/runtime/sys_linux_mipsx.s
@@ -35,7 +35,6 @@
#define SYS_madvise 4218
#define SYS_mincore 4217
#define SYS_gettid 4222
-#define SYS_tkill 4236
#define SYS_futex 4238
#define SYS_sched_getaffinity 4240
#define SYS_exit_group 4246
@@ -43,6 +42,7 @@
#define SYS_epoll_ctl 4249
#define SYS_epoll_wait 4250
#define SYS_clock_gettime 4263
+#define SYS_tgkill 4266
#define SYS_epoll_create1 4326
TEXT runtime·exit(SB),NOSPLIT,$0-4
@@ -135,11 +135,15 @@ TEXT runtime·gettid(SB),NOSPLIT,$0-4
RET
TEXT runtime·raise(SB),NOSPLIT,$0-4
+ MOVW $SYS_getpid, R2
+ SYSCALL
+ MOVW R2, R16
MOVW $SYS_gettid, R2
SYSCALL
- MOVW R2, R4 // arg 1 tid
- MOVW sig+0(FP), R5 // arg 2
- MOVW $SYS_tkill, R2
+ MOVW R2, R5 // arg 2 tid
+ MOVW R16, R4 // arg 1 pid
+ MOVW sig+0(FP), R6 // arg 3
+ MOVW $SYS_tgkill, R2
SYSCALL
RET
@@ -298,13 +302,13 @@ TEXT runtime·munmap(SB),NOSPLIT,$0-8
UNDEF // crash
RET
-TEXT runtime·madvise(SB),NOSPLIT,$0-12
+TEXT runtime·madvise(SB),NOSPLIT,$0-16
MOVW addr+0(FP), R4
MOVW n+4(FP), R5
MOVW flags+8(FP), R6
MOVW $SYS_madvise, R2
SYSCALL
- // ignore failure - maybe pages are locked
+ MOVW R2, ret+12(FP)
RET
// int32 futex(int32 *uaddr, int32 op, int32 val, struct timespec *timeout, int32 *uaddr2, int32 val2);
diff --git a/src/runtime/sys_linux_ppc64x.s b/src/runtime/sys_linux_ppc64x.s
index 075adf2368..ed79b69257 100644
--- a/src/runtime/sys_linux_ppc64x.s
+++ b/src/runtime/sys_linux_ppc64x.s
@@ -36,7 +36,6 @@
#define SYS_madvise 205
#define SYS_mincore 206
#define SYS_gettid 207
-#define SYS_tkill 208
#define SYS_futex 221
#define SYS_sched_getaffinity 223
#define SYS_exit_group 234
@@ -44,6 +43,7 @@
#define SYS_epoll_ctl 237
#define SYS_epoll_wait 238
#define SYS_clock_gettime 246
+#define SYS_tgkill 250
#define SYS_epoll_create1 315
TEXT runtime·exit(SB),NOSPLIT|NOFRAME,$0-4
@@ -123,10 +123,13 @@ TEXT runtime·gettid(SB),NOSPLIT,$0-4
RET
TEXT runtime·raise(SB),NOSPLIT|NOFRAME,$0
+ SYSCALL $SYS_getpid
+ MOVW R3, R14
SYSCALL $SYS_gettid
- MOVW R3, R3 // arg 1 tid
- MOVW sig+0(FP), R4 // arg 2
- SYSCALL $SYS_tkill
+ MOVW R3, R4 // arg 2 tid
+ MOVW R14, R3 // arg 1 pid
+ MOVW sig+0(FP), R5 // arg 3
+ SYSCALL $SYS_tgkill
RET
TEXT runtime·raiseproc(SB),NOSPLIT|NOFRAME,$0
@@ -451,7 +454,7 @@ TEXT runtime·madvise(SB),NOSPLIT|NOFRAME,$0
MOVD n+8(FP), R4
MOVW flags+16(FP), R5
SYSCALL $SYS_madvise
- // ignore failure - maybe pages are locked
+ MOVW R3, ret+24(FP)
RET
// int64 futex(int32 *uaddr, int32 op, int32 val,
diff --git a/src/runtime/sys_linux_s390x.s b/src/runtime/sys_linux_s390x.s
index 1ff110c232..c79ceea751 100644
--- a/src/runtime/sys_linux_s390x.s
+++ b/src/runtime/sys_linux_s390x.s
@@ -31,9 +31,9 @@
#define SYS_madvise 219
#define SYS_mincore 218
#define SYS_gettid 236
-#define SYS_tkill 237
#define SYS_futex 238
#define SYS_sched_getaffinity 240
+#define SYS_tgkill 241
#define SYS_exit_group 248
#define SYS_epoll_create 249
#define SYS_epoll_ctl 250
@@ -129,11 +129,15 @@ TEXT runtime·gettid(SB),NOSPLIT,$0-4
RET
TEXT runtime·raise(SB),NOSPLIT|NOFRAME,$0
+ MOVW $SYS_getpid, R1
+ SYSCALL
+ MOVW R2, R10
MOVW $SYS_gettid, R1
SYSCALL
- MOVW R2, R2 // arg 1 tid
- MOVW sig+0(FP), R3 // arg 2
- MOVW $SYS_tkill, R1
+ MOVW R2, R3 // arg 2 tid
+ MOVW R10, R2 // arg 1 pid
+ MOVW sig+0(FP), R4 // arg 2
+ MOVW $SYS_tgkill, R1
SYSCALL
RET
@@ -286,7 +290,7 @@ TEXT runtime·madvise(SB),NOSPLIT|NOFRAME,$0
MOVW flags+16(FP), R4
MOVW $SYS_madvise, R1
SYSCALL
- // ignore failure - maybe pages are locked
+ MOVW R2, ret+24(FP)
RET
// int64 futex(int32 *uaddr, int32 op, int32 val,
diff --git a/src/runtime/sys_nacl_386.s b/src/runtime/sys_nacl_386.s
index cdc8ff1a02..24eaeb238c 100644
--- a/src/runtime/sys_nacl_386.s
+++ b/src/runtime/sys_nacl_386.s
@@ -266,7 +266,7 @@ TEXT runtime·nacl_clock_gettime(SB),NOSPLIT,$8
NACL_SYSCALL(SYS_clock_gettime)
MOVL AX, ret+8(FP)
RET
-
+
TEXT runtime·nanotime(SB),NOSPLIT,$20
MOVL $0, 0(SP) // real time clock
LEAL 8(SP), AX
@@ -308,12 +308,12 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0
// save g
MOVL DI, 20(SP)
-
+
// g = m->gsignal
MOVL g_m(DI), BX
MOVL m_gsignal(BX), BX
MOVL BX, g(CX)
-
+
// copy arguments for sighandler
MOVL $11, 0(SP) // signal
MOVL $0, 4(SP) // siginfo
@@ -356,7 +356,7 @@ ret:
// Today those registers are just PC and SP, but in case additional registers
// are relevant in the future (for example DX is the Go func context register)
// we restore as many registers as possible.
- //
+ //
// We smash BP, because that's what the linker smashes during RET.
//
LEAL ctxt+4(FP), BP
diff --git a/src/runtime/sys_nacl_amd64p32.s b/src/runtime/sys_nacl_amd64p32.s
index 4c4d509576..b4a108346d 100644
--- a/src/runtime/sys_nacl_amd64p32.s
+++ b/src/runtime/sys_nacl_amd64p32.s
@@ -334,13 +334,13 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$80
// check that g exists
get_tls(CX)
MOVL g(CX), DI
-
+
CMPL DI, $0
JEQ nog
// save g
MOVL DI, 20(SP)
-
+
// g = m->gsignal
MOVL g_m(DI), BX
MOVL m_gsignal(BX), BX
diff --git a/src/runtime/sys_netbsd_386.s b/src/runtime/sys_netbsd_386.s
index 4042ab4f8a..66f4620cab 100644
--- a/src/runtime/sys_netbsd_386.s
+++ b/src/runtime/sys_netbsd_386.s
@@ -135,7 +135,9 @@ TEXT runtime·munmap(SB),NOSPLIT,$-4
TEXT runtime·madvise(SB),NOSPLIT,$-4
MOVL $75, AX // sys_madvise
INT $0x80
- // ignore failure - maybe pages are locked
+ JAE 2(PC)
+ MOVL $-1, AX
+ MOVL AX, ret+12(FP)
RET
TEXT runtime·setitimer(SB),NOSPLIT,$-4
diff --git a/src/runtime/sys_netbsd_amd64.s b/src/runtime/sys_netbsd_amd64.s
index 11b9c1b417..531c227a7b 100644
--- a/src/runtime/sys_netbsd_amd64.s
+++ b/src/runtime/sys_netbsd_amd64.s
@@ -23,7 +23,7 @@ TEXT runtime·lwp_create(SB),NOSPLIT,$0
RET
TEXT runtime·lwp_tramp(SB),NOSPLIT,$0
-
+
// Set FS to point at m->tls.
LEAQ m_tls(R8), DI
CALL runtime·settls(SB)
@@ -319,7 +319,9 @@ TEXT runtime·madvise(SB),NOSPLIT,$0
MOVL flags+16(FP), DX // arg 3 - behav
MOVQ $75, AX // sys_madvise
SYSCALL
- // ignore failure - maybe pages are locked
+ JCC 2(PC)
+ MOVL $-1, AX
+ MOVL AX, ret+24(FP)
RET
TEXT runtime·sigaltstack(SB),NOSPLIT,$-8
diff --git a/src/runtime/sys_netbsd_arm.s b/src/runtime/sys_netbsd_arm.s
index 6b2c5a8357..304075f295 100644
--- a/src/runtime/sys_netbsd_arm.s
+++ b/src/runtime/sys_netbsd_arm.s
@@ -284,11 +284,12 @@ TEXT runtime·munmap(SB),NOSPLIT,$0
RET
TEXT runtime·madvise(SB),NOSPLIT,$0
- MOVW addr+0(FP), R0 // arg 1 - addr
- MOVW n+4(FP), R1 // arg 2 - len
- MOVW flags+8(FP), R2 // arg 3 - behav
- SWI $0xa0004b // sys_madvise
- // ignore failure - maybe pages are locked
+ MOVW addr+0(FP), R0 // arg 1 - addr
+ MOVW n+4(FP), R1 // arg 2 - len
+ MOVW flags+8(FP), R2 // arg 3 - behav
+ SWI $0xa0004b // sys_madvise
+ MOVW.CS $-1, R0
+ MOVW R0, ret+12(FP)
RET
TEXT runtime·sigaltstack(SB),NOSPLIT|NOFRAME,$0
diff --git a/src/runtime/sys_openbsd_386.s b/src/runtime/sys_openbsd_386.s
index 21f13c806e..d555edb71f 100644
--- a/src/runtime/sys_openbsd_386.s
+++ b/src/runtime/sys_openbsd_386.s
@@ -136,7 +136,8 @@ TEXT runtime·madvise(SB),NOSPLIT,$-4
MOVL $75, AX // sys_madvise
INT $0x80
JAE 2(PC)
- MOVL $0xf1, 0xf1 // crash
+ MOVL $-1, AX
+ MOVL AX, ret+12(FP)
RET
TEXT runtime·setitimer(SB),NOSPLIT,$-4
@@ -294,7 +295,7 @@ TEXT runtime·tfork(SB),NOSPLIT,$12
CALL runtime·settls(SB)
POPL AX
POPAL
-
+
// Now segment is established. Initialize m, g.
get_tls(AX)
MOVL DX, g(AX)
diff --git a/src/runtime/sys_openbsd_amd64.s b/src/runtime/sys_openbsd_amd64.s
index 38ac38d9bf..227e81869c 100644
--- a/src/runtime/sys_openbsd_amd64.s
+++ b/src/runtime/sys_openbsd_amd64.s
@@ -305,7 +305,9 @@ TEXT runtime·madvise(SB),NOSPLIT,$0
MOVL flags+16(FP), DX // arg 3 - behav
MOVQ $75, AX // sys_madvise
SYSCALL
- // ignore failure - maybe pages are locked
+ JCC 2(PC)
+ MOVL $-1, AX
+ MOVL AX, ret+24(FP)
RET
TEXT runtime·sigaltstack(SB),NOSPLIT,$-8
diff --git a/src/runtime/sys_openbsd_arm.s b/src/runtime/sys_openbsd_arm.s
index ff1c1da9b9..52d3638bc1 100644
--- a/src/runtime/sys_openbsd_arm.s
+++ b/src/runtime/sys_openbsd_arm.s
@@ -143,8 +143,8 @@ TEXT runtime·madvise(SB),NOSPLIT,$0
MOVW flags+8(FP), R2 // arg 2 - flags
MOVW $75, R12 // sys_madvise
SWI $0
- MOVW.CS $0, R8 // crash on syscall failure
- MOVW.CS R8, (R8)
+ MOVW.CS $-1, R0
+ MOVW R0, ret+12(FP)
RET
TEXT runtime·setitimer(SB),NOSPLIT,$0
diff --git a/src/runtime/sys_plan9_386.s b/src/runtime/sys_plan9_386.s
index 47dcb8db04..a7fb9fe6f7 100644
--- a/src/runtime/sys_plan9_386.s
+++ b/src/runtime/sys_plan9_386.s
@@ -126,7 +126,7 @@ TEXT runtime·noted(SB),NOSPLIT,$0
INT $64
MOVL AX, ret+4(FP)
RET
-
+
TEXT runtime·plan9_semrelease(SB),NOSPLIT,$0
MOVL $38, AX
INT $64
diff --git a/src/runtime/sys_plan9_amd64.s b/src/runtime/sys_plan9_amd64.s
index 8077d6d324..4ef4aab376 100644
--- a/src/runtime/sys_plan9_amd64.s
+++ b/src/runtime/sys_plan9_amd64.s
@@ -123,7 +123,7 @@ TEXT runtime·noted(SB),NOSPLIT,$0
SYSCALL
MOVL AX, ret+8(FP)
RET
-
+
TEXT runtime·plan9_semrelease(SB),NOSPLIT,$0
MOVQ $38, BP
SYSCALL
diff --git a/src/runtime/sys_solaris_amd64.s b/src/runtime/sys_solaris_amd64.s
index 2b6dabab99..930fc88997 100644
--- a/src/runtime/sys_solaris_amd64.s
+++ b/src/runtime/sys_solaris_amd64.s
@@ -63,9 +63,9 @@ TEXT runtime·pipe1(SB),NOSPLIT,$0
// Call a library function with SysV calling conventions.
// The called function can take a maximum of 6 INTEGER class arguments,
-// see
+// see
// Michael Matz, Jan Hubicka, Andreas Jaeger, and Mark Mitchell
-// System V Application Binary Interface
+// System V Application Binary Interface
// AMD64 Architecture Processor Supplement
// section 3.2.3.
//
@@ -119,7 +119,7 @@ skipargs:
MOVL 0(AX), AX
MOVQ AX, libcall_err(DI)
-skiperrno2:
+skiperrno2:
RET
// uint32 tstart_sysvicall(M *newm);
@@ -186,7 +186,7 @@ allgood:
// Save m->libcall and m->scratch. We need to do this because we
// might get interrupted by a signal in runtime·asmcgocall.
- // save m->libcall
+ // save m->libcall
MOVQ g_m(R10), BP
LEAQ m_libcall(BP), R11
MOVQ libcall_fn(R11), R10
diff --git a/src/runtime/sys_windows_386.s b/src/runtime/sys_windows_386.s
index 3c091adcb1..babd91c936 100644
--- a/src/runtime/sys_windows_386.s
+++ b/src/runtime/sys_windows_386.s
@@ -494,13 +494,13 @@ wall:
MOVL (_SYSTEM_TIME+time_hi2), DX
CMPL CX, DX
JNE wall
-
+
// w = DX:AX
// convert to Unix epoch (but still 100ns units)
#define delta 116444736000000000
SUBL $(delta & 0xFFFFFFFF), AX
SBBL $(delta >> 32), DX
-
+
// nano/100 = DX:AX
// split into two decimal halves by div 1e9.
// (decimal point is two spots over from correct place,
@@ -509,7 +509,7 @@ wall:
DIVL CX
MOVL AX, DI
MOVL DX, SI
-
+
// DI = nano/100/1e9 = nano/1e11 = sec/100, DX = SI = nano/100%1e9
// split DX into seconds and nanoseconds by div 1e7 magic multiply.
MOVL DX, AX
@@ -520,7 +520,7 @@ wall:
IMULL $10000000, DX
MOVL SI, CX
SUBL DX, CX
-
+
// DI = sec/100 (still)
// BX = (nano/100%1e9)/1e7 = (nano/1e9)%100 = sec%100
// CX = (nano/100%1e9)%1e7 = (nano%1e9)/100 = nsec/100
diff --git a/src/runtime/sys_windows_amd64.s b/src/runtime/sys_windows_amd64.s
index c9127ac2d2..ec49caa43e 100644
--- a/src/runtime/sys_windows_amd64.s
+++ b/src/runtime/sys_windows_amd64.s
@@ -89,7 +89,7 @@ TEXT runtime·badsignal2(SB),NOSPLIT|NOFRAME,$48
MOVQ $0, 32(SP) // overlapped
MOVQ runtime·_WriteFile(SB), AX
CALL AX
-
+
RET
// faster get/set last error
diff --git a/src/runtime/sys_windows_arm.s b/src/runtime/sys_windows_arm.s
new file mode 100644
index 0000000000..409c72c554
--- /dev/null
+++ b/src/runtime/sys_windows_arm.s
@@ -0,0 +1,605 @@
+// Copyright 2018 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 "go_asm.h"
+#include "go_tls.h"
+#include "textflag.h"
+
+// void runtime·asmstdcall(void *c);
+TEXT runtime·asmstdcall(SB),NOSPLIT|NOFRAME,$0
+ MOVM.DB.W [R4, R5, R14], (R13) // push {r4, r5, lr}
+ MOVW R0, R4 // put libcall * in r4
+ MOVW R13, R5 // save stack pointer in r5
+
+ // SetLastError(0)
+ MOVW $0, R0
+ MRC 15, 0, R1, C13, C0, 2
+ MOVW R0, 0x34(R1)
+
+ MOVW 8(R4), R12 // libcall->args
+
+ // Do we have more than 4 arguments?
+ MOVW 4(R4), R0 // libcall->n
+ SUB.S $4, R0, R2
+ BLE loadregs
+
+ // Reserve stack space for remaining args
+ SUB R2<<2, R13
+ BIC $0x7, R13 // alignment for ABI
+
+ // R0: count of arguments
+ // R1:
+ // R2: loop counter, from 0 to (n-4)
+ // R3: scratch
+ // R4: pointer to libcall struct
+ // R12: libcall->args
+ MOVW $0, R2
+stackargs:
+ ADD $4, R2, R3 // r3 = args[4 + i]
+ MOVW R3<<2(R12), R3
+ MOVW R3, R2<<2(R13) // stack[i] = r3
+
+ ADD $1, R2 // i++
+ SUB $4, R0, R3 // while (i < (n - 4))
+ CMP R3, R2
+ BLT stackargs
+
+loadregs:
+ CMP $3, R0
+ MOVW.GT 12(R12), R3
+
+ CMP $2, R0
+ MOVW.GT 8(R12), R2
+
+ CMP $1, R0
+ MOVW.GT 4(R12), R1
+
+ CMP $0, R0
+ MOVW.GT 0(R12), R0
+
+ BIC $0x7, R13 // alignment for ABI
+ MOVW 0(R4), R12 // branch to libcall->fn
+ BL (R12)
+
+ MOVW R5, R13 // free stack space
+ MOVW R0, 12(R4) // save return value to libcall->r1
+ MOVW R1, 16(R4)
+
+ // GetLastError
+ MRC 15, 0, R1, C13, C0, 2
+ MOVW 0x34(R1), R0
+ MOVW R0, 20(R4) // store in libcall->err
+
+ MOVM.IA.W (R13), [R4, R5, R15]
+
+TEXT runtime·badsignal2(SB),NOSPLIT|NOFRAME,$0
+ MOVM.DB.W [R4, R14], (R13) // push {r4, lr}
+ MOVW R13, R4 // save original stack pointer
+ SUB $8, R13 // space for 2 variables
+ BIC $0x7, R13 // alignment for ABI
+
+ // stderr
+ MOVW runtime·_GetStdHandle(SB), R1
+ MOVW $-12, R0
+ BL (R1)
+
+ MOVW $runtime·badsignalmsg(SB), R1 // lpBuffer
+ MOVW $runtime·badsignallen(SB), R2 // lpNumberOfBytesToWrite
+ MOVW (R2), R2
+ ADD $0x4, R13, R3 // lpNumberOfBytesWritten
+ MOVW $0, R12 // lpOverlapped
+ MOVW R12, (R13)
+
+ MOVW runtime·_WriteFile(SB), R12
+ BL (R12)
+
+ MOVW R4, R13 // restore SP
+ MOVM.IA.W (R13), [R4, R15] // pop {r4, pc}
+
+TEXT runtime·getlasterror(SB),NOSPLIT,$0
+ MRC 15, 0, R0, C13, C0, 2
+ MOVW 0x34(R0), R0
+ MOVW R0, ret+0(FP)
+ RET
+
+TEXT runtime·setlasterror(SB),NOSPLIT|NOFRAME,$0
+ MRC 15, 0, R1, C13, C0, 2
+ MOVW R0, 0x34(R1)
+ RET
+
+// Called by Windows as a Vectored Exception Handler (VEH).
+// First argument is pointer to struct containing
+// exception record and context pointers.
+// Handler function is stored in R1
+// Return 0 for 'not handled', -1 for handled.
+// int32_t sigtramp(
+// PEXCEPTION_POINTERS ExceptionInfo,
+// func *GoExceptionHandler);
+TEXT runtime·sigtramp(SB),NOSPLIT|NOFRAME,$0
+ MOVM.DB.W [R0, R4-R11, R14], (R13) // push {r0, r4-r11, lr} (SP-=40)
+ SUB $(8+20), R13 // reserve space for g, sp, and
+ // parameters/retval to go call
+
+ MOVW R0, R6 // Save param0
+ MOVW R1, R7 // Save param1
+
+ BL runtime·load_g(SB)
+ CMP $0, g // is there a current g?
+ BL.EQ runtime·badsignal2(SB)
+
+ // save g and SP in case of stack switch
+ MOVW R13, 24(R13)
+ MOVW g, 20(R13)
+
+ // do we need to switch to the g0 stack?
+ MOVW g, R5 // R5 = g
+ MOVW g_m(R5), R2 // R2 = m
+ MOVW m_g0(R2), R4 // R4 = g0
+ CMP R5, R4 // if curg == g0
+ BEQ g0
+
+ // switch to g0 stack
+ MOVW R4, g // g = g0
+ MOVW (g_sched+gobuf_sp)(g), R3 // R3 = g->gobuf.sp
+ BL runtime·save_g(SB)
+
+ // traceback will think that we've done PUSH and SUB
+ // on this stack, so subtract them here to match.
+ // (we need room for sighandler arguments anyway).
+ // and re-save old SP for restoring later.
+ SUB $(40+8+20), R3
+ MOVW R13, 24(R3) // save old stack pointer
+ MOVW R3, R13 // switch stack
+
+g0:
+ MOVW 0(R6), R2 // R2 = ExceptionPointers->ExceptionRecord
+ MOVW 4(R6), R3 // R3 = ExceptionPointers->ContextRecord
+
+ // make it look like mstart called us on g0, to stop traceback
+ MOVW $runtime·mstart(SB), R4
+
+ MOVW R4, 0(R13) // Save link register for traceback
+ MOVW R2, 4(R13) // Move arg0 (ExceptionRecord) into position
+ MOVW R3, 8(R13) // Move arg1 (ContextRecord) into position
+ MOVW R5, 12(R13) // Move arg2 (original g) into position
+ BL (R7) // Call the go routine
+ MOVW 16(R13), R4 // Fetch return value from stack
+
+ // Compute the value of the g0 stack pointer after deallocating
+ // this frame, then allocating 8 bytes. We may need to store
+ // the resume SP and PC on the g0 stack to work around
+ // control flow guard when we resume from the exception.
+ ADD $(40+20), R13, R12
+
+ // switch back to original stack and g
+ MOVW 24(R13), R13
+ MOVW 20(R13), g
+ BL runtime·save_g(SB)
+
+done:
+ MOVW R4, R0 // move retval into position
+ ADD $(8 + 20), R13 // free locals
+ MOVM.IA.W (R13), [R3, R4-R11, R14] // pop {r3, r4-r11, lr}
+
+ // if return value is CONTINUE_SEARCH, do not set up control
+ // flow guard workaround
+ CMP $0, R0
+ BEQ return
+
+ // Check if we need to set up the control flow guard workaround.
+ // On Windows/ARM, the stack pointer must lie within system
+ // stack limits when we resume from exception.
+ // Store the resume SP and PC on the g0 stack,
+ // and return to returntramp on the g0 stack. returntramp
+ // pops the saved PC and SP from the g0 stack, resuming execution
+ // at the desired location.
+ // If returntramp has already been set up by a previous exception
+ // handler, don't clobber the stored SP and PC on the stack.
+ MOVW 4(R3), R3 // PEXCEPTION_POINTERS->Context
+ MOVW 0x40(R3), R2 // load PC from context record
+ MOVW $runtime·returntramp(SB), R1
+ CMP R1, R2
+ B.EQ return // do not clobber saved SP/PC
+
+ // Save resume SP and PC on g0 stack
+ MOVW 0x38(R3), R2 // load SP from context record
+ MOVW R2, 0(R12) // Store resume SP on g0 stack
+ MOVW 0x40(R3), R2 // load PC from context record
+ MOVW R2, 4(R12) // Store resume PC on g0 stack
+
+ // Set up context record to return to returntramp on g0 stack
+ MOVW R12, 0x38(R3) // save g0 stack pointer
+ // in context record
+ MOVW $runtime·returntramp(SB), R2 // save resume address
+ MOVW R2, 0x40(R3) // in context record
+
+return:
+ B (R14) // return
+
+//
+// Trampoline to resume execution from exception handler.
+// This is part of the control flow guard workaround.
+// It switches stacks and jumps to the continuation address.
+//
+TEXT runtime·returntramp(SB),NOSPLIT|NOFRAME,$0
+ MOVM.IA (R13), [R13, R15] // ldm sp, [sp, pc]
+
+TEXT runtime·exceptiontramp(SB),NOSPLIT|NOFRAME,$0
+ MOVW $runtime·exceptionhandler(SB), R1
+ B runtime·sigtramp(SB)
+
+TEXT runtime·firstcontinuetramp(SB),NOSPLIT|NOFRAME,$0
+ MOVW $runtime·firstcontinuehandler(SB), R1
+ B runtime·sigtramp(SB)
+
+TEXT runtime·lastcontinuetramp(SB),NOSPLIT|NOFRAME,$0
+ MOVW $runtime·lastcontinuehandler(SB), R1
+ B runtime·sigtramp(SB)
+
+TEXT runtime·ctrlhandler(SB),NOSPLIT|NOFRAME,$0
+ MOVW $runtime·ctrlhandler1(SB), R1
+ B runtime·externalthreadhandler(SB)
+
+TEXT runtime·profileloop(SB),NOSPLIT|NOFRAME,$0
+ MOVW $runtime·profileloop1(SB), R1
+ B runtime·externalthreadhandler(SB)
+
+// int32 externalthreadhandler(uint32 arg, int (*func)(uint32))
+// stack layout:
+// +----------------+
+// | callee-save |
+// | registers |
+// +----------------+
+// | m |
+// +----------------+
+// 20| g |
+// +----------------+
+// 16| func ptr (r1) |
+// +----------------+
+// 12| argument (r0) |
+//---+----------------+
+// 8 | param1 |
+// +----------------+
+// 4 | param0 |
+// +----------------+
+// 0 | retval |
+// +----------------+
+//
+TEXT runtime·externalthreadhandler(SB),NOSPLIT|NOFRAME,$0
+ MOVM.DB.W [R4-R11, R14], (R13) // push {r4-r11, lr}
+ SUB $(m__size + g__size + 20), R13 // space for locals
+ MOVW R0, 12(R13)
+ MOVW R1, 16(R13)
+
+ // zero out m and g structures
+ ADD $20, R13, R0 // compute pointer to g
+ MOVW R0, 4(R13)
+ MOVW $(m__size + g__size), R0
+ MOVW R0, 8(R13)
+ BL runtime·memclrNoHeapPointers(SB)
+
+ // initialize m and g structures
+ ADD $20, R13, R2 // R2 = g
+ ADD $(20 + g__size), R13, R3 // R3 = m
+ MOVW R2, m_g0(R3) // m->g0 = g
+ MOVW R3, g_m(R2) // g->m = m
+ MOVW R2, m_curg(R3) // m->curg = g
+
+ MOVW R2, g
+ BL runtime·save_g(SB)
+
+ // set up stackguard stuff
+ MOVW R13, R0
+ MOVW R0, g_stack+stack_hi(g)
+ SUB $(32*1024), R0
+ MOVW R0, (g_stack+stack_lo)(g)
+ MOVW R0, g_stackguard0(g)
+ MOVW R0, g_stackguard1(g)
+
+ // move argument into position and call function
+ MOVW 12(R13), R0
+ MOVW R0, 4(R13)
+ MOVW 16(R13), R1
+ BL (R1)
+
+ // clear g
+ MOVW $0, g
+ BL runtime·save_g(SB)
+
+ MOVW 0(R13), R0 // load return value
+ ADD $(m__size + g__size + 20), R13 // free locals
+ MOVM.IA.W (R13), [R4-R11, R15] // pop {r4-r11, pc}
+
+GLOBL runtime·cbctxts(SB), NOPTR, $4
+
+TEXT runtime·callbackasm1(SB),NOSPLIT|NOFRAME,$0
+ MOVM.DB.W [R4-R11, R14], (R13) // push {r4-r11, lr}
+ SUB $36, R13 // space for locals
+
+ // save callback arguments to stack. We currently support up to 4 arguments
+ ADD $16, R13, R4
+ MOVM.IA [R0-R3], (R4)
+
+ // load cbctxts[i]. The trampoline in zcallback_windows.s puts the callback
+ // index in R12
+ MOVW runtime·cbctxts(SB), R4
+ MOVW R12<<2(R4), R4 // R4 holds pointer to wincallbackcontext structure
+
+ // extract callback context
+ MOVW wincallbackcontext_argsize(R4), R5
+ MOVW wincallbackcontext_gobody(R4), R4
+
+ // we currently support up to 4 arguments
+ CMP $(4 * 4), R5
+ BL.GT runtime·abort(SB)
+
+ // extend argsize by size of return value
+ ADD $4, R5
+
+ // Build 'type args struct'
+ MOVW R4, 4(R13) // fn
+ ADD $16, R13, R0 // arg (points to r0-r3, ret on stack)
+ MOVW R0, 8(R13)
+ MOVW R5, 12(R13) // argsize
+
+ BL runtime·load_g(SB)
+ BL runtime·cgocallback_gofunc(SB)
+
+ ADD $16, R13, R0 // load arg
+ MOVW 12(R13), R1 // load argsize
+ SUB $4, R1 // offset to return value
+ MOVW R1<<0(R0), R0 // load return value
+
+ ADD $36, R13 // free locals
+ MOVM.IA.W (R13), [R4-R11, R15] // pop {r4-r11, pc}
+
+// uint32 tstart_stdcall(M *newm);
+TEXT runtime·tstart_stdcall(SB),NOSPLIT|NOFRAME,$0
+ MOVM.DB.W [R4-R11, R14], (R13) // push {r4-r11, lr}
+
+ MOVW m_g0(R0), g
+ MOVW R0, g_m(g)
+ BL runtime·save_g(SB)
+
+ // Layout new m scheduler stack on os stack.
+ MOVW R13, R0
+ MOVW R0, g_stack+stack_hi(g)
+ SUB $(64*1024), R0
+ MOVW R0, (g_stack+stack_lo)(g)
+ MOVW R0, g_stackguard0(g)
+ MOVW R0, g_stackguard1(g)
+
+ BL runtime·emptyfunc(SB) // fault if stack check is wrong
+ BL runtime·mstart(SB)
+
+ // Exit the thread.
+ MOVW $0, R0
+ MOVM.IA.W (R13), [R4-R11, R15] // pop {r4-r11, pc}
+
+// onosstack calls fn on OS stack.
+// adapted from asm_arm.s : systemstack
+// func onosstack(fn unsafe.Pointer, arg uint32)
+TEXT runtime·onosstack(SB),NOSPLIT,$0
+ MOVW fn+0(FP), R5 // R5 = fn
+ MOVW arg+4(FP), R6 // R6 = arg
+
+ // This function can be called when there is no g,
+ // for example, when we are handling a callback on a non-go thread.
+ // In this case we're already on the system stack.
+ CMP $0, g
+ BEQ noswitch
+
+ MOVW g_m(g), R1 // R1 = m
+
+ MOVW m_gsignal(R1), R2 // R2 = gsignal
+ CMP g, R2
+ B.EQ noswitch
+
+ MOVW m_g0(R1), R2 // R2 = g0
+ CMP g, R2
+ B.EQ noswitch
+
+ MOVW m_curg(R1), R3
+ CMP g, R3
+ B.EQ switch
+
+ // Bad: g is not gsignal, not g0, not curg. What is it?
+ // Hide call from linker nosplit analysis.
+ MOVW $runtime·badsystemstack(SB), R0
+ BL (R0)
+ B runtime·abort(SB)
+
+switch:
+ // save our state in g->sched. Pretend to
+ // be systemstack_switch if the G stack is scanned.
+ MOVW $runtime·systemstack_switch(SB), R3
+ ADD $4, R3, R3 // get past push {lr}
+ MOVW R3, (g_sched+gobuf_pc)(g)
+ MOVW R13, (g_sched+gobuf_sp)(g)
+ MOVW LR, (g_sched+gobuf_lr)(g)
+ MOVW g, (g_sched+gobuf_g)(g)
+
+ // switch to g0
+ MOVW R2, g
+ MOVW (g_sched+gobuf_sp)(R2), R3
+ // make it look like mstart called systemstack on g0, to stop traceback
+ SUB $4, R3, R3
+ MOVW $runtime·mstart(SB), R4
+ MOVW R4, 0(R3)
+ MOVW R3, R13
+
+ // call target function
+ MOVW R6, R0 // arg
+ BL (R5)
+
+ // switch back to g
+ MOVW g_m(g), R1
+ MOVW m_curg(R1), g
+ MOVW (g_sched+gobuf_sp)(g), R13
+ MOVW $0, R3
+ MOVW R3, (g_sched+gobuf_sp)(g)
+ RET
+
+noswitch:
+ // Using a tail call here cleans up tracebacks since we won't stop
+ // at an intermediate systemstack.
+ MOVW.P 4(R13), R14 // restore LR
+ MOVW R6, R0 // arg
+ B (R5)
+
+// Runs on OS stack. Duration (in 100ns units) is in R0.
+TEXT runtime·usleep2(SB),NOSPLIT|NOFRAME,$0
+ MOVM.DB.W [R4, R14], (R13) // push {r4, lr}
+ MOVW R13, R4 // Save SP
+ SUB $8, R13 // R13 = R13 - 8
+ BIC $0x7, R13 // Align SP for ABI
+ RSB $0, R0, R3 // R3 = -R0
+ MOVW $0, R1 // R1 = FALSE (alertable)
+ MOVW $-1, R0 // R0 = handle
+ MOVW R13, R2 // R2 = pTime
+ MOVW R3, 0(R2) // time_lo
+ MOVW R0, 4(R2) // time_hi
+ MOVW runtime·_NtWaitForSingleObject(SB), R3
+ BL (R3)
+ MOVW R4, R13 // Restore SP
+ MOVM.IA.W (R13), [R4, R15] // pop {R4, pc}
+
+// Runs on OS stack.
+TEXT runtime·switchtothread(SB),NOSPLIT|NOFRAME,$0
+ MOVM.DB.W [R4, R14], (R13) // push {R4, lr}
+ MOVW R13, R4
+ BIC $0x7, R13 // alignment for ABI
+ MOVW runtime·_SwitchToThread(SB), R0
+ BL (R0)
+ MOVW R4, R13 // restore stack pointer
+ MOVM.IA.W (R13), [R4, R15] // pop {R4, pc}
+
+TEXT ·publicationBarrier(SB),NOSPLIT|NOFRAME,$0-0
+ B runtime·armPublicationBarrier(SB)
+
+// never called (cgo not supported)
+TEXT runtime·read_tls_fallback(SB),NOSPLIT|NOFRAME,$0
+ MOVW $0xabcd, R0
+ MOVW R0, (R0)
+ RET
+
+// See http://www.dcl.hpi.uni-potsdam.de/research/WRK/2007/08/getting-os-information-the-kuser_shared_data-structure/
+// Must read hi1, then lo, then hi2. The snapshot is valid if hi1 == hi2.
+#define _INTERRUPT_TIME 0x7ffe0008
+#define _SYSTEM_TIME 0x7ffe0014
+#define time_lo 0
+#define time_hi1 4
+#define time_hi2 8
+
+TEXT runtime·nanotime(SB),NOSPLIT,$0-8
+ MOVW $0, R0
+ MOVB runtime·useQPCTime(SB), R0
+ CMP $0, R0
+ BNE useQPC
+ MOVW $_INTERRUPT_TIME, R3
+loop:
+ MOVW time_hi1(R3), R1
+ MOVW time_lo(R3), R0
+ MOVW time_hi2(R3), R2
+ CMP R1, R2
+ BNE loop
+
+ // wintime = R1:R0, multiply by 100
+ MOVW $100, R2
+ MULLU R0, R2, (R4, R3) // R4:R3 = R1:R0 * R2
+ MULA R1, R2, R4, R4
+
+ // wintime*100 = R4:R3, subtract startNano and return
+ MOVW runtime·startNano+0(SB), R0
+ MOVW runtime·startNano+4(SB), R1
+ SUB.S R0, R3
+ SBC R1, R4
+ MOVW R3, ret_lo+0(FP)
+ MOVW R4, ret_hi+4(FP)
+ RET
+useQPC:
+ B runtime·nanotimeQPC(SB) // tail call
+ RET
+
+TEXT time·now(SB),NOSPLIT,$0-20
+ MOVW $0, R0
+ MOVB runtime·useQPCTime(SB), R0
+ CMP $0, R0
+ BNE useQPC
+ MOVW $_INTERRUPT_TIME, R3
+loop:
+ MOVW time_hi1(R3), R1
+ MOVW time_lo(R3), R0
+ MOVW time_hi2(R3), R2
+ CMP R1, R2
+ BNE loop
+
+ // wintime = R1:R0, multiply by 100
+ MOVW $100, R2
+ MULLU R0, R2, (R4, R3) // R4:R3 = R1:R0 * R2
+ MULA R1, R2, R4, R4
+
+ // wintime*100 = R4:R3, subtract startNano and return
+ MOVW runtime·startNano+0(SB), R0
+ MOVW runtime·startNano+4(SB), R1
+ SUB.S R0, R3
+ SBC R1, R4
+ MOVW R3, mono+12(FP)
+ MOVW R4, mono+16(FP)
+
+ MOVW $_SYSTEM_TIME, R3
+wall:
+ MOVW time_hi1(R3), R1
+ MOVW time_lo(R3), R0
+ MOVW time_hi2(R3), R2
+ CMP R1, R2
+ BNE wall
+
+ // w = R1:R0 in 100ns untis
+ // convert to Unix epoch (but still 100ns units)
+ #define delta 116444736000000000
+ SUB.S $(delta & 0xFFFFFFFF), R0
+ SBC $(delta >> 32), R1
+
+ // Convert to nSec
+ MOVW $100, R2
+ MULLU R0, R2, (R4, R3) // R4:R3 = R1:R0 * R2
+ MULA R1, R2, R4, R4
+ // w = R2:R1 in nSec
+ MOVW R3, R1 // R4:R3 -> R2:R1
+ MOVW R4, R2
+
+ // multiply nanoseconds by reciprocal of 10**9 (scaled by 2**61)
+ // to get seconds (96 bit scaled result)
+ MOVW $0x89705f41, R3 // 2**61 * 10**-9
+ MULLU R1,R3,(R6,R5) // R7:R6:R5 = R2:R1 * R3
+ MOVW $0,R7
+ MULALU R2,R3,(R7,R6)
+
+ // unscale by discarding low 32 bits, shifting the rest by 29
+ MOVW R6>>29,R6 // R7:R6 = (R7:R6:R5 >> 61)
+ ORR R7<<3,R6
+ MOVW R7>>29,R7
+
+ // subtract (10**9 * sec) from nsec to get nanosecond remainder
+ MOVW $1000000000, R5 // 10**9
+ MULLU R6,R5,(R9,R8) // R9:R8 = R7:R6 * R5
+ MULA R7,R5,R9,R9
+ SUB.S R8,R1 // R2:R1 -= R9:R8
+ SBC R9,R2
+
+ // because reciprocal was a truncated repeating fraction, quotient
+ // may be slightly too small -- adjust to make remainder < 10**9
+ CMP R5,R1 // if remainder > 10**9
+ SUB.HS R5,R1 // remainder -= 10**9
+ ADD.HS $1,R6 // sec += 1
+
+ MOVW R6,sec_lo+0(FP)
+ MOVW R7,sec_hi+4(FP)
+ MOVW R1,nsec+8(FP)
+ RET
+useQPC:
+ B runtime·nanotimeQPC(SB) // tail call
+ RET
+
diff --git a/src/runtime/syscall_windows.go b/src/runtime/syscall_windows.go
index 8264070569..0858efaf61 100644
--- a/src/runtime/syscall_windows.go
+++ b/src/runtime/syscall_windows.go
@@ -25,18 +25,32 @@ func (c *wincallbackcontext) setCleanstack(cleanstack bool) {
var (
cbs callbacks
cbctxts **wincallbackcontext = &cbs.ctxt[0] // to simplify access to cbs.ctxt in sys_windows_*.s
-
- callbackasm byte // type isn't really byte, it's code in runtime
)
+func callbackasm()
+
// callbackasmAddr returns address of runtime.callbackasm
// function adjusted by i.
-// runtime.callbackasm is just a series of CALL instructions
-// (each is 5 bytes long), and we want callback to arrive at
+// On x86 and amd64, runtime.callbackasm is a series of CALL instructions,
+// and we want callback to arrive at
// correspondent call instruction instead of start of
// runtime.callbackasm.
+// On ARM, runtime.callbackasm is a series of mov and branch instructions.
+// R12 is loaded with the callback index. Each entry is two instructions,
+// hence 8 bytes.
func callbackasmAddr(i int) uintptr {
- return uintptr(add(unsafe.Pointer(&callbackasm), uintptr(i*5)))
+ var entrySize int
+ switch GOARCH {
+ default:
+ panic("unsupported architecture")
+ case "386", "amd64":
+ entrySize = 5
+ case "arm":
+ // On ARM, each entry is a MOV instruction
+ // followed by a branch instruction
+ entrySize = 8
+ }
+ return funcPC(callbackasm) + uintptr(i*entrySize)
}
//go:linkname compileCallback syscall.compileCallback
diff --git a/src/runtime/testdata/testprogcgo/exec.go b/src/runtime/testdata/testprogcgo/exec.go
index 2e948401c8..94da5dc526 100644
--- a/src/runtime/testdata/testprogcgo/exec.go
+++ b/src/runtime/testdata/testprogcgo/exec.go
@@ -75,6 +75,14 @@ func CgoExecSignalMask() {
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
+ // An overloaded system
+ // may fail with EAGAIN.
+ // This doesn't tell us
+ // anything useful; ignore it.
+ // Issue #27731.
+ if isEAGAIN(err) {
+ return
+ }
fmt.Printf("iteration %d: %v\n", j, err)
os.Exit(1)
}
@@ -87,3 +95,11 @@ func CgoExecSignalMask() {
fmt.Println("OK")
}
+
+// isEAGAIN reports whether err is an EAGAIN error from a process execution.
+func isEAGAIN(err error) bool {
+ if p, ok := err.(*os.PathError); ok {
+ err = p.Err
+ }
+ return err == syscall.EAGAIN
+}
diff --git a/src/runtime/timestub2.go b/src/runtime/timestub2.go
index 9ddc6fed91..00c2c55f46 100644
--- a/src/runtime/timestub2.go
+++ b/src/runtime/timestub2.go
@@ -5,6 +5,7 @@
// +build !darwin
// +build !windows
// +build !freebsd
+// +build !aix
package runtime
diff --git a/src/runtime/tls_arm.s b/src/runtime/tls_arm.s
index cc547a5db1..e2c945d183 100644
--- a/src/runtime/tls_arm.s
+++ b/src/runtime/tls_arm.s
@@ -23,6 +23,9 @@
#ifdef GOOS_darwin
#define TLSG_IS_VARIABLE
#endif
+#ifdef GOOS_windows
+#define TLSG_IS_VARIABLE
+#endif
// save_g saves the g register into pthread-provided
// thread-local memory, so that we can call externally compiled
@@ -36,6 +39,17 @@ TEXT runtime·save_g(SB),NOSPLIT|NOFRAME,$0
MOVW g, R0 // preserve R0 across call to setg<>
RET
#else
+#ifdef GOOS_windows
+ // Save the value in the _TEB->TlsSlots array.
+ // Effectively implements TlsSetValue().
+ MRC 15, 0, R0, C13, C0, 2
+ ADD $0xe10, R0
+ MOVW $runtime·tls_g(SB), R11
+ MOVW (R11), R11
+ MOVW g, R11<<2(R0)
+ MOVW g, R0 // preserve R0 accross call to setg<>
+ RET
+#else
// If the host does not support MRC the linker will replace it with
// a call to runtime.read_tls_fallback which jumps to __kuser_get_tls.
// The replacement function saves LR in R11 over the call to read_tls_fallback.
@@ -47,6 +61,7 @@ TEXT runtime·save_g(SB),NOSPLIT|NOFRAME,$0
MOVW g, R0 // preserve R0 across call to setg<>
RET
#endif
+#endif
// load_g loads the g register from pthread-provided
// thread-local memory, for use after calling externally compiled
@@ -56,6 +71,16 @@ TEXT runtime·load_g(SB),NOSPLIT,$0
// nothing to do as nacl/arm does not use TLS at all.
RET
#else
+#ifdef GOOS_windows
+ // Get the value from the _TEB->TlsSlots array.
+ // Effectively implements TlsGetValue().
+ MRC 15, 0, R0, C13, C0, 2
+ ADD $0xe10, R0
+ MOVW $runtime·tls_g(SB), g
+ MOVW (g), g
+ MOVW g<<2(R0), g
+ RET
+#else
// See save_g
MRC 15, 0, R0, C13, C0, 3 // fetch TLS base pointer
BIC $3, R0 // Darwin/ARM might return unaligned pointer
@@ -64,6 +89,7 @@ TEXT runtime·load_g(SB),NOSPLIT,$0
MOVW 0(R0), g
RET
#endif
+#endif
// This is called from rt0_go, which runs on the system stack
// using the initial stack allocated by the OS.
@@ -76,6 +102,20 @@ TEXT runtime·load_g(SB),NOSPLIT,$0
// Declare a dummy word ($4, not $0) to make sure the
// frame is 8 bytes and stays 8-byte-aligned.
TEXT runtime·_initcgo(SB),NOSPLIT,$4
+#ifdef GOOS_windows
+ MOVW R13, R4
+ BIC $0x7, R13
+ MOVW $runtime·_TlsAlloc(SB), R0
+ MOVW (R0), R0
+ BL (R0)
+ // Assert that slot is less than 64 so we can use _TEB->TlsSlots
+ CMP $64, R0
+ MOVW $runtime·abort(SB), R1
+ BL.GE (R1)
+ MOVW $runtime·tls_g(SB), R1
+ MOVW R0, (R1)
+ MOVW R4, R13
+#else
#ifndef GOOS_nacl
// if there is an _cgo_init, call it.
MOVW _cgo_init(SB), R4
@@ -91,7 +131,8 @@ TEXT runtime·_initcgo(SB),NOSPLIT,$4
MOVW $setg_gcc<>(SB), R1 // arg 1: setg
MOVW g, R0 // arg 0: G
BL (R4) // will clobber R0-R3
-#endif
+#endif // GOOS_nacl
+#endif // GOOS_windows
nocgo:
RET
diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go
index 4c2010493a..d7265b2bb9 100644
--- a/src/runtime/traceback.go
+++ b/src/runtime/traceback.go
@@ -312,8 +312,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
// the function either doesn't return at all (if it has no defers or if the
// defers do not recover) or it returns from one of the calls to
// deferproc a second time (if the corresponding deferred func recovers).
- // It suffices to assume that the most recent deferproc is the one that
- // returns; everything live at earlier deferprocs is still live at that one.
+ // In the latter case, use a deferreturn call site as the continuation pc.
frame.continpc = frame.pc
if waspanic {
// We match up defers with frames using the SP.
@@ -324,7 +323,10 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
// can't push a defer, the defer can't belong
// to that frame.
if _defer != nil && _defer.sp == frame.sp && frame.sp != frame.fp {
- frame.continpc = _defer.pc
+ frame.continpc = frame.fn.entry + uintptr(frame.fn.deferreturn) + 1
+ // Note: the +1 is to offset the -1 that
+ // stack.go:getStackMap does to back up a return
+ // address make sure the pc is in the CALL instruction.
} else {
frame.continpc = 0
}
@@ -571,8 +573,9 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
// reflectMethodValue is a partial duplicate of reflect.makeFuncImpl
// and reflect.methodValue.
type reflectMethodValue struct {
- fn uintptr
- stack *bitvector // args bitmap
+ fn uintptr
+ stack *bitvector // ptrmap for both args and results
+ argLen uintptr // just args
}
// getArgInfoFast returns the argument frame information for a call to f.
@@ -601,6 +604,7 @@ func getArgInfo(frame *stkframe, f funcInfo, needArgMap bool, ctxt *funcval) (ar
// These take a *reflect.methodValue as their
// context register.
var mv *reflectMethodValue
+ var retValid bool
if ctxt != nil {
// This is not an actual call, but a
// deferred call. The function value
@@ -614,6 +618,10 @@ func getArgInfo(frame *stkframe, f funcInfo, needArgMap bool, ctxt *funcval) (ar
// 0(SP).
arg0 := frame.sp + sys.MinFrameSize
mv = *(**reflectMethodValue)(unsafe.Pointer(arg0))
+ // Figure out whether the return values are valid.
+ // Reflect will update this value after it copies
+ // in the return values.
+ retValid = *(*bool)(unsafe.Pointer(arg0 + 3*sys.PtrSize))
}
if mv.fn != f.entry {
print("runtime: confused by ", funcname(f), "\n")
@@ -621,6 +629,9 @@ func getArgInfo(frame *stkframe, f funcInfo, needArgMap bool, ctxt *funcval) (ar
}
bv := mv.stack
arglen = uintptr(bv.n * sys.PtrSize)
+ if !retValid {
+ arglen = uintptr(mv.argLen) &^ (sys.PtrSize - 1)
+ }
argmap = bv
}
}
@@ -936,7 +947,7 @@ func tracebackothers(me *g) {
lock(&allglock)
for _, gp := range allgs {
- if gp == me || gp == g.m.curg || readgstatus(gp) == _Gdead || isSystemGoroutine(gp) && level < 2 {
+ if gp == me || gp == g.m.curg || readgstatus(gp) == _Gdead || isSystemGoroutine(gp, false) && level < 2 {
continue
}
print("\n")
@@ -1022,7 +1033,11 @@ func topofstack(f funcInfo, g0 bool) bool {
// in stack dumps and deadlock detector. This is any goroutine that
// starts at a runtime.* entry point, except for runtime.main and
// sometimes runtime.runfinq.
-func isSystemGoroutine(gp *g) bool {
+//
+// If fixed is true, any goroutine that can vary between user and
+// system (that is, the finalizer goroutine) is considered a user
+// goroutine.
+func isSystemGoroutine(gp *g, fixed bool) bool {
// Keep this in sync with cmd/trace/trace.go:isSystemGoroutine.
f := findfunc(gp.startpc)
if !f.valid() {
@@ -1034,6 +1049,11 @@ func isSystemGoroutine(gp *g) bool {
if f.funcID == funcID_runfinq {
// We include the finalizer goroutine if it's calling
// back into user code.
+ if fixed {
+ // This goroutine can vary. In fixed mode,
+ // always consider it a user goroutine.
+ return false
+ }
return !fingRunning
}
return hasPrefix(funcname(f), "runtime.")
diff --git a/src/runtime/vlop_arm.s b/src/runtime/vlop_arm.s
index 729653488f..41d285874d 100644
--- a/src/runtime/vlop_arm.s
+++ b/src/runtime/vlop_arm.s
@@ -30,7 +30,7 @@
// func runtime·udiv(n, d uint32) (q, r uint32)
// compiler knowns the register usage of this function
-// Reference:
+// Reference:
// Sloss, Andrew et. al; ARM System Developer's Guide: Designing and Optimizing System Software
// Morgan Kaufmann; 1 edition (April 8, 2004), ISBN 978-1558608740
#define Rq R0 // input d, output q
diff --git a/src/runtime/wincallback.go b/src/runtime/wincallback.go
index 9f003aed05..c022916422 100644
--- a/src/runtime/wincallback.go
+++ b/src/runtime/wincallback.go
@@ -17,11 +17,12 @@ import (
const maxCallback = 2000
-func genasm() {
+func genasm386Amd64() {
var buf bytes.Buffer
- buf.WriteString(`// generated by wincallback.go; run go generate
+ buf.WriteString(`// Code generated by wincallback.go using 'go generate'. DO NOT EDIT.
+// +build 386 amd64
// runtime·callbackasm is called by external code to
// execute Go implemented callback function. It is not
// called from the start, instead runtime·compilecallback
@@ -29,13 +30,43 @@ func genasm() {
// appropriately so different callbacks start with different
// CALL instruction in runtime·callbackasm. This determines
// which Go callback function is executed later on.
+
TEXT runtime·callbackasm(SB),7,$0
`)
for i := 0; i < maxCallback; i++ {
buf.WriteString("\tCALL\truntime·callbackasm1(SB)\n")
}
- err := ioutil.WriteFile("zcallback_windows.s", buf.Bytes(), 0666)
+ filename := fmt.Sprintf("zcallback_windows.s")
+ err := ioutil.WriteFile(filename, buf.Bytes(), 0666)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "wincallback: %s\n", err)
+ os.Exit(2)
+ }
+}
+
+func genasmArm() {
+ var buf bytes.Buffer
+
+ buf.WriteString(`// Code generated by wincallback.go using 'go generate'. DO NOT EDIT.
+
+// External code calls into callbackasm at an offset corresponding
+// to the callback index. Callbackasm is a table of MOV and B instructions.
+// The MOV instruction loads R12 with the callback index, and the
+// B instruction branches to callbackasm1.
+// callbackasm1 takes the callback index from R12 and
+// indexes into an array that stores information about each callback.
+// It then calls the Go implementation for that callback.
+#include "textflag.h"
+
+TEXT runtime·callbackasm(SB),NOSPLIT|NOFRAME,$0
+`)
+ for i := 0; i < maxCallback; i++ {
+ buf.WriteString(fmt.Sprintf("\tMOVW\t$%d, R12\n", i))
+ buf.WriteString("\tB\truntime·callbackasm1(SB)\n")
+ }
+
+ err := ioutil.WriteFile("zcallback_windows_arm.s", buf.Bytes(), 0666)
if err != nil {
fmt.Fprintf(os.Stderr, "wincallback: %s\n", err)
os.Exit(2)
@@ -45,7 +76,7 @@ TEXT runtime·callbackasm(SB),7,$0
func gengo() {
var buf bytes.Buffer
- buf.WriteString(fmt.Sprintf(`// generated by wincallback.go; run go generate
+ buf.WriteString(fmt.Sprintf(`// Code generated by wincallback.go using 'go generate'. DO NOT EDIT.
package runtime
@@ -59,6 +90,7 @@ const cb_max = %d // maximum number of windows callbacks allowed
}
func main() {
- genasm()
+ genasm386Amd64()
+ genasmArm()
gengo()
}
diff --git a/src/runtime/zcallback_windows.go b/src/runtime/zcallback_windows.go
index 9908d4ec23..2c3cb28518 100644
--- a/src/runtime/zcallback_windows.go
+++ b/src/runtime/zcallback_windows.go
@@ -1,4 +1,4 @@
-// generated by wincallback.go; run go generate
+// Code generated by wincallback.go using 'go generate'. DO NOT EDIT.
package runtime
diff --git a/src/runtime/zcallback_windows.s b/src/runtime/zcallback_windows.s
index b9a3a30811..7772eef329 100644
--- a/src/runtime/zcallback_windows.s
+++ b/src/runtime/zcallback_windows.s
@@ -1,5 +1,6 @@
-// generated by wincallback.go; run go generate
+// Code generated by wincallback.go using 'go generate'. DO NOT EDIT.
+// +build 386 amd64
// runtime·callbackasm is called by external code to
// execute Go implemented callback function. It is not
// called from the start, instead runtime·compilecallback
@@ -7,6 +8,7 @@
// appropriately so different callbacks start with different
// CALL instruction in runtime·callbackasm. This determines
// which Go callback function is executed later on.
+
TEXT runtime·callbackasm(SB),7,$0
CALL runtime·callbackasm1(SB)
CALL runtime·callbackasm1(SB)
diff --git a/src/runtime/zcallback_windows_arm.s b/src/runtime/zcallback_windows_arm.s
new file mode 100644
index 0000000000..f943d84cbf
--- /dev/null
+++ b/src/runtime/zcallback_windows_arm.s
@@ -0,0 +1,4012 @@
+// Code generated by wincallback.go using 'go generate'. DO NOT EDIT.
+
+// External code calls into callbackasm at an offset corresponding
+// to the callback index. Callbackasm is a table of MOV and B instructions.
+// The MOV instruction loads R12 with the callback index, and the
+// B instruction branches to callbackasm1.
+// callbackasm1 takes the callback index from R12 and
+// indexes into an array that stores information about each callback.
+// It then calls the Go implementation for that callback.
+#include "textflag.h"
+
+TEXT runtime·callbackasm(SB),NOSPLIT|NOFRAME,$0
+ MOVW $0, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1, R12
+ B runtime·callbackasm1(SB)
+ MOVW $2, R12
+ B runtime·callbackasm1(SB)
+ MOVW $3, R12
+ B runtime·callbackasm1(SB)
+ MOVW $4, R12
+ B runtime·callbackasm1(SB)
+ MOVW $5, R12
+ B runtime·callbackasm1(SB)
+ MOVW $6, R12
+ B runtime·callbackasm1(SB)
+ MOVW $7, R12
+ B runtime·callbackasm1(SB)
+ MOVW $8, R12
+ B runtime·callbackasm1(SB)
+ MOVW $9, R12
+ B runtime·callbackasm1(SB)
+ MOVW $10, R12
+ B runtime·callbackasm1(SB)
+ MOVW $11, R12
+ B runtime·callbackasm1(SB)
+ MOVW $12, R12
+ B runtime·callbackasm1(SB)
+ MOVW $13, R12
+ B runtime·callbackasm1(SB)
+ MOVW $14, R12
+ B runtime·callbackasm1(SB)
+ MOVW $15, R12
+ B runtime·callbackasm1(SB)
+ MOVW $16, R12
+ B runtime·callbackasm1(SB)
+ MOVW $17, R12
+ B runtime·callbackasm1(SB)
+ MOVW $18, R12
+ B runtime·callbackasm1(SB)
+ MOVW $19, R12
+ B runtime·callbackasm1(SB)
+ MOVW $20, R12
+ B runtime·callbackasm1(SB)
+ MOVW $21, R12
+ B runtime·callbackasm1(SB)
+ MOVW $22, R12
+ B runtime·callbackasm1(SB)
+ MOVW $23, R12
+ B runtime·callbackasm1(SB)
+ MOVW $24, R12
+ B runtime·callbackasm1(SB)
+ MOVW $25, R12
+ B runtime·callbackasm1(SB)
+ MOVW $26, R12
+ B runtime·callbackasm1(SB)
+ MOVW $27, R12
+ B runtime·callbackasm1(SB)
+ MOVW $28, R12
+ B runtime·callbackasm1(SB)
+ MOVW $29, R12
+ B runtime·callbackasm1(SB)
+ MOVW $30, R12
+ B runtime·callbackasm1(SB)
+ MOVW $31, R12
+ B runtime·callbackasm1(SB)
+ MOVW $32, R12
+ B runtime·callbackasm1(SB)
+ MOVW $33, R12
+ B runtime·callbackasm1(SB)
+ MOVW $34, R12
+ B runtime·callbackasm1(SB)
+ MOVW $35, R12
+ B runtime·callbackasm1(SB)
+ MOVW $36, R12
+ B runtime·callbackasm1(SB)
+ MOVW $37, R12
+ B runtime·callbackasm1(SB)
+ MOVW $38, R12
+ B runtime·callbackasm1(SB)
+ MOVW $39, R12
+ B runtime·callbackasm1(SB)
+ MOVW $40, R12
+ B runtime·callbackasm1(SB)
+ MOVW $41, R12
+ B runtime·callbackasm1(SB)
+ MOVW $42, R12
+ B runtime·callbackasm1(SB)
+ MOVW $43, R12
+ B runtime·callbackasm1(SB)
+ MOVW $44, R12
+ B runtime·callbackasm1(SB)
+ MOVW $45, R12
+ B runtime·callbackasm1(SB)
+ MOVW $46, R12
+ B runtime·callbackasm1(SB)
+ MOVW $47, R12
+ B runtime·callbackasm1(SB)
+ MOVW $48, R12
+ B runtime·callbackasm1(SB)
+ MOVW $49, R12
+ B runtime·callbackasm1(SB)
+ MOVW $50, R12
+ B runtime·callbackasm1(SB)
+ MOVW $51, R12
+ B runtime·callbackasm1(SB)
+ MOVW $52, R12
+ B runtime·callbackasm1(SB)
+ MOVW $53, R12
+ B runtime·callbackasm1(SB)
+ MOVW $54, R12
+ B runtime·callbackasm1(SB)
+ MOVW $55, R12
+ B runtime·callbackasm1(SB)
+ MOVW $56, R12
+ B runtime·callbackasm1(SB)
+ MOVW $57, R12
+ B runtime·callbackasm1(SB)
+ MOVW $58, R12
+ B runtime·callbackasm1(SB)
+ MOVW $59, R12
+ B runtime·callbackasm1(SB)
+ MOVW $60, R12
+ B runtime·callbackasm1(SB)
+ MOVW $61, R12
+ B runtime·callbackasm1(SB)
+ MOVW $62, R12
+ B runtime·callbackasm1(SB)
+ MOVW $63, R12
+ B runtime·callbackasm1(SB)
+ MOVW $64, R12
+ B runtime·callbackasm1(SB)
+ MOVW $65, R12
+ B runtime·callbackasm1(SB)
+ MOVW $66, R12
+ B runtime·callbackasm1(SB)
+ MOVW $67, R12
+ B runtime·callbackasm1(SB)
+ MOVW $68, R12
+ B runtime·callbackasm1(SB)
+ MOVW $69, R12
+ B runtime·callbackasm1(SB)
+ MOVW $70, R12
+ B runtime·callbackasm1(SB)
+ MOVW $71, R12
+ B runtime·callbackasm1(SB)
+ MOVW $72, R12
+ B runtime·callbackasm1(SB)
+ MOVW $73, R12
+ B runtime·callbackasm1(SB)
+ MOVW $74, R12
+ B runtime·callbackasm1(SB)
+ MOVW $75, R12
+ B runtime·callbackasm1(SB)
+ MOVW $76, R12
+ B runtime·callbackasm1(SB)
+ MOVW $77, R12
+ B runtime·callbackasm1(SB)
+ MOVW $78, R12
+ B runtime·callbackasm1(SB)
+ MOVW $79, R12
+ B runtime·callbackasm1(SB)
+ MOVW $80, R12
+ B runtime·callbackasm1(SB)
+ MOVW $81, R12
+ B runtime·callbackasm1(SB)
+ MOVW $82, R12
+ B runtime·callbackasm1(SB)
+ MOVW $83, R12
+ B runtime·callbackasm1(SB)
+ MOVW $84, R12
+ B runtime·callbackasm1(SB)
+ MOVW $85, R12
+ B runtime·callbackasm1(SB)
+ MOVW $86, R12
+ B runtime·callbackasm1(SB)
+ MOVW $87, R12
+ B runtime·callbackasm1(SB)
+ MOVW $88, R12
+ B runtime·callbackasm1(SB)
+ MOVW $89, R12
+ B runtime·callbackasm1(SB)
+ MOVW $90, R12
+ B runtime·callbackasm1(SB)
+ MOVW $91, R12
+ B runtime·callbackasm1(SB)
+ MOVW $92, R12
+ B runtime·callbackasm1(SB)
+ MOVW $93, R12
+ B runtime·callbackasm1(SB)
+ MOVW $94, R12
+ B runtime·callbackasm1(SB)
+ MOVW $95, R12
+ B runtime·callbackasm1(SB)
+ MOVW $96, R12
+ B runtime·callbackasm1(SB)
+ MOVW $97, R12
+ B runtime·callbackasm1(SB)
+ MOVW $98, R12
+ B runtime·callbackasm1(SB)
+ MOVW $99, R12
+ B runtime·callbackasm1(SB)
+ MOVW $100, R12
+ B runtime·callbackasm1(SB)
+ MOVW $101, R12
+ B runtime·callbackasm1(SB)
+ MOVW $102, R12
+ B runtime·callbackasm1(SB)
+ MOVW $103, R12
+ B runtime·callbackasm1(SB)
+ MOVW $104, R12
+ B runtime·callbackasm1(SB)
+ MOVW $105, R12
+ B runtime·callbackasm1(SB)
+ MOVW $106, R12
+ B runtime·callbackasm1(SB)
+ MOVW $107, R12
+ B runtime·callbackasm1(SB)
+ MOVW $108, R12
+ B runtime·callbackasm1(SB)
+ MOVW $109, R12
+ B runtime·callbackasm1(SB)
+ MOVW $110, R12
+ B runtime·callbackasm1(SB)
+ MOVW $111, R12
+ B runtime·callbackasm1(SB)
+ MOVW $112, R12
+ B runtime·callbackasm1(SB)
+ MOVW $113, R12
+ B runtime·callbackasm1(SB)
+ MOVW $114, R12
+ B runtime·callbackasm1(SB)
+ MOVW $115, R12
+ B runtime·callbackasm1(SB)
+ MOVW $116, R12
+ B runtime·callbackasm1(SB)
+ MOVW $117, R12
+ B runtime·callbackasm1(SB)
+ MOVW $118, R12
+ B runtime·callbackasm1(SB)
+ MOVW $119, R12
+ B runtime·callbackasm1(SB)
+ MOVW $120, R12
+ B runtime·callbackasm1(SB)
+ MOVW $121, R12
+ B runtime·callbackasm1(SB)
+ MOVW $122, R12
+ B runtime·callbackasm1(SB)
+ MOVW $123, R12
+ B runtime·callbackasm1(SB)
+ MOVW $124, R12
+ B runtime·callbackasm1(SB)
+ MOVW $125, R12
+ B runtime·callbackasm1(SB)
+ MOVW $126, R12
+ B runtime·callbackasm1(SB)
+ MOVW $127, R12
+ B runtime·callbackasm1(SB)
+ MOVW $128, R12
+ B runtime·callbackasm1(SB)
+ MOVW $129, R12
+ B runtime·callbackasm1(SB)
+ MOVW $130, R12
+ B runtime·callbackasm1(SB)
+ MOVW $131, R12
+ B runtime·callbackasm1(SB)
+ MOVW $132, R12
+ B runtime·callbackasm1(SB)
+ MOVW $133, R12
+ B runtime·callbackasm1(SB)
+ MOVW $134, R12
+ B runtime·callbackasm1(SB)
+ MOVW $135, R12
+ B runtime·callbackasm1(SB)
+ MOVW $136, R12
+ B runtime·callbackasm1(SB)
+ MOVW $137, R12
+ B runtime·callbackasm1(SB)
+ MOVW $138, R12
+ B runtime·callbackasm1(SB)
+ MOVW $139, R12
+ B runtime·callbackasm1(SB)
+ MOVW $140, R12
+ B runtime·callbackasm1(SB)
+ MOVW $141, R12
+ B runtime·callbackasm1(SB)
+ MOVW $142, R12
+ B runtime·callbackasm1(SB)
+ MOVW $143, R12
+ B runtime·callbackasm1(SB)
+ MOVW $144, R12
+ B runtime·callbackasm1(SB)
+ MOVW $145, R12
+ B runtime·callbackasm1(SB)
+ MOVW $146, R12
+ B runtime·callbackasm1(SB)
+ MOVW $147, R12
+ B runtime·callbackasm1(SB)
+ MOVW $148, R12
+ B runtime·callbackasm1(SB)
+ MOVW $149, R12
+ B runtime·callbackasm1(SB)
+ MOVW $150, R12
+ B runtime·callbackasm1(SB)
+ MOVW $151, R12
+ B runtime·callbackasm1(SB)
+ MOVW $152, R12
+ B runtime·callbackasm1(SB)
+ MOVW $153, R12
+ B runtime·callbackasm1(SB)
+ MOVW $154, R12
+ B runtime·callbackasm1(SB)
+ MOVW $155, R12
+ B runtime·callbackasm1(SB)
+ MOVW $156, R12
+ B runtime·callbackasm1(SB)
+ MOVW $157, R12
+ B runtime·callbackasm1(SB)
+ MOVW $158, R12
+ B runtime·callbackasm1(SB)
+ MOVW $159, R12
+ B runtime·callbackasm1(SB)
+ MOVW $160, R12
+ B runtime·callbackasm1(SB)
+ MOVW $161, R12
+ B runtime·callbackasm1(SB)
+ MOVW $162, R12
+ B runtime·callbackasm1(SB)
+ MOVW $163, R12
+ B runtime·callbackasm1(SB)
+ MOVW $164, R12
+ B runtime·callbackasm1(SB)
+ MOVW $165, R12
+ B runtime·callbackasm1(SB)
+ MOVW $166, R12
+ B runtime·callbackasm1(SB)
+ MOVW $167, R12
+ B runtime·callbackasm1(SB)
+ MOVW $168, R12
+ B runtime·callbackasm1(SB)
+ MOVW $169, R12
+ B runtime·callbackasm1(SB)
+ MOVW $170, R12
+ B runtime·callbackasm1(SB)
+ MOVW $171, R12
+ B runtime·callbackasm1(SB)
+ MOVW $172, R12
+ B runtime·callbackasm1(SB)
+ MOVW $173, R12
+ B runtime·callbackasm1(SB)
+ MOVW $174, R12
+ B runtime·callbackasm1(SB)
+ MOVW $175, R12
+ B runtime·callbackasm1(SB)
+ MOVW $176, R12
+ B runtime·callbackasm1(SB)
+ MOVW $177, R12
+ B runtime·callbackasm1(SB)
+ MOVW $178, R12
+ B runtime·callbackasm1(SB)
+ MOVW $179, R12
+ B runtime·callbackasm1(SB)
+ MOVW $180, R12
+ B runtime·callbackasm1(SB)
+ MOVW $181, R12
+ B runtime·callbackasm1(SB)
+ MOVW $182, R12
+ B runtime·callbackasm1(SB)
+ MOVW $183, R12
+ B runtime·callbackasm1(SB)
+ MOVW $184, R12
+ B runtime·callbackasm1(SB)
+ MOVW $185, R12
+ B runtime·callbackasm1(SB)
+ MOVW $186, R12
+ B runtime·callbackasm1(SB)
+ MOVW $187, R12
+ B runtime·callbackasm1(SB)
+ MOVW $188, R12
+ B runtime·callbackasm1(SB)
+ MOVW $189, R12
+ B runtime·callbackasm1(SB)
+ MOVW $190, R12
+ B runtime·callbackasm1(SB)
+ MOVW $191, R12
+ B runtime·callbackasm1(SB)
+ MOVW $192, R12
+ B runtime·callbackasm1(SB)
+ MOVW $193, R12
+ B runtime·callbackasm1(SB)
+ MOVW $194, R12
+ B runtime·callbackasm1(SB)
+ MOVW $195, R12
+ B runtime·callbackasm1(SB)
+ MOVW $196, R12
+ B runtime·callbackasm1(SB)
+ MOVW $197, R12
+ B runtime·callbackasm1(SB)
+ MOVW $198, R12
+ B runtime·callbackasm1(SB)
+ MOVW $199, R12
+ B runtime·callbackasm1(SB)
+ MOVW $200, R12
+ B runtime·callbackasm1(SB)
+ MOVW $201, R12
+ B runtime·callbackasm1(SB)
+ MOVW $202, R12
+ B runtime·callbackasm1(SB)
+ MOVW $203, R12
+ B runtime·callbackasm1(SB)
+ MOVW $204, R12
+ B runtime·callbackasm1(SB)
+ MOVW $205, R12
+ B runtime·callbackasm1(SB)
+ MOVW $206, R12
+ B runtime·callbackasm1(SB)
+ MOVW $207, R12
+ B runtime·callbackasm1(SB)
+ MOVW $208, R12
+ B runtime·callbackasm1(SB)
+ MOVW $209, R12
+ B runtime·callbackasm1(SB)
+ MOVW $210, R12
+ B runtime·callbackasm1(SB)
+ MOVW $211, R12
+ B runtime·callbackasm1(SB)
+ MOVW $212, R12
+ B runtime·callbackasm1(SB)
+ MOVW $213, R12
+ B runtime·callbackasm1(SB)
+ MOVW $214, R12
+ B runtime·callbackasm1(SB)
+ MOVW $215, R12
+ B runtime·callbackasm1(SB)
+ MOVW $216, R12
+ B runtime·callbackasm1(SB)
+ MOVW $217, R12
+ B runtime·callbackasm1(SB)
+ MOVW $218, R12
+ B runtime·callbackasm1(SB)
+ MOVW $219, R12
+ B runtime·callbackasm1(SB)
+ MOVW $220, R12
+ B runtime·callbackasm1(SB)
+ MOVW $221, R12
+ B runtime·callbackasm1(SB)
+ MOVW $222, R12
+ B runtime·callbackasm1(SB)
+ MOVW $223, R12
+ B runtime·callbackasm1(SB)
+ MOVW $224, R12
+ B runtime·callbackasm1(SB)
+ MOVW $225, R12
+ B runtime·callbackasm1(SB)
+ MOVW $226, R12
+ B runtime·callbackasm1(SB)
+ MOVW $227, R12
+ B runtime·callbackasm1(SB)
+ MOVW $228, R12
+ B runtime·callbackasm1(SB)
+ MOVW $229, R12
+ B runtime·callbackasm1(SB)
+ MOVW $230, R12
+ B runtime·callbackasm1(SB)
+ MOVW $231, R12
+ B runtime·callbackasm1(SB)
+ MOVW $232, R12
+ B runtime·callbackasm1(SB)
+ MOVW $233, R12
+ B runtime·callbackasm1(SB)
+ MOVW $234, R12
+ B runtime·callbackasm1(SB)
+ MOVW $235, R12
+ B runtime·callbackasm1(SB)
+ MOVW $236, R12
+ B runtime·callbackasm1(SB)
+ MOVW $237, R12
+ B runtime·callbackasm1(SB)
+ MOVW $238, R12
+ B runtime·callbackasm1(SB)
+ MOVW $239, R12
+ B runtime·callbackasm1(SB)
+ MOVW $240, R12
+ B runtime·callbackasm1(SB)
+ MOVW $241, R12
+ B runtime·callbackasm1(SB)
+ MOVW $242, R12
+ B runtime·callbackasm1(SB)
+ MOVW $243, R12
+ B runtime·callbackasm1(SB)
+ MOVW $244, R12
+ B runtime·callbackasm1(SB)
+ MOVW $245, R12
+ B runtime·callbackasm1(SB)
+ MOVW $246, R12
+ B runtime·callbackasm1(SB)
+ MOVW $247, R12
+ B runtime·callbackasm1(SB)
+ MOVW $248, R12
+ B runtime·callbackasm1(SB)
+ MOVW $249, R12
+ B runtime·callbackasm1(SB)
+ MOVW $250, R12
+ B runtime·callbackasm1(SB)
+ MOVW $251, R12
+ B runtime·callbackasm1(SB)
+ MOVW $252, R12
+ B runtime·callbackasm1(SB)
+ MOVW $253, R12
+ B runtime·callbackasm1(SB)
+ MOVW $254, R12
+ B runtime·callbackasm1(SB)
+ MOVW $255, R12
+ B runtime·callbackasm1(SB)
+ MOVW $256, R12
+ B runtime·callbackasm1(SB)
+ MOVW $257, R12
+ B runtime·callbackasm1(SB)
+ MOVW $258, R12
+ B runtime·callbackasm1(SB)
+ MOVW $259, R12
+ B runtime·callbackasm1(SB)
+ MOVW $260, R12
+ B runtime·callbackasm1(SB)
+ MOVW $261, R12
+ B runtime·callbackasm1(SB)
+ MOVW $262, R12
+ B runtime·callbackasm1(SB)
+ MOVW $263, R12
+ B runtime·callbackasm1(SB)
+ MOVW $264, R12
+ B runtime·callbackasm1(SB)
+ MOVW $265, R12
+ B runtime·callbackasm1(SB)
+ MOVW $266, R12
+ B runtime·callbackasm1(SB)
+ MOVW $267, R12
+ B runtime·callbackasm1(SB)
+ MOVW $268, R12
+ B runtime·callbackasm1(SB)
+ MOVW $269, R12
+ B runtime·callbackasm1(SB)
+ MOVW $270, R12
+ B runtime·callbackasm1(SB)
+ MOVW $271, R12
+ B runtime·callbackasm1(SB)
+ MOVW $272, R12
+ B runtime·callbackasm1(SB)
+ MOVW $273, R12
+ B runtime·callbackasm1(SB)
+ MOVW $274, R12
+ B runtime·callbackasm1(SB)
+ MOVW $275, R12
+ B runtime·callbackasm1(SB)
+ MOVW $276, R12
+ B runtime·callbackasm1(SB)
+ MOVW $277, R12
+ B runtime·callbackasm1(SB)
+ MOVW $278, R12
+ B runtime·callbackasm1(SB)
+ MOVW $279, R12
+ B runtime·callbackasm1(SB)
+ MOVW $280, R12
+ B runtime·callbackasm1(SB)
+ MOVW $281, R12
+ B runtime·callbackasm1(SB)
+ MOVW $282, R12
+ B runtime·callbackasm1(SB)
+ MOVW $283, R12
+ B runtime·callbackasm1(SB)
+ MOVW $284, R12
+ B runtime·callbackasm1(SB)
+ MOVW $285, R12
+ B runtime·callbackasm1(SB)
+ MOVW $286, R12
+ B runtime·callbackasm1(SB)
+ MOVW $287, R12
+ B runtime·callbackasm1(SB)
+ MOVW $288, R12
+ B runtime·callbackasm1(SB)
+ MOVW $289, R12
+ B runtime·callbackasm1(SB)
+ MOVW $290, R12
+ B runtime·callbackasm1(SB)
+ MOVW $291, R12
+ B runtime·callbackasm1(SB)
+ MOVW $292, R12
+ B runtime·callbackasm1(SB)
+ MOVW $293, R12
+ B runtime·callbackasm1(SB)
+ MOVW $294, R12
+ B runtime·callbackasm1(SB)
+ MOVW $295, R12
+ B runtime·callbackasm1(SB)
+ MOVW $296, R12
+ B runtime·callbackasm1(SB)
+ MOVW $297, R12
+ B runtime·callbackasm1(SB)
+ MOVW $298, R12
+ B runtime·callbackasm1(SB)
+ MOVW $299, R12
+ B runtime·callbackasm1(SB)
+ MOVW $300, R12
+ B runtime·callbackasm1(SB)
+ MOVW $301, R12
+ B runtime·callbackasm1(SB)
+ MOVW $302, R12
+ B runtime·callbackasm1(SB)
+ MOVW $303, R12
+ B runtime·callbackasm1(SB)
+ MOVW $304, R12
+ B runtime·callbackasm1(SB)
+ MOVW $305, R12
+ B runtime·callbackasm1(SB)
+ MOVW $306, R12
+ B runtime·callbackasm1(SB)
+ MOVW $307, R12
+ B runtime·callbackasm1(SB)
+ MOVW $308, R12
+ B runtime·callbackasm1(SB)
+ MOVW $309, R12
+ B runtime·callbackasm1(SB)
+ MOVW $310, R12
+ B runtime·callbackasm1(SB)
+ MOVW $311, R12
+ B runtime·callbackasm1(SB)
+ MOVW $312, R12
+ B runtime·callbackasm1(SB)
+ MOVW $313, R12
+ B runtime·callbackasm1(SB)
+ MOVW $314, R12
+ B runtime·callbackasm1(SB)
+ MOVW $315, R12
+ B runtime·callbackasm1(SB)
+ MOVW $316, R12
+ B runtime·callbackasm1(SB)
+ MOVW $317, R12
+ B runtime·callbackasm1(SB)
+ MOVW $318, R12
+ B runtime·callbackasm1(SB)
+ MOVW $319, R12
+ B runtime·callbackasm1(SB)
+ MOVW $320, R12
+ B runtime·callbackasm1(SB)
+ MOVW $321, R12
+ B runtime·callbackasm1(SB)
+ MOVW $322, R12
+ B runtime·callbackasm1(SB)
+ MOVW $323, R12
+ B runtime·callbackasm1(SB)
+ MOVW $324, R12
+ B runtime·callbackasm1(SB)
+ MOVW $325, R12
+ B runtime·callbackasm1(SB)
+ MOVW $326, R12
+ B runtime·callbackasm1(SB)
+ MOVW $327, R12
+ B runtime·callbackasm1(SB)
+ MOVW $328, R12
+ B runtime·callbackasm1(SB)
+ MOVW $329, R12
+ B runtime·callbackasm1(SB)
+ MOVW $330, R12
+ B runtime·callbackasm1(SB)
+ MOVW $331, R12
+ B runtime·callbackasm1(SB)
+ MOVW $332, R12
+ B runtime·callbackasm1(SB)
+ MOVW $333, R12
+ B runtime·callbackasm1(SB)
+ MOVW $334, R12
+ B runtime·callbackasm1(SB)
+ MOVW $335, R12
+ B runtime·callbackasm1(SB)
+ MOVW $336, R12
+ B runtime·callbackasm1(SB)
+ MOVW $337, R12
+ B runtime·callbackasm1(SB)
+ MOVW $338, R12
+ B runtime·callbackasm1(SB)
+ MOVW $339, R12
+ B runtime·callbackasm1(SB)
+ MOVW $340, R12
+ B runtime·callbackasm1(SB)
+ MOVW $341, R12
+ B runtime·callbackasm1(SB)
+ MOVW $342, R12
+ B runtime·callbackasm1(SB)
+ MOVW $343, R12
+ B runtime·callbackasm1(SB)
+ MOVW $344, R12
+ B runtime·callbackasm1(SB)
+ MOVW $345, R12
+ B runtime·callbackasm1(SB)
+ MOVW $346, R12
+ B runtime·callbackasm1(SB)
+ MOVW $347, R12
+ B runtime·callbackasm1(SB)
+ MOVW $348, R12
+ B runtime·callbackasm1(SB)
+ MOVW $349, R12
+ B runtime·callbackasm1(SB)
+ MOVW $350, R12
+ B runtime·callbackasm1(SB)
+ MOVW $351, R12
+ B runtime·callbackasm1(SB)
+ MOVW $352, R12
+ B runtime·callbackasm1(SB)
+ MOVW $353, R12
+ B runtime·callbackasm1(SB)
+ MOVW $354, R12
+ B runtime·callbackasm1(SB)
+ MOVW $355, R12
+ B runtime·callbackasm1(SB)
+ MOVW $356, R12
+ B runtime·callbackasm1(SB)
+ MOVW $357, R12
+ B runtime·callbackasm1(SB)
+ MOVW $358, R12
+ B runtime·callbackasm1(SB)
+ MOVW $359, R12
+ B runtime·callbackasm1(SB)
+ MOVW $360, R12
+ B runtime·callbackasm1(SB)
+ MOVW $361, R12
+ B runtime·callbackasm1(SB)
+ MOVW $362, R12
+ B runtime·callbackasm1(SB)
+ MOVW $363, R12
+ B runtime·callbackasm1(SB)
+ MOVW $364, R12
+ B runtime·callbackasm1(SB)
+ MOVW $365, R12
+ B runtime·callbackasm1(SB)
+ MOVW $366, R12
+ B runtime·callbackasm1(SB)
+ MOVW $367, R12
+ B runtime·callbackasm1(SB)
+ MOVW $368, R12
+ B runtime·callbackasm1(SB)
+ MOVW $369, R12
+ B runtime·callbackasm1(SB)
+ MOVW $370, R12
+ B runtime·callbackasm1(SB)
+ MOVW $371, R12
+ B runtime·callbackasm1(SB)
+ MOVW $372, R12
+ B runtime·callbackasm1(SB)
+ MOVW $373, R12
+ B runtime·callbackasm1(SB)
+ MOVW $374, R12
+ B runtime·callbackasm1(SB)
+ MOVW $375, R12
+ B runtime·callbackasm1(SB)
+ MOVW $376, R12
+ B runtime·callbackasm1(SB)
+ MOVW $377, R12
+ B runtime·callbackasm1(SB)
+ MOVW $378, R12
+ B runtime·callbackasm1(SB)
+ MOVW $379, R12
+ B runtime·callbackasm1(SB)
+ MOVW $380, R12
+ B runtime·callbackasm1(SB)
+ MOVW $381, R12
+ B runtime·callbackasm1(SB)
+ MOVW $382, R12
+ B runtime·callbackasm1(SB)
+ MOVW $383, R12
+ B runtime·callbackasm1(SB)
+ MOVW $384, R12
+ B runtime·callbackasm1(SB)
+ MOVW $385, R12
+ B runtime·callbackasm1(SB)
+ MOVW $386, R12
+ B runtime·callbackasm1(SB)
+ MOVW $387, R12
+ B runtime·callbackasm1(SB)
+ MOVW $388, R12
+ B runtime·callbackasm1(SB)
+ MOVW $389, R12
+ B runtime·callbackasm1(SB)
+ MOVW $390, R12
+ B runtime·callbackasm1(SB)
+ MOVW $391, R12
+ B runtime·callbackasm1(SB)
+ MOVW $392, R12
+ B runtime·callbackasm1(SB)
+ MOVW $393, R12
+ B runtime·callbackasm1(SB)
+ MOVW $394, R12
+ B runtime·callbackasm1(SB)
+ MOVW $395, R12
+ B runtime·callbackasm1(SB)
+ MOVW $396, R12
+ B runtime·callbackasm1(SB)
+ MOVW $397, R12
+ B runtime·callbackasm1(SB)
+ MOVW $398, R12
+ B runtime·callbackasm1(SB)
+ MOVW $399, R12
+ B runtime·callbackasm1(SB)
+ MOVW $400, R12
+ B runtime·callbackasm1(SB)
+ MOVW $401, R12
+ B runtime·callbackasm1(SB)
+ MOVW $402, R12
+ B runtime·callbackasm1(SB)
+ MOVW $403, R12
+ B runtime·callbackasm1(SB)
+ MOVW $404, R12
+ B runtime·callbackasm1(SB)
+ MOVW $405, R12
+ B runtime·callbackasm1(SB)
+ MOVW $406, R12
+ B runtime·callbackasm1(SB)
+ MOVW $407, R12
+ B runtime·callbackasm1(SB)
+ MOVW $408, R12
+ B runtime·callbackasm1(SB)
+ MOVW $409, R12
+ B runtime·callbackasm1(SB)
+ MOVW $410, R12
+ B runtime·callbackasm1(SB)
+ MOVW $411, R12
+ B runtime·callbackasm1(SB)
+ MOVW $412, R12
+ B runtime·callbackasm1(SB)
+ MOVW $413, R12
+ B runtime·callbackasm1(SB)
+ MOVW $414, R12
+ B runtime·callbackasm1(SB)
+ MOVW $415, R12
+ B runtime·callbackasm1(SB)
+ MOVW $416, R12
+ B runtime·callbackasm1(SB)
+ MOVW $417, R12
+ B runtime·callbackasm1(SB)
+ MOVW $418, R12
+ B runtime·callbackasm1(SB)
+ MOVW $419, R12
+ B runtime·callbackasm1(SB)
+ MOVW $420, R12
+ B runtime·callbackasm1(SB)
+ MOVW $421, R12
+ B runtime·callbackasm1(SB)
+ MOVW $422, R12
+ B runtime·callbackasm1(SB)
+ MOVW $423, R12
+ B runtime·callbackasm1(SB)
+ MOVW $424, R12
+ B runtime·callbackasm1(SB)
+ MOVW $425, R12
+ B runtime·callbackasm1(SB)
+ MOVW $426, R12
+ B runtime·callbackasm1(SB)
+ MOVW $427, R12
+ B runtime·callbackasm1(SB)
+ MOVW $428, R12
+ B runtime·callbackasm1(SB)
+ MOVW $429, R12
+ B runtime·callbackasm1(SB)
+ MOVW $430, R12
+ B runtime·callbackasm1(SB)
+ MOVW $431, R12
+ B runtime·callbackasm1(SB)
+ MOVW $432, R12
+ B runtime·callbackasm1(SB)
+ MOVW $433, R12
+ B runtime·callbackasm1(SB)
+ MOVW $434, R12
+ B runtime·callbackasm1(SB)
+ MOVW $435, R12
+ B runtime·callbackasm1(SB)
+ MOVW $436, R12
+ B runtime·callbackasm1(SB)
+ MOVW $437, R12
+ B runtime·callbackasm1(SB)
+ MOVW $438, R12
+ B runtime·callbackasm1(SB)
+ MOVW $439, R12
+ B runtime·callbackasm1(SB)
+ MOVW $440, R12
+ B runtime·callbackasm1(SB)
+ MOVW $441, R12
+ B runtime·callbackasm1(SB)
+ MOVW $442, R12
+ B runtime·callbackasm1(SB)
+ MOVW $443, R12
+ B runtime·callbackasm1(SB)
+ MOVW $444, R12
+ B runtime·callbackasm1(SB)
+ MOVW $445, R12
+ B runtime·callbackasm1(SB)
+ MOVW $446, R12
+ B runtime·callbackasm1(SB)
+ MOVW $447, R12
+ B runtime·callbackasm1(SB)
+ MOVW $448, R12
+ B runtime·callbackasm1(SB)
+ MOVW $449, R12
+ B runtime·callbackasm1(SB)
+ MOVW $450, R12
+ B runtime·callbackasm1(SB)
+ MOVW $451, R12
+ B runtime·callbackasm1(SB)
+ MOVW $452, R12
+ B runtime·callbackasm1(SB)
+ MOVW $453, R12
+ B runtime·callbackasm1(SB)
+ MOVW $454, R12
+ B runtime·callbackasm1(SB)
+ MOVW $455, R12
+ B runtime·callbackasm1(SB)
+ MOVW $456, R12
+ B runtime·callbackasm1(SB)
+ MOVW $457, R12
+ B runtime·callbackasm1(SB)
+ MOVW $458, R12
+ B runtime·callbackasm1(SB)
+ MOVW $459, R12
+ B runtime·callbackasm1(SB)
+ MOVW $460, R12
+ B runtime·callbackasm1(SB)
+ MOVW $461, R12
+ B runtime·callbackasm1(SB)
+ MOVW $462, R12
+ B runtime·callbackasm1(SB)
+ MOVW $463, R12
+ B runtime·callbackasm1(SB)
+ MOVW $464, R12
+ B runtime·callbackasm1(SB)
+ MOVW $465, R12
+ B runtime·callbackasm1(SB)
+ MOVW $466, R12
+ B runtime·callbackasm1(SB)
+ MOVW $467, R12
+ B runtime·callbackasm1(SB)
+ MOVW $468, R12
+ B runtime·callbackasm1(SB)
+ MOVW $469, R12
+ B runtime·callbackasm1(SB)
+ MOVW $470, R12
+ B runtime·callbackasm1(SB)
+ MOVW $471, R12
+ B runtime·callbackasm1(SB)
+ MOVW $472, R12
+ B runtime·callbackasm1(SB)
+ MOVW $473, R12
+ B runtime·callbackasm1(SB)
+ MOVW $474, R12
+ B runtime·callbackasm1(SB)
+ MOVW $475, R12
+ B runtime·callbackasm1(SB)
+ MOVW $476, R12
+ B runtime·callbackasm1(SB)
+ MOVW $477, R12
+ B runtime·callbackasm1(SB)
+ MOVW $478, R12
+ B runtime·callbackasm1(SB)
+ MOVW $479, R12
+ B runtime·callbackasm1(SB)
+ MOVW $480, R12
+ B runtime·callbackasm1(SB)
+ MOVW $481, R12
+ B runtime·callbackasm1(SB)
+ MOVW $482, R12
+ B runtime·callbackasm1(SB)
+ MOVW $483, R12
+ B runtime·callbackasm1(SB)
+ MOVW $484, R12
+ B runtime·callbackasm1(SB)
+ MOVW $485, R12
+ B runtime·callbackasm1(SB)
+ MOVW $486, R12
+ B runtime·callbackasm1(SB)
+ MOVW $487, R12
+ B runtime·callbackasm1(SB)
+ MOVW $488, R12
+ B runtime·callbackasm1(SB)
+ MOVW $489, R12
+ B runtime·callbackasm1(SB)
+ MOVW $490, R12
+ B runtime·callbackasm1(SB)
+ MOVW $491, R12
+ B runtime·callbackasm1(SB)
+ MOVW $492, R12
+ B runtime·callbackasm1(SB)
+ MOVW $493, R12
+ B runtime·callbackasm1(SB)
+ MOVW $494, R12
+ B runtime·callbackasm1(SB)
+ MOVW $495, R12
+ B runtime·callbackasm1(SB)
+ MOVW $496, R12
+ B runtime·callbackasm1(SB)
+ MOVW $497, R12
+ B runtime·callbackasm1(SB)
+ MOVW $498, R12
+ B runtime·callbackasm1(SB)
+ MOVW $499, R12
+ B runtime·callbackasm1(SB)
+ MOVW $500, R12
+ B runtime·callbackasm1(SB)
+ MOVW $501, R12
+ B runtime·callbackasm1(SB)
+ MOVW $502, R12
+ B runtime·callbackasm1(SB)
+ MOVW $503, R12
+ B runtime·callbackasm1(SB)
+ MOVW $504, R12
+ B runtime·callbackasm1(SB)
+ MOVW $505, R12
+ B runtime·callbackasm1(SB)
+ MOVW $506, R12
+ B runtime·callbackasm1(SB)
+ MOVW $507, R12
+ B runtime·callbackasm1(SB)
+ MOVW $508, R12
+ B runtime·callbackasm1(SB)
+ MOVW $509, R12
+ B runtime·callbackasm1(SB)
+ MOVW $510, R12
+ B runtime·callbackasm1(SB)
+ MOVW $511, R12
+ B runtime·callbackasm1(SB)
+ MOVW $512, R12
+ B runtime·callbackasm1(SB)
+ MOVW $513, R12
+ B runtime·callbackasm1(SB)
+ MOVW $514, R12
+ B runtime·callbackasm1(SB)
+ MOVW $515, R12
+ B runtime·callbackasm1(SB)
+ MOVW $516, R12
+ B runtime·callbackasm1(SB)
+ MOVW $517, R12
+ B runtime·callbackasm1(SB)
+ MOVW $518, R12
+ B runtime·callbackasm1(SB)
+ MOVW $519, R12
+ B runtime·callbackasm1(SB)
+ MOVW $520, R12
+ B runtime·callbackasm1(SB)
+ MOVW $521, R12
+ B runtime·callbackasm1(SB)
+ MOVW $522, R12
+ B runtime·callbackasm1(SB)
+ MOVW $523, R12
+ B runtime·callbackasm1(SB)
+ MOVW $524, R12
+ B runtime·callbackasm1(SB)
+ MOVW $525, R12
+ B runtime·callbackasm1(SB)
+ MOVW $526, R12
+ B runtime·callbackasm1(SB)
+ MOVW $527, R12
+ B runtime·callbackasm1(SB)
+ MOVW $528, R12
+ B runtime·callbackasm1(SB)
+ MOVW $529, R12
+ B runtime·callbackasm1(SB)
+ MOVW $530, R12
+ B runtime·callbackasm1(SB)
+ MOVW $531, R12
+ B runtime·callbackasm1(SB)
+ MOVW $532, R12
+ B runtime·callbackasm1(SB)
+ MOVW $533, R12
+ B runtime·callbackasm1(SB)
+ MOVW $534, R12
+ B runtime·callbackasm1(SB)
+ MOVW $535, R12
+ B runtime·callbackasm1(SB)
+ MOVW $536, R12
+ B runtime·callbackasm1(SB)
+ MOVW $537, R12
+ B runtime·callbackasm1(SB)
+ MOVW $538, R12
+ B runtime·callbackasm1(SB)
+ MOVW $539, R12
+ B runtime·callbackasm1(SB)
+ MOVW $540, R12
+ B runtime·callbackasm1(SB)
+ MOVW $541, R12
+ B runtime·callbackasm1(SB)
+ MOVW $542, R12
+ B runtime·callbackasm1(SB)
+ MOVW $543, R12
+ B runtime·callbackasm1(SB)
+ MOVW $544, R12
+ B runtime·callbackasm1(SB)
+ MOVW $545, R12
+ B runtime·callbackasm1(SB)
+ MOVW $546, R12
+ B runtime·callbackasm1(SB)
+ MOVW $547, R12
+ B runtime·callbackasm1(SB)
+ MOVW $548, R12
+ B runtime·callbackasm1(SB)
+ MOVW $549, R12
+ B runtime·callbackasm1(SB)
+ MOVW $550, R12
+ B runtime·callbackasm1(SB)
+ MOVW $551, R12
+ B runtime·callbackasm1(SB)
+ MOVW $552, R12
+ B runtime·callbackasm1(SB)
+ MOVW $553, R12
+ B runtime·callbackasm1(SB)
+ MOVW $554, R12
+ B runtime·callbackasm1(SB)
+ MOVW $555, R12
+ B runtime·callbackasm1(SB)
+ MOVW $556, R12
+ B runtime·callbackasm1(SB)
+ MOVW $557, R12
+ B runtime·callbackasm1(SB)
+ MOVW $558, R12
+ B runtime·callbackasm1(SB)
+ MOVW $559, R12
+ B runtime·callbackasm1(SB)
+ MOVW $560, R12
+ B runtime·callbackasm1(SB)
+ MOVW $561, R12
+ B runtime·callbackasm1(SB)
+ MOVW $562, R12
+ B runtime·callbackasm1(SB)
+ MOVW $563, R12
+ B runtime·callbackasm1(SB)
+ MOVW $564, R12
+ B runtime·callbackasm1(SB)
+ MOVW $565, R12
+ B runtime·callbackasm1(SB)
+ MOVW $566, R12
+ B runtime·callbackasm1(SB)
+ MOVW $567, R12
+ B runtime·callbackasm1(SB)
+ MOVW $568, R12
+ B runtime·callbackasm1(SB)
+ MOVW $569, R12
+ B runtime·callbackasm1(SB)
+ MOVW $570, R12
+ B runtime·callbackasm1(SB)
+ MOVW $571, R12
+ B runtime·callbackasm1(SB)
+ MOVW $572, R12
+ B runtime·callbackasm1(SB)
+ MOVW $573, R12
+ B runtime·callbackasm1(SB)
+ MOVW $574, R12
+ B runtime·callbackasm1(SB)
+ MOVW $575, R12
+ B runtime·callbackasm1(SB)
+ MOVW $576, R12
+ B runtime·callbackasm1(SB)
+ MOVW $577, R12
+ B runtime·callbackasm1(SB)
+ MOVW $578, R12
+ B runtime·callbackasm1(SB)
+ MOVW $579, R12
+ B runtime·callbackasm1(SB)
+ MOVW $580, R12
+ B runtime·callbackasm1(SB)
+ MOVW $581, R12
+ B runtime·callbackasm1(SB)
+ MOVW $582, R12
+ B runtime·callbackasm1(SB)
+ MOVW $583, R12
+ B runtime·callbackasm1(SB)
+ MOVW $584, R12
+ B runtime·callbackasm1(SB)
+ MOVW $585, R12
+ B runtime·callbackasm1(SB)
+ MOVW $586, R12
+ B runtime·callbackasm1(SB)
+ MOVW $587, R12
+ B runtime·callbackasm1(SB)
+ MOVW $588, R12
+ B runtime·callbackasm1(SB)
+ MOVW $589, R12
+ B runtime·callbackasm1(SB)
+ MOVW $590, R12
+ B runtime·callbackasm1(SB)
+ MOVW $591, R12
+ B runtime·callbackasm1(SB)
+ MOVW $592, R12
+ B runtime·callbackasm1(SB)
+ MOVW $593, R12
+ B runtime·callbackasm1(SB)
+ MOVW $594, R12
+ B runtime·callbackasm1(SB)
+ MOVW $595, R12
+ B runtime·callbackasm1(SB)
+ MOVW $596, R12
+ B runtime·callbackasm1(SB)
+ MOVW $597, R12
+ B runtime·callbackasm1(SB)
+ MOVW $598, R12
+ B runtime·callbackasm1(SB)
+ MOVW $599, R12
+ B runtime·callbackasm1(SB)
+ MOVW $600, R12
+ B runtime·callbackasm1(SB)
+ MOVW $601, R12
+ B runtime·callbackasm1(SB)
+ MOVW $602, R12
+ B runtime·callbackasm1(SB)
+ MOVW $603, R12
+ B runtime·callbackasm1(SB)
+ MOVW $604, R12
+ B runtime·callbackasm1(SB)
+ MOVW $605, R12
+ B runtime·callbackasm1(SB)
+ MOVW $606, R12
+ B runtime·callbackasm1(SB)
+ MOVW $607, R12
+ B runtime·callbackasm1(SB)
+ MOVW $608, R12
+ B runtime·callbackasm1(SB)
+ MOVW $609, R12
+ B runtime·callbackasm1(SB)
+ MOVW $610, R12
+ B runtime·callbackasm1(SB)
+ MOVW $611, R12
+ B runtime·callbackasm1(SB)
+ MOVW $612, R12
+ B runtime·callbackasm1(SB)
+ MOVW $613, R12
+ B runtime·callbackasm1(SB)
+ MOVW $614, R12
+ B runtime·callbackasm1(SB)
+ MOVW $615, R12
+ B runtime·callbackasm1(SB)
+ MOVW $616, R12
+ B runtime·callbackasm1(SB)
+ MOVW $617, R12
+ B runtime·callbackasm1(SB)
+ MOVW $618, R12
+ B runtime·callbackasm1(SB)
+ MOVW $619, R12
+ B runtime·callbackasm1(SB)
+ MOVW $620, R12
+ B runtime·callbackasm1(SB)
+ MOVW $621, R12
+ B runtime·callbackasm1(SB)
+ MOVW $622, R12
+ B runtime·callbackasm1(SB)
+ MOVW $623, R12
+ B runtime·callbackasm1(SB)
+ MOVW $624, R12
+ B runtime·callbackasm1(SB)
+ MOVW $625, R12
+ B runtime·callbackasm1(SB)
+ MOVW $626, R12
+ B runtime·callbackasm1(SB)
+ MOVW $627, R12
+ B runtime·callbackasm1(SB)
+ MOVW $628, R12
+ B runtime·callbackasm1(SB)
+ MOVW $629, R12
+ B runtime·callbackasm1(SB)
+ MOVW $630, R12
+ B runtime·callbackasm1(SB)
+ MOVW $631, R12
+ B runtime·callbackasm1(SB)
+ MOVW $632, R12
+ B runtime·callbackasm1(SB)
+ MOVW $633, R12
+ B runtime·callbackasm1(SB)
+ MOVW $634, R12
+ B runtime·callbackasm1(SB)
+ MOVW $635, R12
+ B runtime·callbackasm1(SB)
+ MOVW $636, R12
+ B runtime·callbackasm1(SB)
+ MOVW $637, R12
+ B runtime·callbackasm1(SB)
+ MOVW $638, R12
+ B runtime·callbackasm1(SB)
+ MOVW $639, R12
+ B runtime·callbackasm1(SB)
+ MOVW $640, R12
+ B runtime·callbackasm1(SB)
+ MOVW $641, R12
+ B runtime·callbackasm1(SB)
+ MOVW $642, R12
+ B runtime·callbackasm1(SB)
+ MOVW $643, R12
+ B runtime·callbackasm1(SB)
+ MOVW $644, R12
+ B runtime·callbackasm1(SB)
+ MOVW $645, R12
+ B runtime·callbackasm1(SB)
+ MOVW $646, R12
+ B runtime·callbackasm1(SB)
+ MOVW $647, R12
+ B runtime·callbackasm1(SB)
+ MOVW $648, R12
+ B runtime·callbackasm1(SB)
+ MOVW $649, R12
+ B runtime·callbackasm1(SB)
+ MOVW $650, R12
+ B runtime·callbackasm1(SB)
+ MOVW $651, R12
+ B runtime·callbackasm1(SB)
+ MOVW $652, R12
+ B runtime·callbackasm1(SB)
+ MOVW $653, R12
+ B runtime·callbackasm1(SB)
+ MOVW $654, R12
+ B runtime·callbackasm1(SB)
+ MOVW $655, R12
+ B runtime·callbackasm1(SB)
+ MOVW $656, R12
+ B runtime·callbackasm1(SB)
+ MOVW $657, R12
+ B runtime·callbackasm1(SB)
+ MOVW $658, R12
+ B runtime·callbackasm1(SB)
+ MOVW $659, R12
+ B runtime·callbackasm1(SB)
+ MOVW $660, R12
+ B runtime·callbackasm1(SB)
+ MOVW $661, R12
+ B runtime·callbackasm1(SB)
+ MOVW $662, R12
+ B runtime·callbackasm1(SB)
+ MOVW $663, R12
+ B runtime·callbackasm1(SB)
+ MOVW $664, R12
+ B runtime·callbackasm1(SB)
+ MOVW $665, R12
+ B runtime·callbackasm1(SB)
+ MOVW $666, R12
+ B runtime·callbackasm1(SB)
+ MOVW $667, R12
+ B runtime·callbackasm1(SB)
+ MOVW $668, R12
+ B runtime·callbackasm1(SB)
+ MOVW $669, R12
+ B runtime·callbackasm1(SB)
+ MOVW $670, R12
+ B runtime·callbackasm1(SB)
+ MOVW $671, R12
+ B runtime·callbackasm1(SB)
+ MOVW $672, R12
+ B runtime·callbackasm1(SB)
+ MOVW $673, R12
+ B runtime·callbackasm1(SB)
+ MOVW $674, R12
+ B runtime·callbackasm1(SB)
+ MOVW $675, R12
+ B runtime·callbackasm1(SB)
+ MOVW $676, R12
+ B runtime·callbackasm1(SB)
+ MOVW $677, R12
+ B runtime·callbackasm1(SB)
+ MOVW $678, R12
+ B runtime·callbackasm1(SB)
+ MOVW $679, R12
+ B runtime·callbackasm1(SB)
+ MOVW $680, R12
+ B runtime·callbackasm1(SB)
+ MOVW $681, R12
+ B runtime·callbackasm1(SB)
+ MOVW $682, R12
+ B runtime·callbackasm1(SB)
+ MOVW $683, R12
+ B runtime·callbackasm1(SB)
+ MOVW $684, R12
+ B runtime·callbackasm1(SB)
+ MOVW $685, R12
+ B runtime·callbackasm1(SB)
+ MOVW $686, R12
+ B runtime·callbackasm1(SB)
+ MOVW $687, R12
+ B runtime·callbackasm1(SB)
+ MOVW $688, R12
+ B runtime·callbackasm1(SB)
+ MOVW $689, R12
+ B runtime·callbackasm1(SB)
+ MOVW $690, R12
+ B runtime·callbackasm1(SB)
+ MOVW $691, R12
+ B runtime·callbackasm1(SB)
+ MOVW $692, R12
+ B runtime·callbackasm1(SB)
+ MOVW $693, R12
+ B runtime·callbackasm1(SB)
+ MOVW $694, R12
+ B runtime·callbackasm1(SB)
+ MOVW $695, R12
+ B runtime·callbackasm1(SB)
+ MOVW $696, R12
+ B runtime·callbackasm1(SB)
+ MOVW $697, R12
+ B runtime·callbackasm1(SB)
+ MOVW $698, R12
+ B runtime·callbackasm1(SB)
+ MOVW $699, R12
+ B runtime·callbackasm1(SB)
+ MOVW $700, R12
+ B runtime·callbackasm1(SB)
+ MOVW $701, R12
+ B runtime·callbackasm1(SB)
+ MOVW $702, R12
+ B runtime·callbackasm1(SB)
+ MOVW $703, R12
+ B runtime·callbackasm1(SB)
+ MOVW $704, R12
+ B runtime·callbackasm1(SB)
+ MOVW $705, R12
+ B runtime·callbackasm1(SB)
+ MOVW $706, R12
+ B runtime·callbackasm1(SB)
+ MOVW $707, R12
+ B runtime·callbackasm1(SB)
+ MOVW $708, R12
+ B runtime·callbackasm1(SB)
+ MOVW $709, R12
+ B runtime·callbackasm1(SB)
+ MOVW $710, R12
+ B runtime·callbackasm1(SB)
+ MOVW $711, R12
+ B runtime·callbackasm1(SB)
+ MOVW $712, R12
+ B runtime·callbackasm1(SB)
+ MOVW $713, R12
+ B runtime·callbackasm1(SB)
+ MOVW $714, R12
+ B runtime·callbackasm1(SB)
+ MOVW $715, R12
+ B runtime·callbackasm1(SB)
+ MOVW $716, R12
+ B runtime·callbackasm1(SB)
+ MOVW $717, R12
+ B runtime·callbackasm1(SB)
+ MOVW $718, R12
+ B runtime·callbackasm1(SB)
+ MOVW $719, R12
+ B runtime·callbackasm1(SB)
+ MOVW $720, R12
+ B runtime·callbackasm1(SB)
+ MOVW $721, R12
+ B runtime·callbackasm1(SB)
+ MOVW $722, R12
+ B runtime·callbackasm1(SB)
+ MOVW $723, R12
+ B runtime·callbackasm1(SB)
+ MOVW $724, R12
+ B runtime·callbackasm1(SB)
+ MOVW $725, R12
+ B runtime·callbackasm1(SB)
+ MOVW $726, R12
+ B runtime·callbackasm1(SB)
+ MOVW $727, R12
+ B runtime·callbackasm1(SB)
+ MOVW $728, R12
+ B runtime·callbackasm1(SB)
+ MOVW $729, R12
+ B runtime·callbackasm1(SB)
+ MOVW $730, R12
+ B runtime·callbackasm1(SB)
+ MOVW $731, R12
+ B runtime·callbackasm1(SB)
+ MOVW $732, R12
+ B runtime·callbackasm1(SB)
+ MOVW $733, R12
+ B runtime·callbackasm1(SB)
+ MOVW $734, R12
+ B runtime·callbackasm1(SB)
+ MOVW $735, R12
+ B runtime·callbackasm1(SB)
+ MOVW $736, R12
+ B runtime·callbackasm1(SB)
+ MOVW $737, R12
+ B runtime·callbackasm1(SB)
+ MOVW $738, R12
+ B runtime·callbackasm1(SB)
+ MOVW $739, R12
+ B runtime·callbackasm1(SB)
+ MOVW $740, R12
+ B runtime·callbackasm1(SB)
+ MOVW $741, R12
+ B runtime·callbackasm1(SB)
+ MOVW $742, R12
+ B runtime·callbackasm1(SB)
+ MOVW $743, R12
+ B runtime·callbackasm1(SB)
+ MOVW $744, R12
+ B runtime·callbackasm1(SB)
+ MOVW $745, R12
+ B runtime·callbackasm1(SB)
+ MOVW $746, R12
+ B runtime·callbackasm1(SB)
+ MOVW $747, R12
+ B runtime·callbackasm1(SB)
+ MOVW $748, R12
+ B runtime·callbackasm1(SB)
+ MOVW $749, R12
+ B runtime·callbackasm1(SB)
+ MOVW $750, R12
+ B runtime·callbackasm1(SB)
+ MOVW $751, R12
+ B runtime·callbackasm1(SB)
+ MOVW $752, R12
+ B runtime·callbackasm1(SB)
+ MOVW $753, R12
+ B runtime·callbackasm1(SB)
+ MOVW $754, R12
+ B runtime·callbackasm1(SB)
+ MOVW $755, R12
+ B runtime·callbackasm1(SB)
+ MOVW $756, R12
+ B runtime·callbackasm1(SB)
+ MOVW $757, R12
+ B runtime·callbackasm1(SB)
+ MOVW $758, R12
+ B runtime·callbackasm1(SB)
+ MOVW $759, R12
+ B runtime·callbackasm1(SB)
+ MOVW $760, R12
+ B runtime·callbackasm1(SB)
+ MOVW $761, R12
+ B runtime·callbackasm1(SB)
+ MOVW $762, R12
+ B runtime·callbackasm1(SB)
+ MOVW $763, R12
+ B runtime·callbackasm1(SB)
+ MOVW $764, R12
+ B runtime·callbackasm1(SB)
+ MOVW $765, R12
+ B runtime·callbackasm1(SB)
+ MOVW $766, R12
+ B runtime·callbackasm1(SB)
+ MOVW $767, R12
+ B runtime·callbackasm1(SB)
+ MOVW $768, R12
+ B runtime·callbackasm1(SB)
+ MOVW $769, R12
+ B runtime·callbackasm1(SB)
+ MOVW $770, R12
+ B runtime·callbackasm1(SB)
+ MOVW $771, R12
+ B runtime·callbackasm1(SB)
+ MOVW $772, R12
+ B runtime·callbackasm1(SB)
+ MOVW $773, R12
+ B runtime·callbackasm1(SB)
+ MOVW $774, R12
+ B runtime·callbackasm1(SB)
+ MOVW $775, R12
+ B runtime·callbackasm1(SB)
+ MOVW $776, R12
+ B runtime·callbackasm1(SB)
+ MOVW $777, R12
+ B runtime·callbackasm1(SB)
+ MOVW $778, R12
+ B runtime·callbackasm1(SB)
+ MOVW $779, R12
+ B runtime·callbackasm1(SB)
+ MOVW $780, R12
+ B runtime·callbackasm1(SB)
+ MOVW $781, R12
+ B runtime·callbackasm1(SB)
+ MOVW $782, R12
+ B runtime·callbackasm1(SB)
+ MOVW $783, R12
+ B runtime·callbackasm1(SB)
+ MOVW $784, R12
+ B runtime·callbackasm1(SB)
+ MOVW $785, R12
+ B runtime·callbackasm1(SB)
+ MOVW $786, R12
+ B runtime·callbackasm1(SB)
+ MOVW $787, R12
+ B runtime·callbackasm1(SB)
+ MOVW $788, R12
+ B runtime·callbackasm1(SB)
+ MOVW $789, R12
+ B runtime·callbackasm1(SB)
+ MOVW $790, R12
+ B runtime·callbackasm1(SB)
+ MOVW $791, R12
+ B runtime·callbackasm1(SB)
+ MOVW $792, R12
+ B runtime·callbackasm1(SB)
+ MOVW $793, R12
+ B runtime·callbackasm1(SB)
+ MOVW $794, R12
+ B runtime·callbackasm1(SB)
+ MOVW $795, R12
+ B runtime·callbackasm1(SB)
+ MOVW $796, R12
+ B runtime·callbackasm1(SB)
+ MOVW $797, R12
+ B runtime·callbackasm1(SB)
+ MOVW $798, R12
+ B runtime·callbackasm1(SB)
+ MOVW $799, R12
+ B runtime·callbackasm1(SB)
+ MOVW $800, R12
+ B runtime·callbackasm1(SB)
+ MOVW $801, R12
+ B runtime·callbackasm1(SB)
+ MOVW $802, R12
+ B runtime·callbackasm1(SB)
+ MOVW $803, R12
+ B runtime·callbackasm1(SB)
+ MOVW $804, R12
+ B runtime·callbackasm1(SB)
+ MOVW $805, R12
+ B runtime·callbackasm1(SB)
+ MOVW $806, R12
+ B runtime·callbackasm1(SB)
+ MOVW $807, R12
+ B runtime·callbackasm1(SB)
+ MOVW $808, R12
+ B runtime·callbackasm1(SB)
+ MOVW $809, R12
+ B runtime·callbackasm1(SB)
+ MOVW $810, R12
+ B runtime·callbackasm1(SB)
+ MOVW $811, R12
+ B runtime·callbackasm1(SB)
+ MOVW $812, R12
+ B runtime·callbackasm1(SB)
+ MOVW $813, R12
+ B runtime·callbackasm1(SB)
+ MOVW $814, R12
+ B runtime·callbackasm1(SB)
+ MOVW $815, R12
+ B runtime·callbackasm1(SB)
+ MOVW $816, R12
+ B runtime·callbackasm1(SB)
+ MOVW $817, R12
+ B runtime·callbackasm1(SB)
+ MOVW $818, R12
+ B runtime·callbackasm1(SB)
+ MOVW $819, R12
+ B runtime·callbackasm1(SB)
+ MOVW $820, R12
+ B runtime·callbackasm1(SB)
+ MOVW $821, R12
+ B runtime·callbackasm1(SB)
+ MOVW $822, R12
+ B runtime·callbackasm1(SB)
+ MOVW $823, R12
+ B runtime·callbackasm1(SB)
+ MOVW $824, R12
+ B runtime·callbackasm1(SB)
+ MOVW $825, R12
+ B runtime·callbackasm1(SB)
+ MOVW $826, R12
+ B runtime·callbackasm1(SB)
+ MOVW $827, R12
+ B runtime·callbackasm1(SB)
+ MOVW $828, R12
+ B runtime·callbackasm1(SB)
+ MOVW $829, R12
+ B runtime·callbackasm1(SB)
+ MOVW $830, R12
+ B runtime·callbackasm1(SB)
+ MOVW $831, R12
+ B runtime·callbackasm1(SB)
+ MOVW $832, R12
+ B runtime·callbackasm1(SB)
+ MOVW $833, R12
+ B runtime·callbackasm1(SB)
+ MOVW $834, R12
+ B runtime·callbackasm1(SB)
+ MOVW $835, R12
+ B runtime·callbackasm1(SB)
+ MOVW $836, R12
+ B runtime·callbackasm1(SB)
+ MOVW $837, R12
+ B runtime·callbackasm1(SB)
+ MOVW $838, R12
+ B runtime·callbackasm1(SB)
+ MOVW $839, R12
+ B runtime·callbackasm1(SB)
+ MOVW $840, R12
+ B runtime·callbackasm1(SB)
+ MOVW $841, R12
+ B runtime·callbackasm1(SB)
+ MOVW $842, R12
+ B runtime·callbackasm1(SB)
+ MOVW $843, R12
+ B runtime·callbackasm1(SB)
+ MOVW $844, R12
+ B runtime·callbackasm1(SB)
+ MOVW $845, R12
+ B runtime·callbackasm1(SB)
+ MOVW $846, R12
+ B runtime·callbackasm1(SB)
+ MOVW $847, R12
+ B runtime·callbackasm1(SB)
+ MOVW $848, R12
+ B runtime·callbackasm1(SB)
+ MOVW $849, R12
+ B runtime·callbackasm1(SB)
+ MOVW $850, R12
+ B runtime·callbackasm1(SB)
+ MOVW $851, R12
+ B runtime·callbackasm1(SB)
+ MOVW $852, R12
+ B runtime·callbackasm1(SB)
+ MOVW $853, R12
+ B runtime·callbackasm1(SB)
+ MOVW $854, R12
+ B runtime·callbackasm1(SB)
+ MOVW $855, R12
+ B runtime·callbackasm1(SB)
+ MOVW $856, R12
+ B runtime·callbackasm1(SB)
+ MOVW $857, R12
+ B runtime·callbackasm1(SB)
+ MOVW $858, R12
+ B runtime·callbackasm1(SB)
+ MOVW $859, R12
+ B runtime·callbackasm1(SB)
+ MOVW $860, R12
+ B runtime·callbackasm1(SB)
+ MOVW $861, R12
+ B runtime·callbackasm1(SB)
+ MOVW $862, R12
+ B runtime·callbackasm1(SB)
+ MOVW $863, R12
+ B runtime·callbackasm1(SB)
+ MOVW $864, R12
+ B runtime·callbackasm1(SB)
+ MOVW $865, R12
+ B runtime·callbackasm1(SB)
+ MOVW $866, R12
+ B runtime·callbackasm1(SB)
+ MOVW $867, R12
+ B runtime·callbackasm1(SB)
+ MOVW $868, R12
+ B runtime·callbackasm1(SB)
+ MOVW $869, R12
+ B runtime·callbackasm1(SB)
+ MOVW $870, R12
+ B runtime·callbackasm1(SB)
+ MOVW $871, R12
+ B runtime·callbackasm1(SB)
+ MOVW $872, R12
+ B runtime·callbackasm1(SB)
+ MOVW $873, R12
+ B runtime·callbackasm1(SB)
+ MOVW $874, R12
+ B runtime·callbackasm1(SB)
+ MOVW $875, R12
+ B runtime·callbackasm1(SB)
+ MOVW $876, R12
+ B runtime·callbackasm1(SB)
+ MOVW $877, R12
+ B runtime·callbackasm1(SB)
+ MOVW $878, R12
+ B runtime·callbackasm1(SB)
+ MOVW $879, R12
+ B runtime·callbackasm1(SB)
+ MOVW $880, R12
+ B runtime·callbackasm1(SB)
+ MOVW $881, R12
+ B runtime·callbackasm1(SB)
+ MOVW $882, R12
+ B runtime·callbackasm1(SB)
+ MOVW $883, R12
+ B runtime·callbackasm1(SB)
+ MOVW $884, R12
+ B runtime·callbackasm1(SB)
+ MOVW $885, R12
+ B runtime·callbackasm1(SB)
+ MOVW $886, R12
+ B runtime·callbackasm1(SB)
+ MOVW $887, R12
+ B runtime·callbackasm1(SB)
+ MOVW $888, R12
+ B runtime·callbackasm1(SB)
+ MOVW $889, R12
+ B runtime·callbackasm1(SB)
+ MOVW $890, R12
+ B runtime·callbackasm1(SB)
+ MOVW $891, R12
+ B runtime·callbackasm1(SB)
+ MOVW $892, R12
+ B runtime·callbackasm1(SB)
+ MOVW $893, R12
+ B runtime·callbackasm1(SB)
+ MOVW $894, R12
+ B runtime·callbackasm1(SB)
+ MOVW $895, R12
+ B runtime·callbackasm1(SB)
+ MOVW $896, R12
+ B runtime·callbackasm1(SB)
+ MOVW $897, R12
+ B runtime·callbackasm1(SB)
+ MOVW $898, R12
+ B runtime·callbackasm1(SB)
+ MOVW $899, R12
+ B runtime·callbackasm1(SB)
+ MOVW $900, R12
+ B runtime·callbackasm1(SB)
+ MOVW $901, R12
+ B runtime·callbackasm1(SB)
+ MOVW $902, R12
+ B runtime·callbackasm1(SB)
+ MOVW $903, R12
+ B runtime·callbackasm1(SB)
+ MOVW $904, R12
+ B runtime·callbackasm1(SB)
+ MOVW $905, R12
+ B runtime·callbackasm1(SB)
+ MOVW $906, R12
+ B runtime·callbackasm1(SB)
+ MOVW $907, R12
+ B runtime·callbackasm1(SB)
+ MOVW $908, R12
+ B runtime·callbackasm1(SB)
+ MOVW $909, R12
+ B runtime·callbackasm1(SB)
+ MOVW $910, R12
+ B runtime·callbackasm1(SB)
+ MOVW $911, R12
+ B runtime·callbackasm1(SB)
+ MOVW $912, R12
+ B runtime·callbackasm1(SB)
+ MOVW $913, R12
+ B runtime·callbackasm1(SB)
+ MOVW $914, R12
+ B runtime·callbackasm1(SB)
+ MOVW $915, R12
+ B runtime·callbackasm1(SB)
+ MOVW $916, R12
+ B runtime·callbackasm1(SB)
+ MOVW $917, R12
+ B runtime·callbackasm1(SB)
+ MOVW $918, R12
+ B runtime·callbackasm1(SB)
+ MOVW $919, R12
+ B runtime·callbackasm1(SB)
+ MOVW $920, R12
+ B runtime·callbackasm1(SB)
+ MOVW $921, R12
+ B runtime·callbackasm1(SB)
+ MOVW $922, R12
+ B runtime·callbackasm1(SB)
+ MOVW $923, R12
+ B runtime·callbackasm1(SB)
+ MOVW $924, R12
+ B runtime·callbackasm1(SB)
+ MOVW $925, R12
+ B runtime·callbackasm1(SB)
+ MOVW $926, R12
+ B runtime·callbackasm1(SB)
+ MOVW $927, R12
+ B runtime·callbackasm1(SB)
+ MOVW $928, R12
+ B runtime·callbackasm1(SB)
+ MOVW $929, R12
+ B runtime·callbackasm1(SB)
+ MOVW $930, R12
+ B runtime·callbackasm1(SB)
+ MOVW $931, R12
+ B runtime·callbackasm1(SB)
+ MOVW $932, R12
+ B runtime·callbackasm1(SB)
+ MOVW $933, R12
+ B runtime·callbackasm1(SB)
+ MOVW $934, R12
+ B runtime·callbackasm1(SB)
+ MOVW $935, R12
+ B runtime·callbackasm1(SB)
+ MOVW $936, R12
+ B runtime·callbackasm1(SB)
+ MOVW $937, R12
+ B runtime·callbackasm1(SB)
+ MOVW $938, R12
+ B runtime·callbackasm1(SB)
+ MOVW $939, R12
+ B runtime·callbackasm1(SB)
+ MOVW $940, R12
+ B runtime·callbackasm1(SB)
+ MOVW $941, R12
+ B runtime·callbackasm1(SB)
+ MOVW $942, R12
+ B runtime·callbackasm1(SB)
+ MOVW $943, R12
+ B runtime·callbackasm1(SB)
+ MOVW $944, R12
+ B runtime·callbackasm1(SB)
+ MOVW $945, R12
+ B runtime·callbackasm1(SB)
+ MOVW $946, R12
+ B runtime·callbackasm1(SB)
+ MOVW $947, R12
+ B runtime·callbackasm1(SB)
+ MOVW $948, R12
+ B runtime·callbackasm1(SB)
+ MOVW $949, R12
+ B runtime·callbackasm1(SB)
+ MOVW $950, R12
+ B runtime·callbackasm1(SB)
+ MOVW $951, R12
+ B runtime·callbackasm1(SB)
+ MOVW $952, R12
+ B runtime·callbackasm1(SB)
+ MOVW $953, R12
+ B runtime·callbackasm1(SB)
+ MOVW $954, R12
+ B runtime·callbackasm1(SB)
+ MOVW $955, R12
+ B runtime·callbackasm1(SB)
+ MOVW $956, R12
+ B runtime·callbackasm1(SB)
+ MOVW $957, R12
+ B runtime·callbackasm1(SB)
+ MOVW $958, R12
+ B runtime·callbackasm1(SB)
+ MOVW $959, R12
+ B runtime·callbackasm1(SB)
+ MOVW $960, R12
+ B runtime·callbackasm1(SB)
+ MOVW $961, R12
+ B runtime·callbackasm1(SB)
+ MOVW $962, R12
+ B runtime·callbackasm1(SB)
+ MOVW $963, R12
+ B runtime·callbackasm1(SB)
+ MOVW $964, R12
+ B runtime·callbackasm1(SB)
+ MOVW $965, R12
+ B runtime·callbackasm1(SB)
+ MOVW $966, R12
+ B runtime·callbackasm1(SB)
+ MOVW $967, R12
+ B runtime·callbackasm1(SB)
+ MOVW $968, R12
+ B runtime·callbackasm1(SB)
+ MOVW $969, R12
+ B runtime·callbackasm1(SB)
+ MOVW $970, R12
+ B runtime·callbackasm1(SB)
+ MOVW $971, R12
+ B runtime·callbackasm1(SB)
+ MOVW $972, R12
+ B runtime·callbackasm1(SB)
+ MOVW $973, R12
+ B runtime·callbackasm1(SB)
+ MOVW $974, R12
+ B runtime·callbackasm1(SB)
+ MOVW $975, R12
+ B runtime·callbackasm1(SB)
+ MOVW $976, R12
+ B runtime·callbackasm1(SB)
+ MOVW $977, R12
+ B runtime·callbackasm1(SB)
+ MOVW $978, R12
+ B runtime·callbackasm1(SB)
+ MOVW $979, R12
+ B runtime·callbackasm1(SB)
+ MOVW $980, R12
+ B runtime·callbackasm1(SB)
+ MOVW $981, R12
+ B runtime·callbackasm1(SB)
+ MOVW $982, R12
+ B runtime·callbackasm1(SB)
+ MOVW $983, R12
+ B runtime·callbackasm1(SB)
+ MOVW $984, R12
+ B runtime·callbackasm1(SB)
+ MOVW $985, R12
+ B runtime·callbackasm1(SB)
+ MOVW $986, R12
+ B runtime·callbackasm1(SB)
+ MOVW $987, R12
+ B runtime·callbackasm1(SB)
+ MOVW $988, R12
+ B runtime·callbackasm1(SB)
+ MOVW $989, R12
+ B runtime·callbackasm1(SB)
+ MOVW $990, R12
+ B runtime·callbackasm1(SB)
+ MOVW $991, R12
+ B runtime·callbackasm1(SB)
+ MOVW $992, R12
+ B runtime·callbackasm1(SB)
+ MOVW $993, R12
+ B runtime·callbackasm1(SB)
+ MOVW $994, R12
+ B runtime·callbackasm1(SB)
+ MOVW $995, R12
+ B runtime·callbackasm1(SB)
+ MOVW $996, R12
+ B runtime·callbackasm1(SB)
+ MOVW $997, R12
+ B runtime·callbackasm1(SB)
+ MOVW $998, R12
+ B runtime·callbackasm1(SB)
+ MOVW $999, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1000, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1001, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1002, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1003, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1004, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1005, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1006, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1007, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1008, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1009, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1010, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1011, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1012, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1013, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1014, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1015, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1016, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1017, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1018, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1019, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1020, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1021, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1022, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1023, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1024, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1025, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1026, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1027, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1028, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1029, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1030, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1031, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1032, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1033, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1034, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1035, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1036, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1037, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1038, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1039, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1040, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1041, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1042, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1043, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1044, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1045, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1046, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1047, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1048, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1049, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1050, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1051, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1052, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1053, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1054, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1055, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1056, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1057, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1058, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1059, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1060, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1061, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1062, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1063, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1064, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1065, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1066, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1067, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1068, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1069, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1070, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1071, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1072, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1073, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1074, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1075, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1076, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1077, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1078, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1079, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1080, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1081, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1082, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1083, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1084, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1085, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1086, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1087, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1088, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1089, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1090, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1091, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1092, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1093, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1094, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1095, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1096, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1097, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1098, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1099, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1100, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1101, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1102, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1103, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1104, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1105, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1106, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1107, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1108, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1109, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1110, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1111, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1112, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1113, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1114, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1115, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1116, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1117, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1118, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1119, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1120, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1121, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1122, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1123, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1124, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1125, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1126, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1127, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1128, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1129, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1130, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1131, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1132, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1133, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1134, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1135, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1136, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1137, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1138, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1139, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1140, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1141, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1142, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1143, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1144, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1145, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1146, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1147, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1148, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1149, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1150, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1151, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1152, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1153, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1154, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1155, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1156, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1157, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1158, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1159, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1160, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1161, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1162, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1163, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1164, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1165, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1166, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1167, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1168, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1169, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1170, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1171, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1172, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1173, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1174, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1175, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1176, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1177, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1178, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1179, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1180, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1181, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1182, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1183, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1184, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1185, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1186, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1187, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1188, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1189, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1190, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1191, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1192, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1193, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1194, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1195, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1196, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1197, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1198, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1199, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1200, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1201, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1202, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1203, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1204, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1205, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1206, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1207, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1208, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1209, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1210, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1211, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1212, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1213, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1214, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1215, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1216, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1217, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1218, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1219, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1220, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1221, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1222, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1223, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1224, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1225, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1226, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1227, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1228, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1229, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1230, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1231, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1232, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1233, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1234, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1235, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1236, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1237, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1238, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1239, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1240, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1241, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1242, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1243, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1244, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1245, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1246, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1247, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1248, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1249, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1250, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1251, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1252, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1253, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1254, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1255, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1256, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1257, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1258, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1259, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1260, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1261, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1262, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1263, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1264, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1265, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1266, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1267, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1268, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1269, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1270, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1271, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1272, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1273, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1274, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1275, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1276, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1277, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1278, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1279, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1280, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1281, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1282, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1283, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1284, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1285, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1286, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1287, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1288, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1289, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1290, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1291, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1292, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1293, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1294, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1295, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1296, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1297, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1298, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1299, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1300, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1301, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1302, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1303, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1304, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1305, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1306, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1307, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1308, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1309, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1310, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1311, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1312, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1313, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1314, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1315, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1316, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1317, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1318, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1319, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1320, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1321, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1322, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1323, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1324, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1325, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1326, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1327, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1328, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1329, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1330, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1331, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1332, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1333, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1334, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1335, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1336, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1337, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1338, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1339, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1340, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1341, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1342, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1343, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1344, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1345, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1346, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1347, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1348, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1349, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1350, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1351, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1352, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1353, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1354, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1355, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1356, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1357, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1358, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1359, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1360, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1361, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1362, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1363, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1364, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1365, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1366, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1367, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1368, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1369, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1370, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1371, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1372, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1373, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1374, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1375, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1376, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1377, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1378, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1379, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1380, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1381, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1382, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1383, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1384, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1385, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1386, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1387, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1388, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1389, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1390, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1391, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1392, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1393, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1394, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1395, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1396, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1397, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1398, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1399, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1400, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1401, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1402, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1403, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1404, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1405, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1406, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1407, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1408, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1409, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1410, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1411, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1412, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1413, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1414, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1415, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1416, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1417, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1418, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1419, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1420, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1421, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1422, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1423, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1424, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1425, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1426, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1427, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1428, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1429, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1430, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1431, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1432, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1433, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1434, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1435, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1436, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1437, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1438, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1439, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1440, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1441, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1442, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1443, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1444, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1445, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1446, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1447, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1448, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1449, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1450, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1451, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1452, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1453, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1454, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1455, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1456, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1457, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1458, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1459, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1460, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1461, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1462, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1463, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1464, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1465, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1466, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1467, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1468, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1469, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1470, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1471, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1472, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1473, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1474, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1475, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1476, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1477, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1478, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1479, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1480, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1481, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1482, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1483, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1484, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1485, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1486, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1487, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1488, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1489, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1490, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1491, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1492, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1493, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1494, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1495, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1496, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1497, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1498, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1499, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1500, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1501, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1502, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1503, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1504, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1505, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1506, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1507, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1508, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1509, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1510, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1511, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1512, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1513, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1514, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1515, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1516, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1517, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1518, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1519, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1520, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1521, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1522, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1523, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1524, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1525, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1526, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1527, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1528, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1529, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1530, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1531, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1532, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1533, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1534, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1535, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1536, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1537, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1538, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1539, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1540, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1541, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1542, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1543, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1544, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1545, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1546, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1547, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1548, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1549, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1550, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1551, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1552, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1553, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1554, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1555, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1556, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1557, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1558, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1559, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1560, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1561, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1562, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1563, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1564, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1565, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1566, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1567, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1568, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1569, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1570, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1571, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1572, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1573, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1574, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1575, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1576, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1577, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1578, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1579, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1580, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1581, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1582, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1583, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1584, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1585, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1586, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1587, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1588, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1589, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1590, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1591, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1592, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1593, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1594, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1595, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1596, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1597, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1598, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1599, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1600, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1601, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1602, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1603, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1604, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1605, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1606, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1607, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1608, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1609, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1610, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1611, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1612, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1613, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1614, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1615, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1616, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1617, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1618, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1619, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1620, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1621, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1622, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1623, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1624, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1625, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1626, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1627, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1628, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1629, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1630, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1631, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1632, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1633, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1634, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1635, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1636, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1637, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1638, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1639, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1640, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1641, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1642, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1643, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1644, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1645, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1646, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1647, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1648, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1649, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1650, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1651, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1652, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1653, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1654, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1655, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1656, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1657, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1658, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1659, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1660, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1661, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1662, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1663, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1664, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1665, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1666, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1667, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1668, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1669, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1670, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1671, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1672, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1673, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1674, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1675, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1676, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1677, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1678, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1679, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1680, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1681, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1682, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1683, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1684, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1685, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1686, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1687, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1688, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1689, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1690, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1691, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1692, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1693, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1694, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1695, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1696, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1697, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1698, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1699, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1700, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1701, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1702, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1703, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1704, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1705, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1706, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1707, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1708, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1709, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1710, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1711, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1712, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1713, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1714, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1715, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1716, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1717, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1718, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1719, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1720, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1721, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1722, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1723, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1724, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1725, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1726, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1727, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1728, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1729, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1730, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1731, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1732, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1733, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1734, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1735, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1736, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1737, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1738, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1739, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1740, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1741, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1742, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1743, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1744, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1745, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1746, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1747, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1748, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1749, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1750, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1751, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1752, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1753, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1754, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1755, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1756, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1757, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1758, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1759, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1760, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1761, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1762, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1763, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1764, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1765, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1766, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1767, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1768, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1769, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1770, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1771, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1772, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1773, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1774, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1775, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1776, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1777, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1778, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1779, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1780, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1781, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1782, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1783, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1784, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1785, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1786, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1787, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1788, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1789, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1790, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1791, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1792, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1793, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1794, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1795, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1796, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1797, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1798, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1799, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1800, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1801, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1802, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1803, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1804, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1805, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1806, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1807, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1808, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1809, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1810, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1811, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1812, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1813, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1814, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1815, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1816, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1817, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1818, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1819, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1820, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1821, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1822, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1823, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1824, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1825, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1826, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1827, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1828, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1829, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1830, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1831, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1832, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1833, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1834, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1835, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1836, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1837, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1838, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1839, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1840, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1841, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1842, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1843, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1844, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1845, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1846, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1847, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1848, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1849, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1850, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1851, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1852, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1853, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1854, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1855, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1856, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1857, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1858, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1859, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1860, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1861, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1862, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1863, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1864, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1865, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1866, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1867, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1868, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1869, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1870, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1871, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1872, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1873, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1874, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1875, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1876, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1877, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1878, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1879, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1880, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1881, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1882, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1883, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1884, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1885, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1886, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1887, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1888, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1889, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1890, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1891, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1892, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1893, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1894, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1895, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1896, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1897, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1898, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1899, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1900, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1901, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1902, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1903, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1904, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1905, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1906, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1907, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1908, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1909, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1910, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1911, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1912, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1913, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1914, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1915, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1916, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1917, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1918, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1919, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1920, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1921, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1922, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1923, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1924, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1925, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1926, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1927, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1928, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1929, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1930, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1931, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1932, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1933, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1934, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1935, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1936, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1937, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1938, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1939, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1940, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1941, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1942, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1943, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1944, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1945, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1946, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1947, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1948, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1949, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1950, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1951, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1952, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1953, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1954, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1955, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1956, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1957, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1958, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1959, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1960, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1961, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1962, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1963, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1964, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1965, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1966, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1967, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1968, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1969, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1970, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1971, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1972, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1973, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1974, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1975, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1976, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1977, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1978, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1979, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1980, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1981, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1982, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1983, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1984, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1985, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1986, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1987, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1988, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1989, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1990, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1991, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1992, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1993, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1994, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1995, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1996, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1997, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1998, R12
+ B runtime·callbackasm1(SB)
+ MOVW $1999, R12
+ B runtime·callbackasm1(SB)
diff --git a/src/strings/example_test.go b/src/strings/example_test.go
index 607e4a0a70..103ef51f29 100644
--- a/src/strings/example_test.go
+++ b/src/strings/example_test.go
@@ -199,7 +199,7 @@ func ExampleRepeat() {
func ExampleReplace() {
fmt.Println(strings.Replace("oink oink oink", "k", "ky", 2))
- fmt.Println(strings.Replace("oink oink oink", "oink", "moo", -1))
+ fmt.Println(strings.ReplaceAll("oink oink oink", "oink", "moo"))
// Output:
// oinky oinky oink
// moo moo moo
diff --git a/src/strings/replace.go b/src/strings/replace.go
index dbda950194..9ddf5e1e3f 100644
--- a/src/strings/replace.go
+++ b/src/strings/replace.go
@@ -308,10 +308,6 @@ func (w *appendSliceWriter) WriteString(s string) (int, error) {
return len(s), nil
}
-type stringWriterIface interface {
- WriteString(string) (int, error)
-}
-
type stringWriter struct {
w io.Writer
}
@@ -320,8 +316,8 @@ func (w stringWriter) WriteString(s string) (int, error) {
return w.w.Write([]byte(s))
}
-func getStringWriter(w io.Writer) stringWriterIface {
- sw, ok := w.(stringWriterIface)
+func getStringWriter(w io.Writer) io.StringWriter {
+ sw, ok := w.(io.StringWriter)
if !ok {
sw = stringWriter{w}
}
diff --git a/src/strings/strings.go b/src/strings/strings.go
index df95715ec8..ecc8c97d9e 100644
--- a/src/strings/strings.go
+++ b/src/strings/strings.go
@@ -463,27 +463,27 @@ func Map(mapping func(rune) rune, s string) string {
for i, c := range s {
r := mapping(c)
- if r == c {
+ if r == c && c != utf8.RuneError {
continue
}
+ var width int
+ if c == utf8.RuneError {
+ c, width = utf8.DecodeRuneInString(s[i:])
+ if width != 1 && r == c {
+ continue
+ }
+ } else {
+ width = utf8.RuneLen(c)
+ }
+
b.Grow(len(s) + utf8.UTFMax)
b.WriteString(s[:i])
if r >= 0 {
b.WriteRune(r)
}
- if c == utf8.RuneError {
- // RuneError is the result of either decoding
- // an invalid sequence or '\uFFFD'. Determine
- // the correct number of bytes we need to advance.
- _, w := utf8.DecodeRuneInString(s[i:])
- i += w
- } else {
- i += utf8.RuneLen(c)
- }
-
- s = s[i:]
+ s = s[i+width:]
break
}
@@ -561,15 +561,16 @@ func ToUpper(s string) string {
if !hasLower {
return s
}
- b := make([]byte, len(s))
+ var b Builder
+ b.Grow(len(s))
for i := 0; i < len(s); i++ {
c := s[i]
if c >= 'a' && c <= 'z' {
c -= 'a' - 'A'
}
- b[i] = c
+ b.WriteByte(c)
}
- return string(b)
+ return b.String()
}
return Map(unicode.ToUpper, s)
}
@@ -590,15 +591,16 @@ func ToLower(s string) string {
if !hasUpper {
return s
}
- b := make([]byte, len(s))
+ var b Builder
+ b.Grow(len(s))
for i := 0; i < len(s); i++ {
c := s[i]
if c >= 'A' && c <= 'Z' {
c += 'a' - 'A'
}
- b[i] = c
+ b.WriteByte(c)
}
- return string(b)
+ return b.String()
}
return Map(unicode.ToLower, s)
}
@@ -872,6 +874,15 @@ func Replace(s, old, new string, n int) string {
return string(t[0:w])
}
+// ReplaceAll returns a copy of the string s with all
+// non-overlapping instances of old replaced by new.
+// If old is empty, it matches at the beginning of the string
+// and after each UTF-8 sequence, yielding up to k+1 replacements
+// for a k-rune string.
+func ReplaceAll(s, old, new string) string {
+ return Replace(s, old, new, -1)
+}
+
// EqualFold reports whether s and t, interpreted as UTF-8 strings,
// are equal under Unicode case-folding.
func EqualFold(s, t string) bool {
@@ -947,21 +958,22 @@ func Index(s, substr string) int {
if len(s) <= bytealg.MaxBruteForce {
return bytealg.IndexString(s, substr)
}
- c := substr[0]
+ c0 := substr[0]
+ c1 := substr[1]
i := 0
- t := s[:len(s)-n+1]
+ t := len(s) - n + 1
fails := 0
- for i < len(t) {
- if t[i] != c {
+ for i < t {
+ if s[i] != c0 {
// IndexByte is faster than bytealg.IndexString, so use it as long as
// we're not getting lots of false positives.
- o := IndexByte(t[i:], c)
+ o := IndexByte(s[i:t], c0)
if o < 0 {
return -1
}
i += o
}
- if s[i:i+n] == substr {
+ if s[i+1] == c1 && s[i:i+n] == substr {
return i
}
fails++
@@ -977,24 +989,25 @@ func Index(s, substr string) int {
}
return -1
}
- c := substr[0]
+ c0 := substr[0]
+ c1 := substr[1]
i := 0
- t := s[:len(s)-n+1]
+ t := len(s) - n + 1
fails := 0
- for i < len(t) {
- if t[i] != c {
- o := IndexByte(t[i:], c)
+ for i < t {
+ if s[i] != c0 {
+ o := IndexByte(s[i:t], c0)
if o < 0 {
return -1
}
i += o
}
- if s[i:i+n] == substr {
+ if s[i+1] == c1 && s[i:i+n] == substr {
return i
}
i++
fails++
- if fails >= 4+i>>4 && i < len(t) {
+ if fails >= 4+i>>4 && i < t {
// See comment in ../bytes/bytes_generic.go.
j := indexRabinKarp(s[i:], substr)
if j < 0 {
diff --git a/src/strings/strings_test.go b/src/strings/strings_test.go
index 20bc484f39..eee2dd55df 100644
--- a/src/strings/strings_test.go
+++ b/src/strings/strings_test.go
@@ -646,10 +646,10 @@ func TestMap(t *testing.T) {
if unicode.Is(unicode.Latin, r) {
return r
}
- return '?'
+ return utf8.RuneError
}
m = Map(replaceNotLatin, "Hello\255World")
- expect = "Hello?World"
+ expect = "Hello\uFFFDWorld"
if m != expect {
t.Errorf("replace invalid sequence: expected %q got %q", expect, m)
}
@@ -1243,6 +1243,12 @@ func TestReplace(t *testing.T) {
if s := Replace(tt.in, tt.old, tt.new, tt.n); s != tt.out {
t.Errorf("Replace(%q, %q, %q, %d) = %q, want %q", tt.in, tt.old, tt.new, tt.n, s, tt.out)
}
+ if tt.n == -1 {
+ s := ReplaceAll(tt.in, tt.old, tt.new)
+ if s != tt.out {
+ t.Errorf("ReplaceAll(%q, %q, %q) = %q, want %q", tt.in, tt.old, tt.new, s, tt.out)
+ }
+ }
}
}
diff --git a/src/sync/map.go b/src/sync/map.go
index c4a0dc4194..c6aa308856 100644
--- a/src/sync/map.go
+++ b/src/sync/map.go
@@ -167,18 +167,14 @@ func (m *Map) Store(key, value interface{}) {
// If the entry is expunged, tryStore returns false and leaves the entry
// unchanged.
func (e *entry) tryStore(i *interface{}) bool {
- p := atomic.LoadPointer(&e.p)
- if p == expunged {
- return false
- }
for {
- if atomic.CompareAndSwapPointer(&e.p, p, unsafe.Pointer(i)) {
- return true
- }
- p = atomic.LoadPointer(&e.p)
+ p := atomic.LoadPointer(&e.p)
if p == expunged {
return false
}
+ if atomic.CompareAndSwapPointer(&e.p, p, unsafe.Pointer(i)) {
+ return true
+ }
}
}
diff --git a/src/syscall/asm_nacl_386.s b/src/syscall/asm_nacl_386.s
index 9d1e541c7c..b989171120 100644
--- a/src/syscall/asm_nacl_386.s
+++ b/src/syscall/asm_nacl_386.s
@@ -42,4 +42,4 @@ ok:
MOVL DX, r2+20(FP)
MOVL $0, err+24(FP)
CALL runtime·exitsyscall(SB)
- RET
+ RET
diff --git a/src/syscall/asm_nacl_amd64p32.s b/src/syscall/asm_nacl_amd64p32.s
index b8c097b539..816f7dccfb 100644
--- a/src/syscall/asm_nacl_amd64p32.s
+++ b/src/syscall/asm_nacl_amd64p32.s
@@ -39,4 +39,4 @@ ok:
MOVL DX, r2+20(FP)
MOVL $0, err+24(FP)
CALL runtime·exitsyscall(SB)
- RET
+ RET
diff --git a/src/syscall/asm_nacl_arm.s b/src/syscall/asm_nacl_arm.s
index 3e7df1aadf..6092afd9e6 100644
--- a/src/syscall/asm_nacl_arm.s
+++ b/src/syscall/asm_nacl_arm.s
@@ -41,4 +41,4 @@ ok:
MOVW $0, R2
MOVW R2, err+24(FP)
BL runtime·exitsyscall(SB)
- RET
+ RET
diff --git a/src/syscall/asm_plan9_386.s b/src/syscall/asm_plan9_386.s
index 65ae6c77fb..7a2c2daaaa 100644
--- a/src/syscall/asm_plan9_386.s
+++ b/src/syscall/asm_plan9_386.s
@@ -45,11 +45,11 @@ TEXT ·Syscall(SB),NOSPLIT,$148-32
CALL runtime·gostring(SB)
LEAL str-144(SP), SI
JMP copyresult3
-
+
ok3:
CALL runtime·exitsyscall(SB)
LEAL ·emptystring(SB), SI
-
+
copyresult3:
LEAL err+24(FP), DI
@@ -78,7 +78,7 @@ TEXT ·Syscall6(SB),NOSPLIT,$148-44
MOVL $0, r2+32(FP)
CMPL AX, $-1
JNE ok4
-
+
LEAL errbuf-128(SP), AX
MOVL AX, sysargs-144(SP)
MOVL $128, sysargs1-140(SP)
@@ -90,11 +90,11 @@ TEXT ·Syscall6(SB),NOSPLIT,$148-44
CALL runtime·gostring(SB)
LEAL str-144(SP), SI
JMP copyresult4
-
+
ok4:
CALL runtime·exitsyscall(SB)
LEAL ·emptystring(SB), SI
-
+
copyresult4:
LEAL err+36(FP), DI
@@ -144,7 +144,7 @@ TEXT ·seek(SB),NOSPLIT,$24-36
NO_LOCAL_POINTERS
LEAL newoffset+20(FP), AX
MOVL AX, placeholder+0(FP)
-
+
// copy args down
LEAL placeholder+0(FP), SI
LEAL sysargs-20(SP), DI
@@ -156,19 +156,19 @@ TEXT ·seek(SB),NOSPLIT,$24-36
MOVSL
MOVL $SYS_SEEK, AX // syscall entry
INT $64
-
+
CMPL AX, $-1
JNE ok6
MOVL AX, newoffset_lo+20(FP)
MOVL AX, newoffset_hi+24(FP)
-
+
CALL syscall·errstr(SB)
MOVL SP, SI
JMP copyresult6
-
+
ok6:
LEAL ·emptystring(SB), SI
-
+
copyresult6:
LEAL err+28(FP), DI
diff --git a/src/syscall/asm_plan9_amd64.s b/src/syscall/asm_plan9_amd64.s
index bba4012e5c..d5c9f6c63f 100644
--- a/src/syscall/asm_plan9_amd64.s
+++ b/src/syscall/asm_plan9_amd64.s
@@ -44,11 +44,11 @@ TEXT ·Syscall(SB),NOSPLIT,$168-64
CALL runtime·gostring(SB)
LEAQ str-160(SP), SI
JMP copyresult3
-
+
ok3:
CALL runtime·exitsyscall(SB)
LEAQ ·emptystring(SB), SI
-
+
copyresult3:
LEAQ err+48(FP), DI
@@ -77,7 +77,7 @@ TEXT ·Syscall6(SB),NOSPLIT,$168-88
MOVQ $0, r2+64(FP)
CMPL AX, $-1
JNE ok4
-
+
LEAQ errbuf-128(SP), AX
MOVQ AX, sysargs-160(SP)
MOVQ $128, sysargs1-152(SP)
@@ -89,11 +89,11 @@ TEXT ·Syscall6(SB),NOSPLIT,$168-88
CALL runtime·gostring(SB)
LEAQ str-160(SP), SI
JMP copyresult4
-
+
ok4:
CALL runtime·exitsyscall(SB)
LEAQ ·emptystring(SB), SI
-
+
copyresult4:
LEAQ err+72(FP), DI
@@ -143,7 +143,7 @@ TEXT ·seek(SB),NOSPLIT,$48-56
NO_LOCAL_POINTERS
LEAQ newoffset+32(FP), AX
MOVQ AX, placeholder+0(FP)
-
+
// copy args down
LEAQ placeholder+0(FP), SI
LEAQ sysargs-40(SP), DI
@@ -155,18 +155,18 @@ TEXT ·seek(SB),NOSPLIT,$48-56
MOVSQ
MOVQ $SYS_SEEK, BP // syscall entry
SYSCALL
-
+
CMPL AX, $-1
JNE ok6
MOVQ AX, newoffset+32(FP)
-
+
CALL syscall·errstr(SB)
MOVQ SP, SI
JMP copyresult6
-
+
ok6:
LEAQ ·emptystring(SB), SI
-
+
copyresult6:
LEAQ err+40(FP), DI
diff --git a/src/syscall/syscall_linux_386.go b/src/syscall/syscall_linux_386.go
index 49db72450f..6e162ebb41 100644
--- a/src/syscall/syscall_linux_386.go
+++ b/src/syscall/syscall_linux_386.go
@@ -62,8 +62,6 @@ func Pipe2(p []int, flags int) (err error) {
//sysnb InotifyInit() (fd int, err error)
//sys Ioperm(from int, num int, on int) (err error)
//sys Iopl(level int) (err error)
-//sys Lchown(path string, uid int, gid int) (err error) = SYS_LCHOWN32
-//sys Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64
//sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = SYS_SENDFILE64
@@ -74,7 +72,6 @@ func Pipe2(p []int, flags int) (err error) {
//sysnb Setresuid(ruid int, euid int, suid int) (err error) = SYS_SETRESUID32
//sysnb Setreuid(ruid int, euid int) (err error) = SYS_SETREUID32
//sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int, err error)
-//sys Stat(path string, stat *Stat_t) (err error) = SYS_STAT64
//sys SyncFileRange(fd int, off int64, n int64, flags int) (err error)
//sys Truncate(path string, length int64) (err error) = SYS_TRUNCATE64
//sysnb getgroups(n int, list *_Gid_t) (nn int, err error) = SYS_GETGROUPS32
@@ -84,6 +81,18 @@ func Pipe2(p []int, flags int) (err error) {
//sys mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, err error)
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
+func Stat(path string, stat *Stat_t) (err error) {
+ return fstatat(_AT_FDCWD, path, stat, 0)
+}
+
+func Lchown(path string, uid int, gid int) (err error) {
+ return Fchownat(_AT_FDCWD, path, uid, gid, _AT_SYMLINK_NOFOLLOW)
+}
+
+func Lstat(path string, stat *Stat_t) (err error) {
+ return fstatat(_AT_FDCWD, path, stat, _AT_SYMLINK_NOFOLLOW)
+}
+
func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) {
page := uintptr(offset / 4096)
if offset != int64(page)*4096 {
diff --git a/src/syscall/syscall_linux_amd64.go b/src/syscall/syscall_linux_amd64.go
index 1a21d9db6f..f740ab4e72 100644
--- a/src/syscall/syscall_linux_amd64.go
+++ b/src/syscall/syscall_linux_amd64.go
@@ -22,9 +22,7 @@ const (
//sysnb InotifyInit() (fd int, err error)
//sys Ioperm(from int, num int, on int) (err error)
//sys Iopl(level int) (err error)
-//sys Lchown(path string, uid int, gid int) (err error)
//sys Listen(s int, n int) (err error)
-//sys Lstat(path string, stat *Stat_t) (err error)
//sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
//sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
@@ -66,6 +64,14 @@ func Stat(path string, stat *Stat_t) (err error) {
return fstatat(_AT_FDCWD, path, stat, 0)
}
+func Lchown(path string, uid int, gid int) (err error) {
+ return Fchownat(_AT_FDCWD, path, uid, gid, _AT_SYMLINK_NOFOLLOW)
+}
+
+func Lstat(path string, stat *Stat_t) (err error) {
+ return fstatat(_AT_FDCWD, path, stat, _AT_SYMLINK_NOFOLLOW)
+}
+
//go:noescape
func gettimeofday(tv *Timeval) (err Errno)
diff --git a/src/syscall/syscall_linux_arm.go b/src/syscall/syscall_linux_arm.go
index b0c0ac7c4f..65543193e1 100644
--- a/src/syscall/syscall_linux_arm.go
+++ b/src/syscall/syscall_linux_arm.go
@@ -83,9 +83,7 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
//sysnb Getgid() (gid int) = SYS_GETGID32
//sysnb Getuid() (uid int) = SYS_GETUID32
//sysnb InotifyInit() (fd int, err error)
-//sys Lchown(path string, uid int, gid int) (err error) = SYS_LCHOWN32
//sys Listen(s int, n int) (err error)
-//sys Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = SYS_SENDFILE64
//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) = SYS__NEWSELECT
//sys Setfsgid(gid int) (err error) = SYS_SETFSGID32
@@ -96,7 +94,6 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
//sysnb Setreuid(ruid int, euid int) (err error) = SYS_SETREUID32
//sys Shutdown(fd int, how int) (err error)
//sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int, err error)
-//sys Stat(path string, stat *Stat_t) (err error) = SYS_STAT64
// Vsyscalls on amd64.
//sysnb Gettimeofday(tv *Timeval) (err error)
@@ -110,6 +107,18 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
//sys mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, err error)
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
+func Stat(path string, stat *Stat_t) (err error) {
+ return fstatat(_AT_FDCWD, path, stat, 0)
+}
+
+func Lchown(path string, uid int, gid int) (err error) {
+ return Fchownat(_AT_FDCWD, path, uid, gid, _AT_SYMLINK_NOFOLLOW)
+}
+
+func Lstat(path string, stat *Stat_t) (err error) {
+ return fstatat(_AT_FDCWD, path, stat, _AT_SYMLINK_NOFOLLOW)
+}
+
func Fstatfs(fd int, buf *Statfs_t) (err error) {
_, _, e := Syscall(SYS_FSTATFS64, uintptr(fd), unsafe.Sizeof(*buf), uintptr(unsafe.Pointer(buf)))
if e != 0 {
diff --git a/src/syscall/syscall_linux_test.go b/src/syscall/syscall_linux_test.go
index 1fd70b07e3..293549a841 100644
--- a/src/syscall/syscall_linux_test.go
+++ b/src/syscall/syscall_linux_test.go
@@ -19,6 +19,7 @@ import (
"syscall"
"testing"
"time"
+ "unsafe"
)
// chtmpdir changes the working directory to a new temporary directory and
@@ -294,7 +295,7 @@ func TestSyscallNoError(t *testing.T) {
// On Linux there are currently no syscalls which don't fail and return
// a value larger than 0xfffffffffffff001 so we could test RawSyscall
// vs. RawSyscallNoError on 64bit architectures.
- if runtime.GOARCH != "386" && runtime.GOARCH != "arm" {
+ if unsafe.Sizeof(uintptr(0)) != 4 {
t.Skip("skipping on non-32bit architecture")
}
diff --git a/src/syscall/zsyscall_linux_386.go b/src/syscall/zsyscall_linux_386.go
index 62827f16dc..0882494c47 100644
--- a/src/syscall/zsyscall_linux_386.go
+++ b/src/syscall/zsyscall_linux_386.go
@@ -1276,36 +1276,6 @@ func Iopl(level int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Lchown(path string, uid int, gid int) (err error) {
- var _p0 *byte
- _p0, err = BytePtrFromString(path)
- if err != nil {
- return
- }
- _, _, e1 := Syscall(SYS_LCHOWN32, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
-func Lstat(path string, stat *Stat_t) (err error) {
- var _p0 *byte
- _p0, err = BytePtrFromString(path)
- if err != nil {
- return
- }
- _, _, e1 := Syscall(SYS_LSTAT64, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
func Pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
@@ -1422,21 +1392,6 @@ func Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n i
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Stat(path string, stat *Stat_t) (err error) {
- var _p0 *byte
- _p0, err = BytePtrFromString(path)
- if err != nil {
- return
- }
- _, _, e1 := Syscall(SYS_STAT64, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
func SyncFileRange(fd int, off int64, n int64, flags int) (err error) {
_, _, e1 := Syscall6(SYS_SYNC_FILE_RANGE, uintptr(fd), uintptr(off), uintptr(off>>32), uintptr(n), uintptr(n>>32), uintptr(flags))
if e1 != 0 {
diff --git a/src/syscall/zsyscall_linux_amd64.go b/src/syscall/zsyscall_linux_amd64.go
index b6638269be..9f2046bf93 100644
--- a/src/syscall/zsyscall_linux_amd64.go
+++ b/src/syscall/zsyscall_linux_amd64.go
@@ -1261,21 +1261,6 @@ func Iopl(level int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Lchown(path string, uid int, gid int) (err error) {
- var _p0 *byte
- _p0, err = BytePtrFromString(path)
- if err != nil {
- return
- }
- _, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
func Listen(s int, n int) (err error) {
_, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(n), 0)
if e1 != 0 {
@@ -1286,21 +1271,6 @@ func Listen(s int, n int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Lstat(path string, stat *Stat_t) (err error) {
- var _p0 *byte
- _p0, err = BytePtrFromString(path)
- if err != nil {
- return
- }
- _, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
func Pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
diff --git a/src/syscall/zsyscall_linux_arm.go b/src/syscall/zsyscall_linux_arm.go
index bb20d6e946..3d099aa16d 100644
--- a/src/syscall/zsyscall_linux_arm.go
+++ b/src/syscall/zsyscall_linux_arm.go
@@ -1415,21 +1415,6 @@ func InotifyInit() (fd int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Lchown(path string, uid int, gid int) (err error) {
- var _p0 *byte
- _p0, err = BytePtrFromString(path)
- if err != nil {
- return
- }
- _, _, e1 := Syscall(SYS_LCHOWN32, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
func Listen(s int, n int) (err error) {
_, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(n), 0)
if e1 != 0 {
@@ -1440,21 +1425,6 @@ func Listen(s int, n int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Lstat(path string, stat *Stat_t) (err error) {
- var _p0 *byte
- _p0, err = BytePtrFromString(path)
- if err != nil {
- return
- }
- _, _, e1 := Syscall(SYS_LSTAT64, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
r0, _, e1 := Syscall6(SYS_SENDFILE64, uintptr(outfd), uintptr(infd), uintptr(unsafe.Pointer(offset)), uintptr(count), 0, 0)
written = int(r0)
@@ -1558,21 +1528,6 @@ func Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n i
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Stat(path string, stat *Stat_t) (err error) {
- var _p0 *byte
- _p0, err = BytePtrFromString(path)
- if err != nil {
- return
- }
- _, _, e1 := Syscall(SYS_STAT64, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
func Gettimeofday(tv *Timeval) (err error) {
_, _, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0)
if e1 != 0 {
diff --git a/src/testdata/Isaac.Newton-Opticks.txt b/src/testdata/Isaac.Newton-Opticks.txt
new file mode 100644
index 0000000000..15bb4c54d0
--- /dev/null
+++ b/src/testdata/Isaac.Newton-Opticks.txt
@@ -0,0 +1,9286 @@
+Produced by Suzanne Lybarger, steve harris, Josephine
+Paolucci and the Online Distributed Proofreading Team at
+http://www.pgdp.net.
+
+
+
+
+
+
+OPTICKS:
+
+OR, A
+
+TREATISE
+
+OF THE
+
+_Reflections_, _Refractions_,
+_Inflections_ and _Colours_
+
+OF
+
+LIGHT.
+
+_The_ FOURTH EDITION, _corrected_.
+
+By Sir _ISAAC NEWTON_, Knt.
+
+LONDON:
+
+Printed for WILLIAM INNYS at the West-End of St. _Paul's_. MDCCXXX.
+
+TITLE PAGE OF THE 1730 EDITION
+
+
+
+
+SIR ISAAC NEWTON'S ADVERTISEMENTS
+
+
+
+
+Advertisement I
+
+
+_Part of the ensuing Discourse about Light was written at the Desire of
+some Gentlemen of the_ Royal-Society, _in the Year 1675, and then sent
+to their Secretary, and read at their Meetings, and the rest was added
+about twelve Years after to complete the Theory; except the third Book,
+and the last Proposition of the Second, which were since put together
+out of scatter'd Papers. To avoid being engaged in Disputes about these
+Matters, I have hitherto delayed the printing, and should still have
+delayed it, had not the Importunity of Friends prevailed upon me. If any
+other Papers writ on this Subject are got out of my Hands they are
+imperfect, and were perhaps written before I had tried all the
+Experiments here set down, and fully satisfied my self about the Laws of
+Refractions and Composition of Colours. I have here publish'd what I
+think proper to come abroad, wishing that it may not be translated into
+another Language without my Consent._
+
+_The Crowns of Colours, which sometimes appear about the Sun and Moon, I
+have endeavoured to give an Account of; but for want of sufficient
+Observations leave that Matter to be farther examined. The Subject of
+the Third Book I have also left imperfect, not having tried all the
+Experiments which I intended when I was about these Matters, nor
+repeated some of those which I did try, until I had satisfied my self
+about all their Circumstances. To communicate what I have tried, and
+leave the rest to others for farther Enquiry, is all my Design in
+publishing these Papers._
+
+_In a Letter written to Mr._ Leibnitz _in the year 1679, and published
+by Dr._ Wallis, _I mention'd a Method by which I had found some general
+Theorems about squaring Curvilinear Figures, or comparing them with the
+Conic Sections, or other the simplest Figures with which they may be
+compared. And some Years ago I lent out a Manuscript containing such
+Theorems, and having since met with some Things copied out of it, I have
+on this Occasion made it publick, prefixing to it an_ Introduction, _and
+subjoining a_ Scholium _concerning that Method. And I have joined with
+it another small Tract concerning the Curvilinear Figures of the Second
+Kind, which was also written many Years ago, and made known to some
+Friends, who have solicited the making it publick._
+
+ _I. N._
+
+April 1, 1704.
+
+
+Advertisement II
+
+_In this Second Edition of these Opticks I have omitted the Mathematical
+Tracts publish'd at the End of the former Edition, as not belonging to
+the Subject. And at the End of the Third Book I have added some
+Questions. And to shew that I do not take Gravity for an essential
+Property of Bodies, I have added one Question concerning its Cause,
+chusing to propose it by way of a Question, because I am not yet
+satisfied about it for want of Experiments._
+
+ _I. N._
+
+July 16, 1717.
+
+
+Advertisement to this Fourth Edition
+
+_This new Edition of Sir_ Isaac Newton's Opticks _is carefully printed
+from the Third Edition, as it was corrected by the Author's own Hand,
+and left before his Death with the Bookseller. Since Sir_ Isaac's
+Lectiones Opticæ, _which he publickly read in the University of_
+Cambridge _in the Years 1669, 1670, and 1671, are lately printed, it has
+been thought proper to make at the bottom of the Pages several Citations
+from thence, where may be found the Demonstrations, which the Author
+omitted in these_ Opticks.
+
+ * * * * *
+
+Transcriber's Note: There are several greek letters used in the
+descriptions of the illustrations. They are signified by [Greek:
+letter]. Square roots are noted by the letters sqrt before the equation.
+
+ * * * * *
+
+THE FIRST BOOK OF OPTICKS
+
+
+
+
+_PART I._
+
+
+My Design in this Book is not to explain the Properties of Light by
+Hypotheses, but to propose and prove them by Reason and Experiments: In
+order to which I shall premise the following Definitions and Axioms.
+
+
+
+
+_DEFINITIONS_
+
+
+DEFIN. I.
+
+_By the Rays of Light I understand its least Parts, and those as well
+Successive in the same Lines, as Contemporary in several Lines._ For it
+is manifest that Light consists of Parts, both Successive and
+Contemporary; because in the same place you may stop that which comes
+one moment, and let pass that which comes presently after; and in the
+same time you may stop it in any one place, and let it pass in any
+other. For that part of Light which is stopp'd cannot be the same with
+that which is let pass. The least Light or part of Light, which may be
+stopp'd alone without the rest of the Light, or propagated alone, or do
+or suffer any thing alone, which the rest of the Light doth not or
+suffers not, I call a Ray of Light.
+
+
+DEFIN. II.
+
+_Refrangibility of the Rays of Light, is their Disposition to be
+refracted or turned out of their Way in passing out of one transparent
+Body or Medium into another. And a greater or less Refrangibility of
+Rays, is their Disposition to be turned more or less out of their Way in
+like Incidences on the same Medium._ Mathematicians usually consider the
+Rays of Light to be Lines reaching from the luminous Body to the Body
+illuminated, and the refraction of those Rays to be the bending or
+breaking of those lines in their passing out of one Medium into another.
+And thus may Rays and Refractions be considered, if Light be propagated
+in an instant. But by an Argument taken from the Æquations of the times
+of the Eclipses of _Jupiter's Satellites_, it seems that Light is
+propagated in time, spending in its passage from the Sun to us about
+seven Minutes of time: And therefore I have chosen to define Rays and
+Refractions in such general terms as may agree to Light in both cases.
+
+
+DEFIN. III.
+
+_Reflexibility of Rays, is their Disposition to be reflected or turned
+back into the same Medium from any other Medium upon whose Surface they
+fall. And Rays are more or less reflexible, which are turned back more
+or less easily._ As if Light pass out of a Glass into Air, and by being
+inclined more and more to the common Surface of the Glass and Air,
+begins at length to be totally reflected by that Surface; those sorts of
+Rays which at like Incidences are reflected most copiously, or by
+inclining the Rays begin soonest to be totally reflected, are most
+reflexible.
+
+
+DEFIN. IV.
+
+_The Angle of Incidence is that Angle, which the Line described by the
+incident Ray contains with the Perpendicular to the reflecting or
+refracting Surface at the Point of Incidence._
+
+
+DEFIN. V.
+
+_The Angle of Reflexion or Refraction, is the Angle which the line
+described by the reflected or refracted Ray containeth with the
+Perpendicular to the reflecting or refracting Surface at the Point of
+Incidence._
+
+
+DEFIN. VI.
+
+_The Sines of Incidence, Reflexion, and Refraction, are the Sines of the
+Angles of Incidence, Reflexion, and Refraction._
+
+
+DEFIN. VII
+
+_The Light whose Rays are all alike Refrangible, I call Simple,
+Homogeneal and Similar; and that whose Rays are some more Refrangible
+than others, I call Compound, Heterogeneal and Dissimilar._ The former
+Light I call Homogeneal, not because I would affirm it so in all
+respects, but because the Rays which agree in Refrangibility, agree at
+least in all those their other Properties which I consider in the
+following Discourse.
+
+
+DEFIN. VIII.
+
+_The Colours of Homogeneal Lights, I call Primary, Homogeneal and
+Simple; and those of Heterogeneal Lights, Heterogeneal and Compound._
+For these are always compounded of the colours of Homogeneal Lights; as
+will appear in the following Discourse.
+
+
+
+
+_AXIOMS._
+
+
+AX. I.
+
+_The Angles of Reflexion and Refraction, lie in one and the same Plane
+with the Angle of Incidence._
+
+
+AX. II.
+
+_The Angle of Reflexion is equal to the Angle of Incidence._
+
+
+AX. III.
+
+_If the refracted Ray be returned directly back to the Point of
+Incidence, it shall be refracted into the Line before described by the
+incident Ray._
+
+
+AX. IV.
+
+_Refraction out of the rarer Medium into the denser, is made towards the
+Perpendicular; that is, so that the Angle of Refraction be less than the
+Angle of Incidence._
+
+
+AX. V.
+
+_The Sine of Incidence is either accurately or very nearly in a given
+Ratio to the Sine of Refraction._
+
+Whence if that Proportion be known in any one Inclination of the
+incident Ray, 'tis known in all the Inclinations, and thereby the
+Refraction in all cases of Incidence on the same refracting Body may be
+determined. Thus if the Refraction be made out of Air into Water, the
+Sine of Incidence of the red Light is to the Sine of its Refraction as 4
+to 3. If out of Air into Glass, the Sines are as 17 to 11. In Light of
+other Colours the Sines have other Proportions: but the difference is so
+little that it need seldom be considered.
+
+[Illustration: FIG. 1]
+
+Suppose therefore, that RS [in _Fig._ 1.] represents the Surface of
+stagnating Water, and that C is the point of Incidence in which any Ray
+coming in the Air from A in the Line AC is reflected or refracted, and I
+would know whither this Ray shall go after Reflexion or Refraction: I
+erect upon the Surface of the Water from the point of Incidence the
+Perpendicular CP and produce it downwards to Q, and conclude by the
+first Axiom, that the Ray after Reflexion and Refraction, shall be
+found somewhere in the Plane of the Angle of Incidence ACP produced. I
+let fall therefore upon the Perpendicular CP the Sine of Incidence AD;
+and if the reflected Ray be desired, I produce AD to B so that DB be
+equal to AD, and draw CB. For this Line CB shall be the reflected Ray;
+the Angle of Reflexion BCP and its Sine BD being equal to the Angle and
+Sine of Incidence, as they ought to be by the second Axiom, But if the
+refracted Ray be desired, I produce AD to H, so that DH may be to AD as
+the Sine of Refraction to the Sine of Incidence, that is, (if the Light
+be red) as 3 to 4; and about the Center C and in the Plane ACP with the
+Radius CA describing a Circle ABE, I draw a parallel to the
+Perpendicular CPQ, the Line HE cutting the Circumference in E, and
+joining CE, this Line CE shall be the Line of the refracted Ray. For if
+EF be let fall perpendicularly on the Line PQ, this Line EF shall be the
+Sine of Refraction of the Ray CE, the Angle of Refraction being ECQ; and
+this Sine EF is equal to DH, and consequently in Proportion to the Sine
+of Incidence AD as 3 to 4.
+
+In like manner, if there be a Prism of Glass (that is, a Glass bounded
+with two Equal and Parallel Triangular ends, and three plain and well
+polished Sides, which meet in three Parallel Lines running from the
+three Angles of one end to the three Angles of the other end) and if the
+Refraction of the Light in passing cross this Prism be desired: Let ACB
+[in _Fig._ 2.] represent a Plane cutting this Prism transversly to its
+three Parallel lines or edges there where the Light passeth through it,
+and let DE be the Ray incident upon the first side of the Prism AC where
+the Light goes into the Glass; and by putting the Proportion of the Sine
+of Incidence to the Sine of Refraction as 17 to 11 find EF the first
+refracted Ray. Then taking this Ray for the Incident Ray upon the second
+side of the Glass BC where the Light goes out, find the next refracted
+Ray FG by putting the Proportion of the Sine of Incidence to the Sine of
+Refraction as 11 to 17. For if the Sine of Incidence out of Air into
+Glass be to the Sine of Refraction as 17 to 11, the Sine of Incidence
+out of Glass into Air must on the contrary be to the Sine of Refraction
+as 11 to 17, by the third Axiom.
+
+[Illustration: FIG. 2.]
+
+Much after the same manner, if ACBD [in _Fig._ 3.] represent a Glass
+spherically convex on both sides (usually called a _Lens_, such as is a
+Burning-glass, or Spectacle-glass, or an Object-glass of a Telescope)
+and it be required to know how Light falling upon it from any lucid
+point Q shall be refracted, let QM represent a Ray falling upon any
+point M of its first spherical Surface ACB, and by erecting a
+Perpendicular to the Glass at the point M, find the first refracted Ray
+MN by the Proportion of the Sines 17 to 11. Let that Ray in going out of
+the Glass be incident upon N, and then find the second refracted Ray
+N_q_ by the Proportion of the Sines 11 to 17. And after the same manner
+may the Refraction be found when the Lens is convex on one side and
+plane or concave on the other, or concave on both sides.
+
+[Illustration: FIG. 3.]
+
+
+AX. VI.
+
+_Homogeneal Rays which flow from several Points of any Object, and fall
+perpendicularly or almost perpendicularly on any reflecting or
+refracting Plane or spherical Surface, shall afterwards diverge from so
+many other Points, or be parallel to so many other Lines, or converge to
+so many other Points, either accurately or without any sensible Error.
+And the same thing will happen, if the Rays be reflected or refracted
+successively by two or three or more Plane or Spherical Surfaces._
+
+The Point from which Rays diverge or to which they converge may be
+called their _Focus_. And the Focus of the incident Rays being given,
+that of the reflected or refracted ones may be found by finding the
+Refraction of any two Rays, as above; or more readily thus.
+
+_Cas._ 1. Let ACB [in _Fig._ 4.] be a reflecting or refracting Plane,
+and Q the Focus of the incident Rays, and Q_q_C a Perpendicular to that
+Plane. And if this Perpendicular be produced to _q_, so that _q_C be
+equal to QC, the Point _q_ shall be the Focus of the reflected Rays: Or
+if _q_C be taken on the same side of the Plane with QC, and in
+proportion to QC as the Sine of Incidence to the Sine of Refraction, the
+Point _q_ shall be the Focus of the refracted Rays.
+
+[Illustration: FIG. 4.]
+
+_Cas._ 2. Let ACB [in _Fig._ 5.] be the reflecting Surface of any Sphere
+whose Centre is E. Bisect any Radius thereof, (suppose EC) in T, and if
+in that Radius on the same side the Point T you take the Points Q and
+_q_, so that TQ, TE, and T_q_, be continual Proportionals, and the Point
+Q be the Focus of the incident Rays, the Point _q_ shall be the Focus of
+the reflected ones.
+
+[Illustration: FIG. 5.]
+
+_Cas._ 3. Let ACB [in _Fig._ 6.] be the refracting Surface of any Sphere
+whose Centre is E. In any Radius thereof EC produced both ways take ET
+and C_t_ equal to one another and severally in such Proportion to that
+Radius as the lesser of the Sines of Incidence and Refraction hath to
+the difference of those Sines. And then if in the same Line you find any
+two Points Q and _q_, so that TQ be to ET as E_t_ to _tq_, taking _tq_
+the contrary way from _t_ which TQ lieth from T, and if the Point Q be
+the Focus of any incident Rays, the Point _q_ shall be the Focus of the
+refracted ones.
+
+[Illustration: FIG. 6.]
+
+And by the same means the Focus of the Rays after two or more Reflexions
+or Refractions may be found.
+
+[Illustration: FIG. 7.]
+
+_Cas._ 4. Let ACBD [in _Fig._ 7.] be any refracting Lens, spherically
+Convex or Concave or Plane on either side, and let CD be its Axis (that
+is, the Line which cuts both its Surfaces perpendicularly, and passes
+through the Centres of the Spheres,) and in this Axis produced let F and
+_f_ be the Foci of the refracted Rays found as above, when the incident
+Rays on both sides the Lens are parallel to the same Axis; and upon the
+Diameter F_f_ bisected in E, describe a Circle. Suppose now that any
+Point Q be the Focus of any incident Rays. Draw QE cutting the said
+Circle in T and _t_, and therein take _tq_ in such proportion to _t_E as
+_t_E or TE hath to TQ. Let _tq_ lie the contrary way from _t_ which TQ
+doth from T, and _q_ shall be the Focus of the refracted Rays without
+any sensible Error, provided the Point Q be not so remote from the Axis,
+nor the Lens so broad as to make any of the Rays fall too obliquely on
+the refracting Surfaces.[A]
+
+And by the like Operations may the reflecting or refracting Surfaces be
+found when the two Foci are given, and thereby a Lens be formed, which
+shall make the Rays flow towards or from what Place you please.[B]
+
+So then the Meaning of this Axiom is, that if Rays fall upon any Plane
+or Spherical Surface or Lens, and before their Incidence flow from or
+towards any Point Q, they shall after Reflexion or Refraction flow from
+or towards the Point _q_ found by the foregoing Rules. And if the
+incident Rays flow from or towards several points Q, the reflected or
+refracted Rays shall flow from or towards so many other Points _q_
+found by the same Rules. Whether the reflected and refracted Rays flow
+from or towards the Point _q_ is easily known by the situation of that
+Point. For if that Point be on the same side of the reflecting or
+refracting Surface or Lens with the Point Q, and the incident Rays flow
+from the Point Q, the reflected flow towards the Point _q_ and the
+refracted from it; and if the incident Rays flow towards Q, the
+reflected flow from _q_, and the refracted towards it. And the contrary
+happens when _q_ is on the other side of the Surface.
+
+
+AX. VII.
+
+_Wherever the Rays which come from all the Points of any Object meet
+again in so many Points after they have been made to converge by
+Reflection or Refraction, there they will make a Picture of the Object
+upon any white Body on which they fall._
+
+So if PR [in _Fig._ 3.] represent any Object without Doors, and AB be a
+Lens placed at a hole in the Window-shut of a dark Chamber, whereby the
+Rays that come from any Point Q of that Object are made to converge and
+meet again in the Point _q_; and if a Sheet of white Paper be held at
+_q_ for the Light there to fall upon it, the Picture of that Object PR
+will appear upon the Paper in its proper shape and Colours. For as the
+Light which comes from the Point Q goes to the Point _q_, so the Light
+which comes from other Points P and R of the Object, will go to so many
+other correspondent Points _p_ and _r_ (as is manifest by the sixth
+Axiom;) so that every Point of the Object shall illuminate a
+correspondent Point of the Picture, and thereby make a Picture like the
+Object in Shape and Colour, this only excepted, that the Picture shall
+be inverted. And this is the Reason of that vulgar Experiment of casting
+the Species of Objects from abroad upon a Wall or Sheet of white Paper
+in a dark Room.
+
+In like manner, when a Man views any Object PQR, [in _Fig._ 8.] the
+Light which comes from the several Points of the Object is so refracted
+by the transparent skins and humours of the Eye, (that is, by the
+outward coat EFG, called the _Tunica Cornea_, and by the crystalline
+humour AB which is beyond the Pupil _mk_) as to converge and meet again
+in so many Points in the bottom of the Eye, and there to paint the
+Picture of the Object upon that skin (called the _Tunica Retina_) with
+which the bottom of the Eye is covered. For Anatomists, when they have
+taken off from the bottom of the Eye that outward and most thick Coat
+called the _Dura Mater_, can then see through the thinner Coats, the
+Pictures of Objects lively painted thereon. And these Pictures,
+propagated by Motion along the Fibres of the Optick Nerves into the
+Brain, are the cause of Vision. For accordingly as these Pictures are
+perfect or imperfect, the Object is seen perfectly or imperfectly. If
+the Eye be tinged with any colour (as in the Disease of the _Jaundice_)
+so as to tinge the Pictures in the bottom of the Eye with that Colour,
+then all Objects appear tinged with the same Colour. If the Humours of
+the Eye by old Age decay, so as by shrinking to make the _Cornea_ and
+Coat of the _Crystalline Humour_ grow flatter than before, the Light
+will not be refracted enough, and for want of a sufficient Refraction
+will not converge to the bottom of the Eye but to some place beyond it,
+and by consequence paint in the bottom of the Eye a confused Picture,
+and according to the Indistinctness of this Picture the Object will
+appear confused. This is the reason of the decay of sight in old Men,
+and shews why their Sight is mended by Spectacles. For those Convex
+glasses supply the defect of plumpness in the Eye, and by increasing the
+Refraction make the Rays converge sooner, so as to convene distinctly at
+the bottom of the Eye if the Glass have a due degree of convexity. And
+the contrary happens in short-sighted Men whose Eyes are too plump. For
+the Refraction being now too great, the Rays converge and convene in the
+Eyes before they come at the bottom; and therefore the Picture made in
+the bottom and the Vision caused thereby will not be distinct, unless
+the Object be brought so near the Eye as that the place where the
+converging Rays convene may be removed to the bottom, or that the
+plumpness of the Eye be taken off and the Refractions diminished by a
+Concave-glass of a due degree of Concavity, or lastly that by Age the
+Eye grow flatter till it come to a due Figure: For short-sighted Men see
+remote Objects best in Old Age, and therefore they are accounted to have
+the most lasting Eyes.
+
+[Illustration: FIG. 8.]
+
+
+AX. VIII.
+
+_An Object seen by Reflexion or Refraction, appears in that place from
+whence the Rays after their last Reflexion or Refraction diverge in
+falling on the Spectator's Eye._
+
+[Illustration: FIG. 9.]
+
+If the Object A [in FIG. 9.] be seen by Reflexion of a Looking-glass
+_mn_, it shall appear, not in its proper place A, but behind the Glass
+at _a_, from whence any Rays AB, AC, AD, which flow from one and the
+same Point of the Object, do after their Reflexion made in the Points B,
+C, D, diverge in going from the Glass to E, F, G, where they are
+incident on the Spectator's Eyes. For these Rays do make the same
+Picture in the bottom of the Eyes as if they had come from the Object
+really placed at _a_ without the Interposition of the Looking-glass; and
+all Vision is made according to the place and shape of that Picture.
+
+In like manner the Object D [in FIG. 2.] seen through a Prism, appears
+not in its proper place D, but is thence translated to some other place
+_d_ situated in the last refracted Ray FG drawn backward from F to _d_.
+
+[Illustration: FIG. 10.]
+
+And so the Object Q [in FIG. 10.] seen through the Lens AB, appears at
+the place _q_ from whence the Rays diverge in passing from the Lens to
+the Eye. Now it is to be noted, that the Image of the Object at _q_ is
+so much bigger or lesser than the Object it self at Q, as the distance
+of the Image at _q_ from the Lens AB is bigger or less than the distance
+of the Object at Q from the same Lens. And if the Object be seen through
+two or more such Convex or Concave-glasses, every Glass shall make a new
+Image, and the Object shall appear in the place of the bigness of the
+last Image. Which consideration unfolds the Theory of Microscopes and
+Telescopes. For that Theory consists in almost nothing else than the
+describing such Glasses as shall make the last Image of any Object as
+distinct and large and luminous as it can conveniently be made.
+
+I have now given in Axioms and their Explications the sum of what hath
+hitherto been treated of in Opticks. For what hath been generally
+agreed on I content my self to assume under the notion of Principles, in
+order to what I have farther to write. And this may suffice for an
+Introduction to Readers of quick Wit and good Understanding not yet
+versed in Opticks: Although those who are already acquainted with this
+Science, and have handled Glasses, will more readily apprehend what
+followeth.
+
+FOOTNOTES:
+
+[A] In our Author's _Lectiones Opticæ_, Part I. Sect. IV. Prop 29, 30,
+there is an elegant Method of determining these _Foci_; not only in
+spherical Surfaces, but likewise in any other curved Figure whatever:
+And in Prop. 32, 33, the same thing is done for any Ray lying out of the
+Axis.
+
+[B] _Ibid._ Prop. 34.
+
+
+
+
+_PROPOSITIONS._
+
+
+
+_PROP._ I. THEOR. I.
+
+_Lights which differ in Colour, differ also in Degrees of
+Refrangibility._
+
+The PROOF by Experiments.
+
+_Exper._ 1.
+
+I took a black oblong stiff Paper terminated by Parallel Sides, and with
+a Perpendicular right Line drawn cross from one Side to the other,
+distinguished it into two equal Parts. One of these parts I painted with
+a red colour and the other with a blue. The Paper was very black, and
+the Colours intense and thickly laid on, that the Phænomenon might be
+more conspicuous. This Paper I view'd through a Prism of solid Glass,
+whose two Sides through which the Light passed to the Eye were plane and
+well polished, and contained an Angle of about sixty degrees; which
+Angle I call the refracting Angle of the Prism. And whilst I view'd it,
+I held it and the Prism before a Window in such manner that the Sides of
+the Paper were parallel to the Prism, and both those Sides and the Prism
+were parallel to the Horizon, and the cross Line was also parallel to
+it: and that the Light which fell from the Window upon the Paper made an
+Angle with the Paper, equal to that Angle which was made with the same
+Paper by the Light reflected from it to the Eye. Beyond the Prism was
+the Wall of the Chamber under the Window covered over with black Cloth,
+and the Cloth was involved in Darkness that no Light might be reflected
+from thence, which in passing by the Edges of the Paper to the Eye,
+might mingle itself with the Light of the Paper, and obscure the
+Phænomenon thereof. These things being thus ordered, I found that if the
+refracting Angle of the Prism be turned upwards, so that the Paper may
+seem to be lifted upwards by the Refraction, its blue half will be
+lifted higher by the Refraction than its red half. But if the refracting
+Angle of the Prism be turned downward, so that the Paper may seem to be
+carried lower by the Refraction, its blue half will be carried something
+lower thereby than its red half. Wherefore in both Cases the Light which
+comes from the blue half of the Paper through the Prism to the Eye, does
+in like Circumstances suffer a greater Refraction than the Light which
+comes from the red half, and by consequence is more refrangible.
+
+_Illustration._ In the eleventh Figure, MN represents the Window, and DE
+the Paper terminated with parallel Sides DJ and HE, and by the
+transverse Line FG distinguished into two halfs, the one DG of an
+intensely blue Colour, the other FE of an intensely red. And BAC_cab_
+represents the Prism whose refracting Planes AB_ba_ and AC_ca_ meet in
+the Edge of the refracting Angle A_a_. This Edge A_a_ being upward, is
+parallel both to the Horizon, and to the Parallel-Edges of the Paper DJ
+and HE, and the transverse Line FG is perpendicular to the Plane of the
+Window. And _de_ represents the Image of the Paper seen by Refraction
+upwards in such manner, that the blue half DG is carried higher to _dg_
+than the red half FE is to _fe_, and therefore suffers a greater
+Refraction. If the Edge of the refracting Angle be turned downward, the
+Image of the Paper will be refracted downward; suppose to [Greek: de],
+and the blue half will be refracted lower to [Greek: dg] than the red
+half is to [Greek: pe].
+
+[Illustration: FIG. 11.]
+
+_Exper._ 2. About the aforesaid Paper, whose two halfs were painted over
+with red and blue, and which was stiff like thin Pasteboard, I lapped
+several times a slender Thred of very black Silk, in such manner that
+the several parts of the Thred might appear upon the Colours like so
+many black Lines drawn over them, or like long and slender dark Shadows
+cast upon them. I might have drawn black Lines with a Pen, but the
+Threds were smaller and better defined. This Paper thus coloured and
+lined I set against a Wall perpendicularly to the Horizon, so that one
+of the Colours might stand to the Right Hand, and the other to the Left.
+Close before the Paper, at the Confine of the Colours below, I placed a
+Candle to illuminate the Paper strongly: For the Experiment was tried in
+the Night. The Flame of the Candle reached up to the lower edge of the
+Paper, or a very little higher. Then at the distance of six Feet, and
+one or two Inches from the Paper upon the Floor I erected a Glass Lens
+four Inches and a quarter broad, which might collect the Rays coming
+from the several Points of the Paper, and make them converge towards so
+many other Points at the same distance of six Feet, and one or two
+Inches on the other side of the Lens, and so form the Image of the
+coloured Paper upon a white Paper placed there, after the same manner
+that a Lens at a Hole in a Window casts the Images of Objects abroad
+upon a Sheet of white Paper in a dark Room. The aforesaid white Paper,
+erected perpendicular to the Horizon, and to the Rays which fell upon it
+from the Lens, I moved sometimes towards the Lens, sometimes from it, to
+find the Places where the Images of the blue and red Parts of the
+coloured Paper appeared most distinct. Those Places I easily knew by the
+Images of the black Lines which I had made by winding the Silk about the
+Paper. For the Images of those fine and slender Lines (which by reason
+of their Blackness were like Shadows on the Colours) were confused and
+scarce visible, unless when the Colours on either side of each Line were
+terminated most distinctly, Noting therefore, as diligently as I could,
+the Places where the Images of the red and blue halfs of the coloured
+Paper appeared most distinct, I found that where the red half of the
+Paper appeared distinct, the blue half appeared confused, so that the
+black Lines drawn upon it could scarce be seen; and on the contrary,
+where the blue half appeared most distinct, the red half appeared
+confused, so that the black Lines upon it were scarce visible. And
+between the two Places where these Images appeared distinct there was
+the distance of an Inch and a half; the distance of the white Paper from
+the Lens, when the Image of the red half of the coloured Paper appeared
+most distinct, being greater by an Inch and an half than the distance of
+the same white Paper from the Lens, when the Image of the blue half
+appeared most distinct. In like Incidences therefore of the blue and red
+upon the Lens, the blue was refracted more by the Lens than the red, so
+as to converge sooner by an Inch and a half, and therefore is more
+refrangible.
+
+_Illustration._ In the twelfth Figure (p. 27), DE signifies the coloured
+Paper, DG the blue half, FE the red half, MN the Lens, HJ the white
+Paper in that Place where the red half with its black Lines appeared
+distinct, and _hi_ the same Paper in that Place where the blue half
+appeared distinct. The Place _hi_ was nearer to the Lens MN than the
+Place HJ by an Inch and an half.
+
+_Scholium._ The same Things succeed, notwithstanding that some of the
+Circumstances be varied; as in the first Experiment when the Prism and
+Paper are any ways inclined to the Horizon, and in both when coloured
+Lines are drawn upon very black Paper. But in the Description of these
+Experiments, I have set down such Circumstances, by which either the
+Phænomenon might be render'd more conspicuous, or a Novice might more
+easily try them, or by which I did try them only. The same Thing, I have
+often done in the following Experiments: Concerning all which, this one
+Admonition may suffice. Now from these Experiments it follows not, that
+all the Light of the blue is more refrangible than all the Light of the
+red: For both Lights are mixed of Rays differently refrangible, so that
+in the red there are some Rays not less refrangible than those of the
+blue, and in the blue there are some Rays not more refrangible than
+those of the red: But these Rays, in proportion to the whole Light, are
+but few, and serve to diminish the Event of the Experiment, but are not
+able to destroy it. For, if the red and blue Colours were more dilute
+and weak, the distance of the Images would be less than an Inch and a
+half; and if they were more intense and full, that distance would be
+greater, as will appear hereafter. These Experiments may suffice for the
+Colours of Natural Bodies. For in the Colours made by the Refraction of
+Prisms, this Proposition will appear by the Experiments which are now to
+follow in the next Proposition.
+
+
+_PROP._ II. THEOR. II.
+
+_The Light of the Sun consists of Rays differently Refrangible._
+
+The PROOF by Experiments.
+
+[Illustration: FIG. 12.]
+
+[Illustration: FIG. 13.]
+
+_Exper._ 3.
+
+In a very dark Chamber, at a round Hole, about one third Part of an Inch
+broad, made in the Shut of a Window, I placed a Glass Prism, whereby the
+Beam of the Sun's Light, which came in at that Hole, might be refracted
+upwards toward the opposite Wall of the Chamber, and there form a
+colour'd Image of the Sun. The Axis of the Prism (that is, the Line
+passing through the middle of the Prism from one end of it to the other
+end parallel to the edge of the Refracting Angle) was in this and the
+following Experiments perpendicular to the incident Rays. About this
+Axis I turned the Prism slowly, and saw the refracted Light on the Wall,
+or coloured Image of the Sun, first to descend, and then to ascend.
+Between the Descent and Ascent, when the Image seemed Stationary, I
+stopp'd the Prism, and fix'd it in that Posture, that it should be moved
+no more. For in that Posture the Refractions of the Light at the two
+Sides of the refracting Angle, that is, at the Entrance of the Rays into
+the Prism, and at their going out of it, were equal to one another.[C]
+So also in other Experiments, as often as I would have the Refractions
+on both sides the Prism to be equal to one another, I noted the Place
+where the Image of the Sun formed by the refracted Light stood still
+between its two contrary Motions, in the common Period of its Progress
+and Regress; and when the Image fell upon that Place, I made fast the
+Prism. And in this Posture, as the most convenient, it is to be
+understood that all the Prisms are placed in the following Experiments,
+unless where some other Posture is described. The Prism therefore being
+placed in this Posture, I let the refracted Light fall perpendicularly
+upon a Sheet of white Paper at the opposite Wall of the Chamber, and
+observed the Figure and Dimensions of the Solar Image formed on the
+Paper by that Light. This Image was Oblong and not Oval, but terminated
+with two Rectilinear and Parallel Sides, and two Semicircular Ends. On
+its Sides it was bounded pretty distinctly, but on its Ends very
+confusedly and indistinctly, the Light there decaying and vanishing by
+degrees. The Breadth of this Image answered to the Sun's Diameter, and
+was about two Inches and the eighth Part of an Inch, including the
+Penumbra. For the Image was eighteen Feet and an half distant from the
+Prism, and at this distance that Breadth, if diminished by the Diameter
+of the Hole in the Window-shut, that is by a quarter of an Inch,
+subtended an Angle at the Prism of about half a Degree, which is the
+Sun's apparent Diameter. But the Length of the Image was about ten
+Inches and a quarter, and the Length of the Rectilinear Sides about
+eight Inches; and the refracting Angle of the Prism, whereby so great a
+Length was made, was 64 degrees. With a less Angle the Length of the
+Image was less, the Breadth remaining the same. If the Prism was turned
+about its Axis that way which made the Rays emerge more obliquely out of
+the second refracting Surface of the Prism, the Image soon became an
+Inch or two longer, or more; and if the Prism was turned about the
+contrary way, so as to make the Rays fall more obliquely on the first
+refracting Surface, the Image soon became an Inch or two shorter. And
+therefore in trying this Experiment, I was as curious as I could be in
+placing the Prism by the above-mention'd Rule exactly in such a Posture,
+that the Refractions of the Rays at their Emergence out of the Prism
+might be equal to that at their Incidence on it. This Prism had some
+Veins running along within the Glass from one end to the other, which
+scattered some of the Sun's Light irregularly, but had no sensible
+Effect in increasing the Length of the coloured Spectrum. For I tried
+the same Experiment with other Prisms with the same Success. And
+particularly with a Prism which seemed free from such Veins, and whose
+refracting Angle was 62-1/2 Degrees, I found the Length of the Image
+9-3/4 or 10 Inches at the distance of 18-1/2 Feet from the Prism, the
+Breadth of the Hole in the Window-shut being 1/4 of an Inch, as before.
+And because it is easy to commit a Mistake in placing the Prism in its
+due Posture, I repeated the Experiment four or five Times, and always
+found the Length of the Image that which is set down above. With another
+Prism of clearer Glass and better Polish, which seemed free from Veins,
+and whose refracting Angle was 63-1/2 Degrees, the Length of this Image
+at the same distance of 18-1/2 Feet was also about 10 Inches, or 10-1/8.
+Beyond these Measures for about a 1/4 or 1/3 of an Inch at either end of
+the Spectrum the Light of the Clouds seemed to be a little tinged with
+red and violet, but so very faintly, that I suspected that Tincture
+might either wholly, or in great Measure arise from some Rays of the
+Spectrum scattered irregularly by some Inequalities in the Substance and
+Polish of the Glass, and therefore I did not include it in these
+Measures. Now the different Magnitude of the hole in the Window-shut,
+and different thickness of the Prism where the Rays passed through it,
+and different inclinations of the Prism to the Horizon, made no sensible
+changes in the length of the Image. Neither did the different matter of
+the Prisms make any: for in a Vessel made of polished Plates of Glass
+cemented together in the shape of a Prism and filled with Water, there
+is the like Success of the Experiment according to the quantity of the
+Refraction. It is farther to be observed, that the Rays went on in right
+Lines from the Prism to the Image, and therefore at their very going out
+of the Prism had all that Inclination to one another from which the
+length of the Image proceeded, that is, the Inclination of more than two
+degrees and an half. And yet according to the Laws of Opticks vulgarly
+received, they could not possibly be so much inclined to one another.[D]
+For let EG [_Fig._ 13. (p. 27)] represent the Window-shut, F the hole
+made therein through which a beam of the Sun's Light was transmitted
+into the darkened Chamber, and ABC a Triangular Imaginary Plane whereby
+the Prism is feigned to be cut transversely through the middle of the
+Light. Or if you please, let ABC represent the Prism it self, looking
+directly towards the Spectator's Eye with its nearer end: And let XY be
+the Sun, MN the Paper upon which the Solar Image or Spectrum is cast,
+and PT the Image it self whose sides towards _v_ and _w_ are Rectilinear
+and Parallel, and ends towards P and T Semicircular. YKHP and XLJT are
+two Rays, the first of which comes from the lower part of the Sun to the
+higher part of the Image, and is refracted in the Prism at K and H, and
+the latter comes from the higher part of the Sun to the lower part of
+the Image, and is refracted at L and J. Since the Refractions on both
+sides the Prism are equal to one another, that is, the Refraction at K
+equal to the Refraction at J, and the Refraction at L equal to the
+Refraction at H, so that the Refractions of the incident Rays at K and L
+taken together, are equal to the Refractions of the emergent Rays at H
+and J taken together: it follows by adding equal things to equal things,
+that the Refractions at K and H taken together, are equal to the
+Refractions at J and L taken together, and therefore the two Rays being
+equally refracted, have the same Inclination to one another after
+Refraction which they had before; that is, the Inclination of half a
+Degree answering to the Sun's Diameter. For so great was the inclination
+of the Rays to one another before Refraction. So then, the length of the
+Image PT would by the Rules of Vulgar Opticks subtend an Angle of half a
+Degree at the Prism, and by Consequence be equal to the breadth _vw_;
+and therefore the Image would be round. Thus it would be were the two
+Rays XLJT and YKHP, and all the rest which form the Image P_w_T_v_,
+alike refrangible. And therefore seeing by Experience it is found that
+the Image is not round, but about five times longer than broad, the Rays
+which going to the upper end P of the Image suffer the greatest
+Refraction, must be more refrangible than those which go to the lower
+end T, unless the Inequality of Refraction be casual.
+
+This Image or Spectrum PT was coloured, being red at its least refracted
+end T, and violet at its most refracted end P, and yellow green and
+blue in the intermediate Spaces. Which agrees with the first
+Proposition, that Lights which differ in Colour, do also differ in
+Refrangibility. The length of the Image in the foregoing Experiments, I
+measured from the faintest and outmost red at one end, to the faintest
+and outmost blue at the other end, excepting only a little Penumbra,
+whose breadth scarce exceeded a quarter of an Inch, as was said above.
+
+_Exper._ 4. In the Sun's Beam which was propagated into the Room through
+the hole in the Window-shut, at the distance of some Feet from the hole,
+I held the Prism in such a Posture, that its Axis might be perpendicular
+to that Beam. Then I looked through the Prism upon the hole, and turning
+the Prism to and fro about its Axis, to make the Image of the Hole
+ascend and descend, when between its two contrary Motions it seemed
+Stationary, I stopp'd the Prism, that the Refractions of both sides of
+the refracting Angle might be equal to each other, as in the former
+Experiment. In this situation of the Prism viewing through it the said
+Hole, I observed the length of its refracted Image to be many times
+greater than its breadth, and that the most refracted part thereof
+appeared violet, the least refracted red, the middle parts blue, green
+and yellow in order. The same thing happen'd when I removed the Prism
+out of the Sun's Light, and looked through it upon the hole shining by
+the Light of the Clouds beyond it. And yet if the Refraction were done
+regularly according to one certain Proportion of the Sines of Incidence
+and Refraction as is vulgarly supposed, the refracted Image ought to
+have appeared round.
+
+So then, by these two Experiments it appears, that in Equal Incidences
+there is a considerable inequality of Refractions. But whence this
+inequality arises, whether it be that some of the incident Rays are
+refracted more, and others less, constantly, or by chance, or that one
+and the same Ray is by Refraction disturbed, shatter'd, dilated, and as
+it were split and spread into many diverging Rays, as _Grimaldo_
+supposes, does not yet appear by these Experiments, but will appear by
+those that follow.
+
+_Exper._ 5. Considering therefore, that if in the third Experiment the
+Image of the Sun should be drawn out into an oblong Form, either by a
+Dilatation of every Ray, or by any other casual inequality of the
+Refractions, the same oblong Image would by a second Refraction made
+sideways be drawn out as much in breadth by the like Dilatation of the
+Rays, or other casual inequality of the Refractions sideways, I tried
+what would be the Effects of such a second Refraction. For this end I
+ordered all things as in the third Experiment, and then placed a second
+Prism immediately after the first in a cross Position to it, that it
+might again refract the beam of the Sun's Light which came to it through
+the first Prism. In the first Prism this beam was refracted upwards, and
+in the second sideways. And I found that by the Refraction of the second
+Prism, the breadth of the Image was not increased, but its superior
+part, which in the first Prism suffered the greater Refraction, and
+appeared violet and blue, did again in the second Prism suffer a greater
+Refraction than its inferior part, which appeared red and yellow, and
+this without any Dilatation of the Image in breadth.
+
+[Illustration: FIG. 14]
+
+_Illustration._ Let S [_Fig._ 14, 15.] represent the Sun, F the hole in
+the Window, ABC the first Prism, DH the second Prism, Y the round Image
+of the Sun made by a direct beam of Light when the Prisms are taken
+away, PT the oblong Image of the Sun made by that beam passing through
+the first Prism alone, when the second Prism is taken away, and _pt_ the
+Image made by the cross Refractions of both Prisms together. Now if the
+Rays which tend towards the several Points of the round Image Y were
+dilated and spread by the Refraction of the first Prism, so that they
+should not any longer go in single Lines to single Points, but that
+every Ray being split, shattered, and changed from a Linear Ray to a
+Superficies of Rays diverging from the Point of Refraction, and lying in
+the Plane of the Angles of Incidence and Refraction, they should go in
+those Planes to so many Lines reaching almost from one end of the Image
+PT to the other, and if that Image should thence become oblong: those
+Rays and their several parts tending towards the several Points of the
+Image PT ought to be again dilated and spread sideways by the transverse
+Refraction of the second Prism, so as to compose a four square Image,
+such as is represented at [Greek: pt]. For the better understanding of
+which, let the Image PT be distinguished into five equal parts PQK,
+KQRL, LRSM, MSVN, NVT. And by the same irregularity that the orbicular
+Light Y is by the Refraction of the first Prism dilated and drawn out
+into a long Image PT, the Light PQK which takes up a space of the same
+length and breadth with the Light Y ought to be by the Refraction of the
+second Prism dilated and drawn out into the long Image _[Greek: p]qkp_,
+and the Light KQRL into the long Image _kqrl_, and the Lights LRSM,
+MSVN, NVT, into so many other long Images _lrsm_, _msvn_, _nvt[Greek:
+t]_; and all these long Images would compose the four square Images
+_[Greek: pt]_. Thus it ought to be were every Ray dilated by Refraction,
+and spread into a triangular Superficies of Rays diverging from the
+Point of Refraction. For the second Refraction would spread the Rays one
+way as much as the first doth another, and so dilate the Image in
+breadth as much as the first doth in length. And the same thing ought to
+happen, were some rays casually refracted more than others. But the
+Event is otherwise. The Image PT was not made broader by the Refraction
+of the second Prism, but only became oblique, as 'tis represented at
+_pt_, its upper end P being by the Refraction translated to a greater
+distance than its lower end T. So then the Light which went towards the
+upper end P of the Image, was (at equal Incidences) more refracted in
+the second Prism, than the Light which tended towards the lower end T,
+that is the blue and violet, than the red and yellow; and therefore was
+more refrangible. The same Light was by the Refraction of the first
+Prism translated farther from the place Y to which it tended before
+Refraction; and therefore suffered as well in the first Prism as in the
+second a greater Refraction than the rest of the Light, and by
+consequence was more refrangible than the rest, even before its
+incidence on the first Prism.
+
+Sometimes I placed a third Prism after the second, and sometimes also a
+fourth after the third, by all which the Image might be often refracted
+sideways: but the Rays which were more refracted than the rest in the
+first Prism were also more refracted in all the rest, and that without
+any Dilatation of the Image sideways: and therefore those Rays for their
+constancy of a greater Refraction are deservedly reputed more
+refrangible.
+
+[Illustration: FIG. 15]
+
+But that the meaning of this Experiment may more clearly appear, it is
+to be considered that the Rays which are equally refrangible do fall
+upon a Circle answering to the Sun's Disque. For this was proved in the
+third Experiment. By a Circle I understand not here a perfect
+geometrical Circle, but any orbicular Figure whose length is equal to
+its breadth, and which, as to Sense, may seem circular. Let therefore AG
+[in _Fig._ 15.] represent the Circle which all the most refrangible Rays
+propagated from the whole Disque of the Sun, would illuminate and paint
+upon the opposite Wall if they were alone; EL the Circle which all the
+least refrangible Rays would in like manner illuminate and paint if they
+were alone; BH, CJ, DK, the Circles which so many intermediate sorts of
+Rays would successively paint upon the Wall, if they were singly
+propagated from the Sun in successive order, the rest being always
+intercepted; and conceive that there are other intermediate Circles
+without Number, which innumerable other intermediate sorts of Rays would
+successively paint upon the Wall if the Sun should successively emit
+every sort apart. And seeing the Sun emits all these sorts at once, they
+must all together illuminate and paint innumerable equal Circles, of all
+which, being according to their degrees of Refrangibility placed in
+order in a continual Series, that oblong Spectrum PT is composed which I
+described in the third Experiment. Now if the Sun's circular Image Y [in
+_Fig._ 15.] which is made by an unrefracted beam of Light was by any
+Dilation of the single Rays, or by any other irregularity in the
+Refraction of the first Prism, converted into the oblong Spectrum, PT:
+then ought every Circle AG, BH, CJ, &c. in that Spectrum, by the cross
+Refraction of the second Prism again dilating or otherwise scattering
+the Rays as before, to be in like manner drawn out and transformed into
+an oblong Figure, and thereby the breadth of the Image PT would be now
+as much augmented as the length of the Image Y was before by the
+Refraction of the first Prism; and thus by the Refractions of both
+Prisms together would be formed a four square Figure _p[Greek:
+p]t[Greek: t]_, as I described above. Wherefore since the breadth of the
+Spectrum PT is not increased by the Refraction sideways, it is certain
+that the Rays are not split or dilated, or otherways irregularly
+scatter'd by that Refraction, but that every Circle is by a regular and
+uniform Refraction translated entire into another Place, as the Circle
+AG by the greatest Refraction into the place _ag_, the Circle BH by a
+less Refraction into the place _bh_, the Circle CJ by a Refraction still
+less into the place _ci_, and so of the rest; by which means a new
+Spectrum _pt_ inclined to the former PT is in like manner composed of
+Circles lying in a right Line; and these Circles must be of the same
+bigness with the former, because the breadths of all the Spectrums Y, PT
+and _pt_ at equal distances from the Prisms are equal.
+
+I considered farther, that by the breadth of the hole F through which
+the Light enters into the dark Chamber, there is a Penumbra made in the
+Circuit of the Spectrum Y, and that Penumbra remains in the rectilinear
+Sides of the Spectrums PT and _pt_. I placed therefore at that hole a
+Lens or Object-glass of a Telescope which might cast the Image of the
+Sun distinctly on Y without any Penumbra at all, and found that the
+Penumbra of the rectilinear Sides of the oblong Spectrums PT and _pt_
+was also thereby taken away, so that those Sides appeared as distinctly
+defined as did the Circumference of the first Image Y. Thus it happens
+if the Glass of the Prisms be free from Veins, and their sides be
+accurately plane and well polished without those numberless Waves or
+Curles which usually arise from Sand-holes a little smoothed in
+polishing with Putty. If the Glass be only well polished and free from
+Veins, and the Sides not accurately plane, but a little Convex or
+Concave, as it frequently happens; yet may the three Spectrums Y, PT and
+_pt_ want Penumbras, but not in equal distances from the Prisms. Now
+from this want of Penumbras, I knew more certainly that every one of the
+Circles was refracted according to some most regular, uniform and
+constant Law. For if there were any irregularity in the Refraction, the
+right Lines AE and GL, which all the Circles in the Spectrum PT do
+touch, could not by that Refraction be translated into the Lines _ae_
+and _gl_ as distinct and straight as they were before, but there would
+arise in those translated Lines some Penumbra or Crookedness or
+Undulation, or other sensible Perturbation contrary to what is found by
+Experience. Whatsoever Penumbra or Perturbation should be made in the
+Circles by the cross Refraction of the second Prism, all that Penumbra
+or Perturbation would be conspicuous in the right Lines _ae_ and _gl_
+which touch those Circles. And therefore since there is no such Penumbra
+or Perturbation in those right Lines, there must be none in the
+Circles. Since the distance between those Tangents or breadth of the
+Spectrum is not increased by the Refractions, the Diameters of the
+Circles are not increased thereby. Since those Tangents continue to be
+right Lines, every Circle which in the first Prism is more or less
+refracted, is exactly in the same proportion more or less refracted in
+the second. And seeing all these things continue to succeed after the
+same manner when the Rays are again in a third Prism, and again in a
+fourth refracted sideways, it is evident that the Rays of one and the
+same Circle, as to their degree of Refrangibility, continue always
+uniform and homogeneal to one another, and that those of several Circles
+do differ in degree of Refrangibility, and that in some certain and
+constant Proportion. Which is the thing I was to prove.
+
+There is yet another Circumstance or two of this Experiment by which it
+becomes still more plain and convincing. Let the second Prism DH [in
+_Fig._ 16.] be placed not immediately after the first, but at some
+distance from it; suppose in the mid-way between it and the Wall on
+which the oblong Spectrum PT is cast, so that the Light from the first
+Prism may fall upon it in the form of an oblong Spectrum [Greek: pt]
+parallel to this second Prism, and be refracted sideways to form the
+oblong Spectrum _pt_ upon the Wall. And you will find as before, that
+this Spectrum _pt_ is inclined to that Spectrum PT, which the first
+Prism forms alone without the second; the blue ends P and _p_ being
+farther distant from one another than the red ones T and _t_, and by
+consequence that the Rays which go to the blue end [Greek: p] of the
+Image [Greek: pt], and which therefore suffer the greatest Refraction in
+the first Prism, are again in the second Prism more refracted than the
+rest.
+
+[Illustration: FIG. 16.]
+
+[Illustration: FIG. 17.]
+
+The same thing I try'd also by letting the Sun's Light into a dark Room
+through two little round holes F and [Greek: ph] [in _Fig._ 17.] made in
+the Window, and with two parallel Prisms ABC and [Greek: abg] placed at
+those holes (one at each) refracting those two beams of Light to the
+opposite Wall of the Chamber, in such manner that the two colour'd
+Images PT and MN which they there painted were joined end to end and lay
+in one straight Line, the red end T of the one touching the blue end M
+of the other. For if these two refracted Beams were again by a third
+Prism DH placed cross to the two first, refracted sideways, and the
+Spectrums thereby translated to some other part of the Wall of the
+Chamber, suppose the Spectrum PT to _pt_ and the Spectrum MN to _mn_,
+these translated Spectrums _pt_ and _mn_ would not lie in one straight
+Line with their ends contiguous as before, but be broken off from one
+another and become parallel, the blue end _m_ of the Image _mn_ being by
+a greater Refraction translated farther from its former place MT, than
+the red end _t_ of the other Image _pt_ from the same place MT; which
+puts the Proposition past Dispute. And this happens whether the third
+Prism DH be placed immediately after the two first, or at a great
+distance from them, so that the Light refracted in the two first Prisms
+be either white and circular, or coloured and oblong when it falls on
+the third.
+
+_Exper._ 6. In the middle of two thin Boards I made round holes a third
+part of an Inch in diameter, and in the Window-shut a much broader hole
+being made to let into my darkned Chamber a large Beam of the Sun's
+Light; I placed a Prism behind the Shut in that beam to refract it
+towards the opposite Wall, and close behind the Prism I fixed one of the
+Boards, in such manner that the middle of the refracted Light might pass
+through the hole made in it, and the rest be intercepted by the Board.
+Then at the distance of about twelve Feet from the first Board I fixed
+the other Board in such manner that the middle of the refracted Light
+which came through the hole in the first Board, and fell upon the
+opposite Wall, might pass through the hole in this other Board, and the
+rest being intercepted by the Board might paint upon it the coloured
+Spectrum of the Sun. And close behind this Board I fixed another Prism
+to refract the Light which came through the hole. Then I returned
+speedily to the first Prism, and by turning it slowly to and fro about
+its Axis, I caused the Image which fell upon the second Board to move up
+and down upon that Board, that all its parts might successively pass
+through the hole in that Board and fall upon the Prism behind it. And in
+the mean time, I noted the places on the opposite Wall to which that
+Light after its Refraction in the second Prism did pass; and by the
+difference of the places I found that the Light which being most
+refracted in the first Prism did go to the blue end of the Image, was
+again more refracted in the second Prism than the Light which went to
+the red end of that Image, which proves as well the first Proposition as
+the second. And this happened whether the Axis of the two Prisms were
+parallel, or inclined to one another, and to the Horizon in any given
+Angles.
+
+_Illustration._ Let F [in _Fig._ 18.] be the wide hole in the
+Window-shut, through which the Sun shines upon the first Prism ABC, and
+let the refracted Light fall upon the middle of the Board DE, and the
+middle part of that Light upon the hole G made in the middle part of
+that Board. Let this trajected part of that Light fall again upon the
+middle of the second Board _de_, and there paint such an oblong coloured
+Image of the Sun as was described in the third Experiment. By turning
+the Prism ABC slowly to and fro about its Axis, this Image will be made
+to move up and down the Board _de_, and by this means all its parts from
+one end to the other may be made to pass successively through the hole
+_g_ which is made in the middle of that Board. In the mean while another
+Prism _abc_ is to be fixed next after that hole _g_, to refract the
+trajected Light a second time. And these things being thus ordered, I
+marked the places M and N of the opposite Wall upon which the refracted
+Light fell, and found that whilst the two Boards and second Prism
+remained unmoved, those places by turning the first Prism about its Axis
+were changed perpetually. For when the lower part of the Light which
+fell upon the second Board _de_ was cast through the hole _g_, it went
+to a lower place M on the Wall and when the higher part of that Light
+was cast through the same hole _g_, it went to a higher place N on the
+Wall, and when any intermediate part of the Light was cast through that
+hole, it went to some place on the Wall between M and N. The unchanged
+Position of the holes in the Boards, made the Incidence of the Rays upon
+the second Prism to be the same in all cases. And yet in that common
+Incidence some of the Rays were more refracted, and others less. And
+those were more refracted in this Prism, which by a greater Refraction
+in the first Prism were more turned out of the way, and therefore for
+their Constancy of being more refracted are deservedly called more
+refrangible.
+
+[Illustration: FIG. 18.]
+
+[Illustration: FIG. 20.]
+
+_Exper._ 7. At two holes made near one another in my Window-shut I
+placed two Prisms, one at each, which might cast upon the opposite Wall
+(after the manner of the third Experiment) two oblong coloured Images of
+the Sun. And at a little distance from the Wall I placed a long slender
+Paper with straight and parallel edges, and ordered the Prisms and Paper
+so, that the red Colour of one Image might fall directly upon one half
+of the Paper, and the violet Colour of the other Image upon the other
+half of the same Paper; so that the Paper appeared of two Colours, red
+and violet, much after the manner of the painted Paper in the first and
+second Experiments. Then with a black Cloth I covered the Wall behind
+the Paper, that no Light might be reflected from it to disturb the
+Experiment, and viewing the Paper through a third Prism held parallel
+to it, I saw that half of it which was illuminated by the violet Light
+to be divided from the other half by a greater Refraction, especially
+when I went a good way off from the Paper. For when I viewed it too near
+at hand, the two halfs of the Paper did not appear fully divided from
+one another, but seemed contiguous at one of their Angles like the
+painted Paper in the first Experiment. Which also happened when the
+Paper was too broad.
+
+[Illustration: FIG. 19.]
+
+Sometimes instead of the Paper I used a white Thred, and this appeared
+through the Prism divided into two parallel Threds as is represented in
+the nineteenth Figure, where DG denotes the Thred illuminated with
+violet Light from D to E and with red Light from F to G, and _defg_ are
+the parts of the Thred seen by Refraction. If one half of the Thred be
+constantly illuminated with red, and the other half be illuminated with
+all the Colours successively, (which may be done by causing one of the
+Prisms to be turned about its Axis whilst the other remains unmoved)
+this other half in viewing the Thred through the Prism, will appear in
+a continual right Line with the first half when illuminated with red,
+and begin to be a little divided from it when illuminated with Orange,
+and remove farther from it when illuminated with yellow, and still
+farther when with green, and farther when with blue, and go yet farther
+off when illuminated with Indigo, and farthest when with deep violet.
+Which plainly shews, that the Lights of several Colours are more and
+more refrangible one than another, in this Order of their Colours, red,
+orange, yellow, green, blue, indigo, deep violet; and so proves as well
+the first Proposition as the second.
+
+I caused also the coloured Spectrums PT [in _Fig._ 17.] and MN made in a
+dark Chamber by the Refractions of two Prisms to lie in a Right Line end
+to end, as was described above in the fifth Experiment, and viewing them
+through a third Prism held parallel to their Length, they appeared no
+longer in a Right Line, but became broken from one another, as they are
+represented at _pt_ and _mn_, the violet end _m_ of the Spectrum _mn_
+being by a greater Refraction translated farther from its former Place
+MT than the red end _t_ of the other Spectrum _pt_.
+
+I farther caused those two Spectrums PT [in _Fig._ 20.] and MN to become
+co-incident in an inverted Order of their Colours, the red end of each
+falling on the violet end of the other, as they are represented in the
+oblong Figure PTMN; and then viewing them through a Prism DH held
+parallel to their Length, they appeared not co-incident, as when view'd
+with the naked Eye, but in the form of two distinct Spectrums _pt_ and
+_mn_ crossing one another in the middle after the manner of the Letter
+X. Which shews that the red of the one Spectrum and violet of the other,
+which were co-incident at PN and MT, being parted from one another by a
+greater Refraction of the violet to _p_ and _m_ than of the red to _n_
+and _t_, do differ in degrees of Refrangibility.
+
+I illuminated also a little Circular Piece of white Paper all over with
+the Lights of both Prisms intermixed, and when it was illuminated with
+the red of one Spectrum, and deep violet of the other, so as by the
+Mixture of those Colours to appear all over purple, I viewed the Paper,
+first at a less distance, and then at a greater, through a third Prism;
+and as I went from the Paper, the refracted Image thereof became more
+and more divided by the unequal Refraction of the two mixed Colours, and
+at length parted into two distinct Images, a red one and a violet one,
+whereof the violet was farthest from the Paper, and therefore suffered
+the greatest Refraction. And when that Prism at the Window, which cast
+the violet on the Paper was taken away, the violet Image disappeared;
+but when the other Prism was taken away the red vanished; which shews,
+that these two Images were nothing else than the Lights of the two
+Prisms, which had been intermixed on the purple Paper, but were parted
+again by their unequal Refractions made in the third Prism, through
+which the Paper was view'd. This also was observable, that if one of the
+Prisms at the Window, suppose that which cast the violet on the Paper,
+was turned about its Axis to make all the Colours in this order,
+violet, indigo, blue, green, yellow, orange, red, fall successively on
+the Paper from that Prism, the violet Image changed Colour accordingly,
+turning successively to indigo, blue, green, yellow and red, and in
+changing Colour came nearer and nearer to the red Image made by the
+other Prism, until when it was also red both Images became fully
+co-incident.
+
+I placed also two Paper Circles very near one another, the one in the
+red Light of one Prism, and the other in the violet Light of the other.
+The Circles were each of them an Inch in diameter, and behind them the
+Wall was dark, that the Experiment might not be disturbed by any Light
+coming from thence. These Circles thus illuminated, I viewed through a
+Prism, so held, that the Refraction might be made towards the red
+Circle, and as I went from them they came nearer and nearer together,
+and at length became co-incident; and afterwards when I went still
+farther off, they parted again in a contrary Order, the violet by a
+greater Refraction being carried beyond the red.
+
+_Exper._ 8. In Summer, when the Sun's Light uses to be strongest, I
+placed a Prism at the Hole of the Window-shut, as in the third
+Experiment, yet so that its Axis might be parallel to the Axis of the
+World, and at the opposite Wall in the Sun's refracted Light, I placed
+an open Book. Then going six Feet and two Inches from the Book, I placed
+there the above-mentioned Lens, by which the Light reflected from the
+Book might be made to converge and meet again at the distance of six
+Feet and two Inches behind the Lens, and there paint the Species of the
+Book upon a Sheet of white Paper much after the manner of the second
+Experiment. The Book and Lens being made fast, I noted the Place where
+the Paper was, when the Letters of the Book, illuminated by the fullest
+red Light of the Solar Image falling upon it, did cast their Species on
+that Paper most distinctly: And then I stay'd till by the Motion of the
+Sun, and consequent Motion of his Image on the Book, all the Colours
+from that red to the middle of the blue pass'd over those Letters; and
+when those Letters were illuminated by that blue, I noted again the
+Place of the Paper when they cast their Species most distinctly upon it:
+And I found that this last Place of the Paper was nearer to the Lens
+than its former Place by about two Inches and an half, or two and three
+quarters. So much sooner therefore did the Light in the violet end of
+the Image by a greater Refraction converge and meet, than the Light in
+the red end. But in trying this, the Chamber was as dark as I could make
+it. For, if these Colours be diluted and weakned by the Mixture of any
+adventitious Light, the distance between the Places of the Paper will
+not be so great. This distance in the second Experiment, where the
+Colours of natural Bodies were made use of, was but an Inch and an half,
+by reason of the Imperfection of those Colours. Here in the Colours of
+the Prism, which are manifestly more full, intense, and lively than
+those of natural Bodies, the distance is two Inches and three quarters.
+And were the Colours still more full, I question not but that the
+distance would be considerably greater. For the coloured Light of the
+Prism, by the interfering of the Circles described in the second Figure
+of the fifth Experiment, and also by the Light of the very bright Clouds
+next the Sun's Body intermixing with these Colours, and by the Light
+scattered by the Inequalities in the Polish of the Prism, was so very
+much compounded, that the Species which those faint and dark Colours,
+the indigo and violet, cast upon the Paper were not distinct enough to
+be well observed.
+
+_Exper._ 9. A Prism, whose two Angles at its Base were equal to one
+another, and half right ones, and the third a right one, I placed in a
+Beam of the Sun's Light let into a dark Chamber through a Hole in the
+Window-shut, as in the third Experiment. And turning the Prism slowly
+about its Axis, until all the Light which went through one of its
+Angles, and was refracted by it began to be reflected by its Base, at
+which till then it went out of the Glass, I observed that those Rays
+which had suffered the greatest Refraction were sooner reflected than
+the rest. I conceived therefore, that those Rays of the reflected Light,
+which were most refrangible, did first of all by a total Reflexion
+become more copious in that Light than the rest, and that afterwards the
+rest also, by a total Reflexion, became as copious as these. To try
+this, I made the reflected Light pass through another Prism, and being
+refracted by it to fall afterwards upon a Sheet of white Paper placed
+at some distance behind it, and there by that Refraction to paint the
+usual Colours of the Prism. And then causing the first Prism to be
+turned about its Axis as above, I observed that when those Rays, which
+in this Prism had suffered the greatest Refraction, and appeared of a
+blue and violet Colour began to be totally reflected, the blue and
+violet Light on the Paper, which was most refracted in the second Prism,
+received a sensible Increase above that of the red and yellow, which was
+least refracted; and afterwards, when the rest of the Light which was
+green, yellow, and red, began to be totally reflected in the first
+Prism, the Light of those Colours on the Paper received as great an
+Increase as the violet and blue had done before. Whence 'tis manifest,
+that the Beam of Light reflected by the Base of the Prism, being
+augmented first by the more refrangible Rays, and afterwards by the less
+refrangible ones, is compounded of Rays differently refrangible. And
+that all such reflected Light is of the same Nature with the Sun's Light
+before its Incidence on the Base of the Prism, no Man ever doubted; it
+being generally allowed, that Light by such Reflexions suffers no
+Alteration in its Modifications and Properties. I do not here take
+Notice of any Refractions made in the sides of the first Prism, because
+the Light enters it perpendicularly at the first side, and goes out
+perpendicularly at the second side, and therefore suffers none. So then,
+the Sun's incident Light being of the same Temper and Constitution with
+his emergent Light, and the last being compounded of Rays differently
+refrangible, the first must be in like manner compounded.
+
+[Illustration: FIG. 21.]
+
+_Illustration._ In the twenty-first Figure, ABC is the first Prism, BC
+its Base, B and C its equal Angles at the Base, each of 45 Degrees, A
+its rectangular Vertex, FM a beam of the Sun's Light let into a dark
+Room through a hole F one third part of an Inch broad, M its Incidence
+on the Base of the Prism, MG a less refracted Ray, MH a more refracted
+Ray, MN the beam of Light reflected from the Base, VXY the second Prism
+by which this beam in passing through it is refracted, N_t_ the less
+refracted Light of this beam, and N_p_ the more refracted part thereof.
+When the first Prism ABC is turned about its Axis according to the order
+of the Letters ABC, the Rays MH emerge more and more obliquely out of
+that Prism, and at length after their most oblique Emergence are
+reflected towards N, and going on to _p_ do increase the Number of the
+Rays N_p_. Afterwards by continuing the Motion of the first Prism, the
+Rays MG are also reflected to N and increase the number of the Rays
+N_t_. And therefore the Light MN admits into its Composition, first the
+more refrangible Rays, and then the less refrangible Rays, and yet after
+this Composition is of the same Nature with the Sun's immediate Light
+FM, the Reflexion of the specular Base BC causing no Alteration therein.
+
+_Exper._ 10. Two Prisms, which were alike in Shape, I tied so together,
+that their Axis and opposite Sides being parallel, they composed a
+Parallelopiped. And, the Sun shining into my dark Chamber through a
+little hole in the Window-shut, I placed that Parallelopiped in his beam
+at some distance from the hole, in such a Posture, that the Axes of the
+Prisms might be perpendicular to the incident Rays, and that those Rays
+being incident upon the first Side of one Prism, might go on through the
+two contiguous Sides of both Prisms, and emerge out of the last Side of
+the second Prism. This Side being parallel to the first Side of the
+first Prism, caused the emerging Light to be parallel to the incident.
+Then, beyond these two Prisms I placed a third, which might refract that
+emergent Light, and by that Refraction cast the usual Colours of the
+Prism upon the opposite Wall, or upon a sheet of white Paper held at a
+convenient Distance behind the Prism for that refracted Light to fall
+upon it. After this I turned the Parallelopiped about its Axis, and
+found that when the contiguous Sides of the two Prisms became so oblique
+to the incident Rays, that those Rays began all of them to be
+reflected, those Rays which in the third Prism had suffered the greatest
+Refraction, and painted the Paper with violet and blue, were first of
+all by a total Reflexion taken out of the transmitted Light, the rest
+remaining and on the Paper painting their Colours of green, yellow,
+orange and red, as before; and afterwards by continuing the Motion of
+the two Prisms, the rest of the Rays also by a total Reflexion vanished
+in order, according to their degrees of Refrangibility. The Light
+therefore which emerged out of the two Prisms is compounded of Rays
+differently refrangible, seeing the more refrangible Rays may be taken
+out of it, while the less refrangible remain. But this Light being
+trajected only through the parallel Superficies of the two Prisms, if it
+suffer'd any change by the Refraction of one Superficies it lost that
+Impression by the contrary Refraction of the other Superficies, and so
+being restor'd to its pristine Constitution, became of the same Nature
+and Condition as at first before its Incidence on those Prisms; and
+therefore, before its Incidence, was as much compounded of Rays
+differently refrangible, as afterwards.
+
+[Illustration: FIG. 22.]
+
+_Illustration._ In the twenty second Figure ABC and BCD are the two
+Prisms tied together in the form of a Parallelopiped, their Sides BC and
+CB being contiguous, and their Sides AB and CD parallel. And HJK is the
+third Prism, by which the Sun's Light propagated through the hole F into
+the dark Chamber, and there passing through those sides of the Prisms
+AB, BC, CB and CD, is refracted at O to the white Paper PT, falling
+there partly upon P by a greater Refraction, partly upon T by a less
+Refraction, and partly upon R and other intermediate places by
+intermediate Refractions. By turning the Parallelopiped ACBD about its
+Axis, according to the order of the Letters A, C, D, B, at length when
+the contiguous Planes BC and CB become sufficiently oblique to the Rays
+FM, which are incident upon them at M, there will vanish totally out of
+the refracted Light OPT, first of all the most refracted Rays OP, (the
+rest OR and OT remaining as before) then the Rays OR and other
+intermediate ones, and lastly, the least refracted Rays OT. For when
+the Plane BC becomes sufficiently oblique to the Rays incident upon it,
+those Rays will begin to be totally reflected by it towards N; and first
+the most refrangible Rays will be totally reflected (as was explained in
+the preceding Experiment) and by Consequence must first disappear at P,
+and afterwards the rest as they are in order totally reflected to N,
+they must disappear in the same order at R and T. So then the Rays which
+at O suffer the greatest Refraction, may be taken out of the Light MO
+whilst the rest of the Rays remain in it, and therefore that Light MO is
+compounded of Rays differently refrangible. And because the Planes AB
+and CD are parallel, and therefore by equal and contrary Refractions
+destroy one anothers Effects, the incident Light FM must be of the same
+Kind and Nature with the emergent Light MO, and therefore doth also
+consist of Rays differently refrangible. These two Lights FM and MO,
+before the most refrangible Rays are separated out of the emergent Light
+MO, agree in Colour, and in all other Properties so far as my
+Observation reaches, and therefore are deservedly reputed of the same
+Nature and Constitution, and by Consequence the one is compounded as
+well as the other. But after the most refrangible Rays begin to be
+totally reflected, and thereby separated out of the emergent Light MO,
+that Light changes its Colour from white to a dilute and faint yellow, a
+pretty good orange, a very full red successively, and then totally
+vanishes. For after the most refrangible Rays which paint the Paper at
+P with a purple Colour, are by a total Reflexion taken out of the beam
+of Light MO, the rest of the Colours which appear on the Paper at R and
+T being mix'd in the Light MO compound there a faint yellow, and after
+the blue and part of the green which appear on the Paper between P and R
+are taken away, the rest which appear between R and T (that is the
+yellow, orange, red and a little green) being mixed in the beam MO
+compound there an orange; and when all the Rays are by Reflexion taken
+out of the beam MO, except the least refrangible, which at T appear of a
+full red, their Colour is the same in that beam MO as afterwards at T,
+the Refraction of the Prism HJK serving only to separate the differently
+refrangible Rays, without making any Alteration in their Colours, as
+shall be more fully proved hereafter. All which confirms as well the
+first Proposition as the second.
+
+_Scholium._ If this Experiment and the former be conjoined and made one
+by applying a fourth Prism VXY [in _Fig._ 22.] to refract the reflected
+beam MN towards _tp_, the Conclusion will be clearer. For then the Light
+N_p_ which in the fourth Prism is more refracted, will become fuller and
+stronger when the Light OP, which in the third Prism HJK is more
+refracted, vanishes at P; and afterwards when the less refracted Light
+OT vanishes at T, the less refracted Light N_t_ will become increased
+whilst the more refracted Light at _p_ receives no farther increase. And
+as the trajected beam MO in vanishing is always of such a Colour as
+ought to result from the mixture of the Colours which fall upon the
+Paper PT, so is the reflected beam MN always of such a Colour as ought
+to result from the mixture of the Colours which fall upon the Paper
+_pt_. For when the most refrangible Rays are by a total Reflexion taken
+out of the beam MO, and leave that beam of an orange Colour, the Excess
+of those Rays in the reflected Light, does not only make the violet,
+indigo and blue at _p_ more full, but also makes the beam MN change from
+the yellowish Colour of the Sun's Light, to a pale white inclining to
+blue, and afterward recover its yellowish Colour again, so soon as all
+the rest of the transmitted Light MOT is reflected.
+
+Now seeing that in all this variety of Experiments, whether the Trial be
+made in Light reflected, and that either from natural Bodies, as in the
+first and second Experiment, or specular, as in the ninth; or in Light
+refracted, and that either before the unequally refracted Rays are by
+diverging separated from one another, and losing their whiteness which
+they have altogether, appear severally of several Colours, as in the
+fifth Experiment; or after they are separated from one another, and
+appear colour'd as in the sixth, seventh, and eighth Experiments; or in
+Light trajected through parallel Superficies, destroying each others
+Effects, as in the tenth Experiment; there are always found Rays, which
+at equal Incidences on the same Medium suffer unequal Refractions, and
+that without any splitting or dilating of single Rays, or contingence in
+the inequality of the Refractions, as is proved in the fifth and sixth
+Experiments. And seeing the Rays which differ in Refrangibility may be
+parted and sorted from one another, and that either by Refraction as in
+the third Experiment, or by Reflexion as in the tenth, and then the
+several sorts apart at equal Incidences suffer unequal Refractions, and
+those sorts are more refracted than others after Separation, which were
+more refracted before it, as in the sixth and following Experiments, and
+if the Sun's Light be trajected through three or more cross Prisms
+successively, those Rays which in the first Prism are refracted more
+than others, are in all the following Prisms refracted more than others
+in the same Rate and Proportion, as appears by the fifth Experiment;
+it's manifest that the Sun's Light is an heterogeneous Mixture of Rays,
+some of which are constantly more refrangible than others, as was
+proposed.
+
+
+_PROP._ III. THEOR. III.
+
+_The Sun's Light consists of Rays differing in Reflexibility, and those
+Rays are more reflexible than others which are more refrangible._
+
+This is manifest by the ninth and tenth Experiments: For in the ninth
+Experiment, by turning the Prism about its Axis, until the Rays within
+it which in going out into the Air were refracted by its Base, became so
+oblique to that Base, as to begin to be totally reflected thereby; those
+Rays became first of all totally reflected, which before at equal
+Incidences with the rest had suffered the greatest Refraction. And the
+same thing happens in the Reflexion made by the common Base of the two
+Prisms in the tenth Experiment.
+
+
+_PROP._ IV. PROB. I.
+
+_To separate from one another the heterogeneous Rays of compound Light._
+
+[Illustration: FIG. 23.]
+
+The heterogeneous Rays are in some measure separated from one another by
+the Refraction of the Prism in the third Experiment, and in the fifth
+Experiment, by taking away the Penumbra from the rectilinear sides of
+the coloured Image, that Separation in those very rectilinear sides or
+straight edges of the Image becomes perfect. But in all places between
+those rectilinear edges, those innumerable Circles there described,
+which are severally illuminated by homogeneal Rays, by interfering with
+one another, and being every where commix'd, do render the Light
+sufficiently compound. But if these Circles, whilst their Centers keep
+their Distances and Positions, could be made less in Diameter, their
+interfering one with another, and by Consequence the Mixture of the
+heterogeneous Rays would be proportionally diminish'd. In the twenty
+third Figure let AG, BH, CJ, DK, EL, FM be the Circles which so many
+sorts of Rays flowing from the same disque of the Sun, do in the third
+Experiment illuminate; of all which and innumerable other intermediate
+ones lying in a continual Series between the two rectilinear and
+parallel edges of the Sun's oblong Image PT, that Image is compos'd, as
+was explained in the fifth Experiment. And let _ag_, _bh_, _ci_, _dk_,
+_el_, _fm_ be so many less Circles lying in a like continual Series
+between two parallel right Lines _af_ and _gm_ with the same distances
+between their Centers, and illuminated by the same sorts of Rays, that
+is the Circle _ag_ with the same sort by which the corresponding Circle
+AG was illuminated, and the Circle _bh_ with the same sort by which the
+corresponding Circle BH was illuminated, and the rest of the Circles
+_ci_, _dk_, _el_, _fm_ respectively, with the same sorts of Rays by
+which the several corresponding Circles CJ, DK, EL, FM were illuminated.
+In the Figure PT composed of the greater Circles, three of those Circles
+AG, BH, CJ, are so expanded into one another, that the three sorts of
+Rays by which those Circles are illuminated, together with other
+innumerable sorts of intermediate Rays, are mixed at QR in the middle
+of the Circle BH. And the like Mixture happens throughout almost the
+whole length of the Figure PT. But in the Figure _pt_ composed of the
+less Circles, the three less Circles _ag_, _bh_, _ci_, which answer to
+those three greater, do not extend into one another; nor are there any
+where mingled so much as any two of the three sorts of Rays by which
+those Circles are illuminated, and which in the Figure PT are all of
+them intermingled at BH.
+
+Now he that shall thus consider it, will easily understand that the
+Mixture is diminished in the same Proportion with the Diameters of the
+Circles. If the Diameters of the Circles whilst their Centers remain the
+same, be made three times less than before, the Mixture will be also
+three times less; if ten times less, the Mixture will be ten times less,
+and so of other Proportions. That is, the Mixture of the Rays in the
+greater Figure PT will be to their Mixture in the less _pt_, as the
+Latitude of the greater Figure is to the Latitude of the less. For the
+Latitudes of these Figures are equal to the Diameters of their Circles.
+And hence it easily follows, that the Mixture of the Rays in the
+refracted Spectrum _pt_ is to the Mixture of the Rays in the direct and
+immediate Light of the Sun, as the breadth of that Spectrum is to the
+difference between the length and breadth of the same Spectrum.
+
+So then, if we would diminish the Mixture of the Rays, we are to
+diminish the Diameters of the Circles. Now these would be diminished if
+the Sun's Diameter to which they answer could be made less than it is,
+or (which comes to the same Purpose) if without Doors, at a great
+distance from the Prism towards the Sun, some opake Body were placed,
+with a round hole in the middle of it, to intercept all the Sun's Light,
+excepting so much as coming from the middle of his Body could pass
+through that Hole to the Prism. For so the Circles AG, BH, and the rest,
+would not any longer answer to the whole Disque of the Sun, but only to
+that Part of it which could be seen from the Prism through that Hole,
+that it is to the apparent Magnitude of that Hole view'd from the Prism.
+But that these Circles may answer more distinctly to that Hole, a Lens
+is to be placed by the Prism to cast the Image of the Hole, (that is,
+every one of the Circles AG, BH, &c.) distinctly upon the Paper at PT,
+after such a manner, as by a Lens placed at a Window, the Species of
+Objects abroad are cast distinctly upon a Paper within the Room, and the
+rectilinear Sides of the oblong Solar Image in the fifth Experiment
+became distinct without any Penumbra. If this be done, it will not be
+necessary to place that Hole very far off, no not beyond the Window. And
+therefore instead of that Hole, I used the Hole in the Window-shut, as
+follows.
+
+_Exper._ 11. In the Sun's Light let into my darken'd Chamber through a
+small round Hole in my Window-shut, at about ten or twelve Feet from the
+Window, I placed a Lens, by which the Image of the Hole might be
+distinctly cast upon a Sheet of white Paper, placed at the distance of
+six, eight, ten, or twelve Feet from the Lens. For, according to the
+difference of the Lenses I used various distances, which I think not
+worth the while to describe. Then immediately after the Lens I placed a
+Prism, by which the trajected Light might be refracted either upwards or
+sideways, and thereby the round Image, which the Lens alone did cast
+upon the Paper might be drawn out into a long one with Parallel Sides,
+as in the third Experiment. This oblong Image I let fall upon another
+Paper at about the same distance from the Prism as before, moving the
+Paper either towards the Prism or from it, until I found the just
+distance where the Rectilinear Sides of the Image became most distinct.
+For in this Case, the Circular Images of the Hole, which compose that
+Image after the same manner that the Circles _ag_, _bh_, _ci_, &c. do
+the Figure _pt_ [in _Fig._ 23.] were terminated most distinctly without
+any Penumbra, and therefore extended into one another the least that
+they could, and by consequence the Mixture of the heterogeneous Rays was
+now the least of all. By this means I used to form an oblong Image (such
+as is _pt_) [in _Fig._ 23, and 24.] of Circular Images of the Hole,
+(such as are _ag_, _bh_, _ci_, &c.) and by using a greater or less Hole
+in the Window-shut, I made the Circular Images _ag_, _bh_, _ci_, &c. of
+which it was formed, to become greater or less at pleasure, and thereby
+the Mixture of the Rays in the Image _pt_ to be as much, or as little as
+I desired.
+
+[Illustration: FIG. 24.]
+
+_Illustration._ In the twenty-fourth Figure, F represents the Circular
+Hole in the Window-shut, MN the Lens, whereby the Image or Species of
+that Hole is cast distinctly upon a Paper at J, ABC the Prism, whereby
+the Rays are at their emerging out of the Lens refracted from J towards
+another Paper at _pt_, and the round Image at J is turned into an oblong
+Image _pt_ falling on that other Paper. This Image _pt_ consists of
+Circles placed one after another in a Rectilinear Order, as was
+sufficiently explained in the fifth Experiment; and these Circles are
+equal to the Circle J, and consequently answer in magnitude to the Hole
+F; and therefore by diminishing that Hole they may be at pleasure
+diminished, whilst their Centers remain in their Places. By this means I
+made the Breadth of the Image _pt_ to be forty times, and sometimes
+sixty or seventy times less than its Length. As for instance, if the
+Breadth of the Hole F be one tenth of an Inch, and MF the distance of
+the Lens from the Hole be 12 Feet; and if _p_B or _p_M the distance of
+the Image _pt_ from the Prism or Lens be 10 Feet, and the refracting
+Angle of the Prism be 62 Degrees, the Breadth of the Image _pt_ will be
+one twelfth of an Inch, and the Length about six Inches, and therefore
+the Length to the Breadth as 72 to 1, and by consequence the Light of
+this Image 71 times less compound than the Sun's direct Light. And Light
+thus far simple and homogeneal, is sufficient for trying all the
+Experiments in this Book about simple Light. For the Composition of
+heterogeneal Rays is in this Light so little, that it is scarce to be
+discovered and perceiv'd by Sense, except perhaps in the indigo and
+violet. For these being dark Colours do easily suffer a sensible Allay
+by that little scattering Light which uses to be refracted irregularly
+by the Inequalities of the Prism.
+
+Yet instead of the Circular Hole F, 'tis better to substitute an oblong
+Hole shaped like a long Parallelogram with its Length parallel to the
+Prism ABC. For if this Hole be an Inch or two long, and but a tenth or
+twentieth Part of an Inch broad, or narrower; the Light of the Image
+_pt_ will be as simple as before, or simpler, and the Image will become
+much broader, and therefore more fit to have Experiments try'd in its
+Light than before.
+
+Instead of this Parallelogram Hole may be substituted a triangular one
+of equal Sides, whose Base, for instance, is about the tenth Part of an
+Inch, and its Height an Inch or more. For by this means, if the Axis of
+the Prism be parallel to the Perpendicular of the Triangle, the Image
+_pt_ [in _Fig._ 25.] will now be form'd of equicrural Triangles _ag_,
+_bh_, _ci_, _dk_, _el_, _fm_, &c. and innumerable other intermediate
+ones answering to the triangular Hole in Shape and Bigness, and lying
+one after another in a continual Series between two Parallel Lines _af_
+and _gm_. These Triangles are a little intermingled at their Bases, but
+not at their Vertices; and therefore the Light on the brighter Side _af_
+of the Image, where the Bases of the Triangles are, is a little
+compounded, but on the darker Side _gm_ is altogether uncompounded, and
+in all Places between the Sides the Composition is proportional to the
+distances of the Places from that obscurer Side _gm_. And having a
+Spectrum _pt_ of such a Composition, we may try Experiments either in
+its stronger and less simple Light near the Side _af_, or in its weaker
+and simpler Light near the other Side _gm_, as it shall seem most
+convenient.
+
+[Illustration: FIG. 25.]
+
+But in making Experiments of this kind, the Chamber ought to be made as
+dark as can be, lest any Foreign Light mingle it self with the Light of
+the Spectrum _pt_, and render it compound; especially if we would try
+Experiments in the more simple Light next the Side _gm_ of the Spectrum;
+which being fainter, will have a less proportion to the Foreign Light;
+and so by the mixture of that Light be more troubled, and made more
+compound. The Lens also ought to be good, such as may serve for optical
+Uses, and the Prism ought to have a large Angle, suppose of 65 or 70
+Degrees, and to be well wrought, being made of Glass free from Bubbles
+and Veins, with its Sides not a little convex or concave, as usually
+happens, but truly plane, and its Polish elaborate, as in working
+Optick-glasses, and not such as is usually wrought with Putty, whereby
+the edges of the Sand-holes being worn away, there are left all over the
+Glass a numberless Company of very little convex polite Risings like
+Waves. The edges also of the Prism and Lens, so far as they may make any
+irregular Refraction, must be covered with a black Paper glewed on. And
+all the Light of the Sun's Beam let into the Chamber, which is useless
+and unprofitable to the Experiment, ought to be intercepted with black
+Paper, or other black Obstacles. For otherwise the useless Light being
+reflected every way in the Chamber, will mix with the oblong Spectrum,
+and help to disturb it. In trying these Things, so much diligence is not
+altogether necessary, but it will promote the Success of the
+Experiments, and by a very scrupulous Examiner of Things deserves to be
+apply'd. It's difficult to get Glass Prisms fit for this Purpose, and
+therefore I used sometimes prismatick Vessels made with pieces of broken
+Looking-glasses, and filled with Rain Water. And to increase the
+Refraction, I sometimes impregnated the Water strongly with _Saccharum
+Saturni_.
+
+
+_PROP._ V. THEOR. IV.
+
+_Homogeneal Light is refracted regularly without any Dilatation
+splitting or shattering of the Rays, and the confused Vision of Objects
+seen through refracting Bodies by heterogeneal Light arises from the
+different Refrangibility of several sorts of Rays._
+
+The first Part of this Proposition has been already sufficiently proved
+in the fifth Experiment, and will farther appear by the Experiments
+which follow.
+
+_Exper._ 12. In the middle of a black Paper I made a round Hole about a
+fifth or sixth Part of an Inch in diameter. Upon this Paper I caused the
+Spectrum of homogeneal Light described in the former Proposition, so to
+fall, that some part of the Light might pass through the Hole of the
+Paper. This transmitted part of the Light I refracted with a Prism
+placed behind the Paper, and letting this refracted Light fall
+perpendicularly upon a white Paper two or three Feet distant from the
+Prism, I found that the Spectrum formed on the Paper by this Light was
+not oblong, as when 'tis made (in the third Experiment) by refracting
+the Sun's compound Light, but was (so far as I could judge by my Eye)
+perfectly circular, the Length being no greater than the Breadth. Which
+shews, that this Light is refracted regularly without any Dilatation of
+the Rays.
+
+_Exper._ 13. In the homogeneal Light I placed a Paper Circle of a
+quarter of an Inch in diameter, and in the Sun's unrefracted
+heterogeneal white Light I placed another Paper Circle of the same
+Bigness. And going from the Papers to the distance of some Feet, I
+viewed both Circles through a Prism. The Circle illuminated by the Sun's
+heterogeneal Light appeared very oblong, as in the fourth Experiment,
+the Length being many times greater than the Breadth; but the other
+Circle, illuminated with homogeneal Light, appeared circular and
+distinctly defined, as when 'tis view'd with the naked Eye. Which proves
+the whole Proposition.
+
+_Exper._ 14. In the homogeneal Light I placed Flies, and such-like
+minute Objects, and viewing them through a Prism, I saw their Parts as
+distinctly defined, as if I had viewed them with the naked Eye. The same
+Objects placed in the Sun's unrefracted heterogeneal Light, which was
+white, I viewed also through a Prism, and saw them most confusedly
+defined, so that I could not distinguish their smaller Parts from one
+another. I placed also the Letters of a small print, one while in the
+homogeneal Light, and then in the heterogeneal, and viewing them through
+a Prism, they appeared in the latter Case so confused and indistinct,
+that I could not read them; but in the former they appeared so distinct,
+that I could read readily, and thought I saw them as distinct, as when I
+view'd them with my naked Eye. In both Cases I view'd the same Objects,
+through the same Prism at the same distance from me, and in the same
+Situation. There was no difference, but in the Light by which the
+Objects were illuminated, and which in one Case was simple, and in the
+other compound; and therefore, the distinct Vision in the former Case,
+and confused in the latter, could arise from nothing else than from that
+difference of the Lights. Which proves the whole Proposition.
+
+And in these three Experiments it is farther very remarkable, that the
+Colour of homogeneal Light was never changed by the Refraction.
+
+
+_PROP._ VI. THEOR. V.
+
+_The Sine of Incidence of every Ray considered apart, is to its Sine of
+Refraction in a given Ratio._
+
+That every Ray consider'd apart, is constant to it self in some degree
+of Refrangibility, is sufficiently manifest out of what has been said.
+Those Rays, which in the first Refraction, are at equal Incidences most
+refracted, are also in the following Refractions at equal Incidences
+most refracted; and so of the least refrangible, and the rest which have
+any mean Degree of Refrangibility, as is manifest by the fifth, sixth,
+seventh, eighth, and ninth Experiments. And those which the first Time
+at like Incidences are equally refracted, are again at like Incidences
+equally and uniformly refracted, and that whether they be refracted
+before they be separated from one another, as in the fifth Experiment,
+or whether they be refracted apart, as in the twelfth, thirteenth and
+fourteenth Experiments. The Refraction therefore of every Ray apart is
+regular, and what Rule that Refraction observes we are now to shew.[E]
+
+The late Writers in Opticks teach, that the Sines of Incidence are in a
+given Proportion to the Sines of Refraction, as was explained in the
+fifth Axiom, and some by Instruments fitted for measuring of
+Refractions, or otherwise experimentally examining this Proportion, do
+acquaint us that they have found it accurate. But whilst they, not
+understanding the different Refrangibility of several Rays, conceived
+them all to be refracted according to one and the same Proportion, 'tis
+to be presumed that they adapted their Measures only to the middle of
+the refracted Light; so that from their Measures we may conclude only
+that the Rays which have a mean Degree of Refrangibility, that is, those
+which when separated from the rest appear green, are refracted according
+to a given Proportion of their Sines. And therefore we are now to shew,
+that the like given Proportions obtain in all the rest. That it should
+be so is very reasonable, Nature being ever conformable to her self; but
+an experimental Proof is desired. And such a Proof will be had, if we
+can shew that the Sines of Refraction of Rays differently refrangible
+are one to another in a given Proportion when their Sines of Incidence
+are equal. For, if the Sines of Refraction of all the Rays are in given
+Proportions to the Sine of Refractions of a Ray which has a mean Degree
+of Refrangibility, and this Sine is in a given Proportion to the equal
+Sines of Incidence, those other Sines of Refraction will also be in
+given Proportions to the equal Sines of Incidence. Now, when the Sines
+of Incidence are equal, it will appear by the following Experiment, that
+the Sines of Refraction are in a given Proportion to one another.
+
+[Illustration: FIG. 26.]
+
+_Exper._ 15. The Sun shining into a dark Chamber through a little round
+Hole in the Window-shut, let S [in _Fig._ 26.] represent his round white
+Image painted on the opposite Wall by his direct Light, PT his oblong
+coloured Image made by refracting that Light with a Prism placed at the
+Window; and _pt_, or _2p 2t_, _3p 3t_, his oblong colour'd Image made by
+refracting again the same Light sideways with a second Prism placed
+immediately after the first in a cross Position to it, as was explained
+in the fifth Experiment; that is to say, _pt_ when the Refraction of the
+second Prism is small, _2p 2t_ when its Refraction is greater, and _3p
+3t_ when it is greatest. For such will be the diversity of the
+Refractions, if the refracting Angle of the second Prism be of various
+Magnitudes; suppose of fifteen or twenty Degrees to make the Image _pt_,
+of thirty or forty to make the Image _2p 2t_, and of sixty to make the
+Image _3p 3t_. But for want of solid Glass Prisms with Angles of
+convenient Bignesses, there may be Vessels made of polished Plates of
+Glass cemented together in the form of Prisms and filled with Water.
+These things being thus ordered, I observed that all the solar Images or
+coloured Spectrums PT, _pt_, _2p 2t_, _3p 3t_ did very nearly converge
+to the place S on which the direct Light of the Sun fell and painted his
+white round Image when the Prisms were taken away. The Axis of the
+Spectrum PT, that is the Line drawn through the middle of it parallel to
+its rectilinear Sides, did when produced pass exactly through the middle
+of that white round Image S. And when the Refraction of the second Prism
+was equal to the Refraction of the first, the refracting Angles of them
+both being about 60 Degrees, the Axis of the Spectrum _3p 3t_ made by
+that Refraction, did when produced pass also through the middle of the
+same white round Image S. But when the Refraction of the second Prism
+was less than that of the first, the produced Axes of the Spectrums _tp_
+or _2t 2p_ made by that Refraction did cut the produced Axis of the
+Spectrum TP in the points _m_ and _n_, a little beyond the Center of
+that white round Image S. Whence the proportion of the Line 3_t_T to the
+Line 3_p_P was a little greater than the Proportion of 2_t_T or 2_p_P,
+and this Proportion a little greater than that of _t_T to _p_P. Now when
+the Light of the Spectrum PT falls perpendicularly upon the Wall, those
+Lines 3_t_T, 3_p_P, and 2_t_T, and 2_p_P, and _t_T, _p_P, are the
+Tangents of the Refractions, and therefore by this Experiment the
+Proportions of the Tangents of the Refractions are obtained, from whence
+the Proportions of the Sines being derived, they come out equal, so far
+as by viewing the Spectrums, and using some mathematical Reasoning I
+could estimate. For I did not make an accurate Computation. So then the
+Proposition holds true in every Ray apart, so far as appears by
+Experiment. And that it is accurately true, may be demonstrated upon
+this Supposition. _That Bodies refract Light by acting upon its Rays in
+Lines perpendicular to their Surfaces._ But in order to this
+Demonstration, I must distinguish the Motion of every Ray into two
+Motions, the one perpendicular to the refracting Surface, the other
+parallel to it, and concerning the perpendicular Motion lay down the
+following Proposition.
+
+If any Motion or moving thing whatsoever be incident with any Velocity
+on any broad and thin space terminated on both sides by two parallel
+Planes, and in its Passage through that space be urged perpendicularly
+towards the farther Plane by any force which at given distances from the
+Plane is of given Quantities; the perpendicular velocity of that Motion
+or Thing, at its emerging out of that space, shall be always equal to
+the square Root of the sum of the square of the perpendicular velocity
+of that Motion or Thing at its Incidence on that space; and of the
+square of the perpendicular velocity which that Motion or Thing would
+have at its Emergence, if at its Incidence its perpendicular velocity
+was infinitely little.
+
+And the same Proposition holds true of any Motion or Thing
+perpendicularly retarded in its passage through that space, if instead
+of the sum of the two Squares you take their difference. The
+Demonstration Mathematicians will easily find out, and therefore I shall
+not trouble the Reader with it.
+
+Suppose now that a Ray coming most obliquely in the Line MC [in _Fig._
+1.] be refracted at C by the Plane RS into the Line CN, and if it be
+required to find the Line CE, into which any other Ray AC shall be
+refracted; let MC, AD, be the Sines of Incidence of the two Rays, and
+NG, EF, their Sines of Refraction, and let the equal Motions of the
+incident Rays be represented by the equal Lines MC and AC, and the
+Motion MC being considered as parallel to the refracting Plane, let the
+other Motion AC be distinguished into two Motions AD and DC, one of
+which AD is parallel, and the other DC perpendicular to the refracting
+Surface. In like manner, let the Motions of the emerging Rays be
+distinguish'd into two, whereof the perpendicular ones are MC/NG × CG
+and AD/EF × CF. And if the force of the refracting Plane begins to act
+upon the Rays either in that Plane or at a certain distance from it on
+the one side, and ends at a certain distance from it on the other side,
+and in all places between those two limits acts upon the Rays in Lines
+perpendicular to that refracting Plane, and the Actions upon the Rays at
+equal distances from the refracting Plane be equal, and at unequal ones
+either equal or unequal according to any rate whatever; that Motion of
+the Ray which is parallel to the refracting Plane, will suffer no
+Alteration by that Force; and that Motion which is perpendicular to it
+will be altered according to the rule of the foregoing Proposition. If
+therefore for the perpendicular velocity of the emerging Ray CN you
+write MC/NG × CG as above, then the perpendicular velocity of any other
+emerging Ray CE which was AD/EF × CF, will be equal to the square Root
+of CD_q_ + (_MCq/NGq_ × CG_q_). And by squaring these Equals, and adding
+to them the Equals AD_q_ and MC_q_ - CD_q_, and dividing the Sums by the
+Equals CF_q_ + EF_q_ and CG_q_ + NG_q_, you will have _MCq/NGq_ equal to
+_ADq/EFq_. Whence AD, the Sine of Incidence, is to EF the Sine of
+Refraction, as MC to NG, that is, in a given _ratio_. And this
+Demonstration being general, without determining what Light is, or by
+what kind of Force it is refracted, or assuming any thing farther than
+that the refracting Body acts upon the Rays in Lines perpendicular to
+its Surface; I take it to be a very convincing Argument of the full
+truth of this Proposition.
+
+So then, if the _ratio_ of the Sines of Incidence and Refraction of any
+sort of Rays be found in any one case, 'tis given in all cases; and this
+may be readily found by the Method in the following Proposition.
+
+
+_PROP._ VII. THEOR. VI.
+
+_The Perfection of Telescopes is impeded by the different Refrangibility
+of the Rays of Light._
+
+The Imperfection of Telescopes is vulgarly attributed to the spherical
+Figures of the Glasses, and therefore Mathematicians have propounded to
+figure them by the conical Sections. To shew that they are mistaken, I
+have inserted this Proposition; the truth of which will appear by the
+measure of the Refractions of the several sorts of Rays; and these
+measures I thus determine.
+
+In the third Experiment of this first Part, where the refracting Angle
+of the Prism was 62-1/2 Degrees, the half of that Angle 31 deg. 15 min.
+is the Angle of Incidence of the Rays at their going out of the Glass
+into the Air[F]; and the Sine of this Angle is 5188, the Radius being
+10000. When the Axis of this Prism was parallel to the Horizon, and the
+Refraction of the Rays at their Incidence on this Prism equal to that at
+their Emergence out of it, I observed with a Quadrant the Angle which
+the mean refrangible Rays, (that is those which went to the middle of
+the Sun's coloured Image) made with the Horizon, and by this Angle and
+the Sun's altitude observed at the same time, I found the Angle which
+the emergent Rays contained with the incident to be 44 deg. and 40 min.
+and the half of this Angle added to the Angle of Incidence 31 deg. 15
+min. makes the Angle of Refraction, which is therefore 53 deg. 35 min.
+and its Sine 8047. These are the Sines of Incidence and Refraction of
+the mean refrangible Rays, and their Proportion in round Numbers is 20
+to 31. This Glass was of a Colour inclining to green. The last of the
+Prisms mentioned in the third Experiment was of clear white Glass. Its
+refracting Angle 63-1/2 Degrees. The Angle which the emergent Rays
+contained, with the incident 45 deg. 50 min. The Sine of half the first
+Angle 5262. The Sine of half the Sum of the Angles 8157. And their
+Proportion in round Numbers 20 to 31, as before.
+
+From the Length of the Image, which was about 9-3/4 or 10 Inches,
+subduct its Breadth, which was 2-1/8 Inches, and the Remainder 7-3/4
+Inches would be the Length of the Image were the Sun but a Point, and
+therefore subtends the Angle which the most and least refrangible Rays,
+when incident on the Prism in the same Lines, do contain with one
+another after their Emergence. Whence this Angle is 2 deg. 0´. 7´´. For
+the distance between the Image and the Prism where this Angle is made,
+was 18-1/2 Feet, and at that distance the Chord 7-3/4 Inches subtends an
+Angle of 2 deg. 0´. 7´´. Now half this Angle is the Angle which these
+emergent Rays contain with the emergent mean refrangible Rays, and a
+quarter thereof, that is 30´. 2´´. may be accounted the Angle which they
+would contain with the same emergent mean refrangible Rays, were they
+co-incident to them within the Glass, and suffered no other Refraction
+than that at their Emergence. For, if two equal Refractions, the one at
+the Incidence of the Rays on the Prism, the other at their Emergence,
+make half the Angle 2 deg. 0´. 7´´. then one of those Refractions will
+make about a quarter of that Angle, and this quarter added to, and
+subducted from the Angle of Refraction of the mean refrangible Rays,
+which was 53 deg. 35´, gives the Angles of Refraction of the most and
+least refrangible Rays 54 deg. 5´ 2´´, and 53 deg. 4´ 58´´, whose Sines
+are 8099 and 7995, the common Angle of Incidence being 31 deg. 15´, and
+its Sine 5188; and these Sines in the least round Numbers are in
+proportion to one another, as 78 and 77 to 50.
+
+Now, if you subduct the common Sine of Incidence 50 from the Sines of
+Refraction 77 and 78, the Remainders 27 and 28 shew, that in small
+Refractions the Refraction of the least refrangible Rays is to the
+Refraction of the most refrangible ones, as 27 to 28 very nearly, and
+that the difference of the Refractions of the least refrangible and most
+refrangible Rays is about the 27-1/2th Part of the whole Refraction of
+the mean refrangible Rays.
+
+Whence they that are skilled in Opticks will easily understand,[G] that
+the Breadth of the least circular Space, into which Object-glasses of
+Telescopes can collect all sorts of Parallel Rays, is about the 27-1/2th
+Part of half the Aperture of the Glass, or 55th Part of the whole
+Aperture; and that the Focus of the most refrangible Rays is nearer to
+the Object-glass than the Focus of the least refrangible ones, by about
+the 27-1/2th Part of the distance between the Object-glass and the Focus
+of the mean refrangible ones.
+
+And if Rays of all sorts, flowing from any one lucid Point in the Axis
+of any convex Lens, be made by the Refraction of the Lens to converge to
+Points not too remote from the Lens, the Focus of the most refrangible
+Rays shall be nearer to the Lens than the Focus of the least refrangible
+ones, by a distance which is to the 27-1/2th Part of the distance of the
+Focus of the mean refrangible Rays from the Lens, as the distance
+between that Focus and the lucid Point, from whence the Rays flow, is to
+the distance between that lucid Point and the Lens very nearly.
+
+Now to examine whether the Difference between the Refractions, which the
+most refrangible and the least refrangible Rays flowing from the same
+Point suffer in the Object-glasses of Telescopes and such-like Glasses,
+be so great as is here described, I contrived the following Experiment.
+
+_Exper._ 16. The Lens which I used in the second and eighth Experiments,
+being placed six Feet and an Inch distant from any Object, collected the
+Species of that Object by the mean refrangible Rays at the distance of
+six Feet and an Inch from the Lens on the other side. And therefore by
+the foregoing Rule, it ought to collect the Species of that Object by
+the least refrangible Rays at the distance of six Feet and 3-2/3 Inches
+from the Lens, and by the most refrangible ones at the distance of five
+Feet and 10-1/3 Inches from it: So that between the two Places, where
+these least and most refrangible Rays collect the Species, there may be
+the distance of about 5-1/3 Inches. For by that Rule, as six Feet and an
+Inch (the distance of the Lens from the lucid Object) is to twelve Feet
+and two Inches (the distance of the lucid Object from the Focus of the
+mean refrangible Rays) that is, as One is to Two; so is the 27-1/2th
+Part of six Feet and an Inch (the distance between the Lens and the same
+Focus) to the distance between the Focus of the most refrangible Rays
+and the Focus of the least refrangible ones, which is therefore 5-17/55
+Inches, that is very nearly 5-1/3 Inches. Now to know whether this
+Measure was true, I repeated the second and eighth Experiment with
+coloured Light, which was less compounded than that I there made use of:
+For I now separated the heterogeneous Rays from one another by the
+Method I described in the eleventh Experiment, so as to make a coloured
+Spectrum about twelve or fifteen Times longer than broad. This Spectrum
+I cast on a printed Book, and placing the above-mentioned Lens at the
+distance of six Feet and an Inch from this Spectrum to collect the
+Species of the illuminated Letters at the same distance on the other
+side, I found that the Species of the Letters illuminated with blue were
+nearer to the Lens than those illuminated with deep red by about three
+Inches, or three and a quarter; but the Species of the Letters
+illuminated with indigo and violet appeared so confused and indistinct,
+that I could not read them: Whereupon viewing the Prism, I found it was
+full of Veins running from one end of the Glass to the other; so that
+the Refraction could not be regular. I took another Prism therefore
+which was free from Veins, and instead of the Letters I used two or
+three Parallel black Lines a little broader than the Strokes of the
+Letters, and casting the Colours upon these Lines in such manner, that
+the Lines ran along the Colours from one end of the Spectrum to the
+other, I found that the Focus where the indigo, or confine of this
+Colour and violet cast the Species of the black Lines most distinctly,
+to be about four Inches, or 4-1/4 nearer to the Lens than the Focus,
+where the deepest red cast the Species of the same black Lines most
+distinctly. The violet was so faint and dark, that I could not discern
+the Species of the Lines distinctly by that Colour; and therefore
+considering that the Prism was made of a dark coloured Glass inclining
+to green, I took another Prism of clear white Glass; but the Spectrum of
+Colours which this Prism made had long white Streams of faint Light
+shooting out from both ends of the Colours, which made me conclude that
+something was amiss; and viewing the Prism, I found two or three little
+Bubbles in the Glass, which refracted the Light irregularly. Wherefore I
+covered that Part of the Glass with black Paper, and letting the Light
+pass through another Part of it which was free from such Bubbles, the
+Spectrum of Colours became free from those irregular Streams of Light,
+and was now such as I desired. But still I found the violet so dark and
+faint, that I could scarce see the Species of the Lines by the violet,
+and not at all by the deepest Part of it, which was next the end of the
+Spectrum. I suspected therefore, that this faint and dark Colour might
+be allayed by that scattering Light which was refracted, and reflected
+irregularly, partly by some very small Bubbles in the Glasses, and
+partly by the Inequalities of their Polish; which Light, tho' it was but
+little, yet it being of a white Colour, might suffice to affect the
+Sense so strongly as to disturb the Phænomena of that weak and dark
+Colour the violet, and therefore I tried, as in the 12th, 13th, and 14th
+Experiments, whether the Light of this Colour did not consist of a
+sensible Mixture of heterogeneous Rays, but found it did not. Nor did
+the Refractions cause any other sensible Colour than violet to emerge
+out of this Light, as they would have done out of white Light, and by
+consequence out of this violet Light had it been sensibly compounded
+with white Light. And therefore I concluded, that the reason why I could
+not see the Species of the Lines distinctly by this Colour, was only
+the Darkness of this Colour, and Thinness of its Light, and its distance
+from the Axis of the Lens; I divided therefore those Parallel black
+Lines into equal Parts, by which I might readily know the distances of
+the Colours in the Spectrum from one another, and noted the distances of
+the Lens from the Foci of such Colours, as cast the Species of the Lines
+distinctly, and then considered whether the difference of those
+distances bear such proportion to 5-1/3 Inches, the greatest Difference
+of the distances, which the Foci of the deepest red and violet ought to
+have from the Lens, as the distance of the observed Colours from one
+another in the Spectrum bear to the greatest distance of the deepest red
+and violet measured in the Rectilinear Sides of the Spectrum, that is,
+to the Length of those Sides, or Excess of the Length of the Spectrum
+above its Breadth. And my Observations were as follows.
+
+When I observed and compared the deepest sensible red, and the Colour in
+the Confine of green and blue, which at the Rectilinear Sides of the
+Spectrum was distant from it half the Length of those Sides, the Focus
+where the Confine of green and blue cast the Species of the Lines
+distinctly on the Paper, was nearer to the Lens than the Focus, where
+the red cast those Lines distinctly on it by about 2-1/2 or 2-3/4
+Inches. For sometimes the Measures were a little greater, sometimes a
+little less, but seldom varied from one another above 1/3 of an Inch.
+For it was very difficult to define the Places of the Foci, without some
+little Errors. Now, if the Colours distant half the Length of the
+Image, (measured at its Rectilinear Sides) give 2-1/2 or 2-3/4
+Difference of the distances of their Foci from the Lens, then the
+Colours distant the whole Length ought to give 5 or 5-1/2 Inches
+difference of those distances.
+
+But here it's to be noted, that I could not see the red to the full end
+of the Spectrum, but only to the Center of the Semicircle which bounded
+that end, or a little farther; and therefore I compared this red not
+with that Colour which was exactly in the middle of the Spectrum, or
+Confine of green and blue, but with that which verged a little more to
+the blue than to the green: And as I reckoned the whole Length of the
+Colours not to be the whole Length of the Spectrum, but the Length of
+its Rectilinear Sides, so compleating the semicircular Ends into
+Circles, when either of the observed Colours fell within those Circles,
+I measured the distance of that Colour from the semicircular End of the
+Spectrum, and subducting half this distance from the measured distance
+of the two Colours, I took the Remainder for their corrected distance;
+and in these Observations set down this corrected distance for the
+difference of the distances of their Foci from the Lens. For, as the
+Length of the Rectilinear Sides of the Spectrum would be the whole
+Length of all the Colours, were the Circles of which (as we shewed) that
+Spectrum consists contracted and reduced to Physical Points, so in that
+Case this corrected distance would be the real distance of the two
+observed Colours.
+
+When therefore I farther observed the deepest sensible red, and that
+blue whose corrected distance from it was 7/12 Parts of the Length of
+the Rectilinear Sides of the Spectrum, the difference of the distances
+of their Foci from the Lens was about 3-1/4 Inches, and as 7 to 12, so
+is 3-1/4 to 5-4/7.
+
+When I observed the deepest sensible red, and that indigo whose
+corrected distance was 8/12 or 2/3 of the Length of the Rectilinear
+Sides of the Spectrum, the difference of the distances of their Foci
+from the Lens, was about 3-2/3 Inches, and as 2 to 3, so is 3-2/3 to
+5-1/2.
+
+When I observed the deepest sensible red, and that deep indigo whose
+corrected distance from one another was 9/12 or 3/4 of the Length of the
+Rectilinear Sides of the Spectrum, the difference of the distances of
+their Foci from the Lens was about 4 Inches; and as 3 to 4, so is 4 to
+5-1/3.
+
+When I observed the deepest sensible red, and that Part of the violet
+next the indigo, whose corrected distance from the red was 10/12 or 5/6
+of the Length of the Rectilinear Sides of the Spectrum, the difference
+of the distances of their Foci from the Lens was about 4-1/2 Inches, and
+as 5 to 6, so is 4-1/2 to 5-2/5. For sometimes, when the Lens was
+advantageously placed, so that its Axis respected the blue, and all
+Things else were well ordered, and the Sun shone clear, and I held my
+Eye very near to the Paper on which the Lens cast the Species of the
+Lines, I could see pretty distinctly the Species of those Lines by that
+Part of the violet which was next the indigo; and sometimes I could see
+them by above half the violet, For in making these Experiments I had
+observed, that the Species of those Colours only appear distinct, which
+were in or near the Axis of the Lens: So that if the blue or indigo were
+in the Axis, I could see their Species distinctly; and then the red
+appeared much less distinct than before. Wherefore I contrived to make
+the Spectrum of Colours shorter than before, so that both its Ends might
+be nearer to the Axis of the Lens. And now its Length was about 2-1/2
+Inches, and Breadth about 1/5 or 1/6 of an Inch. Also instead of the
+black Lines on which the Spectrum was cast, I made one black Line
+broader than those, that I might see its Species more easily; and this
+Line I divided by short cross Lines into equal Parts, for measuring the
+distances of the observed Colours. And now I could sometimes see the
+Species of this Line with its Divisions almost as far as the Center of
+the semicircular violet End of the Spectrum, and made these farther
+Observations.
+
+When I observed the deepest sensible red, and that Part of the violet,
+whose corrected distance from it was about 8/9 Parts of the Rectilinear
+Sides of the Spectrum, the Difference of the distances of the Foci of
+those Colours from the Lens, was one time 4-2/3, another time 4-3/4,
+another time 4-7/8 Inches; and as 8 to 9, so are 4-2/3, 4-3/4, 4-7/8, to
+5-1/4, 5-11/32, 5-31/64 respectively.
+
+When I observed the deepest sensible red, and deepest sensible violet,
+(the corrected distance of which Colours, when all Things were ordered
+to the best Advantage, and the Sun shone very clear, was about 11/12 or
+15/16 Parts of the Length of the Rectilinear Sides of the coloured
+Spectrum) I found the Difference of the distances of their Foci from the
+Lens sometimes 4-3/4 sometimes 5-1/4, and for the most part 5 Inches or
+thereabouts; and as 11 to 12, or 15 to 16, so is five Inches to 5-2/2 or
+5-1/3 Inches.
+
+And by this Progression of Experiments I satisfied my self, that had the
+Light at the very Ends of the Spectrum been strong enough to make the
+Species of the black Lines appear plainly on the Paper, the Focus of the
+deepest violet would have been found nearer to the Lens, than the Focus
+of the deepest red, by about 5-1/3 Inches at least. And this is a
+farther Evidence, that the Sines of Incidence and Refraction of the
+several sorts of Rays, hold the same Proportion to one another in the
+smallest Refractions which they do in the greatest.
+
+My Progress in making this nice and troublesome Experiment I have set
+down more at large, that they that shall try it after me may be aware of
+the Circumspection requisite to make it succeed well. And if they cannot
+make it succeed so well as I did, they may notwithstanding collect by
+the Proportion of the distance of the Colours of the Spectrum, to the
+Difference of the distances of their Foci from the Lens, what would be
+the Success in the more distant Colours by a better trial. And yet, if
+they use a broader Lens than I did, and fix it to a long strait Staff,
+by means of which it may be readily and truly directed to the Colour
+whose Focus is desired, I question not but the Experiment will succeed
+better with them than it did with me. For I directed the Axis as nearly
+as I could to the middle of the Colours, and then the faint Ends of the
+Spectrum being remote from the Axis, cast their Species less distinctly
+on the Paper than they would have done, had the Axis been successively
+directed to them.
+
+Now by what has been said, it's certain that the Rays which differ in
+Refrangibility do not converge to the same Focus; but if they flow from
+a lucid Point, as far from the Lens on one side as their Foci are on the
+other, the Focus of the most refrangible Rays shall be nearer to the
+Lens than that of the least refrangible, by above the fourteenth Part of
+the whole distance; and if they flow from a lucid Point, so very remote
+from the Lens, that before their Incidence they may be accounted
+parallel, the Focus of the most refrangible Rays shall be nearer to the
+Lens than the Focus of the least refrangible, by about the 27th or 28th
+Part of their whole distance from it. And the Diameter of the Circle in
+the middle Space between those two Foci which they illuminate, when they
+fall there on any Plane, perpendicular to the Axis (which Circle is the
+least into which they can all be gathered) is about the 55th Part of the
+Diameter of the Aperture of the Glass. So that 'tis a wonder, that
+Telescopes represent Objects so distinct as they do. But were all the
+Rays of Light equally refrangible, the Error arising only from the
+Sphericalness of the Figures of Glasses would be many hundred times
+less. For, if the Object-glass of a Telescope be Plano-convex, and the
+Plane side be turned towards the Object, and the Diameter of the
+Sphere, whereof this Glass is a Segment, be called D, and the
+Semi-diameter of the Aperture of the Glass be called S, and the Sine of
+Incidence out of Glass into Air, be to the Sine of Refraction as I to R;
+the Rays which come parallel to the Axis of the Glass, shall in the
+Place where the Image of the Object is most distinctly made, be
+scattered all over a little Circle, whose Diameter is _(Rq/Iq) × (S
+cub./D quad.)_ very nearly,[H] as I gather by computing the Errors of
+the Rays by the Method of infinite Series, and rejecting the Terms,
+whose Quantities are inconsiderable. As for instance, if the Sine of
+Incidence I, be to the Sine of Refraction R, as 20 to 31, and if D the
+Diameter of the Sphere, to which the Convex-side of the Glass is ground,
+be 100 Feet or 1200 Inches, and S the Semi-diameter of the Aperture be
+two Inches, the Diameter of the little Circle, (that is (_Rq × S
+cub.)/(Iq × D quad._)) will be (31 × 31 × 8)/(20 × 20 × 1200 × 1200) (or
+961/72000000) Parts of an Inch. But the Diameter of the little Circle,
+through which these Rays are scattered by unequal Refrangibility, will
+be about the 55th Part of the Aperture of the Object-glass, which here
+is four Inches. And therefore, the Error arising from the Spherical
+Figure of the Glass, is to the Error arising from the different
+Refrangibility of the Rays, as 961/72000000 to 4/55, that is as 1 to
+5449; and therefore being in comparison so very little, deserves not to
+be considered.
+
+[Illustration: FIG. 27.]
+
+But you will say, if the Errors caused by the different Refrangibility
+be so very great, how comes it to pass, that Objects appear through
+Telescopes so distinct as they do? I answer, 'tis because the erring
+Rays are not scattered uniformly over all that Circular Space, but
+collected infinitely more densely in the Center than in any other Part
+of the Circle, and in the Way from the Center to the Circumference, grow
+continually rarer and rarer, so as at the Circumference to become
+infinitely rare; and by reason of their Rarity are not strong enough to
+be visible, unless in the Center and very near it. Let ADE [in _Fig._
+27.] represent one of those Circles described with the Center C, and
+Semi-diameter AC, and let BFG be a smaller Circle concentrick to the
+former, cutting with its Circumference the Diameter AC in B, and bisect
+AC in N; and by my reckoning, the Density of the Light in any Place B,
+will be to its Density in N, as AB to BC; and the whole Light within the
+lesser Circle BFG, will be to the whole Light within the greater AED, as
+the Excess of the Square of AC above the Square of AB, is to the Square
+of AC. As if BC be the fifth Part of AC, the Light will be four times
+denser in B than in N, and the whole Light within the less Circle, will
+be to the whole Light within the greater, as nine to twenty-five. Whence
+it's evident, that the Light within the less Circle, must strike the
+Sense much more strongly, than that faint and dilated Light round about
+between it and the Circumference of the greater.
+
+But it's farther to be noted, that the most luminous of the Prismatick
+Colours are the yellow and orange. These affect the Senses more strongly
+than all the rest together, and next to these in strength are the red
+and green. The blue compared with these is a faint and dark Colour, and
+the indigo and violet are much darker and fainter, so that these
+compared with the stronger Colours are little to be regarded. The Images
+of Objects are therefore to be placed, not in the Focus of the mean
+refrangible Rays, which are in the Confine of green and blue, but in the
+Focus of those Rays which are in the middle of the orange and yellow;
+there where the Colour is most luminous and fulgent, that is in the
+brightest yellow, that yellow which inclines more to orange than to
+green. And by the Refraction of these Rays (whose Sines of Incidence and
+Refraction in Glass are as 17 and 11) the Refraction of Glass and
+Crystal for Optical Uses is to be measured. Let us therefore place the
+Image of the Object in the Focus of these Rays, and all the yellow and
+orange will fall within a Circle, whose Diameter is about the 250th
+Part of the Diameter of the Aperture of the Glass. And if you add the
+brighter half of the red, (that half which is next the orange) and the
+brighter half of the green, (that half which is next the yellow) about
+three fifth Parts of the Light of these two Colours will fall within the
+same Circle, and two fifth Parts will fall without it round about; and
+that which falls without will be spread through almost as much more
+space as that which falls within, and so in the gross be almost three
+times rarer. Of the other half of the red and green, (that is of the
+deep dark red and willow green) about one quarter will fall within this
+Circle, and three quarters without, and that which falls without will be
+spread through about four or five times more space than that which falls
+within; and so in the gross be rarer, and if compared with the whole
+Light within it, will be about 25 times rarer than all that taken in the
+gross; or rather more than 30 or 40 times rarer, because the deep red in
+the end of the Spectrum of Colours made by a Prism is very thin and
+rare, and the willow green is something rarer than the orange and
+yellow. The Light of these Colours therefore being so very much rarer
+than that within the Circle, will scarce affect the Sense, especially
+since the deep red and willow green of this Light, are much darker
+Colours than the rest. And for the same reason the blue and violet being
+much darker Colours than these, and much more rarified, may be
+neglected. For the dense and bright Light of the Circle, will obscure
+the rare and weak Light of these dark Colours round about it, and
+render them almost insensible. The sensible Image of a lucid Point is
+therefore scarce broader than a Circle, whose Diameter is the 250th Part
+of the Diameter of the Aperture of the Object-glass of a good Telescope,
+or not much broader, if you except a faint and dark misty Light round
+about it, which a Spectator will scarce regard. And therefore in a
+Telescope, whose Aperture is four Inches, and Length an hundred Feet, it
+exceeds not 2´´ 45´´´, or 3´´. And in a Telescope whose Aperture is two
+Inches, and Length 20 or 30 Feet, it may be 5´´ or 6´´, and scarce
+above. And this answers well to Experience: For some Astronomers have
+found the Diameters of the fix'd Stars, in Telescopes of between 20 and
+60 Feet in length, to be about 5´´ or 6´´, or at most 8´´ or 10´´ in
+diameter. But if the Eye-Glass be tincted faintly with the Smoak of a
+Lamp or Torch, to obscure the Light of the Star, the fainter Light in
+the Circumference of the Star ceases to be visible, and the Star (if the
+Glass be sufficiently soiled with Smoak) appears something more like a
+mathematical Point. And for the same Reason, the enormous Part of the
+Light in the Circumference of every lucid Point ought to be less
+discernible in shorter Telescopes than in longer, because the shorter
+transmit less Light to the Eye.
+
+Now, that the fix'd Stars, by reason of their immense Distance, appear
+like Points, unless so far as their Light is dilated by Refraction, may
+appear from hence; that when the Moon passes over them and eclipses
+them, their Light vanishes, not gradually like that of the Planets, but
+all at once; and in the end of the Eclipse it returns into Sight all at
+once, or certainly in less time than the second of a Minute; the
+Refraction of the Moon's Atmosphere a little protracting the time in
+which the Light of the Star first vanishes, and afterwards returns into
+Sight.
+
+Now, if we suppose the sensible Image of a lucid Point, to be even 250
+times narrower than the Aperture of the Glass; yet this Image would be
+still much greater than if it were only from the spherical Figure of the
+Glass. For were it not for the different Refrangibility of the Rays, its
+breadth in an 100 Foot Telescope whose aperture is 4 Inches, would be
+but 961/72000000 parts of an Inch, as is manifest by the foregoing
+Computation. And therefore in this case the greatest Errors arising from
+the spherical Figure of the Glass, would be to the greatest sensible
+Errors arising from the different Refrangibility of the Rays as
+961/72000000 to 4/250 at most, that is only as 1 to 1200. And this
+sufficiently shews that it is not the spherical Figures of Glasses, but
+the different Refrangibility of the Rays which hinders the perfection of
+Telescopes.
+
+There is another Argument by which it may appear that the different
+Refrangibility of Rays, is the true cause of the imperfection of
+Telescopes. For the Errors of the Rays arising from the spherical
+Figures of Object-glasses, are as the Cubes of the Apertures of the
+Object Glasses; and thence to make Telescopes of various Lengths magnify
+with equal distinctness, the Apertures of the Object-glasses, and the
+Charges or magnifying Powers ought to be as the Cubes of the square
+Roots of their lengths; which doth not answer to Experience. But the
+Errors of the Rays arising from the different Refrangibility, are as the
+Apertures of the Object-glasses; and thence to make Telescopes of
+various lengths, magnify with equal distinctness, their Apertures and
+Charges ought to be as the square Roots of their lengths; and this
+answers to Experience, as is well known. For Instance, a Telescope of 64
+Feet in length, with an Aperture of 2-2/3 Inches, magnifies about 120
+times, with as much distinctness as one of a Foot in length, with 1/3 of
+an Inch aperture, magnifies 15 times.
+
+[Illustration: FIG. 28.]
+
+Now were it not for this different Refrangibility of Rays, Telescopes
+might be brought to a greater perfection than we have yet describ'd, by
+composing the Object-glass of two Glasses with Water between them. Let
+ADFC [in _Fig._ 28.] represent the Object-glass composed of two Glasses
+ABED and BEFC, alike convex on the outsides AGD and CHF, and alike
+concave on the insides BME, BNE, with Water in the concavity BMEN. Let
+the Sine of Incidence out of Glass into Air be as I to R, and out of
+Water into Air, as K to R, and by consequence out of Glass into Water,
+as I to K: and let the Diameter of the Sphere to which the convex sides
+AGD and CHF are ground be D, and the Diameter of the Sphere to which the
+concave sides BME and BNE, are ground be to D, as the Cube Root of
+KK--KI to the Cube Root of RK--RI: and the Refractions on the concave
+sides of the Glasses, will very much correct the Errors of the
+Refractions on the convex sides, so far as they arise from the
+sphericalness of the Figure. And by this means might Telescopes be
+brought to sufficient perfection, were it not for the different
+Refrangibility of several sorts of Rays. But by reason of this different
+Refrangibility, I do not yet see any other means of improving Telescopes
+by Refractions alone, than that of increasing their lengths, for which
+end the late Contrivance of _Hugenius_ seems well accommodated. For very
+long Tubes are cumbersome, and scarce to be readily managed, and by
+reason of their length are very apt to bend, and shake by bending, so as
+to cause a continual trembling in the Objects, whereby it becomes
+difficult to see them distinctly: whereas by his Contrivance the Glasses
+are readily manageable, and the Object-glass being fix'd upon a strong
+upright Pole becomes more steady.
+
+Seeing therefore the Improvement of Telescopes of given lengths by
+Refractions is desperate; I contrived heretofore a Perspective by
+Reflexion, using instead of an Object-glass a concave Metal. The
+diameter of the Sphere to which the Metal was ground concave was about
+25 _English_ Inches, and by consequence the length of the Instrument
+about six Inches and a quarter. The Eye-glass was Plano-convex, and the
+diameter of the Sphere to which the convex side was ground was about 1/5
+of an Inch, or a little less, and by consequence it magnified between 30
+and 40 times. By another way of measuring I found that it magnified
+about 35 times. The concave Metal bore an Aperture of an Inch and a
+third part; but the Aperture was limited not by an opake Circle,
+covering the Limb of the Metal round about, but by an opake Circle
+placed between the Eyeglass and the Eye, and perforated in the middle
+with a little round hole for the Rays to pass through to the Eye. For
+this Circle by being placed here, stopp'd much of the erroneous Light,
+which otherwise would have disturbed the Vision. By comparing it with a
+pretty good Perspective of four Feet in length, made with a concave
+Eye-glass, I could read at a greater distance with my own Instrument
+than with the Glass. Yet Objects appeared much darker in it than in the
+Glass, and that partly because more Light was lost by Reflexion in the
+Metal, than by Refraction in the Glass, and partly because my Instrument
+was overcharged. Had it magnified but 30 or 25 times, it would have made
+the Object appear more brisk and pleasant. Two of these I made about 16
+Years ago, and have one of them still by me, by which I can prove the
+truth of what I write. Yet it is not so good as at the first. For the
+concave has been divers times tarnished and cleared again, by rubbing
+it with very soft Leather. When I made these an Artist in _London_
+undertook to imitate it; but using another way of polishing them than I
+did, he fell much short of what I had attained to, as I afterwards
+understood by discoursing the Under-workman he had employed. The Polish
+I used was in this manner. I had two round Copper Plates, each six
+Inches in Diameter, the one convex, the other concave, ground very true
+to one another. On the convex I ground the Object-Metal or Concave which
+was to be polish'd, 'till it had taken the Figure of the Convex and was
+ready for a Polish. Then I pitched over the convex very thinly, by
+dropping melted Pitch upon it, and warming it to keep the Pitch soft,
+whilst I ground it with the concave Copper wetted to make it spread
+eavenly all over the convex. Thus by working it well I made it as thin
+as a Groat, and after the convex was cold I ground it again to give it
+as true a Figure as I could. Then I took Putty which I had made very
+fine by washing it from all its grosser Particles, and laying a little
+of this upon the Pitch, I ground it upon the Pitch with the concave
+Copper, till it had done making a Noise; and then upon the Pitch I
+ground the Object-Metal with a brisk motion, for about two or three
+Minutes of time, leaning hard upon it. Then I put fresh Putty upon the
+Pitch, and ground it again till it had done making a noise, and
+afterwards ground the Object-Metal upon it as before. And this Work I
+repeated till the Metal was polished, grinding it the last time with all
+my strength for a good while together, and frequently breathing upon
+the Pitch, to keep it moist without laying on any more fresh Putty. The
+Object-Metal was two Inches broad, and about one third part of an Inch
+thick, to keep it from bending. I had two of these Metals, and when I
+had polished them both, I tried which was best, and ground the other
+again, to see if I could make it better than that which I kept. And thus
+by many Trials I learn'd the way of polishing, till I made those two
+reflecting Perspectives I spake of above. For this Art of polishing will
+be better learn'd by repeated Practice than by my Description. Before I
+ground the Object-Metal on the Pitch, I always ground the Putty on it
+with the concave Copper, till it had done making a noise, because if the
+Particles of the Putty were not by this means made to stick fast in the
+Pitch, they would by rolling up and down grate and fret the Object-Metal
+and fill it full of little holes.
+
+But because Metal is more difficult to polish than Glass, and is
+afterwards very apt to be spoiled by tarnishing, and reflects not so
+much Light as Glass quick-silver'd over does: I would propound to use
+instead of the Metal, a Glass ground concave on the foreside, and as
+much convex on the backside, and quick-silver'd over on the convex side.
+The Glass must be every where of the same thickness exactly. Otherwise
+it will make Objects look colour'd and indistinct. By such a Glass I
+tried about five or six Years ago to make a reflecting Telescope of four
+Feet in length to magnify about 150 times, and I satisfied my self that
+there wants nothing but a good Artist to bring the Design to
+perfection. For the Glass being wrought by one of our _London_ Artists
+after such a manner as they grind Glasses for Telescopes, though it
+seemed as well wrought as the Object-glasses use to be, yet when it was
+quick-silver'd, the Reflexion discovered innumerable Inequalities all
+over the Glass. And by reason of these Inequalities, Objects appeared
+indistinct in this Instrument. For the Errors of reflected Rays caused
+by any Inequality of the Glass, are about six times greater than the
+Errors of refracted Rays caused by the like Inequalities. Yet by this
+Experiment I satisfied my self that the Reflexion on the concave side of
+the Glass, which I feared would disturb the Vision, did no sensible
+prejudice to it, and by consequence that nothing is wanting to perfect
+these Telescopes, but good Workmen who can grind and polish Glasses
+truly spherical. An Object-glass of a fourteen Foot Telescope, made by
+an Artificer at _London_, I once mended considerably, by grinding it on
+Pitch with Putty, and leaning very easily on it in the grinding, lest
+the Putty should scratch it. Whether this way may not do well enough for
+polishing these reflecting Glasses, I have not yet tried. But he that
+shall try either this or any other way of polishing which he may think
+better, may do well to make his Glasses ready for polishing, by grinding
+them without that Violence, wherewith our _London_ Workmen press their
+Glasses in grinding. For by such violent pressure, Glasses are apt to
+bend a little in the grinding, and such bending will certainly spoil
+their Figure. To recommend therefore the consideration of these
+reflecting Glasses to such Artists as are curious in figuring Glasses, I
+shall describe this optical Instrument in the following Proposition.
+
+
+_PROP._ VIII. PROB. II.
+
+_To shorten Telescopes._
+
+Let ABCD [in _Fig._ 29.] represent a Glass spherically concave on the
+foreside AB, and as much convex on the backside CD, so that it be every
+where of an equal thickness. Let it not be thicker on one side than on
+the other, lest it make Objects appear colour'd and indistinct, and let
+it be very truly wrought and quick-silver'd over on the backside; and
+set in the Tube VXYZ which must be very black within. Let EFG represent
+a Prism of Glass or Crystal placed near the other end of the Tube, in
+the middle of it, by means of a handle of Brass or Iron FGK, to the end
+of which made flat it is cemented. Let this Prism be rectangular at E,
+and let the other two Angles at F and G be accurately equal to each
+other, and by consequence equal to half right ones, and let the plane
+sides FE and GE be square, and by consequence the third side FG a
+rectangular Parallelogram, whose length is to its breadth in a
+subduplicate proportion of two to one. Let it be so placed in the Tube,
+that the Axis of the Speculum may pass through the middle of the square
+side EF perpendicularly and by consequence through the middle of the
+side FG at an Angle of 45 Degrees, and let the side EF be turned towards
+the Speculum, and the distance of this Prism from the Speculum be such
+that the Rays of the Light PQ, RS, &c. which are incident upon the
+Speculum in Lines parallel to the Axis thereof, may enter the Prism at
+the side EF, and be reflected by the side FG, and thence go out of it
+through the side GE, to the Point T, which must be the common Focus of
+the Speculum ABDC, and of a Plano-convex Eye-glass H, through which
+those Rays must pass to the Eye. And let the Rays at their coming out of
+the Glass pass through a small round hole, or aperture made in a little
+plate of Lead, Brass, or Silver, wherewith the Glass is to be covered,
+which hole must be no bigger than is necessary for Light enough to pass
+through. For so it will render the Object distinct, the Plate in which
+'tis made intercepting all the erroneous part of the Light which comes
+from the verges of the Speculum AB. Such an Instrument well made, if it
+be six Foot long, (reckoning the length from the Speculum to the Prism,
+and thence to the Focus T) will bear an aperture of six Inches at the
+Speculum, and magnify between two and three hundred times. But the hole
+H here limits the aperture with more advantage, than if the aperture was
+placed at the Speculum. If the Instrument be made longer or shorter, the
+aperture must be in proportion as the Cube of the square-square Root of
+the length, and the magnifying as the aperture. But it's convenient that
+the Speculum be an Inch or two broader than the aperture at the least,
+and that the Glass of the Speculum be thick, that it bend not in the
+working. The Prism EFG must be no bigger than is necessary, and its back
+side FG must not be quick-silver'd over. For without quicksilver it will
+reflect all the Light incident on it from the Speculum.
+
+[Illustration: FIG. 29.]
+
+In this Instrument the Object will be inverted, but may be erected by
+making the square sides FF and EG of the Prism EFG not plane but
+spherically convex, that the Rays may cross as well before they come at
+it as afterwards between it and the Eye-glass. If it be desired that the
+Instrument bear a larger aperture, that may be also done by composing
+the Speculum of two Glasses with Water between them.
+
+If the Theory of making Telescopes could at length be fully brought into
+Practice, yet there would be certain Bounds beyond which Telescopes
+could not perform. For the Air through which we look upon the Stars, is
+in a perpetual Tremor; as may be seen by the tremulous Motion of Shadows
+cast from high Towers, and by the twinkling of the fix'd Stars. But
+these Stars do not twinkle when viewed through Telescopes which have
+large apertures. For the Rays of Light which pass through divers parts
+of the aperture, tremble each of them apart, and by means of their
+various and sometimes contrary Tremors, fall at one and the same time
+upon different points in the bottom of the Eye, and their trembling
+Motions are too quick and confused to be perceived severally. And all
+these illuminated Points constitute one broad lucid Point, composed of
+those many trembling Points confusedly and insensibly mixed with one
+another by very short and swift Tremors, and thereby cause the Star to
+appear broader than it is, and without any trembling of the whole. Long
+Telescopes may cause Objects to appear brighter and larger than short
+ones can do, but they cannot be so formed as to take away that confusion
+of the Rays which arises from the Tremors of the Atmosphere. The only
+Remedy is a most serene and quiet Air, such as may perhaps be found on
+the tops of the highest Mountains above the grosser Clouds.
+
+FOOTNOTES:
+
+[C] _See our_ Author's Lectiones Opticæ § 10. _Sect. II. § 29. and Sect.
+III. Prop. 25._
+
+[D] See our Author's _Lectiones Opticæ_, Part. I. Sect. 1. §5.
+
+[E] _This is very fully treated of in our_ Author's Lect. Optic. _Part_
+I. _Sect._ II.
+
+[F] _See our_ Author's Lect. Optic. Part I. Sect. II. § 29.
+
+[G] _This is demonstrated in our_ Author's Lect. Optic. _Part_ I.
+_Sect._ IV. _Prop._ 37.
+
+[H] _How to do this, is shewn in our_ Author's Lect. Optic. _Part_ I.
+_Sect._ IV. _Prop._ 31.
+
+
+
+
+THE FIRST BOOK OF OPTICKS
+
+
+
+
+_PART II._
+
+
+_PROP._ I. THEOR. I.
+
+_The Phænomena of Colours in refracted or reflected Light are not caused
+by new Modifications of the Light variously impress'd, according to the
+various Terminations of the Light and Shadow_.
+
+The PROOF by Experiments.
+
+_Exper._ 1. For if the Sun shine into a very dark Chamber through an
+oblong hole F, [in _Fig._ 1.] whose breadth is the sixth or eighth part
+of an Inch, or something less; and his beam FH do afterwards pass first
+through a very large Prism ABC, distant about 20 Feet from the hole, and
+parallel to it, and then (with its white part) through an oblong hole H,
+whose breadth is about the fortieth or sixtieth part of an Inch, and
+which is made in a black opake Body GI, and placed at the distance of
+two or three Feet from the Prism, in a parallel Situation both to the
+Prism and to the former hole, and if this white Light thus transmitted
+through the hole H, fall afterwards upon a white Paper _pt_, placed
+after that hole H, at the distance of three or four Feet from it, and
+there paint the usual Colours of the Prism, suppose red at _t_, yellow
+at _s_, green at _r_, blue at _q_, and violet at _p_; you may with an
+Iron Wire, or any such like slender opake Body, whose breadth is about
+the tenth part of an Inch, by intercepting the Rays at _k_, _l_, _m_,
+_n_ or _o_, take away any one of the Colours at _t_, _s_, _r_, _q_ or
+_p_, whilst the other Colours remain upon the Paper as before; or with
+an Obstacle something bigger you may take away any two, or three, or
+four Colours together, the rest remaining: So that any one of the
+Colours as well as violet may become outmost in the Confine of the
+Shadow towards _p_, and any one of them as well as red may become
+outmost in the Confine of the Shadow towards _t_, and any one of them
+may also border upon the Shadow made within the Colours by the Obstacle
+R intercepting some intermediate part of the Light; and, lastly, any one
+of them by being left alone, may border upon the Shadow on either hand.
+All the Colours have themselves indifferently to any Confines of Shadow,
+and therefore the differences of these Colours from one another, do not
+arise from the different Confines of Shadow, whereby Light is variously
+modified, as has hitherto been the Opinion of Philosophers. In trying
+these things 'tis to be observed, that by how much the holes F and H are
+narrower, and the Intervals between them and the Prism greater, and the
+Chamber darker, by so much the better doth the Experiment succeed;
+provided the Light be not so far diminished, but that the Colours at
+_pt_ be sufficiently visible. To procure a Prism of solid Glass large
+enough for this Experiment will be difficult, and therefore a prismatick
+Vessel must be made of polish'd Glass Plates cemented together, and
+filled with salt Water or clear Oil.
+
+[Illustration: FIG. 1.]
+
+_Exper._ 2. The Sun's Light let into a dark Chamber through the round
+hole F, [in _Fig._ 2.] half an Inch wide, passed first through the Prism
+ABC placed at the hole, and then through a Lens PT something more than
+four Inches broad, and about eight Feet distant from the Prism, and
+thence converged to O the Focus of the Lens distant from it about three
+Feet, and there fell upon a white Paper DE. If that Paper was
+perpendicular to that Light incident upon it, as 'tis represented in the
+posture DE, all the Colours upon it at O appeared white. But if the
+Paper being turned about an Axis parallel to the Prism, became very much
+inclined to the Light, as 'tis represented in the Positions _de_ and
+_[Greek: de]_; the same Light in the one case appeared yellow and red,
+in the other blue. Here one and the same part of the Light in one and
+the same place, according to the various Inclinations of the Paper,
+appeared in one case white, in another yellow or red, in a third blue,
+whilst the Confine of Light and shadow, and the Refractions of the Prism
+in all these cases remained the same.
+
+[Illustration: FIG. 2.]
+
+[Illustration: FIG. 3.]
+
+_Exper._ 3. Such another Experiment may be more easily tried as follows.
+Let a broad beam of the Sun's Light coming into a dark Chamber through a
+hole in the Window-shut be refracted by a large Prism ABC, [in _Fig._
+3.] whose refracting Angle C is more than 60 Degrees, and so soon as it
+comes out of the Prism, let it fall upon the white Paper DE glewed upon
+a stiff Plane; and this Light, when the Paper is perpendicular to it, as
+'tis represented in DE, will appear perfectly white upon the Paper; but
+when the Paper is very much inclin'd to it in such a manner as to keep
+always parallel to the Axis of the Prism, the whiteness of the whole
+Light upon the Paper will according to the inclination of the Paper this
+way or that way, change either into yellow and red, as in the posture
+_de_, or into blue and violet, as in the posture [Greek: de]. And if the
+Light before it fall upon the Paper be twice refracted the same way by
+two parallel Prisms, these Colours will become the more conspicuous.
+Here all the middle parts of the broad beam of white Light which fell
+upon the Paper, did without any Confine of Shadow to modify it, become
+colour'd all over with one uniform Colour, the Colour being always the
+same in the middle of the Paper as at the edges, and this Colour changed
+according to the various Obliquity of the reflecting Paper, without any
+change in the Refractions or Shadow, or in the Light which fell upon the
+Paper. And therefore these Colours are to be derived from some other
+Cause than the new Modifications of Light by Refractions and Shadows.
+
+If it be asked, what then is their Cause? I answer, That the Paper in
+the posture _de_, being more oblique to the more refrangible Rays than
+to the less refrangible ones, is more strongly illuminated by the latter
+than by the former, and therefore the less refrangible Rays are
+predominant in the reflected Light. And where-ever they are predominant
+in any Light, they tinge it with red or yellow, as may in some measure
+appear by the first Proposition of the first Part of this Book, and will
+more fully appear hereafter. And the contrary happens in the posture of
+the Paper [Greek: de], the more refrangible Rays being then predominant
+which always tinge Light with blues and violets.
+
+_Exper._ 4. The Colours of Bubbles with which Children play are various,
+and change their Situation variously, without any respect to any Confine
+or Shadow. If such a Bubble be cover'd with a concave Glass, to keep it
+from being agitated by any Wind or Motion of the Air, the Colours will
+slowly and regularly change their situation, even whilst the Eye and the
+Bubble, and all Bodies which emit any Light, or cast any Shadow, remain
+unmoved. And therefore their Colours arise from some regular Cause which
+depends not on any Confine of Shadow. What this Cause is will be shewed
+in the next Book.
+
+To these Experiments may be added the tenth Experiment of the first Part
+of this first Book, where the Sun's Light in a dark Room being
+trajected through the parallel Superficies of two Prisms tied together
+in the form of a Parallelopipede, became totally of one uniform yellow
+or red Colour, at its emerging out of the Prisms. Here, in the
+production of these Colours, the Confine of Shadow can have nothing to
+do. For the Light changes from white to yellow, orange and red
+successively, without any alteration of the Confine of Shadow: And at
+both edges of the emerging Light where the contrary Confines of Shadow
+ought to produce different Effects, the Colour is one and the same,
+whether it be white, yellow, orange or red: And in the middle of the
+emerging Light, where there is no Confine of Shadow at all, the Colour
+is the very same as at the edges, the whole Light at its very first
+Emergence being of one uniform Colour, whether white, yellow, orange or
+red, and going on thence perpetually without any change of Colour, such
+as the Confine of Shadow is vulgarly supposed to work in refracted Light
+after its Emergence. Neither can these Colours arise from any new
+Modifications of the Light by Refractions, because they change
+successively from white to yellow, orange and red, while the Refractions
+remain the same, and also because the Refractions are made contrary ways
+by parallel Superficies which destroy one another's Effects. They arise
+not therefore from any Modifications of Light made by Refractions and
+Shadows, but have some other Cause. What that Cause is we shewed above
+in this tenth Experiment, and need not here repeat it.
+
+There is yet another material Circumstance of this Experiment. For this
+emerging Light being by a third Prism HIK [in _Fig._ 22. _Part_ I.][I]
+refracted towards the Paper PT, and there painting the usual Colours of
+the Prism, red, yellow, green, blue, violet: If these Colours arose from
+the Refractions of that Prism modifying the Light, they would not be in
+the Light before its Incidence on that Prism. And yet in that Experiment
+we found, that when by turning the two first Prisms about their common
+Axis all the Colours were made to vanish but the red; the Light which
+makes that red being left alone, appeared of the very same red Colour
+before its Incidence on the third Prism. And in general we find by other
+Experiments, that when the Rays which differ in Refrangibility are
+separated from one another, and any one Sort of them is considered
+apart, the Colour of the Light which they compose cannot be changed by
+any Refraction or Reflexion whatever, as it ought to be were Colours
+nothing else than Modifications of Light caused by Refractions, and
+Reflexions, and Shadows. This Unchangeableness of Colour I am now to
+describe in the following Proposition.
+
+
+_PROP._ II. THEOR. II.
+
+_All homogeneal Light has its proper Colour answering to its Degree of
+Refrangibility, and that Colour cannot be changed by Reflexions and
+Refractions._
+
+In the Experiments of the fourth Proposition of the first Part of this
+first Book, when I had separated the heterogeneous Rays from one
+another, the Spectrum _pt_ formed by the separated Rays, did in the
+Progress from its End _p_, on which the most refrangible Rays fell, unto
+its other End _t_, on which the least refrangible Rays fell, appear
+tinged with this Series of Colours, violet, indigo, blue, green, yellow,
+orange, red, together with all their intermediate Degrees in a continual
+Succession perpetually varying. So that there appeared as many Degrees
+of Colours, as there were sorts of Rays differing in Refrangibility.
+
+_Exper._ 5. Now, that these Colours could not be changed by Refraction,
+I knew by refracting with a Prism sometimes one very little Part of this
+Light, sometimes another very little Part, as is described in the
+twelfth Experiment of the first Part of this Book. For by this
+Refraction the Colour of the Light was never changed in the least. If
+any Part of the red Light was refracted, it remained totally of the same
+red Colour as before. No orange, no yellow, no green or blue, no other
+new Colour was produced by that Refraction. Neither did the Colour any
+ways change by repeated Refractions, but continued always the same red
+entirely as at first. The like Constancy and Immutability I found also
+in the blue, green, and other Colours. So also, if I looked through a
+Prism upon any Body illuminated with any part of this homogeneal Light,
+as in the fourteenth Experiment of the first Part of this Book is
+described; I could not perceive any new Colour generated this way. All
+Bodies illuminated with compound Light appear through Prisms confused,
+(as was said above) and tinged with various new Colours, but those
+illuminated with homogeneal Light appeared through Prisms neither less
+distinct, nor otherwise colour'd, than when viewed with the naked Eyes.
+Their Colours were not in the least changed by the Refraction of the
+interposed Prism. I speak here of a sensible Change of Colour: For the
+Light which I here call homogeneal, being not absolutely homogeneal,
+there ought to arise some little Change of Colour from its
+Heterogeneity. But, if that Heterogeneity was so little as it might be
+made by the said Experiments of the fourth Proposition, that Change was
+not sensible, and therefore in Experiments, where Sense is Judge, ought
+to be accounted none at all.
+
+_Exper._ 6. And as these Colours were not changeable by Refractions, so
+neither were they by Reflexions. For all white, grey, red, yellow,
+green, blue, violet Bodies, as Paper, Ashes, red Lead, Orpiment, Indico
+Bise, Gold, Silver, Copper, Grass, blue Flowers, Violets, Bubbles of
+Water tinged with various Colours, Peacock's Feathers, the Tincture of
+_Lignum Nephriticum_, and such-like, in red homogeneal Light appeared
+totally red, in blue Light totally blue, in green Light totally green,
+and so of other Colours. In the homogeneal Light of any Colour they all
+appeared totally of that same Colour, with this only Difference, that
+some of them reflected that Light more strongly, others more faintly. I
+never yet found any Body, which by reflecting homogeneal Light could
+sensibly change its Colour.
+
+From all which it is manifest, that if the Sun's Light consisted of but
+one sort of Rays, there would be but one Colour in the whole World, nor
+would it be possible to produce any new Colour by Reflexions and
+Refractions, and by consequence that the variety of Colours depends upon
+the Composition of Light.
+
+
+_DEFINITION._
+
+The homogeneal Light and Rays which appear red, or rather make Objects
+appear so, I call Rubrifick or Red-making; those which make Objects
+appear yellow, green, blue, and violet, I call Yellow-making,
+Green-making, Blue-making, Violet-making, and so of the rest. And if at
+any time I speak of Light and Rays as coloured or endued with Colours, I
+would be understood to speak not philosophically and properly, but
+grossly, and accordingly to such Conceptions as vulgar People in seeing
+all these Experiments would be apt to frame. For the Rays to speak
+properly are not coloured. In them there is nothing else than a certain
+Power and Disposition to stir up a Sensation of this or that Colour.
+For as Sound in a Bell or musical String, or other sounding Body, is
+nothing but a trembling Motion, and in the Air nothing but that Motion
+propagated from the Object, and in the Sensorium 'tis a Sense of that
+Motion under the Form of Sound; so Colours in the Object are nothing but
+a Disposition to reflect this or that sort of Rays more copiously than
+the rest; in the Rays they are nothing but their Dispositions to
+propagate this or that Motion into the Sensorium, and in the Sensorium
+they are Sensations of those Motions under the Forms of Colours.
+
+
+_PROP._ III. PROB. I.
+
+_To define the Refrangibility of the several sorts of homogeneal Light
+answering to the several Colours._
+
+For determining this Problem I made the following Experiment.[J]
+
+_Exper._ 7. When I had caused the Rectilinear Sides AF, GM, [in _Fig._
+4.] of the Spectrum of Colours made by the Prism to be distinctly
+defined, as in the fifth Experiment of the first Part of this Book is
+described, there were found in it all the homogeneal Colours in the same
+Order and Situation one among another as in the Spectrum of simple
+Light, described in the fourth Proposition of that Part. For the Circles
+of which the Spectrum of compound Light PT is composed, and which in
+the middle Parts of the Spectrum interfere, and are intermix'd with one
+another, are not intermix'd in their outmost Parts where they touch
+those Rectilinear Sides AF and GM. And therefore, in those Rectilinear
+Sides when distinctly defined, there is no new Colour generated by
+Refraction. I observed also, that if any where between the two outmost
+Circles TMF and PGA a Right Line, as [Greek: gd], was cross to the
+Spectrum, so as both Ends to fall perpendicularly upon its Rectilinear
+Sides, there appeared one and the same Colour, and degree of Colour from
+one End of this Line to the other. I delineated therefore in a Paper the
+Perimeter of the Spectrum FAP GMT, and in trying the third Experiment of
+the first Part of this Book, I held the Paper so that the Spectrum might
+fall upon this delineated Figure, and agree with it exactly, whilst an
+Assistant, whose Eyes for distinguishing Colours were more critical than
+mine, did by Right Lines [Greek: ab, gd, ez,] &c. drawn cross the
+Spectrum, note the Confines of the Colours, that is of the red M[Greek:
+ab]F, of the orange [Greek: agdb], of the yellow [Greek: gezd], of the
+green [Greek: eêthz], of the blue [Greek: êikth], of the indico [Greek:
+ilmk], and of the violet [Greek: l]GA[Greek: m]. And this Operation
+being divers times repeated both in the same, and in several Papers, I
+found that the Observations agreed well enough with one another, and
+that the Rectilinear Sides MG and FA were by the said cross Lines
+divided after the manner of a Musical Chord. Let GM be produced to X,
+that MX may be equal to GM, and conceive GX, [Greek: l]X, [Greek: i]X,
+[Greek: ê]X, [Greek: e]X, [Greek: g]X, [Greek: a]X, MX, to be in
+proportion to one another, as the Numbers, 1, 8/9, 5/6, 3/4, 2/3, 3/5,
+9/16, 1/2, and so to represent the Chords of the Key, and of a Tone, a
+third Minor, a fourth, a fifth, a sixth Major, a seventh and an eighth
+above that Key: And the Intervals M[Greek: a], [Greek: ag], [Greek: ge],
+[Greek: eê], [Greek: êi], [Greek: il], and [Greek: l]G, will be the
+Spaces which the several Colours (red, orange, yellow, green, blue,
+indigo, violet) take up.
+
+[Illustration: FIG. 4.]
+
+[Illustration: FIG. 5.]
+
+Now these Intervals or Spaces subtending the Differences of the
+Refractions of the Rays going to the Limits of those Colours, that is,
+to the Points M, [Greek: a], [Greek: g], [Greek: e], [Greek: ê], [Greek:
+i], [Greek: l], G, may without any sensible Error be accounted
+proportional to the Differences of the Sines of Refraction of those Rays
+having one common Sine of Incidence, and therefore since the common Sine
+of Incidence of the most and least refrangible Rays out of Glass into
+Air was (by a Method described above) found in proportion to their Sines
+of Refraction, as 50 to 77 and 78, divide the Difference between the
+Sines of Refraction 77 and 78, as the Line GM is divided by those
+Intervals, and you will have 77, 77-1/8, 77-1/5, 77-1/3, 77-1/2, 77-2/3,
+77-7/9, 78, the Sines of Refraction of those Rays out of Glass into Air,
+their common Sine of Incidence being 50. So then the Sines of the
+Incidences of all the red-making Rays out of Glass into Air, were to the
+Sines of their Refractions, not greater than 50 to 77, nor less than 50
+to 77-1/8, but they varied from one another according to all
+intermediate Proportions. And the Sines of the Incidences of the
+green-making Rays were to the Sines of their Refractions in all
+Proportions from that of 50 to 77-1/3, unto that of 50 to 77-1/2. And
+by the like Limits above-mentioned were the Refractions of the Rays
+belonging to the rest of the Colours defined, the Sines of the
+red-making Rays extending from 77 to 77-1/8, those of the orange-making
+from 77-1/8 to 77-1/5, those of the yellow-making from 77-1/5 to 77-1/3,
+those of the green-making from 77-1/3 to 77-1/2, those of the
+blue-making from 77-1/2 to 77-2/3, those of the indigo-making from
+77-2/3 to 77-7/9, and those of the violet from 77-7/9, to 78.
+
+These are the Laws of the Refractions made out of Glass into Air, and
+thence by the third Axiom of the first Part of this Book, the Laws of
+the Refractions made out of Air into Glass are easily derived.
+
+_Exper._ 8. I found moreover, that when Light goes out of Air through
+several contiguous refracting Mediums as through Water and Glass, and
+thence goes out again into Air, whether the refracting Superficies be
+parallel or inclin'd to one another, that Light as often as by contrary
+Refractions 'tis so corrected, that it emergeth in Lines parallel to
+those in which it was incident, continues ever after to be white. But if
+the emergent Rays be inclined to the incident, the Whiteness of the
+emerging Light will by degrees in passing on from the Place of
+Emergence, become tinged in its Edges with Colours. This I try'd by
+refracting Light with Prisms of Glass placed within a Prismatick Vessel
+of Water. Now those Colours argue a diverging and separation of the
+heterogeneous Rays from one another by means of their unequal
+Refractions, as in what follows will more fully appear. And, on the
+contrary, the permanent whiteness argues, that in like Incidences of the
+Rays there is no such separation of the emerging Rays, and by
+consequence no inequality of their whole Refractions. Whence I seem to
+gather the two following Theorems.
+
+1. The Excesses of the Sines of Refraction of several sorts of Rays
+above their common Sine of Incidence when the Refractions are made out
+of divers denser Mediums immediately into one and the same rarer Medium,
+suppose of Air, are to one another in a given Proportion.
+
+2. The Proportion of the Sine of Incidence to the Sine of Refraction of
+one and the same sort of Rays out of one Medium into another, is
+composed of the Proportion of the Sine of Incidence to the Sine of
+Refraction out of the first Medium into any third Medium, and of the
+Proportion of the Sine of Incidence to the Sine of Refraction out of
+that third Medium into the second Medium.
+
+By the first Theorem the Refractions of the Rays of every sort made out
+of any Medium into Air are known by having the Refraction of the Rays of
+any one sort. As for instance, if the Refractions of the Rays of every
+sort out of Rain-water into Air be desired, let the common Sine of
+Incidence out of Glass into Air be subducted from the Sines of
+Refraction, and the Excesses will be 27, 27-1/8, 27-1/5, 27-1/3, 27-1/2,
+27-2/3, 27-7/9, 28. Suppose now that the Sine of Incidence of the least
+refrangible Rays be to their Sine of Refraction out of Rain-water into
+Air as 3 to 4, and say as 1 the difference of those Sines is to 3 the
+Sine of Incidence, so is 27 the least of the Excesses above-mentioned to
+a fourth Number 81; and 81 will be the common Sine of Incidence out of
+Rain-water into Air, to which Sine if you add all the above-mentioned
+Excesses, you will have the desired Sines of the Refractions 108,
+108-1/8, 108-1/5, 108-1/3, 108-1/2, 108-2/3, 108-7/9, 109.
+
+By the latter Theorem the Refraction out of one Medium into another is
+gathered as often as you have the Refractions out of them both into any
+third Medium. As if the Sine of Incidence of any Ray out of Glass into
+Air be to its Sine of Refraction, as 20 to 31, and the Sine of Incidence
+of the same Ray out of Air into Water, be to its Sine of Refraction as 4
+to 3; the Sine of Incidence of that Ray out of Glass into Water will be
+to its Sine of Refraction as 20 to 31 and 4 to 3 jointly, that is, as
+the Factum of 20 and 4 to the Factum of 31 and 3, or as 80 to 93.
+
+And these Theorems being admitted into Opticks, there would be scope
+enough of handling that Science voluminously after a new manner,[K] not
+only by teaching those things which tend to the perfection of Vision,
+but also by determining mathematically all kinds of Phænomena of Colours
+which could be produced by Refractions. For to do this, there is nothing
+else requisite than to find out the Separations of heterogeneous Rays,
+and their various Mixtures and Proportions in every Mixture. By this
+way of arguing I invented almost all the Phænomena described in these
+Books, beside some others less necessary to the Argument; and by the
+successes I met with in the Trials, I dare promise, that to him who
+shall argue truly, and then try all things with good Glasses and
+sufficient Circumspection, the expected Event will not be wanting. But
+he is first to know what Colours will arise from any others mix'd in any
+assigned Proportion.
+
+
+_PROP._ IV. THEOR. III.
+
+_Colours may be produced by Composition which shall be like to the
+Colours of homogeneal Light as to the Appearance of Colour, but not as
+to the Immutability of Colour and Constitution of Light. And those
+Colours by how much they are more compounded by so much are they less
+full and intense, and by too much Composition they maybe diluted and
+weaken'd till they cease, and the Mixture becomes white or grey. There
+may be also Colours produced by Composition, which are not fully like
+any of the Colours of homogeneal Light._
+
+For a Mixture of homogeneal red and yellow compounds an Orange, like in
+appearance of Colour to that orange which in the series of unmixed
+prismatick Colours lies between them; but the Light of one orange is
+homogeneal as to Refrangibility, and that of the other is heterogeneal,
+and the Colour of the one, if viewed through a Prism, remains unchanged,
+that of the other is changed and resolved into its component Colours red
+and yellow. And after the same manner other neighbouring homogeneal
+Colours may compound new Colours, like the intermediate homogeneal ones,
+as yellow and green, the Colour between them both, and afterwards, if
+blue be added, there will be made a green the middle Colour of the three
+which enter the Composition. For the yellow and blue on either hand, if
+they are equal in quantity they draw the intermediate green equally
+towards themselves in Composition, and so keep it as it were in
+Æquilibrion, that it verge not more to the yellow on the one hand, and
+to the blue on the other, but by their mix'd Actions remain still a
+middle Colour. To this mix'd green there may be farther added some red
+and violet, and yet the green will not presently cease, but only grow
+less full and vivid, and by increasing the red and violet, it will grow
+more and more dilute, until by the prevalence of the added Colours it be
+overcome and turned into whiteness, or some other Colour. So if to the
+Colour of any homogeneal Light, the Sun's white Light composed of all
+sorts of Rays be added, that Colour will not vanish or change its
+Species, but be diluted, and by adding more and more white it will be
+diluted more and more perpetually. Lastly, If red and violet be mingled,
+there will be generated according to their various Proportions various
+Purples, such as are not like in appearance to the Colour of any
+homogeneal Light, and of these Purples mix'd with yellow and blue may be
+made other new Colours.
+
+
+_PROP._ V. THEOR. IV.
+
+_Whiteness and all grey Colours between white and black, may be
+compounded of Colours, and the whiteness of the Sun's Light is
+compounded of all the primary Colours mix'd in a due Proportion._
+
+The PROOF by Experiments.
+
+_Exper._ 9. The Sun shining into a dark Chamber through a little round
+hole in the Window-shut, and his Light being there refracted by a Prism
+to cast his coloured Image PT [in _Fig._ 5.] upon the opposite Wall: I
+held a white Paper V to that image in such manner that it might be
+illuminated by the colour'd Light reflected from thence, and yet not
+intercept any part of that Light in its passage from the Prism to the
+Spectrum. And I found that when the Paper was held nearer to any Colour
+than to the rest, it appeared of that Colour to which it approached
+nearest; but when it was equally or almost equally distant from all the
+Colours, so that it might be equally illuminated by them all it appeared
+white. And in this last situation of the Paper, if some Colours were
+intercepted, the Paper lost its white Colour, and appeared of the Colour
+of the rest of the Light which was not intercepted. So then the Paper
+was illuminated with Lights of various Colours, namely, red, yellow,
+green, blue and violet, and every part of the Light retained its proper
+Colour, until it was incident on the Paper, and became reflected thence
+to the Eye; so that if it had been either alone (the rest of the Light
+being intercepted) or if it had abounded most, and been predominant in
+the Light reflected from the Paper, it would have tinged the Paper with
+its own Colour; and yet being mixed with the rest of the Colours in a
+due proportion, it made the Paper look white, and therefore by a
+Composition with the rest produced that Colour. The several parts of the
+coloured Light reflected from the Spectrum, whilst they are propagated
+from thence through the Air, do perpetually retain their proper Colours,
+because wherever they fall upon the Eyes of any Spectator, they make the
+several parts of the Spectrum to appear under their proper Colours. They
+retain therefore their proper Colours when they fall upon the Paper V,
+and so by the confusion and perfect mixture of those Colours compound
+the whiteness of the Light reflected from thence.
+
+_Exper._ 10. Let that Spectrum or solar Image PT [in _Fig._ 6.] fall now
+upon the Lens MN above four Inches broad, and about six Feet distant
+from the Prism ABC and so figured that it may cause the coloured Light
+which divergeth from the Prism to converge and meet again at its Focus
+G, about six or eight Feet distant from the Lens, and there to fall
+perpendicularly upon a white Paper DE. And if you move this Paper to and
+fro, you will perceive that near the Lens, as at _de_, the whole solar
+Image (suppose at _pt_) will appear upon it intensely coloured after the
+manner above-explained, and that by receding from the Lens those Colours
+will perpetually come towards one another, and by mixing more and more
+dilute one another continually, until at length the Paper come to the
+Focus G, where by a perfect mixture they will wholly vanish and be
+converted into whiteness, the whole Light appearing now upon the Paper
+like a little white Circle. And afterwards by receding farther from the
+Lens, the Rays which before converged will now cross one another in the
+Focus G, and diverge from thence, and thereby make the Colours to appear
+again, but yet in a contrary order; suppose at [Greek: de], where the
+red _t_ is now above which before was below, and the violet _p_ is below
+which before was above.
+
+Let us now stop the Paper at the Focus G, where the Light appears
+totally white and circular, and let us consider its whiteness. I say,
+that this is composed of the converging Colours. For if any of those
+Colours be intercepted at the Lens, the whiteness will cease and
+degenerate into that Colour which ariseth from the composition of the
+other Colours which are not intercepted. And then if the intercepted
+Colours be let pass and fall upon that compound Colour, they mix with
+it, and by their mixture restore the whiteness. So if the violet, blue
+and green be intercepted, the remaining yellow, orange and red will
+compound upon the Paper an orange, and then if the intercepted Colours
+be let pass, they will fall upon this compounded orange, and together
+with it decompound a white. So also if the red and violet be
+intercepted, the remaining yellow, green and blue, will compound a green
+upon the Paper, and then the red and violet being let pass will fall
+upon this green, and together with it decompound a white. And that in
+this Composition of white the several Rays do not suffer any Change in
+their colorific Qualities by acting upon one another, but are only
+mixed, and by a mixture of their Colours produce white, may farther
+appear by these Arguments.
+
+[Illustration: FIG. 6.]
+
+If the Paper be placed beyond the Focus G, suppose at [Greek: de], and
+then the red Colour at the Lens be alternately intercepted, and let pass
+again, the violet Colour on the Paper will not suffer any Change
+thereby, as it ought to do if the several sorts of Rays acted upon one
+another in the Focus G, where they cross. Neither will the red upon the
+Paper be changed by any alternate stopping, and letting pass the violet
+which crosseth it.
+
+And if the Paper be placed at the Focus G, and the white round Image at
+G be viewed through the Prism HIK, and by the Refraction of that Prism
+be translated to the place _rv_, and there appear tinged with various
+Colours, namely, the violet at _v_ and red at _r_, and others between,
+and then the red Colours at the Lens be often stopp'd and let pass by
+turns, the red at _r_ will accordingly disappear, and return as often,
+but the violet at _v_ will not thereby suffer any Change. And so by
+stopping and letting pass alternately the blue at the Lens, the blue at
+_v_ will accordingly disappear and return, without any Change made in
+the red at _r_. The red therefore depends on one sort of Rays, and the
+blue on another sort, which in the Focus G where they are commix'd, do
+not act on one another. And there is the same Reason of the other
+Colours.
+
+I considered farther, that when the most refrangible Rays P_p_, and the
+least refrangible ones T_t_, are by converging inclined to one another,
+the Paper, if held very oblique to those Rays in the Focus G, might
+reflect one sort of them more copiously than the other sort, and by that
+Means the reflected Light would be tinged in that Focus with the Colour
+of the predominant Rays, provided those Rays severally retained their
+Colours, or colorific Qualities in the Composition of White made by them
+in that Focus. But if they did not retain them in that White, but became
+all of them severally endued there with a Disposition to strike the
+Sense with the Perception of White, then they could never lose their
+Whiteness by such Reflexions. I inclined therefore the Paper to the Rays
+very obliquely, as in the second Experiment of this second Part of the
+first Book, that the most refrangible Rays, might be more copiously
+reflected than the rest, and the Whiteness at Length changed
+successively into blue, indigo, and violet. Then I inclined it the
+contrary Way, that the least refrangible Rays might be more copious in
+the reflected Light than the rest, and the Whiteness turned successively
+to yellow, orange, and red.
+
+Lastly, I made an Instrument XY in fashion of a Comb, whose Teeth being
+in number sixteen, were about an Inch and a half broad, and the
+Intervals of the Teeth about two Inches wide. Then by interposing
+successively the Teeth of this Instrument near the Lens, I intercepted
+Part of the Colours by the interposed Tooth, whilst the rest of them
+went on through the Interval of the Teeth to the Paper DE, and there
+painted a round Solar Image. But the Paper I had first placed so, that
+the Image might appear white as often as the Comb was taken away; and
+then the Comb being as was said interposed, that Whiteness by reason of
+the intercepted Part of the Colours at the Lens did always change into
+the Colour compounded of those Colours which were not intercepted, and
+that Colour was by the Motion of the Comb perpetually varied so, that in
+the passing of every Tooth over the Lens all these Colours, red, yellow,
+green, blue, and purple, did always succeed one another. I caused
+therefore all the Teeth to pass successively over the Lens, and when the
+Motion was slow, there appeared a perpetual Succession of the Colours
+upon the Paper: But if I so much accelerated the Motion, that the
+Colours by reason of their quick Succession could not be distinguished
+from one another, the Appearance of the single Colours ceased. There was
+no red, no yellow, no green, no blue, nor purple to be seen any longer,
+but from a Confusion of them all there arose one uniform white Colour.
+Of the Light which now by the Mixture of all the Colours appeared white,
+there was no Part really white. One Part was red, another yellow, a
+third green, a fourth blue, a fifth purple, and every Part retains its
+proper Colour till it strike the Sensorium. If the Impressions follow
+one another slowly, so that they may be severally perceived, there is
+made a distinct Sensation of all the Colours one after another in a
+continual Succession. But if the Impressions follow one another so
+quickly, that they cannot be severally perceived, there ariseth out of
+them all one common Sensation, which is neither of this Colour alone nor
+of that alone, but hath it self indifferently to 'em all, and this is a
+Sensation of Whiteness. By the Quickness of the Successions, the
+Impressions of the several Colours are confounded in the Sensorium, and
+out of that Confusion ariseth a mix'd Sensation. If a burning Coal be
+nimbly moved round in a Circle with Gyrations continually repeated, the
+whole Circle will appear like Fire; the reason of which is, that the
+Sensation of the Coal in the several Places of that Circle remains
+impress'd on the Sensorium, until the Coal return again to the same
+Place. And so in a quick Consecution of the Colours the Impression of
+every Colour remains in the Sensorium, until a Revolution of all the
+Colours be compleated, and that first Colour return again. The
+Impressions therefore of all the successive Colours are at once in the
+Sensorium, and jointly stir up a Sensation of them all; and so it is
+manifest by this Experiment, that the commix'd Impressions of all the
+Colours do stir up and beget a Sensation of white, that is, that
+Whiteness is compounded of all the Colours.
+
+And if the Comb be now taken away, that all the Colours may at once pass
+from the Lens to the Paper, and be there intermixed, and together
+reflected thence to the Spectator's Eyes; their Impressions on the
+Sensorium being now more subtilly and perfectly commixed there, ought
+much more to stir up a Sensation of Whiteness.
+
+You may instead of the Lens use two Prisms HIK and LMN, which by
+refracting the coloured Light the contrary Way to that of the first
+Refraction, may make the diverging Rays converge and meet again in G, as
+you see represented in the seventh Figure. For where they meet and mix,
+they will compose a white Light, as when a Lens is used.
+
+_Exper._ 11. Let the Sun's coloured Image PT [in _Fig._ 8.] fall upon
+the Wall of a dark Chamber, as in the third Experiment of the first
+Book, and let the same be viewed through a Prism _abc_, held parallel to
+the Prism ABC, by whose Refraction that Image was made, and let it now
+appear lower than before, suppose in the Place S over-against the red
+Colour T. And if you go near to the Image PT, the Spectrum S will appear
+oblong and coloured like the Image PT; but if you recede from it, the
+Colours of the spectrum S will be contracted more and more, and at
+length vanish, that Spectrum S becoming perfectly round and white; and
+if you recede yet farther, the Colours will emerge again, but in a
+contrary Order. Now that Spectrum S appears white in that Case, when the
+Rays of several sorts which converge from the several Parts of the Image
+PT, to the Prism _abc_, are so refracted unequally by it, that in their
+Passage from the Prism to the Eye they may diverge from one and the same
+Point of the Spectrum S, and so fall afterwards upon one and the same
+Point in the bottom of the Eye, and there be mingled.
+
+[Illustration: FIG. 7.]
+
+[Illustration: FIG. 8.]
+
+And farther, if the Comb be here made use of, by whose Teeth the Colours
+at the Image PT may be successively intercepted; the Spectrum S, when
+the Comb is moved slowly, will be perpetually tinged with successive
+Colours: But when by accelerating the Motion of the Comb, the Succession
+of the Colours is so quick that they cannot be severally seen, that
+Spectrum S, by a confused and mix'd Sensation of them all, will appear
+white.
+
+_Exper._ 12. The Sun shining through a large Prism ABC [in _Fig._ 9.]
+upon a Comb XY, placed immediately behind the Prism, his Light which
+passed through the Interstices of the Teeth fell upon a white Paper DE.
+The Breadths of the Teeth were equal to their Interstices, and seven
+Teeth together with their Interstices took up an Inch in Breadth. Now,
+when the Paper was about two or three Inches distant from the Comb, the
+Light which passed through its several Interstices painted so many
+Ranges of Colours, _kl_, _mn_, _op_, _qr_, &c. which were parallel to
+one another, and contiguous, and without any Mixture of white. And these
+Ranges of Colours, if the Comb was moved continually up and down with a
+reciprocal Motion, ascended and descended in the Paper, and when the
+Motion of the Comb was so quick, that the Colours could not be
+distinguished from one another, the whole Paper by their Confusion and
+Mixture in the Sensorium appeared white.
+
+[Illustration: FIG. 9.]
+
+Let the Comb now rest, and let the Paper be removed farther from the
+Prism, and the several Ranges of Colours will be dilated and expanded
+into one another more and more, and by mixing their Colours will dilute
+one another, and at length, when the distance of the Paper from the Comb
+is about a Foot, or a little more (suppose in the Place 2D 2E) they will
+so far dilute one another, as to become white.
+
+With any Obstacle, let all the Light be now stopp'd which passes through
+any one Interval of the Teeth, so that the Range of Colours which comes
+from thence may be taken away, and you will see the Light of the rest of
+the Ranges to be expanded into the Place of the Range taken away, and
+there to be coloured. Let the intercepted Range pass on as before, and
+its Colours falling upon the Colours of the other Ranges, and mixing
+with them, will restore the Whiteness.
+
+Let the Paper 2D 2E be now very much inclined to the Rays, so that the
+most refrangible Rays may be more copiously reflected than the rest, and
+the white Colour of the Paper through the Excess of those Rays will be
+changed into blue and violet. Let the Paper be as much inclined the
+contrary way, that the least refrangible Rays may be now more copiously
+reflected than the rest, and by their Excess the Whiteness will be
+changed into yellow and red. The several Rays therefore in that white
+Light do retain their colorific Qualities, by which those of any sort,
+whenever they become more copious than the rest, do by their Excess and
+Predominance cause their proper Colour to appear.
+
+And by the same way of arguing, applied to the third Experiment of this
+second Part of the first Book, it may be concluded, that the white
+Colour of all refracted Light at its very first Emergence, where it
+appears as white as before its Incidence, is compounded of various
+Colours.
+
+[Illustration: FIG. 10.]
+
+_Exper._ 13. In the foregoing Experiment the several Intervals of the
+Teeth of the Comb do the Office of so many Prisms, every Interval
+producing the Phænomenon of one Prism. Whence instead of those Intervals
+using several Prisms, I try'd to compound Whiteness by mixing their
+Colours, and did it by using only three Prisms, as also by using only
+two as follows. Let two Prisms ABC and _abc_, [in _Fig._ 10.] whose
+refracting Angles B and _b_ are equal, be so placed parallel to one
+another, that the refracting Angle B of the one may touch the Angle _c_
+at the Base of the other, and their Planes CB and _cb_, at which the
+Rays emerge, may lie in Directum. Then let the Light trajected through
+them fall upon the Paper MN, distant about 8 or 12 Inches from the
+Prisms. And the Colours generated by the interior Limits B and _c_ of
+the two Prisms, will be mingled at PT, and there compound white. For if
+either Prism be taken away, the Colours made by the other will appear in
+that Place PT, and when the Prism is restored to its Place again, so
+that its Colours may there fall upon the Colours of the other, the
+Mixture of them both will restore the Whiteness.
+
+This Experiment succeeds also, as I have tried, when the Angle _b_ of
+the lower Prism, is a little greater than the Angle B of the upper, and
+between the interior Angles B and _c_, there intercedes some Space B_c_,
+as is represented in the Figure, and the refracting Planes BC and _bc_,
+are neither in Directum, nor parallel to one another. For there is
+nothing more requisite to the Success of this Experiment, than that the
+Rays of all sorts may be uniformly mixed upon the Paper in the Place PT.
+If the most refrangible Rays coming from the superior Prism take up all
+the Space from M to P, the Rays of the same sort which come from the
+inferior Prism ought to begin at P, and take up all the rest of the
+Space from thence towards N. If the least refrangible Rays coming from
+the superior Prism take up the Space MT, the Rays of the same kind which
+come from the other Prism ought to begin at T, and take up the
+remaining Space TN. If one sort of the Rays which have intermediate
+Degrees of Refrangibility, and come from the superior Prism be extended
+through the Space MQ, and another sort of those Rays through the Space
+MR, and a third sort of them through the Space MS, the same sorts of
+Rays coming from the lower Prism, ought to illuminate the remaining
+Spaces QN, RN, SN, respectively. And the same is to be understood of all
+the other sorts of Rays. For thus the Rays of every sort will be
+scattered uniformly and evenly through the whole Space MN, and so being
+every where mix'd in the same Proportion, they must every where produce
+the same Colour. And therefore, since by this Mixture they produce white
+in the Exterior Spaces MP and TN, they must also produce white in the
+Interior Space PT. This is the reason of the Composition by which
+Whiteness was produced in this Experiment, and by what other way soever
+I made the like Composition, the Result was Whiteness.
+
+Lastly, If with the Teeth of a Comb of a due Size, the coloured Lights
+of the two Prisms which fall upon the Space PT be alternately
+intercepted, that Space PT, when the Motion of the Comb is slow, will
+always appear coloured, but by accelerating the Motion of the Comb so
+much that the successive Colours cannot be distinguished from one
+another, it will appear white.
+
+_Exper._ 14. Hitherto I have produced Whiteness by mixing the Colours of
+Prisms. If now the Colours of natural Bodies are to be mingled, let
+Water a little thicken'd with Soap be agitated to raise a Froth, and
+after that Froth has stood a little, there will appear to one that shall
+view it intently various Colours every where in the Surfaces of the
+several Bubbles; but to one that shall go so far off, that he cannot
+distinguish the Colours from one another, the whole Froth will grow
+white with a perfect Whiteness.
+
+_Exper._ 15. Lastly, In attempting to compound a white, by mixing the
+coloured Powders which Painters use, I consider'd that all colour'd
+Powders do suppress and stop in them a very considerable Part of the
+Light by which they are illuminated. For they become colour'd by
+reflecting the Light of their own Colours more copiously, and that of
+all other Colours more sparingly, and yet they do not reflect the Light
+of their own Colours so copiously as white Bodies do. If red Lead, for
+instance, and a white Paper, be placed in the red Light of the colour'd
+Spectrum made in a dark Chamber by the Refraction of a Prism, as is
+described in the third Experiment of the first Part of this Book; the
+Paper will appear more lucid than the red Lead, and therefore reflects
+the red-making Rays more copiously than red Lead doth. And if they be
+held in the Light of any other Colour, the Light reflected by the Paper
+will exceed the Light reflected by the red Lead in a much greater
+Proportion. And the like happens in Powders of other Colours. And
+therefore by mixing such Powders, we are not to expect a strong and
+full White, such as is that of Paper, but some dusky obscure one, such
+as might arise from a Mixture of Light and Darkness, or from white and
+black, that is, a grey, or dun, or russet brown, such as are the Colours
+of a Man's Nail, of a Mouse, of Ashes, of ordinary Stones, of Mortar, of
+Dust and Dirt in High-ways, and the like. And such a dark white I have
+often produced by mixing colour'd Powders. For thus one Part of red
+Lead, and five Parts of _Viride Æris_, composed a dun Colour like that
+of a Mouse. For these two Colours were severally so compounded of
+others, that in both together were a Mixture of all Colours; and there
+was less red Lead used than _Viride Æris_, because of the Fulness of its
+Colour. Again, one Part of red Lead, and four Parts of blue Bise,
+composed a dun Colour verging a little to purple, and by adding to this
+a certain Mixture of Orpiment and _Viride Æris_ in a due Proportion, the
+Mixture lost its purple Tincture, and became perfectly dun. But the
+Experiment succeeded best without Minium thus. To Orpiment I added by
+little and little a certain full bright purple, which Painters use,
+until the Orpiment ceased to be yellow, and became of a pale red. Then I
+diluted that red by adding a little _Viride Æris_, and a little more
+blue Bise than _Viride Æris_, until it became of such a grey or pale
+white, as verged to no one of the Colours more than to another. For thus
+it became of a Colour equal in Whiteness to that of Ashes, or of Wood
+newly cut, or of a Man's Skin. The Orpiment reflected more Light than
+did any other of the Powders, and therefore conduced more to the
+Whiteness of the compounded Colour than they. To assign the Proportions
+accurately may be difficult, by reason of the different Goodness of
+Powders of the same kind. Accordingly, as the Colour of any Powder is
+more or less full and luminous, it ought to be used in a less or greater
+Proportion.
+
+Now, considering that these grey and dun Colours may be also produced by
+mixing Whites and Blacks, and by consequence differ from perfect Whites,
+not in Species of Colours, but only in degree of Luminousness, it is
+manifest that there is nothing more requisite to make them perfectly
+white than to increase their Light sufficiently; and, on the contrary,
+if by increasing their Light they can be brought to perfect Whiteness,
+it will thence also follow, that they are of the same Species of Colour
+with the best Whites, and differ from them only in the Quantity of
+Light. And this I tried as follows. I took the third of the
+above-mention'd grey Mixtures, (that which was compounded of Orpiment,
+Purple, Bise, and _Viride Æris_) and rubbed it thickly upon the Floor of
+my Chamber, where the Sun shone upon it through the opened Casement; and
+by it, in the shadow, I laid a Piece of white Paper of the same Bigness.
+Then going from them to the distance of 12 or 18 Feet, so that I could
+not discern the Unevenness of the Surface of the Powder, nor the little
+Shadows let fall from the gritty Particles thereof; the Powder appeared
+intensely white, so as to transcend even the Paper it self in Whiteness,
+especially if the Paper were a little shaded from the Light of the
+Clouds, and then the Paper compared with the Powder appeared of such a
+grey Colour as the Powder had done before. But by laying the Paper where
+the Sun shines through the Glass of the Window, or by shutting the
+Window that the Sun might shine through the Glass upon the Powder, and
+by such other fit Means of increasing or decreasing the Lights wherewith
+the Powder and Paper were illuminated, the Light wherewith the Powder is
+illuminated may be made stronger in such a due Proportion than the Light
+wherewith the Paper is illuminated, that they shall both appear exactly
+alike in Whiteness. For when I was trying this, a Friend coming to visit
+me, I stopp'd him at the Door, and before I told him what the Colours
+were, or what I was doing; I asked him, Which of the two Whites were the
+best, and wherein they differed? And after he had at that distance
+viewed them well, he answer'd, that they were both good Whites, and that
+he could not say which was best, nor wherein their Colours differed.
+Now, if you consider, that this White of the Powder in the Sun-shine was
+compounded of the Colours which the component Powders (Orpiment, Purple,
+Bise, and _Viride Æris_) have in the same Sun-shine, you must
+acknowledge by this Experiment, as well as by the former, that perfect
+Whiteness may be compounded of Colours.
+
+From what has been said it is also evident, that the Whiteness of the
+Sun's Light is compounded of all the Colours wherewith the several sorts
+of Rays whereof that Light consists, when by their several
+Refrangibilities they are separated from one another, do tinge Paper or
+any other white Body whereon they fall. For those Colours (by _Prop._
+II. _Part_ 2.) are unchangeable, and whenever all those Rays with those
+their Colours are mix'd again, they reproduce the same white Light as
+before.
+
+
+_PROP._ VI. PROB. II.
+
+_In a mixture of Primary Colours, the Quantity and Quality of each being
+given, to know the Colour of the Compound._
+
+[Illustration: FIG. 11.]
+
+With the Center O [in _Fig._ 11.] and Radius OD describe a Circle ADF,
+and distinguish its Circumference into seven Parts DE, EF, FG, GA, AB,
+BC, CD, proportional to the seven Musical Tones or Intervals of the
+eight Sounds, _Sol_, _la_, _fa_, _sol_, _la_, _mi_, _fa_, _sol_,
+contained in an eight, that is, proportional to the Number 1/9, 1/16,
+1/10, 1/9, 1/16, 1/16, 1/9. Let the first Part DE represent a red
+Colour, the second EF orange, the third FG yellow, the fourth CA green,
+the fifth AB blue, the sixth BC indigo, and the seventh CD violet. And
+conceive that these are all the Colours of uncompounded Light gradually
+passing into one another, as they do when made by Prisms; the
+Circumference DEFGABCD, representing the whole Series of Colours from
+one end of the Sun's colour'd Image to the other, so that from D to E be
+all degrees of red, at E the mean Colour between red and orange, from E
+to F all degrees of orange, at F the mean between orange and yellow,
+from F to G all degrees of yellow, and so on. Let _p_ be the Center of
+Gravity of the Arch DE, and _q_, _r_, _s_, _t_, _u_, _x_, the Centers of
+Gravity of the Arches EF, FG, GA, AB, BC, and CD respectively, and about
+those Centers of Gravity let Circles proportional to the Number of Rays
+of each Colour in the given Mixture be describ'd: that is, the Circle
+_p_ proportional to the Number of the red-making Rays in the Mixture,
+the Circle _q_ proportional to the Number of the orange-making Rays in
+the Mixture, and so of the rest. Find the common Center of Gravity of
+all those Circles, _p_, _q_, _r_, _s_, _t_, _u_, _x_. Let that Center be
+Z; and from the Center of the Circle ADF, through Z to the
+Circumference, drawing the Right Line OY, the Place of the Point Y in
+the Circumference shall shew the Colour arising from the Composition of
+all the Colours in the given Mixture, and the Line OZ shall be
+proportional to the Fulness or Intenseness of the Colour, that is, to
+its distance from Whiteness. As if Y fall in the middle between F and G,
+the compounded Colour shall be the best yellow; if Y verge from the
+middle towards F or G, the compound Colour shall accordingly be a
+yellow, verging towards orange or green. If Z fall upon the
+Circumference, the Colour shall be intense and florid in the highest
+Degree; if it fall in the mid-way between the Circumference and Center,
+it shall be but half so intense, that is, it shall be such a Colour as
+would be made by diluting the intensest yellow with an equal quantity of
+whiteness; and if it fall upon the center O, the Colour shall have lost
+all its intenseness, and become a white. But it is to be noted, That if
+the point Z fall in or near the line OD, the main ingredients being the
+red and violet, the Colour compounded shall not be any of the prismatick
+Colours, but a purple, inclining to red or violet, accordingly as the
+point Z lieth on the side of the line DO towards E or towards C, and in
+general the compounded violet is more bright and more fiery than the
+uncompounded. Also if only two of the primary Colours which in the
+circle are opposite to one another be mixed in an equal proportion, the
+point Z shall fall upon the center O, and yet the Colour compounded of
+those two shall not be perfectly white, but some faint anonymous Colour.
+For I could never yet by mixing only two primary Colours produce a
+perfect white. Whether it may be compounded of a mixture of three taken
+at equal distances in the circumference I do not know, but of four or
+five I do not much question but it may. But these are Curiosities of
+little or no moment to the understanding the Phænomena of Nature. For in
+all whites produced by Nature, there uses to be a mixture of all sorts
+of Rays, and by consequence a composition of all Colours.
+
+To give an instance of this Rule; suppose a Colour is compounded of
+these homogeneal Colours, of violet one part, of indigo one part, of
+blue two parts, of green three parts, of yellow five parts, of orange
+six parts, and of red ten parts. Proportional to these parts describe
+the Circles _x_, _v_, _t_, _s_, _r_, _q_, _p_, respectively, that is, so
+that if the Circle _x_ be one, the Circle _v_ may be one, the Circle _t_
+two, the Circle _s_ three, and the Circles _r_, _q_ and _p_, five, six
+and ten. Then I find Z the common center of gravity of these Circles,
+and through Z drawing the Line OY, the Point Y falls upon the
+circumference between E and F, something nearer to E than to F, and
+thence I conclude, that the Colour compounded of these Ingredients will
+be an orange, verging a little more to red than to yellow. Also I find
+that OZ is a little less than one half of OY, and thence I conclude,
+that this orange hath a little less than half the fulness or intenseness
+of an uncompounded orange; that is to say, that it is such an orange as
+may be made by mixing an homogeneal orange with a good white in the
+proportion of the Line OZ to the Line ZY, this Proportion being not of
+the quantities of mixed orange and white Powders, but of the quantities
+of the Lights reflected from them.
+
+This Rule I conceive accurate enough for practice, though not
+mathematically accurate; and the truth of it may be sufficiently proved
+to Sense, by stopping any of the Colours at the Lens in the tenth
+Experiment of this Book. For the rest of the Colours which are not
+stopp'd, but pass on to the Focus of the Lens, will there compound
+either accurately or very nearly such a Colour, as by this Rule ought to
+result from their Mixture.
+
+
+_PROP._ VII. THEOR. V.
+
+_All the Colours in the Universe which are made by Light, and depend not
+on the Power of Imagination, are either the Colours of homogeneal
+Lights, or compounded of these, and that either accurately or very
+nearly, according to the Rule of the foregoing Problem._
+
+For it has been proved (in _Prop. 1. Part 2._) that the changes of
+Colours made by Refractions do not arise from any new Modifications of
+the Rays impress'd by those Refractions, and by the various Terminations
+of Light and Shadow, as has been the constant and general Opinion of
+Philosophers. It has also been proved that the several Colours of the
+homogeneal Rays do constantly answer to their degrees of Refrangibility,
+(_Prop._ 1. _Part_ 1. and _Prop._ 2. _Part_ 2.) and that their degrees
+of Refrangibility cannot be changed by Refractions and Reflexions
+(_Prop._ 2. _Part_ 1.) and by consequence that those their Colours are
+likewise immutable. It has also been proved directly by refracting and
+reflecting homogeneal Lights apart, that their Colours cannot be
+changed, (_Prop._ 2. _Part_ 2.) It has been proved also, that when the
+several sorts of Rays are mixed, and in crossing pass through the same
+space, they do not act on one another so as to change each others
+colorific qualities. (_Exper._ 10. _Part_ 2.) but by mixing their
+Actions in the Sensorium beget a Sensation differing from what either
+would do apart, that is a Sensation of a mean Colour between their
+proper Colours; and particularly when by the concourse and mixtures of
+all sorts of Rays, a white Colour is produced, the white is a mixture of
+all the Colours which the Rays would have apart, (_Prop._ 5. _Part_ 2.)
+The Rays in that mixture do not lose or alter their several colorific
+qualities, but by all their various kinds of Actions mix'd in the
+Sensorium, beget a Sensation of a middling Colour between all their
+Colours, which is whiteness. For whiteness is a mean between all
+Colours, having it self indifferently to them all, so as with equal
+facility to be tinged with any of them. A red Powder mixed with a little
+blue, or a blue with a little red, doth not presently lose its Colour,
+but a white Powder mix'd with any Colour is presently tinged with that
+Colour, and is equally capable of being tinged with any Colour whatever.
+It has been shewed also, that as the Sun's Light is mix'd of all sorts
+of Rays, so its whiteness is a mixture of the Colours of all sorts of
+Rays; those Rays having from the beginning their several colorific
+qualities as well as their several Refrangibilities, and retaining them
+perpetually unchanged notwithstanding any Refractions or Reflexions they
+may at any time suffer, and that whenever any sort of the Sun's Rays is
+by any means (as by Reflexion in _Exper._ 9, and 10. _Part_ 1. or by
+Refraction as happens in all Refractions) separated from the rest, they
+then manifest their proper Colours. These things have been prov'd, and
+the sum of all this amounts to the Proposition here to be proved. For if
+the Sun's Light is mix'd of several sorts of Rays, each of which have
+originally their several Refrangibilities and colorific Qualities, and
+notwithstanding their Refractions and Reflexions, and their various
+Separations or Mixtures, keep those their original Properties
+perpetually the same without alteration; then all the Colours in the
+World must be such as constantly ought to arise from the original
+colorific qualities of the Rays whereof the Lights consist by which
+those Colours are seen. And therefore if the reason of any Colour
+whatever be required, we have nothing else to do than to consider how
+the Rays in the Sun's Light have by Reflexions or Refractions, or other
+causes, been parted from one another, or mixed together; or otherwise to
+find out what sorts of Rays are in the Light by which that Colour is
+made, and in what Proportion; and then by the last Problem to learn the
+Colour which ought to arise by mixing those Rays (or their Colours) in
+that proportion. I speak here of Colours so far as they arise from
+Light. For they appear sometimes by other Causes, as when by the power
+of Phantasy we see Colours in a Dream, or a Mad-man sees things before
+him which are not there; or when we see Fire by striking the Eye, or see
+Colours like the Eye of a Peacock's Feather, by pressing our Eyes in
+either corner whilst we look the other way. Where these and such like
+Causes interpose not, the Colour always answers to the sort or sorts of
+the Rays whereof the Light consists, as I have constantly found in
+whatever Phænomena of Colours I have hitherto been able to examine. I
+shall in the following Propositions give instances of this in the
+Phænomena of chiefest note.
+
+
+_PROP._ VIII. PROB. III.
+
+_By the discovered Properties of Light to explain the Colours made by
+Prisms._
+
+Let ABC [in _Fig._ 12.] represent a Prism refracting the Light of the
+Sun, which comes into a dark Chamber through a hole F[Greek: ph] almost
+as broad as the Prism, and let MN represent a white Paper on which the
+refracted Light is cast, and suppose the most refrangible or deepest
+violet-making Rays fall upon the Space P[Greek: p], the least
+refrangible or deepest red-making Rays upon the Space T[Greek: t], the
+middle sort between the indigo-making and blue-making Rays upon the
+Space Q[Greek: ch], the middle sort of the green-making Rays upon the
+Space R, the middle sort between the yellow-making and orange-making
+Rays upon the Space S[Greek: s], and other intermediate sorts upon
+intermediate Spaces. For so the Spaces upon which the several sorts
+adequately fall will by reason of the different Refrangibility of those
+sorts be one lower than another. Now if the Paper MN be so near the
+Prism that the Spaces PT and [Greek: pt] do not interfere with one
+another, the distance between them T[Greek: p] will be illuminated by
+all the sorts of Rays in that proportion to one another which they have
+at their very first coming out of the Prism, and consequently be white.
+But the Spaces PT and [Greek: pt] on either hand, will not be
+illuminated by them all, and therefore will appear coloured. And
+particularly at P, where the outmost violet-making Rays fall alone, the
+Colour must be the deepest violet. At Q where the violet-making and
+indigo-making Rays are mixed, it must be a violet inclining much to
+indigo. At R where the violet-making, indigo-making, blue-making, and
+one half of the green-making Rays are mixed, their Colours must (by the
+construction of the second Problem) compound a middle Colour between
+indigo and blue. At S where all the Rays are mixed, except the
+red-making and orange-making, their Colours ought by the same Rule to
+compound a faint blue, verging more to green than indigo. And in the
+progress from S to T, this blue will grow more and more faint and
+dilute, till at T, where all the Colours begin to be mixed, it ends in
+whiteness.
+
+[Illustration: FIG. 12.]
+
+So again, on the other side of the white at [Greek: t], where the least
+refrangible or utmost red-making Rays are alone, the Colour must be the
+deepest red. At [Greek: s] the mixture of red and orange will compound a
+red inclining to orange. At [Greek: r] the mixture of red, orange,
+yellow, and one half of the green must compound a middle Colour between
+orange and yellow. At [Greek: ch] the mixture of all Colours but violet
+and indigo will compound a faint yellow, verging more to green than to
+orange. And this yellow will grow more faint and dilute continually in
+its progress from [Greek: ch] to [Greek: p], where by a mixture of all
+sorts of Rays it will become white.
+
+These Colours ought to appear were the Sun's Light perfectly white: But
+because it inclines to yellow, the Excess of the yellow-making Rays
+whereby 'tis tinged with that Colour, being mixed with the faint blue
+between S and T, will draw it to a faint green. And so the Colours in
+order from P to [Greek: t] ought to be violet, indigo, blue, very faint
+green, white, faint yellow, orange, red. Thus it is by the computation:
+And they that please to view the Colours made by a Prism will find it so
+in Nature.
+
+These are the Colours on both sides the white when the Paper is held
+between the Prism and the Point X where the Colours meet, and the
+interjacent white vanishes. For if the Paper be held still farther off
+from the Prism, the most refrangible and least refrangible Rays will be
+wanting in the middle of the Light, and the rest of the Rays which are
+found there, will by mixture produce a fuller green than before. Also
+the yellow and blue will now become less compounded, and by consequence
+more intense than before. And this also agrees with experience.
+
+And if one look through a Prism upon a white Object encompassed with
+blackness or darkness, the reason of the Colours arising on the edges is
+much the same, as will appear to one that shall a little consider it. If
+a black Object be encompassed with a white one, the Colours which appear
+through the Prism are to be derived from the Light of the white one,
+spreading into the Regions of the black, and therefore they appear in a
+contrary order to that, when a white Object is surrounded with black.
+And the same is to be understood when an Object is viewed, whose parts
+are some of them less luminous than others. For in the borders of the
+more and less luminous Parts, Colours ought always by the same
+Principles to arise from the Excess of the Light of the more luminous,
+and to be of the same kind as if the darker parts were black, but yet to
+be more faint and dilute.
+
+What is said of Colours made by Prisms may be easily applied to Colours
+made by the Glasses of Telescopes or Microscopes, or by the Humours of
+the Eye. For if the Object-glass of a Telescope be thicker on one side
+than on the other, or if one half of the Glass, or one half of the Pupil
+of the Eye be cover'd with any opake substance; the Object-glass, or
+that part of it or of the Eye which is not cover'd, may be consider'd as
+a Wedge with crooked Sides, and every Wedge of Glass or other pellucid
+Substance has the effect of a Prism in refracting the Light which passes
+through it.[L]
+
+How the Colours in the ninth and tenth Experiments of the first Part
+arise from the different Reflexibility of Light, is evident by what was
+there said. But it is observable in the ninth Experiment, that whilst
+the Sun's direct Light is yellow, the Excess of the blue-making Rays in
+the reflected beam of Light MN, suffices only to bring that yellow to a
+pale white inclining to blue, and not to tinge it with a manifestly blue
+Colour. To obtain therefore a better blue, I used instead of the yellow
+Light of the Sun the white Light of the Clouds, by varying a little the
+Experiment, as follows.
+
+[Illustration: FIG. 13.]
+
+_Exper._ 16 Let HFG [in _Fig._ 13.] represent a Prism in the open Air,
+and S the Eye of the Spectator, viewing the Clouds by their Light coming
+into the Prism at the Plane Side FIGK, and reflected in it by its Base
+HEIG, and thence going out through its Plane Side HEFK to the Eye. And
+when the Prism and Eye are conveniently placed, so that the Angles of
+Incidence and Reflexion at the Base may be about 40 Degrees, the
+Spectator will see a Bow MN of a blue Colour, running from one End of
+the Base to the other, with the Concave Side towards him, and the Part
+of the Base IMNG beyond this Bow will be brighter than the other Part
+EMNH on the other Side of it. This blue Colour MN being made by nothing
+else than by Reflexion of a specular Superficies, seems so odd a
+Phænomenon, and so difficult to be explained by the vulgar Hypothesis of
+Philosophers, that I could not but think it deserved to be taken Notice
+of. Now for understanding the Reason of it, suppose the Plane ABC to cut
+the Plane Sides and Base of the Prism perpendicularly. From the Eye to
+the Line BC, wherein that Plane cuts the Base, draw the Lines S_p_ and
+S_t_, in the Angles S_pc_ 50 degr. 1/9, and S_tc_ 49 degr. 1/28, and the
+Point _p_ will be the Limit beyond which none of the most refrangible
+Rays can pass through the Base of the Prism, and be refracted, whose
+Incidence is such that they may be reflected to the Eye; and the Point
+_t_ will be the like Limit for the least refrangible Rays, that is,
+beyond which none of them can pass through the Base, whose Incidence is
+such that by Reflexion they may come to the Eye. And the Point _r_ taken
+in the middle Way between _p_ and _t_, will be the like Limit for the
+meanly refrangible Rays. And therefore all the least refrangible Rays
+which fall upon the Base beyond _t_, that is, between _t_ and B, and can
+come from thence to the Eye, will be reflected thither: But on this side
+_t_, that is, between _t_ and _c_, many of these Rays will be
+transmitted through the Base. And all the most refrangible Rays which
+fall upon the Base beyond _p_, that is, between, _p_ and B, and can by
+Reflexion come from thence to the Eye, will be reflected thither, but
+every where between _p_ and _c_, many of these Rays will get through the
+Base, and be refracted; and the same is to be understood of the meanly
+refrangible Rays on either side of the Point _r_. Whence it follows,
+that the Base of the Prism must every where between _t_ and B, by a
+total Reflexion of all sorts of Rays to the Eye, look white and bright.
+And every where between _p_ and C, by reason of the Transmission of many
+Rays of every sort, look more pale, obscure, and dark. But at _r_, and
+in other Places between _p_ and _t_, where all the more refrangible Rays
+are reflected to the Eye, and many of the less refrangible are
+transmitted, the Excess of the most refrangible in the reflected Light
+will tinge that Light with their Colour, which is violet and blue. And
+this happens by taking the Line C _prt_ B any where between the Ends of
+the Prism HG and EI.
+
+
+_PROP._ IX. PROB. IV.
+
+_By the discovered Properties of Light to explain the Colours of the
+Rain-bow._
+
+[Illustration: FIG. 14.]
+
+This Bow never appears, but where it rains in the Sun-shine, and may be
+made artificially by spouting up Water which may break aloft, and
+scatter into Drops, and fall down like Rain. For the Sun shining upon
+these Drops certainly causes the Bow to appear to a Spectator standing
+in a due Position to the Rain and Sun. And hence it is now agreed upon,
+that this Bow is made by Refraction of the Sun's Light in drops of
+falling Rain. This was understood by some of the Antients, and of late
+more fully discover'd and explain'd by the famous _Antonius de Dominis_
+Archbishop of _Spalato_, in his book _De Radiis Visûs & Lucis_,
+published by his Friend _Bartolus_ at _Venice_, in the Year 1611, and
+written above 20 Years before. For he teaches there how the interior Bow
+is made in round Drops of Rain by two Refractions of the Sun's Light,
+and one Reflexion between them, and the exterior by two Refractions, and
+two sorts of Reflexions between them in each Drop of Water, and proves
+his Explications by Experiments made with a Phial full of Water, and
+with Globes of Glass filled with Water, and placed in the Sun to make
+the Colours of the two Bows appear in them. The same Explication
+_Des-Cartes_ hath pursued in his Meteors, and mended that of the
+exterior Bow. But whilst they understood not the true Origin of Colours,
+it's necessary to pursue it here a little farther. For understanding
+therefore how the Bow is made, let a Drop of Rain, or any other
+spherical transparent Body be represented by the Sphere BNFG, [in _Fig._
+14.] described with the Center C, and Semi-diameter CN. And let AN be
+one of the Sun's Rays incident upon it at N, and thence refracted to F,
+where let it either go out of the Sphere by Refraction towards V, or be
+reflected to G; and at G let it either go out by Refraction to R, or be
+reflected to H; and at H let it go out by Refraction towards S, cutting
+the incident Ray in Y. Produce AN and RG, till they meet in X, and upon
+AX and NF, let fall the Perpendiculars CD and CE, and produce CD till it
+fall upon the Circumference at L. Parallel to the incident Ray AN draw
+the Diameter BQ, and let the Sine of Incidence out of Air into Water be
+to the Sine of Refraction as I to R. Now, if you suppose the Point of
+Incidence N to move from the Point B, continually till it come to L, the
+Arch QF will first increase and then decrease, and so will the Angle AXR
+which the Rays AN and GR contain; and the Arch QF and Angle AXR will be
+biggest when ND is to CN as sqrt(II - RR) to sqrt(3)RR, in which
+case NE will be to ND as 2R to I. Also the Angle AYS, which the Rays AN
+and HS contain will first decrease, and then increase and grow least
+when ND is to CN as sqrt(II - RR) to sqrt(8)RR, in which case NE
+will be to ND, as 3R to I. And so the Angle which the next emergent Ray
+(that is, the emergent Ray after three Reflexions) contains with the
+incident Ray AN will come to its Limit when ND is to CN as sqrt(II -
+RR) to sqrt(15)RR, in which case NE will be to ND as 4R to I. And the
+Angle which the Ray next after that Emergent, that is, the Ray emergent
+after four Reflexions, contains with the Incident, will come to its
+Limit, when ND is to CN as sqrt(II - RR) to sqrt(24)RR, in which
+case NE will be to ND as 5R to I; and so on infinitely, the Numbers 3,
+8, 15, 24, &c. being gather'd by continual Addition of the Terms of the
+arithmetical Progression 3, 5, 7, 9, &c. The Truth of all this
+Mathematicians will easily examine.[M]
+
+Now it is to be observed, that as when the Sun comes to his Tropicks,
+Days increase and decrease but a very little for a great while together;
+so when by increasing the distance CD, these Angles come to their
+Limits, they vary their quantity but very little for some time together,
+and therefore a far greater number of the Rays which fall upon all the
+Points N in the Quadrant BL, shall emerge in the Limits of these Angles,
+than in any other Inclinations. And farther it is to be observed, that
+the Rays which differ in Refrangibility will have different Limits of
+their Angles of Emergence, and by consequence according to their
+different Degrees of Refrangibility emerge most copiously in different
+Angles, and being separated from one another appear each in their proper
+Colours. And what those Angles are may be easily gather'd from the
+foregoing Theorem by Computation.
+
+For in the least refrangible Rays the Sines I and R (as was found above)
+are 108 and 81, and thence by Computation the greatest Angle AXR will be
+found 42 Degrees and 2 Minutes, and the least Angle AYS, 50 Degrees and
+57 Minutes. And in the most refrangible Rays the Sines I and R are 109
+and 81, and thence by Computation the greatest Angle AXR will be found
+40 Degrees and 17 Minutes, and the least Angle AYS 54 Degrees and 7
+Minutes.
+
+Suppose now that O [in _Fig._ 15.] is the Spectator's Eye, and OP a Line
+drawn parallel to the Sun's Rays and let POE, POF, POG, POH, be Angles
+of 40 Degr. 17 Min. 42 Degr. 2 Min. 50 Degr. 57 Min. and 54 Degr. 7 Min.
+respectively, and these Angles turned about their common Side OP, shall
+with their other Sides OE, OF; OG, OH, describe the Verges of two
+Rain-bows AF, BE and CHDG. For if E, F, G, H, be drops placed any where
+in the conical Superficies described by OE, OF, OG, OH, and be
+illuminated by the Sun's Rays SE, SF, SG, SH; the Angle SEO being equal
+to the Angle POE, or 40 Degr. 17 Min. shall be the greatest Angle in
+which the most refrangible Rays can after one Reflexion be refracted to
+the Eye, and therefore all the Drops in the Line OE shall send the most
+refrangible Rays most copiously to the Eye, and thereby strike the
+Senses with the deepest violet Colour in that Region. And in like
+manner the Angle SFO being equal to the Angle POF, or 42 Degr. 2 Min.
+shall be the greatest in which the least refrangible Rays after one
+Reflexion can emerge out of the Drops, and therefore those Rays shall
+come most copiously to the Eye from the Drops in the Line OF, and strike
+the Senses with the deepest red Colour in that Region. And by the same
+Argument, the Rays which have intermediate Degrees of Refrangibility
+shall come most copiously from Drops between E and F, and strike the
+Senses with the intermediate Colours, in the Order which their Degrees
+of Refrangibility require, that is in the Progress from E to F, or from
+the inside of the Bow to the outside in this order, violet, indigo,
+blue, green, yellow, orange, red. But the violet, by the mixture of the
+white Light of the Clouds, will appear faint and incline to purple.
+
+[Illustration: FIG. 15.]
+
+Again, the Angle SGO being equal to the Angle POG, or 50 Gr. 51 Min.
+shall be the least Angle in which the least refrangible Rays can after
+two Reflexions emerge out of the Drops, and therefore the least
+refrangible Rays shall come most copiously to the Eye from the Drops in
+the Line OG, and strike the Sense with the deepest red in that Region.
+And the Angle SHO being equal to the Angle POH, or 54 Gr. 7 Min. shall
+be the least Angle, in which the most refrangible Rays after two
+Reflexions can emerge out of the Drops; and therefore those Rays shall
+come most copiously to the Eye from the Drops in the Line OH, and strike
+the Senses with the deepest violet in that Region. And by the same
+Argument, the Drops in the Regions between G and H shall strike the
+Sense with the intermediate Colours in the Order which their Degrees of
+Refrangibility require, that is, in the Progress from G to H, or from
+the inside of the Bow to the outside in this order, red, orange, yellow,
+green, blue, indigo, violet. And since these four Lines OE, OF, OG, OH,
+may be situated any where in the above-mention'd conical Superficies;
+what is said of the Drops and Colours in these Lines is to be understood
+of the Drops and Colours every where in those Superficies.
+
+Thus shall there be made two Bows of Colours, an interior and stronger,
+by one Reflexion in the Drops, and an exterior and fainter by two; for
+the Light becomes fainter by every Reflexion. And their Colours shall
+lie in a contrary Order to one another, the red of both Bows bordering
+upon the Space GF, which is between the Bows. The Breadth of the
+interior Bow EOF measured cross the Colours shall be 1 Degr. 45 Min. and
+the Breadth of the exterior GOH shall be 3 Degr. 10 Min. and the
+distance between them GOF shall be 8 Gr. 15 Min. the greatest
+Semi-diameter of the innermost, that is, the Angle POF being 42 Gr. 2
+Min. and the least Semi-diameter of the outermost POG, being 50 Gr. 57
+Min. These are the Measures of the Bows, as they would be were the Sun
+but a Point; for by the Breadth of his Body, the Breadth of the Bows
+will be increased, and their Distance decreased by half a Degree, and so
+the breadth of the interior Iris will be 2 Degr. 15 Min. that of the
+exterior 3 Degr. 40 Min. their distance 8 Degr. 25 Min. the greatest
+Semi-diameter of the interior Bow 42 Degr. 17 Min. and the least of the
+exterior 50 Degr. 42 Min. And such are the Dimensions of the Bows in the
+Heavens found to be very nearly, when their Colours appear strong and
+perfect. For once, by such means as I then had, I measured the greatest
+Semi-diameter of the interior Iris about 42 Degrees, and the breadth of
+the red, yellow and green in that Iris 63 or 64 Minutes, besides the
+outmost faint red obscured by the brightness of the Clouds, for which we
+may allow 3 or 4 Minutes more. The breadth of the blue was about 40
+Minutes more besides the violet, which was so much obscured by the
+brightness of the Clouds, that I could not measure its breadth. But
+supposing the breadth of the blue and violet together to equal that of
+the red, yellow and green together, the whole breadth of this Iris will
+be about 2-1/4 Degrees, as above. The least distance between this Iris
+and the exterior Iris was about 8 Degrees and 30 Minutes. The exterior
+Iris was broader than the interior, but so faint, especially on the blue
+side, that I could not measure its breadth distinctly. At another time
+when both Bows appeared more distinct, I measured the breadth of the
+interior Iris 2 Gr. 10´, and the breadth of the red, yellow and green in
+the exterior Iris, was to the breadth of the same Colours in the
+interior as 3 to 2.
+
+This Explication of the Rain-bow is yet farther confirmed by the known
+Experiment (made by _Antonius de Dominis_ and _Des-Cartes_) of hanging
+up any where in the Sun-shine a Glass Globe filled with Water, and
+viewing it in such a posture, that the Rays which come from the Globe to
+the Eye may contain with the Sun's Rays an Angle of either 42 or 50
+Degrees. For if the Angle be about 42 or 43 Degrees, the Spectator
+(suppose at O) shall see a full red Colour in that side of the Globe
+opposed to the Sun as 'tis represented at F, and if that Angle become
+less (suppose by depressing the Globe to E) there will appear other
+Colours, yellow, green and blue successive in the same side of the
+Globe. But if the Angle be made about 50 Degrees (suppose by lifting up
+the Globe to G) there will appear a red Colour in that side of the Globe
+towards the Sun, and if the Angle be made greater (suppose by lifting
+up the Globe to H) the red will turn successively to the other Colours,
+yellow, green and blue. The same thing I have tried, by letting a Globe
+rest, and raising or depressing the Eye, or otherwise moving it to make
+the Angle of a just magnitude.
+
+I have heard it represented, that if the Light of a Candle be refracted
+by a Prism to the Eye; when the blue Colour falls upon the Eye, the
+Spectator shall see red in the Prism, and when the red falls upon the
+Eye he shall see blue; and if this were certain, the Colours of the
+Globe and Rain-bow ought to appear in a contrary order to what we find.
+But the Colours of the Candle being very faint, the mistake seems to
+arise from the difficulty of discerning what Colours fall on the Eye.
+For, on the contrary, I have sometimes had occasion to observe in the
+Sun's Light refracted by a Prism, that the Spectator always sees that
+Colour in the Prism which falls upon his Eye. And the same I have found
+true also in Candle-light. For when the Prism is moved slowly from the
+Line which is drawn directly from the Candle to the Eye, the red appears
+first in the Prism and then the blue, and therefore each of them is seen
+when it falls upon the Eye. For the red passes over the Eye first, and
+then the blue.
+
+The Light which comes through drops of Rain by two Refractions without
+any Reflexion, ought to appear strongest at the distance of about 26
+Degrees from the Sun, and to decay gradually both ways as the distance
+from him increases and decreases. And the same is to be understood of
+Light transmitted through spherical Hail-stones. And if the Hail be a
+little flatted, as it often is, the Light transmitted may grow so strong
+at a little less distance than that of 26 Degrees, as to form a Halo
+about the Sun or Moon; which Halo, as often as the Hail-stones are duly
+figured may be colour'd, and then it must be red within by the least
+refrangible Rays, and blue without by the most refrangible ones,
+especially if the Hail-stones have opake Globules of Snow in their
+center to intercept the Light within the Halo (as _Hugenius_ has
+observ'd) and make the inside thereof more distinctly defined than it
+would otherwise be. For such Hail-stones, though spherical, by
+terminating the Light by the Snow, may make a Halo red within and
+colourless without, and darker in the red than without, as Halos used to
+be. For of those Rays which pass close by the Snow the Rubriform will be
+least refracted, and so come to the Eye in the directest Lines.
+
+The Light which passes through a drop of Rain after two Refractions, and
+three or more Reflexions, is scarce strong enough to cause a sensible
+Bow; but in those Cylinders of Ice by which _Hugenius_ explains the
+_Parhelia_, it may perhaps be sensible.
+
+
+_PROP._ X. PROB. V.
+
+_By the discovered Properties of Light to explain the permanent Colours
+of Natural Bodies._
+
+These Colours arise from hence, that some natural Bodies reflect some
+sorts of Rays, others other sorts more copiously than the rest. Minium
+reflects the least refrangible or red-making Rays most copiously, and
+thence appears red. Violets reflect the most refrangible most copiously,
+and thence have their Colour, and so of other Bodies. Every Body
+reflects the Rays of its own Colour more copiously than the rest, and
+from their excess and predominance in the reflected Light has its
+Colour.
+
+_Exper._ 17. For if in the homogeneal Lights obtained by the solution of
+the Problem proposed in the fourth Proposition of the first Part of this
+Book, you place Bodies of several Colours, you will find, as I have
+done, that every Body looks most splendid and luminous in the Light of
+its own Colour. Cinnaber in the homogeneal red Light is most
+resplendent, in the green Light it is manifestly less resplendent, and
+in the blue Light still less. Indigo in the violet blue Light is most
+resplendent, and its splendor is gradually diminish'd, as it is removed
+thence by degrees through the green and yellow Light to the red. By a
+Leek the green Light, and next that the blue and yellow which compound
+green, are more strongly reflected than the other Colours red and
+violet, and so of the rest. But to make these Experiments the more
+manifest, such Bodies ought to be chosen as have the fullest and most
+vivid Colours, and two of those Bodies are to be compared together.
+Thus, for instance, if Cinnaber and _ultra_-marine blue, or some other
+full blue be held together in the red homogeneal Light, they will both
+appear red, but the Cinnaber will appear of a strongly luminous and
+resplendent red, and the _ultra_-marine blue of a faint obscure and dark
+red; and if they be held together in the blue homogeneal Light, they
+will both appear blue, but the _ultra_-marine will appear of a strongly
+luminous and resplendent blue, and the Cinnaber of a faint and dark
+blue. Which puts it out of dispute that the Cinnaber reflects the red
+Light much more copiously than the _ultra_-marine doth, and the
+_ultra_-marine reflects the blue Light much more copiously than the
+Cinnaber doth. The same Experiment may be tried successfully with red
+Lead and Indigo, or with any other two colour'd Bodies, if due allowance
+be made for the different strength or weakness of their Colour and
+Light.
+
+And as the reason of the Colours of natural Bodies is evident by these
+Experiments, so it is farther confirmed and put past dispute by the two
+first Experiments of the first Part, whereby 'twas proved in such Bodies
+that the reflected Lights which differ in Colours do differ also in
+degrees of Refrangibility. For thence it's certain, that some Bodies
+reflect the more refrangible, others the less refrangible Rays more
+copiously.
+
+And that this is not only a true reason of these Colours, but even the
+only reason, may appear farther from this Consideration, that the Colour
+of homogeneal Light cannot be changed by the Reflexion of natural
+Bodies.
+
+For if Bodies by Reflexion cannot in the least change the Colour of any
+one sort of Rays, they cannot appear colour'd by any other means than by
+reflecting those which either are of their own Colour, or which by
+mixture must produce it.
+
+But in trying Experiments of this kind care must be had that the Light
+be sufficiently homogeneal. For if Bodies be illuminated by the ordinary
+prismatick Colours, they will appear neither of their own Day-light
+Colours, nor of the Colour of the Light cast on them, but of some middle
+Colour between both, as I have found by Experience. Thus red Lead (for
+instance) illuminated with the ordinary prismatick green will not appear
+either red or green, but orange or yellow, or between yellow and green,
+accordingly as the green Light by which 'tis illuminated is more or less
+compounded. For because red Lead appears red when illuminated with white
+Light, wherein all sorts of Rays are equally mix'd, and in the green
+Light all sorts of Rays are not equally mix'd, the Excess of the
+yellow-making, green-making and blue-making Rays in the incident green
+Light, will cause those Rays to abound so much in the reflected Light,
+as to draw the Colour from red towards their Colour. And because the red
+Lead reflects the red-making Rays most copiously in proportion to their
+number, and next after them the orange-making and yellow-making Rays;
+these Rays in the reflected Light will be more in proportion to the
+Light than they were in the incident green Light, and thereby will draw
+the reflected Light from green towards their Colour. And therefore the
+red Lead will appear neither red nor green, but of a Colour between
+both.
+
+In transparently colour'd Liquors 'tis observable, that their Colour
+uses to vary with their thickness. Thus, for instance, a red Liquor in a
+conical Glass held between the Light and the Eye, looks of a pale and
+dilute yellow at the bottom where 'tis thin, and a little higher where
+'tis thicker grows orange, and where 'tis still thicker becomes red, and
+where 'tis thickest the red is deepest and darkest. For it is to be
+conceiv'd that such a Liquor stops the indigo-making and violet-making
+Rays most easily, the blue-making Rays more difficultly, the
+green-making Rays still more difficultly, and the red-making most
+difficultly: And that if the thickness of the Liquor be only so much as
+suffices to stop a competent number of the violet-making and
+indigo-making Rays, without diminishing much the number of the rest, the
+rest must (by _Prop._ 6. _Part_ 2.) compound a pale yellow. But if the
+Liquor be so much thicker as to stop also a great number of the
+blue-making Rays, and some of the green-making, the rest must compound
+an orange; and where it is so thick as to stop also a great number of
+the green-making and a considerable number of the yellow-making, the
+rest must begin to compound a red, and this red must grow deeper and
+darker as the yellow-making and orange-making Rays are more and more
+stopp'd by increasing the thickness of the Liquor, so that few Rays
+besides the red-making can get through.
+
+Of this kind is an Experiment lately related to me by Mr. _Halley_, who,
+in diving deep into the Sea in a diving Vessel, found in a clear
+Sun-shine Day, that when he was sunk many Fathoms deep into the Water
+the upper part of his Hand on which the Sun shone directly through the
+Water and through a small Glass Window in the Vessel appeared of a red
+Colour, like that of a Damask Rose, and the Water below and the under
+part of his Hand illuminated by Light reflected from the Water below
+look'd green. For thence it may be gather'd, that the Sea-Water reflects
+back the violet and blue-making Rays most easily, and lets the
+red-making Rays pass most freely and copiously to great Depths. For
+thereby the Sun's direct Light at all great Depths, by reason of the
+predominating red-making Rays, must appear red; and the greater the
+Depth is, the fuller and intenser must that red be. And at such Depths
+as the violet-making Rays scarce penetrate unto, the blue-making,
+green-making, and yellow-making Rays being reflected from below more
+copiously than the red-making ones, must compound a green.
+
+Now, if there be two Liquors of full Colours, suppose a red and blue,
+and both of them so thick as suffices to make their Colours sufficiently
+full; though either Liquor be sufficiently transparent apart, yet will
+you not be able to see through both together. For, if only the
+red-making Rays pass through one Liquor, and only the blue-making
+through the other, no Rays can pass through both. This Mr. _Hook_ tried
+casually with Glass Wedges filled with red and blue Liquors, and was
+surprized at the unexpected Event, the reason of it being then unknown;
+which makes me trust the more to his Experiment, though I have not tried
+it my self. But he that would repeat it, must take care the Liquors be
+of very good and full Colours.
+
+Now, whilst Bodies become coloured by reflecting or transmitting this or
+that sort of Rays more copiously than the rest, it is to be conceived
+that they stop and stifle in themselves the Rays which they do not
+reflect or transmit. For, if Gold be foliated and held between your Eye
+and the Light, the Light looks of a greenish blue, and therefore massy
+Gold lets into its Body the blue-making Rays to be reflected to and fro
+within it till they be stopp'd and stifled, whilst it reflects the
+yellow-making outwards, and thereby looks yellow. And much after the
+same manner that Leaf Gold is yellow by reflected, and blue by
+transmitted Light, and massy Gold is yellow in all Positions of the Eye;
+there are some Liquors, as the Tincture of _Lignum Nephriticum_, and
+some sorts of Glass which transmit one sort of Light most copiously, and
+reflect another sort, and thereby look of several Colours, according to
+the Position of the Eye to the Light. But, if these Liquors or Glasses
+were so thick and massy that no Light could get through them, I question
+not but they would like all other opake Bodies appear of one and the
+same Colour in all Positions of the Eye, though this I cannot yet affirm
+by Experience. For all colour'd Bodies, so far as my Observation
+reaches, may be seen through if made sufficiently thin, and therefore
+are in some measure transparent, and differ only in degrees of
+Transparency from tinged transparent Liquors; these Liquors, as well as
+those Bodies, by a sufficient Thickness becoming opake. A transparent
+Body which looks of any Colour by transmitted Light, may also look of
+the same Colour by reflected Light, the Light of that Colour being
+reflected by the farther Surface of the Body, or by the Air beyond it.
+And then the reflected Colour will be diminished, and perhaps cease, by
+making the Body very thick, and pitching it on the backside to diminish
+the Reflexion of its farther Surface, so that the Light reflected from
+the tinging Particles may predominate. In such Cases, the Colour of the
+reflected Light will be apt to vary from that of the Light transmitted.
+But whence it is that tinged Bodies and Liquors reflect some sort of
+Rays, and intromit or transmit other sorts, shall be said in the next
+Book. In this Proposition I content my self to have put it past dispute,
+that Bodies have such Properties, and thence appear colour'd.
+
+
+_PROP._ XI. PROB. VI.
+
+_By mixing colour'd Lights to compound a beam of Light of the same
+Colour and Nature with a beam of the Sun's direct Light, and therein to
+experience the Truth of the foregoing Propositions._
+
+[Illustration: FIG. 16.]
+
+Let ABC _abc_ [in _Fig._ 16.] represent a Prism, by which the Sun's
+Light let into a dark Chamber through the Hole F, may be refracted
+towards the Lens MN, and paint upon it at _p_, _q_, _r_, _s_, and _t_,
+the usual Colours violet, blue, green, yellow, and red, and let the
+diverging Rays by the Refraction of this Lens converge again towards X,
+and there, by the mixture of all those their Colours, compound a white
+according to what was shewn above. Then let another Prism DEG _deg_,
+parallel to the former, be placed at X, to refract that white Light
+upwards towards Y. Let the refracting Angles of the Prisms, and their
+distances from the Lens be equal, so that the Rays which converged from
+the Lens towards X, and without Refraction, would there have crossed and
+diverged again, may by the Refraction of the second Prism be reduced
+into Parallelism and diverge no more. For then those Rays will recompose
+a beam of white Light XY. If the refracting Angle of either Prism be the
+bigger, that Prism must be so much the nearer to the Lens. You will know
+when the Prisms and the Lens are well set together, by observing if the
+beam of Light XY, which comes out of the second Prism be perfectly white
+to the very edges of the Light, and at all distances from the Prism
+continue perfectly and totally white like a beam of the Sun's Light. For
+till this happens, the Position of the Prisms and Lens to one another
+must be corrected; and then if by the help of a long beam of Wood, as is
+represented in the Figure, or by a Tube, or some other such Instrument,
+made for that Purpose, they be made fast in that Situation, you may try
+all the same Experiments in this compounded beam of Light XY, which have
+been made in the Sun's direct Light. For this compounded beam of Light
+has the same appearance, and is endow'd with all the same Properties
+with a direct beam of the Sun's Light, so far as my Observation reaches.
+And in trying Experiments in this beam you may by stopping any of the
+Colours, _p_, _q_, _r_, _s_, and _t_, at the Lens, see how the Colours
+produced in the Experiments are no other than those which the Rays had
+at the Lens before they entered the Composition of this Beam: And by
+consequence, that they arise not from any new Modifications of the Light
+by Refractions and Reflexions, but from the various Separations and
+Mixtures of the Rays originally endow'd with their colour-making
+Qualities.
+
+So, for instance, having with a Lens 4-1/4 Inches broad, and two Prisms
+on either hand 6-1/4 Feet distant from the Lens, made such a beam of
+compounded Light; to examine the reason of the Colours made by Prisms, I
+refracted this compounded beam of Light XY with another Prism HIK _kh_,
+and thereby cast the usual Prismatick Colours PQRST upon the Paper LV
+placed behind. And then by stopping any of the Colours _p_, _q_, _r_,
+_s_, _t_, at the Lens, I found that the same Colour would vanish at the
+Paper. So if the Purple _p_ was stopp'd at the Lens, the Purple P upon
+the Paper would vanish, and the rest of the Colours would remain
+unalter'd, unless perhaps the blue, so far as some purple latent in it
+at the Lens might be separated from it by the following Refractions. And
+so by intercepting the green upon the Lens, the green R upon the Paper
+would vanish, and so of the rest; which plainly shews, that as the white
+beam of Light XY was compounded of several Lights variously colour'd at
+the Lens, so the Colours which afterwards emerge out of it by new
+Refractions are no other than those of which its Whiteness was
+compounded. The Refraction of the Prism HIK _kh_ generates the Colours
+PQRST upon the Paper, not by changing the colorific Qualities of the
+Rays, but by separating the Rays which had the very same colorific
+Qualities before they enter'd the Composition of the refracted beam of
+white Light XY. For otherwise the Rays which were of one Colour at the
+Lens might be of another upon the Paper, contrary to what we find.
+
+So again, to examine the reason of the Colours of natural Bodies, I
+placed such Bodies in the Beam of Light XY, and found that they all
+appeared there of those their own Colours which they have in Day-light,
+and that those Colours depend upon the Rays which had the same Colours
+at the Lens before they enter'd the Composition of that beam. Thus, for
+instance, Cinnaber illuminated by this beam appears of the same red
+Colour as in Day-light; and if at the Lens you intercept the
+green-making and blue-making Rays, its redness will become more full and
+lively: But if you there intercept the red-making Rays, it will not any
+longer appear red, but become yellow or green, or of some other Colour,
+according to the sorts of Rays which you do not intercept. So Gold in
+this Light XY appears of the same yellow Colour as in Day-light, but by
+intercepting at the Lens a due Quantity of the yellow-making Rays it
+will appear white like Silver (as I have tried) which shews that its
+yellowness arises from the Excess of the intercepted Rays tinging that
+Whiteness with their Colour when they are let pass. So the Infusion of
+_Lignum Nephriticum_ (as I have also tried) when held in this beam of
+Light XY, looks blue by the reflected Part of the Light, and red by the
+transmitted Part of it, as when 'tis view'd in Day-light; but if you
+intercept the blue at the Lens the Infusion will lose its reflected blue
+Colour, whilst its transmitted red remains perfect, and by the loss of
+some blue-making Rays, wherewith it was allay'd, becomes more intense
+and full. And, on the contrary, if the red and orange-making Rays be
+intercepted at the Lens, the Infusion will lose its transmitted red,
+whilst its blue will remain and become more full and perfect. Which
+shews, that the Infusion does not tinge the Rays with blue and red, but
+only transmits those most copiously which were red-making before, and
+reflects those most copiously which were blue-making before. And after
+the same manner may the Reasons of other Phænomena be examined, by
+trying them in this artificial beam of Light XY.
+
+FOOTNOTES:
+
+[I] See p. 59.
+
+[J] _See our_ Author's Lect. Optic. _Part_ II. _Sect._ II. _p._ 239.
+
+[K] _As is done in our_ Author's Lect. Optic. _Part_ I. _Sect._ III.
+_and_ IV. _and Part_ II. _Sect._ II.
+
+[L] _See our_ Author's Lect. Optic. _Part_ II. _Sect._ II. _pag._ 269,
+&c.
+
+[M] _This is demonstrated in our_ Author's Lect. Optic. _Part_ I.
+_Sect._ IV. _Prop._ 35 _and_ 36.
+
+
+
+
+THE
+
+SECOND BOOK
+
+OF
+
+OPTICKS
+
+
+
+
+_PART I._
+
+_Observations concerning the Reflexions, Refractions, and Colours of
+thin transparent Bodies._
+
+
+It has been observed by others, that transparent Substances, as Glass,
+Water, Air, &c. when made very thin by being blown into Bubbles, or
+otherwise formed into Plates, do exhibit various Colours according to
+their various thinness, altho' at a greater thickness they appear very
+clear and colourless. In the former Book I forbore to treat of these
+Colours, because they seemed of a more difficult Consideration, and were
+not necessary for establishing the Properties of Light there discoursed
+of. But because they may conduce to farther Discoveries for compleating
+the Theory of Light, especially as to the constitution of the parts of
+natural Bodies, on which their Colours or Transparency depend; I have
+here set down an account of them. To render this Discourse short and
+distinct, I have first described the principal of my Observations, and
+then consider'd and made use of them. The Observations are these.
+
+_Obs._ 1. Compressing two Prisms hard together that their sides (which
+by chance were a very little convex) might somewhere touch one another:
+I found the place in which they touched to become absolutely
+transparent, as if they had there been one continued piece of Glass. For
+when the Light fell so obliquely on the Air, which in other places was
+between them, as to be all reflected; it seemed in that place of contact
+to be wholly transmitted, insomuch that when look'd upon, it appeared
+like a black or dark spot, by reason that little or no sensible Light
+was reflected from thence, as from other places; and when looked through
+it seemed (as it were) a hole in that Air which was formed into a thin
+Plate, by being compress'd between the Glasses. And through this hole
+Objects that were beyond might be seen distinctly, which could not at
+all be seen through other parts of the Glasses where the Air was
+interjacent. Although the Glasses were a little convex, yet this
+transparent spot was of a considerable breadth, which breadth seemed
+principally to proceed from the yielding inwards of the parts of the
+Glasses, by reason of their mutual pressure. For by pressing them very
+hard together it would become much broader than otherwise.
+
+_Obs._ 2. When the Plate of Air, by turning the Prisms about their
+common Axis, became so little inclined to the incident Rays, that some
+of them began to be transmitted, there arose in it many slender Arcs of
+Colours which at first were shaped almost like the Conchoid, as you see
+them delineated in the first Figure. And by continuing the Motion of the
+Prisms, these Arcs increased and bended more and more about the said
+transparent spot, till they were compleated into Circles or Rings
+incompassing it, and afterwards continually grew more and more
+contracted.
+
+[Illustration: FIG. 1.]
+
+These Arcs at their first appearance were of a violet and blue Colour,
+and between them were white Arcs of Circles, which presently by
+continuing the Motion of the Prisms became a little tinged in their
+inward Limbs with red and yellow, and to their outward Limbs the blue
+was adjacent. So that the order of these Colours from the central dark
+spot, was at that time white, blue, violet; black, red, orange, yellow,
+white, blue, violet, &c. But the yellow and red were much fainter than
+the blue and violet.
+
+The Motion of the Prisms about their Axis being continued, these Colours
+contracted more and more, shrinking towards the whiteness on either
+side of it, until they totally vanished into it. And then the Circles in
+those parts appear'd black and white, without any other Colours
+intermix'd. But by farther moving the Prisms about, the Colours again
+emerged out of the whiteness, the violet and blue at its inward Limb,
+and at its outward Limb the red and yellow. So that now their order from
+the central Spot was white, yellow, red; black; violet, blue, white,
+yellow, red, &c. contrary to what it was before.
+
+_Obs._ 3. When the Rings or some parts of them appeared only black and
+white, they were very distinct and well defined, and the blackness
+seemed as intense as that of the central Spot. Also in the Borders of
+the Rings, where the Colours began to emerge out of the whiteness, they
+were pretty distinct, which made them visible to a very great multitude.
+I have sometimes number'd above thirty Successions (reckoning every
+black and white Ring for one Succession) and seen more of them, which by
+reason of their smalness I could not number. But in other Positions of
+the Prisms, at which the Rings appeared of many Colours, I could not
+distinguish above eight or nine of them, and the Exterior of those were
+very confused and dilute.
+
+In these two Observations to see the Rings distinct, and without any
+other Colour than Black and white, I found it necessary to hold my Eye
+at a good distance from them. For by approaching nearer, although in the
+same inclination of my Eye to the Plane of the Rings, there emerged a
+bluish Colour out of the white, which by dilating it self more and more
+into the black, render'd the Circles less distinct, and left the white a
+little tinged with red and yellow. I found also by looking through a
+slit or oblong hole, which was narrower than the pupil of my Eye, and
+held close to it parallel to the Prisms, I could see the Circles much
+distincter and visible to a far greater number than otherwise.
+
+_Obs._ 4. To observe more nicely the order of the Colours which arose
+out of the white Circles as the Rays became less and less inclined to
+the Plate of Air; I took two Object-glasses, the one a Plano-convex for
+a fourteen Foot Telescope, and the other a large double Convex for one
+of about fifty Foot; and upon this, laying the other with its plane side
+downwards, I pressed them slowly together, to make the Colours
+successively emerge in the middle of the Circles, and then slowly lifted
+the upper Glass from the lower to make them successively vanish again in
+the same place. The Colour, which by pressing the Glasses together,
+emerged last in the middle of the other Colours, would upon its first
+appearance look like a Circle of a Colour almost uniform from the
+circumference to the center and by compressing the Glasses still more,
+grow continually broader until a new Colour emerged in its center, and
+thereby it became a Ring encompassing that new Colour. And by
+compressing the Glasses still more, the diameter of this Ring would
+increase, and the breadth of its Orbit or Perimeter decrease until
+another new Colour emerged in the center of the last: And so on until a
+third, a fourth, a fifth, and other following new Colours successively
+emerged there, and became Rings encompassing the innermost Colour, the
+last of which was the black Spot. And, on the contrary, by lifting up
+the upper Glass from the lower, the diameter of the Rings would
+decrease, and the breadth of their Orbit increase, until their Colours
+reached successively to the center; and then they being of a
+considerable breadth, I could more easily discern and distinguish their
+Species than before. And by this means I observ'd their Succession and
+Quantity to be as followeth.
+
+Next to the pellucid central Spot made by the contact of the Glasses
+succeeded blue, white, yellow, and red. The blue was so little in
+quantity, that I could not discern it in the Circles made by the Prisms,
+nor could I well distinguish any violet in it, but the yellow and red
+were pretty copious, and seemed about as much in extent as the white,
+and four or five times more than the blue. The next Circuit in order of
+Colours immediately encompassing these were violet, blue, green, yellow,
+and red: and these were all of them copious and vivid, excepting the
+green, which was very little in quantity, and seemed much more faint and
+dilute than the other Colours. Of the other four, the violet was the
+least in extent, and the blue less than the yellow or red. The third
+Circuit or Order was purple, blue, green, yellow, and red; in which the
+purple seemed more reddish than the violet in the former Circuit, and
+the green was much more conspicuous, being as brisk and copious as any
+of the other Colours, except the yellow, but the red began to be a
+little faded, inclining very much to purple. After this succeeded the
+fourth Circuit of green and red. The green was very copious and lively,
+inclining on the one side to blue, and on the other side to yellow. But
+in this fourth Circuit there was neither violet, blue, nor yellow, and
+the red was very imperfect and dirty. Also the succeeding Colours became
+more and more imperfect and dilute, till after three or four revolutions
+they ended in perfect whiteness. Their form, when the Glasses were most
+compress'd so as to make the black Spot appear in the center, is
+delineated in the second Figure; where _a_, _b_, _c_, _d_, _e_: _f_,
+_g_, _h_, _i_, _k_: _l_, _m_, _n_, _o_, _p_: _q_, _r_: _s_, _t_: _v_,
+_x_: _y_, _z_, denote the Colours reckon'd in order from the center,
+black, blue, white, yellow, red: violet, blue, green, yellow, red:
+purple, blue, green, yellow, red: green, red: greenish blue, red:
+greenish blue, pale red: greenish blue, reddish white.
+
+[Illustration: FIG. 2.]
+
+_Obs._ 5. To determine the interval of the Glasses, or thickness of the
+interjacent Air, by which each Colour was produced, I measured the
+Diameters of the first six Rings at the most lucid part of their Orbits,
+and squaring them, I found their Squares to be in the arithmetical
+Progression of the odd Numbers, 1, 3, 5, 7, 9, 11. And since one of
+these Glasses was plane, and the other spherical, their Intervals at
+those Rings must be in the same Progression. I measured also the
+Diameters of the dark or faint Rings between the more lucid Colours, and
+found their Squares to be in the arithmetical Progression of the even
+Numbers, 2, 4, 6, 8, 10, 12. And it being very nice and difficult to
+take these measures exactly; I repeated them divers times at divers
+parts of the Glasses, that by their Agreement I might be confirmed in
+them. And the same method I used in determining some others of the
+following Observations.
+
+_Obs._ 6. The Diameter of the sixth Ring at the most lucid part of its
+Orbit was 58/100 parts of an Inch, and the Diameter of the Sphere on
+which the double convex Object-glass was ground was about 102 Feet, and
+hence I gathered the thickness of the Air or Aereal Interval of the
+Glasses at that Ring. But some time after, suspecting that in making
+this Observation I had not determined the Diameter of the Sphere with
+sufficient accurateness, and being uncertain whether the Plano-convex
+Glass was truly plane, and not something concave or convex on that side
+which I accounted plane; and whether I had not pressed the Glasses
+together, as I often did, to make them touch; (For by pressing such
+Glasses together their parts easily yield inwards, and the Rings thereby
+become sensibly broader than they would be, did the Glasses keep their
+Figures.) I repeated the Experiment, and found the Diameter of the sixth
+lucid Ring about 55/100 parts of an Inch. I repeated the Experiment also
+with such an Object-glass of another Telescope as I had at hand. This
+was a double Convex ground on both sides to one and the same Sphere, and
+its Focus was distant from it 83-2/5 Inches. And thence, if the Sines of
+Incidence and Refraction of the bright yellow Light be assumed in
+proportion as 11 to 17, the Diameter of the Sphere to which the Glass
+was figured will by computation be found 182 Inches. This Glass I laid
+upon a flat one, so that the black Spot appeared in the middle of the
+Rings of Colours without any other Pressure than that of the weight of
+the Glass. And now measuring the Diameter of the fifth dark Circle as
+accurately as I could, I found it the fifth part of an Inch precisely.
+This Measure was taken with the points of a pair of Compasses on the
+upper Surface on the upper Glass, and my Eye was about eight or nine
+Inches distance from the Glass, almost perpendicularly over it, and the
+Glass was 1/6 of an Inch thick, and thence it is easy to collect that
+the true Diameter of the Ring between the Glasses was greater than its
+measur'd Diameter above the Glasses in the Proportion of 80 to 79, or
+thereabouts, and by consequence equal to 16/79 parts of an Inch, and its
+true Semi-diameter equal to 8/79 parts. Now as the Diameter of the
+Sphere (182 Inches) is to the Semi-diameter of this fifth dark Ring
+(8/79 parts of an Inch) so is this Semi-diameter to the thickness of the
+Air at this fifth dark Ring; which is therefore 32/567931 or
+100/1774784. Parts of an Inch; and the fifth Part thereof, _viz._ the
+1/88739 Part of an Inch, is the Thickness of the Air at the first of
+these dark Rings.
+
+The same Experiment I repeated with another double convex Object-glass
+ground on both sides to one and the same Sphere. Its Focus was distant
+from it 168-1/2 Inches, and therefore the Diameter of that Sphere was
+184 Inches. This Glass being laid upon the same plain Glass, the
+Diameter of the fifth of the dark Rings, when the black Spot in their
+Center appear'd plainly without pressing the Glasses, was by the measure
+of the Compasses upon the upper Glass 121/600 Parts of an Inch, and by
+consequence between the Glasses it was 1222/6000: For the upper Glass
+was 1/8 of an Inch thick, and my Eye was distant from it 8 Inches. And a
+third proportional to half this from the Diameter of the Sphere is
+5/88850 Parts of an Inch. This is therefore the Thickness of the Air at
+this Ring, and a fifth Part thereof, _viz._ the 1/88850th Part of an
+Inch is the Thickness thereof at the first of the Rings, as above.
+
+I tried the same Thing, by laying these Object-glasses upon flat Pieces
+of a broken Looking-glass, and found the same Measures of the Rings:
+Which makes me rely upon them till they can be determin'd more
+accurately by Glasses ground to larger Spheres, though in such Glasses
+greater care must be taken of a true Plane.
+
+These Dimensions were taken, when my Eye was placed almost
+perpendicularly over the Glasses, being about an Inch, or an Inch and a
+quarter, distant from the incident Rays, and eight Inches distant from
+the Glass; so that the Rays were inclined to the Glass in an Angle of
+about four Degrees. Whence by the following Observation you will
+understand, that had the Rays been perpendicular to the Glasses, the
+Thickness of the Air at these Rings would have been less in the
+Proportion of the Radius to the Secant of four Degrees, that is, of
+10000 to 10024. Let the Thicknesses found be therefore diminish'd in
+this Proportion, and they will become 1/88952 and 1/89063, or (to use
+the nearest round Number) the 1/89000th Part of an Inch. This is the
+Thickness of the Air at the darkest Part of the first dark Ring made by
+perpendicular Rays; and half this Thickness multiplied by the
+Progression, 1, 3, 5, 7, 9, 11, &c. gives the Thicknesses of the Air at
+the most luminous Parts of all the brightest Rings, _viz._ 1/178000,
+3/178000, 5/178000, 7/178000, &c. their arithmetical Means 2/178000,
+4/178000, 6/178000, &c. being its Thicknesses at the darkest Parts of
+all the dark ones.
+
+_Obs._ 7. The Rings were least, when my Eye was placed perpendicularly
+over the Glasses in the Axis of the Rings: And when I view'd them
+obliquely they became bigger, continually swelling as I removed my Eye
+farther from the Axis. And partly by measuring the Diameter of the same
+Circle at several Obliquities of my Eye, partly by other Means, as also
+by making use of the two Prisms for very great Obliquities, I found its
+Diameter, and consequently the Thickness of the Air at its Perimeter in
+all those Obliquities to be very nearly in the Proportions express'd in
+this Table.
+
+-------------------+--------------------+----------+----------
+Angle of Incidence |Angle of Refraction |Diameter |Thickness
+ on | into | of the | of the
+ the Air. | the Air. | Ring. | Air.
+-------------------+--------------------+----------+----------
+ Deg. Min. | | |
+ | | |
+ 00 00 | 00 00 | 10 | 10
+ | | |
+ 06 26 | 10 00 | 10-1/13 | 10-2/13
+ | | |
+ 12 45 | 20 00 | 10-1/3 | 10-2/3
+ | | |
+ 18 49 | 30 00 | 10-3/4 | 11-1/2
+ | | |
+ 24 30 | 40 00 | 11-2/5 | 13
+ | | |
+ 29 37 | 50 00 | 12-1/2 | 15-1/2
+ | | |
+ 33 58 | 60 00 | 14 | 20
+ | | |
+ 35 47 | 65 00 | 15-1/4 | 23-1/4
+ | | |
+ 37 19 | 70 00 | 16-4/5 | 28-1/4
+ | | |
+ 38 33 | 75 00 | 19-1/4 | 37
+ | | |
+ 39 27 | 80 00 | 22-6/7 | 52-1/4
+ | | |
+ 40 00 | 85 00 | 29 | 84-1/12
+ | | |
+ 40 11 | 90 00 | 35 | 122-1/2
+-------------------+--------------------+----------+----------
+
+In the two first Columns are express'd the Obliquities of the incident
+and emergent Rays to the Plate of the Air, that is, their Angles of
+Incidence and Refraction. In the third Column the Diameter of any
+colour'd Ring at those Obliquities is expressed in Parts, of which ten
+constitute that Diameter when the Rays are perpendicular. And in the
+fourth Column the Thickness of the Air at the Circumference of that Ring
+is expressed in Parts, of which also ten constitute its Thickness when
+the Rays are perpendicular.
+
+And from these Measures I seem to gather this Rule: That the Thickness
+of the Air is proportional to the Secant of an Angle, whose Sine is a
+certain mean Proportional between the Sines of Incidence and Refraction.
+And that mean Proportional, so far as by these Measures I can determine
+it, is the first of an hundred and six arithmetical mean Proportionals
+between those Sines counted from the bigger Sine, that is, from the Sine
+of Refraction when the Refraction is made out of the Glass into the
+Plate of Air, or from the Sine of Incidence when the Refraction is made
+out of the Plate of Air into the Glass.
+
+_Obs._ 8. The dark Spot in the middle of the Rings increased also by the
+Obliquation of the Eye, although almost insensibly. But, if instead of
+the Object-glasses the Prisms were made use of, its Increase was more
+manifest when viewed so obliquely that no Colours appear'd about it. It
+was least when the Rays were incident most obliquely on the interjacent
+Air, and as the obliquity decreased it increased more and more until the
+colour'd Rings appear'd, and then decreased again, but not so much as it
+increased before. And hence it is evident, that the Transparency was
+not only at the absolute Contact of the Glasses, but also where they had
+some little Interval. I have sometimes observed the Diameter of that
+Spot to be between half and two fifth parts of the Diameter of the
+exterior Circumference of the red in the first Circuit or Revolution of
+Colours when view'd almost perpendicularly; whereas when view'd
+obliquely it hath wholly vanish'd and become opake and white like the
+other parts of the Glass; whence it may be collected that the Glasses
+did then scarcely, or not at all, touch one another, and that their
+Interval at the perimeter of that Spot when view'd perpendicularly was
+about a fifth or sixth part of their Interval at the circumference of
+the said red.
+
+_Obs._ 9. By looking through the two contiguous Object-glasses, I found
+that the interjacent Air exhibited Rings of Colours, as well by
+transmitting Light as by reflecting it. The central Spot was now white,
+and from it the order of the Colours were yellowish red; black, violet,
+blue, white, yellow, red; violet, blue, green, yellow, red, &c. But
+these Colours were very faint and dilute, unless when the Light was
+trajected very obliquely through the Glasses: For by that means they
+became pretty vivid. Only the first yellowish red, like the blue in the
+fourth Observation, was so little and faint as scarcely to be discern'd.
+Comparing the colour'd Rings made by Reflexion, with these made by
+transmission of the Light; I found that white was opposite to black, red
+to blue, yellow to violet, and green to a Compound of red and violet.
+That is, those parts of the Glass were black when looked through, which
+when looked upon appeared white, and on the contrary. And so those which
+in one case exhibited blue, did in the other case exhibit red. And the
+like of the other Colours. The manner you have represented in the third
+Figure, where AB, CD, are the Surfaces of the Glasses contiguous at E,
+and the black Lines between them are their Distances in arithmetical
+Progression, and the Colours written above are seen by reflected Light,
+and those below by Light transmitted (p. 209).
+
+_Obs._ 10. Wetting the Object-glasses a little at their edges, the Water
+crept in slowly between them, and the Circles thereby became less and
+the Colours more faint: Insomuch that as the Water crept along, one half
+of them at which it first arrived would appear broken off from the other
+half, and contracted into a less Room. By measuring them I found the
+Proportions of their Diameters to the Diameters of the like Circles made
+by Air to be about seven to eight, and consequently the Intervals of the
+Glasses at like Circles, caused by those two Mediums Water and Air, are
+as about three to four. Perhaps it may be a general Rule, That if any
+other Medium more or less dense than Water be compress'd between the
+Glasses, their Intervals at the Rings caused thereby will be to their
+Intervals caused by interjacent Air, as the Sines are which measure the
+Refraction made out of that Medium into Air.
+
+_Obs._ 11. When the Water was between the Glasses, if I pressed the
+upper Glass variously at its edges to make the Rings move nimbly from
+one place to another, a little white Spot would immediately follow the
+center of them, which upon creeping in of the ambient Water into that
+place would presently vanish. Its appearance was such as interjacent Air
+would have caused, and it exhibited the same Colours. But it was not
+air, for where any Bubbles of Air were in the Water they would not
+vanish. The Reflexion must have rather been caused by a subtiler Medium,
+which could recede through the Glasses at the creeping in of the Water.
+
+_Obs._ 12. These Observations were made in the open Air. But farther to
+examine the Effects of colour'd Light falling on the Glasses, I darken'd
+the Room, and view'd them by Reflexion of the Colours of a Prism cast on
+a Sheet of white Paper, my Eye being so placed that I could see the
+colour'd Paper by Reflexion in the Glasses, as in a Looking-glass. And
+by this means the Rings became distincter and visible to a far greater
+number than in the open Air. I have sometimes seen more than twenty of
+them, whereas in the open Air I could not discern above eight or nine.
+
+[Illustration: FIG. 3.]
+
+_Obs._ 13. Appointing an Assistant to move the Prism to and fro about
+its Axis, that all the Colours might successively fall on that part of
+the Paper which I saw by Reflexion from that part of the Glasses, where
+the Circles appear'd, so that all the Colours might be successively
+reflected from the Circles to my Eye, whilst I held it immovable, I
+found the Circles which the red Light made to be manifestly bigger than
+those which were made by the blue and violet. And it was very pleasant
+to see them gradually swell or contract accordingly as the Colour of the
+Light was changed. The Interval of the Glasses at any of the Rings when
+they were made by the utmost red Light, was to their Interval at the
+same Ring when made by the utmost violet, greater than as 3 to 2, and
+less than as 13 to 8. By the most of my Observations it was as 14 to 9.
+And this Proportion seem'd very nearly the same in all Obliquities of my
+Eye; unless when two Prisms were made use of instead of the
+Object-glasses. For then at a certain great obliquity of my Eye, the
+Rings made by the several Colours seem'd equal, and at a greater
+obliquity those made by the violet would be greater than the same Rings
+made by the red: the Refraction of the Prism in this case causing the
+most refrangible Rays to fall more obliquely on that plate of the Air
+than the least refrangible ones. Thus the Experiment succeeded in the
+colour'd Light, which was sufficiently strong and copious to make the
+Rings sensible. And thence it may be gather'd, that if the most
+refrangible and least refrangible Rays had been copious enough to make
+the Rings sensible without the mixture of other Rays, the Proportion
+which here was 14 to 9 would have been a little greater, suppose 14-1/4
+or 14-1/3 to 9.
+
+_Obs._ 14. Whilst the Prism was turn'd about its Axis with an uniform
+Motion, to make all the several Colours fall successively upon the
+Object-glasses, and thereby to make the Rings contract and dilate: The
+Contraction or Dilatation of each Ring thus made by the variation of its
+Colour was swiftest in the red, and slowest in the violet, and in the
+intermediate Colours it had intermediate degrees of Celerity. Comparing
+the quantity of Contraction and Dilatation made by all the degrees of
+each Colour, I found that it was greatest in the red; less in the
+yellow, still less in the blue, and least in the violet. And to make as
+just an Estimation as I could of the Proportions of their Contractions
+or Dilatations, I observ'd that the whole Contraction or Dilatation of
+the Diameter of any Ring made by all the degrees of red, was to that of
+the Diameter of the same Ring made by all the degrees of violet, as
+about four to three, or five to four, and that when the Light was of the
+middle Colour between yellow and green, the Diameter of the Ring was
+very nearly an arithmetical Mean between the greatest Diameter of the
+same Ring made by the outmost red, and the least Diameter thereof made
+by the outmost violet: Contrary to what happens in the Colours of the
+oblong Spectrum made by the Refraction of a Prism, where the red is most
+contracted, the violet most expanded, and in the midst of all the
+Colours is the Confine of green and blue. And hence I seem to collect
+that the thicknesses of the Air between the Glasses there, where the
+Ring is successively made by the limits of the five principal Colours
+(red, yellow, green, blue, violet) in order (that is, by the extreme
+red, by the limit of red and yellow in the middle of the orange, by the
+limit of yellow and green, by the limit of green and blue, by the limit
+of blue and violet in the middle of the indigo, and by the extreme
+violet) are to one another very nearly as the sixth lengths of a Chord
+which found the Notes in a sixth Major, _sol_, _la_, _mi_, _fa_, _sol_,
+_la_. But it agrees something better with the Observation to say, that
+the thicknesses of the Air between the Glasses there, where the Rings
+are successively made by the limits of the seven Colours, red, orange,
+yellow, green, blue, indigo, violet in order, are to one another as the
+Cube Roots of the Squares of the eight lengths of a Chord, which found
+the Notes in an eighth, _sol_, _la_, _fa_, _sol_, _la_, _mi_, _fa_,
+_sol_; that is, as the Cube Roots of the Squares of the Numbers, 1, 8/9,
+5/6, 3/4, 2/3, 3/5, 9/16, 1/2.
+
+_Obs._ 15. These Rings were not of various Colours like those made in
+the open Air, but appeared all over of that prismatick Colour only with
+which they were illuminated. And by projecting the prismatick Colours
+immediately upon the Glasses, I found that the Light which fell on the
+dark Spaces which were between the Colour'd Rings was transmitted
+through the Glasses without any variation of Colour. For on a white
+Paper placed behind, it would paint Rings of the same Colour with those
+which were reflected, and of the bigness of their immediate Spaces. And
+from thence the origin of these Rings is manifest; namely, that the Air
+between the Glasses, according to its various thickness, is disposed in
+some places to reflect, and in others to transmit the Light of any one
+Colour (as you may see represented in the fourth Figure) and in the same
+place to reflect that of one Colour where it transmits that of another.
+
+[Illustration: FIG. 4.]
+
+_Obs._ 16. The Squares of the Diameters of these Rings made by any
+prismatick Colour were in arithmetical Progression, as in the fifth
+Observation. And the Diameter of the sixth Circle, when made by the
+citrine yellow, and viewed almost perpendicularly was about 58/100 parts
+of an Inch, or a little less, agreeable to the sixth Observation.
+
+The precedent Observations were made with a rarer thin Medium,
+terminated by a denser, such as was Air or Water compress'd between two
+Glasses. In those that follow are set down the Appearances of a denser
+Medium thin'd within a rarer, such as are Plates of Muscovy Glass,
+Bubbles of Water, and some other thin Substances terminated on all sides
+with air.
+
+_Obs._ 17. If a Bubble be blown with Water first made tenacious by
+dissolving a little Soap in it, 'tis a common Observation, that after a
+while it will appear tinged with a great variety of Colours. To defend
+these Bubbles from being agitated by the external Air (whereby their
+Colours are irregularly moved one among another, so that no accurate
+Observation can be made of them,) as soon as I had blown any of them I
+cover'd it with a clear Glass, and by that means its Colours emerged in
+a very regular order, like so many concentrick Rings encompassing the
+top of the Bubble. And as the Bubble grew thinner by the continual
+subsiding of the Water, these Rings dilated slowly and overspread the
+whole Bubble, descending in order to the bottom of it, where they
+vanish'd successively. In the mean while, after all the Colours were
+emerged at the top, there grew in the center of the Rings a small round
+black Spot, like that in the first Observation, which continually
+dilated it self till it became sometimes more than 1/2 or 3/4 of an Inch
+in breadth before the Bubble broke. At first I thought there had been no
+Light reflected from the Water in that place, but observing it more
+curiously, I saw within it several smaller round Spots, which appeared
+much blacker and darker than the rest, whereby I knew that there was
+some Reflexion at the other places which were not so dark as those
+Spots. And by farther Tryal I found that I could see the Images of some
+things (as of a Candle or the Sun) very faintly reflected, not only from
+the great black Spot, but also from the little darker Spots which were
+within it.
+
+Besides the aforesaid colour'd Rings there would often appear small
+Spots of Colours, ascending and descending up and down the sides of the
+Bubble, by reason of some Inequalities in the subsiding of the Water.
+And sometimes small black Spots generated at the sides would ascend up
+to the larger black Spot at the top of the Bubble, and unite with it.
+
+_Obs._ 18. Because the Colours of these Bubbles were more extended and
+lively than those of the Air thinn'd between two Glasses, and so more
+easy to be distinguish'd, I shall here give you a farther description of
+their order, as they were observ'd in viewing them by Reflexion of the
+Skies when of a white Colour, whilst a black substance was placed
+behind the Bubble. And they were these, red, blue; red, blue; red, blue;
+red, green; red, yellow, green, blue, purple; red, yellow, green, blue,
+violet; red, yellow, white, blue, black.
+
+The three first Successions of red and blue were very dilute and dirty,
+especially the first, where the red seem'd in a manner to be white.
+Among these there was scarce any other Colour sensible besides red and
+blue, only the blues (and principally the second blue) inclined a little
+to green.
+
+The fourth red was also dilute and dirty, but not so much as the former
+three; after that succeeded little or no yellow, but a copious green,
+which at first inclined a little to yellow, and then became a pretty
+brisk and good willow green, and afterwards changed to a bluish Colour;
+but there succeeded neither blue nor violet.
+
+The fifth red at first inclined very much to purple, and afterwards
+became more bright and brisk, but yet not very pure. This was succeeded
+with a very bright and intense yellow, which was but little in quantity,
+and soon chang'd to green: But that green was copious and something more
+pure, deep and lively, than the former green. After that follow'd an
+excellent blue of a bright Sky-colour, and then a purple, which was less
+in quantity than the blue, and much inclined to red.
+
+The sixth red was at first of a very fair and lively scarlet, and soon
+after of a brighter Colour, being very pure and brisk, and the best of
+all the reds. Then after a lively orange follow'd an intense bright and
+copious yellow, which was also the best of all the yellows, and this
+changed first to a greenish yellow, and then to a greenish blue; but the
+green between the yellow and the blue, was very little and dilute,
+seeming rather a greenish white than a green. The blue which succeeded
+became very good, and of a very bright Sky-colour, but yet something
+inferior to the former blue; and the violet was intense and deep with
+little or no redness in it. And less in quantity than the blue.
+
+In the last red appeared a tincture of scarlet next to violet, which
+soon changed to a brighter Colour, inclining to an orange; and the
+yellow which follow'd was at first pretty good and lively, but
+afterwards it grew more dilute until by degrees it ended in perfect
+whiteness. And this whiteness, if the Water was very tenacious and
+well-temper'd, would slowly spread and dilate it self over the greater
+part of the Bubble; continually growing paler at the top, where at
+length it would crack in many places, and those cracks, as they dilated,
+would appear of a pretty good, but yet obscure and dark Sky-colour; the
+white between the blue Spots diminishing, until it resembled the Threds
+of an irregular Net-work, and soon after vanish'd, and left all the
+upper part of the Bubble of the said dark blue Colour. And this Colour,
+after the aforesaid manner, dilated it self downwards, until sometimes
+it hath overspread the whole Bubble. In the mean while at the top, which
+was of a darker blue than the bottom, and appear'd also full of many
+round blue Spots, something darker than the rest, there would emerge
+one or more very black Spots, and within those, other Spots of an
+intenser blackness, which I mention'd in the former Observation; and
+these continually dilated themselves until the Bubble broke.
+
+If the Water was not very tenacious, the black Spots would break forth
+in the white, without any sensible intervention of the blue. And
+sometimes they would break forth within the precedent yellow, or red, or
+perhaps within the blue of the second order, before the intermediate
+Colours had time to display themselves.
+
+By this description you may perceive how great an affinity these Colours
+have with those of Air described in the fourth Observation, although set
+down in a contrary order, by reason that they begin to appear when the
+Bubble is thickest, and are most conveniently reckon'd from the lowest
+and thickest part of the Bubble upwards.
+
+_Obs._ 19. Viewing in several oblique Positions of my Eye the Rings of
+Colours emerging on the top of the Bubble, I found that they were
+sensibly dilated by increasing the obliquity, but yet not so much by far
+as those made by thinn'd Air in the seventh Observation. For there they
+were dilated so much as, when view'd most obliquely, to arrive at a part
+of the Plate more than twelve times thicker than that where they
+appear'd when viewed perpendicularly; whereas in this case the thickness
+of the Water, at which they arrived when viewed most obliquely, was to
+that thickness which exhibited them by perpendicular Rays, something
+less than as 8 to 5. By the best of my Observations it was between 15
+and 15-1/2 to 10; an increase about 24 times less than in the other
+case.
+
+Sometimes the Bubble would become of an uniform thickness all over,
+except at the top of it near the black Spot, as I knew, because it would
+exhibit the same appearance of Colours in all Positions of the Eye. And
+then the Colours which were seen at its apparent circumference by the
+obliquest Rays, would be different from those that were seen in other
+places, by Rays less oblique to it. And divers Spectators might see the
+same part of it of differing Colours, by viewing it at very differing
+Obliquities. Now observing how much the Colours at the same places of
+the Bubble, or at divers places of equal thickness, were varied by the
+several Obliquities of the Rays; by the assistance of the 4th, 14th,
+16th and 18th Observations, as they are hereafter explain'd, I collect
+the thickness of the Water requisite to exhibit any one and the same
+Colour, at several Obliquities, to be very nearly in the Proportion
+expressed in this Table.
+
+-----------------+------------------+----------------
+ Incidence on | Refraction into | Thickness of
+ the Water. | the Water. | the Water.
+-----------------+------------------+----------------
+ Deg. Min. | Deg. Min. |
+ | |
+ 00 00 | 00 00 | 10
+ | |
+ 15 00 | 11 11 | 10-1/4
+ | |
+ 30 00 | 22 1 | 10-4/5
+ | |
+ 45 00 | 32 2 | 11-4/5
+ | |
+ 60 00 | 40 30 | 13
+ | |
+ 75 00 | 46 25 | 14-1/2
+ | |
+ 90 00 | 48 35 | 15-1/5
+-----------------+------------------+----------------
+
+In the two first Columns are express'd the Obliquities of the Rays to
+the Superficies of the Water, that is, their Angles of Incidence and
+Refraction. Where I suppose, that the Sines which measure them are in
+round Numbers, as 3 to 4, though probably the Dissolution of Soap in the
+Water, may a little alter its refractive Virtue. In the third Column,
+the Thickness of the Bubble, at which any one Colour is exhibited in
+those several Obliquities, is express'd in Parts, of which ten
+constitute its Thickness when the Rays are perpendicular. And the Rule
+found by the seventh Observation agrees well with these Measures, if
+duly apply'd; namely, that the Thickness of a Plate of Water requisite
+to exhibit one and the same Colour at several Obliquities of the Eye, is
+proportional to the Secant of an Angle, whose Sine is the first of an
+hundred and six arithmetical mean Proportionals between the Sines of
+Incidence and Refraction counted from the lesser Sine, that is, from the
+Sine of Refraction when the Refraction is made out of Air into Water,
+otherwise from the Sine of Incidence.
+
+I have sometimes observ'd, that the Colours which arise on polish'd
+Steel by heating it, or on Bell-metal, and some other metalline
+Substances, when melted and pour'd on the Ground, where they may cool in
+the open Air, have, like the Colours of Water-bubbles, been a little
+changed by viewing them at divers Obliquities, and particularly that a
+deep blue, or violet, when view'd very obliquely, hath been changed to a
+deep red. But the Changes of these Colours are not so great and
+sensible as of those made by Water. For the Scoria, or vitrified Part of
+the Metal, which most Metals when heated or melted do continually
+protrude, and send out to their Surface, and which by covering the
+Metals in form of a thin glassy Skin, causes these Colours, is much
+denser than Water; and I find that the Change made by the Obliquation of
+the Eye is least in Colours of the densest thin Substances.
+
+_Obs._ 20. As in the ninth Observation, so here, the Bubble, by
+transmitted Light, appear'd of a contrary Colour to that, which it
+exhibited by Reflexion. Thus when the Bubble being look'd on by the
+Light of the Clouds reflected from it, seemed red at its apparent
+Circumference, if the Clouds at the same time, or immediately after,
+were view'd through it, the Colour at its Circumference would be blue.
+And, on the contrary, when by reflected Light it appeared blue, it would
+appear red by transmitted Light.
+
+_Obs._ 21. By wetting very thin Plates of _Muscovy_ Glass, whose
+thinness made the like Colours appear, the Colours became more faint and
+languid, especially by wetting the Plates on that side opposite to the
+Eye: But I could not perceive any variation of their Species. So then
+the thickness of a Plate requisite to produce any Colour, depends only
+on the density of the Plate, and not on that of the ambient Medium. And
+hence, by the 10th and 16th Observations, may be known the thickness
+which Bubbles of Water, or Plates of _Muscovy_ Glass, or other
+Substances, have at any Colour produced by them.
+
+_Obs._ 22. A thin transparent Body, which is denser than its ambient
+Medium, exhibits more brisk and vivid Colours than that which is so much
+rarer; as I have particularly observed in the Air and Glass. For blowing
+Glass very thin at a Lamp Furnace, those Plates encompassed with Air did
+exhibit Colours much more vivid than those of Air made thin between two
+Glasses.
+
+_Obs._ 23. Comparing the quantity of Light reflected from the several
+Rings, I found that it was most copious from the first or inmost, and in
+the exterior Rings became gradually less and less. Also the whiteness of
+the first Ring was stronger than that reflected from those parts of the
+thin Medium or Plate which were without the Rings; as I could manifestly
+perceive by viewing at a distance the Rings made by the two
+Object-glasses; or by comparing two Bubbles of Water blown at distant
+Times, in the first of which the Whiteness appear'd, which succeeded all
+the Colours, and in the other, the Whiteness which preceded them all.
+
+_Obs._ 24. When the two Object-glasses were lay'd upon one another, so
+as to make the Rings of the Colours appear, though with my naked Eye I
+could not discern above eight or nine of those Rings, yet by viewing
+them through a Prism I have seen a far greater Multitude, insomuch that
+I could number more than forty, besides many others, that were so very
+small and close together, that I could not keep my Eye steady on them
+severally so as to number them, but by their Extent I have sometimes
+estimated them to be more than an hundred. And I believe the Experiment
+may be improved to the Discovery of far greater Numbers. For they seem
+to be really unlimited, though visible only so far as they can be
+separated by the Refraction of the Prism, as I shall hereafter explain.
+
+[Illustration: FIG. 5.]
+
+But it was but one side of these Rings, namely, that towards which the
+Refraction was made, which by that Refraction was render'd distinct, and
+the other side became more confused than when view'd by the naked Eye,
+insomuch that there I could not discern above one or two, and sometimes
+none of those Rings, of which I could discern eight or nine with my
+naked Eye. And their Segments or Arcs, which on the other side appear'd
+so numerous, for the most part exceeded not the third Part of a Circle.
+If the Refraction was very great, or the Prism very distant from the
+Object-glasses, the middle Part of those Arcs became also confused, so
+as to disappear and constitute an even Whiteness, whilst on either side
+their Ends, as also the whole Arcs farthest from the Center, became
+distincter than before, appearing in the Form as you see them design'd
+in the fifth Figure.
+
+The Arcs, where they seem'd distinctest, were only white and black
+successively, without any other Colours intermix'd. But in other Places
+there appeared Colours, whose Order was inverted by the refraction in
+such manner, that if I first held the Prism very near the
+Object-glasses, and then gradually removed it farther off towards my
+Eye, the Colours of the 2d, 3d, 4th, and following Rings, shrunk towards
+the white that emerged between them, until they wholly vanish'd into it
+at the middle of the Arcs, and afterwards emerged again in a contrary
+Order. But at the Ends of the Arcs they retain'd their Order unchanged.
+
+I have sometimes so lay'd one Object-glass upon the other, that to the
+naked Eye they have all over seem'd uniformly white, without the least
+Appearance of any of the colour'd Rings; and yet by viewing them through
+a Prism, great Multitudes of those Rings have discover'd themselves. And
+in like manner Plates of _Muscovy_ Glass, and Bubbles of Glass blown at
+a Lamp-Furnace, which were not so thin as to exhibit any Colours to the
+naked Eye, have through the Prism exhibited a great Variety of them
+ranged irregularly up and down in the Form of Waves. And so Bubbles of
+Water, before they began to exhibit their Colours to the naked Eye of a
+Bystander, have appeared through a Prism, girded about with many
+parallel and horizontal Rings; to produce which Effect, it was necessary
+to hold the Prism parallel, or very nearly parallel to the Horizon, and
+to dispose it so that the Rays might be refracted upwards.
+
+
+
+
+THE
+
+SECOND BOOK
+
+OF
+
+OPTICKS
+
+
+_PART II._
+
+_Remarks upon the foregoing Observations._
+
+
+Having given my Observations of these Colours, before I make use of them
+to unfold the Causes of the Colours of natural Bodies, it is convenient
+that by the simplest of them, such as are the 2d, 3d, 4th, 9th, 12th,
+18th, 20th, and 24th, I first explain the more compounded. And first to
+shew how the Colours in the fourth and eighteenth Observations are
+produced, let there be taken in any Right Line from the Point Y, [in
+_Fig._ 6.] the Lengths YA, YB, YC, YD, YE, YF, YG, YH, in proportion to
+one another, as the Cube-Roots of the Squares of the Numbers, 1/2, 9/16,
+3/5, 2/3, 3/4, 5/6, 8/9, 1, whereby the Lengths of a Musical Chord to
+sound all the Notes in an eighth are represented; that is, in the
+Proportion of the Numbers 6300, 6814, 7114, 7631, 8255, 8855, 9243,
+10000. And at the Points A, B, C, D, E, F, G, H, let Perpendiculars
+A[Greek: a], B[Greek: b], &c. be erected, by whose Intervals the Extent
+of the several Colours set underneath against them, is to be
+represented. Then divide the Line _A[Greek: a]_ in such Proportion as
+the Numbers 1, 2, 3, 5, 6, 7, 9, 10, 11, &c. set at the Points of
+Division denote. And through those Divisions from Y draw Lines 1I, 2K,
+3L, 5M, 6N, 7O, &c.
+
+Now, if A2 be supposed to represent the Thickness of any thin
+transparent Body, at which the outmost Violet is most copiously
+reflected in the first Ring, or Series of Colours, then by the 13th
+Observation, HK will represent its Thickness, at which the utmost Red is
+most copiously reflected in the same Series. Also by the 5th and 16th
+Observations, A6 and HN will denote the Thicknesses at which those
+extreme Colours are most copiously reflected in the second Series, and
+A10 and HQ the Thicknesses at which they are most copiously reflected in
+the third Series, and so on. And the Thickness at which any of the
+intermediate Colours are reflected most copiously, will, according to
+the 14th Observation, be defined by the distance of the Line AH from the
+intermediate parts of the Lines 2K, 6N, 10Q, &c. against which the Names
+of those Colours are written below.
+
+[Illustration: FIG. 6.]
+
+But farther, to define the Latitude of these Colours in each Ring or
+Series, let A1 design the least thickness, and A3 the greatest
+thickness, at which the extreme violet in the first Series is reflected,
+and let HI, and HL, design the like limits for the extreme red, and let
+the intermediate Colours be limited by the intermediate parts of the
+Lines 1I, and 3L, against which the Names of those Colours are written,
+and so on: But yet with this caution, that the Reflexions be supposed
+strongest at the intermediate Spaces, 2K, 6N, 10Q, &c. and from thence
+to decrease gradually towards these limits, 1I, 3L, 5M, 7O, &c. on
+either side; where you must not conceive them to be precisely limited,
+but to decay indefinitely. And whereas I have assign'd the same Latitude
+to every Series, I did it, because although the Colours in the first
+Series seem to be a little broader than the rest, by reason of a
+stronger Reflexion there, yet that inequality is so insensible as
+scarcely to be determin'd by Observation.
+
+Now according to this Description, conceiving that the Rays originally
+of several Colours are by turns reflected at the Spaces 1I, L3, 5M, O7,
+9PR11, &c. and transmitted at the Spaces AHI1, 3LM5, 7OP9, &c. it is
+easy to know what Colour must in the open Air be exhibited at any
+thickness of a transparent thin Body. For if a Ruler be applied parallel
+to AH, at that distance from it by which the thickness of the Body is
+represented, the alternate Spaces 1IL3, 5MO7, &c. which it crosseth will
+denote the reflected original Colours, of which the Colour exhibited in
+the open Air is compounded. Thus if the constitution of the green in the
+third Series of Colours be desired, apply the Ruler as you see at
+[Greek: prsph], and by its passing through some of the blue at [Greek:
+p] and yellow at [Greek: s], as well as through the green at [Greek: r],
+you may conclude that the green exhibited at that thickness of the Body
+is principally constituted of original green, but not without a mixture
+of some blue and yellow.
+
+By this means you may know how the Colours from the center of the Rings
+outward ought to succeed in order as they were described in the 4th and
+18th Observations. For if you move the Ruler gradually from AH through
+all distances, having pass'd over the first Space which denotes little
+or no Reflexion to be made by thinnest Substances, it will first arrive
+at 1 the violet, and then very quickly at the blue and green, which
+together with that violet compound blue, and then at the yellow and red,
+by whose farther addition that blue is converted into whiteness, which
+whiteness continues during the transit of the edge of the Ruler from I
+to 3, and after that by the successive deficience of its component
+Colours, turns first to compound yellow, and then to red, and last of
+all the red ceaseth at L. Then begin the Colours of the second Series,
+which succeed in order during the transit of the edge of the Ruler from
+5 to O, and are more lively than before, because more expanded and
+severed. And for the same reason instead of the former white there
+intercedes between the blue and yellow a mixture of orange, yellow,
+green, blue and indigo, all which together ought to exhibit a dilute and
+imperfect green. So the Colours of the third Series all succeed in
+order; first, the violet, which a little interferes with the red of the
+second order, and is thereby inclined to a reddish purple; then the blue
+and green, which are less mix'd with other Colours, and consequently
+more lively than before, especially the green: Then follows the yellow,
+some of which towards the green is distinct and good, but that part of
+it towards the succeeding red, as also that red is mix'd with the violet
+and blue of the fourth Series, whereby various degrees of red very much
+inclining to purple are compounded. This violet and blue, which should
+succeed this red, being mixed with, and hidden in it, there succeeds a
+green. And this at first is much inclined to blue, but soon becomes a
+good green, the only unmix'd and lively Colour in this fourth Series.
+For as it verges towards the yellow, it begins to interfere with the
+Colours of the fifth Series, by whose mixture the succeeding yellow and
+red are very much diluted and made dirty, especially the yellow, which
+being the weaker Colour is scarce able to shew it self. After this the
+several Series interfere more and more, and their Colours become more
+and more intermix'd, till after three or four more revolutions (in which
+the red and blue predominate by turns) all sorts of Colours are in all
+places pretty equally blended, and compound an even whiteness.
+
+And since by the 15th Observation the Rays endued with one Colour are
+transmitted, where those of another Colour are reflected, the reason of
+the Colours made by the transmitted Light in the 9th and 20th
+Observations is from hence evident.
+
+If not only the Order and Species of these Colours, but also the precise
+thickness of the Plate, or thin Body at which they are exhibited, be
+desired in parts of an Inch, that may be also obtained by assistance of
+the 6th or 16th Observations. For according to those Observations the
+thickness of the thinned Air, which between two Glasses exhibited the
+most luminous parts of the first six Rings were 1/178000, 3/178000,
+5/178000, 7/178000, 9/178000, 11/178000 parts of an Inch. Suppose the
+Light reflected most copiously at these thicknesses be the bright
+citrine yellow, or confine of yellow and orange, and these thicknesses
+will be F[Greek: l], F[Greek: m], F[Greek: u], F[Greek: x], F[Greek: o],
+F[Greek: t]. And this being known, it is easy to determine what
+thickness of Air is represented by G[Greek: ph], or by any other
+distance of the Ruler from AH.
+
+But farther, since by the 10th Observation the thickness of Air was to
+the thickness of Water, which between the same Glasses exhibited the
+same Colour, as 4 to 3, and by the 21st Observation the Colours of thin
+Bodies are not varied by varying the ambient Medium; the thickness of a
+Bubble of Water, exhibiting any Colour, will be 3/4 of the thickness of
+Air producing the same Colour. And so according to the same 10th and
+21st Observations, the thickness of a Plate of Glass, whose Refraction
+of the mean refrangible Ray, is measured by the proportion of the Sines
+31 to 20, may be 20/31 of the thickness of Air producing the same
+Colours; and the like of other Mediums. I do not affirm, that this
+proportion of 20 to 31, holds in all the Rays; for the Sines of other
+sorts of Rays have other Proportions. But the differences of those
+Proportions are so little that I do not here consider them. On these
+Grounds I have composed the following Table, wherein the thickness of
+Air, Water, and Glass, at which each Colour is most intense and
+specifick, is expressed in parts of an Inch divided into ten hundred
+thousand equal parts.
+
+Now if this Table be compared with the 6th Scheme, you will there see
+the constitution of each Colour, as to its Ingredients, or the original
+Colours of which it is compounded, and thence be enabled to judge of its
+Intenseness or Imperfection; which may suffice in explication of the 4th
+and 18th Observations, unless it be farther desired to delineate the
+manner how the Colours appear, when the two Object-glasses are laid upon
+one another. To do which, let there be described a large Arc of a
+Circle, and a streight Line which may touch that Arc, and parallel to
+that Tangent several occult Lines, at such distances from it, as the
+Numbers set against the several Colours in the Table denote. For the
+Arc, and its Tangent, will represent the Superficies of the Glasses
+terminating the interjacent Air; and the places where the occult Lines
+cut the Arc will show at what distances from the center, or Point of
+contact, each Colour is reflected.
+
+_The thickness of colour'd Plates and Particles of_
+ _____________|_______________
+ / \
+ Air. Water. Glass.
+ |---------+----------+----------+
+ {Very black | 1/2 | 3/8 | 10/31 |
+ {Black | 1 | 3/4 | 20/31 |
+ {Beginning of | | | |
+ { Black | 2 | 1-1/2 | 1-2/7 |
+Their Colours of the {Blue | 2-2/5 | 1-4/5 | 1-11/22 |
+first Order, {White | 5-1/4 | 3-7/8 | 3-2/5 |
+ {Yellow | 7-1/9 | 5-1/3 | 4-3/5 |
+ {Orange | 8 | 6 | 5-1/6 |
+ {Red | 9 | 6-3/4 | 5-4/5 |
+ |---------+----------+----------|
+ {Violet | 11-1/6 | 8-3/8 | 7-1/5 |
+ {Indigo | 12-5/6 | 9-5/8 | 8-2/11 |
+ {Blue | 14 | 10-1/2 | 9 |
+ {Green | 15-1/8 | 11-2/3 | 9-5/7 |
+Of the second order, {Yellow | 16-2/7 | 12-1/5 | 10-2/5 |
+ {Orange | 17-2/9 | 13 | 11-1/9 |
+ {Bright red | 18-1/3 | 13-3/4 | 11-5/6 |
+ {Scarlet | 19-2/3 | 14-3/4 | 12-2/3 |
+ |---------+----------+----------|
+ {Purple | 21 | 15-3/4 | 13-11/20 |
+ {Indigo | 22-1/10 | 16-4/7 | 14-1/4 |
+ {Blue | 23-2/5 | 17-11/20 | 15-1/10 |
+Of the third Order, {Green | 25-1/5 | 18-9/10 | 16-1/4 |
+ {Yellow | 27-1/7 | 20-1/3 | 17-1/2 |
+ {Red | 29 | 21-3/4 | 18-5/7 |
+ {Bluish red | 32 | 24 | 20-2/3 |
+ |---------+----------+----------|
+ {Bluish green | 34 | 25-1/2 | 22 |
+ {Green | 35-2/7 | 26-1/2 | 22-3/4 |
+Of the fourth Order, {Yellowish green | 36 | 27 | 23-2/9 |
+ {Red | 40-1/3 | 30-1/4 | 26 |
+ |---------+----------+----------|
+ {Greenish blue | 46 | 34-1/2 | 29-2/3 |
+Of the fifth Order, {Red | 52-1/2 | 39-3/8 | 34 |
+ |---------+----------+----------|
+ {Greenish blue | 58-3/4 | 44 | 38 |
+Of the sixth Order, {Red | 65 | 48-3/4 | 42 |
+ |---------+----------+----------|
+Of the seventh Order, {Greenish blue | 71 | 53-1/4 | 45-4/5 |
+ {Ruddy White | 77 | 57-3/4 | 49-2/3 |
+ |---------+----------+----------|
+
+There are also other Uses of this Table: For by its assistance the
+thickness of the Bubble in the 19th Observation was determin'd by the
+Colours which it exhibited. And so the bigness of the parts of natural
+Bodies may be conjectured by their Colours, as shall be hereafter shewn.
+Also, if two or more very thin Plates be laid one upon another, so as to
+compose one Plate equalling them all in thickness, the resulting Colour
+may be hereby determin'd. For instance, Mr. _Hook_ observed, as is
+mentioned in his _Micrographia_, that a faint yellow Plate of _Muscovy_
+Glass laid upon a blue one, constituted a very deep purple. The yellow
+of the first Order is a faint one, and the thickness of the Plate
+exhibiting it, according to the Table is 4-3/5, to which add 9, the
+thickness exhibiting blue of the second Order, and the Sum will be
+13-3/5, which is the thickness exhibiting the purple of the third Order.
+
+To explain, in the next place, the circumstances of the 2d and 3d
+Observations; that is, how the Rings of the Colours may (by turning the
+Prisms about their common Axis the contrary way to that expressed in
+those Observations) be converted into white and black Rings, and
+afterwards into Rings of Colours again, the Colours of each Ring lying
+now in an inverted order; it must be remember'd, that those Rings of
+Colours are dilated by the obliquation of the Rays to the Air which
+intercedes the Glasses, and that according to the Table in the 7th
+Observation, their Dilatation or Increase of their Diameter is most
+manifest and speedy when they are obliquest. Now the Rays of yellow
+being more refracted by the first Superficies of the said Air than those
+of red, are thereby made more oblique to the second Superficies, at
+which they are reflected to produce the colour'd Rings, and consequently
+the yellow Circle in each Ring will be more dilated than the red; and
+the Excess of its Dilatation will be so much the greater, by how much
+the greater is the obliquity of the Rays, until at last it become of
+equal extent with the red of the same Ring. And for the same reason the
+green, blue and violet, will be also so much dilated by the still
+greater obliquity of their Rays, as to become all very nearly of equal
+extent with the red, that is, equally distant from the center of the
+Rings. And then all the Colours of the same Ring must be co-incident,
+and by their mixture exhibit a white Ring. And these white Rings must
+have black and dark Rings between them, because they do not spread and
+interfere with one another, as before. And for that reason also they
+must become distincter, and visible to far greater numbers. But yet the
+violet being obliquest will be something more dilated, in proportion to
+its extent, than the other Colours, and so very apt to appear at the
+exterior Verges of the white.
+
+Afterwards, by a greater obliquity of the Rays, the violet and blue
+become more sensibly dilated than the red and yellow, and so being
+farther removed from the center of the Rings, the Colours must emerge
+out of the white in an order contrary to that which they had before; the
+violet and blue at the exterior Limbs of each Ring, and the red and
+yellow at the interior. And the violet, by reason of the greatest
+obliquity of its Rays, being in proportion most of all expanded, will
+soonest appear at the exterior Limb of each white Ring, and become more
+conspicuous than the rest. And the several Series of Colours belonging
+to the several Rings, will, by their unfolding and spreading, begin
+again to interfere, and thereby render the Rings less distinct, and not
+visible to so great numbers.
+
+If instead of the Prisms the Object-glasses be made use of, the Rings
+which they exhibit become not white and distinct by the obliquity of the
+Eye, by reason that the Rays in their passage through that Air which
+intercedes the Glasses are very nearly parallel to those Lines in which
+they were first incident on the Glasses, and consequently the Rays
+endued with several Colours are not inclined one more than another to
+that Air, as it happens in the Prisms.
+
+There is yet another circumstance of these Experiments to be consider'd,
+and that is why the black and white Rings which when view'd at a
+distance appear distinct, should not only become confused by viewing
+them near at hand, but also yield a violet Colour at both the edges of
+every white Ring. And the reason is, that the Rays which enter the Eye
+at several parts of the Pupil, have several Obliquities to the Glasses,
+and those which are most oblique, if consider'd apart, would represent
+the Rings bigger than those which are the least oblique. Whence the
+breadth of the Perimeter of every white Ring is expanded outwards by the
+obliquest Rays, and inwards by the least oblique. And this Expansion is
+so much the greater by how much the greater is the difference of the
+Obliquity; that is, by how much the Pupil is wider, or the Eye nearer to
+the Glasses. And the breadth of the violet must be most expanded,
+because the Rays apt to excite a Sensation of that Colour are most
+oblique to a second or farther Superficies of the thinn'd Air at which
+they are reflected, and have also the greatest variation of Obliquity,
+which makes that Colour soonest emerge out of the edges of the white.
+And as the breadth of every Ring is thus augmented, the dark Intervals
+must be diminish'd, until the neighbouring Rings become continuous, and
+are blended, the exterior first, and then those nearer the center; so
+that they can no longer be distinguish'd apart, but seem to constitute
+an even and uniform whiteness.
+
+Among all the Observations there is none accompanied with so odd
+circumstances as the twenty-fourth. Of those the principal are, that in
+thin Plates, which to the naked Eye seem of an even and uniform
+transparent whiteness, without any terminations of Shadows, the
+Refraction of a Prism should make Rings of Colours appear, whereas it
+usually makes Objects appear colour'd only there where they are
+terminated with Shadows, or have parts unequally luminous; and that it
+should make those Rings exceedingly distinct and white, although it
+usually renders Objects confused and coloured. The Cause of these things
+you will understand by considering, that all the Rings of Colours are
+really in the Plate, when view'd with the naked Eye, although by reason
+of the great breadth of their Circumferences they so much interfere and
+are blended together, that they seem to constitute an uniform whiteness.
+But when the Rays pass through the Prism to the Eye, the Orbits of the
+several Colours in every Ring are refracted, some more than others,
+according to their degrees of Refrangibility: By which means the Colours
+on one side of the Ring (that is in the circumference on one side of its
+center), become more unfolded and dilated, and those on the other side
+more complicated and contracted. And where by a due Refraction they are
+so much contracted, that the several Rings become narrower than to
+interfere with one another, they must appear distinct, and also white,
+if the constituent Colours be so much contracted as to be wholly
+co-incident. But on the other side, where the Orbit of every Ring is
+made broader by the farther unfolding of its Colours, it must interfere
+more with other Rings than before, and so become less distinct.
+
+[Illustration: FIG. 7.]
+
+To explain this a little farther, suppose the concentrick Circles AV,
+and BX, [in _Fig._ 7.] represent the red and violet of any Order, which,
+together with the intermediate Colours, constitute any one of these
+Rings. Now these being view'd through a Prism, the violet Circle BX,
+will, by a greater Refraction, be farther translated from its place than
+the red AV, and so approach nearer to it on that side of the Circles,
+towards which the Refractions are made. For instance, if the red be
+translated to _av_, the violet may be translated to _bx_, so as to
+approach nearer to it at _x_ than before; and if the red be farther
+translated to av, the violet may be so much farther translated to bx as
+to convene with it at x; and if the red be yet farther translated to
+[Greek: aY], the violet may be still so much farther translated to
+[Greek: bx] as to pass beyond it at [Greek: x], and convene with it at
+_e_ and _f_. And this being understood not only of the red and violet,
+but of all the other intermediate Colours, and also of every revolution
+of those Colours, you will easily perceive how those of the same
+revolution or order, by their nearness at _xv_ and [Greek: Yx], and
+their coincidence at xv, _e_ and _f_, ought to constitute pretty
+distinct Arcs of Circles, especially at xv, or at _e_ and _f_; and that
+they will appear severally at _x_[Greek: u] and at xv exhibit whiteness
+by their coincidence, and again appear severally at [Greek: Yx], but yet
+in a contrary order to that which they had before, and still retain
+beyond _e_ and _f_. But on the other side, at _ab_, ab, or [Greek: ab],
+these Colours must become much more confused by being dilated and spread
+so as to interfere with those of other Orders. And the same confusion
+will happen at [Greek: Ux] between _e_ and _f_, if the Refraction be
+very great, or the Prism very distant from the Object-glasses: In which
+case no parts of the Rings will be seen, save only two little Arcs at
+_e_ and _f_, whose distance from one another will be augmented by
+removing the Prism still farther from the Object-glasses: And these
+little Arcs must be distinctest and whitest at their middle, and at
+their ends, where they begin to grow confused, they must be colour'd.
+And the Colours at one end of every Arc must be in a contrary order to
+those at the other end, by reason that they cross in the intermediate
+white; namely, their ends, which verge towards [Greek: Ux], will be red
+and yellow on that side next the center, and blue and violet on the
+other side. But their other ends which verge from [Greek: Ux], will on
+the contrary be blue and violet on that side towards the center, and on
+the other side red and yellow.
+
+Now as all these things follow from the properties of Light by a
+mathematical way of reasoning, so the truth of them may be manifested by
+Experiments. For in a dark Room, by viewing these Rings through a Prism,
+by reflexion of the several prismatick Colours, which an assistant
+causes to move to and fro upon a Wall or Paper from whence they are
+reflected, whilst the Spectator's Eye, the Prism, and the
+Object-glasses, (as in the 13th Observation,) are placed steady; the
+Position of the Circles made successively by the several Colours, will
+be found such, in respect of one another, as I have described in the
+Figures _abxv_, or abxv, or _[Greek: abxU]_. And by the same method the
+truth of the Explications of other Observations may be examined.
+
+By what hath been said, the like Phænomena of Water and thin Plates of
+Glass may be understood. But in small fragments of those Plates there is
+this farther observable, that where they lie flat upon a Table, and are
+turned about their centers whilst they are view'd through a Prism, they
+will in some postures exhibit Waves of various Colours; and some of them
+exhibit these Waves in one or two Positions only, but the most of them
+do in all Positions exhibit them, and make them for the most part appear
+almost all over the Plates. The reason is, that the Superficies of such
+Plates are not even, but have many Cavities and Swellings, which, how
+shallow soever, do a little vary the thickness of the Plate. For at the
+several sides of those Cavities, for the Reasons newly described, there
+ought to be produced Waves in several postures of the Prism. Now though
+it be but some very small and narrower parts of the Glass, by which
+these Waves for the most part are caused, yet they may seem to extend
+themselves over the whole Glass, because from the narrowest of those
+parts there are Colours of several Orders, that is, of several Rings,
+confusedly reflected, which by Refraction of the Prism are unfolded,
+separated, and, according to their degrees of Refraction, dispersed to
+several places, so as to constitute so many several Waves, as there were
+divers orders of Colours promiscuously reflected from that part of the
+Glass.
+
+These are the principal Phænomena of thin Plates or Bubbles, whose
+Explications depend on the properties of Light, which I have heretofore
+deliver'd. And these you see do necessarily follow from them, and agree
+with them, even to their very least circumstances; and not only so, but
+do very much tend to their proof. Thus, by the 24th Observation it
+appears, that the Rays of several Colours, made as well by thin Plates
+or Bubbles, as by Refractions of a Prism, have several degrees of
+Refrangibility; whereby those of each order, which at the reflexion from
+the Plate or Bubble are intermix'd with those of other orders, are
+separated from them by Refraction, and associated together so as to
+become visible by themselves like Arcs of Circles. For if the Rays were
+all alike refrangible, 'tis impossible that the whiteness, which to the
+naked Sense appears uniform, should by Refraction have its parts
+transposed and ranged into those black and white Arcs.
+
+It appears also that the unequal Refractions of difform Rays proceed not
+from any contingent irregularities; such as are Veins, an uneven Polish,
+or fortuitous Position of the Pores of Glass; unequal and casual Motions
+in the Air or Æther, the spreading, breaking, or dividing the same Ray
+into many diverging parts; or the like. For, admitting any such
+irregularities, it would be impossible for Refractions to render those
+Rings so very distinct, and well defined, as they do in the 24th
+Observation. It is necessary therefore that every Ray have its proper
+and constant degree of Refrangibility connate with it, according to
+which its refraction is ever justly and regularly perform'd; and that
+several Rays have several of those degrees.
+
+And what is said of their Refrangibility may be also understood of their
+Reflexibility, that is, of their Dispositions to be reflected, some at a
+greater, and others at a less thickness of thin Plates or Bubbles;
+namely, that those Dispositions are also connate with the Rays, and
+immutable; as may appear by the 13th, 14th, and 15th Observations,
+compared with the fourth and eighteenth.
+
+By the Precedent Observations it appears also, that whiteness is a
+dissimilar mixture of all Colours, and that Light is a mixture of Rays
+endued with all those Colours. For, considering the multitude of the
+Rings of Colours in the 3d, 12th, and 24th Observations, it is manifest,
+that although in the 4th and 18th Observations there appear no more than
+eight or nine of those Rings, yet there are really a far greater number,
+which so much interfere and mingle with one another, as after those
+eight or nine revolutions to dilute one another wholly, and constitute
+an even and sensibly uniform whiteness. And consequently that whiteness
+must be allow'd a mixture of all Colours, and the Light which conveys it
+to the Eye must be a mixture of Rays endued with all those Colours.
+
+But farther; by the 24th Observation it appears, that there is a
+constant relation between Colours and Refrangibility; the most
+refrangible Rays being violet, the least refrangible red, and those of
+intermediate Colours having proportionably intermediate degrees of
+Refrangibility. And by the 13th, 14th, and 15th Observations, compared
+with the 4th or 18th there appears to be the same constant relation
+between Colour and Reflexibility; the violet being in like circumstances
+reflected at least thicknesses of any thin Plate or Bubble, the red at
+greatest thicknesses, and the intermediate Colours at intermediate
+thicknesses. Whence it follows, that the colorifick Dispositions of
+Rays are also connate with them, and immutable; and by consequence, that
+all the Productions and Appearances of Colours in the World are derived,
+not from any physical Change caused in Light by Refraction or Reflexion,
+but only from the various Mixtures or Separations of Rays, by virtue of
+their different Refrangibility or Reflexibility. And in this respect the
+Science of Colours becomes a Speculation as truly mathematical as any
+other part of Opticks. I mean, so far as they depend on the Nature of
+Light, and are not produced or alter'd by the Power of Imagination, or
+by striking or pressing the Eye.
+
+
+
+
+THE
+
+SECOND BOOK
+
+OF
+
+OPTICKS
+
+
+_PART III._
+
+_Of the permanent Colours of natural Bodies, and the Analogy between
+them and the Colours of thin transparent Plates._
+
+I am now come to another part of this Design, which is to consider how
+the Phænomena of thin transparent Plates stand related to those of all
+other natural Bodies. Of these Bodies I have already told you that they
+appear of divers Colours, accordingly as they are disposed to reflect
+most copiously the Rays originally endued with those Colours. But their
+Constitutions, whereby they reflect some Rays more copiously than
+others, remain to be discover'd; and these I shall endeavour to manifest
+in the following Propositions.
+
+
+PROP. I.
+
+_Those Superficies of transparent Bodies reflect the greatest quantity
+of Light, which have the greatest refracting Power; that is, which
+intercede Mediums that differ most in their refractive Densities. And in
+the Confines of equally refracting Mediums there is no Reflexion._
+
+The Analogy between Reflexion and Refraction will appear by considering,
+that when Light passeth obliquely out of one Medium into another which
+refracts from the perpendicular, the greater is the difference of their
+refractive Density, the less Obliquity of Incidence is requisite to
+cause a total Reflexion. For as the Sines are which measure the
+Refraction, so is the Sine of Incidence at which the total Reflexion
+begins, to the Radius of the Circle; and consequently that Angle of
+Incidence is least where there is the greatest difference of the Sines.
+Thus in the passing of Light out of Water into Air, where the Refraction
+is measured by the Ratio of the Sines 3 to 4, the total Reflexion begins
+when the Angle of Incidence is about 48 Degrees 35 Minutes. In passing
+out of Glass into Air, where the Refraction is measured by the Ratio of
+the Sines 20 to 31, the total Reflexion begins when the Angle of
+Incidence is 40 Degrees 10 Minutes; and so in passing out of Crystal, or
+more strongly refracting Mediums into Air, there is still a less
+obliquity requisite to cause a total reflexion. Superficies therefore
+which refract most do soonest reflect all the Light which is incident on
+them, and so must be allowed most strongly reflexive.
+
+But the truth of this Proposition will farther appear by observing, that
+in the Superficies interceding two transparent Mediums, (such as are
+Air, Water, Oil, common Glass, Crystal, metalline Glasses, Island
+Glasses, white transparent Arsenick, Diamonds, &c.) the Reflexion is
+stronger or weaker accordingly, as the Superficies hath a greater or
+less refracting Power. For in the Confine of Air and Sal-gem 'tis
+stronger than in the Confine of Air and Water, and still stronger in the
+Confine of Air and common Glass or Crystal, and stronger in the Confine
+of Air and a Diamond. If any of these, and such like transparent Solids,
+be immerged in Water, its Reflexion becomes, much weaker than before;
+and still weaker if they be immerged in the more strongly refracting
+Liquors of well rectified Oil of Vitriol or Spirit of Turpentine. If
+Water be distinguish'd into two parts by any imaginary Surface, the
+Reflexion in the Confine of those two parts is none at all. In the
+Confine of Water and Ice 'tis very little; in that of Water and Oil 'tis
+something greater; in that of Water and Sal-gem still greater; and in
+that of Water and Glass, or Crystal or other denser Substances still
+greater, accordingly as those Mediums differ more or less in their
+refracting Powers. Hence in the Confine of common Glass and Crystal,
+there ought to be a weak Reflexion, and a stronger Reflexion in the
+Confine of common and metalline Glass; though I have not yet tried
+this. But in the Confine of two Glasses of equal density, there is not
+any sensible Reflexion; as was shewn in the first Observation. And the
+same may be understood of the Superficies interceding two Crystals, or
+two Liquors, or any other Substances in which no Refraction is caused.
+So then the reason why uniform pellucid Mediums (such as Water, Glass,
+or Crystal,) have no sensible Reflexion but in their external
+Superficies, where they are adjacent to other Mediums of a different
+density, is because all their contiguous parts have one and the same
+degree of density.
+
+
+PROP. II.
+
+_The least parts of almost all natural Bodies are in some measure
+transparent: And the Opacity of those Bodies ariseth from the multitude
+of Reflexions caused in their internal Parts._
+
+That this is so has been observed by others, and will easily be granted
+by them that have been conversant with Microscopes. And it may be also
+tried by applying any substance to a hole through which some Light is
+immitted into a dark Room. For how opake soever that Substance may seem
+in the open Air, it will by that means appear very manifestly
+transparent, if it be of a sufficient thinness. Only white metalline
+Bodies must be excepted, which by reason of their excessive density seem
+to reflect almost all the Light incident on their first Superficies;
+unless by solution in Menstruums they be reduced into very small
+Particles, and then they become transparent.
+
+
+PROP. III.
+
+_Between the parts of opake and colour'd Bodies are many Spaces, either
+empty, or replenish'd with Mediums of other Densities; as Water between
+the tinging Corpuscles wherewith any Liquor is impregnated, Air between
+the aqueous Globules that constitute Clouds or Mists; and for the most
+part Spaces void of both Air and Water, but yet perhaps not wholly void
+of all Substance, between the parts of hard Bodies._
+
+The truth of this is evinced by the two precedent Propositions: For by
+the second Proposition there are many Reflexions made by the internal
+parts of Bodies, which, by the first Proposition, would not happen if
+the parts of those Bodies were continued without any such Interstices
+between them; because Reflexions are caused only in Superficies, which
+intercede Mediums of a differing density, by _Prop._ 1.
+
+But farther, that this discontinuity of parts is the principal Cause of
+the opacity of Bodies, will appear by considering, that opake Substances
+become transparent by filling their Pores with any Substance of equal or
+almost equal density with their parts. Thus Paper dipped in Water or
+Oil, the _Oculus Mundi_ Stone steep'd in Water, Linnen Cloth oiled or
+varnish'd, and many other Substances soaked in such Liquors as will
+intimately pervade their little Pores, become by that means more
+transparent than otherwise; so, on the contrary, the most transparent
+Substances, may, by evacuating their Pores, or separating their parts,
+be render'd sufficiently opake; as Salts or wet Paper, or the _Oculus
+Mundi_ Stone by being dried, Horn by being scraped, Glass by being
+reduced to Powder, or otherwise flawed; Turpentine by being stirred
+about with Water till they mix imperfectly, and Water by being form'd
+into many small Bubbles, either alone in the form of Froth, or by
+shaking it together with Oil of Turpentine, or Oil Olive, or with some
+other convenient Liquor, with which it will not perfectly incorporate.
+And to the increase of the opacity of these Bodies, it conduces
+something, that by the 23d Observation the Reflexions of very thin
+transparent Substances are considerably stronger than those made by the
+same Substances of a greater thickness.
+
+
+PROP. IV.
+
+_The Parts of Bodies and their Interstices must not be less than of some
+definite bigness, to render them opake and colour'd._
+
+For the opakest Bodies, if their parts be subtilly divided, (as Metals,
+by being dissolved in acid Menstruums, &c.) become perfectly
+transparent. And you may also remember, that in the eighth Observation
+there was no sensible reflexion at the Superficies of the
+Object-glasses, where they were very near one another, though they did
+not absolutely touch. And in the 17th Observation the Reflexion of the
+Water-bubble where it became thinnest was almost insensible, so as to
+cause very black Spots to appear on the top of the Bubble, by the want
+of reflected Light.
+
+On these grounds I perceive it is that Water, Salt, Glass, Stones, and
+such like Substances, are transparent. For, upon divers Considerations,
+they seem to be as full of Pores or Interstices between their parts as
+other Bodies are, but yet their Parts and Interstices to be too small to
+cause Reflexions in their common Surfaces.
+
+
+PROP. V.
+
+_The transparent parts of Bodies, according to their several sizes,
+reflect Rays of one Colour, and transmit those of another, on the same
+grounds that thin Plates or Bubbles do reflect or transmit those Rays.
+And this I take to be the ground of all their Colours._
+
+For if a thinn'd or plated Body, which being of an even thickness,
+appears all over of one uniform Colour, should be slit into Threads, or
+broken into Fragments, of the same thickness with the Plate; I see no
+reason why every Thread or Fragment should not keep its Colour, and by
+consequence why a heap of those Threads or Fragments should not
+constitute a Mass or Powder of the same Colour, which the Plate
+exhibited before it was broken. And the parts of all natural Bodies
+being like so many Fragments of a Plate, must on the same grounds
+exhibit the same Colours.
+
+Now, that they do so will appear by the affinity of their Properties.
+The finely colour'd Feathers of some Birds, and particularly those of
+Peacocks Tails, do, in the very same part of the Feather, appear of
+several Colours in several Positions of the Eye, after the very same
+manner that thin Plates were found to do in the 7th and 19th
+Observations, and therefore their Colours arise from the thinness of the
+transparent parts of the Feathers; that is, from the slenderness of the
+very fine Hairs, or _Capillamenta_, which grow out of the sides of the
+grosser lateral Branches or Fibres of those Feathers. And to the same
+purpose it is, that the Webs of some Spiders, by being spun very fine,
+have appeared colour'd, as some have observ'd, and that the colour'd
+Fibres of some Silks, by varying the Position of the Eye, do vary their
+Colour. Also the Colours of Silks, Cloths, and other Substances, which
+Water or Oil can intimately penetrate, become more faint and obscure by
+being immerged in those Liquors, and recover their Vigor again by being
+dried; much after the manner declared of thin Bodies in the 10th and
+21st Observations. Leaf-Gold, some sorts of painted Glass, the Infusion
+of _Lignum Nephriticum_, and some other Substances, reflect one Colour,
+and transmit another; like thin Bodies in the 9th and 20th Observations.
+And some of those colour'd Powders which Painters use, may have their
+Colours a little changed, by being very elaborately and finely ground.
+Where I see not what can be justly pretended for those changes, besides
+the breaking of their parts into less parts by that contrition, after
+the same manner that the Colour of a thin Plate is changed by varying
+its thickness. For which reason also it is that the colour'd Flowers of
+Plants and Vegetables, by being bruised, usually become more transparent
+than before, or at least in some degree or other change their Colours.
+Nor is it much less to my purpose, that, by mixing divers Liquors, very
+odd and remarkable Productions and Changes of Colours may be effected,
+of which no cause can be more obvious and rational than that the saline
+Corpuscles of one Liquor do variously act upon or unite with the tinging
+Corpuscles of another, so as to make them swell, or shrink, (whereby not
+only their bulk but their density also may be changed,) or to divide
+them into smaller Corpuscles, (whereby a colour'd Liquor may become
+transparent,) or to make many of them associate into one cluster,
+whereby two transparent Liquors may compose a colour'd one. For we see
+how apt those saline Menstruums are to penetrate and dissolve Substances
+to which they are applied, and some of them to precipitate what others
+dissolve. In like manner, if we consider the various Phænomena of the
+Atmosphere, we may observe, that when Vapours are first raised, they
+hinder not the transparency of the Air, being divided into parts too
+small to cause any Reflexion in their Superficies. But when in order to
+compose drops of Rain they begin to coalesce and constitute Globules of
+all intermediate sizes, those Globules, when they become of convenient
+size to reflect some Colours and transmit others, may constitute Clouds
+of various Colours according to their sizes. And I see not what can be
+rationally conceived in so transparent a Substance as Water for the
+production of these Colours, besides the various sizes of its fluid and
+globular Parcels.
+
+
+PROP. VI.
+
+_The parts of Bodies on which their Colours depend, are denser than the
+Medium which pervades their Interstices._
+
+This will appear by considering, that the Colour of a Body depends not
+only on the Rays which are incident perpendicularly on its parts, but on
+those also which are incident at all other Angles. And that according to
+the 7th Observation, a very little variation of obliquity will change
+the reflected Colour, where the thin Body or small Particles is rarer
+than the ambient Medium, insomuch that such a small Particle will at
+diversly oblique Incidences reflect all sorts of Colours, in so great a
+variety that the Colour resulting from them all, confusedly reflected
+from a heap of such Particles, must rather be a white or grey than any
+other Colour, or at best it must be but a very imperfect and dirty
+Colour. Whereas if the thin Body or small Particle be much denser than
+the ambient Medium, the Colours, according to the 19th Observation, are
+so little changed by the variation of obliquity, that the Rays which
+are reflected least obliquely may predominate over the rest, so much as
+to cause a heap of such Particles to appear very intensely of their
+Colour.
+
+It conduces also something to the confirmation of this Proposition,
+that, according to the 22d Observation, the Colours exhibited by the
+denser thin Body within the rarer, are more brisk than those exhibited
+by the rarer within the denser.
+
+
+PROP. VII.
+
+_The bigness of the component parts of natural Bodies may be conjectured
+by their Colours._
+
+For since the parts of these Bodies, by _Prop._ 5. do most probably
+exhibit the same Colours with a Plate of equal thickness, provided they
+have the same refractive density; and since their parts seem for the
+most part to have much the same density with Water or Glass, as by many
+circumstances is obvious to collect; to determine the sizes of those
+parts, you need only have recourse to the precedent Tables, in which the
+thickness of Water or Glass exhibiting any Colour is expressed. Thus if
+it be desired to know the diameter of a Corpuscle, which being of equal
+density with Glass shall reflect green of the third Order; the Number
+16-1/4 shews it to be (16-1/4)/10000 parts of an Inch.
+
+The greatest difficulty is here to know of what Order the Colour of any
+Body is. And for this end we must have recourse to the 4th and 18th
+Observations; from whence may be collected these particulars.
+
+_Scarlets_, and other _reds_, _oranges_, and _yellows_, if they be pure
+and intense, are most probably of the second order. Those of the first
+and third order also may be pretty good; only the yellow of the first
+order is faint, and the orange and red of the third Order have a great
+Mixture of violet and blue.
+
+There may be good _Greens_ of the fourth Order, but the purest are of
+the third. And of this Order the green of all Vegetables seems to be,
+partly by reason of the Intenseness of their Colours, and partly because
+when they wither some of them turn to a greenish yellow, and others to a
+more perfect yellow or orange, or perhaps to red, passing first through
+all the aforesaid intermediate Colours. Which Changes seem to be
+effected by the exhaling of the Moisture which may leave the tinging
+Corpuscles more dense, and something augmented by the Accretion of the
+oily and earthy Part of that Moisture. Now the green, without doubt, is
+of the same Order with those Colours into which it changeth, because the
+Changes are gradual, and those Colours, though usually not very full,
+yet are often too full and lively to be of the fourth Order.
+
+_Blues_ and _Purples_ may be either of the second or third Order, but
+the best are of the third. Thus the Colour of Violets seems to be of
+that Order, because their Syrup by acid Liquors turns red, and by
+urinous and alcalizate turns green. For since it is of the Nature of
+Acids to dissolve or attenuate, and of Alcalies to precipitate or
+incrassate, if the Purple Colour of the Syrup was of the second Order,
+an acid Liquor by attenuating its tinging Corpuscles would change it to
+a red of the first Order, and an Alcali by incrassating them would
+change it to a green of the second Order; which red and green,
+especially the green, seem too imperfect to be the Colours produced by
+these Changes. But if the said Purple be supposed of the third Order,
+its Change to red of the second, and green of the third, may without any
+Inconvenience be allow'd.
+
+If there be found any Body of a deeper and less reddish Purple than that
+of the Violets, its Colour most probably is of the second Order. But yet
+there being no Body commonly known whose Colour is constantly more deep
+than theirs, I have made use of their Name to denote the deepest and
+least reddish Purples, such as manifestly transcend their Colour in
+purity.
+
+The _blue_ of the first Order, though very faint and little, may
+possibly be the Colour of some Substances; and particularly the azure
+Colour of the Skies seems to be of this Order. For all Vapours when they
+begin to condense and coalesce into small Parcels, become first of that
+Bigness, whereby such an Azure must be reflected before they can
+constitute Clouds of other Colours. And so this being the first Colour
+which Vapours begin to reflect, it ought to be the Colour of the finest
+and most transparent Skies, in which Vapours are not arrived to that
+Grossness requisite to reflect other Colours, as we find it is by
+Experience.
+
+_Whiteness_, if most intense and luminous, is that of the first Order,
+if less strong and luminous, a Mixture of the Colours of several Orders.
+Of this last kind is the Whiteness of Froth, Paper, Linnen, and most
+white Substances; of the former I reckon that of white Metals to be. For
+whilst the densest of Metals, Gold, if foliated, is transparent, and all
+Metals become transparent if dissolved in Menstruums or vitrified, the
+Opacity of white Metals ariseth not from their Density alone. They being
+less dense than Gold would be more transparent than it, did not some
+other Cause concur with their Density to make them opake. And this Cause
+I take to be such a Bigness of their Particles as fits them to reflect
+the white of the first order. For, if they be of other Thicknesses they
+may reflect other Colours, as is manifest by the Colours which appear
+upon hot Steel in tempering it, and sometimes upon the Surface of melted
+Metals in the Skin or Scoria which arises upon them in their cooling.
+And as the white of the first order is the strongest which can be made
+by Plates of transparent Substances, so it ought to be stronger in the
+denser Substances of Metals than in the rarer of Air, Water, and Glass.
+Nor do I see but that metallick Substances of such a Thickness as may
+fit them to reflect the white of the first order, may, by reason of
+their great Density (according to the Tenor of the first of these
+Propositions) reflect all the Light incident upon them, and so be as
+opake and splendent as it's possible for any Body to be. Gold, or Copper
+mix'd with less than half their Weight of Silver, or Tin, or Regulus of
+Antimony, in fusion, or amalgamed with a very little Mercury, become
+white; which shews both that the Particles of white Metals have much
+more Superficies, and so are smaller, than those of Gold and Copper, and
+also that they are so opake as not to suffer the Particles of Gold or
+Copper to shine through them. Now it is scarce to be doubted but that
+the Colours of Gold and Copper are of the second and third order, and
+therefore the Particles of white Metals cannot be much bigger than is
+requisite to make them reflect the white of the first order. The
+Volatility of Mercury argues that they are not much bigger, nor may they
+be much less, lest they lose their Opacity, and become either
+transparent as they do when attenuated by Vitrification, or by Solution
+in Menstruums, or black as they do when ground smaller, by rubbing
+Silver, or Tin, or Lead, upon other Substances to draw black Lines. The
+first and only Colour which white Metals take by grinding their
+Particles smaller, is black, and therefore their white ought to be that
+which borders upon the black Spot in the Center of the Rings of Colours,
+that is, the white of the first order. But, if you would hence gather
+the Bigness of metallick Particles, you must allow for their Density.
+For were Mercury transparent, its Density is such that the Sine of
+Incidence upon it (by my Computation) would be to the Sine of its
+Refraction, as 71 to 20, or 7 to 2. And therefore the Thickness of its
+Particles, that they may exhibit the same Colours with those of Bubbles
+of Water, ought to be less than the Thickness of the Skin of those
+Bubbles in the Proportion of 2 to 7. Whence it's possible, that the
+Particles of Mercury may be as little as the Particles of some
+transparent and volatile Fluids, and yet reflect the white of the first
+order.
+
+Lastly, for the production of _black_, the Corpuscles must be less than
+any of those which exhibit Colours. For at all greater sizes there is
+too much Light reflected to constitute this Colour. But if they be
+supposed a little less than is requisite to reflect the white and very
+faint blue of the first order, they will, according to the 4th, 8th,
+17th and 18th Observations, reflect so very little Light as to appear
+intensely black, and yet may perhaps variously refract it to and fro
+within themselves so long, until it happen to be stifled and lost, by
+which means they will appear black in all positions of the Eye without
+any transparency. And from hence may be understood why Fire, and the
+more subtile dissolver Putrefaction, by dividing the Particles of
+Substances, turn them to black, why small quantities of black Substances
+impart their Colour very freely and intensely to other Substances to
+which they are applied; the minute Particles of these, by reason of
+their very great number, easily overspreading the gross Particles of
+others; why Glass ground very elaborately with Sand on a Copper Plate,
+'till it be well polish'd, makes the Sand, together with what is worn
+off from the Glass and Copper, become very black: why black Substances
+do soonest of all others become hot in the Sun's Light and burn, (which
+Effect may proceed partly from the multitude of Refractions in a little
+room, and partly from the easy Commotion of so very small Corpuscles;)
+and why blacks are usually a little inclined to a bluish Colour. For
+that they are so may be seen by illuminating white Paper by Light
+reflected from black Substances. For the Paper will usually appear of a
+bluish white; and the reason is, that black borders in the obscure blue
+of the order described in the 18th Observation, and therefore reflects
+more Rays of that Colour than of any other.
+
+In these Descriptions I have been the more particular, because it is not
+impossible but that Microscopes may at length be improved to the
+discovery of the Particles of Bodies on which their Colours depend, if
+they are not already in some measure arrived to that degree of
+perfection. For if those Instruments are or can be so far improved as
+with sufficient distinctness to represent Objects five or six hundred
+times bigger than at a Foot distance they appear to our naked Eyes, I
+should hope that we might be able to discover some of the greatest of
+those Corpuscles. And by one that would magnify three or four thousand
+times perhaps they might all be discover'd, but those which produce
+blackness. In the mean while I see nothing material in this Discourse
+that may rationally be doubted of, excepting this Position: That
+transparent Corpuscles of the same thickness and density with a Plate,
+do exhibit the same Colour. And this I would have understood not without
+some Latitude, as well because those Corpuscles may be of irregular
+Figures, and many Rays must be obliquely incident on them, and so have
+a shorter way through them than the length of their Diameters, as
+because the straitness of the Medium put in on all sides within such
+Corpuscles may a little alter its Motions or other qualities on which
+the Reflexion depends. But yet I cannot much suspect the last, because I
+have observed of some small Plates of Muscovy Glass which were of an
+even thickness, that through a Microscope they have appeared of the same
+Colour at their edges and corners where the included Medium was
+terminated, which they appeared of in other places. However it will add
+much to our Satisfaction, if those Corpuscles can be discover'd with
+Microscopes; which if we shall at length attain to, I fear it will be
+the utmost improvement of this Sense. For it seems impossible to see the
+more secret and noble Works of Nature within the Corpuscles by reason of
+their transparency.
+
+
+PROP. VIII.
+
+_The Cause of Reflexion is not the impinging of Light on the solid or
+impervious parts of Bodies, as is commonly believed._
+
+This will appear by the following Considerations. First, That in the
+passage of Light out of Glass into Air there is a Reflexion as strong as
+in its passage out of Air into Glass, or rather a little stronger, and
+by many degrees stronger than in its passage out of Glass into Water.
+And it seems not probable that Air should have more strongly reflecting
+parts than Water or Glass. But if that should possibly be supposed, yet
+it will avail nothing; for the Reflexion is as strong or stronger when
+the Air is drawn away from the Glass, (suppose by the Air-Pump invented
+by _Otto Gueriet_, and improved and made useful by Mr. _Boyle_) as when
+it is adjacent to it. Secondly, If Light in its passage out of Glass
+into Air be incident more obliquely than at an Angle of 40 or 41 Degrees
+it is wholly reflected, if less obliquely it is in great measure
+transmitted. Now it is not to be imagined that Light at one degree of
+obliquity should meet with Pores enough in the Air to transmit the
+greater part of it, and at another degree of obliquity should meet with
+nothing but parts to reflect it wholly, especially considering that in
+its passage out of Air into Glass, how oblique soever be its Incidence,
+it finds Pores enough in the Glass to transmit a great part of it. If
+any Man suppose that it is not reflected by the Air, but by the outmost
+superficial parts of the Glass, there is still the same difficulty:
+Besides, that such a Supposition is unintelligible, and will also appear
+to be false by applying Water behind some part of the Glass instead of
+Air. For so in a convenient obliquity of the Rays, suppose of 45 or 46
+Degrees, at which they are all reflected where the Air is adjacent to
+the Glass, they shall be in great measure transmitted where the Water is
+adjacent to it; which argues, that their Reflexion or Transmission
+depends on the constitution of the Air and Water behind the Glass, and
+not on the striking of the Rays upon the parts of the Glass. Thirdly,
+If the Colours made by a Prism placed at the entrance of a Beam of Light
+into a darken'd Room be successively cast on a second Prism placed at a
+greater distance from the former, in such manner that they are all alike
+incident upon it, the second Prism may be so inclined to the incident
+Rays, that those which are of a blue Colour shall be all reflected by
+it, and yet those of a red Colour pretty copiously transmitted. Now if
+the Reflexion be caused by the parts of Air or Glass, I would ask, why
+at the same Obliquity of Incidence the blue should wholly impinge on
+those parts, so as to be all reflected, and yet the red find Pores
+enough to be in a great measure transmitted. Fourthly, Where two Glasses
+touch one another, there is no sensible Reflexion, as was declared in
+the first Observation; and yet I see no reason why the Rays should not
+impinge on the parts of Glass, as much when contiguous to other Glass as
+when contiguous to Air. Fifthly, When the top of a Water-Bubble (in the
+17th Observation,) by the continual subsiding and exhaling of the Water
+grew very thin, there was such a little and almost insensible quantity
+of Light reflected from it, that it appeared intensely black; whereas
+round about that black Spot, where the Water was thicker, the Reflexion
+was so strong as to make the Water seem very white. Nor is it only at
+the least thickness of thin Plates or Bubbles, that there is no manifest
+Reflexion, but at many other thicknesses continually greater and
+greater. For in the 15th Observation the Rays of the same Colour were by
+turns transmitted at one thickness, and reflected at another thickness,
+for an indeterminate number of Successions. And yet in the Superficies
+of the thinned Body, where it is of any one thickness, there are as many
+parts for the Rays to impinge on, as where it is of any other thickness.
+Sixthly, If Reflexion were caused by the parts of reflecting Bodies, it
+would be impossible for thin Plates or Bubbles, at one and the same
+place, to reflect the Rays of one Colour, and transmit those of another,
+as they do according to the 13th and 15th Observations. For it is not to
+be imagined that at one place the Rays which, for instance, exhibit a
+blue Colour, should have the fortune to dash upon the parts, and those
+which exhibit a red to hit upon the Pores of the Body; and then at
+another place, where the Body is either a little thicker or a little
+thinner, that on the contrary the blue should hit upon its pores, and
+the red upon its parts. Lastly, Were the Rays of Light reflected by
+impinging on the solid parts of Bodies, their Reflexions from polish'd
+Bodies could not be so regular as they are. For in polishing Glass with
+Sand, Putty, or Tripoly, it is not to be imagined that those Substances
+can, by grating and fretting the Glass, bring all its least Particles to
+an accurate Polish; so that all their Surfaces shall be truly plain or
+truly spherical, and look all the same way, so as together to compose
+one even Surface. The smaller the Particles of those Substances are, the
+smaller will be the Scratches by which they continually fret and wear
+away the Glass until it be polish'd; but be they never so small they can
+wear away the Glass no otherwise than by grating and scratching it, and
+breaking the Protuberances; and therefore polish it no otherwise than by
+bringing its roughness to a very fine Grain, so that the Scratches and
+Frettings of the Surface become too small to be visible. And therefore
+if Light were reflected by impinging upon the solid parts of the Glass,
+it would be scatter'd as much by the most polish'd Glass as by the
+roughest. So then it remains a Problem, how Glass polish'd by fretting
+Substances can reflect Light so regularly as it does. And this Problem
+is scarce otherwise to be solved, than by saying, that the Reflexion of
+a Ray is effected, not by a single point of the reflecting Body, but by
+some power of the Body which is evenly diffused all over its Surface,
+and by which it acts upon the Ray without immediate Contact. For that
+the parts of Bodies do act upon Light at a distance shall be shewn
+hereafter.
+
+Now if Light be reflected, not by impinging on the solid parts of
+Bodies, but by some other principle; it's probable that as many of its
+Rays as impinge on the solid parts of Bodies are not reflected but
+stifled and lost in the Bodies. For otherwise we must allow two sorts of
+Reflexions. Should all the Rays be reflected which impinge on the
+internal parts of clear Water or Crystal, those Substances would rather
+have a cloudy Colour than a clear Transparency. To make Bodies look
+black, it's necessary that many Rays be stopp'd, retained, and lost in
+them; and it seems not probable that any Rays can be stopp'd and
+stifled in them which do not impinge on their parts.
+
+And hence we may understand that Bodies are much more rare and porous
+than is commonly believed. Water is nineteen times lighter, and by
+consequence nineteen times rarer than Gold; and Gold is so rare as very
+readily and without the least opposition to transmit the magnetick
+Effluvia, and easily to admit Quicksilver into its Pores, and to let
+Water pass through it. For a concave Sphere of Gold filled with Water,
+and solder'd up, has, upon pressing the Sphere with great force, let the
+Water squeeze through it, and stand all over its outside in multitudes
+of small Drops, like Dew, without bursting or cracking the Body of the
+Gold, as I have been inform'd by an Eye witness. From all which we may
+conclude, that Gold has more Pores than solid parts, and by consequence
+that Water has above forty times more Pores than Parts. And he that
+shall find out an Hypothesis, by which Water may be so rare, and yet not
+be capable of compression by force, may doubtless by the same Hypothesis
+make Gold, and Water, and all other Bodies, as much rarer as he pleases;
+so that Light may find a ready passage through transparent Substances.
+
+The Magnet acts upon Iron through all dense Bodies not magnetick nor red
+hot, without any diminution of its Virtue; as for instance, through
+Gold, Silver, Lead, Glass, Water. The gravitating Power of the Sun is
+transmitted through the vast Bodies of the Planets without any
+diminution, so as to act upon all their parts to their very centers
+with the same Force and according to the same Laws, as if the part upon
+which it acts were not surrounded with the Body of the Planet, The Rays
+of Light, whether they be very small Bodies projected, or only Motion or
+Force propagated, are moved in right Lines; and whenever a Ray of Light
+is by any Obstacle turned out of its rectilinear way, it will never
+return into the same rectilinear way, unless perhaps by very great
+accident. And yet Light is transmitted through pellucid solid Bodies in
+right Lines to very great distances. How Bodies can have a sufficient
+quantity of Pores for producing these Effects is very difficult to
+conceive, but perhaps not altogether impossible. For the Colours of
+Bodies arise from the Magnitudes of the Particles which reflect them, as
+was explained above. Now if we conceive these Particles of Bodies to be
+so disposed amongst themselves, that the Intervals or empty Spaces
+between them may be equal in magnitude to them all; and that these
+Particles may be composed of other Particles much smaller, which have as
+much empty Space between them as equals all the Magnitudes of these
+smaller Particles: And that in like manner these smaller Particles are
+again composed of others much smaller, all which together are equal to
+all the Pores or empty Spaces between them; and so on perpetually till
+you come to solid Particles, such as have no Pores or empty Spaces
+within them: And if in any gross Body there be, for instance, three such
+degrees of Particles, the least of which are solid; this Body will have
+seven times more Pores than solid Parts. But if there be four such
+degrees of Particles, the least of which are solid, the Body will have
+fifteen times more Pores than solid Parts. If there be five degrees, the
+Body will have one and thirty times more Pores than solid Parts. If six
+degrees, the Body will have sixty and three times more Pores than solid
+Parts. And so on perpetually. And there are other ways of conceiving how
+Bodies may be exceeding porous. But what is really their inward Frame is
+not yet known to us.
+
+
+PROP. IX.
+
+_Bodies reflect and refract Light by one and the same power, variously
+exercised in various Circumstances._
+
+This appears by several Considerations. First, Because when Light goes
+out of Glass into Air, as obliquely as it can possibly do. If its
+Incidence be made still more oblique, it becomes totally reflected. For
+the power of the Glass after it has refracted the Light as obliquely as
+is possible, if the Incidence be still made more oblique, becomes too
+strong to let any of its Rays go through, and by consequence causes
+total Reflexions. Secondly, Because Light is alternately reflected and
+transmitted by thin Plates of Glass for many Successions, accordingly as
+the thickness of the Plate increases in an arithmetical Progression. For
+here the thickness of the Glass determines whether that Power by which
+Glass acts upon Light shall cause it to be reflected, or suffer it to
+be transmitted. And, Thirdly, because those Surfaces of transparent
+Bodies which have the greatest refracting power, reflect the greatest
+quantity of Light, as was shewn in the first Proposition.
+
+
+PROP. X.
+
+_If Light be swifter in Bodies than in Vacuo, in the proportion of the
+Sines which measure the Refraction of the Bodies, the Forces of the
+Bodies to reflect and refract Light, are very nearly proportional to the
+densities of the same Bodies; excepting that unctuous and sulphureous
+Bodies refract more than others of this same density._
+
+[Illustration: FIG. 8.]
+
+Let AB represent the refracting plane Surface of any Body, and IC a Ray
+incident very obliquely upon the Body in C, so that the Angle ACI may be
+infinitely little, and let CR be the refracted Ray. From a given Point B
+perpendicular to the refracting Surface erect BR meeting with the
+refracting Ray CR in R, and if CR represent the Motion of the refracted
+Ray, and this Motion be distinguish'd into two Motions CB and BR,
+whereof CB is parallel to the refracting Plane, and BR perpendicular to
+it: CB shall represent the Motion of the incident Ray, and BR the
+Motion generated by the Refraction, as Opticians have of late explain'd.
+
+Now if any Body or Thing, in moving through any Space of a given breadth
+terminated on both sides by two parallel Planes, be urged forward in all
+parts of that Space by Forces tending directly forwards towards the last
+Plane, and before its Incidence on the first Plane, had no Motion
+towards it, or but an infinitely little one; and if the Forces in all
+parts of that Space, between the Planes, be at equal distances from the
+Planes equal to one another, but at several distances be bigger or less
+in any given Proportion, the Motion generated by the Forces in the whole
+passage of the Body or thing through that Space shall be in a
+subduplicate Proportion of the Forces, as Mathematicians will easily
+understand. And therefore, if the Space of activity of the refracting
+Superficies of the Body be consider'd as such a Space, the Motion of the
+Ray generated by the refracting Force of the Body, during its passage
+through that Space, that is, the Motion BR, must be in subduplicate
+Proportion of that refracting Force. I say therefore, that the Square of
+the Line BR, and by consequence the refracting Force of the Body, is
+very nearly as the density of the same Body. For this will appear by the
+following Table, wherein the Proportion of the Sines which measure the
+Refractions of several Bodies, the Square of BR, supposing CB an unite,
+the Densities of the Bodies estimated by their Specifick Gravities, and
+their Refractive Power in respect of their Densities are set down in
+several Columns.
+
+---------------------+----------------+----------------+----------+-----------
+ | | | |
+ | | The Square | The | The
+ | | of BR, to | density | refractive
+ | The Proportion | which the | and | Power of
+ | of the Sines of| refracting | specifick| the Body
+ | Incidence and | force of the | gravity | in respect
+ The refracting | Refraction of | Body is | of the | of its
+ Bodies. | yellow Light. | proportionate. | Body. | density.
+---------------------+----------------+----------------+----------+-----------
+A Pseudo-Topazius, | | | |
+ being a natural, | | | |
+ pellucid, brittle, | 23 to 14 | 1'699 | 4'27 | 3979
+ hairy Stone, of a | | | |
+ yellow Colour. | | | |
+Air. | 3201 to 3200 | 0'000625 | 0'0012 | 5208
+Glass of Antimony. | 17 to 9 | 2'568 | 5'28 | 4864
+A Selenitis. | 61 to 41 | 1'213 | 2'252 | 5386
+Glass vulgar. | 31 to 20 | 1'4025 | 2'58 | 5436
+Crystal of the Rock. | 25 to 16 | 1'445 | 2'65 | 5450
+Island Crystal. | 5 to 3 | 1'778 | 2'72 | 6536
+Sal Gemmæ. | 17 to 11 | 1'388 | 2'143 | 6477
+Alume. | 35 to 24 | 1'1267 | 1'714 | 6570
+Borax. | 22 to 15 | 1'1511 | 1'714 | 6716
+Niter. | 32 to 21 | 1'345 | 1'9 | 7079
+Dantzick Vitriol. | 303 to 200 | 1'295 | 1'715 | 7551
+Oil of Vitriol. | 10 to 7 | 1'041 | 1'7 | 6124
+Rain Water. | 529 to 396 | 0'7845 | 1' | 7845
+Gum Arabick. | 31 to 21 | 1'179 | 1'375 | 8574
+Spirit of Wine well | | | |
+ rectified. | 100 to 73 | 0'8765 | 0'866 | 10121
+Camphire. | 3 to 2 | 1'25 | 0'996 | 12551
+Oil Olive. | 22 to 15 | 1'1511 | 0'913 | 12607
+Linseed Oil. | 40 to 27 | 1'1948 | 0'932 | 12819
+Spirit of Turpentine.| 25 to 17 | 1'1626 | 0'874 | 13222
+Amber. | 14 to 9 | 1'42 | 1'04 | 13654
+A Diamond. | 100 to 41 | 4'949 | 3'4 | 14556
+---------------------+----------------+----------------+----------+-----------
+
+The Refraction of the Air in this Table is determin'd by that of the
+Atmosphere observed by Astronomers. For, if Light pass through many
+refracting Substances or Mediums gradually denser and denser, and
+terminated with parallel Surfaces, the Sum of all the Refractions will
+be equal to the single Refraction which it would have suffer'd in
+passing immediately out of the first Medium into the last. And this
+holds true, though the Number of the refracting Substances be increased
+to Infinity, and the Distances from one another as much decreased, so
+that the Light may be refracted in every Point of its Passage, and by
+continual Refractions bent into a Curve-Line. And therefore the whole
+Refraction of Light in passing through the Atmosphere from the highest
+and rarest Part thereof down to the lowest and densest Part, must be
+equal to the Refraction which it would suffer in passing at like
+Obliquity out of a Vacuum immediately into Air of equal Density with
+that in the lowest Part of the Atmosphere.
+
+Now, although a Pseudo-Topaz, a Selenitis, Rock Crystal, Island Crystal,
+Vulgar Glass (that is, Sand melted together) and Glass of Antimony,
+which are terrestrial stony alcalizate Concretes, and Air which probably
+arises from such Substances by Fermentation, be Substances very
+differing from one another in Density, yet by this Table, they have
+their refractive Powers almost in the same Proportion to one another as
+their Densities are, excepting that the Refraction of that strange
+Substance, Island Crystal is a little bigger than the rest. And
+particularly Air, which is 3500 Times rarer than the Pseudo-Topaz, and
+4400 Times rarer than Glass of Antimony, and 2000 Times rarer than the
+Selenitis, Glass vulgar, or Crystal of the Rock, has notwithstanding its
+rarity the same refractive Power in respect of its Density which those
+very dense Substances have in respect of theirs, excepting so far as
+those differ from one another.
+
+Again, the Refraction of Camphire, Oil Olive, Linseed Oil, Spirit of
+Turpentine and Amber, which are fat sulphureous unctuous Bodies, and a
+Diamond, which probably is an unctuous Substance coagulated, have their
+refractive Powers in Proportion to one another as their Densities
+without any considerable Variation. But the refractive Powers of these
+unctuous Substances are two or three Times greater in respect of their
+Densities than the refractive Powers of the former Substances in respect
+of theirs.
+
+Water has a refractive Power in a middle degree between those two sorts
+of Substances, and probably is of a middle nature. For out of it grow
+all vegetable and animal Substances, which consist as well of
+sulphureous fat and inflamable Parts, as of earthy lean and alcalizate
+ones.
+
+Salts and Vitriols have refractive Powers in a middle degree between
+those of earthy Substances and Water, and accordingly are composed of
+those two sorts of Substances. For by distillation and rectification of
+their Spirits a great Part of them goes into Water, and a great Part
+remains behind in the form of a dry fix'd Earth capable of
+Vitrification.
+
+Spirit of Wine has a refractive Power in a middle degree between those
+of Water and oily Substances, and accordingly seems to be composed of
+both, united by Fermentation; the Water, by means of some saline Spirits
+with which 'tis impregnated, dissolving the Oil, and volatizing it by
+the Action. For Spirit of Wine is inflamable by means of its oily Parts,
+and being distilled often from Salt of Tartar, grow by every
+distillation more and more aqueous and phlegmatick. And Chymists
+observe, that Vegetables (as Lavender, Rue, Marjoram, &c.) distilled
+_per se_, before fermentation yield Oils without any burning Spirits,
+but after fermentation yield ardent Spirits without Oils: Which shews,
+that their Oil is by fermentation converted into Spirit. They find also,
+that if Oils be poured in a small quantity upon fermentating Vegetables,
+they distil over after fermentation in the form of Spirits.
+
+So then, by the foregoing Table, all Bodies seem to have their
+refractive Powers proportional to their Densities, (or very nearly;)
+excepting so far as they partake more or less of sulphureous oily
+Particles, and thereby have their refractive Power made greater or less.
+Whence it seems rational to attribute the refractive Power of all Bodies
+chiefly, if not wholly, to the sulphureous Parts with which they abound.
+For it's probable that all Bodies abound more or less with Sulphurs. And
+as Light congregated by a Burning-glass acts most upon sulphureous
+Bodies, to turn them into Fire and Flame; so, since all Action is
+mutual, Sulphurs ought to act most upon Light. For that the action
+between Light and Bodies is mutual, may appear from this Consideration;
+That the densest Bodies which refract and reflect Light most strongly,
+grow hottest in the Summer Sun, by the action of the refracted or
+reflected Light.
+
+I have hitherto explain'd the power of Bodies to reflect and refract,
+and shew'd, that thin transparent Plates, Fibres, and Particles, do,
+according to their several thicknesses and densities, reflect several
+sorts of Rays, and thereby appear of several Colours; and by consequence
+that nothing more is requisite for producing all the Colours of natural
+Bodies, than the several sizes and densities of their transparent
+Particles. But whence it is that these Plates, Fibres, and Particles,
+do, according to their several thicknesses and densities, reflect
+several sorts of Rays, I have not yet explain'd. To give some insight
+into this matter, and make way for understanding the next part of this
+Book, I shall conclude this part with a few more Propositions. Those
+which preceded respect the nature of Bodies, these the nature of Light:
+For both must be understood, before the reason of their Actions upon one
+another can be known. And because the last Proposition depended upon the
+velocity of Light, I will begin with a Proposition of that kind.
+
+
+PROP. XI.
+
+_Light is propagated from luminous Bodies in time, and spends about
+seven or eight Minutes of an Hour in passing from the Sun to the Earth._
+
+This was observed first by _Roemer_, and then by others, by means of the
+Eclipses of the Satellites of _Jupiter_. For these Eclipses, when the
+Earth is between the Sun and _Jupiter_, happen about seven or eight
+Minutes sooner than they ought to do by the Tables, and when the Earth
+is beyond the Sun they happen about seven or eight Minutes later than
+they ought to do; the reason being, that the Light of the Satellites has
+farther to go in the latter case than in the former by the Diameter of
+the Earth's Orbit. Some inequalities of time may arise from the
+Excentricities of the Orbs of the Satellites; but those cannot answer in
+all the Satellites, and at all times to the Position and Distance of the
+Earth from the Sun. The mean motions of _Jupiter_'s Satellites is also
+swifter in his descent from his Aphelium to his Perihelium, than in his
+ascent in the other half of his Orb. But this inequality has no respect
+to the position of the Earth, and in the three interior Satellites is
+insensible, as I find by computation from the Theory of their Gravity.
+
+
+PROP. XII.
+
+_Every Ray of Light in its passage through any refracting Surface is put
+into a certain transient Constitution or State, which in the progress of
+the Ray returns at equal Intervals, and disposes the Ray at every return
+to be easily transmitted through the next refracting Surface, and
+between the returns to be easily reflected by it._
+
+This is manifest by the 5th, 9th, 12th, and 15th Observations. For by
+those Observations it appears, that one and the same sort of Rays at
+equal Angles of Incidence on any thin transparent Plate, is alternately
+reflected and transmitted for many Successions accordingly as the
+thickness of the Plate increases in arithmetical Progression of the
+Numbers, 0, 1, 2, 3, 4, 5, 6, 7, 8, &c. so that if the first Reflexion
+(that which makes the first or innermost of the Rings of Colours there
+described) be made at the thickness 1, the Rays shall be transmitted at
+the thicknesses 0, 2, 4, 6, 8, 10, 12, &c. and thereby make the central
+Spot and Rings of Light, which appear by transmission, and be reflected
+at the thickness 1, 3, 5, 7, 9, 11, &c. and thereby make the Rings which
+appear by Reflexion. And this alternate Reflexion and Transmission, as I
+gather by the 24th Observation, continues for above an hundred
+vicissitudes, and by the Observations in the next part of this Book, for
+many thousands, being propagated from one Surface of a Glass Plate to
+the other, though the thickness of the Plate be a quarter of an Inch or
+above: So that this alternation seems to be propagated from every
+refracting Surface to all distances without end or limitation.
+
+This alternate Reflexion and Refraction depends on both the Surfaces of
+every thin Plate, because it depends on their distance. By the 21st
+Observation, if either Surface of a thin Plate of _Muscovy_ Glass be
+wetted, the Colours caused by the alternate Reflexion and Refraction
+grow faint, and therefore it depends on them both.
+
+It is therefore perform'd at the second Surface; for if it were
+perform'd at the first, before the Rays arrive at the second, it would
+not depend on the second.
+
+It is also influenced by some action or disposition, propagated from the
+first to the second, because otherwise at the second it would not depend
+on the first. And this action or disposition, in its propagation,
+intermits and returns by equal Intervals, because in all its progress it
+inclines the Ray at one distance from the first Surface to be reflected
+by the second, at another to be transmitted by it, and that by equal
+Intervals for innumerable vicissitudes. And because the Ray is disposed
+to Reflexion at the distances 1, 3, 5, 7, 9, &c. and to Transmission at
+the distances 0, 2, 4, 6, 8, 10, &c. (for its transmission through the
+first Surface, is at the distance 0, and it is transmitted through both
+together, if their distance be infinitely little or much less than 1)
+the disposition to be transmitted at the distances 2, 4, 6, 8, 10, &c.
+is to be accounted a return of the same disposition which the Ray first
+had at the distance 0, that is at its transmission through the first
+refracting Surface. All which is the thing I would prove.
+
+What kind of action or disposition this is; Whether it consists in a
+circulating or a vibrating motion of the Ray, or of the Medium, or
+something else, I do not here enquire. Those that are averse from
+assenting to any new Discoveries, but such as they can explain by an
+Hypothesis, may for the present suppose, that as Stones by falling upon
+Water put the Water into an undulating Motion, and all Bodies by
+percussion excite vibrations in the Air; so the Rays of Light, by
+impinging on any refracting or reflecting Surface, excite vibrations in
+the refracting or reflecting Medium or Substance, and by exciting them
+agitate the solid parts of the refracting or reflecting Body, and by
+agitating them cause the Body to grow warm or hot; that the vibrations
+thus excited are propagated in the refracting or reflecting Medium or
+Substance, much after the manner that vibrations are propagated in the
+Air for causing Sound, and move faster than the Rays so as to overtake
+them; and that when any Ray is in that part of the vibration which
+conspires with its Motion, it easily breaks through a refracting
+Surface, but when it is in the contrary part of the vibration which
+impedes its Motion, it is easily reflected; and, by consequence, that
+every Ray is successively disposed to be easily reflected, or easily
+transmitted, by every vibration which overtakes it. But whether this
+Hypothesis be true or false I do not here consider. I content my self
+with the bare Discovery, that the Rays of Light are by some cause or
+other alternately disposed to be reflected or refracted for many
+vicissitudes.
+
+
+DEFINITION.
+
+_The returns of the disposition of any Ray to be reflected I will call
+its_ Fits of easy Reflexion, _and those of its disposition to be
+transmitted its_ Fits of easy Transmission, _and the space it passes
+between every return and the next return, the_ Interval of its Fits.
+
+
+PROP. XIII.
+
+_The reason why the Surfaces of all thick transparent Bodies reflect
+part of the Light incident on them, and refract the rest, is, that some
+Rays at their Incidence are in Fits of easy Reflexion, and others in
+Fits of easy Transmission._
+
+This may be gather'd from the 24th Observation, where the Light
+reflected by thin Plates of Air and Glass, which to the naked Eye
+appear'd evenly white all over the Plate, did through a Prism appear
+waved with many Successions of Light and Darkness made by alternate Fits
+of easy Reflexion and easy Transmission, the Prism severing and
+distinguishing the Waves of which the white reflected Light was
+composed, as was explain'd above.
+
+And hence Light is in Fits of easy Reflexion and easy Transmission,
+before its Incidence on transparent Bodies. And probably it is put into
+such fits at its first emission from luminous Bodies, and continues in
+them during all its progress. For these Fits are of a lasting nature, as
+will appear by the next part of this Book.
+
+In this Proposition I suppose the transparent Bodies to be thick;
+because if the thickness of the Body be much less than the Interval of
+the Fits of easy Reflexion and Transmission of the Rays, the Body loseth
+its reflecting power. For if the Rays, which at their entering into the
+Body are put into Fits of easy Transmission, arrive at the farthest
+Surface of the Body before they be out of those Fits, they must be
+transmitted. And this is the reason why Bubbles of Water lose their
+reflecting power when they grow very thin; and why all opake Bodies,
+when reduced into very small parts, become transparent.
+
+
+PROP. XIV.
+
+_Those Surfaces of transparent Bodies, which if the Ray be in a Fit of
+Refraction do refract it most strongly, if the Ray be in a Fit of
+Reflexion do reflect it most easily._
+
+For we shewed above, in _Prop._ 8. that the cause of Reflexion is not
+the impinging of Light on the solid impervious parts of Bodies, but some
+other power by which those solid parts act on Light at a distance. We
+shewed also in _Prop._ 9. that Bodies reflect and refract Light by one
+and the same power, variously exercised in various circumstances; and in
+_Prop._ 1. that the most strongly refracting Surfaces reflect the most
+Light: All which compared together evince and rarify both this and the
+last Proposition.
+
+
+PROP. XV.
+
+_In any one and the same sort of Rays, emerging in any Angle out of any
+refracting Surface into one and the same Medium, the Interval of the
+following Fits of easy Reflexion and Transmission are either accurately
+or very nearly, as the Rectangle of the Secant of the Angle of
+Refraction, and of the Secant of another Angle, whose Sine is the first
+of 106 arithmetical mean Proportionals, between the Sines of Incidence
+and Refraction, counted from the Sine of Refraction._
+
+This is manifest by the 7th and 19th Observations.
+
+
+PROP. XVI.
+
+_In several sorts of Rays emerging in equal Angles out of any refracting
+Surface into the same Medium, the Intervals of the following Fits of
+easy Reflexion and easy Transmission are either accurately, or very
+nearly, as the Cube-Roots of the Squares of the lengths of a Chord,
+which found the Notes in an Eight_, sol, la, fa, sol, la, mi, fa, sol,
+_with all their intermediate degrees answering to the Colours of those
+Rays, according to the Analogy described in the seventh Experiment of
+the second Part of the first Book._
+
+This is manifest by the 13th and 14th Observations.
+
+
+PROP. XVII.
+
+_If Rays of any sort pass perpendicularly into several Mediums, the
+Intervals of the Fits of easy Reflexion and Transmission in any one
+Medium, are to those Intervals in any other, as the Sine of Incidence to
+the Sine of Refraction, when the Rays pass out of the first of those two
+Mediums into the second._
+
+This is manifest by the 10th Observation.
+
+
+PROP. XVIII.
+
+_If the Rays which paint the Colour in the Confine of yellow and orange
+pass perpendicularly out of any Medium into Air, the Intervals of their
+Fits of easy Reflexion are the 1/89000th part of an Inch. And of the
+same length are the Intervals of their Fits of easy Transmission._
+
+This is manifest by the 6th Observation. From these Propositions it is
+easy to collect the Intervals of the Fits of easy Reflexion and easy
+Transmission of any sort of Rays refracted in any angle into any Medium;
+and thence to know, whether the Rays shall be reflected or transmitted
+at their subsequent Incidence upon any other pellucid Medium. Which
+thing, being useful for understanding the next part of this Book, was
+here to be set down. And for the same reason I add the two following
+Propositions.
+
+
+PROP. XIX.
+
+_If any sort of Rays falling on the polite Surface of any pellucid
+Medium be reflected back, the Fits of easy Reflexion, which they have at
+the point of Reflexion, shall still continue to return; and the Returns
+shall be at distances from the point of Reflexion in the arithmetical
+progression of the Numbers 2, 4, 6, 8, 10, 12, &c. and between these
+Fits the Rays shall be in Fits of easy Transmission._
+
+For since the Fits of easy Reflexion and easy Transmission are of a
+returning nature, there is no reason why these Fits, which continued
+till the Ray arrived at the reflecting Medium, and there inclined the
+Ray to Reflexion, should there cease. And if the Ray at the point of
+Reflexion was in a Fit of easy Reflexion, the progression of the
+distances of these Fits from that point must begin from 0, and so be of
+the Numbers 0, 2, 4, 6, 8, &c. And therefore the progression of the
+distances of the intermediate Fits of easy Transmission, reckon'd from
+the same point, must be in the progression of the odd Numbers 1, 3, 5,
+7, 9, &c. contrary to what happens when the Fits are propagated from
+points of Refraction.
+
+
+PROP. XX.
+
+_The Intervals of the Fits of easy Reflexion and easy Transmission,
+propagated from points of Reflexion into any Medium, are equal to the
+Intervals of the like Fits, which the same Rays would have, if refracted
+into the same Medium in Angles of Refraction equal to their Angles of
+Reflexion._
+
+For when Light is reflected by the second Surface of thin Plates, it
+goes out afterwards freely at the first Surface to make the Rings of
+Colours which appear by Reflexion; and, by the freedom of its egress,
+makes the Colours of these Rings more vivid and strong than those which
+appear on the other side of the Plates by the transmitted Light. The
+reflected Rays are therefore in Fits of easy Transmission at their
+egress; which would not always happen, if the Intervals of the Fits
+within the Plate after Reflexion were not equal, both in length and
+number, to their Intervals before it. And this confirms also the
+proportions set down in the former Proposition. For if the Rays both in
+going in and out at the first Surface be in Fits of easy Transmission,
+and the Intervals and Numbers of those Fits between the first and second
+Surface, before and after Reflexion, be equal, the distances of the Fits
+of easy Transmission from either Surface, must be in the same
+progression after Reflexion as before; that is, from the first Surface
+which transmitted them in the progression of the even Numbers 0, 2, 4,
+6, 8, &c. and from the second which reflected them, in that of the odd
+Numbers 1, 3, 5, 7, &c. But these two Propositions will become much more
+evident by the Observations in the following part of this Book.
+
+
+
+
+THE
+
+SECOND BOOK
+
+OF
+
+OPTICKS
+
+
+_PART IV._
+
+_Observations concerning the Reflexions and Colours of thick transparent
+polish'd Plates._
+
+There is no Glass or Speculum how well soever polished, but, besides the
+Light which it refracts or reflects regularly, scatters every way
+irregularly a faint Light, by means of which the polish'd Surface, when
+illuminated in a dark room by a beam of the Sun's Light, may be easily
+seen in all positions of the Eye. There are certain Phænomena of this
+scatter'd Light, which when I first observed them, seem'd very strange
+and surprizing to me. My Observations were as follows.
+
+_Obs._ 1. The Sun shining into my darken'd Chamber through a hole one
+third of an Inch wide, I let the intromitted beam of Light fall
+perpendicularly upon a Glass Speculum ground concave on one side and
+convex on the other, to a Sphere of five Feet and eleven Inches Radius,
+and Quick-silver'd over on the convex side. And holding a white opake
+Chart, or a Quire of Paper at the center of the Spheres to which the
+Speculum was ground, that is, at the distance of about five Feet and
+eleven Inches from the Speculum, in such manner, that the beam of Light
+might pass through a little hole made in the middle of the Chart to the
+Speculum, and thence be reflected back to the same hole: I observed upon
+the Chart four or five concentric Irises or Rings of Colours, like
+Rain-bows, encompassing the hole much after the manner that those, which
+in the fourth and following Observations of the first part of this Book
+appear'd between the Object-glasses, encompassed the black Spot, but yet
+larger and fainter than those. These Rings as they grew larger and
+larger became diluter and fainter, so that the fifth was scarce visible.
+Yet sometimes, when the Sun shone very clear, there appear'd faint
+Lineaments of a sixth and seventh. If the distance of the Chart from the
+Speculum was much greater or much less than that of six Feet, the Rings
+became dilute and vanish'd. And if the distance of the Speculum from the
+Window was much greater than that of six Feet, the reflected beam of
+Light would be so broad at the distance of six Feet from the Speculum
+where the Rings appear'd, as to obscure one or two of the innermost
+Rings. And therefore I usually placed the Speculum at about six Feet
+from the Window; so that its Focus might there fall in with the center
+of its concavity at the Rings upon the Chart. And this Posture is always
+to be understood in the following Observations where no other is
+express'd.
+
+_Obs._ 2. The Colours of these Rain-bows succeeded one another from the
+center outwards, in the same form and order with those which were made
+in the ninth Observation of the first Part of this Book by Light not
+reflected, but transmitted through the two Object-glasses. For, first,
+there was in their common center a white round Spot of faint Light,
+something broader than the reflected beam of Light, which beam sometimes
+fell upon the middle of the Spot, and sometimes by a little inclination
+of the Speculum receded from the middle, and left the Spot white to the
+center.
+
+This white Spot was immediately encompassed with a dark grey or russet,
+and that dark grey with the Colours of the first Iris; which Colours on
+the inside next the dark grey were a little violet and indigo, and next
+to that a blue, which on the outside grew pale, and then succeeded a
+little greenish yellow, and after that a brighter yellow, and then on
+the outward edge of the Iris a red which on the outside inclined to
+purple.
+
+This Iris was immediately encompassed with a second, whose Colours were
+in order from the inside outwards, purple, blue, green, yellow, light
+red, a red mix'd with purple.
+
+Then immediately follow'd the Colours of the third Iris, which were in
+order outwards a green inclining to purple, a good green, and a red more
+bright than that of the former Iris.
+
+The fourth and fifth Iris seem'd of a bluish green within, and red
+without, but so faintly that it was difficult to discern the Colours.
+
+_Obs._ 3. Measuring the Diameters of these Rings upon the Chart as
+accurately as I could, I found them also in the same proportion to one
+another with the Rings made by Light transmitted through the two
+Object-glasses. For the Diameters of the four first of the bright Rings
+measured between the brightest parts of their Orbits, at the distance of
+six Feet from the Speculum were 1-11/16, 2-3/8, 2-11/12, 3-3/8 Inches,
+whose Squares are in arithmetical progression of the numbers 1, 2, 3, 4.
+If the white circular Spot in the middle be reckon'd amongst the Rings,
+and its central Light, where it seems to be most luminous, be put
+equipollent to an infinitely little Ring; the Squares of the Diameters
+of the Rings will be in the progression 0, 1, 2, 3, 4, &c. I measured
+also the Diameters of the dark Circles between these luminous ones, and
+found their Squares in the progression of the numbers 1/2, 1-1/2, 2-1/2,
+3-1/2, &c. the Diameters of the first four at the distance of six Feet
+from the Speculum, being 1-3/16, 2-1/16, 2-2/3, 3-3/20 Inches. If the
+distance of the Chart from the Speculum was increased or diminished, the
+Diameters of the Circles were increased or diminished proportionally.
+
+_Obs._ 4. By the analogy between these Rings and those described in the
+Observations of the first Part of this Book, I suspected that there
+were many more of them which spread into one another, and by interfering
+mix'd their Colours, and diluted one another so that they could not be
+seen apart. I viewed them therefore through a Prism, as I did those in
+the 24th Observation of the first Part of this Book. And when the Prism
+was so placed as by refracting the Light of their mix'd Colours to
+separate them, and distinguish the Rings from one another, as it did
+those in that Observation, I could then see them distincter than before,
+and easily number eight or nine of them, and sometimes twelve or
+thirteen. And had not their Light been so very faint, I question not but
+that I might have seen many more.
+
+_Obs._ 5. Placing a Prism at the Window to refract the intromitted beam
+of Light, and cast the oblong Spectrum of Colours on the Speculum: I
+covered the Speculum with a black Paper which had in the middle of it a
+hole to let any one of the Colours pass through to the Speculum, whilst
+the rest were intercepted by the Paper. And now I found Rings of that
+Colour only which fell upon the Speculum. If the Speculum was
+illuminated with red, the Rings were totally red with dark Intervals, if
+with blue they were totally blue, and so of the other Colours. And when
+they were illuminated with any one Colour, the Squares of their
+Diameters measured between their most luminous Parts, were in the
+arithmetical Progression of the Numbers, 0, 1, 2, 3, 4 and the Squares
+of the Diameters of their dark Intervals in the Progression of the
+intermediate Numbers 1/2, 1-1/2, 2-1/2, 3-1/2. But if the Colour was
+varied, they varied their Magnitude. In the red they were largest, in
+the indigo and violet least, and in the intermediate Colours yellow,
+green, and blue, they were of several intermediate Bignesses answering
+to the Colour, that is, greater in yellow than in green, and greater in
+green than in blue. And hence I knew, that when the Speculum was
+illuminated with white Light, the red and yellow on the outside of the
+Rings were produced by the least refrangible Rays, and the blue and
+violet by the most refrangible, and that the Colours of each Ring spread
+into the Colours of the neighbouring Rings on either side, after the
+manner explain'd in the first and second Part of this Book, and by
+mixing diluted one another so that they could not be distinguish'd,
+unless near the Center where they were least mix'd. For in this
+Observation I could see the Rings more distinctly, and to a greater
+Number than before, being able in the yellow Light to number eight or
+nine of them, besides a faint shadow of a tenth. To satisfy my self how
+much the Colours of the several Rings spread into one another, I
+measured the Diameters of the second and third Rings, and found them
+when made by the Confine of the red and orange to be to the same
+Diameters when made by the Confine of blue and indigo, as 9 to 8, or
+thereabouts. For it was hard to determine this Proportion accurately.
+Also the Circles made successively by the red, yellow, and green,
+differ'd more from one another than those made successively by the
+green, blue, and indigo. For the Circle made by the violet was too dark
+to be seen. To carry on the Computation, let us therefore suppose that
+the Differences of the Diameters of the Circles made by the outmost red,
+the Confine of red and orange, the Confine of orange and yellow, the
+Confine of yellow and green, the Confine of green and blue, the Confine
+of blue and indigo, the Confine of indigo and violet, and outmost
+violet, are in proportion as the Differences of the Lengths of a
+Monochord which sound the Tones in an Eight; _sol_, _la_, _fa_, _sol_,
+_la_, _mi_, _fa_, _sol_, that is, as the Numbers 1/9, 1/18, 1/12, 1/12,
+2/27, 1/27, 1/18. And if the Diameter of the Circle made by the Confine
+of red and orange be 9A, and that of the Circle made by the Confine of
+blue and indigo be 8A as above; their difference 9A-8A will be to the
+difference of the Diameters of the Circles made by the outmost red, and
+by the Confine of red and orange, as 1/18 + 1/12 + 1/12 + 2/27 to 1/9,
+that is as 8/27 to 1/9, or 8 to 3, and to the difference of the Circles
+made by the outmost violet, and by the Confine of blue and indigo, as
+1/18 + 1/12 + 1/12 + 2/27 to 1/27 + 1/18, that is, as 8/27 to 5/54, or
+as 16 to 5. And therefore these differences will be 3/8A and 5/16A. Add
+the first to 9A and subduct the last from 8A, and you will have the
+Diameters of the Circles made by the least and most refrangible Rays
+75/8A and ((61-1/2)/8)A. These diameters are therefore to one another as
+75 to 61-1/2 or 50 to 41, and their Squares as 2500 to 1681, that is, as
+3 to 2 very nearly. Which proportion differs not much from the
+proportion of the Diameters of the Circles made by the outmost red and
+outmost violet, in the 13th Observation of the first part of this Book.
+
+_Obs._ 6. Placing my Eye where these Rings appear'd plainest, I saw the
+Speculum tinged all over with Waves of Colours, (red, yellow, green,
+blue;) like those which in the Observations of the first part of this
+Book appeared between the Object-glasses, and upon Bubbles of Water, but
+much larger. And after the manner of those, they were of various
+magnitudes in various Positions of the Eye, swelling and shrinking as I
+moved my Eye this way and that way. They were formed like Arcs of
+concentrick Circles, as those were; and when my Eye was over against the
+center of the concavity of the Speculum, (that is, 5 Feet and 10 Inches
+distant from the Speculum,) their common center was in a right Line with
+that center of concavity, and with the hole in the Window. But in other
+postures of my Eye their center had other positions. They appear'd by
+the Light of the Clouds propagated to the Speculum through the hole in
+the Window; and when the Sun shone through that hole upon the Speculum,
+his Light upon it was of the Colour of the Ring whereon it fell, but by
+its splendor obscured the Rings made by the Light of the Clouds, unless
+when the Speculum was removed to a great distance from the Window, so
+that his Light upon it might be broad and faint. By varying the position
+of my Eye, and moving it nearer to or farther from the direct beam of
+the Sun's Light, the Colour of the Sun's reflected Light constantly
+varied upon the Speculum, as it did upon my Eye, the same Colour always
+appearing to a Bystander upon my Eye which to me appear'd upon the
+Speculum. And thence I knew that the Rings of Colours upon the Chart
+were made by these reflected Colours, propagated thither from the
+Speculum in several Angles, and that their production depended not upon
+the termination of Light and Shadow.
+
+_Obs._ 7. By the Analogy of all these Phænomena with those of the like
+Rings of Colours described in the first part of this Book, it seemed to
+me that these Colours were produced by this thick Plate of Glass, much
+after the manner that those were produced by very thin Plates. For, upon
+trial, I found that if the Quick-silver were rubb'd off from the
+backside of the Speculum, the Glass alone would cause the same Rings of
+Colours, but much more faint than before; and therefore the Phænomenon
+depends not upon the Quick-silver, unless so far as the Quick-silver by
+increasing the Reflexion of the backside of the Glass increases the
+Light of the Rings of Colours. I found also that a Speculum of Metal
+without Glass made some Years since for optical uses, and very well
+wrought, produced none of those Rings; and thence I understood that
+these Rings arise not from one specular Surface alone, but depend upon
+the two Surfaces of the Plate of Glass whereof the Speculum was made,
+and upon the thickness of the Glass between them. For as in the 7th and
+19th Observations of the first part of this Book a thin Plate of Air,
+Water, or Glass of an even thickness appeared of one Colour when the
+Rays were perpendicular to it, of another when they were a little
+oblique, of another when more oblique, of another when still more
+oblique, and so on; so here, in the sixth Observation, the Light which
+emerged out of the Glass in several Obliquities, made the Glass appear
+of several Colours, and being propagated in those Obliquities to the
+Chart, there painted Rings of those Colours. And as the reason why a
+thin Plate appeared of several Colours in several Obliquities of the
+Rays, was, that the Rays of one and the same sort are reflected by the
+thin Plate at one obliquity and transmitted at another, and those of
+other sorts transmitted where these are reflected, and reflected where
+these are transmitted: So the reason why the thick Plate of Glass
+whereof the Speculum was made did appear of various Colours in various
+Obliquities, and in those Obliquities propagated those Colours to the
+Chart, was, that the Rays of one and the same sort did at one Obliquity
+emerge out of the Glass, at another did not emerge, but were reflected
+back towards the Quick-silver by the hither Surface of the Glass, and
+accordingly as the Obliquity became greater and greater, emerged and
+were reflected alternately for many Successions; and that in one and the
+same Obliquity the Rays of one sort were reflected, and those of another
+transmitted. This is manifest by the fifth Observation of this part of
+this Book. For in that Observation, when the Speculum was illuminated by
+any one of the prismatick Colours, that Light made many Rings of the
+same Colour upon the Chart with dark Intervals, and therefore at its
+emergence out of the Speculum was alternately transmitted and not
+transmitted from the Speculum to the Chart for many Successions,
+according to the various Obliquities of its Emergence. And when the
+Colour cast on the Speculum by the Prism was varied, the Rings became of
+the Colour cast on it, and varied their bigness with their Colour, and
+therefore the Light was now alternately transmitted and not transmitted
+from the Speculum to the Chart at other Obliquities than before. It
+seemed to me therefore that these Rings were of one and the same
+original with those of thin Plates, but yet with this difference, that
+those of thin Plates are made by the alternate Reflexions and
+Transmissions of the Rays at the second Surface of the Plate, after one
+passage through it; but here the Rays go twice through the Plate before
+they are alternately reflected and transmitted. First, they go through
+it from the first Surface to the Quick-silver, and then return through
+it from the Quick-silver to the first Surface, and there are either
+transmitted to the Chart or reflected back to the Quick-silver,
+accordingly as they are in their Fits of easy Reflexion or Transmission
+when they arrive at that Surface. For the Intervals of the Fits of the
+Rays which fall perpendicularly on the Speculum, and are reflected back
+in the same perpendicular Lines, by reason of the equality of these
+Angles and Lines, are of the same length and number within the Glass
+after Reflexion as before, by the 19th Proposition of the third part of
+this Book. And therefore since all the Rays that enter through the
+first Surface are in their Fits of easy Transmission at their entrance,
+and as many of these as are reflected by the second are in their Fits of
+easy Reflexion there, all these must be again in their Fits of easy
+Transmission at their return to the first, and by consequence there go
+out of the Glass to the Chart, and form upon it the white Spot of Light
+in the center of the Rings. For the reason holds good in all sorts of
+Rays, and therefore all sorts must go out promiscuously to that Spot,
+and by their mixture cause it to be white. But the Intervals of the Fits
+of those Rays which are reflected more obliquely than they enter, must
+be greater after Reflexion than before, by the 15th and 20th
+Propositions. And thence it may happen that the Rays at their return to
+the first Surface, may in certain Obliquities be in Fits of easy
+Reflexion, and return back to the Quick-silver, and in other
+intermediate Obliquities be again in Fits of easy Transmission, and so
+go out to the Chart, and paint on it the Rings of Colours about the
+white Spot. And because the Intervals of the Fits at equal obliquities
+are greater and fewer in the less refrangible Rays, and less and more
+numerous in the more refrangible, therefore the less refrangible at
+equal obliquities shall make fewer Rings than the more refrangible, and
+the Rings made by those shall be larger than the like number of Rings
+made by these; that is, the red Rings shall be larger than the yellow,
+the yellow than the green, the green than the blue, and the blue than
+the violet, as they were really found to be in the fifth Observation.
+And therefore the first Ring of all Colours encompassing the white Spot
+of Light shall be red without any violet within, and yellow, and green,
+and blue in the middle, as it was found in the second Observation; and
+these Colours in the second Ring, and those that follow, shall be more
+expanded, till they spread into one another, and blend one another by
+interfering.
+
+These seem to be the reasons of these Rings in general; and this put me
+upon observing the thickness of the Glass, and considering whether the
+dimensions and proportions of the Rings may be truly derived from it by
+computation.
+
+_Obs._ 8. I measured therefore the thickness of this concavo-convex
+Plate of Glass, and found it every where 1/4 of an Inch precisely. Now,
+by the sixth Observation of the first Part of this Book, a thin Plate of
+Air transmits the brightest Light of the first Ring, that is, the bright
+yellow, when its thickness is the 1/89000th part of an Inch; and by the
+tenth Observation of the same Part, a thin Plate of Glass transmits the
+same Light of the same Ring, when its thickness is less in proportion of
+the Sine of Refraction to the Sine of Incidence, that is, when its
+thickness is the 11/1513000th or 1/137545th part of an Inch, supposing
+the Sines are as 11 to 17. And if this thickness be doubled, it
+transmits the same bright Light of the second Ring; if tripled, it
+transmits that of the third, and so on; the bright yellow Light in all
+these cases being in its Fits of Transmission. And therefore if its
+thickness be multiplied 34386 times, so as to become 1/4 of an Inch, it
+transmits the same bright Light of the 34386th Ring. Suppose this be the
+bright yellow Light transmitted perpendicularly from the reflecting
+convex side of the Glass through the concave side to the white Spot in
+the center of the Rings of Colours on the Chart: And by a Rule in the
+7th and 19th Observations in the first Part of this Book, and by the
+15th and 20th Propositions of the third Part of this Book, if the Rays
+be made oblique to the Glass, the thickness of the Glass requisite to
+transmit the same bright Light of the same Ring in any obliquity, is to
+this thickness of 1/4 of an Inch, as the Secant of a certain Angle to
+the Radius, the Sine of which Angle is the first of an hundred and six
+arithmetical Means between the Sines of Incidence and Refraction,
+counted from the Sine of Incidence when the Refraction is made out of
+any plated Body into any Medium encompassing it; that is, in this case,
+out of Glass into Air. Now if the thickness of the Glass be increased by
+degrees, so as to bear to its first thickness, (_viz._ that of a quarter
+of an Inch,) the Proportions which 34386 (the number of Fits of the
+perpendicular Rays in going through the Glass towards the white Spot in
+the center of the Rings,) hath to 34385, 34384, 34383, and 34382, (the
+numbers of the Fits of the oblique Rays in going through the Glass
+towards the first, second, third, and fourth Rings of Colours,) and if
+the first thickness be divided into 100000000 equal parts, the increased
+thicknesses will be 100002908, 100005816, 100008725, and 100011633, and
+the Angles of which these thicknesses are Secants will be 26´ 13´´, 37´
+5´´, 45´ 6´´, and 52´ 26´´, the Radius being 100000000; and the Sines of
+these Angles are 762, 1079, 1321, and 1525, and the proportional Sines
+of Refraction 1172, 1659, 2031, and 2345, the Radius being 100000. For
+since the Sines of Incidence out of Glass into Air are to the Sines of
+Refraction as 11 to 17, and to the above-mentioned Secants as 11 to the
+first of 106 arithmetical Means between 11 and 17, that is, as 11 to
+11-6/106, those Secants will be to the Sines of Refraction as 11-6/106,
+to 17, and by this Analogy will give these Sines. So then, if the
+obliquities of the Rays to the concave Surface of the Glass be such that
+the Sines of their Refraction in passing out of the Glass through that
+Surface into the Air be 1172, 1659, 2031, 2345, the bright Light of the
+34386th Ring shall emerge at the thicknesses of the Glass, which are to
+1/4 of an Inch as 34386 to 34385, 34384, 34383, 34382, respectively. And
+therefore, if the thickness in all these Cases be 1/4 of an Inch (as it
+is in the Glass of which the Speculum was made) the bright Light of the
+34385th Ring shall emerge where the Sine of Refraction is 1172, and that
+of the 34384th, 34383th, and 34382th Ring where the Sine is 1659, 2031,
+and 2345 respectively. And in these Angles of Refraction the Light of
+these Rings shall be propagated from the Speculum to the Chart, and
+there paint Rings about the white central round Spot of Light which we
+said was the Light of the 34386th Ring. And the Semidiameters of these
+Rings shall subtend the Angles of Refraction made at the
+Concave-Surface of the Speculum, and by consequence their Diameters
+shall be to the distance of the Chart from the Speculum as those Sines
+of Refraction doubled are to the Radius, that is, as 1172, 1659, 2031,
+and 2345, doubled are to 100000. And therefore, if the distance of the
+Chart from the Concave-Surface of the Speculum be six Feet (as it was in
+the third of these Observations) the Diameters of the Rings of this
+bright yellow Light upon the Chart shall be 1'688, 2'389, 2'925, 3'375
+Inches: For these Diameters are to six Feet, as the above-mention'd
+Sines doubled are to the Radius. Now, these Diameters of the bright
+yellow Rings, thus found by Computation are the very same with those
+found in the third of these Observations by measuring them, _viz._ with
+1-11/16, 2-3/8, 2-11/12, and 3-3/8 Inches, and therefore the Theory of
+deriving these Rings from the thickness of the Plate of Glass of which
+the Speculum was made, and from the Obliquity of the emerging Rays
+agrees with the Observation. In this Computation I have equalled the
+Diameters of the bright Rings made by Light of all Colours, to the
+Diameters of the Rings made by the bright yellow. For this yellow makes
+the brightest Part of the Rings of all Colours. If you desire the
+Diameters of the Rings made by the Light of any other unmix'd Colour,
+you may find them readily by putting them to the Diameters of the bright
+yellow ones in a subduplicate Proportion of the Intervals of the Fits of
+the Rays of those Colours when equally inclined to the refracting or
+reflecting Surface which caused those Fits, that is, by putting the
+Diameters of the Rings made by the Rays in the Extremities and Limits of
+the seven Colours, red, orange, yellow, green, blue, indigo, violet,
+proportional to the Cube-roots of the Numbers, 1, 8/9, 5/6, 3/4, 2/3,
+3/5, 9/16, 1/2, which express the Lengths of a Monochord sounding the
+Notes in an Eighth: For by this means the Diameters of the Rings of
+these Colours will be found pretty nearly in the same Proportion to one
+another, which they ought to have by the fifth of these Observations.
+
+And thus I satisfy'd my self, that these Rings were of the same kind and
+Original with those of thin Plates, and by consequence that the Fits or
+alternate Dispositions of the Rays to be reflected and transmitted are
+propagated to great distances from every reflecting and refracting
+Surface. But yet to put the matter out of doubt, I added the following
+Observation.
+
+_Obs._ 9. If these Rings thus depend on the thickness of the Plate of
+Glass, their Diameters at equal distances from several Speculums made of
+such concavo-convex Plates of Glass as are ground on the same Sphere,
+ought to be reciprocally in a subduplicate Proportion of the thicknesses
+of the Plates of Glass. And if this Proportion be found true by
+experience it will amount to a demonstration that these Rings (like
+those formed in thin Plates) do depend on the thickness of the Glass. I
+procured therefore another concavo-convex Plate of Glass ground on both
+sides to the same Sphere with the former Plate. Its thickness was 5/62
+Parts of an Inch; and the Diameters of the three first bright Rings
+measured between the brightest Parts of their Orbits at the distance of
+six Feet from the Glass were 3·4-1/6·5-1/8· Inches. Now, the thickness
+of the other Glass being 1/4 of an Inch was to the thickness of this
+Glass as 1/4 to 5/62, that is as 31 to 10, or 310000000 to 100000000,
+and the Roots of these Numbers are 17607 and 10000, and in the
+Proportion of the first of these Roots to the second are the Diameters
+of the bright Rings made in this Observation by the thinner Glass,
+3·4-1/6·5-1/8, to the Diameters of the same Rings made in the third of
+these Observations by the thicker Glass 1-11/16, 2-3/8. 2-11/12, that
+is, the Diameters of the Rings are reciprocally in a subduplicate
+Proportion of the thicknesses of the Plates of Glass.
+
+So then in Plates of Glass which are alike concave on one side, and
+alike convex on the other side, and alike quick-silver'd on the convex
+sides, and differ in nothing but their thickness, the Diameters of the
+Rings are reciprocally in a subduplicate Proportion of the thicknesses
+of the Plates. And this shews sufficiently that the Rings depend on both
+the Surfaces of the Glass. They depend on the convex Surface, because
+they are more luminous when that Surface is quick-silver'd over than
+when it is without Quick-silver. They depend also upon the concave
+Surface, because without that Surface a Speculum makes them not. They
+depend on both Surfaces, and on the distances between them, because
+their bigness is varied by varying only that distance. And this
+dependence is of the same kind with that which the Colours of thin
+Plates have on the distance of the Surfaces of those Plates, because the
+bigness of the Rings, and their Proportion to one another, and the
+variation of their bigness arising from the variation of the thickness
+of the Glass, and the Orders of their Colours, is such as ought to
+result from the Propositions in the end of the third Part of this Book,
+derived from the Phænomena of the Colours of thin Plates set down in the
+first Part.
+
+There are yet other Phænomena of these Rings of Colours, but such as
+follow from the same Propositions, and therefore confirm both the Truth
+of those Propositions, and the Analogy between these Rings and the Rings
+of Colours made by very thin Plates. I shall subjoin some of them.
+
+_Obs._ 10. When the beam of the Sun's Light was reflected back from the
+Speculum not directly to the hole in the Window, but to a place a little
+distant from it, the common center of that Spot, and of all the Rings of
+Colours fell in the middle way between the beam of the incident Light,
+and the beam of the reflected Light, and by consequence in the center of
+the spherical concavity of the Speculum, whenever the Chart on which the
+Rings of Colours fell was placed at that center. And as the beam of
+reflected Light by inclining the Speculum receded more and more from the
+beam of incident Light and from the common center of the colour'd Rings
+between them, those Rings grew bigger and bigger, and so also did the
+white round Spot, and new Rings of Colours emerged successively out of
+their common center, and the white Spot became a white Ring
+encompassing them; and the incident and reflected beams of Light always
+fell upon the opposite parts of this white Ring, illuminating its
+Perimeter like two mock Suns in the opposite parts of an Iris. So then
+the Diameter of this Ring, measured from the middle of its Light on one
+side to the middle of its Light on the other side, was always equal to
+the distance between the middle of the incident beam of Light, and the
+middle of the reflected beam measured at the Chart on which the Rings
+appeared: And the Rays which form'd this Ring were reflected by the
+Speculum in Angles equal to their Angles of Incidence, and by
+consequence to their Angles of Refraction at their entrance into the
+Glass, but yet their Angles of Reflexion were not in the same Planes
+with their Angles of Incidence.
+
+_Obs._ 11. The Colours of the new Rings were in a contrary order to
+those of the former, and arose after this manner. The white round Spot
+of Light in the middle of the Rings continued white to the center till
+the distance of the incident and reflected beams at the Chart was about
+7/8 parts of an Inch, and then it began to grow dark in the middle. And
+when that distance was about 1-3/16 of an Inch, the white Spot was
+become a Ring encompassing a dark round Spot which in the middle
+inclined to violet and indigo. And the luminous Rings encompassing it
+were grown equal to those dark ones which in the four first Observations
+encompassed them, that is to say, the white Spot was grown a white Ring
+equal to the first of those dark Rings, and the first of those luminous
+Rings was now grown equal to the second of those dark ones, and the
+second of those luminous ones to the third of those dark ones, and so
+on. For the Diameters of the luminous Rings were now 1-3/16, 2-1/16,
+2-2/3, 3-3/20, &c. Inches.
+
+When the distance between the incident and reflected beams of Light
+became a little bigger, there emerged out of the middle of the dark Spot
+after the indigo a blue, and then out of that blue a pale green, and
+soon after a yellow and red. And when the Colour at the center was
+brightest, being between yellow and red, the bright Rings were grown
+equal to those Rings which in the four first Observations next
+encompassed them; that is to say, the white Spot in the middle of those
+Rings was now become a white Ring equal to the first of those bright
+Rings, and the first of those bright ones was now become equal to the
+second of those, and so on. For the Diameters of the white Ring, and of
+the other luminous Rings encompassing it, were now 1-11/16, 2-3/8,
+2-11/12, 3-3/8, &c. or thereabouts.
+
+When the distance of the two beams of Light at the Chart was a little
+more increased, there emerged out of the middle in order after the red,
+a purple, a blue, a green, a yellow, and a red inclining much to purple,
+and when the Colour was brightest being between yellow and red, the
+former indigo, blue, green, yellow and red, were become an Iris or Ring
+of Colours equal to the first of those luminous Rings which appeared in
+the four first Observations, and the white Ring which was now become
+the second of the luminous Rings was grown equal to the second of those,
+and the first of those which was now become the third Ring was become
+equal to the third of those, and so on. For their Diameters were
+1-11/16, 2-3/8, 2-11/12, 3-3/8 Inches, the distance of the two beams of
+Light, and the Diameter of the white Ring being 2-3/8 Inches.
+
+When these two beams became more distant there emerged out of the middle
+of the purplish red, first a darker round Spot, and then out of the
+middle of that Spot a brighter. And now the former Colours (purple,
+blue, green, yellow, and purplish red) were become a Ring equal to the
+first of the bright Rings mentioned in the four first Observations, and
+the Rings about this Ring were grown equal to the Rings about that
+respectively; the distance between the two beams of Light and the
+Diameter of the white Ring (which was now become the third Ring) being
+about 3 Inches.
+
+The Colours of the Rings in the middle began now to grow very dilute,
+and if the distance between the two Beams was increased half an Inch, or
+an Inch more, they vanish'd whilst the white Ring, with one or two of
+the Rings next it on either side, continued still visible. But if the
+distance of the two beams of Light was still more increased, these also
+vanished: For the Light which coming from several parts of the hole in
+the Window fell upon the Speculum in several Angles of Incidence, made
+Rings of several bignesses, which diluted and blotted out one another,
+as I knew by intercepting some part of that Light. For if I intercepted
+that part which was nearest to the Axis of the Speculum the Rings would
+be less, if the other part which was remotest from it they would be
+bigger.
+
+_Obs._ 12. When the Colours of the Prism were cast successively on the
+Speculum, that Ring which in the two last Observations was white, was of
+the same bigness in all the Colours, but the Rings without it were
+greater in the green than in the blue, and still greater in the yellow,
+and greatest in the red. And, on the contrary, the Rings within that
+white Circle were less in the green than in the blue, and still less in
+the yellow, and least in the red. For the Angles of Reflexion of those
+Rays which made this Ring, being equal to their Angles of Incidence, the
+Fits of every reflected Ray within the Glass after Reflexion are equal
+in length and number to the Fits of the same Ray within the Glass before
+its Incidence on the reflecting Surface. And therefore since all the
+Rays of all sorts at their entrance into the Glass were in a Fit of
+Transmission, they were also in a Fit of Transmission at their returning
+to the same Surface after Reflexion; and by consequence were
+transmitted, and went out to the white Ring on the Chart. This is the
+reason why that Ring was of the same bigness in all the Colours, and why
+in a mixture of all it appears white. But in Rays which are reflected in
+other Angles, the Intervals of the Fits of the least refrangible being
+greatest, make the Rings of their Colour in their progress from this
+white Ring, either outwards or inwards, increase or decrease by the
+greatest steps; so that the Rings of this Colour without are greatest,
+and within least. And this is the reason why in the last Observation,
+when the Speculum was illuminated with white Light, the exterior Rings
+made by all Colours appeared red without and blue within, and the
+interior blue without and red within.
+
+These are the Phænomena of thick convexo-concave Plates of Glass, which
+are every where of the same thickness. There are yet other Phænomena
+when these Plates are a little thicker on one side than on the other,
+and others when the Plates are more or less concave than convex, or
+plano-convex, or double-convex. For in all these cases the Plates make
+Rings of Colours, but after various manners; all which, so far as I have
+yet observed, follow from the Propositions in the end of the third part
+of this Book, and so conspire to confirm the truth of those
+Propositions. But the Phænomena are too various, and the Calculations
+whereby they follow from those Propositions too intricate to be here
+prosecuted. I content my self with having prosecuted this kind of
+Phænomena so far as to discover their Cause, and by discovering it to
+ratify the Propositions in the third Part of this Book.
+
+_Obs._ 13. As Light reflected by a Lens quick-silver'd on the backside
+makes the Rings of Colours above described, so it ought to make the like
+Rings of Colours in passing through a drop of Water. At the first
+Reflexion of the Rays within the drop, some Colours ought to be
+transmitted, as in the case of a Lens, and others to be reflected back
+to the Eye. For instance, if the Diameter of a small drop or globule of
+Water be about the 500th part of an Inch, so that a red-making Ray in
+passing through the middle of this globule has 250 Fits of easy
+Transmission within the globule, and that all the red-making Rays which
+are at a certain distance from this middle Ray round about it have 249
+Fits within the globule, and all the like Rays at a certain farther
+distance round about it have 248 Fits, and all those at a certain
+farther distance 247 Fits, and so on; these concentrick Circles of Rays
+after their transmission, falling on a white Paper, will make
+concentrick Rings of red upon the Paper, supposing the Light which
+passes through one single globule, strong enough to be sensible. And, in
+like manner, the Rays of other Colours will make Rings of other Colours.
+Suppose now that in a fair Day the Sun shines through a thin Cloud of
+such globules of Water or Hail, and that the globules are all of the
+same bigness; and the Sun seen through this Cloud shall appear
+encompassed with the like concentrick Rings of Colours, and the Diameter
+of the first Ring of red shall be 7-1/4 Degrees, that of the second
+10-1/4 Degrees, that of the third 12 Degrees 33 Minutes. And accordingly
+as the Globules of Water are bigger or less, the Rings shall be less or
+bigger. This is the Theory, and Experience answers it. For in _June_
+1692, I saw by reflexion in a Vessel of stagnating Water three Halos,
+Crowns, or Rings of Colours about the Sun, like three little Rain-bows,
+concentrick to his Body. The Colours of the first or innermost Crown
+were blue next the Sun, red without, and white in the middle between the
+blue and red. Those of the second Crown were purple and blue within, and
+pale red without, and green in the middle. And those of the third were
+pale blue within, and pale red without; these Crowns enclosed one
+another immediately, so that their Colours proceeded in this continual
+order from the Sun outward: blue, white, red; purple, blue, green, pale
+yellow and red; pale blue, pale red. The Diameter of the second Crown
+measured from the middle of the yellow and red on one side of the Sun,
+to the middle of the same Colour on the other side was 9-1/3 Degrees, or
+thereabouts. The Diameters of the first and third I had not time to
+measure, but that of the first seemed to be about five or six Degrees,
+and that of the third about twelve. The like Crowns appear sometimes
+about the Moon; for in the beginning of the Year 1664, _Febr._ 19th at
+Night, I saw two such Crowns about her. The Diameter of the first or
+innermost was about three Degrees, and that of the second about five
+Degrees and an half. Next about the Moon was a Circle of white, and next
+about that the inner Crown, which was of a bluish green within next the
+white, and of a yellow and red without, and next about these Colours
+were blue and green on the inside of the outward Crown, and red on the
+outside of it. At the same time there appear'd a Halo about 22 Degrees
+35´ distant from the center of the Moon. It was elliptical, and its long
+Diameter was perpendicular to the Horizon, verging below farthest from
+the Moon. I am told that the Moon has sometimes three or more
+concentrick Crowns of Colours encompassing one another next about her
+Body. The more equal the globules of Water or Ice are to one another,
+the more Crowns of Colours will appear, and the Colours will be the more
+lively. The Halo at the distance of 22-1/2 Degrees from the Moon is of
+another sort. By its being oval and remoter from the Moon below than
+above, I conclude, that it was made by Refraction in some sort of Hail
+or Snow floating in the Air in an horizontal posture, the refracting
+Angle being about 58 or 60 Degrees.
+
+
+
+
+THE
+
+THIRD BOOK
+
+OF
+
+OPTICKS
+
+
+_PART I._
+
+_Observations concerning the Inflexions of the Rays of Light, and the
+Colours made thereby._
+
+Grimaldo has inform'd us, that if a beam of the Sun's Light be let into
+a dark Room through a very small hole, the Shadows of things in this
+Light will be larger than they ought to be if the Rays went on by the
+Bodies in straight Lines, and that these Shadows have three parallel
+Fringes, Bands or Ranks of colour'd Light adjacent to them. But if the
+Hole be enlarged the Fringes grow broad and run into one another, so
+that they cannot be distinguish'd. These broad Shadows and Fringes have
+been reckon'd by some to proceed from the ordinary refraction of the
+Air, but without due examination of the Matter. For the circumstances of
+the Phænomenon, so far as I have observed them, are as follows.
+
+_Obs._ 1. I made in a piece of Lead a small Hole with a Pin, whose
+breadth was the 42d part of an Inch. For 21 of those Pins laid together
+took up the breadth of half an Inch. Through this Hole I let into my
+darken'd Chamber a beam of the Sun's Light, and found that the Shadows
+of Hairs, Thred, Pins, Straws, and such like slender Substances placed
+in this beam of Light, were considerably broader than they ought to be,
+if the Rays of Light passed on by these Bodies in right Lines. And
+particularly a Hair of a Man's Head, whose breadth was but the 280th
+part of an Inch, being held in this Light, at the distance of about
+twelve Feet from the Hole, did cast a Shadow which at the distance of
+four Inches from the Hair was the sixtieth part of an Inch broad, that
+is, above four times broader than the Hair, and at the distance of two
+Feet from the Hair was about the eight and twentieth part of an Inch
+broad, that is, ten times broader than the Hair, and at the distance of
+ten Feet was the eighth part of an Inch broad, that is 35 times broader.
+
+Nor is it material whether the Hair be encompassed with Air, or with any
+other pellucid Substance. For I wetted a polish'd Plate of Glass, and
+laid the Hair in the Water upon the Glass, and then laying another
+polish'd Plate of Glass upon it, so that the Water might fill up the
+space between the Glasses, I held them in the aforesaid beam of Light,
+so that the Light might pass through them perpendicularly, and the
+Shadow of the Hair was at the same distances as big as before. The
+Shadows of Scratches made in polish'd Plates of Glass were also much
+broader than they ought to be, and the Veins in polish'd Plates of Glass
+did also cast the like broad Shadows. And therefore the great breadth of
+these Shadows proceeds from some other cause than the Refraction of the
+Air.
+
+Let the Circle X [in _Fig._ 1.] represent the middle of the Hair; ADG,
+BEH, CFI, three Rays passing by one side of the Hair at several
+distances; KNQ, LOR, MPS, three other Rays passing by the other side of
+the Hair at the like distances; D, E, F, and N, O, P, the places where
+the Rays are bent in their passage by the Hair; G, H, I, and Q, R, S,
+the places where the Rays fall on a Paper GQ; IS the breadth of the
+Shadow of the Hair cast on the Paper, and TI, VS, two Rays passing to
+the Points I and S without bending when the Hair is taken away. And it's
+manifest that all the Light between these two Rays TI and VS is bent in
+passing by the Hair, and turned aside from the Shadow IS, because if any
+part of this Light were not bent it would fall on the Paper within the
+Shadow, and there illuminate the Paper, contrary to experience. And
+because when the Paper is at a great distance from the Hair, the Shadow
+is broad, and therefore the Rays TI and VS are at a great distance from
+one another, it follows that the Hair acts upon the Rays of Light at a
+good distance in their passing by it. But the Action is strongest on the
+Rays which pass by at least distances, and grows weaker and weaker
+accordingly as the Rays pass by at distances greater and greater, as is
+represented in the Scheme: For thence it comes to pass, that the Shadow
+of the Hair is much broader in proportion to the distance of the Paper
+from the Hair, when the Paper is nearer the Hair, than when it is at a
+great distance from it.
+
+_Obs._ 2. The Shadows of all Bodies (Metals, Stones, Glass, Wood, Horn,
+Ice, &c.) in this Light were border'd with three Parallel Fringes or
+Bands of colour'd Light, whereof that which was contiguous to the Shadow
+was broadest and most luminous, and that which was remotest from it was
+narrowest, and so faint, as not easily to be visible. It was difficult
+to distinguish the Colours, unless when the Light fell very obliquely
+upon a smooth Paper, or some other smooth white Body, so as to make them
+appear much broader than they would otherwise do. And then the Colours
+were plainly visible in this Order: The first or innermost Fringe was
+violet and deep blue next the Shadow, and then light blue, green, and
+yellow in the middle, and red without. The second Fringe was almost
+contiguous to the first, and the third to the second, and both were blue
+within, and yellow and red without, but their Colours were very faint,
+especially those of the third. The Colours therefore proceeded in this
+order from the Shadow; violet, indigo, pale blue, green, yellow, red;
+blue, yellow, red; pale blue, pale yellow and red. The Shadows made by
+Scratches and Bubbles in polish'd Plates of Glass were border'd with the
+like Fringes of colour'd Light. And if Plates of Looking-glass sloop'd
+off near the edges with a Diamond-cut, be held in the same beam of
+Light, the Light which passes through the parallel Planes of the Glass
+will be border'd with the like Fringes of Colours where those Planes
+meet with the Diamond-cut, and by this means there will sometimes appear
+four or five Fringes of Colours. Let AB, CD [in _Fig._ 2.] represent the
+parallel Planes of a Looking-glass, and BD the Plane of the Diamond-cut,
+making at B a very obtuse Angle with the Plane AB. And let all the Light
+between the Rays ENI and FBM pass directly through the parallel Planes
+of the Glass, and fall upon the Paper between I and M, and all the Light
+between the Rays GO and HD be refracted by the oblique Plane of the
+Diamond-cut BD, and fall upon the Paper between K and L; and the Light
+which passes directly through the parallel Planes of the Glass, and
+falls upon the Paper between I and M, will be border'd with three or
+more Fringes at M.
+
+[Illustration: FIG. 1.]
+
+[Illustration: FIG. 2.]
+
+So by looking on the Sun through a Feather or black Ribband held close
+to the Eye, several Rain-bows will appear; the Shadows which the Fibres
+or Threds cast on the _Tunica Retina_, being border'd with the like
+Fringes of Colours.
+
+_Obs._ 3. When the Hair was twelve Feet distant from this Hole, and its
+Shadow fell obliquely upon a flat white Scale of Inches and Parts of an
+Inch placed half a Foot beyond it, and also when the Shadow fell
+perpendicularly upon the same Scale placed nine Feet beyond it; I
+measured the breadth of the Shadow and Fringes as accurately as I could,
+and found them in Parts of an Inch as follows.
+
+-------------------------------------------+-----------+--------
+ | half a | Nine
+ At the Distance of | Foot | Feet
+-------------------------------------------+-----------+--------
+The breadth of the Shadow | 1/54 | 1/9
+-------------------------------------------+-----------+--------
+The breadth between the Middles of the | 1/38 |
+ brightest Light of the innermost Fringes | or |
+ on either side the Shadow | 1/39 | 7/50
+-------------------------------------------+-----------+--------
+The breadth between the Middles of the | |
+ brightest Light of the middlemost Fringes| |
+ on either side the Shadow | 1/23-1/2 | 4/17
+-------------------------------------------+-----------+--------
+The breadth between the Middles of the | 1/18 |
+ brightest Light of the outmost Fringes | or |
+ on either side the Shadow | 1/18-1/2 | 3/10
+-------------------------------------------+-----------+--------
+The distance between the Middles of the | |
+ brightest Light of the first and second | |
+ Fringes | 1/120 | 1/21
+-------------------------------------------+-----------+--------
+The distance between the Middles of the | |
+ brightest Light of the second and third | |
+ Fringes | 1/170 | 1/31
+-------------------------------------------+-----------+--------
+The breadth of the luminous Part (green, | |
+ white, yellow, and red) of the first | |
+ Fringe | 1/170 | 1/32
+-------------------------------------------+-----------+--------
+The breadth of the darker Space between | |
+ the first and second Fringes | 1/240 | 1/45
+-------------------------------------------+-----------+--------
+The breadth of the luminous Part of the | |
+ second Fringe | 1/290 | 1/55
+-------------------------------------------+-----------+--------
+The breadth of the darker Space between | |
+ the second and third Fringes | 1/340 | 1/63
+-------------------------------------------+-----------+--------
+
+These Measures I took by letting the Shadow of the Hair, at half a Foot
+distance, fall so obliquely on the Scale, as to appear twelve times
+broader than when it fell perpendicularly on it at the same distance,
+and setting down in this Table the twelfth part of the Measures I then
+took.
+
+_Obs._ 4. When the Shadow and Fringes were cast obliquely upon a smooth
+white Body, and that Body was removed farther and farther from the Hair,
+the first Fringe began to appear and look brighter than the rest of the
+Light at the distance of less than a quarter of an Inch from the Hair,
+and the dark Line or Shadow between that and the second Fringe began to
+appear at a less distance from the Hair than that of the third part of
+an Inch. The second Fringe began to appear at a distance from the Hair
+of less than half an Inch, and the Shadow between that and the third
+Fringe at a distance less than an inch, and the third Fringe at a
+distance less than three Inches. At greater distances they became much
+more sensible, but kept very nearly the same proportion of their
+breadths and intervals which they had at their first appearing. For the
+distance between the middle of the first, and middle of the second
+Fringe, was to the distance between the middle of the second and middle
+of the third Fringe, as three to two, or ten to seven. And the last of
+these two distances was equal to the breadth of the bright Light or
+luminous part of the first Fringe. And this breadth was to the breadth
+of the bright Light of the second Fringe as seven to four, and to the
+dark Interval of the first and second Fringe as three to two, and to
+the like dark Interval between the second and third as two to one. For
+the breadths of the Fringes seem'd to be in the progression of the
+Numbers 1, sqrt(1/3), sqrt(1/5), and their Intervals to be in the
+same progression with them; that is, the Fringes and their Intervals
+together to be in the continual progression of the Numbers 1,
+sqrt(1/2), sqrt(1/3), sqrt(1/4), sqrt(1/5), or thereabouts. And
+these Proportions held the same very nearly at all distances from the
+Hair; the dark Intervals of the Fringes being as broad in proportion to
+the breadth of the Fringes at their first appearance as afterwards at
+great distances from the Hair, though not so dark and distinct.
+
+_Obs._ 5. The Sun shining into my darken'd Chamber through a hole a
+quarter of an Inch broad, I placed at the distance of two or three Feet
+from the Hole a Sheet of Pasteboard, which was black'd all over on both
+sides, and in the middle of it had a hole about three quarters of an
+Inch square for the Light to pass through. And behind the hole I
+fasten'd to the Pasteboard with Pitch the blade of a sharp Knife, to
+intercept some part of the Light which passed through the hole. The
+Planes of the Pasteboard and blade of the Knife were parallel to one
+another, and perpendicular to the Rays. And when they were so placed
+that none of the Sun's Light fell on the Pasteboard, but all of it
+passed through the hole to the Knife, and there part of it fell upon the
+blade of the Knife, and part of it passed by its edge; I let this part
+of the Light which passed by, fall on a white Paper two or three Feet
+beyond the Knife, and there saw two streams of faint Light shoot out
+both ways from the beam of Light into the shadow, like the Tails of
+Comets. But because the Sun's direct Light by its brightness upon the
+Paper obscured these faint streams, so that I could scarce see them, I
+made a little hole in the midst of the Paper for that Light to pass
+through and fall on a black Cloth behind it; and then I saw the two
+streams plainly. They were like one another, and pretty nearly equal in
+length, and breadth, and quantity of Light. Their Light at that end next
+the Sun's direct Light was pretty strong for the space of about a
+quarter of an Inch, or half an Inch, and in all its progress from that
+direct Light decreased gradually till it became insensible. The whole
+length of either of these streams measured upon the paper at the
+distance of three Feet from the Knife was about six or eight Inches; so
+that it subtended an Angle at the edge of the Knife of about 10 or 12,
+or at most 14 Degrees. Yet sometimes I thought I saw it shoot three or
+four Degrees farther, but with a Light so very faint that I could scarce
+perceive it, and suspected it might (in some measure at least) arise
+from some other cause than the two streams did. For placing my Eye in
+that Light beyond the end of that stream which was behind the Knife, and
+looking towards the Knife, I could see a line of Light upon its edge,
+and that not only when my Eye was in the line of the Streams, but also
+when it was without that line either towards the point of the Knife, or
+towards the handle. This line of Light appear'd contiguous to the edge
+of the Knife, and was narrower than the Light of the innermost Fringe,
+and narrowest when my Eye was farthest from the direct Light, and
+therefore seem'd to pass between the Light of that Fringe and the edge
+of the Knife, and that which passed nearest the edge to be most bent,
+though not all of it.
+
+_Obs._ 6. I placed another Knife by this, so that their edges might be
+parallel, and look towards one another, and that the beam of Light might
+fall upon both the Knives, and some part of it pass between their edges.
+And when the distance of their edges was about the 400th part of an
+Inch, the stream parted in the middle, and left a Shadow between the two
+parts. This Shadow was so black and dark that all the Light which passed
+between the Knives seem'd to be bent, and turn'd aside to the one hand
+or to the other. And as the Knives still approach'd one another the
+Shadow grew broader, and the streams shorter at their inward ends which
+were next the Shadow, until upon the contact of the Knives the whole
+Light vanish'd, leaving its place to the Shadow.
+
+And hence I gather that the Light which is least bent, and goes to the
+inward ends of the streams, passes by the edges of the Knives at the
+greatest distance, and this distance when the Shadow begins to appear
+between the streams, is about the 800th part of an Inch. And the Light
+which passes by the edges of the Knives at distances still less and
+less, is more and more bent, and goes to those parts of the streams
+which are farther and farther from the direct Light; because when the
+Knives approach one another till they touch, those parts of the streams
+vanish last which are farthest from the direct Light.
+
+_Obs._ 7. In the fifth Observation the Fringes did not appear, but by
+reason of the breadth of the hole in the Window became so broad as to
+run into one another, and by joining, to make one continued Light in the
+beginning of the streams. But in the sixth, as the Knives approached one
+another, a little before the Shadow appeared between the two streams,
+the Fringes began to appear on the inner ends of the Streams on either
+side of the direct Light; three on one side made by the edge of one
+Knife, and three on the other side made by the edge of the other Knife.
+They were distinctest when the Knives were placed at the greatest
+distance from the hole in the Window, and still became more distinct by
+making the hole less, insomuch that I could sometimes see a faint
+lineament of a fourth Fringe beyond the three above mention'd. And as
+the Knives continually approach'd one another, the Fringes grew
+distincter and larger, until they vanish'd. The outmost Fringe vanish'd
+first, and the middlemost next, and the innermost last. And after they
+were all vanish'd, and the line of Light which was in the middle between
+them was grown very broad, enlarging it self on both sides into the
+streams of Light described in the fifth Observation, the above-mention'd
+Shadow began to appear in the middle of this line, and divide it along
+the middle into two lines of Light, and increased until the whole Light
+vanish'd. This enlargement of the Fringes was so great that the Rays
+which go to the innermost Fringe seem'd to be bent above twenty times
+more when this Fringe was ready to vanish, than when one of the Knives
+was taken away.
+
+And from this and the former Observation compared, I gather, that the
+Light of the first Fringe passed by the edge of the Knife at a distance
+greater than the 800th part of an Inch, and the Light of the second
+Fringe passed by the edge of the Knife at a greater distance than the
+Light of the first Fringe did, and that of the third at a greater
+distance than that of the second, and that of the streams of Light
+described in the fifth and sixth Observations passed by the edges of the
+Knives at less distances than that of any of the Fringes.
+
+_Obs._ 8. I caused the edges of two Knives to be ground truly strait,
+and pricking their points into a Board so that their edges might look
+towards one another, and meeting near their points contain a rectilinear
+Angle, I fasten'd their Handles together with Pitch to make this Angle
+invariable. The distance of the edges of the Knives from one another at
+the distance of four Inches from the angular Point, where the edges of
+the Knives met, was the eighth part of an Inch; and therefore the Angle
+contain'd by the edges was about one Degree 54: The Knives thus fix'd
+together I placed in a beam of the Sun's Light, let into my darken'd
+Chamber through a Hole the 42d Part of an Inch wide, at the distance of
+10 or 15 Feet from the Hole, and let the Light which passed between
+their edges fall very obliquely upon a smooth white Ruler at the
+distance of half an Inch, or an Inch from the Knives, and there saw the
+Fringes by the two edges of the Knives run along the edges of the
+Shadows of the Knives in Lines parallel to those edges without growing
+sensibly broader, till they met in Angles equal to the Angle contained
+by the edges of the Knives, and where they met and joined they ended
+without crossing one another. But if the Ruler was held at a much
+greater distance from the Knives, the Fringes where they were farther
+from the Place of their Meeting, were a little narrower, and became
+something broader and broader as they approach'd nearer and nearer to
+one another, and after they met they cross'd one another, and then
+became much broader than before.
+
+Whence I gather that the distances at which the Fringes pass by the
+Knives are not increased nor alter'd by the approach of the Knives, but
+the Angles in which the Rays are there bent are much increased by that
+approach; and that the Knife which is nearest any Ray determines which
+way the Ray shall be bent, and the other Knife increases the bent.
+
+_Obs._ 9. When the Rays fell very obliquely upon the Ruler at the
+distance of the third Part of an Inch from the Knives, the dark Line
+between the first and second Fringe of the Shadow of one Knife, and the
+dark Line between the first and second Fringe of the Shadow of the other
+knife met with one another, at the distance of the fifth Part of an Inch
+from the end of the Light which passed between the Knives at the
+concourse of their edges. And therefore the distance of the edges of the
+Knives at the meeting of these dark Lines was the 160th Part of an Inch.
+For as four Inches to the eighth Part of an Inch, so is any Length of
+the edges of the Knives measured from the point of their concourse to
+the distance of the edges of the Knives at the end of that Length, and
+so is the fifth Part of an Inch to the 160th Part. So then the dark
+Lines above-mention'd meet in the middle of the Light which passes
+between the Knives where they are distant the 160th Part of an Inch, and
+the one half of that Light passes by the edge of one Knife at a distance
+not greater than the 320th Part of an Inch, and falling upon the Paper
+makes the Fringes of the Shadow of that Knife, and the other half passes
+by the edge of the other Knife, at a distance not greater than the 320th
+Part of an Inch, and falling upon the Paper makes the Fringes of the
+Shadow of the other Knife. But if the Paper be held at a distance from
+the Knives greater than the third Part of an Inch, the dark Lines
+above-mention'd meet at a greater distance than the fifth Part of an
+Inch from the end of the Light which passed between the Knives at the
+concourse of their edges; and therefore the Light which falls upon the
+Paper where those dark Lines meet passes between the Knives where the
+edges are distant above the 160th part of an Inch.
+
+For at another time, when the two Knives were distant eight Feet and
+five Inches from the little hole in the Window, made with a small Pin as
+above, the Light which fell upon the Paper where the aforesaid dark
+lines met, passed between the Knives, where the distance between their
+edges was as in the following Table, when the distance of the Paper from
+the Knives was also as follows.
+
+-----------------------------+------------------------------
+ | Distances between the edges
+ Distances of the Paper | of the Knives in millesimal
+ from the Knives in Inches. | parts of an Inch.
+-----------------------------+------------------------------
+ 1-1/2. | 0'012
+ 3-1/3. | 0'020
+ 8-3/5. | 0'034
+ 32. | 0'057
+ 96. | 0'081
+ 131. | 0'087
+_____________________________|______________________________
+
+And hence I gather, that the Light which makes the Fringes upon the
+Paper is not the same Light at all distances of the Paper from the
+Knives, but when the Paper is held near the Knives, the Fringes are made
+by Light which passes by the edges of the Knives at a less distance, and
+is more bent than when the Paper is held at a greater distance from the
+Knives.
+
+[Illustration: FIG. 3.]
+
+_Obs._ 10. When the Fringes of the Shadows of the Knives fell
+perpendicularly upon a Paper at a great distance from the Knives, they
+were in the form of Hyperbola's, and their Dimensions were as follows.
+Let CA, CB [in _Fig._ 3.] represent Lines drawn upon the Paper parallel
+to the edges of the Knives, and between which all the Light would fall,
+if it passed between the edges of the Knives without inflexion; DE a
+Right Line drawn through C making the Angles ACD, BCE, equal to one
+another, and terminating all the Light which falls upon the Paper from
+the point where the edges of the Knives meet; _eis_, _fkt_, and _glv_,
+three hyperbolical Lines representing the Terminus of the Shadow of one
+of the Knives, the dark Line between the first and second Fringes of
+that Shadow, and the dark Line between the second and third Fringes of
+the same Shadow; _xip_, _ykq_, and _zlr_, three other hyperbolical Lines
+representing the Terminus of the Shadow of the other Knife, the dark
+Line between the first and second Fringes of that Shadow, and the dark
+line between the second and third Fringes of the same Shadow. And
+conceive that these three Hyperbola's are like and equal to the former
+three, and cross them in the points _i_, _k_, and _l_, and that the
+Shadows of the Knives are terminated and distinguish'd from the first
+luminous Fringes by the lines _eis_ and _xip_, until the meeting and
+crossing of the Fringes, and then those lines cross the Fringes in the
+form of dark lines, terminating the first luminous Fringes within side,
+and distinguishing them from another Light which begins to appear at
+_i_, and illuminates all the triangular space _ip_DE_s_ comprehended by
+these dark lines, and the right line DE. Of these Hyperbola's one
+Asymptote is the line DE, and their other Asymptotes are parallel to the
+lines CA and CB. Let _rv_ represent a line drawn any where upon the
+Paper parallel to the Asymptote DE, and let this line cross the right
+lines AC in _m_, and BC in _n_, and the six dark hyperbolical lines in
+_p_, _q_, _r_; _s_, _t_, _v_; and by measuring the distances _ps_, _qt_,
+_rv_, and thence collecting the lengths of the Ordinates _np_, _nq_,
+_nr_ or _ms_, _mt_, _mv_, and doing this at several distances of the
+line _rv_ from the Asymptote DD, you may find as many points of these
+Hyperbola's as you please, and thereby know that these curve lines are
+Hyperbola's differing little from the conical Hyperbola. And by
+measuring the lines C_i_, C_k_, C_l_, you may find other points of these
+Curves.
+
+For instance; when the Knives were distant from the hole in the Window
+ten Feet, and the Paper from the Knives nine Feet, and the Angle
+contained by the edges of the Knives to which the Angle ACB is equal,
+was subtended by a Chord which was to the Radius as 1 to 32, and the
+distance of the line _rv_ from the Asymptote DE was half an Inch: I
+measured the lines _ps_, _qt_, _rv_, and found them 0'35, 0'65, 0'98
+Inches respectively; and by adding to their halfs the line 1/2 _mn_,
+(which here was the 128th part of an Inch, or 0'0078 Inches,) the Sums
+_np_, _nq_, _nr_, were 0'1828, 0'3328, 0'4978 Inches. I measured also
+the distances of the brightest parts of the Fringes which run between
+_pq_ and _st_, _qr_ and _tv_, and next beyond _r_ and _v_, and found
+them 0'5, 0'8, and 1'17 Inches.
+
+_Obs._ 11. The Sun shining into my darken'd Room through a small round
+hole made in a Plate of Lead with a slender Pin, as above; I placed at
+the hole a Prism to refract the Light, and form on the opposite Wall the
+Spectrum of Colours, described in the third Experiment of the first
+Book. And then I found that the Shadows of all Bodies held in the
+colour'd Light between the Prism and the Wall, were border'd with
+Fringes of the Colour of that Light in which they were held. In the full
+red Light they were totally red without any sensible blue or violet, and
+in the deep blue Light they were totally blue without any sensible red
+or yellow; and so in the green Light they were totally green, excepting
+a little yellow and blue, which were mixed in the green Light of the
+Prism. And comparing the Fringes made in the several colour'd Lights, I
+found that those made in the red Light were largest, those made in the
+violet were least, and those made in the green were of a middle bigness.
+For the Fringes with which the Shadow of a Man's Hair were bordered,
+being measured cross the Shadow at the distance of six Inches from the
+Hair, the distance between the middle and most luminous part of the
+first or innermost Fringe on one side of the Shadow, and that of the
+like Fringe on the other side of the Shadow, was in the full red Light
+1/37-1/4 of an Inch, and in the full violet 7/46. And the like distance
+between the middle and most luminous parts of the second Fringes on
+either side the Shadow was in the full red Light 1/22, and in the violet
+1/27 of an Inch. And these distances of the Fringes held the same
+proportion at all distances from the Hair without any sensible
+variation.
+
+So then the Rays which made these Fringes in the red Light passed by the
+Hair at a greater distance than those did which made the like Fringes in
+the violet; and therefore the Hair in causing these Fringes acted alike
+upon the red Light or least refrangible Rays at a greater distance, and
+upon the violet or most refrangible Rays at a less distance, and by
+those actions disposed the red Light into Larger Fringes, and the violet
+into smaller, and the Lights of intermediate Colours into Fringes of
+intermediate bignesses without changing the Colour of any sort of Light.
+
+When therefore the Hair in the first and second of these Observations
+was held in the white beam of the Sun's Light, and cast a Shadow which
+was border'd with three Fringes of coloured Light, those Colours arose
+not from any new modifications impress'd upon the Rays of Light by the
+Hair, but only from the various inflexions whereby the several Sorts of
+Rays were separated from one another, which before separation, by the
+mixture of all their Colours, composed the white beam of the Sun's
+Light, but whenever separated compose Lights of the several Colours
+which they are originally disposed to exhibit. In this 11th Observation,
+where the Colours are separated before the Light passes by the Hair, the
+least refrangible Rays, which when separated from the rest make red,
+were inflected at a greater distance from the Hair, so as to make three
+red Fringes at a greater distance from the middle of the Shadow of the
+Hair; and the most refrangible Rays which when separated make violet,
+were inflected at a less distance from the Hair, so as to make three
+violet Fringes at a less distance from the middle of the Shadow of the
+Hair. And other Rays of intermediate degrees of Refrangibility were
+inflected at intermediate distances from the Hair, so as to make Fringes
+of intermediate Colours at intermediate distances from the middle of the
+Shadow of the Hair. And in the second Observation, where all the Colours
+are mix'd in the white Light which passes by the Hair, these Colours are
+separated by the various inflexions of the Rays, and the Fringes which
+they make appear all together, and the innermost Fringes being
+contiguous make one broad Fringe composed of all the Colours in due
+order, the violet lying on the inside of the Fringe next the Shadow, the
+red on the outside farthest from the Shadow, and the blue, green, and
+yellow, in the middle. And, in like manner, the middlemost Fringes of
+all the Colours lying in order, and being contiguous, make another broad
+Fringe composed of all the Colours; and the outmost Fringes of all the
+Colours lying in order, and being contiguous, make a third broad Fringe
+composed of all the Colours. These are the three Fringes of colour'd
+Light with which the Shadows of all Bodies are border'd in the second
+Observation.
+
+When I made the foregoing Observations, I design'd to repeat most of
+them with more care and exactness, and to make some new ones for
+determining the manner how the Rays of Light are bent in their passage
+by Bodies, for making the Fringes of Colours with the dark lines between
+them. But I was then interrupted, and cannot now think of taking these
+things into farther Consideration. And since I have not finish'd this
+part of my Design, I shall conclude with proposing only some Queries, in
+order to a farther search to be made by others.
+
+_Query_ 1. Do not Bodies act upon Light at a distance, and by their
+action bend its Rays; and is not this action (_cæteris paribus_)
+strongest at the least distance?
+
+_Qu._ 2. Do not the Rays which differ in Refrangibility differ also in
+Flexibity; and are they not by their different Inflexions separated from
+one another, so as after separation to make the Colours in the three
+Fringes above described? And after what manner are they inflected to
+make those Fringes?
+
+_Qu._ 3. Are not the Rays of Light in passing by the edges and sides of
+Bodies, bent several times backwards and forwards, with a motion like
+that of an Eel? And do not the three Fringes of colour'd Light
+above-mention'd arise from three such bendings?
+
+_Qu._ 4. Do not the Rays of Light which fall upon Bodies, and are
+reflected or refracted, begin to bend before they arrive at the Bodies;
+and are they not reflected, refracted, and inflected, by one and the
+same Principle, acting variously in various Circumstances?
+
+_Qu._ 5. Do not Bodies and Light act mutually upon one another; that is
+to say, Bodies upon Light in emitting, reflecting, refracting and
+inflecting it, and Light upon Bodies for heating them, and putting their
+parts into a vibrating motion wherein heat consists?
+
+_Qu._ 6. Do not black Bodies conceive heat more easily from Light than
+those of other Colours do, by reason that the Light falling on them is
+not reflected outwards, but enters the Bodies, and is often reflected
+and refracted within them, until it be stifled and lost?
+
+_Qu._ 7. Is not the strength and vigor of the action between Light and
+sulphureous Bodies observed above, one reason why sulphureous Bodies
+take fire more readily, and burn more vehemently than other Bodies do?
+
+_Qu._ 8. Do not all fix'd Bodies, when heated beyond a certain degree,
+emit Light and shine; and is not this Emission perform'd by the
+vibrating motions of their parts? And do not all Bodies which abound
+with terrestrial parts, and especially with sulphureous ones, emit Light
+as often as those parts are sufficiently agitated; whether that
+agitation be made by Heat, or by Friction, or Percussion, or
+Putrefaction, or by any vital Motion, or any other Cause? As for
+instance; Sea-Water in a raging Storm; Quick-silver agitated in _vacuo_;
+the Back of a Cat, or Neck of a Horse, obliquely struck or rubbed in a
+dark place; Wood, Flesh and Fish while they putrefy; Vapours arising
+from putrefy'd Waters, usually call'd _Ignes Fatui_; Stacks of moist Hay
+or Corn growing hot by fermentation; Glow-worms and the Eyes of some
+Animals by vital Motions; the vulgar _Phosphorus_ agitated by the
+attrition of any Body, or by the acid Particles of the Air; Amber and
+some Diamonds by striking, pressing or rubbing them; Scrapings of Steel
+struck off with a Flint; Iron hammer'd very nimbly till it become so hot
+as to kindle Sulphur thrown upon it; the Axletrees of Chariots taking
+fire by the rapid rotation of the Wheels; and some Liquors mix'd with
+one another whose Particles come together with an Impetus, as Oil of
+Vitriol distilled from its weight of Nitre, and then mix'd with twice
+its weight of Oil of Anniseeds. So also a Globe of Glass about 8 or 10
+Inches in diameter, being put into a Frame where it may be swiftly
+turn'd round its Axis, will in turning shine where it rubs against the
+palm of ones Hand apply'd to it: And if at the same time a piece of
+white Paper or white Cloth, or the end of ones Finger be held at the
+distance of about a quarter of an Inch or half an Inch from that part of
+the Glass where it is most in motion, the electrick Vapour which is
+excited by the friction of the Glass against the Hand, will by dashing
+against the white Paper, Cloth or Finger, be put into such an agitation
+as to emit Light, and make the white Paper, Cloth or Finger, appear
+lucid like a Glowworm; and in rushing out of the Glass will sometimes
+push against the finger so as to be felt. And the same things have been
+found by rubbing a long and large Cylinder or Glass or Amber with a
+Paper held in ones hand, and continuing the friction till the Glass grew
+warm.
+
+_Qu._ 9. Is not Fire a Body heated so hot as to emit Light copiously?
+For what else is a red hot Iron than Fire? And what else is a burning
+Coal than red hot Wood?
+
+_Qu._ 10. Is not Flame a Vapour, Fume or Exhalation heated red hot, that
+is, so hot as to shine? For Bodies do not flame without emitting a
+copious Fume, and this Fume burns in the Flame. The _Ignis Fatuus_ is a
+Vapour shining without heat, and is there not the same difference
+between this Vapour and Flame, as between rotten Wood shining without
+heat and burning Coals of Fire? In distilling hot Spirits, if the Head
+of the Still be taken off, the Vapour which ascends out of the Still
+will take fire at the Flame of a Candle, and turn into Flame, and the
+Flame will run along the Vapour from the Candle to the Still. Some
+Bodies heated by Motion, or Fermentation, if the heat grow intense, fume
+copiously, and if the heat be great enough the Fumes will shine and
+become Flame. Metals in fusion do not flame for want of a copious Fume,
+except Spelter, which fumes copiously, and thereby flames. All flaming
+Bodies, as Oil, Tallow, Wax, Wood, fossil Coals, Pitch, Sulphur, by
+flaming waste and vanish into burning Smoke, which Smoke, if the Flame
+be put out, is very thick and visible, and sometimes smells strongly,
+but in the Flame loses its smell by burning, and according to the nature
+of the Smoke the Flame is of several Colours, as that of Sulphur blue,
+that of Copper open'd with sublimate green, that of Tallow yellow, that
+of Camphire white. Smoke passing through Flame cannot but grow red hot,
+and red hot Smoke can have no other appearance than that of Flame. When
+Gun-powder takes fire, it goes away into Flaming Smoke. For the Charcoal
+and Sulphur easily take fire, and set fire to the Nitre, and the Spirit
+of the Nitre being thereby rarified into Vapour, rushes out with
+Explosion much after the manner that the Vapour of Water rushes out of
+an Æolipile; the Sulphur also being volatile is converted into Vapour,
+and augments the Explosion. And the acid Vapour of the Sulphur (namely
+that which distils under a Bell into Oil of Sulphur,) entring violently
+into the fix'd Body of the Nitre, sets loose the Spirit of the Nitre,
+and excites a great Fermentation, whereby the Heat is farther augmented,
+and the fix'd Body of the Nitre is also rarified into Fume, and the
+Explosion is thereby made more vehement and quick. For if Salt of Tartar
+be mix'd with Gun-powder, and that Mixture be warm'd till it takes fire,
+the Explosion will be more violent and quick than that of Gun-powder
+alone; which cannot proceed from any other cause than the action of the
+Vapour of the Gun-powder upon the Salt of Tartar, whereby that Salt is
+rarified. The Explosion of Gun-powder arises therefore from the violent
+action whereby all the Mixture being quickly and vehemently heated, is
+rarified and converted into Fume and Vapour: which Vapour, by the
+violence of that action, becoming so hot as to shine, appears in the
+form of Flame.
+
+_Qu._ 11. Do not great Bodies conserve their heat the longest, their
+parts heating one another, and may not great dense and fix'd Bodies,
+when heated beyond a certain degree, emit Light so copiously, as by the
+Emission and Re-action of its Light, and the Reflexions and Refractions
+of its Rays within its Pores to grow still hotter, till it comes to a
+certain period of heat, such as is that of the Sun? And are not the Sun
+and fix'd Stars great Earths vehemently hot, whose heat is conserved by
+the greatness of the Bodies, and the mutual Action and Reaction between
+them, and the Light which they emit, and whose parts are kept from
+fuming away, not only by their fixity, but also by the vast weight and
+density of the Atmospheres incumbent upon them; and very strongly
+compressing them, and condensing the Vapours and Exhalations which arise
+from them? For if Water be made warm in any pellucid Vessel emptied of
+Air, that Water in the _Vacuum_ will bubble and boil as vehemently as it
+would in the open Air in a Vessel set upon the Fire till it conceives a
+much greater heat. For the weight of the incumbent Atmosphere keeps down
+the Vapours, and hinders the Water from boiling, until it grow much
+hotter than is requisite to make it boil _in vacuo_. Also a mixture of
+Tin and Lead being put upon a red hot Iron _in vacuo_ emits a Fume and
+Flame, but the same Mixture in the open Air, by reason of the incumbent
+Atmosphere, does not so much as emit any Fume which can be perceived by
+Sight. In like manner the great weight of the Atmosphere which lies upon
+the Globe of the Sun may hinder Bodies there from rising up and going
+away from the Sun in the form of Vapours and Fumes, unless by means of a
+far greater heat than that which on the Surface of our Earth would very
+easily turn them into Vapours and Fumes. And the same great weight may
+condense those Vapours and Exhalations as soon as they shall at any time
+begin to ascend from the Sun, and make them presently fall back again
+into him, and by that action increase his Heat much after the manner
+that in our Earth the Air increases the Heat of a culinary Fire. And the
+same weight may hinder the Globe of the Sun from being diminish'd,
+unless by the Emission of Light, and a very small quantity of Vapours
+and Exhalations.
+
+_Qu._ 12. Do not the Rays of Light in falling upon the bottom of the Eye
+excite Vibrations in the _Tunica Retina_? Which Vibrations, being
+propagated along the solid Fibres of the optick Nerves into the Brain,
+cause the Sense of seeing. For because dense Bodies conserve their Heat
+a long time, and the densest Bodies conserve their Heat the longest, the
+Vibrations of their parts are of a lasting nature, and therefore may be
+propagated along solid Fibres of uniform dense Matter to a great
+distance, for conveying into the Brain the impressions made upon all the
+Organs of Sense. For that Motion which can continue long in one and the
+same part of a Body, can be propagated a long way from one part to
+another, supposing the Body homogeneal, so that the Motion may not be
+reflected, refracted, interrupted or disorder'd by any unevenness of the
+Body.
+
+_Qu._ 13. Do not several sorts of Rays make Vibrations of several
+bignesses, which according to their bignesses excite Sensations of
+several Colours, much after the manner that the Vibrations of the Air,
+according to their several bignesses excite Sensations of several
+Sounds? And particularly do not the most refrangible Rays excite the
+shortest Vibrations for making a Sensation of deep violet, the least
+refrangible the largest for making a Sensation of deep red, and the
+several intermediate sorts of Rays, Vibrations of several intermediate
+bignesses to make Sensations of the several intermediate Colours?
+
+_Qu._ 14. May not the harmony and discord of Colours arise from the
+proportions of the Vibrations propagated through the Fibres of the
+optick Nerves into the Brain, as the harmony and discord of Sounds arise
+from the proportions of the Vibrations of the Air? For some Colours, if
+they be view'd together, are agreeable to one another, as those of Gold
+and Indigo, and others disagree.
+
+_Qu._ 15. Are not the Species of Objects seen with both Eyes united
+where the optick Nerves meet before they come into the Brain, the Fibres
+on the right side of both Nerves uniting there, and after union going
+thence into the Brain in the Nerve which is on the right side of the
+Head, and the Fibres on the left side of both Nerves uniting in the same
+place, and after union going into the Brain in the Nerve which is on the
+left side of the Head, and these two Nerves meeting in the Brain in such
+a manner that their Fibres make but one entire Species or Picture, half
+of which on the right side of the Sensorium comes from the right side of
+both Eyes through the right side of both optick Nerves to the place
+where the Nerves meet, and from thence on the right side of the Head
+into the Brain, and the other half on the left side of the Sensorium
+comes in like manner from the left side of both Eyes. For the optick
+Nerves of such Animals as look the same way with both Eyes (as of Men,
+Dogs, Sheep, Oxen, &c.) meet before they come into the Brain, but the
+optick Nerves of such Animals as do not look the same way with both Eyes
+(as of Fishes, and of the Chameleon,) do not meet, if I am rightly
+inform'd.
+
+_Qu._ 16. When a Man in the dark presses either corner of his Eye with
+his Finger, and turns his Eye away from his Finger, he will see a Circle
+of Colours like those in the Feather of a Peacock's Tail. If the Eye and
+the Finger remain quiet these Colours vanish in a second Minute of Time,
+but if the Finger be moved with a quavering Motion they appear again. Do
+not these Colours arise from such Motions excited in the bottom of the
+Eye by the Pressure and Motion of the Finger, as, at other times are
+excited there by Light for causing Vision? And do not the Motions once
+excited continue about a Second of Time before they cease? And when a
+Man by a stroke upon his Eye sees a flash of Light, are not the like
+Motions excited in the _Retina_ by the stroke? And when a Coal of Fire
+moved nimbly in the circumference of a Circle, makes the whole
+circumference appear like a Circle of Fire; is it not because the
+Motions excited in the bottom of the Eye by the Rays of Light are of a
+lasting nature, and continue till the Coal of Fire in going round
+returns to its former place? And considering the lastingness of the
+Motions excited in the bottom of the Eye by Light, are they not of a
+vibrating nature?
+
+_Qu._ 17. If a stone be thrown into stagnating Water, the Waves excited
+thereby continue some time to arise in the place where the Stone fell
+into the Water, and are propagated from thence in concentrick Circles
+upon the Surface of the Water to great distances. And the Vibrations or
+Tremors excited in the Air by percussion, continue a little time to move
+from the place of percussion in concentrick Spheres to great distances.
+And in like manner, when a Ray of Light falls upon the Surface of any
+pellucid Body, and is there refracted or reflected, may not Waves of
+Vibrations, or Tremors, be thereby excited in the refracting or
+reflecting Medium at the point of Incidence, and continue to arise
+there, and to be propagated from thence as long as they continue to
+arise and be propagated, when they are excited in the bottom of the Eye
+by the Pressure or Motion of the Finger, or by the Light which comes
+from the Coal of Fire in the Experiments above-mention'd? and are not
+these Vibrations propagated from the point of Incidence to great
+distances? And do they not overtake the Rays of Light, and by overtaking
+them successively, do they not put them into the Fits of easy Reflexion
+and easy Transmission described above? For if the Rays endeavour to
+recede from the densest part of the Vibration, they may be alternately
+accelerated and retarded by the Vibrations overtaking them.
+
+_Qu._ 18. If in two large tall cylindrical Vessels of Glass inverted,
+two little Thermometers be suspended so as not to touch the Vessels, and
+the Air be drawn out of one of these Vessels, and these Vessels thus
+prepared be carried out of a cold place into a warm one; the Thermometer
+_in vacuo_ will grow warm as much, and almost as soon as the Thermometer
+which is not _in vacuo_. And when the Vessels are carried back into the
+cold place, the Thermometer _in vacuo_ will grow cold almost as soon as
+the other Thermometer. Is not the Heat of the warm Room convey'd through
+the _Vacuum_ by the Vibrations of a much subtiler Medium than Air, which
+after the Air was drawn out remained in the _Vacuum_? And is not this
+Medium the same with that Medium by which Light is refracted and
+reflected, and by whose Vibrations Light communicates Heat to Bodies,
+and is put into Fits of easy Reflexion and easy Transmission? And do not
+the Vibrations of this Medium in hot Bodies contribute to the
+intenseness and duration of their Heat? And do not hot Bodies
+communicate their Heat to contiguous cold ones, by the Vibrations of
+this Medium propagated from them into the cold ones? And is not this
+Medium exceedingly more rare and subtile than the Air, and exceedingly
+more elastick and active? And doth it not readily pervade all Bodies?
+And is it not (by its elastick force) expanded through all the Heavens?
+
+_Qu._ 19. Doth not the Refraction of Light proceed from the different
+density of this Æthereal Medium in different places, the Light receding
+always from the denser parts of the Medium? And is not the density
+thereof greater in free and open Spaces void of Air and other grosser
+Bodies, than within the Pores of Water, Glass, Crystal, Gems, and other
+compact Bodies? For when Light passes through Glass or Crystal, and
+falling very obliquely upon the farther Surface thereof is totally
+reflected, the total Reflexion ought to proceed rather from the density
+and vigour of the Medium without and beyond the Glass, than from the
+rarity and weakness thereof.
+
+_Qu._ 20. Doth not this Æthereal Medium in passing out of Water, Glass,
+Crystal, and other compact and dense Bodies into empty Spaces, grow
+denser and denser by degrees, and by that means refract the Rays of
+Light not in a point, but by bending them gradually in curve Lines? And
+doth not the gradual condensation of this Medium extend to some distance
+from the Bodies, and thereby cause the Inflexions of the Rays of Light,
+which pass by the edges of dense Bodies, at some distance from the
+Bodies?
+
+_Qu._ 21. Is not this Medium much rarer within the dense Bodies of the
+Sun, Stars, Planets and Comets, than in the empty celestial Spaces
+between them? And in passing from them to great distances, doth it not
+grow denser and denser perpetually, and thereby cause the gravity of
+those great Bodies towards one another, and of their parts towards the
+Bodies; every Body endeavouring to go from the denser parts of the
+Medium towards the rarer? For if this Medium be rarer within the Sun's
+Body than at its Surface, and rarer there than at the hundredth part of
+an Inch from its Body, and rarer there than at the fiftieth part of an
+Inch from its Body, and rarer there than at the Orb of _Saturn_; I see
+no reason why the Increase of density should stop any where, and not
+rather be continued through all distances from the Sun to _Saturn_, and
+beyond. And though this Increase of density may at great distances be
+exceeding slow, yet if the elastick force of this Medium be exceeding
+great, it may suffice to impel Bodies from the denser parts of the
+Medium towards the rarer, with all that power which we call Gravity. And
+that the elastick force of this Medium is exceeding great, may be
+gather'd from the swiftness of its Vibrations. Sounds move about 1140
+_English_ Feet in a second Minute of Time, and in seven or eight Minutes
+of Time they move about one hundred _English_ Miles. Light moves from
+the Sun to us in about seven or eight Minutes of Time, which distance is
+about 70,000,000 _English_ Miles, supposing the horizontal Parallax of
+the Sun to be about 12´´. And the Vibrations or Pulses of this Medium,
+that they may cause the alternate Fits of easy Transmission and easy
+Reflexion, must be swifter than Light, and by consequence above 700,000
+times swifter than Sounds. And therefore the elastick force of this
+Medium, in proportion to its density, must be above 700000 x 700000
+(that is, above 490,000,000,000) times greater than the elastick force
+of the Air is in proportion to its density. For the Velocities of the
+Pulses of elastick Mediums are in a subduplicate _Ratio_ of the
+Elasticities and the Rarities of the Mediums taken together.
+
+As Attraction is stronger in small Magnets than in great ones in
+proportion to their Bulk, and Gravity is greater in the Surfaces of
+small Planets than in those of great ones in proportion to their bulk,
+and small Bodies are agitated much more by electric attraction than
+great ones; so the smallness of the Rays of Light may contribute very
+much to the power of the Agent by which they are refracted. And so if
+any one should suppose that _Æther_ (like our Air) may contain Particles
+which endeavour to recede from one another (for I do not know what this
+_Æther_ is) and that its Particles are exceedingly smaller than those of
+Air, or even than those of Light: The exceeding smallness of its
+Particles may contribute to the greatness of the force by which those
+Particles may recede from one another, and thereby make that Medium
+exceedingly more rare and elastick than Air, and by consequence
+exceedingly less able to resist the motions of Projectiles, and
+exceedingly more able to press upon gross Bodies, by endeavouring to
+expand it self.
+
+_Qu._ 22. May not Planets and Comets, and all gross Bodies, perform
+their Motions more freely, and with less resistance in this Æthereal
+Medium than in any Fluid, which fills all Space adequately without
+leaving any Pores, and by consequence is much denser than Quick-silver
+or Gold? And may not its resistance be so small, as to be
+inconsiderable? For instance; If this _Æther_ (for so I will call it)
+should be supposed 700000 times more elastick than our Air, and above
+700000 times more rare; its resistance would be above 600,000,000 times
+less than that of Water. And so small a resistance would scarce make any
+sensible alteration in the Motions of the Planets in ten thousand
+Years. If any one would ask how a Medium can be so rare, let him tell me
+how the Air, in the upper parts of the Atmosphere, can be above an
+hundred thousand thousand times rarer than Gold. Let him also tell me,
+how an electrick Body can by Friction emit an Exhalation so rare and
+subtile, and yet so potent, as by its Emission to cause no sensible
+Diminution of the weight of the electrick Body, and to be expanded
+through a Sphere, whose Diameter is above two Feet, and yet to be able
+to agitate and carry up Leaf Copper, or Leaf Gold, at the distance of
+above a Foot from the electrick Body? And how the Effluvia of a Magnet
+can be so rare and subtile, as to pass through a Plate of Glass without
+any Resistance or Diminution of their Force, and yet so potent as to
+turn a magnetick Needle beyond the Glass?
+
+_Qu._ 23. Is not Vision perform'd chiefly by the Vibrations of this
+Medium, excited in the bottom of the Eye by the Rays of Light, and
+propagated through the solid, pellucid and uniform Capillamenta of the
+optick Nerves into the place of Sensation? And is not Hearing perform'd
+by the Vibrations either of this or some other Medium, excited in the
+auditory Nerves by the Tremors of the Air, and propagated through the
+solid, pellucid and uniform Capillamenta of those Nerves into the place
+of Sensation? And so of the other Senses.
+
+_Qu._ 24. Is not Animal Motion perform'd by the Vibrations of this
+Medium, excited in the Brain by the power of the Will, and propagated
+from thence through the solid, pellucid and uniform Capillamenta of the
+Nerves into the Muscles, for contracting and dilating them? I suppose
+that the Capillamenta of the Nerves are each of them solid and uniform,
+that the vibrating Motion of the Æthereal Medium may be propagated along
+them from one end to the other uniformly, and without interruption: For
+Obstructions in the Nerves create Palsies. And that they may be
+sufficiently uniform, I suppose them to be pellucid when view'd singly,
+tho' the Reflexions in their cylindrical Surfaces may make the whole
+Nerve (composed of many Capillamenta) appear opake and white. For
+opacity arises from reflecting Surfaces, such as may disturb and
+interrupt the Motions of this Medium.
+
+[Sidenote: _See the following Scheme, p. 356._]
+
+_Qu._ 25. Are there not other original Properties of the Rays of Light,
+besides those already described? An instance of another original
+Property we have in the Refraction of Island Crystal, described first by
+_Erasmus Bartholine_, and afterwards more exactly by _Hugenius_, in his
+Book _De la Lumiere_. This Crystal is a pellucid fissile Stone, clear as
+Water or Crystal of the Rock, and without Colour; enduring a red Heat
+without losing its transparency, and in a very strong Heat calcining
+without Fusion. Steep'd a Day or two in Water, it loses its natural
+Polish. Being rubb'd on Cloth, it attracts pieces of Straws and other
+light things, like Ambar or Glass; and with _Aqua fortis_ it makes an
+Ebullition. It seems to be a sort of Talk, and is found in form of an
+oblique Parallelopiped, with six parallelogram Sides and eight solid
+Angles. The obtuse Angles of the Parallelograms are each of them 101
+Degrees and 52 Minutes; the acute ones 78 Degrees and 8 Minutes. Two of
+the solid Angles opposite to one another, as C and E, are compassed each
+of them with three of these obtuse Angles, and each of the other six
+with one obtuse and two acute ones. It cleaves easily in planes parallel
+to any of its Sides, and not in any other Planes. It cleaves with a
+glossy polite Surface not perfectly plane, but with some little
+unevenness. It is easily scratch'd, and by reason of its softness it
+takes a Polish very difficultly. It polishes better upon polish'd
+Looking-glass than upon Metal, and perhaps better upon Pitch, Leather or
+Parchment. Afterwards it must be rubb'd with a little Oil or white of an
+Egg, to fill up its Scratches; whereby it will become very transparent
+and polite. But for several Experiments, it is not necessary to polish
+it. If a piece of this crystalline Stone be laid upon a Book, every
+Letter of the Book seen through it will appear double, by means of a
+double Refraction. And if any beam of Light falls either
+perpendicularly, or in any oblique Angle upon any Surface of this
+Crystal, it becomes divided into two beams by means of the same double
+Refraction. Which beams are of the same Colour with the incident beam of
+Light, and seem equal to one another in the quantity of their Light, or
+very nearly equal. One of these Refractions is perform'd by the usual
+Rule of Opticks, the Sine of Incidence out of Air into this Crystal
+being to the Sine of Refraction, as five to three. The other
+Refraction, which may be called the unusual Refraction, is perform'd by
+the following Rule.
+
+[Illustration: FIG. 4.]
+
+Let ADBC represent the refracting Surface of the Crystal, C the biggest
+solid Angle at that Surface, GEHF the opposite Surface, and CK a
+perpendicular on that Surface. This perpendicular makes with the edge of
+the Crystal CF, an Angle of 19 Degr. 3'. Join KF, and in it take KL, so
+that the Angle KCL be 6 Degr. 40'. and the Angle LCF 12 Degr. 23'. And
+if ST represent any beam of Light incident at T in any Angle upon the
+refracting Surface ADBC, let TV be the refracted beam determin'd by the
+given Portion of the Sines 5 to 3, according to the usual Rule of
+Opticks. Draw VX parallel and equal to KL. Draw it the same way from V
+in which L lieth from K; and joining TX, this line TX shall be the other
+refracted beam carried from T to X, by the unusual Refraction.
+
+If therefore the incident beam ST be perpendicular to the refracting
+Surface, the two beams TV and TX, into which it shall become divided,
+shall be parallel to the lines CK and CL; one of those beams going
+through the Crystal perpendicularly, as it ought to do by the usual Laws
+of Opticks, and the other TX by an unusual Refraction diverging from the
+perpendicular, and making with it an Angle VTX of about 6-2/3 Degrees,
+as is found by Experience. And hence, the Plane VTX, and such like
+Planes which are parallel to the Plane CFK, may be called the Planes of
+perpendicular Refraction. And the Coast towards which the lines KL and
+VX are drawn, may be call'd the Coast of unusual Refraction.
+
+In like manner Crystal of the Rock has a double Refraction: But the
+difference of the two Refractions is not so great and manifest as in
+Island Crystal.
+
+When the beam ST incident on Island Crystal is divided into two beams TV
+and TX, and these two beams arrive at the farther Surface of the Glass;
+the beam TV, which was refracted at the first Surface after the usual
+manner, shall be again refracted entirely after the usual manner at the
+second Surface; and the beam TX, which was refracted after the unusual
+manner in the first Surface, shall be again refracted entirely after the
+unusual manner in the second Surface; so that both these beams shall
+emerge out of the second Surface in lines parallel to the first incident
+beam ST.
+
+And if two pieces of Island Crystal be placed one after another, in such
+manner that all the Surfaces of the latter be parallel to all the
+corresponding Surfaces of the former: The Rays which are refracted after
+the usual manner in the first Surface of the first Crystal, shall be
+refracted after the usual manner in all the following Surfaces; and the
+Rays which are refracted after the unusual manner in the first Surface,
+shall be refracted after the unusual manner in all the following
+Surfaces. And the same thing happens, though the Surfaces of the
+Crystals be any ways inclined to one another, provided that their Planes
+of perpendicular Refraction be parallel to one another.
+
+And therefore there is an original difference in the Rays of Light, by
+means of which some Rays are in this Experiment constantly refracted
+after the usual manner, and others constantly after the unusual manner:
+For if the difference be not original, but arises from new Modifications
+impress'd on the Rays at their first Refraction, it would be alter'd by
+new Modifications in the three following Refractions; whereas it suffers
+no alteration, but is constant, and has the same effect upon the Rays in
+all the Refractions. The unusual Refraction is therefore perform'd by an
+original property of the Rays. And it remains to be enquired, whether
+the Rays have not more original Properties than are yet discover'd.
+
+_Qu._ 26. Have not the Rays of Light several sides, endued with several
+original Properties? For if the Planes of perpendicular Refraction of
+the second Crystal be at right Angles with the Planes of perpendicular
+Refraction of the first Crystal, the Rays which are refracted after the
+usual manner in passing through the first Crystal, will be all of them
+refracted after the unusual manner in passing through the second
+Crystal; and the Rays which are refracted after the unusual manner in
+passing through the first Crystal, will be all of them refracted after
+the usual manner in passing through the second Crystal. And therefore
+there are not two sorts of Rays differing in their nature from one
+another, one of which is constantly and in all Positions refracted after
+the usual manner, and the other constantly and in all Positions after
+the unusual manner. The difference between the two sorts of Rays in the
+Experiment mention'd in the 25th Question, was only in the Positions of
+the Sides of the Rays to the Planes of perpendicular Refraction. For one
+and the same Ray is here refracted sometimes after the usual, and
+sometimes after the unusual manner, according to the Position which its
+Sides have to the Crystals. If the Sides of the Ray are posited the same
+way to both Crystals, it is refracted after the same manner in them
+both: But if that side of the Ray which looks towards the Coast of the
+unusual Refraction of the first Crystal, be 90 Degrees from that side of
+the same Ray which looks toward the Coast of the unusual Refraction of
+the second Crystal, (which may be effected by varying the Position of
+the second Crystal to the first, and by consequence to the Rays of
+Light,) the Ray shall be refracted after several manners in the several
+Crystals. There is nothing more required to determine whether the Rays
+of Light which fall upon the second Crystal shall be refracted after
+the usual or after the unusual manner, but to turn about this Crystal,
+so that the Coast of this Crystal's unusual Refraction may be on this or
+on that side of the Ray. And therefore every Ray may be consider'd as
+having four Sides or Quarters, two of which opposite to one another
+incline the Ray to be refracted after the unusual manner, as often as
+either of them are turn'd towards the Coast of unusual Refraction; and
+the other two, whenever either of them are turn'd towards the Coast of
+unusual Refraction, do not incline it to be otherwise refracted than
+after the usual manner. The two first may therefore be call'd the Sides
+of unusual Refraction. And since these Dispositions were in the Rays
+before their Incidence on the second, third, and fourth Surfaces of the
+two Crystals, and suffered no alteration (so far as appears,) by the
+Refraction of the Rays in their passage through those Surfaces, and the
+Rays were refracted by the same Laws in all the four Surfaces; it
+appears that those Dispositions were in the Rays originally, and
+suffer'd no alteration by the first Refraction, and that by means of
+those Dispositions the Rays were refracted at their Incidence on the
+first Surface of the first Crystal, some of them after the usual, and
+some of them after the unusual manner, accordingly as their Sides of
+unusual Refraction were then turn'd towards the Coast of the unusual
+Refraction of that Crystal, or sideways from it.
+
+Every Ray of Light has therefore two opposite Sides, originally endued
+with a Property on which the unusual Refraction depends, and the other
+two opposite Sides not endued with that Property. And it remains to be
+enquired, whether there are not more Properties of Light by which the
+Sides of the Rays differ, and are distinguished from one another.
+
+In explaining the difference of the Sides of the Rays above mention'd, I
+have supposed that the Rays fall perpendicularly on the first Crystal.
+But if they fall obliquely on it, the Success is the same. Those Rays
+which are refracted after the usual manner in the first Crystal, will be
+refracted after the unusual manner in the second Crystal, supposing the
+Planes of perpendicular Refraction to be at right Angles with one
+another, as above; and on the contrary.
+
+If the Planes of the perpendicular Refraction of the two Crystals be
+neither parallel nor perpendicular to one another, but contain an acute
+Angle: The two beams of Light which emerge out of the first Crystal,
+will be each of them divided into two more at their Incidence on the
+second Crystal. For in this case the Rays in each of the two beams will
+some of them have their Sides of unusual Refraction, and some of them
+their other Sides turn'd towards the Coast of the unusual Refraction of
+the second Crystal.
+
+_Qu._ 27. Are not all Hypotheses erroneous which have hitherto been
+invented for explaining the Phænomena of Light, by new Modifications of
+the Rays? For those Phænomena depend not upon new Modifications, as has
+been supposed, but upon the original and unchangeable Properties of the
+Rays.
+
+_Qu._ 28. Are not all Hypotheses erroneous, in which Light is supposed
+to consist in Pression or Motion, propagated through a fluid Medium? For
+in all these Hypotheses the Phænomena of Light have been hitherto
+explain'd by supposing that they arise from new Modifications of the
+Rays; which is an erroneous Supposition.
+
+If Light consisted only in Pression propagated without actual Motion, it
+would not be able to agitate and heat the Bodies which refract and
+reflect it. If it consisted in Motion propagated to all distances in an
+instant, it would require an infinite force every moment, in every
+shining Particle, to generate that Motion. And if it consisted in
+Pression or Motion, propagated either in an instant or in time, it would
+bend into the Shadow. For Pression or Motion cannot be propagated in a
+Fluid in right Lines, beyond an Obstacle which stops part of the Motion,
+but will bend and spread every way into the quiescent Medium which lies
+beyond the Obstacle. Gravity tends downwards, but the Pressure of Water
+arising from Gravity tends every way with equal Force, and is propagated
+as readily, and with as much force sideways as downwards, and through
+crooked passages as through strait ones. The Waves on the Surface of
+stagnating Water, passing by the sides of a broad Obstacle which stops
+part of them, bend afterwards and dilate themselves gradually into the
+quiet Water behind the Obstacle. The Waves, Pulses or Vibrations of the
+Air, wherein Sounds consist, bend manifestly, though not so much as the
+Waves of Water. For a Bell or a Cannon may be heard beyond a Hill which
+intercepts the sight of the sounding Body, and Sounds are propagated as
+readily through crooked Pipes as through streight ones. But Light is
+never known to follow crooked Passages nor to bend into the Shadow. For
+the fix'd Stars by the Interposition of any of the Planets cease to be
+seen. And so do the Parts of the Sun by the Interposition of the Moon,
+_Mercury_ or _Venus_. The Rays which pass very near to the edges of any
+Body, are bent a little by the action of the Body, as we shew'd above;
+but this bending is not towards but from the Shadow, and is perform'd
+only in the passage of the Ray by the Body, and at a very small distance
+from it. So soon as the Ray is past the Body, it goes right on.
+
+[Sidenote: _Mais pour dire comment cela se fait, je n'ay rien trove
+jusqu' ici qui me satisfasse._ C. H. de la lumiere, c. 5, p. 91.]
+
+To explain the unusual Refraction of Island Crystal by Pression or
+Motion propagated, has not hitherto been attempted (to my knowledge)
+except by _Huygens_, who for that end supposed two several vibrating
+Mediums within that Crystal. But when he tried the Refractions in two
+successive pieces of that Crystal, and found them such as is mention'd
+above; he confessed himself at a loss for explaining them. For Pressions
+or Motions, propagated from a shining Body through an uniform Medium,
+must be on all sides alike; whereas by those Experiments it appears,
+that the Rays of Light have different Properties in their different
+Sides. He suspected that the Pulses of _Æther_ in passing through the
+first Crystal might receive certain new Modifications, which might
+determine them to be propagated in this or that Medium within the
+second Crystal, according to the Position of that Crystal. But what
+Modifications those might be he could not say, nor think of any thing
+satisfactory in that Point. And if he had known that the unusual
+Refraction depends not on new Modifications, but on the original and
+unchangeable Dispositions of the Rays, he would have found it as
+difficult to explain how those Dispositions which he supposed to be
+impress'd on the Rays by the first Crystal, could be in them before
+their Incidence on that Crystal, and in general, how all Rays emitted by
+shining Bodies, can have those Dispositions in them from the beginning.
+To me, at least, this seems inexplicable, if Light be nothing else than
+Pression or Motion propagated through _Æther_.
+
+And it is as difficult to explain by these Hypotheses, how Rays can be
+alternately in Fits of easy Reflexion and easy Transmission; unless
+perhaps one might suppose that there are in all Space two Æthereal
+vibrating Mediums, and that the Vibrations of one of them constitute
+Light, and the Vibrations of the other are swifter, and as often as they
+overtake the Vibrations of the first, put them into those Fits. But how
+two _Æthers_ can be diffused through all Space, one of which acts upon
+the other, and by consequence is re-acted upon, without retarding,
+shattering, dispersing and confounding one anothers Motions, is
+inconceivable. And against filling the Heavens with fluid Mediums,
+unless they be exceeding rare, a great Objection arises from the regular
+and very lasting Motions of the Planets and Comets in all manner of
+Courses through the Heavens. For thence it is manifest, that the Heavens
+are void of all sensible Resistance, and by consequence of all sensible
+Matter.
+
+For the resisting Power of fluid Mediums arises partly from the
+Attrition of the Parts of the Medium, and partly from the _Vis inertiæ_
+of the Matter. That part of the Resistance of a spherical Body which
+arises from the Attrition of the Parts of the Medium is very nearly as
+the Diameter, or, at the most, as the _Factum_ of the Diameter, and the
+Velocity of the spherical Body together. And that part of the Resistance
+which arises from the _Vis inertiæ_ of the Matter, is as the Square of
+that _Factum_. And by this difference the two sorts of Resistance may be
+distinguish'd from one another in any Medium; and these being
+distinguish'd, it will be found that almost all the Resistance of Bodies
+of a competent Magnitude moving in Air, Water, Quick-silver, and such
+like Fluids with a competent Velocity, arises from the _Vis inertiæ_ of
+the Parts of the Fluid.
+
+Now that part of the resisting Power of any Medium which arises from the
+Tenacity, Friction or Attrition of the Parts of the Medium, may be
+diminish'd by dividing the Matter into smaller Parts, and making the
+Parts more smooth and slippery: But that part of the Resistance which
+arises from the _Vis inertiæ_, is proportional to the Density of the
+Matter, and cannot be diminish'd by dividing the Matter into smaller
+Parts, nor by any other means than by decreasing the Density of the
+Medium. And for these Reasons the Density of fluid Mediums is very
+nearly proportional to their Resistance. Liquors which differ not much
+in Density, as Water, Spirit of Wine, Spirit of Turpentine, hot Oil,
+differ not much in Resistance. Water is thirteen or fourteen times
+lighter than Quick-silver and by consequence thirteen or fourteen times
+rarer, and its Resistance is less than that of Quick-silver in the same
+Proportion, or thereabouts, as I have found by Experiments made with
+Pendulums. The open Air in which we breathe is eight or nine hundred
+times lighter than Water, and by consequence eight or nine hundred times
+rarer, and accordingly its Resistance is less than that of Water in the
+same Proportion, or thereabouts; as I have also found by Experiments
+made with Pendulums. And in thinner Air the Resistance is still less,
+and at length, by ratifying the Air, becomes insensible. For small
+Feathers falling in the open Air meet with great Resistance, but in a
+tall Glass well emptied of Air, they fall as fast as Lead or Gold, as I
+have seen tried several times. Whence the Resistance seems still to
+decrease in proportion to the Density of the Fluid. For I do not find by
+any Experiments, that Bodies moving in Quick-silver, Water or Air, meet
+with any other sensible Resistance than what arises from the Density and
+Tenacity of those sensible Fluids, as they would do if the Pores of
+those Fluids, and all other Spaces, were filled with a dense and
+subtile Fluid. Now if the Resistance in a Vessel well emptied of Air,
+was but an hundred times less than in the open Air, it would be about a
+million of times less than in Quick-silver. But it seems to be much less
+in such a Vessel, and still much less in the Heavens, at the height of
+three or four hundred Miles from the Earth, or above. For Mr. _Boyle_
+has shew'd that Air may be rarified above ten thousand times in Vessels
+of Glass; and the Heavens are much emptier of Air than any _Vacuum_ we
+can make below. For since the Air is compress'd by the Weight of the
+incumbent Atmosphere, and the Density of Air is proportional to the
+Force compressing it, it follows by Computation, that at the height of
+about seven and a half _English_ Miles from the Earth, the Air is four
+times rarer than at the Surface of the Earth; and at the height of 15
+Miles it is sixteen times rarer than that at the Surface of the Earth;
+and at the height of 22-1/2, 30, or 38 Miles, it is respectively 64,
+256, or 1024 times rarer, or thereabouts; and at the height of 76, 152,
+228 Miles, it is about 1000000, 1000000000000, or 1000000000000000000
+times rarer; and so on.
+
+Heat promotes Fluidity very much by diminishing the Tenacity of Bodies.
+It makes many Bodies fluid which are not fluid in cold, and increases
+the Fluidity of tenacious Liquids, as of Oil, Balsam, and Honey, and
+thereby decreases their Resistance. But it decreases not the Resistance
+of Water considerably, as it would do if any considerable part of the
+Resistance of Water arose from the Attrition or Tenacity of its Parts.
+And therefore the Resistance of Water arises principally and almost
+entirely from the _Vis inertiæ_ of its Matter; and by consequence, if
+the Heavens were as dense as Water, they would not have much less
+Resistance than Water; if as dense as Quick-silver, they would not have
+much less Resistance than Quick-silver; if absolutely dense, or full of
+Matter without any _Vacuum_, let the Matter be never so subtil and
+fluid, they would have a greater Resistance than Quick-silver. A solid
+Globe in such a Medium would lose above half its Motion in moving three
+times the length of its Diameter, and a Globe not solid (such as are the
+Planets,) would be retarded sooner. And therefore to make way for the
+regular and lasting Motions of the Planets and Comets, it's necessary to
+empty the Heavens of all Matter, except perhaps some very thin Vapours,
+Steams, or Effluvia, arising from the Atmospheres of the Earth, Planets,
+and Comets, and from such an exceedingly rare Æthereal Medium as we
+described above. A dense Fluid can be of no use for explaining the
+Phænomena of Nature, the Motions of the Planets and Comets being better
+explain'd without it. It serves only to disturb and retard the Motions
+of those great Bodies, and make the Frame of Nature languish: And in the
+Pores of Bodies, it serves only to stop the vibrating Motions of their
+Parts, wherein their Heat and Activity consists. And as it is of no use,
+and hinders the Operations of Nature, and makes her languish, so there
+is no evidence for its Existence, and therefore it ought to be rejected.
+And if it be rejected, the Hypotheses that Light consists in Pression
+or Motion, propagated through such a Medium, are rejected with it.
+
+And for rejecting such a Medium, we have the Authority of those the
+oldest and most celebrated Philosophers of _Greece_ and _Phoenicia_,
+who made a _Vacuum_, and Atoms, and the Gravity of Atoms, the first
+Principles of their Philosophy; tacitly attributing Gravity to some
+other Cause than dense Matter. Later Philosophers banish the
+Consideration of such a Cause out of natural Philosophy, feigning
+Hypotheses for explaining all things mechanically, and referring other
+Causes to Metaphysicks: Whereas the main Business of natural Philosophy
+is to argue from Phænomena without feigning Hypotheses, and to deduce
+Causes from Effects, till we come to the very first Cause, which
+certainly is not mechanical; and not only to unfold the Mechanism of the
+World, but chiefly to resolve these and such like Questions. What is
+there in places almost empty of Matter, and whence is it that the Sun
+and Planets gravitate towards one another, without dense Matter between
+them? Whence is it that Nature doth nothing in vain; and whence arises
+all that Order and Beauty which we see in the World? To what end are
+Comets, and whence is it that Planets move all one and the same way in
+Orbs concentrick, while Comets move all manner of ways in Orbs very
+excentrick; and what hinders the fix'd Stars from falling upon one
+another? How came the Bodies of Animals to be contrived with so much
+Art, and for what ends were their several Parts? Was the Eye contrived
+without Skill in Opticks, and the Ear without Knowledge of Sounds? How
+do the Motions of the Body follow from the Will, and whence is the
+Instinct in Animals? Is not the Sensory of Animals that place to which
+the sensitive Substance is present, and into which the sensible Species
+of Things are carried through the Nerves and Brain, that there they may
+be perceived by their immediate presence to that Substance? And these
+things being rightly dispatch'd, does it not appear from Phænomena that
+there is a Being incorporeal, living, intelligent, omnipresent, who in
+infinite Space, as it were in his Sensory, sees the things themselves
+intimately, and throughly perceives them, and comprehends them wholly by
+their immediate presence to himself: Of which things the Images only
+carried through the Organs of Sense into our little Sensoriums, are
+there seen and beheld by that which in us perceives and thinks. And
+though every true Step made in this Philosophy brings us not immediately
+to the Knowledge of the first Cause, yet it brings us nearer to it, and
+on that account is to be highly valued.
+
+_Qu._ 29. Are not the Rays of Light very small Bodies emitted from
+shining Substances? For such Bodies will pass through uniform Mediums in
+right Lines without bending into the Shadow, which is the Nature of the
+Rays of Light. They will also be capable of several Properties, and be
+able to conserve their Properties unchanged in passing through several
+Mediums, which is another Condition of the Rays of Light. Pellucid
+Substances act upon the Rays of Light at a distance in refracting,
+reflecting, and inflecting them, and the Rays mutually agitate the Parts
+of those Substances at a distance for heating them; and this Action and
+Re-action at a distance very much resembles an attractive Force between
+Bodies. If Refraction be perform'd by Attraction of the Rays, the Sines
+of Incidence must be to the Sines of Refraction in a given Proportion,
+as we shew'd in our Principles of Philosophy: And this Rule is true by
+Experience. The Rays of Light in going out of Glass into a _Vacuum_, are
+bent towards the Glass; and if they fall too obliquely on the _Vacuum_,
+they are bent backwards into the Glass, and totally reflected; and this
+Reflexion cannot be ascribed to the Resistance of an absolute _Vacuum_,
+but must be caused by the Power of the Glass attracting the Rays at
+their going out of it into the _Vacuum_, and bringing them back. For if
+the farther Surface of the Glass be moisten'd with Water or clear Oil,
+or liquid and clear Honey, the Rays which would otherwise be reflected
+will go into the Water, Oil, or Honey; and therefore are not reflected
+before they arrive at the farther Surface of the Glass, and begin to go
+out of it. If they go out of it into the Water, Oil, or Honey, they go
+on, because the Attraction of the Glass is almost balanced and rendered
+ineffectual by the contrary Attraction of the Liquor. But if they go out
+of it into a _Vacuum_ which has no Attraction to balance that of the
+Glass, the Attraction of the Glass either bends and refracts them, or
+brings them back and reflects them. And this is still more evident by
+laying together two Prisms of Glass, or two Object-glasses of very long
+Telescopes, the one plane, the other a little convex, and so compressing
+them that they do not fully touch, nor are too far asunder. For the
+Light which falls upon the farther Surface of the first Glass where the
+Interval between the Glasses is not above the ten hundred thousandth
+Part of an Inch, will go through that Surface, and through the Air or
+_Vacuum_ between the Glasses, and enter into the second Glass, as was
+explain'd in the first, fourth, and eighth Observations of the first
+Part of the second Book. But, if the second Glass be taken away, the
+Light which goes out of the second Surface of the first Glass into the
+Air or _Vacuum_, will not go on forwards, but turns back into the first
+Glass, and is reflected; and therefore it is drawn back by the Power of
+the first Glass, there being nothing else to turn it back. Nothing more
+is requisite for producing all the variety of Colours, and degrees of
+Refrangibility, than that the Rays of Light be Bodies of different
+Sizes, the least of which may take violet the weakest and darkest of the
+Colours, and be more easily diverted by refracting Surfaces from the
+right Course; and the rest as they are bigger and bigger, may make the
+stronger and more lucid Colours, blue, green, yellow, and red, and be
+more and more difficultly diverted. Nothing more is requisite for
+putting the Rays of Light into Fits of easy Reflexion and easy
+Transmission, than that they be small Bodies which by their attractive
+Powers, or some other Force, stir up Vibrations in what they act upon,
+which Vibrations being swifter than the Rays, overtake them
+successively, and agitate them so as by turns to increase and decrease
+their Velocities, and thereby put them into those Fits. And lastly, the
+unusual Refraction of Island-Crystal looks very much as if it were
+perform'd by some kind of attractive virtue lodged in certain Sides both
+of the Rays, and of the Particles of the Crystal. For were it not for
+some kind of Disposition or Virtue lodged in some Sides of the Particles
+of the Crystal, and not in their other Sides, and which inclines and
+bends the Rays towards the Coast of unusual Refraction, the Rays which
+fall perpendicularly on the Crystal, would not be refracted towards that
+Coast rather than towards any other Coast, both at their Incidence and
+at their Emergence, so as to emerge perpendicularly by a contrary
+Situation of the Coast of unusual Refraction at the second Surface; the
+Crystal acting upon the Rays after they have pass'd through it, and are
+emerging into the Air; or, if you please, into a _Vacuum_. And since the
+Crystal by this Disposition or Virtue does not act upon the Rays, unless
+when one of their Sides of unusual Refraction looks towards that Coast,
+this argues a Virtue or Disposition in those Sides of the Rays, which
+answers to, and sympathizes with that Virtue or Disposition of the
+Crystal, as the Poles of two Magnets answer to one another. And as
+Magnetism may be intended and remitted, and is found only in the Magnet
+and in Iron: So this Virtue of refracting the perpendicular Rays is
+greater in Island-Crystal, less in Crystal of the Rock, and is not yet
+found in other Bodies. I do not say that this Virtue is magnetical: It
+seems to be of another kind. I only say, that whatever it be, it's
+difficult to conceive how the Rays of Light, unless they be Bodies, can
+have a permanent Virtue in two of their Sides which is not in their
+other Sides, and this without any regard to their Position to the Space
+or Medium through which they pass.
+
+What I mean in this Question by a _Vacuum_, and by the Attractions of
+the Rays of Light towards Glass or Crystal, may be understood by what
+was said in the 18th, 19th, and 20th Questions.
+
+_Quest._ 30. Are not gross Bodies and Light convertible into one
+another, and may not Bodies receive much of their Activity from the
+Particles of Light which enter their Composition? For all fix'd Bodies
+being heated emit Light so long as they continue sufficiently hot, and
+Light mutually stops in Bodies as often as its Rays strike upon their
+Parts, as we shew'd above. I know no Body less apt to shine than Water;
+and yet Water by frequent Distillations changes into fix'd Earth, as Mr.
+_Boyle_ has try'd; and then this Earth being enabled to endure a
+sufficient Heat, shines by Heat like other Bodies.
+
+The changing of Bodies into Light, and Light into Bodies, is very
+conformable to the Course of Nature, which seems delighted with
+Transmutations. Water, which is a very fluid tasteless Salt, she changes
+by Heat into Vapour, which is a sort of Air, and by Cold into Ice, which
+is a hard, pellucid, brittle, fusible Stone; and this Stone returns into
+Water by Heat, and Vapour returns into Water by Cold. Earth by Heat
+becomes Fire, and by Cold returns into Earth. Dense Bodies by
+Fermentation rarify into several sorts of Air, and this Air by
+Fermentation, and sometimes without it, returns into dense Bodies.
+Mercury appears sometimes in the form of a fluid Metal, sometimes in the
+form of a hard brittle Metal, sometimes in the form of a corrosive
+pellucid Salt call'd Sublimate, sometimes in the form of a tasteless,
+pellucid, volatile white Earth, call'd _Mercurius Dulcis_; or in that of
+a red opake volatile Earth, call'd Cinnaber; or in that of a red or
+white Precipitate, or in that of a fluid Salt; and in Distillation it
+turns into Vapour, and being agitated _in Vacuo_, it shines like Fire.
+And after all these Changes it returns again into its first form of
+Mercury. Eggs grow from insensible Magnitudes, and change into Animals;
+Tadpoles into Frogs; and Worms into Flies. All Birds, Beasts and Fishes,
+Insects, Trees, and other Vegetables, with their several Parts, grow out
+of Water and watry Tinctures and Salts, and by Putrefaction return again
+into watry Substances. And Water standing a few Days in the open Air,
+yields a Tincture, which (like that of Malt) by standing longer yields a
+Sediment and a Spirit, but before Putrefaction is fit Nourishment for
+Animals and Vegetables. And among such various and strange
+Transmutations, why may not Nature change Bodies into Light, and Light
+into Bodies?
+
+_Quest._ 31. Have not the small Particles of Bodies certain Powers,
+Virtues, or Forces, by which they act at a distance, not only upon the
+Rays of Light for reflecting, refracting, and inflecting them, but also
+upon one another for producing a great Part of the Phænomena of Nature?
+For it's well known, that Bodies act one upon another by the Attractions
+of Gravity, Magnetism, and Electricity; and these Instances shew the
+Tenor and Course of Nature, and make it not improbable but that there
+may be more attractive Powers than these. For Nature is very consonant
+and conformable to her self. How these Attractions may be perform'd, I
+do not here consider. What I call Attraction may be perform'd by
+impulse, or by some other means unknown to me. I use that Word here to
+signify only in general any Force by which Bodies tend towards one
+another, whatsoever be the Cause. For we must learn from the Phænomena
+of Nature what Bodies attract one another, and what are the Laws and
+Properties of the Attraction, before we enquire the Cause by which the
+Attraction is perform'd. The Attractions of Gravity, Magnetism, and
+Electricity, reach to very sensible distances, and so have been observed
+by vulgar Eyes, and there may be others which reach to so small
+distances as hitherto escape Observation; and perhaps electrical
+Attraction may reach to such small distances, even without being excited
+by Friction.
+
+For when Salt of Tartar runs _per Deliquium_, is not this done by an
+Attraction between the Particles of the Salt of Tartar, and the
+Particles of the Water which float in the Air in the form of Vapours?
+And why does not common Salt, or Salt-petre, or Vitriol, run _per
+Deliquium_, but for want of such an Attraction? Or why does not Salt of
+Tartar draw more Water out of the Air than in a certain Proportion to
+its quantity, but for want of an attractive Force after it is satiated
+with Water? And whence is it but from this attractive Power that Water
+which alone distils with a gentle luke-warm Heat, will not distil from
+Salt of Tartar without a great Heat? And is it not from the like
+attractive Power between the Particles of Oil of Vitriol and the
+Particles of Water, that Oil of Vitriol draws to it a good quantity of
+Water out of the Air, and after it is satiated draws no more, and in
+Distillation lets go the Water very difficultly? And when Water and Oil
+of Vitriol poured successively into the same Vessel grow very hot in the
+mixing, does not this Heat argue a great Motion in the Parts of the
+Liquors? And does not this Motion argue, that the Parts of the two
+Liquors in mixing coalesce with Violence, and by consequence rush
+towards one another with an accelerated Motion? And when _Aqua fortis_,
+or Spirit of Vitriol poured upon Filings of Iron dissolves the Filings
+with a great Heat and Ebullition, is not this Heat and Ebullition
+effected by a violent Motion of the Parts, and does not that Motion
+argue that the acid Parts of the Liquor rush towards the Parts of the
+Metal with violence, and run forcibly into its Pores till they get
+between its outmost Particles, and the main Mass of the Metal, and
+surrounding those Particles loosen them from the main Mass, and set them
+at liberty to float off into the Water? And when the acid Particles,
+which alone would distil with an easy Heat, will not separate from the
+Particles of the Metal without a very violent Heat, does not this
+confirm the Attraction between them?
+
+When Spirit of Vitriol poured upon common Salt or Salt-petre makes an
+Ebullition with the Salt, and unites with it, and in Distillation the
+Spirit of the common Salt or Salt-petre comes over much easier than it
+would do before, and the acid part of the Spirit of Vitriol stays
+behind; does not this argue that the fix'd Alcaly of the Salt attracts
+the acid Spirit of the Vitriol more strongly than its own Spirit, and
+not being able to hold them both, lets go its own? And when Oil of
+Vitriol is drawn off from its weight of Nitre, and from both the
+Ingredients a compound Spirit of Nitre is distilled, and two parts of
+this Spirit are poured on one part of Oil of Cloves or Carraway Seeds,
+or of any ponderous Oil of vegetable or animal Substances, or Oil of
+Turpentine thicken'd with a little Balsam of Sulphur, and the Liquors
+grow so very hot in mixing, as presently to send up a burning Flame;
+does not this very great and sudden Heat argue that the two Liquors mix
+with violence, and that their Parts in mixing run towards one another
+with an accelerated Motion, and clash with the greatest Force? And is it
+not for the same reason that well rectified Spirit of Wine poured on the
+same compound Spirit flashes; and that the _Pulvis fulminans_, composed
+of Sulphur, Nitre, and Salt of Tartar, goes off with a more sudden and
+violent Explosion than Gun-powder, the acid Spirits of the Sulphur and
+Nitre rushing towards one another, and towards the Salt of Tartar, with
+so great a violence, as by the shock to turn the whole at once into
+Vapour and Flame? Where the Dissolution is slow, it makes a slow
+Ebullition and a gentle Heat; and where it is quicker, it makes a
+greater Ebullition with more heat; and where it is done at once, the
+Ebullition is contracted into a sudden Blast or violent Explosion, with
+a heat equal to that of Fire and Flame. So when a Drachm of the
+above-mention'd compound Spirit of Nitre was poured upon half a Drachm
+of Oil of Carraway Seeds _in vacuo_, the Mixture immediately made a
+flash like Gun-powder, and burst the exhausted Receiver, which was a
+Glass six Inches wide, and eight Inches deep. And even the gross Body of
+Sulphur powder'd, and with an equal weight of Iron Filings and a little
+Water made into Paste, acts upon the Iron, and in five or six hours
+grows too hot to be touch'd, and emits a Flame. And by these Experiments
+compared with the great quantity of Sulphur with which the Earth
+abounds, and the warmth of the interior Parts of the Earth, and hot
+Springs, and burning Mountains, and with Damps, mineral Coruscations,
+Earthquakes, hot suffocating Exhalations, Hurricanes, and Spouts; we may
+learn that sulphureous Steams abound in the Bowels of the Earth and
+ferment with Minerals, and sometimes take fire with a sudden Coruscation
+and Explosion; and if pent up in subterraneous Caverns, burst the
+Caverns with a great shaking of the Earth, as in springing of a Mine.
+And then the Vapour generated by the Explosion, expiring through the
+Pores of the Earth, feels hot and suffocates, and makes Tempests and
+Hurricanes, and sometimes causes the Land to slide, or the Sea to boil,
+and carries up the Water thereof in Drops, which by their weight fall
+down again in Spouts. Also some sulphureous Steams, at all times when
+the Earth is dry, ascending into the Air, ferment there with nitrous
+Acids, and sometimes taking fire cause Lightning and Thunder, and fiery
+Meteors. For the Air abounds with acid Vapours fit to promote
+Fermentations, as appears by the rusting of Iron and Copper in it, the
+kindling of Fire by blowing, and the beating of the Heart by means of
+Respiration. Now the above-mention'd Motions are so great and violent as
+to shew that in Fermentations the Particles of Bodies which almost rest,
+are put into new Motions by a very potent Principle, which acts upon
+them only when they approach one another, and causes them to meet and
+clash with great violence, and grow hot with the motion, and dash one
+another into pieces, and vanish into Air, and Vapour, and Flame.
+
+When Salt of Tartar _per deliquium_, being poured into the Solution of
+any Metal, precipitates the Metal and makes it fall down to the bottom
+of the Liquor in the form of Mud: Does not this argue that the acid
+Particles are attracted more strongly by the Salt of Tartar than by the
+Metal, and by the stronger Attraction go from the Metal to the Salt of
+Tartar? And so when a Solution of Iron in _Aqua fortis_ dissolves the
+_Lapis Calaminaris_, and lets go the Iron, or a Solution of Copper
+dissolves Iron immersed in it and lets go the Copper, or a Solution of
+Silver dissolves Copper and lets go the Silver, or a Solution of Mercury
+in _Aqua fortis_ being poured upon Iron, Copper, Tin, or Lead, dissolves
+the Metal and lets go the Mercury; does not this argue that the acid
+Particles of the _Aqua fortis_ are attracted more strongly by the _Lapis
+Calaminaris_ than by Iron, and more strongly by Iron than by Copper, and
+more strongly by Copper than by Silver, and more strongly by Iron,
+Copper, Tin, and Lead, than by Mercury? And is it not for the same
+reason that Iron requires more _Aqua fortis_ to dissolve it than Copper,
+and Copper more than the other Metals; and that of all Metals, Iron is
+dissolved most easily, and is most apt to rust; and next after Iron,
+Copper?
+
+When Oil of Vitriol is mix'd with a little Water, or is run _per
+deliquium_, and in Distillation the Water ascends difficultly, and
+brings over with it some part of the Oil of Vitriol in the form of
+Spirit of Vitriol, and this Spirit being poured upon Iron, Copper, or
+Salt of Tartar, unites with the Body and lets go the Water; doth not
+this shew that the acid Spirit is attracted by the Water, and more
+attracted by the fix'd Body than by the Water, and therefore lets go the
+Water to close with the fix'd Body? And is it not for the same reason
+that the Water and acid Spirits which are mix'd together in Vinegar,
+_Aqua fortis_, and Spirit of Salt, cohere and rise together in
+Distillation; but if the _Menstruum_ be poured on Salt of Tartar, or on
+Lead, or Iron, or any fix'd Body which it can dissolve, the Acid by a
+stronger Attraction adheres to the Body, and lets go the Water? And is
+it not also from a mutual Attraction that the Spirits of Soot and
+Sea-Salt unite and compose the Particles of Sal-armoniac, which are less
+volatile than before, because grosser and freer from Water; and that the
+Particles of Sal-armoniac in Sublimation carry up the Particles of
+Antimony, which will not sublime alone; and that the Particles of
+Mercury uniting with the acid Particles of Spirit of Salt compose
+Mercury sublimate, and with the Particles of Sulphur, compose Cinnaber;
+and that the Particles of Spirit of Wine and Spirit of Urine well
+rectified unite, and letting go the Water which dissolved them, compose
+a consistent Body; and that in subliming Cinnaber from Salt of Tartar,
+or from quick Lime, the Sulphur by a stronger Attraction of the Salt or
+Lime lets go the Mercury, and stays with the fix'd Body; and that when
+Mercury sublimate is sublimed from Antimony, or from Regulus of
+Antimony, the Spirit of Salt lets go the Mercury, and unites with the
+antimonial metal which attracts it more strongly, and stays with it till
+the Heat be great enough to make them both ascend together, and then
+carries up the Metal with it in the form of a very fusible Salt, called
+Butter of Antimony, although the Spirit of Salt alone be almost as
+volatile as Water, and the Antimony alone as fix'd as Lead?
+
+When _Aqua fortis_ dissolves Silver and not Gold, and _Aqua regia_
+dissolves Gold and not Silver, may it not be said that _Aqua fortis_ is
+subtil enough to penetrate Gold as well as Silver, but wants the
+attractive Force to give it Entrance; and that _Aqua regia_ is subtil
+enough to penetrate Silver as well as Gold, but wants the attractive
+Force to give it Entrance? For _Aqua regia_ is nothing else than _Aqua
+fortis_ mix'd with some Spirit of Salt, or with Sal-armoniac; and even
+common Salt dissolved in _Aqua fortis_, enables the _Menstruum_ to
+dissolve Gold, though the Salt be a gross Body. When therefore Spirit of
+Salt precipitates Silver out of _Aqua fortis_, is it not done by
+attracting and mixing with the _Aqua fortis_, and not attracting, or
+perhaps repelling Silver? And when Water precipitates Antimony out of
+the Sublimate of Antimony and Sal-armoniac, or out of Butter of
+Antimony, is it not done by its dissolving, mixing with, and weakening
+the Sal-armoniac or Spirit of Salt, and its not attracting, or perhaps
+repelling the Antimony? And is it not for want of an attractive virtue
+between the Parts of Water and Oil, of Quick-silver and Antimony, of
+Lead and Iron, that these Substances do not mix; and by a weak
+Attraction, that Quick-silver and Copper mix difficultly; and from a
+strong one, that Quick-silver and Tin, Antimony and Iron, Water and
+Salts, mix readily? And in general, is it not from the same Principle
+that Heat congregates homogeneal Bodies, and separates heterogeneal
+ones?
+
+When Arsenick with Soap gives a Regulus, and with Mercury sublimate a
+volatile fusible Salt, like Butter of Antimony, doth not this shew that
+Arsenick, which is a Substance totally volatile, is compounded of fix'd
+and volatile Parts, strongly cohering by a mutual Attraction, so that
+the volatile will not ascend without carrying up the fixed? And so, when
+an equal weight of Spirit of Wine and Oil of Vitriol are digested
+together, and in Distillation yield two fragrant and volatile Spirits
+which will not mix with one another, and a fix'd black Earth remains
+behind; doth not this shew that Oil of Vitriol is composed of volatile
+and fix'd Parts strongly united by Attraction, so as to ascend together
+in form of a volatile, acid, fluid Salt, until the Spirit of Wine
+attracts and separates the volatile Parts from the fixed? And therefore,
+since Oil of Sulphur _per Campanam_ is of the same Nature with Oil of
+Vitriol, may it not be inferred, that Sulphur is also a mixture of
+volatile and fix'd Parts so strongly cohering by Attraction, as to
+ascend together in Sublimation. By dissolving Flowers of Sulphur in Oil
+of Turpentine, and distilling the Solution, it is found that Sulphur is
+composed of an inflamable thick Oil or fat Bitumen, an acid Salt, a very
+fix'd Earth, and a little Metal. The three first were found not much
+unequal to one another, the fourth in so small a quantity as scarce to
+be worth considering. The acid Salt dissolved in Water, is the same with
+Oil of Sulphur _per Campanam_, and abounding much in the Bowels of the
+Earth, and particularly in Markasites, unites it self to the other
+Ingredients of the Markasite, which are, Bitumen, Iron, Copper, and
+Earth, and with them compounds Allum, Vitriol, and Sulphur. With the
+Earth alone it compounds Allum; with the Metal alone, or Metal and
+Earth together, it compounds Vitriol; and with the Bitumen and Earth it
+compounds Sulphur. Whence it comes to pass that Markasites abound with
+those three Minerals. And is it not from the mutual Attraction of the
+Ingredients that they stick together for compounding these Minerals, and
+that the Bitumen carries up the other Ingredients of the Sulphur, which
+without it would not sublime? And the same Question may be put
+concerning all, or almost all the gross Bodies in Nature. For all the
+Parts of Animals and Vegetables are composed of Substances volatile and
+fix'd, fluid and solid, as appears by their Analysis; and so are Salts
+and Minerals, so far as Chymists have been hitherto able to examine
+their Composition.
+
+When Mercury sublimate is re-sublimed with fresh Mercury, and becomes
+_Mercurius Dulcis_, which is a white tasteless Earth scarce dissolvable
+in Water, and _Mercurius Dulcis_ re-sublimed with Spirit of Salt returns
+into Mercury sublimate; and when Metals corroded with a little acid turn
+into rust, which is an Earth tasteless and indissolvable in Water, and
+this Earth imbibed with more acid becomes a metallick Salt; and when
+some Stones, as Spar of Lead, dissolved in proper _Menstruums_ become
+Salts; do not these things shew that Salts are dry Earth and watry Acid
+united by Attraction, and that the Earth will not become a Salt without
+so much acid as makes it dissolvable in Water? Do not the sharp and
+pungent Tastes of Acids arise from the strong Attraction whereby the
+acid Particles rush upon and agitate the Particles of the Tongue? And
+when Metals are dissolved in acid _Menstruums_, and the Acids in
+conjunction with the Metal act after a different manner, so that the
+Compound has a different Taste much milder than before, and sometimes a
+sweet one; is it not because the Acids adhere to the metallick
+Particles, and thereby lose much of their Activity? And if the Acid be
+in too small a Proportion to make the Compound dissolvable in Water,
+will it not by adhering strongly to the Metal become unactive and lose
+its Taste, and the Compound be a tasteless Earth? For such things as are
+not dissolvable by the Moisture of the Tongue, act not upon the Taste.
+
+As Gravity makes the Sea flow round the denser and weightier Parts of
+the Globe of the Earth, so the Attraction may make the watry Acid flow
+round the denser and compacter Particles of Earth for composing the
+Particles of Salt. For otherwise the Acid would not do the Office of a
+Medium between the Earth and common Water, for making Salts dissolvable
+in the Water; nor would Salt of Tartar readily draw off the Acid from
+dissolved Metals, nor Metals the Acid from Mercury. Now, as in the great
+Globe of the Earth and Sea, the densest Bodies by their Gravity sink
+down in Water, and always endeavour to go towards the Center of the
+Globe; so in Particles of Salt, the densest Matter may always endeavour
+to approach the Center of the Particle: So that a Particle of Salt may
+be compared to a Chaos; being dense, hard, dry, and earthy in the
+Center; and rare, soft, moist, and watry in the Circumference. And
+hence it seems to be that Salts are of a lasting Nature, being scarce
+destroy'd, unless by drawing away their watry Parts by violence, or by
+letting them soak into the Pores of the central Earth by a gentle Heat
+in Putrefaction, until the Earth be dissolved by the Water, and
+separated into smaller Particles, which by reason of their Smallness
+make the rotten Compound appear of a black Colour. Hence also it may be,
+that the Parts of Animals and Vegetables preserve their several Forms,
+and assimilate their Nourishment; the soft and moist Nourishment easily
+changing its Texture by a gentle Heat and Motion, till it becomes like
+the dense, hard, dry, and durable Earth in the Center of each Particle.
+But when the Nourishment grows unfit to be assimilated, or the central
+Earth grows too feeble to assimilate it, the Motion ends in Confusion,
+Putrefaction, and Death.
+
+If a very small quantity of any Salt or Vitriol be dissolved in a great
+quantity of Water, the Particles of the Salt or Vitriol will not sink to
+the bottom, though they be heavier in Specie than the Water, but will
+evenly diffuse themselves into all the Water, so as to make it as saline
+at the top as at the bottom. And does not this imply that the Parts of
+the Salt or Vitriol recede from one another, and endeavour to expand
+themselves, and get as far asunder as the quantity of Water in which
+they float, will allow? And does not this Endeavour imply that they have
+a repulsive Force by which they fly from one another, or at least, that
+they attract the Water more strongly than they do one another? For as
+all things ascend in Water which are less attracted than Water, by the
+gravitating Power of the Earth; so all the Particles of Salt which float
+in Water, and are less attracted than Water by any one Particle of Salt,
+must recede from that Particle, and give way to the more attracted
+Water.
+
+When any saline Liquor is evaporated to a Cuticle and let cool, the Salt
+concretes in regular Figures; which argues, that the Particles of the
+Salt before they concreted, floated in the Liquor at equal distances in
+rank and file, and by consequence that they acted upon one another by
+some Power which at equal distances is equal, at unequal distances
+unequal. For by such a Power they will range themselves uniformly, and
+without it they will float irregularly, and come together as
+irregularly. And since the Particles of Island-Crystal act all the same
+way upon the Rays of Light for causing the unusual Refraction, may it
+not be supposed that in the Formation of this Crystal, the Particles not
+only ranged themselves in rank and file for concreting in regular
+Figures, but also by some kind of polar Virtue turned their homogeneal
+Sides the same way.
+
+The Parts of all homogeneal hard Bodies which fully touch one another,
+stick together very strongly. And for explaining how this may be, some
+have invented hooked Atoms, which is begging the Question; and others
+tell us that Bodies are glued together by rest, that is, by an occult
+Quality, or rather by nothing; and others, that they stick together by
+conspiring Motions, that is, by relative rest amongst themselves. I had
+rather infer from their Cohesion, that their Particles attract one
+another by some Force, which in immediate Contact is exceeding strong,
+at small distances performs the chymical Operations above-mention'd, and
+reaches not far from the Particles with any sensible Effect.
+
+All Bodies seem to be composed of hard Particles: For otherwise Fluids
+would not congeal; as Water, Oils, Vinegar, and Spirit or Oil of Vitriol
+do by freezing; Mercury by Fumes of Lead; Spirit of Nitre and Mercury,
+by dissolving the Mercury and evaporating the Flegm; Spirit of Wine and
+Spirit of Urine, by deflegming and mixing them; and Spirit of Urine and
+Spirit of Salt, by subliming them together to make Sal-armoniac. Even
+the Rays of Light seem to be hard Bodies; for otherwise they would not
+retain different Properties in their different Sides. And therefore
+Hardness may be reckon'd the Property of all uncompounded Matter. At
+least, this seems to be as evident as the universal Impenetrability of
+Matter. For all Bodies, so far as Experience reaches, are either hard,
+or may be harden'd; and we have no other Evidence of universal
+Impenetrability, besides a large Experience without an experimental
+Exception. Now if compound Bodies are so very hard as we find some of
+them to be, and yet are very porous, and consist of Parts which are only
+laid together; the simple Particles which are void of Pores, and were
+never yet divided, must be much harder. For such hard Particles being
+heaped up together, can scarce touch one another in more than a few
+Points, and therefore must be separable by much less Force than is
+requisite to break a solid Particle, whose Parts touch in all the Space
+between them, without any Pores or Interstices to weaken their Cohesion.
+And how such very hard Particles which are only laid together and touch
+only in a few Points, can stick together, and that so firmly as they do,
+without the assistance of something which causes them to be attracted or
+press'd towards one another, is very difficult to conceive.
+
+The same thing I infer also from the cohering of two polish'd Marbles
+_in vacuo_, and from the standing of Quick-silver in the Barometer at
+the height of 50, 60 or 70 Inches, or above, when ever it is well-purged
+of Air and carefully poured in, so that its Parts be every where
+contiguous both to one another and to the Glass. The Atmosphere by its
+weight presses the Quick-silver into the Glass, to the height of 29 or
+30 Inches. And some other Agent raises it higher, not by pressing it
+into the Glass, but by making its Parts stick to the Glass, and to one
+another. For upon any discontinuation of Parts, made either by Bubbles
+or by shaking the Glass, the whole Mercury falls down to the height of
+29 or 30 Inches.
+
+And of the same kind with these Experiments are those that follow. If
+two plane polish'd Plates of Glass (suppose two pieces of a polish'd
+Looking-glass) be laid together, so that their sides be parallel and at
+a very small distance from one another, and then their lower edges be
+dipped into Water, the Water will rise up between them. And the less
+the distance of the Glasses is, the greater will be the height to which
+the Water will rise. If the distance be about the hundredth part of an
+Inch, the Water will rise to the height of about an Inch; and if the
+distance be greater or less in any Proportion, the height will be
+reciprocally proportional to the distance very nearly. For the
+attractive Force of the Glasses is the same, whether the distance
+between them be greater or less; and the weight of the Water drawn up is
+the same, if the height of it be reciprocally proportional to the
+distance of the Glasses. And in like manner, Water ascends between two
+Marbles polish'd plane, when their polish'd sides are parallel, and at a
+very little distance from one another, And if slender Pipes of Glass be
+dipped at one end into stagnating Water, the Water will rise up within
+the Pipe, and the height to which it rises will be reciprocally
+proportional to the Diameter of the Cavity of the Pipe, and will equal
+the height to which it rises between two Planes of Glass, if the
+Semi-diameter of the Cavity of the Pipe be equal to the distance between
+the Planes, or thereabouts. And these Experiments succeed after the same
+manner _in vacuo_ as in the open Air, (as hath been tried before the
+Royal Society,) and therefore are not influenced by the Weight or
+Pressure of the Atmosphere.
+
+And if a large Pipe of Glass be filled with sifted Ashes well pressed
+together in the Glass, and one end of the Pipe be dipped into stagnating
+Water, the Water will rise up slowly in the Ashes, so as in the space
+of a Week or Fortnight to reach up within the Glass, to the height of 30
+or 40 Inches above the stagnating Water. And the Water rises up to this
+height by the Action only of those Particles of the Ashes which are upon
+the Surface of the elevated Water; the Particles which are within the
+Water, attracting or repelling it as much downwards as upwards. And
+therefore the Action of the Particles is very strong. But the Particles
+of the Ashes being not so dense and close together as those of Glass,
+their Action is not so strong as that of Glass, which keeps Quick-silver
+suspended to the height of 60 or 70 Inches, and therefore acts with a
+Force which would keep Water suspended to the height of above 60 Feet.
+
+By the same Principle, a Sponge sucks in Water, and the Glands in the
+Bodies of Animals, according to their several Natures and Dispositions,
+suck in various Juices from the Blood.
+
+If two plane polish'd Plates of Glass three or four Inches broad, and
+twenty or twenty five long, be laid one of them parallel to the Horizon,
+the other upon the first, so as at one of their ends to touch one
+another, and contain an Angle of about 10 or 15 Minutes, and the same be
+first moisten'd on their inward sides with a clean Cloth dipp'd into Oil
+of Oranges or Spirit of Turpentine, and a Drop or two of the Oil or
+Spirit be let fall upon the lower Glass at the other; so soon as the
+upper Glass is laid down upon the lower, so as to touch it at one end as
+above, and to touch the Drop at the other end, making with the lower
+Glass an Angle of about 10 or 15 Minutes; the Drop will begin to move
+towards the Concourse of the Glasses, and will continue to move with an
+accelerated Motion, till it arrives at that Concourse of the Glasses.
+For the two Glasses attract the Drop, and make it run that way towards
+which the Attractions incline. And if when the Drop is in motion you
+lift up that end of the Glasses where they meet, and towards which the
+Drop moves, the Drop will ascend between the Glasses, and therefore is
+attracted. And as you lift up the Glasses more and more, the Drop will
+ascend slower and slower, and at length rest, being then carried
+downward by its Weight, as much as upwards by the Attraction. And by
+this means you may know the Force by which the Drop is attracted at all
+distances from the Concourse of the Glasses.
+
+Now by some Experiments of this kind, (made by Mr. _Hauksbee_) it has
+been found that the Attraction is almost reciprocally in a duplicate
+Proportion of the distance of the middle of the Drop from the Concourse
+of the Glasses, _viz._ reciprocally in a simple Proportion, by reason of
+the spreading of the Drop, and its touching each Glass in a larger
+Surface; and again reciprocally in a simple Proportion, by reason of the
+Attractions growing stronger within the same quantity of attracting
+Surface. The Attraction therefore within the same quantity of attracting
+Surface, is reciprocally as the distance between the Glasses. And
+therefore where the distance is exceeding small, the Attraction must be
+exceeding great. By the Table in the second Part of the second Book,
+wherein the thicknesses of colour'd Plates of Water between two Glasses
+are set down, the thickness of the Plate where it appears very black, is
+three eighths of the ten hundred thousandth part of an Inch. And where
+the Oil of Oranges between the Glasses is of this thickness, the
+Attraction collected by the foregoing Rule, seems to be so strong, as
+within a Circle of an Inch in diameter, to suffice to hold up a Weight
+equal to that of a Cylinder of Water of an Inch in diameter, and two or
+three Furlongs in length. And where it is of a less thickness the
+Attraction may be proportionally greater, and continue to increase,
+until the thickness do not exceed that of a single Particle of the Oil.
+There are therefore Agents in Nature able to make the Particles of
+Bodies stick together by very strong Attractions. And it is the Business
+of experimental Philosophy to find them out.
+
+Now the smallest Particles of Matter may cohere by the strongest
+Attractions, and compose bigger Particles of weaker Virtue; and many of
+these may cohere and compose bigger Particles whose Virtue is still
+weaker, and so on for divers Successions, until the Progression end in
+the biggest Particles on which the Operations in Chymistry, and the
+Colours of natural Bodies depend, and which by cohering compose Bodies
+of a sensible Magnitude. If the Body is compact, and bends or yields
+inward to Pression without any sliding of its Parts, it is hard and
+elastick, returning to its Figure with a Force rising from the mutual
+Attraction of its Parts. If the Parts slide upon one another, the Body
+is malleable or soft. If they slip easily, and are of a fit Size to be
+agitated by Heat, and the Heat is big enough to keep them in Agitation,
+the Body is fluid; and if it be apt to stick to things, it is humid; and
+the Drops of every fluid affect a round Figure by the mutual Attraction
+of their Parts, as the Globe of the Earth and Sea affects a round Figure
+by the mutual Attraction of its Parts by Gravity.
+
+Since Metals dissolved in Acids attract but a small quantity of the
+Acid, their attractive Force can reach but to a small distance from
+them. And as in Algebra, where affirmative Quantities vanish and cease,
+there negative ones begin; so in Mechanicks, where Attraction ceases,
+there a repulsive Virtue ought to succeed. And that there is such a
+Virtue, seems to follow from the Reflexions and Inflexions of the Rays
+of Light. For the Rays are repelled by Bodies in both these Cases,
+without the immediate Contact of the reflecting or inflecting Body. It
+seems also to follow from the Emission of Light; the Ray so soon as it
+is shaken off from a shining Body by the vibrating Motion of the Parts
+of the Body, and gets beyond the reach of Attraction, being driven away
+with exceeding great Velocity. For that Force which is sufficient to
+turn it back in Reflexion, may be sufficient to emit it. It seems also
+to follow from the Production of Air and Vapour. The Particles when they
+are shaken off from Bodies by Heat or Fermentation, so soon as they are
+beyond the reach of the Attraction of the Body, receding from it, and
+also from one another with great Strength, and keeping at a distance,
+so as sometimes to take up above a Million of Times more space than they
+did before in the form of a dense Body. Which vast Contraction and
+Expansion seems unintelligible, by feigning the Particles of Air to be
+springy and ramous, or rolled up like Hoops, or by any other means than
+a repulsive Power. The Particles of Fluids which do not cohere too
+strongly, and are of such a Smallness as renders them most susceptible
+of those Agitations which keep Liquors in a Fluor, are most easily
+separated and rarified into Vapour, and in the Language of the Chymists,
+they are volatile, rarifying with an easy Heat, and condensing with
+Cold. But those which are grosser, and so less susceptible of Agitation,
+or cohere by a stronger Attraction, are not separated without a stronger
+Heat, or perhaps not without Fermentation. And these last are the Bodies
+which Chymists call fix'd, and being rarified by Fermentation, become
+true permanent Air; those Particles receding from one another with the
+greatest Force, and being most difficultly brought together, which upon
+Contact cohere most strongly. And because the Particles of permanent Air
+are grosser, and arise from denser Substances than those of Vapours,
+thence it is that true Air is more ponderous than Vapour, and that a
+moist Atmosphere is lighter than a dry one, quantity for quantity. From
+the same repelling Power it seems to be that Flies walk upon the Water
+without wetting their Feet; and that the Object-glasses of long
+Telescopes lie upon one another without touching; and that dry Powders
+are difficultly made to touch one another so as to stick together,
+unless by melting them, or wetting them with Water, which by exhaling
+may bring them together; and that two polish'd Marbles, which by
+immediate Contact stick together, are difficultly brought so close
+together as to stick.
+
+And thus Nature will be very conformable to her self and very simple,
+performing all the great Motions of the heavenly Bodies by the
+Attraction of Gravity which intercedes those Bodies, and almost all the
+small ones of their Particles by some other attractive and repelling
+Powers which intercede the Particles. The _Vis inertiæ_ is a passive
+Principle by which Bodies persist in their Motion or Rest, receive
+Motion in proportion to the Force impressing it, and resist as much as
+they are resisted. By this Principle alone there never could have been
+any Motion in the World. Some other Principle was necessary for putting
+Bodies into Motion; and now they are in Motion, some other Principle is
+necessary for conserving the Motion. For from the various Composition of
+two Motions, 'tis very certain that there is not always the same
+quantity of Motion in the World. For if two Globes joined by a slender
+Rod, revolve about their common Center of Gravity with an uniform
+Motion, while that Center moves on uniformly in a right Line drawn in
+the Plane of their circular Motion; the Sum of the Motions of the two
+Globes, as often as the Globes are in the right Line described by their
+common Center of Gravity, will be bigger than the Sum of their Motions,
+when they are in a Line perpendicular to that right Line. By this
+Instance it appears that Motion may be got or lost. But by reason of the
+Tenacity of Fluids, and Attrition of their Parts, and the Weakness of
+Elasticity in Solids, Motion is much more apt to be lost than got, and
+is always upon the Decay. For Bodies which are either absolutely hard,
+or so soft as to be void of Elasticity, will not rebound from one
+another. Impenetrability makes them only stop. If two equal Bodies meet
+directly _in vacuo_, they will by the Laws of Motion stop where they
+meet, and lose all their Motion, and remain in rest, unless they be
+elastick, and receive new Motion from their Spring. If they have so much
+Elasticity as suffices to make them re-bound with a quarter, or half, or
+three quarters of the Force with which they come together, they will
+lose three quarters, or half, or a quarter of their Motion. And this may
+be try'd, by letting two equal Pendulums fall against one another from
+equal heights. If the Pendulums be of Lead or soft Clay, they will lose
+all or almost all their Motions: If of elastick Bodies they will lose
+all but what they recover from their Elasticity. If it be said, that
+they can lose no Motion but what they communicate to other Bodies, the
+consequence is, that _in vacuo_ they can lose no Motion, but when they
+meet they must go on and penetrate one another's Dimensions. If three
+equal round Vessels be filled, the one with Water, the other with Oil,
+the third with molten Pitch, and the Liquors be stirred about alike to
+give them a vortical Motion; the Pitch by its Tenacity will lose its
+Motion quickly, the Oil being less tenacious will keep it longer, and
+the Water being less tenacious will keep it longest, but yet will lose
+it in a short time. Whence it is easy to understand, that if many
+contiguous Vortices of molten Pitch were each of them as large as those
+which some suppose to revolve about the Sun and fix'd Stars, yet these
+and all their Parts would, by their Tenacity and Stiffness, communicate
+their Motion to one another till they all rested among themselves.
+Vortices of Oil or Water, or some fluider Matter, might continue longer
+in Motion; but unless the Matter were void of all Tenacity and Attrition
+of Parts, and Communication of Motion, (which is not to be supposed,)
+the Motion would constantly decay. Seeing therefore the variety of
+Motion which we find in the World is always decreasing, there is a
+necessity of conserving and recruiting it by active Principles, such as
+are the cause of Gravity, by which Planets and Comets keep their Motions
+in their Orbs, and Bodies acquire great Motion in falling; and the cause
+of Fermentation, by which the Heart and Blood of Animals are kept in
+perpetual Motion and Heat; the inward Parts of the Earth are constantly
+warm'd, and in some places grow very hot; Bodies burn and shine,
+Mountains take fire, the Caverns of the Earth are blown up, and the Sun
+continues violently hot and lucid, and warms all things by his Light.
+For we meet with very little Motion in the World, besides what is owing
+to these active Principles. And if it were not for these Principles, the
+Bodies of the Earth, Planets, Comets, Sun, and all things in them,
+would grow cold and freeze, and become inactive Masses; and all
+Putrefaction, Generation, Vegetation and Life would cease, and the
+Planets and Comets would not remain in their Orbs.
+
+All these things being consider'd, it seems probable to me, that God in
+the Beginning form'd Matter in solid, massy, hard, impenetrable,
+moveable Particles, of such Sizes and Figures, and with such other
+Properties, and in such Proportion to Space, as most conduced to the End
+for which he form'd them; and that these primitive Particles being
+Solids, are incomparably harder than any porous Bodies compounded of
+them; even so very hard, as never to wear or break in pieces; no
+ordinary Power being able to divide what God himself made one in the
+first Creation. While the Particles continue entire, they may compose
+Bodies of one and the same Nature and Texture in all Ages: But should
+they wear away, or break in pieces, the Nature of Things depending on
+them, would be changed. Water and Earth, composed of old worn Particles
+and Fragments of Particles, would not be of the same Nature and Texture
+now, with Water and Earth composed of entire Particles in the Beginning.
+And therefore, that Nature may be lasting, the Changes of corporeal
+Things are to be placed only in the various Separations and new
+Associations and Motions of these permanent Particles; compound Bodies
+being apt to break, not in the midst of solid Particles, but where those
+Particles are laid together, and only touch in a few Points.
+
+It seems to me farther, that these Particles have not only a _Vis
+inertiæ_, accompanied with such passive Laws of Motion as naturally
+result from that Force, but also that they are moved by certain active
+Principles, such as is that of Gravity, and that which causes
+Fermentation, and the Cohesion of Bodies. These Principles I consider,
+not as occult Qualities, supposed to result from the specifick Forms of
+Things, but as general Laws of Nature, by which the Things themselves
+are form'd; their Truth appearing to us by Phænomena, though their
+Causes be not yet discover'd. For these are manifest Qualities, and
+their Causes only are occult. And the _Aristotelians_ gave the Name of
+occult Qualities, not to manifest Qualities, but to such Qualities only
+as they supposed to lie hid in Bodies, and to be the unknown Causes of
+manifest Effects: Such as would be the Causes of Gravity, and of
+magnetick and electrick Attractions, and of Fermentations, if we should
+suppose that these Forces or Actions arose from Qualities unknown to us,
+and uncapable of being discovered and made manifest. Such occult
+Qualities put a stop to the Improvement of natural Philosophy, and
+therefore of late Years have been rejected. To tell us that every
+Species of Things is endow'd with an occult specifick Quality by which
+it acts and produces manifest Effects, is to tell us nothing: But to
+derive two or three general Principles of Motion from Phænomena, and
+afterwards to tell us how the Properties and Actions of all corporeal
+Things follow from those manifest Principles, would be a very great step
+in Philosophy, though the Causes of those Principles were not yet
+discover'd: And therefore I scruple not to propose the Principles of
+Motion above-mention'd, they being of very general Extent, and leave
+their Causes to be found out.
+
+Now by the help of these Principles, all material Things seem to have
+been composed of the hard and solid Particles above-mention'd, variously
+associated in the first Creation by the Counsel of an intelligent Agent.
+For it became him who created them to set them in order. And if he did
+so, it's unphilosophical to seek for any other Origin of the World, or
+to pretend that it might arise out of a Chaos by the mere Laws of
+Nature; though being once form'd, it may continue by those Laws for many
+Ages. For while Comets move in very excentrick Orbs in all manner of
+Positions, blind Fate could never make all the Planets move one and the
+same way in Orbs concentrick, some inconsiderable Irregularities
+excepted, which may have risen from the mutual Actions of Comets and
+Planets upon one another, and which will be apt to increase, till this
+System wants a Reformation. Such a wonderful Uniformity in the Planetary
+System must be allowed the Effect of Choice. And so must the Uniformity
+in the Bodies of Animals, they having generally a right and a left side
+shaped alike, and on either side of their Bodies two Legs behind, and
+either two Arms, or two Legs, or two Wings before upon their Shoulders,
+and between their Shoulders a Neck running down into a Back-bone, and a
+Head upon it; and in the Head two Ears, two Eyes, a Nose, a Mouth, and
+a Tongue, alike situated. Also the first Contrivance of those very
+artificial Parts of Animals, the Eyes, Ears, Brain, Muscles, Heart,
+Lungs, Midriff, Glands, Larynx, Hands, Wings, swimming Bladders, natural
+Spectacles, and other Organs of Sense and Motion; and the Instinct of
+Brutes and Insects, can be the effect of nothing else than the Wisdom
+and Skill of a powerful ever-living Agent, who being in all Places, is
+more able by his Will to move the Bodies within his boundless uniform
+Sensorium, and thereby to form and reform the Parts of the Universe,
+than we are by our Will to move the Parts of our own Bodies. And yet we
+are not to consider the World as the Body of God, or the several Parts
+thereof, as the Parts of God. He is an uniform Being, void of Organs,
+Members or Parts, and they are his Creatures subordinate to him, and
+subservient to his Will; and he is no more the Soul of them, than the
+Soul of Man is the Soul of the Species of Things carried through the
+Organs of Sense into the place of its Sensation, where it perceives them
+by means of its immediate Presence, without the Intervention of any
+third thing. The Organs of Sense are not for enabling the Soul to
+perceive the Species of Things in its Sensorium, but only for conveying
+them thither; and God has no need of such Organs, he being every where
+present to the Things themselves. And since Space is divisible _in
+infinitum_, and Matter is not necessarily in all places, it may be also
+allow'd that God is able to create Particles of Matter of several Sizes
+and Figures, and in several Proportions to Space, and perhaps of
+different Densities and Forces, and thereby to vary the Laws of Nature,
+and make Worlds of several sorts in several Parts of the Universe. At
+least, I see nothing of Contradiction in all this.
+
+As in Mathematicks, so in Natural Philosophy, the Investigation of
+difficult Things by the Method of Analysis, ought ever to precede the
+Method of Composition. This Analysis consists in making Experiments and
+Observations, and in drawing general Conclusions from them by Induction,
+and admitting of no Objections against the Conclusions, but such as are
+taken from Experiments, or other certain Truths. For Hypotheses are not
+to be regarded in experimental Philosophy. And although the arguing from
+Experiments and Observations by Induction be no Demonstration of general
+Conclusions; yet it is the best way of arguing which the Nature of
+Things admits of, and may be looked upon as so much the stronger, by how
+much the Induction is more general. And if no Exception occur from
+Phænomena, the Conclusion may be pronounced generally. But if at any
+time afterwards any Exception shall occur from Experiments, it may then
+begin to be pronounced with such Exceptions as occur. By this way of
+Analysis we may proceed from Compounds to Ingredients, and from Motions
+to the Forces producing them; and in general, from Effects to their
+Causes, and from particular Causes to more general ones, till the
+Argument end in the most general. This is the Method of Analysis: And
+the Synthesis consists in assuming the Causes discover'd, and
+establish'd as Principles, and by them explaining the Phænomena
+proceeding from them, and proving the Explanations.
+
+In the two first Books of these Opticks, I proceeded by this Analysis to
+discover and prove the original Differences of the Rays of Light in
+respect of Refrangibility, Reflexibility, and Colour, and their
+alternate Fits of easy Reflexion and easy Transmission, and the
+Properties of Bodies, both opake and pellucid, on which their Reflexions
+and Colours depend. And these Discoveries being proved, may be assumed
+in the Method of Composition for explaining the Phænomena arising from
+them: An Instance of which Method I gave in the End of the first Book.
+In this third Book I have only begun the Analysis of what remains to be
+discover'd about Light and its Effects upon the Frame of Nature, hinting
+several things about it, and leaving the Hints to be examin'd and
+improv'd by the farther Experiments and Observations of such as are
+inquisitive. And if natural Philosophy in all its Parts, by pursuing
+this Method, shall at length be perfected, the Bounds of Moral
+Philosophy will be also enlarged. For so far as we can know by natural
+Philosophy what is the first Cause, what Power he has over us, and what
+Benefits we receive from him, so far our Duty towards him, as well as
+that towards one another, will appear to us by the Light of Nature. And
+no doubt, if the Worship of false Gods had not blinded the Heathen,
+their moral Philosophy would have gone farther than to the four
+Cardinal Virtues; and instead of teaching the Transmigration of Souls,
+and to worship the Sun and Moon, and dead Heroes, they would have taught
+us to worship our true Author and Benefactor, as their Ancestors did
+under the Government of _Noah_ and his Sons before they corrupted
+themselves. \ No newline at end of file
diff --git a/src/testing/sub_test.go b/src/testing/sub_test.go
index 9af3909b35..29803c06e2 100644
--- a/src/testing/sub_test.go
+++ b/src/testing/sub_test.go
@@ -594,8 +594,8 @@ func TestBRun(t *T) {
func makeRegexp(s string) string {
s = regexp.QuoteMeta(s)
- s = strings.Replace(s, ":NNN:", `:\d\d\d:`, -1)
- s = strings.Replace(s, "N\\.NNs", `\d*\.\d*s`, -1)
+ s = strings.ReplaceAll(s, ":NNN:", `:\d\d\d:`)
+ s = strings.ReplaceAll(s, "N\\.NNs", `\d*\.\d*s`)
return s
}
diff --git a/src/text/template/exec.go b/src/text/template/exec.go
index 214f72d51b..1d04c2982f 100644
--- a/src/text/template/exec.go
+++ b/src/text/template/exec.go
@@ -102,7 +102,7 @@ func (s *state) at(node parse.Node) {
// doublePercent returns the string with %'s replaced by %%, if necessary,
// so it can be used safely inside a Printf format string.
func doublePercent(str string) string {
- return strings.Replace(str, "%", "%%", -1)
+ return strings.ReplaceAll(str, "%", "%%")
}
// TODO: It would be nice if ExecError was more broken down, but
diff --git a/src/time/zoneinfo.go b/src/time/zoneinfo.go
index d2bc642d81..54c76f09e1 100644
--- a/src/time/zoneinfo.go
+++ b/src/time/zoneinfo.go
@@ -288,14 +288,23 @@ func LoadLocation(name string) (*Location, error) {
env, _ := syscall.Getenv("ZONEINFO")
zoneinfo = &env
})
+ var firstErr error
if *zoneinfo != "" {
if zoneData, err := loadTzinfoFromDirOrZip(*zoneinfo, name); err == nil {
if z, err := LoadLocationFromTZData(name, zoneData); err == nil {
return z, nil
}
+ firstErr = err
+ } else if err != syscall.ENOENT {
+ firstErr = err
}
}
- return loadLocation(name, zoneSources)
+ if z, err := loadLocation(name, zoneSources); err == nil {
+ return z, nil
+ } else if firstErr == nil {
+ firstErr = err
+ }
+ return nil, firstErr
}
// containsDotDot reports whether s contains "..".
diff --git a/src/time/zoneinfo_android.go b/src/time/zoneinfo_android.go
index 65e0975ab0..237ff202f9 100644
--- a/src/time/zoneinfo_android.go
+++ b/src/time/zoneinfo_android.go
@@ -11,6 +11,7 @@ package time
import (
"errors"
"runtime"
+ "syscall"
)
var zoneSources = []string{
@@ -75,5 +76,5 @@ func androidLoadTzinfoFromTzdata(file, name string) ([]byte, error) {
}
return buf, nil
}
- return nil, errors.New("cannot find " + name + " in tzdata file " + file)
+ return nil, syscall.ENOENT
}
diff --git a/src/time/zoneinfo_read.go b/src/time/zoneinfo_read.go
index 29244db29e..15d6aab1de 100644
--- a/src/time/zoneinfo_read.go
+++ b/src/time/zoneinfo_read.go
@@ -364,7 +364,7 @@ func loadTzinfoFromZip(zipfile, name string) ([]byte, error) {
return buf, nil
}
- return nil, errors.New("cannot find " + name + " in zip file " + zipfile)
+ return nil, syscall.ENOENT
}
// loadTzinfoFromTzdata returns the time zone information of the time zone
diff --git a/src/time/zoneinfo_test.go b/src/time/zoneinfo_test.go
index 450f5aa114..4458ba8e26 100644
--- a/src/time/zoneinfo_test.go
+++ b/src/time/zoneinfo_test.go
@@ -5,6 +5,7 @@
package time_test
import (
+ "errors"
"fmt"
"os"
"reflect"
@@ -36,6 +37,16 @@ func TestEnvVarUsage(t *testing.T) {
}
}
+func TestBadLocationErrMsg(t *testing.T) {
+ time.ResetZoneinfoForTesting()
+ loc := "Asia/SomethingNotExist"
+ want := errors.New("unknown time zone " + loc)
+ _, err := time.LoadLocation(loc)
+ if err.Error() != want.Error() {
+ t.Errorf("LoadLocation(%q) error = %v; want %v", loc, err, want)
+ }
+}
+
func TestLoadLocationValidatesNames(t *testing.T) {
time.ResetZoneinfoForTesting()
const env = "ZONEINFO"