aboutsummaryrefslogtreecommitdiff
path: root/libgo/runtime
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2011-05-20 00:18:15 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2011-05-20 00:18:15 +0000
commit9ff56c9570642711d5b7ab29920ecf5dbff14a27 (patch)
treec891bdec1e6f073f73fedeef23718bc3ac30d499 /libgo/runtime
parent37cb25ed7acdb844b218231130e54b8b7a0ff6e6 (diff)
downloadgcc-9ff56c9570642711d5b7ab29920ecf5dbff14a27.zip
gcc-9ff56c9570642711d5b7ab29920ecf5dbff14a27.tar.gz
gcc-9ff56c9570642711d5b7ab29920ecf5dbff14a27.tar.bz2
Update to current version of Go library.
From-SVN: r173931
Diffstat (limited to 'libgo/runtime')
-rw-r--r--libgo/runtime/chan.goc16
-rw-r--r--libgo/runtime/channel.h9
-rw-r--r--libgo/runtime/go-eface-compare.c6
-rw-r--r--libgo/runtime/go-eface-val-compare.c3
-rw-r--r--libgo/runtime/go-interface-eface-compare.c3
-rw-r--r--libgo/runtime/go-new-channel.c8
-rw-r--r--libgo/runtime/go-rec-big.c9
-rw-r--r--libgo/runtime/go-rec-nb-big.c9
-rw-r--r--libgo/runtime/go-rec-nb-small.c4
-rw-r--r--libgo/runtime/go-rec-small.c4
-rw-r--r--libgo/runtime/go-reflect-call.c55
-rw-r--r--libgo/runtime/go-reflect-chan.c140
-rw-r--r--libgo/runtime/go-reflect-map.c140
-rw-r--r--libgo/runtime/go-reflect.c6
-rw-r--r--libgo/runtime/go-send-big.c7
-rw-r--r--libgo/runtime/go-send-nb-big.c7
-rw-r--r--libgo/runtime/go-send-nb-small.c2
-rw-r--r--libgo/runtime/go-send-small.c2
-rw-r--r--libgo/runtime/go-setenv.c50
-rw-r--r--libgo/runtime/go-signal.c23
-rw-r--r--libgo/runtime/go-type-eface.c4
-rw-r--r--libgo/runtime/go-type.h12
-rw-r--r--libgo/runtime/go-unreflect.c4
-rw-r--r--libgo/runtime/go-unsafe-new.c4
-rw-r--r--libgo/runtime/go-unsafe-newarray.c4
-rw-r--r--libgo/runtime/iface.goc9
-rw-r--r--libgo/runtime/malloc.goc2
-rw-r--r--libgo/runtime/mcache.c2
-rw-r--r--libgo/runtime/mgc0.c7
-rw-r--r--libgo/runtime/mheap.c8
-rw-r--r--libgo/runtime/reflect.goc38
-rw-r--r--libgo/runtime/runtime.h4
32 files changed, 458 insertions, 143 deletions
diff --git a/libgo/runtime/chan.goc b/libgo/runtime/chan.goc
index 9326f26..acfff85 100644
--- a/libgo/runtime/chan.goc
+++ b/libgo/runtime/chan.goc
@@ -13,7 +13,8 @@ typedef struct __go_channel chan;
/* Do a channel receive with closed status. */
func chanrecv2(c *chan, val *byte) (received bool) {
- if (c->element_size > 8) {
+ uintptr_t element_size = c->element_type->__size;
+ if (element_size > 8) {
return __go_receive_big(c, val, 0);
} else {
union {
@@ -23,10 +24,9 @@ func chanrecv2(c *chan, val *byte) (received bool) {
u.v = __go_receive_small_closed(c, 0, &received);
#ifndef WORDS_BIGENDIAN
- __builtin_memcpy(val, u.b, c->element_size);
+ __builtin_memcpy(val, u.b, element_size);
#else
- __builtin_memcpy(val, u.b + 8 - c->element_size,
- c->element_size);
+ __builtin_memcpy(val, u.b + 8 - element_size, element_size);
#endif
return received;
}
@@ -35,7 +35,8 @@ func chanrecv2(c *chan, val *byte) (received bool) {
/* Do a channel receive with closed status for a select statement. */
func chanrecv3(c *chan, val *byte) (received bool) {
- if (c->element_size > 8) {
+ uintptr_t element_size = c->element_type->__size;
+ if (element_size > 8) {
return __go_receive_big(c, val, 1);
} else {
union {
@@ -45,10 +46,9 @@ func chanrecv3(c *chan, val *byte) (received bool) {
u.v = __go_receive_small_closed(c, 1, &received);
#ifndef WORDS_BIGENDIAN
- __builtin_memcpy(val, u.b, c->element_size);
+ __builtin_memcpy(val, u.b, element_size);
#else
- __builtin_memcpy(val, u.b + 8 - c->element_size,
- c->element_size);
+ __builtin_memcpy(val, u.b + 8 - element_size, element_size);
#endif
return received;
}
diff --git a/libgo/runtime/channel.h b/libgo/runtime/channel.h
index 9dcaf7f..d4f1632 100644
--- a/libgo/runtime/channel.h
+++ b/libgo/runtime/channel.h
@@ -7,6 +7,8 @@
#include <stdint.h>
#include <pthread.h>
+#include "go-type.h"
+
/* This structure is used when a select is waiting for a synchronous
channel. */
@@ -34,8 +36,8 @@ struct __go_channel
/* A condition variable. This is signalled when data is added to
the channel and when data is removed from the channel. */
pthread_cond_t cond;
- /* The size of elements on this channel. */
- size_t element_size;
+ /* The type of elements on this channel. */
+ const struct __go_type_descriptor *element_type;
/* True if a goroutine is waiting to send on a synchronous
channel. */
_Bool waiting_to_send;
@@ -82,7 +84,8 @@ typedef struct __go_channel __go_channel;
acquired while this mutex is held. */
extern pthread_mutex_t __go_select_data_mutex;
-extern struct __go_channel *__go_new_channel (uintptr_t, uintptr_t);
+extern struct __go_channel *
+__go_new_channel (const struct __go_type_descriptor *, uintptr_t);
extern _Bool __go_synch_with_select (struct __go_channel *, _Bool);
diff --git a/libgo/runtime/go-eface-compare.c b/libgo/runtime/go-eface-compare.c
index c90177e..6734405 100644
--- a/libgo/runtime/go-eface-compare.c
+++ b/libgo/runtime/go-eface-compare.c
@@ -4,6 +4,7 @@
Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file. */
+#include "go-panic.h"
#include "interface.h"
/* Compare two interface values. Return 0 for equal, not zero for not
@@ -16,6 +17,11 @@ __go_empty_interface_compare (struct __go_empty_interface left,
const struct __go_type_descriptor *left_descriptor;
left_descriptor = left.__type_descriptor;
+
+ if (((uintptr_t) left_descriptor & reflectFlags) != 0
+ || ((uintptr_t) right.__type_descriptor & reflectFlags) != 0)
+ __go_panic_msg ("invalid interface value");
+
if (left_descriptor == NULL && right.__type_descriptor == NULL)
return 0;
if (left_descriptor == NULL || right.__type_descriptor == NULL)
diff --git a/libgo/runtime/go-eface-val-compare.c b/libgo/runtime/go-eface-val-compare.c
index 319ede2..d754cc5 100644
--- a/libgo/runtime/go-eface-val-compare.c
+++ b/libgo/runtime/go-eface-val-compare.c
@@ -4,6 +4,7 @@
Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file. */
+#include "go-panic.h"
#include "go-type.h"
#include "interface.h"
@@ -19,6 +20,8 @@ __go_empty_interface_value_compare (
const struct __go_type_descriptor *left_descriptor;
left_descriptor = left.__type_descriptor;
+ if (((uintptr_t) left_descriptor & reflectFlags) != 0)
+ __go_panic_msg ("invalid interface value");
if (left_descriptor == NULL)
return 1;
if (!__go_type_descriptors_equal (left_descriptor, right_descriptor))
diff --git a/libgo/runtime/go-interface-eface-compare.c b/libgo/runtime/go-interface-eface-compare.c
index 9de8424..ff69a27 100644
--- a/libgo/runtime/go-interface-eface-compare.c
+++ b/libgo/runtime/go-interface-eface-compare.c
@@ -4,6 +4,7 @@
Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file. */
+#include "go-panic.h"
#include "interface.h"
/* Compare a non-empty interface value with an empty interface value.
@@ -16,6 +17,8 @@ __go_interface_empty_compare (struct __go_interface left,
{
const struct __go_type_descriptor *left_descriptor;
+ if (((uintptr_t) right.__type_descriptor & reflectFlags) != 0)
+ __go_panic_msg ("invalid interface value");
if (left.__methods == NULL && right.__type_descriptor == NULL)
return 0;
if (left.__methods == NULL || right.__type_descriptor == NULL)
diff --git a/libgo/runtime/go-new-channel.c b/libgo/runtime/go-new-channel.c
index 028715e..e440e87 100644
--- a/libgo/runtime/go-new-channel.c
+++ b/libgo/runtime/go-new-channel.c
@@ -13,12 +13,16 @@
#include "channel.h"
struct __go_channel*
-__go_new_channel (uintptr_t element_size, uintptr_t entries)
+__go_new_channel (const struct __go_type_descriptor *element_type,
+ uintptr_t entries)
{
+ uintptr_t element_size;
struct __go_channel* ret;
size_t alloc_size;
int i;
+ element_size = element_type->__size;
+
if ((uintptr_t) (int) entries != entries
|| entries > (uintptr_t) -1 / element_size)
__go_panic_msg ("chan size out of range");
@@ -40,7 +44,7 @@ __go_new_channel (uintptr_t element_size, uintptr_t entries)
__go_assert (i == 0);
i = pthread_cond_init (&ret->cond, NULL);
__go_assert (i == 0);
- ret->element_size = element_size;
+ ret->element_type = element_type;
ret->waiting_to_send = 0;
ret->waiting_to_receive = 0;
ret->selected_for_send = 0;
diff --git a/libgo/runtime/go-rec-big.c b/libgo/runtime/go-rec-big.c
index fd3923c..580ccb0 100644
--- a/libgo/runtime/go-rec-big.c
+++ b/libgo/runtime/go-rec-big.c
@@ -15,23 +15,24 @@
_Bool
__go_receive_big (struct __go_channel *channel, void *val, _Bool for_select)
{
+ uintptr_t element_size;
size_t alloc_size;
size_t offset;
if (channel == NULL)
__go_panic_msg ("receive from nil channel");
- alloc_size = ((channel->element_size + sizeof (uint64_t) - 1)
- / sizeof (uint64_t));
+ element_size = channel->element_type->__size;
+ alloc_size = (element_size + sizeof (uint64_t) - 1) / sizeof (uint64_t);
if (!__go_receive_acquire (channel, for_select))
{
- __builtin_memset (val, 0, channel->element_size);
+ __builtin_memset (val, 0, element_size);
return 0;
}
offset = channel->next_fetch * alloc_size;
- __builtin_memcpy (val, &channel->data[offset], channel->element_size);
+ __builtin_memcpy (val, &channel->data[offset], element_size);
__go_receive_release (channel);
diff --git a/libgo/runtime/go-rec-nb-big.c b/libgo/runtime/go-rec-nb-big.c
index 78db587..8c315b1 100644
--- a/libgo/runtime/go-rec-nb-big.c
+++ b/libgo/runtime/go-rec-nb-big.c
@@ -14,23 +14,24 @@ _Bool
__go_receive_nonblocking_big (struct __go_channel* channel, void *val,
_Bool *closed)
{
+ uintptr_t element_size;
size_t alloc_size;
size_t offset;
- alloc_size = ((channel->element_size + sizeof (uint64_t) - 1)
- / sizeof (uint64_t));
+ element_size = channel->element_type->__size;
+ alloc_size = (element_size + sizeof (uint64_t) - 1) / sizeof (uint64_t);
int data = __go_receive_nonblocking_acquire (channel);
if (data != RECEIVE_NONBLOCKING_ACQUIRE_DATA)
{
- __builtin_memset (val, 0, channel->element_size);
+ __builtin_memset (val, 0, element_size);
if (closed != NULL)
*closed = data == RECEIVE_NONBLOCKING_ACQUIRE_CLOSED;
return 0;
}
offset = channel->next_fetch * alloc_size;
- __builtin_memcpy (val, &channel->data[offset], channel->element_size);
+ __builtin_memcpy (val, &channel->data[offset], element_size);
__go_receive_release (channel);
diff --git a/libgo/runtime/go-rec-nb-small.c b/libgo/runtime/go-rec-nb-small.c
index 29cad9a..eb0a25e 100644
--- a/libgo/runtime/go-rec-nb-small.c
+++ b/libgo/runtime/go-rec-nb-small.c
@@ -94,9 +94,11 @@ __go_receive_nonblocking_acquire (struct __go_channel *channel)
struct __go_receive_nonblocking_small
__go_receive_nonblocking_small (struct __go_channel *channel)
{
+ uintptr_t element_size;
struct __go_receive_nonblocking_small ret;
- __go_assert (channel->element_size <= sizeof (uint64_t));
+ element_size = channel->element_type->__size;
+ __go_assert (element_size <= sizeof (uint64_t));
int data = __go_receive_nonblocking_acquire (channel);
if (data != RECEIVE_NONBLOCKING_ACQUIRE_DATA)
diff --git a/libgo/runtime/go-rec-small.c b/libgo/runtime/go-rec-small.c
index 019b20a..946a18c 100644
--- a/libgo/runtime/go-rec-small.c
+++ b/libgo/runtime/go-rec-small.c
@@ -266,12 +266,14 @@ uint64_t
__go_receive_small_closed (struct __go_channel *channel, _Bool for_select,
_Bool *received)
{
+ uintptr_t element_size;
uint64_t ret;
if (channel == NULL)
__go_panic_msg ("receive from nil channel");
- __go_assert (channel->element_size <= sizeof (uint64_t));
+ element_size = channel->element_type->__size;
+ __go_assert (element_size <= sizeof (uint64_t));
if (!__go_receive_acquire (channel, for_select))
{
diff --git a/libgo/runtime/go-reflect-call.c b/libgo/runtime/go-reflect-call.c
index 6ae749f..a769142 100644
--- a/libgo/runtime/go-reflect-call.c
+++ b/libgo/runtime/go-reflect-call.c
@@ -14,9 +14,32 @@
#include "go-type.h"
#include "runtime.h"
-/* Forward declaration. */
-
-static ffi_type *go_type_to_ffi (const struct __go_type_descriptor *);
+/* The functions in this file are only called from reflect_call. As
+ reflect_call calls a libffi function, which will be compiled
+ without -fsplit-stack, it will always run with a large stack. */
+
+static ffi_type *go_array_to_ffi (const struct __go_array_type *)
+ __attribute__ ((no_split_stack));
+static ffi_type *go_slice_to_ffi (const struct __go_slice_type *)
+ __attribute__ ((no_split_stack));
+static ffi_type *go_struct_to_ffi (const struct __go_struct_type *)
+ __attribute__ ((no_split_stack));
+static ffi_type *go_string_to_ffi (void) __attribute__ ((no_split_stack));
+static ffi_type *go_interface_to_ffi (void) __attribute__ ((no_split_stack));
+static ffi_type *go_complex_to_ffi (ffi_type *)
+ __attribute__ ((no_split_stack));
+static ffi_type *go_type_to_ffi (const struct __go_type_descriptor *)
+ __attribute__ ((no_split_stack));
+static ffi_type *go_func_return_ffi (const struct __go_func_type *)
+ __attribute__ ((no_split_stack));
+static void go_func_to_cif (const struct __go_func_type *, _Bool, _Bool,
+ ffi_cif *)
+ __attribute__ ((no_split_stack));
+static size_t go_results_size (const struct __go_func_type *)
+ __attribute__ ((no_split_stack));
+static void go_set_results (const struct __go_func_type *, unsigned char *,
+ void **)
+ __attribute__ ((no_split_stack));
/* Return an ffi_type for a Go array type. The libffi library does
not have any builtin support for passing arrays as values. We work
@@ -31,7 +54,6 @@ go_array_to_ffi (const struct __go_array_type *descriptor)
uintptr_t i;
ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
- __builtin_memset (ret, 0, sizeof (ffi_type));
ret->type = FFI_TYPE_STRUCT;
len = descriptor->__len;
ret->elements = (ffi_type **) __go_alloc ((len + 1) * sizeof (ffi_type *));
@@ -52,7 +74,6 @@ go_slice_to_ffi (
ffi_type *ret;
ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
- __builtin_memset (ret, 0, sizeof (ffi_type));
ret->type = FFI_TYPE_STRUCT;
ret->elements = (ffi_type **) __go_alloc (4 * sizeof (ffi_type *));
ret->elements[0] = &ffi_type_pointer;
@@ -73,7 +94,6 @@ go_struct_to_ffi (const struct __go_struct_type *descriptor)
int i;
ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
- __builtin_memset (ret, 0, sizeof (ffi_type));
ret->type = FFI_TYPE_STRUCT;
field_count = descriptor->__fields.__count;
fields = (const struct __go_struct_field *) descriptor->__fields.__values;
@@ -237,7 +257,6 @@ go_func_return_ffi (const struct __go_func_type *func)
return go_type_to_ffi (types[0]);
ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
- __builtin_memset (ret, 0, sizeof (ffi_type));
ret->type = FFI_TYPE_STRUCT;
ret->elements = (ffi_type **) __go_alloc ((count + 1) * sizeof (ffi_type *));
for (i = 0; i < count; ++i)
@@ -251,7 +270,7 @@ go_func_return_ffi (const struct __go_func_type *func)
static void
go_func_to_cif (const struct __go_func_type *func, _Bool is_interface,
- ffi_cif *cif)
+ _Bool is_method, ffi_cif *cif)
{
int num_params;
const struct __go_type_descriptor **in_types;
@@ -268,10 +287,19 @@ go_func_to_cif (const struct __go_func_type *func, _Bool is_interface,
num_args = num_params + (is_interface ? 1 : 0);
args = (ffi_type **) __go_alloc (num_args * sizeof (ffi_type *));
+ i = 0;
+ off = 0;
if (is_interface)
- args[0] = &ffi_type_pointer;
- off = is_interface ? 1 : 0;
- for (i = 0; i < num_params; ++i)
+ {
+ args[0] = &ffi_type_pointer;
+ off = 1;
+ }
+ else if (is_method)
+ {
+ args[0] = &ffi_type_pointer;
+ i = 1;
+ }
+ for (; i < num_params; ++i)
args[i + off] = go_type_to_ffi (in_types[i]);
rettype = go_func_return_ffi (func);
@@ -354,13 +382,14 @@ go_set_results (const struct __go_func_type *func, unsigned char *call_result,
void
reflect_call (const struct __go_func_type *func_type, const void *func_addr,
- _Bool is_interface, void **params, void **results)
+ _Bool is_interface, _Bool is_method, void **params,
+ void **results)
{
ffi_cif cif;
unsigned char *call_result;
__go_assert (func_type->__common.__code == GO_FUNC);
- go_func_to_cif (func_type, is_interface, &cif);
+ go_func_to_cif (func_type, is_interface, is_method, &cif);
call_result = (unsigned char *) malloc (go_results_size (func_type));
diff --git a/libgo/runtime/go-reflect-chan.c b/libgo/runtime/go-reflect-chan.c
index c9ccda7..d568024 100644
--- a/libgo/runtime/go-reflect-chan.c
+++ b/libgo/runtime/go-reflect-chan.c
@@ -8,30 +8,54 @@
#include <stdint.h>
#include "config.h"
+#include "go-alloc.h"
+#include "go-assert.h"
+#include "go-panic.h"
#include "go-type.h"
#include "channel.h"
/* This file implements support for reflection on channels. These
functions are called from reflect/value.go. */
-extern unsigned char *makechan (const struct __go_type_descriptor *, uint32_t)
+extern uintptr_t makechan (const struct __go_type_descriptor *, uint32_t)
asm ("libgo_reflect.reflect.makechan");
-unsigned char *
+uintptr_t
makechan (const struct __go_type_descriptor *typ, uint32_t size)
{
- return (unsigned char *) __go_new_channel (typ->__size, size);
+ struct __go_channel *channel;
+ void *ret;
+
+ __go_assert (typ->__code == GO_CHAN);
+ typ = ((const struct __go_channel_type *) typ)->__element_type;
+
+ channel = __go_new_channel (typ, size);
+
+ ret = __go_alloc (sizeof (void *));
+ __builtin_memcpy (ret, &channel, sizeof (void *));
+ return (uintptr_t) ret;
}
-extern void chansend (unsigned char *, unsigned char *, _Bool *)
+extern _Bool chansend (uintptr_t, uintptr_t, _Bool)
asm ("libgo_reflect.reflect.chansend");
-void
-chansend (unsigned char *ch, unsigned char *val, _Bool *selected)
+_Bool
+chansend (uintptr_t ch, uintptr_t val_i, _Bool nb)
{
struct __go_channel *channel = (struct __go_channel *) ch;
+ uintptr_t element_size;
+ void *pv;
+
+ if (channel == NULL)
+ __go_panic_msg ("send to nil channel");
+
+ if (__go_is_pointer_type (channel->element_type))
+ pv = &val_i;
+ else
+ pv = (void *) val_i;
- if (channel->element_size <= sizeof (uint64_t))
+ element_size = channel->element_type->__size;
+ if (element_size <= sizeof (uint64_t))
{
union
{
@@ -41,35 +65,60 @@ chansend (unsigned char *ch, unsigned char *val, _Bool *selected)
__builtin_memset (u.b, 0, sizeof (uint64_t));
#ifndef WORDS_BIGENDIAN
- __builtin_memcpy (u.b, val, channel->element_size);
+ __builtin_memcpy (u.b, pv, element_size);
#else
- __builtin_memcpy (u.b + sizeof (uint64_t) - channel->element_size, val,
- channel->element_size);
+ __builtin_memcpy (u.b + sizeof (uint64_t) - element_size, pv,
+ element_size);
#endif
- if (selected == NULL)
- __go_send_small (channel, u.v, 0);
+ if (nb)
+ return __go_send_nonblocking_small (channel, u.v);
else
- *selected = __go_send_nonblocking_small (channel, u.v);
+ {
+ __go_send_small (channel, u.v, 0);
+ return 1;
+ }
}
else
{
- if (selected == NULL)
- __go_send_big (channel, val, 0);
+ if (nb)
+ return __go_send_nonblocking_big (channel, pv);
else
- *selected = __go_send_nonblocking_big (channel, val);
+ {
+ __go_send_big (channel, pv, 0);
+ return 1;
+ }
}
}
-extern void chanrecv (unsigned char *, unsigned char *, _Bool *, _Bool *)
+struct chanrecv_ret
+{
+ uintptr_t val;
+ _Bool selected;
+ _Bool received;
+};
+
+extern struct chanrecv_ret chanrecv (uintptr_t, _Bool)
asm ("libgo_reflect.reflect.chanrecv");
-void
-chanrecv (unsigned char *ch, unsigned char *val, _Bool *selected,
- _Bool *received)
+struct chanrecv_ret
+chanrecv (uintptr_t ch, _Bool nb)
{
struct __go_channel *channel = (struct __go_channel *) ch;
+ void *pv;
+ uintptr_t element_size;
+ struct chanrecv_ret ret;
+
+ element_size = channel->element_type->__size;
- if (channel->element_size <= sizeof (uint64_t))
+ if (__go_is_pointer_type (channel->element_type))
+ pv = &ret.val;
+ else
+ {
+ pv = __go_alloc (element_size);
+ ret.val = (uintptr_t) pv;
+ }
+
+ if (element_size <= sizeof (uint64_t))
{
union
{
@@ -77,74 +126,73 @@ chanrecv (unsigned char *ch, unsigned char *val, _Bool *selected,
uint64_t v;
} u;
- if (selected == NULL)
- u.v = __go_receive_small_closed (channel, 0, received);
+ if (!nb)
+ {
+ u.v = __go_receive_small_closed (channel, 0, &ret.received);
+ ret.selected = 1;
+ }
else
{
struct __go_receive_nonblocking_small s;
s = __go_receive_nonblocking_small (channel);
- *selected = s.__success || s.__closed;
- if (received != NULL)
- *received = s.__success;
+ ret.selected = s.__success || s.__closed;
+ ret.received = s.__success;
u.v = s.__val;
}
#ifndef WORDS_BIGENDIAN
- __builtin_memcpy (val, u.b, channel->element_size);
+ __builtin_memcpy (pv, u.b, element_size);
#else
- __builtin_memcpy (val, u.b + sizeof (uint64_t) - channel->element_size,
- channel->element_size);
+ __builtin_memcpy (pv, u.b + sizeof (uint64_t) - element_size,
+ element_size);
#endif
}
else
{
- if (selected == NULL)
+ if (!nb)
{
- _Bool success;
-
- success = __go_receive_big (channel, val, 0);
- if (received != NULL)
- *received = success;
+ ret.received = __go_receive_big (channel, pv, 0);
+ ret.selected = 1;
}
else
{
_Bool got;
_Bool closed;
- got = __go_receive_nonblocking_big (channel, val, &closed);
- *selected = got || closed;
- if (received != NULL)
- *received = got;
+ got = __go_receive_nonblocking_big (channel, pv, &closed);
+ ret.selected = got || closed;
+ ret.received = got;
}
}
+
+ return ret;
}
-extern void chanclose (unsigned char *)
- asm ("libgo_reflect.reflect.chanclose");
+extern void chanclose (uintptr_t) asm ("libgo_reflect.reflect.chanclose");
void
-chanclose (unsigned char *ch)
+chanclose (uintptr_t ch)
{
struct __go_channel *channel = (struct __go_channel *) ch;
__go_builtin_close (channel);
}
-extern int32_t chanlen (unsigned char *) asm ("libgo_reflect.reflect.chanlen");
+extern int32_t chanlen (uintptr_t) asm ("libgo_reflect.reflect.chanlen");
int32_t
-chanlen (unsigned char *ch)
+chanlen (uintptr_t ch)
{
struct __go_channel *channel = (struct __go_channel *) ch;
return (int32_t) __go_chan_len (channel);
}
-extern int32_t chancap (unsigned char *) asm ("libgo_reflect.reflect.chancap");
+extern int32_t chancap (uintptr_t) asm ("libgo_reflect.reflect.chancap");
int32_t
-chancap (unsigned char *ch)
+chancap (uintptr_t ch)
{
struct __go_channel *channel = (struct __go_channel *) ch;
diff --git a/libgo/runtime/go-reflect-map.c b/libgo/runtime/go-reflect-map.c
index 67960de..5559f6e 100644
--- a/libgo/runtime/go-reflect-map.c
+++ b/libgo/runtime/go-reflect-map.c
@@ -8,69 +8,125 @@
#include <stdint.h>
#include "go-alloc.h"
+#include "go-panic.h"
#include "go-type.h"
#include "map.h"
/* This file implements support for reflection on maps. These
functions are called from reflect/value.go. */
-extern _Bool mapaccess (unsigned char *, unsigned char *, unsigned char *)
+struct mapaccess_ret
+{
+ uintptr_t val;
+ _Bool pres;
+};
+
+extern struct mapaccess_ret mapaccess (uintptr_t, uintptr_t)
asm ("libgo_reflect.reflect.mapaccess");
-_Bool
-mapaccess (unsigned char *m, unsigned char *key, unsigned char *val)
+struct mapaccess_ret
+mapaccess (uintptr_t m, uintptr_t key_i)
{
struct __go_map *map = (struct __go_map *) m;
+ void *key;
+ const struct __go_type_descriptor *key_descriptor;
void *p;
const struct __go_type_descriptor *val_descriptor;
+ struct mapaccess_ret ret;
+ void *val;
+ void *pv;
+
+ if (map == NULL)
+ __go_panic_msg ("lookup in nil map");
+
+ key_descriptor = map->__descriptor->__map_descriptor->__key_type;
+ if (__go_is_pointer_type (key_descriptor))
+ key = &key_i;
+ else
+ key = (void *) key_i;
p = __go_map_index (map, key, 0);
+
+ val_descriptor = map->__descriptor->__map_descriptor->__val_type;
+ if (__go_is_pointer_type (val_descriptor))
+ {
+ val = NULL;
+ pv = &val;
+ }
+ else
+ {
+ val = __go_alloc (val_descriptor->__size);
+ pv = val;
+ }
+
if (p == NULL)
- return 0;
+ ret.pres = 0;
else
{
- val_descriptor = map->__descriptor->__map_descriptor->__val_type;
- __builtin_memcpy (val, p, val_descriptor->__size);
- return 1;
+ __builtin_memcpy (pv, p, val_descriptor->__size);
+ ret.pres = 1;
}
+
+ ret.val = (uintptr_t) val;
+ return ret;
}
-extern void mapassign (unsigned char *, unsigned char *, unsigned char *)
+extern void mapassign (uintptr_t, uintptr_t, uintptr_t, _Bool)
asm ("libgo_reflect.reflect.mapassign");
void
-mapassign (unsigned char *m, unsigned char *key, unsigned char *val)
+mapassign (uintptr_t m, uintptr_t key_i, uintptr_t val_i, _Bool pres)
{
struct __go_map *map = (struct __go_map *) m;
+ const struct __go_type_descriptor *key_descriptor;
+ void *key;
- if (val == NULL)
+ if (map == NULL)
+ __go_panic_msg ("lookup in nil map");
+
+ key_descriptor = map->__descriptor->__map_descriptor->__key_type;
+ if (__go_is_pointer_type (key_descriptor))
+ key = &key_i;
+ else
+ key = (void *) key_i;
+
+ if (!pres)
__go_map_delete (map, key);
else
{
void *p;
const struct __go_type_descriptor *val_descriptor;
+ void *pv;
p = __go_map_index (map, key, 1);
+
val_descriptor = map->__descriptor->__map_descriptor->__val_type;
- __builtin_memcpy (p, val, val_descriptor->__size);
+ if (__go_is_pointer_type (val_descriptor))
+ pv = &val_i;
+ else
+ pv = (void *) val_i;
+ __builtin_memcpy (p, pv, val_descriptor->__size);
}
}
-extern int32_t maplen (unsigned char *)
+extern int32_t maplen (uintptr_t)
asm ("libgo_reflect.reflect.maplen");
int32_t
-maplen (unsigned char *m __attribute__ ((unused)))
+maplen (uintptr_t m)
{
struct __go_map *map = (struct __go_map *) m;
+
+ if (map == NULL)
+ return 0;
return (int32_t) map->__element_count;
}
-extern unsigned char *mapiterinit (unsigned char *)
+extern unsigned char *mapiterinit (uintptr_t)
asm ("libgo_reflect.reflect.mapiterinit");
unsigned char *
-mapiterinit (unsigned char *m)
+mapiterinit (uintptr_t m)
{
struct __go_hash_iter *it;
@@ -88,35 +144,67 @@ mapiternext (unsigned char *it)
__go_mapiternext ((struct __go_hash_iter *) it);
}
-extern _Bool mapiterkey (unsigned char *, unsigned char *)
+struct mapiterkey_ret
+{
+ uintptr_t key;
+ _Bool ok;
+};
+
+extern struct mapiterkey_ret mapiterkey (unsigned char *)
asm ("libgo_reflect.reflect.mapiterkey");
-_Bool
-mapiterkey (unsigned char *ita, unsigned char *key)
+struct mapiterkey_ret
+mapiterkey (unsigned char *ita)
{
struct __go_hash_iter *it = (struct __go_hash_iter *) ita;
+ struct mapiterkey_ret ret;
if (it->entry == NULL)
- return 0;
+ {
+ ret.key = 0;
+ ret.ok = 0;
+ }
else
{
- __go_mapiter1 (it, key);
- return 1;
+ const struct __go_type_descriptor *key_descriptor;
+ void *key;
+ void *pk;
+
+ key_descriptor = it->map->__descriptor->__map_descriptor->__key_type;
+ if (__go_is_pointer_type (key_descriptor))
+ {
+ key = NULL;
+ pk = &key;
+ }
+ else
+ {
+ key = __go_alloc (key_descriptor->__size);
+ pk = key;
+ }
+
+ __go_mapiter1 (it, pk);
+
+ ret.key = (uintptr_t) key;
+ ret.ok = 1;
}
+
+ return ret;
}
/* Make a new map. We have to build our own map descriptor. */
-extern unsigned char *makemap (const struct __go_map_type *)
+extern uintptr_t makemap (const struct __go_map_type *)
asm ("libgo_reflect.reflect.makemap");
-unsigned char *
+uintptr_t
makemap (const struct __go_map_type *t)
{
struct __go_map_descriptor *md;
unsigned int o;
const struct __go_type_descriptor *kt;
const struct __go_type_descriptor *vt;
+ struct __go_map* map;
+ void *ret;
/* FIXME: Reference count. */
md = (struct __go_map_descriptor *) __go_alloc (sizeof (*md));
@@ -135,5 +223,9 @@ makemap (const struct __go_map_type *t)
o = (o + vt->__field_align - 1) & ~ (vt->__field_align - 1);
md->__entry_size = o;
- return (unsigned char *) __go_new_map (md, 0);
+ map = __go_new_map (md, 0);
+
+ ret = __go_alloc (sizeof (void *));
+ __builtin_memcpy (ret, &map, sizeof (void *));
+ return (uintptr_t) ret;
}
diff --git a/libgo/runtime/go-reflect.c b/libgo/runtime/go-reflect.c
index 9485c09..bf13a11 100644
--- a/libgo/runtime/go-reflect.c
+++ b/libgo/runtime/go-reflect.c
@@ -121,6 +121,9 @@ Reflect (struct __go_empty_interface e)
{
struct reflect_ret ret;
+ if (((uintptr_t) e.__type_descriptor & reflectFlags) != 0)
+ __go_panic_msg ("invalid interface value");
+
if (e.__type_descriptor == NULL)
{
ret.rettype.__type_descriptor = NULL;
@@ -166,6 +169,9 @@ Typeof (const struct __go_empty_interface e)
{
struct __go_empty_interface ret;
+ if (((uintptr_t) e.__type_descriptor & reflectFlags) != 0)
+ __go_panic_msg ("invalid interface value");
+
if (e.__type_descriptor == NULL)
{
ret.__type_descriptor = NULL;
diff --git a/libgo/runtime/go-send-big.c b/libgo/runtime/go-send-big.c
index c273263..0b4aa04 100644
--- a/libgo/runtime/go-send-big.c
+++ b/libgo/runtime/go-send-big.c
@@ -12,19 +12,20 @@
void
__go_send_big (struct __go_channel* channel, const void *val, _Bool for_select)
{
+ uintptr_t element_size;
size_t alloc_size;
size_t offset;
if (channel == NULL)
__go_panic_msg ("send to nil channel");
- alloc_size = ((channel->element_size + sizeof (uint64_t) - 1)
- / sizeof (uint64_t));
+ element_size = channel->element_type->__size;
+ alloc_size = (element_size + sizeof (uint64_t) - 1) / sizeof (uint64_t);
__go_send_acquire (channel, for_select);
offset = channel->next_store * alloc_size;
- __builtin_memcpy (&channel->data[offset], val, channel->element_size);
+ __builtin_memcpy (&channel->data[offset], val, element_size);
__go_send_release (channel);
}
diff --git a/libgo/runtime/go-send-nb-big.c b/libgo/runtime/go-send-nb-big.c
index 1d33dd6..1274859 100644
--- a/libgo/runtime/go-send-nb-big.c
+++ b/libgo/runtime/go-send-nb-big.c
@@ -11,17 +11,18 @@
_Bool
__go_send_nonblocking_big (struct __go_channel* channel, const void *val)
{
+ uintptr_t element_size;
size_t alloc_size;
size_t offset;
- alloc_size = ((channel->element_size + sizeof (uint64_t) - 1)
- / sizeof (uint64_t));
+ element_size = channel->element_type->__size;
+ alloc_size = (element_size + sizeof (uint64_t) - 1) / sizeof (uint64_t);
if (!__go_send_nonblocking_acquire (channel))
return 0;
offset = channel->next_store * alloc_size;
- __builtin_memcpy (&channel->data[offset], val, channel->element_size);
+ __builtin_memcpy (&channel->data[offset], val, element_size);
__go_send_release (channel);
diff --git a/libgo/runtime/go-send-nb-small.c b/libgo/runtime/go-send-nb-small.c
index 5c49a67..0a25ba3 100644
--- a/libgo/runtime/go-send-nb-small.c
+++ b/libgo/runtime/go-send-nb-small.c
@@ -93,7 +93,7 @@ __go_send_nonblocking_acquire (struct __go_channel *channel)
_Bool
__go_send_nonblocking_small (struct __go_channel *channel, uint64_t val)
{
- __go_assert (channel->element_size <= sizeof (uint64_t));
+ __go_assert (channel->element_type->__size <= sizeof (uint64_t));
if (!__go_send_nonblocking_acquire (channel))
return 0;
diff --git a/libgo/runtime/go-send-small.c b/libgo/runtime/go-send-small.c
index 56f9470..8e21d36 100644
--- a/libgo/runtime/go-send-small.c
+++ b/libgo/runtime/go-send-small.c
@@ -147,7 +147,7 @@ __go_send_small (struct __go_channel *channel, uint64_t val, _Bool for_select)
if (channel == NULL)
__go_panic_msg ("send to nil channel");
- __go_assert (channel->element_size <= sizeof (uint64_t));
+ __go_assert (channel->element_type->__size <= sizeof (uint64_t));
__go_send_acquire (channel, for_select);
diff --git a/libgo/runtime/go-setenv.c b/libgo/runtime/go-setenv.c
new file mode 100644
index 0000000..20f9939
--- /dev/null
+++ b/libgo/runtime/go-setenv.c
@@ -0,0 +1,50 @@
+/* go-setenv.c -- set the C environment from Go.
+
+ Copyright 2011 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 <stddef.h>
+#include <stdlib.h>
+
+#include "go-alloc.h"
+#include "go-string.h"
+
+/* Set the C environment from Go. This is called by os.Setenv. */
+
+void setenv_c (struct __go_string, struct __go_string)
+ __asm__ ("libgo_os.os.setenv_c");
+
+void
+setenv_c (struct __go_string k, struct __go_string v)
+{
+ const unsigned char *ks;
+ unsigned char *kn;
+ const unsigned char *vs;
+ unsigned char *vn;
+
+ ks = k.__data;
+ kn = NULL;
+ if (ks[k.__length] != 0)
+ {
+ kn = __go_alloc (k.__length + 1);
+ __builtin_memcpy (kn, k.__data, k.__length);
+ ks = kn;
+ }
+
+ vs = v.__data;
+ vn = NULL;
+ if (vs[v.__length] != 0)
+ {
+ vn = __go_alloc (v.__length + 1);
+ __builtin_memcpy (vn, v.__data, v.__length);
+ vs = vn;
+ }
+
+ setenv ((const char *) ks, (const char *) vs, 1);
+
+ if (kn != NULL)
+ __go_free (kn);
+ if (vn != NULL)
+ __go_free (vn);
+}
diff --git a/libgo/runtime/go-signal.c b/libgo/runtime/go-signal.c
index edeeccc..c16b058 100644
--- a/libgo/runtime/go-signal.c
+++ b/libgo/runtime/go-signal.c
@@ -245,3 +245,26 @@ runtime_resetcpuprofiler(int32 hz)
m->profilehz = hz;
}
+
+/* Used by the os package to raise SIGPIPE. */
+
+void os_sigpipe (void) __asm__ ("libgo_os.os.sigpipe");
+
+void
+os_sigpipe (void)
+{
+ struct sigaction sa;
+ int i;
+
+ memset (&sa, 0, sizeof sa);
+
+ sa.sa_handler = SIG_DFL;
+
+ i = sigemptyset (&sa.sa_mask);
+ __go_assert (i == 0);
+
+ if (sigaction (SIGPIPE, &sa, NULL) != 0)
+ abort ();
+
+ raise (SIGPIPE);
+}
diff --git a/libgo/runtime/go-type-eface.c b/libgo/runtime/go-type-eface.c
index 84ca05e..cea9c24 100644
--- a/libgo/runtime/go-type-eface.c
+++ b/libgo/runtime/go-type-eface.c
@@ -5,6 +5,7 @@
license that can be found in the LICENSE file. */
#include "interface.h"
+#include "go-panic.h"
#include "go-type.h"
/* A hash function for an empty interface. */
@@ -43,6 +44,9 @@ __go_type_equal_empty_interface (const void *vv1, const void *vv2,
v2 = (const struct __go_empty_interface *) vv2;
v1_descriptor = v1->__type_descriptor;
v2_descriptor = v2->__type_descriptor;
+ if (((uintptr_t) v1_descriptor & reflectFlags) != 0
+ || ((uintptr_t) v2_descriptor & reflectFlags) != 0)
+ __go_panic_msg ("invalid interface value");
if (v1_descriptor == NULL || v2_descriptor == NULL)
return v1_descriptor == v2_descriptor;
if (!__go_type_descriptors_equal (v1_descriptor, v2_descriptor))
diff --git a/libgo/runtime/go-type.h b/libgo/runtime/go-type.h
index 7668121..e048141 100644
--- a/libgo/runtime/go-type.h
+++ b/libgo/runtime/go-type.h
@@ -149,6 +149,9 @@ struct __go_array_type
/* The element type. */
struct __go_type_descriptor *__element_type;
+ /* The type of a slice of the same element type. */
+ struct __go_type_descriptor *__slice_type;
+
/* The length of the array. */
uintptr_t __len;
};
@@ -289,6 +292,15 @@ struct __go_struct_type
struct __go_open_array __fields;
};
+/* If an empty interface has these bits set in its type pointer, it
+ was copied from a reflect.Value and is not a valid empty
+ interface. */
+
+enum
+{
+ reflectFlags = 3,
+};
+
/* Whether a type descriptor is a pointer. */
static inline _Bool
diff --git a/libgo/runtime/go-unreflect.c b/libgo/runtime/go-unreflect.c
index 8860485..c4da5fd 100644
--- a/libgo/runtime/go-unreflect.c
+++ b/libgo/runtime/go-unreflect.c
@@ -5,6 +5,7 @@
license that can be found in the LICENSE file. */
#include "go-alloc.h"
+#include "go-panic.h"
#include "go-type.h"
#include "interface.h"
@@ -19,6 +20,9 @@ Unreflect (struct __go_empty_interface type, void *object)
{
struct __go_empty_interface ret;
+ if (((uintptr_t) type.__type_descriptor & reflectFlags) != 0)
+ __go_panic_msg ("invalid interface value");
+
/* FIXME: We should check __type_descriptor to verify that this is
really a type descriptor. */
ret.__type_descriptor = type.__object;
diff --git a/libgo/runtime/go-unsafe-new.c b/libgo/runtime/go-unsafe-new.c
index e55d415..b0a65c4 100644
--- a/libgo/runtime/go-unsafe-new.c
+++ b/libgo/runtime/go-unsafe-new.c
@@ -5,6 +5,7 @@
license that can be found in the LICENSE file. */
#include "go-alloc.h"
+#include "go-panic.h"
#include "go-type.h"
#include "interface.h"
@@ -20,6 +21,9 @@ New (struct __go_empty_interface type)
{
const struct __go_type_descriptor *descriptor;
+ if (((uintptr_t) type.__type_descriptor & reflectFlags) != 0)
+ __go_panic_msg ("invalid interface value");
+
/* FIXME: We should check __type_descriptor to verify that this is
really a type descriptor. */
descriptor = (const struct __go_type_descriptor *) type.__object;
diff --git a/libgo/runtime/go-unsafe-newarray.c b/libgo/runtime/go-unsafe-newarray.c
index 3bea282..5fd81ce 100644
--- a/libgo/runtime/go-unsafe-newarray.c
+++ b/libgo/runtime/go-unsafe-newarray.c
@@ -5,6 +5,7 @@
license that can be found in the LICENSE file. */
#include "go-alloc.h"
+#include "go-panic.h"
#include "go-type.h"
#include "interface.h"
@@ -21,6 +22,9 @@ NewArray (struct __go_empty_interface type, int n)
{
const struct __go_type_descriptor *descriptor;
+ if (((uintptr_t) type.__type_descriptor & reflectFlags) != 0)
+ __go_panic_msg ("invalid interface value");
+
/* FIXME: We should check __type_descriptor to verify that this is
really a type descriptor. */
descriptor = (const struct __go_type_descriptor *) type.__object;
diff --git a/libgo/runtime/iface.goc b/libgo/runtime/iface.goc
index 356b318..05e3773 100644
--- a/libgo/runtime/iface.goc
+++ b/libgo/runtime/iface.goc
@@ -3,6 +3,7 @@
// license that can be found in the LICENSE file.
package runtime
+#include "go-panic.h"
#include "go-type.h"
#include "interface.h"
#define nil NULL
@@ -33,6 +34,8 @@ func ifacetype(i interface) (d *const_descriptor) {
// Convert an empty interface to an empty interface.
func ifaceE2E2(e empty_interface) (ret empty_interface, ok bool) {
+ if(((uintptr_t)e.__type_descriptor&reflectFlags) != 0)
+ __go_panic_msg("invalid interface value");
ret = e;
ok = ret.__type_descriptor != nil;
}
@@ -52,6 +55,8 @@ func ifaceI2E2(i interface) (ret empty_interface, ok bool) {
// Convert an empty interface to a non-empty interface.
func ifaceE2I2(inter *descriptor, e empty_interface) (ret interface, ok bool) {
+ if(((uintptr_t)e.__type_descriptor&reflectFlags) != 0)
+ __go_panic_msg("invalid interface value");
if (e.__type_descriptor == nil) {
ret.__methods = nil;
ret.__object = nil;
@@ -81,6 +86,8 @@ func ifaceI2I2(inter *descriptor, i interface) (ret interface, ok bool) {
// Convert an empty interface to a pointer type.
func ifaceE2T2P(inter *descriptor, e empty_interface) (ret *void, ok bool) {
+ if(((uintptr_t)e.__type_descriptor&reflectFlags) != 0)
+ __go_panic_msg("invalid interface value");
if (!__go_type_descriptors_equal(inter, e.__type_descriptor)) {
ret = nil;
ok = 0;
@@ -104,6 +111,8 @@ func ifaceI2T2P(inter *descriptor, i interface) (ret *void, ok bool) {
// Convert an empty interface to a non-pointer type.
func ifaceE2T2(inter *descriptor, e empty_interface, ret *void) (ok bool) {
+ if(((uintptr_t)e.__type_descriptor&reflectFlags) != 0)
+ __go_panic_msg("invalid interface value");
if (!__go_type_descriptors_equal(inter, e.__type_descriptor)) {
__builtin_memset(ret, 0, inter->__size);
ok = 0;
diff --git a/libgo/runtime/malloc.goc b/libgo/runtime/malloc.goc
index 196271a..b46995a 100644
--- a/libgo/runtime/malloc.goc
+++ b/libgo/runtime/malloc.goc
@@ -386,7 +386,7 @@ runtime_MHeap_SysAlloc(MHeap *h, uintptr n)
return nil;
if(p < h->arena_start || (uintptr)(p+n - h->arena_start) >= MaxArena32) {
- runtime_printf("runtime: memory allocated by OS not in usable range");
+ runtime_printf("runtime: memory allocated by OS not in usable range\n");
runtime_SysFree(p, n);
return nil;
}
diff --git a/libgo/runtime/mcache.c b/libgo/runtime/mcache.c
index ce65757..65d849c 100644
--- a/libgo/runtime/mcache.c
+++ b/libgo/runtime/mcache.c
@@ -22,6 +22,8 @@ runtime_MCache_Alloc(MCache *c, int32 sizeclass, uintptr size, int32 zeroed)
// Replenish using central lists.
n = runtime_MCentral_AllocList(&runtime_mheap.central[sizeclass],
runtime_class_to_transfercount[sizeclass], &first);
+ if(n == 0)
+ runtime_throw("out of memory");
l->list = first;
l->nlist = n;
c->size += n*size;
diff --git a/libgo/runtime/mgc0.c b/libgo/runtime/mgc0.c
index 27fc3cd..0f28f5f 100644
--- a/libgo/runtime/mgc0.c
+++ b/libgo/runtime/mgc0.c
@@ -90,6 +90,11 @@ scanblock(byte *b, int64 n)
void **bw, **w, **ew;
Workbuf *wbuf;
+ if((int64)(uintptr)n != n || n < 0) {
+ // runtime_printf("scanblock %p %lld\n", b, (long long)n);
+ runtime_throw("scanblock");
+ }
+
// Memory arena parameters.
arena_start = runtime_mheap.arena_start;
@@ -602,7 +607,7 @@ runfinq(void* dummy)
next = f->next;
params[0] = &f->arg;
- reflect_call(f->ft, (void*)f->fn, 0, params, nil);
+ reflect_call(f->ft, (void*)f->fn, 0, 0, params, nil);
f->fn = nil;
f->arg = nil;
f->next = nil;
diff --git a/libgo/runtime/mheap.c b/libgo/runtime/mheap.c
index b36df25..cc6b3af 100644
--- a/libgo/runtime/mheap.c
+++ b/libgo/runtime/mheap.c
@@ -181,9 +181,7 @@ MHeap_Grow(MHeap *h, uintptr npage)
// Allocate a multiple of 64kB (16 pages).
npage = (npage+15)&~15;
ask = npage<<PageShift;
- if(ask > (uintptr)(h->arena_end - h->arena_used))
- return false;
- if(ask < HeapAllocChunk && HeapAllocChunk <= h->arena_end - h->arena_used)
+ if(ask < HeapAllocChunk)
ask = HeapAllocChunk;
v = runtime_MHeap_SysAlloc(h, ask);
@@ -192,8 +190,10 @@ MHeap_Grow(MHeap *h, uintptr npage)
ask = npage<<PageShift;
v = runtime_MHeap_SysAlloc(h, ask);
}
- if(v == nil)
+ if(v == nil) {
+ runtime_printf("runtime: out of memory: cannot allocate %llu-byte block (%llu in use)\n", (unsigned long long)ask, (unsigned long long)mstats.heap_sys);
return false;
+ }
}
mstats.heap_sys += ask;
diff --git a/libgo/runtime/reflect.goc b/libgo/runtime/reflect.goc
index 01d218a..4666dd5 100644
--- a/libgo/runtime/reflect.goc
+++ b/libgo/runtime/reflect.goc
@@ -5,31 +5,27 @@
package reflect
#include "go-type.h"
#include "interface.h"
-#define nil NULL
-typedef unsigned char byte;
+#include "runtime.h"
+#include "go-panic.h"
+typedef struct __go_type_descriptor Type;
typedef struct __go_interface Iface;
typedef struct __go_empty_interface Eface;
-func setiface(typ *byte, x *byte, ret *byte) {
- struct __go_interface_type *t;
- const struct __go_type_descriptor* xt;
+func ifaceE2I(inter *Type, e Eface, ret *Iface) {
+ const Type *t;
+ Eface err;
- /* FIXME: We should check __type_descriptor to verify that
- this is really a type descriptor. */
- t = (struct __go_interface_type *)typ;
- if(t->__methods.__count == 0) {
- // already an empty interface
- *(Eface*)ret = *(Eface*)x;
- return;
+ if(((uintptr)e.__type_descriptor&reflectFlags) != 0)
+ runtime_throw("invalid interface value");
+ t = e.__type_descriptor;
+ if(t == nil) {
+ // explicit conversions require non-nil interface value.
+ newTypeAssertionError(nil, nil, inter,
+ nil, nil, inter->__reflection,
+ nil, &err);
+ __go_panic(err);
}
- xt = ((Eface*)x)->__type_descriptor;
- if(xt == nil) {
- // can assign nil to any interface
- ((Iface*)ret)->__methods = nil;
- ((Iface*)ret)->__object = nil;
- return;
- }
- ((Iface*)ret)->__methods = __go_convert_interface(&t->__common, xt);
- ((Iface*)ret)->__object = ((Eface*)x)->__object;
+ ret->__object = e.__object;
+ ret->__methods = __go_convert_interface(inter, t);
}
diff --git a/libgo/runtime/runtime.h b/libgo/runtime/runtime.h
index 00ba40f..bf07c12 100644
--- a/libgo/runtime/runtime.h
+++ b/libgo/runtime/runtime.h
@@ -194,8 +194,8 @@ void runtime_resetcpuprofiler(int32);
void runtime_setcpuprofilerate(void(*)(uintptr*, int32), int32);
struct __go_func_type;
-void reflect_call(const struct __go_func_type *, const void *, _Bool, void **,
- void **)
+void reflect_call(const struct __go_func_type *, const void *, _Bool, _Bool,
+ void **, void **)
asm ("libgo_reflect.reflect.call");
#ifdef __rtems__