--- old/src/share/vm/opto/callnode.hpp 2014-05-19 12:43:15.545483727 +0200 +++ new/src/share/vm/opto/callnode.hpp 2014-05-19 12:43:15.242141874 +0200 @@ -312,6 +312,57 @@ #endif }; +// During parsing, when a node is "improved", +// GraphKit::replace_in_map() is called to update the current map so +// that the improved node is used from that point +// on. GraphKit::replace_in_map() doesn't operate on the callers maps +// and so some optimization opportunities may be lost. The +// ReplacedNodes class addresses that problem. +// +// A ReplacedNodes object is a list of pair of nodes. Every +// SafePointNode carries a ReplacedNodes object. Every time +// GraphKit::replace_in_map() is called, a new pair of nodes is pushed +// on the list of replaced nodes. When control flow paths merge, their +// replaced nodes are also merged. When parsing exits a method to +// return to a caller, the replaced nodes on the exit path are used to +// update the caller's map. +class ReplacedNodes VALUE_OBJ_CLASS_SPEC { + private: + class ReplacedNode VALUE_OBJ_CLASS_SPEC { + private: + Node* _before; + Node* _after; + public: + ReplacedNode() : _before(NULL), _after(NULL) {} + ReplacedNode(Node* before, Node* after) : _before(before), _after(after) {} + Node* before() const { return _before; } + Node* after() const { return _after; } + + bool operator==(const ReplacedNode& other) { + return _before == other._before && _after == other._after; + } + }; + GrowableArray* _replaced_nodes; + + void allocate_if_necessary(); + bool has_node(ReplacedNode r) const; + bool has_target_node(Node* n) const; + + public: + ReplacedNodes() + : _replaced_nodes(NULL) {} + + void clone(); + void record(Node* o, Node* n); + void transfer_from(ReplacedNodes other, uint idx); + void reset(); + void apply(Node* n); + void merge_with(ReplacedNodes other); + bool is_empty() const; + void dump(outputStream *st) const; + void apply(Compile* C, Node* ctl); +}; + //------------------------------SafePointNode---------------------------------- // A SafePointNode is a subclass of a MultiNode for convenience (and // potential code sharing) only - conceptually it is independent of @@ -335,6 +386,7 @@ OopMap* _oop_map; // Array of OopMap info (8-bit char) for GC JVMState* const _jvms; // Pointer to list of JVM State objects const TypePtr* _adr_type; // What type of memory does this node produce? + ReplacedNodes _replaced_nodes; // During parsing: list of pair of nodes from calls to GraphKit::replace_in_map() // Many calls take *all* of memory as input, // but some produce a limited subset of that memory as output. @@ -426,6 +478,29 @@ void set_next_exception(SafePointNode* n); bool has_exceptions() const { return next_exception() != NULL; } + // Helper methods to operate on replaced nodes + void clone_replaced_nodes() { + _replaced_nodes.clone(); + } + void record_replaced_node(Node* o, Node* n) { + _replaced_nodes.record(o, n); + } + void transfer_replaced_nodes_from(SafePointNode* sfpt, uint idx = 0) { + _replaced_nodes.transfer_from(sfpt->_replaced_nodes, idx); + } + void delete_replaced_nodes() { + _replaced_nodes.reset(); + } + void apply_replaced_nodes() { + _replaced_nodes.apply(this); + } + void merge_replaced_nodes_with(SafePointNode* sfpt) { + _replaced_nodes.merge_with(sfpt->_replaced_nodes); + } + bool has_replaced_nodes() const { + return !_replaced_nodes.is_empty(); + } + // Standard Node stuff virtual int Opcode() const; virtual bool pinned() const { return true; }