diff --git a/src/pkg/runtime/error.go b/src/pkg/runtime/error.go index b6b520cf27..bd70908839 100644 --- a/src/pkg/runtime/error.go +++ b/src/pkg/runtime/error.go @@ -74,6 +74,22 @@ func newErrorString(s string, ret *interface{}) { *ret = errorString(s) } +// An errorCString represents a runtime error described by a single C string. +type errorCString uintptr + +func (e errorCString) RuntimeError() {} + +func cstringToGo(uintptr) string + +func (e errorCString) Error() string { + return "runtime error: " + cstringToGo(uintptr(e)) +} + +// For calling from C. +func newErrorCString(s uintptr, ret *interface{}) { + *ret = errorCString(s) +} + type stringer interface { String() string } diff --git a/src/pkg/runtime/panic.c b/src/pkg/runtime/panic.c index a1e91d3d8f..8227a444d3 100644 --- a/src/pkg/runtime/panic.c +++ b/src/pkg/runtime/panic.c @@ -470,11 +470,15 @@ runtime·panicstring(int8 *s) { Eface err; + if(m->mallocing) { + runtime·printf("panic: %s\n", s); + runtime·throw("panic during malloc"); + } if(m->gcing) { runtime·printf("panic: %s\n", s); runtime·throw("panic during gc"); } - runtime·newErrorString(runtime·gostringnocopy((byte*)s), &err); + runtime·newErrorCString(s, &err); runtime·panic(err); } diff --git a/src/pkg/runtime/proc.c b/src/pkg/runtime/proc.c index e34e9e5067..d5fc2dcac5 100644 --- a/src/pkg/runtime/proc.c +++ b/src/pkg/runtime/proc.c @@ -128,6 +128,7 @@ runtime·schedinit(void) { int32 n, procs; byte *p; + Eface i; runtime·sched.maxmcount = 10000; runtime·precisestack = haveexperiment("precisestack"); @@ -136,6 +137,12 @@ runtime·schedinit(void) runtime·mprofinit(); runtime·mallocinit(); mcommoninit(m); + + // Initialize the itable value for newErrorCString, + // so that the next time it gets called, possibly + // in a fault during a garbage collection, it will not + // need to allocated memory. + runtime·newErrorCString(0, &i); runtime·goargs(); runtime·goenvs(); diff --git a/src/pkg/runtime/runtime.h b/src/pkg/runtime/runtime.h index 66e87d5c27..c989edcf8d 100644 --- a/src/pkg/runtime/runtime.h +++ b/src/pkg/runtime/runtime.h @@ -1004,6 +1004,7 @@ void runtime·panicslice(void); void runtime·printany(Eface); void runtime·newTypeAssertionError(String*, String*, String*, String*, Eface*); void runtime·newErrorString(String, Eface*); +void runtime·newErrorCString(int8*, Eface*); void runtime·fadd64c(uint64, uint64, uint64*); void runtime·fsub64c(uint64, uint64, uint64*); void runtime·fmul64c(uint64, uint64, uint64*); diff --git a/src/pkg/runtime/string.goc b/src/pkg/runtime/string.goc index 5d472208bf..b79acbe1c2 100644 --- a/src/pkg/runtime/string.goc +++ b/src/pkg/runtime/string.goc @@ -102,6 +102,13 @@ runtime·gostringnocopy(byte *str) return s; } +void +runtime·cstringToGo(byte *str, String s) +{ + s = runtime·gostringnocopy(str); + FLUSH(&s); +} + String runtime·gostringw(uint16 *str) {