diff --git a/src/cpu/sparc/vm/stubRoutines_sparc.hpp b/src/cpu/sparc/vm/stubRoutines_sparc.hpp index 6b23258ffa25b72cb45bb2645a6f8e3ed5b0e2de..b3a2618d0839e6d7a305bfbdcbc8ec38643e0873 100644 --- a/src/cpu/sparc/vm/stubRoutines_sparc.hpp +++ b/src/cpu/sparc/vm/stubRoutines_sparc.hpp @@ -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 @@ static bool returns_to_call_stub(address return_pc) { 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 --git a/src/cpu/x86/vm/stubGenerator_x86_32.cpp b/src/cpu/x86/vm/stubGenerator_x86_32.cpp index e8276e5188ffb557dce542dc4ec6145fe308df5f..1d97193194088f909b879d9d4b131873ccd6cd9a 100644 --- a/src/cpu/x86/vm/stubGenerator_x86_32.cpp +++ b/src/cpu/x86/vm/stubGenerator_x86_32.cpp @@ -2276,16 +2276,6 @@ class StubGenerator: public StubCodeGenerator { // 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 --git a/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/src/cpu/x86/vm/stubGenerator_x86_64.cpp index 516a7826a92406239cf195bf94cfd0a79411f354..5417eb160cb0a19147477d1942b54cb7438133d2 100644 --- a/src/cpu/x86/vm/stubGenerator_x86_64.cpp +++ b/src/cpu/x86/vm/stubGenerator_x86_64.cpp @@ -3009,16 +3009,6 @@ class StubGenerator: public StubCodeGenerator { // 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 --git a/src/cpu/x86/vm/stubRoutines_x86_32.hpp b/src/cpu/x86/vm/stubRoutines_x86_32.hpp index 57e75534fce598d29b6052cd66024066bfa62586..9fa4b048f1b0dcbd9f5ecb557d371b91679ba743 100644 --- a/src/cpu/x86/vm/stubRoutines_x86_32.hpp +++ b/src/cpu/x86/vm/stubRoutines_x86_32.hpp @@ -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 @@ enum platform_dependent_constants { 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 --git a/src/cpu/x86/vm/stubRoutines_x86_64.hpp b/src/cpu/x86/vm/stubRoutines_x86_64.hpp index 7cf06f479ff7ad29a743fd8e774e5ef41bd07b81..6772eb3babb32cc05c0a4f6510d9641a0e02ff74 100644 --- a/src/cpu/x86/vm/stubRoutines_x86_64.hpp +++ b/src/cpu/x86/vm/stubRoutines_x86_64.hpp @@ -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 --git a/src/share/vm/code/codeBlob.cpp b/src/share/vm/code/codeBlob.cpp index 4ccc377a308d6fa29b248cccc581a34efdf28528..d8471b98f1ffb39aa13f01ffaf19530f61170ca3 100644 --- a/src/share/vm/code/codeBlob.cpp +++ b/src/share/vm/code/codeBlob.cpp @@ -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 @@ BufferBlob* BufferBlob::create(const char* name, int buffer_size) { 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 @@ BufferBlob* BufferBlob::create(const char* name, CodeBuffer* cb) { 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 @@ void BufferBlob::free( BufferBlob *blob ) { 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 --git a/src/share/vm/code/codeBlob.hpp b/src/share/vm/code/codeBlob.hpp index bbd430a14c6e1d61e9a5063dbf4ffefdc73b00ed..0c9e43c84222a6877172adc992da4d0ffd72fdc6 100644 --- a/src/share/vm/code/codeBlob.hpp +++ b/src/share/vm/code/codeBlob.hpp @@ -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 @@ class CodeBlob VALUE_OBJ_CLASS_SPEC { 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 CodeBlob VALUE_OBJ_CLASS_SPEC { 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 @@ class BufferBlob: public CodeBlob { 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 */ } @@ -254,6 +257,40 @@ class BufferBlob: public CodeBlob { }; +//---------------------------------------------------------------------------------------------------- +// 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 diff --git a/src/share/vm/includeDB_core b/src/share/vm/includeDB_core index 557db70983b3d7b3a4ec836b0dbf6af54f157995..c0dec44d773d9e3259ce6d9d44edf0ffc54d043c 100644 --- a/src/share/vm/includeDB_core +++ b/src/share/vm/includeDB_core @@ -2017,6 +2017,7 @@ init.cpp handles.inline.hpp 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 methodHandles.hpp 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 --git a/src/share/vm/prims/methodHandles.cpp b/src/share/vm/prims/methodHandles.cpp index 038bb2fa55a5cdac383a3b6ec1d2317b17f0dd86..4131f0f34b877e428ade6fc7fec82d3a705852d3 100644 --- a/src/share/vm/prims/methodHandles.cpp +++ b/src/share/vm/prims/methodHandles.cpp @@ -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 @@ const char* MethodHandles::_entry_names[_EK_LIMIT+1] = { 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 @@ bool MethodHandles::spot_check_entry_names() { } #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 --git a/src/share/vm/prims/methodHandles.hpp b/src/share/vm/prims/methodHandles.hpp index fea29650b5cfb95108622ff79d3f8f15dac9ea2d..1bbf82c41ec0ce4032df33240f853a5e74e4f5ef 100644 --- a/src/share/vm/prims/methodHandles.hpp +++ b/src/share/vm/prims/methodHandles.hpp @@ -115,6 +115,10 @@ class MethodHandles: AllStatic { 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 @@ class MethodHandles: AllStatic { // 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 @@ class MethodHandleEntry { 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 --git a/src/share/vm/runtime/init.cpp b/src/share/vm/runtime/init.cpp index 3f470e3ed9a9313235f6bede892ce35463c8b7bc..0ab624e691dec71bb7e9dac8367fe461cb24be92 100644 --- a/src/share/vm/runtime/init.cpp +++ b/src/share/vm/runtime/init.cpp @@ -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 @@ jint init_globals() { 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 --git a/src/share/vm/runtime/sharedRuntime.cpp b/src/share/vm/runtime/sharedRuntime.cpp index 0e465e46cbe57109b9e0f80826bdb8cbc1c1aa72..d09579b7709ff77962a1e6febd18fe55e5e7aafc 100644 --- a/src/share/vm/runtime/sharedRuntime.cpp +++ b/src/share/vm/runtime/sharedRuntime.cpp @@ -582,7 +582,7 @@ address SharedRuntime::continuation_for_implicit_exception(JavaThread* thread, // 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 @@ class AdapterHandlerTableIterator : public StackObj { // --------------------------------------------------------------------------- // 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 @@ AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(methodHandle method) { ResourceMark rm; NOT_PRODUCT(int code_size); - BufferBlob *B = NULL; + AdapterBlob* B = NULL; AdapterHandlerEntry* entry = NULL; AdapterFingerPrint* fingerprint = NULL; { @@ -2181,7 +2180,7 @@ AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(methodHandle method) { // 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 @@ AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(methodHandle method) { } #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 @@ AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(methodHandle method) { 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 --git a/src/share/vm/runtime/sharedRuntime.hpp b/src/share/vm/runtime/sharedRuntime.hpp index a540065c20d1efae4ffb7878336cb272261d3964..c2348c220226673d24f3ef53258fa59341831594 100644 --- a/src/share/vm/runtime/sharedRuntime.hpp +++ b/src/share/vm/runtime/sharedRuntime.hpp @@ -567,9 +567,6 @@ class AdapterHandlerEntry : public BasicHashtableEntry { 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; }