* [gccgo] Mark memory which can not contain pointers
@ 2010-07-23 16:45 Ian Lance Taylor
0 siblings, 0 replies; only message in thread
From: Ian Lance Taylor @ 2010-07-23 16:45 UTC (permalink / raw)
To: gcc-patches, gofrontend-dev
[-- Attachment #1: Type: text/plain, Size: 282 bytes --]
This patch uses a different allocation routine for memory which can not
contain pointers (e.g., []byte). The marking already exists in the
memory allocator, this just changes the compiler to use it. This is in
preparation for garbage collection. Committed to gccgo branch.
Ian
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: pointers --]
[-- Type: text/x-diff, Size: 11995 bytes --]
diff -r 640e5a4f513f go/expressions.cc
--- a/go/expressions.cc Fri Jul 23 03:59:55 2010 -0700
+++ b/go/expressions.cc Fri Jul 23 09:36:21 2010 -0700
@@ -10252,8 +10252,9 @@
{
tree type_tree = this->type_->get_tree(context->gogo());
tree size_tree = TYPE_SIZE_UNIT(type_tree);
- tree space = context->gogo()->allocate_memory(size_tree, this->location());
- return fold_convert(build_pointer_type (type_tree), space);
+ tree space = context->gogo()->allocate_memory(this->type_, size_tree,
+ this->location());
+ return fold_convert(build_pointer_type(type_tree), space);
}
// Make an allocation expression.
@@ -11122,7 +11123,8 @@
else
{
tree memsize = TYPE_SIZE_UNIT(TREE_TYPE(values));
- space = context->gogo()->allocate_memory(memsize, this->location());
+ space = context->gogo()->allocate_memory(element_type, memsize,
+ this->location());
space = save_expr(space);
tree s = fold_convert(build_pointer_type(TREE_TYPE(values)), space);
@@ -12106,7 +12108,8 @@
return error_mark_node;
tree expr_size = TYPE_SIZE_UNIT(TREE_TYPE(expr_tree));
gcc_assert(TREE_CODE(expr_size) == INTEGER_CST);
- tree space = context->gogo()->allocate_memory(expr_size, this->location());
+ tree space = context->gogo()->allocate_memory(this->expr_->type(),
+ expr_size, this->location());
space = fold_convert(build_pointer_type(TREE_TYPE(expr_tree)), space);
space = save_expr(space);
tree ret = build2(COMPOUND_EXPR, TREE_TYPE(space),
diff -r 640e5a4f513f go/gogo-tree.cc
--- a/go/gogo-tree.cc Fri Jul 23 03:59:55 2010 -0700
+++ b/go/gogo-tree.cc Fri Jul 23 09:36:21 2010 -0700
@@ -666,6 +666,12 @@
// Pass everything back to the middle-end.
+ if (this->imported_unsafe_)
+ {
+ // Importing the "unsafe" package automatically disables TBAA.
+ flag_strict_aliasing = false;
+ }
+
wrapup_global_declarations(vec, count);
cgraph_finalize_compilation_unit();
@@ -918,7 +924,8 @@
init = type->get_init_tree(gogo, false);
else
{
- tree space = gogo->allocate_memory(TYPE_SIZE_UNIT(result_type),
+ tree space = gogo->allocate_memory(type,
+ TYPE_SIZE_UNIT(result_type),
loc);
result_type = build_pointer_type(result_type);
tree subinit = type->get_init_tree(gogo, true);
@@ -1265,7 +1272,8 @@
if (is_in_heap)
{
tree size = TYPE_SIZE_UNIT(val_type);
- tree space = gogo->allocate_memory(size, DECL_SOURCE_LOCATION(var_decl));
+ tree space = gogo->allocate_memory(no->var_value()->type(), size,
+ no->location());
space = save_expr(space);
space = fold_convert(build_pointer_type(val_type), space);
init = build2(COMPOUND_EXPR, TREE_TYPE(space),
@@ -1285,7 +1293,7 @@
// indirection.
tree
-Function::copy_parm_to_heap(Gogo* gogo, tree ref)
+Function::copy_parm_to_heap(Gogo* gogo, Named_object* no, tree ref)
{
gcc_assert(TREE_CODE(ref) == INDIRECT_REF);
@@ -1306,7 +1314,7 @@
DECL_ARG_TYPE(parm_decl) = type;
tree size = TYPE_SIZE_UNIT(type);
- tree space = gogo->allocate_memory(size, loc);
+ tree space = gogo->allocate_memory(no->var_value()->type(), size, loc);
space = save_expr(space);
space = fold_convert(TREE_TYPE(var_decl), space);
tree init = build2(COMPOUND_EXPR, TREE_TYPE(space),
@@ -1359,7 +1367,7 @@
{
// If we take the address of a parameter, then we need
// to copy it into the heap.
- tree parm_decl = this->copy_parm_to_heap(gogo, *pp);
+ tree parm_decl = this->copy_parm_to_heap(gogo, *p, *pp);
gcc_assert(TREE_CODE(*pp) == INDIRECT_REF);
tree var_decl = TREE_OPERAND(*pp, 0);
gcc_assert(TREE_CODE(var_decl) == VAR_DECL);
@@ -1927,19 +1935,36 @@
return NULL_TREE;
}
-// Return a tree which allocates SIZE bytes.
+// Return a tree which allocates SIZE bytes which will holds value of
+// type TYPE.
tree
-Gogo::allocate_memory(tree size, source_location location)
+Gogo::allocate_memory(Type* type, tree size, source_location location)
{
- static tree new_fndecl;
- return Gogo::call_builtin(&new_fndecl,
- location,
- "__go_new",
- 1,
- ptr_type_node,
- sizetype,
- size);
+ // If the package imports unsafe, then it may play games with
+ // pointers that look like integers.
+ if (this->imported_unsafe_ || type->has_pointer())
+ {
+ static tree new_fndecl;
+ return Gogo::call_builtin(&new_fndecl,
+ location,
+ "__go_new",
+ 1,
+ ptr_type_node,
+ sizetype,
+ size);
+ }
+ else
+ {
+ static tree new_nopointers_fndecl;
+ return Gogo::call_builtin(&new_nopointers_fndecl,
+ location,
+ "__go_new_nopointers",
+ 1,
+ ptr_type_node,
+ sizetype,
+ size);
+ }
}
// Build a builtin struct with a list of fields. The name is
diff -r 640e5a4f513f go/gogo.cc
--- a/go/gogo.cc Fri Jul 23 03:59:55 2010 -0700
+++ b/go/gogo.cc Fri Jul 23 09:36:21 2010 -0700
@@ -27,6 +27,7 @@
functions_(),
globals_(new Bindings(NULL)),
imports_(),
+ imported_unsafe_(false),
packages_(),
map_descriptors_(NULL),
type_descriptor_decls_(NULL),
diff -r 640e5a4f513f go/gogo.h
--- a/go/gogo.h Fri Jul 23 03:59:55 2010 -0700
+++ b/go/gogo.h Fri Jul 23 09:36:21 2010 -0700
@@ -520,9 +520,10 @@
tree
interface_method_table_for_type(const Interface_type*, const Named_type*);
- // Return a tree which allocates SIZE bytes.
+ // Return a tree which allocate SIZE bytes to hold values of type
+ // TYPE.
tree
- allocate_memory(tree size, source_location);
+ allocate_memory(Type *type, tree size, source_location);
// Return a type to use for pointer to const char.
static tree
@@ -761,6 +762,8 @@
Bindings* globals_;
// Mapping from import file names to packages.
Imports imports_;
+ // Whether the magic unsafe package was imported.
+ bool imported_unsafe_;
// Mapping from package names we have seen to packages. This does
// not include the package we are compiling.
Packages packages_;
@@ -1084,7 +1087,7 @@
make_receiver_parm_decl(Gogo*, Named_object*, tree);
tree
- copy_parm_to_heap(Gogo*, tree);
+ copy_parm_to_heap(Gogo*, Named_object*, tree);
void
build_defer_wrapper(Gogo*, Named_object*, tree, tree*, tree*);
diff -r 640e5a4f513f go/statements.cc
--- a/go/statements.cc Fri Jul 23 03:59:55 2010 -0700
+++ b/go/statements.cc Fri Jul 23 09:36:21 2010 -0700
@@ -267,7 +267,8 @@
tree type = TREE_TYPE(decl);
gcc_assert(POINTER_TYPE_P(type));
tree size = TYPE_SIZE_UNIT(TREE_TYPE(type));
- tree space = context->gogo()->allocate_memory(size, this->location());
+ tree space = context->gogo()->allocate_memory(variable->type(), size,
+ this->location());
space = fold_convert(TREE_TYPE(decl), space);
DECL_INITIAL(decl) = space;
return build2(COMPOUND_EXPR, void_type_node,
diff -r 640e5a4f513f go/types.cc
--- a/go/types.cc Fri Jul 23 03:59:55 2010 -0700
+++ b/go/types.cc Fri Jul 23 09:36:21 2010 -0700
@@ -2492,6 +2492,10 @@
{ }
protected:
+ bool
+ do_has_pointer() const
+ { gcc_unreachable(); }
+
tree
do_get_tree(Gogo*);
@@ -2649,6 +2653,24 @@
return true;
}
+// Whether this contains a pointer.
+
+bool
+Struct_type::do_has_pointer() const
+{
+ const Struct_field_list* fields = this->fields();
+ if (fields == NULL)
+ return false;
+ for (Struct_field_list::const_iterator p = fields->begin();
+ p != fields->end();
+ ++p)
+ {
+ if (p->type()->has_pointer())
+ return true;
+ }
+ return false;
+}
+
// Whether this contains a reference counted component.
bool
@@ -3621,7 +3643,8 @@
tree size_tree = fold_build2_loc(location, MULT_EXPR, TREE_TYPE(count_field),
element_size_tree, capacity_tree);
- tree space = context->gogo()->allocate_memory(size_tree, location);
+ tree space = context->gogo()->allocate_memory(this->element_type_,
+ size_tree, location);
if (value != NULL_TREE)
space = save_expr(space);
diff -r 640e5a4f513f go/types.h
--- a/go/types.h Fri Jul 23 03:59:55 2010 -0700
+++ b/go/types.h Fri Jul 23 09:36:21 2010 -0700
@@ -583,6 +583,13 @@
Type*
make_non_abstract_type();
+ // Return true if this type is or contains a pointer. This
+ // determines whether the garbage collector needs to look at a value
+ // of this type.
+ bool
+ has_pointer() const
+ { return this->do_has_pointer(); }
+
// Return true if this type requires reference counting: if copying
// or destroying a value of this type requires adjusting a reference
// count.
@@ -888,6 +895,10 @@
{ return true; }
virtual bool
+ do_has_pointer() const
+ { return false; }
+
+ virtual bool
do_is_refcounted() const
{ return false; }
@@ -1488,6 +1499,10 @@
protected:
bool
+ do_has_pointer() const
+ { return true; }
+
+ bool
do_is_refcounted() const
{ return true; }
@@ -1600,6 +1615,11 @@
int
do_traverse(Traverse*);
+ // A trampoline function has a pointer which matters for GC.
+ bool
+ do_has_pointer() const
+ { return true; }
+
// Function types are really pointers, and they are reference
// counted in case that pointer points to a trampoline.
bool
@@ -1670,6 +1690,10 @@
do_traverse(Traverse*);
bool
+ do_has_pointer() const
+ { return true; }
+
+ bool
do_is_refcounted() const
{ return !this->is_unsafe_pointer_type(); }
@@ -1922,6 +1946,9 @@
do_verify();
bool
+ do_has_pointer() const;
+
+ bool
do_has_refcounted_component() const;
void
@@ -2015,6 +2042,12 @@
do_traverse(Traverse* traverse);
bool
+ do_has_pointer() const
+ {
+ return this->length_ == NULL || this->element_type_->has_pointer();
+ }
+
+ bool
do_is_refcounted() const
{
return (this->length_ == NULL
@@ -2108,6 +2141,10 @@
do_verify();
bool
+ do_has_pointer() const
+ { return true; }
+
+ bool
do_is_refcounted() const
{ return true; }
@@ -2189,6 +2226,10 @@
{ return Type::traverse(this->element_type_, traverse); }
bool
+ do_has_pointer() const
+ { return true; }
+
+ bool
do_is_refcounted() const
{ return true; }
@@ -2293,6 +2334,10 @@
do_traverse(Traverse*);
bool
+ do_has_pointer() const
+ { return true; }
+
+ bool
do_is_refcounted() const
{ return true; }
@@ -2493,6 +2538,10 @@
do_verify();
bool
+ do_has_pointer() const
+ { return this->type_->has_pointer(); }
+
+ bool
do_is_refcounted() const
{ return this->type_->is_refcounted(); }
@@ -2626,6 +2675,10 @@
do_traverse(Traverse* traverse);
bool
+ do_has_pointer() const
+ { return this->base()->has_pointer(); }
+
+ bool
do_is_refcounted() const
{ return this->base()->is_refcounted(); }
diff -r 640e5a4f513f go/unsafe.cc
--- a/go/unsafe.cc Fri Jul 23 03:59:55 2010 -0700
+++ b/go/unsafe.cc Fri Jul 23 09:36:21 2010 -0700
@@ -18,9 +18,6 @@
{
location_t bloc = BUILTINS_LOCATION;
- // Importing the "unsafe" package automatically disables TBAA.
- flag_strict_aliasing = false;
-
bool add_to_globals;
Package* package = this->add_imported_package("unsafe", local_name,
is_local_name_exported,
@@ -132,4 +129,6 @@
no = bindings->add_function_declaration("NewArray", package, fntype, bloc);
if (add_to_globals)
this->add_named_object(no);
+
+ this->imported_unsafe_ = true;
}
diff -r 640e5a4f513f libgo/runtime/go-new.c
--- a/libgo/runtime/go-new.c Fri Jul 23 03:59:55 2010 -0700
+++ b/libgo/runtime/go-new.c Fri Jul 23 09:36:21 2010 -0700
@@ -5,13 +5,17 @@
license that can be found in the LICENSE file. */
#include "go-alloc.h"
+#include "runtime.h"
+#include "malloc.h"
void *
__go_new (size_t size)
{
- void *ret;
+ return __go_alloc (size);
+}
- ret = __go_alloc (size);
- __builtin_memset (ret, 0, size);
- return ret;
+void *
+__go_new_nopointers (size_t size)
+{
+ return mallocgc (size, RefNoPointers, 1, 1);
}
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2010-07-23 16:45 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-07-23 16:45 [gccgo] Mark memory which can not contain pointers Ian Lance Taylor
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).