diff --git a/src/share/vm/classfile/systemDictionary.cpp b/src/share/vm/classfile/systemDictionary.cpp index b9ba2062dda52bbc848fb0d457d3057449342a5d..14361bc188d94ed8ef97f89df269171ce76f13d4 100644 --- a/src/share/vm/classfile/systemDictionary.cpp +++ b/src/share/vm/classfile/systemDictionary.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2010, 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 @@ -26,12 +26,12 @@ # include "incls/_systemDictionary.cpp.incl" -Dictionary* SystemDictionary::_dictionary = NULL; -PlaceholderTable* SystemDictionary::_placeholders = NULL; -Dictionary* SystemDictionary::_shared_dictionary = NULL; -LoaderConstraintTable* SystemDictionary::_loader_constraints = NULL; -ResolutionErrorTable* SystemDictionary::_resolution_errors = NULL; -SymbolPropertyTable* SystemDictionary::_invoke_method_table = NULL; +Dictionary* SystemDictionary::_dictionary = NULL; +PlaceholderTable* SystemDictionary::_placeholders = NULL; +Dictionary* SystemDictionary::_shared_dictionary = NULL; +LoaderConstraintTable* SystemDictionary::_loader_constraints = NULL; +ResolutionErrorTable* SystemDictionary::_resolution_errors = NULL; +SymbolPropertyTable* SystemDictionary::_invoke_method_table = NULL; int SystemDictionary::_number_of_modifications = 0; @@ -1727,8 +1727,7 @@ void SystemDictionary::always_strong_classes_do(OopClosure* blk) { placeholders_do(blk); // Visit extra methods - if (invoke_method_table() != NULL) - invoke_method_table()->oops_do(blk); + invoke_method_table()->oops_do(blk); // Loader constraints. We must keep the symbolOop used in the name alive. constraints()->always_strong_classes_do(blk); @@ -1766,8 +1765,7 @@ void SystemDictionary::oops_do(OopClosure* f) { dictionary()->oops_do(f); // Visit extra methods - if (invoke_method_table() != NULL) - invoke_method_table()->oops_do(f); + invoke_method_table()->oops_do(f); // Partially loaded classes placeholders()->oops_do(f); @@ -1841,8 +1839,7 @@ void SystemDictionary::placeholders_do(void f(symbolOop, oop)) { void SystemDictionary::methods_do(void f(methodOop)) { dictionary()->methods_do(f); - if (invoke_method_table() != NULL) - invoke_method_table()->methods_do(f); + invoke_method_table()->methods_do(f); } // ---------------------------------------------------------------------------- @@ -1870,12 +1867,12 @@ void SystemDictionary::initialize(TRAPS) { // Allocate arrays assert(dictionary() == NULL, "SystemDictionary should only be initialized once"); - _dictionary = new Dictionary(_nof_buckets); - _placeholders = new PlaceholderTable(_nof_buckets); + _dictionary = new Dictionary(_nof_buckets); + _placeholders = new PlaceholderTable(_nof_buckets); _number_of_modifications = 0; - _loader_constraints = new LoaderConstraintTable(_loader_constraint_size); - _resolution_errors = new ResolutionErrorTable(_resolution_error_size); - // _invoke_method_table is allocated lazily in find_method_handle_invoke() + _loader_constraints = new LoaderConstraintTable(_loader_constraint_size); + _resolution_errors = new ResolutionErrorTable(_resolution_error_size); + _invoke_method_table = new SymbolPropertyTable(_invoke_method_size); // Allocate private object used as system class loader lock _system_loader_lock_obj = oopFactory::new_system_objArray(0, CHECK); @@ -2346,10 +2343,6 @@ methodOop SystemDictionary::find_method_handle_invoke(symbolHandle name, KlassHandle accessing_klass, TRAPS) { if (!EnableMethodHandles) return NULL; - if (invoke_method_table() == NULL) { - // create this side table lazily - _invoke_method_table = new SymbolPropertyTable(_invoke_method_size); - } vmSymbols::SID name_id = vmSymbols::find_sid(name()); assert(name_id != vmSymbols::NO_SID, "must be a known name"); unsigned int hash = invoke_method_table()->compute_hash(signature, name_id); diff --git a/src/share/vm/interpreter/interpreterRuntime.cpp b/src/share/vm/interpreter/interpreterRuntime.cpp index fd867a4cfd0721306ef7b27e7de7042c7475548a..3a3bd193c4f8f4075a8fbe15e2ece2994cdb6717 100644 --- a/src/share/vm/interpreter/interpreterRuntime.cpp +++ b/src/share/vm/interpreter/interpreterRuntime.cpp @@ -720,8 +720,8 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_invokedynamic(JavaThread* thread)) { // first resolve the signature to a MH.invoke methodOop if (!pool->cache()->entry_at(main_index)->is_resolved(bytecode)) { JvmtiHideSingleStepping jhss(thread); - CallInfo info; - LinkResolver::resolve_invoke(info, Handle(), pool, + CallInfo callinfo; + LinkResolver::resolve_invoke(callinfo, Handle(), pool, site_index, bytecode, CHECK); // The main entry corresponds to a JVM_CONSTANT_InvokeDynamic, and serves // as a common reference point for all invokedynamic call sites with @@ -729,8 +729,8 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_invokedynamic(JavaThread* thread)) { // as if it were an invokevirtual of MethodHandle.invoke. pool->cache()->entry_at(main_index)->set_method( bytecode, - info.resolved_method(), - info.vtable_index()); + callinfo.resolved_method(), + callinfo.vtable_index()); } // The method (f2 entry) of the main entry is the MH.invoke for the diff --git a/src/share/vm/oops/cpCacheOop.cpp b/src/share/vm/oops/cpCacheOop.cpp index eb27f1658ab7ee84c90dfb4838078d3fec1e7f47..c49c934dc60ecbc97d918ff77309f7cb5359591d 100644 --- a/src/share/vm/oops/cpCacheOop.cpp +++ b/src/share/vm/oops/cpCacheOop.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2010, 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 @@ -87,6 +87,19 @@ void ConstantPoolCacheEntry::set_bytecode_2(Bytecodes::Code code) { OrderAccess::release_store_ptr(&_indices, _indices | ((u_char)code << 24)); } +// Atomically sets f1 if it is still NULL, otherwise it keeps the +// current value. +void ConstantPoolCacheEntry::set_f1_if_null_atomic(oop f1) { + // Use barriers as in oop_store + HeapWord* f1_addr = (HeapWord*) &_f1; + update_barrier_set_pre(f1_addr, f1); + void* result = Atomic::cmpxchg_ptr(f1, f1_addr, NULL); + bool success = (result == NULL); + if (success) { + update_barrier_set((void*) f1_addr, f1); + } + } + #ifdef ASSERT // It is possible to have two different dummy methodOops created // when the resolve code for invoke interface executes concurrently @@ -165,7 +178,12 @@ void ConstantPoolCacheEntry::set_method(Bytecodes::Code invoke_code, } assert(method->can_be_statically_bound(), "must be a MH invoker method"); assert(AllowTransitionalJSR292 || _f2 >= constantPoolOopDesc::CPCACHE_INDEX_TAG, "BSM index initialized"); - set_f1(method()); + // SystemDictionary::find_method_handle_invoke only caches + // methods which signature classes are on the boot classpath, + // otherwise the newly created method is returned. To avoid + // races in that case we store the first one coming in into the + // cp-cache atomically if it's still unset. + set_f1_if_null_atomic(method()); needs_vfinal_flag = false; // _f2 is not an oop assert(!is_vfinal(), "f2 not an oop"); byte_no = 1; // coordinate this with bytecode_number & is_resolved diff --git a/src/share/vm/oops/cpCacheOop.hpp b/src/share/vm/oops/cpCacheOop.hpp index 68460717fe07e412abf55235a088f0da5bbfa79f..aa0bd2c5113e7b98848e1aea57bce3d25fef4638 100644 --- a/src/share/vm/oops/cpCacheOop.hpp +++ b/src/share/vm/oops/cpCacheOop.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2010, 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 @@ -130,6 +130,7 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC { assert(existing_f1 == NULL || existing_f1 == f1, "illegal field change"); oop_store(&_f1, f1); } + void set_f1_if_null_atomic(oop f1); void set_f2(intx f2) { assert(_f2 == 0 || _f2 == f2, "illegal field change"); _f2 = f2; } int as_flags(TosState state, bool is_final, bool is_vfinal, bool is_volatile, bool is_method_interface, bool is_method); diff --git a/src/share/vm/runtime/thread.cpp b/src/share/vm/runtime/thread.cpp index 27ea367302bb03fc9eb3c1eb79fc6992c502cd9b..80aa9ca61a035c25d06d0888b293ce895c2ed9ed 100644 --- a/src/share/vm/runtime/thread.cpp +++ b/src/share/vm/runtime/thread.cpp @@ -1199,6 +1199,7 @@ void JavaThread::initialize() { _exception_pc = 0; _exception_handler_pc = 0; _exception_stack_size = 0; + _is_method_handle_return = 0; _jvmti_thread_state= NULL; _should_post_on_exceptions_flag = JNI_FALSE; _jvmti_get_loaded_classes_closure = NULL;