time: faster Nanoseconds call

runtime knows how to get the time of day
without allocating memory.

R=golang-dev, dsymonds, dave, hectorchu, r, cw
CC=golang-dev
https://golang.org/cl/5297078
diff --git a/src/pkg/runtime/Makefile b/src/pkg/runtime/Makefile
index 2d7b51b..40150d2 100644
--- a/src/pkg/runtime/Makefile
+++ b/src/pkg/runtime/Makefile
@@ -98,6 +98,7 @@
 	symtab.$O\
 	sys.$O\
 	thread.$O\
+	time.$O\
 	traceback.$O\
 	$(OFILES_$(GOARCH))\
 	$(OFILES_$(GOOS))\
diff --git a/src/pkg/runtime/darwin/386/sys.s b/src/pkg/runtime/darwin/386/sys.s
index 15eaf93..c8b89bf 100644
--- a/src/pkg/runtime/darwin/386/sys.s
+++ b/src/pkg/runtime/darwin/386/sys.s
@@ -60,20 +60,27 @@
 	INT	$0x80
 	RET
 
-// void gettime(int64 *sec, int32 *usec)
-TEXT runtime·gettime(SB), 7, $32
+// int64 nanotime(void) so really
+// void nanotime(int64 *nsec)
+TEXT runtime·nanotime(SB), 7, $32
 	LEAL	12(SP), AX	// must be non-nil, unused
 	MOVL	AX, 4(SP)
 	MOVL	$0, 8(SP)	// time zone pointer
 	MOVL	$116, AX
 	INT	$0x80
+	MOVL	DX, BX
 
-	MOVL	sec+0(FP), DI
-	MOVL	AX, (DI)
-	MOVL	$0, 4(DI)	// zero extend 32 -> 64
-
-	MOVL	usec+4(FP), DI
-	MOVL	DX, (DI)
+	// sec is in AX, usec in BX
+	// convert to DX:AX nsec
+	MOVL	$1000000000, CX
+	MULL	CX
+	IMULL	$1000, BX
+	ADDL	BX, AX
+	ADCL	$0, DX
+	
+	MOVL	ret+0(FP), DI
+	MOVL	AX, 0(DI)
+	MOVL	DX, 4(DI)
 	RET
 
 TEXT runtime·sigaction(SB),7,$0
diff --git a/src/pkg/runtime/darwin/amd64/sys.s b/src/pkg/runtime/darwin/amd64/sys.s
index 7c79f18..f049d97 100644
--- a/src/pkg/runtime/darwin/amd64/sys.s
+++ b/src/pkg/runtime/darwin/amd64/sys.s
@@ -55,16 +55,18 @@
 	SYSCALL
 	RET
 
-// void gettime(int64 *sec, int32 *usec)
-TEXT runtime·gettime(SB), 7, $32
+// int64 nanotime(void)
+TEXT runtime·nanotime(SB), 7, $32
 	MOVQ	SP, DI	// must be non-nil, unused
 	MOVQ	$0, SI
 	MOVL	$(0x2000000+116), AX
 	SYSCALL
-	MOVQ	sec+0(FP), DI
-	MOVQ	AX, (DI)
-	MOVQ	usec+8(FP), DI
-	MOVL	DX, (DI)
+
+	// sec is in AX, usec in DX
+	// return nsec in AX
+	IMULQ	$1000000000, AX
+	IMULQ	$1000, DX
+	ADDQ	DX, AX
 	RET
 
 TEXT runtime·sigaction(SB),7,$0
diff --git a/src/pkg/runtime/freebsd/386/sys.s b/src/pkg/runtime/freebsd/386/sys.s
index 4c0b4e4..3856a53 100644
--- a/src/pkg/runtime/freebsd/386/sys.s
+++ b/src/pkg/runtime/freebsd/386/sys.s
@@ -106,23 +106,31 @@
 	INT	$0x80
 	RET
 
-TEXT runtime·gettime(SB), 7, $32
+// int64 nanotime(void) so really
+// void nanotime(int64 *nsec)
+TEXT runtime·nanotime(SB), 7, $32
 	MOVL	$116, AX
 	LEAL	12(SP), BX
 	MOVL	BX, 4(SP)
 	MOVL	$0, 8(SP)
 	INT	$0x80
-
-	MOVL	12(SP), BX	// sec
-	MOVL	sec+0(FP), DI
-	MOVL	BX, (DI)
-	MOVL	$0, 4(DI)	// zero extend 32 -> 64 bits
-
+	MOVL	12(SP), AX	// sec
 	MOVL	16(SP), BX	// usec
-	MOVL	usec+4(FP), DI
-	MOVL	BX, (DI)
+
+	// sec is in AX, usec in BX
+	// convert to DX:AX nsec
+	MOVL	$1000000000, CX
+	MULL	CX
+	IMULL	$1000, BX
+	ADDL	BX, AX
+	ADCL	$0, DX
+	
+	MOVL	ret+0(FP), DI
+	MOVL	AX, 0(DI)
+	MOVL	DX, 4(DI)
 	RET
 
+
 TEXT runtime·sigaction(SB),7,$-4
 	MOVL	$416, AX
 	INT	$0x80
diff --git a/src/pkg/runtime/freebsd/amd64/sys.s b/src/pkg/runtime/freebsd/amd64/sys.s
index e973b52..252069e 100644
--- a/src/pkg/runtime/freebsd/amd64/sys.s
+++ b/src/pkg/runtime/freebsd/amd64/sys.s
@@ -85,19 +85,19 @@
 	SYSCALL
 	RET
 
-TEXT runtime·gettime(SB), 7, $32
+TEXT runtime·nanotime(SB), 7, $32
 	MOVL	$116, AX
 	LEAQ	8(SP), DI
 	MOVQ	$0, SI
 	SYSCALL
+	MOVQ	8(SP), AX	// sec
+	MOVL	16(SP), DX	// usec
 
-	MOVQ	8(SP), BX	// sec
-	MOVQ	sec+0(FP), DI
-	MOVQ	BX, (DI)
-
-	MOVL	16(SP), BX	// usec
-	MOVQ	usec+8(FP), DI
-	MOVL	BX, (DI)
+	// sec is in AX, usec in DX
+	// return nsec in AX
+	IMULQ	$1000000000, AX
+	IMULQ	$1000, DX
+	ADDQ	DX, AX
 	RET
 
 TEXT runtime·sigaction(SB),7,$-8
diff --git a/src/pkg/runtime/linux/386/sys.s b/src/pkg/runtime/linux/386/sys.s
index 1b4f649..97d9d5e 100644
--- a/src/pkg/runtime/linux/386/sys.s
+++ b/src/pkg/runtime/linux/386/sys.s
@@ -95,21 +95,28 @@
 	CALL	*runtime·_vdso(SB)
 	RET
 
-TEXT runtime·gettime(SB), 7, $32
+// int64 nanotime(void) so really
+// void nanotime(int64 *nsec)
+TEXT runtime·nanotime(SB), 7, $32
 	MOVL	$78, AX			// syscall - gettimeofday
 	LEAL	8(SP), BX
 	MOVL	$0, CX
 	MOVL	$0, DX
 	CALL	*runtime·_vdso(SB)
-
-	MOVL	8(SP), BX	// sec
-	MOVL	sec+0(FP), DI
-	MOVL	BX, (DI)
-	MOVL	$0, 4(DI)	// zero extend 32 -> 64 bits
-
+	MOVL	8(SP), AX	// sec
 	MOVL	12(SP), BX	// usec
-	MOVL	usec+4(FP), DI
-	MOVL	BX, (DI)
+
+	// sec is in AX, usec in BX
+	// convert to DX:AX nsec
+	MOVL	$1000000000, CX
+	MULL	CX
+	IMULL	$1000, BX
+	ADDL	BX, AX
+	ADCL	$0, DX
+	
+	MOVL	ret+0(FP), DI
+	MOVL	AX, 0(DI)
+	MOVL	DX, 4(DI)
 	RET
 
 TEXT runtime·rt_sigaction(SB),7,$0
diff --git a/src/pkg/runtime/linux/amd64/sys.s b/src/pkg/runtime/linux/amd64/sys.s
index 3174af2..227c8e6 100644
--- a/src/pkg/runtime/linux/amd64/sys.s
+++ b/src/pkg/runtime/linux/amd64/sys.s
@@ -93,19 +93,19 @@
 	SYSCALL
 	RET
 
-TEXT runtime·gettime(SB), 7, $32
+TEXT runtime·nanotime(SB), 7, $32
 	LEAQ	8(SP), DI
 	MOVQ	$0, SI
 	MOVQ	$0xffffffffff600000, AX
 	CALL	AX
+	MOVQ	8(SP), AX	// sec
+	MOVL	16(SP), DX	// usec
 
-	MOVQ	8(SP), BX	// sec
-	MOVQ	sec+0(FP), DI
-	MOVQ	BX, (DI)
-
-	MOVL	16(SP), BX	// usec
-	MOVQ	usec+8(FP), DI
-	MOVL	BX, (DI)
+	// sec is in AX, usec in DX
+	// return nsec in AX
+	IMULQ	$1000000000, AX
+	IMULQ	$1000, DX
+	ADDQ	DX, AX
 	RET
 
 TEXT runtime·rt_sigaction(SB),7,$0-32
diff --git a/src/pkg/runtime/linux/arm/sys.s b/src/pkg/runtime/linux/arm/sys.s
index 764e779..45da858 100644
--- a/src/pkg/runtime/linux/arm/sys.s
+++ b/src/pkg/runtime/linux/arm/sys.s
@@ -127,14 +127,14 @@
 	SWI	$0
 	RET
 
-TEXT runtime·gettime(SB),7,$32
+// int64 nanotime(void) so really
+// void nanotime(int64 *nsec)
+TEXT runtime·nanotime(SB),7,$32
 	/* dummy version - return 0,0 */
 	MOVW	$0, R1
 	MOVW	0(FP), R0
 	MOVW	R1, 0(R0)
 	MOVW	R1, 4(R0)
-	MOVW	4(FP), R0
-	MOVW	R1, 0(R0)
 
 /*
 	attempt at real version - seg faults
diff --git a/src/pkg/runtime/openbsd/386/sys.s b/src/pkg/runtime/openbsd/386/sys.s
index d2df518..6a6a7bb 100644
--- a/src/pkg/runtime/openbsd/386/sys.s
+++ b/src/pkg/runtime/openbsd/386/sys.s
@@ -91,21 +91,28 @@
 	INT	$0x80
 	RET
 
-TEXT runtime·gettime(SB),7,$32
+// int64 nanotime(void) so really
+// void nanotime(int64 *nsec)
+TEXT runtime·nanotime(SB),7,$32
 	MOVL	$116, AX
 	LEAL	12(SP), BX
 	MOVL	BX, 4(SP)
 	MOVL	$0, 8(SP)
 	INT	$0x80
-
-	MOVL	12(SP), BX		// sec
-	MOVL	sec+0(FP), DI
-	MOVL	BX, (DI)
-	MOVL	$0, 4(DI)		// zero extend 32 -> 64 bits
-
+	MOVL	12(SP), AX		// sec
 	MOVL	16(SP), BX		// usec
-	MOVL	usec+4(FP), DI
-	MOVL	BX, (DI)
+
+	// sec is in AX, usec in BX
+	// convert to DX:AX nsec
+	MOVL	$1000000000, CX
+	MULL	CX
+	IMULL	$1000, BX
+	ADDL	BX, AX
+	ADCL	$0, DX
+	
+	MOVL	ret+0(FP), DI
+	MOVL	AX, 0(DI)
+	MOVL	DX, 4(DI)
 	RET
 
 TEXT runtime·sigaction(SB),7,$-4
diff --git a/src/pkg/runtime/openbsd/amd64/sys.s b/src/pkg/runtime/openbsd/amd64/sys.s
index 29d74a1..dfbb254 100644
--- a/src/pkg/runtime/openbsd/amd64/sys.s
+++ b/src/pkg/runtime/openbsd/amd64/sys.s
@@ -133,19 +133,19 @@
 	SYSCALL
 	RET
 
-TEXT runtime·gettime(SB),7,$32
+TEXT runtime·nanotime(SB),7,$32
 	LEAQ	8(SP), DI		// arg 1 - tp
 	MOVQ	$0, SI			// arg 2 - tzp
 	MOVL	$116, AX		// sys_gettimeofday
 	SYSCALL
-
-	MOVQ	8(SP), BX		// sec
-	MOVQ	sec+0(FP), DI
-	MOVQ	BX, (DI)
-
+	MOVQ	8(SP), AX		// sec
 	MOVL	16(SP), BX		// usec
-	MOVQ	usec+8(FP), DI
-	MOVL	BX, (DI)
+
+	// sec is in AX, usec in DX
+	// return nsec in AX
+	IMULQ	$1000000000, AX
+	IMULQ	$1000, DX
+	ADDQ	DX, AX
 	RET
 
 TEXT runtime·sigaction(SB),7,$-8
diff --git a/src/pkg/runtime/plan9/386/signal.c b/src/pkg/runtime/plan9/386/signal.c
index 364fd1c..77e40d3 100644
--- a/src/pkg/runtime/plan9/386/signal.c
+++ b/src/pkg/runtime/plan9/386/signal.c
@@ -4,9 +4,10 @@
 
 #include "runtime.h"
 
-void
-runtime·gettime(int64*, int32*) 
+int64
+runtime·nanotime(void) 
 {
+	// Won't compile.
 }
 
 String
diff --git a/src/pkg/runtime/runtime.c b/src/pkg/runtime/runtime.c
index ae6fd87..a82e8b6 100644
--- a/src/pkg/runtime/runtime.c
+++ b/src/pkg/runtime/runtime.c
@@ -654,18 +654,6 @@
 [ANOEQ128]	{ runtime·nohash, runtime·noequal, memprint, (void*)memcopy128 },
 };
 
-int64
-runtime·nanotime(void)
-{
-	int64 sec;
-	int32 usec;
-
-	sec = 0;
-	usec = 0;
-	runtime·gettime(&sec, &usec);
-	return sec*1000000000 + (int64)usec*1000;
-}
-
 void
 runtime·Caller(int32 skip, uintptr retpc, String retfile, int32 retline, bool retbool)
 {
diff --git a/src/pkg/runtime/runtime.h b/src/pkg/runtime/runtime.h
index 685725a..da80b99 100644
--- a/src/pkg/runtime/runtime.h
+++ b/src/pkg/runtime/runtime.h
@@ -490,7 +490,6 @@
 G*	runtime·newproc1(byte*, byte*, int32, int32, void*);
 void	runtime·siginit(void);
 bool	runtime·sigsend(int32 sig);
-void	runtime·gettime(int64*, int32*);
 int32	runtime·callers(int32, uintptr*, int32);
 int32	runtime·gentraceback(byte*, byte*, byte*, G*, int32, uintptr*, int32);
 int64	runtime·nanotime(void);
diff --git a/src/pkg/runtime/time.goc b/src/pkg/runtime/time.goc
new file mode 100644
index 0000000..a620f2b3
--- /dev/null
+++ b/src/pkg/runtime/time.goc
@@ -0,0 +1,13 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Runtime implementations to help package time.
+
+package time
+
+#include "runtime.h"
+
+func Nanoseconds() (ret int64) {
+	ret = runtime·nanotime();
+}
diff --git a/src/pkg/runtime/windows/thread.c b/src/pkg/runtime/windows/thread.c
index 0498c76..c00485b 100644
--- a/src/pkg/runtime/windows/thread.c
+++ b/src/pkg/runtime/windows/thread.c
@@ -18,10 +18,9 @@
 #pragma dynimport runtime·GetProcAddress GetProcAddress "kernel32.dll"
 #pragma dynimport runtime·GetStdHandle GetStdHandle "kernel32.dll"
 #pragma dynimport runtime·GetSystemInfo GetSystemInfo "kernel32.dll"
+#pragma dynimport runtime·GetSystemTimeAsFileTime GetSystemTimeAsFileTime "kernel32.dll"
 #pragma dynimport runtime·GetThreadContext GetThreadContext "kernel32.dll"
 #pragma dynimport runtime·LoadLibrary LoadLibraryW "kernel32.dll"
-#pragma dynimport runtime·QueryPerformanceCounter QueryPerformanceCounter "kernel32.dll"
-#pragma dynimport runtime·QueryPerformanceFrequency QueryPerformanceFrequency "kernel32.dll"
 #pragma dynimport runtime·ResumeThread ResumeThread "kernel32.dll"
 #pragma dynimport runtime·SetConsoleCtrlHandler SetConsoleCtrlHandler "kernel32.dll"
 #pragma dynimport runtime·SetEvent SetEvent "kernel32.dll"
@@ -44,10 +43,9 @@
 extern void *runtime·GetProcAddress;
 extern void *runtime·GetStdHandle;
 extern void *runtime·GetSystemInfo;
+extern void *runtime·GetSystemTimeAsFileTime;
 extern void *runtime·GetThreadContext;
 extern void *runtime·LoadLibrary;
-extern void *runtime·QueryPerformanceCounter;
-extern void *runtime·QueryPerformanceFrequency;
 extern void *runtime·ResumeThread;
 extern void *runtime·SetConsoleCtrlHandler;
 extern void *runtime·SetEvent;
@@ -59,8 +57,6 @@
 extern void *runtime·WaitForSingleObject;
 extern void *runtime·WriteFile;
 
-static int64 timerfreq;
-
 static int32
 getproccount(void)
 {
@@ -77,7 +73,6 @@
 	runtime·stdcall(runtime·DuplicateHandle, 7,
 		(uintptr)-1, (uintptr)-2, (uintptr)-1, &m->thread,
 		(uintptr)0, (uintptr)0, (uintptr)DUPLICATE_SAME_ACCESS);
-	runtime·stdcall(runtime·QueryPerformanceFrequency, 1, &timerfreq);
 	runtime·stdcall(runtime·SetConsoleCtrlHandler, 2, runtime·ctrlhandler, (uintptr)1);
 	runtime·stdcall(runtime·timeBeginPeriod, 1, (uintptr)1);
 	runtime·ncpu = getproccount();
@@ -197,15 +192,16 @@
 {
 }
 
-void
-runtime·gettime(int64 *sec, int32 *usec)
+int64
+runtime·nanotime(void)
 {
-	int64 count;
+	int64 filetime;
 
-	runtime·stdcall(runtime·QueryPerformanceCounter, 1, &count);
-	*sec = count / timerfreq;
-	count %= timerfreq;
-	*usec = count*1000000 / timerfreq;
+	runtime·stdcall(runtime·GetSystemTimeAsFileTime, 1, &filetime);
+	
+	// Filetime is 100s of nanoseconds since January 1, 1601.
+	// Convert to nanoseconds since January 1, 1970.
+	return (filetime - 116444736000000000LL) * 100LL;
 }
 
 // Calling stdcall on os stack.
diff --git a/src/pkg/time/sys.go b/src/pkg/time/sys.go
index 4bc9253..ca1d334 100644
--- a/src/pkg/time/sys.go
+++ b/src/pkg/time/sys.go
@@ -4,27 +4,17 @@
 
 package time
 
-import "os"
-
 // Seconds reports the number of seconds since the Unix epoch,
 // January 1, 1970 00:00:00 UTC.
 func Seconds() int64 {
-	sec, _, err := os.Time()
-	if err != nil {
-		panic(err)
-	}
-	return sec
+	return Nanoseconds() / 1e9
 }
 
+// Nanoseconds is implemented by package runtime.
+
 // Nanoseconds reports the number of nanoseconds since the Unix epoch,
 // January 1, 1970 00:00:00 UTC.
-func Nanoseconds() int64 {
-	sec, nsec, err := os.Time()
-	if err != nil {
-		panic(err)
-	}
-	return sec*1e9 + nsec
-}
+func Nanoseconds() int64
 
 // Sleep pauses the current goroutine for at least ns nanoseconds.
 // Higher resolution sleeping may be provided by syscall.Nanosleep