Mercurial > hg > graal-jvmci-8
view src/share/vm/interpreter/bytecode.hpp @ 3979:4dfb2df418f2
6484982: G1: process references during evacuation pauses
Summary: G1 now uses two reference processors - one is used by concurrent marking and the other is used by STW GCs (both full and incremental evacuation pauses). In an evacuation pause, the reference processor is embedded into the closures used to scan objects. Doing so causes causes reference objects to be 'discovered' by the reference processor. At the end of the evacuation pause, these discovered reference objects are processed - preserving (and copying) referent objects (and their reachable graphs) as appropriate.
Reviewed-by: ysr, jwilhelm, brutisso, stefank, tonyp
author | johnc |
---|---|
date | Thu, 22 Sep 2011 10:57:37 -0700 |
parents | b92c45f2bc75 |
children | e342a5110bed |
line wrap: on
line source
/* * Copyright (c) 1997, 2011, 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_INTERPRETER_BYTECODE_HPP #define SHARE_VM_INTERPRETER_BYTECODE_HPP #include "interpreter/bytecodes.hpp" #include "memory/allocation.hpp" #include "oops/methodOop.hpp" #ifdef TARGET_ARCH_x86 # include "bytes_x86.hpp" #endif #ifdef TARGET_ARCH_sparc # include "bytes_sparc.hpp" #endif #ifdef TARGET_ARCH_zero # include "bytes_zero.hpp" #endif #ifdef TARGET_ARCH_arm # include "bytes_arm.hpp" #endif #ifdef TARGET_ARCH_ppc # include "bytes_ppc.hpp" #endif class ciBytecodeStream; // The base class for different kinds of bytecode abstractions. // Provides the primitive operations to manipulate code relative // to the bcp. class Bytecode: public StackObj { protected: const address _bcp; const Bytecodes::Code _code; // Address computation address addr_at (int offset) const { return (address)_bcp + offset; } u_char byte_at(int offset) const { return *addr_at(offset); } address aligned_addr_at (int offset) const { return (address)round_to((intptr_t)addr_at(offset), jintSize); } int aligned_offset (int offset) const { return aligned_addr_at(offset) - addr_at(0); } // Word access: int get_Java_u2_at (int offset) const { return Bytes::get_Java_u2(addr_at(offset)); } int get_Java_u4_at (int offset) const { return Bytes::get_Java_u4(addr_at(offset)); } int get_native_u2_at (int offset) const { return Bytes::get_native_u2(addr_at(offset)); } int get_native_u4_at (int offset) const { return Bytes::get_native_u4(addr_at(offset)); } public: Bytecode(methodOop method, address bcp): _bcp(bcp), _code(Bytecodes::code_at(method, addr_at(0))) { assert(method != NULL, "this form requires a valid methodOop"); } // Defined in ciStreams.hpp inline Bytecode(const ciBytecodeStream* stream, address bcp = NULL); // Attributes address bcp() const { return _bcp; } int instruction_size() const { return Bytecodes::length_for_code_at(_code, bcp()); } Bytecodes::Code code() const { return _code; } Bytecodes::Code java_code() const { return Bytecodes::java_code(code()); } // Static functions for parsing bytecodes in place. int get_index_u1(Bytecodes::Code bc) const { assert_same_format_as(bc); assert_index_size(1, bc); return *(jubyte*)addr_at(1); } int get_index_u2(Bytecodes::Code bc, bool is_wide = false) const { assert_same_format_as(bc, is_wide); assert_index_size(2, bc, is_wide); address p = addr_at(is_wide ? 2 : 1); if (can_use_native_byte_order(bc, is_wide)) return Bytes::get_native_u2(p); else return Bytes::get_Java_u2(p); } int get_index_u1_cpcache(Bytecodes::Code bc) const { assert_same_format_as(bc); assert_index_size(1, bc); return *(jubyte*)addr_at(1) + constantPoolOopDesc::CPCACHE_INDEX_TAG; } int get_index_u2_cpcache(Bytecodes::Code bc) const { assert_same_format_as(bc); assert_index_size(2, bc); assert_native_index(bc); return Bytes::get_native_u2(addr_at(1)) + constantPoolOopDesc::CPCACHE_INDEX_TAG; } int get_index_u4(Bytecodes::Code bc) const { assert_same_format_as(bc); assert_index_size(4, bc); assert(can_use_native_byte_order(bc), ""); return Bytes::get_native_u4(addr_at(1)); } bool has_index_u4(Bytecodes::Code bc) const { return bc == Bytecodes::_invokedynamic; } int get_offset_s2(Bytecodes::Code bc) const { assert_same_format_as(bc); assert_offset_size(2, bc); return (jshort) Bytes::get_Java_u2(addr_at(1)); } int get_offset_s4(Bytecodes::Code bc) const { assert_same_format_as(bc); assert_offset_size(4, bc); return (jint) Bytes::get_Java_u4(addr_at(1)); } int get_constant_u1(int offset, Bytecodes::Code bc) const { assert_same_format_as(bc); assert_constant_size(1, offset, bc); return *(jbyte*)addr_at(offset); } int get_constant_u2(int offset, Bytecodes::Code bc, bool is_wide = false) const { assert_same_format_as(bc, is_wide); assert_constant_size(2, offset, bc, is_wide); return (jshort) Bytes::get_Java_u2(addr_at(offset)); } // These are used locally and also from bytecode streams. void assert_same_format_as(Bytecodes::Code testbc, bool is_wide = false) const NOT_DEBUG_RETURN; static void assert_index_size(int required_size, Bytecodes::Code bc, bool is_wide = false) NOT_DEBUG_RETURN; static void assert_offset_size(int required_size, Bytecodes::Code bc, bool is_wide = false) NOT_DEBUG_RETURN; static void assert_constant_size(int required_size, int where, Bytecodes::Code bc, bool is_wide = false) NOT_DEBUG_RETURN; static void assert_native_index(Bytecodes::Code bc, bool is_wide = false) NOT_DEBUG_RETURN; static bool can_use_native_byte_order(Bytecodes::Code bc, bool is_wide = false) { return (!Bytes::is_Java_byte_ordering_different() || Bytecodes::native_byte_order(bc /*, is_wide*/)); } }; // Abstractions for lookupswitch bytecode class LookupswitchPair VALUE_OBJ_CLASS_SPEC { private: const address _bcp; address addr_at (int offset) const { return _bcp + offset; } int get_Java_u4_at (int offset) const { return Bytes::get_Java_u4(addr_at(offset)); } public: LookupswitchPair(address bcp): _bcp(bcp) {} int match() const { return get_Java_u4_at(0 * jintSize); } int offset() const { return get_Java_u4_at(1 * jintSize); } }; class Bytecode_lookupswitch: public Bytecode { public: Bytecode_lookupswitch(methodOop method, address bcp): Bytecode(method, bcp) { verify(); } // Defined in ciStreams.hpp inline Bytecode_lookupswitch(const ciBytecodeStream* stream); void verify() const PRODUCT_RETURN; // Attributes int default_offset() const { return get_Java_u4_at(aligned_offset(1 + 0*jintSize)); } int number_of_pairs() const { return get_Java_u4_at(aligned_offset(1 + 1*jintSize)); } LookupswitchPair pair_at(int i) const { assert(0 <= i && i < number_of_pairs(), "pair index out of bounds"); return LookupswitchPair(aligned_addr_at(1 + (1 + i)*2*jintSize)); } }; class Bytecode_tableswitch: public Bytecode { public: Bytecode_tableswitch(methodOop method, address bcp): Bytecode(method, bcp) { verify(); } // Defined in ciStreams.hpp inline Bytecode_tableswitch(const ciBytecodeStream* stream); void verify() const PRODUCT_RETURN; // Attributes int default_offset() const { return get_Java_u4_at(aligned_offset(1 + 0*jintSize)); } int low_key() const { return get_Java_u4_at(aligned_offset(1 + 1*jintSize)); } int high_key() const { return get_Java_u4_at(aligned_offset(1 + 2*jintSize)); } int dest_offset_at(int i) const; int length() { return high_key()-low_key()+1; } }; // Common code for decoding invokes and field references. class Bytecode_member_ref: public Bytecode { protected: const methodHandle _method; // method containing the bytecode Bytecode_member_ref(methodHandle method, int bci) : Bytecode(method(), method()->bcp_from(bci)), _method(method) {} methodHandle method() const { return _method; } public: int index() const; // cache index (loaded from instruction) int pool_index() const; // constant pool index Symbol* name() const; // returns the name of the method or field Symbol* signature() const; // returns the signature of the method or field BasicType result_type() const; // returns the result type of the getfield or invoke }; // Abstraction for invoke_{virtual, static, interface, special} class Bytecode_invoke: public Bytecode_member_ref { protected: // Constructor that skips verification Bytecode_invoke(methodHandle method, int bci, bool unused) : Bytecode_member_ref(method, bci) {} public: Bytecode_invoke(methodHandle method, int bci) : Bytecode_member_ref(method, bci) { verify(); } void verify() const; // Attributes methodHandle static_target(TRAPS); // "specified" method (from constant pool) // Testers bool is_invokeinterface() const { return java_code() == Bytecodes::_invokeinterface; } bool is_invokevirtual() const { return java_code() == Bytecodes::_invokevirtual; } bool is_invokestatic() const { return java_code() == Bytecodes::_invokestatic; } bool is_invokespecial() const { return java_code() == Bytecodes::_invokespecial; } bool is_invokedynamic() const { return java_code() == Bytecodes::_invokedynamic; } bool has_receiver() const { return !is_invokestatic() && !is_invokedynamic(); } bool is_valid() const { return is_invokeinterface() || is_invokevirtual() || is_invokestatic() || is_invokespecial() || is_invokedynamic(); } // Helper to skip verification. Used is_valid() to check if the result is really an invoke inline friend Bytecode_invoke Bytecode_invoke_check(methodHandle method, int bci); }; inline Bytecode_invoke Bytecode_invoke_check(methodHandle method, int bci) { return Bytecode_invoke(method, bci, false); } // Abstraction for all field accesses (put/get field/static) class Bytecode_field: public Bytecode_member_ref { public: Bytecode_field(methodHandle method, int bci) : Bytecode_member_ref(method, bci) { verify(); } // Testers bool is_getfield() const { return java_code() == Bytecodes::_getfield; } bool is_putfield() const { return java_code() == Bytecodes::_putfield; } bool is_getstatic() const { return java_code() == Bytecodes::_getstatic; } bool is_putstatic() const { return java_code() == Bytecodes::_putstatic; } bool is_getter() const { return is_getfield() || is_getstatic(); } bool is_static() const { return is_getstatic() || is_putstatic(); } bool is_valid() const { return is_getfield() || is_putfield() || is_getstatic() || is_putstatic(); } void verify() const; }; // Abstraction for checkcast class Bytecode_checkcast: public Bytecode { public: Bytecode_checkcast(methodOop method, address bcp): Bytecode(method, bcp) { verify(); } void verify() const { assert(Bytecodes::java_code(code()) == Bytecodes::_checkcast, "check checkcast"); } // Returns index long index() const { return get_index_u2(Bytecodes::_checkcast); }; }; // Abstraction for instanceof class Bytecode_instanceof: public Bytecode { public: Bytecode_instanceof(methodOop method, address bcp): Bytecode(method, bcp) { verify(); } void verify() const { assert(code() == Bytecodes::_instanceof, "check instanceof"); } // Returns index long index() const { return get_index_u2(Bytecodes::_instanceof); }; }; class Bytecode_new: public Bytecode { public: Bytecode_new(methodOop method, address bcp): Bytecode(method, bcp) { verify(); } void verify() const { assert(java_code() == Bytecodes::_new, "check new"); } // Returns index long index() const { return get_index_u2(Bytecodes::_new); }; }; class Bytecode_multianewarray: public Bytecode { public: Bytecode_multianewarray(methodOop method, address bcp): Bytecode(method, bcp) { verify(); } void verify() const { assert(java_code() == Bytecodes::_multianewarray, "check new"); } // Returns index long index() const { return get_index_u2(Bytecodes::_multianewarray); }; }; class Bytecode_anewarray: public Bytecode { public: Bytecode_anewarray(methodOop method, address bcp): Bytecode(method, bcp) { verify(); } void verify() const { assert(java_code() == Bytecodes::_anewarray, "check anewarray"); } // Returns index long index() const { return get_index_u2(Bytecodes::_anewarray); }; }; // Abstraction for ldc, ldc_w and ldc2_w class Bytecode_loadconstant: public Bytecode { private: const methodHandle _method; int raw_index() const; public: Bytecode_loadconstant(methodHandle method, int bci): Bytecode(method(), method->bcp_from(bci)), _method(method) { verify(); } void verify() const { assert(_method.not_null(), "must supply method"); Bytecodes::Code stdc = Bytecodes::java_code(code()); assert(stdc == Bytecodes::_ldc || stdc == Bytecodes::_ldc_w || stdc == Bytecodes::_ldc2_w, "load constant"); } // Only non-standard bytecodes (fast_aldc) have CP cache indexes. bool has_cache_index() const { return code() >= Bytecodes::number_of_java_codes; } int pool_index() const; // index into constant pool int cache_index() const { // index into CP cache (or -1 if none) return has_cache_index() ? raw_index() : -1; } BasicType result_type() const; // returns the result type of the ldc oop resolve_constant(TRAPS) const; }; #endif // SHARE_VM_INTERPRETER_BYTECODE_HPP