Mercurial > hg > truffle
view src/share/vm/c1/c1_RangeCheckElimination.hpp @ 20543:e7d0505c8a30
8059758: Footprint regressions with JDK-8038423
Summary: Changes in JDK-8038423 always initialize (zero out) virtual memory used for auxiliary data structures. This causes a footprint regression for G1 in startup benchmarks. This is because they do not touch that memory at all, so the operating system does not actually commit these pages. The fix is to, if the initialization value of the data structures matches the default value of just committed memory (=0), do not do anything.
Reviewed-by: jwilhelm, brutisso
author | tschatzl |
---|---|
date | Fri, 10 Oct 2014 15:51:58 +0200 |
parents | 55fb97c4c58d |
children | 4ca6dc0799b6 |
line wrap: on
line source
/* * Copyright (c) 2012, 2013, 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. * */ #ifndef SHARE_VM_C1_C1_RANGECHECKELIMINATION_HPP #define SHARE_VM_C1_C1_RANGECHECKELIMINATION_HPP #include "c1/c1_Instruction.hpp" // Base class for range check elimination class RangeCheckElimination : AllStatic { public: static void eliminate(IR *ir); }; // Implementation class RangeCheckEliminator VALUE_OBJ_CLASS_SPEC { private: int _number_of_instructions; bool _optimistic; // Insert predicates and deoptimize when they fail IR *_ir; define_array(BlockBeginArray, BlockBegin*) define_stack(BlockBeginList, BlockBeginArray) define_stack(IntegerStack, intArray) define_array(IntegerMap, IntegerStack*) class Verification : public _ValueObj /*VALUE_OBJ_CLASS_SPEC*/, public BlockClosure { private: IR *_ir; boolArray _used; BlockBeginList _current; BlockBeginList _successors; public: Verification(IR *ir); virtual void block_do(BlockBegin *block); bool can_reach(BlockBegin *start, BlockBegin *end, BlockBegin *dont_use = NULL); bool dominates(BlockBegin *dominator, BlockBegin *block); }; public: // Bounds for an instruction in the form x + c which c integer // constant and x another instruction class Bound : public CompilationResourceObj { private: int _upper; Value _upper_instr; int _lower; Value _lower_instr; public: Bound(); Bound(Value v); Bound(Instruction::Condition cond, Value v, int constant = 0); Bound(int lower, Value lower_instr, int upper, Value upper_instr); ~Bound(); #ifdef ASSERT void add_assertion(Instruction *instruction, Instruction *position, int i, Value instr, Instruction::Condition cond); #endif int upper(); Value upper_instr(); int lower(); Value lower_instr(); void print(); bool check_no_overflow(int const_value); void or_op(Bound *b); void and_op(Bound *b); bool has_upper(); bool has_lower(); void set_upper(int upper, Value upper_instr); void set_lower(int lower, Value lower_instr); bool is_smaller(Bound *b); void remove_upper(); void remove_lower(); void add_constant(int value); Bound *copy(); private: void init(); }; class Visitor : public InstructionVisitor { private: Bound *_bound; RangeCheckEliminator *_rce; public: void set_range_check_eliminator(RangeCheckEliminator *rce) { _rce = rce; } Bound *bound() const { return _bound; } void clear_bound() { _bound = NULL; } protected: // visitor functions void do_Constant (Constant* x); void do_IfOp (IfOp* x); void do_LogicOp (LogicOp* x); void do_ArithmeticOp (ArithmeticOp* x); void do_Phi (Phi* x); void do_StoreField (StoreField* x) { /* nothing to do */ }; void do_StoreIndexed (StoreIndexed* x) { /* nothing to do */ }; void do_MonitorEnter (MonitorEnter* x) { /* nothing to do */ }; void do_MonitorExit (MonitorExit* x) { /* nothing to do */ }; void do_Invoke (Invoke* x) { /* nothing to do */ }; void do_UnsafePutRaw (UnsafePutRaw* x) { /* nothing to do */ }; void do_UnsafePutObject(UnsafePutObject* x) { /* nothing to do */ }; void do_Intrinsic (Intrinsic* x) { /* nothing to do */ }; void do_Local (Local* x) { /* nothing to do */ }; void do_LoadField (LoadField* x) { /* nothing to do */ }; void do_ArrayLength (ArrayLength* x) { /* nothing to do */ }; void do_LoadIndexed (LoadIndexed* x) { /* nothing to do */ }; void do_NegateOp (NegateOp* x) { /* nothing to do */ }; void do_ShiftOp (ShiftOp* x) { /* nothing to do */ }; void do_CompareOp (CompareOp* x) { /* nothing to do */ }; void do_Convert (Convert* x) { /* nothing to do */ }; void do_NullCheck (NullCheck* x) { /* nothing to do */ }; void do_TypeCast (TypeCast* x) { /* nothing to do */ }; void do_NewInstance (NewInstance* x) { /* nothing to do */ }; void do_NewTypeArray (NewTypeArray* x) { /* nothing to do */ }; void do_NewObjectArray (NewObjectArray* x) { /* nothing to do */ }; void do_NewMultiArray (NewMultiArray* x) { /* nothing to do */ }; void do_CheckCast (CheckCast* x) { /* nothing to do */ }; void do_InstanceOf (InstanceOf* x) { /* nothing to do */ }; void do_BlockBegin (BlockBegin* x) { /* nothing to do */ }; void do_Goto (Goto* x) { /* nothing to do */ }; void do_If (If* x) { /* nothing to do */ }; void do_IfInstanceOf (IfInstanceOf* x) { /* nothing to do */ }; void do_TableSwitch (TableSwitch* x) { /* nothing to do */ }; void do_LookupSwitch (LookupSwitch* x) { /* nothing to do */ }; void do_Return (Return* x) { /* nothing to do */ }; void do_Throw (Throw* x) { /* nothing to do */ }; void do_Base (Base* x) { /* nothing to do */ }; void do_OsrEntry (OsrEntry* x) { /* nothing to do */ }; void do_ExceptionObject(ExceptionObject* x) { /* nothing to do */ }; void do_RoundFP (RoundFP* x) { /* nothing to do */ }; void do_UnsafeGetRaw (UnsafeGetRaw* x) { /* nothing to do */ }; void do_UnsafeGetObject(UnsafeGetObject* x) { /* nothing to do */ }; void do_UnsafeGetAndSetObject(UnsafeGetAndSetObject* x) { /* nothing to do */ }; void do_UnsafePrefetchRead (UnsafePrefetchRead* x) { /* nothing to do */ }; void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) { /* nothing to do */ }; void do_ProfileCall (ProfileCall* x) { /* nothing to do */ }; void do_ProfileReturnType (ProfileReturnType* x) { /* nothing to do */ }; void do_ProfileInvoke (ProfileInvoke* x) { /* nothing to do */ }; void do_RuntimeCall (RuntimeCall* x) { /* nothing to do */ }; void do_MemBar (MemBar* x) { /* nothing to do */ }; void do_RangeCheckPredicate(RangeCheckPredicate* x) { /* nothing to do */ }; #ifdef ASSERT void do_Assert (Assert* x) { /* nothing to do */ }; #endif }; #ifdef ASSERT void add_assertions(Bound *bound, Instruction *instruction, Instruction *position); #endif define_array(BoundArray, Bound *) define_stack(BoundStack, BoundArray) define_array(BoundMap, BoundStack *) define_array(AccessIndexedArray, AccessIndexed *) define_stack(AccessIndexedList, AccessIndexedArray) define_array(InstructionArray, Instruction *) define_stack(InstructionList, InstructionArray) class AccessIndexedInfo : public CompilationResourceObj { public: AccessIndexedList *_list; int _min; int _max; }; define_array(AccessIndexedInfoArray, AccessIndexedInfo *) BoundMap _bounds; // Mapping from Instruction's id to current bound AccessIndexedInfoArray _access_indexed_info; // Mapping from Instruction's id to AccessIndexedInfo for in block motion Visitor _visitor; public: RangeCheckEliminator(IR *ir); IR *ir() const { return _ir; } // Pass over the dominator tree to identify blocks where there's an oppportunity for optimization bool set_process_block_flags(BlockBegin *block); // The core of the optimization work: pass over the dominator tree // to propagate bound information, insert predicate out of loops, // eliminate bound checks when possible and perform in block motion void calc_bounds(BlockBegin *block, BlockBegin *loop_header); // reorder bound checks within a block in order to eliminate some of them void in_block_motion(BlockBegin *block, AccessIndexedList &accessIndexed, InstructionList &arrays); // update/access current bound void update_bound(IntegerStack &pushed, Value v, Instruction::Condition cond, Value value, int constant); void update_bound(IntegerStack &pushed, Value v, Bound *bound); Bound *get_bound(Value v); bool loop_invariant(BlockBegin *loop_header, Instruction *instruction); // check for loop invariance void add_access_indexed_info(InstructionList &indices, int i, Value instruction, AccessIndexed *ai); // record indexed access for in block motion void remove_range_check(AccessIndexed *ai); // Mark this instructions as not needing a range check void add_if_condition(IntegerStack &pushed, Value x, Value y, Instruction::Condition condition); // Update bound for an If bool in_array_bound(Bound *bound, Value array); // Check whether bound is known to fall within array // helper functions to work with predicates Instruction* insert_after(Instruction* insert_position, Instruction* instr, int bci); Instruction* predicate(Instruction* left, Instruction::Condition cond, Instruction* right, ValueStack* state, Instruction *insert_position, int bci=-1); Instruction* predicate_cmp_with_const(Instruction* instr, Instruction::Condition cond, int constant, ValueStack* state, Instruction *insert_position, int bci=1); Instruction* predicate_add(Instruction* left, int left_const, Instruction::Condition cond, Instruction* right, ValueStack* state, Instruction *insert_position, int bci=-1); Instruction* predicate_add_cmp_with_const(Instruction* left, int left_const, Instruction::Condition cond, int constant, ValueStack* state, Instruction *insert_position, int bci=-1); void insert_deoptimization(ValueStack *state, Instruction *insert_position, Instruction *array_instr, // Add predicate Instruction *length_instruction, Instruction *lower_instr, int lower, Instruction *upper_instr, int upper, AccessIndexed *ai); bool is_ok_for_deoptimization(Instruction *insert_position, Instruction *array_instr, // Can we safely add a predicate? Instruction *length_instr, Instruction *lower_instr, int lower, Instruction *upper_instr, int upper); void process_if(IntegerStack &pushed, BlockBegin *block, If *cond); // process If Instruction void process_access_indexed(BlockBegin *loop_header, BlockBegin *block, AccessIndexed *ai); // process indexed access void dump_condition_stack(BlockBegin *cur_block); static void print_statistics(); }; #endif // SHARE_VM_C1_C1_RANGECHECKELIMINATION_HPP