# HG changeset patch # User twisti # Date 1268736737 -3600 # Node ID 47ecd86932cef6946c1465d7a71659a04914cf81 # Parent cdeb352c6bbee36e269861fce9a4ceb2cb0eaaba 6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob Summary: Passing a null pointer to an InvokeDynamic function call should lead to a NullPointerException. Reviewed-by: kvn, never diff -r cdeb352c6bbe -r 47ecd86932ce hotspot/src/cpu/sparc/vm/stubRoutines_sparc.hpp --- a/hotspot/src/cpu/sparc/vm/stubRoutines_sparc.hpp Thu Mar 11 05:09:20 2010 -0800 +++ b/hotspot/src/cpu/sparc/vm/stubRoutines_sparc.hpp Tue Mar 16 11:52:17 2010 +0100 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2010 Sun Microsystems, Inc. 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 @@ -37,8 +37,13 @@ enum /* platform_dependent_constants */ { // %%%%%%%% May be able to shrink this a lot - code_size1 = 20000, // simply increase if too small (assembler will crash if too small) - code_size2 = 20000 // simply increase if too small (assembler will crash if too small) + code_size1 = 20000, // simply increase if too small (assembler will crash if too small) + code_size2 = 20000 // simply increase if too small (assembler will crash if too small) +}; + +// MethodHandles adapters +enum method_handles_platform_dependent_constants { + method_handles_adapters_code_size = 5000 }; class Sparc { diff -r cdeb352c6bbe -r 47ecd86932ce hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp Thu Mar 11 05:09:20 2010 -0800 +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp Tue Mar 16 11:52:17 2010 +0100 @@ -2276,16 +2276,6 @@ // arraycopy stubs used by compilers generate_arraycopy_stubs(); - // generic method handle stubs - if (EnableMethodHandles && SystemDictionary::MethodHandle_klass() != NULL) { - for (MethodHandles::EntryKind ek = MethodHandles::_EK_FIRST; - ek < MethodHandles::_EK_LIMIT; - ek = MethodHandles::EntryKind(1 + (int)ek)) { - StubCodeMark mark(this, "MethodHandle", MethodHandles::entry_name(ek)); - MethodHandles::generate_method_handle_stub(_masm, ek); - } - } - generate_math_stubs(); } diff -r cdeb352c6bbe -r 47ecd86932ce hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp Thu Mar 11 05:09:20 2010 -0800 +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp Tue Mar 16 11:52:17 2010 +0100 @@ -3009,16 +3009,6 @@ // arraycopy stubs used by compilers generate_arraycopy_stubs(); - // generic method handle stubs - if (EnableMethodHandles && SystemDictionary::MethodHandle_klass() != NULL) { - for (MethodHandles::EntryKind ek = MethodHandles::_EK_FIRST; - ek < MethodHandles::_EK_LIMIT; - ek = MethodHandles::EntryKind(1 + (int)ek)) { - StubCodeMark mark(this, "MethodHandle", MethodHandles::entry_name(ek)); - MethodHandles::generate_method_handle_stub(_masm, ek); - } - } - generate_math_stubs(); } diff -r cdeb352c6bbe -r 47ecd86932ce hotspot/src/cpu/x86/vm/stubRoutines_x86_32.hpp --- a/hotspot/src/cpu/x86/vm/stubRoutines_x86_32.hpp Thu Mar 11 05:09:20 2010 -0800 +++ b/hotspot/src/cpu/x86/vm/stubRoutines_x86_32.hpp Tue Mar 16 11:52:17 2010 +0100 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2010 Sun Microsystems, Inc. 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 @@ -31,6 +31,11 @@ code_size2 = 22000 // simply increase if too small (assembler will crash if too small) }; +// MethodHandles adapters +enum method_handles_platform_dependent_constants { + method_handles_adapters_code_size = 5000 +}; + class x86 { friend class StubGenerator; friend class VMStructs; diff -r cdeb352c6bbe -r 47ecd86932ce hotspot/src/cpu/x86/vm/stubRoutines_x86_64.hpp --- a/hotspot/src/cpu/x86/vm/stubRoutines_x86_64.hpp Thu Mar 11 05:09:20 2010 -0800 +++ b/hotspot/src/cpu/x86/vm/stubRoutines_x86_64.hpp Tue Mar 16 11:52:17 2010 +0100 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2010 Sun Microsystems, Inc. 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 @@ -28,12 +28,14 @@ static bool returns_to_call_stub(address return_pc) { return return_pc == _call_stub_return_address; } -enum platform_dependent_constants -{ - code_size1 = 19000, // simply increase if too small (assembler will - // crash if too small) - code_size2 = 22000 // simply increase if too small (assembler will - // crash if too small) +enum platform_dependent_constants { + code_size1 = 19000, // simply increase if too small (assembler will crash if too small) + code_size2 = 22000 // simply increase if too small (assembler will crash if too small) +}; + +// MethodHandles adapters +enum method_handles_platform_dependent_constants { + method_handles_adapters_code_size = 13000 }; class x86 { diff -r cdeb352c6bbe -r 47ecd86932ce hotspot/src/share/vm/code/codeBlob.cpp --- a/hotspot/src/share/vm/code/codeBlob.cpp Thu Mar 11 05:09:20 2010 -0800 +++ b/hotspot/src/share/vm/code/codeBlob.cpp Tue Mar 16 11:52:17 2010 +0100 @@ -1,5 +1,5 @@ /* - * Copyright 1998-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1998-2010 Sun Microsystems, Inc. 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 @@ -249,7 +249,6 @@ size += round_to(buffer_size, oopSize); assert(name != NULL, "must provide a name"); { - MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); blob = new (size) BufferBlob(name, size); } @@ -271,7 +270,6 @@ unsigned int size = allocation_size(cb, sizeof(BufferBlob)); assert(name != NULL, "must provide a name"); { - MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); blob = new (size) BufferBlob(name, size, cb); } @@ -298,10 +296,48 @@ MemoryService::track_code_cache_memory_usage(); } -bool BufferBlob::is_adapter_blob() const { - return (strcmp(AdapterHandlerEntry::name, name()) == 0); + +//---------------------------------------------------------------------------------------------------- +// Implementation of AdapterBlob + +AdapterBlob* AdapterBlob::create(CodeBuffer* cb) { + ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock + + AdapterBlob* blob = NULL; + unsigned int size = allocation_size(cb, sizeof(AdapterBlob)); + { + MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); + blob = new (size) AdapterBlob(size, cb); + } + // Track memory usage statistic after releasing CodeCache_lock + MemoryService::track_code_cache_memory_usage(); + + return blob; } + +//---------------------------------------------------------------------------------------------------- +// Implementation of MethodHandlesAdapterBlob + +MethodHandlesAdapterBlob* MethodHandlesAdapterBlob::create(int buffer_size) { + ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock + + MethodHandlesAdapterBlob* blob = NULL; + unsigned int size = sizeof(MethodHandlesAdapterBlob); + // align the size to CodeEntryAlignment + size = align_code_offset(size); + size += round_to(buffer_size, oopSize); + { + MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); + blob = new (size) MethodHandlesAdapterBlob(size); + } + // Track memory usage statistic after releasing CodeCache_lock + MemoryService::track_code_cache_memory_usage(); + + return blob; +} + + //---------------------------------------------------------------------------------------------------- // Implementation of RuntimeStub diff -r cdeb352c6bbe -r 47ecd86932ce hotspot/src/share/vm/code/codeBlob.hpp --- a/hotspot/src/share/vm/code/codeBlob.hpp Thu Mar 11 05:09:20 2010 -0800 +++ b/hotspot/src/share/vm/code/codeBlob.hpp Tue Mar 16 11:52:17 2010 +0100 @@ -1,5 +1,5 @@ /* - * Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1998-2010 Sun Microsystems, Inc. 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 @@ -90,14 +90,15 @@ void flush(); // Typing - virtual bool is_buffer_blob() const { return false; } - virtual bool is_nmethod() const { return false; } - virtual bool is_runtime_stub() const { return false; } - virtual bool is_deoptimization_stub() const { return false; } - virtual bool is_uncommon_trap_stub() const { return false; } - virtual bool is_exception_stub() const { return false; } - virtual bool is_safepoint_stub() const { return false; } - virtual bool is_adapter_blob() const { return false; } + virtual bool is_buffer_blob() const { return false; } + virtual bool is_nmethod() const { return false; } + virtual bool is_runtime_stub() const { return false; } + virtual bool is_deoptimization_stub() const { return false; } + virtual bool is_uncommon_trap_stub() const { return false; } + virtual bool is_exception_stub() const { return false; } + virtual bool is_safepoint_stub() const { return false; } + virtual bool is_adapter_blob() const { return false; } + virtual bool is_method_handles_adapter_blob() const { return false; } virtual bool is_compiled_by_c2() const { return false; } virtual bool is_compiled_by_c1() const { return false; } @@ -221,6 +222,9 @@ class BufferBlob: public CodeBlob { friend class VMStructs; + friend class AdapterBlob; + friend class MethodHandlesAdapterBlob; + private: // Creation support BufferBlob(const char* name, int size); @@ -236,8 +240,7 @@ static void free(BufferBlob* buf); // Typing - bool is_buffer_blob() const { return true; } - bool is_adapter_blob() const; + virtual bool is_buffer_blob() const { return true; } // GC/Verification support void preserve_callee_argument_oops(frame fr, const RegisterMap* reg_map, OopClosure* f) { /* nothing to do */ } @@ -255,6 +258,40 @@ //---------------------------------------------------------------------------------------------------- +// AdapterBlob: used to hold C2I/I2C adapters + +class AdapterBlob: public BufferBlob { +private: + AdapterBlob(int size) : BufferBlob("I2C/C2I adapters", size) {} + AdapterBlob(int size, CodeBuffer* cb) : BufferBlob("I2C/C2I adapters", size, cb) {} + +public: + // Creation + static AdapterBlob* create(CodeBuffer* cb); + + // Typing + virtual bool is_adapter_blob() const { return true; } +}; + + +//---------------------------------------------------------------------------------------------------- +// MethodHandlesAdapterBlob: used to hold MethodHandles adapters + +class MethodHandlesAdapterBlob: public BufferBlob { +private: + MethodHandlesAdapterBlob(int size) : BufferBlob("MethodHandles adapters", size) {} + MethodHandlesAdapterBlob(int size, CodeBuffer* cb) : BufferBlob("MethodHandles adapters", size, cb) {} + +public: + // Creation + static MethodHandlesAdapterBlob* create(int buffer_size); + + // Typing + virtual bool is_method_handles_adapter_blob() const { return true; } +}; + + +//---------------------------------------------------------------------------------------------------- // RuntimeStub: describes stubs used by compiled code to call a (static) C++ runtime routine class RuntimeStub: public CodeBlob { diff -r cdeb352c6bbe -r 47ecd86932ce hotspot/src/share/vm/includeDB_core --- a/hotspot/src/share/vm/includeDB_core Thu Mar 11 05:09:20 2010 -0800 +++ b/hotspot/src/share/vm/includeDB_core Tue Mar 16 11:52:17 2010 +0100 @@ -2017,6 +2017,7 @@ init.cpp icBuffer.hpp init.cpp icache.hpp init.cpp init.hpp +init.cpp methodHandles.hpp init.cpp safepoint.hpp init.cpp sharedRuntime.hpp init.cpp universe.hpp @@ -2871,6 +2872,7 @@ methodHandles.cpp oopFactory.hpp methodHandles.cpp reflection.hpp methodHandles.cpp signature.hpp +methodHandles.cpp stubRoutines.hpp methodHandles.cpp symbolTable.hpp methodHandles_.cpp allocation.inline.hpp diff -r cdeb352c6bbe -r 47ecd86932ce hotspot/src/share/vm/prims/methodHandles.cpp --- a/hotspot/src/share/vm/prims/methodHandles.cpp Thu Mar 11 05:09:20 2010 -0800 +++ b/hotspot/src/share/vm/prims/methodHandles.cpp Tue Mar 16 11:52:17 2010 +0100 @@ -1,5 +1,5 @@ /* - * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2008-2010 Sun Microsystems, Inc. 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 @@ -82,6 +82,10 @@ NULL }; +// Adapters. +MethodHandlesAdapterBlob* MethodHandles::_adapter_code = NULL; +int MethodHandles::_adapter_code_size = StubRoutines::method_handles_adapters_code_size; + jobject MethodHandles::_raise_exception_method; #ifdef ASSERT @@ -95,6 +99,41 @@ } #endif + +//------------------------------------------------------------------------------ +// MethodHandles::generate_adapters +// +void MethodHandles::generate_adapters() { + if (!EnableMethodHandles || SystemDictionary::MethodHandle_klass() == NULL) return; + + assert(_adapter_code == NULL, "generate only once"); + + ResourceMark rm; + TraceTime timer("MethodHandles adapters generation", TraceStartupTime); + _adapter_code = MethodHandlesAdapterBlob::create(_adapter_code_size); + if (_adapter_code == NULL) + vm_exit_out_of_memory(_adapter_code_size, "CodeCache: no room for MethodHandles adapters"); + CodeBuffer code(_adapter_code->instructions_begin(), _adapter_code->instructions_size()); + + MethodHandlesAdapterGenerator g(&code); + g.generate(); +} + + +//------------------------------------------------------------------------------ +// MethodHandlesAdapterGenerator::generate +// +void MethodHandlesAdapterGenerator::generate() { + // Generate generic method handle adapters. + for (MethodHandles::EntryKind ek = MethodHandles::_EK_FIRST; + ek < MethodHandles::_EK_LIMIT; + ek = MethodHandles::EntryKind(1 + (int)ek)) { + StubCodeMark mark(this, "MethodHandle", MethodHandles::entry_name(ek)); + MethodHandles::generate_method_handle_stub(_masm, ek); + } +} + + void MethodHandles::set_enabled(bool z) { if (_enabled != z) { guarantee(z && EnableMethodHandles, "can only enable once, and only if -XX:+EnableMethodHandles"); diff -r cdeb352c6bbe -r 47ecd86932ce hotspot/src/share/vm/prims/methodHandles.hpp --- a/hotspot/src/share/vm/prims/methodHandles.hpp Thu Mar 11 05:09:20 2010 -0800 +++ b/hotspot/src/share/vm/prims/methodHandles.hpp Tue Mar 16 11:52:17 2010 +0100 @@ -115,6 +115,10 @@ static const char* _entry_names[_EK_LIMIT+1]; static jobject _raise_exception_method; + // Adapters. + static MethodHandlesAdapterBlob* _adapter_code; + static int _adapter_code_size; + static bool ek_valid(EntryKind ek) { return (uint)ek < (uint)_EK_LIMIT; } static bool conv_op_valid(int op) { return (uint)op < (uint)CONV_OP_LIMIT; } @@ -230,7 +234,10 @@ // bit values for suppress argument to expand_MemberName: enum { _suppress_defc = 1, _suppress_name = 2, _suppress_type = 4 }; - // called from InterpreterGenerator and StubGenerator + // Generate MethodHandles adapters. + static void generate_adapters(); + + // Called from InterpreterGenerator and MethodHandlesAdapterGenerator. static address generate_method_handle_interpreter_entry(MacroAssembler* _masm); static void generate_method_handle_stub(MacroAssembler* _masm, EntryKind ek); @@ -447,3 +454,14 @@ address MethodHandles::from_compiled_entry(EntryKind ek) { return entry(ek)->from_compiled_entry(); } address MethodHandles::from_interpreted_entry(EntryKind ek) { return entry(ek)->from_interpreted_entry(); } + + +//------------------------------------------------------------------------------ +// MethodHandlesAdapterGenerator +// +class MethodHandlesAdapterGenerator : public StubCodeGenerator { +public: + MethodHandlesAdapterGenerator(CodeBuffer* code) : StubCodeGenerator(code) {} + + void generate(); +}; diff -r cdeb352c6bbe -r 47ecd86932ce hotspot/src/share/vm/runtime/init.cpp --- a/hotspot/src/share/vm/runtime/init.cpp Thu Mar 11 05:09:20 2010 -0800 +++ b/hotspot/src/share/vm/runtime/init.cpp Tue Mar 16 11:52:17 2010 +0100 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2010 Sun Microsystems, Inc. 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 @@ -118,6 +118,9 @@ javaClasses_init(); // must happen after vtable initialization stubRoutines_init2(); // note: StubRoutines need 2-phase init + // Generate MethodHandles adapters. + MethodHandles::generate_adapters(); + // Although we'd like to, we can't easily do a heap verify // here because the main thread isn't yet a JavaThread, so // its TLAB may not be made parseable from the usual interfaces. diff -r cdeb352c6bbe -r 47ecd86932ce hotspot/src/share/vm/runtime/sharedRuntime.cpp --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp Thu Mar 11 05:09:20 2010 -0800 +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Tue Mar 16 11:52:17 2010 +0100 @@ -582,7 +582,7 @@ // 3. Implict null exception in nmethod if (!cb->is_nmethod()) { - guarantee(cb->is_adapter_blob(), + guarantee(cb->is_adapter_blob() || cb->is_method_handles_adapter_blob(), "exception happened outside interpreter, nmethods and vtable stubs (1)"); // There is no handler here, so we will simply unwind. return StubRoutines::throw_NullPointerException_at_call_entry(); @@ -2079,7 +2079,6 @@ // --------------------------------------------------------------------------- // Implementation of AdapterHandlerLibrary -const char* AdapterHandlerEntry::name = "I2C/C2I adapters"; AdapterHandlerTable* AdapterHandlerLibrary::_adapters = NULL; AdapterHandlerEntry* AdapterHandlerLibrary::_abstract_method_handler = NULL; const int AdapterHandlerLibrary_size = 16*K; @@ -2131,7 +2130,7 @@ ResourceMark rm; NOT_PRODUCT(int code_size); - BufferBlob *B = NULL; + AdapterBlob* B = NULL; AdapterHandlerEntry* entry = NULL; AdapterFingerPrint* fingerprint = NULL; { @@ -2181,7 +2180,7 @@ // Create I2C & C2I handlers - BufferBlob* buf = buffer_blob(); // the temporary code buffer in CodeCache + BufferBlob* buf = buffer_blob(); // the temporary code buffer in CodeCache if (buf != NULL) { CodeBuffer buffer(buf->instructions_begin(), buf->instructions_size()); short buffer_locs[20]; @@ -2210,7 +2209,7 @@ } #endif - B = BufferBlob::create(AdapterHandlerEntry::name, &buffer); + B = AdapterBlob::create(&buffer); NOT_PRODUCT(code_size = buffer.code_size()); } if (B == NULL) { @@ -2242,7 +2241,7 @@ jio_snprintf(blob_id, sizeof(blob_id), "%s(%s)@" PTR_FORMAT, - AdapterHandlerEntry::name, + B->name(), fingerprint->as_string(), B->instructions_begin()); VTune::register_stub(blob_id, B->instructions_begin(), B->instructions_end()); diff -r cdeb352c6bbe -r 47ecd86932ce hotspot/src/share/vm/runtime/sharedRuntime.hpp --- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp Thu Mar 11 05:09:20 2010 -0800 +++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp Tue Mar 16 11:52:17 2010 +0100 @@ -567,9 +567,6 @@ AdapterHandlerEntry(); public: - // The name we give all buffer blobs - static const char* name; - address get_i2c_entry() { return _i2c_entry; } address get_c2i_entry() { return _c2i_entry; } address get_c2i_unverified_entry() { return _c2i_unverified_entry; }