* [gccgo] Remove old reference counting code
@ 2010-07-23 20:35 Ian Lance Taylor
0 siblings, 0 replies; only message in thread
From: Ian Lance Taylor @ 2010-07-23 20:35 UTC (permalink / raw)
To: gcc-patches, gofrontend-dev
[-- Attachment #1: Type: text/plain, Size: 230 bytes --]
This patch removes the old reference counting code. It never actually
worked, and the new garbage collector code doesn't use it. If we go
back to this approach, it needs to be rewritten anyhow. Committed to
gccgo branch.
Ian
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: refcount --]
[-- Type: text/x-diff, Size: 142206 bytes --]
diff -r 38d1b9933c3e go/Make-lang.in
--- a/go/Make-lang.in Fri Jul 23 09:49:42 2010 -0700
+++ b/go/Make-lang.in Fri Jul 23 13:26:04 2010 -0700
@@ -60,7 +60,6 @@
go/import-elf.o \
go/lex.o \
go/parse.o \
- go/refcount.o \
go/statements.o \
go/types.o \
go/unsafe.o
@@ -149,7 +148,7 @@
go/expressions.o: go/expressions.cc $(GO_SYSTEM_H) intl.h $(TREE_H) \
$(GIMPLE_H) tree-iterator.h convert.h $(REAL_H) $(TM_P_H) \
$(GO_C_H) $(GO_GOGO_H) $(GO_TYPES_H) go/export.h $(GO_IMPORT_H) \
- go/refcount.h $(GO_STATEMENTS_H) $(GO_LEX_H) $(GO_EXPRESSIONS_H)
+ $(GO_STATEMENTS_H) $(GO_LEX_H) $(GO_EXPRESSIONS_H)
go/go.o: go/go.cc $(GO_SYSTEM_H) $(GO_C_H) $(GO_LEX_H) $(GO_PARSE_H) \
$(GO_GOGO_H)
go/go-dump.o: go/go-dump.cc $(GO_SYSTEM_H) $(GO_C_H) go/go-dump.h
@@ -160,10 +159,10 @@
go/gogo-tree.o: go/gogo-tree.cc $(GO_SYSTEM_H) $(TREE_H) $(GIMPLE_H) \
tree-iterator.h $(CGRAPH_H) langhooks.h convert.h output.h \
$(TM_P_H) $(DIAGNOSTIC_H) $(GO_TYPES_H) $(GO_EXPRESSIONS_H) \
- $(GO_STATEMENTS_H) go/refcount.h $(GO_GOGO_H)
+ $(GO_STATEMENTS_H) $(GO_GOGO_H)
go/gogo.o: go/gogo.cc $(GO_SYSTEM_H) go/go-dump.h $(GO_LEX_H) $(GO_TYPES_H) \
$(GO_STATEMENTS_H) $(GO_EXPRESSIONS_H) go/dataflow.h $(GO_IMPORT_H) \
- go/export.h go/refcount.h $(GO_GOGO_H)
+ go/export.h $(GO_GOGO_H)
go/import.o: go/import.cc $(GO_SYSTEM_H) $(srcdir)/../include/filenames.h \
$(GO_C_H) $(GO_GOGO_H) $(GO_TYPES_H) go/export.h $(GO_IMPORT_H)
go/import-archive.o: go/import-archive.cc $(GO_SYSTEM_H) $(GO_IMPORT_H)
@@ -172,15 +171,11 @@
go/lex.o: go/lex.cc $(GO_LEX_H) $(GO_SYSTEM_H)
go/parse.o: go/parse.cc $(GO_SYSTEM_H) $(GO_LEX_H) $(GO_GOGO_H) $(GO_TYPES_H) \
$(GO_STATEMENTS_H) $(GO_EXPRESSIONS_H) $(GO_PARSE_H)
-go/refcount.o: go/refcount.cc $(GO_SYSTEM_H) $(TREE_H) $(GIMPLE_H) \
- tree-iterator.h $(RTL_H) $(GO_C_H) go/go-dump.h $(GO_GOGO_H) \
- $(GO_TYPES_H) $(GO_EXPRESSIONS_H) $(GO_STATEMENTS_H) go/refcount.h
go/statements.o: go/statements.cc $(GO_SYSTEM_H) intl.h $(TREE_H) \
$(GIMPLE_H) convert.h tree-iterator.h $(TREE_FLOW_H) $(REAL_H) \
- $(GO_C_H) $(GO_TYPES_H) $(GO_EXPRESSIONS_H) $(GO_GOGO_H) go/refcount.h \
+ $(GO_C_H) $(GO_TYPES_H) $(GO_EXPRESSIONS_H) $(GO_GOGO_H) \
$(GO_STATEMENTS_H)
go/types.o: go/types.cc $(GO_SYSTEM_H) intl.h $(TREE_H) $(GIMPLE_H) \
$(REAL_H) $(GO_C_H) $(GO_GOGO_H) go/operator.h $(GO_EXPRESSIONS_H) \
- $(GO_STATEMENTS_H) go/export.h $(GO_IMPORT_H) go/refcount.h \
- $(GO_TYPES_H)
+ $(GO_STATEMENTS_H) go/export.h $(GO_IMPORT_H) $(GO_TYPES_H)
go/unsafe.o: go/unsafe.cc $(GO_SYSTEM_H) $(GO_TYPES_H) $(GO_GOGO_H)
diff -r 38d1b9933c3e go/expressions.cc
--- a/go/expressions.cc Fri Jul 23 09:49:42 2010 -0700
+++ b/go/expressions.cc Fri Jul 23 13:26:04 2010 -0700
@@ -24,7 +24,6 @@
#include "types.h"
#include "export.h"
#include "import.h"
-#include "refcount.h"
#include "statements.h"
#include "lex.h"
#include "expressions.h"
@@ -135,16 +134,6 @@
this->warn_unused_value();
}
-// This is the default implementation of the function to handle
-// decrementing the reference count of the old value of an lvalue.
-// Any expression which may be an l-value must implement this.
-
-Expression*
-Expression::do_being_set(Refcounts*)
-{
- gcc_unreachable();
-}
-
// This virtual function is called to export expressions. This will
// only be used by expressions which may be constant.
@@ -802,10 +791,6 @@
do_is_addressable() const
{ return true; }
- Expression*
- do_being_set(Refcounts*)
- { return this; }
-
tree
do_get_tree(Translate_context*)
{ return error_mark_node; }
@@ -925,38 +910,6 @@
gcc_unreachable();
}
-// This variable is being copied. We may need to increment the
-// reference count.
-
-Expression*
-Var_expression::do_being_copied(Refcounts* refcounts, bool for_local)
-{
- if (!this->type()->has_refcounted_component())
- return this;
-
- // FIXME: If this is the last use of this variable, then instead of
- // introducing a copy we can avoid freeing this variable at the end
- // of the function.
-
- return Expression::make_refcount_adjust(refcounts,
- REFCOUNT_INCREMENT_COPIED,
- this, for_local);
-}
-
-// This variable is being set. We may need to decrement the reference
-// count of the old value.
-
-Expression*
-Var_expression::do_being_set(Refcounts* refcounts)
-{
- if (this->variable_->is_variable()
- && this->variable_->var_value()->holds_only_args())
- return this;
- if (!this->type()->has_refcounted_component())
- return this;
- return Expression::make_refcount_decrement_lvalue(refcounts, this);
-}
-
// Get the tree for a reference to a variable.
tree
@@ -999,31 +952,6 @@
this->statement_->set_is_address_taken();
}
-// The temporary variable is being copied. We may need to increment
-// the reference count.
-
-Expression*
-Temporary_reference_expression::do_being_copied(Refcounts* refcounts,
- bool for_local)
-{
- if (!this->type()->has_refcounted_component())
- return this;
- return Expression::make_refcount_adjust(refcounts,
- REFCOUNT_INCREMENT_COPIED,
- this, for_local);
-}
-
-// The variable is being set. We may need to decrement the reference
-// count of the old value.
-
-Expression*
-Temporary_reference_expression::do_being_set(Refcounts* refcounts)
-{
- if (!this->type()->has_refcounted_component())
- return this;
- return Expression::make_refcount_decrement_lvalue(refcounts, this);
-}
-
// Get a tree referring to the variable.
tree
@@ -1070,10 +998,6 @@
do_is_lvalue() const
{ return true; }
- Expression*
- do_being_set(Refcounts*)
- { return this; }
-
tree
do_get_tree(Translate_context*);
@@ -1141,9 +1065,7 @@
return this->function_->name();
}
-// Traversal. FIXME: Traversing the closure means that we make an
-// entry in the reference count queue for it, but we will never use
-// that entry in practice.
+// Traversal.
int
Func_expression::do_traverse(Traverse* traverse)
@@ -1166,24 +1088,6 @@
gcc_unreachable();
}
-// Copying a function expression requires copying the closure, if any.
-
-Expression*
-Func_expression::do_being_copied(Refcounts* refcounts, bool for_local)
-{
- if (this->closure_ != NULL)
- this->closure_ = this->closure_->being_copied(refcounts, for_local);
- return this;
-}
-
-// There is nothing to do if we discard a function expression.
-
-Expression*
-Func_expression::do_note_decrements(Refcounts*)
-{
- return this;
-}
-
// Get the tree for a function expression without evaluating the
// closure.
@@ -2345,12 +2249,6 @@
do_copy()
{ return this; }
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts*);
-
tree
do_get_tree(Translate_context* context);
@@ -2556,32 +2454,6 @@
}
}
-// Copying a constant will require incrementing a reference count if
-// the constant is a struct or an array with components that require
-// reference counts. If the type itself is reference counted then
-// copying it should not require any adustment.
-
-Expression*
-Const_expression::do_being_copied(Refcounts* refcounts, bool for_local)
-{
- Type* type = this->type();
- if (type->is_refcounted())
- return this;
- if (!type->has_refcounted_component())
- return this;
- return Expression::make_refcount_adjust(refcounts,
- REFCOUNT_INCREMENT_COPIED,
- this, for_local);
-}
-
-// Referring to a constant never increments a reference count.
-
-Expression*
-Const_expression::do_note_decrements(Refcounts*)
-{
- return this;
-}
-
// Return a tree for the const reference.
tree
@@ -2763,7 +2635,7 @@
Type_conversion_expression(Type* type, Expression* expr,
source_location location)
: Expression(EXPRESSION_CONVERSION, location),
- type_(type), expr_(expr), is_being_copied_(false)
+ type_(type), expr_(expr)
{ }
// Return the type to which we are converting.
@@ -2823,12 +2695,6 @@
this->location());
}
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts*);
-
tree
do_get_tree(Translate_context* context);
@@ -2840,8 +2706,6 @@
Type* type_;
// The expression to convert.
Expression* expr_;
- // Whether this expression is being copied.
- bool is_being_copied_;
};
// Traversal.
@@ -3223,66 +3087,6 @@
}
}
-// The type conversion is being copied elsewhere. If we do not call a
-// function which creates a new reference, then we need to pass this
-// on to the subsidiary expression.
-
-Expression*
-Type_conversion_expression::do_being_copied(Refcounts* refcounts,
- bool for_local)
-{
- this->is_being_copied_ = true;
- Type* type = this->type_;
- Type* expr_type = this->expr_->type();
- bool copy_base;
- if (type == expr_type)
- copy_base = true;
- else if (type->interface_type() != NULL
- || expr_type->interface_type() != NULL)
- copy_base = false;
- else if (type->is_string_type()
- && (expr_type->integer_type() != NULL
- || expr_type->deref()->array_type() != NULL))
- copy_base = false;
- else if (type->is_open_array_type() && expr_type->is_string_type())
- copy_base = false;
- else
- copy_base = true;
- if (copy_base && expr_type->has_refcounted_component())
- this->expr_ = this->expr_->being_copied(refcounts, for_local);
- return this;
-}
-
-// A type conversion may introduce a reference count.
-
-Expression*
-Type_conversion_expression::do_note_decrements(Refcounts* refcounts)
-{
- if (this->is_being_copied_)
- return this;
- Type* type = this->type_;
- Type* expr_type = this->expr_->type();
- bool need_decrement;
- if (type == expr_type)
- need_decrement = false;
- else if (type->interface_type() != NULL)
- need_decrement = true;
- else if (expr_type->interface_type() != NULL)
- need_decrement = type->has_refcounted_component();
- else if (type->is_string_type()
- && (expr_type->integer_type() != NULL
- || expr_type->deref()->array_type() != NULL))
- need_decrement = true;
- else if (type->is_open_array_type() && expr_type->is_string_type())
- need_decrement = true;
- else
- need_decrement = false;
- if (!need_decrement)
- return this;
- return Expression::make_refcount_adjust(refcounts, REFCOUNT_DECREMENT_NEW,
- this, false);
-}
-
// Get a tree for a type conversion.
tree
@@ -3572,15 +3376,6 @@
do_is_addressable() const
{ return this->op_ == OPERATOR_MULT; }
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts*);
-
- Expression*
- do_being_set(Refcounts*);
-
tree
do_get_tree(Translate_context*);
@@ -4030,52 +3825,6 @@
}
}
-// Copying a unary expression may require incrementing a reference
-// count.
-
-Expression*
-Unary_expression::do_being_copied(Refcounts* refcounts, bool for_local)
-{
- if (!this->type()->has_refcounted_component())
- return this;
- if (this->op_ == OPERATOR_PLUS)
- {
- this->expr_ = this->expr_->being_copied(refcounts, for_local);
- return this;
- }
- else if (this->op_ == OPERATOR_AND && this->is_constant())
- {
- // No need to increment the reference count when the address is
- // a constant.
- return this;
- }
- else
- return Expression::make_refcount_adjust(refcounts,
- REFCOUNT_INCREMENT_COPIED,
- this, for_local);
-}
-
-// A unary expression does not increment any reference counts, so
-// there are no reference counts to decrement afterward.
-
-Expression*
-Unary_expression::do_note_decrements(Refcounts*)
-{
- return this;
-}
-
-// Assigning to *p requires decrementing the reference count of the
-// old value.
-
-Expression*
-Unary_expression::do_being_set(Refcounts* refcounts)
-{
- gcc_assert(this->op_ == OPERATOR_MULT);
- if (!this->type()->has_refcounted_component())
- return this;
- return Expression::make_refcount_decrement_lvalue(refcounts, this);
-}
-
// Get a tree for a unary expression.
tree
@@ -5674,31 +5423,6 @@
}
}
-// Copying a binary expression never requires incrementing a reference
-// count, but we do have to disable incrementing the reference count.
-
-Expression*
-Binary_expression::do_being_copied(Refcounts*, bool)
-{
- this->is_being_copied_ = true;
- return this;
-}
-
-// A binary expression increments a reference count when adding
-// strings.
-
-Expression*
-Binary_expression::do_note_decrements(Refcounts* refcounts)
-{
- if (this->op_ != OPERATOR_PLUS
- || !this->left_->type()->is_string_type()
- || this->is_being_copied_)
- return this;
- return Expression::make_refcount_adjust(refcounts,
- REFCOUNT_DECREMENT_NEW,
- this, false);
-}
-
// Get a tree for a binary expression.
tree
@@ -8348,64 +8072,6 @@
return interface_method->get_function_tree(context, expr);
}
-// The call expression is being copied. There is nothing to do here
-// except to disable any decrements--the function should return with
-// an appropriate reference count.
-
-Expression*
-Call_expression::do_being_copied(Refcounts*, bool)
-{
- this->is_being_copied_ = true;
- return this;
-}
-
-// Where needed, decrement the reference counts of any values returned
-// by this call.
-
-Expression*
-Call_expression::do_note_decrements(Refcounts* refcounts)
-{
- if (this->is_being_copied_)
- return this;
- Function_type* fntype = this->get_function_type();
- if (fntype == NULL)
- return this;
- const Typed_identifier_list* results = fntype->results();
- if (results == NULL)
- return this;
- if (results->size() == 1)
- {
- if (!results->begin()->type()->has_refcounted_component())
- return this;
- return Expression::make_refcount_adjust(refcounts,
- REFCOUNT_DECREMENT_COMPUTED,
- this, false);
- }
- else if (!this->is_value_discarded_)
- {
- // If the value is not discarded, each result will be handled
- // separately via Call_expression_result.
- return this;
- }
- else
- {
- for (Typed_identifier_list::const_iterator p = results->begin();
- p != results->end();
- p++)
- {
- if (p->type()->has_refcounted_component())
- {
- if (this->refcount_entries_ == NULL)
- this->refcount_entries_ = new std::vector<Refcount_entry>;
- Refcount_entry re = refcounts->add(REFCOUNT_DECREMENT_COMPUTED,
- p->type());
- this->refcount_entries_->push_back(re);
- }
- }
- return this;
- }
-}
-
// Build the call expression.
tree
@@ -8542,49 +8208,11 @@
if (fntype->results() != NULL && fntype->results()->size() > 1)
ret = save_expr(ret);
- if (this->refcount_entries_ != NULL)
- ret = this->set_refcount_queue_entries(context, ret);
-
this->tree_ = ret;
return ret;
}
-// Set entries in the decrement queue as needed.
-
-tree
-Call_expression::set_refcount_queue_entries(Translate_context* context,
- tree ret)
-{
- Gogo* gogo = context->gogo();
- Refcounts* refcounts = context->function()->func_value()->refcounts();
- tree val = ret;
- Function_type* fntype = this->get_function_type();
- const Typed_identifier_list* results = fntype->results();
- gcc_assert(TREE_CODE(TREE_TYPE(val)) == RECORD_TYPE);
- std::vector<Refcount_entry>::const_iterator pre =
- this->refcount_entries_->begin();
- tree field = TYPE_FIELDS(TREE_TYPE(val));
- for (Typed_identifier_list::const_iterator pr = results->begin();
- pr != results->end();
- ++pr, field = TREE_CHAIN(field))
- {
- gcc_assert(field != NULL_TREE);
- if (pr->type()->has_refcounted_component())
- {
- gcc_assert(pre != this->refcount_entries_->end());
- Refcount_entry re = *pre;
- tree f = fold_build3(COMPONENT_REF, TREE_TYPE(field), val, field,
- NULL_TREE);
- pr->type()->set_refcount_queue_entry(gogo, refcounts, &re, f);
- ++pre;
- }
- }
- gcc_assert(pre == this->refcount_entries_->end());
- gcc_assert(field == NULL_TREE);
- return ret;
-}
-
// Make a call expression.
Call_expression*
@@ -8601,7 +8229,7 @@
public:
Call_result_expression(Call_expression* call, unsigned int index)
: Expression(EXPRESSION_CALL_RESULT, call->location()),
- call_(call), index_(index), is_being_copied_(false)
+ call_(call), index_(index)
{ }
protected:
@@ -8628,12 +8256,6 @@
do_must_eval_in_order() const
{ return true; }
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts*);
-
tree
do_get_tree(Translate_context*);
@@ -8642,8 +8264,6 @@
Expression* call_;
// Which result we want.
unsigned int index_;
- // Whether the result is being copied.
- bool is_being_copied_;
};
// Traverse a call result.
@@ -8718,28 +8338,6 @@
this->call_->determine_type_no_context();
}
-// The result will come back with a reference, so we don't need to do
-// anything to copy it.
-
-Expression*
-Call_result_expression::do_being_copied(Refcounts*, bool)
-{
- this->is_being_copied_ = true;
- return this;
-}
-
-// Decrement the reference count if necessary.
-
-Expression*
-Call_result_expression::do_note_decrements(Refcounts* refcounts)
-{
- if (this->is_being_copied_ || !this->type()->has_refcounted_component())
- return this;
- return Expression::make_refcount_adjust(refcounts,
- REFCOUNT_DECREMENT_COMPUTED,
- this, false);
-}
-
// Return the tree.
tree
@@ -8880,15 +8478,6 @@
do_address_taken(bool escapes)
{ this->array_->address_taken(escapes); }
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts*);
-
- Expression*
- do_being_set(Refcounts*);
-
tree
do_get_tree(Translate_context*);
@@ -9011,44 +8600,6 @@
mpz_clear(lval);
}
-// Copying an element of an array may require incrementing a reference
-// count. Copying a slice requires incrementing the reference count
-// of the underlying array.
-
-Expression*
-Array_index_expression::do_being_copied(Refcounts* refcounts, bool for_local)
-{
- if (this->end_ == NULL && !this->type()->has_refcounted_component())
- return this;
- return Expression::make_refcount_adjust(refcounts,
- REFCOUNT_INCREMENT_COPIED,
- this, for_local);
-}
-
-// Referring to an element of an array does not require changing any
-// reference counts. If the array is changed before the value is
-// used, the program is ill-defined. We do not introduce a reference
-// count for a slice, so there is nothing to decrement. FIXME: Is
-// that safe?
-
-Expression*
-Array_index_expression::do_note_decrements(Refcounts*)
-{
- return this;
-}
-
-// Assigning to an element of an array may require decrementing a
-// reference count of the old value.
-
-Expression*
-Array_index_expression::do_being_set(Refcounts* refcounts)
-{
- gcc_assert(this->end_ == NULL);
- if (!this->type()->has_refcounted_component())
- return this;
- return Expression::make_refcount_decrement_lvalue(refcounts, this);
-}
-
// Get a tree for an array index.
tree
@@ -9249,7 +8800,7 @@
String_index_expression(Expression* string, Expression* start,
Expression* end, source_location location)
: Expression(EXPRESSION_STRING_INDEX, location),
- string_(string), start_(start), end_(end), is_being_copied_(false)
+ string_(string), start_(start), end_(end)
{ }
protected:
@@ -9276,12 +8827,6 @@
this->location());
}
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts*);
-
tree
do_get_tree(Translate_context*);
@@ -9293,8 +8838,6 @@
// The end index of a slice. This may be NULL for a single index,
// or it may be a nil expression for the length of the string.
Expression* end_;
- // Whether the slice is being copied.
- bool is_being_copied_;
};
// String index traversal.
@@ -9379,28 +8922,6 @@
mpz_clear(ival);
}
-// Copying a string index or a string slice does not require any
-// special action.
-
-Expression*
-String_index_expression::do_being_copied(Refcounts*, bool)
-{
- this->is_being_copied_ = true;
- return this;
-}
-
-// A string slice introduces a new reference which must be decremented
-// if the value is discarded.
-
-Expression*
-String_index_expression::do_note_decrements(Refcounts* refcounts)
-{
- if (this->end_ == NULL || this->is_being_copied_)
- return this;
- return Expression::make_refcount_adjust(refcounts, REFCOUNT_DECREMENT_NEW,
- this, false);
-}
-
// Get a tree for a string index.
tree
@@ -9561,43 +9082,6 @@
}
}
-// If we are copying the map index to a variable, we need to increment
-// the reference count.
-
-Expression*
-Map_index_expression::do_being_copied(Refcounts* refcounts, bool for_local)
-{
- if (!this->type()->has_refcounted_component())
- return this;
- return Expression::make_refcount_adjust(refcounts,
- REFCOUNT_INCREMENT_COPIED,
- this, for_local);
-}
-
-// We don't do anything with the reference count of a map index if we
-// aren't copying it, so there is nothing to do here. FIXME: Is this
-// safe?
-
-Expression*
-Map_index_expression::do_note_decrements(Refcounts*)
-{
- return this;
-}
-
-// If we are changing the map index, we need to decrement the
-// reference count for the old value, and we may need to increment the
-// reference count for the new index.
-
-Expression*
-Map_index_expression::do_being_set(Refcounts* refcounts)
-{
- if (this->get_map_type()->key_type()->has_refcounted_component())
- this->index_ = this->index_->being_copied(refcounts, false);
- if (!this->type()->has_refcounted_component())
- return this;
- return Expression::make_refcount_decrement_lvalue(refcounts, this);
-}
-
// Get a tree for a map index.
tree
@@ -9726,41 +9210,6 @@
gcc_assert(struct_type->field(this->field_index_) != NULL);
}
-// If we are copying the field to a variable, we need to increment the
-// reference count.
-
-Expression*
-Field_reference_expression::do_being_copied(Refcounts* refcounts,
- bool for_local)
-{
- if (!this->type()->has_refcounted_component())
- return this;
- return Expression::make_refcount_adjust(refcounts,
- REFCOUNT_INCREMENT_COPIED,
- this, for_local);
-}
-
-// We do not need to bump the reference count; any change to the
-// structure before the value of the field is used would mean an
-// invalid program.
-
-Expression*
-Field_reference_expression::do_note_decrements(Refcounts*)
-{
- return this;
-}
-
-// If we are changing the field, we need to decrement the reference
-// count for the old value.
-
-Expression*
-Field_reference_expression::do_being_set(Refcounts* refcounts)
-{
- if (!this->type()->has_refcounted_component())
- return this;
- return Expression::make_refcount_decrement_lvalue(refcounts, this);
-}
-
// Get a tree for a field reference.
tree
@@ -10175,7 +9624,7 @@
public:
Allocation_expression(Type* type, source_location location)
: Expression(EXPRESSION_ALLOCATION, location),
- type_(type), is_being_copied_(false)
+ type_(type)
{ }
protected:
@@ -10198,20 +9647,12 @@
do_copy()
{ return new Allocation_expression(this->type_, this->location()); }
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts*);
-
tree
do_get_tree(Translate_context*);
private:
// The type we are allocating.
Type* type_;
- // Whether this value is being copied.
- bool is_being_copied_;
};
// Check the type of an allocation expression.
@@ -10223,28 +9664,6 @@
this->report_error(_("invalid new of function type"));
}
-// An allocation expression arrives with a reference count, so nothing
-// special is needed to copy it.
-
-Expression*
-Allocation_expression::do_being_copied(Refcounts*, bool)
-{
- this->is_being_copied_ = true;
- return this;
-}
-
-// An allocation expression arrives with a reference count, so if we
-// don't copy the value we must free it.
-
-Expression*
-Allocation_expression::do_note_decrements(Refcounts* refcounts)
-{
- if (this->is_being_copied_)
- return this;
- return Expression::make_refcount_adjust(refcounts, REFCOUNT_DECREMENT_NEW,
- this, false);
-}
-
// Return a tree for an allocation expression.
tree
@@ -10272,7 +9691,7 @@
public:
Make_expression(Type* type, Expression_list* args, source_location location)
: Expression(EXPRESSION_MAKE, location),
- type_(type), args_(args), is_being_copied_(false)
+ type_(type), args_(args)
{ }
protected:
@@ -10296,12 +9715,6 @@
this->location());
}
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts*);
-
tree
do_get_tree(Translate_context*);
@@ -10310,8 +9723,6 @@
Type* type_;
// The arguments to pass to the make routine.
Expression_list* args_;
- // Whether the expression is being copied.
- bool is_being_copied_;
};
// Traversal.
@@ -10355,28 +9766,6 @@
this->set_is_error();
}
-// An newly created object arrives with a reference count, so nothing
-// special is needed to copy it.
-
-Expression*
-Make_expression::do_being_copied(Refcounts*, bool)
-{
- this->is_being_copied_ = true;
- return this;
-}
-
-// A newly created object arrives with a reference count, so if we
-// don't copy the value we must free it.
-
-Expression*
-Make_expression::do_note_decrements(Refcounts* refcounts)
-{
- if (this->is_being_copied_)
- return this;
- return Expression::make_refcount_adjust(refcounts, REFCOUNT_DECREMENT_NEW,
- this, false);
-}
-
// Return a tree for a make expression.
tree
@@ -10435,12 +9824,6 @@
do_is_addressable() const
{ return true; }
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts*);
-
tree
do_get_tree(Translate_context*);
@@ -10572,49 +9955,6 @@
gcc_assert(pv == this->vals_->end());
}
-// If we are copying the constructed struct, then we need to increment
-// the reference count of any elements as needed.
-
-Expression*
-Struct_construction_expression::do_being_copied(Refcounts* refcounts,
- bool for_local)
-{
- if (this->vals_ == NULL
- || !this->type()->has_refcounted_component()
- || this->is_constant_struct())
- return this;
- Expression_list* newvals = new Expression_list;
- for (Expression_list::const_iterator pv = this->vals_->begin();
- pv != this->vals_->end();
- ++pv)
- {
- if (*pv == NULL)
- newvals->push_back(NULL);
- else if (!(*pv)->type()->has_refcounted_component())
- newvals->push_back(*pv);
- else
- {
- Expression* e = (*pv)->being_copied(refcounts, for_local);
- newvals->push_back(e);
- }
- }
- delete this->vals_;
- this->vals_ = newvals;
- return this;
-}
-
-// This is called if the constructed struct does not appear on the
-// right hand side of an assignment statement--in other words, the
-// value is built, used, and discarded. In this case we don't need to
-// do anything. If any of the values require a reference count
-// adjustment, that will be handled by the expression itself.
-
-Expression*
-Struct_construction_expression::do_note_decrements(Refcounts*)
-{
- return this;
-}
-
// Return a tree for constructing a struct.
tree
@@ -10746,12 +10086,6 @@
do_is_addressable() const
{ return true; }
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts* refcounts);
-
void
do_export(Export*) const;
@@ -10867,49 +10201,6 @@
}
}
-// If we are copying the constructed array, then we need to increment
-// the reference count of any elements as needed.
-
-Expression*
-Array_construction_expression::do_being_copied(Refcounts* refcounts,
- bool for_local)
-{
- if (this->vals_ == NULL
- || !this->type()->has_refcounted_component()
- || this->is_constant_array())
- return this;
- Expression_list* newvals = new Expression_list;
- for (Expression_list::const_iterator pv = this->vals_->begin();
- pv != this->vals_->end();
- ++pv)
- {
- if (*pv == NULL)
- newvals->push_back(NULL);
- else if (!(*pv)->type()->has_refcounted_component())
- newvals->push_back(*pv);
- else
- {
- Expression* e = (*pv)->being_copied(refcounts, for_local);
- newvals->push_back(e);
- }
- }
- delete this->vals_;
- this->vals_ = newvals;
- return this;
-}
-
-// This is called if the constructed array does not appear on the
-// right hand side of an assignment statement--in other words, the
-// value is built, used, and discarded. In this case we don't need to
-// do anything. If any of the values require a reference count
-// adjustment, that will be handled by the expression itself.
-
-Expression*
-Array_construction_expression::do_note_decrements(Refcounts*)
-{
- return this;
-}
-
// Get a constructor tree for the array values.
tree
@@ -11175,7 +10466,7 @@
Map_construction_expression(Type* type, Expression_list* vals,
source_location location)
: Expression(EXPRESSION_MAP_CONSTRUCTION, location),
- type_(type), vals_(vals), is_being_copied_(false)
+ type_(type), vals_(vals)
{ gcc_assert(vals == NULL || vals->size() % 2 == 0); }
protected:
@@ -11199,12 +10490,6 @@
this->location());
}
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts* refcounts);
-
tree
do_get_tree(Translate_context*);
@@ -11216,8 +10501,6 @@
Type* type_;
// The list of values.
Expression_list* vals_;
- // Whether the expression is being copied.
- bool is_being_copied_;
};
// Traversal.
@@ -11289,26 +10572,6 @@
}
}
-// Copying a map construction should not require any special action.
-
-Expression*
-Map_construction_expression::do_being_copied(Refcounts*, bool)
-{
- this->is_being_copied_ = true;
- return this;
-}
-
-// Constructing a map always introduces a reference count.
-
-Expression*
-Map_construction_expression::do_note_decrements(Refcounts* refcounts)
-{
- if (this->is_being_copied_)
- return this;
- return Expression::make_refcount_adjust(refcounts, REFCOUNT_DECREMENT_NEW,
- this, false);
-}
-
// Return a tree for constructing a map.
tree
@@ -11953,29 +11216,6 @@
this->report_error(_("type guard only valid for interface types"));
}
-// If we are copying the type guard to a variable, we don't need to do
-// anything; any reference count will already have been incremented.
-
-Expression*
-Type_guard_expression::do_being_copied(Refcounts*, bool)
-{
- this->is_being_copied_ = true;
- return this;
-}
-
-// If we are converting to a reference counted type, then the
-// conversion process will increment the reference count.
-
-Expression*
-Type_guard_expression::do_note_decrements(Refcounts* refcounts)
-{
- if (!this->type_->has_refcounted_component() || this->is_being_copied_)
- return this;
- return Expression::make_refcount_adjust(refcounts,
- REFCOUNT_DECREMENT_COMPUTED,
- this, false);
-}
-
// Return a tree for a type guard expression.
tree
@@ -12018,10 +11258,9 @@
class Heap_composite_expression : public Expression
{
public:
- Heap_composite_expression(Expression* expr, bool for_go_statement,
- source_location location)
+ Heap_composite_expression(Expression* expr, source_location location)
: Expression(EXPRESSION_HEAP_COMPOSITE, location),
- expr_(expr), for_go_statement_(for_go_statement), is_being_copied_(false)
+ expr_(expr)
{ }
protected:
@@ -12041,16 +11280,9 @@
do_copy()
{
return Expression::make_heap_composite(this->expr_->copy(),
- this->for_go_statement_,
this->location());
}
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts*);
-
tree
do_get_tree(Translate_context*);
@@ -12063,41 +11295,8 @@
private:
// The composite literal which is being put on the heap.
Expression* expr_;
- // True if this composite literal is being created for a go
- // statement. This is used to control reference count adjustments.
- bool for_go_statement_;
- // Whether this expression is being copied.
- bool is_being_copied_;
};
-// A heap composite is created with a new reference count, so nothing
-// special need be done to copy it. However, we do have to increment
-// the reference counts of the composite literal of which it is a
-// copy.
-
-Expression*
-Heap_composite_expression::do_being_copied(Refcounts* refcounts,
- bool for_local)
-{
- gcc_assert(!this->for_go_statement_);
- this->is_being_copied_ = true;
- this->expr_ = this->expr_->being_copied(refcounts, for_local);
- return this;
-}
-
-// Constructing a heap composite always introduces a reference count.
-// If we are creating this for a go statement, then the reference
-// count should be decremented in the thunk, not here.
-
-Expression*
-Heap_composite_expression::do_note_decrements(Refcounts* refcounts)
-{
- if (this->for_go_statement_ || this->is_being_copied_)
- return this;
- return Expression::make_refcount_adjust(refcounts, REFCOUNT_DECREMENT_NEW,
- this, false);
-}
-
// Return a tree which allocates a composite literal on the heap.
tree
@@ -12124,10 +11323,9 @@
// Allocate a composite literal on the heap.
Expression*
-Expression::make_heap_composite(Expression* expr, bool for_go_statement,
- source_location location)
-{
- return new Heap_composite_expression(expr, for_go_statement, location);
+Expression::make_heap_composite(Expression* expr, source_location location)
+{
+ return new Heap_composite_expression(expr, location);
}
// Class Receive_expression.
@@ -12166,36 +11364,6 @@
}
}
-// If we are copying the received value to a variable, we don't need
-// to do anything; any reference count will already have been
-// incremented.
-
-Expression*
-Receive_expression::do_being_copied(Refcounts*, bool)
-{
- this->is_being_copied_ = true;
- return this;
-}
-
-// The receive will come with a reference count which we need to
-// decrement afterward.
-
-Expression*
-Receive_expression::do_note_decrements(Refcounts* refcounts)
-{
- if (this->is_being_copied_)
- return this;
- Channel_type* channel_type = this->channel_->type()->channel_type();
- if (channel_type == NULL)
- return this;
- Type* element_type = channel_type->element_type();
- if (!element_type->has_refcounted_component())
- return this;
- return Expression::make_refcount_adjust(refcounts,
- REFCOUNT_DECREMENT_COMPUTED,
- this, false);
-}
-
// Get a tree for a receive expression.
tree
@@ -12288,24 +11456,6 @@
}
}
-// Called if the value is being copied. There is nothing to do here.
-
-Expression*
-Send_expression::do_being_copied(Refcounts*, bool)
-{
- return this;
-}
-
-// Reference count adjustments for a send expression. The expression
-// that we are sending is being copied.
-
-Expression*
-Send_expression::do_note_decrements(Refcounts* refcounts)
-{
- this->val_ = this->val_->being_copied(refcounts, false);
- return this;
-}
-
// Get a tree for a send expression.
tree
@@ -12334,189 +11484,6 @@
return new Send_expression(channel, val, location);
}
-// Class Refcount_adjust_expression.
-
-// The type of adjustment.
-
-int
-Refcount_adjust_expression::classification() const
-{
- return this->refcount_entry_->classification();
-}
-
-// Types should already have been determined and checked.
-
-void
-Refcount_adjust_expression::do_determine_type(const Type_context*)
-{
- gcc_unreachable();
-}
-
-void
-Refcount_adjust_expression::do_check_types(Gogo*)
-{
- gcc_unreachable();
-}
-
-// Return a tree for the reference count adjustment.
-
-tree
-Refcount_adjust_expression::do_get_tree(Translate_context* context)
-{
- // If we are incrementing a decrement, then skip both adjustments.
- if (this->expr_->classification() == EXPRESSION_REFCOUNT_ADJUST
- && this->classification() == REFCOUNT_INCREMENT_COPIED)
- {
- Refcount_adjust_expression* rae =
- static_cast<Refcount_adjust_expression*>(this->expr_);
- int rae_cl = rae->classification();
- // We should never see an increment of an old value; that makes
- // no sense.
- if (rae_cl == REFCOUNT_DECREMENT_NEW
- || rae_cl == REFCOUNT_DECREMENT_COMPUTED)
- return rae->expr()->get_tree(context);
- }
-
- tree expr_tree = this->expr_->get_tree(context);
- if (expr_tree == error_mark_node)
- return error_mark_node;
- if (DECL_P(expr_tree)
- || (TREE_CODE(expr_tree) == ADDR_EXPR
- && DECL_P(TREE_OPERAND(expr_tree, 0))))
- {
- // Because of the limited context, we don't need to save V or
- // &V.
- }
- else if (this->expr_->type()->array_type() != NULL
- && !this->expr_->type()->is_open_array_type())
- {
- // We are just going to take the address of a fixed array, don't
- // try to save it. Saving it fails because it requires an array
- // copy to the temporary variable.
- }
- else
- expr_tree = save_expr(expr_tree);
- Refcounts* refcounts = context->function()->func_value()->refcounts();
- Refcount_entry re = *this->refcount_entry_;
- tree set = this->expr_->type()->set_refcount_queue_entry(context->gogo(),
- refcounts,
- &re,
- expr_tree);
- return build2(COMPOUND_EXPR, TREE_TYPE(expr_tree), set, expr_tree);
-}
-
-// Make a reference count adjustment.
-
-Expression*
-Expression::make_refcount_adjust(Refcounts* refcounts, int classification,
- Expression* expr, bool for_local)
-{
- // Simplify adjusting the reference count of a reference count
- // adjustment.
- if (expr->classification() == EXPRESSION_REFCOUNT_ADJUST)
- {
- Refcount_adjust_expression* rae =
- static_cast<Refcount_adjust_expression*>(expr);
- int rae_cl = rae->classification();
-
- // If we are incrementing a decrement, then we can discard both
- // the increment and the decrement.
- if (classification == REFCOUNT_INCREMENT_COPIED)
- {
- // We should never see an increment of an old value; that
- // makes no sense.
- gcc_assert(rae_cl != REFCOUNT_DECREMENT_OLD);
- if (rae_cl == REFCOUNT_DECREMENT_NEW
- || rae_cl == REFCOUNT_DECREMENT_COMPUTED)
- {
- // FIXME: We don't reclaim the Refcount_entry.
- return rae->expr();
- }
- }
-
- // If we are decrementing an increment, then we can not in
- // general discard both adjustments. The count might be
- // incremented in order to pass the value to a function. If we
- // discard both adjustments, then the object may be freed during
- // the function call.
- }
-
- Refcount_entry entry = refcounts->add(classification, expr->type());
- return new Refcount_adjust_expression(new Refcount_entry(entry),
- expr, for_local);
-}
-
-// Class Refcount_decrement_lvalue_expression
-
-// Constructor.
-
-Refcount_decrement_lvalue_expression::Refcount_decrement_lvalue_expression(
- Refcount_entry* entry,
- Expression* expr)
- : Expression(EXPRESSION_REFCOUNT_DECREMENT_LVALUE, expr->location()),
- refcount_entry_(entry), expr_(expr)
-{
- gcc_assert(expr->is_lvalue());
-}
-
-
-// Traversal.
-
-int
-Refcount_decrement_lvalue_expression::do_traverse(Traverse* traverse)
-{
- return Expression::traverse(&this->expr_, traverse);
-}
-
-// Types should already have been determined and checked at this
-// point.
-
-void
-Refcount_decrement_lvalue_expression::do_determine_type(const Type_context*)
-{
- gcc_unreachable();
-}
-
-void
-Refcount_decrement_lvalue_expression::do_check_types(Gogo*)
-{
- gcc_unreachable();
-}
-
-// The normal tree expansion is simply the one for THIS->EXPR_. We
-// require that the user call the set function appropriately.
-
-tree
-Refcount_decrement_lvalue_expression::do_get_tree(Translate_context* context)
-{
- return this->expr_->get_tree(context);
-}
-
-// Set the expression to VAL.
-
-tree
-Refcount_decrement_lvalue_expression::set(Translate_context* context,
- tree lhs_tree, tree rhs_tree)
-{
- if (lhs_tree == error_mark_node || rhs_tree == error_mark_node)
- return error_mark_node;
- lhs_tree = stabilize_reference(lhs_tree);
-
- // FIXME: If we are changing a value which may be visible to
- // multiple goroutines--i.e., anything other than a local
- // variable--then we should use an atomic swap. Otherwise we can
- // get inconsistent reference counts.
-
- Refcounts* refcounts = context->function()->func_value()->refcounts();
- Refcount_entry re = *this->refcount_entry_;
- tree save = this->expr_->type()->set_refcount_queue_entry(context->gogo(),
- refcounts,
- &re,
- lhs_tree);
- tree set = fold_build2(MODIFY_EXPR, void_type_node, lhs_tree, rhs_tree);
- return fold_build2(COMPOUND_EXPR, void_type_node, save, set);
-}
-
// An expression which evaluates to a pointer to the type descriptor
// of a type.
@@ -12598,17 +11565,6 @@
return new Label_addr_expression(label, location);
}
-// Make a reference count decrement of an lvalue.
-
-Expression*
-Expression::make_refcount_decrement_lvalue(Refcounts* refcounts,
- Expression* expr)
-{
- Refcount_entry entry = refcounts->add(REFCOUNT_DECREMENT_OLD, expr->type());
- return new Refcount_decrement_lvalue_expression(new Refcount_entry(entry),
- expr);
-}
-
// Import an expression. This comes at the end in order to see the
// various class definitions.
diff -r 38d1b9933c3e go/expressions.h
--- a/go/expressions.h Fri Jul 23 09:49:42 2010 -0700
+++ b/go/expressions.h Fri Jul 23 13:26:04 2010 -0700
@@ -35,14 +35,10 @@
class Type_guard_expression;
class Receive_expression;
class Send_expression;
-class Refcount_adjust_expression;
-class Refcount_decrement_lvalue_expression;
class Named_object;
class Export;
class Import;
class Temporary_statement;
-class Refcounts;
-class Refcount_entry;
class Label;
// The base class for all expressions.
@@ -92,8 +88,6 @@
EXPRESSION_HEAP_COMPOSITE,
EXPRESSION_RECEIVE,
EXPRESSION_SEND,
- EXPRESSION_REFCOUNT_ADJUST,
- EXPRESSION_REFCOUNT_DECREMENT_LVALUE,
EXPRESSION_TYPE_DESCRIPTOR,
EXPRESSION_LABEL_ADDR
};
@@ -262,7 +256,7 @@
// Take a composite literal and allocate it on the heap.
static Expression*
- make_heap_composite(Expression*, bool for_go_statement, source_location);
+ make_heap_composite(Expression*, source_location);
// Make a receive expression. VAL is NULL for a unary receive.
static Receive_expression*
@@ -272,19 +266,6 @@
static Send_expression*
make_send(Expression* channel, Expression* val, source_location);
- // Make an expression which evaluates another expression and stores
- // the value into the reference queue. This expression then
- // evaluates to the same value. FOR_LOCAL is true if this is for a
- // local variable.
- static Expression*
- make_refcount_adjust(Refcounts*, int classification, Expression*,
- bool for_local);
-
- // Make an expression which decrements the reference count of the
- // old value of an lvalue.
- static Expression*
- make_refcount_decrement_lvalue(Refcounts*, Expression*);
-
// Make an expression which evaluates to the type descriptor of a
// type.
static Expression*
@@ -481,24 +462,6 @@
receive_expression()
{ return this->convert<Receive_expression, EXPRESSION_RECEIVE>(); }
- // If this is a reference count adjustment, return the
- // Refcount_adjust_expression. Otherwise, return NULL.
- Refcount_adjust_expression*
- refcount_adjust_expression()
- {
- return this->convert<Refcount_adjust_expression,
- EXPRESSION_REFCOUNT_ADJUST>();
- }
-
- // If this is a reference decrement expression, return it.
- // Otherwise, return NULL.
- Refcount_decrement_lvalue_expression*
- refcount_decrement_lvalue_expression()
- {
- return this->convert<Refcount_decrement_lvalue_expression,
- EXPRESSION_REFCOUNT_DECREMENT_LVALUE>();
- }
-
// Return true if this is a composite literal.
bool
is_composite_literal() const;
@@ -579,42 +542,6 @@
must_eval_in_order() const
{ return this->do_must_eval_in_order(); }
- // This is called when the value of an expression is being stored
- // somewhere. In some cases this requires that the reference count
- // be incremented. FOR_LOCAL is true if this is called when either
- // a local variable appears on the left hand of the assignment or
- // when this is in a return statement. This should return a new
- // Expression which does the appropriate reference count adjustment.
- // When no reference count needs to be increment, this should simply
- // return THIS. The note_decrements method will be called on this
- // expression later; in some cases all that being_copied has to do
- // is prevent note_decrements from doing anything.
- Expression*
- being_copied(Refcounts* refcounts, bool for_local)
- { return this->do_being_copied(refcounts, for_local); }
-
- // If this expression computes any values whose reference count must
- // be decremented when the statement is complete, store them in the
- // reference count decrement queue. This is not called for an
- // expression which is the complete left hand side of an assignment.
- // It will be called for subexpressions of LHS's, and for all RHS
- // expressions. This returns a new expression which should replace
- // the current expression. When no reference counts need to be
- // decremented, this should simply return THIS.
- Expression*
- note_decrements(Refcounts* refcounts)
- { return this->do_note_decrements(refcounts); }
-
- // This is called when the expression is being set. The expression
- // must be an lvalue. In some cases this requires that the
- // reference count of the old value of the expression be
- // decremented. This should return a new Expression which does the
- // appropriate adjustment. When no reference count needs to be
- // decremented, this should simply return THIS.
- Expression*
- being_set(Refcounts* refcounts)
- { return this->do_being_set(refcounts); }
-
// Return the tree for this expression.
tree
get_tree(Translate_context*);
@@ -736,21 +663,6 @@
do_must_eval_in_order() const
{ return false; }
- // Child class implements incrementing reference count.
- virtual Expression*
- do_being_copied(Refcounts*, bool)
- { return this; }
-
- // Child class implements noting reference count decrements.
- virtual Expression*
- do_note_decrements(Refcounts*)
- { return this; }
-
- // Child class implements whether the old value of an lvalue needs
- // to have its reference count decremented.
- virtual Expression*
- do_being_set(Refcounts*);
-
// Child class implements conversion to tree.
virtual tree
do_get_tree(Translate_context*) = 0;
@@ -969,12 +881,6 @@
void
do_address_taken(bool);
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_being_set(Refcounts*);
-
tree
do_get_tree(Translate_context*);
@@ -1017,12 +923,6 @@
void
do_address_taken(bool);
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_being_set(Refcounts*);
-
tree
do_get_tree(Translate_context*);
@@ -1090,7 +990,7 @@
Binary_expression(Operator op, Expression* left, Expression* right,
source_location location)
: Expression(EXPRESSION_BINARY, location),
- op_(op), left_(left), right_(right), is_being_copied_(false)
+ op_(op), left_(left), right_(right)
{ }
// Return the operator.
@@ -1192,12 +1092,6 @@
this->right_->copy(), this->location());
}
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts*);
-
tree
do_get_tree(Translate_context*);
@@ -1211,8 +1105,6 @@
Expression* left_;
// The right hand side operand.
Expression* right_;
- // Whether the expression is being copied.
- bool is_being_copied_;
};
// A call expression. The go statement needs to dig inside this.
@@ -1223,9 +1115,9 @@
Call_expression(Expression* fn, Expression_list* args,
source_location location)
: Expression(EXPRESSION_CALL, location),
- fn_(fn), args_(args), type_(NULL), tree_(NULL), refcount_entries_(NULL),
+ fn_(fn), args_(args), type_(NULL), tree_(NULL),
is_value_discarded_(false), varargs_are_lowered_(false),
- is_being_copied_(false), is_deferred_(false)
+ is_deferred_(false)
{ }
// The function to call.
@@ -1299,12 +1191,6 @@
bool
do_must_eval_in_order() const;
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts*);
-
virtual tree
do_get_tree(Translate_context*);
@@ -1337,9 +1223,6 @@
Interface_field_reference_expression*,
tree*);
- tree
- set_refcount_queue_entries(Translate_context*, tree ret);
-
// The function to call.
Expression* fn_;
// The arguments to pass. This may be NULL if there are no
@@ -1349,16 +1232,10 @@
Type* type_;
// The tree for the call, used for a call which returns a tuple.
tree tree_;
- // If needed a list of entries in the reference count queue. These
- // are set to values returned by a tuple call if some of the values
- // need to have their reference counts decremented.
- std::vector<Refcount_entry>* refcount_entries_;
// True if the value is being discarded.
bool is_value_discarded_;
// True if varargs have already been lowered.
bool varargs_are_lowered_;
- // True if the value is being copied.
- bool is_being_copied_;
// True if the call is an argument to a defer statement.
bool is_deferred_;
};
@@ -1415,12 +1292,6 @@
this->location());
}
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts*);
-
tree
do_get_tree(Translate_context*);
@@ -1607,15 +1478,6 @@
// A map index expression is an lvalue but it is not addressable.
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts*);
-
- Expression*
- do_being_set(Refcounts*);
-
tree
do_get_tree(Translate_context*);
@@ -1760,15 +1622,6 @@
do_is_addressable() const
{ return this->expr_->is_addressable(); }
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts*);
-
- Expression*
- do_being_set(Refcounts*);
-
tree
do_get_tree(Translate_context*);
@@ -1852,7 +1705,7 @@
public:
Type_guard_expression(Expression* expr, Type* type, source_location location)
: Expression(EXPRESSION_TYPE_GUARD, location),
- expr_(expr), type_(type), is_being_copied_(false)
+ expr_(expr), type_(type)
{ }
// Return the expression to convert.
@@ -1887,12 +1740,6 @@
this->location());
}
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts*);
-
tree
do_get_tree(Translate_context*);
@@ -1901,8 +1748,6 @@
Expression* expr_;
// The type to which to convert.
Type* type_;
- // Whether this expression is being copied.
- bool is_being_copied_;
};
// A receive expression.
@@ -1912,8 +1757,7 @@
public:
Receive_expression(Expression* channel, source_location location)
: Expression(EXPRESSION_RECEIVE, location),
- channel_(channel), is_value_discarded_(false), for_select_(false),
- is_being_copied_(false)
+ channel_(channel), is_value_discarded_(false), for_select_(false)
{ }
// Return the channel.
@@ -1955,12 +1799,6 @@
do_must_eval_in_order() const
{ return true; }
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts*);
-
tree
do_get_tree(Translate_context*);
@@ -1971,8 +1809,6 @@
bool is_value_discarded_;
// Whether this is for a select statement.
bool for_select_;
- // Whether the value is being copied.
- bool is_being_copied_;
};
// A send expression.
@@ -2020,12 +1856,6 @@
do_must_eval_in_order() const
{ return true; }
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts*);
-
tree
do_get_tree(Translate_context*);
@@ -2040,115 +1870,4 @@
bool for_select_;
};
-// Adjust the reference count of a value.
-
-class Refcount_adjust_expression : public Expression
-{
- public:
- Refcount_adjust_expression(Refcount_entry* entry, Expression* expr,
- bool for_local)
- : Expression(EXPRESSION_REFCOUNT_ADJUST, expr->location()),
- refcount_entry_(entry), expr_(expr), for_local_(for_local)
- { }
-
- // The type of adjustment.
- int
- classification() const;
-
- // The underlying expression.
- Expression*
- expr()
- { return this->expr_; }
-
- protected:
- int
- do_traverse(Traverse* traverse)
- { return Expression::traverse(&this->expr_, traverse); }
-
- Type*
- do_type()
- { return this->expr_->type(); }
-
- void
- do_determine_type(const Type_context*);
-
- void
- do_check_types(Gogo*);
-
- Expression*
- do_copy()
- {
- return new Refcount_adjust_expression(this->refcount_entry_,
- this->expr_,
- this->for_local_);
- }
-
- tree
- do_get_tree(Translate_context*);
-
- private:
- // The reference count entry.
- Refcount_entry* refcount_entry_;
- // The expression whose reference count we are incrementing.
- Expression* expr_;
- // Whether this is to be stored in a local variable, for debugging
- // purposes.
- bool for_local_;
-};
-
-// Decrement the reference count of the old value of an lvalue in an
-// assignment.
-
-class Refcount_decrement_lvalue_expression : public Expression
-{
- public:
- Refcount_decrement_lvalue_expression(Refcount_entry* entry,
- Expression* expr);
-
- // The underlying expression.
- Expression*
- expr()
- { return this->expr_; }
-
- // Set THIS->EXPR_ (an lvalue) to RHS_TREE. LHS_TREE is THIS
- // converted to tree form. This should be called instead of
- // get_tree.
- tree
- set(Translate_context*, tree lhs_tree, tree rhs_tree);
-
- protected:
- int
- do_traverse(Traverse*);
-
- Type*
- do_type()
- { return this->expr_->type(); }
-
- void
- do_determine_type(const Type_context*);
-
- void
- do_check_types(Gogo*);
-
- Expression*
- do_copy()
- {
- return new Refcount_decrement_lvalue_expression(this->refcount_entry_,
- this->expr_);
- }
-
- bool
- do_is_lvalue() const
- { return true; }
-
- tree
- do_get_tree(Translate_context*);
-
- private:
- // The reference count entry.
- Refcount_entry* refcount_entry_;
- // The expression which is being set.
- Expression* expr_;
-};
-
#endif // !defined(GO_EXPRESSIONS_H)
diff -r 38d1b9933c3e go/go.cc
--- a/go/go.cc Fri Jul 23 09:49:42 2010 -0700
+++ b/go/go.cc Fri Jul 23 13:26:04 2010 -0700
@@ -135,12 +135,6 @@
// Convert complicated go and defer statements into simpler ones.
::gogo->simplify_thunk_statements();
-
- // Check which variables are only set to argument values.
- ::gogo->find_only_arg_vars();
-
- // Add reference counts for garbage collection.
- ::gogo->add_refcounts();
}
// Write out globals.
diff -r 38d1b9933c3e go/gogo-tree.cc
--- a/go/gogo-tree.cc Fri Jul 23 09:49:42 2010 -0700
+++ b/go/gogo-tree.cc Fri Jul 23 13:26:04 2010 -0700
@@ -28,7 +28,6 @@
#include "types.h"
#include "expressions.h"
#include "statements.h"
-#include "refcount.h"
#include "gogo.h"
// Whether we have seen any errors.
@@ -1424,7 +1423,6 @@
tree init = NULL_TREE;
tree except = NULL_TREE;
tree fini = NULL_TREE;
- source_location end_loc = this->block_->end_location();
// Initialize variables if necessary.
for (tree v = declare_vars; v != NULL_TREE; v = TREE_CHAIN(v))
@@ -1434,21 +1432,6 @@
append_to_statement_list(dv, &init);
}
- // If there is a reference count queue, initialize it at the
- // start of the function.
- bool have_refcounts = (this->refcounts_ != NULL
- && !this->refcounts_->empty());
- if (have_refcounts)
- {
- tree iq = this->refcounts_->init_queue(gogo, this->location_);
- append_to_statement_list(iq, &init);
- }
-
- // Flush the reference count queue when we leave the function.
- tree flush = NULL_TREE;
- if (have_refcounts)
- flush = this->refcounts_->flush_queue(gogo, true, end_loc);
-
// If we have a defer stack, initialize it at the start of a
// function.
if (this->defer_stack_ != NULL_TREE)
@@ -1459,15 +1442,7 @@
append_to_statement_list(defer_init, &init);
// Clean up the defer stack when we leave the function.
- this->build_defer_wrapper(gogo, named_function, flush, &except,
- &fini);
- flush = NULL_TREE;
- }
-
- if (flush != NULL_TREE)
- {
- gcc_assert(fini == NULL_TREE);
- fini = flush;
+ this->build_defer_wrapper(gogo, named_function, &except, &fini);
}
if (code != NULL_TREE && code != error_mark_node)
@@ -1495,11 +1470,11 @@
// Build the wrappers around function code needed if the function has
// any defer statements. This sets *EXCEPT to an exception handler
-// and *FINI to a finally handler. FLUSH is run in *FINI if not NULL.
+// and *FINI to a finally handler.
void
Function::build_defer_wrapper(Gogo* gogo, Named_object* named_function,
- tree flush, tree *except, tree *fini)
+ tree *except, tree *fini)
{
source_location end_loc = this->block_->end_location();
@@ -1571,9 +1546,6 @@
append_to_statement_list(try_catch, &stmt_list);
- if (flush != NULL_TREE)
- append_to_statement_list(flush, &stmt_list);
-
if (this->type_->results() != NULL
&& !this->type_->results()->empty()
&& !this->type_->results()->front().name().empty())
@@ -1760,31 +1732,6 @@
append_to_statement_list(statement, &statements);
}
- if (!this->final_statements_.empty())
- {
- tree final_statements = NULL_TREE;
- source_location loc = UNKNOWN_LOCATION;
- for (std::vector<Statement*>::const_iterator p =
- this->final_statements_.begin();
- p != this->final_statements_.end();
- ++p)
- {
- tree statement = (*p)->get_tree(&subcontext);
- if (statement != error_mark_node)
- {
- append_to_statement_list(statement, &final_statements);
- if (loc == UNKNOWN_LOCATION)
- loc = (*p)->location();
- }
- }
- if (final_statements != NULL_TREE)
- {
- statements = build2(TRY_FINALLY_EXPR, void_type_node,
- statements, final_statements);
- SET_EXPR_LOCATION(statements, loc);
- }
- }
-
TREE_USED(block) = 1;
tree bind = build3(BIND_EXPR, void_type_node, BLOCK_VARS(block), statements,
@@ -2961,7 +2908,7 @@
// which the length of an array calls the len function on another
// array with the same type descriptor, and that other array is
// initialized with values which require reference count
- // adjustments.
+ // adjustments. This may no longer be required.
go_preserve_from_gc(decl);
*pdecl = decl;
if (phash != NULL)
diff -r 38d1b9933c3e go/gogo.cc
--- a/go/gogo.cc Fri Jul 23 09:49:42 2010 -0700
+++ b/go/gogo.cc Fri Jul 23 13:26:04 2010 -0700
@@ -17,7 +17,6 @@
#include "dataflow.h"
#include "import.h"
#include "export.h"
-#include "refcount.h"
#include "gogo.h"
// Class Gogo.
@@ -2312,111 +2311,6 @@
return TRAVERSE_CONTINUE;
}
-// A dump for find_only_arg_vars.
-
-static Go_dump find_only_arg_vars_dump("argvars");
-
-// A traversal class to find all the local variables.
-
-class Traverse_find_vars : public Traverse
-{
- public:
- Traverse_find_vars(std::list<Named_object*>* vars)
- : Traverse(traverse_variables),
- vars_(vars)
- { }
-
- protected:
- int
- variable(Named_object* var)
- {
- if (var->is_variable() && !var->var_value()->is_global())
- this->vars_->push_back(var);
- return TRAVERSE_CONTINUE;
- }
-
- private:
- // We add variables to this list.
- std::list<Named_object*>* vars_;
-};
-
-// Find variables which are only set to argument values.
-
-void
-Gogo::find_only_arg_vars()
-{
- std::list<Named_object*> vars;
- Traverse_find_vars tfv(&vars);
- this->traverse(&tfv);
-
- Dataflow dataflow;
- dataflow.initialize(this);
-
- // We start with all the variables. As we find variables which are
- // set to values which are not arguments, we remove them from the
- // list. Note that this is flow-insensitive; we could in some cases
- // do slightly better by being flow-sensitive.
-
- bool changed = true;
- while (changed)
- {
- changed = false;
- std::list<Named_object*>::iterator pv = vars.begin();
- while (pv != vars.end())
- {
- const Dataflow::Defs* defs = dataflow.find_defs(*pv);
- if (defs == NULL)
- {
- // The variable is never set.
- gcc_assert((*pv)->var_value()->is_parameter());
- ++pv;
- }
- else
- {
- Dataflow::Defs::const_iterator pd;
- for (pd = defs->begin(); pd != defs->end(); ++pd)
- {
- if (pd->val == NULL)
- {
- if (!pd->is_init)
- break;
- }
- else if (pd->val->var_expression() == NULL)
- break;
- else
- {
- Var_expression* ve = pd->val->var_expression();
- Named_object* source = ve->named_object();
- if (std::find(vars.begin(), vars.end(), source)
- == vars.end())
- break;
- }
- }
- if (pd == defs->end())
- ++pv;
- else
- {
- // This variable is set to something which is not an
- // argument value.
- pv = vars.erase(pv);
- changed = true;
- }
- }
- }
- }
-
- for (std::list<Named_object*>::const_iterator pv = vars.begin();
- pv != vars.end();
- ++pv)
- {
- (*pv)->var_value()->set_holds_only_args();
-
- // FIXME: This should go to a file.
- if (find_only_arg_vars_dump.is_enabled())
- inform((*pv)->location(), "%qs: only args var", (*pv)->name().c_str());
- }
-}
-
// Traversal class used to check for return statements.
class Check_return_statements_traverse : public Traverse
@@ -2519,9 +2413,9 @@
Function::Function(Function_type* type, Function* enclosing, Block* block,
source_location location)
: type_(type), enclosing_(enclosing), named_results_(NULL),
- closure_var_(NULL), refcounts_(NULL), block_(block), location_(location),
- fndecl_(NULL), defer_stack_(NULL), calls_recover_(false),
- is_recover_thunk_(false), has_recover_thunk_(false)
+ closure_var_(NULL), block_(block), location_(location), fndecl_(NULL),
+ defer_stack_(NULL), calls_recover_(false), is_recover_thunk_(false),
+ has_recover_thunk_(false)
{
}
@@ -2601,16 +2495,6 @@
}
}
-// Allocate reference count information for the function.
-
-Refcounts*
-Function::refcounts()
-{
- if (this->refcounts_ == NULL)
- this->refcounts_ = new Refcounts;
- return this->refcounts_;
-}
-
// Return whether this function is a method.
bool
@@ -2687,7 +2571,6 @@
gcc_assert(this->enclosing_ == x->enclosing_);
gcc_assert(this->named_results_ == x->named_results_);
std::swap(this->closure_var_, x->closure_var_);
- gcc_assert(this->refcounts_ == NULL && x->refcounts_ == NULL);
std::swap(this->block_, x->block_);
gcc_assert(this->location_ == x->location_);
gcc_assert(this->fndecl_ == NULL && x->fndecl_ == NULL);
@@ -2908,7 +2791,6 @@
bindings_(new Bindings(enclosing == NULL
? NULL
: enclosing->bindings())),
- final_statements_(),
start_location_(location),
end_location_(UNKNOWN_LOCATION)
{
@@ -2931,14 +2813,6 @@
this->statements_.insert(this->statements_.begin(), statement);
}
-// Add a statement which runs when the block is complete.
-
-void
-Block::add_final_statement(Statement* statement)
-{
- this->final_statements_.push_back(statement);
-}
-
// Replace a statement in a block.
void
@@ -3089,9 +2963,6 @@
return TRAVERSE_EXIT;
}
- // We don't traverse the final statements, which are only used for
- // reference counting purposes.
-
return TRAVERSE_CONTINUE;
}
@@ -3135,7 +3006,7 @@
: type_(type), init_(init), preinit_(NULL), location_(location),
is_global_(is_global), is_parameter_(is_parameter),
is_receiver_(is_receiver), is_varargs_parameter_(false),
- is_address_taken_(false), holds_only_args_(false), init_is_lowered_(false),
+ is_address_taken_(false), init_is_lowered_(false),
type_from_init_tuple_(false), type_from_range_index_(false),
type_from_range_value_(false), type_from_chan_element_(false),
is_type_switch_var_(false)
diff -r 38d1b9933c3e go/gogo.h
--- a/go/gogo.h Fri Jul 23 09:49:42 2010 -0700
+++ b/go/gogo.h Fri Jul 23 13:26:04 2010 -0700
@@ -43,7 +43,6 @@
class Translate_context;
class Export;
class Import;
-class Refcounts;
// This file declares the basic classes used to hold the internal
// representation of Go which is built by the parser.
@@ -363,10 +362,6 @@
void
check_types_in_block(Block*);
- // Find variables which are only set to argument values.
- void
- find_only_arg_vars();
-
// Check for return statements.
void
check_return_statements();
@@ -402,10 +397,6 @@
void
simplify_thunk_statements();
- // Add reference counts for garbage collection.
- void
- add_refcounts();
-
// Write out the global values.
void
write_globals();
@@ -831,10 +822,6 @@
void
add_statement_at_front(Statement*);
- // Add a statement which runs when the block is done.
- void
- add_final_statement(Statement*);
-
// Replace a statement in a block.
void
replace_statement(size_t index, Statement*);
@@ -893,8 +880,6 @@
std::vector<Statement*> statements_;
// Binding contour.
Bindings* bindings_;
- // A list of statements which must be run when exiting the block.
- std::vector<Statement*> final_statements_;
// Location of start of block.
source_location start_location_;
// Location of end of block.
@@ -968,10 +953,6 @@
void
set_closure_type();
- // Get the reference count adjustments for this function.
- Refcounts*
- refcounts();
-
// Get the block of statements associated with the function.
Block*
block() const
@@ -1090,7 +1071,7 @@
copy_parm_to_heap(Gogo*, Named_object*, tree);
void
- build_defer_wrapper(Gogo*, Named_object*, tree, tree*, tree*);
+ build_defer_wrapper(Gogo*, Named_object*, tree*, tree*);
typedef std::vector<Named_object*> Named_results;
@@ -1111,9 +1092,6 @@
// The closure variable, passed as a parameter using the static
// chain parameter. Normally NULL.
Named_object* closure_var_;
- // The reference count adjustments which must be made in this
- // function.
- Refcounts* refcounts_;
// The outer block of statements in the function.
Block* block_;
// The source location of the start of the function.
@@ -1255,11 +1233,6 @@
is_address_taken() const
{ return this->is_address_taken_; }
- // Whether this variable only holds argument values.
- bool
- holds_only_args() const
- { return this->holds_only_args_; }
-
// Whether this variable should live in the heap.
bool
is_in_heap() const
@@ -1283,8 +1256,7 @@
clear_init()
{ this->init_ = NULL; }
- // Set the initial value; used for reference counts and converting
- // shortcuts.
+ // Set the initial value; used for converting shortcuts.
void
set_init(Expression* init)
{ this->init_ = init; }
@@ -1363,11 +1335,6 @@
set_address_taken()
{ this->is_address_taken_ = true; }
- // Note that this variable only holds argument values.
- void
- set_holds_only_args()
- { this->holds_only_args_ = true; }
-
// Get the initial value of the variable as a tree. This may only
// be called if has_pre_init() returns false.
tree
@@ -1420,10 +1387,6 @@
bool is_varargs_parameter_ : 1;
// Whether something takes the address of this variable.
bool is_address_taken_ : 1;
- // True if this variable is only set to argument values (e.g., it is
- // a parameter which is not changed, or a local variable set only to
- // parameters).
- bool holds_only_args_ : 1;
// True if we have lowered the initialization expression.
bool init_is_lowered_ : 1;
// True if init is a tuple used to set the type.
diff -r 38d1b9933c3e go/parse.cc
--- a/go/parse.cc Fri Jul 23 09:49:42 2010 -0700
+++ b/go/parse.cc Fri Jul 23 13:26:04 2010 -0700
@@ -2446,7 +2446,7 @@
Struct_type* st = closure_var->var_value()->type()->deref()->struct_type();
Expression* cv = Expression::make_struct_composite_literal(st, initializer,
location);
- return Expression::make_heap_composite(cv, false, location);
+ return Expression::make_heap_composite(cv, location);
}
// PrimaryExpr = Operand { Selector | Index | Slice | TypeGuard | Call } .
@@ -2866,7 +2866,7 @@
expr = Expression::make_type(Type::make_pointer_type(expr->type()),
location);
else if (op == OPERATOR_AND && expr->is_composite_literal())
- expr = Expression::make_heap_composite(expr, false, location);
+ expr = Expression::make_heap_composite(expr, location);
else if (op != OPERATOR_CHANOP)
expr = Expression::make_unary(op, expr, location);
else
diff -r 38d1b9933c3e go/refcount.cc
--- a/go/refcount.cc Fri Jul 23 09:49:42 2010 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,942 +0,0 @@
-// refcount.cc -- Go frontend reference counts.
-
-// 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.
-
-#include <algorithm>
-
-#include "go-system.h"
-
-#include <gmp.h>
-
-extern "C"
-{
-#include "tree.h"
-#include "gimple.h"
-#include "tree-iterator.h"
-#include "rtl.h"
-}
-
-#include "go-c.h"
-#include "go-dump.h"
-#include "gogo.h"
-#include "types.h"
-#include "expressions.h"
-#include "statements.h"
-#include "refcount.h"
-
-// Class Refcounts.
-
-// Add a new reference count entry.
-
-Refcount_entry
-Refcounts::add(int classification, Type* type)
-{
- gcc_assert(!this->is_complete_);
- Entries* pentries = &this->entries_[classification];
- int index = pentries->size();
- Refcount_entry r(classification, index);
- type->add_refcount_queue_entries(this, &r);
- return Refcount_entry(classification, index);
-}
-
-// Add a new entry for a type which only requires a single entry.
-
-void
-Refcounts::add_one(Type* type, Refcount_entry *entry)
-{
- gcc_assert(!this->is_complete_);
- Entries* pentries = &this->entries_[entry->classification()];
- gcc_assert(pentries->size() == entry->index());
- pentries->push_back(type);
- entry->increment();
-}
-
-// The type of a reference count entry.
-
-Type*
-Refcounts::get_type(Refcount_entry entry)
-{
- int cl = entry.classification();
- gcc_assert(cl >= REFCOUNT_DECREMENT_NEW && cl < REFCOUNT_MAX);
- Entries* entries = &this->entries_[cl];
- gcc_assert(entry.index() < entries->size());
- return (*entries)[entry.index()];
-}
-
-// Return whether there are no reference count adjustments.
-
-bool
-Refcounts::empty() const
-{
- for (int i = 0; i < REFCOUNT_MAX; ++i)
- if (!this->entries_[i].empty())
- return false;
- return true;
-}
-
-// Whether we can handle this reference count queue in a simple way,
-// without building a full queue structure. We want to use the queue
-// structure if there is a decrement of a newly allocated value,
-// because an increment in a called function will remove the
-// decrement. Otherwise, we use a simple approach if there is only
-// one entry in the queue.
-
-bool
-Refcounts::is_simple() const
-{
- gcc_assert(this->is_complete_);
- if (!this->entries_[REFCOUNT_DECREMENT_NEW].empty())
- return false;
- size_t count = 0;
- for (int i = 0; i < REFCOUNT_MAX; ++i)
- count += this->entries_[i].size();
- return count <= 1;
-}
-
-// Get the descriptor for a simple queue. Return true if this is an
-// increment.
-
-bool
-Refcounts::simple_descriptor(Gogo* gogo, tree* pdescriptor) const
-{
- for (int i = 0; i < REFCOUNT_MAX; ++i)
- {
- if (!this->entries_[i].empty())
- {
- gcc_assert(this->entries_[i].size() == 1);
- Type* type = this->entries_[i][0];
- *pdescriptor = type->type_descriptor(gogo);
- return i == REFCOUNT_INCREMENT_COPIED;
- }
- }
- gcc_unreachable();
-}
-
-// The type of an entry in the reference count array. This is the
-// structure declared in libgo/runtime/go-refcount.h.
-
-tree
-Refcounts::entry_type(Gogo* gogo)
-{
- static tree struct_type;
- if (struct_type == NULL_TREE)
- {
- struct_type = make_node(RECORD_TYPE);
-
- tree dtype = gogo->type_descriptor_type_tree();
- dtype = build_qualified_type(dtype, TYPE_QUAL_CONST);
- tree fields = build_decl(BUILTINS_LOCATION, FIELD_DECL,
- get_identifier("__descriptor"),
- build_pointer_type(dtype));
-
- tree field = build_decl(BUILTINS_LOCATION, FIELD_DECL,
- get_identifier("__value"),
- ptr_type_node);
- TREE_CHAIN(field) = fields;
- fields = field;
-
- finish_builtin_struct(struct_type, "__go_refcount_entry", fields,
- NULL_TREE);
-
- go_preserve_from_gc(struct_type);
- }
-
- return struct_type;
-}
-
-// The type of the reference count array for this structure.. This is
-// the structure declared in libgo/runtime/go-refcount.h.
-
-tree
-Refcounts::struct_type(Gogo* gogo)
-{
- gcc_assert(this->is_complete_);
-
- tree struct_type = make_node(RECORD_TYPE);
-
- tree fields = build_decl(BUILTINS_LOCATION, FIELD_DECL,
- get_identifier("__caller"),
- build_pointer_type(struct_type));
-
- tree field = build_decl(BUILTINS_LOCATION, FIELD_DECL,
- get_identifier("__callers_were_scanned"),
- boolean_type_node);
- TREE_CHAIN(field) = fields;
- fields = field;
-
- field = build_decl(BUILTINS_LOCATION, FIELD_DECL,
- get_identifier("__did_not_scan_decrements"),
- boolean_type_node);
- TREE_CHAIN(field) = fields;
- fields = field;
-
- field = build_decl(BUILTINS_LOCATION, FIELD_DECL,
- get_identifier("__decrement_new_count"),
- short_unsigned_type_node);
- TREE_CHAIN(field) = fields;
- fields = field;
-
- field = build_decl(BUILTINS_LOCATION, FIELD_DECL,
- get_identifier("__decrement_computed_count"),
- short_unsigned_type_node);
- TREE_CHAIN(field) = fields;
- fields = field;
-
- field = build_decl(BUILTINS_LOCATION, FIELD_DECL,
- get_identifier("__decrement_old_count"),
- short_unsigned_type_node);
- TREE_CHAIN(field) = fields;
- fields = field;
-
- field = build_decl(BUILTINS_LOCATION, FIELD_DECL,
- get_identifier("__increment_copy_count"),
- short_unsigned_type_node);
- TREE_CHAIN(field) = fields;
- fields = field;
-
- size_t count = 0;
- for (int i = 0; i < REFCOUNT_MAX; ++i)
- count += this->entries_[i].size();
- gcc_assert(count > 0);
-
- tree entry_type = Refcounts::entry_type(gogo);
- tree index_type = build_index_type(size_int(count - 1));
- tree array_type = build_array_type(entry_type, index_type);
- field = build_decl(BUILTINS_LOCATION, FIELD_DECL,
- get_identifier("__entries"), array_type);
- TREE_CHAIN(field) = fields;
- fields = field;
-
- finish_builtin_struct(struct_type, "__go_refcount", fields, NULL_TREE);
-
- return struct_type;
-}
-
-// Get the initializer for the reference count tree.
-
-tree
-Refcounts::get_initializer(Gogo* gogo)
-{
- gcc_assert(this->is_complete_);
- gcc_assert(!this->is_simple());
-
- size_t count = 0;
- for (int i = 0; i < REFCOUNT_MAX; ++i)
- count += this->entries_[i].size();
- gcc_assert(count > 0);
-
- VEC(constructor_elt, gc)* init = VEC_alloc(constructor_elt, gc, 8);
-
- tree decl = this->get_tree(gogo);
- tree type = TREE_TYPE(decl);
-
- tree field = TYPE_FIELDS(type);
-
- constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)),
- "__caller") == 0);
- elt->index = field;
- elt->value = this->queue_head_decl(gogo);
-
- field = TREE_CHAIN(field);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)),
- "__callers_were_scanned") == 0);
- elt->index = field;
- elt->value = boolean_false_node;
-
- field = TREE_CHAIN(field);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)),
- "__did_not_scan_decrements") == 0);
- elt->index = field;
- elt->value = boolean_false_node;
-
- field = TREE_CHAIN(field);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)),
- "__decrement_new_count") == 0);
- elt->index = field;
- size_t c = this->entries_[REFCOUNT_DECREMENT_NEW].size();
- gcc_assert(c <= 0xffff);
- elt->value = build_int_cst_type(TREE_TYPE(field), c);
-
- field = TREE_CHAIN(field);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)),
- "__decrement_computed_count") == 0);
- elt->index = field;
- c = this->entries_[REFCOUNT_DECREMENT_COMPUTED].size();
- gcc_assert(c <= 0xffff);
- elt->value = build_int_cst_type(TREE_TYPE(field), c);
-
- field = TREE_CHAIN(field);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)),
- "__decrement_old_count") == 0);
- elt->index = field;
- c = this->entries_[REFCOUNT_DECREMENT_OLD].size();
- gcc_assert(c <= 0xffff);
- elt->value = build_int_cst_type(TREE_TYPE(field), c);
-
- field = TREE_CHAIN(field);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)),
- "__increment_copy_count") == 0);
- elt->index = field;
- c = this->entries_[REFCOUNT_INCREMENT_COPIED].size();
- gcc_assert(c <= 0xffff);
- elt->value = build_int_cst_type(TREE_TYPE(field), c);
-
- field = TREE_CHAIN(field);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)),
- "__entries") == 0);
- elt->index = field;
-
- tree desc_field = TYPE_FIELDS(TREE_TYPE(TREE_TYPE(field)));
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(desc_field)),
- "__descriptor") == 0);
- tree value_field = TREE_CHAIN(desc_field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(value_field)),
- "__value") == 0);
-
- VEC(constructor_elt, gc)* entries_init = VEC_alloc(constructor_elt,
- gc, count);
- size_t index = 0;
- for (int i = 0; i < REFCOUNT_MAX; ++i)
- {
- Entries* entries = &this->entries_[i];
- for (Entries::const_iterator p = entries->begin();
- p != entries->end();
- ++p, ++index)
- {
- VEC(constructor_elt, gc)* entry_init = VEC_alloc(constructor_elt,
- gc, 2);
- constructor_elt* eelt = VEC_quick_push(constructor_elt,
- entry_init, NULL);
- eelt->index = desc_field;
- Type* type = *p;
- eelt->value = type->type_descriptor(gogo);
-
- eelt = VEC_quick_push(constructor_elt, entry_init, NULL);
- eelt->index = value_field;
- eelt->value = fold_convert(TREE_TYPE(value_field),
- null_pointer_node);
-
- eelt = VEC_quick_push(constructor_elt, entries_init, NULL);
- eelt->index = size_int(index);
- eelt->value = build_constructor(TREE_TYPE(TREE_TYPE(field)),
- entry_init);
- }
- }
-
- elt->value = build_constructor(TREE_TYPE(field), entries_init);
-
- return build_constructor(TREE_TYPE(decl), init);
-}
-
-// Get the local variable which holds the reference count tree.
-
-tree
-Refcounts::get_tree(Gogo* gogo)
-{
- gcc_assert(!this->is_simple());
- if (this->decl_ == NULL_TREE)
- {
- tree type = this->struct_type(gogo);
- this->decl_ = create_tmp_var(type, NULL);
- }
- return this->decl_;
-}
-
-// Get the local variable which holds the only entry we need if the
-// queue is simple.
-
-tree
-Refcounts::get_simple_tree(Gogo*)
-{
- gcc_assert(this->is_simple());
- if (this->simple_decl_ == NULL_TREE)
- this->simple_decl_ = create_tmp_var(ptr_type_node, NULL);
- return this->simple_decl_;
-}
-
-// Return a tree which sets the queue entry for ENTRY to VAL.
-
-tree
-Refcounts::set_entry_tree(Gogo* gogo, Refcount_entry entry, tree val)
-{
- gcc_assert(this->is_complete_);
-
- gcc_assert(POINTER_TYPE_P(TREE_TYPE(val)));
-
- if (this->is_simple())
- return build2(MODIFY_EXPR, void_type_node, this->get_simple_tree(gogo),
- fold_convert(ptr_type_node, val));
-
- int cl = entry.classification();
- gcc_assert(cl >= REFCOUNT_DECREMENT_NEW && cl < REFCOUNT_MAX);
- Entries* entries = &this->entries_[cl];
- tree decl = this->get_tree(gogo);
- tree field = TYPE_FIELDS(TREE_TYPE(decl));
- field = TREE_CHAIN(TREE_CHAIN(field));
- field = TREE_CHAIN(TREE_CHAIN(field));
- field = TREE_CHAIN(TREE_CHAIN(field));
- field = TREE_CHAIN(field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__entries") == 0);
-
- // Set R to the __entries array.
- tree r = build3(COMPONENT_REF, TREE_TYPE(field), decl, field, NULL_TREE);
-
- unsigned int index = entry.index();
- gcc_assert(index < entries->size());
- for (int i = 0; i < cl; ++i)
- index += this->entries_[i].size();
-
- // Set R to the specific entry in the __entries array.
- r = build4(ARRAY_REF, TREE_TYPE(TREE_TYPE(r)), r, size_int(index),
- NULL_TREE, NULL_TREE);
-
- field = TREE_CHAIN(TYPE_FIELDS(TREE_TYPE(r)));
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__value") == 0);
-
- // Set R to the __value field in the specific entry in the __entries
- // array.
- r = build3(COMPONENT_REF, TREE_TYPE(field), r, field, NULL_TREE);
-
- // An assignment to the field.
- tree set = build2(MODIFY_EXPR, void_type_node, r,
- fold_convert(ptr_type_node, val));
-
- // Set the changed flag to true.
- tree set_flag = build2(MODIFY_EXPR, void_type_node,
- this->get_flag_tree(gogo), boolean_true_node);
-
- // Return the pair of assignments.
- return build2(COMPOUND_EXPR, void_type_node, set, set_flag);
-}
-
-// Return the tree for the flag which indicates whether anything
-// changed.
-
-tree
-Refcounts::get_flag_tree(Gogo*)
-{
- gcc_assert(!this->is_simple());
- if (this->flag_decl_ == NULL_TREE)
- {
- tree decl = create_tmp_var(boolean_type_node, NULL);
- DECL_INITIAL(decl) = boolean_false_node;
- this->flag_decl_ = decl;
- }
- return this->flag_decl_;
-}
-
-// Return a decl for the thread-local variable which holds the head of
-// the list of reference count queues.
-
-tree
-Refcounts::queue_head_decl(Gogo* gogo)
-{
- gcc_assert(!this->is_simple());
- if (this->queue_head_decl_ == NULL_TREE)
- {
- tree local_decl = this->get_tree(gogo);
- tree decl = build_decl(BUILTINS_LOCATION, VAR_DECL,
- get_identifier("__go_refcount_head"),
- build_pointer_type(TREE_TYPE(local_decl)));
- TREE_PUBLIC(decl) = 1;
- DECL_EXTERNAL(decl) = 1;
- DECL_TLS_MODEL(decl) = decl_default_tls_model(decl);
- go_preserve_from_gc(decl);
- this->queue_head_decl_ = decl;
- }
- return this->queue_head_decl_;
-}
-
-// Return the tree for initializating the reference count queue at the
-// start of a function. We use a thread-local variable to record the
-// current queue.
-
-tree
-Refcounts::init_queue(Gogo* gogo, source_location location)
-{
- tree statements = NULL_TREE;
-
- if (this->is_simple())
- {
- tree decl = this->get_simple_tree(gogo);
- tree set = build2(INIT_EXPR, void_type_node, decl, null_pointer_node);
- SET_EXPR_LOCATION(set, location);
- append_to_statement_list(set, &statements);
- }
- else
- {
- tree decl = this->get_tree(gogo);
- tree init = build2(INIT_EXPR, void_type_node, decl,
- this->get_initializer(gogo));
- SET_EXPR_LOCATION(init, location);
- append_to_statement_list(init, &statements);
-
- tree queue_head = this->queue_head_decl(gogo);
- tree set = build2(MODIFY_EXPR, void_type_node, queue_head,
- fold_convert(TREE_TYPE(queue_head),
- build_fold_addr_expr(decl)));
- SET_EXPR_LOCATION(set, location);
- append_to_statement_list(set, &statements);
-
- init = build1(DECL_EXPR, void_type_node, this->get_flag_tree(gogo));
- SET_EXPR_LOCATION(init, location);
- append_to_statement_list(init, &statements);
- }
-
- return statements;
-}
-
-// Return the tree for flushing the reference count queue.
-
-tree
-Refcounts::flush_queue(Gogo* gogo, bool at_end_of_function,
- source_location location)
-{
- if (this->is_simple())
- {
- tree decl = this->get_simple_tree(gogo);
- static tree increment_fndecl;
- static tree decrement_fndecl;
- static tree* pfndecl;
- const char* name;
- tree descriptor;
- if (this->simple_descriptor(gogo, &descriptor))
- {
- pfndecl = &increment_fndecl;
- name = "__go_increment_refcount";
- }
- else
- {
- pfndecl = &decrement_fndecl;
- name = "__go_decrement_refcount";
- }
- return Gogo::call_builtin(pfndecl,
- location,
- name,
- 2,
- void_type_node,
- ptr_type_node,
- decl,
- TREE_TYPE(descriptor),
- descriptor);
- }
-
- tree decl = this->get_tree(gogo);
- tree flag_decl = this->get_flag_tree(gogo);
- static tree flush_fndecl;
- tree call = Gogo::call_builtin(&flush_fndecl,
- location,
- "__go_refcount_flush_queue",
- 1,
- void_type_node,
- build_pointer_type(TREE_TYPE(decl)),
- build_fold_addr_expr(decl));
- tree set = build2(MODIFY_EXPR, void_type_node, flag_decl,
- boolean_false_node);
- tree ret = build3(COND_EXPR, void_type_node, flag_decl,
- build2(COMPOUND_EXPR, void_type_node, call, set),
- NULL_TREE);
- SET_EXPR_LOCATION(ret, location);
-
- if (at_end_of_function)
- {
- tree queue_head = this->queue_head_decl(gogo);
- tree decl = this->get_tree(gogo);
- tree field = TYPE_FIELDS(TREE_TYPE(decl));
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)),
- "__caller") == 0);
- tree field_ref = build3(COMPONENT_REF, TREE_TYPE(field), decl, field,
- NULL_TREE);
- tree set_head = build2(MODIFY_EXPR, void_type_node, queue_head,
- field_ref);
- SET_EXPR_LOCATION(set_head, location);
- ret = build2(COMPOUND_EXPR, void_type_node, ret, set_head);
- }
-
- return ret;
-}
-
-// Class Refcount_traverse_expressions.
-
-// Gather expressions which need to have their reference count
-// decremented after a statement is complete. This is called for
-// expressions which are not in themselves lvalues or rvalues.
-
-class Refcount_traverse_expressions : public Traverse
-{
- public:
- Refcount_traverse_expressions(Refcounts* refcounts,
- Expression* skip)
- : Traverse(traverse_blocks | traverse_expressions),
- refcounts_(refcounts), skip_(skip)
- { }
-
- void
- set_skip(Expression* skip)
- { this->skip_ = skip; }
-
- protected:
- // We only want to look at expressions which are the top level of a
- // statement. If a statement includes a block, we do not want to
- // look at the expressions in the statements in the block. For
- // example, we want to look at the condition of an If_statement, not
- // the expressions in the statements in the then and else blocks.
- int
- block(Block*)
- { return TRAVERSE_SKIP_COMPONENTS; }
-
- int
- expression(Expression**);
-
- private:
- // Temporary values which need decrementing.
- Refcounts* refcounts_;
- // An Expression to skip, because it occurs as the complete RHS.
- Expression* skip_;
-};
-
-int
-Refcount_traverse_expressions::expression(Expression** pexpr)
-{
- Expression* expr = *pexpr;
-
- if (expr == this->skip_)
- return TRAVERSE_CONTINUE;
-
- // If EXPR is a constant, we don't need to increment any reference
- // counts. We check here to catch cases like &global_variable,
- // where we can tell that is a constant when we take the address,
- // but not if we recurse down to look at the global variable.
- if (expr->is_constant())
- return TRAVERSE_SKIP_COMPONENTS;
-
- *pexpr = expr->note_decrements(this->refcounts_);
-
- return TRAVERSE_CONTINUE;
-}
-
-// Class Refcount_traverse_assignments.
-
-// For each assignment in a statement, gather values which need
-// reference count increments and decrements.
-
-class Refcount_traverse_assignments : public Traverse_assignments
-{
- public:
- Refcount_traverse_assignments(Refcounts* refcounts,
- Expression_list* do_not_increment)
- : refcounts_(refcounts), do_not_increment_(do_not_increment)
- { }
-
- protected:
- void
- initialize_variable(Named_object*);
-
- void
- assignment(Expression**, Expression**);
-
- void
- value(Expression**, bool, bool);
-
- private:
- static bool
- holds_only_arg_vars(Expression* expr);
-
- // Temporary values which need decrementing.
- Refcounts* refcounts_;
- // A list of expressions whose reference counts should not be
- // incremented. This may be NULL.
- Expression_list* do_not_increment_;
-};
-
-// Handle reference counts for a variable initialization.
-
-void
-Refcount_traverse_assignments::initialize_variable(Named_object* var)
-{
- Expression* init = var->var_value()->init();
- if (init != NULL)
- {
- Expression* init_hold = init;
- if (!var->var_value()->holds_only_args()
- || !Refcount_traverse_assignments::holds_only_arg_vars(init))
- init = init->being_copied(this->refcounts_,
- !var->var_value()->is_global());
- Refcount_traverse_expressions rte(this->refcounts_, NULL);
- Expression::traverse(&init, &rte);
- if (init != init_hold)
- var->var_value()->set_init(init);
- }
-}
-
-// Return whether EXPR is a variable which only holds argument values.
-
-bool
-Refcount_traverse_assignments::holds_only_arg_vars(Expression* expr)
-{
- if (expr == NULL)
- return false;
- Var_expression* ve = expr->var_expression();
- if (ve == NULL)
- return false;
- Named_object* no = ve->named_object();
- return no->is_variable() && no->var_value()->holds_only_args();
-}
-
-// Handle reference counts for an assignment in a statement.
-
-void
-Refcount_traverse_assignments::assignment(Expression** plhs, Expression** prhs)
-{
- if (!Refcount_traverse_assignments::holds_only_arg_vars(*plhs)
- || !Refcount_traverse_assignments::holds_only_arg_vars(*prhs))
- {
- bool is_local = (*plhs)->is_local_variable();
- if (plhs != NULL)
- *plhs = (*plhs)->being_set(this->refcounts_);
- if (prhs != NULL)
- *prhs = (*prhs)->being_copied(this->refcounts_,
- is_local);
- }
- Refcount_traverse_expressions rte(this->refcounts_, NULL);
- if (plhs != NULL)
- {
- rte.set_skip(*plhs);
- Expression::traverse(plhs, &rte);
- }
- if (prhs != NULL)
- {
- rte.set_skip(NULL);
- Expression::traverse(prhs, &rte);
- }
-}
-
-// Handle reference counts for a value used in an assignment.
-
-void
-Refcount_traverse_assignments::value(Expression** pval, bool is_stored,
- bool is_local)
-{
- if (is_stored)
- {
- bool increment = true;
- if (this->do_not_increment_ != NULL)
- {
- Expression_list::iterator p =
- std::find(this->do_not_increment_->begin(),
- this->do_not_increment_->end(),
- *pval);
- if (p != this->do_not_increment_->end())
- {
- this->do_not_increment_->erase(p);
- increment = false;
- }
- }
-
- if (increment)
- *pval = (*pval)->being_copied(this->refcounts_,
- is_local);
- }
-
- Refcount_traverse_expressions rte(this->refcounts_, NULL);
- Expression::traverse(pval, &rte);
-}
-
-// Class Refcount_traverse_statements.
-
-// Find statements which need reference count adjustments.
-
-class Refcount_traverse_statements : public Traverse
-{
- public:
- Refcount_traverse_statements(Refcounts* refcounts)
- : Traverse(traverse_functions | traverse_blocks | traverse_statements),
- refcounts_(refcounts)
- { }
-
- protected:
- int
- function(Named_object*)
- { return TRAVERSE_SKIP_COMPONENTS; }
-
- int
- block(Block*);
-
- int
- statement(Block*, size_t* pindex, Statement*);
-
- private:
- // Reference count entries for this function.
- Refcounts* refcounts_;
-};
-
-// Adjust reference counts for a block. This is where we decrement
-// the reference count for local variables.
-
-int
-Refcount_traverse_statements::block(Block* b)
-{
- // If the block ends with a return statement, build a list of
- // variables which are returned. Use the list to optimize returning
- // a reference counted local variable. FIXME: This is a very
- // simple-minded version of this optimization.
- std::vector<Named_object*> returned;
- Return_statement* r = NULL;
- const std::vector<Statement*>* statements = b->statements();
- if (!statements->empty())
- {
- r = statements->back()->return_statement();
- if (r != NULL)
- {
- const Expression_list* vals = r->vals();
- if (vals != NULL)
- {
- for (Expression_list::const_iterator pv = vals->begin();
- pv != vals->end();
- ++pv)
- {
- Var_expression* ve = (*pv)->var_expression();
- if (ve != NULL)
- {
- Named_object* no = ve->named_object();
- if (std::find(returned.begin(), returned.end(), no)
- == returned.end())
- returned.push_back(no);
- }
- }
- }
- }
- }
-
- Bindings* bindings = b->bindings();
- for (Bindings::const_definitions_iterator p = bindings->begin_definitions();
- p != bindings->end_definitions();
- ++p)
- {
- // If we find a parameter which does not only hold parameter
- // values, we need to queue up a reference count increment at
- // the start of the function.
- if ((*p)->is_variable()
- && (*p)->var_value()->is_parameter()
- && !(*p)->var_value()->holds_only_args()
- && (*p)->var_value()->type()->has_refcounted_component())
- {
- source_location loc = (*p)->location();
- Refcounts* rc = this->refcounts_;
- Refcount_entry re = rc->add(REFCOUNT_INCREMENT_COPIED,
- (*p)->var_value()->type());
- Expression* rhs = Expression::make_var_reference(*p, loc);
- Statement* s =
- Statement::make_refcount_queue_assignment_statement(rc, &re, rhs,
- loc);
- b->add_statement_at_front(s);
- }
-
- // We need to queue up reference count decrements for all local
- // variables at the end of the block.
- if ((*p)->is_variable()
- && ((*p)->var_value()->is_in_heap()
- || (!(*p)->var_value()->holds_only_args()
- && (*p)->var_value()->type()->has_refcounted_component())))
- {
- std::vector<Named_object*>::iterator prv =
- std::find(returned.begin(), returned.end(), *p);
- if (prv == returned.end())
- {
- source_location loc = b->end_location();
- Refcounts* rc = this->refcounts_;
- Type* type = (*p)->var_value()->type();
- const bool is_in_heap = (*p)->var_value()->is_in_heap();
- if (is_in_heap)
- type = Type::make_pointer_type(type);
- Refcount_entry re = rc->add(REFCOUNT_DECREMENT_OLD, type);
- Expression* rhs = Expression::make_var_reference(*p, loc);
- if (is_in_heap)
- rhs = Expression::make_unary(OPERATOR_AND, rhs, loc);
- Statement* s =
- Statement::make_refcount_queue_assignment_statement(rc, &re,
- rhs, loc);
- b->add_final_statement(s);
- }
- else
- {
- r->add_do_not_increment(*p);
- returned.erase(prv);
- }
- }
- }
- return TRAVERSE_CONTINUE;
-}
-
-// Adjust reference counts for a statement.
-
-int
-Refcount_traverse_statements::statement(Block* block, size_t* pindex,
- Statement* s)
-{
- if (s->is_block_statement())
- return TRAVERSE_CONTINUE;
-
- // Simple avoidance of reference count adjustments when returning a
- // local variable.
- Expression_list* do_not_increment = NULL;
- Return_statement* r = s->return_statement();
- if (r != NULL)
- do_not_increment = r->do_not_increment();
-
- Refcount_traverse_assignments rta(this->refcounts_, do_not_increment);
- if (!s->traverse_assignments(&rta))
- {
- Refcount_traverse_expressions rte(this->refcounts_, NULL);
- s->traverse(block, pindex, &rte);
- }
-
- gcc_assert(do_not_increment == NULL || do_not_increment->empty());
-
- return TRAVERSE_CONTINUE;
-}
-
-// Class Refcount_traverse_functions.
-
-// Walk over the functions adding reference count adjustments.
-
-class Refcount_traverse_functions : public Traverse
-{
- public:
- Refcount_traverse_functions()
- : Traverse(traverse_functions)
- { }
-
- protected:
- int
- function(Named_object*);
-};
-
-int
-Refcount_traverse_functions::function(Named_object* no)
-{
- Refcounts* refcounts = no->func_value()->refcounts();
- Refcount_traverse_statements rts(refcounts);
- no->func_value()->block()->traverse(&rts);
- refcounts->set_is_complete();
- return TRAVERSE_CONTINUE;
-}
-
-// Walk the tree adding reference count adjustments.
-
-void
-Gogo::add_refcounts()
-{
- Refcount_traverse_functions rtf;
- this->traverse(&rtf);
-}
diff -r 38d1b9933c3e go/refcount.h
--- a/go/refcount.h Fri Jul 23 09:49:42 2010 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,167 +0,0 @@
-// refcount.h -- Go fronetnd reference counts. -*- C++ -*-
-
-// 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.
-
-#ifndef GO_REFCOUNT_H
-#define GO_REFCOUNT_H
-
-// This file defines classes used to insert reference count
-// manipulation as needed in the generated program.
-
-class Gogo;
-class Type;
-class Block;
-class Expression;
-class Call_expression;
-
-// Each function maintains a local queue of values whose reference
-// count must be incremented or decremented when exiting the function.
-// These are the different sorts of values found on that queue. This
-// is not an enum because we want to declare values of this in other
-// header files without including this one.
-
-// Decrement reference count for newly allocated value created via a
-// call to new or some builtin function such as string addition.
-const int REFCOUNT_DECREMENT_NEW = 0;
-
-// Decrement reference count for value referenced during the course of
-// an expression, such as a value returned by a function call.
-const int REFCOUNT_DECREMENT_COMPUTED = 1;
-
-// Decrement reference count for old value stored in a variable or
-// memory location to which a new value was assigned.
-const int REFCOUNT_DECREMENT_OLD = 2;
-
-// Increment reference count for value copied into variable or memory
-// location.
-const int REFCOUNT_INCREMENT_COPIED = 3;
-
-// One more than the largest value.
-const int REFCOUNT_MAX = 4;
-
-// An entry in a reference count queue.
-
-class Refcount_entry
-{
- public:
- Refcount_entry(int classification, unsigned int index)
- : classification_(classification), index_(index)
- { }
-
- // The type of reference count adjustment.
- int
- classification() const
- { return this->classification_; }
-
- // The index in the specific reference count queue.
- unsigned int
- index() const
- { return this->index_; }
-
- // Update this entry to point to the next entry in the queue.
- void
- increment()
- { ++this->index_; }
-
- private:
- // Which sort of adjustment this is.
- int classification_;
- // The index in the specific reference count queue.
- unsigned int index_;
-};
-
-// The overall reference count queue. There will be one of these
-// objects for each function.
-
-class Refcounts
-{
- public:
- Refcounts()
- : entries_(), decl_(NULL), flag_decl_(NULL), queue_head_decl_(NULL),
- simple_decl_(NULL), is_complete_(false)
- { }
-
- // Add a new entry.
- Refcount_entry
- add(int classification, Type*);
-
- // Add a new entry for a type which only requires a single entry.
- // Increment *ENTRY.
- void
- add_one(Type*, Refcount_entry* entry);
-
- // Called after all entries have been added.
- void
- set_is_complete()
- { this->is_complete_ = true; }
-
- // Get the type of the variable stored in ENTRY.
- Type*
- get_type(Refcount_entry);
-
- // Return whether there are no reference count adjustments.
- bool
- empty() const;
-
- // Return a tree which sets the queue entry for ENTRY to VAL. VAL
- // must be a pointer type.
- tree
- set_entry_tree(Gogo*, Refcount_entry entry, tree val);
-
- // Initialize the reference count queue at the start of a function.
- tree
- init_queue(Gogo*, source_location);
-
- // Return the tree for flushing the reference count queue.
- tree
- flush_queue(Gogo*, bool at_end_of_function, source_location);
-
- private:
- bool
- is_simple() const;
-
- bool
- simple_descriptor(Gogo*, tree*) const;
-
- static tree
- entry_type(Gogo*);
-
- tree
- struct_type(Gogo*);
-
- tree
- get_tree(Gogo*);
-
- tree
- get_initializer(Gogo*);
-
- tree
- get_flag_tree(Gogo*);
-
- tree
- queue_head_decl(Gogo*);
-
- tree
- get_simple_tree(Gogo*);
-
- /* The type of a list of entries. */
- typedef std::vector<Type*> Entries;
-
- // Reference count adjustments, indexed by a REFCOUNT_xxx value.
- Entries entries_[REFCOUNT_MAX];
- // The local variable which holds the reference count queue.
- tree decl_;
- // The local variable which is a flag which is set when anything
- // changes.
- tree flag_decl_;
- // A decl for the head of the list of reference count queues.
- tree queue_head_decl_;
- // A decl used if the queue is simple (i.e., has only one entry).
- tree simple_decl_;
- // Set to true after we have added all reference counts.
- bool is_complete_;
-};
-
-#endif // !defined(GO_REFCOUNT_H)
diff -r 38d1b9933c3e go/statements.cc
--- a/go/statements.cc Fri Jul 23 09:49:42 2010 -0700
+++ b/go/statements.cc Fri Jul 23 13:26:04 2010 -0700
@@ -24,7 +24,6 @@
#include "types.h"
#include "expressions.h"
#include "gogo.h"
-#include "refcount.h"
#include "statements.h"
// Class Statement.
@@ -407,49 +406,7 @@
Statement::make_temporary(Block* block, Type* type, Expression* init,
source_location location)
{
- Temporary_statement* ret = new Temporary_statement(type, init, location);
- if (ret->type()->has_refcounted_component())
- block->add_final_statement(Statement::destroy_temporary(ret));
- return ret;
-}
-
-// Destroy a temporary variable.
-
-class Destroy_temporary_statement : public Statement
-{
- public:
- Destroy_temporary_statement(Temporary_statement* statement)
- : Statement(STATEMENT_DESTROY_TEMPORARY, statement->location()),
- ref_(Expression::make_temporary_reference(statement,
- statement->location()))
- { }
-
- protected:
- int
- do_traverse(Traverse*)
- { gcc_unreachable(); }
-
- bool
- do_traverse_assignments(Traverse_assignments*)
- { gcc_unreachable(); }
-
- // FIXME.
- tree
- do_get_tree(Translate_context* context)
- { return this->ref_->get_tree(context); }
-
- private:
- // A reference to the temporary variable being destroyed.
- Expression* ref_;
-};
-
-// Make a statement which destroys a temporary variable.
-
-Statement*
-Statement::destroy_temporary(Temporary_statement* statement)
-{
- gcc_assert(statement->type()->has_refcounted_component());
- return new Destroy_temporary_statement(statement);
+ return new Temporary_statement(type, init, location);
}
// An assignment statement.
@@ -568,21 +525,11 @@
rhs_tree = Expression::convert_for_assignment(context, this->lhs_->type(),
this->rhs_->type(), rhs_tree,
this->location());
-
- Refcount_decrement_lvalue_expression *rdle =
- this->lhs_->refcount_decrement_lvalue_expression();
- tree ret;
- if (rdle == NULL)
- ret = fold_build2_loc(this->location(), MODIFY_EXPR, void_type_node,
- lhs_tree, rhs_tree);
- else
- {
- ret = rdle->set(context, lhs_tree, rhs_tree);
- if (CAN_HAVE_LOCATION_P(ret))
- SET_EXPR_LOCATION(ret, this->location());
- }
-
- return ret;
+ if (rhs_tree == error_mark_node)
+ return error_mark_node;
+
+ return fold_build2_loc(this->location(), MODIFY_EXPR, void_type_node,
+ lhs_tree, rhs_tree);
}
// Make an assignment statement.
@@ -1714,15 +1661,6 @@
&& parameters->begin()->type()->points_to() == NULL)))
return false;
- // If the single parameter is reference counted, then we need a
- // thunk in order to decrement the reference count when the function
- // is complete. FIXME: In practice this means that the only simple
- // go statements are the ones with no parameters.
- if (parameters != NULL
- && !parameters->empty()
- && parameters->begin()->type()->has_refcounted_component())
- return false;
-
// If the function returns multiple values, or returns a type other
// than integer, floating point, or pointer, then it may get a
// hidden first parameter, in which case we need the more
@@ -1736,13 +1674,6 @@
&& results->begin()->type()->points_to() == NULL)))
return false;
- // If the function returns a reference counted type, then we need a
- // thunk in order to discard the function's return value.
- if (results != NULL
- && !results->empty()
- && results->begin()->type()->has_refcounted_component())
- return false;
-
// If this calls something which is not a simple function, then we
// need a thunk.
Expression* fn = this->call_->call_expression()->fn();
@@ -1767,8 +1698,6 @@
bool
Thunk_statement::do_traverse_assignments(Traverse_assignments* tassign)
{
- // FIXME: This doesn't work, because we might get a REFCOUNT_ADJUST
- // which we will never execute.
Expression* fn = this->call_->call_expression()->fn();
Expression* fn2 = fn;
tassign->value(&fn2, true, false);
@@ -1933,7 +1862,7 @@
location);
// Allocate the initialized struct on the heap.
- constructor = Expression::make_heap_composite(constructor, true, location);
+ constructor = Expression::make_heap_composite(constructor, location);
// Look up the thunk.
Named_object* named_thunk = gogo->lookup(thunk_name, NULL);
@@ -2251,9 +2180,6 @@
location));
}
- // FIXME: Now we need to decrement the reference count of the
- // parameter.
-
// That is all the thunk has to do.
gogo->finish_function(location);
}
@@ -2282,19 +2208,6 @@
else
{
gcc_assert(args->size() == 1);
- Expression* arg = args->front();
-
- // The argument will typically include a reference count
- // decrement. We do not want that decrement: the thunk is
- // responsible for decrementing the reference count. FIXME: We
- // will have an entry on the queue which is never used.
- if (arg->refcount_adjust_expression() != NULL)
- {
- int cl = arg->refcount_adjust_expression()->classification();
- if (cl != REFCOUNT_INCREMENT_COPIED)
- arg = arg->refcount_adjust_expression()->expr();
- }
-
*parg = args->front()->get_tree(context);
}
}
@@ -2388,32 +2301,8 @@
// Class Return_statement.
-// Record that we should not increment the reference count of NO.
-
-void
-Return_statement::add_do_not_increment(Named_object* no)
-{
- gcc_assert(this->vals_ != NULL);
- for (Expression_list::const_iterator p = this->vals_->begin();
- p != this->vals_->end();
- ++p)
- {
- Var_expression* ve = (*p)->var_expression();
- if (ve != NULL && ve->named_object() == no)
- {
- if (this->do_not_increment_ == NULL)
- this->do_not_increment_ = new Expression_list;
- this->do_not_increment_->push_back(ve);
- return;
- }
- }
- gcc_unreachable();
-}
-
-// Traverse assignments. A return statement doesn't assign any
-// values, but it does require that we increment the reference count
-// of the values we are returning. So we treat each return value as a
-// top level RHS in an expression.
+// Traverse assignments. We treat each return value as a top level
+// RHS in an expression.
bool
Return_statement::do_traverse_assignments(Traverse_assignments* tassign)
@@ -2880,23 +2769,7 @@
tree
Label_statement::do_get_tree(Translate_context* context)
{
- tree ret = this->build_stmt_1(LABEL_EXPR, this->label_->get_decl());
-
- // If this function has a reference count queue, we flush it at each
- // label. We need to do this in case the label is used to implement
- // a loop; otherwise some entries in the reference count queue may
- // get reused.
- Refcounts* refcounts = context->function()->func_value()->refcounts();
- if (refcounts != NULL && !refcounts->empty())
- {
- tree flush = refcounts->flush_queue(context->gogo(), false,
- this->location());
- tree statements = NULL_TREE;
- append_to_statement_list(ret, &statements);
- append_to_statement_list(flush, &statements);
- ret = statements;
- }
- return ret;
+ return this->build_stmt_1(LABEL_EXPR, this->label_->get_decl());
}
// Make a label statement.
@@ -5232,73 +5105,3 @@
{
return new For_range_statement(index_var, value_var, range, location);
}
-
-// An assignment to an entry in the reference count queue.
-
-class Refcount_queue_assignment_statement : public Statement
-{
- public:
- Refcount_queue_assignment_statement(Refcount_entry entry,
- Expression* expr,
- source_location location)
- : Statement(STATEMENT_REFCOUNT_QUEUE_ASSIGNMENT, location),
- entry_(entry), expr_(expr)
- { }
-
- protected:
- int
- do_traverse(Traverse* traverse)
- { return this->traverse_expression(traverse, &this->expr_); }
-
- // Types should have been determined and checked before any of these
- // statements are created.
-
- void
- do_determine_types()
- { gcc_unreachable(); }
-
- void
- do_check_types(Gogo*)
- { gcc_unreachable(); }
-
- tree
- do_get_tree(Translate_context*);
-
- private:
- // The entry in the reference count queue.
- Refcount_entry entry_;
- // The expression we are storing in the queue.
- Expression* expr_;
-};
-
-// Implement the actual assignment.
-
-tree
-Refcount_queue_assignment_statement::do_get_tree(Translate_context* context)
-{
- // We only need this statement for variables. It will only work for
- // expressions without side effects.
- tree expr_tree = this->expr_->get_tree(context);
- if (expr_tree == error_mark_node)
- return error_mark_node;
- gcc_assert(TREE_CODE(expr_tree) == VAR_DECL
- || TREE_CODE(expr_tree) == PARM_DECL
- || (TREE_CODE(expr_tree) == INDIRECT_REF
- && TREE_CODE(TREE_OPERAND(expr_tree, 0)) == VAR_DECL));
- Refcounts* refcounts = context->function()->func_value()->refcounts();
- return this->expr_->type()->set_refcount_queue_entry(context->gogo(),
- refcounts,
- &this->entry_,
- expr_tree);
-}
-
-// Make an assignment to an entry in the reference count queue.
-
-Statement*
-Statement::make_refcount_queue_assignment_statement(Refcounts*,
- Refcount_entry* entry,
- Expression* expr,
- source_location location)
-{
- return new Refcount_queue_assignment_statement(*entry, expr, location);
-}
diff -r 38d1b9933c3e go/statements.h
--- a/go/statements.h Fri Jul 23 09:49:42 2010 -0700
+++ b/go/statements.h Fri Jul 23 13:26:04 2010 -0700
@@ -40,8 +40,6 @@
class Type_case_clauses;
class Select_clauses;
class Typed_identifier_list;
-class Refcounts;
-class Refcount_entry;
// This class is used to traverse assignments made by a statement
// which makes assignments.
@@ -90,7 +88,6 @@
STATEMENT_ERROR,
STATEMENT_VARIABLE_DECLARATION,
STATEMENT_TEMPORARY,
- STATEMENT_DESTROY_TEMPORARY,
STATEMENT_ASSIGNMENT,
STATEMENT_EXPRESSION,
STATEMENT_BLOCK,
@@ -105,7 +102,6 @@
STATEMENT_IF,
STATEMENT_CONSTANT_SWITCH,
STATEMENT_SELECT,
- STATEMENT_REFCOUNT_QUEUE_ASSIGNMENT,
// These statements types are created by the parser, but they
// disappear during the lowering pass.
@@ -140,11 +136,6 @@
static Temporary_statement*
make_temporary(Block*, Type*, Expression*, source_location);
- // Make a statement which destroys a temporary variable. This may
- // return NULL if there is nothing to do.
- static Statement*
- destroy_temporary(Temporary_statement*);
-
// Make an assignment statement.
static Statement*
make_assignment(Expression*, Expression*, source_location);
@@ -261,12 +252,6 @@
make_for_range_statement(Expression* index_var, Expression* value_var,
Expression* range, source_location);
- // Make a statement which stores a value in the reference count
- // queue.
- static Statement*
- make_refcount_queue_assignment_statement(Refcounts*, Refcount_entry*,
- Expression*, source_location);
-
// Return the statement classification.
Statement_classification
classification() const
@@ -572,7 +557,7 @@
Return_statement(const Typed_identifier_list* results, Expression_list* vals,
source_location location)
: Statement(STATEMENT_RETURN, location),
- results_(results), vals_(vals), do_not_increment_(NULL)
+ results_(results), vals_(vals)
{ }
// The list of values being returned. This may be NULL.
@@ -580,17 +565,6 @@
vals() const
{ return this->vals_; }
- // Return list of expressions whose reference count should not be
- // incremented. This is modified by the caller.
- Expression_list*
- do_not_increment()
- { return this->do_not_increment_; }
-
- // Indicate that we should not increment the reference count of the
- // variable. The variable is being returned by this statement.
- void
- add_do_not_increment(Named_object*);
-
protected:
int
do_traverse(Traverse* traverse)
@@ -622,10 +596,6 @@
const Typed_identifier_list* results_;
// Return values. This may be NULL.
Expression_list* vals_;
- // List of variables whose reference count should not be
- // incremented. This may be NULL. This is only used during the
- // reference counting pass.
- Expression_list* do_not_increment_;
};
// Select_clauses holds the clauses of a select statement. This is
diff -r 38d1b9933c3e go/types.cc
--- a/go/types.cc Fri Jul 23 09:49:42 2010 -0700
+++ b/go/types.cc Fri Jul 23 13:26:04 2010 -0700
@@ -25,7 +25,6 @@
#include "statements.h"
#include "export.h"
#include "import.h"
-#include "refcount.h"
#include "types.h"
// Class Type.
@@ -197,17 +196,6 @@
}
}
-// Add entries to the reference count queue for this type. This is
-// the default version, which adds a single pointer.
-
-void
-Type::do_add_refcount_queue_entries(Refcounts* refcounts,
- Refcount_entry* entry)
-{
- gcc_assert(this->is_refcounted());
- refcounts->add_one(this, entry);
-}
-
// Return true if this is an error type. Don't give an error if we
// try to dereference an undefined forwarding type, as this is called
// in the parser when the type may legitimately be undefined.
@@ -731,30 +719,6 @@
gcc_unreachable();
}
-// Return a tree copying VAL, a value of this type, into the reference
-// count queue at ENTRY. This modifies ENTRY.
-
-tree
-Type::set_refcount_queue_entry(Gogo* gogo, Refcounts* refcounts,
- Refcount_entry* entry, tree val) const
-{
- return this->do_set_refcount_queue_entry(gogo, refcounts, entry, val);
-}
-
-// Default implementation of do_set_refcount_queue_entry. This works
-// for any reference count type which is represented as a pointer.
-
-tree
-Type::do_set_refcount_queue_entry(Gogo* gogo, Refcounts* refcounts,
- Refcount_entry* entry, tree val) const
-{
- gcc_assert(this->is_refcounted());
- gcc_assert(POINTER_TYPE_P(TREE_TYPE(val)));
- tree ret = refcounts->set_entry_tree(gogo, *entry, val);
- entry->increment();
- return ret;
-}
-
// Return a type descriptor for this type.
tree
@@ -1559,18 +1523,6 @@
return ret;
}
-// Copy a string into the reference count queue.
-
-tree
-String_type::do_set_refcount_queue_entry(Gogo *gogo, Refcounts* refcounts,
- Refcount_entry *entry, tree val) const
-{
- tree ret = refcounts->set_entry_tree(gogo, *entry,
- this->bytes_tree(gogo, val));
- entry->increment();
- return ret;
-}
-
// The type descriptor for the string type.
void
@@ -2671,41 +2623,6 @@
return false;
}
-// Whether this contains a reference counted component.
-
-bool
-Struct_type::do_has_refcounted_component() 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_refcounted_component())
- return true;
- }
- return false;
-}
-
-// Add entries to the refcount queue for this type.
-
-void
-Struct_type::do_add_refcount_queue_entries(Refcounts* refcounts,
- Refcount_entry* entry)
-{
- const Struct_field_list* fields = this->fields();
- gcc_assert(fields != NULL);
- for (Struct_field_list::const_iterator p = fields->begin();
- p != fields->end();
- ++p)
- {
- if (p->type()->has_refcounted_component())
- p->type()->add_refcount_queue_entries(refcounts, entry);
- }
-}
-
// Whether this type is compatible with T.
bool
@@ -3084,38 +3001,6 @@
return ret;
}
-// Copy a struct into the reference count queue.
-
-tree
-Struct_type::do_set_refcount_queue_entry(Gogo* gogo, Refcounts* refcounts,
- Refcount_entry* entry, tree val) const
-{
- const Struct_field_list* fields = this->fields();
- gcc_assert(fields != NULL);
- tree ret = NULL_TREE;
- tree field = TYPE_FIELDS(TREE_TYPE(val));
- for (Struct_field_list::const_iterator p = fields->begin();
- p != fields->end();
- ++p, field = TREE_CHAIN(field))
- {
- gcc_assert(field != NULL_TREE);
- if (p->type()->has_refcounted_component())
- {
- tree f = build3(COMPONENT_REF, TREE_TYPE(field), val, field,
- NULL_TREE);
- tree set = p->type()->set_refcount_queue_entry(gogo, refcounts,
- entry, f);
- if (ret == NULL_TREE)
- ret = set;
- else
- ret = build2(COMPOUND_EXPR, void_type_node, ret, set);
- }
- }
- gcc_assert(field == NULL_TREE);
- gcc_assert(ret != NULL_TREE);
- return ret;
-}
-
// Type descriptor.
void
@@ -3484,14 +3369,7 @@
length_tree,
size_one_node));
- tree ret = build_array_type(element_type_tree, index_type);
-
- // If the element type requires reference counting, then we need
- // this to be stored in memory.
- if (this->element_type_->has_refcounted_component())
- TREE_ADDRESSABLE(ret) = 1;
-
- return ret;
+ return build_array_type(element_type_tree, index_type);
}
else
{
@@ -3684,18 +3562,6 @@
constructor);
}
-// Copy an array into the reference count queue.
-
-tree
-Array_type::do_set_refcount_queue_entry(Gogo* gogo, Refcounts* refcounts,
- Refcount_entry* entry, tree val) const
-{
- tree ret = refcounts->set_entry_tree(gogo, *entry,
- this->value_pointer_tree(gogo, val));
- entry->increment();
- return ret;
-}
-
// Return a tree for a pointer to the values in ARRAY.
tree
@@ -5515,19 +5381,6 @@
return true;
}
-// The number of reference count queue entries required.
-
-void
-Named_type::do_add_refcount_queue_entries(Refcounts* refcounts,
- Refcount_entry* entry)
-{
- // If this is not a struct or an array, just use the type itself.
- if (this->struct_type() == NULL && this->array_type() == NULL)
- this->Type::do_add_refcount_queue_entries(refcounts, entry);
- else
- this->type_->add_refcount_queue_entries(refcounts, entry);
-}
-
// Return a hash code. This is used for method lookup. We simply
// hash on the name itself.
diff -r 38d1b9933c3e go/types.h
--- a/go/types.h Fri Jul 23 09:49:42 2010 -0700
+++ b/go/types.h Fri Jul 23 13:26:04 2010 -0700
@@ -45,8 +45,6 @@
class Translate_context;
class Export;
class Import;
-class Refcounts;
-class Refcount_entry;
// Type codes used in type descriptors. These must match the values
// in libgo/runtime/go-type.h.
@@ -590,27 +588,6 @@
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.
- bool
- is_refcounted() const
- { return this->do_is_refcounted(); }
-
- // Return true if this type has some component which is reference
- // counted. If IS_REFCOUNTED returns true for this type, then this
- // returns true as well.
- bool
- has_refcounted_component() const
- { return this->do_has_refcounted_component(); }
-
- // Add entries to the reference count queue to hold an object of
- // this type. This normally adds a single entry but may add more
- // for structures.
- void
- add_refcount_queue_entries(Refcounts* refcounts, Refcount_entry* entry)
- { return this->do_add_refcount_queue_entries(refcounts, entry); }
-
// Return true if this is an error type. An error type indicates a
// parsing error.
bool
@@ -829,12 +806,6 @@
source_location location)
{ return this->do_make_expression_tree(context, args, location); }
- // Return a tree copying VAL, a value of this type, into the
- // reference count queue at ENTRY. This modifies ENTRY.
- tree
- set_refcount_queue_entry(Gogo* gogo, Refcounts* refcounts,
- Refcount_entry* entry, tree val) const;
-
// Build a type descriptor entry for this type. Return a pointer to
// it.
tree
@@ -898,17 +869,6 @@
do_has_pointer() const
{ return false; }
- virtual bool
- do_is_refcounted() const
- { return false; }
-
- virtual bool
- do_has_refcounted_component() const
- { return this->do_is_refcounted(); }
-
- virtual void
- do_add_refcount_queue_entries(Refcounts* refcounts, Refcount_entry* entry);
-
virtual unsigned int
do_hash_for_method(Gogo*) const;
@@ -926,10 +886,6 @@
do_make_expression_tree(Translate_context*, Expression_list*,
source_location);
- virtual tree
- do_set_refcount_queue_entry(Gogo* gogo, Refcounts* refcounts,
- Refcount_entry* entry, tree val) const;
-
virtual void
do_type_descriptor_decl(Gogo* gogo, Named_type* name, tree* pdecl) = 0;
@@ -1029,10 +985,6 @@
static tree
build_receive_return_type(tree type);
- tree
- inc_or_dec_refcount(Gogo* gogo, tree expr_tree, source_location,
- bool is_local, bool is_increment);
-
// A hash table we use to avoid infinite recursion.
typedef std::tr1::unordered_set<const Named_type*, Type_hash_identical,
Type_identical> Types_seen;
@@ -1502,20 +1454,12 @@
do_has_pointer() const
{ return true; }
- bool
- do_is_refcounted() const
- { return true; }
-
tree
do_get_tree(Gogo*);
tree
do_init_tree(Gogo* gogo, bool);
- tree
- do_set_refcount_queue_entry(Gogo* gogo, Refcounts* refcounts,
- Refcount_entry* entry, tree val) const;
-
void
do_type_descriptor_decl(Gogo*, Named_type*, tree*);
@@ -1620,12 +1564,6 @@
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
- do_is_refcounted() const
- { return true; }
-
unsigned int
do_hash_for_method(Gogo*) const;
@@ -1693,10 +1631,6 @@
do_has_pointer() const
{ return true; }
- bool
- do_is_refcounted() const
- { return !this->is_unsafe_pointer_type(); }
-
unsigned int
do_hash_for_method(Gogo*) const;
@@ -1948,12 +1882,6 @@
bool
do_has_pointer() const;
- bool
- do_has_refcounted_component() const;
-
- void
- do_add_refcount_queue_entries(Refcounts*, Refcount_entry*);
-
unsigned int
do_hash_for_method(Gogo*) const;
@@ -1963,10 +1891,6 @@
tree
do_init_tree(Gogo*, bool);
- tree
- do_set_refcount_queue_entry(Gogo* gogo, Refcounts* refcounts,
- Refcount_entry* entry, tree val) const;
-
void
do_type_descriptor_decl(Gogo*, Named_type*, tree*);
@@ -2047,13 +1971,6 @@
return this->length_ == NULL || this->element_type_->has_pointer();
}
- bool
- do_is_refcounted() const
- {
- return (this->length_ == NULL
- || this->element_type_->has_refcounted_component());
- }
-
unsigned int
do_hash_for_method(Gogo*) const;
@@ -2070,10 +1987,6 @@
do_make_expression_tree(Translate_context*, Expression_list*,
source_location);
- tree
- do_set_refcount_queue_entry(Gogo* gogo, Refcounts* refcounts,
- Refcount_entry* entry, tree val) const;
-
void
do_type_descriptor_decl(Gogo*, Named_type*, tree*);
@@ -2144,10 +2057,6 @@
do_has_pointer() const
{ return true; }
- bool
- do_is_refcounted() const
- { return true; }
-
unsigned int
do_hash_for_method(Gogo*) const;
@@ -2229,10 +2138,6 @@
do_has_pointer() const
{ return true; }
- bool
- do_is_refcounted() const
- { return true; }
-
unsigned int
do_hash_for_method(Gogo*) const;
@@ -2337,10 +2242,6 @@
do_has_pointer() const
{ return true; }
- bool
- do_is_refcounted() const
- { return true; }
-
unsigned int
do_hash_for_method(Gogo*) const;
@@ -2541,17 +2442,6 @@
do_has_pointer() const
{ return this->type_->has_pointer(); }
- bool
- do_is_refcounted() const
- { return this->type_->is_refcounted(); }
-
- bool
- do_has_refcounted_component() const
- { return this->type_->has_refcounted_component(); }
-
- void
- do_add_refcount_queue_entries(Refcounts* refcounts, Refcount_entry* entry);
-
unsigned int
do_hash_for_method(Gogo*) const;
@@ -2571,13 +2461,6 @@
source_location location)
{ return this->type_->make_expression_tree(context, args, location); }
- tree
- do_set_refcount_queue_entry(Gogo* gogo, Refcounts* refcounts,
- Refcount_entry* entry, tree val) const
- {
- return this->type_->set_refcount_queue_entry(gogo, refcounts, entry, val);
- }
-
void
do_type_descriptor_decl(Gogo*, Named_type*, tree*);
@@ -2678,18 +2561,6 @@
do_has_pointer() const
{ return this->base()->has_pointer(); }
- bool
- do_is_refcounted() const
- { return this->base()->is_refcounted(); }
-
- bool
- do_has_refcounted_component() const
- { return this->base()->has_refcounted_component(); }
-
- void
- do_add_refcount_queue_entries(Refcounts* refcounts, Refcount_entry* entry)
- { return this->real_type()->add_refcount_queue_entries(refcounts, entry); }
-
unsigned int
do_hash_for_method(Gogo* gogo) const
{ return this->real_type()->hash_for_method(gogo); }
@@ -2710,13 +2581,6 @@
source_location location)
{ return this->base()->make_expression_tree(context, args, location); }
- tree
- do_set_refcount_queue_entry(Gogo* gogo, Refcounts* refcounts,
- Refcount_entry* entry, tree val) const
- {
- return this->base()->set_refcount_queue_entry(gogo, refcounts, entry, val);
- }
-
void
do_type_descriptor_decl(Gogo*, Named_type*, tree*);
diff -r 38d1b9933c3e libgo/Makefile.am
--- a/libgo/Makefile.am Fri Jul 23 09:49:42 2010 -0700
+++ b/libgo/Makefile.am Fri Jul 23 13:26:04 2010 -0700
@@ -315,10 +315,6 @@
runtime/go-rec-nb-small.c \
runtime/go-rec-small.c \
runtime/go-recover.c \
- runtime/go-refcount-decrement.c \
- runtime/go-refcount-flush.c \
- runtime/go-refcount-increment.c \
- runtime/go-refcount-msg.c \
runtime/go-reflect.c \
runtime/go-reflect-call.c \
runtime/go-reflect-chan.c \
diff -r 38d1b9933c3e libgo/runtime/go-convert-interface.c
--- a/libgo/runtime/go-convert-interface.c Fri Jul 23 09:49:42 2010 -0700
+++ b/libgo/runtime/go-convert-interface.c Fri Jul 23 13:26:04 2010 -0700
@@ -9,7 +9,6 @@
#include "go-alloc.h"
#include "go-panic.h"
-#include "go-refcount.h"
#include "interface.h"
/* Convert one interface type into another interface type.
@@ -118,8 +117,6 @@
ret->__methods = methods;
ret->__object = rhs->__object;
- __go_increment_refcount (ret->__object, ret->__type_descriptor);
-
if (success != NULL)
*success = 1;
diff -r 38d1b9933c3e libgo/runtime/go-new-interface-pointer.c
--- a/libgo/runtime/go-new-interface-pointer.c Fri Jul 23 09:49:42 2010 -0700
+++ b/libgo/runtime/go-new-interface-pointer.c Fri Jul 23 13:26:04 2010 -0700
@@ -7,7 +7,6 @@
#include <assert.h>
#include "go-alloc.h"
-#include "go-refcount.h"
#include "interface.h"
/* Allocate a new interface for a type which is represented as a
@@ -25,7 +24,5 @@
ret->__methods = methods;
ret->__object = object;
- __go_increment_refcount (object, type_descriptor);
-
return ret;
}
diff -r 38d1b9933c3e libgo/runtime/go-refcount-decrement.c
--- a/libgo/runtime/go-refcount-decrement.c Fri Jul 23 09:49:42 2010 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/* go-refcount-decrement.c -- decrement reference count.
-
- 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. */
-
-#include <assert.h>
-#include <stdlib.h>
-
-#include "go-refcount.h"
-
-/* Decrement the reference count for a pointer. */
-
-void
-__go_decrement_refcount (void *value,
- const struct __go_type_descriptor *descriptor)
-{
- struct
- {
- struct __go_refcount q;
- struct __go_refcount_entry e;
- } s;
- struct __go_refcount *queue;
-
- queue = &s.q;
- __builtin_memset (queue, 0, sizeof (struct __go_refcount));
- queue->__caller = __go_refcount_head;
- __go_refcount_head = queue;
- queue->__decrement_computed_count = 1;
- queue->__entries[0].__descriptor = descriptor;
- queue->__entries[0].__value = value;
- __go_refcount_flush_queue (queue);
- __go_refcount_head = queue->__caller;
-}
diff -r 38d1b9933c3e libgo/runtime/go-refcount-flush.c
--- a/libgo/runtime/go-refcount-flush.c Fri Jul 23 09:49:42 2010 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,224 +0,0 @@
-/* go-refcount-flush.c -- flush reference count queue.
-
- 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. */
-
-#include <assert.h>
-#include <stdlib.h>
-
-#include "go-alloc.h"
-#include "go-refcount.h"
-#include "runtime.h"
-#include "malloc.h"
-
-/* The head of the list of reference count queues. This variable is
- maintained by the code generated by the compiler. It exists in
- order to initialize the __caller field of struct __go_refcount. */
-
-__thread struct __go_refcount *__go_refcount_head;
-
-void
-__go_refcount_flush_queue (struct __go_refcount *queue)
-{
- unsigned int allocated;
- struct __go_refcount_msg *msg;
- struct __go_refcount *prc;
- unsigned int increment_count;
- unsigned int count;
- unsigned int offset;
- unsigned int i;
- unsigned int decrement_count;
-
- /* Gather all the increments. We gather up all the increments in
- this function and in all the callers. */
- allocated = 0;
- msg = NULL;
- increment_count = 0;
- for (prc = queue; prc != NULL; prc = prc->__caller)
- {
- count = prc->__increment_copy_count;
- if (count > 0)
- {
- offset = (prc->__decrement_new_count
- + prc->__decrement_computed_count
- + prc->__decrement_old_count);
- for (i = offset; i < offset + count; ++i)
- {
- struct __go_refcount_entry *pre;
- void *value;
- struct __go_refcount *qrc;
- _Bool found;
- unsigned int up_count;
- const unsigned int up_count_limit = 20;
-
- pre = &prc->__entries[i];
- value = pre->__value;
- if (value == NULL)
- continue;
- pre->__value = NULL;
-
- /* If we find an increment for something which has a
- decrement queued up, we can discard both the
- increment and the decrement. Don't look up more than
- 20 stack frames, so that this doesn't take too
- long. */
- found = 0;
- for (qrc = queue, up_count = 0;
- qrc != NULL && up_count < up_count_limit && !found;
- qrc = qrc->__caller, ++up_count)
- {
- unsigned int c;
- unsigned int j;
-
- c = (qrc->__decrement_new_count
- + qrc->__decrement_computed_count
- + qrc->__decrement_old_count);
- for (j = 0; j < c; ++j)
- {
- struct __go_refcount_entry *qre;
-
- qre = &qrc->__entries[j];
- if (qre->__value == value)
- {
- qre->__value = NULL;
- found = 1;
- break;
- }
- }
- }
-
- if (!found)
- {
- if (qrc != NULL)
- qrc->__did_not_scan_decrements = 1;
- if (increment_count >= allocated)
- {
- unsigned int new_allocated;
- struct __go_refcount_msg *new_msg;
-
- new_allocated = allocated == 0 ? 32 : allocated * 2;
- new_msg = __go_alloc (sizeof (struct __go_refcount_msg)
- + new_allocated * sizeof (void *));
- if (allocated > 0)
- {
- __builtin_memcpy (new_msg, msg,
- (sizeof (struct __go_refcount_msg)
- + allocated * sizeof (void *)));
- __go_free (msg);
- }
- allocated = new_allocated;
- msg = new_msg;
- }
- msg->__pointers[increment_count] = value;
- ++increment_count;
- }
- }
- }
-
- /* If we've already scanned the callers for increments, we can
- stop now. */
- if (prc->__callers_were_scanned)
- break;
-
- /* We are going to scan all the callers of PRC for increments;
- mark it now to avoid future scanning. */
- prc->__callers_were_scanned = 1;
- }
-
- /* Gather up the decrements. We can only send the decrements from
- the current function. That is because callers may have queued up
- decrements for temporary objects they created in order to call
- this function. If we apply those decrements now, we will discard
- objects that we might still be using. */
- decrement_count = 0;
-
- if (queue->__did_not_scan_decrements)
- {
- if (queue->__caller != NULL)
- queue->__caller->__did_not_scan_decrements = 1;
- count = (queue->__decrement_new_count
- + queue->__decrement_computed_count
- + queue->__decrement_old_count);
- offset = 0;
- }
- else
- {
- /* Any decrements in __decrement_new_count can be freed
- immediately. We did not see any increments for these
- objects; if we did, the increment would have cleared the
- decrement in the loop above. */
- count = queue->__decrement_new_count;
- for (i = 0; i < count; ++i)
- {
- struct __go_refcount_entry *pre;
- void *value;
- size_t size;
-
- pre = &queue->__entries[i];
- value = pre->__value;
- if (value == NULL)
- continue;
- pre->__value = NULL;
-
- /* FIXME: For debugging. We can't just free a slice because
- it has an embedded pointer. */
- if (pre->__descriptor->__code != GO_SLICE
- && mlookup (value, NULL, NULL, NULL, NULL))
- {
- size = pre->__descriptor->__size;
-
-#if 0
- /* FIXME: This is wrong if the value has embedded pointers. */
- __builtin_memset (value, 0xa5, size);
- __go_free (value);
-#endif
- }
- }
-
- count = queue->__decrement_computed_count + queue->__decrement_old_count;
- offset = queue->__decrement_new_count;
- }
-
- for (i = offset; i < offset + count; ++i)
- {
- struct __go_refcount_entry *pre;
- void *value;
-
- pre = &queue->__entries[i];
- value = pre->__value;
- if (value == NULL)
- continue;
- pre->__value = NULL;
-
- if (increment_count + decrement_count >= allocated)
- {
- unsigned int new_allocated;
- struct __go_refcount_msg *new_msg;
-
- new_allocated = allocated == 0 ? 32 : allocated * 2;
- new_msg = __go_alloc (sizeof (struct __go_refcount_msg)
- + new_allocated * sizeof (void *));
- if (allocated > 0)
- {
- __builtin_memcpy (new_msg, msg,
- (sizeof (struct __go_refcount_msg)
- + allocated * sizeof (void *)));
- __go_free (msg);
- }
- allocated = new_allocated;
- msg = new_msg;
- }
- msg->__pointers[increment_count + decrement_count] = value;
- ++decrement_count;
- }
-
- if (increment_count == 0 && decrement_count == 0)
- assert (msg == NULL);
- else
- {
- msg->__increments = increment_count;
- msg->__decrements = decrement_count;
- __go_send_refcount_msg (msg);
- }
-}
diff -r 38d1b9933c3e libgo/runtime/go-refcount-increment.c
--- a/libgo/runtime/go-refcount-increment.c Fri Jul 23 09:49:42 2010 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/* go-refcount-increment.c -- increment reference count.
-
- 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. */
-
-#include <assert.h>
-#include <stdlib.h>
-
-#include "go-refcount.h"
-
-/* Increment the reference count for a pointer. */
-
-void
-__go_increment_refcount (void *value,
- const struct __go_type_descriptor *descriptor)
-{
- struct
- {
- struct __go_refcount q;
- struct __go_refcount_entry e;
- } s;
- struct __go_refcount *queue;
-
- queue = &s.q;
- __builtin_memset (queue, 0, sizeof (struct __go_refcount));
- queue->__caller = __go_refcount_head;
- __go_refcount_head = queue;
- queue->__increment_copy_count = 1;
- queue->__entries[0].__descriptor = descriptor;
- queue->__entries[0].__value = value;
- __go_refcount_flush_queue (queue);
- __go_refcount_head = queue->__caller;
-}
diff -r 38d1b9933c3e libgo/runtime/go-refcount-msg.c
--- a/libgo/runtime/go-refcount-msg.c Fri Jul 23 09:49:42 2010 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/* go-refcount-msg.c -- send reference counts to GC thread.
-
- 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. */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "go-alloc.h"
-#include "go-refcount.h"
-
-/* Send a reference count message to the GC thread. */
-
-void
-__go_send_refcount_msg (struct __go_refcount_msg *msg)
-{
- static _Bool init;
- static _Bool debug;
-
- if (!init)
- {
- debug = getenv ("GO_DEBUG_REFCOUNT") != NULL;
- init = 1;
- }
-
- if (debug)
- {
- unsigned int count;
- unsigned int i;
- unsigned int offset;
-
- count = msg->__increments;
- for (i = 0; i < count; ++i)
- fprintf (stderr, "Increment refcount %p\n", msg->__pointers[i]);
- offset = count;
- count = msg->__decrements;
- for (i = 0; i < count; ++i)
- fprintf (stderr, "Decrement refcount %p\n",
- msg->__pointers[i + offset]);
- }
-
- /* FIXME: Not implemented. */
-
- __go_free (msg);
-}
diff -r 38d1b9933c3e libgo/runtime/go-refcount.h
--- a/libgo/runtime/go-refcount.h Fri Jul 23 09:49:42 2010 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/* go-refcount.h -- reference count structure.
-
- 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. */
-
-#ifndef LIBGO_GO_REFCOUNT_H
-#define LIBGO_GO_REFCOUNT_H
-
-#include "go-type.h"
-
-/* Each entry in the reference count table looks like this. */
-
-struct __go_refcount_entry
-{
- /* The type descriptor. */
- const struct __go_type_descriptor *__descriptor;
- /* If the value is a pointer, or in general if the size of the value
- is the size of a pointer, this holds the value itself. Otherwise
- it holds a pointer to the value. This will be NULL when there is
- no value whose reference count needs adjusting. */
- void *__value;
-};
-
-/* Each function which requires reference count adjustments has a
- local variable whose type is this structure. */
-
-struct __go_refcount
-{
- /* A pointer to the reference count structure for the calling
- function. This will be set to NULL if there is no caller with
- reference counts, or if all reference counts in the caller have
- been processed. */
- struct __go_refcount *__caller;
- /* This flag is initialized to false. It is set to true when we
- have scanned all the callers for increments. We only need to
- scan the callers once, since we zero out each increment as we
- find it. */
- _Bool __callers_were_scanned;
- /* This flag is initialized to false. It is set to true if we have
- stopped scanning for decrements because there were too many stack
- frames. When this flag is true we can not simply free newly
- allocated values. */
- _Bool __did_not_scan_decrements;
-
- /* The number of entries for newly allocated values. */
- unsigned short __decrement_new_count;
- /* The number of entries for computed values. */
- unsigned short __decrement_computed_count;
- /* The number of entries for old values which must be
- decremented. */
- unsigned short __decrement_old_count;
- /* The number of entries for copied values which must be
- incremented. */
- unsigned short __increment_copy_count;
-
- /* The actual entries. The number of elements in this array is the
- sum of the count variables. */
- struct __go_refcount_entry __entries[];
-};
-
-/* The struct used to send reference count adjustments to the GC
- thread. */
-
-struct __go_refcount_msg
-{
- /* The current epoch. */
- unsigned int __epoch;
- /* The number of pointers whose reference counts need to be
- incremented. */
- unsigned short __increments;
- /* The number of pointers whose reference counts need to be
- decremented. */
- unsigned short __decrements;
- /* The pointers whose reference counts need adjusting. The
- increment pointers come first, followed by the decrement
- pointers. */
- void *__pointers[];
-};
-
-/* The head of the list of reference count structures. */
-
-extern __thread struct __go_refcount *__go_refcount_head;
-
-extern void __go_increment_refcount (void *,
- const struct __go_type_descriptor *);
-
-extern void __go_refcount_flush_queue (struct __go_refcount *);
-
-extern void __go_send_refcount_msg (struct __go_refcount_msg *);
-
-#endif /* !defined (LIBGO_GO_REFCOUNT_H) */
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2010-07-23 20:35 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-07-23 20:35 [gccgo] Remove old reference counting code 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).