Mercurial > hg > graal-compiler
diff src/share/vm/c1/c1_ValueStack.hpp @ 1819:f02a8bbe6ed4
6986046: C1 valuestack cleanup
Summary: fixes an historical oddity in C1 with inlining where all of the expression stacks are kept in the topmost ValueStack instead of being in their respective ValueStacks.
Reviewed-by: never
Contributed-by: Christian Wimmer <cwimmer@uci.edu>
author | roland |
---|---|
date | Tue, 29 Dec 2009 19:08:54 +0100 |
parents | b812ff5abc73 |
children | 1375bc8922e4 |
line wrap: on
line diff
--- a/src/share/vm/c1/c1_ValueStack.hpp Wed Sep 22 23:51:03 2010 -0700 +++ b/src/share/vm/c1/c1_ValueStack.hpp Tue Dec 29 19:08:54 2009 +0100 @@ -23,9 +23,23 @@ */ class ValueStack: public CompilationResourceObj { + public: + enum Kind { + Parsing, // During abstract interpretation in GraphBuilder + CallerState, // Caller state when inlining + StateBefore, // Before before execution of instruction + StateAfter, // After execution of instruction + ExceptionState, // Exception handling of instruction + EmptyExceptionState, // Exception handling of instructions not covered by an xhandler + BlockBeginState // State of BlockBegin instruction with phi functions of this block + }; + private: IRScope* _scope; // the enclosing scope - bool _lock_stack; // indicates that this ValueStack is for an exception site + ValueStack* _caller_state; + int _bci; + Kind _kind; + Values _locals; // the locals Values _stack; // the expression stack Values _locks; // the monitor stack (holding the locked values) @@ -36,100 +50,79 @@ } Value check(ValueTag tag, Value t, Value h) { - assert(h->as_HiWord()->lo_word() == t, "incorrect stack pair"); + assert(h == NULL, "hi-word of doubleword value must be NULL"); return check(tag, t); } // helper routine static void apply(Values list, ValueVisitor* f); + // for simplified copying + ValueStack(ValueStack* copy_from, Kind kind, int bci); + public: // creation - ValueStack(IRScope* scope, int locals_size, int max_stack_size); + ValueStack(IRScope* scope, ValueStack* caller_state); - // merging - ValueStack* copy(); // returns a copy of this w/ cleared locals - ValueStack* copy_locks(); // returns a copy of this w/ cleared locals and stack - // Note that when inlining of methods with exception - // handlers is enabled, this stack may have a - // non-empty expression stack (size defined by - // scope()->lock_stack_size()) + ValueStack* copy() { return new ValueStack(this, _kind, _bci); } + ValueStack* copy(Kind new_kind, int new_bci) { return new ValueStack(this, new_kind, new_bci); } + ValueStack* copy_for_parsing() { return new ValueStack(this, Parsing, -99); } + + void set_caller_state(ValueStack* s) { assert(kind() == EmptyExceptionState, "only EmptyExceptionStates can be modified"); _caller_state = s; } + bool is_same(ValueStack* s); // returns true if this & s's types match (w/o checking locals) - bool is_same_across_scopes(ValueStack* s); // same as is_same but returns true even if stacks are in different scopes (used for block merging w/inlining) // accessors IRScope* scope() const { return _scope; } - bool is_lock_stack() const { return _lock_stack; } + ValueStack* caller_state() const { return _caller_state; } + int bci() const { return _bci; } + Kind kind() const { return _kind; } + int locals_size() const { return _locals.length(); } int stack_size() const { return _stack.length(); } int locks_size() const { return _locks.length(); } - int max_stack_size() const { return _stack.capacity(); } bool stack_is_empty() const { return _stack.is_empty(); } bool no_active_locks() const { return _locks.is_empty(); } - ValueStack* caller_state() const; + int total_locks_size() const; // locals access void clear_locals(); // sets all locals to NULL; - // Kill local i. Also kill local i+1 if i was a long or double. void invalidate_local(int i) { - Value x = _locals.at(i); - if (x != NULL && x->type()->is_double_word()) { - assert(_locals.at(i + 1)->as_HiWord()->lo_word() == x, "locals inconsistent"); - _locals.at_put(i + 1, NULL); - } + assert(_locals.at(i)->type()->is_single_word() || + _locals.at(i + 1) == NULL, "hi-word of doubleword value must be NULL"); _locals.at_put(i, NULL); } - - Value load_local(int i) const { + Value local_at(int i) const { Value x = _locals.at(i); - if (x != NULL && x->type()->is_illegal()) return NULL; - assert(x == NULL || x->as_HiWord() == NULL, "index points to hi word"); - assert(x == NULL || x->type()->is_illegal() || x->type()->is_single_word() || x == _locals.at(i+1)->as_HiWord()->lo_word(), "locals inconsistent"); + assert(x == NULL || x->type()->is_single_word() || + _locals.at(i + 1) == NULL, "hi-word of doubleword value must be NULL"); return x; } - Value local_at(int i) const { return _locals.at(i); } - - // Store x into local i. void store_local(int i, Value x) { - // Kill the old value - invalidate_local(i); - _locals.at_put(i, x); - - // Writing a double word can kill other locals - if (x != NULL && x->type()->is_double_word()) { - // If x + i was the start of a double word local then kill i + 2. - Value x2 = _locals.at(i + 1); - if (x2 != NULL && x2->type()->is_double_word()) { - _locals.at_put(i + 2, NULL); - } - - // If x is a double word local, also update i + 1. -#ifdef ASSERT - _locals.at_put(i + 1, x->hi_word()); -#else - _locals.at_put(i + 1, NULL); -#endif - } - // If x - 1 was the start of a double word local then kill i - 1. + // When overwriting local i, check if i - 1 was the start of a + // double word local and kill it. if (i > 0) { Value prev = _locals.at(i - 1); if (prev != NULL && prev->type()->is_double_word()) { _locals.at_put(i - 1, NULL); } } + + _locals.at_put(i, x); + if (x->type()->is_double_word()) { + // hi-word of doubleword value is always NULL + _locals.at_put(i + 1, NULL); + } } - void replace_locals(ValueStack* with); - // stack access Value stack_at(int i) const { Value x = _stack.at(i); - assert(x->as_HiWord() == NULL, "index points to hi word"); assert(x->type()->is_single_word() || - x->subst() == _stack.at(i+1)->as_HiWord()->lo_word(), "stack inconsistent"); + _stack.at(i + 1) == NULL, "hi-word of doubleword value must be NULL"); return x; } @@ -146,7 +139,6 @@ void values_do(ValueVisitor* f); // untyped manipulation (for dup_x1, etc.) - void clear_stack() { _stack.clear(); } void truncate_stack(int size) { _stack.trunc_to(size); } void raw_push(Value t) { _stack.push(t); } Value raw_pop() { return _stack.pop(); } @@ -156,15 +148,8 @@ void fpush(Value t) { _stack.push(check(floatTag , t)); } void apush(Value t) { _stack.push(check(objectTag , t)); } void rpush(Value t) { _stack.push(check(addressTag, t)); } -#ifdef ASSERT - // in debug mode, use HiWord for 2-word values - void lpush(Value t) { _stack.push(check(longTag , t)); _stack.push(new HiWord(t)); } - void dpush(Value t) { _stack.push(check(doubleTag , t)); _stack.push(new HiWord(t)); } -#else - // in optimized mode, use NULL for 2-word values void lpush(Value t) { _stack.push(check(longTag , t)); _stack.push(NULL); } void dpush(Value t) { _stack.push(check(doubleTag , t)); _stack.push(NULL); } -#endif // ASSERT void push(ValueType* type, Value t) { switch (type->tag()) { @@ -182,15 +167,8 @@ Value fpop() { return check(floatTag , _stack.pop()); } Value apop() { return check(objectTag , _stack.pop()); } Value rpop() { return check(addressTag, _stack.pop()); } -#ifdef ASSERT - // in debug mode, check for HiWord consistency Value lpop() { Value h = _stack.pop(); return check(longTag , _stack.pop(), h); } Value dpop() { Value h = _stack.pop(); return check(doubleTag, _stack.pop(), h); } -#else - // in optimized mode, ignore HiWord since it is NULL - Value lpop() { _stack.pop(); return check(longTag , _stack.pop()); } - Value dpop() { _stack.pop(); return check(doubleTag, _stack.pop()); } -#endif // ASSERT Value pop(ValueType* type) { switch (type->tag()) { @@ -208,16 +186,10 @@ Values* pop_arguments(int argument_size); // locks access - int lock (IRScope* scope, Value obj); + int lock (Value obj); int unlock(); Value lock_at(int i) const { return _locks.at(i); } - // Inlining support - ValueStack* push_scope(IRScope* scope); // "Push" new scope, returning new resulting stack - // Preserves stack and locks, destroys locals - ValueStack* pop_scope(); // "Pop" topmost scope, returning new resulting stack - // Preserves stack and locks, destroys locals - // SSA form IR support void setup_phi_for_stack(BlockBegin* b, int index); void setup_phi_for_local(BlockBegin* b, int index); @@ -298,16 +270,18 @@ { \ int cur_index; \ ValueStack* cur_state = v_state; \ - Value v_value; \ - { \ - for_each_stack_value(cur_state, cur_index, v_value) { \ - v_code; \ + Value v_value; \ + for_each_state(cur_state) { \ + { \ + for_each_local_value(cur_state, cur_index, v_value) { \ + v_code; \ + } \ } \ - } \ - for_each_state(cur_state) { \ - for_each_local_value(cur_state, cur_index, v_value) { \ - v_code; \ - } \ + { \ + for_each_stack_value(cur_state, cur_index, v_value) { \ + v_code; \ + } \ + } \ } \ }