/* * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. *
*/
// Forward definition class GenerateOopMap; class BasicBlock; class CellTypeState; class StackMap;
// These two should be removed. But requires some code to be cleaned up #define MAXARGSIZE 256 // This should be enough #define MAX_LOCAL_VARS 65536 // 16-bit entry
typedefvoid (*jmpFct_t)(GenerateOopMap *c, int bcpDelta, int* data);
// RetTable // // Contains mapping between jsr targets and there return addresses. One-to-many mapping // class RetTableEntry : public ResourceObj { private: staticint _init_nof_jsrs; // Default size of jsrs list int _target_bci; // Target PC address of jump (bytecode index)
GrowableArray<intptr_t> * _jsrs; // List of return addresses (bytecode index)
RetTableEntry *_next; // Link to next entry public:
RetTableEntry(int target, RetTableEntry *next);
// Query int target_bci() const { return _target_bci; } int nof_jsrs() const { return _jsrs->length(); } int jsrs(int i) const { assert(i>=0 && i<nof_jsrs(), "Index out of bounds"); return _jsrs->at(i); }
class RetTable { private:
RetTableEntry *_first; staticint _init_nof_entries;
void add_jsr(int return_bci, int target_bci); // Adds entry to list public:
RetTable() { _first = NULL; } void compute_ret_table(const methodHandle& method); void update_ret_table(int bci, int delta);
RetTableEntry* find_jsrs_for_target(int targBci);
};
// // CellTypeState // class CellTypeState { private: unsignedint _state;
// Masks for separating the BITS and INFO portions of a CellTypeState enum { info_mask = right_n_bits(28),
bits_mask = (int)(~info_mask) };
// These constant are used for manipulating the BITS portion of a // CellTypeState enum { uninit_bit = (int)(nth_bit(31)),
ref_bit = nth_bit(30),
val_bit = nth_bit(29),
addr_bit = nth_bit(28),
live_bits_mask = (int)(bits_mask & ~uninit_bit) };
// These constants are used for manipulating the INFO portion of a // CellTypeState enum { top_info_bit = nth_bit(27),
not_bottom_info_bit = nth_bit(26),
info_data_mask = right_n_bits(26),
info_conflict = info_mask };
// Within the INFO data, these values are used to distinguish different // kinds of references. enum { ref_not_lock_bit = nth_bit(25), // 0 if this reference is locked as a monitor
ref_slot_bit = nth_bit(24), // 1 if this reference is a "slot" reference, // 0 if it is a "line" reference.
ref_data_mask = right_n_bits(24) };
// These values are used to initialize commonly used CellTypeState // constants. enum { bottom_value = 0,
uninit_value = (int)(uninit_bit | info_conflict),
ref_value = ref_bit,
ref_conflict = ref_bit | info_conflict,
val_value = val_bit | info_conflict,
addr_value = addr_bit,
addr_conflict = addr_bit | info_conflict };
public:
// Since some C++ constructors generate poor code for declarations of the // form... // // CellTypeState vector[length]; // // ...we avoid making a constructor for this class. CellTypeState values // should be constructed using one of the make_* methods:
static CellTypeState make_any(int state) {
CellTypeState s;
s._state = state; // Causes SS10 warning. // assert(s.is_valid_state(), "check to see if CellTypeState is valid"); return s;
}
// Query methods: bool is_bottom() const { return _state == 0; } bool is_live() const { return ((_state & live_bits_mask) != 0); } bool is_valid_state() const { // Uninitialized and value cells must contain no data in their info field: if ((can_be_uninit() || can_be_value()) && !is_info_top()) { returnfalse;
} // The top bit is only set when all info bits are set: if (is_info_top() && ((_state & info_mask) != info_mask)) { returnfalse;
} // The not_bottom_bit must be set when any other info bit is set: if (is_info_bottom() && ((_state & info_mask) != 0)) { returnfalse;
} returntrue;
}
// // BasicBlockStruct // class BasicBlock: ResourceObj { private: bool _changed; // Reached a fixpoint or not public: enum Constants {
_dead_basic_block = -2,
_unreached = -1 // Alive but not yet reached by analysis // >=0 // Alive and has a merged state
};
int _bci; // Start of basic block int _end_bci; // Bci of last instruction in basicblock int _max_locals; // Determines split between vars and stack int _max_stack; // Determines split between stack and monitors
CellTypeState* _state; // State (vars, stack) at entry. int _stack_top; // -1 indicates bottom stack value. int _monitor_top; // -1 indicates bottom monitor stack value.
bool is_reachable() const { return _stack_top >= 0; } // Analysis has reached this basicblock
// All basicblocks that are unreachable are going to have a _stack_top == _dead_basic_block. // This info. is setup in a pre-parse before the real abstract interpretation starts. bool is_dead() const { return _stack_top == _dead_basic_block; } bool is_alive() const { return _stack_top != _dead_basic_block; } void mark_as_alive() { assert(is_dead(), "must be dead"); _stack_top = _unreached; }
};
// // GenerateOopMap // // Main class used to compute the pointer-maps in a Method // class GenerateOopMap { protected:
// _monitor_top is set to this constant to indicate that a monitor matching // problem was encountered prior to this point in control flow. enum { bad_monitors = -1 };
// Main variables
methodHandle _method; // The method we are examine
RetTable _rt; // Contains the return address mappings int _max_locals; // Cached value of no. of locals int _max_stack; // Cached value of max. stack depth int _max_monitors; // Cached value of max. monitor stack depth int _has_exceptions; // True, if exceptions exist for method bool _got_error; // True, if an error occurred during interpretation.
Handle _exception; // Exception if got_error is true. bool _did_rewriting; // was bytecodes rewritten bool _did_relocation; // was relocation necessary bool _monitor_safe; // The monitors in this method have been determined // to be safe.
// Working Cell type state int _state_len; // Size of states
CellTypeState *_state; // list of states char *_state_vec_buf; // Buffer used to print a readable version of a state int _stack_top; int _monitor_top;
// Timing and statistics static elapsedTimer _total_oopmap_time; // Holds cumulative oopmap generation time static uint64_t _total_byte_count; // Holds cumulative number of bytes inspected
// Create result set bool _report_result; bool _report_result_for_send; // Unfortunately, stackmaps for sends are special, so we need some extra
BytecodeStream *_itr_send; // variables to handle them properly.
// Conflicts rewrite logic bool _conflict; // True, if a conflict occurred during interpretation int _nof_refval_conflicts; // No. of conflicts that require rewrites int * _new_var_map;
int binsToHold (int no) { return ((no+(BitsPerWord-1))/BitsPerWord); } char *state_vec_to_string (CellTypeState* vec, int len);
// Helper method. Can be used in subclasses to fx. calculate gc_points. If the current instruction // is a control transfer, then calls the jmpFct all possible destinations. void ret_jump_targets_do (BytecodeStream *bcs, jmpFct_t jmpFct, int varNo,int *data); bool jump_targets_do (BytecodeStream *bcs, jmpFct_t jmpFct, int *data);
// Compute the map - returns true on success and false on error. bool compute_map(Thread* current); // Returns the exception related to any error, if the map was computed by a suitable JavaThread.
Handle exception() { return _exception; }
void result_for_basicblock(int bci); // Do a callback on fill_stackmap_for_opcodes for basicblock containing bci
// Specialization methods. Intended use: // - possible_gc_point must return true for every bci for which the stackmaps must be returned // - fill_stackmap_prolog is called just before the result is reported. The arguments tells the estimated // number of gc points // - fill_stackmap_for_opcodes is called once for each bytecode index in order (0...code_length-1) // - fill_stackmap_epilog is called after all results has been reported. Note: Since the algorithm does not report // stackmaps for deadcode, fewer gc_points might have been encountered than assumed during the epilog. It is the // responsibility of the subclass to count the correct number. // - fill_init_vars are called once with the result of the init_vars computation // // All these methods are used during a call to: compute_map. Note: Non of the return results are valid // after compute_map returns, since all values are allocated as resource objects. // // All virtual method must be implemented in subclasses virtualbool allow_rewrites () const { returnfalse; } virtualbool report_results () const { returntrue; } virtualbool report_init_vars () const { returntrue; } virtualbool possible_gc_point (BytecodeStream *bcs) { ShouldNotReachHere(); returnfalse; } virtualvoid fill_stackmap_prolog (int nof_gc_points) { ShouldNotReachHere(); } virtualvoid fill_stackmap_epilog () { ShouldNotReachHere(); } virtualvoid fill_stackmap_for_opcodes (BytecodeStream *bcs,
CellTypeState* vars,
CellTypeState* stack, int stackTop) { ShouldNotReachHere(); } virtualvoid fill_init_vars (GrowableArray<intptr_t> *init_vars) { ShouldNotReachHere();; }
};
// // Subclass of the GenerateOopMap Class that just do rewrites of the method, if needed. // It does not store any oopmaps. // class ResolveOopMapConflicts: public GenerateOopMap { private:
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.