From 83f1d02a67d75fc995ee5e6aeddf6e4dd71f23d6 Mon Sep 17 00:00:00 2001 From: John Cuthbertson Date: Tue, 27 Apr 2010 18:13:47 -0700 Subject: [PATCH 01/54] 6946056: assert((intptr_t) sp()<=(intptr_t) result,"result must>=than stack pointer"), frame_x86.cpp:295 Frame::interpreter_frame_monitor_end() will spuriously assert for a frame that spans 0x80000000. Cast values to intptr_t* (rather than intptr_t) so that an unsigned pointer compare is performed. Reviewed-by: never, jcoomes, pbk --- hotspot/src/cpu/x86/vm/frame_x86.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hotspot/src/cpu/x86/vm/frame_x86.cpp b/hotspot/src/cpu/x86/vm/frame_x86.cpp index 01f49e3dba8..d219e32ef30 100644 --- a/hotspot/src/cpu/x86/vm/frame_x86.cpp +++ b/hotspot/src/cpu/x86/vm/frame_x86.cpp @@ -291,8 +291,8 @@ BasicObjectLock* frame::interpreter_frame_monitor_begin() const { BasicObjectLock* frame::interpreter_frame_monitor_end() const { BasicObjectLock* result = (BasicObjectLock*) *addr_at(interpreter_frame_monitor_block_top_offset); // make sure the pointer points inside the frame - assert((intptr_t) fp() > (intptr_t) result, "result must < than frame pointer"); - assert((intptr_t) sp() <= (intptr_t) result, "result must >= than stack pointer"); + assert(sp() <= (intptr_t*) result, "monitor end should be above the stack pointer"); + assert((intptr_t*) result < fp(), "monitor end should be strictly below the frame pointer"); return result; } From 7e76feaf427ccff82a99fd38c26a402edf7ed626 Mon Sep 17 00:00:00 2001 From: John Coomes Date: Sun, 11 Oct 2009 16:19:25 -0700 Subject: [PATCH 02/54] 6888953: some calls to function-like macros are missing semicolons Reviewed-by: pbk, kvn --- hotspot/src/cpu/sparc/vm/assembler_sparc.cpp | 2 +- hotspot/src/cpu/x86/vm/assembler_x86.cpp | 2 +- hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp | 2 +- hotspot/src/share/vm/adlc/output_c.cpp | 4 ++-- hotspot/src/share/vm/classfile/dictionary.cpp | 2 +- hotspot/src/share/vm/classfile/loaderConstraints.cpp | 2 +- hotspot/src/share/vm/classfile/resolutionErrors.cpp | 2 +- hotspot/src/share/vm/code/nmethod.cpp | 3 ++- hotspot/src/share/vm/compiler/compileBroker.hpp | 2 +- hotspot/src/share/vm/compiler/compileLog.cpp | 2 +- .../concurrentMarkSweep/binaryTreeDictionary.cpp | 2 +- .../src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp | 2 +- hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp | 2 +- .../share/vm/gc_implementation/parNew/asParNewGeneration.cpp | 2 +- .../vm/gc_implementation/parallelScavenge/asPSYoungGen.cpp | 4 ++-- .../share/vm/gc_implementation/parallelScavenge/psOldGen.hpp | 2 +- .../gc_implementation/parallelScavenge/psParallelCompact.cpp | 2 +- .../vm/gc_implementation/parallelScavenge/psYoungGen.cpp | 4 ++-- hotspot/src/share/vm/interpreter/oopMapCache.cpp | 4 ++-- hotspot/src/share/vm/interpreter/templateInterpreter.cpp | 2 +- hotspot/src/share/vm/memory/blockOffsetTable.cpp | 2 +- hotspot/src/share/vm/memory/heapInspection.cpp | 2 +- hotspot/src/share/vm/oops/generateOopMap.cpp | 2 +- hotspot/src/share/vm/oops/klassVtable.cpp | 2 +- hotspot/src/share/vm/opto/node.cpp | 2 +- hotspot/src/share/vm/opto/output.cpp | 2 +- hotspot/src/share/vm/opto/phaseX.hpp | 2 +- hotspot/src/share/vm/prims/forte.cpp | 2 +- hotspot/src/share/vm/runtime/frame.cpp | 2 +- hotspot/src/share/vm/runtime/vmThread.cpp | 2 +- hotspot/src/share/vm/utilities/xmlstream.cpp | 2 +- 31 files changed, 36 insertions(+), 35 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp index e4799550fd8..d61ce6af305 100644 --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp @@ -4082,7 +4082,7 @@ static int EnqueueCodeSize = 128 DEBUG_ONLY( + 256); // Instructions? // make it work. static void check_index(int ind) { assert(0 <= ind && ind <= 64*K && ((ind % oopSize) == 0), - "Invariants.") + "Invariants."); } static void generate_satb_log_enqueue(bool with_frame) { diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.cpp b/hotspot/src/cpu/x86/vm/assembler_x86.cpp index 72086baee03..9038c3ccaba 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp @@ -7975,7 +7975,7 @@ class FPU_State { case 2: return "special"; case 3: return "empty"; } - ShouldNotReachHere() + ShouldNotReachHere(); return NULL; } diff --git a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp index 966a01d8624..88c1e1204bd 100644 --- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp @@ -2844,7 +2844,7 @@ void LIR_Assembler::emit_static_call_stub() { // On 64bit this will die since it will take a movq & jmp, must be only a jmp __ jump(RuntimeAddress(__ pc())); - assert(__ offset() - start <= call_stub_size, "stub too big") + assert(__ offset() - start <= call_stub_size, "stub too big"); __ end_a_stub(); } diff --git a/hotspot/src/share/vm/adlc/output_c.cpp b/hotspot/src/share/vm/adlc/output_c.cpp index 1e9fd56ff3a..580a022ad35 100644 --- a/hotspot/src/share/vm/adlc/output_c.cpp +++ b/hotspot/src/share/vm/adlc/output_c.cpp @@ -721,8 +721,8 @@ void ArchDesc::build_pipe_classes(FILE *fp_cpp) { fprintf(fp_cpp, " }\n"); fprintf(fp_cpp, "#endif\n\n"); #endif - fprintf(fp_cpp, " assert(this, \"NULL pipeline info\")\n"); - fprintf(fp_cpp, " assert(pred, \"NULL predecessor pipline info\")\n\n"); + fprintf(fp_cpp, " assert(this, \"NULL pipeline info\");\n"); + fprintf(fp_cpp, " assert(pred, \"NULL predecessor pipline info\");\n\n"); fprintf(fp_cpp, " if (pred->hasFixedLatency())\n return (pred->fixedLatency());\n\n"); fprintf(fp_cpp, " // If this is not an operand, then assume a dependence with 0 latency\n"); fprintf(fp_cpp, " if (opnd > _read_stage_count)\n return (0);\n\n"); diff --git a/hotspot/src/share/vm/classfile/dictionary.cpp b/hotspot/src/share/vm/classfile/dictionary.cpp index 5bf9132f4ce..3367a318483 100644 --- a/hotspot/src/share/vm/classfile/dictionary.cpp +++ b/hotspot/src/share/vm/classfile/dictionary.cpp @@ -127,7 +127,7 @@ void DictionaryEntry::add_protection_domain(oop protection_domain) { bool Dictionary::do_unloading(BoolObjectClosure* is_alive) { - assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint") + assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); bool class_was_unloaded = false; int index = 0; // Defined here for portability! Do not move diff --git a/hotspot/src/share/vm/classfile/loaderConstraints.cpp b/hotspot/src/share/vm/classfile/loaderConstraints.cpp index d4df39e4034..c8c8955e276 100644 --- a/hotspot/src/share/vm/classfile/loaderConstraints.cpp +++ b/hotspot/src/share/vm/classfile/loaderConstraints.cpp @@ -103,7 +103,7 @@ LoaderConstraintEntry** LoaderConstraintTable::find_loader_constraint( void LoaderConstraintTable::purge_loader_constraints(BoolObjectClosure* is_alive) { - assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint") + assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); // Remove unloaded entries from constraint table for (int index = 0; index < table_size(); index++) { LoaderConstraintEntry** p = bucket_addr(index); diff --git a/hotspot/src/share/vm/classfile/resolutionErrors.cpp b/hotspot/src/share/vm/classfile/resolutionErrors.cpp index 397981540df..962fc985670 100644 --- a/hotspot/src/share/vm/classfile/resolutionErrors.cpp +++ b/hotspot/src/share/vm/classfile/resolutionErrors.cpp @@ -102,7 +102,7 @@ void ResolutionErrorTable::always_strong_classes_do(OopClosure* blk) { // Remove unloaded entries from the table void ResolutionErrorTable::purge_resolution_errors(BoolObjectClosure* is_alive) { - assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint") + assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); for (int i = 0; i < table_size(); i++) { for (ResolutionErrorEntry** p = bucket_addr(i); *p != NULL; ) { ResolutionErrorEntry* entry = *p; diff --git a/hotspot/src/share/vm/code/nmethod.cpp b/hotspot/src/share/vm/code/nmethod.cpp index 946e5f67aed..7e0a86915cf 100644 --- a/hotspot/src/share/vm/code/nmethod.cpp +++ b/hotspot/src/share/vm/code/nmethod.cpp @@ -1534,7 +1534,8 @@ void nmethod::do_unloading(BoolObjectClosure* is_alive, } } ic->set_to_clean(); - assert(ic->cached_oop() == NULL, "cached oop in IC should be cleared") + assert(ic->cached_oop() == NULL, + "cached oop in IC should be cleared"); } } } diff --git a/hotspot/src/share/vm/compiler/compileBroker.hpp b/hotspot/src/share/vm/compiler/compileBroker.hpp index 83383378fa6..e615858ffdd 100644 --- a/hotspot/src/share/vm/compiler/compileBroker.hpp +++ b/hotspot/src/share/vm/compiler/compileBroker.hpp @@ -310,7 +310,7 @@ class CompileBroker: AllStatic { static AbstractCompiler* compiler(int level ) { if (level == CompLevel_fast_compile) return _compilers[0]; - assert(level == CompLevel_highest_tier, "what level?") + assert(level == CompLevel_highest_tier, "what level?"); return _compilers[1]; } diff --git a/hotspot/src/share/vm/compiler/compileLog.cpp b/hotspot/src/share/vm/compiler/compileLog.cpp index e5cf481e985..e375521c7a3 100644 --- a/hotspot/src/share/vm/compiler/compileLog.cpp +++ b/hotspot/src/share/vm/compiler/compileLog.cpp @@ -68,7 +68,7 @@ static const char* split_attrs(const char* &kind, char* buffer) { return attrs; } else { // park it in the buffer, so we can put a null on the end - assert(!(kind >= buffer && kind < buffer+100), "not obviously in buffer") + assert(!(kind >= buffer && kind < buffer+100), "not obviously in buffer"); int klen = attrs - kind; strncpy(buffer, kind, klen); buffer[klen] = 0; diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/binaryTreeDictionary.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/binaryTreeDictionary.cpp index ec4caa22fc6..90c3f146e1d 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/binaryTreeDictionary.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/binaryTreeDictionary.cpp @@ -118,7 +118,7 @@ TreeList* TreeList::removeChunkReplaceIfNeeded(TreeChunk* tc) { // TreeList from the first chunk to the next chunk and update all // the TreeList pointers in the chunks in the list. if (nextTC == NULL) { - assert(prevFC == NULL, "Not last chunk in the list") + assert(prevFC == NULL, "Not last chunk in the list"); set_tail(NULL); set_head(NULL); } else { diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp index 978367af7ae..32baaa97016 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp @@ -517,7 +517,7 @@ void G1BlockOffsetArray::alloc_block_work2(HeapWord** threshold_, size_t* index_ assert(blk_start != NULL && blk_end > blk_start, "phantom block"); assert(blk_end > threshold, "should be past threshold"); - assert(blk_start <= threshold, "blk_start should be at or before threshold") + assert(blk_start <= threshold, "blk_start should be at or before threshold"); assert(pointer_delta(threshold, blk_start) <= N_words, "offset should be <= BlockOffsetSharedArray::N"); assert(Universe::heap()->is_in_reserved(blk_start), diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 2881eb6f335..017102285ee 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -4965,7 +4965,7 @@ void G1CollectedHeap::tear_down_region_lists() { MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag); while (pop_unclean_region_list_locked() != NULL) ; assert(_unclean_region_list.hd() == NULL && _unclean_region_list.sz() == 0, - "Postconditions of loop.") + "Postconditions of loop."); while (pop_free_region_list_locked() != NULL) ; assert(_free_region_list == NULL, "Postcondition of loop."); if (_free_region_list_size != 0) { diff --git a/hotspot/src/share/vm/gc_implementation/parNew/asParNewGeneration.cpp b/hotspot/src/share/vm/gc_implementation/parNew/asParNewGeneration.cpp index 224e2dcefa7..262c6f729f8 100644 --- a/hotspot/src/share/vm/gc_implementation/parNew/asParNewGeneration.cpp +++ b/hotspot/src/share/vm/gc_implementation/parNew/asParNewGeneration.cpp @@ -325,7 +325,7 @@ void ASParNewGeneration::resize_spaces(size_t requested_eden_size, eden_size = align_size_down(eden_size, alignment); eden_end = eden_start + eden_size; - assert(eden_end >= eden_start, "addition overflowed") + assert(eden_end >= eden_start, "addition overflowed"); // To may resize into from space as long as it is clear of live data. // From space must remain page aligned, though, so we need to do some diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/asPSYoungGen.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/asPSYoungGen.cpp index f4740bf3f27..d29bf78a305 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/asPSYoungGen.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/asPSYoungGen.cpp @@ -326,7 +326,7 @@ void ASPSYoungGen::resize_spaces(size_t requested_eden_size, } eden_end = eden_start + eden_size; - assert(eden_end >= eden_start, "addition overflowed") + assert(eden_end >= eden_start, "addition overflowed"); // To may resize into from space as long as it is clear of live data. // From space must remain page aligned, though, so we need to do some @@ -413,7 +413,7 @@ void ASPSYoungGen::resize_spaces(size_t requested_eden_size, pointer_delta(to_start, eden_start, sizeof(char))); } eden_end = eden_start + eden_size; - assert(eden_end >= eden_start, "addition overflowed") + assert(eden_end >= eden_start, "addition overflowed"); // Don't let eden shrink down to 0 or less. eden_end = MAX2(eden_end, eden_start + alignment); diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psOldGen.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psOldGen.hpp index f7fadd78bd0..d66521d1eae 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psOldGen.hpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psOldGen.hpp @@ -65,7 +65,7 @@ class PSOldGen : public CHeapObj { // and releasing the heap lock, which is held during gc's anyway. This method is not // safe for use at the same time as allocate_noexpand()! HeapWord* cas_allocate_noexpand(size_t word_size) { - assert(SafepointSynchronize::is_at_safepoint(), "Must only be called at safepoint") + assert(SafepointSynchronize::is_at_safepoint(), "Must only be called at safepoint"); HeapWord* res = object_space()->cas_allocate(word_size); if (res != NULL) { _start_array.allocate_block(res); diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp index d3eba4d3bb4..56d91d65331 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp @@ -3277,7 +3277,7 @@ void PSParallelCompact::fill_region(ParCompactionManager* cm, size_t region_idx) if (status == ParMarkBitMap::incomplete) { // The last obj that starts in the source region does not end in the // region. - assert(closure.source() < end_addr, "sanity") + assert(closure.source() < end_addr, "sanity"); HeapWord* const obj_beg = closure.source(); HeapWord* const range_end = MIN2(obj_beg + closure.words_remaining(), src_space_top); diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.cpp index d78fbae12de..498cf7c082e 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.cpp @@ -521,7 +521,7 @@ void PSYoungGen::resize_spaces(size_t requested_eden_size, } eden_end = eden_start + eden_size; - assert(eden_end >= eden_start, "addition overflowed") + assert(eden_end >= eden_start, "addition overflowed"); // To may resize into from space as long as it is clear of live data. // From space must remain page aligned, though, so we need to do some @@ -605,7 +605,7 @@ void PSYoungGen::resize_spaces(size_t requested_eden_size, pointer_delta(to_start, eden_start, sizeof(char))); } eden_end = eden_start + eden_size; - assert(eden_end >= eden_start, "addition overflowed") + assert(eden_end >= eden_start, "addition overflowed"); // Could choose to not let eden shrink // to_start = MAX2(to_start, eden_end); diff --git a/hotspot/src/share/vm/interpreter/oopMapCache.cpp b/hotspot/src/share/vm/interpreter/oopMapCache.cpp index 170a73f9ce9..6c7bf00e79f 100644 --- a/hotspot/src/share/vm/interpreter/oopMapCache.cpp +++ b/hotspot/src/share/vm/interpreter/oopMapCache.cpp @@ -224,8 +224,8 @@ void InterpreterOopMap::verify() { // If we are doing mark sweep _method may not have a valid header // $$$ This used to happen only for m/s collections; we might want to // think of an appropriate generalization of this distinction. - guarantee(Universe::heap()->is_gc_active() || - _method->is_oop_or_null(), "invalid oop in oopMapCache") + guarantee(Universe::heap()->is_gc_active() || _method->is_oop_or_null(), + "invalid oop in oopMapCache"); } #ifdef ENABLE_ZAP_DEAD_LOCALS diff --git a/hotspot/src/share/vm/interpreter/templateInterpreter.cpp b/hotspot/src/share/vm/interpreter/templateInterpreter.cpp index e617623506b..4cfc1a9c45f 100644 --- a/hotspot/src/share/vm/interpreter/templateInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/templateInterpreter.cpp @@ -457,7 +457,7 @@ void TemplateInterpreterGenerator::set_entry_points(Bytecodes::Code code) { void TemplateInterpreterGenerator::set_wide_entry_point(Template* t, address& wep) { assert(t->is_valid(), "template must exist"); - assert(t->tos_in() == vtos, "only vtos tos_in supported for wide instructions") + assert(t->tos_in() == vtos, "only vtos tos_in supported for wide instructions"); wep = __ pc(); generate_and_dispatch(t); } diff --git a/hotspot/src/share/vm/memory/blockOffsetTable.cpp b/hotspot/src/share/vm/memory/blockOffsetTable.cpp index 078dc413537..d49df66ff50 100644 --- a/hotspot/src/share/vm/memory/blockOffsetTable.cpp +++ b/hotspot/src/share/vm/memory/blockOffsetTable.cpp @@ -689,7 +689,7 @@ void BlockOffsetArrayContigSpace::alloc_block_work(HeapWord* blk_start, assert(blk_end > _next_offset_threshold, "should be past threshold"); assert(blk_start <= _next_offset_threshold, - "blk_start should be at or before threshold") + "blk_start should be at or before threshold"); assert(pointer_delta(_next_offset_threshold, blk_start) <= N_words, "offset should be <= BlockOffsetSharedArray::N"); assert(Universe::heap()->is_in_reserved(blk_start), diff --git a/hotspot/src/share/vm/memory/heapInspection.cpp b/hotspot/src/share/vm/memory/heapInspection.cpp index 4216b1301dd..164ae6a3a71 100644 --- a/hotspot/src/share/vm/memory/heapInspection.cpp +++ b/hotspot/src/share/vm/memory/heapInspection.cpp @@ -315,7 +315,7 @@ class FindInstanceClosure : public ObjectClosure { void HeapInspection::find_instances_at_safepoint(klassOop k, GrowableArray* result) { assert(SafepointSynchronize::is_at_safepoint(), "all threads are stopped"); - assert(Heap_lock->is_locked(), "should have the Heap_lock") + assert(Heap_lock->is_locked(), "should have the Heap_lock"); // Ensure that the heap is parsable Universe::heap()->ensure_parsability(false); // no need to retire TALBs diff --git a/hotspot/src/share/vm/oops/generateOopMap.cpp b/hotspot/src/share/vm/oops/generateOopMap.cpp index 845f1ec22b6..093c084e9f5 100644 --- a/hotspot/src/share/vm/oops/generateOopMap.cpp +++ b/hotspot/src/share/vm/oops/generateOopMap.cpp @@ -807,7 +807,7 @@ void GenerateOopMap::set_var(int localNo, CellTypeState cts) { } CellTypeState GenerateOopMap::get_var(int localNo) { - assert(localNo < _max_locals + _nof_refval_conflicts, "variable read error") + assert(localNo < _max_locals + _nof_refval_conflicts, "variable read error"); if (localNo < 0 || localNo > _max_locals) { verify_error("variable read error: r%d", localNo); return valCTS; // just to pick something; diff --git a/hotspot/src/share/vm/oops/klassVtable.cpp b/hotspot/src/share/vm/oops/klassVtable.cpp index 4afcf3e41bf..96651c37d56 100644 --- a/hotspot/src/share/vm/oops/klassVtable.cpp +++ b/hotspot/src/share/vm/oops/klassVtable.cpp @@ -899,7 +899,7 @@ void klassItable::initialize_itable_for_interface(int method_table_offset, Klass int nof_methods = methods()->length(); HandleMark hm; KlassHandle klass = _klass; - assert(nof_methods > 0, "at least one method must exist for interface to be in vtable") + assert(nof_methods > 0, "at least one method must exist for interface to be in vtable"); Handle interface_loader (THREAD, instanceKlass::cast(interf_h())->class_loader()); int ime_num = 0; diff --git a/hotspot/src/share/vm/opto/node.cpp b/hotspot/src/share/vm/opto/node.cpp index f7d71d17234..e45de385b50 100644 --- a/hotspot/src/share/vm/opto/node.cpp +++ b/hotspot/src/share/vm/opto/node.cpp @@ -1188,7 +1188,7 @@ static void kill_dead_code( Node *dead, PhaseIterGVN *igvn ) { Node* use = dead->last_out(k); igvn->hash_delete(use); // Yank from hash table prior to mod if (use->in(0) == dead) { // Found another dead node - assert (!use->is_Con(), "Control for Con node should be Root node.") + assert (!use->is_Con(), "Control for Con node should be Root node."); use->set_req(0, top); // Cut dead edge to prevent processing nstack.push(use); // the dead node again. } else { // Else found a not-dead user diff --git a/hotspot/src/share/vm/opto/output.cpp b/hotspot/src/share/vm/opto/output.cpp index 5e371e27f0c..853ed4700fb 100644 --- a/hotspot/src/share/vm/opto/output.cpp +++ b/hotspot/src/share/vm/opto/output.cpp @@ -1231,7 +1231,7 @@ void Compile::Fill_buffer() { if (is_sfn && !is_mcall && padding == 0 && current_offset == last_call_offset ) { padding = nop_size; } - assert( labels_not_set || padding == 0, "instruction should already be aligned") + assert( labels_not_set || padding == 0, "instruction should already be aligned"); if(padding > 0) { assert((padding % nop_size) == 0, "padding is not a multiple of NOP size"); diff --git a/hotspot/src/share/vm/opto/phaseX.hpp b/hotspot/src/share/vm/opto/phaseX.hpp index 33ff56f0ee4..37c4e57f4a7 100644 --- a/hotspot/src/share/vm/opto/phaseX.hpp +++ b/hotspot/src/share/vm/opto/phaseX.hpp @@ -310,7 +310,7 @@ public: void dump_nodes_and_types_recur( const Node *n, uint depth, bool only_ctrl, VectorSet &visited); uint _count_progress; // For profiling, count transforms that make progress - void set_progress() { ++_count_progress; assert( allow_progress(),"No progress allowed during verification") } + void set_progress() { ++_count_progress; assert( allow_progress(),"No progress allowed during verification"); } void clear_progress() { _count_progress = 0; } uint made_progress() const { return _count_progress; } diff --git a/hotspot/src/share/vm/prims/forte.cpp b/hotspot/src/share/vm/prims/forte.cpp index 4b0596c1fe3..0260414c2fe 100644 --- a/hotspot/src/share/vm/prims/forte.cpp +++ b/hotspot/src/share/vm/prims/forte.cpp @@ -647,7 +647,7 @@ void collector_func_load(char* name, void Forte::register_stub(const char* name, address start, address end) { #if !defined(_WINDOWS) && !defined(IA64) assert(pointer_delta(end, start, sizeof(jbyte)) < INT_MAX, - "Code size exceeds maximum range") + "Code size exceeds maximum range"); collector_func_load((char*)name, NULL, NULL, start, pointer_delta(end, start, sizeof(jbyte)), 0, NULL); diff --git a/hotspot/src/share/vm/runtime/frame.cpp b/hotspot/src/share/vm/runtime/frame.cpp index 30782f355c6..1112720d262 100644 --- a/hotspot/src/share/vm/runtime/frame.cpp +++ b/hotspot/src/share/vm/runtime/frame.cpp @@ -844,7 +844,7 @@ class EntryFrameOopFinder: public SignatureInfo { } void oop_at_offset_do(int offset) { - assert (offset >= 0, "illegal offset") + assert (offset >= 0, "illegal offset"); oop* addr = (oop*) _fr->entry_frame_argument_at(offset); _f->do_oop(addr); } diff --git a/hotspot/src/share/vm/runtime/vmThread.cpp b/hotspot/src/share/vm/runtime/vmThread.cpp index 4fec3f983b3..95538a7248a 100644 --- a/hotspot/src/share/vm/runtime/vmThread.cpp +++ b/hotspot/src/share/vm/runtime/vmThread.cpp @@ -106,7 +106,7 @@ VM_Operation* VMOperationQueue::queue_drain(int prio) { // restore queue to empty state _queue[prio]->set_next(_queue[prio]); _queue[prio]->set_prev(_queue[prio]); - assert(queue_empty(prio), "drain corrupted queue") + assert(queue_empty(prio), "drain corrupted queue"); #ifdef DEBUG int len = 0; VM_Operation* cur; diff --git a/hotspot/src/share/vm/utilities/xmlstream.cpp b/hotspot/src/share/vm/utilities/xmlstream.cpp index 3f03a442773..e93949a5deb 100644 --- a/hotspot/src/share/vm/utilities/xmlstream.cpp +++ b/hotspot/src/share/vm/utilities/xmlstream.cpp @@ -328,7 +328,7 @@ void xmlStream::done_raw(const char* kind) { // ------------------------------------------------------------------ void xmlStream::va_done(const char* format, va_list ap) { char buffer[200]; - guarantee(strlen(format) + 10 < sizeof(buffer), "bigger format buffer") + guarantee(strlen(format) + 10 < sizeof(buffer), "bigger format buffer"); const char* kind = format; const char* kind_end = strchr(kind, ' '); size_t kind_len = (kind_end != NULL) ? (kind_end - kind) : strlen(kind); From 50654ebc2b33d3bd8cfa460f88c0beac19aad8dd Mon Sep 17 00:00:00 2001 From: Andreas Kohn Date: Mon, 19 Apr 2010 18:58:31 -0400 Subject: [PATCH 03/54] 6944822: Fix for 6938627 exposes problem with hard-coded buffer sizes Make tmpdir buffer sizes MAX_PATH+1 Reviewed-by: dholmes, coleenp --- hotspot/src/os/linux/vm/attachListener_linux.cpp | 2 +- hotspot/src/os/linux/vm/os_linux.cpp | 2 +- hotspot/src/os/solaris/vm/attachListener_solaris.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hotspot/src/os/linux/vm/attachListener_linux.cpp b/hotspot/src/os/linux/vm/attachListener_linux.cpp index 93a85678688..7999828fa74 100644 --- a/hotspot/src/os/linux/vm/attachListener_linux.cpp +++ b/hotspot/src/os/linux/vm/attachListener_linux.cpp @@ -461,7 +461,7 @@ bool AttachListener::is_init_trigger() { if (init_at_startup() || is_initialized()) { return false; // initialized at startup or already initialized } - char fn[128]; + char fn[PATH_MAX+1]; sprintf(fn, ".attach_pid%d", os::current_process_id()); int ret; struct stat64 st; diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index d38f3866c72..b7d609e315f 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -2305,7 +2305,7 @@ void linux_wrap_code(char* base, size_t size) { return; } - char buf[40]; + char buf[PATH_MAX+1]; int num = Atomic::add(1, &cnt); snprintf(buf, sizeof(buf), "%s/hs-vm-%d-%d", diff --git a/hotspot/src/os/solaris/vm/attachListener_solaris.cpp b/hotspot/src/os/solaris/vm/attachListener_solaris.cpp index c3f73da353c..6ba1a897dff 100644 --- a/hotspot/src/os/solaris/vm/attachListener_solaris.cpp +++ b/hotspot/src/os/solaris/vm/attachListener_solaris.cpp @@ -592,7 +592,7 @@ bool AttachListener::is_init_trigger() { if (init_at_startup() || is_initialized()) { return false; // initialized at startup or already initialized } - char fn[128]; + char fn[PATH_MAX+1]; sprintf(fn, ".attach_pid%d", os::current_process_id()); int ret; struct stat64 st; From ed15f54cfbc4535041f799d2b15770057fc7962c Mon Sep 17 00:00:00 2001 From: Yuka Kamiya Date: Wed, 21 Apr 2010 10:34:56 +0900 Subject: [PATCH 04/54] 6943963: NumericShaper with ARABIC doesn't shape digits correctly after calling another instance Reviewed-by: okutsu --- .../classes/java/awt/font/NumericShaper.java | 8 +- .../java/awt/font/NumericShaper/MTTest.java | 51 +++++---- .../awt/font/NumericShaper/ShapingTest.java | 107 +++++++++++------- 3 files changed, 100 insertions(+), 66 deletions(-) diff --git a/jdk/src/share/classes/java/awt/font/NumericShaper.java b/jdk/src/share/classes/java/awt/font/NumericShaper.java index 75f4dbad751..6aff9cba920 100644 --- a/jdk/src/share/classes/java/awt/font/NumericShaper.java +++ b/jdk/src/share/classes/java/awt/font/NumericShaper.java @@ -1163,8 +1163,14 @@ public final class NumericShaper implements java.io.Serializable { lastkey = newkey; ctxKey = newkey; - if (((mask & EASTERN_ARABIC) != 0) && (ctxKey == ARABIC_KEY || ctxKey == EASTERN_ARABIC_KEY)) { + if (((mask & EASTERN_ARABIC) != 0) && + (ctxKey == ARABIC_KEY || + ctxKey == EASTERN_ARABIC_KEY)) { ctxKey = EASTERN_ARABIC_KEY; + } else if (((mask & ARABIC) != 0) && + (ctxKey == ARABIC_KEY || + ctxKey == EASTERN_ARABIC_KEY)) { + ctxKey = ARABIC_KEY; } else if ((mask & (1<."); + System.err.println(" text = " + given); + System.err.println(" got = " + got); + System.err.println(" expected = " + expected); + } else { + System.out.println("OK with range(s) <" + ranges + ">."); + System.out.println(" text = " + given); + System.out.println(" got = " + got); + System.out.println(" expected = " + expected); } } From f05dd156c2cb16c6c78ccdced90a625f11119c46 Mon Sep 17 00:00:00 2001 From: Pavel Porvatov Date: Wed, 21 Apr 2010 18:12:21 +0400 Subject: [PATCH 05/54] 6945316: The Win32ShellFolderManager2.isFileSystemRoot can throw NPE Reviewed-by: alexp --- .../awt/shell/Win32ShellFolderManager2.java | 11 ++- .../JFileChooser/6945316/bug6945316.java | 74 +++++++++++++++++++ 2 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 jdk/test/javax/swing/JFileChooser/6945316/bug6945316.java diff --git a/jdk/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java b/jdk/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java index b7639fa77bb..1a53198349f 100644 --- a/jdk/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java +++ b/jdk/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java @@ -403,9 +403,14 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { } } String path = dir.getPath(); - return (path.length() == 3 - && path.charAt(1) == ':' - && Arrays.asList(drives.listFiles()).contains(dir)); + + if (path.length() != 3 || path.charAt(1) != ':') { + return false; + } + + File[] files = drives.listFiles(); + + return files != null && Arrays.asList(files).contains(dir); } return false; } diff --git a/jdk/test/javax/swing/JFileChooser/6945316/bug6945316.java b/jdk/test/javax/swing/JFileChooser/6945316/bug6945316.java new file mode 100644 index 00000000000..cc495f7a6db --- /dev/null +++ b/jdk/test/javax/swing/JFileChooser/6945316/bug6945316.java @@ -0,0 +1,74 @@ +/* + * Copyright 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 + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @bug 6945316 + @summary The Win32ShellFolderManager2.isFileSystemRoot can throw NPE + @author Pavel Porvatov + @run main bug6945316 +*/ + +import sun.awt.OSInfo; +import sun.awt.shell.ShellFolder; + +import java.awt.*; +import java.io.File; +import java.util.concurrent.CountDownLatch; + +public class bug6945316 { + public static void main(String[] args) throws Exception { + if (OSInfo.getOSType() != OSInfo.OSType.WINDOWS) { + System.out.println("The test is suitable only for Windows OS. Skipped."); + + return; + } + + // Init toolkit because it shouldn't be interrupted while initialization + Toolkit.getDefaultToolkit(); + + // Init the sun.awt.shell.Win32ShellFolderManager2.drives field + ShellFolder.get("fileChooserComboBoxFolders"); + + // To get NPE the path must obey the following rules: + // path.length() == 3 && path.charAt(1) == ':' + final File tempFile = new File("c:\\"); + + for (int i = 0; i < 10000; i++) { + final CountDownLatch countDownLatch = new CountDownLatch(1); + + final Thread thread = new Thread() { + public void run() { + countDownLatch.countDown(); + + ShellFolder.isFileSystemRoot(tempFile); + } + }; + + thread.start(); + + countDownLatch.await(); + + thread.interrupt(); + } + } +} From 7cc72590c763920d35e8646ec04d00795fd16d0b Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Thu, 22 Apr 2010 12:45:36 +0800 Subject: [PATCH 06/54] 6856069: PrincipalName.clone() does not invoke super.clone() Reviewed-by: chegar --- .../sun/security/krb5/PrincipalName.java | 27 ++++++------ .../sun/security/krb5/ServiceNameClone.java | 41 +++++++++++++++++++ 2 files changed, 55 insertions(+), 13 deletions(-) create mode 100644 jdk/test/sun/security/krb5/ServiceNameClone.java diff --git a/jdk/src/share/classes/sun/security/krb5/PrincipalName.java b/jdk/src/share/classes/sun/security/krb5/PrincipalName.java index 6705fd63e9a..91d5d8bb395 100644 --- a/jdk/src/share/classes/sun/security/krb5/PrincipalName.java +++ b/jdk/src/share/classes/sun/security/krb5/PrincipalName.java @@ -1,5 +1,5 @@ /* - * Portions Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. + * Portions Copyright 2000-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 @@ -101,7 +101,7 @@ public class PrincipalName private Realm nameRealm; // optional; a null realm means use default // Note: the nameRealm is not included in the default ASN.1 encoding - // salt for principal + // cached salt, might be changed by KDC info, not used in clone private String salt = null; protected PrincipalName() { @@ -123,18 +123,19 @@ public class PrincipalName } public Object clone() { - PrincipalName pName = new PrincipalName(); - pName.nameType = nameType; - if (nameStrings != null) { - pName.nameStrings = - new String[nameStrings.length]; - System.arraycopy(nameStrings,0,pName.nameStrings,0, - nameStrings.length); + try { + PrincipalName pName = (PrincipalName) super.clone(); + // Re-assign mutable fields + if (nameStrings != null) { + pName.nameStrings = nameStrings.clone(); + } + if (nameRealm != null) { + pName.nameRealm = (Realm)nameRealm.clone(); + } + return pName; + } catch (CloneNotSupportedException ex) { + throw new AssertionError("Should never happen"); } - if (nameRealm != null) { - pName.nameRealm = (Realm)nameRealm.clone(); - } - return pName; } /* diff --git a/jdk/test/sun/security/krb5/ServiceNameClone.java b/jdk/test/sun/security/krb5/ServiceNameClone.java new file mode 100644 index 00000000000..282712c032a --- /dev/null +++ b/jdk/test/sun/security/krb5/ServiceNameClone.java @@ -0,0 +1,41 @@ +/* + * Copyright 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 + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +/* + * @test + * @bug 6856069 + * @summary PrincipalName.clone() does not invoke super.clone() + */ + +import sun.security.krb5.ServiceName; + +public class ServiceNameClone { + public static void main(String[] args) throws Exception { + ServiceName sn = new ServiceName("me@HERE"); + if (sn.clone().getClass() != ServiceName.class) { + throw new Exception("ServiceName's clone is not a ServiceName"); + } + if (!sn.clone().equals(sn)) { + throw new Exception("ServiceName's clone changed"); + } + } +} From 99196ff9ca212c4e2ae291dac9701e910d34eebd Mon Sep 17 00:00:00 2001 From: John Coomes Date: Thu, 22 Apr 2010 13:23:15 -0700 Subject: [PATCH 07/54] 6888954: argument formatting for assert() and friends Reviewed-by: kvn, twisti, apetrusenko, never, dcubed --- hotspot/src/cpu/sparc/vm/assembler_sparc.hpp | 2 +- hotspot/src/os/linux/vm/os_linux.cpp | 6 +- hotspot/src/os/solaris/vm/os_solaris.cpp | 16 +- .../os/solaris/vm/threadCritical_solaris.cpp | 6 +- hotspot/src/os/windows/vm/os_windows.cpp | 4 +- .../os_cpu/linux_sparc/vm/os_linux_sparc.cpp | 2 +- .../src/os_cpu/linux_x86/vm/os_linux_x86.cpp | 2 +- hotspot/src/share/vm/asm/assembler.cpp | 3 +- .../share/vm/classfile/classFileParser.cpp | 3 +- .../share/vm/code/exceptionHandlerTable.cpp | 2 +- hotspot/src/share/vm/code/nmethod.cpp | 5 +- hotspot/src/share/vm/code/stubs.cpp | 4 +- hotspot/src/share/vm/code/vtableStubs.cpp | 8 +- .../vm/interpreter/bytecodeInterpreter.cpp | 4 +- .../src/share/vm/interpreter/bytecodes.cpp | 4 +- hotspot/src/share/vm/oops/instanceKlass.cpp | 4 +- .../src/share/vm/oops/instanceKlassKlass.cpp | 4 +- hotspot/src/share/vm/oops/klassVtable.cpp | 6 +- .../src/share/vm/opto/idealGraphPrinter.cpp | 3 +- hotspot/src/share/vm/opto/output.cpp | 6 +- hotspot/src/share/vm/prims/jni.cpp | 1 + hotspot/src/share/vm/runtime/globals.hpp | 5 + hotspot/src/share/vm/runtime/memprofiler.cpp | 2 +- hotspot/src/share/vm/runtime/mutex.cpp | 8 +- hotspot/src/share/vm/runtime/mutexLocker.cpp | 4 +- hotspot/src/share/vm/runtime/os.cpp | 6 +- hotspot/src/share/vm/runtime/safepoint.cpp | 2 +- hotspot/src/share/vm/runtime/signature.cpp | 2 +- hotspot/src/share/vm/runtime/stubRoutines.cpp | 10 +- hotspot/src/share/vm/runtime/vmThread.cpp | 3 +- hotspot/src/share/vm/utilities/debug.cpp | 117 ++++++----- hotspot/src/share/vm/utilities/debug.hpp | 186 +++++++++++------- hotspot/src/share/vm/utilities/exceptions.cpp | 2 +- hotspot/src/share/vm/utilities/macros.hpp | 2 - hotspot/src/share/vm/utilities/vmError.cpp | 80 ++++---- hotspot/src/share/vm/utilities/vmError.hpp | 12 +- hotspot/test/runtime/6888954/vmerrors.sh | 71 +++++++ 37 files changed, 396 insertions(+), 211 deletions(-) create mode 100644 hotspot/test/runtime/6888954/vmerrors.sh diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp index 1e184bd4584..4a73fecae23 100644 --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp @@ -1065,7 +1065,7 @@ class Assembler : public AbstractAssembler { } void assert_not_delayed(const char* msg) { #ifdef CHECK_DELAY - assert_msg ( delay_state == no_delay, msg); + assert(delay_state == no_delay, msg); #endif } diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index d38f3866c72..478d34e7170 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -3495,7 +3495,8 @@ void os::Linux::set_signal_handler(int sig, bool set_installed) { // libjsig also interposes the sigaction() call below and saves the // old sigaction on it own. } else { - fatal2("Encountered unexpected pre-existing sigaction handler %#lx for signal %d.", (long)oldhand, sig); + fatal(err_msg("Encountered unexpected pre-existing sigaction handler " + "%#lx for signal %d.", (long)oldhand, sig)); } } @@ -3817,7 +3818,8 @@ void os::init(void) { Linux::set_page_size(sysconf(_SC_PAGESIZE)); if (Linux::page_size() == -1) { - fatal1("os_linux.cpp: os::init: sysconf failed (%s)", strerror(errno)); + fatal(err_msg("os_linux.cpp: os::init: sysconf failed (%s)", + strerror(errno))); } init_page_sizes((size_t) Linux::page_size()); diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index a137234854c..7009a5d5877 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -1567,7 +1567,8 @@ int os::allocate_thread_local_storage() { // treat %g2 as a caller-save register, preserving it in a %lN. thread_key_t tk; if (thr_keycreate( &tk, NULL ) ) - fatal1("os::allocate_thread_local_storage: thr_keycreate failed (%s)", strerror(errno)); + fatal(err_msg("os::allocate_thread_local_storage: thr_keycreate failed " + "(%s)", strerror(errno))); return int(tk); } @@ -1585,7 +1586,8 @@ void os::thread_local_storage_at_put(int index, void* value) { if (errno == ENOMEM) { vm_exit_out_of_memory(SMALLINT, "thr_setspecific: out of swap space"); } else { - fatal1("os::thread_local_storage_at_put: thr_setspecific failed (%s)", strerror(errno)); + fatal(err_msg("os::thread_local_storage_at_put: thr_setspecific failed " + "(%s)", strerror(errno))); } } else { ThreadLocalStorage::set_thread_in_slot ((Thread *) value) ; @@ -1738,7 +1740,7 @@ jlong getTimeMillis() { jlong os::javaTimeMillis() { timeval t; if (gettimeofday( &t, NULL) == -1) - fatal1("os::javaTimeMillis: gettimeofday (%s)", strerror(errno)); + fatal(err_msg("os::javaTimeMillis: gettimeofday (%s)", strerror(errno))); return jlong(t.tv_sec) * 1000 + jlong(t.tv_usec) / 1000; } @@ -4233,7 +4235,8 @@ void os::Solaris::set_signal_handler(int sig, bool set_installed, bool oktochain // libjsig also interposes the sigaction() call below and saves the // old sigaction on it own. } else { - fatal2("Encountered unexpected pre-existing sigaction handler %#lx for signal %d.", (long)oldhand, sig); + fatal(err_msg("Encountered unexpected pre-existing sigaction handler " + "%#lx for signal %d.", (long)oldhand, sig)); } } @@ -4764,7 +4767,8 @@ void os::init(void) { page_size = sysconf(_SC_PAGESIZE); if (page_size == -1) - fatal1("os_solaris.cpp: os::init: sysconf failed (%s)", strerror(errno)); + fatal(err_msg("os_solaris.cpp: os::init: sysconf failed (%s)", + strerror(errno))); init_page_sizes((size_t) page_size); Solaris::initialize_system_info(); @@ -4775,7 +4779,7 @@ void os::init(void) { int fd = open("/dev/zero", O_RDWR); if (fd < 0) { - fatal1("os::init: cannot open /dev/zero (%s)", strerror(errno)); + fatal(err_msg("os::init: cannot open /dev/zero (%s)", strerror(errno))); } else { Solaris::set_dev_zero_fd(fd); diff --git a/hotspot/src/os/solaris/vm/threadCritical_solaris.cpp b/hotspot/src/os/solaris/vm/threadCritical_solaris.cpp index 58ef055e510..1f98ec920e2 100644 --- a/hotspot/src/os/solaris/vm/threadCritical_solaris.cpp +++ b/hotspot/src/os/solaris/vm/threadCritical_solaris.cpp @@ -47,7 +47,8 @@ ThreadCritical::ThreadCritical() { thread_t owner = thr_self(); if (global_mut_owner != owner) { if (os::Solaris::mutex_lock(&global_mut)) - fatal1("ThreadCritical::ThreadCritical: mutex_lock failed (%s)", strerror(errno)); + fatal(err_msg("ThreadCritical::ThreadCritical: mutex_lock failed (%s)", + strerror(errno))); assert(global_mut_count == 0, "must have clean count"); assert(global_mut_owner == -1, "must have clean owner"); } @@ -66,7 +67,8 @@ ThreadCritical::~ThreadCritical() { if (global_mut_count == 0) { global_mut_owner = -1; if (os::Solaris::mutex_unlock(&global_mut)) - fatal1("ThreadCritical::~ThreadCritical: mutex_unlock failed (%s)", strerror(errno)); + fatal(err_msg("ThreadCritical::~ThreadCritical: mutex_unlock failed " + "(%s)", strerror(errno))); } } else { assert (Threads::number_of_threads() == 0, "valid only during initialization"); diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index 3763e504e2e..c2952697627 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -724,7 +724,7 @@ jlong offset() { java_origin.wMilliseconds = 0; FILETIME jot; if (!SystemTimeToFileTime(&java_origin, &jot)) { - fatal1("Error = %d\nWindows error", GetLastError()); + fatal(err_msg("Error = %d\nWindows error", GetLastError())); } _calculated_offset = jlong_from(jot.dwHighDateTime, jot.dwLowDateTime); _has_calculated_offset = 1; @@ -4095,7 +4095,7 @@ bool os::check_heap(bool force) { } int err = GetLastError(); if (err != ERROR_NO_MORE_ITEMS && err != ERROR_CALL_NOT_IMPLEMENTED) { - fatal1("heap walk aborted with error %d", err); + fatal(err_msg("heap walk aborted with error %d", err)); } HeapUnlock(heap); } diff --git a/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp b/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp index 2226285c0e7..6bde1fccba5 100644 --- a/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp +++ b/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp @@ -153,7 +153,7 @@ static void current_stack_region(address* bottom, size_t* size) { if (rslt == ENOMEM) { vm_exit_out_of_memory(0, "pthread_getattr_np"); } else { - fatal1("pthread_getattr_np failed with errno = %d", rslt); + fatal(err_msg("pthread_getattr_np failed with errno = %d", rslt)); } } diff --git a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp index df685ff5148..f1fcdb9c531 100644 --- a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp +++ b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp @@ -680,7 +680,7 @@ static void current_stack_region(address * bottom, size_t * size) { if (rslt == ENOMEM) { vm_exit_out_of_memory(0, "pthread_getattr_np"); } else { - fatal1("pthread_getattr_np failed with errno = %d", rslt); + fatal(err_msg("pthread_getattr_np failed with errno = %d", rslt)); } } diff --git a/hotspot/src/share/vm/asm/assembler.cpp b/hotspot/src/share/vm/asm/assembler.cpp index 492f2fd134c..96af7789ca6 100644 --- a/hotspot/src/share/vm/asm/assembler.cpp +++ b/hotspot/src/share/vm/asm/assembler.cpp @@ -43,7 +43,8 @@ AbstractAssembler::AbstractAssembler(CodeBuffer* code) { _code_pos = cs->end(); _oop_recorder= code->oop_recorder(); if (_code_begin == NULL) { - vm_exit_out_of_memory1(0, "CodeCache: no room for %s", code->name()); + vm_exit_out_of_memory(0, err_msg("CodeCache: no room for %s", + code->name())); } } diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index 23ec4746bcc..982e2b1bed6 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -334,7 +334,8 @@ constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) { } break; default: - fatal1("bad constant pool tag value %u", cp->tag_at(index).value()); + fatal(err_msg("bad constant pool tag value %u", + cp->tag_at(index).value())); ShouldNotReachHere(); break; } // end of switch diff --git a/hotspot/src/share/vm/code/exceptionHandlerTable.cpp b/hotspot/src/share/vm/code/exceptionHandlerTable.cpp index 19d95e9cf1d..c0e59ad30c8 100644 --- a/hotspot/src/share/vm/code/exceptionHandlerTable.cpp +++ b/hotspot/src/share/vm/code/exceptionHandlerTable.cpp @@ -221,6 +221,6 @@ void ImplicitExceptionTable::verify(nmethod *nm) const { for (uint i = 0; i < len(); i++) { if ((*adr(i) > (unsigned int)nm->code_size()) || (*(adr(i)+1) > (unsigned int)nm->code_size())) - fatal1("Invalid offset in ImplicitExceptionTable at %lx", _data); + fatal(err_msg("Invalid offset in ImplicitExceptionTable at " PTR_FORMAT, _data)); } } diff --git a/hotspot/src/share/vm/code/nmethod.cpp b/hotspot/src/share/vm/code/nmethod.cpp index 7e0a86915cf..f7845bb8b93 100644 --- a/hotspot/src/share/vm/code/nmethod.cpp +++ b/hotspot/src/share/vm/code/nmethod.cpp @@ -2124,7 +2124,7 @@ void nmethod::verify() { ResourceMark rm; if (!CodeCache::contains(this)) { - fatal1("nmethod at " INTPTR_FORMAT " not in zone", this); + fatal(err_msg("nmethod at " INTPTR_FORMAT " not in zone", this)); } if(is_native_method() ) @@ -2132,7 +2132,8 @@ void nmethod::verify() { nmethod* nm = CodeCache::find_nmethod(verified_entry_point()); if (nm != this) { - fatal1("findNMethod did not find this nmethod (" INTPTR_FORMAT ")", this); + fatal(err_msg("findNMethod did not find this nmethod (" INTPTR_FORMAT ")", + this)); } for (PcDesc* p = scopes_pcs_begin(); p < scopes_pcs_end(); p++) { diff --git a/hotspot/src/share/vm/code/stubs.cpp b/hotspot/src/share/vm/code/stubs.cpp index 90323e87824..0e32e919fa2 100644 --- a/hotspot/src/share/vm/code/stubs.cpp +++ b/hotspot/src/share/vm/code/stubs.cpp @@ -62,7 +62,9 @@ StubQueue::StubQueue(StubInterface* stub_interface, int buffer_size, Mutex* lock, const char* name) : _mutex(lock) { intptr_t size = round_to(buffer_size, 2*BytesPerWord); BufferBlob* blob = BufferBlob::create(name, size); - if( blob == NULL ) vm_exit_out_of_memory1(size, "CodeCache: no room for %s", name); + if( blob == NULL) { + vm_exit_out_of_memory(size, err_msg("CodeCache: no room for %s", name)); + } _stub_interface = stub_interface; _buffer_size = blob->instructions_size(); _buffer_limit = blob->instructions_size(); diff --git a/hotspot/src/share/vm/code/vtableStubs.cpp b/hotspot/src/share/vm/code/vtableStubs.cpp index 67149eae5c6..948e34c6e19 100644 --- a/hotspot/src/share/vm/code/vtableStubs.cpp +++ b/hotspot/src/share/vm/code/vtableStubs.cpp @@ -45,7 +45,9 @@ void* VtableStub::operator new(size_t size, int code_size) { if (_chunk == NULL || _chunk + real_size > _chunk_end) { const int bytes = chunk_factor * real_size + pd_code_alignment(); BufferBlob* blob = BufferBlob::create("vtable chunks", bytes); - if( blob == NULL ) vm_exit_out_of_memory1(bytes, "CodeCache: no room for %s", "vtable chunks"); + if (blob == NULL) { + vm_exit_out_of_memory(bytes, "CodeCache: no room for vtable chunks"); + } _chunk = blob->instructions_begin(); _chunk_end = _chunk + bytes; VTune::register_stub("vtable stub", _chunk, _chunk_end); @@ -189,7 +191,9 @@ extern "C" void bad_compiled_vtable_index(JavaThread* thread, oop receiver, int instanceKlass* ik = instanceKlass::cast(klass); klassVtable* vt = ik->vtable(); klass->print(); - fatal3("bad compiled vtable dispatch: receiver " INTPTR_FORMAT ", index %d (vtable length %d)", (address)receiver, index, vt->length()); + fatal(err_msg("bad compiled vtable dispatch: receiver " INTPTR_FORMAT ", " + "index %d (vtable length %d)", + (address)receiver, index, vt->length())); } #endif // Product diff --git a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp index a8400339093..e6d5d5bf846 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp @@ -2339,8 +2339,8 @@ run: goto opcode_switch; } #endif - fatal2("\t*** Unimplemented opcode: %d = %s\n", - opcode, Bytecodes::name((Bytecodes::Code)opcode)); + fatal(err_msg("Unimplemented opcode %d = %s", opcode, + Bytecodes::name((Bytecodes::Code)opcode))); goto finish; } /* switch(opc) */ diff --git a/hotspot/src/share/vm/interpreter/bytecodes.cpp b/hotspot/src/share/vm/interpreter/bytecodes.cpp index cb2a7ecb234..46d2727fa1b 100644 --- a/hotspot/src/share/vm/interpreter/bytecodes.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodes.cpp @@ -426,7 +426,9 @@ void Bytecodes::initialize() { if (is_defined(i)) { Code code = cast(i); Code java = java_code(code); - if (can_trap(code) && !can_trap(java)) fatal2("%s can trap => %s can trap, too", name(code), name(java)); + if (can_trap(code) && !can_trap(java)) + fatal(err_msg("%s can trap => %s can trap, too", name(code), + name(java))); } } } diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index 483d28496d3..40bf5392cb0 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -966,7 +966,7 @@ methodOop instanceKlass::find_method(objArrayOop methods, symbolOop name, symbol // not found #ifdef ASSERT int index = linear_search(methods, name, signature); - if (index != -1) fatal1("binary search bug: should have found entry %d", index); + assert(index == -1, err_msg("binary search should have found entry %d", index)); #endif return NULL; } else if (res < 0) { @@ -977,7 +977,7 @@ methodOop instanceKlass::find_method(objArrayOop methods, symbolOop name, symbol } #ifdef ASSERT int index = linear_search(methods, name, signature); - if (index != -1) fatal1("binary search bug: should have found entry %d", index); + assert(index == -1, err_msg("binary search should have found entry %d", index)); #endif return NULL; } diff --git a/hotspot/src/share/vm/oops/instanceKlassKlass.cpp b/hotspot/src/share/vm/oops/instanceKlassKlass.cpp index 05748104d3b..11b133f3b1e 100644 --- a/hotspot/src/share/vm/oops/instanceKlassKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlassKlass.cpp @@ -712,10 +712,10 @@ void instanceKlassKlass::oop_verify_on(oop obj, outputStream* st) { int sib_count = 0; while (sib != NULL) { if (sib == ik) { - fatal1("subclass cycle of length %d", sib_count); + fatal(err_msg("subclass cycle of length %d", sib_count)); } if (sib_count >= 100000) { - fatal1("suspiciously long subclass list %d", sib_count); + fatal(err_msg("suspiciously long subclass list %d", sib_count)); } guarantee(sib->as_klassOop()->is_klass(), "should be klass"); guarantee(sib->as_klassOop()->is_perm(), "should be in permspace"); diff --git a/hotspot/src/share/vm/oops/klassVtable.cpp b/hotspot/src/share/vm/oops/klassVtable.cpp index 96651c37d56..6dc3497778f 100644 --- a/hotspot/src/share/vm/oops/klassVtable.cpp +++ b/hotspot/src/share/vm/oops/klassVtable.cpp @@ -1180,8 +1180,8 @@ void klassVtable::verify(outputStream* st, bool forced) { oop* end_of_obj = (oop*)_klass() + _klass()->size(); oop* end_of_vtable = (oop *)&table()[_length]; if (end_of_vtable > end_of_obj) { - fatal1("klass %s: klass object too short (vtable extends beyond end)", - _klass->internal_name()); + fatal(err_msg("klass %s: klass object too short (vtable extends beyond " + "end)", _klass->internal_name())); } for (int i = 0; i < _length; i++) table()[i].verify(this, st); @@ -1224,7 +1224,7 @@ void vtableEntry::verify(klassVtable* vt, outputStream* st) { #ifndef PRODUCT print(); #endif - fatal1("vtableEntry %#lx: method is from subclass", this); + fatal(err_msg("vtableEntry " PTR_FORMAT ": method is from subclass", this)); } } diff --git a/hotspot/src/share/vm/opto/idealGraphPrinter.cpp b/hotspot/src/share/vm/opto/idealGraphPrinter.cpp index a375b92a93b..0f51d17ce91 100644 --- a/hotspot/src/share/vm/opto/idealGraphPrinter.cpp +++ b/hotspot/src/share/vm/opto/idealGraphPrinter.cpp @@ -151,7 +151,8 @@ IdealGraphPrinter::IdealGraphPrinter() { } else { // It would be nice if we could shut down cleanly but it should // be an error if we can't connect to the visualizer. - fatal2("Couldn't connect to visualizer at %s:%d", PrintIdealGraphAddress, PrintIdealGraphPort); + fatal(err_msg("Couldn't connect to visualizer at %s:%d", + PrintIdealGraphAddress, PrintIdealGraphPort)); } } diff --git a/hotspot/src/share/vm/opto/output.cpp b/hotspot/src/share/vm/opto/output.cpp index 853ed4700fb..da47f0db03a 100644 --- a/hotspot/src/share/vm/opto/output.cpp +++ b/hotspot/src/share/vm/opto/output.cpp @@ -2407,7 +2407,7 @@ void Scheduling::verify_do_def( Node *n, OptoReg::Name def, const char *msg ) { n->dump(); tty->print_cr("..."); prior_use->dump(); - assert_msg(edge_from_to(prior_use,n),msg); + assert(edge_from_to(prior_use,n),msg); } _reg_node.map(def,NULL); // Kill live USEs } @@ -2446,11 +2446,11 @@ void Scheduling::verify_good_schedule( Block *b, const char *msg ) { OptoReg::Name reg_lo = _regalloc->get_reg_first(def); OptoReg::Name reg_hi = _regalloc->get_reg_second(def); if( OptoReg::is_valid(reg_lo) ) { - assert_msg(!_reg_node[reg_lo] || edge_from_to(_reg_node[reg_lo],def), msg ); + assert(!_reg_node[reg_lo] || edge_from_to(_reg_node[reg_lo],def), msg); _reg_node.map(reg_lo,n); } if( OptoReg::is_valid(reg_hi) ) { - assert_msg(!_reg_node[reg_hi] || edge_from_to(_reg_node[reg_hi],def), msg ); + assert(!_reg_node[reg_hi] || edge_from_to(_reg_node[reg_hi],def), msg); _reg_node.map(reg_hi,n); } } diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp index 1cbfa61a17a..aea1c0cb664 100644 --- a/hotspot/src/share/vm/prims/jni.cpp +++ b/hotspot/src/share/vm/prims/jni.cpp @@ -3311,6 +3311,7 @@ _JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_CreateJavaVM(JavaVM **vm, void **penv, v OrderAccess::release_store(&vm_created, 0); } + NOT_PRODUCT(test_error_handler(ErrorHandlerTest)); return result; } diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 861d89cb699..911b2abb4cb 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -652,6 +652,11 @@ class CommandLineFlags { product(bool, PrintGCApplicationStoppedTime, false, \ "Print the time the application has been stopped") \ \ + notproduct(uintx, ErrorHandlerTest, 0, \ + "If > 0, provokes an error after VM initialization; the value" \ + "determines which error to provoke. See test_error_handler()" \ + "in debug.cpp.") \ + \ develop(bool, Verbose, false, \ "Prints additional debugging information from other modes") \ \ diff --git a/hotspot/src/share/vm/runtime/memprofiler.cpp b/hotspot/src/share/vm/runtime/memprofiler.cpp index c141e3216a6..69d0f597f6c 100644 --- a/hotspot/src/share/vm/runtime/memprofiler.cpp +++ b/hotspot/src/share/vm/runtime/memprofiler.cpp @@ -62,7 +62,7 @@ void MemProfiler::engage() { // Create log file _log_fp = fopen(log_name , "w+"); if (_log_fp == NULL) { - fatal1("MemProfiler: Cannot create log file: %s", log_name); + fatal(err_msg("MemProfiler: Cannot create log file: %s", log_name)); } fprintf(_log_fp, "MemProfiler: sizes are in Kb, time is in seconds since startup\n\n"); fprintf(_log_fp, " time, #thr, #cls, heap, heap, perm, perm, code, hndls, rescs, oopmp\n"); diff --git a/hotspot/src/share/vm/runtime/mutex.cpp b/hotspot/src/share/vm/runtime/mutex.cpp index 9804bee0403..f47f66f213f 100644 --- a/hotspot/src/share/vm/runtime/mutex.cpp +++ b/hotspot/src/share/vm/runtime/mutex.cpp @@ -1288,8 +1288,9 @@ void Monitor::set_owner_implementation(Thread *new_owner) { !(this == Safepoint_lock && contains(locks, Terminator_lock) && SafepointSynchronize::is_synchronizing())) { new_owner->print_owned_locks(); - fatal4("acquiring lock %s/%d out of order with lock %s/%d -- possible deadlock", - this->name(), this->rank(), locks->name(), locks->rank()); + fatal(err_msg("acquiring lock %s/%d out of order with lock %s/%d -- " + "possible deadlock", this->name(), this->rank(), + locks->name(), locks->rank())); } this->_next = new_owner->_owned_locks; @@ -1342,7 +1343,8 @@ void Monitor::check_prelock_state(Thread *thread) { || rank() == Mutex::special, "wrong thread state for using locks"); if (StrictSafepointChecks) { if (thread->is_VM_thread() && !allow_vm_block()) { - fatal1("VM thread using lock %s (not allowed to block on)", name()); + fatal(err_msg("VM thread using lock %s (not allowed to block on)", + name())); } debug_only(if (rank() != Mutex::special) \ thread->check_for_valid_safepoint_state(false);) diff --git a/hotspot/src/share/vm/runtime/mutexLocker.cpp b/hotspot/src/share/vm/runtime/mutexLocker.cpp index 019dbb4524b..4a89fdf16ae 100644 --- a/hotspot/src/share/vm/runtime/mutexLocker.cpp +++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp @@ -136,7 +136,7 @@ void assert_locked_or_safepoint(const Monitor * lock) { // see if invoker of VM operation owns it VM_Operation* op = VMThread::vm_operation(); if (op != NULL && op->calling_thread() == lock->owner()) return; - fatal1("must own lock %s", lock->name()); + fatal(err_msg("must own lock %s", lock->name())); } // a stronger assertion than the above @@ -144,7 +144,7 @@ void assert_lock_strong(const Monitor * lock) { if (IgnoreLockingAssertions) return; assert(lock != NULL, "Need non-NULL lock"); if (lock->owned_by_self()) return; - fatal1("must own lock %s", lock->name()); + fatal(err_msg("must own lock %s", lock->name())); } #endif diff --git a/hotspot/src/share/vm/runtime/os.cpp b/hotspot/src/share/vm/runtime/os.cpp index ff16581eb51..9b86ee8ae6c 100644 --- a/hotspot/src/share/vm/runtime/os.cpp +++ b/hotspot/src/share/vm/runtime/os.cpp @@ -406,8 +406,10 @@ char *os::strdup(const char *str) { #ifdef ASSERT inline size_t get_size(void* obj) { size_t size = *size_addr_from_obj(obj); - if (size < 0 ) - fatal2("free: size field of object #%p was overwritten (%lu)", obj, size); + if (size < 0) { + fatal(err_msg("free: size field of object #" PTR_FORMAT " was overwritten (" + SIZE_FORMAT ")", obj, size)); + } return size; } diff --git a/hotspot/src/share/vm/runtime/safepoint.cpp b/hotspot/src/share/vm/runtime/safepoint.cpp index 056de5b2669..283896292f1 100644 --- a/hotspot/src/share/vm/runtime/safepoint.cpp +++ b/hotspot/src/share/vm/runtime/safepoint.cpp @@ -594,7 +594,7 @@ void SafepointSynchronize::block(JavaThread *thread) { break; default: - fatal1("Illegal threadstate encountered: %d", state); + fatal(err_msg("Illegal threadstate encountered: %d", state)); } // Check for pending. async. exceptions or suspends - except if the diff --git a/hotspot/src/share/vm/runtime/signature.cpp b/hotspot/src/share/vm/runtime/signature.cpp index c9c3859a612..f914baee9c0 100644 --- a/hotspot/src/share/vm/runtime/signature.cpp +++ b/hotspot/src/share/vm/runtime/signature.cpp @@ -57,7 +57,7 @@ SignatureIterator::SignatureIterator(Thread *thread, symbolOop signature) { } void SignatureIterator::expect(char c) { - if (_signature->byte_at(_index) != c) fatal1("expecting %c", c); + if (_signature->byte_at(_index) != c) fatal(err_msg("expecting %c", c)); _index++; } diff --git a/hotspot/src/share/vm/runtime/stubRoutines.cpp b/hotspot/src/share/vm/runtime/stubRoutines.cpp index 22b1df86804..c29e4726fb3 100644 --- a/hotspot/src/share/vm/runtime/stubRoutines.cpp +++ b/hotspot/src/share/vm/runtime/stubRoutines.cpp @@ -118,7 +118,10 @@ void StubRoutines::initialize1() { ResourceMark rm; TraceTime timer("StubRoutines generation 1", TraceStartupTime); _code1 = BufferBlob::create("StubRoutines (1)", code_size1); - if( _code1 == NULL) vm_exit_out_of_memory1(code_size1, "CodeCache: no room for %s", "StubRoutines (1)"); + if (_code1 == NULL) { + vm_exit_out_of_memory(code_size1, + "CodeCache: no room for StubRoutines (1)"); + } CodeBuffer buffer(_code1->instructions_begin(), _code1->instructions_size()); StubGenerator_generate(&buffer, false); } @@ -164,7 +167,10 @@ void StubRoutines::initialize2() { ResourceMark rm; TraceTime timer("StubRoutines generation 2", TraceStartupTime); _code2 = BufferBlob::create("StubRoutines (2)", code_size2); - if( _code2 == NULL) vm_exit_out_of_memory1(code_size2, "CodeCache: no room for %s", "StubRoutines (2)"); + if (_code2 == NULL) { + vm_exit_out_of_memory(code_size2, + "CodeCache: no room for StubRoutines (2)"); + } CodeBuffer buffer(_code2->instructions_begin(), _code2->instructions_size()); StubGenerator_generate(&buffer, true); } diff --git a/hotspot/src/share/vm/runtime/vmThread.cpp b/hotspot/src/share/vm/runtime/vmThread.cpp index 95538a7248a..63af069b93f 100644 --- a/hotspot/src/share/vm/runtime/vmThread.cpp +++ b/hotspot/src/share/vm/runtime/vmThread.cpp @@ -593,7 +593,8 @@ void VMThread::execute(VM_Operation* op) { // Check the VM operation allows nested VM operation. This normally not the case, e.g., the compiler // does not allow nested scavenges or compiles. if (!prev_vm_operation->allow_nested_vm_operations()) { - fatal2("Nested VM operation %s requested by operation %s", op->name(), vm_operation()->name()); + fatal(err_msg("Nested VM operation %s requested by operation %s", + op->name(), vm_operation()->name())); } op->set_calling_thread(prev_vm_operation->calling_thread(), prev_vm_operation->priority()); } diff --git a/hotspot/src/share/vm/utilities/debug.cpp b/hotspot/src/share/vm/utilities/debug.cpp index ef3e123551d..3ab0183be10 100644 --- a/hotspot/src/share/vm/utilities/debug.cpp +++ b/hotspot/src/share/vm/utilities/debug.cpp @@ -72,7 +72,7 @@ static int last_line_no = -1; // assert/guarantee/... may happen very early during VM initialization. // Don't rely on anything that is initialized by Threads::create_vm(). For // example, don't use tty. -bool assert_is_suppressed(const char* file_name, int line_no) { +bool error_is_suppressed(const char* file_name, int line_no) { // The following 1-element cache requires that passed-in // file names are always only constant literals. if (file_name == last_file_name && line_no == last_line_no) return true; @@ -163,38 +163,30 @@ bool assert_is_suppressed(const char* file_name, int line_no) { #else // Place-holder for non-existent suppression check: -#define assert_is_suppressed(file_name, line_no) (false) +#define error_is_suppressed(file_name, line_no) (false) #endif //PRODUCT -void report_assertion_failure(const char* file_name, int line_no, const char* message) { - if (Debugging || assert_is_suppressed(file_name, line_no)) return; - VMError err(ThreadLocalStorage::get_thread_slow(), message, file_name, line_no); +void report_vm_error(const char* file, int line, const char* error_msg, + const char* detail_msg) +{ + if (Debugging || error_is_suppressed(file, line)) return; + Thread* const thread = ThreadLocalStorage::get_thread_slow(); + VMError err(thread, file, line, error_msg, detail_msg); err.report_and_die(); } -void report_fatal(const char* file_name, int line_no, const char* message) { - if (Debugging || assert_is_suppressed(file_name, line_no)) return; - VMError err(ThreadLocalStorage::get_thread_slow(), message, file_name, line_no); - err.report_and_die(); +void report_fatal(const char* file, int line, const char* message) +{ + report_vm_error(file, line, "fatal error", message); } -void report_fatal_vararg(const char* file_name, int line_no, const char* format, ...) { - char buffer[256]; - va_list ap; - va_start(ap, format); - jio_vsnprintf(buffer, sizeof(buffer), format, ap); - va_end(ap); - report_fatal(file_name, line_no, buffer); -} - - // Used by report_vm_out_of_memory to detect recursion. static jint _exiting_out_of_mem = 0; -// Just passing the flow to VMError to handle error -void report_vm_out_of_memory(const char* file_name, int line_no, size_t size, const char* message) { - if (Debugging || assert_is_suppressed(file_name, line_no)) return; +void report_vm_out_of_memory(const char* file, int line, size_t size, + const char* message) { + if (Debugging || error_is_suppressed(file, line)) return; // We try to gather additional information for the first out of memory // error only; gathering additional data might cause an allocation and a @@ -206,46 +198,28 @@ void report_vm_out_of_memory(const char* file_name, int line_no, size_t size, co if (first_time_here) { Thread* thread = ThreadLocalStorage::get_thread_slow(); - VMError(thread, size, message, file_name, line_no).report_and_die(); + VMError(thread, file, line, size, message).report_and_die(); } // Dump core and abort vm_abort(true); } -void report_vm_out_of_memory_vararg(const char* file_name, int line_no, size_t size, const char* format, ...) { - char buffer[256]; - va_list ap; - va_start(ap, format); - jio_vsnprintf(buffer, sizeof(buffer), format, ap); - va_end(ap); - report_vm_out_of_memory(file_name, line_no, size, buffer); +void report_should_not_call(const char* file, int line) { + report_vm_error(file, line, "ShouldNotCall()"); } -void report_should_not_call(const char* file_name, int line_no) { - if (Debugging || assert_is_suppressed(file_name, line_no)) return; - VMError err(ThreadLocalStorage::get_thread_slow(), "ShouldNotCall()", file_name, line_no); - err.report_and_die(); +void report_should_not_reach_here(const char* file, int line) { + report_vm_error(file, line, "ShouldNotReachHere()"); } - -void report_should_not_reach_here(const char* file_name, int line_no) { - if (Debugging || assert_is_suppressed(file_name, line_no)) return; - VMError err(ThreadLocalStorage::get_thread_slow(), "ShouldNotReachHere()", file_name, line_no); - err.report_and_die(); +void report_unimplemented(const char* file, int line) { + report_vm_error(file, line, "Unimplemented()"); } - -void report_unimplemented(const char* file_name, int line_no) { - if (Debugging || assert_is_suppressed(file_name, line_no)) return; - VMError err(ThreadLocalStorage::get_thread_slow(), "Unimplemented()", file_name, line_no); - err.report_and_die(); -} - - -void report_untested(const char* file_name, int line_no, const char* msg) { +void report_untested(const char* file, int line, const char* message) { #ifndef PRODUCT - warning("Untested: %s in %s: %d\n", msg, file_name, line_no); + warning("Untested: %s in %s: %d\n", message, file, line); #endif // PRODUCT } @@ -284,6 +258,51 @@ bool is_error_reported() { return error_reported; } +#ifndef PRODUCT +#include + +void test_error_handler(size_t test_num) +{ + if (test_num == 0) return; + + // If asserts are disabled, use the corresponding guarantee instead. + size_t n = test_num; + NOT_DEBUG(if (n <= 2) n += 2); + + const char* const str = "hello"; + const size_t num = (size_t)os::vm_page_size(); + + const char* const eol = os::line_separator(); + const char* const msg = "this message should be truncated during formatting"; + + // Keep this in sync with test/runtime/6888954/vmerrors.sh. + switch (n) { + case 1: assert(str == NULL, "expected null"); + case 2: assert(num == 1023 && *str == 'X', + err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str)); + case 3: guarantee(str == NULL, "expected null"); + case 4: guarantee(num == 1023 && *str == 'X', + err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str)); + case 5: fatal("expected null"); + case 6: fatal(err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str)); + case 7: fatal(err_msg("%s%s# %s%s# %s%s# %s%s# %s%s# " + "%s%s# %s%s# %s%s# %s%s# %s%s# " + "%s%s# %s%s# %s%s# %s%s# %s", + msg, eol, msg, eol, msg, eol, msg, eol, msg, eol, + msg, eol, msg, eol, msg, eol, msg, eol, msg, eol, + msg, eol, msg, eol, msg, eol, msg, eol, msg)); + case 8: vm_exit_out_of_memory(num, "ChunkPool::allocate"); + case 9: ShouldNotCallThis(); + case 10: ShouldNotReachHere(); + case 11: Unimplemented(); + // This is last because it does not generate an hs_err* file on Windows. + case 12: os::signal_raise(SIGSEGV); + + default: ShouldNotReachHere(); + } +} +#endif // #ifndef PRODUCT + // ------ helper functions for debugging go here ------------ #ifndef PRODUCT diff --git a/hotspot/src/share/vm/utilities/debug.hpp b/hotspot/src/share/vm/utilities/debug.hpp index 98d3e622697..e6dd851d190 100644 --- a/hotspot/src/share/vm/utilities/debug.hpp +++ b/hotspot/src/share/vm/utilities/debug.hpp @@ -22,28 +22,54 @@ * */ +#include + +// Simple class to format the ctor arguments into a fixed-sized buffer. +template +class FormatBuffer { +public: + inline FormatBuffer(const char * format, ...); + operator const char *() const { return _buf; } + +private: + FormatBuffer(const FormatBuffer &); // prevent copies + +private: + char _buf[bufsz]; +}; + +template +FormatBuffer::FormatBuffer(const char * format, ...) { + va_list argp; + va_start(argp, format); + vsnprintf(_buf, bufsz, format, argp); + va_end(argp); +} + +// Used to format messages for assert(), guarantee(), fatal(), etc. +typedef FormatBuffer<> err_msg; + // assertions #ifdef ASSERT -// Turn this off by default: -//#define USE_REPEATED_ASSERTS -#ifdef USE_REPEATED_ASSERTS - #define assert(p,msg) \ - { for (int __i = 0; __i < AssertRepeat; __i++) { \ - if (!(p)) { \ - report_assertion_failure(__FILE__, __LINE__, \ - "assert(" XSTR(p) ",\"" msg "\")");\ - BREAKPOINT; \ - } \ - } \ - } -#else - #define assert(p,msg) \ - if (!(p)) { \ - report_assertion_failure(__FILE__, __LINE__, \ - "assert(" XSTR(p) ",\"" msg "\")");\ - BREAKPOINT; \ - } -#endif +#ifndef USE_REPEATED_ASSERTS +#define assert(p, msg) \ +do { \ + if (!(p)) { \ + report_vm_error(__FILE__, __LINE__, "assert(" #p ") failed", msg); \ + BREAKPOINT; \ + } \ +} while (0) +#else // #ifndef USE_REPEATED_ASSERTS +#define assert(p, msg) +do { \ + for (int __i = 0; __i < AssertRepeat; __i++) { \ + if (!(p)) { \ + report_vm_error(__FILE__, __LINE__, "assert(" #p ") failed", msg); \ + BREAKPOINT; \ + } \ + } \ +} while (0) +#endif // #ifndef USE_REPEATED_ASSERTS // This version of assert is for use with checking return status from // library calls that return actual error values eg. EINVAL, @@ -52,70 +78,83 @@ // what status was actually returned, so we pass the status variable as // an extra arg and use strerror to convert it to a meaningful string // like "Invalid argument", "out of memory" etc -#define assert_status(p, status, msg) \ - do { \ - if (!(p)) { \ - char buf[128]; \ - snprintf(buf, 127, \ - "assert_status(" XSTR(p) ", error: %s(%d), \"" msg "\")" , \ - strerror((status)), (status)); \ - report_assertion_failure(__FILE__, __LINE__, buf); \ - BREAKPOINT; \ - } \ - } while (0) - -// Another version of assert where the message is not a string literal -// The boolean condition is not printed out because cpp doesn't like it. -#define assert_msg(p, msg) \ - if (!(p)) { \ - report_assertion_failure(__FILE__, __LINE__, msg); \ - BREAKPOINT; \ - } +#define assert_status(p, status, msg) \ +do { \ + if (!(p)) { \ + report_vm_error(__FILE__, __LINE__, "assert(" #p ") failed", \ + err_msg("error %s(%d) %s", strerror(status), \ + status, msg)); \ + BREAKPOINT; \ + } \ +} while (0) // Do not assert this condition if there's already another error reported. #define assert_if_no_error(cond,msg) assert((cond) || is_error_reported(), msg) -#else +#else // #ifdef ASSERT #define assert(p,msg) #define assert_status(p,status,msg) #define assert_if_no_error(cond,msg) - #define assert_msg(cond,msg) -#endif - - -// fatals -#define fatal(m) { report_fatal(__FILE__, __LINE__, m ); BREAKPOINT; } -#define fatal1(m,x1) { report_fatal_vararg(__FILE__, __LINE__, m, x1 ); BREAKPOINT; } -#define fatal2(m,x1,x2) { report_fatal_vararg(__FILE__, __LINE__, m, x1, x2 ); BREAKPOINT; } -#define fatal3(m,x1,x2,x3) { report_fatal_vararg(__FILE__, __LINE__, m, x1, x2, x3 ); BREAKPOINT; } -#define fatal4(m,x1,x2,x3,x4) { report_fatal_vararg(__FILE__, __LINE__, m, x1, x2, x3, x4 ); BREAKPOINT; } - -// out of memory -#define vm_exit_out_of_memory(s,m) { report_vm_out_of_memory(__FILE__, __LINE__, s, m ); BREAKPOINT; } -#define vm_exit_out_of_memory1(s,m,x1) { report_vm_out_of_memory_vararg(__FILE__, __LINE__, s, m, x1 ); BREAKPOINT; } -#define vm_exit_out_of_memory2(s,m,x1,x2) { report_vm_out_of_memory_vararg(__FILE__, __LINE__, s, m, x1, x2 ); BREAKPOINT; } -#define vm_exit_out_of_memory3(s,m,x1,x2,x3) { report_vm_out_of_memory_vararg(__FILE__, __LINE__, s, m, x1, x2, x3 ); BREAKPOINT; } -#define vm_exit_out_of_memory4(s,m,x1,x2,x3,x4) { report_vm_out_of_memory_vararg(__FILE__, __LINE__, s, m, x1, x2, x3, x4); BREAKPOINT; } +#endif // #ifdef ASSERT // guarantee is like assert except it's always executed -- use it for -// cheap tests that catch errors that would otherwise be hard to find +// cheap tests that catch errors that would otherwise be hard to find. // guarantee is also used for Verify options. -#define guarantee(b,msg) { if (!(b)) fatal("guarantee(" XSTR(b) ",\"" msg "\")"); } +#define guarantee(p, msg) \ +do { \ + if (!(p)) { \ + report_vm_error(__FILE__, __LINE__, "guarantee(" #p ") failed", msg); \ + BREAKPOINT; \ + } \ +} while (0) -#define ShouldNotCallThis() { report_should_not_call (__FILE__, __LINE__); BREAKPOINT; } -#define ShouldNotReachHere() { report_should_not_reach_here (__FILE__, __LINE__); BREAKPOINT; } -#define Unimplemented() { report_unimplemented (__FILE__, __LINE__); BREAKPOINT; } -#define Untested(msg) { report_untested (__FILE__, __LINE__, msg); BREAKPOINT; } +#define fatal(msg) \ +do { \ + report_fatal(__FILE__, __LINE__, msg); \ + BREAKPOINT; \ +} while (0) + +// out of memory +#define vm_exit_out_of_memory(size, msg) \ +do { \ + report_vm_out_of_memory(__FILE__, __LINE__, size, msg); \ + BREAKPOINT; \ +} while (0) + +#define ShouldNotCallThis() \ +do { \ + report_should_not_call(__FILE__, __LINE__); \ + BREAKPOINT; \ +} while (0) + +#define ShouldNotReachHere() \ +do { \ + report_should_not_reach_here(__FILE__, __LINE__); \ + BREAKPOINT; \ +} while (0) + +#define Unimplemented() \ +do { \ + report_unimplemented(__FILE__, __LINE__); \ + BREAKPOINT; \ +} while (0) + +#define Untested(msg) \ +do { \ + report_untested(__FILE__, __LINE__, msg); \ + BREAKPOINT; \ +} while (0); // error reporting helper functions -void report_assertion_failure(const char* file_name, int line_no, const char* message); -void report_fatal_vararg(const char* file_name, int line_no, const char* format, ...); -void report_fatal(const char* file_name, int line_no, const char* message); -void report_vm_out_of_memory_vararg(const char* file_name, int line_no, size_t size, const char* format, ...); -void report_vm_out_of_memory(const char* file_name, int line_no, size_t size, const char* message); -void report_should_not_call(const char* file_name, int line_no); -void report_should_not_reach_here(const char* file_name, int line_no); -void report_unimplemented(const char* file_name, int line_no); -void report_untested(const char* file_name, int line_no, const char* msg); +void report_vm_error(const char* file, int line, const char* error_msg, + const char* detail_msg = NULL); +void report_fatal(const char* file, int line, const char* message); +void report_vm_out_of_memory(const char* file, int line, size_t size, + const char* message); +void report_should_not_call(const char* file, int line); +void report_should_not_reach_here(const char* file, int line); +void report_unimplemented(const char* file, int line); +void report_untested(const char* file, int line, const char* message); + void warning(const char* format, ...); // out of memory reporting @@ -125,5 +164,8 @@ void report_java_out_of_memory(const char* message); bool is_error_reported(); void set_error_reported(); +/* Test assert(), fatal(), guarantee(), etc. */ +NOT_PRODUCT(void test_error_handler(size_t test_num);) + void pd_ps(frame f); void pd_obfuscate_location(char *buf, size_t buflen); diff --git a/hotspot/src/share/vm/utilities/exceptions.cpp b/hotspot/src/share/vm/utilities/exceptions.cpp index 70fbc289fca..290559f8953 100644 --- a/hotspot/src/share/vm/utilities/exceptions.cpp +++ b/hotspot/src/share/vm/utilities/exceptions.cpp @@ -378,7 +378,7 @@ ExceptionMark::~ExceptionMark() { void Exceptions::debug_check_abort(const char *value_string) { if (AbortVMOnException != NULL && value_string != NULL && strstr(value_string, AbortVMOnException)) { - fatal1("Saw %s, aborting", value_string); + fatal(err_msg("Saw %s, aborting", value_string)); } } diff --git a/hotspot/src/share/vm/utilities/macros.hpp b/hotspot/src/share/vm/utilities/macros.hpp index b4d7ea45743..a08e0950a38 100644 --- a/hotspot/src/share/vm/utilities/macros.hpp +++ b/hotspot/src/share/vm/utilities/macros.hpp @@ -188,6 +188,4 @@ #define NOT_SPARC(code) code #endif -#define FIX_THIS(code) report_assertion_failure("FIX_THIS",__FILE__, __LINE__, "") - #define define_pd_global(type, name, value) const type pd_##name = value; diff --git a/hotspot/src/share/vm/utilities/vmError.cpp b/hotspot/src/share/vm/utilities/vmError.cpp index a9013bace94..b28fab7184a 100644 --- a/hotspot/src/share/vm/utilities/vmError.cpp +++ b/hotspot/src/share/vm/utilities/vmError.cpp @@ -65,7 +65,8 @@ VMError::VMError(Thread* thread, int sig, address pc, void* siginfo, void* conte _current_step = 0; _current_step_info = NULL; - _message = ""; + _message = NULL; + _detail_msg = NULL; _filename = NULL; _lineno = 0; @@ -73,31 +74,36 @@ VMError::VMError(Thread* thread, int sig, address pc, void* siginfo, void* conte } // Constructor for internal errors -VMError::VMError(Thread* thread, const char* message, const char* filename, int lineno) { - _thread = thread; - _id = internal_error; // set it to a value that's not an OS exception/signal - _filename = filename; - _lineno = lineno; - _message = message; +VMError::VMError(Thread* thread, const char* filename, int lineno, + const char* message, const char * detail_msg) +{ + _thread = thread; + _id = internal_error; // Value that's not an OS exception/signal + _filename = filename; + _lineno = lineno; + _message = message; + _detail_msg = detail_msg; - _verbose = false; - _current_step = 0; - _current_step_info = NULL; + _verbose = false; + _current_step = 0; + _current_step_info = NULL; - _pc = NULL; - _siginfo = NULL; - _context = NULL; + _pc = NULL; + _siginfo = NULL; + _context = NULL; - _size = 0; + _size = 0; } // Constructor for OOM errors -VMError::VMError(Thread* thread, size_t size, const char* message, const char* filename, int lineno) { +VMError::VMError(Thread* thread, const char* filename, int lineno, size_t size, + const char* message) { _thread = thread; - _id = oom_error; // set it to a value that's not an OS exception/signal + _id = oom_error; // Value that's not an OS exception/signal _filename = filename; _lineno = lineno; _message = message; + _detail_msg = NULL; _verbose = false; _current_step = 0; @@ -114,10 +120,11 @@ VMError::VMError(Thread* thread, size_t size, const char* message, const char* f // Constructor for non-fatal errors VMError::VMError(const char* message) { _thread = NULL; - _id = internal_error; // set it to a value that's not an OS exception/signal + _id = internal_error; // Value that's not an OS exception/signal _filename = NULL; _lineno = 0; _message = message; + _detail_msg = NULL; _verbose = false; _current_step = 0; @@ -191,22 +198,27 @@ char* VMError::error_string(char* buf, int buflen) { "%s (0x%x) at pc=" PTR_FORMAT ", pid=%d, tid=" UINTX_FORMAT, signame, _id, _pc, os::current_process_id(), os::current_thread_id()); - } else { - if (_filename != NULL && _lineno > 0) { - // skip directory names - char separator = os::file_separator()[0]; - const char *p = strrchr(_filename, separator); - - jio_snprintf(buf, buflen, - "Internal Error at %s:%d, pid=%d, tid=" UINTX_FORMAT " \nError: %s", - p ? p + 1 : _filename, _lineno, - os::current_process_id(), os::current_thread_id(), - _message ? _message : ""); - } else { - jio_snprintf(buf, buflen, - "Internal Error (0x%x), pid=%d, tid=" UINTX_FORMAT, - _id, os::current_process_id(), os::current_thread_id()); + } else if (_filename != NULL && _lineno > 0) { + // skip directory names + char separator = os::file_separator()[0]; + const char *p = strrchr(_filename, separator); + int n = jio_snprintf(buf, buflen, + "Internal Error at %s:%d, pid=%d, tid=" UINTX_FORMAT, + p ? p + 1 : _filename, _lineno, + os::current_process_id(), os::current_thread_id()); + if (n >= 0 && n < buflen && _message) { + if (_detail_msg) { + jio_snprintf(buf + n, buflen - n, "%s%s: %s", + os::line_separator(), _message, _detail_msg); + } else { + jio_snprintf(buf + n, buflen - n, "%sError: %s", + os::line_separator(), _message); + } } + } else { + jio_snprintf(buf, buflen, + "Internal Error (0x%x), pid=%d, tid=" UINTX_FORMAT, + _id, os::current_process_id(), os::current_thread_id()); } return buf; @@ -369,7 +381,9 @@ void VMError::report(outputStream* st) { STEP(40, "(printing error message)") // error message - if (_message && _message[0] != '\0') { + if (_detail_msg) { + st->print_cr("# %s: %s", _message ? _message : "Error", _detail_msg); + } else if (_message) { st->print_cr("# Error: %s", _message); } diff --git a/hotspot/src/share/vm/utilities/vmError.hpp b/hotspot/src/share/vm/utilities/vmError.hpp index e3845b57386..9d83e42d2d1 100644 --- a/hotspot/src/share/vm/utilities/vmError.hpp +++ b/hotspot/src/share/vm/utilities/vmError.hpp @@ -37,6 +37,7 @@ class VMError : public StackObj { // 0x8xxxxxxx system warnings const char * _message; + const char * _detail_msg; Thread * _thread; // NULL if it's native thread @@ -75,16 +76,19 @@ class VMError : public StackObj { char* buf, int buflen, bool verbose = false); // accessor - const char* message() { return _message; } + const char* message() const { return _message; } + const char* detail_msg() const { return _detail_msg; } public: // Constructor for crashes VMError(Thread* thread, int sig, address pc, void* siginfo, void* context); // Constructor for VM internal errors - VMError(Thread* thread, const char* message, const char* filename, int lineno); + VMError(Thread* thread, const char* filename, int lineno, + const char* message, const char * detail_msg); - // Constructors for VM OOM errors - VMError(Thread* thread, size_t size, const char* message, const char* filename, int lineno); + // Constructor for VM OOM errors + VMError(Thread* thread, const char* filename, int lineno, size_t size, + const char* message); // Constructor for non-fatal errors VMError(const char* message); diff --git a/hotspot/test/runtime/6888954/vmerrors.sh b/hotspot/test/runtime/6888954/vmerrors.sh new file mode 100644 index 00000000000..d5db80a6f33 --- /dev/null +++ b/hotspot/test/runtime/6888954/vmerrors.sh @@ -0,0 +1,71 @@ +# @test +# @bug 6888954 +# @summary exercise HotSpot error handling code +# @author John Coomes +# @run shell vmerrors.sh + +# Repeatedly invoke java with a command-line option that causes HotSpot to +# produce an error report and terminate just after initialization. Each +# invocation is identified by a small integer, , which provokes a different +# error (assertion failure, guarantee failure, fatal error, etc.). The output +# from stdout/stderr is written to .out and the hs_err_pidXXX.log file is +# renamed to .log. +# +# The automated checking done by this script is minimal. When updating the +# fatal error handler it is more useful to run it manually or to use the -retain +# option with the jtreg so that test directories are not removed automatically. +# To run stand-alone: +# +# TESTJAVA=/java/home/dir +# TESTVMOPTS=... +# export TESTJAVA TESTVMOPTS +# sh test/runtime/6888954/vmerrors.sh + +ulimit -c 0 # no core files + +i=1 +rc=0 + +assert_re='(assert|guarantee)[(](str|num).*failed: *' +guarantee_re='guarantee[(](str|num).*failed: *' +fatal_re='fatal error: *' +signal_re='(SIGSEGV|EXCEPTION_ACCESS_VIOLATION).* at pc=' +tail_1='.*expected null' +tail_2='.*num=' + +for re in \ + "${assert_re}${tail_1}" "${assert_re}${tail_2}" \ + "${guarantee_re}${tail_1}" "${guarantee_re}${tail_2}" \ + "${fatal_re}${tail_1}" "${fatal_re}${tail_2}" \ + "${fatal_re}.*truncated" "ChunkPool::allocate" \ + "ShouldNotCall" "ShouldNotReachHere" \ + "Unimplemented" "$signal_re" + +do + i2=$i + [ $i -lt 10 ] && i2=0$i + + "$TESTJAVA/bin/java" $TESTVMOPTS -XX:+IgnoreUnrecognizedVMOptions \ + -XX:ErrorHandlerTest=${i} -version > ${i2}.out 2>&1 + + # If ErrorHandlerTest is ignored (product build), stop. + # + # Using the built-in variable $! to get the pid does not work reliably on + # windows; use a wildcard instead. + mv hs_err_pid*.log ${i2}.log || exit $rc + + for f in ${i2}.log ${i2}.out + do + egrep -- "$re" $f > $$ + if [ $? -ne 0 ] + then + echo "ErrorHandlerTest=$i failed ($f)" + rc=1 + fi + done + rm -f $$ + + i=$(expr $i + 1) +done + +exit $rc From 77a56e5d33e82d4128ac36861c3704223821f888 Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Tue, 27 Apr 2010 09:42:51 +0100 Subject: [PATCH 08/54] 6718504: IN6_IS_ADDR_ANY tests only 12 bytes of 16-byte address Reviewed-by: alanb --- jdk/src/windows/native/java/net/net_util_md.h | 3 +- .../DatagramSocket/LocalSocketAddress.java | 71 +++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 jdk/test/java/net/DatagramSocket/LocalSocketAddress.java diff --git a/jdk/src/windows/native/java/net/net_util_md.h b/jdk/src/windows/native/java/net/net_util_md.h index 23574f1725f..679fbfc08d4 100644 --- a/jdk/src/windows/native/java/net/net_util_md.h +++ b/jdk/src/windows/native/java/net/net_util_md.h @@ -222,7 +222,8 @@ LPFN_GETNAMEINFO getnameinfo_ptr; #define IN6_IS_ADDR_ANY(a) \ (((a)->s6_words[0] == 0) && ((a)->s6_words[1] == 0) && \ ((a)->s6_words[2] == 0) && ((a)->s6_words[3] == 0) && \ - ((a)->s6_words[4] == 0) && ((a)->s6_words[5] == 0)) + ((a)->s6_words[4] == 0) && ((a)->s6_words[5] == 0) && \ + ((a)->s6_words[6] == 0) && ((a)->s6_words[7] == 0)) #endif #ifndef IPV6_V6ONLY diff --git a/jdk/test/java/net/DatagramSocket/LocalSocketAddress.java b/jdk/test/java/net/DatagramSocket/LocalSocketAddress.java new file mode 100644 index 00000000000..bf20cf17283 --- /dev/null +++ b/jdk/test/java/net/DatagramSocket/LocalSocketAddress.java @@ -0,0 +1,71 @@ +/* + * Copyright 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 + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 6718504 + * @summary IN6_IS_ADDR_ANY tests only 12 bytes of 16-byte address + */ + +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.Inet6Address; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.util.*; + +public class LocalSocketAddress { + public static void main(String[] args) throws SocketException { + InetAddress IPv6LoopbackAddr = null; + DatagramSocket soc = null; + + try { + List nics = Collections.list(NetworkInterface.getNetworkInterfaces()); + for (NetworkInterface nic : nics) { + if (!nic.isLoopback()) + continue; + + List addrs = Collections.list(nic.getInetAddresses()); + for (InetAddress addr : addrs) { + if (addr instanceof Inet6Address) { + IPv6LoopbackAddr = addr; + break; + } + } + } + + if (IPv6LoopbackAddr == null) { + System.out.println("IPv6 is not available, exiting test."); + return; + } + + soc = new DatagramSocket(0, IPv6LoopbackAddr); + + if (!IPv6LoopbackAddr.equals(soc.getLocalAddress())) { + throw new RuntimeException("Bound address is " + soc.getLocalAddress() + + ", but should be " + IPv6LoopbackAddr); + } + } finally { + if (soc != null) { soc.close(); } + } + } +} From d052130c49573b0212a3cf1250284a7e6e6f605c Mon Sep 17 00:00:00 2001 From: Artem Ananiev Date: Tue, 27 Apr 2010 18:08:26 +0400 Subject: [PATCH 09/54] 6880336: SwingWorker deadlocks due one thread in the swingworker-pool Reviewed-by: dcherepanov, alexp --- .../classes/javax/swing/SwingWorker.java | 11 +-- .../SwingWorker/6880336/NestedWorkers.java | 72 +++++++++++++++++++ 2 files changed, 78 insertions(+), 5 deletions(-) create mode 100644 jdk/test/javax/swing/SwingWorker/6880336/NestedWorkers.java diff --git a/jdk/src/share/classes/javax/swing/SwingWorker.java b/jdk/src/share/classes/javax/swing/SwingWorker.java index 263284acc4e..ebeeb639112 100644 --- a/jdk/src/share/classes/javax/swing/SwingWorker.java +++ b/jdk/src/share/classes/javax/swing/SwingWorker.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-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 @@ -42,9 +42,10 @@ import sun.awt.AppContext; import sun.swing.AccumulativeRunnable; /** - * An abstract class to perform lengthy GUI-interacting tasks in a - * dedicated thread. - * + * An abstract class to perform lengthy GUI-interaction tasks in a + * background thread. Several background threads can be used to execute such + * tasks. However, the exact strategy of choosing a thread for any particular + * {@code SwingWorker} is unspecified and should not be relied on. *

* When writing a multi-threaded application using Swing, there are * two constraints to keep in mind: @@ -772,7 +773,7 @@ public abstract class SwingWorker implements RunnableFuture { }; executorService = - new ThreadPoolExecutor(1, MAX_WORKER_THREADS, + new ThreadPoolExecutor(MAX_WORKER_THREADS, MAX_WORKER_THREADS, 10L, TimeUnit.MINUTES, new LinkedBlockingQueue(), threadFactory); diff --git a/jdk/test/javax/swing/SwingWorker/6880336/NestedWorkers.java b/jdk/test/javax/swing/SwingWorker/6880336/NestedWorkers.java new file mode 100644 index 00000000000..1df1dbd1834 --- /dev/null +++ b/jdk/test/javax/swing/SwingWorker/6880336/NestedWorkers.java @@ -0,0 +1,72 @@ +/* + * Copyright 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 + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 6880336 + * @summary Test for nested SwingWorkers, i.e. when the second worker is +started from the first's doInBackground() method. A timeout when running +* this test is an indication of failure. + * @author Artem Ananiev + * @run main/timeout=32 NestedWorkers + */ + +import javax.swing.*; + +public class NestedWorkers extends SwingWorker { + + private final static int MAX_LEVEL = 2; + + private int level; + + public NestedWorkers(int level) { + super(); + this.level = level; + } + + @Override + public String doInBackground() throws Exception { + if (level < MAX_LEVEL) { + SwingWorker nested = new NestedWorkers(level + 1); + nested.execute(); + nested.get(); + } + System.out.println("doInBackground " + level + " is complete"); + return String.valueOf(level); + } + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + SwingWorker sw = new NestedWorkers(0); + sw.execute(); + try { + System.err.println(sw.get()); + } catch (Exception z) { + throw new RuntimeException(z); + } + } + }); + } + +} From c21ea1a6d8cc5202eab80efca1d036e40e631aec Mon Sep 17 00:00:00 2001 From: Costantino Cerbo Date: Wed, 28 Apr 2010 17:16:05 +0400 Subject: [PATCH 10/54] 6913179: The java.awt.FileDialog should use native GTK file chooser on linux distros Introduce a GTK-based alternative implementation of the FileDialogPeer on X11 Reviewed-by: anthony, peterz --- jdk/make/sun/xawt/FILES_c_unix.gmk | 3 +- jdk/make/sun/xawt/FILES_export_unix.gmk | 3 +- jdk/make/sun/xawt/mapfile-vers | 4 + .../solaris/classes/sun/awt/UNIXToolkit.java | 23 ++ .../sun/awt/X11/GtkFileDialogPeer.java | 134 +++++++++++ .../solaris/classes/sun/awt/X11/XToolkit.java | 4 +- .../solaris/native/sun/awt/awt_UNIXToolkit.c | 20 ++ .../solaris/native/sun/awt/gtk2_interface.c | 87 ++++++- .../solaris/native/sun/awt/gtk2_interface.h | 133 ++++++++++- .../sun/awt/sun_awt_X11_GtkFileDialogPeer.c | 225 ++++++++++++++++++ .../sun/awt/sun_awt_X11_GtkFileDialogPeer.h | 31 +++ .../solaris/native/sun/awt/swing_GTKEngine.c | 44 +++- .../solaris/native/sun/awt/swing_GTKStyle.c | 30 ++- 13 files changed, 725 insertions(+), 16 deletions(-) create mode 100644 jdk/src/solaris/classes/sun/awt/X11/GtkFileDialogPeer.java create mode 100644 jdk/src/solaris/native/sun/awt/sun_awt_X11_GtkFileDialogPeer.c create mode 100644 jdk/src/solaris/native/sun/awt/sun_awt_X11_GtkFileDialogPeer.h diff --git a/jdk/make/sun/xawt/FILES_c_unix.gmk b/jdk/make/sun/xawt/FILES_c_unix.gmk index 604955e1e6e..5edc187388e 100644 --- a/jdk/make/sun/xawt/FILES_c_unix.gmk +++ b/jdk/make/sun/xawt/FILES_c_unix.gmk @@ -79,4 +79,5 @@ FILES_c = \ gtk2_interface.c \ swing_GTKEngine.c \ swing_GTKStyle.c \ - rect.c + rect.c \ + sun_awt_X11_GtkFileDialogPeer.c diff --git a/jdk/make/sun/xawt/FILES_export_unix.gmk b/jdk/make/sun/xawt/FILES_export_unix.gmk index f09f83242a9..bade1544e0e 100644 --- a/jdk/make/sun/xawt/FILES_export_unix.gmk +++ b/jdk/make/sun/xawt/FILES_export_unix.gmk @@ -33,4 +33,5 @@ FILES_export = \ sun/awt/X11/XDesktopPeer.java \ sun/awt/X11/XToolkit.java \ sun/awt/X11/XComponentPeer.java \ - sun/awt/X11/XInputMethod.java + sun/awt/X11/XInputMethod.java \ + sun/awt/X11/GtkFileDialogPeer.java diff --git a/jdk/make/sun/xawt/mapfile-vers b/jdk/make/sun/xawt/mapfile-vers index 82fe94f63ec..aee09457fb1 100644 --- a/jdk/make/sun/xawt/mapfile-vers +++ b/jdk/make/sun/xawt/mapfile-vers @@ -172,6 +172,7 @@ SUNWprivate_1.1 { Java_sun_awt_UNIXToolkit_load_1stock_1icon; Java_sun_awt_UNIXToolkit_load_1gtk_1icon; Java_sun_awt_UNIXToolkit_nativeSync; + Java_sun_awt_UNIXToolkit_gtkCheckVersionImpl; Java_java_awt_AWTEvent_initIDs; Java_java_awt_event_InputEvent_initIDs; Java_java_awt_event_KeyEvent_initIDs; @@ -396,6 +397,9 @@ SUNWprivate_1.1 { Java_com_sun_java_swing_plaf_gtk_GTKStyle_nativeGetClassValue; Java_com_sun_java_swing_plaf_gtk_GTKStyle_nativeGetPangoFontName; + Java_sun_awt_X11_GtkFileDialogPeer_run; + Java_sun_awt_X11_GtkFileDialogPeer_quit; + Java_sun_print_CUPSPrinter_initIDs; Java_sun_print_CUPSPrinter_getCupsServer; Java_sun_print_CUPSPrinter_getCupsPort; diff --git a/jdk/src/solaris/classes/sun/awt/UNIXToolkit.java b/jdk/src/solaris/classes/sun/awt/UNIXToolkit.java index 23e39cabe49..c35e4859c80 100644 --- a/jdk/src/solaris/classes/sun/awt/UNIXToolkit.java +++ b/jdk/src/solaris/classes/sun/awt/UNIXToolkit.java @@ -314,4 +314,27 @@ public abstract class UNIXToolkit extends SunToolkit } return new RenderingHints(KEY_TEXT_ANTIALIASING, aaHint); } + + private native boolean gtkCheckVersionImpl(int major, int minor, + int micro); + + /** + * Returns {@code true} if the GTK+ library is compatible with the given + * version. + * + * @param major + * The required major version. + * @param minor + * The required minor version. + * @param micro + * The required micro version. + * @return {@code true} if the GTK+ library is compatible with the given + * version. + */ + public boolean checkGtkVersion(int major, int minor, int micro) { + if (loadGTK()) { + return gtkCheckVersionImpl(major, minor, micro); + } + return false; + } } diff --git a/jdk/src/solaris/classes/sun/awt/X11/GtkFileDialogPeer.java b/jdk/src/solaris/classes/sun/awt/X11/GtkFileDialogPeer.java new file mode 100644 index 00000000000..5860b396b61 --- /dev/null +++ b/jdk/src/solaris/classes/sun/awt/X11/GtkFileDialogPeer.java @@ -0,0 +1,134 @@ +/* + * Copyright 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package sun.awt.X11; + +import java.awt.Dialog; +import java.awt.FileDialog; +import java.awt.peer.FileDialogPeer; +import java.io.File; +import java.io.FilenameFilter; +import javax.swing.SwingUtilities; +import javax.swing.SwingWorker; +import sun.awt.AWTAccessor; + +/** + * FileDialogPeer for the GtkFileChooser. + * + * @author Costantino Cerbo (c.cerbo@gmail.com) + */ +class GtkFileDialogPeer extends XDialogPeer implements FileDialogPeer { + + private FileDialog fd; + + public GtkFileDialogPeer(FileDialog fd) { + super((Dialog) fd); + this.fd = fd; + } + + private native void run(String title, int mode, String dir, String file, + FilenameFilter filter, boolean isMultipleMode); + + private native void quit(); + + /** + * Called exclusively by the native C code. + */ + private void setFileInternal(String directory, String[] filenames) { + AWTAccessor.FileDialogAccessor accessor = AWTAccessor + .getFileDialogAccessor(); + + if (filenames == null) { + accessor.setDirectory(fd, null); + accessor.setFile(fd, null); + accessor.setFiles(fd, null, null); + } else { + accessor.setDirectory(fd, directory); + accessor.setFile(fd, filenames[0]); + accessor.setFiles(fd, directory, filenames); + } + } + + /** + * Called exclusively by the native C code. + */ + private boolean filenameFilterCallback(String fullname) { + if (fd.getFilenameFilter() == null) { + // no filter, accept all. + return true; + } + + File filen = new File(fullname); + return fd.getFilenameFilter().accept(new File(filen.getParent()), + filen.getName()); + } + + @Override + public void setVisible(boolean b) { + XToolkit.awtLock(); + try { + if (b) { + Thread t = new Thread() { + public void run() { + GtkFileDialogPeer.this.run(fd.getTitle(), fd.getMode(), + fd.getDirectory(), fd.getFile(), fd + .getFilenameFilter(), fd + .isMultipleMode()); + fd.setVisible(false); + } + }; + t.start(); + } else { + quit(); + fd.setVisible(false); + } + } finally { + XToolkit.awtUnlock(); + } + } + + @Override + public void dispose() { + quit(); + super.dispose(); + } + + @Override + public void setDirectory(String dir) { + // We do not implement this method because we + // have delegated to FileDialog#setDirectory + } + + @Override + public void setFile(String file) { + // We do not implement this method because we + // have delegated to FileDialog#setFile + } + + @Override + public void setFilenameFilter(FilenameFilter filter) { + // We do not implement this method because we + // have delegated to FileDialog#setFilenameFilter + } +} diff --git a/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java b/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java index 8676c6affb9..4ab6cd21960 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java @@ -1041,7 +1041,9 @@ public final class XToolkit extends UNIXToolkit implements Runnable { } public FileDialogPeer createFileDialog(FileDialog target) { - FileDialogPeer peer = new XFileDialogPeer(target); + // The current GtkFileChooser is available from GTK+ 2.4 + FileDialogPeer peer = checkGtkVersion(2, 4, 0) ? new GtkFileDialogPeer( + target) : new XFileDialogPeer(target); targetCreatedPeer(target, peer); return peer; } diff --git a/jdk/src/solaris/native/sun/awt/awt_UNIXToolkit.c b/jdk/src/solaris/native/sun/awt/awt_UNIXToolkit.c index f802f9f7c68..b315832b106 100644 --- a/jdk/src/solaris/native/sun/awt/awt_UNIXToolkit.c +++ b/jdk/src/solaris/native/sun/awt/awt_UNIXToolkit.c @@ -260,3 +260,23 @@ Java_sun_awt_SunToolkit_closeSplashScreen(JNIEnv *env, jclass cls) } dlclose(hSplashLib); } + +/* + * Class: sun_awt_UNIXToolkit + * Method: gtkCheckVersionImpl + * Signature: (III)Ljava/lang/String; + */ +JNIEXPORT jboolean JNICALL +Java_sun_awt_UNIXToolkit_gtkCheckVersionImpl(JNIEnv *env, jobject this, + jint major, jint minor, jint micro) +{ + char *ret; + + ret = fp_gtk_check_version(major, minor, micro); + if (ret == NULL) { + return TRUE; + } + + free(ret); + return FALSE; +} diff --git a/jdk/src/solaris/native/sun/awt/gtk2_interface.c b/jdk/src/solaris/native/sun/awt/gtk2_interface.c index e6ede306824..dfa7ef1dfb4 100644 --- a/jdk/src/solaris/native/sun/awt/gtk2_interface.c +++ b/jdk/src/solaris/native/sun/awt/gtk2_interface.c @@ -32,6 +32,7 @@ #include "java_awt_Transparency.h" #define GTK2_LIB "libgtk-x11-2.0.so.0" +#define GTHREAD_LIB "libgthread-2.0.so.0" #define G_TYPE_INVALID G_TYPE_MAKE_FUNDAMENTAL (0) #define G_TYPE_NONE G_TYPE_MAKE_FUNDAMENTAL (1) @@ -75,6 +76,7 @@ const gint SELECTED = 1 << 9; const gint DEFAULT = 1 << 10; static void *gtk2_libhandle = NULL; +static void *gthread_libhandle = NULL; static jmp_buf j; /* Widgets */ @@ -150,7 +152,6 @@ static GtkWidget *gtk2_widgets[_GTK_WIDGET_TYPE_SIZE]; /************************* * Glib function pointers *************************/ -static void (*fp_g_free)(gpointer mem); static gboolean (*fp_g_main_context_iteration)(GMainContext *context, gboolean may_block); @@ -204,9 +205,6 @@ static void (*fp_gdk_drawable_get_size)(GdkDrawable *drawable, /************************ * Gtk function pointers ************************/ -static gchar* (*fp_gtk_check_version)(guint required_major, - guint required_minor, - guint required_micro); static gboolean (*fp_gtk_init_check)(int* argc, char** argv); /* Painting */ @@ -330,7 +328,6 @@ static void (*fp_gtk_menu_shell_append)(GtkMenuShell *menu_shell, static void (*fp_gtk_menu_item_set_submenu)(GtkMenuItem *menu_item, GtkWidget *submenu); static void (*fp_gtk_widget_realize)(GtkWidget *widget); -static void (*fp_gtk_widget_destroy)(GtkWidget *widget); static GdkPixbuf* (*fp_gtk_widget_render_icon)(GtkWidget *widget, const gchar *stock_id, GtkIconSize size, const gchar *detail); static void (*fp_gtk_widget_set_name)(GtkWidget *widget, const gchar *name); @@ -388,6 +385,15 @@ static void* dl_symbol(const char* name) return result; } +static void* dl_symbol_gthread(const char* name) +{ + void* result = dlsym(gthread_libhandle, name); + if (!result) + longjmp(j, NO_SYMBOL_EXCEPTION); + + return result; +} + gboolean gtk2_check_version() { if (gtk2_libhandle != NULL) { @@ -414,6 +420,33 @@ gboolean gtk2_check_version() } } +/** + * Functions for sun_awt_X11_GtkFileDialogPeer.c + */ +void gtk2_file_chooser_load() +{ + fp_gtk_file_chooser_get_filename = dl_symbol( + "gtk_file_chooser_get_filename"); + fp_gtk_file_chooser_dialog_new = dl_symbol("gtk_file_chooser_dialog_new"); + fp_gtk_file_chooser_set_current_folder = dl_symbol( + "gtk_file_chooser_set_current_folder"); + fp_gtk_file_chooser_set_filename = dl_symbol( + "gtk_file_chooser_set_filename"); + fp_gtk_file_filter_add_custom = dl_symbol("gtk_file_filter_add_custom"); + fp_gtk_file_chooser_set_filter = dl_symbol("gtk_file_chooser_set_filter"); + fp_gtk_file_chooser_get_type = dl_symbol("gtk_file_chooser_get_type"); + fp_gtk_file_filter_new = dl_symbol("gtk_file_filter_new"); + fp_gtk_file_chooser_set_do_overwrite_confirmation = dl_symbol( + "gtk_file_chooser_set_do_overwrite_confirmation"); + fp_gtk_file_chooser_set_select_multiple = dl_symbol( + "gtk_file_chooser_set_select_multiple"); + fp_gtk_file_chooser_get_current_folder = dl_symbol( + "gtk_file_chooser_get_current_folder"); + fp_gtk_file_chooser_get_filenames = dl_symbol( + "gtk_file_chooser_get_filenames"); + fp_gtk_g_slist_length = dl_symbol("g_slist_length"); +} + gboolean gtk2_load() { gboolean result; @@ -423,7 +456,9 @@ gboolean gtk2_load() char *gtk_modules_env; gtk2_libhandle = dlopen(GTK2_LIB, RTLD_LAZY | RTLD_LOCAL); - if (gtk2_libhandle == NULL) + gthread_libhandle = dlopen(GTHREAD_LIB, RTLD_LAZY | RTLD_LOCAL); + + if (gtk2_libhandle == NULL || gthread_libhandle == NULL) return FALSE; if (setjmp(j) == 0) @@ -597,6 +632,30 @@ gboolean gtk2_load() fp_gtk_range_get_adjustment = dl_symbol("gtk_range_get_adjustment"); + fp_gtk_widget_hide = dl_symbol("gtk_widget_hide"); + fp_gtk_main_quit = dl_symbol("gtk_main_quit"); + fp_g_signal_connect_data = dl_symbol("g_signal_connect_data"); + fp_gtk_widget_show = dl_symbol("gtk_widget_show"); + fp_gtk_main = dl_symbol("gtk_main"); + + /** + * GLib thread system + */ + fp_g_thread_get_initialized = dl_symbol_gthread( + "g_thread_get_initialized"); + fp_g_thread_init = dl_symbol_gthread("g_thread_init"); + fp_gdk_threads_init = dl_symbol("gdk_threads_init"); + fp_gdk_threads_enter = dl_symbol("gdk_threads_enter"); + fp_gdk_threads_leave = dl_symbol("gdk_threads_leave"); + + /** + * Functions for sun_awt_X11_GtkFileDialogPeer.c + */ + if (fp_gtk_check_version(2, 4, 0) == NULL) { + // The current GtkFileChooser is available from GTK+ 2.4 + gtk2_file_chooser_load(); + } + /* Some functions may be missing in pre-2.4 GTK. We handle them specially here. */ @@ -626,6 +685,10 @@ gboolean gtk2_load() { dlclose(gtk2_libhandle); gtk2_libhandle = NULL; + + dlclose(gthread_libhandle); + gthread_libhandle = NULL; + return FALSE; } @@ -678,6 +741,17 @@ gboolean gtk2_load() */ handler = XSetErrorHandler(NULL); io_handler = XSetIOErrorHandler(NULL); + + if (fp_gtk_check_version(2, 2, 0) == NULL) { + // Init the thread system to use GLib in a thread-safe mode + if (!fp_g_thread_get_initialized()) { + fp_g_thread_init(NULL); + + //According the GTK documentation, gdk_threads_init() should be + //called before gtk_init() or gtk_init_check() + fp_gdk_threads_init(); + } + } result = (*fp_gtk_init_check)(NULL, NULL); XSetErrorHandler(handler); @@ -722,6 +796,7 @@ int gtk2_unload() dlerror(); dlclose(gtk2_libhandle); + dlclose(gthread_libhandle); if ((gtk2_error = dlerror()) != NULL) { return FALSE; diff --git a/jdk/src/solaris/native/sun/awt/gtk2_interface.h b/jdk/src/solaris/native/sun/awt/gtk2_interface.h index bde5ec1bc19..95ca3cecaad 100644 --- a/jdk/src/solaris/native/sun/awt/gtk2_interface.h +++ b/jdk/src/solaris/native/sun/awt/gtk2_interface.h @@ -28,6 +28,21 @@ #include #include +#define _G_TYPE_CIC(ip, gt, ct) ((ct*) ip) +#define G_TYPE_CHECK_INSTANCE_CAST(instance, g_type, c_type) (_G_TYPE_CIC ((instance), (g_type), c_type)) +#define GTK_TYPE_FILE_CHOOSER (fp_gtk_file_chooser_get_type ()) +#define GTK_FILE_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_FILE_CHOOSER, GtkFileChooser)) +#define fp_g_signal_connect(instance, detailed_signal, c_handler, data) \ + fp_g_signal_connect_data ((instance), (detailed_signal), (c_handler), (data), NULL, (GConnectFlags) 0) +#define G_CALLBACK(f) ((GCallback) (f)) +#define G_TYPE_FUNDAMENTAL_SHIFT (2) +#define G_TYPE_MAKE_FUNDAMENTAL(x) ((GType) ((x) << G_TYPE_FUNDAMENTAL_SHIFT)) +#define G_TYPE_OBJECT G_TYPE_MAKE_FUNDAMENTAL (20) +#define G_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), G_TYPE_OBJECT, GObject)) +#define GTK_STOCK_CANCEL "gtk-cancel" +#define GTK_STOCK_SAVE "gtk-save" +#define GTK_STOCK_OPEN "gtk-open" + typedef enum _WidgetType { BUTTON, /* GtkButton */ @@ -254,7 +269,13 @@ typedef enum /* We define all structure pointers to be void* */ typedef void GError; typedef void GMainContext; -typedef void GSList; + +typedef struct _GSList GSList; +struct _GSList +{ + gpointer data; + GSList *next; +}; typedef void GdkColormap; typedef void GdkDrawable; @@ -556,6 +577,65 @@ struct _GtkProgressBar guint ellipsize : 3; }; +typedef enum { + GTK_RESPONSE_NONE = -1, + GTK_RESPONSE_REJECT = -2, + GTK_RESPONSE_ACCEPT = -3, + GTK_RESPONSE_DELETE_EVENT = -4, + GTK_RESPONSE_OK = -5, + GTK_RESPONSE_CANCEL = -6, + GTK_RESPONSE_CLOSE = -7, + GTK_RESPONSE_YES = -8, + GTK_RESPONSE_NO = -9, + GTK_RESPONSE_APPLY = -10, + GTK_RESPONSE_HELP = -11 +} GtkResponseType; + +typedef struct _GtkWindow GtkWindow; + +typedef struct _GtkFileChooser GtkFileChooser; + +typedef enum { + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, + GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER +} GtkFileChooserAction; + +typedef struct _GtkFileFilter GtkFileFilter; + +typedef enum { + GTK_FILE_FILTER_FILENAME = 1 << 0, + GTK_FILE_FILTER_URI = 1 << 1, + GTK_FILE_FILTER_DISPLAY_NAME = 1 << 2, + GTK_FILE_FILTER_MIME_TYPE = 1 << 3 +} GtkFileFilterFlags; + +typedef struct { + GtkFileFilterFlags contains; + const gchar *filename; + const gchar *uri; + const gchar *display_name; + const gchar *mime_type; +} GtkFileFilterInfo; + +typedef gboolean (*GtkFileFilterFunc)(const GtkFileFilterInfo *filter_info, + gpointer data); + +typedef void (*GDestroyNotify)(gpointer data); + +typedef void (*GCallback)(void); + +typedef struct _GClosure GClosure; + +typedef void (*GClosureNotify)(gpointer data, GClosure *closure); + +typedef enum { + G_CONNECT_AFTER = 1 << 0, G_CONNECT_SWAPPED = 1 << 1 +} GConnectFlags; + +typedef struct _GThreadFunctions GThreadFunctions; + /* * Converts java.lang.String object to UTF-8 character string. */ @@ -569,6 +649,13 @@ const char *getStrFor(JNIEnv *env, jstring value); */ gboolean gtk2_check_version(); +/** + * Returns : + * NULL if the GTK+ library is compatible with the given version, or a string + * describing the version mismatch. + */ +gchar* (*fp_gtk_check_version)(guint required_major, guint required_minor, + guint required_micro); /* * Load the gtk2 library. If the library is already loaded this method has no * effect and returns success. @@ -651,6 +738,7 @@ jobject gtk2_get_setting(JNIEnv *env, Setting property); void gtk2_set_range_value(WidgetType widget_type, jdouble value, jdouble min, jdouble max, jdouble visible); +void (*fp_g_free)(gpointer mem); void (*fp_g_object_unref)(gpointer object); int (*fp_gdk_pixbuf_get_bits_per_sample)(const GdkPixbuf *pixbuf); guchar *(*fp_gdk_pixbuf_get_pixels)(const GdkPixbuf *pixbuf); @@ -660,5 +748,48 @@ int (*fp_gdk_pixbuf_get_n_channels)(const GdkPixbuf *pixbuf); int (*fp_gdk_pixbuf_get_rowstride)(const GdkPixbuf *pixbuf); int (*fp_gdk_pixbuf_get_width)(const GdkPixbuf *pixbuf); GdkPixbuf *(*fp_gdk_pixbuf_new_from_file)(const char *filename, GError **error); +void (*fp_gtk_widget_destroy)(GtkWidget *widget); + + +/** + * Function Pointers for GtkFileChooser + */ +gchar* (*fp_gtk_file_chooser_get_filename)(GtkFileChooser *chooser); +void (*fp_gtk_widget_hide)(GtkWidget *widget); +void (*fp_gtk_main_quit)(void); +GtkWidget* (*fp_gtk_file_chooser_dialog_new)(const gchar *title, + GtkWindow *parent, GtkFileChooserAction action, + const gchar *first_button_text, ...); +gboolean (*fp_gtk_file_chooser_set_current_folder)(GtkFileChooser *chooser, + const gchar *filename); +gboolean (*fp_gtk_file_chooser_set_filename)(GtkFileChooser *chooser, + const char *filename); +void (*fp_gtk_file_filter_add_custom)(GtkFileFilter *filter, + GtkFileFilterFlags needed, GtkFileFilterFunc func, gpointer data, + GDestroyNotify notify); +void (*fp_gtk_file_chooser_set_filter)(GtkFileChooser *chooser, + GtkFileFilter *filter); +GType (*fp_gtk_file_chooser_get_type)(void); +GtkFileFilter* (*fp_gtk_file_filter_new)(void); +void (*fp_gtk_file_chooser_set_do_overwrite_confirmation)( + GtkFileChooser *chooser, gboolean do_overwrite_confirmation); +void (*fp_gtk_file_chooser_set_select_multiple)( + GtkFileChooser *chooser, gboolean select_multiple); +gchar* (*fp_gtk_file_chooser_get_current_folder)(GtkFileChooser *chooser); +GSList* (*fp_gtk_file_chooser_get_filenames)(GtkFileChooser *chooser); +guint (*fp_gtk_g_slist_length)(GSList *list); +gulong (*fp_g_signal_connect_data)(gpointer instance, + const gchar *detailed_signal, GCallback c_handler, gpointer data, + GClosureNotify destroy_data, GConnectFlags connect_flags); +void (*fp_gtk_widget_show)(GtkWidget *widget); +void (*fp_gtk_main)(void); +guint (*fp_gtk_main_level)(void); + + +gboolean (*fp_g_thread_get_initialized)(void); +void (*fp_g_thread_init)(GThreadFunctions *vtable); +void (*fp_gdk_threads_init)(void); +void (*fp_gdk_threads_enter)(void); +void (*fp_gdk_threads_leave)(void); #endif /* !_GTK2_INTERFACE_H */ diff --git a/jdk/src/solaris/native/sun/awt/sun_awt_X11_GtkFileDialogPeer.c b/jdk/src/solaris/native/sun/awt/sun_awt_X11_GtkFileDialogPeer.c new file mode 100644 index 00000000000..717a38382d7 --- /dev/null +++ b/jdk/src/solaris/native/sun/awt/sun_awt_X11_GtkFileDialogPeer.c @@ -0,0 +1,225 @@ +#include +#include +#include +#include +#include "gtk2_interface.h" +#include "sun_awt_X11_GtkFileDialogPeer.h" + +static JavaVM *jvm; +static GtkWidget *dialog = NULL; + +/* To cache some method IDs */ +static jmethodID filenameFilterCallbackMethodID = NULL; +static jmethodID setFileInternalMethodID = NULL; + +static gboolean filenameFilterCallback(const GtkFileFilterInfo * filter_info, gpointer obj) +{ + JNIEnv *env; + jclass cx; + jstring filename; + + env = (JNIEnv *) JNU_GetEnv(jvm, JNI_VERSION_1_2); + + if (filenameFilterCallbackMethodID == NULL) { + cx = (*env)->GetObjectClass(env, (jobject) obj); + if (cx == NULL) { + JNU_ThrowInternalError(env, "Could not get file filter class"); + return 0; + } + + filenameFilterCallbackMethodID = (*env)->GetMethodID(env, cx, + "filenameFilterCallback", "(Ljava/lang/String;)Z"); + if (filenameFilterCallbackMethodID == NULL) { + JNU_ThrowInternalError(env, + "Could not get filenameFilterCallback method id"); + return 0; + } + } + + filename = (*env)->NewStringUTF(env, filter_info->filename); + + return (*env)->CallBooleanMethod(env, obj, filenameFilterCallbackMethodID, + filename); +} + +/* + * Class: sun_awt_X11_GtkFileDialogPeer + * Method: quit + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_sun_awt_X11_GtkFileDialogPeer_quit +(JNIEnv * env, jobject jpeer) +{ + if (dialog != NULL) + { + fp_gtk_widget_hide (dialog); + fp_gtk_widget_destroy (dialog); + + fp_gtk_main_quit (); + dialog = NULL; + } +} + +/** + * Convert a GSList to an array of filenames (without the parent folder) + */ +static jobjectArray toFilenamesArray(JNIEnv *env, GSList* list) +{ + jstring str; + jclass stringCls; + GSList *iterator; + jobjectArray array; + int i; + char* entry; + + if (NULL == list) { + return NULL; + } + + stringCls = (*env)->FindClass(env, "java/lang/String"); + if (stringCls == NULL) { + JNU_ThrowInternalError(env, "Could not get java.lang.String class"); + return NULL; + } + + array = (*env)->NewObjectArray(env, fp_gtk_g_slist_length(list), stringCls, + NULL); + if (array == NULL) { + JNU_ThrowInternalError(env, "Could not instantiate array files array"); + return NULL; + } + + i = 0; + for (iterator = list; iterator; iterator = iterator->next) { + entry = (char*) iterator->data; + entry = strrchr(entry, '/') + 1; + str = (*env)->NewStringUTF(env, entry); + (*env)->SetObjectArrayElement(env, array, i, str); + i++; + } + + return array; +} + +static void handle_response(GtkWidget* aDialog, gint responseId, gpointer obj) +{ + JNIEnv *env; + char *current_folder; + GSList *filenames; + jclass cx; + jstring jcurrent_folder; + jobjectArray jfilenames; + + env = (JNIEnv *) JNU_GetEnv(jvm, JNI_VERSION_1_2); + current_folder = NULL; + filenames = NULL; + + if (responseId == GTK_RESPONSE_ACCEPT) { + current_folder = fp_gtk_file_chooser_get_current_folder( + GTK_FILE_CHOOSER(dialog)); + filenames = fp_gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog)); + } + + if (setFileInternalMethodID == NULL) { + cx = (*env)->GetObjectClass(env, (jobject) obj); + if (cx == NULL) { + JNU_ThrowInternalError(env, "Could not get GTK peer class"); + return; + } + + setFileInternalMethodID = (*env)->GetMethodID(env, cx, + "setFileInternal", "(Ljava/lang/String;[Ljava/lang/String;)V"); + if (setFileInternalMethodID == NULL) { + JNU_ThrowInternalError(env, + "Could not get setFileInternalMethodID method id"); + return; + } + } + + jcurrent_folder = (*env)->NewStringUTF(env, current_folder); + jfilenames = toFilenamesArray(env, filenames); + + (*env)->CallVoidMethod(env, obj, setFileInternalMethodID, jcurrent_folder, + jfilenames); + fp_g_free(current_folder); + + Java_sun_awt_X11_GtkFileDialogPeer_quit(NULL, NULL); +} + +/* + * Class: sun_awt_X11_GtkFileDialogPeer + * Method: run + * Signature: (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/io/FilenameFilter;Z;)V + */ +JNIEXPORT void JNICALL +Java_sun_awt_X11_GtkFileDialogPeer_run(JNIEnv * env, jobject jpeer, + jstring jtitle, jint mode, jstring jdir, jstring jfile, + jobject jfilter, jboolean multiple) +{ + GtkFileFilter *filter; + + if (jvm == NULL) { + (*env)->GetJavaVM(env, &jvm); + } + + fp_gdk_threads_init(); + fp_gdk_threads_enter(); + + const char *title = (*env)->GetStringUTFChars(env, jtitle, 0); + + if (mode == 1) { + /* Save action */ + dialog = fp_gtk_file_chooser_dialog_new(title, NULL, + GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL); + } + else { + /* Default action OPEN */ + dialog = fp_gtk_file_chooser_dialog_new(title, NULL, + GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); + + /* Set multiple selection mode, that is allowed only in OPEN action */ + if (multiple) { + fp_gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), + multiple); + } + } + + (*env)->ReleaseStringUTFChars(env, jtitle, title); + + /* Set the directory */ + if (jdir != NULL) { + const char *dir = (*env)->GetStringUTFChars(env, jdir, 0); + fp_gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), dir); + (*env)->ReleaseStringUTFChars(env, jdir, dir); + } + + /* Set the filename */ + if (jfile != NULL) { + const char *filename = (*env)->GetStringUTFChars(env, jfile, 0); + fp_gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), filename); + (*env)->ReleaseStringUTFChars(env, jfile, filename); + } + + /* Set the file filter */ + if (jfilter != NULL) { + filter = fp_gtk_file_filter_new(); + fp_gtk_file_filter_add_custom(filter, GTK_FILE_FILTER_FILENAME, + filenameFilterCallback, jpeer, NULL); + fp_gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter); + } + + /* Other Properties */ + if (fp_gtk_check_version(2, 8, 0) == NULL) { + fp_gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER( + dialog), TRUE); + } + + fp_g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK( + handle_response), jpeer); + fp_gtk_widget_show(dialog); + + fp_gtk_main(); + fp_gdk_threads_leave(); +} diff --git a/jdk/src/solaris/native/sun/awt/sun_awt_X11_GtkFileDialogPeer.h b/jdk/src/solaris/native/sun/awt/sun_awt_X11_GtkFileDialogPeer.h new file mode 100644 index 00000000000..91334b4ebee --- /dev/null +++ b/jdk/src/solaris/native/sun/awt/sun_awt_X11_GtkFileDialogPeer.h @@ -0,0 +1,31 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class sun_awt_X11_GtkFileDialogPeer */ + +#ifndef _Included_sun_awt_X11_GtkFileDialogPeer +#define _Included_sun_awt_X11_GtkFileDialogPeer +#ifdef __cplusplus +extern "C" +{ +#endif + +/* + * Class: sun_awt_X11_GtkFileDialogPeer + * Method: run + * Signature: (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/io/FilenameFilter;Z;)V + */ +JNIEXPORT void JNICALL Java_sun_awt_X11_GtkFileDialogPeer_run +(JNIEnv *, jobject, jstring, jint, jstring, jstring, jobject, jboolean); + +/* + * Class: sun_awt_X11_GtkFileDialogPeer + * Method: quit + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_sun_awt_X11_GtkFileDialogPeer_quit +(JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/jdk/src/solaris/native/sun/awt/swing_GTKEngine.c b/jdk/src/solaris/native/sun/awt/swing_GTKEngine.c index c213a17c62d..d0a4aa864fb 100644 --- a/jdk/src/solaris/native/sun/awt/swing_GTKEngine.c +++ b/jdk/src/solaris/native/sun/awt/swing_GTKEngine.c @@ -38,8 +38,10 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1arrow( jint widget_type, jint state, jint shadow_type, jstring detail, jint x, jint y, jint w, jint h, jint arrow_type) { + fp_gdk_threads_enter(); gtk2_paint_arrow(widget_type, state, shadow_type, getStrFor(env, detail), x, y, w, h, arrow_type, TRUE); + fp_gdk_threads_leave(); } /* @@ -54,8 +56,10 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1box( jint x, jint y, jint w, jint h, jint synth_state, jint dir) { + fp_gdk_threads_enter(); gtk2_paint_box(widget_type, state, shadow_type, getStrFor(env, detail), x, y, w, h, synth_state, dir); + fp_gdk_threads_leave(); } /* @@ -70,8 +74,10 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1box_1gap( jint x, jint y, jint w, jint h, jint gap_side, jint gap_x, jint gap_w) { + fp_gdk_threads_enter(); gtk2_paint_box_gap(widget_type, state, shadow_type, getStrFor(env, detail), x, y, w, h, gap_side, gap_x, gap_w); + fp_gdk_threads_leave(); } /* @@ -85,8 +91,10 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1check( jint widget_type, jint synth_state, jstring detail, jint x, jint y, jint w, jint h) { + fp_gdk_threads_enter(); gtk2_paint_check(widget_type, synth_state, getStrFor(env, detail), x, y, w, h); + fp_gdk_threads_leave(); } /* @@ -100,8 +108,10 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1expander( jint widget_type, jint state, jstring detail, jint x, jint y, jint w, jint h, jint expander_style) { + fp_gdk_threads_enter(); gtk2_paint_expander(widget_type, state, getStrFor(env, detail), x, y, w, h, expander_style); + fp_gdk_threads_leave(); } /* @@ -115,8 +125,10 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1extension( jint widget_type, jint state, jint shadow_type, jstring detail, jint x, jint y, jint w, jint h, jint placement) { + fp_gdk_threads_enter(); gtk2_paint_extension(widget_type, state, shadow_type, getStrFor(env, detail), x, y, w, h, placement); + fp_gdk_threads_leave(); } /* @@ -130,8 +142,10 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1flat_1box( jint widget_type, jint state, jint shadow_type, jstring detail, jint x, jint y, jint w, jint h, jboolean has_focus) { + fp_gdk_threads_enter(); gtk2_paint_flat_box(widget_type, state, shadow_type, getStrFor(env, detail), x, y, w, h, has_focus); + fp_gdk_threads_leave(); } /* @@ -145,8 +159,10 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1focus( jint widget_type, jint state, jstring detail, jint x, jint y, jint w, jint h) { + fp_gdk_threads_enter(); gtk2_paint_focus(widget_type, state, getStrFor(env, detail), x, y, w, h); + fp_gdk_threads_leave(); } /* @@ -160,8 +176,10 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1handle( jint widget_type, jint state, jint shadow_type, jstring detail, jint x, jint y, jint w, jint h, jint orientation) { + fp_gdk_threads_enter(); gtk2_paint_handle(widget_type, state, shadow_type, getStrFor(env, detail), x, y, w, h, orientation); + fp_gdk_threads_leave(); } /* @@ -175,8 +193,10 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1hline( jint widget_type, jint state, jstring detail, jint x, jint y, jint w, jint h) { + fp_gdk_threads_enter(); gtk2_paint_hline(widget_type, state, getStrFor(env, detail), x, y, w, h); + fp_gdk_threads_leave(); } /* @@ -190,8 +210,10 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1option( jint widget_type, jint synth_state, jstring detail, jint x, jint y, jint w, jint h) { + fp_gdk_threads_enter(); gtk2_paint_option(widget_type, synth_state, getStrFor(env, detail), x, y, w, h); + fp_gdk_threads_leave(); } /* @@ -206,8 +228,10 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1shadow( jint x, jint y, jint w, jint h, jint synth_state, jint dir) { + fp_gdk_threads_enter(); gtk2_paint_shadow(widget_type, state, shadow_type, getStrFor(env, detail), x, y, w, h, synth_state, dir); + fp_gdk_threads_leave(); } /* @@ -221,8 +245,10 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1slider( jint widget_type, jint state, jint shadow_type, jstring detail, jint x, jint y, jint w, jint h, jint orientation) { + fp_gdk_threads_enter(); gtk2_paint_slider(widget_type, state, shadow_type, getStrFor(env, detail), x, y, w, h, orientation); + fp_gdk_threads_leave(); } /* @@ -236,8 +262,10 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1vline( jint widget_type, jint state, jstring detail, jint x, jint y, jint w, jint h) { + fp_gdk_threads_enter(); gtk2_paint_vline(widget_type, state, getStrFor(env, detail), x, y, w, h); + fp_gdk_threads_leave(); } /* @@ -250,7 +278,9 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1background( JNIEnv *env, jobject this, jint widget_type, jint state, jint x, jint y, jint w, jint h) { + fp_gdk_threads_enter(); gtk_paint_background(widget_type, state, x, y, w, h); + fp_gdk_threads_leave(); } /* @@ -262,7 +292,9 @@ JNIEXPORT void JNICALL Java_com_sun_java_swing_plaf_gtk_GTKEngine_nativeStartPainting( JNIEnv *env, jobject this, jint w, jint h) { + fp_gdk_threads_enter(); gtk2_init_painting(w, h); + fp_gdk_threads_leave(); } /* @@ -276,7 +308,9 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_nativeFinishPainting( { jint transparency; gint *buffer = (gint*) (*env)->GetPrimitiveArrayCritical(env, dest, 0); + fp_gdk_threads_enter(); transparency = gtk2_copy_image(buffer, width, height); + fp_gdk_threads_leave(); (*env)->ReleasePrimitiveArrayCritical(env, dest, buffer, 0); return transparency; } @@ -289,7 +323,9 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_nativeFinishPainting( JNIEXPORT void JNICALL Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1switch_1theme( JNIEnv *env, jobject this) { + fp_gdk_threads_enter(); flush_gtk_event_loop(); + fp_gdk_threads_leave(); } /* @@ -300,7 +336,11 @@ JNIEXPORT void JNICALL Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1switch JNIEXPORT jobject JNICALL Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1get_1gtk_1setting( JNIEnv *env, jobject this, jint property) { - return gtk2_get_setting(env, property); + jobject obj; + fp_gdk_threads_enter(); + obj = gtk2_get_setting(env, property); + fp_gdk_threads_leave(); + return obj; } /* @@ -313,5 +353,7 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_nativeSetRangeValue( JNIEnv *env, jobject this, jint widget_type, jdouble value, jdouble min, jdouble max, jdouble visible) { + fp_gdk_threads_enter(); gtk2_set_range_value(widget_type, value, min, max, visible); + fp_gdk_threads_leave(); } diff --git a/jdk/src/solaris/native/sun/awt/swing_GTKStyle.c b/jdk/src/solaris/native/sun/awt/swing_GTKStyle.c index 111ae47b311..076e701681b 100644 --- a/jdk/src/solaris/native/sun/awt/swing_GTKStyle.c +++ b/jdk/src/solaris/native/sun/awt/swing_GTKStyle.c @@ -36,7 +36,11 @@ JNIEXPORT jint JNICALL Java_com_sun_java_swing_plaf_gtk_GTKStyle_nativeGetXThickness( JNIEnv *env, jclass klass, jint widget_type) { - return gtk2_get_xthickness(env, widget_type); + jint ret; + fp_gdk_threads_enter(); + ret = gtk2_get_xthickness(env, widget_type); + fp_gdk_threads_leave(); + return ret; } /* @@ -48,7 +52,11 @@ JNIEXPORT jint JNICALL Java_com_sun_java_swing_plaf_gtk_GTKStyle_nativeGetYThickness( JNIEnv *env, jclass klass, jint widget_type) { - return gtk2_get_ythickness(env, widget_type); + jint ret; + fp_gdk_threads_enter(); + ret = gtk2_get_ythickness(env, widget_type); + fp_gdk_threads_leave(); + return ret; } /* @@ -61,7 +69,11 @@ Java_com_sun_java_swing_plaf_gtk_GTKStyle_nativeGetColorForState( JNIEnv *env, jclass klass, jint widget_type, jint state_type, jint type_id) { - return gtk2_get_color_for_state(env, widget_type, state_type, type_id); + jint ret; + fp_gdk_threads_enter(); + ret = gtk2_get_color_for_state(env, widget_type, state_type, type_id); + fp_gdk_threads_leave(); + return ret; } /* @@ -73,7 +85,11 @@ JNIEXPORT jobject JNICALL Java_com_sun_java_swing_plaf_gtk_GTKStyle_nativeGetClassValue( JNIEnv *env, jclass klass, jint widget_type, jstring key) { - return gtk2_get_class_value(env, widget_type, key); + jobject ret; + fp_gdk_threads_enter(); + ret = gtk2_get_class_value(env, widget_type, key); + fp_gdk_threads_leave(); + return ret; } /* @@ -85,5 +101,9 @@ JNIEXPORT jstring JNICALL Java_com_sun_java_swing_plaf_gtk_GTKStyle_nativeGetPangoFontName( JNIEnv *env, jclass klass, jint widget_type) { - return gtk2_get_pango_font_name(env, widget_type); + jstring ret; + fp_gdk_threads_enter(); + ret = gtk2_get_pango_font_name(env, widget_type); + fp_gdk_threads_leave(); + return ret; } From 46ebf10e260dbc24210c4dd6cf8f2cde166ff40b Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Thu, 29 Apr 2010 15:50:40 +0800 Subject: [PATCH 11/54] 6947487: use HexDumpEncoder.encodeBuffer() Reviewed-by: mullan --- .../com/sun/security/auth/module/Krb5LoginModule.java | 4 ++-- .../com/sun/security/jgss/AuthorizationDataEntry.java | 4 ++-- .../classes/javax/security/auth/kerberos/KeyImpl.java | 4 ++-- jdk/src/share/classes/sun/security/krb5/EncryptionKey.java | 7 ++++--- .../classes/sun/security/provider/certpath/CertId.java | 6 +++--- jdk/src/share/classes/sun/security/tools/KeyTool.java | 2 +- 6 files changed, 14 insertions(+), 13 deletions(-) diff --git a/jdk/src/share/classes/com/sun/security/auth/module/Krb5LoginModule.java b/jdk/src/share/classes/com/sun/security/auth/module/Krb5LoginModule.java index 55972eefe89..8e16c4d4a55 100644 --- a/jdk/src/share/classes/com/sun/security/auth/module/Krb5LoginModule.java +++ b/jdk/src/share/classes/com/sun/security/auth/module/Krb5LoginModule.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-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 @@ -717,7 +717,7 @@ public class Krb5LoginModule implements LoginModule { for (int i = 0; i < encKeys.length; i++) { System.out.println("EncryptionKey: keyType=" + encKeys[i].getEType() + " keyBytes (hex dump)=" + - hd.encode(encKeys[i].getBytes())); + hd.encodeBuffer(encKeys[i].getBytes())); } } diff --git a/jdk/src/share/classes/com/sun/security/jgss/AuthorizationDataEntry.java b/jdk/src/share/classes/com/sun/security/jgss/AuthorizationDataEntry.java index 0386792a7c2..b885b037d50 100644 --- a/jdk/src/share/classes/com/sun/security/jgss/AuthorizationDataEntry.java +++ b/jdk/src/share/classes/com/sun/security/jgss/AuthorizationDataEntry.java @@ -1,5 +1,5 @@ /* - * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2009-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 @@ -63,6 +63,6 @@ final public class AuthorizationDataEntry { public String toString() { return "AuthorizationDataEntry: type="+type+", data=" + data.length + " bytes:\n" + - new sun.misc.HexDumpEncoder().encode(data); + new sun.misc.HexDumpEncoder().encodeBuffer(data); } } diff --git a/jdk/src/share/classes/javax/security/auth/kerberos/KeyImpl.java b/jdk/src/share/classes/javax/security/auth/kerberos/KeyImpl.java index a91f3925267..f7a724b146b 100644 --- a/jdk/src/share/classes/javax/security/auth/kerberos/KeyImpl.java +++ b/jdk/src/share/classes/javax/security/auth/kerberos/KeyImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-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 @@ -205,7 +205,7 @@ class KeyImpl implements SecretKey, Destroyable, Serializable { + " keyBytes (hex dump)=" + (keyBytes == null || keyBytes.length == 0 ? " Empty Key" : - '\n' + hd.encode(keyBytes) + '\n' + hd.encodeBuffer(keyBytes) + '\n'); diff --git a/jdk/src/share/classes/sun/security/krb5/EncryptionKey.java b/jdk/src/share/classes/sun/security/krb5/EncryptionKey.java index 15d6d78c04d..e67d504f617 100644 --- a/jdk/src/share/classes/sun/security/krb5/EncryptionKey.java +++ b/jdk/src/share/classes/sun/security/krb5/EncryptionKey.java @@ -1,5 +1,5 @@ /* - * Portions Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. + * Portions Copyright 2000-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 @@ -499,8 +499,9 @@ public class EncryptionKey + " kvno=" + kvno + " keyValue (hex dump)=" + (keyValue == null || keyValue.length == 0 ? - " Empty Key" : '\n' + Krb5.hexDumper.encode(keyValue) - + '\n')); + " Empty Key" : '\n' + + Krb5.hexDumper.encodeBuffer(keyValue) + + '\n')); } /** diff --git a/jdk/src/share/classes/sun/security/provider/certpath/CertId.java b/jdk/src/share/classes/sun/security/provider/certpath/CertId.java index 20e9aa2a789..e85ed531b99 100644 --- a/jdk/src/share/classes/sun/security/provider/certpath/CertId.java +++ b/jdk/src/share/classes/sun/security/provider/certpath/CertId.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2009 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 @@ -96,9 +96,9 @@ public class CertId { HexDumpEncoder encoder = new HexDumpEncoder(); System.out.println("Issuer Certificate is " + issuerCert); System.out.println("issuerNameHash is " + - encoder.encode(issuerNameHash)); + encoder.encodeBuffer(issuerNameHash)); System.out.println("issuerKeyHash is " + - encoder.encode(issuerKeyHash)); + encoder.encodeBuffer(issuerKeyHash)); System.out.println("SerialNumber is " + serialNumber.getNumber()); } } diff --git a/jdk/src/share/classes/sun/security/tools/KeyTool.java b/jdk/src/share/classes/sun/security/tools/KeyTool.java index bd03c696e0e..2539d43e14b 100644 --- a/jdk/src/share/classes/sun/security/tools/KeyTool.java +++ b/jdk/src/share/classes/sun/security/tools/KeyTool.java @@ -2620,7 +2620,7 @@ public final class KeyTool { if (v.length == 0) { out.println(rb.getString("(Empty value)")); } else { - new sun.misc.HexDumpEncoder().encode(ext.getExtensionValue(), out); + new sun.misc.HexDumpEncoder().encodeBuffer(ext.getExtensionValue(), out); out.println(); } } From 20fbeb53cdd1dacc3f5967842aa782a4eb872e0a Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Thu, 29 Apr 2010 15:51:10 +0800 Subject: [PATCH 12/54] 6844193: support max_retries in krb5.conf Reviewed-by: valeriep --- .../classes/sun/security/krb5/Config.java | 4 +- .../classes/sun/security/krb5/KrbKdcReq.java | 141 +++++++----- .../sun/security/krb5/auto/MaxRetries.java | 203 ++++++++++++++++++ 3 files changed, 293 insertions(+), 55 deletions(-) create mode 100644 jdk/test/sun/security/krb5/auto/MaxRetries.java diff --git a/jdk/src/share/classes/sun/security/krb5/Config.java b/jdk/src/share/classes/sun/security/krb5/Config.java index 3cc209c9f21..3980deb8e2d 100644 --- a/jdk/src/share/classes/sun/security/krb5/Config.java +++ b/jdk/src/share/classes/sun/security/krb5/Config.java @@ -1,5 +1,5 @@ /* - * Portions Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. + * Portions Copyright 2000-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 @@ -109,7 +109,7 @@ public class Config { public static synchronized void refresh() throws KrbException { singleton = new Config(); KeyTab.refresh(); - KrbKdcReq.KdcAccessibility.reset(); + KrbKdcReq.initStatic(); } diff --git a/jdk/src/share/classes/sun/security/krb5/KrbKdcReq.java b/jdk/src/share/classes/sun/security/krb5/KrbKdcReq.java index 389fd04be4e..74c5edab291 100644 --- a/jdk/src/share/classes/sun/security/krb5/KrbKdcReq.java +++ b/jdk/src/share/classes/sun/security/krb5/KrbKdcReq.java @@ -1,5 +1,5 @@ /* - * Portions Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. + * Portions Copyright 2000-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 @@ -51,28 +51,31 @@ import java.util.HashSet; public abstract class KrbKdcReq { - // Currently there is no option to specify retries - // in the kerberos configuration file - - private static final int DEFAULT_KDC_RETRY_LIMIT = Krb5.KDC_RETRY_LIMIT; + // The following settings can be configured in [libdefaults] + // section of krb5.conf, which are global for all realms. Each of + // them can also be defined in a realm, which overrides value here. /** - * Default timeout period when requesting a ticket from a KDC. - * If not specified in the configuration file, - * a value of 30 seconds is used. + * max retry time for a single KDC, default Krb5.KDC_RETRY_LIMIT (3) */ - public static final int DEFAULT_KDC_TIMEOUT; // milliseconds + private static int defaultKdcRetryLimit; + /** + * timeout requesting a ticket from KDC, in millisec, default 30 sec + */ + private static int defaultKdcTimeout; + /** + * max UDP packet size, default unlimited (-1) + */ + private static int defaultUdpPrefLimit; private static final boolean DEBUG = Krb5.DEBUG; - private static int udpPrefLimit = -1; - private static final String BAD_POLICY_KEY = "krb5.kdc.bad.policy"; /** * What to do when a KDC is unavailable, specified in the * java.security file with key krb5.kdc.bad.policy. - * Possible values can be TRY_LAST or TRY_LESS + * Possible values can be TRY_LAST or TRY_LESS. Reloaded when refreshed. */ private enum BpType { NONE, TRY_LAST, TRY_LESS @@ -80,9 +83,16 @@ public abstract class KrbKdcReq { private static int tryLessMaxRetries = 1; private static int tryLessTimeout = 5000; - private static final BpType badPolicy; + private static BpType badPolicy; static { + initStatic(); + } + + /** + * Read global settings + */ + public static void initStatic() { String value = AccessController.doPrivileged( new PrivilegedAction() { public String run() { @@ -95,9 +105,21 @@ public abstract class KrbKdcReq { if ("tryless".equals(ss[0])) { if (ss.length > 1) { String[] params = ss[1].split(","); - tryLessMaxRetries = Integer.parseInt(params[0]); - if (params.length > 1) { - tryLessTimeout = Integer.parseInt(params[1]); + try { + int tmp0 = Integer.parseInt(params[0]); + if (params.length > 1) { + tryLessTimeout = Integer.parseInt(params[1]); + } + // Assign here in case of exception at params[1] + tryLessMaxRetries = tmp0; + } catch (NumberFormatException nfe) { + // Ignored. Please note that tryLess is recognized and + // used, parameters using default values + if (DEBUG) { + System.out.println("Invalid " + BAD_POLICY_KEY + + " parameter for tryLess: " + + value + ", use default"); + } } } badPolicy = BpType.TRY_LESS; @@ -110,30 +132,33 @@ public abstract class KrbKdcReq { badPolicy = BpType.NONE; } - /* - * Get default timeout. - */ int timeout = -1; + int max_retries = -1; + int udf_pref_limit = -1; + try { Config cfg = Config.getInstance(); String temp = cfg.getDefault("kdc_timeout", "libdefaults"); timeout = parsePositiveIntString(temp); + temp = cfg.getDefault("max_retries", "libdefaults"); + max_retries = parsePositiveIntString(temp); temp = cfg.getDefault("udp_preference_limit", "libdefaults"); - udpPrefLimit = parsePositiveIntString(temp); + udf_pref_limit = parsePositiveIntString(temp); } catch (Exception exc) { - // ignore any exceptions; use the default time out values + // ignore any exceptions; use default values if (DEBUG) { - System.out.println ("Exception in getting kdc_timeout value, " + - "using default value " + + System.out.println ("Exception in getting KDC communication " + + "settings, using default value " + exc.getMessage()); } } + defaultKdcTimeout = timeout > 0 ? timeout : 30*1000; // 30 seconds + defaultKdcRetryLimit = + max_retries > 0 ? max_retries : Krb5.KDC_RETRY_LIMIT; + defaultUdpPrefLimit = udf_pref_limit; - if (timeout > 0) - DEFAULT_KDC_TIMEOUT = timeout; - else - DEFAULT_KDC_TIMEOUT = 30*1000; // 30 seconds + KdcAccessibility.reset(); } protected byte[] obuf; @@ -151,6 +176,9 @@ public abstract class KrbKdcReq { public String send(String realm) throws IOException, KrbException { + int udpPrefLimit = getRealmSpecificValue( + realm, "udp_preference_limit", defaultUdpPrefLimit); + boolean useTCP = (udpPrefLimit > 0 && (obuf != null && obuf.length > udpPrefLimit)); @@ -213,9 +241,10 @@ public abstract class KrbKdcReq { return; int port = Krb5.KDC_INET_DEFAULT_PORT; - int retries = DEFAULT_KDC_RETRY_LIMIT; - int timeout = getKdcTimeout(realm); - + int retries = getRealmSpecificValue( + realm, "max_retries", defaultKdcRetryLimit); + int timeout = getRealmSpecificValue( + realm, "kdc_timeout", defaultKdcTimeout); if (badPolicy == BpType.TRY_LESS && KdcAccessibility.isBad(tempKdc)) { if (retries > tryLessMaxRetries) { @@ -322,6 +351,12 @@ public abstract class KrbKdcReq { if (useTCP) { TCPClient kdcClient = new TCPClient(kdc, port); + if (DEBUG) { + System.out.println(">>> KDCCommunication: kdc=" + kdc + + " TCP:" + + port + + ", #bytes=" + obuf.length); + } try { /* * Send the data to the kdc. @@ -336,7 +371,7 @@ public abstract class KrbKdcReq { } } else { - // For each KDC we try DEFAULT_KDC_RETRY_LIMIT (3) times to + // For each KDC we try defaultKdcRetryLimit times to // get the response for (int i=1; i <= retries; i++) { UDPClient kdcClient = new UDPClient(kdc, port, timeout); @@ -382,37 +417,37 @@ public abstract class KrbKdcReq { } /** - * Returns a timeout value for the KDC of the given realm. - * A KDC-specific timeout, if specified in the config file, - * overrides the default timeout (which may also be specified - * in the config file). Default timeout is returned if null - * is specified for realm. - * @param realm the realm which kdc's timeout is requested - * @return KDC timeout + * Returns krb5.conf setting of {@code key} for a specfic realm, + * which can be: + * 1. defined in the sub-stanza for the given realm inside [realms], or + * 2. defined in [libdefaults], or + * 3. defValue + * @param realm the given realm in which the setting is requested. Returns + * the global setting if null + * @param key the key for the setting + * @param defValue default value + * @return a value for the key */ - private int getKdcTimeout(String realm) - { - int timeout = DEFAULT_KDC_TIMEOUT; + private int getRealmSpecificValue(String realm, String key, int defValue) { + int v = defValue; - if (realm == null) - return timeout; + if (realm == null) return v; - int tempTimeout = -1; + int temp = -1; try { - String temp = - Config.getInstance().getDefault("kdc_timeout", realm); - tempTimeout = parsePositiveIntString(temp); + String value = + Config.getInstance().getDefault(key, realm); + temp = parsePositiveIntString(value); } catch (Exception exc) { + // Ignored, defValue will be picked up } - if (tempTimeout > 0) - timeout = tempTimeout; + if (temp > 0) v = temp; - return timeout; + return v; } - private static int parsePositiveIntString(String intString) - { + private static int parsePositiveIntString(String intString) { if (intString == null) return -1; @@ -461,7 +496,7 @@ public abstract class KrbKdcReq { return bads.contains(kdc); } - public static synchronized void reset() { + private static synchronized void reset() { if (DEBUG) { System.out.println(">>> KdcAccessibility: reset"); } diff --git a/jdk/test/sun/security/krb5/auto/MaxRetries.java b/jdk/test/sun/security/krb5/auto/MaxRetries.java new file mode 100644 index 00000000000..4a995bb7f3e --- /dev/null +++ b/jdk/test/sun/security/krb5/auto/MaxRetries.java @@ -0,0 +1,203 @@ +/* + * Copyright 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 + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6844193 + * @run main/timeout=300 MaxRetries + * @summary support max_retries in krb5.conf + */ + +import java.io.*; +import java.security.Security; + +public class MaxRetries { + public static void main(String[] args) + throws Exception { + + System.setProperty("sun.security.krb5.debug", "true"); + new OneKDC(null).writeJAASConf(); + System.setProperty("java.security.krb5.conf", "alternative-krb5.conf"); + + // For tryLast + Security.setProperty("krb5.kdc.bad.policy", "trylast"); + rewriteMaxRetries(4); + test1(4000, 6); // 1 1 1 1 2 2 + test1(4000, 2); // 2 2 + + rewriteMaxRetries(1); + test1(1000, 3); // 1 2 2 + test1(1000, 2); // 2 2 + + rewriteMaxRetries(-1); + test1(5000, 4); // 1 1 2 2 + test1(5000, 2); // 2 2 + + // For tryLess + Security.setProperty("krb5.kdc.bad.policy", "tryless"); + rewriteMaxRetries(4); + test1(4000, 7); // 1 1 1 1 2 1 2 + test1(4000, 4); // 1 2 1 2 + + rewriteMaxRetries(1); + test1(1000, 4); // 1 2 1 2 + test1(1000, 4); // 1 2 1 2 + + rewriteMaxRetries(-1); + test1(5000, 5); // 1 1 2 1 2 + test1(5000, 4); // 1 2 1 2 + + rewriteUdpPrefLimit(-1, -1); // default, no limit + test2("UDP"); + + rewriteUdpPrefLimit(10, -1); // global rules + test2("TCP"); + + rewriteUdpPrefLimit(10, 10000); // realm rules + test2("UDP"); + + rewriteUdpPrefLimit(10000, 10); // realm rules + test2("TCP"); + } + + /** + * One round of test for max_retries and timeout. + * @param timeout the expected timeout + * @param count the expected total try + */ + private static void test1(int timeout, int count) throws Exception { + String timeoutTag = "timeout=" + timeout; + ByteArrayOutputStream bo = new ByteArrayOutputStream(); + PrintStream oldout = System.out; + System.setOut(new PrintStream(bo)); + Context c = Context.fromJAAS("client"); + System.setOut(oldout); + + String[] lines = new String(bo.toByteArray()).split("\n"); + System.out.println("----------------- TEST (" + timeout + "," + + count + ") -----------------"); + for (String line: lines) { + if (line.startsWith(">>> KDCCommunication")) { + System.out.println(line); + if (line.indexOf(timeoutTag) < 0) { + throw new Exception("Wrong timeout value"); + } + count--; + } + } + if (count != 0) { + throw new Exception("Retry count is " + count + " less"); + } + } + + /** + * One round of test for udp_preference_limit. + * @param proto the expected protocol used + */ + private static void test2(String proto) throws Exception { + ByteArrayOutputStream bo = new ByteArrayOutputStream(); + PrintStream oldout = System.out; + System.setOut(new PrintStream(bo)); + Context c = Context.fromJAAS("client"); + System.setOut(oldout); + + int count = 2; + String[] lines = new String(bo.toByteArray()).split("\n"); + System.out.println("----------------- TEST -----------------"); + for (String line: lines) { + if (line.startsWith(">>> KDCCommunication")) { + System.out.println(line); + count--; + if (line.indexOf(proto) < 0) { + throw new Exception("Wrong timeout value"); + } + } + } + if (count != 0) { + throw new Exception("Retry count is " + count + " less"); + } + } + + /** + * Set udp_preference_limit for global and realm + */ + private static void rewriteUdpPrefLimit(int global, int realm) + throws Exception { + BufferedReader fr = new BufferedReader(new FileReader(OneKDC.KRB5_CONF)); + FileWriter fw = new FileWriter("alternative-krb5.conf"); + while (true) { + String s = fr.readLine(); + if (s == null) { + break; + } + if (s.startsWith("[realms]")) { + // Reconfig global setting + if (global != -1) { + fw.write("udp_preference_limit = " + global + "\n"); + } + } else if (s.trim().startsWith("kdc = ")) { + if (realm != -1) { + // Reconfig for realm + fw.write(" udp_preference_limit = " + realm + "\n"); + } + } + fw.write(s + "\n"); + } + fr.close(); + fw.close(); + sun.security.krb5.Config.refresh(); + } + + /** + * Set max_retries and timeout value for realm. The global value is always + * 2 and 5000. + * @param value max_retries and timeout/1000 for a realm, -1 means none. + */ + private static void rewriteMaxRetries(int value) throws Exception { + BufferedReader fr = new BufferedReader(new FileReader(OneKDC.KRB5_CONF)); + FileWriter fw = new FileWriter("alternative-krb5.conf"); + while (true) { + String s = fr.readLine(); + if (s == null) { + break; + } + if (s.startsWith("[realms]")) { + // Reconfig global setting + fw.write("max_retries = 2\n"); + fw.write("kdc_timeout = 5000\n"); + } else if (s.trim().startsWith("kdc = ")) { + if (value != -1) { + // Reconfig for realm + fw.write(" max_retries = " + value + "\n"); + fw.write(" kdc_timeout = " + (value*1000) + "\n"); + } + // Add a bad KDC as the first candidate + fw.write(" kdc = localhost:33333\n"); + } + fw.write(s + "\n"); + } + fr.close(); + fw.close(); + sun.security.krb5.Config.refresh(); + } +} From 6d2a896bcd40da725fe544696e4f038a0e293b3d Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Thu, 29 Apr 2010 06:30:25 -0700 Subject: [PATCH 13/54] 6829193: JSR 292 needs to support SPARC There are unimplemented portions of the hotspot code for method handles and invokedynamic specific to SPARC. Reviewed-by: kvn, never, jrose --- hotspot/src/cpu/sparc/vm/assembler_sparc.cpp | 189 +++- hotspot/src/cpu/sparc/vm/assembler_sparc.hpp | 58 +- .../cpu/sparc/vm/assembler_sparc.inline.hpp | 9 +- .../src/cpu/sparc/vm/interp_masm_sparc.cpp | 45 +- .../src/cpu/sparc/vm/interp_masm_sparc.hpp | 7 +- .../src/cpu/sparc/vm/interpreter_sparc.cpp | 6 +- .../src/cpu/sparc/vm/methodHandles_sparc.cpp | 875 +++++++++++++++++- .../src/cpu/sparc/vm/stubGenerator_sparc.cpp | 10 + .../sparc/vm/templateInterpreter_sparc.cpp | 30 +- .../src/cpu/sparc/vm/templateTable_sparc.cpp | 69 +- hotspot/src/cpu/x86/vm/assembler_x86.cpp | 24 +- hotspot/src/cpu/x86/vm/assembler_x86.hpp | 4 +- hotspot/src/cpu/x86/vm/methodHandles_x86.cpp | 6 +- hotspot/src/share/vm/prims/methodHandles.hpp | 4 +- 14 files changed, 1210 insertions(+), 126 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp index e4799550fd8..00fa5f4a629 100644 --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2009 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 @@ -2333,6 +2333,18 @@ void MacroAssembler::lcmp( Register Ra, Register Rb, Register Rresult) { #endif +void MacroAssembler::load_sized_value(Address src, Register dst, + size_t size_in_bytes, bool is_signed) { + switch (size_in_bytes) { + case 8: ldx(src, dst); break; + case 4: ld( src, dst); break; + case 2: is_signed ? ldsh(src, dst) : lduh(src, dst); break; + case 1: is_signed ? ldsb(src, dst) : ldub(src, dst); break; + default: ShouldNotReachHere(); + } +} + + void MacroAssembler::float_cmp( bool is_float, int unordered_result, FloatRegister Fa, FloatRegister Fb, Register Rresult) { @@ -2625,40 +2637,103 @@ RegisterOrConstant MacroAssembler::delayed_value_impl(intptr_t* delayed_value_ad } -void MacroAssembler::regcon_inc_ptr( RegisterOrConstant& dest, RegisterOrConstant src, Register temp ) { - assert(dest.register_or_noreg() != G0, "lost side effect"); - if ((src.is_constant() && src.as_constant() == 0) || - (src.is_register() && src.as_register() == G0)) { - // do nothing - } else if (dest.is_register()) { - add(dest.as_register(), ensure_simm13_or_reg(src, temp), dest.as_register()); - } else if (src.is_constant()) { - intptr_t res = dest.as_constant() + src.as_constant(); - dest = RegisterOrConstant(res); // side effect seen by caller +RegisterOrConstant MacroAssembler::regcon_andn_ptr(RegisterOrConstant s1, RegisterOrConstant s2, RegisterOrConstant d, Register temp) { + assert(d.register_or_noreg() != G0, "lost side effect"); + if ((s2.is_constant() && s2.as_constant() == 0) || + (s2.is_register() && s2.as_register() == G0)) { + // Do nothing, just move value. + if (s1.is_register()) { + if (d.is_constant()) d = temp; + mov(s1.as_register(), d.as_register()); + return d; + } else { + return s1; + } + } + + if (s1.is_register()) { + assert_different_registers(s1.as_register(), temp); + if (d.is_constant()) d = temp; + andn(s1.as_register(), ensure_simm13_or_reg(s2, temp), d.as_register()); + return d; } else { - assert(temp != noreg, "cannot handle constant += register"); - add(src.as_register(), ensure_simm13_or_reg(dest, temp), temp); - dest = RegisterOrConstant(temp); // side effect seen by caller + if (s2.is_register()) { + assert_different_registers(s2.as_register(), temp); + if (d.is_constant()) d = temp; + set(s1.as_constant(), temp); + andn(temp, s2.as_register(), d.as_register()); + return d; + } else { + intptr_t res = s1.as_constant() & ~s2.as_constant(); + return res; + } } } -void MacroAssembler::regcon_sll_ptr( RegisterOrConstant& dest, RegisterOrConstant src, Register temp ) { - assert(dest.register_or_noreg() != G0, "lost side effect"); - if (!is_simm13(src.constant_or_zero())) - src = (src.as_constant() & 0xFF); - if ((src.is_constant() && src.as_constant() == 0) || - (src.is_register() && src.as_register() == G0)) { - // do nothing - } else if (dest.is_register()) { - sll_ptr(dest.as_register(), src, dest.as_register()); - } else if (src.is_constant()) { - intptr_t res = dest.as_constant() << src.as_constant(); - dest = RegisterOrConstant(res); // side effect seen by caller +RegisterOrConstant MacroAssembler::regcon_inc_ptr(RegisterOrConstant s1, RegisterOrConstant s2, RegisterOrConstant d, Register temp) { + assert(d.register_or_noreg() != G0, "lost side effect"); + if ((s2.is_constant() && s2.as_constant() == 0) || + (s2.is_register() && s2.as_register() == G0)) { + // Do nothing, just move value. + if (s1.is_register()) { + if (d.is_constant()) d = temp; + mov(s1.as_register(), d.as_register()); + return d; + } else { + return s1; + } + } + + if (s1.is_register()) { + assert_different_registers(s1.as_register(), temp); + if (d.is_constant()) d = temp; + add(s1.as_register(), ensure_simm13_or_reg(s2, temp), d.as_register()); + return d; } else { - assert(temp != noreg, "cannot handle constant <<= register"); - set(dest.as_constant(), temp); - sll_ptr(temp, src, temp); - dest = RegisterOrConstant(temp); // side effect seen by caller + if (s2.is_register()) { + assert_different_registers(s2.as_register(), temp); + if (d.is_constant()) d = temp; + add(s2.as_register(), ensure_simm13_or_reg(s1, temp), d.as_register()); + return d; + } else { + intptr_t res = s1.as_constant() + s2.as_constant(); + return res; + } + } +} + +RegisterOrConstant MacroAssembler::regcon_sll_ptr(RegisterOrConstant s1, RegisterOrConstant s2, RegisterOrConstant d, Register temp) { + assert(d.register_or_noreg() != G0, "lost side effect"); + if (!is_simm13(s2.constant_or_zero())) + s2 = (s2.as_constant() & 0xFF); + if ((s2.is_constant() && s2.as_constant() == 0) || + (s2.is_register() && s2.as_register() == G0)) { + // Do nothing, just move value. + if (s1.is_register()) { + if (d.is_constant()) d = temp; + mov(s1.as_register(), d.as_register()); + return d; + } else { + return s1; + } + } + + if (s1.is_register()) { + assert_different_registers(s1.as_register(), temp); + if (d.is_constant()) d = temp; + sll_ptr(s1.as_register(), ensure_simm13_or_reg(s2, temp), d.as_register()); + return d; + } else { + if (s2.is_register()) { + assert_different_registers(s2.as_register(), temp); + if (d.is_constant()) d = temp; + set(s1.as_constant(), temp); + sll_ptr(temp, s2.as_register(), d.as_register()); + return d; + } else { + intptr_t res = s1.as_constant() << s2.as_constant(); + return res; + } } } @@ -2708,8 +2783,8 @@ void MacroAssembler::lookup_interface_method(Register recv_klass, // Adjust recv_klass by scaled itable_index, so we can free itable_index. RegisterOrConstant itable_offset = itable_index; - regcon_sll_ptr(itable_offset, exact_log2(itableMethodEntry::size() * wordSize)); - regcon_inc_ptr(itable_offset, itableMethodEntry::method_offset_in_bytes()); + itable_offset = regcon_sll_ptr(itable_index, exact_log2(itableMethodEntry::size() * wordSize), itable_offset); + itable_offset = regcon_inc_ptr(itable_offset, itableMethodEntry::method_offset_in_bytes(), itable_offset); add(recv_klass, ensure_simm13_or_reg(itable_offset, sethi_temp), recv_klass); // for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) { @@ -2805,7 +2880,7 @@ void MacroAssembler::check_klass_subtype_fast_path(Register sub_klass, assert_different_registers(sub_klass, super_klass, temp_reg); if (super_check_offset.is_register()) { - assert_different_registers(sub_klass, super_klass, + assert_different_registers(sub_klass, super_klass, temp_reg, super_check_offset.as_register()); } else if (must_load_sco) { assert(temp2_reg != noreg, "supply either a temp or a register offset"); @@ -2855,6 +2930,8 @@ void MacroAssembler::check_klass_subtype_fast_path(Register sub_klass, // The super check offset is always positive... lduw(super_klass, sco_offset, temp2_reg); super_check_offset = RegisterOrConstant(temp2_reg); + // super_check_offset is register. + assert_different_registers(sub_klass, super_klass, temp_reg, super_check_offset.as_register()); } ld_ptr(sub_klass, super_check_offset, temp_reg); cmp(super_klass, temp_reg); @@ -3014,11 +3091,10 @@ void MacroAssembler::check_klass_subtype_slow_path(Register sub_klass, } - - void MacroAssembler::check_method_handle_type(Register mtype_reg, Register mh_reg, Register temp_reg, Label& wrong_method_type) { + if (UseCompressedOops) unimplemented("coop"); // field accesses must decode assert_different_registers(mtype_reg, mh_reg, temp_reg); // compare method type against that of the receiver RegisterOrConstant mhtype_offset = delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg); @@ -3029,10 +3105,33 @@ void MacroAssembler::check_method_handle_type(Register mtype_reg, Register mh_re } -void MacroAssembler::jump_to_method_handle_entry(Register mh_reg, Register temp_reg) { +// A method handle has a "vmslots" field which gives the size of its +// argument list in JVM stack slots. This field is either located directly +// in every method handle, or else is indirectly accessed through the +// method handle's MethodType. This macro hides the distinction. +void MacroAssembler::load_method_handle_vmslots(Register vmslots_reg, Register mh_reg, + Register temp_reg) { + assert_different_registers(vmslots_reg, mh_reg, temp_reg); + if (UseCompressedOops) unimplemented("coop"); // field accesses must decode + // load mh.type.form.vmslots + if (java_dyn_MethodHandle::vmslots_offset_in_bytes() != 0) { + // hoist vmslots into every mh to avoid dependent load chain + ld( Address(mh_reg, delayed_value(java_dyn_MethodHandle::vmslots_offset_in_bytes, temp_reg)), vmslots_reg); + } else { + Register temp2_reg = vmslots_reg; + ld_ptr(Address(mh_reg, delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg)), temp2_reg); + ld_ptr(Address(temp2_reg, delayed_value(java_dyn_MethodType::form_offset_in_bytes, temp_reg)), temp2_reg); + ld( Address(temp2_reg, delayed_value(java_dyn_MethodTypeForm::vmslots_offset_in_bytes, temp_reg)), vmslots_reg); + } +} + + +void MacroAssembler::jump_to_method_handle_entry(Register mh_reg, Register temp_reg, bool emit_delayed_nop) { assert(mh_reg == G3_method_handle, "caller must put MH object in G3"); assert_different_registers(mh_reg, temp_reg); + if (UseCompressedOops) unimplemented("coop"); // field accesses must decode + // pick out the interpreted side of the handler ld_ptr(mh_reg, delayed_value(java_dyn_MethodHandle::vmentry_offset_in_bytes, temp_reg), temp_reg); @@ -3043,17 +3142,18 @@ void MacroAssembler::jump_to_method_handle_entry(Register mh_reg, Register temp_ // for the various stubs which take control at this point, // see MethodHandles::generate_method_handle_stub - // (Can any caller use this delay slot? If so, add an option for supression.) - delayed()->nop(); + // Some callers can fill the delay slot. + if (emit_delayed_nop) { + delayed()->nop(); + } } + RegisterOrConstant MacroAssembler::argument_offset(RegisterOrConstant arg_slot, int extra_slot_offset) { // cf. TemplateTable::prepare_invoke(), if (load_receiver). - int stackElementSize = Interpreter::stackElementWords() * wordSize; - int offset = Interpreter::expr_offset_in_bytes(extra_slot_offset+0); - int offset1 = Interpreter::expr_offset_in_bytes(extra_slot_offset+1); - assert(offset1 - offset == stackElementSize, "correct arithmetic"); + int stackElementSize = Interpreter::stackElementSize(); + int offset = extra_slot_offset * stackElementSize; if (arg_slot.is_constant()) { offset += arg_slot.as_constant() * stackElementSize; return offset; @@ -3067,6 +3167,11 @@ RegisterOrConstant MacroAssembler::argument_offset(RegisterOrConstant arg_slot, } +Address MacroAssembler::argument_address(RegisterOrConstant arg_slot, + int extra_slot_offset) { + return Address(Gargs, argument_offset(arg_slot, extra_slot_offset)); +} + void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg, Register temp_reg, diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp index f053ec57771..715d3b5d17b 100644 --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2009 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 @@ -1380,24 +1380,25 @@ public: // pp 181 - void and3( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(and_op3 ) | rs1(s1) | rs2(s2) ); } - void and3( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(and_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } + void and3( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(and_op3 ) | rs1(s1) | rs2(s2) ); } + void and3( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(and_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } void andcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(and_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); } void andcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(and_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } void andn( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(andn_op3 ) | rs1(s1) | rs2(s2) ); } void andn( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(andn_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } + void andn( Register s1, RegisterOrConstant s2, Register d); void andncc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(andn_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); } void andncc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(andn_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } - void or3( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(or_op3 ) | rs1(s1) | rs2(s2) ); } - void or3( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(or_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } + void or3( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(or_op3 ) | rs1(s1) | rs2(s2) ); } + void or3( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(or_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } void orcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(or_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); } void orcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(or_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } void orn( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(orn_op3) | rs1(s1) | rs2(s2) ); } void orn( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(orn_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } void orncc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(orn_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); } void orncc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(orn_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } - void xor3( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(xor_op3 ) | rs1(s1) | rs2(s2) ); } - void xor3( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(xor_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } + void xor3( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(xor_op3 ) | rs1(s1) | rs2(s2) ); } + void xor3( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(xor_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } void xorcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(xor_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); } void xorcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(xor_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } void xnor( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(xnor_op3 ) | rs1(s1) | rs2(s2) ); } @@ -2026,8 +2027,8 @@ public: inline void st_ptr(Register d, Register s1, ByteSize simm13a); #endif - // ld_long will perform ld for 32 bit VM's and ldx for 64 bit VM's - // st_long will perform st for 32 bit VM's and stx for 64 bit VM's + // ld_long will perform ldd for 32 bit VM's and ldx for 64 bit VM's + // st_long will perform std for 32 bit VM's and stx for 64 bit VM's inline void ld_long(Register s1, Register s2, Register d); inline void ld_long(Register s1, int simm13a, Register d); inline void ld_long(Register s1, RegisterOrConstant s2, Register d); @@ -2038,23 +2039,19 @@ public: inline void st_long(Register d, const Address& a, int offset = 0); // Helpers for address formation. - // They update the dest in place, whether it is a register or constant. - // They emit no code at all if src is a constant zero. - // If dest is a constant and src is a register, the temp argument - // is required, and becomes the result. - // If dest is a register and src is a non-simm13 constant, - // the temp argument is required, and is used to materialize the constant. - void regcon_inc_ptr( RegisterOrConstant& dest, RegisterOrConstant src, - Register temp = noreg ); - void regcon_sll_ptr( RegisterOrConstant& dest, RegisterOrConstant src, - Register temp = noreg ); + // - They emit only a move if s2 is a constant zero. + // - If dest is a constant and either s1 or s2 is a register, the temp argument is required and becomes the result. + // - If dest is a register and either s1 or s2 is a non-simm13 constant, the temp argument is required and used to materialize the constant. + RegisterOrConstant regcon_andn_ptr(RegisterOrConstant s1, RegisterOrConstant s2, RegisterOrConstant d, Register temp = noreg); + RegisterOrConstant regcon_inc_ptr( RegisterOrConstant s1, RegisterOrConstant s2, RegisterOrConstant d, Register temp = noreg); + RegisterOrConstant regcon_sll_ptr( RegisterOrConstant s1, RegisterOrConstant s2, RegisterOrConstant d, Register temp = noreg); - RegisterOrConstant ensure_simm13_or_reg(RegisterOrConstant roc, Register Rtemp) { - guarantee(Rtemp != noreg, "constant offset overflow"); - if (is_simm13(roc.constant_or_zero())) - return roc; // register or short constant - set(roc.as_constant(), Rtemp); - return RegisterOrConstant(Rtemp); + RegisterOrConstant ensure_simm13_or_reg(RegisterOrConstant src, Register temp) { + if (is_simm13(src.constant_or_zero())) + return src; // register or short constant + guarantee(temp != noreg, "constant offset overflow"); + set(src.as_constant(), temp); + return temp; } // -------------------------------------------------- @@ -2303,6 +2300,9 @@ public: void lcmp( Register Ra, Register Rb, Register Rresult); #endif + // Loading values by size and signed-ness + void load_sized_value(Address src, Register dst, size_t size_in_bytes, bool is_signed); + void float_cmp( bool is_float, int unordered_result, FloatRegister Fa, FloatRegister Fb, Register Rresult); @@ -2421,12 +2421,16 @@ public: void check_method_handle_type(Register mtype_reg, Register mh_reg, Register temp_reg, Label& wrong_method_type); - void jump_to_method_handle_entry(Register mh_reg, Register temp_reg); + void load_method_handle_vmslots(Register vmslots_reg, Register mh_reg, + Register temp_reg); + void jump_to_method_handle_entry(Register mh_reg, Register temp_reg, bool emit_delayed_nop = true); // offset relative to Gargs of argument at tos[arg_slot]. // (arg_slot == 0 means the last argument, not the first). RegisterOrConstant argument_offset(RegisterOrConstant arg_slot, int extra_slot_offset = 0); - + // Address of Gargs and argument_offset. + Address argument_address(RegisterOrConstant arg_slot, + int extra_slot_offset = 0); // Stack overflow checking diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp index 6ec0d8d2ed3..d769f711125 100644 --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp @@ -206,12 +206,17 @@ inline void Assembler::ld( Register s1, RegisterOrConstant s2, Register d) { ld inline void Assembler::ldd( Register s1, RegisterOrConstant s2, Register d) { ldd( Address(s1, s2), d); } // form effective addresses this way: -inline void Assembler::add( Register s1, RegisterOrConstant s2, Register d, int offset) { - if (s2.is_register()) add(s1, s2.as_register(), d); +inline void Assembler::add(Register s1, RegisterOrConstant s2, Register d, int offset) { + if (s2.is_register()) add(s1, s2.as_register(), d); else { add(s1, s2.as_constant() + offset, d); offset = 0; } if (offset != 0) add(d, offset, d); } +inline void Assembler::andn(Register s1, RegisterOrConstant s2, Register d) { + if (s2.is_register()) andn(s1, s2.as_register(), d); + else andn(s1, s2.as_constant(), d); +} + inline void Assembler::ldstub( Register s1, Register s2, Register d) { emit_long( op(ldst_op) | rd(d) | op3(ldstub_op3) | rs1(s1) | rs2(s2) ); } inline void Assembler::ldstub( Register s1, int simm13a, Register d) { emit_data( op(ldst_op) | rd(d) | op3(ldstub_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } diff --git a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp index 9189f95d355..b5535f86f51 100644 --- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp @@ -814,22 +814,39 @@ void InterpreterMacroAssembler::get_4_byte_integer_at_bcp( } -void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache, Register tmp, int bcp_offset) { +void InterpreterMacroAssembler::get_cache_index_at_bcp(Register cache, Register tmp, + int bcp_offset, bool giant_index) { + assert(bcp_offset > 0, "bcp is still pointing to start of bytecode"); + if (!giant_index) { + get_2_byte_integer_at_bcp(bcp_offset, cache, tmp, Unsigned); + } else { + assert(EnableInvokeDynamic, "giant index used only for EnableInvokeDynamic"); + get_4_byte_integer_at_bcp(bcp_offset, cache, tmp); + assert(constantPoolCacheOopDesc::decode_secondary_index(~123) == 123, "else change next line"); + xor3(tmp, -1, tmp); // convert to plain index + } +} + + +void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache, Register tmp, + int bcp_offset, bool giant_index) { assert(bcp_offset > 0, "bcp is still pointing to start of bytecode"); assert_different_registers(cache, tmp); assert_not_delayed(); - get_2_byte_integer_at_bcp(bcp_offset, cache, tmp, Unsigned); - // convert from field index to ConstantPoolCacheEntry index - // and from word index to byte offset + get_cache_index_at_bcp(cache, tmp, bcp_offset, giant_index); + // convert from field index to ConstantPoolCacheEntry index and from + // word index to byte offset sll(tmp, exact_log2(in_words(ConstantPoolCacheEntry::size()) * BytesPerWord), tmp); add(LcpoolCache, tmp, cache); } -void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset) { +void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache, Register tmp, + int bcp_offset, bool giant_index) { assert(bcp_offset > 0, "bcp is still pointing to start of bytecode"); assert_different_registers(cache, tmp); assert_not_delayed(); + assert(!giant_index,"NYI"); get_2_byte_integer_at_bcp(bcp_offset, cache, tmp, Unsigned); // convert from field index to ConstantPoolCacheEntry index // and from word index to byte offset @@ -1675,15 +1692,31 @@ void InterpreterMacroAssembler::profile_final_call(Register scratch) { // Count a virtual call in the bytecodes. void InterpreterMacroAssembler::profile_virtual_call(Register receiver, - Register scratch) { + Register scratch, + bool receiver_can_be_null) { if (ProfileInterpreter) { Label profile_continue; // If no method data exists, go to profile_continue. test_method_data_pointer(profile_continue); + + Label skip_receiver_profile; + if (receiver_can_be_null) { + Label not_null; + tst(receiver); + brx(Assembler::notZero, false, Assembler::pt, not_null); + delayed()->nop(); + // We are making a call. Increment the count for null receiver. + increment_mdp_data_at(in_bytes(CounterData::count_offset()), scratch); + ba(false, skip_receiver_profile); + delayed()->nop(); + bind(not_null); + } + // Record the receiver type. record_klass_in_profile(receiver, scratch, true); + bind(skip_receiver_profile); // The method data pointer needs to be updated to reflect the new target. update_mdp_by_constant(in_bytes(VirtualCallData::virtual_call_data_size())); diff --git a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp index cbb6fb4e276..0fd57778afe 100644 --- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp @@ -191,8 +191,9 @@ class InterpreterMacroAssembler: public MacroAssembler { Register Rdst, setCCOrNot should_set_CC = dont_set_CC ); - void get_cache_and_index_at_bcp(Register cache, Register tmp, int bcp_offset); - void get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset); + void get_cache_and_index_at_bcp(Register cache, Register tmp, int bcp_offset, bool giant_index = false); + void get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset, bool giant_index = false); + void get_cache_index_at_bcp(Register cache, Register tmp, int bcp_offset, bool giant_index = false); // common code @@ -304,7 +305,7 @@ class InterpreterMacroAssembler: public MacroAssembler { void profile_not_taken_branch(Register scratch); void profile_call(Register scratch); void profile_final_call(Register scratch); - void profile_virtual_call(Register receiver, Register scratch); + void profile_virtual_call(Register receiver, Register scratch, bool receiver_can_be_null = false); void profile_ret(TosState state, Register return_bci, Register scratch); void profile_null_seen(Register scratch); void profile_typecheck(Register klass, Register scratch); diff --git a/hotspot/src/cpu/sparc/vm/interpreter_sparc.cpp b/hotspot/src/cpu/sparc/vm/interpreter_sparc.cpp index d68d2b7702c..24560ab643e 100644 --- a/hotspot/src/cpu/sparc/vm/interpreter_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/interpreter_sparc.cpp @@ -235,19 +235,17 @@ address InterpreterGenerator::generate_abstract_entry(void) { } - // Method handle invoker // Dispatch a method of the form java.dyn.MethodHandles::invoke(...) address InterpreterGenerator::generate_method_handle_entry(void) { if (!EnableMethodHandles) { return generate_abstract_entry(); } - return generate_abstract_entry(); //6815692// + + return MethodHandles::generate_method_handle_interpreter_entry(_masm); } - - //---------------------------------------------------------------------------------------------------- // Entry points & stack frame layout // diff --git a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp index dd40006e102..c8accffeaf7 100644 --- a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-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 @@ -29,6 +29,9 @@ address MethodHandleEntry::start_compiled_entry(MacroAssembler* _masm, address interpreted_entry) { + // Just before the actual machine code entry point, allocate space + // for a MethodHandleEntry::Data record, so that we can manage everything + // from one base pointer. __ align(wordSize); address target = __ pc() + sizeof(Data); while (__ pc() < target) { @@ -59,12 +62,876 @@ MethodHandleEntry* MethodHandleEntry::finish_compiled_entry(MacroAssembler* _mas // Code generation address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* _masm) { - ShouldNotReachHere(); //NYI, 6815692 - return NULL; + // I5_savedSP: sender SP (must preserve) + // G4 (Gargs): incoming argument list (must preserve) + // G5_method: invoke methodOop; becomes method type. + // G3_method_handle: receiver method handle (must load from sp[MethodTypeForm.vmslots]) + // O0, O1: garbage temps, blown away + Register O0_argslot = O0; + Register O1_scratch = O1; + + // emit WrongMethodType path first, to enable back-branch from main path + Label wrong_method_type; + __ bind(wrong_method_type); + __ jump_to(AddressLiteral(Interpreter::throw_WrongMethodType_entry()), O1_scratch); + __ delayed()->nop(); + + // here's where control starts out: + __ align(CodeEntryAlignment); + address entry_point = __ pc(); + + // fetch the MethodType from the method handle into G5_method_type + { + Register tem = G5_method; + assert(tem == G5_method_type, "yes, it's the same register"); + for (jint* pchase = methodOopDesc::method_type_offsets_chain(); (*pchase) != -1; pchase++) { + __ ld_ptr(Address(tem, *pchase), G5_method_type); + } + } + + // given the MethodType, find out where the MH argument is buried + __ ld_ptr(Address(G5_method_type, __ delayed_value(java_dyn_MethodType::form_offset_in_bytes, O1_scratch)), O0_argslot); + __ ldsw( Address(O0_argslot, __ delayed_value(java_dyn_MethodTypeForm::vmslots_offset_in_bytes, O1_scratch)), O0_argslot); + __ ld_ptr(__ argument_address(O0_argslot), G3_method_handle); + + __ check_method_handle_type(G5_method_type, G3_method_handle, O1_scratch, wrong_method_type); + __ jump_to_method_handle_entry(G3_method_handle, O1_scratch); + + return entry_point; } + +#ifdef ASSERT +static void verify_argslot(MacroAssembler* _masm, Register argslot_reg, Register temp_reg, const char* error_message) { + // Verify that argslot lies within (Gargs, FP]. + Label L_ok, L_bad; +#ifdef _LP64 + __ add(FP, STACK_BIAS, temp_reg); + __ cmp(argslot_reg, temp_reg); +#else + __ cmp(argslot_reg, FP); +#endif + __ brx(Assembler::greaterUnsigned, false, Assembler::pn, L_bad); + __ delayed()->nop(); + __ cmp(Gargs, argslot_reg); + __ brx(Assembler::lessEqualUnsigned, false, Assembler::pt, L_ok); + __ delayed()->nop(); + __ bind(L_bad); + __ stop(error_message); + __ bind(L_ok); +} +#endif + + +// Helper to insert argument slots into the stack. +// arg_slots must be a multiple of stack_move_unit() and <= 0 +void MethodHandles::insert_arg_slots(MacroAssembler* _masm, + RegisterOrConstant arg_slots, + int arg_mask, + Register argslot_reg, + Register temp_reg, Register temp2_reg, Register temp3_reg) { + assert(temp3_reg != noreg, "temp3 required"); + assert_different_registers(argslot_reg, temp_reg, temp2_reg, temp3_reg, + (!arg_slots.is_register() ? Gargs : arg_slots.as_register())); + +#ifdef ASSERT + verify_argslot(_masm, argslot_reg, temp_reg, "insertion point must fall within current frame"); + if (arg_slots.is_register()) { + Label L_ok, L_bad; + __ cmp(arg_slots.as_register(), (int32_t) NULL_WORD); + __ br(Assembler::greater, false, Assembler::pn, L_bad); + __ delayed()->nop(); + __ btst(-stack_move_unit() - 1, arg_slots.as_register()); + __ br(Assembler::zero, false, Assembler::pt, L_ok); + __ delayed()->nop(); + __ bind(L_bad); + __ stop("assert arg_slots <= 0 and clear low bits"); + __ bind(L_ok); + } else { + assert(arg_slots.as_constant() <= 0, ""); + assert(arg_slots.as_constant() % -stack_move_unit() == 0, ""); + } +#endif // ASSERT + +#ifdef _LP64 + if (arg_slots.is_register()) { + // Was arg_slots register loaded as signed int? + Label L_ok; + __ sll(arg_slots.as_register(), BitsPerInt, temp_reg); + __ sra(temp_reg, BitsPerInt, temp_reg); + __ cmp(arg_slots.as_register(), temp_reg); + __ br(Assembler::equal, false, Assembler::pt, L_ok); + __ delayed()->nop(); + __ stop("arg_slots register not loaded as signed int"); + __ bind(L_ok); + } +#endif + + // Make space on the stack for the inserted argument(s). + // Then pull down everything shallower than argslot_reg. + // The stacked return address gets pulled down with everything else. + // That is, copy [sp, argslot) downward by -size words. In pseudo-code: + // sp -= size; + // for (temp = sp + size; temp < argslot; temp++) + // temp[-size] = temp[0] + // argslot -= size; + RegisterOrConstant offset = __ regcon_sll_ptr(arg_slots, LogBytesPerWord, temp3_reg); + + // Keep the stack pointer 2*wordSize aligned. + const int TwoWordAlignmentMask = right_n_bits(LogBytesPerWord + 1); + RegisterOrConstant masked_offset = __ regcon_andn_ptr(offset, TwoWordAlignmentMask, temp_reg); + __ add(SP, masked_offset, SP); + + __ mov(Gargs, temp_reg); // source pointer for copy + __ add(Gargs, offset, Gargs); + + { + Label loop; + __ bind(loop); + // pull one word down each time through the loop + __ ld_ptr(Address(temp_reg, 0), temp2_reg); + __ st_ptr(temp2_reg, Address(temp_reg, offset)); + __ add(temp_reg, wordSize, temp_reg); + __ cmp(temp_reg, argslot_reg); + __ brx(Assembler::less, false, Assembler::pt, loop); + __ delayed()->nop(); // FILLME + } + + // Now move the argslot down, to point to the opened-up space. + __ add(argslot_reg, offset, argslot_reg); +} + + +// Helper to remove argument slots from the stack. +// arg_slots must be a multiple of stack_move_unit() and >= 0 +void MethodHandles::remove_arg_slots(MacroAssembler* _masm, + RegisterOrConstant arg_slots, + Register argslot_reg, + Register temp_reg, Register temp2_reg, Register temp3_reg) { + assert(temp3_reg != noreg, "temp3 required"); + assert_different_registers(argslot_reg, temp_reg, temp2_reg, temp3_reg, + (!arg_slots.is_register() ? Gargs : arg_slots.as_register())); + + RegisterOrConstant offset = __ regcon_sll_ptr(arg_slots, LogBytesPerWord, temp3_reg); + +#ifdef ASSERT + // Verify that [argslot..argslot+size) lies within (Gargs, FP). + __ add(argslot_reg, offset, temp2_reg); + verify_argslot(_masm, temp2_reg, temp_reg, "deleted argument(s) must fall within current frame"); + if (arg_slots.is_register()) { + Label L_ok, L_bad; + __ cmp(arg_slots.as_register(), (int32_t) NULL_WORD); + __ br(Assembler::less, false, Assembler::pn, L_bad); + __ delayed()->nop(); + __ btst(-stack_move_unit() - 1, arg_slots.as_register()); + __ br(Assembler::zero, false, Assembler::pt, L_ok); + __ delayed()->nop(); + __ bind(L_bad); + __ stop("assert arg_slots >= 0 and clear low bits"); + __ bind(L_ok); + } else { + assert(arg_slots.as_constant() >= 0, ""); + assert(arg_slots.as_constant() % -stack_move_unit() == 0, ""); + } +#endif // ASSERT + + // Pull up everything shallower than argslot. + // Then remove the excess space on the stack. + // The stacked return address gets pulled up with everything else. + // That is, copy [sp, argslot) upward by size words. In pseudo-code: + // for (temp = argslot-1; temp >= sp; --temp) + // temp[size] = temp[0] + // argslot += size; + // sp += size; + __ sub(argslot_reg, wordSize, temp_reg); // source pointer for copy + { + Label loop; + __ bind(loop); + // pull one word up each time through the loop + __ ld_ptr(Address(temp_reg, 0), temp2_reg); + __ st_ptr(temp2_reg, Address(temp_reg, offset)); + __ sub(temp_reg, wordSize, temp_reg); + __ cmp(temp_reg, Gargs); + __ brx(Assembler::greaterEqual, false, Assembler::pt, loop); + __ delayed()->nop(); // FILLME + } + + // Now move the argslot up, to point to the just-copied block. + __ add(Gargs, offset, Gargs); + // And adjust the argslot address to point at the deletion point. + __ add(argslot_reg, offset, argslot_reg); + + // Keep the stack pointer 2*wordSize aligned. + const int TwoWordAlignmentMask = right_n_bits(LogBytesPerWord + 1); + RegisterOrConstant masked_offset = __ regcon_andn_ptr(offset, TwoWordAlignmentMask, temp_reg); + __ add(SP, masked_offset, SP); +} + + +#ifndef PRODUCT +extern "C" void print_method_handle(oop mh); +void trace_method_handle_stub(const char* adaptername, + oop mh) { +#if 0 + intptr_t* entry_sp, + intptr_t* saved_sp, + intptr_t* saved_bp) { + // called as a leaf from native code: do not block the JVM! + intptr_t* last_sp = (intptr_t*) saved_bp[frame::interpreter_frame_last_sp_offset]; + intptr_t* base_sp = (intptr_t*) saved_bp[frame::interpreter_frame_monitor_block_top_offset]; + printf("MH %s mh="INTPTR_FORMAT" sp=("INTPTR_FORMAT"+"INTX_FORMAT") stack_size="INTX_FORMAT" bp="INTPTR_FORMAT"\n", + adaptername, (intptr_t)mh, (intptr_t)entry_sp, (intptr_t)(saved_sp - entry_sp), (intptr_t)(base_sp - last_sp), (intptr_t)saved_bp); + if (last_sp != saved_sp) + printf("*** last_sp="INTPTR_FORMAT"\n", (intptr_t)last_sp); +#endif + + printf("MH %s mh="INTPTR_FORMAT"\n", adaptername, (intptr_t) mh); + print_method_handle(mh); +} +#endif // PRODUCT + + +//------------------------------------------------------------------------------ +// MethodHandles::generate_method_handle_stub +// // Generate an "entry" field for a method handle. // This determines how the method handle will respond to calls. void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek) { - ShouldNotReachHere(); //NYI, 6815692 + // Here is the register state during an interpreted call, + // as set up by generate_method_handle_interpreter_entry(): + // - G5: garbage temp (was MethodHandle.invoke methodOop, unused) + // - G3: receiver method handle + // - O5_savedSP: sender SP (must preserve) + + Register O0_argslot = O0; + Register O1_scratch = O1; + Register O2_scratch = O2; + Register O3_scratch = O3; + Register G5_index = G5; + + guarantee(java_dyn_MethodHandle::vmentry_offset_in_bytes() != 0, "must have offsets"); + + // Some handy addresses: + Address G5_method_fie( G5_method, in_bytes(methodOopDesc::from_interpreted_offset())); + + Address G3_mh_vmtarget( G3_method_handle, java_dyn_MethodHandle::vmtarget_offset_in_bytes()); + + Address G3_dmh_vmindex( G3_method_handle, sun_dyn_DirectMethodHandle::vmindex_offset_in_bytes()); + + Address G3_bmh_vmargslot( G3_method_handle, sun_dyn_BoundMethodHandle::vmargslot_offset_in_bytes()); + Address G3_bmh_argument( G3_method_handle, sun_dyn_BoundMethodHandle::argument_offset_in_bytes()); + + Address G3_amh_vmargslot( G3_method_handle, sun_dyn_AdapterMethodHandle::vmargslot_offset_in_bytes()); + Address G3_amh_argument ( G3_method_handle, sun_dyn_AdapterMethodHandle::argument_offset_in_bytes()); + Address G3_amh_conversion(G3_method_handle, sun_dyn_AdapterMethodHandle::conversion_offset_in_bytes()); + + const int java_mirror_offset = klassOopDesc::klass_part_offset_in_bytes() + Klass::java_mirror_offset_in_bytes(); + + if (have_entry(ek)) { + __ nop(); // empty stubs make SG sick + return; + } + + address interp_entry = __ pc(); + if (UseCompressedOops) __ unimplemented("UseCompressedOops"); + +#ifndef PRODUCT + if (TraceMethodHandles) { + // save: Gargs, O5_savedSP + __ save(SP, -16*wordSize, SP); + __ set((intptr_t) entry_name(ek), O0); + __ mov(G3_method_handle, O1); + __ call_VM_leaf(Lscratch, CAST_FROM_FN_PTR(address, trace_method_handle_stub)); + __ restore(SP, 16*wordSize, SP); + } +#endif // PRODUCT + + switch ((int) ek) { + case _raise_exception: + { + // Not a real MH entry, but rather shared code for raising an + // exception. Extra local arguments are passed in scratch + // registers, as required type in O3, failing object (or NULL) + // in O2, failing bytecode type in O1. + + __ mov(O5_savedSP, SP); // Cut the stack back to where the caller started. + + // Push arguments as if coming from the interpreter. + Register O0_scratch = O0_argslot; + int stackElementSize = Interpreter::stackElementSize(); + + // Make space on the stack for the arguments. + __ sub(SP, 4*stackElementSize, SP); + __ sub(Gargs, 3*stackElementSize, Gargs); + //__ sub(Lesp, 3*stackElementSize, Lesp); + + // void raiseException(int code, Object actual, Object required) + __ st( O1_scratch, Address(Gargs, 2*stackElementSize)); // code + __ st_ptr(O2_scratch, Address(Gargs, 1*stackElementSize)); // actual + __ st_ptr(O3_scratch, Address(Gargs, 0*stackElementSize)); // required + + Label no_method; + // FIXME: fill in _raise_exception_method with a suitable sun.dyn method + __ set(AddressLiteral((address) &_raise_exception_method), G5_method); + __ ld_ptr(Address(G5_method, 0), G5_method); + __ tst(G5_method); + __ brx(Assembler::zero, false, Assembler::pn, no_method); + __ delayed()->nop(); + + int jobject_oop_offset = 0; + __ ld_ptr(Address(G5_method, jobject_oop_offset), G5_method); + __ tst(G5_method); + __ brx(Assembler::zero, false, Assembler::pn, no_method); + __ delayed()->nop(); + + __ verify_oop(G5_method); + __ jump_indirect_to(G5_method_fie, O1_scratch); + __ delayed()->nop(); + + // If we get here, the Java runtime did not do its job of creating the exception. + // Do something that is at least causes a valid throw from the interpreter. + __ bind(no_method); + __ unimplemented("_raise_exception no method"); + } + break; + + case _invokestatic_mh: + case _invokespecial_mh: + { + __ ld_ptr(G3_mh_vmtarget, G5_method); // target is a methodOop + __ verify_oop(G5_method); + // Same as TemplateTable::invokestatic or invokespecial, + // minus the CP setup and profiling: + if (ek == _invokespecial_mh) { + // Must load & check the first argument before entering the target method. + __ load_method_handle_vmslots(O0_argslot, G3_method_handle, O1_scratch); + __ ld_ptr(__ argument_address(O0_argslot), G3_method_handle); + __ null_check(G3_method_handle); + __ verify_oop(G3_method_handle); + } + __ jump_indirect_to(G5_method_fie, O1_scratch); + __ delayed()->nop(); + } + break; + + case _invokevirtual_mh: + { + // Same as TemplateTable::invokevirtual, + // minus the CP setup and profiling: + + // Pick out the vtable index and receiver offset from the MH, + // and then we can discard it: + __ load_method_handle_vmslots(O0_argslot, G3_method_handle, O1_scratch); + __ ldsw(G3_dmh_vmindex, G5_index); + // Note: The verifier allows us to ignore G3_mh_vmtarget. + __ ld_ptr(__ argument_address(O0_argslot, -1), G3_method_handle); + __ null_check(G3_method_handle, oopDesc::klass_offset_in_bytes()); + + // Get receiver klass: + Register O0_klass = O0_argslot; + __ load_klass(G3_method_handle, O0_klass); + __ verify_oop(O0_klass); + + // Get target methodOop & entry point: + const int base = instanceKlass::vtable_start_offset() * wordSize; + assert(vtableEntry::size() * wordSize == wordSize, "adjust the scaling in the code below"); + + __ sll_ptr(G5_index, LogBytesPerWord, G5_index); + __ add(O0_klass, G5_index, O0_klass); + Address vtable_entry_addr(O0_klass, base + vtableEntry::method_offset_in_bytes()); + __ ld_ptr(vtable_entry_addr, G5_method); + + __ verify_oop(G5_method); + __ jump_indirect_to(G5_method_fie, O1_scratch); + __ delayed()->nop(); + } + break; + + case _invokeinterface_mh: + { + // Same as TemplateTable::invokeinterface, + // minus the CP setup and profiling: + __ load_method_handle_vmslots(O0_argslot, G3_method_handle, O1_scratch); + Register O1_intf = O1_scratch; + __ ld_ptr(G3_mh_vmtarget, O1_intf); + __ ldsw(G3_dmh_vmindex, G5_index); + __ ld_ptr(__ argument_address(O0_argslot, -1), G3_method_handle); + __ null_check(G3_method_handle, oopDesc::klass_offset_in_bytes()); + + // Get receiver klass: + Register O0_klass = O0_argslot; + __ load_klass(G3_method_handle, O0_klass); + __ verify_oop(O0_klass); + + // Get interface: + Label no_such_interface; + __ verify_oop(O1_intf); + __ lookup_interface_method(O0_klass, O1_intf, + // Note: next two args must be the same: + G5_index, G5_method, + O2_scratch, + O3_scratch, + no_such_interface); + + __ verify_oop(G5_method); + __ jump_indirect_to(G5_method_fie, O1_scratch); + __ delayed()->nop(); + + __ bind(no_such_interface); + // Throw an exception. + // For historical reasons, it will be IncompatibleClassChangeError. + __ unimplemented("not tested yet"); + __ ld_ptr(Address(O1_intf, java_mirror_offset), O3_scratch); // required interface + __ mov(O0_klass, O2_scratch); // bad receiver + __ jump_to(AddressLiteral(from_interpreted_entry(_raise_exception)), O0_argslot); + __ delayed()->mov(Bytecodes::_invokeinterface, O1_scratch); // who is complaining? + } + break; + + case _bound_ref_mh: + case _bound_int_mh: + case _bound_long_mh: + case _bound_ref_direct_mh: + case _bound_int_direct_mh: + case _bound_long_direct_mh: + { + const bool direct_to_method = (ek >= _bound_ref_direct_mh); + BasicType arg_type = T_ILLEGAL; + int arg_mask = _INSERT_NO_MASK; + int arg_slots = -1; + get_ek_bound_mh_info(ek, arg_type, arg_mask, arg_slots); + + // Make room for the new argument: + __ ldsw(G3_bmh_vmargslot, O0_argslot); + __ add(Gargs, __ argument_offset(O0_argslot), O0_argslot); + + insert_arg_slots(_masm, arg_slots * stack_move_unit(), arg_mask, O0_argslot, O1_scratch, O2_scratch, G5_index); + + // Store bound argument into the new stack slot: + __ ld_ptr(G3_bmh_argument, O1_scratch); + if (arg_type == T_OBJECT) { + __ st_ptr(O1_scratch, Address(O0_argslot, 0)); + } else { + Address prim_value_addr(O1_scratch, java_lang_boxing_object::value_offset_in_bytes(arg_type)); + __ load_sized_value(prim_value_addr, O2_scratch, type2aelembytes(arg_type), is_signed_subword_type(arg_type)); + if (arg_slots == 2) { + __ unimplemented("not yet tested"); +#ifndef _LP64 + __ signx(O2_scratch, O3_scratch); // Sign extend +#endif + __ st_long(O2_scratch, Address(O0_argslot, 0)); // Uses O2/O3 on !_LP64 + } else { + __ st_ptr( O2_scratch, Address(O0_argslot, 0)); + } + } + + if (direct_to_method) { + __ ld_ptr(G3_mh_vmtarget, G5_method); // target is a methodOop + __ verify_oop(G5_method); + __ jump_indirect_to(G5_method_fie, O1_scratch); + __ delayed()->nop(); + } else { + __ ld_ptr(G3_mh_vmtarget, G3_method_handle); // target is a methodOop + __ verify_oop(G3_method_handle); + __ jump_to_method_handle_entry(G3_method_handle, O1_scratch); + } + } + break; + + case _adapter_retype_only: + case _adapter_retype_raw: + // Immediately jump to the next MH layer: + __ ld_ptr(G3_mh_vmtarget, G3_method_handle); + __ jump_to_method_handle_entry(G3_method_handle, O1_scratch); + // This is OK when all parameter types widen. + // It is also OK when a return type narrows. + break; + + case _adapter_check_cast: + { + // Temps: + Register G5_klass = G5_index; // Interesting AMH data. + + // Check a reference argument before jumping to the next layer of MH: + __ ldsw(G3_amh_vmargslot, O0_argslot); + Address vmarg = __ argument_address(O0_argslot); + + // What class are we casting to? + __ ld_ptr(G3_amh_argument, G5_klass); // This is a Class object! + __ ld_ptr(Address(G5_klass, java_lang_Class::klass_offset_in_bytes()), G5_klass); + + Label done; + __ ld_ptr(vmarg, O1_scratch); + __ tst(O1_scratch); + __ brx(Assembler::zero, false, Assembler::pn, done); // No cast if null. + __ delayed()->nop(); + __ load_klass(O1_scratch, O1_scratch); + + // Live at this point: + // - G5_klass : klass required by the target method + // - O1_scratch : argument klass to test + // - G3_method_handle: adapter method handle + __ check_klass_subtype(O1_scratch, G5_klass, O0_argslot, O2_scratch, done); + + // If we get here, the type check failed! + __ ldsw(G3_amh_vmargslot, O0_argslot); // reload argslot field + __ ld_ptr(G3_amh_argument, O3_scratch); // required class + __ ld_ptr(vmarg, O2_scratch); // bad object + __ jump_to(AddressLiteral(from_interpreted_entry(_raise_exception)), O0_argslot); + __ delayed()->mov(Bytecodes::_checkcast, O1_scratch); // who is complaining? + + __ bind(done); + // Get the new MH: + __ ld_ptr(G3_mh_vmtarget, G3_method_handle); + __ jump_to_method_handle_entry(G3_method_handle, O1_scratch); + } + break; + + case _adapter_prim_to_prim: + case _adapter_ref_to_prim: + // Handled completely by optimized cases. + __ stop("init_AdapterMethodHandle should not issue this"); + break; + + case _adapter_opt_i2i: // optimized subcase of adapt_prim_to_prim +//case _adapter_opt_f2i: // optimized subcase of adapt_prim_to_prim + case _adapter_opt_l2i: // optimized subcase of adapt_prim_to_prim + case _adapter_opt_unboxi: // optimized subcase of adapt_ref_to_prim + { + // Perform an in-place conversion to int or an int subword. + __ ldsw(G3_amh_vmargslot, O0_argslot); + Address vmarg = __ argument_address(O0_argslot); + Address value; + bool value_left_justified = false; + + switch (ek) { + case _adapter_opt_i2i: + case _adapter_opt_l2i: + __ unimplemented(entry_name(ek)); + value = vmarg; + break; + case _adapter_opt_unboxi: + { + // Load the value up from the heap. + __ ld_ptr(vmarg, O1_scratch); + int value_offset = java_lang_boxing_object::value_offset_in_bytes(T_INT); +#ifdef ASSERT + for (int bt = T_BOOLEAN; bt < T_INT; bt++) { + if (is_subword_type(BasicType(bt))) + assert(value_offset == java_lang_boxing_object::value_offset_in_bytes(BasicType(bt)), ""); + } +#endif + __ null_check(O1_scratch, value_offset); + value = Address(O1_scratch, value_offset); +#ifdef _BIG_ENDIAN + // Values stored in objects are packed. + value_left_justified = true; +#endif + } + break; + default: + ShouldNotReachHere(); + } + + // This check is required on _BIG_ENDIAN + Register G5_vminfo = G5_index; + __ ldsw(G3_amh_conversion, G5_vminfo); + assert(CONV_VMINFO_SHIFT == 0, "preshifted"); + + // Original 32-bit vmdata word must be of this form: + // | MBZ:6 | signBitCount:8 | srcDstTypes:8 | conversionOp:8 | + __ lduw(value, O1_scratch); + if (!value_left_justified) + __ sll(O1_scratch, G5_vminfo, O1_scratch); + Label zero_extend, done; + __ btst(CONV_VMINFO_SIGN_FLAG, G5_vminfo); + __ br(Assembler::zero, false, Assembler::pn, zero_extend); + __ delayed()->nop(); + + // this path is taken for int->byte, int->short + __ sra(O1_scratch, G5_vminfo, O1_scratch); + __ ba(false, done); + __ delayed()->nop(); + + __ bind(zero_extend); + // this is taken for int->char + __ srl(O1_scratch, G5_vminfo, O1_scratch); + + __ bind(done); + __ st(O1_scratch, vmarg); + + // Get the new MH: + __ ld_ptr(G3_mh_vmtarget, G3_method_handle); + __ jump_to_method_handle_entry(G3_method_handle, O1_scratch); + } + break; + + case _adapter_opt_i2l: // optimized subcase of adapt_prim_to_prim + case _adapter_opt_unboxl: // optimized subcase of adapt_ref_to_prim + { + // Perform an in-place int-to-long or ref-to-long conversion. + __ ldsw(G3_amh_vmargslot, O0_argslot); + + // On big-endian machine we duplicate the slot and store the MSW + // in the first slot. + __ add(Gargs, __ argument_offset(O0_argslot, 1), O0_argslot); + + insert_arg_slots(_masm, stack_move_unit(), _INSERT_INT_MASK, O0_argslot, O1_scratch, O2_scratch, G5_index); + + Address arg_lsw(O0_argslot, 0); + Address arg_msw(O0_argslot, -Interpreter::stackElementSize()); + + switch (ek) { + case _adapter_opt_i2l: + { + __ ldsw(arg_lsw, O2_scratch); // Load LSW +#ifndef _LP64 + __ signx(O2_scratch, O3_scratch); // Sign extend +#endif + __ st_long(O2_scratch, arg_msw); // Uses O2/O3 on !_LP64 + } + break; + case _adapter_opt_unboxl: + { + // Load the value up from the heap. + __ ld_ptr(arg_lsw, O1_scratch); + int value_offset = java_lang_boxing_object::value_offset_in_bytes(T_LONG); + assert(value_offset == java_lang_boxing_object::value_offset_in_bytes(T_DOUBLE), ""); + __ null_check(O1_scratch, value_offset); + __ ld_long(Address(O1_scratch, value_offset), O2_scratch); // Uses O2/O3 on !_LP64 + __ st_long(O2_scratch, arg_msw); + } + break; + default: + ShouldNotReachHere(); + } + + __ ld_ptr(G3_mh_vmtarget, G3_method_handle); + __ jump_to_method_handle_entry(G3_method_handle, O1_scratch); + } + break; + + case _adapter_opt_f2d: // optimized subcase of adapt_prim_to_prim + case _adapter_opt_d2f: // optimized subcase of adapt_prim_to_prim + { + // perform an in-place floating primitive conversion + __ unimplemented(entry_name(ek)); + } + break; + + case _adapter_prim_to_ref: + __ unimplemented(entry_name(ek)); // %%% FIXME: NYI + break; + + case _adapter_swap_args: + case _adapter_rot_args: + // handled completely by optimized cases + __ stop("init_AdapterMethodHandle should not issue this"); + break; + + case _adapter_opt_swap_1: + case _adapter_opt_swap_2: + case _adapter_opt_rot_1_up: + case _adapter_opt_rot_1_down: + case _adapter_opt_rot_2_up: + case _adapter_opt_rot_2_down: + { + int swap_bytes = 0, rotate = 0; + get_ek_adapter_opt_swap_rot_info(ek, swap_bytes, rotate); + + // 'argslot' is the position of the first argument to swap. + __ ldsw(G3_amh_vmargslot, O0_argslot); + __ add(Gargs, __ argument_offset(O0_argslot), O0_argslot); + + // 'vminfo' is the second. + Register O1_destslot = O1_scratch; + __ ldsw(G3_amh_conversion, O1_destslot); + assert(CONV_VMINFO_SHIFT == 0, "preshifted"); + __ and3(O1_destslot, CONV_VMINFO_MASK, O1_destslot); + __ add(Gargs, __ argument_offset(O1_destslot), O1_destslot); + + if (!rotate) { + for (int i = 0; i < swap_bytes; i += wordSize) { + __ ld_ptr(Address(O0_argslot, i), O2_scratch); + __ ld_ptr(Address(O1_destslot, i), O3_scratch); + __ st_ptr(O3_scratch, Address(O0_argslot, i)); + __ st_ptr(O2_scratch, Address(O1_destslot, i)); + } + } else { + // Save the first chunk, which is going to get overwritten. + switch (swap_bytes) { + case 4 : __ lduw(Address(O0_argslot, 0), O2_scratch); break; + case 16: __ ldx( Address(O0_argslot, 8), O3_scratch); //fall-thru + case 8 : __ ldx( Address(O0_argslot, 0), O2_scratch); break; + default: ShouldNotReachHere(); + } + + if (rotate > 0) { + // Rorate upward. + __ sub(O0_argslot, swap_bytes, O0_argslot); +#if ASSERT + { + // Verify that argslot > destslot, by at least swap_bytes. + Label L_ok; + __ cmp(O0_argslot, O1_destslot); + __ brx(Assembler::greaterEqualUnsigned, false, Assembler::pt, L_ok); + __ delayed()->nop(); + __ stop("source must be above destination (upward rotation)"); + __ bind(L_ok); + } +#endif + // Work argslot down to destslot, copying contiguous data upwards. + // Pseudo-code: + // argslot = src_addr - swap_bytes + // destslot = dest_addr + // while (argslot >= destslot) { + // *(argslot + swap_bytes) = *(argslot + 0); + // argslot--; + // } + Label loop; + __ bind(loop); + __ ld_ptr(Address(O0_argslot, 0), G5_index); + __ st_ptr(G5_index, Address(O0_argslot, swap_bytes)); + __ sub(O0_argslot, wordSize, O0_argslot); + __ cmp(O0_argslot, O1_destslot); + __ brx(Assembler::greaterEqualUnsigned, false, Assembler::pt, loop); + __ delayed()->nop(); // FILLME + } else { + __ add(O0_argslot, swap_bytes, O0_argslot); +#if ASSERT + { + // Verify that argslot < destslot, by at least swap_bytes. + Label L_ok; + __ cmp(O0_argslot, O1_destslot); + __ brx(Assembler::lessEqualUnsigned, false, Assembler::pt, L_ok); + __ delayed()->nop(); + __ stop("source must be above destination (upward rotation)"); + __ bind(L_ok); + } +#endif + // Work argslot up to destslot, copying contiguous data downwards. + // Pseudo-code: + // argslot = src_addr + swap_bytes + // destslot = dest_addr + // while (argslot >= destslot) { + // *(argslot - swap_bytes) = *(argslot + 0); + // argslot++; + // } + Label loop; + __ bind(loop); + __ ld_ptr(Address(O0_argslot, 0), G5_index); + __ st_ptr(G5_index, Address(O0_argslot, -swap_bytes)); + __ add(O0_argslot, wordSize, O0_argslot); + __ cmp(O0_argslot, O1_destslot); + __ brx(Assembler::lessEqualUnsigned, false, Assembler::pt, loop); + __ delayed()->nop(); // FILLME + } + + // Store the original first chunk into the destination slot, now free. + switch (swap_bytes) { + case 4 : __ stw(O2_scratch, Address(O1_destslot, 0)); break; + case 16: __ stx(O3_scratch, Address(O1_destslot, 8)); // fall-thru + case 8 : __ stx(O2_scratch, Address(O1_destslot, 0)); break; + default: ShouldNotReachHere(); + } + } + + __ ld_ptr(G3_mh_vmtarget, G3_method_handle); + __ jump_to_method_handle_entry(G3_method_handle, O1_scratch); + } + break; + + case _adapter_dup_args: + { + // 'argslot' is the position of the first argument to duplicate. + __ ldsw(G3_amh_vmargslot, O0_argslot); + __ add(Gargs, __ argument_offset(O0_argslot), O0_argslot); + + // 'stack_move' is negative number of words to duplicate. + Register G5_stack_move = G5_index; + __ ldsw(G3_amh_conversion, G5_stack_move); + __ sra(G5_stack_move, CONV_STACK_MOVE_SHIFT, G5_stack_move); + + // Remember the old Gargs (argslot[0]). + Register O1_oldarg = O1_scratch; + __ mov(Gargs, O1_oldarg); + + // Move Gargs down to make room for dups. + __ sll_ptr(G5_stack_move, LogBytesPerWord, G5_stack_move); + __ add(Gargs, G5_stack_move, Gargs); + + // Compute the new Gargs (argslot[0]). + Register O2_newarg = O2_scratch; + __ mov(Gargs, O2_newarg); + + // Copy from oldarg[0...] down to newarg[0...] + // Pseude-code: + // O1_oldarg = old-Gargs + // O2_newarg = new-Gargs + // O0_argslot = argslot + // while (O2_newarg < O1_oldarg) *O2_newarg = *O0_argslot++ + Label loop; + __ bind(loop); + __ ld_ptr(Address(O0_argslot, 0), O3_scratch); + __ st_ptr(O3_scratch, Address(O2_newarg, 0)); + __ add(O0_argslot, wordSize, O0_argslot); + __ add(O2_newarg, wordSize, O2_newarg); + __ cmp(O2_newarg, O1_oldarg); + __ brx(Assembler::less, false, Assembler::pt, loop); + __ delayed()->nop(); // FILLME + + __ ld_ptr(G3_mh_vmtarget, G3_method_handle); + __ jump_to_method_handle_entry(G3_method_handle, O1_scratch); + } + break; + + case _adapter_drop_args: + { + // 'argslot' is the position of the first argument to nuke. + __ ldsw(G3_amh_vmargslot, O0_argslot); + __ add(Gargs, __ argument_offset(O0_argslot), O0_argslot); + + // 'stack_move' is number of words to drop. + Register G5_stack_move = G5_index; + __ ldsw(G3_amh_conversion, G5_stack_move); + __ sra(G5_stack_move, CONV_STACK_MOVE_SHIFT, G5_stack_move); + + remove_arg_slots(_masm, G5_stack_move, O0_argslot, O1_scratch, O2_scratch, O3_scratch); + + __ ld_ptr(G3_mh_vmtarget, G3_method_handle); + __ jump_to_method_handle_entry(G3_method_handle, O1_scratch); + } + break; + + case _adapter_collect_args: + __ unimplemented(entry_name(ek)); // %%% FIXME: NYI + break; + + case _adapter_spread_args: + // Handled completely by optimized cases. + __ stop("init_AdapterMethodHandle should not issue this"); + break; + + case _adapter_opt_spread_0: + case _adapter_opt_spread_1: + case _adapter_opt_spread_more: + { + // spread an array out into a group of arguments + __ unimplemented(entry_name(ek)); + } + break; + + case _adapter_flyby: + case _adapter_ricochet: + __ unimplemented(entry_name(ek)); // %%% FIXME: NYI + break; + + default: + ShouldNotReachHere(); + } + + address me_cookie = MethodHandleEntry::start_compiled_entry(_masm, interp_entry); + __ unimplemented(entry_name(ek)); // %%% FIXME: NYI + + init_entry(ek, MethodHandleEntry::finish_compiled_entry(_masm, me_cookie)); } diff --git a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp index 2fed8cd83b5..e1ea96a3f5b 100644 --- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp @@ -2917,6 +2917,16 @@ 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); + } + } + // Don't initialize the platform math functions since sparc // doesn't have intrinsics for these operations. } diff --git a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp index 8feef8bd8af..fc539099985 100644 --- a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp @@ -151,8 +151,10 @@ address TemplateInterpreterGenerator::generate_StackOverflowError_handler() { address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step) { - address compiled_entry = __ pc(); + TosState incoming_state = state; + Label cont; + address compiled_entry = __ pc(); address entry = __ pc(); #if !defined(_LP64) && defined(COMPILER2) @@ -165,12 +167,11 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, // do this here. Unfortunately if we did a rethrow we'd see an machepilog node // first which would move g1 -> O0/O1 and destroy the exception we were throwing. - if( state == ltos ) { - __ srl (G1, 0,O1); - __ srlx(G1,32,O0); + if (incoming_state == ltos) { + __ srl (G1, 0, O1); + __ srlx(G1, 32, O0); } -#endif /* !_LP64 && COMPILER2 */ - +#endif // !_LP64 && COMPILER2 __ bind(cont); @@ -182,10 +183,17 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, __ mov(Llast_SP, SP); // Remove any adapter added stack space. - + Label L_got_cache, L_giant_index; const Register cache = G3_scratch; const Register size = G1_scratch; + if (EnableInvokeDynamic) { + __ ldub(Address(Lbcp, 0), G1_scratch); // Load current bytecode. + __ cmp(G1_scratch, Bytecodes::_invokedynamic); + __ br(Assembler::equal, false, Assembler::pn, L_giant_index); + __ delayed()->nop(); + } __ get_cache_and_index_at_bcp(cache, G1_scratch, 1); + __ bind(L_got_cache); __ ld_ptr(cache, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::flags_offset(), size); __ and3(size, 0xFF, size); // argument size in words @@ -193,6 +201,14 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, __ add(Lesp, size, Lesp); // pop arguments __ dispatch_next(state, step); + // out of the main line of code... + if (EnableInvokeDynamic) { + __ bind(L_giant_index); + __ get_cache_and_index_at_bcp(cache, G1_scratch, 1, true); + __ ba(false, L_got_cache); + __ delayed()->nop(); + } + return entry; } diff --git a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp index 0849aaef697..5ab2ffc1308 100644 --- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2009 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 @@ -1963,19 +1963,30 @@ void TemplateTable::volatile_barrier(Assembler::Membar_mask_bits order_constrain // ---------------------------------------------------------------------------- void TemplateTable::resolve_cache_and_index(int byte_no, Register Rcache, Register index) { assert(byte_no == 1 || byte_no == 2, "byte_no out of range"); + bool is_invokedynamic = (bytecode() == Bytecodes::_invokedynamic); + // Depends on cpCacheOop layout! const int shift_count = (1 + byte_no)*BitsPerByte; Label resolved; - __ get_cache_and_index_at_bcp(Rcache, index, 1); - __ ld_ptr(Rcache, constantPoolCacheOopDesc::base_offset() + - ConstantPoolCacheEntry::indices_offset(), Lbyte_code); + __ get_cache_and_index_at_bcp(Rcache, index, 1, is_invokedynamic); + if (is_invokedynamic) { + // We are resolved if the f1 field contains a non-null CallSite object. + __ ld_ptr(Rcache, constantPoolCacheOopDesc::base_offset() + + ConstantPoolCacheEntry::f1_offset(), Lbyte_code); + __ tst(Lbyte_code); + __ br(Assembler::notEqual, false, Assembler::pt, resolved); + __ delayed()->set((int)bytecode(), O1); + } else { + __ ld_ptr(Rcache, constantPoolCacheOopDesc::base_offset() + + ConstantPoolCacheEntry::indices_offset(), Lbyte_code); - __ srl( Lbyte_code, shift_count, Lbyte_code ); - __ and3( Lbyte_code, 0xFF, Lbyte_code ); - __ cmp( Lbyte_code, (int)bytecode()); - __ br( Assembler::equal, false, Assembler::pt, resolved); - __ delayed()->set((int)bytecode(), O1); + __ srl( Lbyte_code, shift_count, Lbyte_code ); + __ and3( Lbyte_code, 0xFF, Lbyte_code ); + __ cmp( Lbyte_code, (int)bytecode()); + __ br( Assembler::equal, false, Assembler::pt, resolved); + __ delayed()->set((int)bytecode(), O1); + } address entry; switch (bytecode()) { @@ -1987,12 +1998,13 @@ void TemplateTable::resolve_cache_and_index(int byte_no, Register Rcache, Regist case Bytecodes::_invokespecial : // fall through case Bytecodes::_invokestatic : // fall through case Bytecodes::_invokeinterface: entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke); break; + case Bytecodes::_invokedynamic : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic); break; default : ShouldNotReachHere(); break; } // first time invocation - must resolve first __ call_VM(noreg, entry, O1); // Update registers with resolved info - __ get_cache_and_index_at_bcp(Rcache, index, 1); + __ get_cache_and_index_at_bcp(Rcache, index, 1, is_invokedynamic); __ bind(resolved); } @@ -3130,7 +3142,42 @@ void TemplateTable::invokedynamic(int byte_no) { return; } - __ stop("invokedynamic NYI");//6815692// + // G5: CallSite object (f1) + // XX: unused (f2) + // G3: receiver address + // XX: flags (unused) + + Register G5_callsite = G5_method; + Register Rscratch = G3_scratch; + Register Rtemp = G1_scratch; + Register Rret = Lscratch; + + load_invoke_cp_cache_entry(byte_no, G5_callsite, noreg, Rret, false); + __ mov(SP, O5_savedSP); // record SP that we wanted the callee to restore + + __ verify_oop(G5_callsite); + + // profile this call + __ profile_call(O4); + + // get return address + AddressLiteral table(Interpreter::return_5_addrs_by_index_table()); + __ set(table, Rtemp); + __ srl(Rret, ConstantPoolCacheEntry::tosBits, Rret); // get return type + // Make sure we don't need to mask Rret for tosBits after the above shift + ConstantPoolCacheEntry::verify_tosBits(); + __ sll(Rret, LogBytesPerWord, Rret); + __ ld_ptr(Rtemp, Rret, Rret); // get return address + + __ ld_ptr(G5_callsite, __ delayed_value(java_dyn_CallSite::target_offset_in_bytes, Rscratch), G3_method_handle); + __ null_check(G3_method_handle); + + // Adjust Rret first so Llast_SP can be same as Rret + __ add(Rret, -frame::pc_return_offset, O7); + __ add(Lesp, BytesPerWord, Gargs); // setup parameter pointer + __ jump_to_method_handle_entry(G3_method_handle, Rtemp, /* emit_delayed_nop */ false); + // Record SP so we can remove any stack space allocated by adapter transition + __ delayed()->mov(SP, Llast_SP); } diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.cpp b/hotspot/src/cpu/x86/vm/assembler_x86.cpp index 72086baee03..c3fed6bcd1b 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2009 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 @@ -6492,24 +6492,19 @@ int MacroAssembler::load_unsigned_short(Register dst, Address src) { } void MacroAssembler::load_sized_value(Register dst, Address src, - int size_in_bytes, bool is_signed) { - switch (size_in_bytes ^ (is_signed ? -1 : 0)) { + size_t size_in_bytes, bool is_signed) { + switch (size_in_bytes) { #ifndef _LP64 // For case 8, caller is responsible for manually loading // the second word into another register. - case ~8: // fall through: - case 8: movl( dst, src ); break; + case 8: movl(dst, src); break; #else - case ~8: // fall through: - case 8: movq( dst, src ); break; + case 8: movq(dst, src); break; #endif - case ~4: // fall through: - case 4: movl( dst, src ); break; - case ~2: load_signed_short( dst, src ); break; - case 2: load_unsigned_short( dst, src ); break; - case ~1: load_signed_byte( dst, src ); break; - case 1: load_unsigned_byte( dst, src ); break; - default: ShouldNotReachHere(); + case 4: movl(dst, src); break; + case 2: is_signed ? load_signed_short(dst, src) : load_unsigned_short(dst, src); break; + case 1: is_signed ? load_signed_byte( dst, src) : load_unsigned_byte( dst, src); break; + default: ShouldNotReachHere(); } } @@ -7706,6 +7701,7 @@ void MacroAssembler::check_method_handle_type(Register mtype_reg, Register mh_re // method handle's MethodType. This macro hides the distinction. void MacroAssembler::load_method_handle_vmslots(Register vmslots_reg, Register mh_reg, Register temp_reg) { + assert_different_registers(vmslots_reg, mh_reg, temp_reg); if (UseCompressedOops) unimplemented(); // field accesses must decode // load mh.type.form.vmslots if (java_dyn_MethodHandle::vmslots_offset_in_bytes() != 0) { diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.hpp b/hotspot/src/cpu/x86/vm/assembler_x86.hpp index f44ae2dde48..bc02c964691 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2009 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 @@ -1511,7 +1511,7 @@ class MacroAssembler: public Assembler { void extend_sign(Register hi, Register lo); // Loading values by size and signed-ness - void load_sized_value(Register dst, Address src, int size_in_bytes, bool is_signed); + void load_sized_value(Register dst, Address src, size_t size_in_bytes, bool is_signed); // Support for inc/dec with optimal instruction selection depending on value diff --git a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp index 94c824abbce..a99296f73d4 100644 --- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp +++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp @@ -127,7 +127,8 @@ void MethodHandles::insert_arg_slots(MacroAssembler* _masm, RegisterOrConstant arg_slots, int arg_mask, Register rax_argslot, - Register rbx_temp, Register rdx_temp) { + Register rbx_temp, Register rdx_temp, Register temp3_reg) { + assert(temp3_reg == noreg, "temp3 not required"); assert_different_registers(rax_argslot, rbx_temp, rdx_temp, (!arg_slots.is_register() ? rsp : arg_slots.as_register())); @@ -185,7 +186,8 @@ void MethodHandles::insert_arg_slots(MacroAssembler* _masm, void MethodHandles::remove_arg_slots(MacroAssembler* _masm, RegisterOrConstant arg_slots, Register rax_argslot, - Register rbx_temp, Register rdx_temp) { + Register rbx_temp, Register rdx_temp, Register temp3_reg) { + assert(temp3_reg == noreg, "temp3 not required"); assert_different_registers(rax_argslot, rbx_temp, rdx_temp, (!arg_slots.is_register() ? rsp : arg_slots.as_register())); diff --git a/hotspot/src/share/vm/prims/methodHandles.hpp b/hotspot/src/share/vm/prims/methodHandles.hpp index 1929c4f00cc..7e31e08438a 100644 --- a/hotspot/src/share/vm/prims/methodHandles.hpp +++ b/hotspot/src/share/vm/prims/methodHandles.hpp @@ -430,12 +430,12 @@ class MethodHandles: AllStatic { RegisterOrConstant arg_slots, int arg_mask, Register argslot_reg, - Register temp_reg, Register temp2_reg); + Register temp_reg, Register temp2_reg, Register temp3_reg = noreg); static void remove_arg_slots(MacroAssembler* _masm, RegisterOrConstant arg_slots, Register argslot_reg, - Register temp_reg, Register temp2_reg); + Register temp_reg, Register temp2_reg, Register temp3_reg = noreg); }; From ac7a6db631d1bb905a0be8b53eafb29cc3a85286 Mon Sep 17 00:00:00 2001 From: Alexander Potochkin Date: Thu, 29 Apr 2010 18:38:25 +0400 Subject: [PATCH 14/54] 6899413: Fix for CR #6878399 should be refactored Reviewed-by: peterz --- .../classes/javax/swing/JEditorPane.java | 15 +++-- jdk/src/share/classes/javax/swing/JList.java | 24 +++---- jdk/src/share/classes/javax/swing/JTable.java | 21 ++++--- .../share/classes/javax/swing/JTextField.java | 2 +- jdk/src/share/classes/javax/swing/JTree.java | 12 ++-- .../classes/javax/swing/SwingUtilities.java | 63 +++++++++---------- .../javax/swing/text/JTextComponent.java | 12 ++-- 7 files changed, 70 insertions(+), 79 deletions(-) diff --git a/jdk/src/share/classes/javax/swing/JEditorPane.java b/jdk/src/share/classes/javax/swing/JEditorPane.java index eaf61f1e60e..acd825c1d96 100644 --- a/jdk/src/share/classes/javax/swing/JEditorPane.java +++ b/jdk/src/share/classes/javax/swing/JEditorPane.java @@ -1330,8 +1330,9 @@ public class JEditorPane extends JTextComponent { */ public Dimension getPreferredSize() { Dimension d = super.getPreferredSize(); - JViewport port = SwingUtilities.getParentViewport(this); - if (port != null) { + Container parent = SwingUtilities.getUnwrappedParent(this); + if (parent instanceof JViewport) { + JViewport port = (JViewport) parent; TextUI ui = getUI(); int prefWidth = d.width; int prefHeight = d.height; @@ -1452,8 +1453,9 @@ public class JEditorPane extends JTextComponent { * match its own, false otherwise */ public boolean getScrollableTracksViewportWidth() { - JViewport port = SwingUtilities.getParentViewport(this); - if (port != null) { + Container parent = SwingUtilities.getUnwrappedParent(this); + if (parent instanceof JViewport) { + JViewport port = (JViewport) parent; TextUI ui = getUI(); int w = port.getWidth(); Dimension min = ui.getMinimumSize(this); @@ -1474,8 +1476,9 @@ public class JEditorPane extends JTextComponent { * false otherwise */ public boolean getScrollableTracksViewportHeight() { - JViewport port = SwingUtilities.getParentViewport(this); - if (port != null) { + Container parent = SwingUtilities.getUnwrappedParent(this); + if (parent instanceof JViewport) { + JViewport port = (JViewport) parent; TextUI ui = getUI(); int h = port.getHeight(); Dimension min = ui.getMinimumSize(this); diff --git a/jdk/src/share/classes/javax/swing/JList.java b/jdk/src/share/classes/javax/swing/JList.java index 8a86bda547d..10aa3adf93d 100644 --- a/jdk/src/share/classes/javax/swing/JList.java +++ b/jdk/src/share/classes/javax/swing/JList.java @@ -25,17 +25,7 @@ package javax.swing; -import java.awt.Color; -import java.awt.Component; -import java.awt.Cursor; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.GraphicsEnvironment; -import java.awt.HeadlessException; -import java.awt.Insets; -import java.awt.Point; -import java.awt.Rectangle; +import java.awt.*; import java.awt.event.*; import java.util.Vector; @@ -2779,9 +2769,9 @@ public class JList extends JComponent implements Scrollable, Accessible getVisibleRowCount() <= 0) { return true; } - JViewport port = SwingUtilities.getParentViewport(this); - if (port != null) { - return port.getWidth() > getPreferredSize().width; + Container parent = SwingUtilities.getUnwrappedParent(this); + if (parent instanceof JViewport) { + return parent.getWidth() > getPreferredSize().width; } return false; } @@ -2805,9 +2795,9 @@ public class JList extends JComponent implements Scrollable, Accessible getVisibleRowCount() <= 0) { return true; } - JViewport port = SwingUtilities.getParentViewport(this); - if (port != null) { - return port.getHeight() > getPreferredSize().height; + Container parent = SwingUtilities.getUnwrappedParent(this); + if (parent instanceof JViewport) { + return parent.getHeight() > getPreferredSize().height; } return false; } diff --git a/jdk/src/share/classes/javax/swing/JTable.java b/jdk/src/share/classes/javax/swing/JTable.java index 236e59102c1..09157ca93f8 100644 --- a/jdk/src/share/classes/javax/swing/JTable.java +++ b/jdk/src/share/classes/javax/swing/JTable.java @@ -719,8 +719,9 @@ public class JTable extends JComponent implements TableModelListener, Scrollable * @see #addNotify */ protected void configureEnclosingScrollPane() { - JViewport port = SwingUtilities.getParentViewport(this); - if (port != null) { + Container parent = SwingUtilities.getUnwrappedParent(this); + if (parent instanceof JViewport) { + JViewport port = (JViewport) parent; Container gp = port.getParent(); if (gp instanceof JScrollPane) { JScrollPane scrollPane = (JScrollPane)gp; @@ -752,8 +753,9 @@ public class JTable extends JComponent implements TableModelListener, Scrollable * from configureEnclosingScrollPane() and updateUI() in a safe manor. */ private void configureEnclosingScrollPaneUI() { - JViewport port = SwingUtilities.getParentViewport(this); - if (port != null) { + Container parent = SwingUtilities.getUnwrappedParent(this); + if (parent instanceof JViewport) { + JViewport port = (JViewport) parent; Container gp = port.getParent(); if (gp instanceof JScrollPane) { JScrollPane scrollPane = (JScrollPane)gp; @@ -822,8 +824,9 @@ public class JTable extends JComponent implements TableModelListener, Scrollable * @since 1.3 */ protected void unconfigureEnclosingScrollPane() { - JViewport port = SwingUtilities.getParentViewport(this); - if (port != null) { + Container parent = SwingUtilities.getUnwrappedParent(this); + if (parent instanceof JViewport) { + JViewport port = (JViewport) parent; Container gp = port.getParent(); if (gp instanceof JScrollPane) { JScrollPane scrollPane = (JScrollPane)gp; @@ -5217,10 +5220,10 @@ public class JTable extends JComponent implements TableModelListener, Scrollable * @see #getFillsViewportHeight */ public boolean getScrollableTracksViewportHeight() { - JViewport port = SwingUtilities.getParentViewport(this); + Container parent = SwingUtilities.getUnwrappedParent(this); return getFillsViewportHeight() - && port != null - && port.getHeight() > getPreferredSize().height; + && parent instanceof JViewport + && parent.getHeight() > getPreferredSize().height; } /** diff --git a/jdk/src/share/classes/javax/swing/JTextField.java b/jdk/src/share/classes/javax/swing/JTextField.java index 24a3408d1b4..e1e6b640c65 100644 --- a/jdk/src/share/classes/javax/swing/JTextField.java +++ b/jdk/src/share/classes/javax/swing/JTextField.java @@ -292,7 +292,7 @@ public class JTextField extends JTextComponent implements SwingConstants { */ @Override public boolean isValidateRoot() { - return SwingUtilities.getParentViewport(this) == null; + return !(SwingUtilities.getUnwrappedParent(this) instanceof JViewport); } diff --git a/jdk/src/share/classes/javax/swing/JTree.java b/jdk/src/share/classes/javax/swing/JTree.java index 55815b81dc2..788aeab1fc1 100644 --- a/jdk/src/share/classes/javax/swing/JTree.java +++ b/jdk/src/share/classes/javax/swing/JTree.java @@ -3498,9 +3498,9 @@ public class JTree extends JComponent implements Scrollable, Accessible * @see Scrollable#getScrollableTracksViewportWidth */ public boolean getScrollableTracksViewportWidth() { - JViewport port = SwingUtilities.getParentViewport(this); - if (port != null) { - return port.getWidth() > getPreferredSize().width; + Container parent = SwingUtilities.getUnwrappedParent(this); + if (parent instanceof JViewport) { + return parent.getWidth() > getPreferredSize().width; } return false; } @@ -3515,9 +3515,9 @@ public class JTree extends JComponent implements Scrollable, Accessible * @see Scrollable#getScrollableTracksViewportHeight */ public boolean getScrollableTracksViewportHeight() { - JViewport port = SwingUtilities.getParentViewport(this); - if (port != null) { - return port.getHeight() > getPreferredSize().height; + Container parent = SwingUtilities.getUnwrappedParent(this); + if (parent instanceof JViewport) { + return parent.getHeight() > getPreferredSize().height; } return false; } diff --git a/jdk/src/share/classes/javax/swing/SwingUtilities.java b/jdk/src/share/classes/javax/swing/SwingUtilities.java index 1221c4bce74..65b267eb8f3 100644 --- a/jdk/src/share/classes/javax/swing/SwingUtilities.java +++ b/jdk/src/share/classes/javax/swing/SwingUtilities.java @@ -1969,58 +1969,53 @@ public class SwingUtilities implements SwingConstants } /** - * Looks for the first ancestor of the {@code component} + * Returns the first ancestor of the {@code component} * which is not an instance of {@link JLayer}. - * If this ancestor is an instance of {@code JViewport}, - * this {@code JViewport} is returned, otherwise returns {@code null}. - * The following way of obtaining the parent {@code JViewport} - * is not recommended any more: - *

-     * JViewport port = null;
-     * Container parent = component.getParent();
-     * // not recommended any more
-     * if(parent instanceof JViewport) {
-     *     port = (JViewport) parent;
-     * }
-     * 
- * Here is the way to go: - *
-     * // the correct way:
-     * JViewport port = SwingUtilities.getParentViewport(component);
-     * 
- * @param component {@code Component} to get the parent {@code JViewport} of. - * @return the {@code JViewport} instance for the {@code component} - * or {@code null} + * + * @param component {@code Component} to get + * the first ancestor of, which is not a {@link JLayer} instance. + * + * @return the first ancestor of the {@code component} + * which is not an instance of {@link JLayer}. + * If such an ancestor can not be found, {@code null} is returned. + * * @throws NullPointerException if {@code component} is {@code null} + * @see JLayer * * @since 1.7 */ - public static JViewport getParentViewport(Component component) { - do { - component = component.getParent(); - if (component instanceof JViewport) { - return (JViewport) component; - } - } while(component instanceof JLayer); - return null; + public static Container getUnwrappedParent(Component component) { + Container parent = component.getParent(); + while(parent instanceof JLayer) { + parent = parent.getParent(); + } + return parent; } /** * Returns the first {@code JViewport}'s descendant - * which is not an instance of {@code JLayer} or {@code null}. + * which is not an instance of {@code JLayer}. + * If such a descendant can not be found, {@code null} is returned. * * If the {@code viewport}'s view component is not a {@code JLayer}, - * this method is equal to {@link JViewport#getView()} - * otherwise {@link JLayer#getView()} will be recursively tested + * this method is equivalent to {@link JViewport#getView()} + * otherwise {@link JLayer#getView()} will be recursively + * called on all descending {@code JLayer}s. + * + * @param viewport {@code JViewport} to get the first descendant of, + * which in not a {@code JLayer} instance. * * @return the first {@code JViewport}'s descendant - * which is not an instance of {@code JLayer} or {@code null}. + * which is not an instance of {@code JLayer}. + * If such a descendant can not be found, {@code null} is returned. * * @throws NullPointerException if {@code viewport} is {@code null} * @see JViewport#getView() * @see JLayer + * + * @since 1.7 */ - static Component getUnwrappedView(JViewport viewport) { + public static Component getUnwrappedView(JViewport viewport) { Component view = viewport.getView(); while (view instanceof JLayer) { view = ((JLayer)view).getView(); diff --git a/jdk/src/share/classes/javax/swing/text/JTextComponent.java b/jdk/src/share/classes/javax/swing/text/JTextComponent.java index 25ddaf9e3cc..832c6095ec2 100644 --- a/jdk/src/share/classes/javax/swing/text/JTextComponent.java +++ b/jdk/src/share/classes/javax/swing/text/JTextComponent.java @@ -2069,9 +2069,9 @@ public abstract class JTextComponent extends JComponent implements Scrollable, A * width to match its own */ public boolean getScrollableTracksViewportWidth() { - JViewport port = SwingUtilities.getParentViewport(this); - if (port != null) { - return port.getWidth() > getPreferredSize().width; + Container parent = SwingUtilities.getUnwrappedParent(this); + if (parent instanceof JViewport) { + return parent.getWidth() > getPreferredSize().width; } return false; } @@ -2090,9 +2090,9 @@ public abstract class JTextComponent extends JComponent implements Scrollable, A * to match its own */ public boolean getScrollableTracksViewportHeight() { - JViewport port = SwingUtilities.getParentViewport(this); - if (port != null) { - return (port.getHeight() > getPreferredSize().height); + Container parent = SwingUtilities.getUnwrappedParent(this); + if (parent instanceof JViewport) { + return parent.getHeight() > getPreferredSize().height; } return false; } From 98a42c6444e70321355a2153f2979d9271ef6982 Mon Sep 17 00:00:00 2001 From: Alexander Potochkin Date: Thu, 29 Apr 2010 18:56:26 +0400 Subject: [PATCH 15/54] 6899453: Remove unnecessary methods from LayerUI Reviewed-by: peterz --- .../classes/javax/swing/plaf/LayerUI.java | 62 ++----------------- 1 file changed, 4 insertions(+), 58 deletions(-) diff --git a/jdk/src/share/classes/javax/swing/plaf/LayerUI.java b/jdk/src/share/classes/javax/swing/plaf/LayerUI.java index 7f2967bf465..e088db33738 100644 --- a/jdk/src/share/classes/javax/swing/plaf/LayerUI.java +++ b/jdk/src/share/classes/javax/swing/plaf/LayerUI.java @@ -72,53 +72,13 @@ public class LayerUI * the specified {@code Graphics} object to * render the content of the component. *

- * If {@code g} is not an instance of {@code Graphics2D}, - * this method is no-op. + * The default implementation paints the passed component as is. * - * @param g the {@code Graphics} context in which to paint; - * @param c the component being painted; - * it can be safely cast to {@code JLayer} - * - * @see #configureGraphics(Graphics2D, JLayer) - * @see #paintLayer(Graphics2D, JLayer) + * @param g the {@code Graphics} context in which to paint + * @param c the component being painted */ public void paint(Graphics g, JComponent c) { - if (g instanceof Graphics2D) { - Graphics2D g2 = (Graphics2D) g.create(); - JLayer l = (JLayer) c; - configureGraphics(g2, l); - paintLayer(g2, l); - g2.dispose(); - } - } - - /** - * This method is called by the {@link #paint} method prior to - * {@link #paintLayer} to configure the {@code Graphics2D} object. - * The default implementation is empty. - * - * @param g2 the {@code Graphics2D} object to configure - * @param l the {@code JLayer} being painted - * - * @see #paintLayer(Graphics2D, JLayer) - */ - protected void configureGraphics(Graphics2D g2, JLayer l) { - } - - /** - * Called by the {@link #paint} method, - * subclasses should override this method - * to perform any custom painting operations. - *

- * The default implementation paints the passed {@code JLayer} as is. - * - * @param g2 the {@code Graphics2D} context in which to paint - * @param l the {@code JLayer} being painted - * - * @see #configureGraphics(Graphics2D, JLayer) - */ - protected void paintLayer(Graphics2D g2, JLayer l) { - l.paint(g2); + c.paint(g); } /** @@ -627,17 +587,6 @@ public class LayerUI propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue); } - /** - * Repaints all {@code JLayer} instances this {@code LayerUI} is set to. - * Call this method when the state of this {@code LayerUI} is changed - * and the visual appearance of its {@code JLayer} objects needs to be updated. - * - * @see Component#repaint() - */ - protected void repaintLayer() { - firePropertyChange("dirty", null, null); - } - /** * Notifies the {@code LayerUI} when any of its property are changed * and enables updating every {@code JLayer} @@ -647,9 +596,6 @@ public class LayerUI * @param l the {@code JLayer} this LayerUI is set to */ public void applyPropertyChange(PropertyChangeEvent evt, JLayer l) { - if ("dirty".equals(evt.getPropertyName())) { - l.repaint(); - } } /** From 16e7bb5c198f60d9d0ae7643c3b3f7b21df87127 Mon Sep 17 00:00:00 2001 From: Alexander Potochkin Date: Thu, 29 Apr 2010 19:07:26 +0400 Subject: [PATCH 16/54] 6899405: Specification for JLayer.setLayerEventMask() should mention that eventDispatch() might not be called Reviewed-by: peterz --- jdk/src/share/classes/javax/swing/JLayer.java | 60 ++++++++----------- .../classes/javax/swing/plaf/LayerUI.java | 9 +-- 2 files changed, 29 insertions(+), 40 deletions(-) diff --git a/jdk/src/share/classes/javax/swing/JLayer.java b/jdk/src/share/classes/javax/swing/JLayer.java index 93f4b799722..ab082cfc588 100644 --- a/jdk/src/share/classes/javax/swing/JLayer.java +++ b/jdk/src/share/classes/javax/swing/JLayer.java @@ -163,18 +163,6 @@ public final class JLayer private static final LayerEventController eventController = new LayerEventController(); - private static final long ACCEPTED_EVENTS = - AWTEvent.COMPONENT_EVENT_MASK | - AWTEvent.CONTAINER_EVENT_MASK | - AWTEvent.FOCUS_EVENT_MASK | - AWTEvent.KEY_EVENT_MASK | - AWTEvent.MOUSE_WHEEL_EVENT_MASK | - AWTEvent.MOUSE_MOTION_EVENT_MASK | - AWTEvent.MOUSE_EVENT_MASK | - AWTEvent.INPUT_METHOD_EVENT_MASK | - AWTEvent.HIERARCHY_EVENT_MASK | - AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK; - /** * Creates a new {@code JLayer} object with a {@code null} view component * and {@code null} {@link javax.swing.plaf.LayerUI}. @@ -396,24 +384,14 @@ public final class JLayer } /** - * Sets the bitmask of event types to receive by this {@code JLayer}. - * Here is the list of the supported event types: - *

    - *
  • AWTEvent.COMPONENT_EVENT_MASK
  • - *
  • AWTEvent.CONTAINER_EVENT_MASK
  • - *
  • AWTEvent.FOCUS_EVENT_MASK
  • - *
  • AWTEvent.KEY_EVENT_MASK
  • - *
  • AWTEvent.MOUSE_WHEEL_EVENT_MASK
  • - *
  • AWTEvent.MOUSE_MOTION_EVENT_MASK
  • - *
  • AWTEvent.MOUSE_EVENT_MASK
  • - *
  • AWTEvent.INPUT_METHOD_EVENT_MASK
  • - *
  • AWTEvent.HIERARCHY_EVENT_MASK
  • - *
  • AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK
  • - *
+ * Enables the events from JLayer and all its descendants + * defined by the specified event mask parameter + * to be delivered to the + * {@link LayerUI#eventDispatched(AWTEvent, JLayer)} method. *

- * If {@code LayerUI} is installed, - * {@link javax.swing.plaf.LayerUI#eventDispatched(AWTEvent, JLayer)} method - * will only receive events that match the event mask. + * Events are delivered provided that {@code LayerUI} is set + * for this {@code JLayer} and the {@code JLayer} + * is displayable. *

* The following example shows how to correclty use this method * in the {@code LayerUI} implementations: @@ -433,19 +411,15 @@ public final class JLayer * } * * - * By default {@code JLayer} receives no events. + * By default {@code JLayer} receives no events and its event mask is {@code 0}. * * @param layerEventMask the bitmask of event types to receive * - * @throws IllegalArgumentException if the {@code layerEventMask} parameter - * contains unsupported event types * @see #getLayerEventMask() + * @see LayerUI#eventDispatched(AWTEvent, JLayer) + * @see Component#isDisplayable() */ public void setLayerEventMask(long layerEventMask) { - if (layerEventMask != (layerEventMask & ACCEPTED_EVENTS)) { - throw new IllegalArgumentException( - "The event bitmask contains unsupported event types"); - } long oldEventMask = getLayerEventMask(); this.eventMask = layerEventMask; firePropertyChange("layerEventMask", oldEventMask, layerEventMask); @@ -629,6 +603,18 @@ public final class JLayer private long currentEventMask; + private static final long ACCEPTED_EVENTS = + AWTEvent.COMPONENT_EVENT_MASK | + AWTEvent.CONTAINER_EVENT_MASK | + AWTEvent.FOCUS_EVENT_MASK | + AWTEvent.KEY_EVENT_MASK | + AWTEvent.MOUSE_WHEEL_EVENT_MASK | + AWTEvent.MOUSE_MOTION_EVENT_MASK | + AWTEvent.MOUSE_EVENT_MASK | + AWTEvent.INPUT_METHOD_EVENT_MASK | + AWTEvent.HIERARCHY_EVENT_MASK | + AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK; + @SuppressWarnings("unchecked") public void eventDispatched(AWTEvent event) { Object source = event.getSource(); @@ -660,6 +646,8 @@ public final class JLayer for (Long mask : layerMaskList) { combinedMask |= mask; } + // filter out all unaccepted events + combinedMask &= ACCEPTED_EVENTS; if (combinedMask == 0) { removeAWTEventListener(); } else if (getCurrentEventMask() != combinedMask) { diff --git a/jdk/src/share/classes/javax/swing/plaf/LayerUI.java b/jdk/src/share/classes/javax/swing/plaf/LayerUI.java index e088db33738..07df96cd411 100644 --- a/jdk/src/share/classes/javax/swing/plaf/LayerUI.java +++ b/jdk/src/share/classes/javax/swing/plaf/LayerUI.java @@ -82,8 +82,8 @@ public class LayerUI } /** - * Dispatches {@code AWTEvent}s for {@code JLayer} - * and all its subcomponents to this {@code LayerUI} instance. + * Processes {@code AWTEvent}s for {@code JLayer} + * and all its descendants to this {@code LayerUI} instance. *

* To enable the {@code AWTEvent}s of a particular type, * you call {@link JLayer#setLayerEventMask} @@ -93,13 +93,14 @@ public class LayerUI * By default this method calls the appropriate * {@code process<event type>Event} * method for the given class of event. + *

+ * Note: Events are processed only for displayable {@code JLayer}s. * * @param e the event to be dispatched * @param l the layer this LayerUI is set to * * @see JLayer#setLayerEventMask(long) - * @see #installUI(javax.swing.JComponent) - * @see #uninstallUI(javax.swing.JComponent) + * @see Component#isDisplayable() * @see #processComponentEvent * @see #processFocusEvent * @see #processKeyEvent From 61b9d428d1b290f9762b0d0a840b7ed746b6dca2 Mon Sep 17 00:00:00 2001 From: Igor Veresov Date: Thu, 29 Apr 2010 17:53:58 -0700 Subject: [PATCH 17/54] 6948602: Disable use of SSE4.2 in String.indexOf intrinsic until 6942326 is fixed Disable the use of pcmpestri until it can be guaranteed that the load doesn't cross in to the uncommited space. See 6942326. Reviewed-by: never, kvn --- hotspot/src/share/vm/opto/library_call.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index eaa2a06ebb4..7a6ec0dcf43 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -1175,7 +1175,9 @@ bool LibraryCallKit::inline_string_indexOf() { Node *receiver = pop(); Node* result; - if (Matcher::has_match_rule(Op_StrIndexOf) && + // Disable the use of pcmpestri until it can be guaranteed that + // the load doesn't cross into the uncommited space. + if (false && Matcher::has_match_rule(Op_StrIndexOf) && UseSSE42Intrinsics) { // Generate SSE4.2 version of indexOf // We currently only have match rules that use SSE4.2 From 55457c9cc71130bb5964ebe66a275e76865e970b Mon Sep 17 00:00:00 2001 From: Gary Benson Date: Fri, 30 Apr 2010 04:27:25 -0700 Subject: [PATCH 18/54] 6939182: Zero JNI handles fix Zero will exit with an error when invoked with -Xcheck:jni. Reviewed-by: twisti, kamg --- .../src/cpu/zero/vm/cppInterpreter_zero.cpp | 2 +- hotspot/src/cpu/zero/vm/frame_zero.cpp | 10 ++++---- hotspot/src/cpu/zero/vm/frame_zero.hpp | 19 +++++++-------- hotspot/src/cpu/zero/vm/frame_zero.inline.hpp | 12 +++++----- .../src/cpu/zero/vm/javaFrameAnchor_zero.hpp | 23 ++++++++++++++----- hotspot/src/cpu/zero/vm/stack_zero.cpp | 10 +++++++- hotspot/src/cpu/zero/vm/stack_zero.hpp | 3 +++ .../linux_zero/vm/thread_linux_zero.hpp | 15 ++++++++---- 8 files changed, 59 insertions(+), 35 deletions(-) diff --git a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp index 7c38e0820b1..3d6748e4935 100644 --- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp +++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp @@ -833,7 +833,7 @@ int AbstractInterpreter::layout_activation(methodOop method, int callee_extra_locals = callee_locals - callee_param_count; if (interpreter_frame) { - intptr_t *locals = interpreter_frame->sp() + method->max_locals(); + intptr_t *locals = interpreter_frame->fp() + method->max_locals(); interpreterState istate = interpreter_frame->get_interpreterState(); intptr_t *monitor_base = (intptr_t*) istate; intptr_t *stack_base = monitor_base - monitor_words; diff --git a/hotspot/src/cpu/zero/vm/frame_zero.cpp b/hotspot/src/cpu/zero/vm/frame_zero.cpp index 323912e1cb3..0bf4ae68b44 100644 --- a/hotspot/src/cpu/zero/vm/frame_zero.cpp +++ b/hotspot/src/cpu/zero/vm/frame_zero.cpp @@ -1,6 +1,6 @@ /* * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. - * Copyright 2007, 2008, 2009 Red Hat, Inc. + * Copyright 2007, 2008, 2009, 2010 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,14 +44,14 @@ frame frame::sender_for_entry_frame(RegisterMap *map) const { "sender should be next Java frame"); map->clear(); assert(map->include_argument_oops(), "should be set by clear"); - return frame(sender_sp(), sp() + 1); + return frame(zeroframe()->next(), sender_sp()); } frame frame::sender_for_nonentry_frame(RegisterMap *map) const { assert(zeroframe()->is_interpreter_frame() || zeroframe()->is_shark_frame() || zeroframe()->is_fake_stub_frame(), "wrong type of frame"); - return frame(sender_sp(), sp() + 1); + return frame(zeroframe()->next(), sender_sp()); } frame frame::sender(RegisterMap* map) const { @@ -172,8 +172,8 @@ void frame::zero_print_on_error(int frame_index, char *valuebuf = buf + buflen; // Print each word of the frame - for (intptr_t *addr = fp(); addr <= sp(); addr++) { - int offset = sp() - addr; + for (intptr_t *addr = sp(); addr <= fp(); addr++) { + int offset = fp() - addr; // Fill in default values, then try and improve them snprintf(fieldbuf, buflen, "word[%d]", offset); diff --git a/hotspot/src/cpu/zero/vm/frame_zero.hpp b/hotspot/src/cpu/zero/vm/frame_zero.hpp index 84d248fe0c4..31815eb24fb 100644 --- a/hotspot/src/cpu/zero/vm/frame_zero.hpp +++ b/hotspot/src/cpu/zero/vm/frame_zero.hpp @@ -1,6 +1,6 @@ /* * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. - * Copyright 2007, 2008, 2009 Red Hat, Inc. + * Copyright 2007, 2008, 2009, 2010 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,17 +32,18 @@ // Constructor public: - frame(intptr_t* sp, intptr_t* fp); + frame(ZeroFrame* zeroframe, intptr_t* sp); - // The sp of a Zero frame is the address of the highest word in - // that frame. We keep track of the lowest address too, so the - // boundaries of the frame are available for debug printing. private: - intptr_t* _fp; + ZeroFrame* _zeroframe; public: + const ZeroFrame *zeroframe() const { + return _zeroframe; + } + intptr_t* fp() const { - return _fp; + return (intptr_t *) zeroframe(); } #ifdef CC_INTERP @@ -50,10 +51,6 @@ #endif // CC_INTERP public: - const ZeroFrame *zeroframe() const { - return (ZeroFrame *) sp(); - } - const EntryFrame *zero_entryframe() const { return zeroframe()->as_entry_frame(); } diff --git a/hotspot/src/cpu/zero/vm/frame_zero.inline.hpp b/hotspot/src/cpu/zero/vm/frame_zero.inline.hpp index 2751117f897..feab77f339c 100644 --- a/hotspot/src/cpu/zero/vm/frame_zero.inline.hpp +++ b/hotspot/src/cpu/zero/vm/frame_zero.inline.hpp @@ -1,6 +1,6 @@ /* * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. - * Copyright 2007, 2008, 2009 Red Hat, Inc. + * Copyright 2007, 2008, 2009, 2010 Red Hat, Inc. * 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,16 +26,16 @@ // Constructors inline frame::frame() { + _zeroframe = NULL; _sp = NULL; - _fp = NULL; _pc = NULL; _cb = NULL; _deopt_state = unknown; } -inline frame::frame(intptr_t* sp, intptr_t* fp) { +inline frame::frame(ZeroFrame* zf, intptr_t* sp) { + _zeroframe = zf; _sp = sp; - _fp = fp; switch (zeroframe()->type()) { case ZeroFrame::ENTRY_FRAME: _pc = StubRoutines::call_stub_return_pc(); @@ -66,7 +66,7 @@ inline frame::frame(intptr_t* sp, intptr_t* fp) { // Accessors inline intptr_t* frame::sender_sp() const { - return (intptr_t *) zeroframe()->next(); + return fp() + 1; } inline intptr_t* frame::link() const { @@ -120,7 +120,7 @@ inline jint frame::interpreter_frame_expression_stack_direction() { // we can distinguish identity and younger/older relationship. NULL // represents an invalid (incomparable) frame. inline intptr_t* frame::id() const { - return sp(); + return fp(); } inline JavaCallWrapper* frame::entry_frame_call_wrapper() const { diff --git a/hotspot/src/cpu/zero/vm/javaFrameAnchor_zero.hpp b/hotspot/src/cpu/zero/vm/javaFrameAnchor_zero.hpp index e356cc91866..7665780bc01 100644 --- a/hotspot/src/cpu/zero/vm/javaFrameAnchor_zero.hpp +++ b/hotspot/src/cpu/zero/vm/javaFrameAnchor_zero.hpp @@ -1,6 +1,6 @@ /* * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved. - * Copyright 2007, 2008 Red Hat, Inc. + * Copyright 2007, 2008, 2010 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,21 +23,31 @@ * */ + private: + ZeroFrame* volatile _last_Java_fp; + public: // Each arch must define reset, save, restore // These are used by objects that only care about: // 1 - initializing a new state (thread creation, javaCalls) // 2 - saving a current state (javaCalls) // 3 - restoring an old state (javaCalls) + // Note that whenever _last_Java_sp != NULL other anchor fields + // must be valid. The profiler apparently depends on this. void clear() { // clearing _last_Java_sp must be first _last_Java_sp = NULL; // fence? + _last_Java_fp = NULL; _last_Java_pc = NULL; } void copy(JavaFrameAnchor* src) { + set(src->_last_Java_sp, src->_last_Java_pc, src->_last_Java_fp); + } + + void set(intptr_t* sp, address pc, ZeroFrame* fp) { // In order to make sure the transition state is valid for "this" // We must clear _last_Java_sp before copying the rest of the new // data @@ -46,13 +56,14 @@ // previous version (pd_cache_state) don't NULL _last_Java_sp // unless the value is changing // - if (_last_Java_sp != src->_last_Java_sp) + if (_last_Java_sp != sp) _last_Java_sp = NULL; - _last_Java_pc = src->_last_Java_pc; + _last_Java_fp = fp; + _last_Java_pc = pc; // Must be last so profiler will always see valid frame if // has_last_frame() is true - _last_Java_sp = src->_last_Java_sp; + _last_Java_sp = sp; } bool walkable() { @@ -67,6 +78,6 @@ return _last_Java_sp; } - void set_last_Java_sp(intptr_t* sp) { - _last_Java_sp = sp; + ZeroFrame* last_Java_fp() const { + return _last_Java_fp; } diff --git a/hotspot/src/cpu/zero/vm/stack_zero.cpp b/hotspot/src/cpu/zero/vm/stack_zero.cpp index f9c50a6c2fd..328e52e6b00 100644 --- a/hotspot/src/cpu/zero/vm/stack_zero.cpp +++ b/hotspot/src/cpu/zero/vm/stack_zero.cpp @@ -32,6 +32,7 @@ void ZeroStack::handle_overflow(TRAPS) { // Set up the frame anchor if it isn't already bool has_last_Java_frame = thread->has_last_Java_frame(); if (!has_last_Java_frame) { + intptr_t *sp = thread->zero_stack()->sp(); ZeroFrame *frame = thread->top_zero_frame(); while (frame) { if (frame->is_shark_frame()) @@ -44,13 +45,14 @@ void ZeroStack::handle_overflow(TRAPS) { break; } + sp = ((intptr_t *) frame) + 1; frame = frame->next(); } if (frame == NULL) fatal("unrecoverable stack overflow"); - thread->set_last_Java_frame(frame); + thread->set_last_Java_frame(frame, sp); } // Throw the exception @@ -71,3 +73,9 @@ void ZeroStack::handle_overflow(TRAPS) { if (!has_last_Java_frame) thread->reset_last_Java_frame(); } + +#ifndef PRODUCT +void ZeroStack::zap(int c) { + memset(_base, c, available_words() * wordSize); +} +#endif // PRODUCT diff --git a/hotspot/src/cpu/zero/vm/stack_zero.hpp b/hotspot/src/cpu/zero/vm/stack_zero.hpp index 8e02d9f4bff..ab3beca4760 100644 --- a/hotspot/src/cpu/zero/vm/stack_zero.hpp +++ b/hotspot/src/cpu/zero/vm/stack_zero.hpp @@ -94,6 +94,9 @@ class ZeroStack { void overflow_check(int required_words, TRAPS); static void handle_overflow(TRAPS); + public: + void zap(int c) PRODUCT_RETURN; + public: static ByteSize base_offset() { return byte_offset_of(ZeroStack, _base); diff --git a/hotspot/src/os_cpu/linux_zero/vm/thread_linux_zero.hpp b/hotspot/src/os_cpu/linux_zero/vm/thread_linux_zero.hpp index 76f74c49b63..aea90119989 100644 --- a/hotspot/src/os_cpu/linux_zero/vm/thread_linux_zero.hpp +++ b/hotspot/src/os_cpu/linux_zero/vm/thread_linux_zero.hpp @@ -68,19 +68,24 @@ public: void set_last_Java_frame() { - set_last_Java_frame(top_zero_frame()); + set_last_Java_frame(top_zero_frame(), zero_stack()->sp()); } void reset_last_Java_frame() { - set_last_Java_frame(NULL); + frame_anchor()->zap(); } - void set_last_Java_frame(ZeroFrame* frame) { - frame_anchor()->set_last_Java_sp((intptr_t *) frame); + void set_last_Java_frame(ZeroFrame* fp, intptr_t* sp) { + frame_anchor()->set(sp, NULL, fp); + } + + public: + ZeroFrame* last_Java_fp() { + return frame_anchor()->last_Java_fp(); } private: frame pd_last_frame() { assert(has_last_Java_frame(), "must have last_Java_sp() when suspended"); - return frame(last_Java_sp(), zero_stack()->sp()); + return frame(last_Java_fp(), last_Java_sp()); } public: From 0211f9703a9a10b43e55529dbb321c5844e3b985 Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Fri, 30 Apr 2010 08:37:24 -0700 Subject: [PATCH 19/54] 6943304: remove tagged stack interpreter Reviewed-by: coleenp, never, gbenson --- hotspot/src/cpu/sparc/vm/assembler_sparc.cpp | 2 +- .../src/cpu/sparc/vm/cppInterpreter_sparc.hpp | 4 +- hotspot/src/cpu/sparc/vm/frame_sparc.cpp | 2 +- .../src/cpu/sparc/vm/interp_masm_sparc.cpp | 292 ++++-------------- .../src/cpu/sparc/vm/interp_masm_sparc.hpp | 21 +- .../src/cpu/sparc/vm/interpreterRT_sparc.cpp | 52 +--- .../src/cpu/sparc/vm/interpreter_sparc.hpp | 32 +- .../src/cpu/sparc/vm/methodHandles_sparc.cpp | 4 +- .../src/cpu/sparc/vm/sharedRuntime_sparc.cpp | 62 +--- .../src/cpu/sparc/vm/stubGenerator_sparc.cpp | 14 +- .../sparc/vm/templateInterpreter_sparc.cpp | 26 +- .../sparc/vm/templateInterpreter_sparc.hpp | 5 +- .../src/cpu/sparc/vm/templateTable_sparc.cpp | 150 +++++---- hotspot/src/cpu/x86/vm/assembler_x86.cpp | 2 +- hotspot/src/cpu/x86/vm/cppInterpreter_x86.hpp | 6 +- hotspot/src/cpu/x86/vm/frame_x86.cpp | 6 +- hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp | 200 +----------- hotspot/src/cpu/x86/vm/interp_masm_x86_32.hpp | 38 +-- hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp | 178 +---------- hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp | 34 +- .../src/cpu/x86/vm/interpreterRT_x86_32.cpp | 18 +- .../src/cpu/x86/vm/interpreterRT_x86_64.cpp | 45 +-- hotspot/src/cpu/x86/vm/interpreter_x86.hpp | 37 +-- hotspot/src/cpu/x86/vm/interpreter_x86_32.cpp | 11 +- hotspot/src/cpu/x86/vm/methodHandles_x86.cpp | 16 +- .../src/cpu/x86/vm/sharedRuntime_x86_32.cpp | 62 +--- .../src/cpu/x86/vm/sharedRuntime_x86_64.cpp | 37 +-- .../src/cpu/x86/vm/stubGenerator_x86_32.cpp | 8 +- .../src/cpu/x86/vm/stubGenerator_x86_64.cpp | 5 - .../cpu/x86/vm/templateInterpreter_x86.hpp | 6 +- .../cpu/x86/vm/templateInterpreter_x86_32.cpp | 22 +- .../cpu/x86/vm/templateInterpreter_x86_64.cpp | 24 +- .../src/cpu/x86/vm/templateTable_x86_32.cpp | 228 ++++---------- .../src/cpu/x86/vm/templateTable_x86_64.cpp | 156 ++++------ hotspot/src/cpu/zero/vm/interpreter_zero.hpp | 16 +- .../os_cpu/linux_x86/vm/globals_linux_x86.hpp | 8 +- .../solaris_x86/vm/globals_solaris_x86.hpp | 6 +- .../vm/interpreter/abstractInterpreter.hpp | 73 +---- .../vm/interpreter/bytecodeInterpreter.cpp | 91 +----- .../vm/interpreter/interpreterRuntime.cpp | 4 +- hotspot/src/share/vm/oops/methodOop.cpp | 2 +- hotspot/src/share/vm/prims/methodHandles.hpp | 4 +- hotspot/src/share/vm/runtime/arguments.cpp | 11 - hotspot/src/share/vm/runtime/frame.cpp | 171 ++-------- hotspot/src/share/vm/runtime/frame.hpp | 26 +- hotspot/src/share/vm/runtime/globals.hpp | 5 +- hotspot/src/share/vm/runtime/javaCalls.cpp | 12 +- hotspot/src/share/vm/runtime/javaCalls.hpp | 8 +- .../src/share/vm/runtime/sharedRuntime.cpp | 17 +- hotspot/src/share/vm/runtime/vframe.cpp | 129 +++----- hotspot/src/share/vm/runtime/vframeArray.cpp | 13 +- 51 files changed, 510 insertions(+), 1891 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp index 00fa5f4a629..5e4135737c4 100644 --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp @@ -3152,7 +3152,7 @@ void MacroAssembler::jump_to_method_handle_entry(Register mh_reg, Register temp_ RegisterOrConstant MacroAssembler::argument_offset(RegisterOrConstant arg_slot, int extra_slot_offset) { // cf. TemplateTable::prepare_invoke(), if (load_receiver). - int stackElementSize = Interpreter::stackElementSize(); + int stackElementSize = Interpreter::stackElementSize; int offset = extra_slot_offset * stackElementSize; if (arg_slot.is_constant()) { offset += arg_slot.as_constant() * stackElementSize; diff --git a/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.hpp b/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.hpp index c76d1e409c1..c4a256aaa89 100644 --- a/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2002 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2002-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 @@ -26,7 +26,7 @@ // fail with a guarantee ("not enough space for interpreter generation"); // if too small. // Run with +PrintInterpreter to get the VM to print out the size. - // Max size with JVMTI and TaggedStackInterpreter + // Max size with JVMTI // QQQ this is proably way too large for c++ interpreter diff --git a/hotspot/src/cpu/sparc/vm/frame_sparc.cpp b/hotspot/src/cpu/sparc/vm/frame_sparc.cpp index 64b652376eb..bf5bc44a40c 100644 --- a/hotspot/src/cpu/sparc/vm/frame_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/frame_sparc.cpp @@ -620,7 +620,7 @@ bool frame::is_interpreted_frame_valid(JavaThread* thread) const { // stack frames shouldn't be much larger than max_stack elements - if (fp() - sp() > 1024 + m->max_stack()*Interpreter::stackElementSize()) { + if (fp() - sp() > 1024 + m->max_stack()*Interpreter::stackElementSize) { return false; } diff --git a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp index b5535f86f51..257c426ab68 100644 --- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp @@ -50,7 +50,6 @@ void InterpreterMacroAssembler::compute_extra_locals_size_in_bytes(Register args // Any changes should also be applied to CodeEmitter::emit_osr_entry(). assert_different_registers(args_size, locals_size); // max_locals*2 for TAGS. Assumes that args_size has already been adjusted. - if (TaggedStackInterpreter) sll(locals_size, 1, locals_size); subcc(locals_size, args_size, delta);// extra space for non-arguments locals in words // Use br/mov combination because it works on both V8 and V9 and is // faster. @@ -319,7 +318,7 @@ void InterpreterMacroAssembler::load_unaligned_double(Register r1, int offset, F ldf(FloatRegisterImpl::D, r1, offset, d); #else ldf(FloatRegisterImpl::S, r1, offset, d); - ldf(FloatRegisterImpl::S, r1, offset + Interpreter::stackElementSize(), d->successor()); + ldf(FloatRegisterImpl::S, r1, offset + Interpreter::stackElementSize, d->successor()); #endif } @@ -330,10 +329,10 @@ void InterpreterMacroAssembler::store_unaligned_double(FloatRegister d, Register #ifdef _LP64 stf(FloatRegisterImpl::D, d, r1, offset); // store something more useful here - debug_only(stx(G0, r1, offset+Interpreter::stackElementSize());) + debug_only(stx(G0, r1, offset+Interpreter::stackElementSize);) #else stf(FloatRegisterImpl::S, d, r1, offset); - stf(FloatRegisterImpl::S, d->successor(), r1, offset + Interpreter::stackElementSize()); + stf(FloatRegisterImpl::S, d->successor(), r1, offset + Interpreter::stackElementSize); #endif } @@ -345,7 +344,7 @@ void InterpreterMacroAssembler::load_unaligned_long(Register r1, int offset, Reg ldx(r1, offset, rd); #else ld(r1, offset, rd); - ld(r1, offset + Interpreter::stackElementSize(), rd->successor()); + ld(r1, offset + Interpreter::stackElementSize, rd->successor()); #endif } @@ -356,138 +355,62 @@ void InterpreterMacroAssembler::store_unaligned_long(Register l, Register r1, in #ifdef _LP64 stx(l, r1, offset); // store something more useful here - debug_only(stx(G0, r1, offset+Interpreter::stackElementSize());) + debug_only(stx(G0, r1, offset+Interpreter::stackElementSize);) #else st(l, r1, offset); - st(l->successor(), r1, offset + Interpreter::stackElementSize()); + st(l->successor(), r1, offset + Interpreter::stackElementSize); #endif } -#ifdef ASSERT -void InterpreterMacroAssembler::verify_stack_tag(frame::Tag t, - Register r, - Register scratch) { - if (TaggedStackInterpreter) { - Label ok, long_ok; - ld_ptr(Lesp, Interpreter::expr_tag_offset_in_bytes(0), r); - if (t == frame::TagCategory2) { - cmp(r, G0); - brx(Assembler::equal, false, Assembler::pt, long_ok); - delayed()->ld_ptr(Lesp, Interpreter::expr_tag_offset_in_bytes(1), r); - stop("stack long/double tag value bad"); - bind(long_ok); - cmp(r, G0); - } else if (t == frame::TagValue) { - cmp(r, G0); - } else { - assert_different_registers(r, scratch); - mov(t, scratch); - cmp(r, scratch); - } - brx(Assembler::equal, false, Assembler::pt, ok); - delayed()->nop(); - // Also compare if the stack value is zero, then the tag might - // not have been set coming from deopt. - ld_ptr(Lesp, Interpreter::expr_offset_in_bytes(0), r); - cmp(r, G0); - brx(Assembler::equal, false, Assembler::pt, ok); - delayed()->nop(); - stop("Stack tag value is bad"); - bind(ok); - } -} -#endif // ASSERT - void InterpreterMacroAssembler::pop_i(Register r) { assert_not_delayed(); - // Uses destination register r for scratch - debug_only(verify_stack_tag(frame::TagValue, r)); ld(Lesp, Interpreter::expr_offset_in_bytes(0), r); - inc(Lesp, Interpreter::stackElementSize()); + inc(Lesp, Interpreter::stackElementSize); debug_only(verify_esp(Lesp)); } void InterpreterMacroAssembler::pop_ptr(Register r, Register scratch) { assert_not_delayed(); - // Uses destination register r for scratch - debug_only(verify_stack_tag(frame::TagReference, r, scratch)); ld_ptr(Lesp, Interpreter::expr_offset_in_bytes(0), r); - inc(Lesp, Interpreter::stackElementSize()); + inc(Lesp, Interpreter::stackElementSize); debug_only(verify_esp(Lesp)); } void InterpreterMacroAssembler::pop_l(Register r) { assert_not_delayed(); - // Uses destination register r for scratch - debug_only(verify_stack_tag(frame::TagCategory2, r)); load_unaligned_long(Lesp, Interpreter::expr_offset_in_bytes(0), r); - inc(Lesp, 2*Interpreter::stackElementSize()); + inc(Lesp, 2*Interpreter::stackElementSize); debug_only(verify_esp(Lesp)); } void InterpreterMacroAssembler::pop_f(FloatRegister f, Register scratch) { assert_not_delayed(); - debug_only(verify_stack_tag(frame::TagValue, scratch)); ldf(FloatRegisterImpl::S, Lesp, Interpreter::expr_offset_in_bytes(0), f); - inc(Lesp, Interpreter::stackElementSize()); + inc(Lesp, Interpreter::stackElementSize); debug_only(verify_esp(Lesp)); } void InterpreterMacroAssembler::pop_d(FloatRegister f, Register scratch) { assert_not_delayed(); - debug_only(verify_stack_tag(frame::TagCategory2, scratch)); load_unaligned_double(Lesp, Interpreter::expr_offset_in_bytes(0), f); - inc(Lesp, 2*Interpreter::stackElementSize()); + inc(Lesp, 2*Interpreter::stackElementSize); debug_only(verify_esp(Lesp)); } -// (Note use register first, then decrement so dec can be done during store stall) -void InterpreterMacroAssembler::tag_stack(Register r) { - if (TaggedStackInterpreter) { - st_ptr(r, Lesp, Interpreter::tag_offset_in_bytes()); - } -} - -void InterpreterMacroAssembler::tag_stack(frame::Tag t, Register r) { - if (TaggedStackInterpreter) { - assert (frame::TagValue == 0, "TagValue must be zero"); - if (t == frame::TagValue) { - st_ptr(G0, Lesp, Interpreter::tag_offset_in_bytes()); - } else if (t == frame::TagCategory2) { - st_ptr(G0, Lesp, Interpreter::tag_offset_in_bytes()); - // Tag next slot down too - st_ptr(G0, Lesp, -Interpreter::stackElementSize() + Interpreter::tag_offset_in_bytes()); - } else { - assert_different_registers(r, O3); - mov(t, O3); - st_ptr(O3, Lesp, Interpreter::tag_offset_in_bytes()); - } - } -} - void InterpreterMacroAssembler::push_i(Register r) { assert_not_delayed(); debug_only(verify_esp(Lesp)); - tag_stack(frame::TagValue, r); - st( r, Lesp, Interpreter::value_offset_in_bytes()); - dec( Lesp, Interpreter::stackElementSize()); + st(r, Lesp, 0); + dec(Lesp, Interpreter::stackElementSize); } void InterpreterMacroAssembler::push_ptr(Register r) { assert_not_delayed(); - tag_stack(frame::TagReference, r); - st_ptr( r, Lesp, Interpreter::value_offset_in_bytes()); - dec( Lesp, Interpreter::stackElementSize()); -} - -void InterpreterMacroAssembler::push_ptr(Register r, Register tag) { - assert_not_delayed(); - tag_stack(tag); - st_ptr(r, Lesp, Interpreter::value_offset_in_bytes()); - dec( Lesp, Interpreter::stackElementSize()); + st_ptr(r, Lesp, 0); + dec(Lesp, Interpreter::stackElementSize); } // remember: our convention for longs in SPARC is: @@ -497,33 +420,28 @@ void InterpreterMacroAssembler::push_ptr(Register r, Register tag) { void InterpreterMacroAssembler::push_l(Register r) { assert_not_delayed(); debug_only(verify_esp(Lesp)); - tag_stack(frame::TagCategory2, r); - // Longs are in stored in memory-correct order, even if unaligned. - // and may be separated by stack tags. - int offset = -Interpreter::stackElementSize() + Interpreter::value_offset_in_bytes(); + // Longs are stored in memory-correct order, even if unaligned. + int offset = -Interpreter::stackElementSize; store_unaligned_long(r, Lesp, offset); - dec(Lesp, 2 * Interpreter::stackElementSize()); + dec(Lesp, 2 * Interpreter::stackElementSize); } void InterpreterMacroAssembler::push_f(FloatRegister f) { assert_not_delayed(); debug_only(verify_esp(Lesp)); - tag_stack(frame::TagValue, Otos_i); - stf(FloatRegisterImpl::S, f, Lesp, Interpreter::value_offset_in_bytes()); - dec(Lesp, Interpreter::stackElementSize()); + stf(FloatRegisterImpl::S, f, Lesp, 0); + dec(Lesp, Interpreter::stackElementSize); } void InterpreterMacroAssembler::push_d(FloatRegister d) { assert_not_delayed(); debug_only(verify_esp(Lesp)); - tag_stack(frame::TagCategory2, Otos_i); - // Longs are in stored in memory-correct order, even if unaligned. - // and may be separated by stack tags. - int offset = -Interpreter::stackElementSize() + Interpreter::value_offset_in_bytes(); + // Longs are stored in memory-correct order, even if unaligned. + int offset = -Interpreter::stackElementSize; store_unaligned_double(d, Lesp, offset); - dec(Lesp, 2 * Interpreter::stackElementSize()); + dec(Lesp, 2 * Interpreter::stackElementSize); } @@ -561,30 +479,18 @@ void InterpreterMacroAssembler::pop(TosState state) { } -// Tagged stack helpers for swap and dup -void InterpreterMacroAssembler::load_ptr_and_tag(int n, Register val, - Register tag) { +// Helpers for swap and dup +void InterpreterMacroAssembler::load_ptr(int n, Register val) { ld_ptr(Lesp, Interpreter::expr_offset_in_bytes(n), val); - if (TaggedStackInterpreter) { - ld_ptr(Lesp, Interpreter::expr_tag_offset_in_bytes(n), tag); - } } -void InterpreterMacroAssembler::store_ptr_and_tag(int n, Register val, - Register tag) { +void InterpreterMacroAssembler::store_ptr(int n, Register val) { st_ptr(val, Lesp, Interpreter::expr_offset_in_bytes(n)); - if (TaggedStackInterpreter) { - st_ptr(tag, Lesp, Interpreter::expr_tag_offset_in_bytes(n)); - } } void InterpreterMacroAssembler::load_receiver(Register param_count, Register recv) { - - sll(param_count, Interpreter::logStackElementSize(), param_count); - if (TaggedStackInterpreter) { - add(param_count, Interpreter::value_offset_in_bytes(), param_count); // get obj address - } + sll(param_count, Interpreter::logStackElementSize, param_count); ld_ptr(Lesp, param_count, recv); // gets receiver Oop } @@ -605,7 +511,6 @@ void InterpreterMacroAssembler::empty_expression_stack() { // Compute max expression stack+register save area lduh(Lmethod, in_bytes(methodOopDesc::max_stack_offset()), Gframe_size); // Load max stack. - if (TaggedStackInterpreter) sll ( Gframe_size, 1, Gframe_size); // max_stack * 2 for TAGS add( Gframe_size, frame::memory_parameter_word_sp_offset, Gframe_size ); // @@ -2018,51 +1923,11 @@ void InterpreterMacroAssembler::add_monitor_to_stack( bool stack_is_empty, } // Locals -#ifdef ASSERT -void InterpreterMacroAssembler::verify_local_tag(frame::Tag t, - Register base, - Register scratch, - int n) { - if (TaggedStackInterpreter) { - Label ok, long_ok; - // Use dst for scratch - assert_different_registers(base, scratch); - ld_ptr(base, Interpreter::local_tag_offset_in_bytes(n), scratch); - if (t == frame::TagCategory2) { - cmp(scratch, G0); - brx(Assembler::equal, false, Assembler::pt, long_ok); - delayed()->ld_ptr(base, Interpreter::local_tag_offset_in_bytes(n+1), scratch); - stop("local long/double tag value bad"); - bind(long_ok); - // compare second half tag - cmp(scratch, G0); - } else if (t == frame::TagValue) { - cmp(scratch, G0); - } else { - assert_different_registers(O3, base, scratch); - mov(t, O3); - cmp(scratch, O3); - } - brx(Assembler::equal, false, Assembler::pt, ok); - delayed()->nop(); - // Also compare if the local value is zero, then the tag might - // not have been set coming from deopt. - ld_ptr(base, Interpreter::local_offset_in_bytes(n), scratch); - cmp(scratch, G0); - brx(Assembler::equal, false, Assembler::pt, ok); - delayed()->nop(); - stop("Local tag value is bad"); - bind(ok); - } -} -#endif // ASSERT - void InterpreterMacroAssembler::access_local_ptr( Register index, Register dst ) { assert_not_delayed(); - sll(index, Interpreter::logStackElementSize(), index); + sll(index, Interpreter::logStackElementSize, index); sub(Llocals, index, index); - debug_only(verify_local_tag(frame::TagReference, index, dst)); - ld_ptr(index, Interpreter::value_offset_in_bytes(), dst); + ld_ptr(index, 0, dst); // Note: index must hold the effective address--the iinc template uses it } @@ -2070,27 +1935,24 @@ void InterpreterMacroAssembler::access_local_ptr( Register index, Register dst ) void InterpreterMacroAssembler::access_local_returnAddress(Register index, Register dst ) { assert_not_delayed(); - sll(index, Interpreter::logStackElementSize(), index); + sll(index, Interpreter::logStackElementSize, index); sub(Llocals, index, index); - debug_only(verify_local_tag(frame::TagValue, index, dst)); - ld_ptr(index, Interpreter::value_offset_in_bytes(), dst); + ld_ptr(index, 0, dst); } void InterpreterMacroAssembler::access_local_int( Register index, Register dst ) { assert_not_delayed(); - sll(index, Interpreter::logStackElementSize(), index); + sll(index, Interpreter::logStackElementSize, index); sub(Llocals, index, index); - debug_only(verify_local_tag(frame::TagValue, index, dst)); - ld(index, Interpreter::value_offset_in_bytes(), dst); + ld(index, 0, dst); // Note: index must hold the effective address--the iinc template uses it } void InterpreterMacroAssembler::access_local_long( Register index, Register dst ) { assert_not_delayed(); - sll(index, Interpreter::logStackElementSize(), index); + sll(index, Interpreter::logStackElementSize, index); sub(Llocals, index, index); - debug_only(verify_local_tag(frame::TagCategory2, index, dst)); // First half stored at index n+1 (which grows down from Llocals[n]) load_unaligned_long(index, Interpreter::local_offset_in_bytes(1), dst); } @@ -2098,18 +1960,16 @@ void InterpreterMacroAssembler::access_local_long( Register index, Register dst void InterpreterMacroAssembler::access_local_float( Register index, FloatRegister dst ) { assert_not_delayed(); - sll(index, Interpreter::logStackElementSize(), index); + sll(index, Interpreter::logStackElementSize, index); sub(Llocals, index, index); - debug_only(verify_local_tag(frame::TagValue, index, G1_scratch)); - ldf(FloatRegisterImpl::S, index, Interpreter::value_offset_in_bytes(), dst); + ldf(FloatRegisterImpl::S, index, 0, dst); } void InterpreterMacroAssembler::access_local_double( Register index, FloatRegister dst ) { assert_not_delayed(); - sll(index, Interpreter::logStackElementSize(), index); + sll(index, Interpreter::logStackElementSize, index); sub(Llocals, index, index); - debug_only(verify_local_tag(frame::TagCategory2, index, G1_scratch)); load_unaligned_double(index, Interpreter::local_offset_in_bytes(1), dst); } @@ -2135,94 +1995,60 @@ void InterpreterMacroAssembler::check_for_regarea_stomp(Register Rindex, int off } #endif // ASSERT -void InterpreterMacroAssembler::tag_local(frame::Tag t, - Register base, - Register src, - int n) { - if (TaggedStackInterpreter) { - // have to store zero because local slots can be reused (rats!) - if (t == frame::TagValue) { - st_ptr(G0, base, Interpreter::local_tag_offset_in_bytes(n)); - } else if (t == frame::TagCategory2) { - st_ptr(G0, base, Interpreter::local_tag_offset_in_bytes(n)); - st_ptr(G0, base, Interpreter::local_tag_offset_in_bytes(n+1)); - } else { - // assert that we don't stomp the value in 'src' - // O3 is arbitrary because it's not used. - assert_different_registers(src, base, O3); - mov( t, O3); - st_ptr(O3, base, Interpreter::local_tag_offset_in_bytes(n)); - } - } -} - void InterpreterMacroAssembler::store_local_int( Register index, Register src ) { assert_not_delayed(); - sll(index, Interpreter::logStackElementSize(), index); + sll(index, Interpreter::logStackElementSize, index); sub(Llocals, index, index); - debug_only(check_for_regarea_stomp(index, Interpreter::value_offset_in_bytes(), FP, G1_scratch, G4_scratch);) - tag_local(frame::TagValue, index, src); - st(src, index, Interpreter::value_offset_in_bytes()); + debug_only(check_for_regarea_stomp(index, 0, FP, G1_scratch, G4_scratch);) + st(src, index, 0); } -void InterpreterMacroAssembler::store_local_ptr( Register index, Register src, - Register tag ) { +void InterpreterMacroAssembler::store_local_ptr( Register index, Register src ) { assert_not_delayed(); - sll(index, Interpreter::logStackElementSize(), index); + sll(index, Interpreter::logStackElementSize, index); sub(Llocals, index, index); - #ifdef ASSERT - check_for_regarea_stomp(index, Interpreter::value_offset_in_bytes(), FP, G1_scratch, G4_scratch); - #endif - st_ptr(src, index, Interpreter::value_offset_in_bytes()); - // Store tag register directly - if (TaggedStackInterpreter) { - st_ptr(tag, index, Interpreter::tag_offset_in_bytes()); - } +#ifdef ASSERT + check_for_regarea_stomp(index, 0, FP, G1_scratch, G4_scratch); +#endif + st_ptr(src, index, 0); } -void InterpreterMacroAssembler::store_local_ptr( int n, Register src, - Register tag ) { - st_ptr(src, Llocals, Interpreter::local_offset_in_bytes(n)); - if (TaggedStackInterpreter) { - st_ptr(tag, Llocals, Interpreter::local_tag_offset_in_bytes(n)); - } +void InterpreterMacroAssembler::store_local_ptr( int n, Register src ) { + st_ptr(src, Llocals, Interpreter::local_offset_in_bytes(n)); } void InterpreterMacroAssembler::store_local_long( Register index, Register src ) { assert_not_delayed(); - sll(index, Interpreter::logStackElementSize(), index); + sll(index, Interpreter::logStackElementSize, index); sub(Llocals, index, index); - #ifdef ASSERT +#ifdef ASSERT check_for_regarea_stomp(index, Interpreter::local_offset_in_bytes(1), FP, G1_scratch, G4_scratch); - #endif - tag_local(frame::TagCategory2, index, src); +#endif store_unaligned_long(src, index, Interpreter::local_offset_in_bytes(1)); // which is n+1 } void InterpreterMacroAssembler::store_local_float( Register index, FloatRegister src ) { assert_not_delayed(); - sll(index, Interpreter::logStackElementSize(), index); + sll(index, Interpreter::logStackElementSize, index); sub(Llocals, index, index); - #ifdef ASSERT - check_for_regarea_stomp(index, Interpreter::value_offset_in_bytes(), FP, G1_scratch, G4_scratch); - #endif - tag_local(frame::TagValue, index, G1_scratch); - stf(FloatRegisterImpl::S, src, index, Interpreter::value_offset_in_bytes()); +#ifdef ASSERT + check_for_regarea_stomp(index, 0, FP, G1_scratch, G4_scratch); +#endif + stf(FloatRegisterImpl::S, src, index, 0); } void InterpreterMacroAssembler::store_local_double( Register index, FloatRegister src ) { assert_not_delayed(); - sll(index, Interpreter::logStackElementSize(), index); + sll(index, Interpreter::logStackElementSize, index); sub(Llocals, index, index); - #ifdef ASSERT +#ifdef ASSERT check_for_regarea_stomp(index, Interpreter::local_offset_in_bytes(1), FP, G1_scratch, G4_scratch); - #endif - tag_local(frame::TagCategory2, index, G1_scratch); +#endif store_unaligned_double(src, index, Interpreter::local_offset_in_bytes(1)); } diff --git a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp index 0fd57778afe..3db0a0a081b 100644 --- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp @@ -149,7 +149,6 @@ class InterpreterMacroAssembler: public MacroAssembler { void push_i( Register r = Otos_i); void push_ptr( Register r = Otos_i); - void push_ptr( Register r, Register tag); void push_l( Register r = Otos_l1); void push_f(FloatRegister f = Ftos_f); void push_d(FloatRegister f = Ftos_d1); @@ -159,17 +158,9 @@ class InterpreterMacroAssembler: public MacroAssembler { void push(TosState state); // transition state -> vtos void empty_expression_stack(); // resets both Lesp and SP - // Support for Tagged Stacks - void tag_stack(frame::Tag t, Register r); - void tag_stack(Register tag); - void tag_local(frame::Tag t, Register src, Register base, int n = 0); - #ifdef ASSERT void verify_sp(Register Rsp, Register Rtemp); void verify_esp(Register Resp); // verify that Lesp points to a word in the temp stack - - void verify_stack_tag(frame::Tag t, Register r, Register scratch = G0); - void verify_local_tag(frame::Tag t, Register base, Register scr, int n = 0); #endif // ASSERT public: @@ -242,17 +233,17 @@ class InterpreterMacroAssembler: public MacroAssembler { void check_for_regarea_stomp( Register Rindex, int offset, Register Rlimit, Register Rscratch, Register Rscratch1); #endif // ASSERT void store_local_int( Register index, Register src ); - void store_local_ptr( Register index, Register src, Register tag = Otos_l2 ); - void store_local_ptr( int n, Register src, Register tag = Otos_l2 ); + void store_local_ptr( Register index, Register src ); + void store_local_ptr( int n, Register src ); void store_local_long( Register index, Register src ); void store_local_float( Register index, FloatRegister src ); void store_local_double( Register index, FloatRegister src ); - // Tagged stack helpers for swap and dup - void load_ptr_and_tag(int n, Register val, Register tag); - void store_ptr_and_tag(int n, Register val, Register tag); + // Helpers for swap and dup + void load_ptr(int n, Register val); + void store_ptr(int n, Register val); - // Tagged stack helper for getting receiver in register. + // Helper for getting receiver in register. void load_receiver(Register param_count, Register recv); static int top_most_monitor_byte_offset(); // offset in bytes to top of monitor block diff --git a/hotspot/src/cpu/sparc/vm/interpreterRT_sparc.cpp b/hotspot/src/cpu/sparc/vm/interpreterRT_sparc.cpp index 7306f2a7f6e..443a74f4708 100644 --- a/hotspot/src/cpu/sparc/vm/interpreterRT_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/interpreterRT_sparc.cpp @@ -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 @@ -43,19 +43,6 @@ void InterpreterRuntime::SignatureHandlerGenerator::pass_long() { Argument jni_arg(jni_offset(), false); Register Rtmp = O0; -#ifdef ASSERT - if (TaggedStackInterpreter) { - // check at least one tag is okay - Label ok; - __ ld_ptr(Llocals, Interpreter::local_tag_offset_in_bytes(offset() + 1), Rtmp); - __ cmp(Rtmp, G0); - __ brx(Assembler::equal, false, Assembler::pt, ok); - __ delayed()->nop(); - __ stop("Native object has bad tag value"); - __ bind(ok); - } -#endif // ASSERT - #ifdef _LP64 __ ldx(Llocals, Interpreter::local_offset_in_bytes(offset() + 1), Rtmp); __ store_long_argument(Rtmp, jni_arg); @@ -107,18 +94,6 @@ void InterpreterRuntime::SignatureHandlerGenerator::pass_object() { Address h_arg = Address(Llocals, Interpreter::local_offset_in_bytes(offset())); __ ld_ptr(h_arg, Rtmp1); -#ifdef ASSERT - if (TaggedStackInterpreter) { - // check we have the obj and not the tag - Label ok; - __ mov(frame::TagReference, Rtmp3); - __ cmp(Rtmp1, Rtmp3); - __ brx(Assembler::notEqual, true, Assembler::pt, ok); - __ delayed()->nop(); - __ stop("Native object passed tag by mistake"); - __ bind(ok); - } -#endif // ASSERT if (!do_NULL_check) { __ add(h_arg.base(), h_arg.disp(), Rtmp2); } else { @@ -168,17 +143,9 @@ class SlowSignatureHandler: public NativeSignatureIterator { long_sig = 3 }; -#ifdef ASSERT - void verify_tag(frame::Tag t) { - assert(!TaggedStackInterpreter || - *(intptr_t*)(_from+Interpreter::local_tag_offset_in_bytes(0)) == t, "wrong tag"); - } -#endif // ASSERT - virtual void pass_int() { *_to++ = *(jint *)(_from+Interpreter::local_offset_in_bytes(0)); - debug_only(verify_tag(frame::TagValue)); - _from -= Interpreter::stackElementSize(); + _from -= Interpreter::stackElementSize; add_signature( non_float ); } @@ -186,31 +153,27 @@ class SlowSignatureHandler: public NativeSignatureIterator { // pass address of from intptr_t *from_addr = (intptr_t*)(_from + Interpreter::local_offset_in_bytes(0)); *_to++ = (*from_addr == 0) ? NULL : (intptr_t) from_addr; - debug_only(verify_tag(frame::TagReference)); - _from -= Interpreter::stackElementSize(); + _from -= Interpreter::stackElementSize; add_signature( non_float ); } #ifdef _LP64 virtual void pass_float() { *_to++ = *(jint *)(_from+Interpreter::local_offset_in_bytes(0)); - debug_only(verify_tag(frame::TagValue)); - _from -= Interpreter::stackElementSize(); + _from -= Interpreter::stackElementSize; add_signature( float_sig ); } virtual void pass_double() { *_to++ = *(intptr_t*)(_from+Interpreter::local_offset_in_bytes(1)); - debug_only(verify_tag(frame::TagValue)); - _from -= 2*Interpreter::stackElementSize(); + _from -= 2*Interpreter::stackElementSize; add_signature( double_sig ); } virtual void pass_long() { _to[0] = *(intptr_t*)(_from+Interpreter::local_offset_in_bytes(1)); - debug_only(verify_tag(frame::TagValue)); _to += 1; - _from -= 2*Interpreter::stackElementSize(); + _from -= 2*Interpreter::stackElementSize; add_signature( long_sig ); } #else @@ -218,9 +181,8 @@ class SlowSignatureHandler: public NativeSignatureIterator { virtual void pass_long() { _to[0] = *(intptr_t*)(_from+Interpreter::local_offset_in_bytes(1)); _to[1] = *(intptr_t*)(_from+Interpreter::local_offset_in_bytes(0)); - debug_only(verify_tag(frame::TagValue)); _to += 2; - _from -= 2*Interpreter::stackElementSize(); + _from -= 2*Interpreter::stackElementSize; add_signature( non_float ); } #endif // _LP64 diff --git a/hotspot/src/cpu/sparc/vm/interpreter_sparc.hpp b/hotspot/src/cpu/sparc/vm/interpreter_sparc.hpp index 711eedead67..e9a101e8fbe 100644 --- a/hotspot/src/cpu/sparc/vm/interpreter_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/interpreter_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 @@ -24,33 +24,13 @@ public: - // Support for Tagged Stacks + static int expr_offset_in_bytes(int i) { return stackElementSize * i + wordSize; } // Stack index relative to tos (which points at value) - static int expr_index_at(int i) { - return stackElementWords() * i; - } - - static int expr_tag_index_at(int i) { - assert(TaggedStackInterpreter, "should not call this"); - // tag is one word above java stack element - return stackElementWords() * i + 1; - } - - static int expr_offset_in_bytes(int i) { return stackElementSize()*i + wordSize; } - static int expr_tag_offset_in_bytes (int i) { - assert(TaggedStackInterpreter, "should not call this"); - return expr_offset_in_bytes(i) + wordSize; - } + static int expr_index_at(int i) { return stackElementWords * i; } // Already negated by c++ interpreter - static int local_index_at(int i) { - assert(i<=0, "local direction already negated"); - return stackElementWords() * i + (value_offset_in_bytes()/wordSize); - } - - static int local_tag_index_at(int i) { - assert(i<=0, "local direction already negated"); - assert(TaggedStackInterpreter, "should not call this"); - return stackElementWords() * i + (tag_offset_in_bytes()/wordSize); + static int local_index_at(int i) { + assert(i <= 0, "local direction already negated"); + return stackElementWords * i; } diff --git a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp index c8accffeaf7..3eeb885e497 100644 --- a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp @@ -358,7 +358,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan // Push arguments as if coming from the interpreter. Register O0_scratch = O0_argslot; - int stackElementSize = Interpreter::stackElementSize(); + int stackElementSize = Interpreter::stackElementSize; // Make space on the stack for the arguments. __ sub(SP, 4*stackElementSize, SP); @@ -679,7 +679,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan insert_arg_slots(_masm, stack_move_unit(), _INSERT_INT_MASK, O0_argslot, O1_scratch, O2_scratch, G5_index); Address arg_lsw(O0_argslot, 0); - Address arg_msw(O0_argslot, -Interpreter::stackElementSize()); + Address arg_msw(O0_argslot, -Interpreter::stackElementSize); switch (ek) { case _adapter_opt_i2l: diff --git a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp index 50a5b6de13b..7ef64e361be 100644 --- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp @@ -547,17 +547,11 @@ class AdapterGenerator { void set_Rdisp(Register r) { Rdisp = r; } void patch_callers_callsite(); - void tag_c2i_arg(frame::Tag t, Register base, int st_off, Register scratch); // base+st_off points to top of argument - int arg_offset(const int st_off) { return st_off + Interpreter::value_offset_in_bytes(); } + int arg_offset(const int st_off) { return st_off; } int next_arg_offset(const int st_off) { - return st_off - Interpreter::stackElementSize() + Interpreter::value_offset_in_bytes(); - } - - int tag_offset(const int st_off) { return st_off + Interpreter::tag_offset_in_bytes(); } - int next_tag_offset(const int st_off) { - return st_off - Interpreter::stackElementSize() + Interpreter::tag_offset_in_bytes(); + return st_off - Interpreter::stackElementSize; } // Argument slot values may be loaded first into a register because @@ -565,9 +559,6 @@ class AdapterGenerator { RegisterOrConstant arg_slot(const int st_off); RegisterOrConstant next_arg_slot(const int st_off); - RegisterOrConstant tag_slot(const int st_off); - RegisterOrConstant next_tag_slot(const int st_off); - // Stores long into offset pointed to by base void store_c2i_long(Register r, Register base, const int st_off, bool is_stack); @@ -653,23 +644,6 @@ void AdapterGenerator::patch_callers_callsite() { __ bind(L); } -void AdapterGenerator::tag_c2i_arg(frame::Tag t, Register base, int st_off, - Register scratch) { - if (TaggedStackInterpreter) { - RegisterOrConstant slot = tag_slot(st_off); - // have to store zero because local slots can be reused (rats!) - if (t == frame::TagValue) { - __ st_ptr(G0, base, slot); - } else if (t == frame::TagCategory2) { - __ st_ptr(G0, base, slot); - __ st_ptr(G0, base, next_tag_slot(st_off)); - } else { - __ mov(t, scratch); - __ st_ptr(scratch, base, slot); - } - } -} - RegisterOrConstant AdapterGenerator::arg_slot(const int st_off) { RegisterOrConstant roc(arg_offset(st_off)); @@ -682,17 +656,6 @@ RegisterOrConstant AdapterGenerator::next_arg_slot(const int st_off) { } -RegisterOrConstant AdapterGenerator::tag_slot(const int st_off) { - RegisterOrConstant roc(tag_offset(st_off)); - return __ ensure_simm13_or_reg(roc, Rdisp); -} - -RegisterOrConstant AdapterGenerator::next_tag_slot(const int st_off) { - RegisterOrConstant roc(next_tag_offset(st_off)); - return __ ensure_simm13_or_reg(roc, Rdisp); -} - - // Stores long into offset pointed to by base void AdapterGenerator::store_c2i_long(Register r, Register base, const int st_off, bool is_stack) { @@ -718,19 +681,16 @@ void AdapterGenerator::store_c2i_long(Register r, Register base, } #endif // COMPILER2 #endif // _LP64 - tag_c2i_arg(frame::TagCategory2, base, st_off, r); } void AdapterGenerator::store_c2i_object(Register r, Register base, const int st_off) { __ st_ptr (r, base, arg_slot(st_off)); - tag_c2i_arg(frame::TagReference, base, st_off, r); } void AdapterGenerator::store_c2i_int(Register r, Register base, const int st_off) { __ st (r, base, arg_slot(st_off)); - tag_c2i_arg(frame::TagValue, base, st_off, r); } // Stores into offset pointed to by base @@ -745,13 +705,11 @@ void AdapterGenerator::store_c2i_double(VMReg r_2, __ stf(FloatRegisterImpl::S, r_1->as_FloatRegister(), base, next_arg_slot(st_off)); __ stf(FloatRegisterImpl::S, r_2->as_FloatRegister(), base, arg_slot(st_off) ); #endif - tag_c2i_arg(frame::TagCategory2, base, st_off, G1_scratch); } void AdapterGenerator::store_c2i_float(FloatRegister f, Register base, const int st_off) { __ stf(FloatRegisterImpl::S, f, base, arg_slot(st_off)); - tag_c2i_arg(frame::TagValue, base, st_off, G1_scratch); } void AdapterGenerator::gen_c2i_adapter( @@ -786,14 +744,14 @@ void AdapterGenerator::gen_c2i_adapter( // Since all args are passed on the stack, total_args_passed*wordSize is the // space we need. Add in varargs area needed by the interpreter. Round up // to stack alignment. - const int arg_size = total_args_passed * Interpreter::stackElementSize(); + const int arg_size = total_args_passed * Interpreter::stackElementSize; const int varargs_area = (frame::varargs_offset - frame::register_save_words)*wordSize; const int extraspace = round_to(arg_size + varargs_area, 2*wordSize); int bias = STACK_BIAS; const int interp_arg_offset = frame::varargs_offset*wordSize + - (total_args_passed-1)*Interpreter::stackElementSize(); + (total_args_passed-1)*Interpreter::stackElementSize; Register base = SP; @@ -814,7 +772,7 @@ void AdapterGenerator::gen_c2i_adapter( // First write G1 (if used) to where ever it must go for (int i=0; ias_VMReg()) { @@ -831,7 +789,7 @@ void AdapterGenerator::gen_c2i_adapter( // Now write the args into the outgoing interpreter space for (int i=0; iis_valid()) { @@ -900,7 +858,7 @@ void AdapterGenerator::gen_c2i_adapter( #endif // _LP64 __ mov((frame::varargs_offset)*wordSize - - 1*Interpreter::stackElementSize()+bias+BytesPerWord, G1); + 1*Interpreter::stackElementSize+bias+BytesPerWord, G1); // Jump to the interpreter just as if interpreter was doing it. __ jmpl(G3_scratch, 0, G0); // Setup Lesp for the call. Cannot actually set Lesp as the current Lesp @@ -1051,7 +1009,7 @@ void AdapterGenerator::gen_i2c_adapter( // ldx/lddf optimizations. // Load in argument order going down. - const int ld_off = (total_args_passed-i)*Interpreter::stackElementSize(); + const int ld_off = (total_args_passed-i)*Interpreter::stackElementSize; set_Rdisp(G1_scratch); VMReg r_1 = regs[i].first(); @@ -1120,7 +1078,7 @@ void AdapterGenerator::gen_i2c_adapter( for (int i=0; iis_Register() && regs[i].second()->is_valid()) { // Load in argument order going down - int ld_off = (total_args_passed-i)*Interpreter::stackElementSize(); + int ld_off = (total_args_passed-i)*Interpreter::stackElementSize; // Need to marshal 64-bit value from misaligned Lesp loads Register r = regs[i].first()->as_Register()->after_restore(); if (r == G1 || r == G4) { @@ -3062,7 +3020,7 @@ int Deoptimization::last_frame_adjust(int callee_parameters, int callee_locals) "test and remove; got more parms than locals"); if (callee_locals < callee_parameters) return 0; // No adjustment for negative locals - int diff = (callee_locals - callee_parameters) * Interpreter::stackElementWords(); + int diff = (callee_locals - callee_parameters) * Interpreter::stackElementWords; return round_to(diff, WordsPerLong); } diff --git a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp index e1ea96a3f5b..2bb8e8383bd 100644 --- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp @@ -139,7 +139,7 @@ class StubGenerator: public StubCodeGenerator { __ ld_ptr(parameter_size.as_address(), t); // get parameter size (in words) __ add(t, frame::memory_parameter_word_sp_offset, t); // add space for save area (in words) __ round_to(t, WordsPerLong); // make sure it is multiple of 2 (in words) - __ sll(t, Interpreter::logStackElementSize(), t); // compute number of bytes + __ sll(t, Interpreter::logStackElementSize, t); // compute number of bytes __ neg(t); // negate so it can be used with save __ save(SP, t, SP); // setup new frame } @@ -191,19 +191,13 @@ class StubGenerator: public StubCodeGenerator { // copy parameters if any Label loop; __ BIND(loop); - // Store tag first. - if (TaggedStackInterpreter) { - __ ld_ptr(src, 0, tmp); - __ add(src, BytesPerWord, src); // get next - __ st_ptr(tmp, dst, Interpreter::tag_offset_in_bytes()); - } // Store parameter value __ ld_ptr(src, 0, tmp); __ add(src, BytesPerWord, src); - __ st_ptr(tmp, dst, Interpreter::value_offset_in_bytes()); + __ st_ptr(tmp, dst, 0); __ deccc(cnt); __ br(Assembler::greater, false, Assembler::pt, loop); - __ delayed()->sub(dst, Interpreter::stackElementSize(), dst); + __ delayed()->sub(dst, Interpreter::stackElementSize, dst); // done __ BIND(exit); @@ -220,7 +214,7 @@ class StubGenerator: public StubCodeGenerator { // setup parameters const Register t = G3_scratch; __ ld_ptr(parameter_size.as_in().as_address(), t); // get parameter size (in words) - __ sll(t, Interpreter::logStackElementSize(), t); // compute number of bytes + __ sll(t, Interpreter::logStackElementSize, t); // compute number of bytes __ sub(FP, t, Gargs); // setup parameter pointer #ifdef _LP64 __ add( Gargs, STACK_BIAS, Gargs ); // Account for LP64 stack bias diff --git a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp index fc539099985..0c4d7472cd5 100644 --- a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp @@ -197,7 +197,7 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, __ ld_ptr(cache, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::flags_offset(), size); __ and3(size, 0xFF, size); // argument size in words - __ sll(size, Interpreter::logStackElementSize(), size); // each argument size in bytes + __ sll(size, Interpreter::logStackElementSize, size); // each argument size in bytes __ add(Lesp, size, Lesp); // pop arguments __ dispatch_next(state, step); @@ -495,7 +495,7 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) { // Set the saved SP after the register window save // assert_different_registers(Gargs, Glocals_size, Gframe_size, O5_savedSP); - __ sll(Glocals_size, Interpreter::logStackElementSize(), Otmp1); + __ sll(Glocals_size, Interpreter::logStackElementSize, Otmp1); __ add(Gargs, Otmp1, Gargs); if (native_call) { @@ -511,7 +511,7 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) { __ lduh( size_of_locals, Otmp1 ); __ sub( Otmp1, Glocals_size, Glocals_size ); __ round_to( Glocals_size, WordsPerLong ); - __ sll( Glocals_size, Interpreter::logStackElementSize(), Glocals_size ); + __ sll( Glocals_size, Interpreter::logStackElementSize, Glocals_size ); // see if the frame is greater than one page in size. If so, // then we need to verify there is enough stack space remaining @@ -519,7 +519,7 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) { __ lduh( max_stack, Gframe_size ); __ add( Gframe_size, extra_space, Gframe_size ); __ round_to( Gframe_size, WordsPerLong ); - __ sll( Gframe_size, Interpreter::logStackElementSize(), Gframe_size); + __ sll( Gframe_size, Interpreter::logStackElementSize, Gframe_size); // Add in java locals size for stack overflow check only __ add( Gframe_size, Glocals_size, Gframe_size ); @@ -1234,8 +1234,8 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) { // be updated! __ lduh( size_of_locals, O2 ); __ lduh( size_of_parameters, O1 ); - __ sll( O2, Interpreter::logStackElementSize(), O2); - __ sll( O1, Interpreter::logStackElementSize(), O1 ); + __ sll( O2, Interpreter::logStackElementSize, O2); + __ sll( O1, Interpreter::logStackElementSize, O1 ); __ sub( Llocals, O2, O2 ); __ sub( Llocals, O1, O1 ); @@ -1470,8 +1470,8 @@ static int size_activation_helper(int callee_extra_locals, int max_stack, int mo round_to(frame::interpreter_frame_vm_local_words,WordsPerLong); // callee_locals and max_stack are counts, not the size in frame. const int locals_size = - round_to(callee_extra_locals * Interpreter::stackElementWords(), WordsPerLong); - const int max_stack_words = max_stack * Interpreter::stackElementWords(); + round_to(callee_extra_locals * Interpreter::stackElementWords, WordsPerLong); + const int max_stack_words = max_stack * Interpreter::stackElementWords; return (round_to((max_stack_words //6815692//+ methodOopDesc::extra_stack_words() + rounded_vm_local_words @@ -1570,11 +1570,11 @@ int AbstractInterpreter::layout_activation(methodOop method, // preallocate stack space intptr_t* esp = monitors - 1 - - (tempcount * Interpreter::stackElementWords()) - + (tempcount * Interpreter::stackElementWords) - popframe_extra_args; - int local_words = method->max_locals() * Interpreter::stackElementWords(); - int parm_words = method->size_of_parameters() * Interpreter::stackElementWords(); + int local_words = method->max_locals() * Interpreter::stackElementWords; + int parm_words = method->size_of_parameters() * Interpreter::stackElementWords; NEEDS_CLEANUP; intptr_t* locals; if (caller->is_interpreted_frame()) { @@ -1662,7 +1662,7 @@ int AbstractInterpreter::layout_activation(methodOop method, BasicObjectLock* mp = (BasicObjectLock*)monitors; assert(interpreter_frame->interpreter_frame_method() == method, "method matches"); - assert(interpreter_frame->interpreter_frame_local_at(9) == (intptr_t *)((intptr_t)locals - (9 * Interpreter::stackElementSize())+Interpreter::value_offset_in_bytes()), "locals match"); + assert(interpreter_frame->interpreter_frame_local_at(9) == (intptr_t *)((intptr_t)locals - (9 * Interpreter::stackElementSize)), "locals match"); assert(interpreter_frame->interpreter_frame_monitor_end() == mp, "monitor_end matches"); assert(((intptr_t *)interpreter_frame->interpreter_frame_monitor_begin()) == ((intptr_t *)mp)+monitor_size, "monitor_begin matches"); assert(interpreter_frame->interpreter_frame_tos_address()-1 == esp, "esp matches"); @@ -1758,7 +1758,7 @@ void TemplateInterpreterGenerator::generate_throw_exception() { // Compute size of arguments for saving when returning to deoptimized caller __ lduh(Lmethod, in_bytes(methodOopDesc::size_of_parameters_offset()), Gtmp1); - __ sll(Gtmp1, Interpreter::logStackElementSize(), Gtmp1); + __ sll(Gtmp1, Interpreter::logStackElementSize, Gtmp1); __ sub(Llocals, Gtmp1, Gtmp2); __ add(Gtmp2, wordSize, Gtmp2); // Save these arguments diff --git a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.hpp b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.hpp index 6a510688888..3f8de131db5 100644 --- a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/templateInterpreter_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 @@ -29,7 +29,8 @@ // fail with a guarantee ("not enough space for interpreter generation"); // if too small. // Run with +PrintInterpreter to get the VM to print out the size. - // Max size with JVMTI and TaggedStackInterpreter + // Max size with JVMTI + #ifdef _LP64 // The sethi() instruction generates lots more instructions when shell // stack limit is unlimited, so that's why this is much bigger. diff --git a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp index 5ab2ffc1308..6ca719e007a 100644 --- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp @@ -580,7 +580,6 @@ void TemplateTable::saload() { void TemplateTable::iload(int n) { transition(vtos, itos); - debug_only(__ verify_local_tag(frame::TagValue, Llocals, Otos_i, n)); __ ld( Llocals, Interpreter::local_offset_in_bytes(n), Otos_i ); } @@ -588,7 +587,6 @@ void TemplateTable::iload(int n) { void TemplateTable::lload(int n) { transition(vtos, ltos); assert(n+1 < Argument::n_register_parameters, "would need more code"); - debug_only(__ verify_local_tag(frame::TagCategory2, Llocals, Otos_l, n)); __ load_unaligned_long(Llocals, Interpreter::local_offset_in_bytes(n+1), Otos_l); } @@ -596,7 +594,6 @@ void TemplateTable::lload(int n) { void TemplateTable::fload(int n) { transition(vtos, ftos); assert(n < Argument::n_register_parameters, "would need more code"); - debug_only(__ verify_local_tag(frame::TagValue, Llocals, G3_scratch, n)); __ ldf( FloatRegisterImpl::S, Llocals, Interpreter::local_offset_in_bytes(n), Ftos_f ); } @@ -604,14 +601,12 @@ void TemplateTable::fload(int n) { void TemplateTable::dload(int n) { transition(vtos, dtos); FloatRegister dst = Ftos_d; - debug_only(__ verify_local_tag(frame::TagCategory2, Llocals, G3_scratch, n)); __ load_unaligned_double(Llocals, Interpreter::local_offset_in_bytes(n+1), dst); } void TemplateTable::aload(int n) { transition(vtos, atos); - debug_only(__ verify_local_tag(frame::TagReference, Llocals, Otos_i, n)); __ ld_ptr( Llocals, Interpreter::local_offset_in_bytes(n), Otos_i ); } @@ -707,12 +702,11 @@ void TemplateTable::dstore() { void TemplateTable::astore() { transition(vtos, vtos); - // astore tos can also be a returnAddress, so load and store the tag too - __ load_ptr_and_tag(0, Otos_i, Otos_l2); - __ inc(Lesp, Interpreter::stackElementSize()); + __ load_ptr(0, Otos_i); + __ inc(Lesp, Interpreter::stackElementSize); __ verify_oop_or_return_address(Otos_i, G3_scratch); locals_index(G3_scratch); - __ store_local_ptr( G3_scratch, Otos_i, Otos_l2 ); + __ store_local_ptr(G3_scratch, Otos_i); } @@ -750,12 +744,11 @@ void TemplateTable::wide_dstore() { void TemplateTable::wide_astore() { transition(vtos, vtos); - // astore tos can also be a returnAddress, so load and store the tag too - __ load_ptr_and_tag(0, Otos_i, Otos_l2); - __ inc(Lesp, Interpreter::stackElementSize()); + __ load_ptr(0, Otos_i); + __ inc(Lesp, Interpreter::stackElementSize); __ verify_oop_or_return_address(Otos_i, G3_scratch); locals_index_wide(G3_scratch); - __ store_local_ptr( G3_scratch, Otos_i, Otos_l2 ); + __ store_local_ptr(G3_scratch, Otos_i); } @@ -845,13 +838,13 @@ void TemplateTable::aastore() { do_oop_store(_masm, O1, noreg, arrayOopDesc::base_offset_in_bytes(T_OBJECT), Otos_i, G3_scratch, _bs->kind(), true); __ ba(false,done); - __ delayed()->inc(Lesp, 3* Interpreter::stackElementSize()); // adj sp (pops array, index and value) + __ delayed()->inc(Lesp, 3* Interpreter::stackElementSize); // adj sp (pops array, index and value) __ bind(is_null); do_oop_store(_masm, O1, noreg, arrayOopDesc::base_offset_in_bytes(T_OBJECT), G0, G4_scratch, _bs->kind(), true); __ profile_null_seen(G3_scratch); - __ inc(Lesp, 3* Interpreter::stackElementSize()); // adj sp (pops array, index and value) + __ inc(Lesp, 3* Interpreter::stackElementSize); // adj sp (pops array, index and value) __ bind(done); } @@ -884,7 +877,6 @@ void TemplateTable::sastore() { void TemplateTable::istore(int n) { transition(itos, vtos); - __ tag_local(frame::TagValue, Llocals, Otos_i, n); __ st(Otos_i, Llocals, Interpreter::local_offset_in_bytes(n)); } @@ -892,7 +884,6 @@ void TemplateTable::istore(int n) { void TemplateTable::lstore(int n) { transition(ltos, vtos); assert(n+1 < Argument::n_register_parameters, "only handle register cases"); - __ tag_local(frame::TagCategory2, Llocals, Otos_l, n); __ store_unaligned_long(Otos_l, Llocals, Interpreter::local_offset_in_bytes(n+1)); } @@ -901,7 +892,6 @@ void TemplateTable::lstore(int n) { void TemplateTable::fstore(int n) { transition(ftos, vtos); assert(n < Argument::n_register_parameters, "only handle register cases"); - __ tag_local(frame::TagValue, Llocals, Otos_l, n); __ stf(FloatRegisterImpl::S, Ftos_f, Llocals, Interpreter::local_offset_in_bytes(n)); } @@ -909,30 +899,28 @@ void TemplateTable::fstore(int n) { void TemplateTable::dstore(int n) { transition(dtos, vtos); FloatRegister src = Ftos_d; - __ tag_local(frame::TagCategory2, Llocals, Otos_l, n); __ store_unaligned_double(src, Llocals, Interpreter::local_offset_in_bytes(n+1)); } void TemplateTable::astore(int n) { transition(vtos, vtos); - // astore tos can also be a returnAddress, so load and store the tag too - __ load_ptr_and_tag(0, Otos_i, Otos_l2); - __ inc(Lesp, Interpreter::stackElementSize()); + __ load_ptr(0, Otos_i); + __ inc(Lesp, Interpreter::stackElementSize); __ verify_oop_or_return_address(Otos_i, G3_scratch); - __ store_local_ptr( n, Otos_i, Otos_l2 ); + __ store_local_ptr(n, Otos_i); } void TemplateTable::pop() { transition(vtos, vtos); - __ inc(Lesp, Interpreter::stackElementSize()); + __ inc(Lesp, Interpreter::stackElementSize); } void TemplateTable::pop2() { transition(vtos, vtos); - __ inc(Lesp, 2 * Interpreter::stackElementSize()); + __ inc(Lesp, 2 * Interpreter::stackElementSize); } @@ -940,8 +928,8 @@ void TemplateTable::dup() { transition(vtos, vtos); // stack: ..., a // load a and tag - __ load_ptr_and_tag(0, Otos_i, Otos_l2); - __ push_ptr(Otos_i, Otos_l2); + __ load_ptr(0, Otos_i); + __ push_ptr(Otos_i); // stack: ..., a, a } @@ -949,11 +937,11 @@ void TemplateTable::dup() { void TemplateTable::dup_x1() { transition(vtos, vtos); // stack: ..., a, b - __ load_ptr_and_tag(1, G3_scratch, G4_scratch); // get a - __ load_ptr_and_tag(0, Otos_l1, Otos_l2); // get b - __ store_ptr_and_tag(1, Otos_l1, Otos_l2); // put b - __ store_ptr_and_tag(0, G3_scratch, G4_scratch); // put a - like swap - __ push_ptr(Otos_l1, Otos_l2); // push b + __ load_ptr( 1, G3_scratch); // get a + __ load_ptr( 0, Otos_l1); // get b + __ store_ptr(1, Otos_l1); // put b + __ store_ptr(0, G3_scratch); // put a - like swap + __ push_ptr(Otos_l1); // push b // stack: ..., b, a, b } @@ -962,27 +950,27 @@ void TemplateTable::dup_x2() { transition(vtos, vtos); // stack: ..., a, b, c // get c and push on stack, reuse registers - __ load_ptr_and_tag(0, G3_scratch, G4_scratch); // get c - __ push_ptr(G3_scratch, G4_scratch); // push c with tag + __ load_ptr( 0, G3_scratch); // get c + __ push_ptr(G3_scratch); // push c with tag // stack: ..., a, b, c, c (c in reg) (Lesp - 4) // (stack offsets n+1 now) - __ load_ptr_and_tag(3, Otos_l1, Otos_l2); // get a - __ store_ptr_and_tag(3, G3_scratch, G4_scratch); // put c at 3 + __ load_ptr( 3, Otos_l1); // get a + __ store_ptr(3, G3_scratch); // put c at 3 // stack: ..., c, b, c, c (a in reg) - __ load_ptr_and_tag(2, G3_scratch, G4_scratch); // get b - __ store_ptr_and_tag(2, Otos_l1, Otos_l2); // put a at 2 + __ load_ptr( 2, G3_scratch); // get b + __ store_ptr(2, Otos_l1); // put a at 2 // stack: ..., c, a, c, c (b in reg) - __ store_ptr_and_tag(1, G3_scratch, G4_scratch); // put b at 1 + __ store_ptr(1, G3_scratch); // put b at 1 // stack: ..., c, a, b, c } void TemplateTable::dup2() { transition(vtos, vtos); - __ load_ptr_and_tag(1, G3_scratch, G4_scratch); // get a - __ load_ptr_and_tag(0, Otos_l1, Otos_l2); // get b - __ push_ptr(G3_scratch, G4_scratch); // push a - __ push_ptr(Otos_l1, Otos_l2); // push b + __ load_ptr(1, G3_scratch); // get a + __ load_ptr(0, Otos_l1); // get b + __ push_ptr(G3_scratch); // push a + __ push_ptr(Otos_l1); // push b // stack: ..., a, b, a, b } @@ -990,17 +978,17 @@ void TemplateTable::dup2() { void TemplateTable::dup2_x1() { transition(vtos, vtos); // stack: ..., a, b, c - __ load_ptr_and_tag(1, Lscratch, G1_scratch); // get b - __ load_ptr_and_tag(2, Otos_l1, Otos_l2); // get a - __ store_ptr_and_tag(2, Lscratch, G1_scratch); // put b at a + __ load_ptr( 1, Lscratch); // get b + __ load_ptr( 2, Otos_l1); // get a + __ store_ptr(2, Lscratch); // put b at a // stack: ..., b, b, c - __ load_ptr_and_tag(0, G3_scratch, G4_scratch); // get c - __ store_ptr_and_tag(1, G3_scratch, G4_scratch); // put c at b + __ load_ptr( 0, G3_scratch); // get c + __ store_ptr(1, G3_scratch); // put c at b // stack: ..., b, c, c - __ store_ptr_and_tag(0, Otos_l1, Otos_l2); // put a at c + __ store_ptr(0, Otos_l1); // put a at c // stack: ..., b, c, a - __ push_ptr(Lscratch, G1_scratch); // push b - __ push_ptr(G3_scratch, G4_scratch); // push c + __ push_ptr(Lscratch); // push b + __ push_ptr(G3_scratch); // push c // stack: ..., b, c, a, b, c } @@ -1010,18 +998,18 @@ void TemplateTable::dup2_x1() { void TemplateTable::dup2_x2() { transition(vtos, vtos); // stack: ..., a, b, c, d - __ load_ptr_and_tag(1, Lscratch, G1_scratch); // get c - __ load_ptr_and_tag(3, Otos_l1, Otos_l2); // get a - __ store_ptr_and_tag(3, Lscratch, G1_scratch); // put c at 3 - __ store_ptr_and_tag(1, Otos_l1, Otos_l2); // put a at 1 + __ load_ptr( 1, Lscratch); // get c + __ load_ptr( 3, Otos_l1); // get a + __ store_ptr(3, Lscratch); // put c at 3 + __ store_ptr(1, Otos_l1); // put a at 1 // stack: ..., c, b, a, d - __ load_ptr_and_tag(2, G3_scratch, G4_scratch); // get b - __ load_ptr_and_tag(0, Otos_l1, Otos_l2); // get d - __ store_ptr_and_tag(0, G3_scratch, G4_scratch); // put b at 0 - __ store_ptr_and_tag(2, Otos_l1, Otos_l2); // put d at 2 + __ load_ptr( 2, G3_scratch); // get b + __ load_ptr( 0, Otos_l1); // get d + __ store_ptr(0, G3_scratch); // put b at 0 + __ store_ptr(2, Otos_l1); // put d at 2 // stack: ..., c, d, a, b - __ push_ptr(Lscratch, G1_scratch); // push c - __ push_ptr(Otos_l1, Otos_l2); // push d + __ push_ptr(Lscratch); // push c + __ push_ptr(Otos_l1); // push d // stack: ..., c, d, a, b, c, d } @@ -1029,10 +1017,10 @@ void TemplateTable::dup2_x2() { void TemplateTable::swap() { transition(vtos, vtos); // stack: ..., a, b - __ load_ptr_and_tag(1, G3_scratch, G4_scratch); // get a - __ load_ptr_and_tag(0, Otos_l1, Otos_l2); // get b - __ store_ptr_and_tag(0, G3_scratch, G4_scratch); // put b - __ store_ptr_and_tag(1, Otos_l1, Otos_l2); // put a + __ load_ptr( 1, G3_scratch); // get a + __ load_ptr( 0, Otos_l1); // get b + __ store_ptr(0, G3_scratch); // put b + __ store_ptr(1, Otos_l1); // put a // stack: ..., b, a } @@ -1045,9 +1033,9 @@ void TemplateTable::iop2(Operation op) { case sub: __ sub(O1, Otos_i, Otos_i); break; // %%%%% Mul may not exist: better to call .mul? case mul: __ smul(O1, Otos_i, Otos_i); break; - case _and: __ and3(O1, Otos_i, Otos_i); break; - case _or: __ or3(O1, Otos_i, Otos_i); break; - case _xor: __ xor3(O1, Otos_i, Otos_i); break; + case _and: __ and3(O1, Otos_i, Otos_i); break; + case _or: __ or3(O1, Otos_i, Otos_i); break; + case _xor: __ xor3(O1, Otos_i, Otos_i); break; case shl: __ sll(O1, Otos_i, Otos_i); break; case shr: __ sra(O1, Otos_i, Otos_i); break; case ushr: __ srl(O1, Otos_i, Otos_i); break; @@ -1061,17 +1049,17 @@ void TemplateTable::lop2(Operation op) { __ pop_l(O2); switch (op) { #ifdef _LP64 - case add: __ add(O2, Otos_l, Otos_l); break; - case sub: __ sub(O2, Otos_l, Otos_l); break; - case _and: __ and3( O2, Otos_l, Otos_l); break; - case _or: __ or3( O2, Otos_l, Otos_l); break; - case _xor: __ xor3( O2, Otos_l, Otos_l); break; + case add: __ add(O2, Otos_l, Otos_l); break; + case sub: __ sub(O2, Otos_l, Otos_l); break; + case _and: __ and3(O2, Otos_l, Otos_l); break; + case _or: __ or3(O2, Otos_l, Otos_l); break; + case _xor: __ xor3(O2, Otos_l, Otos_l); break; #else case add: __ addcc(O3, Otos_l2, Otos_l2); __ addc(O2, Otos_l1, Otos_l1); break; case sub: __ subcc(O3, Otos_l2, Otos_l2); __ subc(O2, Otos_l1, Otos_l1); break; - case _and: __ and3( O3, Otos_l2, Otos_l2); __ and3( O2, Otos_l1, Otos_l1); break; - case _or: __ or3( O3, Otos_l2, Otos_l2); __ or3( O2, Otos_l1, Otos_l1); break; - case _xor: __ xor3( O3, Otos_l2, Otos_l2); __ xor3( O2, Otos_l1, Otos_l1); break; + case _and: __ and3(O3, Otos_l2, Otos_l2); __ and3(O2, Otos_l1, Otos_l1); break; + case _or: __ or3(O3, Otos_l2, Otos_l2); __ or3(O2, Otos_l1, Otos_l1); break; + case _xor: __ xor3(O3, Otos_l2, Otos_l2); __ xor3(O2, Otos_l1, Otos_l1); break; #endif default: ShouldNotReachHere(); } @@ -1307,7 +1295,7 @@ void TemplateTable::iinc() { __ ldsb(Lbcp, 2, O2); // load constant __ access_local_int(G3_scratch, Otos_i); __ add(Otos_i, O2, Otos_i); - __ st(Otos_i, G3_scratch, Interpreter::value_offset_in_bytes()); // access_local_int puts E.A. in G3_scratch + __ st(Otos_i, G3_scratch, 0); // access_local_int puts E.A. in G3_scratch } @@ -1317,7 +1305,7 @@ void TemplateTable::wide_iinc() { __ get_2_byte_integer_at_bcp( 4, O2, O3, InterpreterMacroAssembler::Signed); __ access_local_int(G3_scratch, Otos_i); __ add(Otos_i, O3, Otos_i); - __ st(Otos_i, G3_scratch, Interpreter::value_offset_in_bytes()); // access_local_int puts E.A. in G3_scratch + __ st(Otos_i, G3_scratch, 0); // access_local_int puts E.A. in G3_scratch } @@ -1555,7 +1543,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) { // Bump Lbcp to target of JSR __ add(Lbcp, O1_disp, Lbcp); // Push returnAddress for "ret" on stack - __ push_ptr(Otos_i, G0); // push ptr sized thing plus 0 for tag. + __ push_ptr(Otos_i); // And away we go! __ dispatch_next(vtos); return; @@ -2754,7 +2742,7 @@ void TemplateTable::fast_xaccess(TosState state) { Register Rflags = G4_scratch; Register Rreceiver = Lscratch; - __ ld_ptr(Llocals, Interpreter::value_offset_in_bytes(), Rreceiver); + __ ld_ptr(Llocals, 0, Rreceiver); // access constant pool cache (is resolved) __ get_cache_and_index_at_bcp(Rcache, G4_scratch, 2); @@ -3696,7 +3684,7 @@ void TemplateTable::multianewarray() { transition(vtos, atos); // put ndims * wordSize into Lscratch __ ldub( Lbcp, 3, Lscratch); - __ sll( Lscratch, Interpreter::logStackElementSize(), Lscratch); + __ sll( Lscratch, Interpreter::logStackElementSize, Lscratch); // Lesp points past last_dim, so set to O1 to first_dim address __ add( Lesp, Lscratch, O1); call_VM(Otos_i, CAST_FROM_FN_PTR(address, InterpreterRuntime::multianewarray), O1); diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.cpp b/hotspot/src/cpu/x86/vm/assembler_x86.cpp index c3fed6bcd1b..4722210351d 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp @@ -7740,7 +7740,7 @@ void MacroAssembler::jump_to_method_handle_entry(Register mh_reg, Register temp_ Address MacroAssembler::argument_address(RegisterOrConstant arg_slot, int extra_slot_offset) { // cf. TemplateTable::prepare_invoke(), if (load_receiver). - int stackElementSize = Interpreter::stackElementSize(); + int stackElementSize = Interpreter::stackElementSize; int offset = Interpreter::expr_offset_in_bytes(extra_slot_offset+0); #ifdef ASSERT int offset1 = Interpreter::expr_offset_in_bytes(extra_slot_offset+1); diff --git a/hotspot/src/cpu/x86/vm/cppInterpreter_x86.hpp b/hotspot/src/cpu/x86/vm/cppInterpreter_x86.hpp index 66c169e9722..f8c7e41c62b 100644 --- a/hotspot/src/cpu/x86/vm/cppInterpreter_x86.hpp +++ b/hotspot/src/cpu/x86/vm/cppInterpreter_x86.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 @@ -28,6 +28,6 @@ // Size of interpreter code. Increase if too small. Interpreter will // fail with a guarantee ("not enough space for interpreter generation"); // if too small. - // Run with +PrintInterpreterSize to get the VM to print out the size. - // Max size with JVMTI and TaggedStackInterpreter + // Run with +PrintInterpreter to get the VM to print out the size. + // Max size with JVMTI const static int InterpreterCodeSize = 168 * 1024; diff --git a/hotspot/src/cpu/x86/vm/frame_x86.cpp b/hotspot/src/cpu/x86/vm/frame_x86.cpp index 01f49e3dba8..6d51fb1a217 100644 --- a/hotspot/src/cpu/x86/vm/frame_x86.cpp +++ b/hotspot/src/cpu/x86/vm/frame_x86.cpp @@ -502,7 +502,7 @@ bool frame::interpreter_frame_equals_unpacked_fp(intptr_t* fp) { // When unpacking an optimized frame the frame pointer is // adjusted with: int diff = (method->max_locals() - method->size_of_parameters()) * - Interpreter::stackElementWords(); + Interpreter::stackElementWords; return _fp == (fp - diff); } @@ -542,7 +542,7 @@ bool frame::is_interpreted_frame_valid(JavaThread* thread) const { // stack frames shouldn't be much larger than max_stack elements - if (fp() - sp() > 1024 + m->max_stack()*Interpreter::stackElementSize()) { + if (fp() - sp() > 1024 + m->max_stack()*Interpreter::stackElementSize) { return false; } @@ -594,7 +594,7 @@ BasicType frame::interpreter_frame_result(oop* oop_result, jvalue* value_result) #ifdef AMD64 // This is times two because we do a push(ltos) after pushing XMM0 // and that takes two interpreter stack slots. - tos_addr += 2 * Interpreter::stackElementWords(); + tos_addr += 2 * Interpreter::stackElementWords; #else tos_addr += 2; #endif // AMD64 diff --git a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp index 205e5d80de5..0513d52d1cc 100644 --- a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp @@ -265,89 +265,30 @@ void InterpreterMacroAssembler::d2ieee() { // Java Expression Stack -#ifdef ASSERT -void InterpreterMacroAssembler::verify_stack_tag(frame::Tag t) { - if (TaggedStackInterpreter) { - Label okay; - cmpptr(Address(rsp, wordSize), (int32_t)t); - jcc(Assembler::equal, okay); - // Also compare if the stack value is zero, then the tag might - // not have been set coming from deopt. - cmpptr(Address(rsp, 0), 0); - jcc(Assembler::equal, okay); - stop("Java Expression stack tag value is bad"); - bind(okay); - } -} -#endif // ASSERT - void InterpreterMacroAssembler::pop_ptr(Register r) { - debug_only(verify_stack_tag(frame::TagReference)); pop(r); - if (TaggedStackInterpreter) addptr(rsp, 1 * wordSize); -} - -void InterpreterMacroAssembler::pop_ptr(Register r, Register tag) { - pop(r); - // Tag may not be reference for jsr, can be returnAddress - if (TaggedStackInterpreter) pop(tag); } void InterpreterMacroAssembler::pop_i(Register r) { - debug_only(verify_stack_tag(frame::TagValue)); pop(r); - if (TaggedStackInterpreter) addptr(rsp, 1 * wordSize); } void InterpreterMacroAssembler::pop_l(Register lo, Register hi) { - debug_only(verify_stack_tag(frame::TagValue)); pop(lo); - if (TaggedStackInterpreter) addptr(rsp, 1 * wordSize); - debug_only(verify_stack_tag(frame::TagValue)); pop(hi); - if (TaggedStackInterpreter) addptr(rsp, 1 * wordSize); } void InterpreterMacroAssembler::pop_f() { - debug_only(verify_stack_tag(frame::TagValue)); fld_s(Address(rsp, 0)); addptr(rsp, 1 * wordSize); - if (TaggedStackInterpreter) addptr(rsp, 1 * wordSize); } void InterpreterMacroAssembler::pop_d() { - // Write double to stack contiguously and load into ST0 - pop_dtos_to_rsp(); fld_d(Address(rsp, 0)); addptr(rsp, 2 * wordSize); } -// Pop the top of the java expression stack to execution stack (which -// happens to be the same place). -void InterpreterMacroAssembler::pop_dtos_to_rsp() { - if (TaggedStackInterpreter) { - // Pop double value into scratch registers - debug_only(verify_stack_tag(frame::TagValue)); - pop(rax); - addptr(rsp, 1* wordSize); - debug_only(verify_stack_tag(frame::TagValue)); - pop(rdx); - addptr(rsp, 1* wordSize); - push(rdx); - push(rax); - } -} - -void InterpreterMacroAssembler::pop_ftos_to_rsp() { - if (TaggedStackInterpreter) { - debug_only(verify_stack_tag(frame::TagValue)); - pop(rax); - addptr(rsp, 1 * wordSize); - push(rax); // ftos is at rsp - } -} - void InterpreterMacroAssembler::pop(TosState state) { switch (state) { case atos: pop_ptr(rax); break; @@ -365,54 +306,28 @@ void InterpreterMacroAssembler::pop(TosState state) { } void InterpreterMacroAssembler::push_ptr(Register r) { - if (TaggedStackInterpreter) push(frame::TagReference); - push(r); -} - -void InterpreterMacroAssembler::push_ptr(Register r, Register tag) { - if (TaggedStackInterpreter) push(tag); // tag first push(r); } void InterpreterMacroAssembler::push_i(Register r) { - if (TaggedStackInterpreter) push(frame::TagValue); push(r); } void InterpreterMacroAssembler::push_l(Register lo, Register hi) { - if (TaggedStackInterpreter) push(frame::TagValue); push(hi); - if (TaggedStackInterpreter) push(frame::TagValue); push(lo); } void InterpreterMacroAssembler::push_f() { - if (TaggedStackInterpreter) push(frame::TagValue); // Do not schedule for no AGI! Never write beyond rsp! subptr(rsp, 1 * wordSize); fstp_s(Address(rsp, 0)); } void InterpreterMacroAssembler::push_d(Register r) { - if (TaggedStackInterpreter) { - // Double values are stored as: - // tag - // high - // tag - // low - push(frame::TagValue); - subptr(rsp, 3 * wordSize); - fstp_d(Address(rsp, 0)); - // move high word up to slot n-1 - movl(r, Address(rsp, 1*wordSize)); - movl(Address(rsp, 2*wordSize), r); - // move tag - movl(Address(rsp, 1*wordSize), frame::TagValue); - } else { - // Do not schedule for no AGI! Never write beyond rsp! - subptr(rsp, 2 * wordSize); - fstp_d(Address(rsp, 0)); - } + // Do not schedule for no AGI! Never write beyond rsp! + subptr(rsp, 2 * wordSize); + fstp_d(Address(rsp, 0)); } @@ -433,118 +348,15 @@ void InterpreterMacroAssembler::push(TosState state) { } -// Tagged stack helpers for swap and dup -void InterpreterMacroAssembler::load_ptr_and_tag(int n, Register val, - Register tag) { +// Helpers for swap and dup +void InterpreterMacroAssembler::load_ptr(int n, Register val) { movptr(val, Address(rsp, Interpreter::expr_offset_in_bytes(n))); - if (TaggedStackInterpreter) { - movptr(tag, Address(rsp, Interpreter::expr_tag_offset_in_bytes(n))); - } } -void InterpreterMacroAssembler::store_ptr_and_tag(int n, Register val, - Register tag) { +void InterpreterMacroAssembler::store_ptr(int n, Register val) { movptr(Address(rsp, Interpreter::expr_offset_in_bytes(n)), val); - if (TaggedStackInterpreter) { - movptr(Address(rsp, Interpreter::expr_tag_offset_in_bytes(n)), tag); - } } - -// Tagged local support -void InterpreterMacroAssembler::tag_local(frame::Tag tag, int n) { - if (TaggedStackInterpreter) { - if (tag == frame::TagCategory2) { - movptr(Address(rdi, Interpreter::local_tag_offset_in_bytes(n+1)), (int32_t)frame::TagValue); - movptr(Address(rdi, Interpreter::local_tag_offset_in_bytes(n)), (int32_t)frame::TagValue); - } else { - movptr(Address(rdi, Interpreter::local_tag_offset_in_bytes(n)), (int32_t)tag); - } - } -} - -void InterpreterMacroAssembler::tag_local(frame::Tag tag, Register idx) { - if (TaggedStackInterpreter) { - if (tag == frame::TagCategory2) { - movptr(Address(rdi, idx, Interpreter::stackElementScale(), - Interpreter::local_tag_offset_in_bytes(1)), (int32_t)frame::TagValue); - movptr(Address(rdi, idx, Interpreter::stackElementScale(), - Interpreter::local_tag_offset_in_bytes(0)), (int32_t)frame::TagValue); - } else { - movptr(Address(rdi, idx, Interpreter::stackElementScale(), - Interpreter::local_tag_offset_in_bytes(0)), (int32_t)tag); - } - } -} - -void InterpreterMacroAssembler::tag_local(Register tag, Register idx) { - if (TaggedStackInterpreter) { - // can only be TagValue or TagReference - movptr(Address(rdi, idx, Interpreter::stackElementScale(), - Interpreter::local_tag_offset_in_bytes(0)), tag); - } -} - - -void InterpreterMacroAssembler::tag_local(Register tag, int n) { - if (TaggedStackInterpreter) { - // can only be TagValue or TagReference - movptr(Address(rdi, Interpreter::local_tag_offset_in_bytes(n)), tag); - } -} - -#ifdef ASSERT -void InterpreterMacroAssembler::verify_local_tag(frame::Tag tag, int n) { - if (TaggedStackInterpreter) { - frame::Tag t = tag; - if (tag == frame::TagCategory2) { - Label nbl; - t = frame::TagValue; // change to what is stored in locals - cmpptr(Address(rdi, Interpreter::local_tag_offset_in_bytes(n+1)), (int32_t)t); - jcc(Assembler::equal, nbl); - stop("Local tag is bad for long/double"); - bind(nbl); - } - Label notBad; - cmpptr(Address(rdi, Interpreter::local_tag_offset_in_bytes(n)), (int32_t)t); - jcc(Assembler::equal, notBad); - // Also compare if the local value is zero, then the tag might - // not have been set coming from deopt. - cmpptr(Address(rdi, Interpreter::local_offset_in_bytes(n)), 0); - jcc(Assembler::equal, notBad); - stop("Local tag is bad"); - bind(notBad); - } -} - -void InterpreterMacroAssembler::verify_local_tag(frame::Tag tag, Register idx) { - if (TaggedStackInterpreter) { - frame::Tag t = tag; - if (tag == frame::TagCategory2) { - Label nbl; - t = frame::TagValue; // change to what is stored in locals - cmpptr(Address(rdi, idx, Interpreter::stackElementScale(), - Interpreter::local_tag_offset_in_bytes(1)), (int32_t)t); - jcc(Assembler::equal, nbl); - stop("Local tag is bad for long/double"); - bind(nbl); - } - Label notBad; - cmpl(Address(rdi, idx, Interpreter::stackElementScale(), - Interpreter::local_tag_offset_in_bytes(0)), (int32_t)t); - jcc(Assembler::equal, notBad); - // Also compare if the local value is zero, then the tag might - // not have been set coming from deopt. - cmpptr(Address(rdi, idx, Interpreter::stackElementScale(), - Interpreter::local_offset_in_bytes(0)), 0); - jcc(Assembler::equal, notBad); - stop("Local tag is bad"); - bind(notBad); - - } -} -#endif // ASSERT - void InterpreterMacroAssembler::super_call_VM_leaf(address entry_point) { MacroAssembler::call_VM_leaf_base(entry_point, 0); } diff --git a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.hpp b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.hpp index f7d17a9fd80..9bafe9fe110 100644 --- a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.hpp +++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2009 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 @@ -85,16 +85,12 @@ class InterpreterMacroAssembler: public MacroAssembler { void d2ieee(); // truncate dtos to 64bits void pop_ptr(Register r = rax); - void pop_ptr(Register r, Register tag); void pop_i(Register r = rax); void pop_l(Register lo = rax, Register hi = rdx); void pop_f(); void pop_d(); - void pop_ftos_to_rsp(); - void pop_dtos_to_rsp(); void push_ptr(Register r = rax); - void push_ptr(Register r, Register tag); void push_i(Register r = rax); void push_l(Register lo = rax, Register hi = rdx); void push_d(Register r = rax); @@ -112,33 +108,15 @@ class InterpreterMacroAssembler: public MacroAssembler { void pop(void* v ); // Add unimplemented ambiguous method void push(void* v ); // Add unimplemented ambiguous method - DEBUG_ONLY(void verify_stack_tag(frame::Tag t);) - -#endif // CC_INTERP - -#ifndef CC_INTERP - - void empty_expression_stack() { - movptr(rsp, Address(rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize)); - // NULL last_sp until next java call - movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); + void empty_expression_stack() { + movptr(rsp, Address(rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize)); + // NULL last_sp until next java call + movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); } - // Tagged stack helpers for swap and dup - void load_ptr_and_tag(int n, Register val, Register tag); - void store_ptr_and_tag(int n, Register val, Register tag); - - // Tagged Local support - - void tag_local(frame::Tag tag, int n); - void tag_local(Register tag, int n); - void tag_local(frame::Tag tag, Register idx); - void tag_local(Register tag, Register idx); - -#ifdef ASSERT - void verify_local_tag(frame::Tag tag, int n); - void verify_local_tag(frame::Tag tag, Register idx); -#endif // ASSERT + // Helpers for swap and dup + void load_ptr(int n, Register val); + void store_ptr(int n, Register val); // Super call_VM calls - correspond to MacroAssembler::call_VM(_leaf) calls void super_call_VM_leaf(address entry_point); diff --git a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp index 62acfa226fb..cfd46e5b96c 100644 --- a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp @@ -264,113 +264,51 @@ void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass, // Java Expression Stack -#ifdef ASSERT -// Verifies that the stack tag matches. Must be called before the stack -// value is popped off the stack. -void InterpreterMacroAssembler::verify_stack_tag(frame::Tag t) { - if (TaggedStackInterpreter) { - frame::Tag tag = t; - if (t == frame::TagCategory2) { - tag = frame::TagValue; - Label hokay; - cmpptr(Address(rsp, 3*wordSize), (int32_t)tag); - jcc(Assembler::equal, hokay); - stop("Java Expression stack tag high value is bad"); - bind(hokay); - } - Label okay; - cmpptr(Address(rsp, wordSize), (int32_t)tag); - jcc(Assembler::equal, okay); - // Also compare if the stack value is zero, then the tag might - // not have been set coming from deopt. - cmpptr(Address(rsp, 0), 0); - jcc(Assembler::equal, okay); - stop("Java Expression stack tag value is bad"); - bind(okay); - } -} -#endif // ASSERT - void InterpreterMacroAssembler::pop_ptr(Register r) { - debug_only(verify_stack_tag(frame::TagReference)); pop(r); - if (TaggedStackInterpreter) addptr(rsp, 1 * wordSize); -} - -void InterpreterMacroAssembler::pop_ptr(Register r, Register tag) { - pop(r); - if (TaggedStackInterpreter) pop(tag); } void InterpreterMacroAssembler::pop_i(Register r) { // XXX can't use pop currently, upper half non clean - debug_only(verify_stack_tag(frame::TagValue)); movl(r, Address(rsp, 0)); addptr(rsp, wordSize); - if (TaggedStackInterpreter) addptr(rsp, 1 * wordSize); } void InterpreterMacroAssembler::pop_l(Register r) { - debug_only(verify_stack_tag(frame::TagCategory2)); movq(r, Address(rsp, 0)); - addptr(rsp, 2 * Interpreter::stackElementSize()); + addptr(rsp, 2 * Interpreter::stackElementSize); } void InterpreterMacroAssembler::pop_f(XMMRegister r) { - debug_only(verify_stack_tag(frame::TagValue)); movflt(r, Address(rsp, 0)); addptr(rsp, wordSize); - if (TaggedStackInterpreter) addptr(rsp, 1 * wordSize); } void InterpreterMacroAssembler::pop_d(XMMRegister r) { - debug_only(verify_stack_tag(frame::TagCategory2)); movdbl(r, Address(rsp, 0)); - addptr(rsp, 2 * Interpreter::stackElementSize()); + addptr(rsp, 2 * Interpreter::stackElementSize); } void InterpreterMacroAssembler::push_ptr(Register r) { - if (TaggedStackInterpreter) push(frame::TagReference); - push(r); -} - -void InterpreterMacroAssembler::push_ptr(Register r, Register tag) { - if (TaggedStackInterpreter) push(tag); push(r); } void InterpreterMacroAssembler::push_i(Register r) { - if (TaggedStackInterpreter) push(frame::TagValue); push(r); } void InterpreterMacroAssembler::push_l(Register r) { - if (TaggedStackInterpreter) { - push(frame::TagValue); - subptr(rsp, 1 * wordSize); - push(frame::TagValue); - subptr(rsp, 1 * wordSize); - } else { - subptr(rsp, 2 * wordSize); - } + subptr(rsp, 2 * wordSize); movq(Address(rsp, 0), r); } void InterpreterMacroAssembler::push_f(XMMRegister r) { - if (TaggedStackInterpreter) push(frame::TagValue); subptr(rsp, wordSize); movflt(Address(rsp, 0), r); } void InterpreterMacroAssembler::push_d(XMMRegister r) { - if (TaggedStackInterpreter) { - push(frame::TagValue); - subptr(rsp, 1 * wordSize); - push(frame::TagValue); - subptr(rsp, 1 * wordSize); - } else { - subptr(rsp, 2 * wordSize); - } + subptr(rsp, 2 * wordSize); movdbl(Address(rsp, 0), r); } @@ -407,118 +345,16 @@ void InterpreterMacroAssembler::push(TosState state) { } - - -// Tagged stack helpers for swap and dup -void InterpreterMacroAssembler::load_ptr_and_tag(int n, Register val, - Register tag) { +// Helpers for swap and dup +void InterpreterMacroAssembler::load_ptr(int n, Register val) { movptr(val, Address(rsp, Interpreter::expr_offset_in_bytes(n))); - if (TaggedStackInterpreter) { - movptr(tag, Address(rsp, Interpreter::expr_tag_offset_in_bytes(n))); - } } -void InterpreterMacroAssembler::store_ptr_and_tag(int n, Register val, - Register tag) { +void InterpreterMacroAssembler::store_ptr(int n, Register val) { movptr(Address(rsp, Interpreter::expr_offset_in_bytes(n)), val); - if (TaggedStackInterpreter) { - movptr(Address(rsp, Interpreter::expr_tag_offset_in_bytes(n)), tag); - } } -// Tagged local support -void InterpreterMacroAssembler::tag_local(frame::Tag tag, int n) { - if (TaggedStackInterpreter) { - if (tag == frame::TagCategory2) { - movptr(Address(r14, Interpreter::local_tag_offset_in_bytes(n+1)), - (int32_t)frame::TagValue); - movptr(Address(r14, Interpreter::local_tag_offset_in_bytes(n)), - (int32_t)frame::TagValue); - } else { - movptr(Address(r14, Interpreter::local_tag_offset_in_bytes(n)), (int32_t)tag); - } - } -} - -void InterpreterMacroAssembler::tag_local(frame::Tag tag, Register idx) { - if (TaggedStackInterpreter) { - if (tag == frame::TagCategory2) { - movptr(Address(r14, idx, Address::times_8, - Interpreter::local_tag_offset_in_bytes(1)), (int32_t)frame::TagValue); - movptr(Address(r14, idx, Address::times_8, - Interpreter::local_tag_offset_in_bytes(0)), (int32_t)frame::TagValue); - } else { - movptr(Address(r14, idx, Address::times_8, Interpreter::local_tag_offset_in_bytes(0)), - (int32_t)tag); - } - } -} - -void InterpreterMacroAssembler::tag_local(Register tag, Register idx) { - if (TaggedStackInterpreter) { - // can only be TagValue or TagReference - movptr(Address(r14, idx, Address::times_8, Interpreter::local_tag_offset_in_bytes(0)), tag); - } -} - - -void InterpreterMacroAssembler::tag_local(Register tag, int n) { - if (TaggedStackInterpreter) { - // can only be TagValue or TagReference - movptr(Address(r14, Interpreter::local_tag_offset_in_bytes(n)), tag); - } -} - -#ifdef ASSERT -void InterpreterMacroAssembler::verify_local_tag(frame::Tag tag, int n) { - if (TaggedStackInterpreter) { - frame::Tag t = tag; - if (tag == frame::TagCategory2) { - Label nbl; - t = frame::TagValue; // change to what is stored in locals - cmpptr(Address(r14, Interpreter::local_tag_offset_in_bytes(n+1)), (int32_t)t); - jcc(Assembler::equal, nbl); - stop("Local tag is bad for long/double"); - bind(nbl); - } - Label notBad; - cmpq(Address(r14, Interpreter::local_tag_offset_in_bytes(n)), (int32_t)t); - jcc(Assembler::equal, notBad); - // Also compare if the local value is zero, then the tag might - // not have been set coming from deopt. - cmpptr(Address(r14, Interpreter::local_offset_in_bytes(n)), 0); - jcc(Assembler::equal, notBad); - stop("Local tag is bad"); - bind(notBad); - } -} - -void InterpreterMacroAssembler::verify_local_tag(frame::Tag tag, Register idx) { - if (TaggedStackInterpreter) { - frame::Tag t = tag; - if (tag == frame::TagCategory2) { - Label nbl; - t = frame::TagValue; // change to what is stored in locals - cmpptr(Address(r14, idx, Address::times_8, Interpreter::local_tag_offset_in_bytes(1)), (int32_t)t); - jcc(Assembler::equal, nbl); - stop("Local tag is bad for long/double"); - bind(nbl); - } - Label notBad; - cmpptr(Address(r14, idx, Address::times_8, Interpreter::local_tag_offset_in_bytes(0)), (int32_t)t); - jcc(Assembler::equal, notBad); - // Also compare if the local value is zero, then the tag might - // not have been set coming from deopt. - cmpptr(Address(r14, idx, Address::times_8, Interpreter::local_offset_in_bytes(0)), 0); - jcc(Assembler::equal, notBad); - stop("Local tag is bad"); - bind(notBad); - } -} -#endif // ASSERT - - void InterpreterMacroAssembler::super_call_VM_leaf(address entry_point) { MacroAssembler::call_VM_leaf_base(entry_point, 0); } diff --git a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp index fd935f1ed8b..d0408b274e4 100644 --- a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp +++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2003-2009 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 @@ -120,38 +120,16 @@ class InterpreterMacroAssembler: public MacroAssembler { void pop(TosState state); // transition vtos -> state void push(TosState state); // transition state -> vtos - // Tagged stack support, pop and push both tag and value. - void pop_ptr(Register r, Register tag); - void push_ptr(Register r, Register tag); -#endif // CC_INTERP - - DEBUG_ONLY(void verify_stack_tag(frame::Tag t);) - -#ifndef CC_INTERP - - // Tagged stack helpers for swap and dup - void load_ptr_and_tag(int n, Register val, Register tag); - void store_ptr_and_tag(int n, Register val, Register tag); - - // Tagged Local support - void tag_local(frame::Tag tag, int n); - void tag_local(Register tag, int n); - void tag_local(frame::Tag tag, Register idx); - void tag_local(Register tag, Register idx); - -#ifdef ASSERT - void verify_local_tag(frame::Tag tag, int n); - void verify_local_tag(frame::Tag tag, Register idx); -#endif // ASSERT - - - void empty_expression_stack() - { + void empty_expression_stack() { movptr(rsp, Address(rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize)); // NULL last_sp until next java call movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD); } + // Helpers for swap and dup + void load_ptr(int n, Register val); + void store_ptr(int n, Register val); + // Super call_VM calls - correspond to MacroAssembler::call_VM(_leaf) calls void super_call_VM_leaf(address entry_point); void super_call_VM_leaf(address entry_point, Register arg_1); diff --git a/hotspot/src/cpu/x86/vm/interpreterRT_x86_32.cpp b/hotspot/src/cpu/x86/vm/interpreterRT_x86_32.cpp index 2faa99b294c..a65d5c9a4f9 100644 --- a/hotspot/src/cpu/x86/vm/interpreterRT_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/interpreterRT_x86_32.cpp @@ -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 @@ -86,33 +86,23 @@ class SlowSignatureHandler: public NativeSignatureIterator { address _from; intptr_t* _to; -#ifdef ASSERT - void verify_tag(frame::Tag t) { - assert(!TaggedStackInterpreter || - *(intptr_t*)(_from+Interpreter::local_tag_offset_in_bytes(0)) == t, "wrong tag"); - } -#endif // ASSERT - virtual void pass_int() { *_to++ = *(jint *)(_from+Interpreter::local_offset_in_bytes(0)); - debug_only(verify_tag(frame::TagValue)); - _from -= Interpreter::stackElementSize(); + _from -= Interpreter::stackElementSize; } virtual void pass_long() { _to[0] = *(intptr_t*)(_from+Interpreter::local_offset_in_bytes(1)); _to[1] = *(intptr_t*)(_from+Interpreter::local_offset_in_bytes(0)); - debug_only(verify_tag(frame::TagValue)); _to += 2; - _from -= 2*Interpreter::stackElementSize(); + _from -= 2*Interpreter::stackElementSize; } virtual void pass_object() { // pass address of from intptr_t from_addr = (intptr_t)(_from + Interpreter::local_offset_in_bytes(0)); *_to++ = (*(intptr_t*)from_addr == 0) ? NULL_WORD : from_addr; - debug_only(verify_tag(frame::TagReference)); - _from -= Interpreter::stackElementSize(); + _from -= Interpreter::stackElementSize; } public: diff --git a/hotspot/src/cpu/x86/vm/interpreterRT_x86_64.cpp b/hotspot/src/cpu/x86/vm/interpreterRT_x86_64.cpp index 6975fdc2699..134d96917b8 100644 --- a/hotspot/src/cpu/x86/vm/interpreterRT_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/interpreterRT_x86_64.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2003-2009 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 @@ -293,18 +293,10 @@ class SlowSignatureHandler intptr_t* _fp_identifiers; unsigned int _num_args; -#ifdef ASSERT - void verify_tag(frame::Tag t) { - assert(!TaggedStackInterpreter || - *(intptr_t*)(_from+Interpreter::local_tag_offset_in_bytes(0)) == t, "wrong tag"); - } -#endif // ASSERT - virtual void pass_int() { jint from_obj = *(jint *)(_from+Interpreter::local_offset_in_bytes(0)); - debug_only(verify_tag(frame::TagValue)); - _from -= Interpreter::stackElementSize(); + _from -= Interpreter::stackElementSize; if (_num_args < Argument::n_int_register_parameters_c-1) { *_reg_args++ = from_obj; @@ -317,8 +309,7 @@ class SlowSignatureHandler virtual void pass_long() { intptr_t from_obj = *(intptr_t*)(_from+Interpreter::local_offset_in_bytes(1)); - debug_only(verify_tag(frame::TagValue)); - _from -= 2*Interpreter::stackElementSize(); + _from -= 2*Interpreter::stackElementSize; if (_num_args < Argument::n_int_register_parameters_c-1) { *_reg_args++ = from_obj; @@ -331,8 +322,7 @@ class SlowSignatureHandler virtual void pass_object() { intptr_t *from_addr = (intptr_t*)(_from + Interpreter::local_offset_in_bytes(0)); - debug_only(verify_tag(frame::TagReference)); - _from -= Interpreter::stackElementSize(); + _from -= Interpreter::stackElementSize; if (_num_args < Argument::n_int_register_parameters_c-1) { *_reg_args++ = (*from_addr == 0) ? NULL : (intptr_t) from_addr; _num_args++; @@ -344,8 +334,7 @@ class SlowSignatureHandler virtual void pass_float() { jint from_obj = *(jint *)(_from+Interpreter::local_offset_in_bytes(0)); - debug_only(verify_tag(frame::TagValue)); - _from -= Interpreter::stackElementSize(); + _from -= Interpreter::stackElementSize; if (_num_args < Argument::n_float_register_parameters_c-1) { *_reg_args++ = from_obj; @@ -359,8 +348,7 @@ class SlowSignatureHandler virtual void pass_double() { intptr_t from_obj = *(intptr_t*)(_from+Interpreter::local_offset_in_bytes(1)); - debug_only(verify_tag(frame::TagValue)); - _from -= 2*Interpreter::stackElementSize(); + _from -= 2*Interpreter::stackElementSize; if (_num_args < Argument::n_float_register_parameters_c-1) { *_reg_args++ = from_obj; @@ -397,18 +385,10 @@ class SlowSignatureHandler unsigned int _num_int_args; unsigned int _num_fp_args; -#ifdef ASSERT - void verify_tag(frame::Tag t) { - assert(!TaggedStackInterpreter || - *(intptr_t*)(_from+Interpreter::local_tag_offset_in_bytes(0)) == t, "wrong tag"); - } -#endif // ASSERT - virtual void pass_int() { jint from_obj = *(jint *)(_from+Interpreter::local_offset_in_bytes(0)); - debug_only(verify_tag(frame::TagValue)); - _from -= Interpreter::stackElementSize(); + _from -= Interpreter::stackElementSize; if (_num_int_args < Argument::n_int_register_parameters_c-1) { *_int_args++ = from_obj; @@ -421,8 +401,7 @@ class SlowSignatureHandler virtual void pass_long() { intptr_t from_obj = *(intptr_t*)(_from+Interpreter::local_offset_in_bytes(1)); - debug_only(verify_tag(frame::TagValue)); - _from -= 2*Interpreter::stackElementSize(); + _from -= 2*Interpreter::stackElementSize; if (_num_int_args < Argument::n_int_register_parameters_c-1) { *_int_args++ = from_obj; @@ -435,8 +414,7 @@ class SlowSignatureHandler virtual void pass_object() { intptr_t *from_addr = (intptr_t*)(_from + Interpreter::local_offset_in_bytes(0)); - debug_only(verify_tag(frame::TagReference)); - _from -= Interpreter::stackElementSize(); + _from -= Interpreter::stackElementSize; if (_num_int_args < Argument::n_int_register_parameters_c-1) { *_int_args++ = (*from_addr == 0) ? NULL : (intptr_t)from_addr; @@ -449,8 +427,7 @@ class SlowSignatureHandler virtual void pass_float() { jint from_obj = *(jint*)(_from+Interpreter::local_offset_in_bytes(0)); - debug_only(verify_tag(frame::TagValue)); - _from -= Interpreter::stackElementSize(); + _from -= Interpreter::stackElementSize; if (_num_fp_args < Argument::n_float_register_parameters_c) { *_fp_args++ = from_obj; @@ -463,7 +440,7 @@ class SlowSignatureHandler virtual void pass_double() { intptr_t from_obj = *(intptr_t*)(_from+Interpreter::local_offset_in_bytes(1)); - _from -= 2*Interpreter::stackElementSize(); + _from -= 2*Interpreter::stackElementSize; if (_num_fp_args < Argument::n_float_register_parameters_c) { *_fp_args++ = from_obj; diff --git a/hotspot/src/cpu/x86/vm/interpreter_x86.hpp b/hotspot/src/cpu/x86/vm/interpreter_x86.hpp index 04db7fdf7b3..3633db50204 100644 --- a/hotspot/src/cpu/x86/vm/interpreter_x86.hpp +++ b/hotspot/src/cpu/x86/vm/interpreter_x86.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 @@ -31,39 +31,16 @@ // the fpu stack. static const int return_sentinel; - - static Address::ScaleFactor stackElementScale() { - return TaggedStackInterpreter? Address::times_8 : Address::times_4; - } + static Address::ScaleFactor stackElementScale() { return Address::times_4; } // Offset from rsp (which points to the last stack element) - static int expr_offset_in_bytes(int i) { return stackElementSize()*i ; } - static int expr_tag_offset_in_bytes(int i) { - assert(TaggedStackInterpreter, "should not call this"); - return expr_offset_in_bytes(i) + wordSize; - } - - // Support for Tagged Stacks + static int expr_offset_in_bytes(int i) { return stackElementSize * i; } // Stack index relative to tos (which points at value) - static int expr_index_at(int i) { - return stackElementWords() * i; - } - - static int expr_tag_index_at(int i) { - assert(TaggedStackInterpreter, "should not call this"); - // tag is one word above java stack element - return stackElementWords() * i + 1; - } + static int expr_index_at(int i) { return stackElementWords * i; } // Already negated by c++ interpreter - static int local_index_at(int i) { - assert(i<=0, "local direction already negated"); - return stackElementWords() * i + (value_offset_in_bytes()/wordSize); - } - - static int local_tag_index_at(int i) { - assert(i<=0, "local direction already negated"); - assert(TaggedStackInterpreter, "should not call this"); - return stackElementWords() * i + (tag_offset_in_bytes()/wordSize); + static int local_index_at(int i) { + assert(i <= 0, "local direction already negated"); + return stackElementWords * i; } diff --git a/hotspot/src/cpu/x86/vm/interpreter_x86_32.cpp b/hotspot/src/cpu/x86/vm/interpreter_x86_32.cpp index 2db290c431b..12470e791f2 100644 --- a/hotspot/src/cpu/x86/vm/interpreter_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/interpreter_x86_32.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2009 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 @@ -131,14 +131,7 @@ address InterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKin // java methods. Interpreter::method_kind(...) will select // this entry point for the corresponding methods in JDK 1.3. // get argument - if (TaggedStackInterpreter) { - __ pushl(Address(rsp, 3*wordSize)); // push hi (and note rsp -= wordSize) - __ pushl(Address(rsp, 2*wordSize)); // push lo - __ fld_d(Address(rsp, 0)); // get double in ST0 - __ addptr(rsp, 2*wordSize); - } else { - __ fld_d(Address(rsp, 1*wordSize)); - } + __ fld_d(Address(rsp, 1*wordSize)); switch (kind) { case Interpreter::java_lang_math_sin : __ trigfunc('s'); diff --git a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp index a99296f73d4..2c47d50dbfc 100644 --- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp +++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp @@ -500,7 +500,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan #ifndef _LP64 if (arg_slots == 2) { __ movl(rdx_temp, prim_value_addr.plus_disp(wordSize)); - __ movl(Address(rax_argslot, Interpreter::stackElementSize()), rdx_temp); + __ movl(Address(rax_argslot, Interpreter::stackElementSize), rdx_temp); } #endif //_LP64 } @@ -596,7 +596,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan __ lea(rax_argslot, __ argument_address(rax_argslot, 1)); remove_arg_slots(_masm, -stack_move_unit(), rax_argslot, rbx_temp, rdx_temp); - vmarg = Address(rax_argslot, -Interpreter::stackElementSize()); + vmarg = Address(rax_argslot, -Interpreter::stackElementSize); __ movl(rdx_temp, vmarg); } break; @@ -665,8 +665,8 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan __ lea(rax_argslot, __ argument_address(rax_argslot, 1)); insert_arg_slots(_masm, stack_move_unit(), _INSERT_INT_MASK, rax_argslot, rbx_temp, rdx_temp); - Address vmarg1(rax_argslot, -Interpreter::stackElementSize()); - Address vmarg2 = vmarg1.plus_disp(Interpreter::stackElementSize()); + Address vmarg1(rax_argslot, -Interpreter::stackElementSize); + Address vmarg2 = vmarg1.plus_disp(Interpreter::stackElementSize); switch (ek) { case _adapter_opt_i2l: @@ -718,7 +718,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan insert_arg_slots(_masm, stack_move_unit(), _INSERT_INT_MASK, rax_argslot, rbx_temp, rdx_temp); } - Address vmarg(rax_argslot, -Interpreter::stackElementSize()); + Address vmarg(rax_argslot, -Interpreter::stackElementSize); #ifdef _LP64 if (ek == _adapter_opt_f2d) { @@ -1016,7 +1016,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan // Array length checks out. Now insert any required stack slots. if (length_constant == -1) { // Form a pointer to the end of the affected region. - __ lea(rdx_argslot_limit, Address(rax_argslot, Interpreter::stackElementSize())); + __ lea(rdx_argslot_limit, Address(rax_argslot, Interpreter::stackElementSize)); // 'stack_move' is negative number of words to insert Register rdi_stack_move = rdi; __ movl2ptr(rdi_stack_move, rcx_amh_conversion); @@ -1054,7 +1054,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan __ movptr(rbx_temp, Address(rsi_source, 0)); __ movptr(Address(rax_argslot, 0), rbx_temp); __ addptr(rsi_source, type2aelembytes(elem_type)); - __ addptr(rax_argslot, Interpreter::stackElementSize()); + __ addptr(rax_argslot, Interpreter::stackElementSize); __ cmpptr(rax_argslot, rdx_argslot_limit); __ jccb(Assembler::less, loop); } else if (length_constant == 0) { @@ -1067,7 +1067,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan __ movptr(rbx_temp, Address(rsi_array, elem_offset)); __ movptr(Address(rax_argslot, slot_offset), rbx_temp); elem_offset += type2aelembytes(elem_type); - slot_offset += Interpreter::stackElementSize(); + slot_offset += Interpreter::stackElementSize; } } diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp index 886aa61214c..b77204baa91 100644 --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp @@ -503,34 +503,9 @@ static void patch_callers_callsite(MacroAssembler *masm) { } -// Helper function to put tags in interpreter stack. -static void tag_stack(MacroAssembler *masm, const BasicType sig, int st_off) { - if (TaggedStackInterpreter) { - int tag_offset = st_off + Interpreter::expr_tag_offset_in_bytes(0); - if (sig == T_OBJECT || sig == T_ARRAY) { - __ movptr(Address(rsp, tag_offset), frame::TagReference); - } else if (sig == T_LONG || sig == T_DOUBLE) { - int next_tag_offset = st_off + Interpreter::expr_tag_offset_in_bytes(1); - __ movptr(Address(rsp, next_tag_offset), frame::TagValue); - __ movptr(Address(rsp, tag_offset), frame::TagValue); - } else { - __ movptr(Address(rsp, tag_offset), frame::TagValue); - } - } -} - -// Double and long values with Tagged stacks are not contiguous. static void move_c2i_double(MacroAssembler *masm, XMMRegister r, int st_off) { - int next_off = st_off - Interpreter::stackElementSize(); - if (TaggedStackInterpreter) { - __ movdbl(Address(rsp, next_off), r); - // Move top half up and put tag in the middle. - __ movl(rdi, Address(rsp, next_off+wordSize)); - __ movl(Address(rsp, st_off), rdi); - tag_stack(masm, T_DOUBLE, next_off); - } else { - __ movdbl(Address(rsp, next_off), r); - } + int next_off = st_off - Interpreter::stackElementSize; + __ movdbl(Address(rsp, next_off), r); } static void gen_c2i_adapter(MacroAssembler *masm, @@ -560,7 +535,7 @@ static void gen_c2i_adapter(MacroAssembler *masm, // Since all args are passed on the stack, total_args_passed * interpreter_ // stack_element_size is the // space we need. - int extraspace = total_args_passed * Interpreter::stackElementSize(); + int extraspace = total_args_passed * Interpreter::stackElementSize; // Get return address __ pop(rax); @@ -578,8 +553,8 @@ static void gen_c2i_adapter(MacroAssembler *masm, } // st_off points to lowest address on stack. - int st_off = ((total_args_passed - 1) - i) * Interpreter::stackElementSize(); - int next_off = st_off - Interpreter::stackElementSize(); + int st_off = ((total_args_passed - 1) - i) * Interpreter::stackElementSize; + int next_off = st_off - Interpreter::stackElementSize; // Say 4 args: // i st_off @@ -601,7 +576,6 @@ static void gen_c2i_adapter(MacroAssembler *masm, if (!r_2->is_valid()) { __ movl(rdi, Address(rsp, ld_off)); __ movptr(Address(rsp, st_off), rdi); - tag_stack(masm, sig_bt[i], st_off); } else { // ld_off == LSW, ld_off+VMRegImpl::stack_slot_size == MSW @@ -619,13 +593,11 @@ static void gen_c2i_adapter(MacroAssembler *masm, __ movptr(Address(rsp, st_off), rax); #endif /* ASSERT */ #endif // _LP64 - tag_stack(masm, sig_bt[i], next_off); } } else if (r_1->is_Register()) { Register r = r_1->as_Register(); if (!r_2->is_valid()) { __ movl(Address(rsp, st_off), r); - tag_stack(masm, sig_bt[i], st_off); } else { // long/double in gpr NOT_LP64(ShouldNotReachHere()); @@ -639,17 +611,14 @@ static void gen_c2i_adapter(MacroAssembler *masm, __ movptr(Address(rsp, st_off), rax); #endif /* ASSERT */ __ movptr(Address(rsp, next_off), r); - tag_stack(masm, sig_bt[i], next_off); } else { __ movptr(Address(rsp, st_off), r); - tag_stack(masm, sig_bt[i], st_off); } } } else { assert(r_1->is_XMMRegister(), ""); if (!r_2->is_valid()) { __ movflt(Address(rsp, st_off), r_1->as_XMMRegister()); - tag_stack(masm, sig_bt[i], st_off); } else { assert(sig_bt[i] == T_DOUBLE || sig_bt[i] == T_LONG, "wrong type"); move_c2i_double(masm, r_1->as_XMMRegister(), st_off); @@ -665,20 +634,9 @@ static void gen_c2i_adapter(MacroAssembler *masm, } -// For tagged stacks, double or long value aren't contiguous on the stack -// so get them contiguous for the xmm load static void move_i2c_double(MacroAssembler *masm, XMMRegister r, Register saved_sp, int ld_off) { - int next_val_off = ld_off - Interpreter::stackElementSize(); - if (TaggedStackInterpreter) { - // use tag slot temporarily for MSW - __ movptr(rsi, Address(saved_sp, ld_off)); - __ movptr(Address(saved_sp, next_val_off+wordSize), rsi); - __ movdbl(r, Address(saved_sp, next_val_off)); - // restore tag - __ movptr(Address(saved_sp, next_val_off+wordSize), frame::TagValue); - } else { - __ movdbl(r, Address(saved_sp, next_val_off)); - } + int next_val_off = ld_off - Interpreter::stackElementSize; + __ movdbl(r, Address(saved_sp, next_val_off)); } static void gen_i2c_adapter(MacroAssembler *masm, @@ -797,9 +755,9 @@ static void gen_i2c_adapter(MacroAssembler *masm, assert(!regs[i].second()->is_valid() || regs[i].first()->next() == regs[i].second(), "scrambled load targets?"); // Load in argument order going down. - int ld_off = (total_args_passed - i)*Interpreter::stackElementSize() + Interpreter::value_offset_in_bytes(); + int ld_off = (total_args_passed - i) * Interpreter::stackElementSize; // Point to interpreter value (vs. tag) - int next_off = ld_off - Interpreter::stackElementSize(); + int next_off = ld_off - Interpreter::stackElementSize; // // // @@ -2322,7 +2280,7 @@ nmethod *SharedRuntime::generate_dtrace_nmethod( // this function returns the adjust size (in number of words) to a c2i adapter // activation for use during deoptimization int Deoptimization::last_frame_adjust(int callee_parameters, int callee_locals ) { - return (callee_locals - callee_parameters) * Interpreter::stackElementWords(); + return (callee_locals - callee_parameters) * Interpreter::stackElementWords; } diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp index 9fa01e4bdef..c6a1bd91477 100644 --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp @@ -452,22 +452,6 @@ static void patch_callers_callsite(MacroAssembler *masm) { __ bind(L); } -// Helper function to put tags in interpreter stack. -static void tag_stack(MacroAssembler *masm, const BasicType sig, int st_off) { - if (TaggedStackInterpreter) { - int tag_offset = st_off + Interpreter::expr_tag_offset_in_bytes(0); - if (sig == T_OBJECT || sig == T_ARRAY) { - __ movptr(Address(rsp, tag_offset), (int32_t) frame::TagReference); - } else if (sig == T_LONG || sig == T_DOUBLE) { - int next_tag_offset = st_off + Interpreter::expr_tag_offset_in_bytes(1); - __ movptr(Address(rsp, next_tag_offset), (int32_t) frame::TagValue); - __ movptr(Address(rsp, tag_offset), (int32_t) frame::TagValue); - } else { - __ movptr(Address(rsp, tag_offset), (int32_t) frame::TagValue); - } - } -} - static void gen_c2i_adapter(MacroAssembler *masm, int total_args_passed, @@ -489,7 +473,7 @@ static void gen_c2i_adapter(MacroAssembler *masm, // we also account for the return address location since // we store it first rather than hold it in rax across all the shuffling - int extraspace = (total_args_passed * Interpreter::stackElementSize()) + wordSize; + int extraspace = (total_args_passed * Interpreter::stackElementSize) + wordSize; // stack is aligned, keep it that way extraspace = round_to(extraspace, 2*wordSize); @@ -513,9 +497,8 @@ static void gen_c2i_adapter(MacroAssembler *masm, } // offset to start parameters - int st_off = (total_args_passed - i) * Interpreter::stackElementSize() + - Interpreter::value_offset_in_bytes(); - int next_off = st_off - Interpreter::stackElementSize(); + int st_off = (total_args_passed - i) * Interpreter::stackElementSize; + int next_off = st_off - Interpreter::stackElementSize; // Say 4 args: // i st_off @@ -543,7 +526,6 @@ static void gen_c2i_adapter(MacroAssembler *masm, // sign extend?? __ movl(rax, Address(rsp, ld_off)); __ movptr(Address(rsp, st_off), rax); - tag_stack(masm, sig_bt[i], st_off); } else { @@ -560,10 +542,8 @@ static void gen_c2i_adapter(MacroAssembler *masm, __ mov64(rax, CONST64(0xdeadffffdeadaaaa)); __ movptr(Address(rsp, st_off), rax); #endif /* ASSERT */ - tag_stack(masm, sig_bt[i], next_off); } else { __ movq(Address(rsp, st_off), rax); - tag_stack(masm, sig_bt[i], st_off); } } } else if (r_1->is_Register()) { @@ -572,7 +552,6 @@ static void gen_c2i_adapter(MacroAssembler *masm, // must be only an int (or less ) so move only 32bits to slot // why not sign extend?? __ movl(Address(rsp, st_off), r); - tag_stack(masm, sig_bt[i], st_off); } else { // Two VMREgs|OptoRegs can be T_OBJECT, T_ADDRESS, T_DOUBLE, T_LONG // T_DOUBLE and T_LONG use two slots in the interpreter @@ -584,10 +563,8 @@ static void gen_c2i_adapter(MacroAssembler *masm, __ movptr(Address(rsp, st_off), rax); #endif /* ASSERT */ __ movq(Address(rsp, next_off), r); - tag_stack(masm, sig_bt[i], next_off); } else { __ movptr(Address(rsp, st_off), r); - tag_stack(masm, sig_bt[i], st_off); } } } else { @@ -595,7 +572,6 @@ static void gen_c2i_adapter(MacroAssembler *masm, if (!r_2->is_valid()) { // only a float use just part of the slot __ movflt(Address(rsp, st_off), r_1->as_XMMRegister()); - tag_stack(masm, sig_bt[i], st_off); } else { #ifdef ASSERT // Overwrite the unused slot with known junk @@ -603,7 +579,6 @@ static void gen_c2i_adapter(MacroAssembler *masm, __ movptr(Address(rsp, st_off), rax); #endif /* ASSERT */ __ movdbl(Address(rsp, next_off), r_1->as_XMMRegister()); - tag_stack(masm, sig_bt[i], next_off); } } } @@ -688,9 +663,9 @@ static void gen_i2c_adapter(MacroAssembler *masm, assert(!regs[i].second()->is_valid() || regs[i].first()->next() == regs[i].second(), "scrambled load targets?"); // Load in argument order going down. - int ld_off = (total_args_passed - i)*Interpreter::stackElementSize() + Interpreter::value_offset_in_bytes(); + int ld_off = (total_args_passed - i)*Interpreter::stackElementSize; // Point to interpreter value (vs. tag) - int next_off = ld_off - Interpreter::stackElementSize(); + int next_off = ld_off - Interpreter::stackElementSize; // // // @@ -2535,7 +2510,7 @@ nmethod *SharedRuntime::generate_dtrace_nmethod(MacroAssembler *masm, // this function returns the adjust size (in number of words) to a c2i adapter // activation for use during deoptimization int Deoptimization::last_frame_adjust(int callee_parameters, int callee_locals ) { - return (callee_locals - callee_parameters) * Interpreter::stackElementWords(); + return (callee_locals - callee_parameters) * Interpreter::stackElementWords; } diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp index ccb8bf0a5b1..99865e668f6 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp @@ -139,7 +139,7 @@ class StubGenerator: public StubCodeGenerator { // stub code __ enter(); __ movptr(rcx, parameter_size); // parameter counter - __ shlptr(rcx, Interpreter::logStackElementSize()); // convert parameter count to bytes + __ shlptr(rcx, Interpreter::logStackElementSize); // convert parameter count to bytes __ addptr(rcx, locals_count_in_bytes); // reserve space for register saves __ subptr(rsp, rcx); __ andptr(rsp, -(StackAlignmentInBytes)); // Align stack @@ -194,12 +194,6 @@ class StubGenerator: public StubCodeGenerator { __ xorptr(rbx, rbx); __ BIND(loop); - if (TaggedStackInterpreter) { - __ movptr(rax, Address(rdx, rcx, Interpreter::stackElementScale(), - -2*wordSize)); // get tag - __ movptr(Address(rsp, rbx, Interpreter::stackElementScale(), - Interpreter::expr_tag_offset_in_bytes(0)), rax); // store tag - } // get parameter __ movptr(rax, Address(rdx, rcx, Interpreter::stackElementScale(), -wordSize)); diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp index 121cfd67381..6f3538b4fea 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp @@ -278,11 +278,6 @@ class StubGenerator: public StubCodeGenerator { __ movptr(c_rarg2, parameters); // parameter pointer __ movl(c_rarg1, c_rarg3); // parameter counter is in c_rarg1 __ BIND(loop); - if (TaggedStackInterpreter) { - __ movl(rax, Address(c_rarg2, 0)); // get tag - __ addptr(c_rarg2, wordSize); // advance to next tag - __ push(rax); // pass tag - } __ movptr(rax, Address(c_rarg2, 0));// get parameter __ addptr(c_rarg2, wordSize); // advance to next parameter __ decrementl(c_rarg1); // decrement counter diff --git a/hotspot/src/cpu/x86/vm/templateInterpreter_x86.hpp b/hotspot/src/cpu/x86/vm/templateInterpreter_x86.hpp index 40a70f9349a..99e9add9527 100644 --- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86.hpp +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86.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 @@ -28,8 +28,8 @@ // Size of interpreter code. Increase if too small. Interpreter will // fail with a guarantee ("not enough space for interpreter generation"); // if too small. - // Run with +PrintInterpreterSize to get the VM to print out the size. - // Max size with JVMTI and TaggedStackInterpreter + // Run with +PrintInterpreter to get the VM to print out the size. + // Max size with JVMTI #ifdef AMD64 const static int InterpreterCodeSize = 200 * 1024; #else diff --git a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp index 6174b2d8bea..fe84b9a1a4b 100644 --- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp @@ -305,7 +305,6 @@ address TemplateInterpreterGenerator::generate_result_handler_for(BasicType type case T_FLOAT : { const Register t = InterpreterRuntime::SignatureHandlerGenerator::temp(); __ pop(t); // remove return address first - __ pop_dtos_to_rsp(); // Must return a result for interpreter or compiler. In SSE // mode, results are returned in xmm0 and the FPU stack must // be empty. @@ -468,7 +467,7 @@ void InterpreterGenerator::generate_stack_overflow_check(void) { // see if the frame is greater than one page in size. If so, // then we need to verify there is enough stack space remaining // for the additional locals. - __ cmpl(rdx, (page_size - overhead_size)/Interpreter::stackElementSize()); + __ cmpl(rdx, (page_size - overhead_size)/Interpreter::stackElementSize); __ jcc(Assembler::belowEqual, after_frame_check); // compute rsp as if this were going to be the last frame on @@ -882,7 +881,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) { __ get_method(method); __ verify_oop(method); __ load_unsigned_short(t, Address(method, methodOopDesc::size_of_parameters_offset())); - __ shlptr(t, Interpreter::logStackElementSize()); + __ shlptr(t, Interpreter::logStackElementSize); __ addptr(t, 2*wordSize); // allocate two more slots for JNIEnv and possible mirror __ subptr(rsp, t); __ andptr(rsp, -(StackAlignmentInBytes)); // gcc needs 16 byte aligned stacks to do XMM intrinsics @@ -1225,9 +1224,6 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) { __ testl(rdx, rdx); __ jcc(Assembler::lessEqual, exit); // do nothing if rdx <= 0 __ bind(loop); - if (TaggedStackInterpreter) { - __ push((int32_t)NULL_WORD); // push tag - } __ push((int32_t)NULL_WORD); // initialize local variables __ decrement(rdx); // until everything initialized __ jcc(Assembler::greater, loop); @@ -1463,7 +1459,7 @@ int AbstractInterpreter::size_top_interpreter_activation(methodOop method) { const int extra_stack = methodOopDesc::extra_stack_entries(); const int method_stack = (method->max_locals() + method->max_stack() + extra_stack) * - Interpreter::stackElementWords(); + Interpreter::stackElementWords; return overhead_size + method_stack + stub_code; } @@ -1487,9 +1483,9 @@ int AbstractInterpreter::layout_activation(methodOop method, // NOTE: return size is in words not bytes // fixed size of an interpreter frame: - int max_locals = method->max_locals() * Interpreter::stackElementWords(); + int max_locals = method->max_locals() * Interpreter::stackElementWords; int extra_locals = (method->max_locals() - method->size_of_parameters()) * - Interpreter::stackElementWords(); + Interpreter::stackElementWords; int overhead = frame::sender_sp_offset - frame::interpreter_frame_initial_sp_offset; @@ -1499,9 +1495,9 @@ int AbstractInterpreter::layout_activation(methodOop method, int size = overhead + - ((callee_locals - callee_param_count)*Interpreter::stackElementWords()) + + ((callee_locals - callee_param_count)*Interpreter::stackElementWords) + (moncount*frame::interpreter_frame_monitor_size()) + - tempcount*Interpreter::stackElementWords() + popframe_extra_args; + tempcount*Interpreter::stackElementWords + popframe_extra_args; if (interpreter_frame != NULL) { #ifdef ASSERT @@ -1525,7 +1521,7 @@ int AbstractInterpreter::layout_activation(methodOop method, // Set last_sp intptr_t* rsp = (intptr_t*) monbot - - tempcount*Interpreter::stackElementWords() - + tempcount*Interpreter::stackElementWords - popframe_extra_args; interpreter_frame->interpreter_frame_set_last_sp(rsp); @@ -1625,7 +1621,7 @@ void TemplateInterpreterGenerator::generate_throw_exception() { __ get_method(rax); __ verify_oop(rax); __ load_unsigned_short(rax, Address(rax, in_bytes(methodOopDesc::size_of_parameters_offset()))); - __ shlptr(rax, Interpreter::logStackElementSize()); + __ shlptr(rax, Interpreter::logStackElementSize); __ restore_locals(); __ subptr(rdi, rax); __ addptr(rdi, wordSize); diff --git a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp index da5a0eca94d..9641f5e2753 100644 --- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp @@ -199,7 +199,6 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, in_bytes(constantPoolCacheOopDesc::base_offset()) + 3 * wordSize)); __ andl(rbx, 0xFF); - if (TaggedStackInterpreter) __ shll(rbx, 1); // 2 slots per parameter. __ lea(rsp, Address(rsp, rbx, Address::times_8)); __ dispatch_next(state, step); @@ -417,7 +416,7 @@ void InterpreterGenerator::generate_stack_overflow_check(void) { // see if the frame is greater than one page in size. If so, // then we need to verify there is enough stack space remaining // for the additional locals. - __ cmpl(rdx, (page_size - overhead_size) / Interpreter::stackElementSize()); + __ cmpl(rdx, (page_size - overhead_size) / Interpreter::stackElementSize); __ jcc(Assembler::belowEqual, after_frame_check); // compute rsp as if this were going to be the last frame on @@ -428,7 +427,7 @@ void InterpreterGenerator::generate_stack_overflow_check(void) { // locals + overhead, in bytes __ mov(rax, rdx); - __ shlptr(rax, Interpreter::logStackElementSize()); // 2 slots per parameter. + __ shlptr(rax, Interpreter::logStackElementSize); // 2 slots per parameter. __ addptr(rax, overhead_size); #ifdef ASSERT @@ -759,7 +758,6 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) { // for natives the size of locals is zero // compute beginning of parameters (r14) - if (TaggedStackInterpreter) __ shll(rcx, 1); // 2 slots per parameter. __ lea(r14, Address(rsp, rcx, Address::times_8, -wordSize)); // add 2 zero-initialized slots for native calls @@ -865,7 +863,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) { __ load_unsigned_short(t, Address(method, methodOopDesc::size_of_parameters_offset())); - __ shll(t, Interpreter::logStackElementSize()); + __ shll(t, Interpreter::logStackElementSize); __ subptr(rsp, t); __ subptr(rsp, frame::arg_reg_save_area_bytes); // windows @@ -1228,7 +1226,6 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) { __ pop(rax); // compute beginning of parameters (r14) - if (TaggedStackInterpreter) __ shll(rcx, 1); // 2 slots per parameter. __ lea(r14, Address(rsp, rcx, Address::times_8, -wordSize)); // rdx - # of additional locals @@ -1239,7 +1236,6 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) { __ testl(rdx, rdx); __ jcc(Assembler::lessEqual, exit); // do nothing if rdx <= 0 __ bind(loop); - if (TaggedStackInterpreter) __ push((int) NULL_WORD); // push tag __ push((int) NULL_WORD); // initialize local variables __ decrementl(rdx); // until everything initialized __ jcc(Assembler::greater, loop); @@ -1486,7 +1482,7 @@ int AbstractInterpreter::size_top_interpreter_activation(methodOop method) { const int stub_code = frame::entry_frame_after_call_words; const int extra_stack = methodOopDesc::extra_stack_entries(); const int method_stack = (method->max_locals() + method->max_stack() + extra_stack) * - Interpreter::stackElementWords(); + Interpreter::stackElementWords; return (overhead_size + method_stack + stub_code); } @@ -1507,9 +1503,9 @@ int AbstractInterpreter::layout_activation(methodOop method, // It is also guaranteed to be walkable even though it is in a skeletal state // fixed size of an interpreter frame: - int max_locals = method->max_locals() * Interpreter::stackElementWords(); + int max_locals = method->max_locals() * Interpreter::stackElementWords; int extra_locals = (method->max_locals() - method->size_of_parameters()) * - Interpreter::stackElementWords(); + Interpreter::stackElementWords; int overhead = frame::sender_sp_offset - frame::interpreter_frame_initial_sp_offset; @@ -1518,9 +1514,9 @@ int AbstractInterpreter::layout_activation(methodOop method, // for the callee's params we only need to account for the extra // locals. int size = overhead + - (callee_locals - callee_param_count)*Interpreter::stackElementWords() + + (callee_locals - callee_param_count)*Interpreter::stackElementWords + moncount * frame::interpreter_frame_monitor_size() + - tempcount* Interpreter::stackElementWords() + popframe_extra_args; + tempcount* Interpreter::stackElementWords + popframe_extra_args; if (interpreter_frame != NULL) { #ifdef ASSERT if (!EnableMethodHandles) @@ -1544,7 +1540,7 @@ int AbstractInterpreter::layout_activation(methodOop method, // Set last_sp intptr_t* esp = (intptr_t*) monbot - - tempcount*Interpreter::stackElementWords() - + tempcount*Interpreter::stackElementWords - popframe_extra_args; interpreter_frame->interpreter_frame_set_last_sp(esp); @@ -1650,7 +1646,7 @@ void TemplateInterpreterGenerator::generate_throw_exception() { __ get_method(rax); __ load_unsigned_short(rax, Address(rax, in_bytes(methodOopDesc:: size_of_parameters_offset()))); - __ shll(rax, Interpreter::logStackElementSize()); + __ shll(rax, Interpreter::logStackElementSize); __ restore_locals(); // XXX do we need this? __ subptr(r14, rax); __ addptr(r14, wordSize); diff --git a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp index dba7aa3617e..7c7c97b05e8 100644 --- a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp @@ -50,7 +50,7 @@ static inline Address daddress(int n) { return laddress(n); } static inline Address aaddress(int n) { return iaddress(n); } static inline Address iaddress(Register r) { - return Address(rdi, r, Interpreter::stackElementScale(), Interpreter::value_offset_in_bytes()); + return Address(rdi, r, Interpreter::stackElementScale()); } static inline Address laddress(Register r) { return Address(rdi, r, Interpreter::stackElementScale(), Interpreter::local_offset_in_bytes(1)); @@ -59,12 +59,9 @@ static inline Address haddress(Register r) { return Address(rdi, r, Interpreter::stackElementScale(), Interpreter::local_offset_in_bytes(0)); } -static inline Address faddress(Register r) { return iaddress(r); }; -static inline Address daddress(Register r) { - assert(!TaggedStackInterpreter, "This doesn't work"); - return laddress(r); -}; -static inline Address aaddress(Register r) { return iaddress(r); }; +static inline Address faddress(Register r) { return iaddress(r); } +static inline Address daddress(Register r) { return laddress(r); } +static inline Address aaddress(Register r) { return iaddress(r); } // expression stack // (Note: Must not use symmetric equivalents at_rsp_m1/2 since they store @@ -448,7 +445,6 @@ void TemplateTable::iload() { // Get the local value into tos locals_index(rbx); __ movl(rax, iaddress(rbx)); - debug_only(__ verify_local_tag(frame::TagValue, rbx)); } @@ -456,18 +452,15 @@ void TemplateTable::fast_iload2() { transition(vtos, itos); locals_index(rbx); __ movl(rax, iaddress(rbx)); - debug_only(__ verify_local_tag(frame::TagValue, rbx)); __ push(itos); locals_index(rbx, 3); __ movl(rax, iaddress(rbx)); - debug_only(__ verify_local_tag(frame::TagValue, rbx)); } void TemplateTable::fast_iload() { transition(vtos, itos); locals_index(rbx); __ movl(rax, iaddress(rbx)); - debug_only(__ verify_local_tag(frame::TagValue, rbx)); } @@ -476,7 +469,6 @@ void TemplateTable::lload() { locals_index(rbx); __ movptr(rax, laddress(rbx)); NOT_LP64(__ movl(rdx, haddress(rbx))); - debug_only(__ verify_local_tag(frame::TagCategory2, rbx)); } @@ -484,26 +476,13 @@ void TemplateTable::fload() { transition(vtos, ftos); locals_index(rbx); __ fld_s(faddress(rbx)); - debug_only(__ verify_local_tag(frame::TagValue, rbx)); } void TemplateTable::dload() { transition(vtos, dtos); locals_index(rbx); - if (TaggedStackInterpreter) { - // Get double out of locals array, onto temp stack and load with - // float instruction into ST0 - __ movl(rax, laddress(rbx)); - __ movl(rdx, haddress(rbx)); - __ push(rdx); // push hi first - __ push(rax); - __ fld_d(Address(rsp, 0)); - __ addptr(rsp, 2*wordSize); - debug_only(__ verify_local_tag(frame::TagCategory2, rbx)); - } else { - __ fld_d(daddress(rbx)); - } + __ fld_d(daddress(rbx)); } @@ -511,7 +490,6 @@ void TemplateTable::aload() { transition(vtos, atos); locals_index(rbx); __ movptr(rax, aaddress(rbx)); - debug_only(__ verify_local_tag(frame::TagReference, rbx)); } @@ -527,7 +505,6 @@ void TemplateTable::wide_iload() { transition(vtos, itos); locals_index_wide(rbx); __ movl(rax, iaddress(rbx)); - debug_only(__ verify_local_tag(frame::TagValue, rbx)); } @@ -536,7 +513,6 @@ void TemplateTable::wide_lload() { locals_index_wide(rbx); __ movptr(rax, laddress(rbx)); NOT_LP64(__ movl(rdx, haddress(rbx))); - debug_only(__ verify_local_tag(frame::TagCategory2, rbx)); } @@ -544,26 +520,13 @@ void TemplateTable::wide_fload() { transition(vtos, ftos); locals_index_wide(rbx); __ fld_s(faddress(rbx)); - debug_only(__ verify_local_tag(frame::TagValue, rbx)); } void TemplateTable::wide_dload() { transition(vtos, dtos); locals_index_wide(rbx); - if (TaggedStackInterpreter) { - // Get double out of locals array, onto temp stack and load with - // float instruction into ST0 - __ movl(rax, laddress(rbx)); - __ movl(rdx, haddress(rbx)); - __ push(rdx); // push hi first - __ push(rax); - __ fld_d(Address(rsp, 0)); - __ addl(rsp, 2*wordSize); - debug_only(__ verify_local_tag(frame::TagCategory2, rbx)); - } else { - __ fld_d(daddress(rbx)); - } + __ fld_d(daddress(rbx)); } @@ -571,7 +534,6 @@ void TemplateTable::wide_aload() { transition(vtos, atos); locals_index_wide(rbx); __ movptr(rax, aaddress(rbx)); - debug_only(__ verify_local_tag(frame::TagReference, rbx)); } void TemplateTable::index_check(Register array, Register index) { @@ -672,7 +634,6 @@ void TemplateTable::fast_icaload() { // load index out of locals locals_index(rbx); __ movl(rax, iaddress(rbx)); - debug_only(__ verify_local_tag(frame::TagValue, rbx)); // rdx: array index_check(rdx, rax); @@ -695,7 +656,6 @@ void TemplateTable::saload() { void TemplateTable::iload(int n) { transition(vtos, itos); __ movl(rax, iaddress(n)); - debug_only(__ verify_local_tag(frame::TagValue, n)); } @@ -703,39 +663,24 @@ void TemplateTable::lload(int n) { transition(vtos, ltos); __ movptr(rax, laddress(n)); NOT_LP64(__ movptr(rdx, haddress(n))); - debug_only(__ verify_local_tag(frame::TagCategory2, n)); } void TemplateTable::fload(int n) { transition(vtos, ftos); __ fld_s(faddress(n)); - debug_only(__ verify_local_tag(frame::TagValue, n)); } void TemplateTable::dload(int n) { transition(vtos, dtos); - if (TaggedStackInterpreter) { - // Get double out of locals array, onto temp stack and load with - // float instruction into ST0 - __ movl(rax, laddress(n)); - __ movl(rdx, haddress(n)); - __ push(rdx); // push hi first - __ push(rax); - __ fld_d(Address(rsp, 0)); - __ addptr(rsp, 2*wordSize); // reset rsp - debug_only(__ verify_local_tag(frame::TagCategory2, n)); - } else { - __ fld_d(daddress(n)); - } + __ fld_d(daddress(n)); } void TemplateTable::aload(int n) { transition(vtos, atos); __ movptr(rax, aaddress(n)); - debug_only(__ verify_local_tag(frame::TagReference, n)); } @@ -809,7 +754,6 @@ void TemplateTable::istore() { transition(itos, vtos); locals_index(rbx); __ movl(iaddress(rbx), rax); - __ tag_local(frame::TagValue, rbx); } @@ -818,7 +762,6 @@ void TemplateTable::lstore() { locals_index(rbx); __ movptr(laddress(rbx), rax); NOT_LP64(__ movptr(haddress(rbx), rdx)); - __ tag_local(frame::TagCategory2, rbx); } @@ -826,34 +769,21 @@ void TemplateTable::fstore() { transition(ftos, vtos); locals_index(rbx); __ fstp_s(faddress(rbx)); - __ tag_local(frame::TagValue, rbx); } void TemplateTable::dstore() { transition(dtos, vtos); locals_index(rbx); - if (TaggedStackInterpreter) { - // Store double on stack and reload into locals nonadjacently - __ subptr(rsp, 2 * wordSize); - __ fstp_d(Address(rsp, 0)); - __ pop(rax); - __ pop(rdx); - __ movptr(laddress(rbx), rax); - __ movptr(haddress(rbx), rdx); - __ tag_local(frame::TagCategory2, rbx); - } else { - __ fstp_d(daddress(rbx)); - } + __ fstp_d(daddress(rbx)); } void TemplateTable::astore() { transition(vtos, vtos); - __ pop_ptr(rax, rdx); // will need to pop tag too + __ pop_ptr(rax); locals_index(rbx); __ movptr(aaddress(rbx), rax); - __ tag_local(rdx, rbx); // need to store same tag in local may be returnAddr } @@ -862,7 +792,6 @@ void TemplateTable::wide_istore() { __ pop_i(rax); locals_index_wide(rbx); __ movl(iaddress(rbx), rax); - __ tag_local(frame::TagValue, rbx); } @@ -872,7 +801,6 @@ void TemplateTable::wide_lstore() { locals_index_wide(rbx); __ movptr(laddress(rbx), rax); NOT_LP64(__ movl(haddress(rbx), rdx)); - __ tag_local(frame::TagCategory2, rbx); } @@ -888,10 +816,9 @@ void TemplateTable::wide_dstore() { void TemplateTable::wide_astore() { transition(vtos, vtos); - __ pop_ptr(rax, rdx); + __ pop_ptr(rax); locals_index_wide(rbx); __ movptr(aaddress(rbx), rax); - __ tag_local(rdx, rbx); } @@ -990,7 +917,7 @@ void TemplateTable::aastore() { // Pop stack arguments __ bind(done); - __ addptr(rsp, 3 * Interpreter::stackElementSize()); + __ addptr(rsp, 3 * Interpreter::stackElementSize); } @@ -1024,7 +951,6 @@ void TemplateTable::sastore() { void TemplateTable::istore(int n) { transition(itos, vtos); __ movl(iaddress(n), rax); - __ tag_local(frame::TagValue, n); } @@ -1032,58 +958,45 @@ void TemplateTable::lstore(int n) { transition(ltos, vtos); __ movptr(laddress(n), rax); NOT_LP64(__ movptr(haddress(n), rdx)); - __ tag_local(frame::TagCategory2, n); } void TemplateTable::fstore(int n) { transition(ftos, vtos); __ fstp_s(faddress(n)); - __ tag_local(frame::TagValue, n); } void TemplateTable::dstore(int n) { transition(dtos, vtos); - if (TaggedStackInterpreter) { - __ subptr(rsp, 2 * wordSize); - __ fstp_d(Address(rsp, 0)); - __ pop(rax); - __ pop(rdx); - __ movl(laddress(n), rax); - __ movl(haddress(n), rdx); - __ tag_local(frame::TagCategory2, n); - } else { - __ fstp_d(daddress(n)); - } + __ fstp_d(daddress(n)); } void TemplateTable::astore(int n) { transition(vtos, vtos); - __ pop_ptr(rax, rdx); + __ pop_ptr(rax); __ movptr(aaddress(n), rax); - __ tag_local(rdx, n); } void TemplateTable::pop() { transition(vtos, vtos); - __ addptr(rsp, Interpreter::stackElementSize()); + __ addptr(rsp, Interpreter::stackElementSize); } void TemplateTable::pop2() { transition(vtos, vtos); - __ addptr(rsp, 2*Interpreter::stackElementSize()); + __ addptr(rsp, 2*Interpreter::stackElementSize); } void TemplateTable::dup() { transition(vtos, vtos); // stack: ..., a - __ load_ptr_and_tag(0, rax, rdx); - __ push_ptr(rax, rdx); + __ load_ptr(0, rax); + __ push_ptr(rax); // stack: ..., a, a } @@ -1091,11 +1004,11 @@ void TemplateTable::dup() { void TemplateTable::dup_x1() { transition(vtos, vtos); // stack: ..., a, b - __ load_ptr_and_tag(0, rax, rdx); // load b - __ load_ptr_and_tag(1, rcx, rbx); // load a - __ store_ptr_and_tag(1, rax, rdx); // store b - __ store_ptr_and_tag(0, rcx, rbx); // store a - __ push_ptr(rax, rdx); // push b + __ load_ptr( 0, rax); // load b + __ load_ptr( 1, rcx); // load a + __ store_ptr(1, rax); // store b + __ store_ptr(0, rcx); // store a + __ push_ptr(rax); // push b // stack: ..., b, a, b } @@ -1103,15 +1016,15 @@ void TemplateTable::dup_x1() { void TemplateTable::dup_x2() { transition(vtos, vtos); // stack: ..., a, b, c - __ load_ptr_and_tag(0, rax, rdx); // load c - __ load_ptr_and_tag(2, rcx, rbx); // load a - __ store_ptr_and_tag(2, rax, rdx); // store c in a - __ push_ptr(rax, rdx); // push c + __ load_ptr( 0, rax); // load c + __ load_ptr( 2, rcx); // load a + __ store_ptr(2, rax); // store c in a + __ push_ptr(rax); // push c // stack: ..., c, b, c, c - __ load_ptr_and_tag(2, rax, rdx); // load b - __ store_ptr_and_tag(2, rcx, rbx); // store a in b + __ load_ptr( 2, rax); // load b + __ store_ptr(2, rcx); // store a in b // stack: ..., c, a, c, c - __ store_ptr_and_tag(1, rax, rdx); // store b in c + __ store_ptr(1, rax); // store b in c // stack: ..., c, a, b, c } @@ -1119,10 +1032,10 @@ void TemplateTable::dup_x2() { void TemplateTable::dup2() { transition(vtos, vtos); // stack: ..., a, b - __ load_ptr_and_tag(1, rax, rdx); // load a - __ push_ptr(rax, rdx); // push a - __ load_ptr_and_tag(1, rax, rdx); // load b - __ push_ptr(rax, rdx); // push b + __ load_ptr(1, rax); // load a + __ push_ptr(rax); // push a + __ load_ptr(1, rax); // load b + __ push_ptr(rax); // push b // stack: ..., a, b, a, b } @@ -1130,17 +1043,17 @@ void TemplateTable::dup2() { void TemplateTable::dup2_x1() { transition(vtos, vtos); // stack: ..., a, b, c - __ load_ptr_and_tag(0, rcx, rbx); // load c - __ load_ptr_and_tag(1, rax, rdx); // load b - __ push_ptr(rax, rdx); // push b - __ push_ptr(rcx, rbx); // push c + __ load_ptr( 0, rcx); // load c + __ load_ptr( 1, rax); // load b + __ push_ptr(rax); // push b + __ push_ptr(rcx); // push c // stack: ..., a, b, c, b, c - __ store_ptr_and_tag(3, rcx, rbx); // store c in b + __ store_ptr(3, rcx); // store c in b // stack: ..., a, c, c, b, c - __ load_ptr_and_tag(4, rcx, rbx); // load a - __ store_ptr_and_tag(2, rcx, rbx); // store a in 2nd c + __ load_ptr( 4, rcx); // load a + __ store_ptr(2, rcx); // store a in 2nd c // stack: ..., a, c, a, b, c - __ store_ptr_and_tag(4, rax, rdx); // store b in a + __ store_ptr(4, rax); // store b in a // stack: ..., b, c, a, b, c // stack: ..., b, c, a, b, c } @@ -1149,19 +1062,19 @@ void TemplateTable::dup2_x1() { void TemplateTable::dup2_x2() { transition(vtos, vtos); // stack: ..., a, b, c, d - __ load_ptr_and_tag(0, rcx, rbx); // load d - __ load_ptr_and_tag(1, rax, rdx); // load c - __ push_ptr(rax, rdx); // push c - __ push_ptr(rcx, rbx); // push d + __ load_ptr( 0, rcx); // load d + __ load_ptr( 1, rax); // load c + __ push_ptr(rax); // push c + __ push_ptr(rcx); // push d // stack: ..., a, b, c, d, c, d - __ load_ptr_and_tag(4, rax, rdx); // load b - __ store_ptr_and_tag(2, rax, rdx); // store b in d - __ store_ptr_and_tag(4, rcx, rbx); // store d in b + __ load_ptr( 4, rax); // load b + __ store_ptr(2, rax); // store b in d + __ store_ptr(4, rcx); // store d in b // stack: ..., a, d, c, b, c, d - __ load_ptr_and_tag(5, rcx, rbx); // load a - __ load_ptr_and_tag(3, rax, rdx); // load c - __ store_ptr_and_tag(3, rcx, rbx); // store a in c - __ store_ptr_and_tag(5, rax, rdx); // store c in a + __ load_ptr( 5, rcx); // load a + __ load_ptr( 3, rax); // load c + __ store_ptr(3, rcx); // store a in c + __ store_ptr(5, rax); // store c in a // stack: ..., c, d, a, b, c, d // stack: ..., c, d, a, b, c, d } @@ -1170,10 +1083,10 @@ void TemplateTable::dup2_x2() { void TemplateTable::swap() { transition(vtos, vtos); // stack: ..., a, b - __ load_ptr_and_tag(1, rcx, rbx); // load a - __ load_ptr_and_tag(0, rax, rdx); // load b - __ store_ptr_and_tag(0, rcx, rbx); // store a in b - __ store_ptr_and_tag(1, rax, rdx); // store b in a + __ load_ptr( 1, rcx); // load a + __ load_ptr( 0, rax); // load b + __ store_ptr(0, rcx); // store a in b + __ store_ptr(1, rax); // store b in a // stack: ..., b, a } @@ -1181,12 +1094,12 @@ void TemplateTable::swap() { void TemplateTable::iop2(Operation op) { transition(itos, itos); switch (op) { - case add : __ pop_i(rdx); __ addl (rax, rdx); break; + case add : __ pop_i(rdx); __ addl (rax, rdx); break; case sub : __ mov(rdx, rax); __ pop_i(rax); __ subl (rax, rdx); break; - case mul : __ pop_i(rdx); __ imull(rax, rdx); break; - case _and : __ pop_i(rdx); __ andl (rax, rdx); break; - case _or : __ pop_i(rdx); __ orl (rax, rdx); break; - case _xor : __ pop_i(rdx); __ xorl (rax, rdx); break; + case mul : __ pop_i(rdx); __ imull(rax, rdx); break; + case _and : __ pop_i(rdx); __ andl (rax, rdx); break; + case _or : __ pop_i(rdx); __ orl (rax, rdx); break; + case _xor : __ pop_i(rdx); __ xorl (rax, rdx); break; case shl : __ mov(rcx, rax); __ pop_i(rax); __ shll (rax); break; // implicit masking of lower 5 bits by Intel shift instr. case shr : __ mov(rcx, rax); __ pop_i(rax); __ sarl (rax); break; // implicit masking of lower 5 bits by Intel shift instr. case ushr : __ mov(rcx, rax); __ pop_i(rax); __ shrl (rax); break; // implicit masking of lower 5 bits by Intel shift instr. @@ -1199,13 +1112,13 @@ void TemplateTable::lop2(Operation op) { transition(ltos, ltos); __ pop_l(rbx, rcx); switch (op) { - case add : __ addl(rax, rbx); __ adcl(rdx, rcx); break; - case sub : __ subl(rbx, rax); __ sbbl(rcx, rdx); - __ mov(rax, rbx); __ mov(rdx, rcx); break; - case _and: __ andl(rax, rbx); __ andl(rdx, rcx); break; - case _or : __ orl (rax, rbx); __ orl (rdx, rcx); break; - case _xor: __ xorl(rax, rbx); __ xorl(rdx, rcx); break; - default : ShouldNotReachHere(); + case add : __ addl(rax, rbx); __ adcl(rdx, rcx); break; + case sub : __ subl(rbx, rax); __ sbbl(rcx, rdx); + __ mov (rax, rbx); __ mov (rdx, rcx); break; + case _and : __ andl(rax, rbx); __ andl(rdx, rcx); break; + case _or : __ orl (rax, rbx); __ orl (rdx, rcx); break; + case _xor : __ xorl(rax, rbx); __ xorl(rdx, rcx); break; + default : ShouldNotReachHere(); } } @@ -1299,7 +1212,6 @@ void TemplateTable::lushr() { void TemplateTable::fop2(Operation op) { transition(ftos, ftos); - __ pop_ftos_to_rsp(); // pop ftos into rsp switch (op) { case add: __ fadd_s (at_rsp()); break; case sub: __ fsubr_s(at_rsp()); break; @@ -1315,7 +1227,6 @@ void TemplateTable::fop2(Operation op) { void TemplateTable::dop2(Operation op) { transition(dtos, dtos); - __ pop_dtos_to_rsp(); // pop dtos into rsp switch (op) { case add: __ fadd_d (at_rsp()); break; @@ -1557,10 +1468,8 @@ void TemplateTable::lcmp() { void TemplateTable::float_cmp(bool is_float, int unordered_result) { if (is_float) { - __ pop_ftos_to_rsp(); __ fld_s(at_rsp()); } else { - __ pop_dtos_to_rsp(); __ fld_d(at_rsp()); __ pop(rdx); } @@ -2854,7 +2763,6 @@ void TemplateTable::fast_xaccess(TosState state) { transition(vtos, state); // get receiver __ movptr(rax, aaddress(0)); - debug_only(__ verify_local_tag(frame::TagReference, 0)); // access constant pool cache __ get_cache_and_index_at_bcp(rcx, rdx, 2); __ movptr(rbx, Address(rcx, diff --git a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp index 8c6a9c1e567..6efd571e200 100644 --- a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp @@ -58,7 +58,7 @@ static inline Address aaddress(int n) { } static inline Address iaddress(Register r) { - return Address(r14, r, Address::times_8, Interpreter::value_offset_in_bytes()); + return Address(r14, r, Address::times_8); } static inline Address laddress(Register r) { @@ -418,7 +418,6 @@ void TemplateTable::ldc2_w() { void TemplateTable::locals_index(Register reg, int offset) { __ load_unsigned_byte(reg, at_bcp(offset)); __ negptr(reg); - if (TaggedStackInterpreter) __ shlptr(reg, 1); // index = index*2 } void TemplateTable::iload() { @@ -460,53 +459,45 @@ void TemplateTable::iload() { // Get the local value into tos locals_index(rbx); __ movl(rax, iaddress(rbx)); - debug_only(__ verify_local_tag(frame::TagValue, rbx)); } void TemplateTable::fast_iload2() { transition(vtos, itos); locals_index(rbx); __ movl(rax, iaddress(rbx)); - debug_only(__ verify_local_tag(frame::TagValue, rbx)); __ push(itos); locals_index(rbx, 3); __ movl(rax, iaddress(rbx)); - debug_only(__ verify_local_tag(frame::TagValue, rbx)); } void TemplateTable::fast_iload() { transition(vtos, itos); locals_index(rbx); __ movl(rax, iaddress(rbx)); - debug_only(__ verify_local_tag(frame::TagValue, rbx)); } void TemplateTable::lload() { transition(vtos, ltos); locals_index(rbx); __ movq(rax, laddress(rbx)); - debug_only(__ verify_local_tag(frame::TagCategory2, rbx)); } void TemplateTable::fload() { transition(vtos, ftos); locals_index(rbx); __ movflt(xmm0, faddress(rbx)); - debug_only(__ verify_local_tag(frame::TagValue, rbx)); } void TemplateTable::dload() { transition(vtos, dtos); locals_index(rbx); __ movdbl(xmm0, daddress(rbx)); - debug_only(__ verify_local_tag(frame::TagCategory2, rbx)); } void TemplateTable::aload() { transition(vtos, atos); locals_index(rbx); __ movptr(rax, aaddress(rbx)); - debug_only(__ verify_local_tag(frame::TagReference, rbx)); } void TemplateTable::locals_index_wide(Register reg) { @@ -514,42 +505,36 @@ void TemplateTable::locals_index_wide(Register reg) { __ bswapl(reg); __ shrl(reg, 16); __ negptr(reg); - if (TaggedStackInterpreter) __ shlptr(reg, 1); // index = index*2 } void TemplateTable::wide_iload() { transition(vtos, itos); locals_index_wide(rbx); __ movl(rax, iaddress(rbx)); - debug_only(__ verify_local_tag(frame::TagValue, rbx)); } void TemplateTable::wide_lload() { transition(vtos, ltos); locals_index_wide(rbx); __ movq(rax, laddress(rbx)); - debug_only(__ verify_local_tag(frame::TagCategory2, rbx)); } void TemplateTable::wide_fload() { transition(vtos, ftos); locals_index_wide(rbx); __ movflt(xmm0, faddress(rbx)); - debug_only(__ verify_local_tag(frame::TagValue, rbx)); } void TemplateTable::wide_dload() { transition(vtos, dtos); locals_index_wide(rbx); __ movdbl(xmm0, daddress(rbx)); - debug_only(__ verify_local_tag(frame::TagCategory2, rbx)); } void TemplateTable::wide_aload() { transition(vtos, atos); locals_index_wide(rbx); __ movptr(rax, aaddress(rbx)); - debug_only(__ verify_local_tag(frame::TagReference, rbx)); } void TemplateTable::index_check(Register array, Register index) { @@ -654,7 +639,6 @@ void TemplateTable::fast_icaload() { // load index out of locals locals_index(rbx); __ movl(rax, iaddress(rbx)); - debug_only(__ verify_local_tag(frame::TagValue, rbx)); // eax: index // rdx: array @@ -681,31 +665,26 @@ void TemplateTable::saload() { void TemplateTable::iload(int n) { transition(vtos, itos); __ movl(rax, iaddress(n)); - debug_only(__ verify_local_tag(frame::TagValue, n)); } void TemplateTable::lload(int n) { transition(vtos, ltos); __ movq(rax, laddress(n)); - debug_only(__ verify_local_tag(frame::TagCategory2, n)); } void TemplateTable::fload(int n) { transition(vtos, ftos); __ movflt(xmm0, faddress(n)); - debug_only(__ verify_local_tag(frame::TagValue, n)); } void TemplateTable::dload(int n) { transition(vtos, dtos); __ movdbl(xmm0, daddress(n)); - debug_only(__ verify_local_tag(frame::TagCategory2, n)); } void TemplateTable::aload(int n) { transition(vtos, atos); __ movptr(rax, aaddress(n)); - debug_only(__ verify_local_tag(frame::TagReference, n)); } void TemplateTable::aload_0() { @@ -791,36 +770,31 @@ void TemplateTable::istore() { transition(itos, vtos); locals_index(rbx); __ movl(iaddress(rbx), rax); - __ tag_local(frame::TagValue, rbx); } void TemplateTable::lstore() { transition(ltos, vtos); locals_index(rbx); __ movq(laddress(rbx), rax); - __ tag_local(frame::TagCategory2, rbx); } void TemplateTable::fstore() { transition(ftos, vtos); locals_index(rbx); __ movflt(faddress(rbx), xmm0); - __ tag_local(frame::TagValue, rbx); } void TemplateTable::dstore() { transition(dtos, vtos); locals_index(rbx); __ movdbl(daddress(rbx), xmm0); - __ tag_local(frame::TagCategory2, rbx); } void TemplateTable::astore() { transition(vtos, vtos); - __ pop_ptr(rax, rdx); // will need to pop tag too + __ pop_ptr(rax); locals_index(rbx); __ movptr(aaddress(rbx), rax); - __ tag_local(rdx, rbx); // store tag from stack, might be returnAddr } void TemplateTable::wide_istore() { @@ -828,7 +802,6 @@ void TemplateTable::wide_istore() { __ pop_i(); locals_index_wide(rbx); __ movl(iaddress(rbx), rax); - __ tag_local(frame::TagValue, rbx); } void TemplateTable::wide_lstore() { @@ -836,7 +809,6 @@ void TemplateTable::wide_lstore() { __ pop_l(); locals_index_wide(rbx); __ movq(laddress(rbx), rax); - __ tag_local(frame::TagCategory2, rbx); } void TemplateTable::wide_fstore() { @@ -844,7 +816,6 @@ void TemplateTable::wide_fstore() { __ pop_f(); locals_index_wide(rbx); __ movflt(faddress(rbx), xmm0); - __ tag_local(frame::TagValue, rbx); } void TemplateTable::wide_dstore() { @@ -852,15 +823,13 @@ void TemplateTable::wide_dstore() { __ pop_d(); locals_index_wide(rbx); __ movdbl(daddress(rbx), xmm0); - __ tag_local(frame::TagCategory2, rbx); } void TemplateTable::wide_astore() { transition(vtos, vtos); - __ pop_ptr(rax, rdx); // will need to pop tag too + __ pop_ptr(rax); locals_index_wide(rbx); __ movptr(aaddress(rbx), rax); - __ tag_local(rdx, rbx); // store tag from stack, might be returnAddr } void TemplateTable::iastore() { @@ -972,7 +941,7 @@ void TemplateTable::aastore() { // Pop stack arguments __ bind(done); - __ addptr(rsp, 3 * Interpreter::stackElementSize()); + __ addptr(rsp, 3 * Interpreter::stackElementSize); } void TemplateTable::bastore() { @@ -1010,130 +979,125 @@ void TemplateTable::sastore() { void TemplateTable::istore(int n) { transition(itos, vtos); __ movl(iaddress(n), rax); - __ tag_local(frame::TagValue, n); } void TemplateTable::lstore(int n) { transition(ltos, vtos); __ movq(laddress(n), rax); - __ tag_local(frame::TagCategory2, n); } void TemplateTable::fstore(int n) { transition(ftos, vtos); __ movflt(faddress(n), xmm0); - __ tag_local(frame::TagValue, n); } void TemplateTable::dstore(int n) { transition(dtos, vtos); __ movdbl(daddress(n), xmm0); - __ tag_local(frame::TagCategory2, n); } void TemplateTable::astore(int n) { transition(vtos, vtos); - __ pop_ptr(rax, rdx); + __ pop_ptr(rax); __ movptr(aaddress(n), rax); - __ tag_local(rdx, n); } void TemplateTable::pop() { transition(vtos, vtos); - __ addptr(rsp, Interpreter::stackElementSize()); + __ addptr(rsp, Interpreter::stackElementSize); } void TemplateTable::pop2() { transition(vtos, vtos); - __ addptr(rsp, 2 * Interpreter::stackElementSize()); + __ addptr(rsp, 2 * Interpreter::stackElementSize); } void TemplateTable::dup() { transition(vtos, vtos); - __ load_ptr_and_tag(0, rax, rdx); - __ push_ptr(rax, rdx); + __ load_ptr(0, rax); + __ push_ptr(rax); // stack: ..., a, a } void TemplateTable::dup_x1() { transition(vtos, vtos); // stack: ..., a, b - __ load_ptr_and_tag(0, rax, rdx); // load b - __ load_ptr_and_tag(1, rcx, rbx); // load a - __ store_ptr_and_tag(1, rax, rdx); // store b - __ store_ptr_and_tag(0, rcx, rbx); // store a - __ push_ptr(rax, rdx); // push b + __ load_ptr( 0, rax); // load b + __ load_ptr( 1, rcx); // load a + __ store_ptr(1, rax); // store b + __ store_ptr(0, rcx); // store a + __ push_ptr(rax); // push b // stack: ..., b, a, b } void TemplateTable::dup_x2() { transition(vtos, vtos); // stack: ..., a, b, c - __ load_ptr_and_tag(0, rax, rdx); // load c - __ load_ptr_and_tag(2, rcx, rbx); // load a - __ store_ptr_and_tag(2, rax, rdx); // store c in a - __ push_ptr(rax, rdx); // push c + __ load_ptr( 0, rax); // load c + __ load_ptr( 2, rcx); // load a + __ store_ptr(2, rax); // store c in a + __ push_ptr(rax); // push c // stack: ..., c, b, c, c - __ load_ptr_and_tag(2, rax, rdx); // load b - __ store_ptr_and_tag(2, rcx, rbx); // store a in b + __ load_ptr( 2, rax); // load b + __ store_ptr(2, rcx); // store a in b // stack: ..., c, a, c, c - __ store_ptr_and_tag(1, rax, rdx); // store b in c + __ store_ptr(1, rax); // store b in c // stack: ..., c, a, b, c } void TemplateTable::dup2() { transition(vtos, vtos); // stack: ..., a, b - __ load_ptr_and_tag(1, rax, rdx); // load a - __ push_ptr(rax, rdx); // push a - __ load_ptr_and_tag(1, rax, rdx); // load b - __ push_ptr(rax, rdx); // push b + __ load_ptr(1, rax); // load a + __ push_ptr(rax); // push a + __ load_ptr(1, rax); // load b + __ push_ptr(rax); // push b // stack: ..., a, b, a, b } void TemplateTable::dup2_x1() { transition(vtos, vtos); // stack: ..., a, b, c - __ load_ptr_and_tag(0, rcx, rbx); // load c - __ load_ptr_and_tag(1, rax, rdx); // load b - __ push_ptr(rax, rdx); // push b - __ push_ptr(rcx, rbx); // push c + __ load_ptr( 0, rcx); // load c + __ load_ptr( 1, rax); // load b + __ push_ptr(rax); // push b + __ push_ptr(rcx); // push c // stack: ..., a, b, c, b, c - __ store_ptr_and_tag(3, rcx, rbx); // store c in b + __ store_ptr(3, rcx); // store c in b // stack: ..., a, c, c, b, c - __ load_ptr_and_tag(4, rcx, rbx); // load a - __ store_ptr_and_tag(2, rcx, rbx); // store a in 2nd c + __ load_ptr( 4, rcx); // load a + __ store_ptr(2, rcx); // store a in 2nd c // stack: ..., a, c, a, b, c - __ store_ptr_and_tag(4, rax, rdx); // store b in a + __ store_ptr(4, rax); // store b in a // stack: ..., b, c, a, b, c } void TemplateTable::dup2_x2() { transition(vtos, vtos); // stack: ..., a, b, c, d - __ load_ptr_and_tag(0, rcx, rbx); // load d - __ load_ptr_and_tag(1, rax, rdx); // load c - __ push_ptr(rax, rdx); // push c - __ push_ptr(rcx, rbx); // push d + __ load_ptr( 0, rcx); // load d + __ load_ptr( 1, rax); // load c + __ push_ptr(rax); // push c + __ push_ptr(rcx); // push d // stack: ..., a, b, c, d, c, d - __ load_ptr_and_tag(4, rax, rdx); // load b - __ store_ptr_and_tag(2, rax, rdx); // store b in d - __ store_ptr_and_tag(4, rcx, rbx); // store d in b + __ load_ptr( 4, rax); // load b + __ store_ptr(2, rax); // store b in d + __ store_ptr(4, rcx); // store d in b // stack: ..., a, d, c, b, c, d - __ load_ptr_and_tag(5, rcx, rbx); // load a - __ load_ptr_and_tag(3, rax, rdx); // load c - __ store_ptr_and_tag(3, rcx, rbx); // store a in c - __ store_ptr_and_tag(5, rax, rdx); // store c in a + __ load_ptr( 5, rcx); // load a + __ load_ptr( 3, rax); // load c + __ store_ptr(3, rcx); // store a in c + __ store_ptr(5, rax); // store c in a // stack: ..., c, d, a, b, c, d } void TemplateTable::swap() { transition(vtos, vtos); // stack: ..., a, b - __ load_ptr_and_tag(1, rcx, rbx); // load a - __ load_ptr_and_tag(0, rax, rdx); // load b - __ store_ptr_and_tag(0, rcx, rbx); // store a in b - __ store_ptr_and_tag(1, rax, rdx); // store b in a + __ load_ptr( 1, rcx); // load a + __ load_ptr( 0, rax); // load b + __ store_ptr(0, rcx); // store a in b + __ store_ptr(1, rax); // store b in a // stack: ..., b, a } @@ -1156,12 +1120,12 @@ void TemplateTable::iop2(Operation op) { void TemplateTable::lop2(Operation op) { transition(ltos, ltos); switch (op) { - case add : __ pop_l(rdx); __ addptr (rax, rdx); break; - case sub : __ mov(rdx, rax); __ pop_l(rax); __ subptr (rax, rdx); break; - case _and : __ pop_l(rdx); __ andptr (rax, rdx); break; - case _or : __ pop_l(rdx); __ orptr (rax, rdx); break; - case _xor : __ pop_l(rdx); __ xorptr (rax, rdx); break; - default : ShouldNotReachHere(); + case add : __ pop_l(rdx); __ addptr(rax, rdx); break; + case sub : __ mov(rdx, rax); __ pop_l(rax); __ subptr(rax, rdx); break; + case _and : __ pop_l(rdx); __ andptr(rax, rdx); break; + case _or : __ pop_l(rdx); __ orptr (rax, rdx); break; + case _xor : __ pop_l(rdx); __ xorptr(rax, rdx); break; + default : ShouldNotReachHere(); } } @@ -1250,7 +1214,7 @@ void TemplateTable::fop2(Operation op) { switch (op) { case add: __ addss(xmm0, at_rsp()); - __ addptr(rsp, Interpreter::stackElementSize()); + __ addptr(rsp, Interpreter::stackElementSize); break; case sub: __ movflt(xmm1, xmm0); @@ -1259,7 +1223,7 @@ void TemplateTable::fop2(Operation op) { break; case mul: __ mulss(xmm0, at_rsp()); - __ addptr(rsp, Interpreter::stackElementSize()); + __ addptr(rsp, Interpreter::stackElementSize); break; case div: __ movflt(xmm1, xmm0); @@ -1282,7 +1246,7 @@ void TemplateTable::dop2(Operation op) { switch (op) { case add: __ addsd(xmm0, at_rsp()); - __ addptr(rsp, 2 * Interpreter::stackElementSize()); + __ addptr(rsp, 2 * Interpreter::stackElementSize); break; case sub: __ movdbl(xmm1, xmm0); @@ -1291,7 +1255,7 @@ void TemplateTable::dop2(Operation op) { break; case mul: __ mulsd(xmm0, at_rsp()); - __ addptr(rsp, 2 * Interpreter::stackElementSize()); + __ addptr(rsp, 2 * Interpreter::stackElementSize); break; case div: __ movdbl(xmm1, xmm0); @@ -2782,7 +2746,6 @@ void TemplateTable::fast_xaccess(TosState state) { // get receiver __ movptr(rax, aaddress(0)); - debug_only(__ verify_local_tag(frame::TagReference, 0)); // access constant pool cache __ get_cache_and_index_at_bcp(rcx, rdx, 2); __ movptr(rbx, @@ -2858,7 +2821,6 @@ void TemplateTable::prepare_invoke(Register method, Register index, int byte_no) if (load_receiver) { __ movl(recv, flags); __ andl(recv, 0xFF); - if (TaggedStackInterpreter) __ shll(recv, 1); // index*2 Address recv_addr(rsp, recv, Address::times_8, -Interpreter::expr_offset_in_bytes(1)); __ movptr(recv, recv_addr); __ verify_oop(recv); @@ -3610,13 +3572,11 @@ void TemplateTable::multianewarray() { __ load_unsigned_byte(rax, at_bcp(3)); // get number of dimensions // last dim is on top of stack; we want address of first one: // first_addr = last_addr + (ndims - 1) * wordSize - if (TaggedStackInterpreter) __ shll(rax, 1); // index*2 __ lea(c_rarg1, Address(rsp, rax, Address::times_8, -wordSize)); call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::multianewarray), c_rarg1); __ load_unsigned_byte(rbx, at_bcp(3)); - if (TaggedStackInterpreter) __ shll(rbx, 1); // index*2 __ lea(rsp, Address(rsp, rbx, Address::times_8)); } #endif // !CC_INTERP diff --git a/hotspot/src/cpu/zero/vm/interpreter_zero.hpp b/hotspot/src/cpu/zero/vm/interpreter_zero.hpp index 67cac47d9a2..df0ccb7348c 100644 --- a/hotspot/src/cpu/zero/vm/interpreter_zero.hpp +++ b/hotspot/src/cpu/zero/vm/interpreter_zero.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2010 Sun Microsystems, Inc. All Rights Reserved. * Copyright 2007, 2008 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -38,24 +38,12 @@ static int expr_index_at(int i) { return stackElementWords() * i; } - static int expr_tag_index_at(int i) { - assert(TaggedStackInterpreter, "should not call this"); - Unimplemented(); - } static int expr_offset_in_bytes(int i) { return stackElementSize() * i; } - static int expr_tag_offset_in_bytes(int i) { - assert(TaggedStackInterpreter, "should not call this"); - Unimplemented(); - } static int local_index_at(int i) { assert(i <= 0, "local direction already negated"); - return stackElementWords() * i + (value_offset_in_bytes() / wordSize); - } - static int local_tag_index_at(int i) { - assert(TaggedStackInterpreter, "should not call this"); - Unimplemented(); + return stackElementWords() * i; } diff --git a/hotspot/src/os_cpu/linux_x86/vm/globals_linux_x86.hpp b/hotspot/src/os_cpu/linux_x86/vm/globals_linux_x86.hpp index 708cc3e085c..98d488e02ea 100644 --- a/hotspot/src/os_cpu/linux_x86/vm/globals_linux_x86.hpp +++ b/hotspot/src/os_cpu/linux_x86/vm/globals_linux_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-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 @@ -30,9 +30,9 @@ define_pd_global(bool, DontYieldALot, false); define_pd_global(intx, ThreadStackSize, 1024); // 0 => use system default define_pd_global(intx, VMThreadStackSize, 1024); #else -// ThreadStackSize 320 allows TaggedStackInterpreter and a couple of test cases -// to run while keeping the number of threads that can be created high. -// System default ThreadStackSize appears to be 512 which is too big. +// ThreadStackSize 320 allows a couple of test cases to run while +// keeping the number of threads that can be created high. System +// default ThreadStackSize appears to be 512 which is too big. define_pd_global(intx, ThreadStackSize, 320); define_pd_global(intx, VMThreadStackSize, 512); #endif // AMD64 diff --git a/hotspot/src/os_cpu/solaris_x86/vm/globals_solaris_x86.hpp b/hotspot/src/os_cpu/solaris_x86/vm/globals_solaris_x86.hpp index 4b2749bc193..51a8b9b2dd6 100644 --- a/hotspot/src/os_cpu/solaris_x86/vm/globals_solaris_x86.hpp +++ b/hotspot/src/os_cpu/solaris_x86/vm/globals_solaris_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-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,8 +31,8 @@ define_pd_global(intx, ThreadStackSize, 1024); // 0 => use system defau define_pd_global(intx, VMThreadStackSize, 1024); define_pd_global(uintx,JVMInvokeMethodSlack, 8*K); #else -// ThreadStackSize 320 allows TaggedStackInterpreter and a couple of test cases -// to run while keeping the number of threads that can be created high. +// ThreadStackSize 320 allows a couple of test cases to run while +// keeping the number of threads that can be created high. define_pd_global(intx, ThreadStackSize, 320); define_pd_global(intx, VMThreadStackSize, 512); define_pd_global(uintx,JVMInvokeMethodSlack, 10*K); diff --git a/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp b/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp index 8ab9e40d32b..72bf5c89db9 100644 --- a/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp +++ b/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp @@ -167,60 +167,15 @@ class AbstractInterpreter: AllStatic { // Debugging/printing static void print(); // prints the interpreter code - // Support for Tagged Stacks - // - // Tags are stored on the Java Expression stack above the value: - // - // tag - // value - // - // For double values: - // - // tag2 - // high word - // tag1 - // low word - public: - static int stackElementWords() { return TaggedStackInterpreter ? 2 : 1; } - static int stackElementSize() { return stackElementWords()*wordSize; } - static int logStackElementSize() { return - TaggedStackInterpreter? LogBytesPerWord+1 : LogBytesPerWord; } - - // Tag is at pointer, value is one below for a stack growing down - // (or above for stack growing up) - static int value_offset_in_bytes() { - return TaggedStackInterpreter ? - frame::interpreter_frame_expression_stack_direction() * wordSize : 0; - } - static int tag_offset_in_bytes() { - assert(TaggedStackInterpreter, "should not call this"); - return 0; - } - - // Tagged Locals - // Locals are stored relative to Llocals: - // - // tag <- Llocals[n] - // value - // - // Category 2 types are indexed as: - // - // tag <- Llocals[-n] - // high word - // tag <- Llocals[-n+1] - // low word - // + // Interpreter helpers + const static int stackElementWords = 1; + const static int stackElementSize = stackElementWords * wordSize; + const static int logStackElementSize = LogBytesPerWord; // Local values relative to locals[n] static int local_offset_in_bytes(int n) { - return ((frame::interpreter_frame_expression_stack_direction() * n) * - stackElementSize()) + value_offset_in_bytes(); - } - static int local_tag_offset_in_bytes(int n) { - assert(TaggedStackInterpreter, "should not call this"); - return ((frame::interpreter_frame_expression_stack_direction() * n) * - stackElementSize()) + tag_offset_in_bytes(); + return ((frame::interpreter_frame_expression_stack_direction() * n) * stackElementSize); } // access to stacked values according to type: @@ -237,29 +192,15 @@ class AbstractInterpreter: AllStatic { static jlong long_in_slot(intptr_t* slot_addr) { if (sizeof(intptr_t) >= sizeof(jlong)) { return *(jlong*) slot_addr; - } else if (!TaggedStackInterpreter) { - return Bytes::get_native_u8((address)slot_addr); } else { - assert(sizeof(intptr_t) * 2 == sizeof(jlong), "ILP32"); - // assemble the long in memory order (not arithmetic order) - union { jlong j; jint i[2]; } u; - u.i[0] = (jint) slot_addr[0*stackElementSize()]; - u.i[1] = (jint) slot_addr[1*stackElementSize()]; - return u.j; + return Bytes::get_native_u8((address)slot_addr); } } static void set_long_in_slot(intptr_t* slot_addr, jlong value) { if (sizeof(intptr_t) >= sizeof(jlong)) { *(jlong*) slot_addr = value; - } else if (!TaggedStackInterpreter) { - Bytes::put_native_u8((address)slot_addr, value); } else { - assert(sizeof(intptr_t) * 2 == sizeof(jlong), "ILP32"); - // assemble the long in memory order (not arithmetic order) - union { jlong j; jint i[2]; } u; - u.j = value; - slot_addr[0*stackElementSize()] = (intptr_t) u.i[0]; - slot_addr[1*stackElementSize()] = (intptr_t) u.i[1]; + Bytes::put_native_u8((address)slot_addr, value); } } static void get_jvalue_in_slot(intptr_t* slot_addr, BasicType type, jvalue* value) { diff --git a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp index a8400339093..f93608f13c0 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2002-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 @@ -2692,219 +2692,141 @@ BytecodeInterpreter::BytecodeInterpreter(messages msg) { // The implementations are platform dependent. We have to worry about alignment // issues on some machines which can change on the same platform depending on // whether it is an LP64 machine also. -#ifdef ASSERT -void BytecodeInterpreter::verify_stack_tag(intptr_t *tos, frame::Tag tag, int offset) { - if (TaggedStackInterpreter) { - frame::Tag t = (frame::Tag)tos[Interpreter::expr_tag_index_at(-offset)]; - assert(t == tag, "stack tag mismatch"); - } -} -#endif // ASSERT - address BytecodeInterpreter::stack_slot(intptr_t *tos, int offset) { - debug_only(verify_stack_tag(tos, frame::TagValue, offset)); return (address) tos[Interpreter::expr_index_at(-offset)]; } jint BytecodeInterpreter::stack_int(intptr_t *tos, int offset) { - debug_only(verify_stack_tag(tos, frame::TagValue, offset)); return *((jint*) &tos[Interpreter::expr_index_at(-offset)]); } jfloat BytecodeInterpreter::stack_float(intptr_t *tos, int offset) { - debug_only(verify_stack_tag(tos, frame::TagValue, offset)); return *((jfloat *) &tos[Interpreter::expr_index_at(-offset)]); } oop BytecodeInterpreter::stack_object(intptr_t *tos, int offset) { - debug_only(verify_stack_tag(tos, frame::TagReference, offset)); return (oop)tos [Interpreter::expr_index_at(-offset)]; } jdouble BytecodeInterpreter::stack_double(intptr_t *tos, int offset) { - debug_only(verify_stack_tag(tos, frame::TagValue, offset)); - debug_only(verify_stack_tag(tos, frame::TagValue, offset-1)); return ((VMJavaVal64*) &tos[Interpreter::expr_index_at(-offset)])->d; } jlong BytecodeInterpreter::stack_long(intptr_t *tos, int offset) { - debug_only(verify_stack_tag(tos, frame::TagValue, offset)); - debug_only(verify_stack_tag(tos, frame::TagValue, offset-1)); return ((VMJavaVal64 *) &tos[Interpreter::expr_index_at(-offset)])->l; } -void BytecodeInterpreter::tag_stack(intptr_t *tos, frame::Tag tag, int offset) { - if (TaggedStackInterpreter) - tos[Interpreter::expr_tag_index_at(-offset)] = (intptr_t)tag; -} - // only used for value types void BytecodeInterpreter::set_stack_slot(intptr_t *tos, address value, int offset) { - tag_stack(tos, frame::TagValue, offset); *((address *)&tos[Interpreter::expr_index_at(-offset)]) = value; } void BytecodeInterpreter::set_stack_int(intptr_t *tos, int value, int offset) { - tag_stack(tos, frame::TagValue, offset); *((jint *)&tos[Interpreter::expr_index_at(-offset)]) = value; } void BytecodeInterpreter::set_stack_float(intptr_t *tos, jfloat value, int offset) { - tag_stack(tos, frame::TagValue, offset); *((jfloat *)&tos[Interpreter::expr_index_at(-offset)]) = value; } void BytecodeInterpreter::set_stack_object(intptr_t *tos, oop value, int offset) { - tag_stack(tos, frame::TagReference, offset); *((oop *)&tos[Interpreter::expr_index_at(-offset)]) = value; } // needs to be platform dep for the 32 bit platforms. void BytecodeInterpreter::set_stack_double(intptr_t *tos, jdouble value, int offset) { - tag_stack(tos, frame::TagValue, offset); - tag_stack(tos, frame::TagValue, offset-1); ((VMJavaVal64*)&tos[Interpreter::expr_index_at(-offset)])->d = value; } void BytecodeInterpreter::set_stack_double_from_addr(intptr_t *tos, address addr, int offset) { - tag_stack(tos, frame::TagValue, offset); - tag_stack(tos, frame::TagValue, offset-1); (((VMJavaVal64*)&tos[Interpreter::expr_index_at(-offset)])->d = ((VMJavaVal64*)addr)->d); } void BytecodeInterpreter::set_stack_long(intptr_t *tos, jlong value, int offset) { - tag_stack(tos, frame::TagValue, offset); ((VMJavaVal64*)&tos[Interpreter::expr_index_at(-offset+1)])->l = 0xdeedbeeb; - tag_stack(tos, frame::TagValue, offset-1); ((VMJavaVal64*)&tos[Interpreter::expr_index_at(-offset)])->l = value; } void BytecodeInterpreter::set_stack_long_from_addr(intptr_t *tos, address addr, int offset) { - tag_stack(tos, frame::TagValue, offset); ((VMJavaVal64*)&tos[Interpreter::expr_index_at(-offset+1)])->l = 0xdeedbeeb; - tag_stack(tos, frame::TagValue, offset-1); ((VMJavaVal64*)&tos[Interpreter::expr_index_at(-offset)])->l = ((VMJavaVal64*)addr)->l; } // Locals -#ifdef ASSERT -void BytecodeInterpreter::verify_locals_tag(intptr_t *locals, frame::Tag tag, - int offset) { - if (TaggedStackInterpreter) { - frame::Tag t = (frame::Tag)locals[Interpreter::local_tag_index_at(-offset)]; - assert(t == tag, "locals tag mismatch"); - } -} -#endif // ASSERT address BytecodeInterpreter::locals_slot(intptr_t* locals, int offset) { - debug_only(verify_locals_tag(locals, frame::TagValue, offset)); return (address)locals[Interpreter::local_index_at(-offset)]; } jint BytecodeInterpreter::locals_int(intptr_t* locals, int offset) { - debug_only(verify_locals_tag(locals, frame::TagValue, offset)); return (jint)locals[Interpreter::local_index_at(-offset)]; } jfloat BytecodeInterpreter::locals_float(intptr_t* locals, int offset) { - debug_only(verify_locals_tag(locals, frame::TagValue, offset)); return (jfloat)locals[Interpreter::local_index_at(-offset)]; } oop BytecodeInterpreter::locals_object(intptr_t* locals, int offset) { - debug_only(verify_locals_tag(locals, frame::TagReference, offset)); return (oop)locals[Interpreter::local_index_at(-offset)]; } jdouble BytecodeInterpreter::locals_double(intptr_t* locals, int offset) { - debug_only(verify_locals_tag(locals, frame::TagValue, offset)); - debug_only(verify_locals_tag(locals, frame::TagValue, offset)); return ((VMJavaVal64*)&locals[Interpreter::local_index_at(-(offset+1))])->d; } jlong BytecodeInterpreter::locals_long(intptr_t* locals, int offset) { - debug_only(verify_locals_tag(locals, frame::TagValue, offset)); - debug_only(verify_locals_tag(locals, frame::TagValue, offset+1)); return ((VMJavaVal64*)&locals[Interpreter::local_index_at(-(offset+1))])->l; } // Returns the address of locals value. address BytecodeInterpreter::locals_long_at(intptr_t* locals, int offset) { - debug_only(verify_locals_tag(locals, frame::TagValue, offset)); - debug_only(verify_locals_tag(locals, frame::TagValue, offset+1)); return ((address)&locals[Interpreter::local_index_at(-(offset+1))]); } address BytecodeInterpreter::locals_double_at(intptr_t* locals, int offset) { - debug_only(verify_locals_tag(locals, frame::TagValue, offset)); - debug_only(verify_locals_tag(locals, frame::TagValue, offset+1)); return ((address)&locals[Interpreter::local_index_at(-(offset+1))]); } -void BytecodeInterpreter::tag_locals(intptr_t *locals, frame::Tag tag, int offset) { - if (TaggedStackInterpreter) - locals[Interpreter::local_tag_index_at(-offset)] = (intptr_t)tag; -} - // Used for local value or returnAddress void BytecodeInterpreter::set_locals_slot(intptr_t *locals, address value, int offset) { - tag_locals(locals, frame::TagValue, offset); *((address*)&locals[Interpreter::local_index_at(-offset)]) = value; } void BytecodeInterpreter::set_locals_int(intptr_t *locals, jint value, int offset) { - tag_locals(locals, frame::TagValue, offset); *((jint *)&locals[Interpreter::local_index_at(-offset)]) = value; } void BytecodeInterpreter::set_locals_float(intptr_t *locals, jfloat value, int offset) { - tag_locals(locals, frame::TagValue, offset); *((jfloat *)&locals[Interpreter::local_index_at(-offset)]) = value; } void BytecodeInterpreter::set_locals_object(intptr_t *locals, oop value, int offset) { - tag_locals(locals, frame::TagReference, offset); *((oop *)&locals[Interpreter::local_index_at(-offset)]) = value; } void BytecodeInterpreter::set_locals_double(intptr_t *locals, jdouble value, int offset) { - tag_locals(locals, frame::TagValue, offset); - tag_locals(locals, frame::TagValue, offset+1); ((VMJavaVal64*)&locals[Interpreter::local_index_at(-(offset+1))])->d = value; } void BytecodeInterpreter::set_locals_long(intptr_t *locals, jlong value, int offset) { - tag_locals(locals, frame::TagValue, offset); - tag_locals(locals, frame::TagValue, offset+1); ((VMJavaVal64*)&locals[Interpreter::local_index_at(-(offset+1))])->l = value; } void BytecodeInterpreter::set_locals_double_from_addr(intptr_t *locals, address addr, int offset) { - tag_locals(locals, frame::TagValue, offset); - tag_locals(locals, frame::TagValue, offset+1); ((VMJavaVal64*)&locals[Interpreter::local_index_at(-(offset+1))])->d = ((VMJavaVal64*)addr)->d; } void BytecodeInterpreter::set_locals_long_from_addr(intptr_t *locals, address addr, int offset) { - tag_locals(locals, frame::TagValue, offset); - tag_locals(locals, frame::TagValue, offset+1); ((VMJavaVal64*)&locals[Interpreter::local_index_at(-(offset+1))])->l = ((VMJavaVal64*)addr)->l; } void BytecodeInterpreter::astore(intptr_t* tos, int stack_offset, intptr_t* locals, int locals_offset) { - // Copy tag from stack to locals. astore's operand can be returnAddress - // and may not be TagReference - if (TaggedStackInterpreter) { - frame::Tag t = (frame::Tag) tos[Interpreter::expr_tag_index_at(-stack_offset)]; - locals[Interpreter::local_tag_index_at(-locals_offset)] = (intptr_t)t; - } intptr_t value = tos[Interpreter::expr_index_at(-stack_offset)]; locals[Interpreter::local_index_at(-locals_offset)] = value; } @@ -2912,10 +2834,6 @@ void BytecodeInterpreter::astore(intptr_t* tos, int stack_offset, void BytecodeInterpreter::copy_stack_slot(intptr_t *tos, int from_offset, int to_offset) { - if (TaggedStackInterpreter) { - tos[Interpreter::expr_tag_index_at(-to_offset)] = - (intptr_t)tos[Interpreter::expr_tag_index_at(-from_offset)]; - } tos[Interpreter::expr_index_at(-to_offset)] = (intptr_t)tos[Interpreter::expr_index_at(-from_offset)]; } @@ -2964,16 +2882,9 @@ void BytecodeInterpreter::dup2_x2(intptr_t *tos) { void BytecodeInterpreter::swap(intptr_t *tos) { // swap top two elements intptr_t val = tos[Interpreter::expr_index_at(1)]; - frame::Tag t; - if (TaggedStackInterpreter) { - t = (frame::Tag) tos[Interpreter::expr_tag_index_at(1)]; - } // Copy -2 entry to -1 copy_stack_slot(tos, -2, -1); // Store saved -1 entry into -2 - if (TaggedStackInterpreter) { - tos[Interpreter::expr_tag_index_at(2)] = (intptr_t)t; - } tos[Interpreter::expr_index_at(2)] = val; } // -------------------------------------------------------------------------------- diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp index 78a6af5549e..84d4fd762f7 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp @@ -1067,7 +1067,7 @@ IRT_ENTRY(void, InterpreterRuntime::post_field_modification(JavaThread *thread, jlong_accessor u; jint* newval = (jint*)value; u.words[0] = newval[0]; - u.words[1] = newval[Interpreter::stackElementWords()]; // skip if tag + u.words[1] = newval[Interpreter::stackElementWords]; // skip if tag fvalue.j = u.long_value; #endif // _LP64 @@ -1252,6 +1252,6 @@ IRT_LEAF(void, InterpreterRuntime::popframe_move_outgoing_args(JavaThread* threa ArgumentSizeComputer asc(invoke->signature()); int size_of_arguments = (asc.size() + (invoke->has_receiver() ? 1 : 0)); // receiver Copy::conjoint_bytes(src_address, dest_address, - size_of_arguments * Interpreter::stackElementSize()); + size_of_arguments * Interpreter::stackElementSize); IRT_END #endif diff --git a/hotspot/src/share/vm/oops/methodOop.cpp b/hotspot/src/share/vm/oops/methodOop.cpp index 07ef9a8b9a5..06825af6c9d 100644 --- a/hotspot/src/share/vm/oops/methodOop.cpp +++ b/hotspot/src/share/vm/oops/methodOop.cpp @@ -306,7 +306,7 @@ void methodOopDesc::cleanup_inline_caches() { int methodOopDesc::extra_stack_words() { // not an inline function, to avoid a header dependency on Interpreter - return extra_stack_entries() * Interpreter::stackElementSize(); + return extra_stack_entries() * Interpreter::stackElementSize; } diff --git a/hotspot/src/share/vm/prims/methodHandles.hpp b/hotspot/src/share/vm/prims/methodHandles.hpp index 7e31e08438a..fc810b9d64e 100644 --- a/hotspot/src/share/vm/prims/methodHandles.hpp +++ b/hotspot/src/share/vm/prims/methodHandles.hpp @@ -163,7 +163,7 @@ class MethodHandles: AllStatic { default: ShouldNotReachHere(); } // Return the size of the stack slots to move in bytes. - swap_bytes = swap_slots * Interpreter::stackElementSize(); + swap_bytes = swap_slots * Interpreter::stackElementSize; } static int get_ek_adapter_opt_spread_info(EntryKind ek) { @@ -219,7 +219,7 @@ class MethodHandles: AllStatic { // Offset in words that the interpreter stack pointer moves when an argument is pushed. // The stack_move value must always be a multiple of this. static int stack_move_unit() { - return frame::interpreter_frame_expression_stack_direction() * Interpreter::stackElementWords(); + return frame::interpreter_frame_expression_stack_direction() * Interpreter::stackElementWords; } enum { CONV_VMINFO_SIGN_FLAG = 0x80 }; diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 7984761451c..963b22df502 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -2867,12 +2867,6 @@ jint Arguments::parse(const JavaVMInitArgs* args) { } #endif // _LP64 - // MethodHandles code does not support TaggedStackInterpreter. - if (EnableMethodHandles && TaggedStackInterpreter) { - warning("TaggedStackInterpreter is not supported by MethodHandles code. Disabling TaggedStackInterpreter."); - TaggedStackInterpreter = false; - } - // Check the GC selections again. if (!check_gc_consistency()) { return JNI_EINVAL; @@ -2915,11 +2909,6 @@ jint Arguments::parse(const JavaVMInitArgs* args) { LP64_ONLY(FLAG_SET_DEFAULT(UseCompressedOops, false)); #endif // CC_INTERP -#ifdef ZERO - // Clear flags not supported by Zero - FLAG_SET_DEFAULT(TaggedStackInterpreter, false); -#endif // ZERO - #ifdef COMPILER2 if (!UseBiasedLocking || EmitSync != 0) { UseOptoBiasInlining = false; diff --git a/hotspot/src/share/vm/runtime/frame.cpp b/hotspot/src/share/vm/runtime/frame.cpp index 30782f355c6..5292bd4bec6 100644 --- a/hotspot/src/share/vm/runtime/frame.cpp +++ b/hotspot/src/share/vm/runtime/frame.cpp @@ -468,42 +468,16 @@ intptr_t* frame::interpreter_frame_local_at(int index) const { return &((*interpreter_frame_locals_addr())[n]); } -frame::Tag frame::interpreter_frame_local_tag(int index) const { - const int n = Interpreter::local_tag_offset_in_bytes(index)/wordSize; - return (Tag)(*interpreter_frame_locals_addr()) [n]; -} - -void frame::interpreter_frame_set_local_tag(int index, Tag tag) const { - const int n = Interpreter::local_tag_offset_in_bytes(index)/wordSize; - (*interpreter_frame_locals_addr())[n] = (intptr_t)tag; -} - intptr_t* frame::interpreter_frame_expression_stack_at(jint offset) const { const int i = offset * interpreter_frame_expression_stack_direction(); - const int n = ((i * Interpreter::stackElementSize()) + - Interpreter::value_offset_in_bytes())/wordSize; + const int n = i * Interpreter::stackElementWords; return &(interpreter_frame_expression_stack()[n]); } -frame::Tag frame::interpreter_frame_expression_stack_tag(jint offset) const { - const int i = offset * interpreter_frame_expression_stack_direction(); - const int n = ((i * Interpreter::stackElementSize()) + - Interpreter::tag_offset_in_bytes())/wordSize; - return (Tag)(interpreter_frame_expression_stack()[n]); -} - -void frame::interpreter_frame_set_expression_stack_tag(jint offset, - Tag tag) const { - const int i = offset * interpreter_frame_expression_stack_direction(); - const int n = ((i * Interpreter::stackElementSize()) + - Interpreter::tag_offset_in_bytes())/wordSize; - interpreter_frame_expression_stack()[n] = (intptr_t)tag; -} - jint frame::interpreter_frame_expression_stack_size() const { // Number of elements on the interpreter expression stack // Callers should span by stackElementWords - int element_size = Interpreter::stackElementWords(); + int element_size = Interpreter::stackElementWords; if (frame::interpreter_frame_expression_stack_direction() < 0) { return (interpreter_frame_expression_stack() - interpreter_frame_tos_address() + 1)/element_size; @@ -585,20 +559,12 @@ void frame::interpreter_frame_print_on(outputStream* st) const { for (i = 0; i < interpreter_frame_method()->max_locals(); i++ ) { intptr_t x = *interpreter_frame_local_at(i); st->print(" - local [" INTPTR_FORMAT "]", x); - if (TaggedStackInterpreter) { - Tag x = interpreter_frame_local_tag(i); - st->print(" - local tag [" INTPTR_FORMAT "]", x); - } st->fill_to(23); st->print_cr("; #%d", i); } for (i = interpreter_frame_expression_stack_size() - 1; i >= 0; --i ) { intptr_t x = *interpreter_frame_expression_stack_at(i); st->print(" - stack [" INTPTR_FORMAT "]", x); - if (TaggedStackInterpreter) { - Tag x = interpreter_frame_expression_stack_tag(i); - st->print(" - stack tag [" INTPTR_FORMAT "]", x); - } st->fill_to(23); st->print_cr("; #%d", i); } @@ -950,103 +916,19 @@ void frame::oops_interpreted_do(OopClosure* f, const RegisterMap* map, bool quer } } - if (TaggedStackInterpreter) { - // process locals & expression stack - InterpreterOopMap *mask = NULL; -#ifdef ASSERT - InterpreterOopMap oopmap_mask; - OopMapCache::compute_one_oop_map(m, bci, &oopmap_mask); - mask = &oopmap_mask; -#endif // ASSERT - oops_interpreted_locals_do(f, max_locals, mask); - oops_interpreted_expressions_do(f, signature, has_receiver, - m->max_stack(), - max_locals, mask); + InterpreterFrameClosure blk(this, max_locals, m->max_stack(), f); + + // process locals & expression stack + InterpreterOopMap mask; + if (query_oop_map_cache) { + m->mask_for(bci, &mask); } else { - InterpreterFrameClosure blk(this, max_locals, m->max_stack(), f); - - // process locals & expression stack - InterpreterOopMap mask; - if (query_oop_map_cache) { - m->mask_for(bci, &mask); - } else { - OopMapCache::compute_one_oop_map(m, bci, &mask); - } - mask.iterate_oop(&blk); + OopMapCache::compute_one_oop_map(m, bci, &mask); } + mask.iterate_oop(&blk); } -void frame::oops_interpreted_locals_do(OopClosure *f, - int max_locals, - InterpreterOopMap *mask) { - // Process locals then interpreter expression stack - for (int i = 0; i < max_locals; i++ ) { - Tag tag = interpreter_frame_local_tag(i); - if (tag == TagReference) { - oop* addr = (oop*) interpreter_frame_local_at(i); - assert((intptr_t*)addr >= sp(), "must be inside the frame"); - f->do_oop(addr); -#ifdef ASSERT - } else { - assert(tag == TagValue, "bad tag value for locals"); - oop* p = (oop*) interpreter_frame_local_at(i); - // Not always true - too bad. May have dead oops without tags in locals. - // assert(*p == NULL || !(*p)->is_oop(), "oop not tagged on interpreter locals"); - assert(*p == NULL || !mask->is_oop(i), "local oop map mismatch"); -#endif // ASSERT - } - } -} - -void frame::oops_interpreted_expressions_do(OopClosure *f, - symbolHandle signature, - bool has_receiver, - int max_stack, - int max_locals, - InterpreterOopMap *mask) { - // There is no stack no matter what the esp is pointing to (native methods - // might look like expression stack is nonempty). - if (max_stack == 0) return; - - // Point the top of the expression stack above arguments to a call so - // arguments aren't gc'ed as both stack values for callee and callee - // arguments in callee's locals. - int args_size = 0; - if (!signature.is_null()) { - args_size = ArgumentSizeComputer(signature).size() + (has_receiver ? 1 : 0); - } - - intptr_t *tos_addr = interpreter_frame_tos_at(args_size); - assert(args_size != 0 || tos_addr == interpreter_frame_tos_address(), "these are same"); - intptr_t *frst_expr = interpreter_frame_expression_stack_at(0); - // In case of exceptions, the expression stack is invalid and the esp - // will be reset to express this condition. Therefore, we call f only - // if addr is 'inside' the stack (i.e., addr >= esp for Intel). - bool in_stack; - if (interpreter_frame_expression_stack_direction() > 0) { - in_stack = (intptr_t*)frst_expr <= tos_addr; - } else { - in_stack = (intptr_t*)frst_expr >= tos_addr; - } - if (!in_stack) return; - - jint stack_size = interpreter_frame_expression_stack_size() - args_size; - for (int j = 0; j < stack_size; j++) { - Tag tag = interpreter_frame_expression_stack_tag(j); - if (tag == TagReference) { - oop *addr = (oop*) interpreter_frame_expression_stack_at(j); - f->do_oop(addr); -#ifdef ASSERT - } else { - assert(tag == TagValue, "bad tag value for stack element"); - oop *p = (oop*) interpreter_frame_expression_stack_at((j)); - assert(*p == NULL || !mask->is_oop(j+max_locals), "stack oop map mismatch"); -#endif // ASSERT - } - } -} - void frame::oops_interpreted_arguments_do(symbolHandle signature, bool has_receiver, OopClosure* f) { InterpretedArgumentOopFinder finder(signature, has_receiver, this, f); finder.oops_do(); @@ -1306,29 +1188,18 @@ void frame::zap_dead_interpreted_locals(JavaThread *thread, const RegisterMap* m int max_locals = m->is_native() ? m->size_of_parameters() : m->max_locals(); - if (TaggedStackInterpreter) { - InterpreterOopMap *mask = NULL; -#ifdef ASSERT - InterpreterOopMap oopmap_mask; - methodHandle method(thread, m); - OopMapCache::compute_one_oop_map(method, bci, &oopmap_mask); - mask = &oopmap_mask; -#endif // ASSERT - oops_interpreted_locals_do(&_check_oop, max_locals, mask); - } else { - // process dynamic part - InterpreterFrameClosure value_blk(this, max_locals, m->max_stack(), - &_check_value); - InterpreterFrameClosure oop_blk(this, max_locals, m->max_stack(), - &_check_oop ); - InterpreterFrameClosure dead_blk(this, max_locals, m->max_stack(), - &_zap_dead ); + // process dynamic part + InterpreterFrameClosure value_blk(this, max_locals, m->max_stack(), + &_check_value); + InterpreterFrameClosure oop_blk(this, max_locals, m->max_stack(), + &_check_oop ); + InterpreterFrameClosure dead_blk(this, max_locals, m->max_stack(), + &_zap_dead ); - // get frame map - InterpreterOopMap mask; - m->mask_for(bci, &mask); - mask.iterate_all( &oop_blk, &value_blk, &dead_blk); - } + // get frame map + InterpreterOopMap mask; + m->mask_for(bci, &mask); + mask.iterate_all( &oop_blk, &value_blk, &dead_blk); } diff --git a/hotspot/src/share/vm/runtime/frame.hpp b/hotspot/src/share/vm/runtime/frame.hpp index 92df6b353d5..ab8084674fb 100644 --- a/hotspot/src/share/vm/runtime/frame.hpp +++ b/hotspot/src/share/vm/runtime/frame.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2009 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 @@ -191,26 +191,10 @@ class frame VALUE_OBJ_CLASS_SPEC { intptr_t* interpreter_frame_mdx_addr() const; public: - // Tags for TaggedStackInterpreter - enum Tag { - TagValue = 0, // Important: must be zero to use G0 on sparc. - TagReference = 0x555, // Reference type - is an oop that needs gc. - TagCategory2 = 0x666 // Only used internally by interpreter - // and not written to the java stack. - // The values above are chosen so that misuse causes a crash - // with a recognizable value. - }; - - static Tag tag_for_basic_type(BasicType typ) { - return (typ == T_OBJECT ? TagReference : TagValue); - } - // Locals // The _at version returns a pointer because the address is used for GC. intptr_t* interpreter_frame_local_at(int index) const; - Tag interpreter_frame_local_tag(int index) const; - void interpreter_frame_set_local_tag(int index, Tag tag) const; void interpreter_frame_set_locals(intptr_t* locs); @@ -260,8 +244,6 @@ class frame VALUE_OBJ_CLASS_SPEC { // The _at version returns a pointer because the address is used for GC. intptr_t* interpreter_frame_expression_stack_at(jint offset) const; - Tag interpreter_frame_expression_stack_tag(jint offset) const; - void interpreter_frame_set_expression_stack_tag(jint offset, Tag tag) const; // top of expression stack intptr_t* interpreter_frame_tos_at(jint offset) const; @@ -375,12 +357,6 @@ class frame VALUE_OBJ_CLASS_SPEC { void oops_interpreted_do(OopClosure* f, const RegisterMap* map, bool query_oop_map_cache = true); private: - void oops_interpreted_locals_do(OopClosure *f, - int max_locals, - InterpreterOopMap *mask); - void oops_interpreted_expressions_do(OopClosure *f, symbolHandle signature, - bool has_receiver, int max_stack, int max_locals, - InterpreterOopMap *mask); void oops_interpreted_arguments_do(symbolHandle signature, bool has_receiver, OopClosure* f); // Iteration of oops diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 861d89cb699..fd345f91393 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2009 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 @@ -3497,9 +3497,6 @@ class CommandLineFlags { develop(bool, TraceInvokeDynamic, false, \ "trace internal invoke dynamic operations") \ \ - product(bool, TaggedStackInterpreter, false, \ - "Insert tags in interpreter execution stack for oopmap generaion")\ - \ diagnostic(bool, PauseAtStartup, false, \ "Causes the VM to pause at startup time and wait for the pause " \ "file to be removed (default: ./vm.paused.)") \ diff --git a/hotspot/src/share/vm/runtime/javaCalls.cpp b/hotspot/src/share/vm/runtime/javaCalls.cpp index a64fdb07a89..0abe9416973 100644 --- a/hotspot/src/share/vm/runtime/javaCalls.cpp +++ b/hotspot/src/share/vm/runtime/javaCalls.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2009 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 @@ -417,17 +417,9 @@ intptr_t* JavaCallArguments::parameters() { // Handle conversion _value[i] = (intptr_t)Handle::raw_resolve((oop *)_value[i]); } - // The parameters are moved to the parameters array to include the tags. - if (TaggedStackInterpreter) { - // Tags are interspersed with arguments. Tags are first. - int tagged_index = i*2; - _parameters[tagged_index] = _is_oop[i] ? frame::TagReference : - frame::TagValue; - _parameters[tagged_index+1] = _value[i]; - } } // Return argument vector - return TaggedStackInterpreter ? _parameters : _value; + return _value; } diff --git a/hotspot/src/share/vm/runtime/javaCalls.hpp b/hotspot/src/share/vm/runtime/javaCalls.hpp index 345206f02c5..2921d59707f 100644 --- a/hotspot/src/share/vm/runtime/javaCalls.hpp +++ b/hotspot/src/share/vm/runtime/javaCalls.hpp @@ -66,11 +66,9 @@ class JavaCallArguments : public StackObj { }; intptr_t _value_buffer [_default_size + 1]; - intptr_t _parameter_buffer [_default_size*2 + 1]; bool _is_oop_buffer[_default_size + 1]; intptr_t* _value; - intptr_t* _parameters; bool* _is_oop; int _size; int _max_size; @@ -81,7 +79,6 @@ class JavaCallArguments : public StackObj { _value = &_value_buffer[1]; _is_oop = &_is_oop_buffer[1]; - _parameters = &_parameter_buffer[0]; _max_size = _default_size; _size = 0; _start_at_zero = false; @@ -99,11 +96,10 @@ class JavaCallArguments : public StackObj { if (max_size > _default_size) { _value = NEW_RESOURCE_ARRAY(intptr_t, max_size + 1); _is_oop = NEW_RESOURCE_ARRAY(bool, max_size + 1); - if (TaggedStackInterpreter) { - _parameters = NEW_RESOURCE_ARRAY(intptr_t, max_size*2 + 1); - } + // Reserve room for potential receiver in value and is_oop _value++; _is_oop++; + _max_size = max_size; _size = 0; _start_at_zero = false; diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp index 06af4af32cd..1b164ab6f5b 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp @@ -1842,14 +1842,11 @@ class AdapterFingerPrint : public CHeapObj { case T_OBJECT: case T_ARRAY: - if (!TaggedStackInterpreter) { #ifdef _LP64 - return T_LONG; + return T_LONG; #else - return T_INT; + return T_INT; #endif - } - return T_OBJECT; case T_INT: case T_LONG: @@ -2595,17 +2592,9 @@ JRT_LEAF(intptr_t*, SharedRuntime::OSR_migration_begin( JavaThread *thread) ) // Copy the locals. Order is preserved so that loading of longs works. // Since there's no GC I can copy the oops blindly. assert( sizeof(HeapWord)==sizeof(intptr_t), "fix this code"); - if (TaggedStackInterpreter) { - for (int i = 0; i < max_locals; i++) { - // copy only each local separately to the buffer avoiding the tag - buf[i] = *fr.interpreter_frame_local_at(max_locals-i-1); - } - } else { - Copy::disjoint_words( - (HeapWord*)fr.interpreter_frame_local_at(max_locals-1), + Copy::disjoint_words((HeapWord*)fr.interpreter_frame_local_at(max_locals-1), (HeapWord*)&buf[0], max_locals); - } // Inflate locks. Copy the displaced headers. Be careful, there can be holes. int i = max_locals; diff --git a/hotspot/src/share/vm/runtime/vframe.cpp b/hotspot/src/share/vm/runtime/vframe.cpp index 1b5a7f8a0c1..a4d25b20f09 100644 --- a/hotspot/src/share/vm/runtime/vframe.cpp +++ b/hotspot/src/share/vm/runtime/vframe.cpp @@ -244,51 +244,30 @@ StackValueCollection* interpretedVFrame::locals() const { StackValueCollection* result = new StackValueCollection(length); // Get oopmap describing oops and int for current bci - if (TaggedStackInterpreter) { - for(int i=0; i < length; i++) { - // Find stack location - intptr_t *addr = locals_addr_at(i); - - // Depending on oop/int put it in the right package - StackValue *sv; - frame::Tag tag = fr().interpreter_frame_local_tag(i); - if (tag == frame::TagReference) { - // oop value - Handle h(*(oop *)addr); - sv = new StackValue(h); - } else { - // integer - sv = new StackValue(*addr); - } - assert(sv != NULL, "sanity check"); - result->add(sv); - } + InterpreterOopMap oop_mask; + if (TraceDeoptimization && Verbose) { + methodHandle m_h(thread(), method()); + OopMapCache::compute_one_oop_map(m_h, bci(), &oop_mask); } else { - InterpreterOopMap oop_mask; - if (TraceDeoptimization && Verbose) { - methodHandle m_h(thread(), method()); - OopMapCache::compute_one_oop_map(m_h, bci(), &oop_mask); - } else { - method()->mask_for(bci(), &oop_mask); - } - // handle locals - for(int i=0; i < length; i++) { - // Find stack location - intptr_t *addr = locals_addr_at(i); + method()->mask_for(bci(), &oop_mask); + } + // handle locals + for(int i=0; i < length; i++) { + // Find stack location + intptr_t *addr = locals_addr_at(i); - // Depending on oop/int put it in the right package - StackValue *sv; - if (oop_mask.is_oop(i)) { - // oop value - Handle h(*(oop *)addr); - sv = new StackValue(h); - } else { - // integer - sv = new StackValue(*addr); - } - assert(sv != NULL, "sanity check"); - result->add(sv); + // Depending on oop/int put it in the right package + StackValue *sv; + if (oop_mask.is_oop(i)) { + // oop value + Handle h(*(oop *)addr); + sv = new StackValue(h); + } else { + // integer + sv = new StackValue(*addr); } + assert(sv != NULL, "sanity check"); + result->add(sv); } return result; } @@ -331,53 +310,31 @@ StackValueCollection* interpretedVFrame::expressions() const { int nof_locals = method()->max_locals(); StackValueCollection* result = new StackValueCollection(length); - if (TaggedStackInterpreter) { - // handle expressions - for(int i=0; i < length; i++) { - // Find stack location - intptr_t *addr = fr().interpreter_frame_expression_stack_at(i); - frame::Tag tag = fr().interpreter_frame_expression_stack_tag(i); - - // Depending on oop/int put it in the right package - StackValue *sv; - if (tag == frame::TagReference) { - // oop value - Handle h(*(oop *)addr); - sv = new StackValue(h); - } else { - // otherwise - sv = new StackValue(*addr); - } - assert(sv != NULL, "sanity check"); - result->add(sv); - } + InterpreterOopMap oop_mask; + // Get oopmap describing oops and int for current bci + if (TraceDeoptimization && Verbose) { + methodHandle m_h(method()); + OopMapCache::compute_one_oop_map(m_h, bci(), &oop_mask); } else { - InterpreterOopMap oop_mask; - // Get oopmap describing oops and int for current bci - if (TraceDeoptimization && Verbose) { - methodHandle m_h(method()); - OopMapCache::compute_one_oop_map(m_h, bci(), &oop_mask); - } else { - method()->mask_for(bci(), &oop_mask); - } - // handle expressions - for(int i=0; i < length; i++) { - // Find stack location - intptr_t *addr = fr().interpreter_frame_expression_stack_at(i); + method()->mask_for(bci(), &oop_mask); + } + // handle expressions + for(int i=0; i < length; i++) { + // Find stack location + intptr_t *addr = fr().interpreter_frame_expression_stack_at(i); - // Depending on oop/int put it in the right package - StackValue *sv; - if (oop_mask.is_oop(i + nof_locals)) { - // oop value - Handle h(*(oop *)addr); - sv = new StackValue(h); - } else { - // integer - sv = new StackValue(*addr); - } - assert(sv != NULL, "sanity check"); - result->add(sv); + // Depending on oop/int put it in the right package + StackValue *sv; + if (oop_mask.is_oop(i + nof_locals)) { + // oop value + Handle h(*(oop *)addr); + sv = new StackValue(h); + } else { + // integer + sv = new StackValue(*addr); } + assert(sv != NULL, "sanity check"); + result->add(sv); } return result; } diff --git a/hotspot/src/share/vm/runtime/vframeArray.cpp b/hotspot/src/share/vm/runtime/vframeArray.cpp index 2fb27dfd920..f76b9e2c608 100644 --- a/hotspot/src/share/vm/runtime/vframeArray.cpp +++ b/hotspot/src/share/vm/runtime/vframeArray.cpp @@ -309,11 +309,6 @@ void vframeArrayElement::unpack_on_stack(int callee_parameters, default: ShouldNotReachHere(); } - if (TaggedStackInterpreter) { - // Write tag to the stack - iframe()->interpreter_frame_set_expression_stack_tag(i, - frame::tag_for_basic_type(value->type())); - } } @@ -335,11 +330,6 @@ void vframeArrayElement::unpack_on_stack(int callee_parameters, default: ShouldNotReachHere(); } - if (TaggedStackInterpreter) { - // Write tag to stack - iframe()->interpreter_frame_set_local_tag(i, - frame::tag_for_basic_type(value->type())); - } } if (is_top_frame && JvmtiExport::can_pop_frame() && thread->popframe_forcing_deopt_reexecution()) { @@ -354,9 +344,8 @@ void vframeArrayElement::unpack_on_stack(int callee_parameters, void* saved_args = thread->popframe_preserved_args(); assert(saved_args != NULL, "must have been saved by interpreter"); #ifdef ASSERT - int stack_words = Interpreter::stackElementWords(); assert(popframe_preserved_args_size_in_words <= - iframe()->interpreter_frame_expression_stack_size()*stack_words, + iframe()->interpreter_frame_expression_stack_size()*Interpreter::stackElementWords, "expression stack size should have been extended"); #endif // ASSERT int top_element = iframe()->interpreter_frame_expression_stack_size()-1; From 4eb75c2df3fba71e551872578249fc65d5872ebc Mon Sep 17 00:00:00 2001 From: John R Rose Date: Sat, 1 May 2010 02:42:18 -0700 Subject: [PATCH 20/54] 6939134: JSR 292 adjustments to method handle invocation Split MethodHandle.invoke into invokeExact and invokeGeneric; also clean up JVM-to-Java interfaces Reviewed-by: twisti --- .../src/cpu/sparc/vm/methodHandles_sparc.cpp | 15 +++ hotspot/src/cpu/x86/vm/methodHandles_x86.cpp | 16 +++ hotspot/src/share/vm/c1/c1_LIR.hpp | 2 +- hotspot/src/share/vm/ci/ciEnv.cpp | 29 +++-- hotspot/src/share/vm/ci/ciObjectFactory.cpp | 5 +- hotspot/src/share/vm/ci/ciSymbol.cpp | 12 +- hotspot/src/share/vm/ci/ciSymbol.hpp | 10 +- .../share/vm/classfile/classFileParser.cpp | 3 +- hotspot/src/share/vm/classfile/dictionary.cpp | 15 +-- hotspot/src/share/vm/classfile/dictionary.hpp | 20 ++- .../src/share/vm/classfile/javaClasses.cpp | 30 +++-- .../src/share/vm/classfile/javaClasses.hpp | 17 +-- .../share/vm/classfile/systemDictionary.cpp | 117 ++++++----------- .../share/vm/classfile/systemDictionary.hpp | 31 ++--- hotspot/src/share/vm/classfile/vmSymbols.hpp | 30 +++-- hotspot/src/share/vm/includeDB_core | 3 + .../vm/interpreter/interpreterRuntime.cpp | 52 ++++---- .../src/share/vm/interpreter/linkResolver.cpp | 21 +++- hotspot/src/share/vm/memory/universe.cpp | 2 +- hotspot/src/share/vm/oops/cpCacheOop.cpp | 13 +- hotspot/src/share/vm/oops/cpCacheOop.hpp | 2 +- hotspot/src/share/vm/oops/methodKlass.cpp | 8 +- hotspot/src/share/vm/oops/methodOop.cpp | 43 +++++-- hotspot/src/share/vm/oops/methodOop.hpp | 7 +- hotspot/src/share/vm/opto/bytecodeInfo.cpp | 5 - .../src/share/vm/prims/methodHandleWalk.cpp | 5 +- hotspot/src/share/vm/prims/methodHandles.cpp | 119 ++++++++++++++---- hotspot/src/share/vm/prims/methodHandles.hpp | 12 +- .../src/share/vm/runtime/sharedRuntime.cpp | 2 +- 29 files changed, 413 insertions(+), 233 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp index 3eeb885e497..2c26318b135 100644 --- a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp @@ -290,6 +290,21 @@ void trace_method_handle_stub(const char* adaptername, } #endif // PRODUCT +// which conversion op types are implemented here? +int MethodHandles::adapter_conversion_ops_supported_mask() { + return ((1<holder()->name() == ciSymbol::java_dyn_MethodHandle() && - method()->name() == ciSymbol::invoke_name()); + methodOopDesc::is_method_handle_invoke_name(method()->name()->sid())); } intptr_t vtable_offset() const { diff --git a/hotspot/src/share/vm/ci/ciEnv.cpp b/hotspot/src/share/vm/ci/ciEnv.cpp index b947e50ab8f..7698c63a334 100644 --- a/hotspot/src/share/vm/ci/ciEnv.cpp +++ b/hotspot/src/share/vm/ci/ciEnv.cpp @@ -731,26 +731,29 @@ ciMethod* ciEnv::get_method_by_index_impl(constantPoolHandle cpool, // ciEnv::get_fake_invokedynamic_method_impl ciMethod* ciEnv::get_fake_invokedynamic_method_impl(constantPoolHandle cpool, int index, Bytecodes::Code bc) { + // Compare the following logic with InterpreterRuntime::resolve_invokedynamic. assert(bc == Bytecodes::_invokedynamic, "must be invokedynamic"); - // Get the CallSite from the constant pool cache. - ConstantPoolCacheEntry* cpc_entry = cpool->cache()->secondary_entry_at(index); - assert(cpc_entry != NULL && cpc_entry->is_secondary_entry(), "sanity"); - Handle call_site = cpc_entry->f1(); + bool is_resolved = cpool->cache()->main_entry_at(index)->is_resolved(bc); + if (is_resolved && (oop) cpool->cache()->secondary_entry_at(index)->f1() == NULL) + // FIXME: code generation could allow for null (unlinked) call site + is_resolved = false; - // Call site might not be linked yet. - if (call_site.is_null()) { + // Call site might not be resolved yet. We could create a real invoker method from the + // compiler, but it is simpler to stop the code path here with an unlinked method. + if (!is_resolved) { ciInstanceKlass* mh_klass = get_object(SystemDictionary::MethodHandle_klass())->as_instance_klass(); - ciSymbol* sig_sym = get_object(cpool->signature_ref_at(index))->as_symbol(); - return get_unloaded_method(mh_klass, ciSymbol::invoke_name(), sig_sym); + ciSymbol* sig_sym = get_object(cpool->signature_ref_at(index))->as_symbol(); + return get_unloaded_method(mh_klass, ciSymbol::invokeExact_name(), sig_sym); } - // Get the methodOop from the CallSite. - methodOop method_oop = (methodOop) java_dyn_CallSite::vmmethod(call_site()); - assert(method_oop != NULL, "sanity"); - assert(method_oop->is_method_handle_invoke(), "consistent"); + // Get the invoker methodOop from the constant pool. + intptr_t f2_value = cpool->cache()->main_entry_at(index)->f2(); + methodOop signature_invoker = methodOop(f2_value); + assert(signature_invoker != NULL && signature_invoker->is_method() && signature_invoker->is_method_handle_invoke(), + "correct result from LinkResolver::resolve_invokedynamic"); - return get_object(method_oop)->as_method(); + return get_object(signature_invoker)->as_method(); } diff --git a/hotspot/src/share/vm/ci/ciObjectFactory.cpp b/hotspot/src/share/vm/ci/ciObjectFactory.cpp index cfbdf1659eb..79c13177e08 100644 --- a/hotspot/src/share/vm/ci/ciObjectFactory.cpp +++ b/hotspot/src/share/vm/ci/ciObjectFactory.cpp @@ -103,7 +103,7 @@ void ciObjectFactory::init_shared_objects() { for (i = vmSymbols::FIRST_SID; i < vmSymbols::SID_LIMIT; i++) { symbolHandle sym_handle = vmSymbolHandles::symbol_handle_at((vmSymbols::SID) i); assert(vmSymbols::find_sid(sym_handle()) == i, "1-1 mapping"); - ciSymbol* sym = new (_arena) ciSymbol(sym_handle); + ciSymbol* sym = new (_arena) ciSymbol(sym_handle, (vmSymbols::SID) i); init_ident_of(sym); _shared_ci_symbols[i] = sym; } @@ -273,7 +273,8 @@ ciObject* ciObjectFactory::create_new_object(oop o) { if (o->is_symbol()) { symbolHandle h_o(THREAD, (symbolOop)o); - return new (arena()) ciSymbol(h_o); + assert(vmSymbols::find_sid(h_o()) == vmSymbols::NO_SID, ""); + return new (arena()) ciSymbol(h_o, vmSymbols::NO_SID); } else if (o->is_klass()) { KlassHandle h_k(THREAD, (klassOop)o); Klass* k = ((klassOop)o)->klass_part(); diff --git a/hotspot/src/share/vm/ci/ciSymbol.cpp b/hotspot/src/share/vm/ci/ciSymbol.cpp index e534f04c3de..319f3327a11 100644 --- a/hotspot/src/share/vm/ci/ciSymbol.cpp +++ b/hotspot/src/share/vm/ci/ciSymbol.cpp @@ -29,7 +29,17 @@ // ciSymbol::ciSymbol // // Preallocated handle variant. Used with handles from vmSymboHandles. -ciSymbol::ciSymbol(symbolHandle h_s) : ciObject(h_s) { +ciSymbol::ciSymbol(symbolHandle h_s, vmSymbols::SID sid) + : ciObject(h_s), _sid(sid) +{ + assert(sid_ok(), "must be in vmSymbols"); +} + +// Normal case for non-famous symbols. +ciSymbol::ciSymbol(symbolOop s) + : ciObject(s), _sid(vmSymbols::NO_SID) +{ + assert(sid_ok(), "must not be in vmSymbols"); } // ciSymbol diff --git a/hotspot/src/share/vm/ci/ciSymbol.hpp b/hotspot/src/share/vm/ci/ciSymbol.hpp index abb3088edbf..db5cdc823fd 100644 --- a/hotspot/src/share/vm/ci/ciSymbol.hpp +++ b/hotspot/src/share/vm/ci/ciSymbol.hpp @@ -36,8 +36,11 @@ class ciSymbol : public ciObject { friend class ciObjArrayKlass; private: - ciSymbol(symbolOop s) : ciObject(s) {} - ciSymbol(symbolHandle s); // for use with vmSymbolHandles + const vmSymbols::SID _sid; + DEBUG_ONLY( bool sid_ok() { return vmSymbols::find_sid(get_symbolOop()) == _sid; } ) + + ciSymbol(symbolOop s); // normal case, for symbols not mentioned in vmSymbols + ciSymbol(symbolHandle s, vmSymbols::SID sid); // for use with vmSymbolHandles symbolOop get_symbolOop() const { return (symbolOop)get_oop(); } @@ -52,6 +55,9 @@ private: static ciSymbol* make_impl(const char* s); public: + // The enumeration ID from vmSymbols, or vmSymbols::NO_SID if none. + vmSymbols::SID sid() const { return _sid; } + // The text of the symbol as a null-terminated utf8 string. const char* as_utf8(); int utf8_length(); diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index 23ec4746bcc..05917d1f1b8 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -1837,7 +1837,8 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf _has_vanilla_constructor = true; } - if (EnableMethodHandles && m->is_method_handle_invoke()) { + if (EnableMethodHandles && (m->is_method_handle_invoke() || + m->is_method_handle_adapter())) { THROW_MSG_(vmSymbols::java_lang_VirtualMachineError(), "Method handle invokers must be defined internally to the VM", nullHandle); } diff --git a/hotspot/src/share/vm/classfile/dictionary.cpp b/hotspot/src/share/vm/classfile/dictionary.cpp index 5bf9132f4ce..d879a2c8ba4 100644 --- a/hotspot/src/share/vm/classfile/dictionary.cpp +++ b/hotspot/src/share/vm/classfile/dictionary.cpp @@ -561,10 +561,11 @@ SymbolPropertyTable::SymbolPropertyTable(int table_size, HashtableBucket* t, SymbolPropertyEntry* SymbolPropertyTable::find_entry(int index, unsigned int hash, - symbolHandle sym) { - assert(index == index_for(sym), "incorrect index?"); + symbolHandle sym, + intptr_t sym_mode) { + assert(index == index_for(sym, sym_mode), "incorrect index?"); for (SymbolPropertyEntry* p = bucket(index); p != NULL; p = p->next()) { - if (p->hash() == hash && p->symbol() == sym()) { + if (p->hash() == hash && p->symbol() == sym() && p->symbol_mode() == sym_mode) { return p; } } @@ -573,12 +574,12 @@ SymbolPropertyEntry* SymbolPropertyTable::find_entry(int index, unsigned int has SymbolPropertyEntry* SymbolPropertyTable::add_entry(int index, unsigned int hash, - symbolHandle sym) { + symbolHandle sym, intptr_t sym_mode) { assert_locked_or_safepoint(SystemDictionary_lock); - assert(index == index_for(sym), "incorrect index?"); - assert(find_entry(index, hash, sym) == NULL, "no double entry"); + assert(index == index_for(sym, sym_mode), "incorrect index?"); + assert(find_entry(index, hash, sym, sym_mode) == NULL, "no double entry"); - SymbolPropertyEntry* p = new_entry(hash, sym()); + SymbolPropertyEntry* p = new_entry(hash, sym(), sym_mode); Hashtable::add_entry(index, p); return p; } diff --git a/hotspot/src/share/vm/classfile/dictionary.hpp b/hotspot/src/share/vm/classfile/dictionary.hpp index 4228b17cc25..e8f2bb563c7 100644 --- a/hotspot/src/share/vm/classfile/dictionary.hpp +++ b/hotspot/src/share/vm/classfile/dictionary.hpp @@ -223,12 +223,16 @@ class DictionaryEntry : public HashtableEntry { class SymbolPropertyEntry : public HashtableEntry { friend class VMStructs; private: + intptr_t _symbol_mode; // secondary key oop _property_oop; address _property_data; public: symbolOop symbol() const { return (symbolOop) literal(); } + intptr_t symbol_mode() const { return _symbol_mode; } + void set_symbol_mode(intptr_t m) { _symbol_mode = m; } + oop property_oop() const { return _property_oop; } void set_property_oop(oop p) { _property_oop = p; } @@ -248,6 +252,7 @@ class SymbolPropertyEntry : public HashtableEntry { void print_on(outputStream* st) const { symbol()->print_value_on(st); + st->print("/mode="INTX_FORMAT, symbol_mode()); st->print(" -> "); bool printed = false; if (property_oop() != NULL) { @@ -285,8 +290,9 @@ private: ShouldNotReachHere(); } - SymbolPropertyEntry* new_entry(unsigned int hash, symbolOop symbol) { + SymbolPropertyEntry* new_entry(unsigned int hash, symbolOop symbol, intptr_t symbol_mode) { SymbolPropertyEntry* entry = (SymbolPropertyEntry*) Hashtable::new_entry(hash, symbol); + entry->set_symbol_mode(symbol_mode); entry->set_property_oop(NULL); entry->set_property_data(NULL); return entry; @@ -300,16 +306,20 @@ public: Hashtable::free_entry(entry); } - unsigned int compute_hash(symbolHandle sym) { + unsigned int compute_hash(symbolHandle sym, intptr_t symbol_mode) { // Use the regular identity_hash. - return Hashtable::compute_hash(sym); + return Hashtable::compute_hash(sym) ^ symbol_mode; + } + + int index_for(symbolHandle name, intptr_t symbol_mode) { + return hash_to_index(compute_hash(name, symbol_mode)); } // need not be locked; no state change - SymbolPropertyEntry* find_entry(int index, unsigned int hash, symbolHandle name); + SymbolPropertyEntry* find_entry(int index, unsigned int hash, symbolHandle name, intptr_t name_mode); // must be done under SystemDictionary_lock - SymbolPropertyEntry* add_entry(int index, unsigned int hash, symbolHandle name); + SymbolPropertyEntry* add_entry(int index, unsigned int hash, symbolHandle name, intptr_t name_mode); // GC support void oops_do(OopClosure* f); diff --git a/hotspot/src/share/vm/classfile/javaClasses.cpp b/hotspot/src/share/vm/classfile/javaClasses.cpp index 730f1c7abc8..26008cd6e9c 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.cpp +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp @@ -2446,24 +2446,20 @@ oop java_dyn_MethodTypeForm::erasedType(oop mtform) { // Support for java_dyn_CallSite -int java_dyn_CallSite::_type_offset; int java_dyn_CallSite::_target_offset; -int java_dyn_CallSite::_vmmethod_offset; +int java_dyn_CallSite::_caller_method_offset; +int java_dyn_CallSite::_caller_bci_offset; void java_dyn_CallSite::compute_offsets() { if (!EnableInvokeDynamic) return; klassOop k = SystemDictionary::CallSite_klass(); if (k != NULL) { - compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::java_dyn_MethodType_signature(), true); - compute_offset(_target_offset, k, vmSymbols::target_name(), vmSymbols::java_dyn_MethodHandle_signature(), true); - compute_offset(_vmmethod_offset, k, vmSymbols::vmmethod_name(), vmSymbols::object_signature(), true); + compute_offset(_target_offset, k, vmSymbols::target_name(), vmSymbols::java_dyn_MethodHandle_signature()); + compute_offset(_caller_method_offset, k, vmSymbols::vmmethod_name(), vmSymbols::sun_dyn_MemberName_signature()); + compute_offset(_caller_bci_offset, k, vmSymbols::vmindex_name(), vmSymbols::int_signature()); } } -oop java_dyn_CallSite::type(oop site) { - return site->obj_field(_type_offset); -} - oop java_dyn_CallSite::target(oop site) { return site->obj_field(_target_offset); } @@ -2472,12 +2468,20 @@ void java_dyn_CallSite::set_target(oop site, oop target) { site->obj_field_put(_target_offset, target); } -oop java_dyn_CallSite::vmmethod(oop site) { - return site->obj_field(_vmmethod_offset); +oop java_dyn_CallSite::caller_method(oop site) { + return site->obj_field(_caller_method_offset); } -void java_dyn_CallSite::set_vmmethod(oop site, oop ref) { - site->obj_field_put(_vmmethod_offset, ref); +void java_dyn_CallSite::set_caller_method(oop site, oop ref) { + site->obj_field_put(_caller_method_offset, ref); +} + +jint java_dyn_CallSite::caller_bci(oop site) { + return site->int_field(_caller_bci_offset); +} + +void java_dyn_CallSite::set_caller_bci(oop site, jint bci) { + site->int_field_put(_caller_bci_offset, bci); } diff --git a/hotspot/src/share/vm/classfile/javaClasses.hpp b/hotspot/src/share/vm/classfile/javaClasses.hpp index af78d5e58b3..ec176a3341e 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.hpp +++ b/hotspot/src/share/vm/classfile/javaClasses.hpp @@ -1068,21 +1068,22 @@ class java_dyn_CallSite: AllStatic { friend class JavaClasses; private: - static int _type_offset; static int _target_offset; - static int _vmmethod_offset; + static int _caller_method_offset; + static int _caller_bci_offset; static void compute_offsets(); public: // Accessors - static oop type(oop site); - static oop target(oop site); static void set_target(oop site, oop target); - static oop vmmethod(oop site); - static void set_vmmethod(oop site, oop ref); + static oop caller_method(oop site); + static void set_caller_method(oop site, oop ref); + + static jint caller_bci(oop site); + static void set_caller_bci(oop site, jint bci); // Testers static bool is_subclass(klassOop klass) { @@ -1094,8 +1095,8 @@ public: // Accessors for code generation: static int target_offset_in_bytes() { return _target_offset; } - static int type_offset_in_bytes() { return _type_offset; } - static int vmmethod_offset_in_bytes() { return _vmmethod_offset; } + static int caller_method_offset_in_bytes() { return _caller_method_offset; } + static int caller_bci_offset_in_bytes() { return _caller_bci_offset; } }; diff --git a/hotspot/src/share/vm/classfile/systemDictionary.cpp b/hotspot/src/share/vm/classfile/systemDictionary.cpp index 83f8717cf65..6ccbb21e634 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp @@ -2341,7 +2341,8 @@ char* SystemDictionary::check_signature_loaders(symbolHandle signature, } -methodOop SystemDictionary::find_method_handle_invoke(symbolHandle signature, +methodOop SystemDictionary::find_method_handle_invoke(symbolHandle name, + symbolHandle signature, Handle class_loader, Handle protection_domain, TRAPS) { @@ -2352,26 +2353,28 @@ methodOop SystemDictionary::find_method_handle_invoke(symbolHandle signature, // create this side table lazily _invoke_method_table = new SymbolPropertyTable(_invoke_method_size); } - unsigned int hash = invoke_method_table()->compute_hash(signature); + 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); int index = invoke_method_table()->hash_to_index(hash); - SymbolPropertyEntry* spe = invoke_method_table()->find_entry(index, hash, signature); + SymbolPropertyEntry* spe = invoke_method_table()->find_entry(index, hash, signature, name_id); if (spe == NULL || spe->property_oop() == NULL) { // Must create lots of stuff here, but outside of the SystemDictionary lock. if (THREAD->is_Compiler_thread()) return NULL; // do not attempt from within compiler - Handle mt = compute_method_handle_type(signature(), - class_loader, protection_domain, - CHECK_NULL); + Handle mt = find_method_handle_type(signature(), + class_loader, protection_domain, + CHECK_NULL); KlassHandle mh_klass = SystemDictionaryHandles::MethodHandle_klass(); - methodHandle m = methodOopDesc::make_invoke_method(mh_klass, signature, + methodHandle m = methodOopDesc::make_invoke_method(mh_klass, name, signature, mt, CHECK_NULL); // Now grab the lock. We might have to throw away the new method, // if a racing thread has managed to install one at the same time. { MutexLocker ml(SystemDictionary_lock, Thread::current()); - spe = invoke_method_table()->find_entry(index, hash, signature); + spe = invoke_method_table()->find_entry(index, hash, signature, name_id); if (spe == NULL) - spe = invoke_method_table()->add_entry(index, hash, signature); + spe = invoke_method_table()->add_entry(index, hash, signature, name_id); if (spe->property_oop() == NULL) spe->set_property_oop(m()); } @@ -2385,10 +2388,10 @@ methodOop SystemDictionary::find_method_handle_invoke(symbolHandle signature, // signature, as interpreted relative to the given class loader. // Because of class loader constraints, all method handle usage must be // consistent with this loader. -Handle SystemDictionary::compute_method_handle_type(symbolHandle signature, - Handle class_loader, - Handle protection_domain, - TRAPS) { +Handle SystemDictionary::find_method_handle_type(symbolHandle signature, + Handle class_loader, + Handle protection_domain, + TRAPS) { Handle empty; int npts = ArgumentCount(signature()).size(); objArrayHandle pts = oopFactory::new_objArray(SystemDictionary::Class_klass(), npts, CHECK_(empty)); @@ -2413,16 +2416,14 @@ Handle SystemDictionary::compute_method_handle_type(symbolHandle signature, } assert(arg == npts, ""); - // call MethodType java.dyn.MethodType::makeImpl(Class rt, Class[] pts, false, true) - bool varargs = false, trusted = true; + // call sun.dyn.MethodHandleNatives::findMethodType(Class rt, Class[] pts) -> MethodType JavaCallArguments args(Handle(THREAD, rt())); args.push_oop(pts()); - args.push_int(false); - args.push_int(trusted); JavaValue result(T_OBJECT); JavaCalls::call_static(&result, - SystemDictionary::MethodType_klass(), - vmSymbols::makeImpl_name(), vmSymbols::makeImpl_signature(), + SystemDictionary::MethodHandleNatives_klass(), + vmSymbols::findMethodHandleType_name(), + vmSymbols::findMethodHandleType_signature(), &args, CHECK_(empty)); return Handle(THREAD, (oop) result.get_jobject()); } @@ -2430,29 +2431,34 @@ Handle SystemDictionary::compute_method_handle_type(symbolHandle signature, // Ask Java code to find or construct a java.dyn.CallSite for the given // name and signature, as interpreted relative to the given class loader. -Handle SystemDictionary::make_dynamic_call_site(KlassHandle caller, - int caller_method_idnum, - int caller_bci, +Handle SystemDictionary::make_dynamic_call_site(Handle bootstrap_method, symbolHandle name, - methodHandle mh_invdyn, + methodHandle signature_invoker, + Handle info, + methodHandle caller_method, + int caller_bci, TRAPS) { Handle empty; - // call java.dyn.CallSite::makeSite(caller, name, mtype, cmid, cbci) + Handle caller_mname = MethodHandles::new_MemberName(CHECK_(empty)); + MethodHandles::init_MemberName(caller_mname(), caller_method()); + + // call sun.dyn.MethodHandleNatives::makeDynamicCallSite(bootm, name, mtype, info, caller_mname, caller_pos) oop name_str_oop = StringTable::intern(name(), CHECK_(empty)); // not a handle! - JavaCallArguments args(Handle(THREAD, caller->java_mirror())); + JavaCallArguments args(Handle(THREAD, bootstrap_method())); args.push_oop(name_str_oop); - args.push_oop(mh_invdyn->method_handle_type()); - args.push_int(caller_method_idnum); + args.push_oop(signature_invoker->method_handle_type()); + args.push_oop(info()); + args.push_oop(caller_mname()); args.push_int(caller_bci); JavaValue result(T_OBJECT); JavaCalls::call_static(&result, - SystemDictionary::CallSite_klass(), - vmSymbols::makeSite_name(), vmSymbols::makeSite_signature(), + SystemDictionary::MethodHandleNatives_klass(), + vmSymbols::makeDynamicCallSite_name(), + vmSymbols::makeDynamicCallSite_signature(), &args, CHECK_(empty)); oop call_site_oop = (oop) result.get_jobject(); assert(call_site_oop->is_oop() /*&& java_dyn_CallSite::is_instance(call_site_oop)*/, "must be sane"); - java_dyn_CallSite::set_vmmethod(call_site_oop, mh_invdyn()); if (TraceMethodHandles) { #ifndef PRODUCT tty->print_cr("Linked invokedynamic bci=%d site="INTPTR_FORMAT":", caller_bci, call_site_oop); @@ -2463,9 +2469,7 @@ Handle SystemDictionary::make_dynamic_call_site(KlassHandle caller, return call_site_oop; } -Handle SystemDictionary::find_bootstrap_method(KlassHandle caller, - KlassHandle search_bootstrap_klass, - TRAPS) { +Handle SystemDictionary::find_bootstrap_method(KlassHandle caller, TRAPS) { Handle empty; if (!caller->oop_is_instance()) return empty; @@ -2476,57 +2480,12 @@ Handle SystemDictionary::find_bootstrap_method(KlassHandle caller, if (TraceMethodHandles) { tty->print_cr("bootstrap method for "PTR_FORMAT" cached as "PTR_FORMAT":", ik(), boot_method_oop); } - NOT_PRODUCT(if (!boot_method_oop->is_oop()) { tty->print_cr("*** boot MH of "PTR_FORMAT" = "PTR_FORMAT, ik(), boot_method_oop); ik()->print(); }); assert(boot_method_oop->is_oop() && java_dyn_MethodHandle::is_instance(boot_method_oop), "must be sane"); return Handle(THREAD, boot_method_oop); } - boot_method_oop = NULL; // GC safety - // call java.dyn.Linkage::findBootstrapMethod(caller, sbk) - JavaCallArguments args(Handle(THREAD, ik->java_mirror())); - if (search_bootstrap_klass.is_null()) - args.push_oop(Handle()); - else - args.push_oop(search_bootstrap_klass->java_mirror()); - JavaValue result(T_OBJECT); - JavaCalls::call_static(&result, - SystemDictionary::Linkage_klass(), - vmSymbols::findBootstrapMethod_name(), - vmSymbols::findBootstrapMethod_signature(), - &args, CHECK_(empty)); - boot_method_oop = (oop) result.get_jobject(); - - if (boot_method_oop != NULL) { - if (TraceMethodHandles) { -#ifndef PRODUCT - tty->print_cr("--------"); - tty->print_cr("bootstrap method for "PTR_FORMAT" computed as "PTR_FORMAT":", ik(), boot_method_oop); - ik()->print(); - boot_method_oop->print(); - tty->print_cr("========"); -#endif //PRODUCT - } - assert(boot_method_oop->is_oop() - && java_dyn_MethodHandle::is_instance(boot_method_oop), "must be sane"); - // probably no race conditions, but let's be careful: - if (Atomic::cmpxchg_ptr(boot_method_oop, ik->adr_bootstrap_method(), NULL) == NULL) - ik->set_bootstrap_method(boot_method_oop); - else - boot_method_oop = ik->bootstrap_method(); - } else { - if (TraceMethodHandles) { -#ifndef PRODUCT - tty->print_cr("--------"); - tty->print_cr("bootstrap method for "PTR_FORMAT" computed as NULL:", ik()); - ik()->print(); - tty->print_cr("========"); -#endif //PRODUCT - } - boot_method_oop = ik->bootstrap_method(); - } - - return Handle(THREAD, boot_method_oop); + return empty; } // Since the identity hash code for symbols changes when the symbols are diff --git a/hotspot/src/share/vm/classfile/systemDictionary.hpp b/hotspot/src/share/vm/classfile/systemDictionary.hpp index 03b2aeb6b42..0d88d4206fd 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.hpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp @@ -136,6 +136,7 @@ class SymbolPropertyTable; template(MethodHandle_klass, java_dyn_MethodHandle, Opt) \ template(MemberName_klass, sun_dyn_MemberName, Opt) \ template(MethodHandleImpl_klass, sun_dyn_MethodHandleImpl, Opt) \ + template(MethodHandleNatives_klass, sun_dyn_MethodHandleNatives, Opt) \ template(AdapterMethodHandle_klass, sun_dyn_AdapterMethodHandle, Opt) \ template(BoundMethodHandle_klass, sun_dyn_BoundMethodHandle, Opt) \ template(DirectMethodHandle_klass, sun_dyn_DirectMethodHandle, Opt) \ @@ -463,29 +464,29 @@ public: // JSR 292 // find the java.dyn.MethodHandles::invoke method for a given signature - static methodOop find_method_handle_invoke(symbolHandle signature, + static methodOop find_method_handle_invoke(symbolHandle name, + symbolHandle signature, Handle class_loader, Handle protection_domain, TRAPS); - // ask Java to compute the java.dyn.MethodType object for a given signature - static Handle compute_method_handle_type(symbolHandle signature, - Handle class_loader, - Handle protection_domain, - TRAPS); + // ask Java to compute a java.dyn.MethodType object for a given signature + static Handle find_method_handle_type(symbolHandle signature, + Handle class_loader, + Handle protection_domain, + TRAPS); // ask Java to create a dynamic call site, while linking an invokedynamic op - static Handle make_dynamic_call_site(KlassHandle caller, - int caller_method_idnum, - int caller_bci, + static Handle make_dynamic_call_site(Handle bootstrap_method, + // Callee information: symbolHandle name, - methodHandle mh_invoke, + methodHandle signature_invoker, + Handle info, + // Caller information: + methodHandle caller_method, + int caller_bci, TRAPS); // coordinate with Java about bootstrap methods - static Handle find_bootstrap_method(KlassHandle caller, - // This argument is non-null only when a - // classfile attribute has been found: - KlassHandle search_bootstrap_klass, - TRAPS); + static Handle find_bootstrap_method(KlassHandle caller, TRAPS); // Utility for printing loader "name" as part of tracing constraints static const char* loader_name(oop loader) { diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp index a7ee43ee6ac..46d8b0c1061 100644 --- a/hotspot/src/share/vm/classfile/vmSymbols.hpp +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp @@ -137,6 +137,7 @@ template(java_lang_CloneNotSupportedException, "java/lang/CloneNotSupportedException") \ template(java_lang_IllegalAccessException, "java/lang/IllegalAccessException") \ template(java_lang_IllegalArgumentException, "java/lang/IllegalArgumentException") \ + template(java_lang_IllegalStateException, "java/lang/IllegalStateException") \ template(java_lang_IllegalMonitorStateException, "java/lang/IllegalMonitorStateException") \ template(java_lang_IllegalThreadStateException, "java/lang/IllegalThreadStateException") \ template(java_lang_IndexOutOfBoundsException, "java/lang/IndexOutOfBoundsException") \ @@ -201,6 +202,11 @@ template(newField_signature, "(Lsun/reflect/FieldInfo;)Ljava/lang/reflect/Field;") \ template(newMethod_name, "newMethod") \ template(newMethod_signature, "(Lsun/reflect/MethodInfo;)Ljava/lang/reflect/Method;") \ + /* the following two names must be in order: */ \ + template(invokeExact_name, "invokeExact") \ + template(invokeGeneric_name, "invokeGeneric") \ + template(invokeVarargs_name, "invokeVarargs") \ + template(star_name, "*") /*not really a name*/ \ template(invoke_name, "invoke") \ template(override_name, "override") \ template(parameterTypes_name, "parameterTypes") \ @@ -231,16 +237,17 @@ template(java_dyn_MethodTypeForm, "java/dyn/MethodTypeForm") \ template(java_dyn_MethodTypeForm_signature, "Ljava/dyn/MethodTypeForm;") \ template(sun_dyn_MemberName, "sun/dyn/MemberName") \ + template(sun_dyn_MemberName_signature, "Lsun/dyn/MemberName;") \ template(sun_dyn_MethodHandleImpl, "sun/dyn/MethodHandleImpl") \ + template(sun_dyn_MethodHandleNatives, "sun/dyn/MethodHandleNatives") \ template(sun_dyn_AdapterMethodHandle, "sun/dyn/AdapterMethodHandle") \ template(sun_dyn_BoundMethodHandle, "sun/dyn/BoundMethodHandle") \ template(sun_dyn_DirectMethodHandle, "sun/dyn/DirectMethodHandle") \ - template(makeImpl_name, "makeImpl") /*MethodType::makeImpl*/ \ - template(makeImpl_signature, "(Ljava/lang/Class;[Ljava/lang/Class;ZZ)Ljava/dyn/MethodType;") \ - template(makeSite_name, "makeSite") /*CallSite::makeSite*/ \ - template(makeSite_signature, "(Ljava/lang/Class;Ljava/lang/String;Ljava/dyn/MethodType;II)Ljava/dyn/CallSite;") \ - template(findBootstrapMethod_name, "findBootstrapMethod") \ - template(findBootstrapMethod_signature, "(Ljava/lang/Class;Ljava/lang/Class;)Ljava/dyn/MethodHandle;") \ + /* internal up-calls made only by the JVM, via class sun.dyn.MethodHandleNatives: */ \ + template(findMethodHandleType_name, "findMethodHandleType") \ + template(findMethodHandleType_signature, "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/dyn/MethodType;") \ + template(makeDynamicCallSite_name, "makeDynamicCallSite") \ + template(makeDynamicCallSite_signature, "(Ljava/dyn/MethodHandle;Ljava/lang/String;Ljava/dyn/MethodType;Ljava/lang/Object;Lsun/dyn/MemberName;I)Ljava/dyn/CallSite;") \ NOT_LP64( do_alias(machine_word_signature, int_signature) ) \ LP64_ONLY( do_alias(machine_word_signature, long_signature) ) \ \ @@ -408,8 +415,9 @@ template(void_classloader_signature, "()Ljava/lang/ClassLoader;") \ template(void_object_signature, "()Ljava/lang/Object;") \ template(void_class_signature, "()Ljava/lang/Class;") \ - template(void_string_signature, "()Ljava/lang/String;") \ - template(object_array_object_object_signature, "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;")\ + template(void_string_signature, "()Ljava/lang/String;") \ + template(object_array_object_signature, "([Ljava/lang/Object;)Ljava/lang/Object;") \ + template(object_object_array_object_signature, "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;")\ template(exception_void_signature, "(Ljava/lang/Exception;)V") \ template(protectiondomain_signature, "[Ljava/security/ProtectionDomain;") \ template(accesscontrolcontext_signature, "Ljava/security/AccessControlContext;") \ @@ -863,11 +871,15 @@ do_intrinsic(_Object_init, java_lang_Object, object_initializer_name, void_method_signature, F_R) \ /* (symbol object_initializer_name defined above) */ \ \ - do_intrinsic(_invoke, java_lang_reflect_Method, invoke_name, object_array_object_object_signature, F_R) \ + do_intrinsic(_invoke, java_lang_reflect_Method, invoke_name, object_object_array_object_signature, F_R) \ /* (symbols invoke_name and invoke_signature defined above) */ \ do_intrinsic(_checkSpreadArgument, sun_dyn_MethodHandleImpl, checkSpreadArgument_name, checkSpreadArgument_signature, F_S) \ do_name( checkSpreadArgument_name, "checkSpreadArgument") \ do_name( checkSpreadArgument_signature, "(Ljava/lang/Object;I)V") \ + do_intrinsic(_invokeExact, java_dyn_MethodHandle, invokeExact_name, object_array_object_signature, F_RN) \ + do_intrinsic(_invokeGeneric, java_dyn_MethodHandle, invokeGeneric_name, object_array_object_signature, F_RN) \ + do_intrinsic(_invokeVarargs, java_dyn_MethodHandle, invokeVarargs_name, object_array_object_signature, F_R) \ + do_intrinsic(_invokeDynamic, java_dyn_InvokeDynamic, star_name, object_array_object_signature, F_SN) \ \ /* unboxing methods: */ \ do_intrinsic(_booleanValue, java_lang_Boolean, booleanValue_name, void_boolean_signature, F_R) \ diff --git a/hotspot/src/share/vm/includeDB_core b/hotspot/src/share/vm/includeDB_core index 5670d3d64c8..7c11beec02d 100644 --- a/hotspot/src/share/vm/includeDB_core +++ b/hotspot/src/share/vm/includeDB_core @@ -2867,6 +2867,7 @@ methodHandles.hpp frame.inline.hpp methodHandles.hpp globals.hpp methodHandles.hpp interfaceSupport.hpp methodHandles.hpp javaClasses.hpp +methodHandles.hpp no_precompiled_headers methodHandles.hpp vmSymbols.hpp methodHandles.cpp allocation.inline.hpp @@ -2930,6 +2931,7 @@ methodOop.cpp interpreter.hpp methodOop.cpp jvmtiExport.hpp methodOop.cpp klassOop.hpp methodOop.cpp methodDataOop.hpp +methodOop.cpp methodHandleWalk.hpp methodOop.cpp methodOop.hpp methodOop.cpp nativeLookup.hpp methodOop.cpp oop.inline.hpp @@ -4075,6 +4077,7 @@ systemDictionary.cpp jvmtiEnvBase.hpp systemDictionary.cpp klass.inline.hpp systemDictionary.cpp loaderConstraints.hpp systemDictionary.cpp methodDataOop.hpp +systemDictionary.cpp methodHandles.hpp systemDictionary.cpp mutexLocker.hpp systemDictionary.cpp objArrayKlass.hpp systemDictionary.cpp oop.inline.hpp diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp index 84d4fd762f7..590edd58380 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp @@ -691,24 +691,21 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_invokedynamic(JavaThread* thread)) { methodHandle caller_method(thread, method(thread)); - // first determine if there is a bootstrap method - { - KlassHandle caller_klass(thread, caller_method->method_holder()); - Handle bootm = SystemDictionary::find_bootstrap_method(caller_klass, KlassHandle(), CHECK); - if (bootm.is_null()) { - // If there is no bootstrap method, throw IncompatibleClassChangeError. - // This is a valid generic error type for resolution (JLS 12.3.3). - char buf[200]; - jio_snprintf(buf, sizeof(buf), "Class %s has not declared a bootstrap method for invokedynamic", - (Klass::cast(caller_klass()))->external_name()); - THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); - } - } + // first find the bootstrap method + KlassHandle caller_klass(thread, caller_method->method_holder()); + Handle bootm = SystemDictionary::find_bootstrap_method(caller_klass, CHECK); constantPoolHandle pool(thread, caller_method->constants()); pool->set_invokedynamic(); // mark header to flag active call sites - int site_index = four_byte_index(thread); + int caller_bci = 0; + int site_index = 0; + { address caller_bcp = bcp(thread); + caller_bci = caller_method->bci_from(caller_bcp); + site_index = Bytes::get_native_u4(caller_bcp+1); + } + assert(site_index == four_byte_index(thread), ""); + assert(constantPoolCacheOopDesc::is_secondary_index(site_index), "proper format"); // there is a second CPC entries that is of interest; it caches signature info: int main_index = pool->cache()->secondary_entry_at(site_index)->main_entry_index(); @@ -732,23 +729,32 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_invokedynamic(JavaThread* thread)) { // The method (f2 entry) of the main entry is the MH.invoke for the // invokedynamic target call signature. intptr_t f2_value = pool->cache()->entry_at(main_index)->f2(); - methodHandle mh_invdyn(THREAD, (methodOop) f2_value); - assert(mh_invdyn.not_null() && mh_invdyn->is_method() && mh_invdyn->is_method_handle_invoke(), + methodHandle signature_invoker(THREAD, (methodOop) f2_value); + assert(signature_invoker.not_null() && signature_invoker->is_method() && signature_invoker->is_method_handle_invoke(), "correct result from LinkResolver::resolve_invokedynamic"); symbolHandle call_site_name(THREAD, pool->name_ref_at(site_index)); + + Handle info; // NYI: Other metadata from a new kind of CP entry. (Annotations?) + + // this is the index which gets stored on the CallSite object (as "callerPosition"): + int call_site_position = constantPoolCacheOopDesc::decode_secondary_index(site_index); + Handle call_site - = SystemDictionary::make_dynamic_call_site(caller_method->method_holder(), - caller_method->method_idnum(), - caller_method->bci_from(bcp(thread)), + = SystemDictionary::make_dynamic_call_site(bootm, + // Callee information: call_site_name, - mh_invdyn, + signature_invoker, + info, + // Caller information: + caller_method, + caller_bci, CHECK); // In the secondary entry, the f1 field is the call site, and the f2 (index) - // field is some data about the invoke site. - int extra_data = 0; - pool->cache()->secondary_entry_at(site_index)->set_dynamic_call(call_site(), extra_data); + // field is some data about the invoke site. Currently, it is just the BCI. + // Later, it might be changed to help manage inlining dependencies. + pool->cache()->secondary_entry_at(site_index)->set_dynamic_call(call_site, signature_invoker); } IRT_END diff --git a/hotspot/src/share/vm/interpreter/linkResolver.cpp b/hotspot/src/share/vm/interpreter/linkResolver.cpp index 4c5fd690393..d80ef9daf52 100644 --- a/hotspot/src/share/vm/interpreter/linkResolver.cpp +++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp @@ -138,6 +138,15 @@ void LinkResolver::resolve_klass_no_update(KlassHandle& result, constantPoolHand void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS) { methodOop result_oop = klass->uncached_lookup_method(name(), signature()); + if (EnableMethodHandles && result_oop != NULL) { + switch (result_oop->intrinsic_id()) { + case vmIntrinsics::_invokeExact: + case vmIntrinsics::_invokeGeneric: + case vmIntrinsics::_invokeDynamic: + // Do not link directly to these. The VM must produce a synthetic one using lookup_implicit_method. + return; + } + } result = methodHandle(THREAD, result_oop); } @@ -165,8 +174,10 @@ void LinkResolver::lookup_method_in_interfaces(methodHandle& result, KlassHandle void LinkResolver::lookup_implicit_method(methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS) { if (EnableMethodHandles && MethodHandles::enabled() && - name == vmSymbolHandles::invoke_name() && klass() == SystemDictionary::MethodHandle_klass()) { - methodOop result_oop = SystemDictionary::find_method_handle_invoke(signature, + klass() == SystemDictionary::MethodHandle_klass() && + methodOopDesc::is_method_handle_invoke_name(name())) { + methodOop result_oop = SystemDictionary::find_method_handle_invoke(name, + signature, Handle(), Handle(), CHECK); @@ -239,7 +250,7 @@ void LinkResolver::resolve_dynamic_method(methodHandle& resolved_method, KlassHa // The class is java.dyn.MethodHandle resolved_klass = SystemDictionaryHandles::MethodHandle_klass(); - symbolHandle method_name = vmSymbolHandles::invoke_name(); + symbolHandle method_name = vmSymbolHandles::invokeExact_name(); symbolHandle method_signature(THREAD, pool->signature_ref_at(index)); KlassHandle current_klass (THREAD, pool->pool_holder()); @@ -1041,10 +1052,10 @@ void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle po // At this point, we only need the signature, and can ignore the name. symbolHandle method_signature(THREAD, pool->signature_ref_at(raw_index)); // raw_index works directly - symbolHandle method_name = vmSymbolHandles::invoke_name(); + symbolHandle method_name = vmSymbolHandles::invokeExact_name(); KlassHandle resolved_klass = SystemDictionaryHandles::MethodHandle_klass(); - // JSR 292: this must be an implicitly generated method MethodHandle.invoke(*...) + // JSR 292: this must be an implicitly generated method MethodHandle.invokeExact(*...) // The extra MH receiver will be inserted into the stack on every call. methodHandle resolved_method; lookup_implicit_method(resolved_method, resolved_klass, method_name, method_signature, CHECK); diff --git a/hotspot/src/share/vm/memory/universe.cpp b/hotspot/src/share/vm/memory/universe.cpp index 5803a4d356e..13b9b556fd0 100644 --- a/hotspot/src/share/vm/memory/universe.cpp +++ b/hotspot/src/share/vm/memory/universe.cpp @@ -1045,7 +1045,7 @@ bool universe_post_init() { k = SystemDictionary::resolve_or_fail(vmSymbolHandles::java_lang_reflect_Method(), true, CHECK_false); k_h = instanceKlassHandle(THREAD, k); k_h->link_class(CHECK_false); - m = k_h->find_method(vmSymbols::invoke_name(), vmSymbols::object_array_object_object_signature()); + m = k_h->find_method(vmSymbols::invoke_name(), vmSymbols::object_object_array_object_signature()); if (m == NULL || m->is_static()) { THROW_MSG_(vmSymbols::java_lang_NoSuchMethodException(), "java.lang.reflect.Method.invoke", false); diff --git a/hotspot/src/share/vm/oops/cpCacheOop.cpp b/hotspot/src/share/vm/oops/cpCacheOop.cpp index 36380c88903..7742b0f5cd4 100644 --- a/hotspot/src/share/vm/oops/cpCacheOop.cpp +++ b/hotspot/src/share/vm/oops/cpCacheOop.cpp @@ -218,18 +218,19 @@ void ConstantPoolCacheEntry::set_interface_call(methodHandle method, int index) } -void ConstantPoolCacheEntry::set_dynamic_call(Handle call_site, int extra_data) { - methodOop method = (methodOop) java_dyn_CallSite::vmmethod(call_site()); - assert(method->is_method(), "must be initialized properly"); - int param_size = method->size_of_parameters(); +void ConstantPoolCacheEntry::set_dynamic_call(Handle call_site, + methodHandle signature_invoker) { + int param_size = signature_invoker->size_of_parameters(); assert(param_size >= 1, "method argument size must include MH.this"); param_size -= 1; // do not count MH.this; it is not stacked for invokedynamic if (Atomic::cmpxchg_ptr(call_site(), &_f1, NULL) == NULL) { // racing threads might be trying to install their own favorites set_f1(call_site()); } - set_f2(extra_data); - set_flags(as_flags(as_TosState(method->result_type()), method->is_final_method(), false, false, false, true) | param_size); + //set_f2(0); + bool is_final = true; + assert(signature_invoker->is_final_method(), "is_final"); + set_flags(as_flags(as_TosState(signature_invoker->result_type()), is_final, false, false, false, true) | param_size); // do not do set_bytecode on a secondary CP cache entry //set_bytecode_1(Bytecodes::_invokedynamic); } diff --git a/hotspot/src/share/vm/oops/cpCacheOop.hpp b/hotspot/src/share/vm/oops/cpCacheOop.hpp index 6fb7a635e56..823a77bb73e 100644 --- a/hotspot/src/share/vm/oops/cpCacheOop.hpp +++ b/hotspot/src/share/vm/oops/cpCacheOop.hpp @@ -181,7 +181,7 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC { void set_dynamic_call( Handle call_site, // Resolved java.dyn.CallSite (f1) - int extra_data // (f2) + methodHandle signature_invoker // determines signature information ); void set_parameter_size(int value) { diff --git a/hotspot/src/share/vm/oops/methodKlass.cpp b/hotspot/src/share/vm/oops/methodKlass.cpp index 1b788c63b13..a69cc59c67b 100644 --- a/hotspot/src/share/vm/oops/methodKlass.cpp +++ b/hotspot/src/share/vm/oops/methodKlass.cpp @@ -236,8 +236,10 @@ void methodKlass::oop_print_on(oop obj, outputStream* st) { assert(obj->is_method(), "must be method"); Klass::oop_print_on(obj, st); methodOop m = methodOop(obj); + // get the effect of PrintOopAddress, always, for methods: + st->print (" - this oop: "INTPTR_FORMAT, (intptr_t)m); st->print (" - method holder: "); m->method_holder()->print_value_on(st); st->cr(); - st->print (" - constants: " INTPTR_FORMAT, " ", (address)m->constants()); + st->print (" - constants: "INTPTR_FORMAT" ", (address)m->constants()); m->constants()->print_value_on(st); st->cr(); st->print (" - access: 0x%x ", m->access_flags().as_int()); m->access_flags().print_on(st); st->cr(); st->print (" - name: "); m->name()->print_value_on(st); st->cr(); @@ -246,6 +248,10 @@ void methodKlass::oop_print_on(oop obj, outputStream* st) { st->print_cr(" - max locals: %d", m->max_locals()); st->print_cr(" - size of params: %d", m->size_of_parameters()); st->print_cr(" - method size: %d", m->method_size()); + if (m->intrinsic_id() != vmIntrinsics::_none) + st->print_cr(" - intrinsic id: %d %s", m->intrinsic_id(), vmIntrinsics::name_at(m->intrinsic_id())); + if (m->highest_tier_compile() != CompLevel_none) + st->print_cr(" - highest tier: %d", m->highest_tier_compile()); st->print_cr(" - vtable index: %d", m->_vtable_index); st->print_cr(" - i2i entry: " INTPTR_FORMAT, m->interpreter_entry()); st->print_cr(" - adapter: " INTPTR_FORMAT, m->adapter()); diff --git a/hotspot/src/share/vm/oops/methodOop.cpp b/hotspot/src/share/vm/oops/methodOop.cpp index 06825af6c9d..5394db3d735 100644 --- a/hotspot/src/share/vm/oops/methodOop.cpp +++ b/hotspot/src/share/vm/oops/methodOop.cpp @@ -807,9 +807,19 @@ bool methodOopDesc::should_not_be_cached() const { return false; } +bool methodOopDesc::is_method_handle_invoke_name(vmSymbols::SID name_sid) { + switch (name_sid) { + case vmSymbols::VM_SYMBOL_ENUM_NAME(invoke_name): // FIXME: remove this transitional form + case vmSymbols::VM_SYMBOL_ENUM_NAME(invokeExact_name): + case vmSymbols::VM_SYMBOL_ENUM_NAME(invokeGeneric_name): + return true; + } + return false; +} + // Constant pool structure for invoke methods: enum { - _imcp_invoke_name = 1, // utf8: 'invoke' + _imcp_invoke_name = 1, // utf8: 'invokeExact' or 'invokeGeneric' _imcp_invoke_signature, // utf8: (variable symbolOop) _imcp_method_type_value, // string: (variable java/dyn/MethodType, sic) _imcp_limit @@ -839,14 +849,15 @@ jint* methodOopDesc::method_type_offsets_chain() { // // Tests if this method is an internal adapter frame from the // MethodHandleCompiler. +// Must be consistent with MethodHandleCompiler::get_method_oop(). bool methodOopDesc::is_method_handle_adapter() const { - return ((name() == vmSymbols::invoke_name() && - method_holder() == SystemDictionary::MethodHandle_klass()) - || - method_holder() == SystemDictionary::InvokeDynamic_klass()); + return (is_method_handle_invoke_name(name()) && + is_synthetic() && + MethodHandleCompiler::klass_is_method_handle_adapter_holder(method_holder())); } methodHandle methodOopDesc::make_invoke_method(KlassHandle holder, + symbolHandle name, symbolHandle signature, Handle method_type, TRAPS) { methodHandle empty; @@ -865,7 +876,7 @@ methodHandle methodOopDesc::make_invoke_method(KlassHandle holder, constantPoolOop cp_oop = oopFactory::new_constantPool(_imcp_limit, IsSafeConc, CHECK_(empty)); cp = constantPoolHandle(THREAD, cp_oop); } - cp->symbol_at_put(_imcp_invoke_name, vmSymbols::invoke_name()); + cp->symbol_at_put(_imcp_invoke_name, name()); cp->symbol_at_put(_imcp_invoke_signature, signature()); cp->string_at_put(_imcp_method_type_value, vmSymbols::void_signature()); cp->set_pool_holder(holder()); @@ -882,7 +893,7 @@ methodHandle methodOopDesc::make_invoke_method(KlassHandle holder, m->set_constants(cp()); m->set_name_index(_imcp_invoke_name); m->set_signature_index(_imcp_invoke_signature); - assert(m->name() == vmSymbols::invoke_name(), ""); + assert(is_method_handle_invoke_name(m->name()), ""); assert(m->signature() == signature(), ""); #ifdef CC_INTERP ResultTypeFinder rtf(signature()); @@ -1033,6 +1044,24 @@ void methodOopDesc::init_intrinsic_id() { id = vmIntrinsics::find_id(klass_id, name_id, sig_id, flags); break; } + break; + + // Signature-polymorphic methods: MethodHandle.invoke*, InvokeDynamic.*. + case vmSymbols::VM_SYMBOL_ENUM_NAME(java_dyn_MethodHandle): + if (is_static() || !is_native()) break; + switch (name_id) { + case vmSymbols::VM_SYMBOL_ENUM_NAME(invokeGeneric_name): + id = vmIntrinsics::_invokeGeneric; break; + default: + if (is_method_handle_invoke_name(name())) + id = vmIntrinsics::_invokeExact; + break; + } + break; + case vmSymbols::VM_SYMBOL_ENUM_NAME(java_dyn_InvokeDynamic): + if (!is_static() || !is_native()) break; + id = vmIntrinsics::_invokeDynamic; + break; } if (id != vmIntrinsics::_none) { diff --git a/hotspot/src/share/vm/oops/methodOop.hpp b/hotspot/src/share/vm/oops/methodOop.hpp index 61dc3f1bc39..a77280da785 100644 --- a/hotspot/src/share/vm/oops/methodOop.hpp +++ b/hotspot/src/share/vm/oops/methodOop.hpp @@ -525,11 +525,16 @@ class methodOopDesc : public oopDesc { // JSR 292 support bool is_method_handle_invoke() const { return access_flags().is_method_handle_invoke(); } + static bool is_method_handle_invoke_name(vmSymbols::SID name_sid); + static bool is_method_handle_invoke_name(symbolOop name) { + return is_method_handle_invoke_name(vmSymbols::find_sid(name)); + } // Tests if this method is an internal adapter frame from the // MethodHandleCompiler. bool is_method_handle_adapter() const; static methodHandle make_invoke_method(KlassHandle holder, - symbolHandle signature, + symbolHandle name, //invokeExact or invokeGeneric + symbolHandle signature, //anything at all Handle method_type, TRAPS); // these operate only on invoke methods: diff --git a/hotspot/src/share/vm/opto/bytecodeInfo.cpp b/hotspot/src/share/vm/opto/bytecodeInfo.cpp index b199d7c7047..922b712cdbe 100644 --- a/hotspot/src/share/vm/opto/bytecodeInfo.cpp +++ b/hotspot/src/share/vm/opto/bytecodeInfo.cpp @@ -477,12 +477,7 @@ InlineTree *InlineTree::build_inline_tree_for_callee( ciMethod* callee_method, J } int new_depth_adjust = 0; if (caller_jvms->method() != NULL) { - if ((caller_jvms->method()->name() == ciSymbol::invoke_name() && - caller_jvms->method()->holder()->name() == ciSymbol::java_dyn_MethodHandle()) - || caller_jvms->method()->holder()->name() == ciSymbol::java_dyn_InvokeDynamic()) - /* @@@ FIXME: if (caller_jvms->method()->is_method_handle_adapter()) - */ new_depth_adjust -= 1; // don't count actions in MH or indy adapter frames else if (callee_method->is_method_handle_invoke()) { new_depth_adjust -= 1; // don't count method handle calls from java.dyn implem diff --git a/hotspot/src/share/vm/prims/methodHandleWalk.cpp b/hotspot/src/share/vm/prims/methodHandleWalk.cpp index 0df6c308bb7..6be78f36e63 100644 --- a/hotspot/src/share/vm/prims/methodHandleWalk.cpp +++ b/hotspot/src/share/vm/prims/methodHandleWalk.cpp @@ -1173,9 +1173,9 @@ methodHandle MethodHandleCompiler::get_method_oop(TRAPS) const { // has no receiver, normal MH calls do. int flags_bits; if (for_invokedynamic()) - flags_bits = (/*JVM_MH_INVOKE_BITS |*/ JVM_ACC_PUBLIC | JVM_ACC_FINAL | JVM_ACC_STATIC); + flags_bits = (/*JVM_MH_INVOKE_BITS |*/ JVM_ACC_PUBLIC | JVM_ACC_FINAL | JVM_ACC_SYNTHETIC | JVM_ACC_STATIC); else - flags_bits = (/*JVM_MH_INVOKE_BITS |*/ JVM_ACC_PUBLIC | JVM_ACC_FINAL); + flags_bits = (/*JVM_MH_INVOKE_BITS |*/ JVM_ACC_PUBLIC | JVM_ACC_FINAL | JVM_ACC_SYNTHETIC); bool is_conc_safe = true; methodOop m_oop = oopFactory::new_method(bytecode_length(), @@ -1217,6 +1217,7 @@ methodHandle MethodHandleCompiler::get_method_oop(TRAPS) const { } #endif //PRODUCT + assert(m->is_method_handle_adapter(), "must be recognized as an adapter"); return m; } diff --git a/hotspot/src/share/vm/prims/methodHandles.cpp b/hotspot/src/share/vm/prims/methodHandles.cpp index 4131f0f34b8..9581757f061 100644 --- a/hotspot/src/share/vm/prims/methodHandles.cpp +++ b/hotspot/src/share/vm/prims/methodHandles.cpp @@ -366,6 +366,13 @@ enum { VM_INDEX_UNINITIALIZED = sun_dyn_MemberName::VM_INDEX_UNINITIALIZED }; +Handle MethodHandles::new_MemberName(TRAPS) { + Handle empty; + instanceKlassHandle k(THREAD, SystemDictionary::MemberName_klass()); + if (!k->is_initialized()) k->initialize(CHECK_(empty)); + return Handle(THREAD, k->allocate_instance(THREAD)); +} + void MethodHandles::init_MemberName(oop mname_oop, oop target_oop) { if (target_oop->klass() == SystemDictionary::reflect_Field_klass()) { oop clazz = java_lang_reflect_Field::clazz(target_oop); // fd.field_holder() @@ -394,16 +401,18 @@ void MethodHandles::init_MemberName(oop mname_oop, methodOop m, bool do_dispatch sun_dyn_MemberName::set_vmtarget(mname_oop, vmtarget); sun_dyn_MemberName::set_vmindex(mname_oop, vmindex); sun_dyn_MemberName::set_flags(mname_oop, flags); + sun_dyn_MemberName::set_clazz(mname_oop, Klass::cast(m->method_holder())->java_mirror()); } void MethodHandles::init_MemberName(oop mname_oop, klassOop field_holder, AccessFlags mods, int offset) { int flags = (IS_FIELD | (jushort)( mods.as_short() & JVM_RECOGNIZED_FIELD_MODIFIERS )); oop vmtarget = field_holder; - int vmindex = offset; // implies no info yet + int vmindex = offset; // determines the field uniquely when combined with static bit assert(vmindex != VM_INDEX_UNINITIALIZED, "bad alias on vmindex"); sun_dyn_MemberName::set_vmtarget(mname_oop, vmtarget); sun_dyn_MemberName::set_vmindex(mname_oop, vmindex); sun_dyn_MemberName::set_flags(mname_oop, flags); + sun_dyn_MemberName::set_clazz(mname_oop, Klass::cast(field_holder)->java_mirror()); } @@ -467,7 +476,7 @@ void MethodHandles::resolve_MemberName(Handle mname, TRAPS) { name_str = NULL; // safety // convert the external string or reflective type to an internal signature - bool force_signature = (name() == vmSymbols::invoke_name()); + bool force_signature = methodOopDesc::is_method_handle_invoke_name(name()); symbolHandle type; { symbolOop type_sym = NULL; if (java_dyn_MethodType::is_instance(type_str)) { @@ -775,6 +784,20 @@ int MethodHandles::find_MemberNames(klassOop k, } +// Decode this java.lang.Class object into an instanceKlass, if possible. +// Throw IAE if not +instanceKlassHandle MethodHandles::resolve_instance_klass(oop java_mirror_oop, TRAPS) { + instanceKlassHandle empty; + klassOop caller = NULL; + if (java_lang_Class::is_instance(java_mirror_oop)) { + caller = java_lang_Class::as_klassOop(java_mirror_oop); + } + if (caller == NULL || !Klass::cast(caller)->oop_is_instance()) { + THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), "not a class", empty); + } + return instanceKlassHandle(THREAD, caller); +} + // Decode the vmtarget field of a method handle. @@ -2115,31 +2138,26 @@ JVM_ENTRY(void, MHI_init_DMH(JNIEnv *env, jobject igcls, jobject mh_jh, KlassHandle caller(THREAD, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(caller_jh))); // If this were a bytecode, the first access check would be against // the "reference class" mentioned in the CONSTANT_Methodref. - // For that class, we use the defining class of m, - // or a more specific receiver limit if available. - klassOop reference_klass = m->method_holder(); // OK approximation - if (receiver_limit != NULL && receiver_limit != reference_klass) { - if (!Klass::cast(receiver_limit)->is_subtype_of(reference_klass)) - THROW_MSG(vmSymbols::java_lang_InternalError(), "receiver limit out of bounds"); // Java code bug - reference_klass = receiver_limit; - } - // Emulate LinkResolver::check_klass_accessability. - if (!Reflection::verify_class_access(caller->as_klassOop(), - reference_klass, - true)) { - THROW_MSG(vmSymbols::java_lang_InternalError(), Klass::cast(m->method_holder())->external_name()); - } + // We don't know at this point which class that was, and if we + // check against m.method_holder we might get the wrong answer. + // So we just make sure to handle this check when the resolution + // happens, when we call resolve_MemberName. + // + // (A public class can inherit public members from private supers, + // and it would be wrong to check access against the private super + // if the original symbolic reference was against the public class.) + // // If there were a bytecode, the next step would be to lookup the method // in the reference class, then then check the method's access bits. // Emulate LinkResolver::check_method_accessability. klassOop resolved_klass = m->method_holder(); if (!Reflection::verify_field_access(caller->as_klassOop(), - resolved_klass, reference_klass, + resolved_klass, resolved_klass, m->access_flags(), true)) { // %%% following cutout belongs in Reflection::verify_field_access? bool same_pm = Reflection::is_same_package_member(caller->as_klassOop(), - reference_klass, THREAD); + resolved_klass, THREAD); if (!same_pm) { THROW_MSG(vmSymbols::java_lang_InternalError(), m->name_and_sig_as_C_string()); } @@ -2244,6 +2262,8 @@ JVM_ENTRY(jint, MHI_getConstant(JNIEnv *env, jobject igcls, jint which)) { case MethodHandles::GC_JVM_STACK_MOVE_UNIT: // return number of words per slot, signed according to stack direction return MethodHandles::stack_move_unit(); + case MethodHandles::GC_CONV_OP_IMPLEMENTED_MASK: + return MethodHandles::adapter_conversion_ops_supported_mask(); } return 0; } @@ -2342,7 +2362,22 @@ JVM_END JVM_ENTRY(void, MHI_resolve_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, jclass caller_jh)) { if (mname_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh)); - // %%% take caller into account! + + // The trusted Java code that calls this method should already have performed + // access checks on behalf of the given caller. But, we can verify this. + if (VerifyMethodHandles && caller_jh != NULL) { + klassOop reference_klass = java_lang_Class::as_klassOop(sun_dyn_MemberName::clazz(mname())); + if (reference_klass != NULL) { + // Emulate LinkResolver::check_klass_accessability. + klassOop caller = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(caller_jh)); + if (!Reflection::verify_class_access(caller, + reference_klass, + true)) { + THROW_MSG(vmSymbols::java_lang_InternalError(), Klass::cast(reference_klass)->external_name()); + } + } + } + MethodHandles::resolve_MemberName(mname, CHECK); } JVM_END @@ -2387,12 +2422,48 @@ JVM_ENTRY(jint, MHI_getMembers(JNIEnv *env, jobject igcls, } JVM_END +JVM_ENTRY(void, MHI_registerBootstrap(JNIEnv *env, jobject igcls, jclass caller_jh, jobject bsm_jh)) { + instanceKlassHandle ik = MethodHandles::resolve_instance_klass(caller_jh, THREAD); + ik->link_class(CHECK); + if (!java_dyn_MethodHandle::is_instance(JNIHandles::resolve(bsm_jh))) { + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "method handle"); + } + const char* err = NULL; + if (ik->is_initialized() || ik->is_in_error_state()) { + err = "too late: class is already initialized"; + } else { + ObjectLocker ol(ik, THREAD); // note: this should be a recursive lock + if (ik->is_not_initialized() || + (ik->is_being_initialized() && ik->is_reentrant_initialization(THREAD))) { + if (ik->bootstrap_method() != NULL) { + err = "class is already equipped with a bootstrap method"; + } else { + ik->set_bootstrap_method(JNIHandles::resolve_non_null(bsm_jh)); + err = NULL; + } + } else { + err = "class is already initialized"; + if (ik->is_being_initialized()) + err = "class is already being initialized in a different thread"; + } + } + if (err != NULL) { + THROW_MSG(vmSymbols::java_lang_IllegalStateException(), err); + } +} +JVM_END -JVM_ENTRY(void, MH_linkCallSite(JNIEnv *env, jobject igcls, jobject site_jh, jobject target_jh)) { +JVM_ENTRY(jobject, MHI_getBootstrap(JNIEnv *env, jobject igcls, jclass caller_jh)) { + instanceKlassHandle ik = MethodHandles::resolve_instance_klass(caller_jh, THREAD); + return JNIHandles::make_local(THREAD, ik->bootstrap_method()); +} +JVM_END + +JVM_ENTRY(void, MHI_setCallSiteTarget(JNIEnv *env, jobject igcls, jobject site_jh, jobject target_jh)) { // No special action required, yet. oop site_oop = JNIHandles::resolve(site_jh); - if (site_oop == NULL || site_oop->klass() != SystemDictionary::CallSite_klass()) - THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "call site"); + if (!java_dyn_CallSite::is_instance(site_oop)) + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "not a CallSite"); java_dyn_CallSite::set_target(site_oop, JNIHandles::resolve(target_jh)); } JVM_END @@ -2442,7 +2513,9 @@ static JNINativeMethod methods[] = { // More entry points specifically for EnableInvokeDynamic. static JNINativeMethod methods2[] = { - {CC"linkCallSite", CC"("CST MH")V", FN_PTR(MH_linkCallSite)} + {CC"registerBootstrap", CC"("CLS MH")V", FN_PTR(MHI_registerBootstrap)}, + {CC"getBootstrap", CC"("CLS")"MH, FN_PTR(MHI_getBootstrap)}, + {CC"setCallSiteTarget", CC"("CST MH")V", FN_PTR(MHI_setCallSiteTarget)} }; diff --git a/hotspot/src/share/vm/prims/methodHandles.hpp b/hotspot/src/share/vm/prims/methodHandles.hpp index fc810b9d64e..3449b8406f1 100644 --- a/hotspot/src/share/vm/prims/methodHandles.hpp +++ b/hotspot/src/share/vm/prims/methodHandles.hpp @@ -216,6 +216,9 @@ class MethodHandles: AllStatic { return (conv >> CONV_VMINFO_SHIFT) & CONV_VMINFO_MASK; } + // Bit mask of conversion_op values. May vary by platform. + static int adapter_conversion_ops_supported_mask(); + // Offset in words that the interpreter stack pointer moves when an argument is pushed. // The stack_move value must always be a multiple of this. static int stack_move_unit() { @@ -262,8 +265,9 @@ class MethodHandles: AllStatic { // working with member names static void resolve_MemberName(Handle mname, TRAPS); // compute vmtarget/vmindex from name/type static void expand_MemberName(Handle mname, int suppress, TRAPS); // expand defc/name/type if missing + static Handle new_MemberName(TRAPS); // must be followed by init_MemberName static void init_MemberName(oop mname_oop, oop target); // compute vmtarget/vmindex from target - static void init_MemberName(oop mname_oop, methodOop m, bool do_dispatch); + static void init_MemberName(oop mname_oop, methodOop m, bool do_dispatch = true); static void init_MemberName(oop mname_oop, klassOop field_holder, AccessFlags mods, int offset); static int find_MemberNames(klassOop k, symbolOop name, symbolOop sig, int mflags, klassOop caller, @@ -300,6 +304,7 @@ class MethodHandles: AllStatic { // format of query to getConstant: GC_JVM_PUSH_LIMIT = 0, GC_JVM_STACK_MOVE_UNIT = 1, + GC_CONV_OP_IMPLEMENTED_MASK = 2, // format of result from getTarget / encode_target: ETF_HANDLE_OR_METHOD_NAME = 0, // all available data (immediate MH or method) @@ -311,6 +316,11 @@ class MethodHandles: AllStatic { static oop encode_target(Handle mh, int format, TRAPS); // report vmtarget (to Java code) static bool class_cast_needed(klassOop src, klassOop dst); + static instanceKlassHandle resolve_instance_klass(oop java_mirror_oop, TRAPS); + static instanceKlassHandle resolve_instance_klass(jclass java_mirror_jh, TRAPS) { + return resolve_instance_klass(JNIHandles::resolve(java_mirror_jh), THREAD); + } + private: // These checkers operate on a pair of whole MethodTypes: static const char* check_method_type_change(oop src_mtype, int src_beg, int src_end, diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp index 1b164ab6f5b..a27ee6024b0 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp @@ -1557,7 +1557,7 @@ char* SharedRuntime::generate_wrong_method_type_message(JavaThread* thread, methodOop actual_method = MethodHandles::decode_method(actual, kignore, fignore); if (actual_method != NULL) { - if (actual_method->name() == vmSymbols::invoke_name()) + if (methodOopDesc::is_method_handle_invoke_name(actual_method->name())) mhName = "$"; else mhName = actual_method->signature()->as_C_string(); From 973b1ef143b7f51a3525086765ac470f334bdce9 Mon Sep 17 00:00:00 2001 From: John R Rose Date: Sat, 1 May 2010 21:57:35 -0700 Subject: [PATCH 21/54] 6939196: method handle signatures off the boot class path get linkage errors Adjust MethodType lookup logic to search off the BCP, but not to cache those results Reviewed-by: twisti --- .../share/vm/classfile/systemDictionary.cpp | 72 +++++++++++------ .../share/vm/classfile/systemDictionary.hpp | 7 +- .../src/share/vm/interpreter/linkResolver.cpp | 13 +-- .../src/share/vm/interpreter/linkResolver.hpp | 3 +- hotspot/src/share/vm/prims/methodHandles.cpp | 79 +++++++++++++++---- hotspot/src/share/vm/runtime/signature.cpp | 20 +++++ hotspot/src/share/vm/runtime/signature.hpp | 3 + 7 files changed, 150 insertions(+), 47 deletions(-) diff --git a/hotspot/src/share/vm/classfile/systemDictionary.cpp b/hotspot/src/share/vm/classfile/systemDictionary.cpp index 6ccbb21e634..23c4434d0fe 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp @@ -2343,12 +2343,9 @@ char* SystemDictionary::check_signature_loaders(symbolHandle signature, methodOop SystemDictionary::find_method_handle_invoke(symbolHandle name, symbolHandle signature, - Handle class_loader, - Handle protection_domain, + KlassHandle accessing_klass, TRAPS) { if (!EnableMethodHandles) return NULL; - assert(class_loader.is_null() && protection_domain.is_null(), - "cannot load specialized versions of MethodHandle.invoke"); if (invoke_method_table() == NULL) { // create this side table lazily _invoke_method_table = new SymbolPropertyTable(_invoke_method_size); @@ -2358,30 +2355,36 @@ methodOop SystemDictionary::find_method_handle_invoke(symbolHandle name, unsigned int hash = invoke_method_table()->compute_hash(signature, name_id); int index = invoke_method_table()->hash_to_index(hash); SymbolPropertyEntry* spe = invoke_method_table()->find_entry(index, hash, signature, name_id); + methodHandle non_cached_result; if (spe == NULL || spe->property_oop() == NULL) { + spe = NULL; // Must create lots of stuff here, but outside of the SystemDictionary lock. if (THREAD->is_Compiler_thread()) return NULL; // do not attempt from within compiler - Handle mt = find_method_handle_type(signature(), - class_loader, protection_domain, - CHECK_NULL); + bool found_on_bcp = false; + Handle mt = find_method_handle_type(signature(), accessing_klass, found_on_bcp, CHECK_NULL); KlassHandle mh_klass = SystemDictionaryHandles::MethodHandle_klass(); methodHandle m = methodOopDesc::make_invoke_method(mh_klass, name, signature, mt, CHECK_NULL); // Now grab the lock. We might have to throw away the new method, // if a racing thread has managed to install one at the same time. - { + if (found_on_bcp) { MutexLocker ml(SystemDictionary_lock, Thread::current()); spe = invoke_method_table()->find_entry(index, hash, signature, name_id); if (spe == NULL) spe = invoke_method_table()->add_entry(index, hash, signature, name_id); if (spe->property_oop() == NULL) spe->set_property_oop(m()); + } else { + non_cached_result = m; } } - methodOop m = (methodOop) spe->property_oop(); - assert(m->is_method(), ""); - return m; + if (spe != NULL && spe->property_oop() != NULL) { + assert(spe->property_oop()->is_method(), ""); + return (methodOop) spe->property_oop(); + } else { + return non_cached_result(); + } } // Ask Java code to find or construct a java.dyn.MethodType for the given @@ -2389,30 +2392,50 @@ methodOop SystemDictionary::find_method_handle_invoke(symbolHandle name, // Because of class loader constraints, all method handle usage must be // consistent with this loader. Handle SystemDictionary::find_method_handle_type(symbolHandle signature, - Handle class_loader, - Handle protection_domain, + KlassHandle accessing_klass, + bool& return_bcp_flag, TRAPS) { + Handle class_loader, protection_domain; + bool is_on_bcp = true; // keep this true as long as we can materialize from the boot classloader Handle empty; int npts = ArgumentCount(signature()).size(); objArrayHandle pts = oopFactory::new_objArray(SystemDictionary::Class_klass(), npts, CHECK_(empty)); int arg = 0; Handle rt; // the return type from the signature for (SignatureStream ss(signature()); !ss.is_done(); ss.next()) { - oop mirror; - if (!ss.is_object()) { - mirror = Universe::java_mirror(ss.type()); - } else { - symbolOop name_oop = ss.as_symbol(CHECK_(empty)); - symbolHandle name(THREAD, name_oop); - klassOop klass = resolve_or_fail(name, - class_loader, protection_domain, - true, CHECK_(empty)); - mirror = Klass::cast(klass)->java_mirror(); + oop mirror = NULL; + if (is_on_bcp) { + mirror = ss.as_java_mirror(class_loader, protection_domain, + SignatureStream::ReturnNull, CHECK_(empty)); + if (mirror == NULL) { + // fall back from BCP to accessing_klass + if (accessing_klass.not_null()) { + class_loader = Handle(THREAD, instanceKlass::cast(accessing_klass())->class_loader()); + protection_domain = Handle(THREAD, instanceKlass::cast(accessing_klass())->protection_domain()); + } + is_on_bcp = false; + } + } + if (!is_on_bcp) { + // Resolve, throwing a real error if it doesn't work. + mirror = ss.as_java_mirror(class_loader, protection_domain, + SignatureStream::NCDFError, CHECK_(empty)); } if (ss.at_return_type()) rt = Handle(THREAD, mirror); else pts->obj_at_put(arg++, mirror); + // Check accessibility. + if (ss.is_object() && accessing_klass.not_null()) { + klassOop sel_klass = java_lang_Class::as_klassOop(mirror); + // Emulate constantPoolOopDesc::verify_constant_pool_resolve. + if (Klass::cast(sel_klass)->oop_is_objArray()) + sel_klass = objArrayKlass::cast(sel_klass)->bottom_klass(); + if (Klass::cast(sel_klass)->oop_is_instance()) { + KlassHandle sel_kh(THREAD, sel_klass); + LinkResolver::check_klass_accessability(accessing_klass, sel_kh, CHECK_(empty)); + } + } } assert(arg == npts, ""); @@ -2425,6 +2448,9 @@ Handle SystemDictionary::find_method_handle_type(symbolHandle signature, vmSymbols::findMethodHandleType_name(), vmSymbols::findMethodHandleType_signature(), &args, CHECK_(empty)); + + // report back to the caller with the MethodType and the "on_bcp" flag + return_bcp_flag = is_on_bcp; return Handle(THREAD, (oop) result.get_jobject()); } diff --git a/hotspot/src/share/vm/classfile/systemDictionary.hpp b/hotspot/src/share/vm/classfile/systemDictionary.hpp index 0d88d4206fd..bd31fbb4957 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.hpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp @@ -466,13 +466,12 @@ public: // find the java.dyn.MethodHandles::invoke method for a given signature static methodOop find_method_handle_invoke(symbolHandle name, symbolHandle signature, - Handle class_loader, - Handle protection_domain, + KlassHandle accessing_klass, TRAPS); // ask Java to compute a java.dyn.MethodType object for a given signature static Handle find_method_handle_type(symbolHandle signature, - Handle class_loader, - Handle protection_domain, + KlassHandle accessing_klass, + bool& return_bcp_flag, TRAPS); // ask Java to create a dynamic call site, while linking an invokedynamic op static Handle make_dynamic_call_site(Handle bootstrap_method, diff --git a/hotspot/src/share/vm/interpreter/linkResolver.cpp b/hotspot/src/share/vm/interpreter/linkResolver.cpp index d80ef9daf52..1dcea5db93f 100644 --- a/hotspot/src/share/vm/interpreter/linkResolver.cpp +++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp @@ -172,14 +172,16 @@ void LinkResolver::lookup_method_in_interfaces(methodHandle& result, KlassHandle result = methodHandle(THREAD, ik->lookup_method_in_all_interfaces(name(), signature())); } -void LinkResolver::lookup_implicit_method(methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS) { +void LinkResolver::lookup_implicit_method(methodHandle& result, + KlassHandle klass, symbolHandle name, symbolHandle signature, + KlassHandle current_klass, + TRAPS) { if (EnableMethodHandles && MethodHandles::enabled() && klass() == SystemDictionary::MethodHandle_klass() && methodOopDesc::is_method_handle_invoke_name(name())) { methodOop result_oop = SystemDictionary::find_method_handle_invoke(name, signature, - Handle(), - Handle(), + current_klass, CHECK); if (result_oop != NULL) { assert(result_oop->is_method_handle_invoke() && result_oop->signature() == signature(), "consistent"); @@ -290,7 +292,7 @@ void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle res if (resolved_method.is_null()) { // JSR 292: see if this is an implicitly generated method MethodHandle.invoke(*...) - lookup_implicit_method(resolved_method, resolved_klass, method_name, method_signature, CHECK); + lookup_implicit_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, CHECK); } if (resolved_method.is_null()) { @@ -1058,7 +1060,8 @@ void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle po // JSR 292: this must be an implicitly generated method MethodHandle.invokeExact(*...) // The extra MH receiver will be inserted into the stack on every call. methodHandle resolved_method; - lookup_implicit_method(resolved_method, resolved_klass, method_name, method_signature, CHECK); + KlassHandle current_klass(THREAD, pool->pool_holder()); + lookup_implicit_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, CHECK); if (resolved_method.is_null()) { THROW(vmSymbols::java_lang_InternalError()); } diff --git a/hotspot/src/share/vm/interpreter/linkResolver.hpp b/hotspot/src/share/vm/interpreter/linkResolver.hpp index efc1b53f5f3..673a166d0e7 100644 --- a/hotspot/src/share/vm/interpreter/linkResolver.hpp +++ b/hotspot/src/share/vm/interpreter/linkResolver.hpp @@ -103,7 +103,8 @@ class LinkResolver: AllStatic { static void lookup_method_in_klasses (methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS); static void lookup_instance_method_in_klasses (methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS); static void lookup_method_in_interfaces (methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS); - static void lookup_implicit_method (methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS); + static void lookup_implicit_method (methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, + KlassHandle current_klass, TRAPS); static int vtable_index_of_miranda_method(KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS); diff --git a/hotspot/src/share/vm/prims/methodHandles.cpp b/hotspot/src/share/vm/prims/methodHandles.cpp index 9581757f061..9d9c2140864 100644 --- a/hotspot/src/share/vm/prims/methodHandles.cpp +++ b/hotspot/src/share/vm/prims/methodHandles.cpp @@ -475,16 +475,25 @@ void MethodHandles::resolve_MemberName(Handle mname, TRAPS) { if (name.is_null()) return; // no such name name_str = NULL; // safety + Handle polymorphic_method_type; + bool polymorphic_signature = false; + if ((flags & ALL_KINDS) == IS_METHOD && + (defc() == SystemDictionary::InvokeDynamic_klass() || + (defc() == SystemDictionary::MethodHandle_klass() && + methodOopDesc::is_method_handle_invoke_name(name())))) + polymorphic_signature = true; + // convert the external string or reflective type to an internal signature - bool force_signature = methodOopDesc::is_method_handle_invoke_name(name()); symbolHandle type; { symbolOop type_sym = NULL; if (java_dyn_MethodType::is_instance(type_str)) { - type_sym = java_dyn_MethodType::as_signature(type_str, force_signature, CHECK); + type_sym = java_dyn_MethodType::as_signature(type_str, polymorphic_signature, CHECK); + if (polymorphic_signature) + polymorphic_method_type = Handle(THREAD, type_str); //preserve exactly } else if (java_lang_Class::is_instance(type_str)) { - type_sym = java_lang_Class::as_signature(type_str, force_signature, CHECK); + type_sym = java_lang_Class::as_signature(type_str, false, CHECK); } else if (java_lang_String::is_instance(type_str)) { - if (force_signature) { + if (polymorphic_signature) { type = java_lang_String::as_symbol(type_str, CHECK); } else { type_sym = java_lang_String::as_symbol_or_null(type_str); @@ -517,7 +526,7 @@ void MethodHandles::resolve_MemberName(Handle mname, TRAPS) { } if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; - return; + break; // go to second chance } } methodHandle m = result.resolved_method(); @@ -591,8 +600,42 @@ void MethodHandles::resolve_MemberName(Handle mname, TRAPS) { sun_dyn_MemberName::set_modifiers(mname(), mods); return; } + default: + THROW_MSG(vmSymbols::java_lang_InternalError(), "unrecognized MemberName format"); + } + + // Second chance. + if (polymorphic_method_type.not_null()) { + // Look on a non-null class loader. + Handle cur_class_loader; + const int nptypes = java_dyn_MethodType::ptype_count(polymorphic_method_type()); + for (int i = 0; i <= nptypes; i++) { + oop type_mirror; + if (i < nptypes) type_mirror = java_dyn_MethodType::ptype(polymorphic_method_type(), i); + else type_mirror = java_dyn_MethodType::rtype(polymorphic_method_type()); + klassOop example_type = java_lang_Class::as_klassOop(type_mirror); + if (example_type == NULL) continue; + oop class_loader = Klass::cast(example_type)->class_loader(); + if (class_loader == NULL || class_loader == cur_class_loader()) continue; + cur_class_loader = Handle(THREAD, class_loader); + methodOop m = SystemDictionary::find_method_handle_invoke(name, + type, + KlassHandle(THREAD, example_type), + THREAD); + if (HAS_PENDING_EXCEPTION) { + CLEAR_PENDING_EXCEPTION; + m = NULL; + // try again with a different class loader... + } + if (m != NULL) { + int mods = (m->access_flags().as_short() & JVM_RECOGNIZED_METHOD_MODIFIERS); + sun_dyn_MemberName::set_vmtarget(mname(), m); + sun_dyn_MemberName::set_vmindex(mname(), m->vtable_index()); + sun_dyn_MemberName::set_modifiers(mname(), mods); + return; + } + } } - THROW_MSG(vmSymbols::java_lang_InternalError(), "unrecognized MemberName format"); } // Conversely, a member name which is only initialized from JVM internals @@ -993,6 +1036,13 @@ void MethodHandles::verify_method_signature(methodHandle m, pnum += 1; mnum += 1; } + klassOop pklass = NULL; + BasicType ptype = T_OBJECT; + if (ptype_oop != NULL) + ptype = java_lang_Class::as_BasicType(ptype_oop, &pklass); + else + // null does not match any non-reference; use Object to report the error + pklass = SystemDictionary::Object_klass(); klassOop mklass = NULL; BasicType mtype = ss.type(); if (mtype == T_ARRAY) mtype = T_OBJECT; // fold all refs to T_OBJECT @@ -1001,21 +1051,22 @@ void MethodHandles::verify_method_signature(methodHandle m, // null matches any reference continue; } + KlassHandle pklass_handle(THREAD, pklass); pklass = NULL; // If we fail to resolve types at this point, we will throw an error. symbolOop name_oop = ss.as_symbol(CHECK); symbolHandle name(THREAD, name_oop); instanceKlass* mk = instanceKlass::cast(m->method_holder()); Handle loader(THREAD, mk->class_loader()); Handle domain(THREAD, mk->protection_domain()); - mklass = SystemDictionary::resolve_or_fail(name, loader, domain, - true, CHECK); + mklass = SystemDictionary::resolve_or_null(name, loader, domain, CHECK); + pklass = pklass_handle(); + if (mklass == NULL && pklass != NULL && + Klass::cast(pklass)->name() == name() && + m->is_method_handle_invoke()) { + // Assume a match. We can't really decode the signature of MH.invoke*. + continue; + } } - if (ptype_oop == NULL) { - // null does not match any non-reference; use Object to report the error - ptype_oop = object_java_mirror(); - } - klassOop pklass = NULL; - BasicType ptype = java_lang_Class::as_BasicType(ptype_oop, &pklass); if (!ss.at_return_type()) { err = check_argument_type_change(ptype, pklass, mtype, mklass, mnum); } else { diff --git a/hotspot/src/share/vm/runtime/signature.cpp b/hotspot/src/share/vm/runtime/signature.cpp index c9c3859a612..ca46e2ceafd 100644 --- a/hotspot/src/share/vm/runtime/signature.cpp +++ b/hotspot/src/share/vm/runtime/signature.cpp @@ -327,6 +327,26 @@ symbolOop SignatureStream::as_symbol(TRAPS) { return result; } +klassOop SignatureStream::as_klass(Handle class_loader, Handle protection_domain, + FailureMode failure_mode, TRAPS) { + if (!is_object()) return NULL; + symbolOop name = as_symbol(CHECK_NULL); + if (failure_mode == ReturnNull) { + return SystemDictionary::resolve_or_null(name, class_loader, protection_domain, THREAD); + } else { + bool throw_error = (failure_mode == NCDFError); + return SystemDictionary::resolve_or_fail(name, class_loader, protection_domain, throw_error, THREAD); + } +} + +oop SignatureStream::as_java_mirror(Handle class_loader, Handle protection_domain, + FailureMode failure_mode, TRAPS) { + if (!is_object()) + return Universe::java_mirror(type()); + klassOop klass = as_klass(class_loader, protection_domain, failure_mode, CHECK_NULL); + if (klass == NULL) return NULL; + return Klass::cast(klass)->java_mirror(); +} symbolOop SignatureStream::as_symbol_or_null() { // Create a symbol from for string _begin _end diff --git a/hotspot/src/share/vm/runtime/signature.hpp b/hotspot/src/share/vm/runtime/signature.hpp index 9d67b0334ec..aeed8037ca9 100644 --- a/hotspot/src/share/vm/runtime/signature.hpp +++ b/hotspot/src/share/vm/runtime/signature.hpp @@ -402,6 +402,9 @@ class SignatureStream : public StackObj { bool is_array() const; // True if this argument is an array BasicType type() const { return _type; } symbolOop as_symbol(TRAPS); + enum FailureMode { ReturnNull, CNFException, NCDFError }; + klassOop as_klass(Handle class_loader, Handle protection_domain, FailureMode failure_mode, TRAPS); + oop as_java_mirror(Handle class_loader, Handle protection_domain, FailureMode failure_mode, TRAPS); // return same as_symbol except allocation of new symbols is avoided. symbolOop as_symbol_or_null(); From 762f60d34358ab9f880cfed0591ec457e83420ab Mon Sep 17 00:00:00 2001 From: "Y. Srinivas Ramakrishna" Date: Mon, 3 May 2010 10:24:51 -0700 Subject: [PATCH 22/54] 6948537: CMS: BOT walkers observe out-of-thin-air zeros on sun4v sparc/CMT On sun4v/CMT avoid use of memset() in BOT updates so as to prevent concurrent BOT readers from seeing the phantom zeros arising from memset()'s use of BIS. Reviewed-by: jmasa, johnc, minqi, poonam, tonyp --- hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp | 6 ++++ .../concurrentMarkSweepGeneration.cpp | 8 ++++++ .../src/share/vm/memory/blockOffsetTable.hpp | 28 +++++++++++++++++-- hotspot/src/share/vm/runtime/globals.hpp | 4 +++ 4 files changed, 44 insertions(+), 2 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp index 9458c1c012f..3b2ef27f75d 100644 --- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp @@ -104,6 +104,12 @@ void VM_Version::initialize() { if (FLAG_IS_DEFAULT(OptoLoopAlignment)) { FLAG_SET_DEFAULT(OptoLoopAlignment, 4); } + // When using CMS, we cannot use memset() in BOT updates because + // the sun4v/CMT version in libc_psr uses BIS which exposes + // "phantom zeros" to concurrent readers. See 6948537. + if (FLAG_IS_DEFAULT(UseMemSetInBOT) && UseConcMarkSweepGC) { + FLAG_SET_DEFAULT(UseMemSetInBOT, false); + } } // Use hardware population count instruction if available. diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp index e96bbae4306..16c1b70fa17 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp @@ -789,6 +789,14 @@ CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen, _gc_counters = new CollectorCounters("CMS", 1); _completed_initialization = true; _inter_sweep_timer.start(); // start of time +#ifdef SPARC + // Issue a stern warning, but allow use for experimentation and debugging. + if (VM_Version::is_sun4v() && UseMemSetInBOT) { + assert(!FLAG_IS_DEFAULT(UseMemSetInBOT), "Error"); + warning("Experimental flag -XX:+UseMemSetInBOT is known to cause instability" + " on sun4v; please understand that you are using at your own risk!"); + } +#endif } const char* ConcurrentMarkSweepGeneration::name() const { diff --git a/hotspot/src/share/vm/memory/blockOffsetTable.hpp b/hotspot/src/share/vm/memory/blockOffsetTable.hpp index 2b64487d5b0..3caa0649855 100644 --- a/hotspot/src/share/vm/memory/blockOffsetTable.hpp +++ b/hotspot/src/share/vm/memory/blockOffsetTable.hpp @@ -140,14 +140,38 @@ class BlockOffsetSharedArray: public CHeapObj { "right address out of range"); assert(left < right, "Heap addresses out of order"); size_t num_cards = pointer_delta(right, left) >> LogN_words; - memset(&_offset_array[index_for(left)], offset, num_cards); + + // Below, we may use an explicit loop instead of memset() + // because on certain platforms memset() can give concurrent + // readers "out-of-thin-air," phantom zeros; see 6948537. + if (UseMemSetInBOT) { + memset(&_offset_array[index_for(left)], offset, num_cards); + } else { + size_t i = index_for(left); + const size_t end = i + num_cards; + for (; i < end; i++) { + _offset_array[i] = offset; + } + } } void set_offset_array(size_t left, size_t right, u_char offset) { assert(right < _vs.committed_size(), "right address out of range"); assert(left <= right, "indexes out of order"); size_t num_cards = right - left + 1; - memset(&_offset_array[left], offset, num_cards); + + // Below, we may use an explicit loop instead of memset + // because on certain platforms memset() can give concurrent + // readers "out-of-thin-air," phantom zeros; see 6948537. + if (UseMemSetInBOT) { + memset(&_offset_array[left], offset, num_cards); + } else { + size_t i = left; + const size_t end = i + num_cards; + for (; i < end; i++) { + _offset_array[i] = offset; + } + } } void check_offset_array(size_t index, HeapWord* high, HeapWord* low) const { diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 911b2abb4cb..95d3055b784 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -327,6 +327,10 @@ class CommandLineFlags { product(bool, UseMembar, false, \ "(Unstable) Issues membars on thread state transitions") \ \ + /* Temporary: See 6948537 */ \ + experimental(bool, UseMemSetInBOT, true, \ + "(Unstable) uses memset in BOT updates in GC code") \ + \ diagnostic(bool, UnlockDiagnosticVMOptions, trueInDebug, \ "Enable normal processing of flags relating to field diagnostics")\ \ From d14cf2e13cb6e896e718de822266b7b8abc71204 Mon Sep 17 00:00:00 2001 From: "Y. Srinivas Ramakrishna" Date: Mon, 3 May 2010 20:19:05 -0700 Subject: [PATCH 23/54] 6919638: CMS: ExplicitGCInvokesConcurrent misinteracts with gc locker GC-locker induced concurrent full gc should be asynchronous; policy now controlled by a separate flag, which defaults to false. Reviewed-by: jmasa --- .../concurrentMarkSweep/concurrentMarkSweepGeneration.cpp | 3 +-- .../concurrentMarkSweep/vmCMSOperations.cpp | 7 +++++-- .../concurrentMarkSweep/vmCMSOperations.hpp | 3 +-- hotspot/src/share/vm/memory/genCollectedHeap.cpp | 6 +++--- hotspot/src/share/vm/runtime/globals.hpp | 4 ++++ 5 files changed, 14 insertions(+), 9 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp index 16c1b70fa17..a7d284fad66 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp @@ -1424,10 +1424,9 @@ bool ConcurrentMarkSweepGeneration::should_collect(bool full, bool CMSCollector::shouldConcurrentCollect() { if (_full_gc_requested) { - assert(ExplicitGCInvokesConcurrent, "Unexpected state"); if (Verbose && PrintGCDetails) { gclog_or_tty->print_cr("CMSCollector: collect because of explicit " - " gc request"); + " gc request (or gc_locker)"); } return true; } diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp index 8d2ce7f19f0..28e64af3e52 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp @@ -163,6 +163,7 @@ void VM_CMS_Final_Remark::doit() { // GenCollectedHeap heap. void VM_GenCollectFullConcurrent::doit() { assert(Thread::current()->is_VM_thread(), "Should be VM thread"); + assert(GCLockerInvokesConcurrent || ExplicitGCInvokesConcurrent, "Unexpected"); GenCollectedHeap* gch = GenCollectedHeap::heap(); if (_gc_count_before == gch->total_collections()) { @@ -190,7 +191,7 @@ void VM_GenCollectFullConcurrent::doit() { CMSCollector::disable_icms(); // In case CMS thread was in icms_wait(), wake it up. CMSCollector::start_icms(); - // Nudge the CMS thread to start a concurrent collection + // Nudge the CMS thread to start a concurrent collection. CMSCollector::request_full_gc(_full_gc_count_before); } else { FullGCCount_lock->notify_all(); // Inform the Java thread its work is done @@ -231,7 +232,9 @@ void VM_GenCollectFullConcurrent::doit_epilogue() { // e.g. at the rate of 1 full gc per ms, this could // overflow in about 1000 years. GenCollectedHeap* gch = GenCollectedHeap::heap(); - if (gch->total_full_collections_completed() <= _full_gc_count_before) { + if (_gc_cause != GCCause::_gc_locker && + gch->total_full_collections_completed() <= _full_gc_count_before) { + assert(ExplicitGCInvokesConcurrent, "Error"); // Now, wait for witnessing concurrent gc cycle to complete, // but do so in native mode, because we want to lock the // FullGCEvent_lock, which may be needed by the VM thread diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.hpp index 0ed06fba99c..cc8bd3abc60 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.hpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.hpp @@ -126,8 +126,7 @@ class VM_GenCollectFullConcurrent: public VM_GC_Operation { GCCause::Cause gc_cause) : VM_GC_Operation(gc_count_before, full_gc_count_before, true /* full */) { _gc_cause = gc_cause; - assert(FullGCCount_lock != NULL && UseConcMarkSweepGC && - ExplicitGCInvokesConcurrent, "Otherwise shouldn't be here"); + assert(FullGCCount_lock != NULL, "Error"); assert(UseAsyncConcMarkSweepGC, "Else will hang caller"); } ~VM_GenCollectFullConcurrent() {} diff --git a/hotspot/src/share/vm/memory/genCollectedHeap.cpp b/hotspot/src/share/vm/memory/genCollectedHeap.cpp index a0549f27c71..f250b01f6de 100644 --- a/hotspot/src/share/vm/memory/genCollectedHeap.cpp +++ b/hotspot/src/share/vm/memory/genCollectedHeap.cpp @@ -410,9 +410,9 @@ bool GenCollectedHeap::must_clear_all_soft_refs() { } bool GenCollectedHeap::should_do_concurrent_full_gc(GCCause::Cause cause) { - return (cause == GCCause::_java_lang_system_gc || - cause == GCCause::_gc_locker) && - UseConcMarkSweepGC && ExplicitGCInvokesConcurrent; + return UseConcMarkSweepGC && + ((cause == GCCause::_gc_locker && GCLockerInvokesConcurrent) || + (cause == GCCause::_java_lang_system_gc && ExplicitGCInvokesConcurrent)); } void GenCollectedHeap::do_collection(bool full, diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 95d3055b784..d37e465bbed 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -1303,6 +1303,10 @@ class CommandLineFlags { "also unloads classes during such a concurrent gc cycle " \ "(effective only when UseConcMarkSweepGC)") \ \ + product(bool, GCLockerInvokesConcurrent, false, \ + "The exit of a JNI CS necessitating a scavenge also" \ + " kicks off a bkgrd concurrent collection") \ + \ develop(bool, UseCMSAdaptiveFreeLists, true, \ "Use Adaptive Free Lists in the CMS generation") \ \ From 416df6da75a1e681bbe353a0dd76cdc97477e9ae Mon Sep 17 00:00:00 2001 From: Gary Benson Date: Tue, 4 May 2010 02:33:59 -0700 Subject: [PATCH 24/54] 6949423: remove tagged stack interpreter for Zero Missed Zero changes for 6943304. Reviewed-by: twisti --- hotspot/src/cpu/zero/vm/interpreter_zero.hpp | 6 +++--- hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp | 8 ++++---- hotspot/src/share/vm/interpreter/bytecodeInterpreter.hpp | 8 +------- 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/hotspot/src/cpu/zero/vm/interpreter_zero.hpp b/hotspot/src/cpu/zero/vm/interpreter_zero.hpp index df0ccb7348c..4ea5623c15a 100644 --- a/hotspot/src/cpu/zero/vm/interpreter_zero.hpp +++ b/hotspot/src/cpu/zero/vm/interpreter_zero.hpp @@ -36,14 +36,14 @@ public: static int expr_index_at(int i) { - return stackElementWords() * i; + return stackElementWords * i; } static int expr_offset_in_bytes(int i) { - return stackElementSize() * i; + return stackElementSize * i; } static int local_index_at(int i) { assert(i <= 0, "local direction already negated"); - return stackElementWords() * i; + return stackElementWords * i; } diff --git a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp index f93608f13c0..bb331380131 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp @@ -189,7 +189,7 @@ // JavaStack Implementation #define MORE_STACK(count) \ - (topOfStack -= ((count) * Interpreter::stackElementWords())) + (topOfStack -= ((count) * Interpreter::stackElementWords)) #define UPDATE_PC(opsize) {pc += opsize; } @@ -1950,8 +1950,8 @@ run: jint size = STACK_INT(-1); // stack grows down, dimensions are up! jint *dimarray = - (jint*)&topOfStack[dims * Interpreter::stackElementWords()+ - Interpreter::stackElementWords()-1]; + (jint*)&topOfStack[dims * Interpreter::stackElementWords+ + Interpreter::stackElementWords-1]; //adjust pointer to start of stack element CALL_VM(InterpreterRuntime::multianewarray(THREAD, dimarray), handle_exception); @@ -2375,7 +2375,7 @@ run: assert(except_oop(), "No exception to process"); intptr_t continuation_bci; // expression stack is emptied - topOfStack = istate->stack_base() - Interpreter::stackElementWords(); + topOfStack = istate->stack_base() - Interpreter::stackElementWords; CALL_VM(continuation_bci = (intptr_t)InterpreterRuntime::exception_handler_for_exception(THREAD, except_oop()), handle_exception); diff --git a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.hpp b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.hpp index ea68b860b4c..c30474597ec 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.hpp +++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2002-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 @@ -510,8 +510,6 @@ static oop stack_object(intptr_t *tos, int offset); static jdouble stack_double(intptr_t *tos, int offset); static jlong stack_long(intptr_t *tos, int offset); -static void tag_stack(intptr_t *tos, frame::Tag tag, int offset); - // only used for value types static void set_stack_slot(intptr_t *tos, address value, int offset); static void set_stack_int(intptr_t *tos, int value, int offset); @@ -537,8 +535,6 @@ static jlong locals_long(intptr_t* locals, int offset); static address locals_long_at(intptr_t* locals, int offset); static address locals_double_at(intptr_t* locals, int offset); -static void tag_locals(intptr_t *locals, frame::Tag tag, int offset); - static void set_locals_slot(intptr_t *locals, address value, int offset); static void set_locals_int(intptr_t *locals, jint value, int offset); static void set_locals_float(intptr_t *locals, jfloat value, int offset); @@ -557,8 +553,6 @@ static void astore(intptr_t* topOfStack, int stack_offset, static void copy_stack_slot(intptr_t *tos, int from_offset, int to_offset); #ifndef PRODUCT -static void verify_locals_tag(intptr_t *locals, frame::Tag tag, int offset); -static void verify_stack_tag(intptr_t *tos, frame::Tag tag, int offset); static const char* C_msg(BytecodeInterpreter::messages msg); void print(); #endif // PRODUCT From 43a9130faa25b37caf3ac36f3484f21fe9b870b4 Mon Sep 17 00:00:00 2001 From: Volker Simonis Date: Tue, 4 May 2010 15:12:08 -0400 Subject: [PATCH 25/54] 6935118: UseCompressedOops modification in methodOopDesc::sort_methods() causes JCK timeout Add comparison functions for compressed oops to use bubblesort. Reviewed-by: never, coleenp --- hotspot/src/share/vm/oops/methodOop.cpp | 24 ++- .../test/runtime/6925573/SortMethodsTest.java | 190 ++++++++++++++++++ 2 files changed, 209 insertions(+), 5 deletions(-) create mode 100644 hotspot/test/runtime/6925573/SortMethodsTest.java diff --git a/hotspot/src/share/vm/oops/methodOop.cpp b/hotspot/src/share/vm/oops/methodOop.cpp index 07ef9a8b9a5..9e281f0d482 100644 --- a/hotspot/src/share/vm/oops/methodOop.cpp +++ b/hotspot/src/share/vm/oops/methodOop.cpp @@ -1114,6 +1114,20 @@ extern "C" { return ( a < b ? -1 : (a == b ? 0 : 1)); } + // We implement special compare versions for narrow oops to avoid + // testing for UseCompressedOops on every comparison. + static int method_compare_narrow(narrowOop* a, narrowOop* b) { + methodOop m = (methodOop)oopDesc::load_decode_heap_oop(a); + methodOop n = (methodOop)oopDesc::load_decode_heap_oop(b); + return m->name()->fast_compare(n->name()); + } + + static int method_compare_narrow_idempotent(narrowOop* a, narrowOop* b) { + int i = method_compare_narrow(a, b); + if (i != 0) return i; + return ( a < b ? -1 : (a == b ? 0 : 1)); + } + typedef int (*compareFn)(const void*, const void*); } @@ -1166,7 +1180,7 @@ void methodOopDesc::sort_methods(objArrayOop methods, // Use a simple bubble sort for small number of methods since // qsort requires a functional pointer call for each comparison. - if (UseCompressedOops || length < 8) { + if (length < 8) { bool sorted = true; for (int i=length-1; i>0; i--) { for (int j=0; jbase(), length, heapOopSize, compare); } diff --git a/hotspot/test/runtime/6925573/SortMethodsTest.java b/hotspot/test/runtime/6925573/SortMethodsTest.java new file mode 100644 index 00000000000..33638c39ff8 --- /dev/null +++ b/hotspot/test/runtime/6925573/SortMethodsTest.java @@ -0,0 +1,190 @@ +/* + * 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 + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.StringWriter; + +import java.lang.reflect.Method; +import java.net.URI; +import java.util.Arrays; +import java.util.Vector; + +import javax.tools.Diagnostic; +import javax.tools.DiagnosticCollector; +import javax.tools.FileObject; +import javax.tools.ForwardingJavaFileManager; +import javax.tools.JavaCompiler; +import javax.tools.JavaCompiler.CompilationTask; +import javax.tools.JavaFileManager; +import javax.tools.JavaFileObject; +import javax.tools.JavaFileObject.Kind; +import javax.tools.SimpleJavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; + +/* + * @test SortMethodsTest + * @bug 6925573 + * @summary verify that class loading does not need quadratic time with regard to the number of class +methods. + * @run main SortMethodsTest + * @author volker.simonis@gmail.com +*/ + +public class SortMethodsTest { + + static String createClass(String name, int nrOfMethods) { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + pw.println("public class " + name + "{"); + for (int i = 0; i < nrOfMethods; i++) { + pw.println(" public void m" + i + "() {}"); + } + pw.println(" public static String sayHello() {"); + pw.println(" return \"Hello from class \" + " + name + + ".class.getName() + \" with \" + " + name + + ".class.getDeclaredMethods().length + \" methods\";"); + pw.println(" }"); + pw.println("}"); + pw.close(); + return sw.toString(); + } + + public static void main(String args[]) { + + JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); + DiagnosticCollector diags = new DiagnosticCollector(); + final String cName = new String("ManyMethodsClass"); + Vector results = new Vector(); + + for (int i = 6; i < 600000; i*=10) { + String klass = createClass(cName, i); + JavaMemoryFileObject file = new JavaMemoryFileObject(cName, klass); + MemoryFileManager mfm = new MemoryFileManager(comp.getStandardFileManager(diags, null, null), file); + CompilationTask task = comp.getTask(null, mfm, diags, null, null, Arrays.asList(file)); + + if (task.call()) { + try { + MemoryClassLoader mcl = new MemoryClassLoader(file); + long start = System.nanoTime(); + Class c = Class.forName(cName, true, mcl); + long end = System.nanoTime(); + results.add(end - start); + Method m = c.getDeclaredMethod("sayHello", new Class[0]); + String ret = (String)m.invoke(null, new Object[0]); + System.out.println(ret + " (loaded and resloved in " + (end - start) + "ns)"); + } catch (Exception e) { + System.err.println(e); + } + } + else { + System.out.println(klass); + System.out.println(); + for (Diagnostic diag : diags.getDiagnostics()) { + System.out.println(diag.getCode() + "\n" + diag.getKind() + "\n" + diag.getPosition()); + System.out.println(diag.getSource() + "\n" + diag.getMessage(null)); + } + } + } + + long lastRatio = 0; + for (int i = 2; i < results.size(); i++) { + long normalized1 = Math.max(results.get(i-1) - results.get(0), 1); + long normalized2 = Math.max(results.get(i) - results.get(0), 1); + long ratio = normalized2/normalized1; + lastRatio = ratio; + System.out.println("10 x more methods requires " + ratio + " x more time"); + } + // The following is just vague estimation but seems to work on current x86_64 and sparcv9 machines + if (lastRatio > 80) { + throw new RuntimeException("ATTENTION: it seems that class loading needs quadratic time with regard to the number of class methods!!!"); + } + } +} + +class JavaMemoryFileObject extends SimpleJavaFileObject { + + private final String code; + private ByteArrayOutputStream byteCode; + + JavaMemoryFileObject(String name, String code) { + super(URI.create("string:///" + name.replace('.','/') + Kind.SOURCE.extension), Kind.SOURCE); + this.code = code; + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return code; + } + + @Override + public OutputStream openOutputStream() { + byteCode = new ByteArrayOutputStream(); + return byteCode; + } + + byte[] getByteCode() { + return byteCode.toByteArray(); + } +} + +class MemoryClassLoader extends ClassLoader { + + private final JavaMemoryFileObject jfo; + + public MemoryClassLoader(JavaMemoryFileObject jfo) { + this.jfo = jfo; + } + + public Class findClass(String name) { + byte[] b = jfo.getByteCode(); + return defineClass(name, b, 0, b.length); + } +} + +class MemoryFileManager extends ForwardingJavaFileManager { + + private final JavaFileObject jfo; + + public MemoryFileManager(StandardJavaFileManager jfm, JavaFileObject jfo) { + super(jfm); + this.jfo = jfo; + } + + @Override + public FileObject getFileForInput(Location location, String packageName, + String relativeName) throws IOException { + return jfo; + } + + @Override + public JavaFileObject getJavaFileForOutput(Location location, String qualifiedName, + Kind kind, FileObject outputFile) throws IOException { + return jfo; + } + +} From e3e5b8ad72dab169c4353988d3ffb9f2c7a44c89 Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Wed, 5 May 2010 13:18:31 +0100 Subject: [PATCH 26/54] 6886723: light weight http server doesn't return correct status code for HEAD requests Reviewed-by: michaelm --- .../sun/net/httpserver/ExchangeImpl.java | 54 +++++--- .../com/sun/net/httpserver/bugs/HeadTest.java | 117 ++++++++++++++++++ 2 files changed, 151 insertions(+), 20 deletions(-) create mode 100644 jdk/test/com/sun/net/httpserver/bugs/HeadTest.java diff --git a/jdk/src/share/classes/sun/net/httpserver/ExchangeImpl.java b/jdk/src/share/classes/sun/net/httpserver/ExchangeImpl.java index ccb9151b69c..69ed824f67f 100644 --- a/jdk/src/share/classes/sun/net/httpserver/ExchangeImpl.java +++ b/jdk/src/share/classes/sun/net/httpserver/ExchangeImpl.java @@ -26,16 +26,12 @@ package sun.net.httpserver; import java.io.*; -import java.nio.*; -import java.nio.channels.*; import java.net.*; import javax.net.ssl.*; import java.util.*; import java.util.logging.Logger; import java.text.*; -import sun.net.www.MessageHeader; import com.sun.net.httpserver.*; -import com.sun.net.httpserver.spi.*; class ExchangeImpl { @@ -65,6 +61,8 @@ class ExchangeImpl { df.setTimeZone (tz); } + private static final String HEAD = "HEAD"; + /* streams which take care of the HTTP protocol framing * and are passed up to higher layers */ @@ -116,6 +114,10 @@ class ExchangeImpl { return connection.getHttpContext(); } + private boolean isHeadRequest() { + return HEAD.equals(getRequestMethod()); + } + public void close () { if (closed) { return; @@ -220,24 +222,36 @@ class ExchangeImpl { } contentLen = -1; } - if (contentLen == 0) { - if (http10) { - o.setWrappedStream (new UndefLengthOutputStream (this, ros)); - close = true; + + if (isHeadRequest()) { + /* HEAD requests should not set a content length by passing it + * through this API, but should instead manually set the required + * headers.*/ + if (contentLen >= 0) { + final Logger logger = server.getLogger(); + String msg = + "sendResponseHeaders: being invoked with a content length for a HEAD request"; + logger.warning (msg); + } + noContentToSend = true; + contentLen = 0; + } else { /* not a HEAD request */ + if (contentLen == 0) { + if (http10) { + o.setWrappedStream (new UndefLengthOutputStream (this, ros)); + close = true; + } else { + rspHdrs.set ("Transfer-encoding", "chunked"); + o.setWrappedStream (new ChunkedOutputStream (this, ros)); + } } else { - rspHdrs.set ("Transfer-encoding", "chunked"); - o.setWrappedStream (new ChunkedOutputStream (this, ros)); + if (contentLen == -1) { + noContentToSend = true; + contentLen = 0; + } + rspHdrs.set("Content-length", Long.toString(contentLen)); + o.setWrappedStream (new FixedLengthOutputStream (this, ros, contentLen)); } - } else { - if (contentLen == -1) { - noContentToSend = true; - contentLen = 0; - } - /* content len might already be set, eg to implement HEAD resp */ - if (rspHdrs.getFirst ("Content-length") == null) { - rspHdrs.set ("Content-length", Long.toString(contentLen)); - } - o.setWrappedStream (new FixedLengthOutputStream (this, ros, contentLen)); } write (rspHdrs, tmpout); this.rspContentLen = contentLen; diff --git a/jdk/test/com/sun/net/httpserver/bugs/HeadTest.java b/jdk/test/com/sun/net/httpserver/bugs/HeadTest.java new file mode 100644 index 00000000000..8b7055338a1 --- /dev/null +++ b/jdk/test/com/sun/net/httpserver/bugs/HeadTest.java @@ -0,0 +1,117 @@ +/* + * Copyright 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 + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 6886723 + * @summary light weight http server doesn't return correct status code for HEAD requests + */ + +import java.net.InetSocketAddress; +import java.net.HttpURLConnection; +import java.net.URL; +import java.io.IOException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import com.sun.net.httpserver.HttpContext; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; + +public class HeadTest { + + public static void main(String[] args) throws Exception { + server(); + } + + static void server() throws Exception { + InetSocketAddress inetAddress = new InetSocketAddress(0); + HttpServer server = HttpServer.create(inetAddress, 5); + try { + server.setExecutor(Executors.newFixedThreadPool(5)); + HttpContext chunkedContext = server.createContext("/chunked"); + chunkedContext.setHandler(new HttpHandler() { + @Override + public void handle(HttpExchange msg) { + try { + try { + if (msg.getRequestMethod().equals("HEAD")) { + msg.getRequestBody().close(); + msg.getResponseHeaders().add("Transfer-encoding", "chunked"); + msg.sendResponseHeaders(200, -1); + } + } catch(IOException ioe) { + ioe.printStackTrace(); + } + } finally { + msg.close(); + } + } + }); + HttpContext clContext = server.createContext("/content"); + clContext.setHandler(new HttpHandler() { + @Override + public void handle(HttpExchange msg) { + try { + try { + if (msg.getRequestMethod().equals("HEAD")) { + msg.getRequestBody().close(); + msg.getResponseHeaders().add("Content-length", "1024"); + msg.sendResponseHeaders(200, -1); + } + } catch(IOException ioe) { + ioe.printStackTrace(); + } + } finally { + msg.close(); + } + } + }); + server.start(); + String urlStr = "http://localhost:" + server.getAddress().getPort() + "/"; + System.out.println("Server is at " + urlStr); + + // Run the chunked client + for(int i=0; i < 10; i++) { + runClient(urlStr + "chunked/"); + } + // Run the content length client + for(int i=0; i < 10; i++) { + runClient(urlStr + "content/"); + } + } finally { + // Stop the server + ((ExecutorService)server.getExecutor()).shutdown(); + server.stop(0); + } + } + + static void runClient(String urlStr) throws Exception { + HttpURLConnection conn = (HttpURLConnection) new URL(urlStr).openConnection(); + conn.setRequestMethod("HEAD"); + int status = conn.getResponseCode(); + if (status != 200) { + throw new RuntimeException("HEAD request doesn't return 200, but returns " + status); + } + } +} From 070ea7c31043d3968655a7993fbb9eefa880c2af Mon Sep 17 00:00:00 2001 From: Gary Benson Date: Wed, 5 May 2010 05:57:21 -0700 Subject: [PATCH 27/54] 6949830: 6939134 broke Zero The commit for 6939134 broke Zero. Reviewed-by: twisti --- hotspot/src/cpu/zero/vm/methodHandles_zero.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hotspot/src/cpu/zero/vm/methodHandles_zero.cpp b/hotspot/src/cpu/zero/vm/methodHandles_zero.cpp index e1344ea005f..b574ddc3675 100644 --- a/hotspot/src/cpu/zero/vm/methodHandles_zero.cpp +++ b/hotspot/src/cpu/zero/vm/methodHandles_zero.cpp @@ -26,6 +26,10 @@ #include "incls/_precompiled.incl" #include "incls/_methodHandles_zero.cpp.incl" +int MethodHandles::adapter_conversion_ops_supported_mask() { + ShouldNotCallThis(); +} + void MethodHandles::generate_method_handle_stub(MacroAssembler* masm, MethodHandles::EntryKind ek) { ShouldNotCallThis(); From 51da92458c80a7584f75b12a72d3a6912756f4f2 Mon Sep 17 00:00:00 2001 From: Keith McGuigan Date: Wed, 5 May 2010 09:28:13 -0400 Subject: [PATCH 28/54] 6949118: jvm.dll shows the company name as Sun Microsystems Changed to "Oracle Corporation" Reviewed-by: coleenp, dcubed --- hotspot/make/hotspot_distro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/make/hotspot_distro b/hotspot/make/hotspot_distro index 51bad9748eb..bb0a6952a72 100644 --- a/hotspot/make/hotspot_distro +++ b/hotspot/make/hotspot_distro @@ -28,5 +28,5 @@ # Don't put quotes (fail windows build). HOTSPOT_VM_DISTRO=Java HotSpot(TM) -COMPANY_NAME=Sun Microsystems, Inc. +COMPANY_NAME=Oracle Corporation PRODUCT_NAME=Java(TM) Platform SE From a94d06f6b77fe7384c8c47b47022115c71bb41d3 Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Thu, 6 May 2010 11:26:16 +0800 Subject: [PATCH 29/54] 6948909: Jarsigner removes MANIFEST.MF info for badly packages jar's Reviewed-by: mullan, xuelei --- .../classes/sun/security/tools/JarSigner.java | 99 ++++++++------- .../sun/security/tools/jarsigner/diffend.sh | 113 ++++++++++++++++++ 2 files changed, 172 insertions(+), 40 deletions(-) create mode 100644 jdk/test/sun/security/tools/jarsigner/diffend.sh diff --git a/jdk/src/share/classes/sun/security/tools/JarSigner.java b/jdk/src/share/classes/sun/security/tools/JarSigner.java index 5c824c5712f..0f7324d7c19 100644 --- a/jdk/src/share/classes/sun/security/tools/JarSigner.java +++ b/jdk/src/share/classes/sun/security/tools/JarSigner.java @@ -1,5 +1,5 @@ /* - * Copyright 1997-2009 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 @@ -1123,6 +1123,8 @@ public class JarSigner { BASE64Encoder encoder = new JarBASE64Encoder(); Vector mfFiles = new Vector(); + boolean wasSigned = false; + for (Enumeration enum_=zipFile.entries(); enum_.hasMoreElements();) { ZipEntry ze = enum_.nextElement(); @@ -1132,6 +1134,11 @@ public class JarSigner { // out first mfFiles.addElement(ze); + if (SignatureFileVerifier.isBlockOrSF( + ze.getName().toUpperCase(Locale.ENGLISH))) { + wasSigned = true; + } + if (signatureRelated(ze.getName())) { // ignore signature-related and manifest files continue; @@ -1159,37 +1166,41 @@ public class JarSigner { if (mfModified) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); manifest.write(baos); - byte[] newBytes = baos.toByteArray(); - if (mfRawBytes != null - && oldAttr.equals(manifest.getMainAttributes())) { + if (wasSigned) { + byte[] newBytes = baos.toByteArray(); + if (mfRawBytes != null + && oldAttr.equals(manifest.getMainAttributes())) { - /* - * Note: - * - * The Attributes object is based on HashMap and can handle - * continuation columns. Therefore, even if the contents are - * not changed (in a Map view), the bytes that it write() - * may be different from the original bytes that it read() - * from. Since the signature on the main attributes is based - * on raw bytes, we must retain the exact bytes. - */ + /* + * Note: + * + * The Attributes object is based on HashMap and can handle + * continuation columns. Therefore, even if the contents are + * not changed (in a Map view), the bytes that it write() + * may be different from the original bytes that it read() + * from. Since the signature on the main attributes is based + * on raw bytes, we must retain the exact bytes. + */ - int newPos = findHeaderEnd(newBytes); - int oldPos = findHeaderEnd(mfRawBytes); + int newPos = findHeaderEnd(newBytes); + int oldPos = findHeaderEnd(mfRawBytes); - if (newPos == oldPos) { - System.arraycopy(mfRawBytes, 0, newBytes, 0, oldPos); - } else { - // cat oldHead newTail > newBytes - byte[] lastBytes = new byte[oldPos + - newBytes.length - newPos]; - System.arraycopy(mfRawBytes, 0, lastBytes, 0, oldPos); - System.arraycopy(newBytes, newPos, lastBytes, oldPos, - newBytes.length - newPos); - newBytes = lastBytes; + if (newPos == oldPos) { + System.arraycopy(mfRawBytes, 0, newBytes, 0, oldPos); + } else { + // cat oldHead newTail > newBytes + byte[] lastBytes = new byte[oldPos + + newBytes.length - newPos]; + System.arraycopy(mfRawBytes, 0, lastBytes, 0, oldPos); + System.arraycopy(newBytes, newPos, lastBytes, oldPos, + newBytes.length - newPos); + newBytes = lastBytes; + } } + mfRawBytes = newBytes; + } else { + mfRawBytes = baos.toByteArray(); } - mfRawBytes = newBytes; } // Write out the manifest @@ -1411,23 +1422,31 @@ public class JarSigner { } /** - * Find the position of an empty line inside bs + * Find the length of header inside bs. The header is a multiple (>=0) + * lines of attributes plus an empty line. The empty line is included + * in the header. */ private int findHeaderEnd(byte[] bs) { - // An empty line can be at the beginning... - if (bs.length > 1 && bs[0] == '\r' && bs[1] == '\n') { - return 0; - } - // ... or after another line - for (int i=0; i 1 +mkdir META-INF + +# Create a fake .RSA file so that jarsigner believes it's signed + +touch META-INF/x.RSA + +# A MANIFEST.MF using \n as newlines and no double newlines at the end + +cat > META-INF/MANIFEST.MF < Date: Thu, 6 May 2010 13:42:52 +0800 Subject: [PATCH 30/54] 6890876: jarsigner can add CRL info into signed jar Reviewed-by: mullan --- .../jarsigner/ContentSignerParameters.java | 11 +- .../classes/java/security/CodeSigner.java | 44 +- .../classes/java/util/jar/JarVerifier.java | 3 +- .../misc/JavaSecurityCodeSignerAccess.java | 33 ++ .../share/classes/sun/misc/SharedSecrets.java | 15 +- .../classes/sun/security/pkcs/PKCS7.java | 40 +- .../classes/sun/security/tools/JarSigner.java | 79 +++- .../security/tools/JarSignerResources.java | 5 +- .../classes/sun/security/tools/KeyTool.java | 384 ++++++++++++++++-- .../sun/security/tools/TimestampedSigner.java | 3 +- .../classes/sun/security/util/Resources.java | 9 +- .../security/util/SignatureFileVerifier.java | 12 +- .../sun/security/x509/X509CRLImpl.java | 11 +- jdk/test/sun/security/tools/jarsigner/crl.sh | 91 +++++ 14 files changed, 683 insertions(+), 57 deletions(-) create mode 100644 jdk/src/share/classes/sun/misc/JavaSecurityCodeSignerAccess.java create mode 100644 jdk/test/sun/security/tools/jarsigner/crl.sh diff --git a/jdk/src/share/classes/com/sun/jarsigner/ContentSignerParameters.java b/jdk/src/share/classes/com/sun/jarsigner/ContentSignerParameters.java index 5ef30e031fa..942d29070da 100644 --- a/jdk/src/share/classes/com/sun/jarsigner/ContentSignerParameters.java +++ b/jdk/src/share/classes/com/sun/jarsigner/ContentSignerParameters.java @@ -1,5 +1,5 @@ /* - * Copyright 2003 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 @@ -26,7 +26,9 @@ package com.sun.jarsigner; import java.net.URI; +import java.security.cert.X509CRL; import java.security.cert.X509Certificate; +import java.util.Set; import java.util.zip.ZipFile; /** @@ -80,6 +82,13 @@ public interface ContentSignerParameters { */ public X509Certificate[] getSignerCertificateChain(); + /** + * Retrieves the signer's X.509 CRLs. + * + * @return An unmodifiable set of X.509 CRLs (never null) + */ + public Set getCRLs(); + /** * Retrieves the content that was signed. * The content is the JAR file's signature file. diff --git a/jdk/src/share/classes/java/security/CodeSigner.java b/jdk/src/share/classes/java/security/CodeSigner.java index a5ef70b7dce..b7abdf06fb8 100644 --- a/jdk/src/share/classes/java/security/CodeSigner.java +++ b/jdk/src/share/classes/java/security/CodeSigner.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2004 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 @@ -26,7 +26,10 @@ package java.security; import java.io.Serializable; +import java.security.cert.CRL; import java.security.cert.CertPath; +import sun.misc.JavaSecurityCodeSignerAccess; +import sun.misc.SharedSecrets; /** * This class encapsulates information about a code signer. @@ -163,4 +166,43 @@ public final class CodeSigner implements Serializable { sb.append(")"); return sb.toString(); } + + // A private attribute attached to this CodeSigner object. Can be accessed + // through SharedSecrets.getJavaSecurityCodeSignerAccess().[g|s]etCRLs + // + // Currently called in SignatureFileVerifier.getSigners + private transient CRL[] crls; + + /** + * Sets the CRLs attached + * @param crls, null to clear + */ + void setCRLs(CRL[] crls) { + this.crls = crls; + } + + /** + * Returns the CRLs attached + * @return the crls, initially null + */ + CRL[] getCRLs() { + return crls; + } + + // Set up JavaSecurityCodeSignerAccess in SharedSecrets + static { + SharedSecrets.setJavaSecurityCodeSignerAccess( + new JavaSecurityCodeSignerAccess() { + @Override + public void setCRLs(CodeSigner signer, CRL[] crls) { + signer.setCRLs(crls); + } + + @Override + public CRL[] getCRLs(CodeSigner signer) { + return signer.getCRLs(); + } + }); + } + } diff --git a/jdk/src/share/classes/java/util/jar/JarVerifier.java b/jdk/src/share/classes/java/util/jar/JarVerifier.java index a4ceaa790fd..1c88d226e28 100644 --- a/jdk/src/share/classes/java/util/jar/JarVerifier.java +++ b/jdk/src/share/classes/java/util/jar/JarVerifier.java @@ -1,5 +1,5 @@ /* - * Copyright 1997-2009 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 @@ -27,7 +27,6 @@ package java.util.jar; import java.io.*; import java.util.*; -import java.util.zip.*; import java.security.*; import java.security.cert.CertificateException; diff --git a/jdk/src/share/classes/sun/misc/JavaSecurityCodeSignerAccess.java b/jdk/src/share/classes/sun/misc/JavaSecurityCodeSignerAccess.java new file mode 100644 index 00000000000..4543b00da5f --- /dev/null +++ b/jdk/src/share/classes/sun/misc/JavaSecurityCodeSignerAccess.java @@ -0,0 +1,33 @@ +/* + * Copyright 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package sun.misc; + +import java.security.CodeSigner; +import java.security.cert.CRL; + +public interface JavaSecurityCodeSignerAccess { + void setCRLs(CodeSigner signer, CRL[] crls); + CRL[] getCRLs(CodeSigner signer); +} diff --git a/jdk/src/share/classes/sun/misc/SharedSecrets.java b/jdk/src/share/classes/sun/misc/SharedSecrets.java index c9f50728860..76ae42f673a 100644 --- a/jdk/src/share/classes/sun/misc/SharedSecrets.java +++ b/jdk/src/share/classes/sun/misc/SharedSecrets.java @@ -27,8 +27,8 @@ package sun.misc; import java.util.jar.JarFile; import java.io.Console; -import java.io.File; import java.io.FileDescriptor; +import java.security.CodeSigner; import java.security.ProtectionDomain; /** A repository of "shared secrets", which are a mechanism for @@ -49,6 +49,7 @@ public class SharedSecrets { private static JavaNioAccess javaNioAccess; private static JavaIOFileDescriptorAccess javaIOFileDescriptorAccess; private static JavaSecurityProtectionDomainAccess javaSecurityProtectionDomainAccess; + private static JavaSecurityCodeSignerAccess javaSecurityCodeSignerAccess; public static JavaUtilJarAccess javaUtilJarAccess() { if (javaUtilJarAccess == null) { @@ -126,4 +127,16 @@ public class SharedSecrets { unsafe.ensureClassInitialized(ProtectionDomain.class); return javaSecurityProtectionDomainAccess; } + + public static void setJavaSecurityCodeSignerAccess + (JavaSecurityCodeSignerAccess jscsa) { + javaSecurityCodeSignerAccess = jscsa; + } + + public static JavaSecurityCodeSignerAccess + getJavaSecurityCodeSignerAccess() { + if (javaSecurityCodeSignerAccess == null) + unsafe.ensureClassInitialized(CodeSigner.class); + return javaSecurityCodeSignerAccess; + } } diff --git a/jdk/src/share/classes/sun/security/pkcs/PKCS7.java b/jdk/src/share/classes/sun/security/pkcs/PKCS7.java index 1a1bcf41cf2..d3342fdb2b5 100644 --- a/jdk/src/share/classes/sun/security/pkcs/PKCS7.java +++ b/jdk/src/share/classes/sun/security/pkcs/PKCS7.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-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,7 +28,6 @@ package sun.security.pkcs; import java.io.*; import java.math.BigInteger; import java.util.*; -import java.security.cert.Certificate; import java.security.cert.X509Certificate; import java.security.cert.CertificateException; import java.security.cert.X509CRL; @@ -173,20 +172,30 @@ public class PKCS7 { * @param digestAlgorithmIds the message digest algorithm identifiers. * @param contentInfo the content information. * @param certificates an array of X.509 certificates. + * @param crls an array of CRLs * @param signerInfos an array of signer information. */ public PKCS7(AlgorithmId[] digestAlgorithmIds, ContentInfo contentInfo, X509Certificate[] certificates, + X509CRL[] crls, SignerInfo[] signerInfos) { version = BigInteger.ONE; this.digestAlgorithmIds = digestAlgorithmIds; this.contentInfo = contentInfo; this.certificates = certificates; + this.crls = crls; this.signerInfos = signerInfos; } + public PKCS7(AlgorithmId[] digestAlgorithmIds, + ContentInfo contentInfo, + X509Certificate[] certificates, + SignerInfo[] signerInfos) { + this(digestAlgorithmIds, contentInfo, certificates, null, signerInfos); + } + private void parseNetscapeCertChain(DerValue val) throws ParsingException, IOException { DerInputStream dis = new DerInputStream(val.toByteArray()); @@ -312,7 +321,7 @@ public class PKCS7 { ByteArrayInputStream bais = null; try { if (certfac == null) - crls[i] = (X509CRL) new X509CRLImpl(crlVals[i]); + crls[i] = new X509CRLImpl(crlVals[i]); else { byte[] encoded = crlVals[i].toByteArray(); bais = new ByteArrayInputStream(encoded); @@ -480,7 +489,30 @@ public class PKCS7 { signedData.putOrderedSetOf((byte)0xA0, implCerts); } - // no crls (OPTIONAL field) + // CRLs (optional) + if (crls != null && crls.length != 0) { + // cast to X509CRLImpl[] since X509CRLImpl implements DerEncoder + Set implCRLs = new HashSet(crls.length); + for (X509CRL crl: crls) { + if (crl instanceof X509CRLImpl) + implCRLs.add((X509CRLImpl) crl); + else { + try { + byte[] encoded = crl.getEncoded(); + implCRLs.add(new X509CRLImpl(encoded)); + } catch (CRLException ce) { + IOException ie = new IOException(ce.getMessage()); + ie.initCause(ce); + throw ie; + } + } + } + + // Add the CRL set (tagged with [1] IMPLICIT) + // to the signed data + signedData.putOrderedSetOf((byte)0xA1, + implCRLs.toArray(new X509CRLImpl[implCRLs.size()])); + } // signerInfos signedData.putOrderedSetOf(DerValue.tag_Set, signerInfos); diff --git a/jdk/src/share/classes/sun/security/tools/JarSigner.java b/jdk/src/share/classes/sun/security/tools/JarSigner.java index 0f7324d7c19..f45a2c93157 100644 --- a/jdk/src/share/classes/sun/security/tools/JarSigner.java +++ b/jdk/src/share/classes/sun/security/tools/JarSigner.java @@ -26,6 +26,7 @@ package sun.security.tools; import java.io.*; +import java.security.cert.X509CRL; import java.util.*; import java.util.zip.*; import java.util.jar.*; @@ -35,6 +36,7 @@ import java.net.URISyntaxException; import java.text.Collator; import java.text.MessageFormat; import java.security.cert.Certificate; +import java.security.cert.CRL; import java.security.cert.X509Certificate; import java.security.cert.CertificateException; import java.security.*; @@ -56,6 +58,7 @@ import java.util.Map.Entry; import sun.security.x509.*; import sun.security.util.*; import sun.misc.BASE64Encoder; +import sun.misc.SharedSecrets; /** @@ -114,14 +117,16 @@ public class JarSigner { static final int SIGNED_BY_ALIAS = 0x08; // signer is in alias list X509Certificate[] certChain; // signer's cert chain (when composing) + Set crls; // signer provided CRLs PrivateKey privateKey; // private key KeyStore store; // the keystore specified by -keystore // or the default keystore, never null String keystore; // key store file + List crlfiles = new ArrayList(); // CRL files to add boolean nullStream = false; // null keystore input stream (NONE) boolean token = false; // token-based keystore - String jarfile; // jar file to sign or verify + String jarfile; // jar files to sign or verify String alias; // alias to sign jar with List ckaliases = new ArrayList(); // aliases in -verify char[] storepass; // keystore password @@ -146,6 +151,7 @@ public class JarSigner { boolean signManifest = true; // "sign" the whole manifest boolean externalSF = true; // leave the .SF out of the PKCS7 block boolean strict = false; // treat warnings as error + boolean autoCRL = false; // Automatcially add CRL defined in cert // read zip entry raw bytes private ByteArrayOutputStream baos = new ByteArrayOutputStream(2048); @@ -226,6 +232,29 @@ public class JarSigner { } else { loadKeyStore(keystore, true); getAliasInfo(alias); + crls = new HashSet(); + if (crlfiles.size() > 0 || autoCRL) { + CertificateFactory fac = + CertificateFactory.getInstance("X509"); + List list = new ArrayList(); + for (String file: crlfiles) { + Collection tmp = KeyTool.loadCRLs(file); + for (CRL crl: tmp) { + if (crl instanceof X509CRL) { + crls.add((X509CRL)crl); + } + } + } + if (autoCRL) { + List crlsFromCert = + KeyTool.readCRLsFromCert(certChain[0]); + for (CRL crl: crlsFromCert) { + if (crl instanceof X509CRL) { + crls.add((X509CRL)crl); + } + } + } + } // load the alternative signing mechanism if (altSignerClass != null) { @@ -367,6 +396,13 @@ public class JarSigner { } else if (collator.compare(flags, "-digestalg") ==0) { if (++n == args.length) usageNoArg(); digestalg = args[n]; + } else if (collator.compare(flags, "-crl") ==0) { + if ("auto".equals(modifier)) { + autoCRL = true; + } else { + if (++n == args.length) usageNoArg(); + crlfiles.add(args[n]); + } } else if (collator.compare(flags, "-certs") ==0) { showcerts = true; } else if (collator.compare(flags, "-strict") ==0) { @@ -515,6 +551,9 @@ public class JarSigner { System.out.println(rb.getString ("[-sigalg ] name of signature algorithm")); System.out.println(); + System.out.println(rb.getString + ("[-crl[:auto| ] include CRL in signed jar")); + System.out.println(); System.out.println(rb.getString ("[-verify] verify a signed JAR file")); System.out.println(); @@ -654,6 +693,20 @@ public class JarSigner { if (showcerts) { sb.append(si); sb.append('\n'); + CRL[] crls = SharedSecrets + .getJavaSecurityCodeSignerAccess() + .getCRLs(signer); + if (crls != null) { + for (CRL crl: crls) { + if (crl instanceof X509CRLImpl) { + sb.append(tab).append("["); + sb.append(String.format( + rb.getString("with a CRL including %d entries"), + ((X509CRLImpl)crl).getRevokedCertificates().size())) + .append("]\n"); + } + } + } } } } else if (showcerts && !verbose.equals("all")) { @@ -1233,7 +1286,7 @@ public class JarSigner { try { block = - sf.generateBlock(privateKey, sigalg, certChain, + sf.generateBlock(privateKey, sigalg, certChain, crls, externalSF, tsaUrl, tsaCert, signingMechanism, args, zipFile); } catch (SocketTimeoutException e) { @@ -2197,6 +2250,7 @@ class SignatureFile { public Block generateBlock(PrivateKey privateKey, String sigalg, X509Certificate[] certChain, + Set crls, boolean externalSF, String tsaUrl, X509Certificate tsaCert, ContentSigner signingMechanism, @@ -2204,7 +2258,7 @@ class SignatureFile { throws NoSuchAlgorithmException, InvalidKeyException, IOException, SignatureException, CertificateException { - return new Block(this, privateKey, sigalg, certChain, externalSF, + return new Block(this, privateKey, sigalg, certChain, crls, externalSF, tsaUrl, tsaCert, signingMechanism, args, zipFile); } @@ -2218,7 +2272,8 @@ class SignatureFile { * Construct a new signature block. */ Block(SignatureFile sfg, PrivateKey privateKey, String sigalg, - X509Certificate[] certChain, boolean externalSF, String tsaUrl, + X509Certificate[] certChain, Set crls, + boolean externalSF, String tsaUrl, X509Certificate tsaCert, ContentSigner signingMechanism, String[] args, ZipFile zipFile) throws NoSuchAlgorithmException, InvalidKeyException, IOException, @@ -2305,7 +2360,7 @@ class SignatureFile { // Assemble parameters for the signing mechanism ContentSignerParameters params = new JarSignerParameters(args, tsaUri, tsaCert, signature, - signatureAlgorithm, certChain, content, zipFile); + signatureAlgorithm, certChain, crls, content, zipFile); // Generate the signature block block = signingMechanism.generateSignedData( @@ -2346,6 +2401,7 @@ class JarSignerParameters implements ContentSignerParameters { private byte[] signature; private String signatureAlgorithm; private X509Certificate[] signerCertificateChain; + private Set crls; private byte[] content; private ZipFile source; @@ -2354,7 +2410,8 @@ class JarSignerParameters implements ContentSignerParameters { */ JarSignerParameters(String[] args, URI tsa, X509Certificate tsaCertificate, byte[] signature, String signatureAlgorithm, - X509Certificate[] signerCertificateChain, byte[] content, + X509Certificate[] signerCertificateChain, Set crls, + byte[] content, ZipFile source) { if (signature == null || signatureAlgorithm == null || @@ -2367,6 +2424,7 @@ class JarSignerParameters implements ContentSignerParameters { this.signature = signature; this.signatureAlgorithm = signatureAlgorithm; this.signerCertificateChain = signerCertificateChain; + this.crls = crls; this.content = content; this.source = source; } @@ -2442,4 +2500,13 @@ class JarSignerParameters implements ContentSignerParameters { public ZipFile getSource() { return source; } + + @Override + public Set getCRLs() { + if (crls == null) { + return Collections.emptySet(); + } else { + return Collections.unmodifiableSet(crls); + } + } } diff --git a/jdk/src/share/classes/sun/security/tools/JarSignerResources.java b/jdk/src/share/classes/sun/security/tools/JarSignerResources.java index 7e259e8e8fe..16cc6863b43 100644 --- a/jdk/src/share/classes/sun/security/tools/JarSignerResources.java +++ b/jdk/src/share/classes/sun/security/tools/JarSignerResources.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-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 @@ -74,6 +74,8 @@ public class JarSignerResources extends java.util.ListResourceBundle { "[-digestalg ] name of digest algorithm"}, {"[-sigalg ] name of signature algorithm", "[-sigalg ] name of signature algorithm"}, + {"[-crl[:auto| ] include CRL in signed jar", + "[-crl[:auto| ] include CRL in signed jar"}, {"[-verify] verify a signed JAR file", "[-verify] verify a signed JAR file"}, {"[-verbose[:suboptions]] verbose output when signing/verifying.", @@ -191,6 +193,7 @@ public class JarSignerResources extends java.util.ListResourceBundle { {"using an alternative signing mechanism", "using an alternative signing mechanism"}, {"entry was signed on", "entry was signed on {0}"}, + {"with a CRL including %d entries", "with a CRL including %d entries"}, {"Warning: ", "Warning: "}, {"This jar contains unsigned entries which have not been integrity-checked. ", "This jar contains unsigned entries which have not been integrity-checked. "}, diff --git a/jdk/src/share/classes/sun/security/tools/KeyTool.java b/jdk/src/share/classes/sun/security/tools/KeyTool.java index 2539d43e14b..b799bfaa7fc 100644 --- a/jdk/src/share/classes/sun/security/tools/KeyTool.java +++ b/jdk/src/share/classes/sun/security/tools/KeyTool.java @@ -25,6 +25,7 @@ package sun.security.tools; +import sun.misc.SharedSecrets; import java.io.*; import java.security.CodeSigner; import java.security.KeyStore; @@ -42,6 +43,7 @@ import java.security.Principal; import java.security.Provider; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; +import java.security.cert.CRL; import java.security.cert.X509Certificate; import java.security.cert.CertificateException; import java.text.Collator; @@ -50,14 +52,20 @@ import java.util.*; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.lang.reflect.Constructor; +import java.math.BigInteger; +import java.net.URI; import java.net.URL; import java.net.URLClassLoader; +import java.security.cert.CertStore; +import java.security.cert.X509CRL; +import java.security.cert.X509CRLEntry; +import java.security.cert.X509CRLSelector; +import javax.security.auth.x500.X500Principal; import sun.misc.BASE64Encoder; import sun.security.util.ObjectIdentifier; import sun.security.pkcs.PKCS10; import sun.security.provider.X509Factory; -import sun.security.util.DerOutputStream; import sun.security.util.Password; import sun.security.util.PathList; import javax.crypto.KeyGenerator; @@ -72,6 +80,7 @@ import javax.net.ssl.X509TrustManager; import sun.misc.BASE64Decoder; import sun.security.pkcs.PKCS10Attribute; import sun.security.pkcs.PKCS9Attribute; +import sun.security.provider.certpath.ldap.LDAPCertStoreHelper; import sun.security.util.DerValue; import sun.security.x509.*; @@ -147,6 +156,7 @@ public final class KeyTool { private Set passwords = new HashSet (); private String startDate = null; + private List ids = new ArrayList (); // used in GENCRL private List v3ext = new ArrayList (); enum Command { @@ -180,9 +190,6 @@ public final class KeyTool { STARTDATE, EXT, VALIDITY, KEYPASS, KEYSTORE, STOREPASS, STORETYPE, PROVIDERNAME, PROVIDERCLASS, PROVIDERARG, PROVIDERPATH, V, PROTECTED), - IDENTITYDB("Imports entries from a JDK 1.1.x-style identity database", - FILEIN, STORETYPE, KEYSTORE, STOREPASS, PROVIDERNAME, - PROVIDERCLASS, PROVIDERARG, PROVIDERPATH, V), IMPORTCERT("Imports a certificate or a certificate chain", NOPROMPT, TRUSTCACERTS, PROTECTED, ALIAS, FILEIN, KEYPASS, KEYSTORE, STOREPASS, STORETYPE, @@ -195,10 +202,6 @@ public final class KeyTool { SRCALIAS, DESTALIAS, SRCKEYPASS, DESTKEYPASS, NOPROMPT, PROVIDERCLASS, PROVIDERARG, PROVIDERPATH, V), - KEYCLONE("Clones a key entry", - ALIAS, DESTALIAS, KEYPASS, NEW, STORETYPE, - KEYSTORE, STOREPASS, PROVIDERNAME, PROVIDERCLASS, - PROVIDERARG, PROVIDERPATH, V), KEYPASSWD("Changes the key password of an entry", ALIAS, KEYPASS, NEW, KEYSTORE, STOREPASS, STORETYPE, PROVIDERNAME, PROVIDERCLASS, PROVIDERARG, @@ -211,12 +214,29 @@ public final class KeyTool { RFC, FILEIN, SSLSERVER, JARFILE, V), PRINTCERTREQ("Prints the content of a certificate request", FILEIN, V), + PRINTCRL("Prints the content of a CRL file", + FILEIN, V), + STOREPASSWD("Changes the store password of a keystore", + NEW, KEYSTORE, STOREPASS, STORETYPE, PROVIDERNAME, + PROVIDERCLASS, PROVIDERARG, PROVIDERPATH, V), + + // Undocumented start here, KEYCLONE is used a marker in -help; + + KEYCLONE("Clones a key entry", + ALIAS, DESTALIAS, KEYPASS, NEW, STORETYPE, + KEYSTORE, STOREPASS, PROVIDERNAME, PROVIDERCLASS, + PROVIDERARG, PROVIDERPATH, V), SELFCERT("Generates a self-signed certificate", ALIAS, SIGALG, DNAME, STARTDATE, VALIDITY, KEYPASS, STORETYPE, KEYSTORE, STOREPASS, PROVIDERNAME, PROVIDERCLASS, PROVIDERARG, PROVIDERPATH, V), - STOREPASSWD("Changes the store password of a keystore", - NEW, KEYSTORE, STOREPASS, STORETYPE, PROVIDERNAME, + GENCRL("Generates CRL", + RFC, FILEOUT, ID, + ALIAS, SIGALG, EXT, KEYPASS, KEYSTORE, + STOREPASS, STORETYPE, PROVIDERNAME, PROVIDERCLASS, + PROVIDERARG, PROVIDERPATH, V, PROTECTED), + IDENTITYDB("Imports entries from a JDK 1.1.x-style identity database", + FILEIN, STORETYPE, KEYSTORE, STOREPASS, PROVIDERNAME, PROVIDERCLASS, PROVIDERARG, PROVIDERPATH, V); final String description; @@ -244,6 +264,7 @@ public final class KeyTool { EXT("ext", "", "X.509 extension"), FILEOUT("file", "", "output file name"), FILEIN("file", "", "input file name"), + ID("id", "", "Serial ID of cert to revoke"), INFILE("infile", "", "input file name"), KEYALG("keyalg", "", "key algorithm name"), KEYPASS("keypass", "", "key password"), @@ -458,6 +479,8 @@ public final class KeyTool { validity = Long.parseLong(args[++i]); } else if (collator.compare(flags, "-ext") == 0) { v3ext.add(args[++i]); + } else if (collator.compare(flags, "-id") == 0) { + ids.add(args[++i]); } else if (collator.compare(flags, "-file") == 0) { filename = args[++i]; } else if (collator.compare(flags, "-infile") == 0) { @@ -720,7 +743,8 @@ public final class KeyTool { command != GENSECKEY && command != IDENTITYDB && command != IMPORTCERT && - command != IMPORTKEYSTORE) { + command != IMPORTKEYSTORE && + command != PRINTCRL) { throw new Exception(rb.getString ("Keystore file does not exist: ") + ksfname); } @@ -855,10 +879,12 @@ public final class KeyTool { && !KeyStoreUtil.isWindowsKeyStore(storetype) && isKeyStoreRelated(command)) { // here we have EXPORTCERT and LIST (info valid until STOREPASSWD) - System.err.print(rb.getString("Enter keystore password: ")); - System.err.flush(); - storePass = Password.readPassword(System.in); - passwords.add(storePass); + if (command != PRINTCRL) { + System.err.print(rb.getString("Enter keystore password: ")); + System.err.flush(); + storePass = Password.readPassword(System.in); + passwords.add(storePass); + } } // Now load a nullStream-based keystore, @@ -895,7 +921,7 @@ public final class KeyTool { // Create a certificate factory if (command == PRINTCERT || command == IMPORTCERT - || command == IDENTITYDB) { + || command == IDENTITYDB || command == PRINTCRL) { cf = CertificateFactory.getInstance("X509"); } @@ -1086,6 +1112,22 @@ public final class KeyTool { ps.close(); } } + } else if (command == GENCRL) { + if (alias == null) { + alias = keyAlias; + } + PrintStream ps = null; + if (filename != null) { + ps = new PrintStream(new FileOutputStream(filename)); + out = ps; + } + try { + doGenCRL(out); + } finally { + if (ps != null) { + ps.close(); + } + } } else if (command == PRINTCERTREQ) { InputStream inStream = System.in; if (filename != null) { @@ -1098,6 +1140,8 @@ public final class KeyTool { inStream.close(); } } + } else if (command == PRINTCRL) { + doPrintCRL(filename, out); } // If we need to save the keystore, do so. @@ -1152,7 +1196,8 @@ public final class KeyTool { CertificateValidity interval = new CertificateValidity(firstDate, lastDate); - PrivateKey privateKey = (PrivateKey)recoverKey(alias, storePass, keyPass).fst; + PrivateKey privateKey = + (PrivateKey)recoverKey(alias, storePass, keyPass).fst; if (sigAlgName == null) { sigAlgName = getCompatibleSigAlgName(privateKey.getAlgorithm()); } @@ -1221,6 +1266,56 @@ public final class KeyTool { } } + private void doGenCRL(PrintStream out) + throws Exception { + if (ids == null) { + throw new Exception("Must provide -id when -gencrl"); + } + Certificate signerCert = keyStore.getCertificate(alias); + byte[] encoded = signerCert.getEncoded(); + X509CertImpl signerCertImpl = new X509CertImpl(encoded); + X509CertInfo signerCertInfo = (X509CertInfo)signerCertImpl.get( + X509CertImpl.NAME + "." + X509CertImpl.INFO); + X500Name owner = (X500Name)signerCertInfo.get(X509CertInfo.SUBJECT + "." + + CertificateSubjectName.DN_NAME); + + Date firstDate = getStartDate(startDate); + Date lastDate = (Date) firstDate.clone(); + lastDate.setTime(lastDate.getTime() + (long)validity*1000*24*60*60); + CertificateValidity interval = new CertificateValidity(firstDate, + lastDate); + + + PrivateKey privateKey = + (PrivateKey)recoverKey(alias, storePass, keyPass).fst; + if (sigAlgName == null) { + sigAlgName = getCompatibleSigAlgName(privateKey.getAlgorithm()); + } + + X509CRLEntry[] badCerts = new X509CRLEntry[ids.size()]; + for (int i=0; i= 0) { + CRLExtensions ext = new CRLExtensions(); + ext.set("Reason", new CRLReasonCodeExtension(Integer.parseInt(id.substring(d+1)))); + badCerts[i] = new X509CRLEntryImpl(new BigInteger(id.substring(0, d)), + firstDate, ext); + } else { + badCerts[i] = new X509CRLEntryImpl(new BigInteger(ids.get(i)), firstDate); + } + } + X509CRLImpl crl = new X509CRLImpl(owner, firstDate, lastDate, badCerts); + crl.sign(privateKey, sigAlgName); + if (rfc) { + out.println("-----BEGIN X509 CRL-----"); + new BASE64Encoder().encodeBuffer(crl.getEncodedInternal(), out); + out.println("-----END X509 CRL-----"); + } else { + out.write(crl.getEncodedInternal()); + } + } + /** * Creates a PKCS#10 cert signing request, corresponding to the * keys (and name) associated with a given alias. @@ -1925,6 +2020,177 @@ public final class KeyTool { } } + private static Iterable e2i(final Enumeration e) { + return new Iterable() { + @Override + public Iterator iterator() { + return new Iterator() { + @Override + public boolean hasNext() { + return e.hasMoreElements(); + } + @Override + public T next() { + return e.nextElement(); + } + public void remove() { + throw new UnsupportedOperationException("Not supported yet."); + } + }; + } + }; + } + + /** + * Loads CRLs from a source. This method is also called in JarSigner. + * @param src the source, which means System.in if null, or a URI, + * or a bare file path name + */ + public static Collection loadCRLs(String src) throws Exception { + InputStream in = null; + URI uri = null; + if (src == null) { + in = System.in; + } else { + try { + uri = new URI(src); + if (uri.getScheme().equals("ldap")) { + // No input stream for LDAP + } else { + in = uri.toURL().openStream(); + } + } catch (Exception e) { + try { + in = new FileInputStream(src); + } catch (Exception e2) { + if (uri == null || uri.getScheme() == null) { + throw e2; // More likely a bare file path + } else { + throw e; // More likely a protocol or network problem + } + } + } + } + if (in != null) { + try { + // Read the full stream before feeding to X509Factory, + // otherwise, keytool -gencrl | keytool -printcrl + // might not work properly, since -gencrl is slow + // and there's no data in the pipe at the beginning. + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + byte[] b = new byte[4096]; + while (true) { + int len = in.read(b); + if (len < 0) break; + bout.write(b, 0, len); + } + return CertificateFactory.getInstance("X509").generateCRLs( + new ByteArrayInputStream(bout.toByteArray())); + } finally { + if (in != System.in) { + in.close(); + } + } + } else { // must be LDAP, and uri is not null + String path = uri.getPath(); + if (path.charAt(0) == '/') path = path.substring(1); + LDAPCertStoreHelper h = new LDAPCertStoreHelper(); + CertStore s = h.getCertStore(uri); + X509CRLSelector sel = + h.wrap(new X509CRLSelector(), null, path); + return s.getCRLs(sel); + } + } + + /** + * Returns CRLs described in a X509Certificate's CRLDistributionPoints + * Extension. Only those containing a general name of type URI are read. + */ + public static List readCRLsFromCert(X509Certificate cert) + throws Exception { + List crls = new ArrayList(); + CRLDistributionPointsExtension ext = + X509CertImpl.toImpl(cert).getCRLDistributionPointsExtension(); + if (ext == null) return crls; + for (DistributionPoint o: (List) + ext.get(CRLDistributionPointsExtension.POINTS)) { + GeneralNames names = o.getFullName(); + if (names != null) { + for (GeneralName name: names.names()) { + if (name.getType() == GeneralNameInterface.NAME_URI) { + URIName uriName = (URIName)name.getName(); + for (CRL crl: KeyTool.loadCRLs(uriName.getName())) { + if (crl instanceof X509CRL) { + crls.add((X509CRL)crl); + } + } + break; // Different name should point to same CRL + } + } + } + } + return crls; + } + + private static String verifyCRL(KeyStore ks, CRL crl) + throws Exception { + X509CRLImpl xcrl = (X509CRLImpl)crl; + X500Principal issuer = xcrl.getIssuerX500Principal(); + for (String s: e2i(ks.aliases())) { + Certificate cert = ks.getCertificate(s); + if (cert instanceof X509Certificate) { + X509Certificate xcert = (X509Certificate)cert; + if (xcert.getSubjectX500Principal().equals(issuer)) { + try { + ((X509CRLImpl)crl).verify(cert.getPublicKey()); + return s; + } catch (Exception e) { + } + } + } + } + return null; + } + + private void doPrintCRL(String src, PrintStream out) + throws Exception { + for (CRL crl: loadCRLs(src)) { + printCRL(crl, out); + String issuer = null; + if (caks != null) { + issuer = verifyCRL(caks, crl); + if (issuer != null) { + System.out.println("Verified by " + issuer + " in cacerts"); + } + } + if (issuer == null && keyStore != null) { + issuer = verifyCRL(keyStore, crl); + if (issuer != null) { + System.out.println("Verified by " + issuer + " in keystore"); + } + } + if (issuer == null) { + out.println(rb.getString + ("*******************************************")); + out.println("WARNING: not verified. Make sure -keystore and -alias are correct."); + out.println(rb.getString + ("*******************************************\n\n")); + } + } + } + + private void printCRL(CRL crl, PrintStream out) + throws Exception { + if (rfc) { + X509CRL xcrl = (X509CRL)crl; + out.println("-----BEGIN X509 CRL-----"); + new BASE64Encoder().encodeBuffer(xcrl.getEncoded(), out); + out.println("-----END X509 CRL-----"); + } else { + out.println(crl.toString()); + } + } + private void doPrintCertReq(InputStream in, PrintStream out) throws Exception { @@ -2063,6 +2329,16 @@ public final class KeyTool { out.println(); } } + CRL[] crls = SharedSecrets + .getJavaSecurityCodeSignerAccess() + .getCRLs(signer); + if (crls != null) { + out.println(rb.getString("CRLs:")); + out.println(); + for (CRL crl: crls) { + printCRL(crl, out); + } + } } } } @@ -3330,15 +3606,22 @@ public final class KeyTool { /** * Match a command (may be abbreviated) with a command set. * @param s the command provided - * @param list the legal command set + * @param list the legal command set. If there is a null, commands after it + * are regarded experimental, which means they are supported but their + * existence should not be revealed to user. * @return the position of a single match, or -1 if none matched * @throws Exception if s is ambiguous */ private static int oneOf(String s, String... list) throws Exception { int[] match = new int[list.length]; int nmatch = 0; + int experiment = Integer.MAX_VALUE; for (int i = 0; i experiment) { + return match[0]; + } + StringBuffer sb = new StringBuffer(); + MessageFormat form = new MessageFormat(rb.getString + ("command {0} is ambiguous:")); + Object[] source = {s}; + sb.append(form.format(source)); + sb.append("\n "); + for (int i=0; i(); } // Append the new code signer - signers.add(new CodeSigner(certChain, getTimestamp(info))); + CodeSigner signer = new CodeSigner(certChain, getTimestamp(info)); + if (block.getCRLs() != null) { + SharedSecrets.getJavaSecurityCodeSignerAccess().setCRLs( + signer, block.getCRLs()); + } + signers.add(signer); if (debug != null) { debug.println("Signature Block Certificate: " + diff --git a/jdk/src/share/classes/sun/security/x509/X509CRLImpl.java b/jdk/src/share/classes/sun/security/x509/X509CRLImpl.java index b1157799663..f5d159891d9 100644 --- a/jdk/src/share/classes/sun/security/x509/X509CRLImpl.java +++ b/jdk/src/share/classes/sun/security/x509/X509CRLImpl.java @@ -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 @@ -89,7 +89,7 @@ import sun.misc.HexDumpEncoder; * @author Hemma Prafullchandra * @see X509CRL */ -public class X509CRLImpl extends X509CRL { +public class X509CRLImpl extends X509CRL implements DerEncoder { // CRL data, and its envelope private byte[] signedCRL = null; // DER encoded crl @@ -1189,6 +1189,13 @@ public class X509CRLImpl extends X509CRL { } } + @Override + public void derEncode(OutputStream out) throws IOException { + if (signedCRL == null) + throw new IOException("Null CRL to encode"); + out.write(signedCRL.clone()); + } + /** * Immutable X.509 Certificate Issuer DN and serial number pair */ diff --git a/jdk/test/sun/security/tools/jarsigner/crl.sh b/jdk/test/sun/security/tools/jarsigner/crl.sh new file mode 100644 index 00000000000..73d0c4eae57 --- /dev/null +++ b/jdk/test/sun/security/tools/jarsigner/crl.sh @@ -0,0 +1,91 @@ +# +# Copyright 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 +# 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +# @test +# @bug 6890876 +# @summary jarsigner can add CRL info into signed jar +# + +if [ "${TESTJAVA}" = "" ] ; then + JAVAC_CMD=`which javac` + TESTJAVA=`dirname $JAVAC_CMD`/.. +fi + +# set platform-dependent variables +# PF: platform name, say, solaris-sparc + +PF="" + +OS=`uname -s` +case "$OS" in + Windows* ) + FS="\\" + ;; + * ) + FS="/" + ;; +esac + +KS=crl.jks +JFILE=crl.jar + +KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit -keystore $KS" +JAR=$TESTJAVA${FS}bin${FS}jar +JARSIGNER=$TESTJAVA${FS}bin${FS}jarsigner + +rm $KS $JFILE + +# Generates some crl files, each containing two entries + +$KT -alias a -dname CN=a -keyalg rsa -genkey -validity 300 +$KT -alias a -gencrl -id 1:1 -id 2:2 -file crl1 +$KT -alias a -gencrl -id 3:3 -id 4:4 -file crl2 +$KT -alias b -dname CN=b -keyalg rsa -genkey -validity 300 +$KT -alias b -gencrl -id 5:1 -id 6:2 -file crl3 + +$KT -alias c -dname CN=c -keyalg rsa -genkey -validity 300 \ + -ext crl=uri:file://`pwd`/crl1 + +echo A > A + +# Test -crl:auto, cRLDistributionPoints is a local file + +$JAR cvf $JFILE A +$JARSIGNER -keystore $KS -storepass changeit $JFILE c \ + -crl:auto || exit 1 +$JARSIGNER -keystore $KS -verify -debug -strict $JFILE || exit 6 +$KT -printcert -jarfile $JFILE | grep CRLs || exit 7 + +# Test -crl + +$JAR cvf $JFILE A +$JARSIGNER -keystore $KS -storepass changeit $JFILE a \ + -crl crl1 -crl crl2 || exit 1 +$JARSIGNER -keystore $KS -storepass changeit $JFILE b \ + -crl crl3 -crl crl2 || exit 1 +$JARSIGNER -keystore $KS -verify -debug -strict $JFILE || exit 3 +$KT -printcert -jarfile $JFILE | grep CRLs || exit 4 +CRLCOUNT=`$KT -printcert -jarfile $JFILE | grep SerialNumber | wc -l` +if [ $CRLCOUNT != 8 ]; then exit 5; fi + +exit 0 From 5a66416a07a4ba361c31018571a51e9b0dbd7a07 Mon Sep 17 00:00:00 2001 From: Peter Zhelezniakov Date: Thu, 6 May 2010 12:57:30 +0400 Subject: [PATCH 31/54] 6919629: Nimbus L&F Nimbus.Overrides option leaks significant amounts of memory Reviewed-by: rupashka --- .../javax/swing/plaf/nimbus/NimbusStyle.java | 13 ++- .../javax/swing/plaf/nimbus/Test6919629.java | 82 +++++++++++++++++++ 2 files changed, 91 insertions(+), 4 deletions(-) create mode 100644 jdk/test/javax/swing/plaf/nimbus/Test6919629.java diff --git a/jdk/src/share/classes/javax/swing/plaf/nimbus/NimbusStyle.java b/jdk/src/share/classes/javax/swing/plaf/nimbus/NimbusStyle.java index a8f8b3fc5b6..c8672e3c8c9 100644 --- a/jdk/src/share/classes/javax/swing/plaf/nimbus/NimbusStyle.java +++ b/jdk/src/share/classes/javax/swing/plaf/nimbus/NimbusStyle.java @@ -38,6 +38,7 @@ import javax.swing.plaf.synth.SynthStyle; import java.awt.Color; import java.awt.Font; import java.awt.Insets; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -193,7 +194,7 @@ public final class NimbusStyle extends SynthStyle { * UIDefaults which overrides (or supplements) those defaults found in * UIManager. */ - private JComponent component; + private WeakReference component; /** * Create a new NimbusStyle. Only the prefix must be supplied. At the @@ -209,7 +210,9 @@ public final class NimbusStyle extends SynthStyle { * should be null otherwise. */ NimbusStyle(String prefix, JComponent c) { - this.component = c; + if (c != null) { + this.component = new WeakReference(c); + } this.prefix = prefix; this.painter = new SynthPainterImpl(this); } @@ -251,9 +254,11 @@ public final class NimbusStyle extends SynthStyle { // value is an instance of UIDefaults, then these defaults are used // in place of, or in addition to, the defaults in UIManager. if (component != null) { - Object o = component.getClientProperty("Nimbus.Overrides"); + // We know component.get() is non-null here, as if the component + // were GC'ed, we wouldn't be processing its style. + Object o = component.get().getClientProperty("Nimbus.Overrides"); if (o instanceof UIDefaults) { - Object i = component.getClientProperty( + Object i = component.get().getClientProperty( "Nimbus.Overrides.InheritDefaults"); boolean inherit = i instanceof Boolean ? (Boolean)i : true; UIDefaults d = (UIDefaults)o; diff --git a/jdk/test/javax/swing/plaf/nimbus/Test6919629.java b/jdk/test/javax/swing/plaf/nimbus/Test6919629.java new file mode 100644 index 00000000000..38d66a0cf42 --- /dev/null +++ b/jdk/test/javax/swing/plaf/nimbus/Test6919629.java @@ -0,0 +1,82 @@ +/* + * Copyright 2009 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 + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @bug 6919629 + @summary Tests that components with Nimbus.Overrides are GC'ed properly + @author Peter Zhelezniakov + @run main Test6919629 +*/ + +import java.awt.Color; +import java.lang.ref.WeakReference; +import javax.swing.*; +import javax.swing.plaf.nimbus.NimbusLookAndFeel; + +public class Test6919629 +{ + JFrame f; + WeakReference ref; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel(new NimbusLookAndFeel()); + Test6919629 t = new Test6919629(); + t.test(); + System.gc(); + t.check(); + } + + void test() throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + UIDefaults d = new UIDefaults(); + d.put("Label.textForeground", Color.MAGENTA); + + JLabel l = new JLabel(); + ref = new WeakReference(l); + l.putClientProperty("Nimbus.Overrides", d); + + f = new JFrame(); + f.getContentPane().add(l); + f.pack(); + f.setVisible(true); + } + }); + Thread.sleep(2000); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + f.getContentPane().removeAll(); + f.setVisible(false); + f.dispose(); + } + }); + Thread.sleep(2000); + } + + void check() { + if (ref.get() != null) { + throw new RuntimeException("Failed: an unused component wasn't collected"); + } + } +} From 4d6c5d6fefa49233162d01d3cbe9cc99814d025f Mon Sep 17 00:00:00 2001 From: Gary Benson Date: Thu, 6 May 2010 02:09:18 -0700 Subject: [PATCH 32/54] 6950178: Zero stack improvements Moves the logic for determining the size of the Zero stack into the ZeroStack class. Reviewed-by: twisti --- hotspot/src/cpu/zero/vm/stack_zero.cpp | 5 +++++ hotspot/src/cpu/zero/vm/stack_zero.hpp | 6 ++++++ hotspot/src/cpu/zero/vm/stack_zero.inline.hpp | 17 +++++++++++------ hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp | 5 +---- hotspot/src/share/vm/includeDB_zero | 1 + 5 files changed, 24 insertions(+), 10 deletions(-) diff --git a/hotspot/src/cpu/zero/vm/stack_zero.cpp b/hotspot/src/cpu/zero/vm/stack_zero.cpp index 328e52e6b00..532f54e7798 100644 --- a/hotspot/src/cpu/zero/vm/stack_zero.cpp +++ b/hotspot/src/cpu/zero/vm/stack_zero.cpp @@ -26,6 +26,11 @@ #include "incls/_precompiled.incl" #include "incls/_stack_zero.cpp.incl" +int ZeroStack::suggest_size(Thread *thread) const { + assert(needs_setup(), "already set up"); + return align_size_down(abi_stack_available(thread) / 2, wordSize); +} + void ZeroStack::handle_overflow(TRAPS) { JavaThread *thread = (JavaThread *) THREAD; diff --git a/hotspot/src/cpu/zero/vm/stack_zero.hpp b/hotspot/src/cpu/zero/vm/stack_zero.hpp index ab3beca4760..691cbc790e5 100644 --- a/hotspot/src/cpu/zero/vm/stack_zero.hpp +++ b/hotspot/src/cpu/zero/vm/stack_zero.hpp @@ -42,6 +42,8 @@ class ZeroStack { return _base == NULL; } + int suggest_size(Thread *thread) const; + void setup(void *mem, size_t size) { assert(needs_setup(), "already set up"); assert(!(size & WordAlignmentMask), "unaligned"); @@ -67,6 +69,9 @@ class ZeroStack { _sp = new_sp; } + int total_words() const { + return _top - _base; + } int available_words() const { return _sp - _base; } @@ -89,6 +94,7 @@ class ZeroStack { int shadow_pages_size() const { return _shadow_pages_size; } + int abi_stack_available(Thread *thread) const; public: void overflow_check(int required_words, TRAPS); diff --git a/hotspot/src/cpu/zero/vm/stack_zero.inline.hpp b/hotspot/src/cpu/zero/vm/stack_zero.inline.hpp index ffb247c6039..89513dbb75e 100644 --- a/hotspot/src/cpu/zero/vm/stack_zero.inline.hpp +++ b/hotspot/src/cpu/zero/vm/stack_zero.inline.hpp @@ -25,19 +25,24 @@ // This function should match SharkStack::CreateStackOverflowCheck inline void ZeroStack::overflow_check(int required_words, TRAPS) { - JavaThread *thread = (JavaThread *) THREAD; - // Check the Zero stack - if (required_words > available_words()) { + if (available_words() < required_words) { handle_overflow(THREAD); return; } // Check the ABI stack - address stack_top = thread->stack_base() - thread->stack_size(); - int free_stack = ((address) &stack_top) - stack_top; - if (free_stack < shadow_pages_size()) { + if (abi_stack_available(THREAD) < 0) { handle_overflow(THREAD); return; } } + +// This method returns the amount of ABI stack available for us +// to use under normal circumstances. Note that the returned +// value can be negative. +inline int ZeroStack::abi_stack_available(Thread *thread) const { + int stack_used = thread->stack_base() - (address) &stack_used; + int stack_free = thread->stack_size() - stack_used; + return stack_free - shadow_pages_size(); +} diff --git a/hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp b/hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp index 4ffa5d18919..a1b093ad57b 100644 --- a/hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp +++ b/hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp @@ -51,10 +51,7 @@ class StubGenerator: public StubCodeGenerator { // Set up the stack if necessary bool stack_needs_teardown = false; if (stack->needs_setup()) { - size_t stack_used = thread->stack_base() - (address) &stack_used; - size_t stack_free = thread->stack_size() - stack_used; - size_t zero_stack_size = align_size_down(stack_free / 2, wordSize); - + size_t zero_stack_size = stack->suggest_size(thread); stack->setup(alloca(zero_stack_size), zero_stack_size); stack_needs_teardown = true; } diff --git a/hotspot/src/share/vm/includeDB_zero b/hotspot/src/share/vm/includeDB_zero index b5c7a60440f..20a7fed1ec3 100644 --- a/hotspot/src/share/vm/includeDB_zero +++ b/hotspot/src/share/vm/includeDB_zero @@ -61,6 +61,7 @@ stack_.inline.hpp thread.hpp stack_.cpp interpreterRuntime.hpp stack_.cpp stack_.hpp +stack_.cpp stack_.inline.hpp stubGenerator_.cpp stack_.inline.hpp From 1a12511929ef912eec9a5a470d07ac49955d28af Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Thu, 6 May 2010 17:17:09 +0100 Subject: [PATCH 33/54] 6946825: com.sun.net.httpserver.HttpServer; Memory Leak on Non HTTP conform open socket Reviewed-by: michaelm --- jdk/src/share/classes/sun/net/httpserver/ServerImpl.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/jdk/src/share/classes/sun/net/httpserver/ServerImpl.java b/jdk/src/share/classes/sun/net/httpserver/ServerImpl.java index 8f5c8bee038..575661e776a 100644 --- a/jdk/src/share/classes/sun/net/httpserver/ServerImpl.java +++ b/jdk/src/share/classes/sun/net/httpserver/ServerImpl.java @@ -451,6 +451,7 @@ class ServerImpl implements TimeSource { if (requestLine == null) { /* connection closed */ connection.close(); + allConnections.remove(connection); return; } int space = requestLine.indexOf (' '); @@ -592,6 +593,8 @@ class ServerImpl implements TimeSource { sendReply ( code, true, "

"+code+Code.msg(code)+"

"+message ); + /* connection is already closed by sendReply, now remove it */ + allConnections.remove(connection); } void sendReply ( From 611ef519647b6bcd18212f6177178388e318c4dc Mon Sep 17 00:00:00 2001 From: Erik Trimble Date: Thu, 6 May 2010 12:46:21 -0700 Subject: [PATCH 34/54] 6950438: Add 6u18 and 6u20 release values explicitly to jprt.properties file Modify jprt.properties to allow JPRT to use 6u18 and 6u18 targets Reviewed-by: ohair --- hotspot/make/jprt.properties | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/hotspot/make/jprt.properties b/hotspot/make/jprt.properties index 66243d17550..a65c653b2ae 100644 --- a/hotspot/make/jprt.properties +++ b/hotspot/make/jprt.properties @@ -51,6 +51,8 @@ jprt.my.solaris.sparc.jdk6=solaris_sparc_5.8 jprt.my.solaris.sparc.jdk6perf=solaris_sparc_5.8 jprt.my.solaris.sparc.jdk6u10=solaris_sparc_5.8 jprt.my.solaris.sparc.jdk6u14=solaris_sparc_5.8 +jprt.my.solaris.sparc.jdk6u18=solaris_sparc_5.8 +jprt.my.solaris.sparc.jdk6u20=solaris_sparc_5.8 jprt.my.solaris.sparc=${jprt.my.solaris.sparc.${jprt.tools.default.release}} jprt.my.solaris.sparcv9.jdk7=solaris_sparcv9_5.10 @@ -58,6 +60,8 @@ jprt.my.solaris.sparcv9.jdk6=solaris_sparcv9_5.8 jprt.my.solaris.sparcv9.jdk6perf=solaris_sparcv9_5.8 jprt.my.solaris.sparcv9.jdk6u10=solaris_sparcv9_5.8 jprt.my.solaris.sparcv9.jdk6u14=solaris_sparcv9_5.8 +jprt.my.solaris.sparcv9.jdk6u18=solaris_sparcv9_5.8 +jprt.my.solaris.sparcv9.jdk6u20=solaris_sparcv9_5.8 jprt.my.solaris.sparcv9=${jprt.my.solaris.sparcv9.${jprt.tools.default.release}} jprt.my.solaris.i586.jdk7=solaris_i586_5.10 @@ -65,6 +69,8 @@ jprt.my.solaris.i586.jdk6=solaris_i586_5.8 jprt.my.solaris.i586.jdk6perf=solaris_i586_5.8 jprt.my.solaris.i586.jdk6u10=solaris_i586_5.8 jprt.my.solaris.i586.jdk6u14=solaris_i586_5.8 +jprt.my.solaris.i586.jdk6u18=solaris_i586_5.8 +jprt.my.solaris.i586.jdk6u20=solaris_i586_5.8 jprt.my.solaris.i586=${jprt.my.solaris.i586.${jprt.tools.default.release}} jprt.my.solaris.x64.jdk7=solaris_x64_5.10 @@ -72,6 +78,8 @@ jprt.my.solaris.x64.jdk6=solaris_x64_5.10 jprt.my.solaris.x64.jdk6perf=solaris_x64_5.10 jprt.my.solaris.x64.jdk6u10=solaris_x64_5.10 jprt.my.solaris.x64.jdk6u14=solaris_x64_5.10 +jprt.my.solaris.x64.jdk6u18=solaris_x64_5.10 +jprt.my.solaris.x64.jdk6u20=solaris_x64_5.10 jprt.my.solaris.x64=${jprt.my.solaris.x64.${jprt.tools.default.release}} jprt.my.linux.i586.jdk7=linux_i586_2.6 @@ -79,6 +87,8 @@ jprt.my.linux.i586.jdk6=linux_i586_2.4 jprt.my.linux.i586.jdk6perf=linux_i586_2.4 jprt.my.linux.i586.jdk6u10=linux_i586_2.4 jprt.my.linux.i586.jdk6u14=linux_i586_2.4 +jprt.my.linux.i586.jdk6u18=linux_i586_2.4 +jprt.my.linux.i586.jdk6u20=linux_i586_2.4 jprt.my.linux.i586=${jprt.my.linux.i586.${jprt.tools.default.release}} jprt.my.linux.x64.jdk7=linux_x64_2.6 @@ -86,6 +96,8 @@ jprt.my.linux.x64.jdk6=linux_x64_2.4 jprt.my.linux.x64.jdk6perf=linux_x64_2.4 jprt.my.linux.x64.jdk6u10=linux_x64_2.4 jprt.my.linux.x64.jdk6u14=linux_x64_2.4 +jprt.my.linux.x64.jdk6u18=linux_x64_2.4 +jprt.my.linux.x64.jdk6u20=linux_x64_2.4 jprt.my.linux.x64=${jprt.my.linux.x64.${jprt.tools.default.release}} jprt.my.windows.i586.jdk7=windows_i586_5.0 @@ -93,6 +105,8 @@ jprt.my.windows.i586.jdk6=windows_i586_5.0 jprt.my.windows.i586.jdk6perf=windows_i586_5.0 jprt.my.windows.i586.jdk6u10=windows_i586_5.0 jprt.my.windows.i586.jdk6u14=windows_i586_5.0 +jprt.my.windows.i586.jdk6u18=windows_i586_5.0 +jprt.my.windows.i586.jdk6u20=windows_i586_5.0 jprt.my.windows.i586=${jprt.my.windows.i586.${jprt.tools.default.release}} jprt.my.windows.x64.jdk7=windows_x64_5.2 @@ -100,6 +114,8 @@ jprt.my.windows.x64.jdk6=windows_x64_5.2 jprt.my.windows.x64.jdk6perf=windows_x64_5.2 jprt.my.windows.x64.jdk6u10=windows_x64_5.2 jprt.my.windows.x64.jdk6u14=windows_x64_5.2 +jprt.my.windows.x64.jdk6u18=windows_x64_5.2 +jprt.my.windows.x64.jdk6u20=windows_x64_5.2 jprt.my.windows.x64=${jprt.my.windows.x64.${jprt.tools.default.release}} # Standard list of jprt build targets for this source tree From 473182bb12e887e84a433df6273842ec21cacf3c Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Fri, 7 May 2010 10:11:37 +0100 Subject: [PATCH 35/54] 6947917: Error in basic authentication when user name and password are long Reviewed-by: weijun --- .../protocol/http/BasicAuthentication.java | 15 ++- .../protocol/http/BasicLongCredentials.java | 111 ++++++++++++++++++ 2 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 jdk/test/sun/net/www/protocol/http/BasicLongCredentials.java diff --git a/jdk/src/share/classes/sun/net/www/protocol/http/BasicAuthentication.java b/jdk/src/share/classes/sun/net/www/protocol/http/BasicAuthentication.java index 8e9c8a7281d..6755b59b061 100644 --- a/jdk/src/share/classes/sun/net/www/protocol/http/BasicAuthentication.java +++ b/jdk/src/share/classes/sun/net/www/protocol/http/BasicAuthentication.java @@ -29,8 +29,10 @@ import java.net.URL; import java.net.URI; import java.net.URISyntaxException; import java.net.PasswordAuthentication; +import java.io.IOException; +import java.io.OutputStream; import sun.net.www.HeaderParser; - +import sun.misc.BASE64Encoder; /** * BasicAuthentication: Encapsulate an http server authentication using @@ -74,7 +76,7 @@ class BasicAuthentication extends AuthenticationInfo { System.arraycopy(nameBytes, 0, concat, 0, nameBytes.length); System.arraycopy(passwdBytes, 0, concat, nameBytes.length, passwdBytes.length); - this.auth = "Basic " + (new sun.misc.BASE64Encoder()).encode(concat); + this.auth = "Basic " + (new BasicBASE64Encoder()).encode(concat); this.pw = pw; } @@ -114,7 +116,7 @@ class BasicAuthentication extends AuthenticationInfo { System.arraycopy(nameBytes, 0, concat, 0, nameBytes.length); System.arraycopy(passwdBytes, 0, concat, nameBytes.length, passwdBytes.length); - this.auth = "Basic " + (new sun.misc.BASE64Encoder()).encode(concat); + this.auth = "Basic " + (new BasicBASE64Encoder()).encode(concat); this.pw = pw; } @@ -200,4 +202,11 @@ class BasicAuthentication extends AuthenticationInfo { return npath; } + /* It is never expected that the header value will exceed the bytesPerLine */ + private class BasicBASE64Encoder extends BASE64Encoder { + @Override + protected int bytesPerLine() { + return (10000); + } + } } diff --git a/jdk/test/sun/net/www/protocol/http/BasicLongCredentials.java b/jdk/test/sun/net/www/protocol/http/BasicLongCredentials.java new file mode 100644 index 00000000000..5ce3c500097 --- /dev/null +++ b/jdk/test/sun/net/www/protocol/http/BasicLongCredentials.java @@ -0,0 +1,111 @@ +/* + * Copyright 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 + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 6947917 + * @summary Error in basic authentication when user name and password are long + */ + +import com.sun.net.httpserver.BasicAuthenticator; +import com.sun.net.httpserver.HttpContext; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpPrincipal; +import com.sun.net.httpserver.HttpServer; +import java.io.InputStream; +import java.io.IOException; +import java.net.Authenticator; +import java.net.InetSocketAddress; +import java.net.PasswordAuthentication; +import java.net.HttpURLConnection; +import java.net.URL; + +public class BasicLongCredentials { + + static final String USERNAME = "ThisIsMyReallyReallyReallyReallyReallyReally" + + "LongFirstNameDotLastNameAtCompanyEmailAddress"; + static final String PASSWORD = "AndThisIsALongLongLongLongLongLongLongLongLong" + + "LongLongLongLongLongLongLongLongLongPassword"; + static final String REALM = "foobar@test.realm"; + + public static void main (String[] args) throws Exception { + HttpServer server = HttpServer.create(new InetSocketAddress(0), 0); + try { + Handler handler = new Handler(); + HttpContext ctx = server.createContext("/test", handler); + + BasicAuthenticator a = new BasicAuthenticator(REALM) { + public boolean checkCredentials (String username, String pw) { + return USERNAME.equals(username) && PASSWORD.equals(pw); + } + }; + ctx.setAuthenticator(a); + server.start(); + + Authenticator.setDefault(new MyAuthenticator()); + + URL url = new URL("http://localhost:"+server.getAddress().getPort()+"/test/"); + HttpURLConnection urlc = (HttpURLConnection)url.openConnection(); + InputStream is = urlc.getInputStream(); + int c = 0; + while (is.read()!= -1) { c ++; } + + if (c != 0) { throw new RuntimeException("Test failed c = " + c); } + if (error) { throw new RuntimeException("Test failed: error"); } + + System.out.println ("OK"); + } finally { + server.stop(0); + } + } + + public static boolean error = false; + + static class MyAuthenticator extends java.net.Authenticator { + @Override + public PasswordAuthentication getPasswordAuthentication () { + if (!getRequestingPrompt().equals(REALM)) { + BasicLongCredentials.error = true; + } + return new PasswordAuthentication (USERNAME, PASSWORD.toCharArray()); + } + } + + static class Handler implements HttpHandler { + public void handle (HttpExchange t) throws IOException { + InputStream is = t.getRequestBody(); + while (is.read () != -1) ; + is.close(); + t.sendResponseHeaders(200, -1); + HttpPrincipal p = t.getPrincipal(); + if (!p.getUsername().equals(USERNAME)) { + error = true; + } + if (!p.getRealm().equals(REALM)) { + error = true; + } + t.close(); + } + } +} From 399d1f6a5f101f8bfd79ac6ff9f6e772b07b915b Mon Sep 17 00:00:00 2001 From: Gary Benson Date: Fri, 7 May 2010 04:20:56 -0700 Subject: [PATCH 36/54] 6950617: Zero/Shark interface updates Zero needs a couple of new methods to allow Shark to access the new frame anchor field. Reviewed-by: twisti --- hotspot/src/cpu/zero/vm/frame_zero.cpp | 4 ++++ hotspot/src/cpu/zero/vm/frame_zero.hpp | 3 +++ hotspot/src/cpu/zero/vm/javaFrameAnchor_zero.hpp | 4 ++++ hotspot/src/os_cpu/linux_zero/vm/thread_linux_zero.hpp | 6 ++++++ 4 files changed, 17 insertions(+) diff --git a/hotspot/src/cpu/zero/vm/frame_zero.cpp b/hotspot/src/cpu/zero/vm/frame_zero.cpp index 0bf4ae68b44..6a573a6254c 100644 --- a/hotspot/src/cpu/zero/vm/frame_zero.cpp +++ b/hotspot/src/cpu/zero/vm/frame_zero.cpp @@ -36,6 +36,10 @@ bool frame::is_interpreted_frame() const { return zeroframe()->is_interpreter_frame(); } +bool frame::is_fake_stub_frame() const { + return zeroframe()->is_fake_stub_frame(); +} + frame frame::sender_for_entry_frame(RegisterMap *map) const { assert(zeroframe()->is_entry_frame(), "wrong type of frame"); assert(map != NULL, "map must be set"); diff --git a/hotspot/src/cpu/zero/vm/frame_zero.hpp b/hotspot/src/cpu/zero/vm/frame_zero.hpp index 31815eb24fb..4d32a5b818b 100644 --- a/hotspot/src/cpu/zero/vm/frame_zero.hpp +++ b/hotspot/src/cpu/zero/vm/frame_zero.hpp @@ -61,6 +61,9 @@ return zeroframe()->as_shark_frame(); } + public: + bool is_fake_stub_frame() const; + public: frame sender_for_nonentry_frame(RegisterMap* map) const; diff --git a/hotspot/src/cpu/zero/vm/javaFrameAnchor_zero.hpp b/hotspot/src/cpu/zero/vm/javaFrameAnchor_zero.hpp index 7665780bc01..93e25a274e1 100644 --- a/hotspot/src/cpu/zero/vm/javaFrameAnchor_zero.hpp +++ b/hotspot/src/cpu/zero/vm/javaFrameAnchor_zero.hpp @@ -81,3 +81,7 @@ ZeroFrame* last_Java_fp() const { return _last_Java_fp; } + + static ByteSize last_Java_fp_offset() { + return byte_offset_of(JavaFrameAnchor, _last_Java_fp); + } diff --git a/hotspot/src/os_cpu/linux_zero/vm/thread_linux_zero.hpp b/hotspot/src/os_cpu/linux_zero/vm/thread_linux_zero.hpp index aea90119989..b92daee9650 100644 --- a/hotspot/src/os_cpu/linux_zero/vm/thread_linux_zero.hpp +++ b/hotspot/src/os_cpu/linux_zero/vm/thread_linux_zero.hpp @@ -88,6 +88,12 @@ return frame(last_Java_fp(), last_Java_sp()); } + public: + static ByteSize last_Java_fp_offset() { + return byte_offset_of(JavaThread, _anchor) + + JavaFrameAnchor::last_Java_fp_offset(); + } + public: // Check for pending suspend requests and pending asynchronous // exceptions. There are separate accessors for these, but From 521354406a4e9226aa2fbfe10238d3c9dac3c7a5 Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Fri, 7 May 2010 16:11:13 +0100 Subject: [PATCH 37/54] 6946673: DatagramSocket.connect() documentation contradicts the implementation Reviewed-by: alanb --- .../classes/java/net/DatagramSocket.java | 63 +++++++++++++------ 1 file changed, 43 insertions(+), 20 deletions(-) diff --git a/jdk/src/share/classes/java/net/DatagramSocket.java b/jdk/src/share/classes/java/net/DatagramSocket.java index 3e3464c677d..b177423979a 100644 --- a/jdk/src/share/classes/java/net/DatagramSocket.java +++ b/jdk/src/share/classes/java/net/DatagramSocket.java @@ -401,29 +401,40 @@ class DatagramSocket implements java.io.Closeable { * send or receive may throw a PortUnreachableException. Note, there is no * guarantee that the exception will be thrown. * - *

A caller's permission to send and receive datagrams to a - * given host and port are checked at connect time. When a socket - * is connected, receive and send will not - * perform any security checks on incoming and outgoing - * packets, other than matching the packet's and the socket's - * address and port. On a send operation, if the packet's address - * is set and the packet's address and the socket's address do not - * match, an IllegalArgumentException will be thrown. A socket - * connected to a multicast address may only be used to send packets. + *

If a security manager has been installed then it is invoked to check + * access to the remote address. Specifically, if the given {@code address} + * is a {@link InetAddress#isMulticastAddress multicast address}, + * the security manager's {@link + * java.lang.SecurityManager#checkMulticast(InetAddress) + * checkMulticast} method is invoked with the given {@code address}. + * Otherwise, the security manager's {@link + * java.lang.SecurityManager#checkConnect(String,int) checkConnect} + * and {@link java.lang.SecurityManager#checkAccept checkAccept} methods + * are invoked, with the given {@code address} and {@code port}, to + * verify that datagrams are permitted to be sent and received + * respectively. + * + *

When a socket is connected, {@link #receive receive} and + * {@link #send send} will not perform any security checks + * on incoming and outgoing packets, other than matching the packet's + * and the socket's address and port. On a send operation, if the + * packet's address is set and the packet's address and the socket's + * address do not match, an {@code IllegalArgumentException} will be + * thrown. A socket connected to a multicast address may only be used + * to send packets. * * @param address the remote address for the socket * * @param port the remote port for the socket. * - * @exception IllegalArgumentException if the address is null, - * or the port is out of range. + * @throws IllegalArgumentException + * if the address is null, or the port is out of range. * - * @exception SecurityException if the caller is not allowed to - * send datagrams to and receive datagrams from the address and port. + * @throws SecurityException + * if a security manager has been installed and it does + * not permit access to the given remote address * * @see #disconnect - * @see #send - * @see #receive */ public void connect(InetAddress address, int port) { try { @@ -435,13 +446,25 @@ class DatagramSocket implements java.io.Closeable { /** * Connects this socket to a remote socket address (IP address + port number). - *

+ * + *

If given an {@link InetSocketAddress InetSocketAddress}, this method + * behaves as if invoking {@link #connect(InetAddress,int) connect(InetAddress,int)} + * with the the given socket addresses IP address and port number. + * * @param addr The remote address. - * @throws SocketException if the connect fails - * @throws IllegalArgumentException if addr is null or addr is a SocketAddress - * subclass not supported by this socket + * + * @throws SocketException + * if the connect fails + * + * @throws IllegalArgumentException + * if {@code addr} is {@code null}, or {@code addr} is a SocketAddress + * subclass not supported by this socket + * + * @throws SecurityException + * if a security manager has been installed and it does + * not permit access to the given remote address + * * @since 1.4 - * @see #connect */ public void connect(SocketAddress addr) throws SocketException { if (addr == null) From bd1c4063c8db5707ba0b8ebdbc4319ea3ec77e9a Mon Sep 17 00:00:00 2001 From: Erik Trimble Date: Fri, 7 May 2010 15:13:00 -0700 Subject: [PATCH 38/54] Added tag hs18-b04 for changeset 31ba466ddb99 --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 1506a9033be..787b20f32c9 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -93,3 +93,4 @@ e7e7e36ccdb5d56edd47e5744351202d38f3b7ad jdk7-b87 e0a1a502e402dbe7bf2d9102b4084a7e79a99a9b jdk7-b91 25f53b53aaa3eb8b2d5391a1e8de9a76ae1dd8a2 hs18-b03 3221d1887d30341bedfdac1dbf365ea41beff20f jdk7-b92 +310cdbc355355a13aa53c002b6bde4a8c5ba67ff hs18-b04 From 4a29f05c6ad61db2932750d9799a050e6954bf04 Mon Sep 17 00:00:00 2001 From: Martin Buchholz Date: Sun, 9 May 2010 00:59:30 -0700 Subject: [PATCH 39/54] 6933217: Huge arrays handled poorly in core libraries Write overflow-conscious array resizing code Reviewed-by: chegar --- .../java/io/ByteArrayOutputStream.java | 56 ++++++-- .../java/lang/AbstractStringBuilder.java | 124 +++++++----------- .../classes/java/util/AbstractCollection.java | 28 +++- .../share/classes/java/util/ArrayList.java | 47 +++++-- .../share/classes/java/util/Hashtable.java | 17 ++- .../classes/java/util/PriorityQueue.java | 31 +++-- jdk/src/share/classes/java/util/Vector.java | 39 ++++-- 7 files changed, 218 insertions(+), 124 deletions(-) diff --git a/jdk/src/share/classes/java/io/ByteArrayOutputStream.java b/jdk/src/share/classes/java/io/ByteArrayOutputStream.java index 6a9b190f20c..a3b0e06bbb4 100644 --- a/jdk/src/share/classes/java/io/ByteArrayOutputStream.java +++ b/jdk/src/share/classes/java/io/ByteArrayOutputStream.java @@ -77,18 +77,51 @@ public class ByteArrayOutputStream extends OutputStream { buf = new byte[size]; } + /** + * Increases the capacity if necessary to ensure that it can hold + * at least the number of elements specified by the minimum + * capacity argument. + * + * @param minCapacity the desired minimum capacity + * @throws OutOfMemoryError if {@code minCapacity < 0}. This is + * interpreted as a request for the unsatisfiably large capacity + * {@code (long) Integer.MAX_VALUE + (minCapacity - Integer.MAX_VALUE)}. + */ + private void ensureCapacity(int minCapacity) { + // overflow-conscious code + if (minCapacity - buf.length > 0) + grow(minCapacity); + } + + /** + * Increases the capacity to ensure that it can hold at least the + * number of elements specified by the minimum capacity argument. + * + * @param minCapacity the desired minimum capacity + */ + private void grow(int minCapacity) { + // overflow-conscious code + int oldCapacity = buf.length; + int newCapacity = oldCapacity << 1; + if (newCapacity - minCapacity < 0) + newCapacity = minCapacity; + if (newCapacity < 0) { + if (minCapacity < 0) // overflow + throw new OutOfMemoryError(); + newCapacity = Integer.MAX_VALUE; + } + buf = Arrays.copyOf(buf, newCapacity); + } + /** * Writes the specified byte to this byte array output stream. * * @param b the byte to be written. */ public synchronized void write(int b) { - int newcount = count + 1; - if (newcount > buf.length) { - buf = Arrays.copyOf(buf, Math.max(buf.length << 1, newcount)); - } - buf[count] = (byte)b; - count = newcount; + ensureCapacity(count + 1); + buf[count] = (byte) b; + count += 1; } /** @@ -101,17 +134,12 @@ public class ByteArrayOutputStream extends OutputStream { */ public synchronized void write(byte b[], int off, int len) { if ((off < 0) || (off > b.length) || (len < 0) || - ((off + len) > b.length) || ((off + len) < 0)) { + ((off + len) - b.length > 0)) { throw new IndexOutOfBoundsException(); - } else if (len == 0) { - return; - } - int newcount = count + len; - if (newcount > buf.length) { - buf = Arrays.copyOf(buf, Math.max(buf.length << 1, newcount)); } + ensureCapacity(count + len); System.arraycopy(b, off, buf, count, len); - count = newcount; + count += len; } /** diff --git a/jdk/src/share/classes/java/lang/AbstractStringBuilder.java b/jdk/src/share/classes/java/lang/AbstractStringBuilder.java index 973e0854d61..fd98eb0403c 100644 --- a/jdk/src/share/classes/java/lang/AbstractStringBuilder.java +++ b/jdk/src/share/classes/java/lang/AbstractStringBuilder.java @@ -36,6 +36,8 @@ import java.util.Arrays; * sequence can be changed through certain method calls. * * @author Michael McCloskey + * @author Martin Buchholz + * @author Ulf Zibis * @since 1.5 */ abstract class AbstractStringBuilder implements Appendable, CharSequence { @@ -98,9 +100,16 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { * @param minimumCapacity the minimum desired capacity. */ public void ensureCapacity(int minimumCapacity) { - if (minimumCapacity > value.length) { + ensureCapacityInternal(minimumCapacity); + } + + /** + * This method has the same contract as ensureCapacity, but is + * never synchronized. + */ + private void ensureCapacityInternal(int minimumCapacity) { + if (minimumCapacity - value.length > 0) expandCapacity(minimumCapacity); - } } /** @@ -108,11 +117,13 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { * size check or synchronization. */ void expandCapacity(int minimumCapacity) { - int newCapacity = (value.length + 1) * 2; - if (newCapacity < 0) { - newCapacity = Integer.MAX_VALUE; - } else if (minimumCapacity > newCapacity) { + int newCapacity = value.length * 2; + if (newCapacity - minimumCapacity < 0) newCapacity = minimumCapacity; + if (newCapacity < 0) { + if (minimumCapacity < 0) // overflow + throw new OutOfMemoryError(); + newCapacity = Integer.MAX_VALUE; } value = Arrays.copyOf(value, newCapacity); } @@ -158,8 +169,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { public void setLength(int newLength) { if (newLength < 0) throw new StringIndexOutOfBoundsException(newLength); - if (newLength > value.length) - expandCapacity(newLength); + ensureCapacityInternal(newLength); if (count < newLength) { for (; count < newLength; count++) @@ -400,12 +410,9 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { public AbstractStringBuilder append(String str) { if (str == null) str = "null"; int len = str.length(); - if (len == 0) return this; - int newCount = count + len; - if (newCount > value.length) - expandCapacity(newCount); + ensureCapacityInternal(count + len); str.getChars(0, len, value, count); - count = newCount; + count += len; return this; } @@ -414,11 +421,9 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { if (sb == null) return append("null"); int len = sb.length(); - int newCount = count + len; - if (newCount > value.length) - expandCapacity(newCount); + ensureCapacityInternal(count + len); sb.getChars(0, len, value, count); - count = newCount; + count += len; return this; } @@ -470,14 +475,10 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { "start " + start + ", end " + end + ", s.length() " + s.length()); int len = end - start; - if (len == 0) - return this; - int newCount = count + len; - if (newCount > value.length) - expandCapacity(newCount); - for (int i=start; i value.length) - expandCapacity(newCount); - System.arraycopy(str, 0, value, count, str.length); - count = newCount; + int len = str.length; + ensureCapacityInternal(count + len); + System.arraycopy(str, 0, value, count, len); + count += len; return this; } @@ -529,11 +529,9 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { * or {@code offset+len > str.length} */ public AbstractStringBuilder append(char str[], int offset, int len) { - int newCount = count + len; - if (newCount > value.length) - expandCapacity(newCount); + ensureCapacityInternal(count + len); System.arraycopy(str, offset, value, count, len); - count = newCount; + count += len; return this; } @@ -551,17 +549,13 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { */ public AbstractStringBuilder append(boolean b) { if (b) { - int newCount = count + 4; - if (newCount > value.length) - expandCapacity(newCount); + ensureCapacityInternal(count + 4); value[count++] = 't'; value[count++] = 'r'; value[count++] = 'u'; value[count++] = 'e'; } else { - int newCount = count + 5; - if (newCount > value.length) - expandCapacity(newCount); + ensureCapacityInternal(count + 5); value[count++] = 'f'; value[count++] = 'a'; value[count++] = 'l'; @@ -587,9 +581,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { * @return a reference to this object. */ public AbstractStringBuilder append(char c) { - int newCount = count + 1; - if (newCount > value.length) - expandCapacity(newCount); + ensureCapacityInternal(count + 1); value[count++] = c; return this; } @@ -614,8 +606,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { int appendedLength = (i < 0) ? Integer.stringSize(-i) + 1 : Integer.stringSize(i); int spaceNeeded = count + appendedLength; - if (spaceNeeded > value.length) - expandCapacity(spaceNeeded); + ensureCapacityInternal(spaceNeeded); Integer.getChars(i, spaceNeeded, value); count = spaceNeeded; return this; @@ -641,8 +632,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { int appendedLength = (l < 0) ? Long.stringSize(-l) + 1 : Long.stringSize(l); int spaceNeeded = count + appendedLength; - if (spaceNeeded > value.length) - expandCapacity(spaceNeeded); + ensureCapacityInternal(spaceNeeded); Long.getChars(l, spaceNeeded, value); count = spaceNeeded; return this; @@ -738,10 +728,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { if (codePoint >= Character.MIN_SUPPLEMENTARY_CODE_POINT) { n++; } - int newCount = count + n; - if (newCount > value.length) { - expandCapacity(newCount); - } + ensureCapacityInternal(count + n); if (n == 1) { value[count++] = (char) codePoint; } else { @@ -807,8 +794,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { end = count; int len = str.length(); int newCount = count + len - (end - start); - if (newCount > value.length) - expandCapacity(newCount); + ensureCapacityInternal(newCount); System.arraycopy(value, end, value, start + len, count - end); str.getChars(value, start); @@ -915,12 +901,10 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { throw new StringIndexOutOfBoundsException( "offset " + offset + ", len " + len + ", str.length " + str.length); - int newCount = count + len; - if (newCount > value.length) - expandCapacity(newCount); + ensureCapacityInternal(count + len); System.arraycopy(value, index, value, index + len, count - index); System.arraycopy(str, offset, value, index, len); - count = newCount; + count += len; return this; } @@ -984,12 +968,10 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { if (str == null) str = "null"; int len = str.length(); - int newCount = count + len; - if (newCount > value.length) - expandCapacity(newCount); + ensureCapacityInternal(count + len); System.arraycopy(value, offset, value, offset + len, count - offset); str.getChars(value, offset); - count = newCount; + count += len; return this; } @@ -1021,12 +1003,10 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { if ((offset < 0) || (offset > length())) throw new StringIndexOutOfBoundsException(offset); int len = str.length; - int newCount = count + len; - if (newCount > value.length) - expandCapacity(newCount); + ensureCapacityInternal(count + len); System.arraycopy(value, offset, value, offset + len, count - offset); System.arraycopy(str, 0, value, offset, len); - count = newCount; + count += len; return this; } @@ -1114,16 +1094,12 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { "start " + start + ", end " + end + ", s.length() " + s.length()); int len = end - start; - if (len == 0) - return this; - int newCount = count + len; - if (newCount > value.length) - expandCapacity(newCount); + ensureCapacityInternal(count + len); System.arraycopy(value, dstOffset, value, dstOffset + len, count - dstOffset); for (int i=start; i value.length) - expandCapacity(newCount); + ensureCapacityInternal(count + 1); System.arraycopy(value, offset, value, offset + 1, count - offset); value[offset] = c; - count = newCount; + count += 1; return this; } diff --git a/jdk/src/share/classes/java/util/AbstractCollection.java b/jdk/src/share/classes/java/util/AbstractCollection.java index 5b13c9b00fd..f40d050589f 100644 --- a/jdk/src/share/classes/java/util/AbstractCollection.java +++ b/jdk/src/share/classes/java/util/AbstractCollection.java @@ -190,6 +190,14 @@ public abstract class AbstractCollection implements Collection { return it.hasNext() ? finishToArray(r, it) : r; } + /** + * The maximum size of array to allocate. + * Some VMs reserve some header words in an array. + * Attempts to allocate larger arrays may result in + * OutOfMemoryError: Requested array size exceeds VM limit + */ + private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; + /** * Reallocates the array being used within toArray when the iterator * returned more elements than expected, and finishes filling it from @@ -205,13 +213,10 @@ public abstract class AbstractCollection implements Collection { while (it.hasNext()) { int cap = r.length; if (i == cap) { - int newCap = ((cap / 2) + 1) * 3; - if (newCap <= cap) { // integer overflow - if (cap == Integer.MAX_VALUE) - throw new OutOfMemoryError - ("Required array size too large"); - newCap = Integer.MAX_VALUE; - } + int newCap = cap + (cap >> 1) + 1; + // overflow-conscious code + if (newCap - MAX_ARRAY_SIZE > 0) + newCap = hugeCapacity(cap + 1); r = Arrays.copyOf(r, newCap); } r[i++] = (T)it.next(); @@ -220,6 +225,15 @@ public abstract class AbstractCollection implements Collection { return (i == r.length) ? r : Arrays.copyOf(r, i); } + private static int hugeCapacity(int minCapacity) { + if (minCapacity < 0) // overflow + throw new OutOfMemoryError + ("Required array size too large"); + return (minCapacity > MAX_ARRAY_SIZE) ? + Integer.MAX_VALUE : + MAX_ARRAY_SIZE; + } + // Modification Operations /** diff --git a/jdk/src/share/classes/java/util/ArrayList.java b/jdk/src/share/classes/java/util/ArrayList.java index dbd46096bf3..92dbfd9c84b 100644 --- a/jdk/src/share/classes/java/util/ArrayList.java +++ b/jdk/src/share/classes/java/util/ArrayList.java @@ -173,18 +173,47 @@ public class ArrayList extends AbstractList * necessary, to ensure that it can hold at least the number of elements * specified by the minimum capacity argument. * - * @param minCapacity the desired minimum capacity + * @param minCapacity the desired minimum capacity */ public void ensureCapacity(int minCapacity) { modCount++; + // overflow-conscious code + if (minCapacity - elementData.length > 0) + grow(minCapacity); + } + + /** + * The maximum size of array to allocate. + * Some VMs reserve some header words in an array. + * Attempts to allocate larger arrays may result in + * OutOfMemoryError: Requested array size exceeds VM limit + */ + private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; + + /** + * Increases the capacity to ensure that it can hold at least the + * number of elements specified by the minimum capacity argument. + * + * @param minCapacity the desired minimum capacity + */ + private void grow(int minCapacity) { + // overflow-conscious code int oldCapacity = elementData.length; - if (minCapacity > oldCapacity) { - int newCapacity = (oldCapacity * 3)/2 + 1; - if (newCapacity < minCapacity) - newCapacity = minCapacity; - // minCapacity is usually close to size, so this is a win: - elementData = Arrays.copyOf(elementData, newCapacity); - } + int newCapacity = oldCapacity + (oldCapacity >> 1); + if (newCapacity - minCapacity < 0) + newCapacity = minCapacity; + if (newCapacity - MAX_ARRAY_SIZE > 0) + newCapacity = hugeCapacity(minCapacity); + // minCapacity is usually close to size, so this is a win: + elementData = Arrays.copyOf(elementData, newCapacity); + } + + private static int hugeCapacity(int minCapacity) { + if (minCapacity < 0) // overflow + throw new OutOfMemoryError(); + return (minCapacity > MAX_ARRAY_SIZE) ? + Integer.MAX_VALUE : + MAX_ARRAY_SIZE; } /** @@ -391,7 +420,7 @@ public class ArrayList extends AbstractList public void add(int index, E element) { rangeCheckForAdd(index); - ensureCapacity(size+1); // Increments modCount!! + ensureCapacity(size + 1); // Increments modCount!! System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; diff --git a/jdk/src/share/classes/java/util/Hashtable.java b/jdk/src/share/classes/java/util/Hashtable.java index 4fbd336ca6c..17267985d2a 100644 --- a/jdk/src/share/classes/java/util/Hashtable.java +++ b/jdk/src/share/classes/java/util/Hashtable.java @@ -364,6 +364,14 @@ public class Hashtable return null; } + /** + * The maximum size of array to allocate. + * Some VMs reserve some header words in an array. + * Attempts to allocate larger arrays may result in + * OutOfMemoryError: Requested array size exceeds VM limit + */ + private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; + /** * Increases the capacity of and internally reorganizes this * hashtable, in order to accommodate and access its entries more @@ -375,7 +383,14 @@ public class Hashtable int oldCapacity = table.length; Entry[] oldMap = table; - int newCapacity = oldCapacity * 2 + 1; + // overflow-conscious code + int newCapacity = (oldCapacity << 1) + 1; + if (newCapacity - MAX_ARRAY_SIZE > 0) { + if (oldCapacity == MAX_ARRAY_SIZE) + // Keep running with MAX_ARRAY_SIZE buckets + return; + newCapacity = MAX_ARRAY_SIZE; + } Entry[] newMap = new Entry[newCapacity]; modCount++; diff --git a/jdk/src/share/classes/java/util/PriorityQueue.java b/jdk/src/share/classes/java/util/PriorityQueue.java index 428792fe1c6..ac87d9fb569 100644 --- a/jdk/src/share/classes/java/util/PriorityQueue.java +++ b/jdk/src/share/classes/java/util/PriorityQueue.java @@ -235,26 +235,39 @@ public class PriorityQueue extends AbstractQueue size = a.length; } + /** + * The maximum size of array to allocate. + * Some VMs reserve some header words in an array. + * Attempts to allocate larger arrays may result in + * OutOfMemoryError: Requested array size exceeds VM limit + */ + private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; + /** * Increases the capacity of the array. * * @param minCapacity the desired minimum capacity */ private void grow(int minCapacity) { - if (minCapacity < 0) // overflow - throw new OutOfMemoryError(); int oldCapacity = queue.length; // Double size if small; else grow by 50% - int newCapacity = ((oldCapacity < 64)? - ((oldCapacity + 1) * 2): - ((oldCapacity / 2) * 3)); - if (newCapacity < 0) // overflow - newCapacity = Integer.MAX_VALUE; - if (newCapacity < minCapacity) - newCapacity = minCapacity; + int newCapacity = oldCapacity + ((oldCapacity < 64) ? + (oldCapacity + 2) : + (oldCapacity >> 1)); + // overflow-conscious code + if (newCapacity - MAX_ARRAY_SIZE > 0) + newCapacity = hugeCapacity(minCapacity); queue = Arrays.copyOf(queue, newCapacity); } + private static int hugeCapacity(int minCapacity) { + if (minCapacity < 0) // overflow + throw new OutOfMemoryError(); + return (minCapacity > MAX_ARRAY_SIZE) ? + Integer.MAX_VALUE : + MAX_ARRAY_SIZE; + } + /** * Inserts the specified element into this priority queue. * diff --git a/jdk/src/share/classes/java/util/Vector.java b/jdk/src/share/classes/java/util/Vector.java index f70d36ee069..6fa6c84f8da 100644 --- a/jdk/src/share/classes/java/util/Vector.java +++ b/jdk/src/share/classes/java/util/Vector.java @@ -235,16 +235,37 @@ public class Vector * @see #ensureCapacity(int) */ private void ensureCapacityHelper(int minCapacity) { + // overflow-conscious code + if (minCapacity - elementData.length > 0) + grow(minCapacity); + } + + /** + * The maximum size of array to allocate. + * Some VMs reserve some header words in an array. + * Attempts to allocate larger arrays may result in + * OutOfMemoryError: Requested array size exceeds VM limit + */ + private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; + + private void grow(int minCapacity) { + // overflow-conscious code int oldCapacity = elementData.length; - if (minCapacity > oldCapacity) { - Object[] oldData = elementData; - int newCapacity = (capacityIncrement > 0) ? - (oldCapacity + capacityIncrement) : (oldCapacity * 2); - if (newCapacity < minCapacity) { - newCapacity = minCapacity; - } - elementData = Arrays.copyOf(elementData, newCapacity); - } + int newCapacity = oldCapacity + ((capacityIncrement > 0) ? + capacityIncrement : oldCapacity); + if (newCapacity - minCapacity < 0) + newCapacity = minCapacity; + if (newCapacity - MAX_ARRAY_SIZE > 0) + newCapacity = hugeCapacity(minCapacity); + elementData = Arrays.copyOf(elementData, newCapacity); + } + + private static int hugeCapacity(int minCapacity) { + if (minCapacity < 0) // overflow + throw new OutOfMemoryError(); + return (minCapacity > MAX_ARRAY_SIZE) ? + Integer.MAX_VALUE : + MAX_ARRAY_SIZE; } /** From b455514c890ea10fbb2104051d2b3b4e347239eb Mon Sep 17 00:00:00 2001 From: Martin Buchholz Date: Sun, 9 May 2010 00:59:49 -0700 Subject: [PATCH 40/54] 6950540: PriorityQueue(collection) should throw NPE if collection contains a null Rewrite PriorityQueue constructors for best performance and error handling Reviewed-by: dholmes, chegar --- .../classes/java/util/PriorityQueue.java | 63 ++++-- jdk/test/java/util/PriorityQueue/NoNulls.java | 204 ++++++++++++++++++ 2 files changed, 248 insertions(+), 19 deletions(-) create mode 100644 jdk/test/java/util/PriorityQueue/NoNulls.java diff --git a/jdk/src/share/classes/java/util/PriorityQueue.java b/jdk/src/share/classes/java/util/PriorityQueue.java index ac87d9fb569..931c287c0c2 100644 --- a/jdk/src/share/classes/java/util/PriorityQueue.java +++ b/jdk/src/share/classes/java/util/PriorityQueue.java @@ -170,17 +170,21 @@ public class PriorityQueue extends AbstractQueue * @throws NullPointerException if the specified collection or any * of its elements are null */ + @SuppressWarnings("unchecked") public PriorityQueue(Collection c) { - initFromCollection(c); - if (c instanceof SortedSet) - comparator = (Comparator) - ((SortedSet)c).comparator(); - else if (c instanceof PriorityQueue) - comparator = (Comparator) - ((PriorityQueue)c).comparator(); + if (c instanceof SortedSet) { + SortedSet ss = (SortedSet) c; + this.comparator = (Comparator) ss.comparator(); + initElementsFromCollection(ss); + } + else if (c instanceof PriorityQueue) { + PriorityQueue pq = (PriorityQueue) c; + this.comparator = (Comparator) pq.comparator(); + initFromPriorityQueue(pq); + } else { - comparator = null; - heapify(); + this.comparator = null; + initFromCollection(c); } } @@ -198,9 +202,10 @@ public class PriorityQueue extends AbstractQueue * @throws NullPointerException if the specified priority queue or any * of its elements are null */ + @SuppressWarnings("unchecked") public PriorityQueue(PriorityQueue c) { - comparator = (Comparator)c.comparator(); - initFromCollection(c); + this.comparator = (Comparator) c.comparator(); + initFromPriorityQueue(c); } /** @@ -216,9 +221,33 @@ public class PriorityQueue extends AbstractQueue * @throws NullPointerException if the specified sorted set or any * of its elements are null */ + @SuppressWarnings("unchecked") public PriorityQueue(SortedSet c) { - comparator = (Comparator)c.comparator(); - initFromCollection(c); + this.comparator = (Comparator) c.comparator(); + initElementsFromCollection(c); + } + + private void initFromPriorityQueue(PriorityQueue c) { + if (c.getClass() == PriorityQueue.class) { + this.queue = c.toArray(); + this.size = c.size(); + } else { + initFromCollection(c); + } + } + + private void initElementsFromCollection(Collection c) { + Object[] a = c.toArray(); + // If c.toArray incorrectly doesn't return Object[], copy it. + if (a.getClass() != Object[].class) + a = Arrays.copyOf(a, a.length, Object[].class); + int len = a.length; + if (len == 1 || this.comparator != null) + for (int i = 0; i < len; i++) + if (a[i] == null) + throw new NullPointerException(); + this.queue = a; + this.size = a.length; } /** @@ -227,12 +256,8 @@ public class PriorityQueue extends AbstractQueue * @param c the collection */ private void initFromCollection(Collection c) { - Object[] a = c.toArray(); - // If c.toArray incorrectly doesn't return Object[], copy it. - if (a.getClass() != Object[].class) - a = Arrays.copyOf(a, a.length, Object[].class); - queue = a; - size = a.length; + initElementsFromCollection(c); + heapify(); } /** diff --git a/jdk/test/java/util/PriorityQueue/NoNulls.java b/jdk/test/java/util/PriorityQueue/NoNulls.java new file mode 100644 index 00000000000..c40c93be893 --- /dev/null +++ b/jdk/test/java/util/PriorityQueue/NoNulls.java @@ -0,0 +1,204 @@ +/* + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Martin Buchholz with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/licenses/publicdomain + */ + +/* + * @test + * @bug 6950540 + * @summary Attempt to add a null throws NullPointerException + */ + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Collection; +import java.util.Collections; +import java.util.PriorityQueue; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.LinkedBlockingDeque; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.PriorityBlockingQueue; + +public class NoNulls { + void test(String[] args) throws Throwable { + final Comparator nullTolerantComparator + = new Comparator<>() { + public int compare(String x, String y) { + return (x == null ? -1 : + y == null ? 1 : + x.compareTo(y)); + }}; + + final SortedSet nullSortedSet + = new TreeSet<>(nullTolerantComparator); + nullSortedSet.add(null); + + final PriorityQueue nullPriorityQueue + = new PriorityQueue<>() { + public Object[] toArray() { return new Object[] { null };}}; + + final Collection nullCollection = new ArrayList<>(); + nullCollection.add(null); + + THROWS(NullPointerException.class, + new F() { void f() { + new PriorityQueue(nullCollection); + }}, + new F() { void f() { + new PriorityBlockingQueue(nullCollection); + }}, + new F() { void f() { + new ArrayBlockingQueue(10, false, nullCollection); + }}, + new F() { void f() { + new ArrayBlockingQueue(10, true, nullCollection); + }}, + new F() { void f() { + new LinkedBlockingQueue(nullCollection); + }}, + new F() { void f() { + new LinkedBlockingDeque(nullCollection); + }}, + + new F() { void f() { + new PriorityQueue((Collection) nullPriorityQueue); + }}, + new F() { void f() { + new PriorityBlockingQueue((Collection) nullPriorityQueue); + }}, + + new F() { void f() { + new PriorityQueue(nullSortedSet); + }}, + new F() { void f() { + new PriorityBlockingQueue(nullSortedSet); + }}, + + new F() { void f() { + new PriorityQueue((Collection) nullSortedSet); + }}, + new F() { void f() { + new PriorityBlockingQueue((Collection) nullSortedSet); + }}, + + new F() { void f() { + new PriorityQueue(nullPriorityQueue); + }}, + new F() { void f() { + new PriorityBlockingQueue(nullPriorityQueue); + }}, + + new F() { void f() { + new PriorityQueue().add(null); + }}, + new F() { void f() { + new PriorityBlockingQueue().add(null); + }}, + new F() { void f() { + new ArrayBlockingQueue(10, false).add(null); + }}, + new F() { void f() { + new ArrayBlockingQueue(10, true).add(null); + }}, + new F() { void f() { + new LinkedBlockingQueue().add(null); + }}, + new F() { void f() { + new LinkedBlockingDeque().add(null); + }}, + + new F() { void f() { + new PriorityQueue().offer(null); + }}, + new F() { void f() { + new PriorityBlockingQueue().offer(null); + }}); + + nullSortedSet.add("foo"); + nullCollection.add("foo"); + THROWS(NullPointerException.class, + new F() { void f() { + new PriorityQueue(nullCollection); + }}, + new F() { void f() { + new PriorityBlockingQueue(nullCollection); + }}, + + new F() { void f() { + new PriorityQueue((Collection) nullPriorityQueue); + }}, + new F() { void f() { + new PriorityBlockingQueue((Collection) nullPriorityQueue); + }}, + + new F() { void f() { + new PriorityQueue(nullSortedSet); + }}, + new F() { void f() { + new PriorityBlockingQueue(nullSortedSet); + }}, + + new F() { void f() { + new PriorityQueue((Collection) nullSortedSet); + }}, + new F() { void f() { + new PriorityBlockingQueue((Collection) nullSortedSet); + }}); + + } + + //--------------------- Infrastructure --------------------------- + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + new NoNulls().instanceMain(args);} + public void instanceMain(String[] args) throws Throwable { + try {test(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} + abstract class F {abstract void f() throws Throwable;} + void THROWS(Class k, F... fs) { + for (F f : fs) + try {f.f(); fail("Expected " + k.getName() + " not thrown");} + catch (Throwable t) { + if (k.isAssignableFrom(t.getClass())) pass(); + else unexpected(t);}} +} From 75e3cde928811b1931a255bbe70e86ba4369d6dc Mon Sep 17 00:00:00 2001 From: Martin Buchholz Date: Sun, 9 May 2010 16:03:13 -0700 Subject: [PATCH 41/54] 6937857: Concurrent calls to new Random() not random enough Seed uniquifier should use an independent PRNG Reviewed-by: dl --- jdk/src/share/classes/java/util/Random.java | 29 +++++++++++--- jdk/test/java/util/Random/DistinctSeeds.java | 40 +++++++++++++++++++- 2 files changed, 61 insertions(+), 8 deletions(-) diff --git a/jdk/src/share/classes/java/util/Random.java b/jdk/src/share/classes/java/util/Random.java index efe3f68a01a..b3381252bef 100644 --- a/jdk/src/share/classes/java/util/Random.java +++ b/jdk/src/share/classes/java/util/Random.java @@ -86,8 +86,23 @@ class Random implements java.io.Serializable { * the seed of the random number generator to a value very likely * to be distinct from any other invocation of this constructor. */ - public Random() { this(++seedUniquifier + System.nanoTime()); } - private static volatile long seedUniquifier = 8682522807148012L; + public Random() { + this(seedUniquifier() ^ System.nanoTime()); + } + + private static long seedUniquifier() { + // L'Ecuyer, "Tables of Linear Congruential Generators of + // Different Sizes and Good Lattice Structure", 1999 + for (;;) { + long current = seedUniquifier.get(); + long next = current * 181783497276652981L; + if (seedUniquifier.compareAndSet(current, next)) + return next; + } + } + + private static final AtomicLong seedUniquifier + = new AtomicLong(8682522807148012L); /** * Creates a new random number generator using a single {@code long} seed. @@ -103,8 +118,11 @@ class Random implements java.io.Serializable { * @see #setSeed(long) */ public Random(long seed) { - this.seed = new AtomicLong(0L); - setSeed(seed); + this.seed = new AtomicLong(initialScramble(seed)); + } + + private static long initialScramble(long seed) { + return (seed ^ multiplier) & mask; } /** @@ -127,8 +145,7 @@ class Random implements java.io.Serializable { * @param seed the initial seed */ synchronized public void setSeed(long seed) { - seed = (seed ^ multiplier) & mask; - this.seed.set(seed); + this.seed.set(initialScramble(seed)); haveNextNextGaussian = false; } diff --git a/jdk/test/java/util/Random/DistinctSeeds.java b/jdk/test/java/util/Random/DistinctSeeds.java index 795051b0298..736761ebb77 100644 --- a/jdk/test/java/util/Random/DistinctSeeds.java +++ b/jdk/test/java/util/Random/DistinctSeeds.java @@ -33,18 +33,54 @@ /* * @test - * @bug 4949279 + * @bug 4949279 6937857 * @summary Independent instantiations of Random() have distinct seeds. */ +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; import java.util.Random; public class DistinctSeeds { public static void main(String[] args) throws Exception { // Strictly speaking, it is possible for these to randomly fail, - // but the probability should be *extremely* small (< 2**-63). + // but the probability should be small (approximately 2**-48). if (new Random().nextLong() == new Random().nextLong() || new Random().nextLong() == new Random().nextLong()) throw new RuntimeException("Random() seeds not unique."); + + // Now try generating seeds concurrently + class RandomCollector implements Runnable { + long[] randoms = new long[1<<17]; + public void run() { + for (int i = 0; i < randoms.length; i++) + randoms[i] = new Random().nextLong(); + } + } + final int threadCount = 2; + List collectors = new ArrayList(); + List threads = new ArrayList(); + for (int i = 0; i < threadCount; i++) { + RandomCollector r = new RandomCollector(); + collectors.add(r); + threads.add(new Thread(r)); + } + for (Thread thread : threads) + thread.start(); + for (Thread thread : threads) + thread.join(); + int collisions = 0; + HashSet s = new HashSet(); + for (RandomCollector r : collectors) { + for (long x : r.randoms) { + if (s.contains(x)) + collisions++; + s.add(x); + } + } + System.out.printf("collisions=%d%n", collisions); + if (collisions > 10) + throw new Error("too many collisions"); } } From 3adf1d8538179a0a788bdaa34621e39c1eb7e8a2 Mon Sep 17 00:00:00 2001 From: Martin Buchholz Date: Sun, 9 May 2010 16:37:06 -0700 Subject: [PATCH 42/54] 6937842: Unreadable \uXXXX in javadoc Replace \uXXXX by \u005CXXXX, or simply delete Reviewed-by: sherman --- jdk/src/share/classes/java/lang/String.java | 8 ++++---- jdk/src/share/classes/java/util/zip/Deflater.java | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/jdk/src/share/classes/java/lang/String.java b/jdk/src/share/classes/java/lang/String.java index 2aead0f545d..918b4dee02e 100644 --- a/jdk/src/share/classes/java/lang/String.java +++ b/jdk/src/share/classes/java/lang/String.java @@ -2551,8 +2551,8 @@ public final class String * Examples are programming language identifiers, protocol keys, and HTML * tags. * For instance, "TITLE".toLowerCase() in a Turkish locale - * returns "t\u0131tle", where '\u0131' is the LATIN SMALL - * LETTER DOTLESS I character. + * returns "t\u005Cu0131tle", where '\u005Cu0131' is the + * LATIN SMALL LETTER DOTLESS I character. * To obtain correct results for locale insensitive strings, use * toLowerCase(Locale.ENGLISH). *

@@ -2714,8 +2714,8 @@ public final class String * Examples are programming language identifiers, protocol keys, and HTML * tags. * For instance, "title".toUpperCase() in a Turkish locale - * returns "T\u0130TLE", where '\u0130' is the LATIN CAPITAL - * LETTER I WITH DOT ABOVE character. + * returns "T\u005Cu0130TLE", where '\u005Cu0130' is the + * LATIN CAPITAL LETTER I WITH DOT ABOVE character. * To obtain correct results for locale insensitive strings, use * toUpperCase(Locale.ENGLISH). *

diff --git a/jdk/src/share/classes/java/util/zip/Deflater.java b/jdk/src/share/classes/java/util/zip/Deflater.java index 9c4c0ce6c8c..abc1b6541ed 100644 --- a/jdk/src/share/classes/java/util/zip/Deflater.java +++ b/jdk/src/share/classes/java/util/zip/Deflater.java @@ -40,7 +40,7 @@ package java.util.zip; *

  * try {
  *     // Encode a String into bytes
- *     String inputString = "blahblahblah\u20AC\u20AC";
+ *     String inputString = "blahblahblah";
  *     byte[] input = inputString.getBytes("UTF-8");
  *
  *     // Compress the bytes

From 4715f32101aa706d6b65269dcd7cd7d0e60542f4 Mon Sep 17 00:00:00 2001
From: "Y. Srinivas Ramakrishna" 
Date: Mon, 10 May 2010 12:31:52 -0700
Subject: [PATCH 43/54] 6951188: CMS: move PromotionInfo into its own file

Moved PromotionInfo and friends into new files promotionInfo.{h,c}pp from their previous compactibleFreeListSpace.{h,c}pp home.

Reviewed-by: apetrusenko
---
 .../compactibleFreeListSpace.cpp              | 328 ----------------
 .../compactibleFreeListSpace.hpp              | 140 +------
 .../concurrentMarkSweepGeneration.cpp         |   2 +-
 .../concurrentMarkSweep/promotionInfo.cpp     | 360 ++++++++++++++++++
 .../concurrentMarkSweep/promotionInfo.hpp     | 161 ++++++++
 .../includeDB_gc_concurrentMarkSweep          |   9 +
 6 files changed, 537 insertions(+), 463 deletions(-)
 create mode 100644 hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/promotionInfo.cpp
 create mode 100644 hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/promotionInfo.hpp

diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp
index 9e3b6cf81cc..e3052ec9962 100644
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp
@@ -1926,59 +1926,6 @@ oop_since_save_marks_iterate##nv_suffix(OopClosureType* blk) {              \
 
 ALL_SINCE_SAVE_MARKS_CLOSURES(CFLS_OOP_SINCE_SAVE_MARKS_DEFN)
 
-//////////////////////////////////////////////////////////////////////////////
-// We go over the list of promoted objects, removing each from the list,
-// and applying the closure (this may, in turn, add more elements to
-// the tail of the promoted list, and these newly added objects will
-// also be processed) until the list is empty.
-// To aid verification and debugging, in the non-product builds
-// we actually forward _promoHead each time we process a promoted oop.
-// Note that this is not necessary in general (i.e. when we don't need to
-// call PromotionInfo::verify()) because oop_iterate can only add to the
-// end of _promoTail, and never needs to look at _promoHead.
-
-#define PROMOTED_OOPS_ITERATE_DEFN(OopClosureType, nv_suffix)               \
-                                                                            \
-void PromotionInfo::promoted_oops_iterate##nv_suffix(OopClosureType* cl) {  \
-  NOT_PRODUCT(verify());                                                    \
-  PromotedObject *curObj, *nextObj;                                         \
-  for (curObj = _promoHead; curObj != NULL; curObj = nextObj) {             \
-    if ((nextObj = curObj->next()) == NULL) {                               \
-      /* protect ourselves against additions due to closure application     \
-         below by resetting the list.  */                                   \
-      assert(_promoTail == curObj, "Should have been the tail");            \
-      _promoHead = _promoTail = NULL;                                       \
-    }                                                                       \
-    if (curObj->hasDisplacedMark()) {                                       \
-      /* restore displaced header */                                        \
-      oop(curObj)->set_mark(nextDisplacedHeader());                         \
-    } else {                                                                \
-      /* restore prototypical header */                                     \
-      oop(curObj)->init_mark();                                             \
-    }                                                                       \
-    /* The "promoted_mark" should now not be set */                         \
-    assert(!curObj->hasPromotedMark(),                                      \
-           "Should have been cleared by restoring displaced mark-word");    \
-    NOT_PRODUCT(_promoHead = nextObj);                                      \
-    if (cl != NULL) oop(curObj)->oop_iterate(cl);                           \
-    if (nextObj == NULL) { /* start at head of list reset above */          \
-      nextObj = _promoHead;                                                 \
-    }                                                                       \
-  }                                                                         \
-  assert(noPromotions(), "post-condition violation");                       \
-  assert(_promoHead == NULL && _promoTail == NULL, "emptied promoted list");\
-  assert(_spoolHead == _spoolTail, "emptied spooling buffers");             \
-  assert(_firstIndex == _nextIndex, "empty buffer");                        \
-}
-
-// This should have been ALL_SINCE_...() just like the others,
-// but, because the body of the method above is somehwat longer,
-// the MSVC compiler cannot cope; as a workaround, we split the
-// macro into its 3 constituent parts below (see original macro
-// definition in specializedOopClosures.hpp).
-SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG(PROMOTED_OOPS_ITERATE_DEFN)
-PROMOTED_OOPS_ITERATE_DEFN(OopsInGenClosure,_v)
-
 
 void CompactibleFreeListSpace::object_iterate_since_last_GC(ObjectClosure* cl) {
   // ugghh... how would one do this efficiently for a non-contiguous space?
@@ -2506,281 +2453,6 @@ void CompactibleFreeListSpace::printFLCensus(size_t sweep_count) const {
   _dictionary->printDictCensus();
 }
 
-// Return the next displaced header, incrementing the pointer and
-// recycling spool area as necessary.
-markOop PromotionInfo::nextDisplacedHeader() {
-  assert(_spoolHead != NULL, "promotionInfo inconsistency");
-  assert(_spoolHead != _spoolTail || _firstIndex < _nextIndex,
-         "Empty spool space: no displaced header can be fetched");
-  assert(_spoolHead->bufferSize > _firstIndex, "Off by one error at head?");
-  markOop hdr = _spoolHead->displacedHdr[_firstIndex];
-  // Spool forward
-  if (++_firstIndex == _spoolHead->bufferSize) { // last location in this block
-    // forward to next block, recycling this block into spare spool buffer
-    SpoolBlock* tmp = _spoolHead->nextSpoolBlock;
-    assert(_spoolHead != _spoolTail, "Spooling storage mix-up");
-    _spoolHead->nextSpoolBlock = _spareSpool;
-    _spareSpool = _spoolHead;
-    _spoolHead = tmp;
-    _firstIndex = 1;
-    NOT_PRODUCT(
-      if (_spoolHead == NULL) {  // all buffers fully consumed
-        assert(_spoolTail == NULL && _nextIndex == 1,
-               "spool buffers processing inconsistency");
-      }
-    )
-  }
-  return hdr;
-}
-
-void PromotionInfo::track(PromotedObject* trackOop) {
-  track(trackOop, oop(trackOop)->klass());
-}
-
-void PromotionInfo::track(PromotedObject* trackOop, klassOop klassOfOop) {
-  // make a copy of header as it may need to be spooled
-  markOop mark = oop(trackOop)->mark();
-  trackOop->clearNext();
-  if (mark->must_be_preserved_for_cms_scavenge(klassOfOop)) {
-    // save non-prototypical header, and mark oop
-    saveDisplacedHeader(mark);
-    trackOop->setDisplacedMark();
-  } else {
-    // we'd like to assert something like the following:
-    // assert(mark == markOopDesc::prototype(), "consistency check");
-    // ... but the above won't work because the age bits have not (yet) been
-    // cleared. The remainder of the check would be identical to the
-    // condition checked in must_be_preserved() above, so we don't really
-    // have anything useful to check here!
-  }
-  if (_promoTail != NULL) {
-    assert(_promoHead != NULL, "List consistency");
-    _promoTail->setNext(trackOop);
-    _promoTail = trackOop;
-  } else {
-    assert(_promoHead == NULL, "List consistency");
-    _promoHead = _promoTail = trackOop;
-  }
-  // Mask as newly promoted, so we can skip over such objects
-  // when scanning dirty cards
-  assert(!trackOop->hasPromotedMark(), "Should not have been marked");
-  trackOop->setPromotedMark();
-}
-
-// Save the given displaced header, incrementing the pointer and
-// obtaining more spool area as necessary.
-void PromotionInfo::saveDisplacedHeader(markOop hdr) {
-  assert(_spoolHead != NULL && _spoolTail != NULL,
-         "promotionInfo inconsistency");
-  assert(_spoolTail->bufferSize > _nextIndex, "Off by one error at tail?");
-  _spoolTail->displacedHdr[_nextIndex] = hdr;
-  // Spool forward
-  if (++_nextIndex == _spoolTail->bufferSize) { // last location in this block
-    // get a new spooling block
-    assert(_spoolTail->nextSpoolBlock == NULL, "tail should terminate spool list");
-    _splice_point = _spoolTail;                   // save for splicing
-    _spoolTail->nextSpoolBlock = getSpoolBlock(); // might fail
-    _spoolTail = _spoolTail->nextSpoolBlock;      // might become NULL ...
-    // ... but will attempt filling before next promotion attempt
-    _nextIndex = 1;
-  }
-}
-
-// Ensure that spooling space exists. Return false if spooling space
-// could not be obtained.
-bool PromotionInfo::ensure_spooling_space_work() {
-  assert(!has_spooling_space(), "Only call when there is no spooling space");
-  // Try and obtain more spooling space
-  SpoolBlock* newSpool = getSpoolBlock();
-  assert(newSpool == NULL ||
-         (newSpool->bufferSize != 0 && newSpool->nextSpoolBlock == NULL),
-        "getSpoolBlock() sanity check");
-  if (newSpool == NULL) {
-    return false;
-  }
-  _nextIndex = 1;
-  if (_spoolTail == NULL) {
-    _spoolTail = newSpool;
-    if (_spoolHead == NULL) {
-      _spoolHead = newSpool;
-      _firstIndex = 1;
-    } else {
-      assert(_splice_point != NULL && _splice_point->nextSpoolBlock == NULL,
-             "Splice point invariant");
-      // Extra check that _splice_point is connected to list
-      #ifdef ASSERT
-      {
-        SpoolBlock* blk = _spoolHead;
-        for (; blk->nextSpoolBlock != NULL;
-             blk = blk->nextSpoolBlock);
-        assert(blk != NULL && blk == _splice_point,
-               "Splice point incorrect");
-      }
-      #endif // ASSERT
-      _splice_point->nextSpoolBlock = newSpool;
-    }
-  } else {
-    assert(_spoolHead != NULL, "spool list consistency");
-    _spoolTail->nextSpoolBlock = newSpool;
-    _spoolTail = newSpool;
-  }
-  return true;
-}
-
-// Get a free spool buffer from the free pool, getting a new block
-// from the heap if necessary.
-SpoolBlock* PromotionInfo::getSpoolBlock() {
-  SpoolBlock* res;
-  if ((res = _spareSpool) != NULL) {
-    _spareSpool = _spareSpool->nextSpoolBlock;
-    res->nextSpoolBlock = NULL;
-  } else {  // spare spool exhausted, get some from heap
-    res = (SpoolBlock*)(space()->allocateScratch(refillSize()));
-    if (res != NULL) {
-      res->init();
-    }
-  }
-  assert(res == NULL || res->nextSpoolBlock == NULL, "postcondition");
-  return res;
-}
-
-void PromotionInfo::startTrackingPromotions() {
-  assert(_spoolHead == _spoolTail && _firstIndex == _nextIndex,
-         "spooling inconsistency?");
-  _firstIndex = _nextIndex = 1;
-  _tracking = true;
-}
-
-#define CMSPrintPromoBlockInfo 1
-
-void PromotionInfo::stopTrackingPromotions(uint worker_id) {
-  assert(_spoolHead == _spoolTail && _firstIndex == _nextIndex,
-         "spooling inconsistency?");
-  _firstIndex = _nextIndex = 1;
-  _tracking = false;
-  if (CMSPrintPromoBlockInfo > 1) {
-    print_statistics(worker_id);
-  }
-}
-
-void PromotionInfo::print_statistics(uint worker_id) const {
-  assert(_spoolHead == _spoolTail && _firstIndex == _nextIndex,
-         "Else will undercount");
-  assert(CMSPrintPromoBlockInfo > 0, "Else unnecessary call");
-  // Count the number of blocks and slots in the free pool
-  size_t slots  = 0;
-  size_t blocks = 0;
-  for (SpoolBlock* cur_spool = _spareSpool;
-       cur_spool != NULL;
-       cur_spool = cur_spool->nextSpoolBlock) {
-    // the first entry is just a self-pointer; indices 1 through
-    // bufferSize - 1 are occupied (thus, bufferSize - 1 slots).
-    guarantee((void*)cur_spool->displacedHdr == (void*)&cur_spool->displacedHdr,
-              "first entry of displacedHdr should be self-referential");
-    slots += cur_spool->bufferSize - 1;
-    blocks++;
-  }
-  if (_spoolHead != NULL) {
-    slots += _spoolHead->bufferSize - 1;
-    blocks++;
-  }
-  gclog_or_tty->print_cr(" [worker %d] promo_blocks = %d, promo_slots = %d ",
-                         worker_id, blocks, slots);
-}
-
-// When _spoolTail is not NULL, then the slot <_spoolTail, _nextIndex>
-// points to the next slot available for filling.
-// The set of slots holding displaced headers are then all those in the
-// right-open interval denoted by:
-//
-//    [ <_spoolHead, _firstIndex>, <_spoolTail, _nextIndex> )
-//
-// When _spoolTail is NULL, then the set of slots with displaced headers
-// is all those starting at the slot <_spoolHead, _firstIndex> and
-// going up to the last slot of last block in the linked list.
-// In this lartter case, _splice_point points to the tail block of
-// this linked list of blocks holding displaced headers.
-void PromotionInfo::verify() const {
-  // Verify the following:
-  // 1. the number of displaced headers matches the number of promoted
-  //    objects that have displaced headers
-  // 2. each promoted object lies in this space
-  debug_only(
-    PromotedObject* junk = NULL;
-    assert(junk->next_addr() == (void*)(oop(junk)->mark_addr()),
-           "Offset of PromotedObject::_next is expected to align with "
-           "  the OopDesc::_mark within OopDesc");
-  )
-  // FIXME: guarantee????
-  guarantee(_spoolHead == NULL || _spoolTail != NULL ||
-            _splice_point != NULL, "list consistency");
-  guarantee(_promoHead == NULL || _promoTail != NULL, "list consistency");
-  // count the number of objects with displaced headers
-  size_t numObjsWithDisplacedHdrs = 0;
-  for (PromotedObject* curObj = _promoHead; curObj != NULL; curObj = curObj->next()) {
-    guarantee(space()->is_in_reserved((HeapWord*)curObj), "Containment");
-    // the last promoted object may fail the mark() != NULL test of is_oop().
-    guarantee(curObj->next() == NULL || oop(curObj)->is_oop(), "must be an oop");
-    if (curObj->hasDisplacedMark()) {
-      numObjsWithDisplacedHdrs++;
-    }
-  }
-  // Count the number of displaced headers
-  size_t numDisplacedHdrs = 0;
-  for (SpoolBlock* curSpool = _spoolHead;
-       curSpool != _spoolTail && curSpool != NULL;
-       curSpool = curSpool->nextSpoolBlock) {
-    // the first entry is just a self-pointer; indices 1 through
-    // bufferSize - 1 are occupied (thus, bufferSize - 1 slots).
-    guarantee((void*)curSpool->displacedHdr == (void*)&curSpool->displacedHdr,
-              "first entry of displacedHdr should be self-referential");
-    numDisplacedHdrs += curSpool->bufferSize - 1;
-  }
-  guarantee((_spoolHead == _spoolTail) == (numDisplacedHdrs == 0),
-            "internal consistency");
-  guarantee(_spoolTail != NULL || _nextIndex == 1,
-            "Inconsistency between _spoolTail and _nextIndex");
-  // We overcounted (_firstIndex-1) worth of slots in block
-  // _spoolHead and we undercounted (_nextIndex-1) worth of
-  // slots in block _spoolTail. We make an appropriate
-  // adjustment by subtracting the first and adding the
-  // second:  - (_firstIndex - 1) + (_nextIndex - 1)
-  numDisplacedHdrs += (_nextIndex - _firstIndex);
-  guarantee(numDisplacedHdrs == numObjsWithDisplacedHdrs, "Displaced hdr count");
-}
-
-void PromotionInfo::print_on(outputStream* st) const {
-  SpoolBlock* curSpool = NULL;
-  size_t i = 0;
-  st->print_cr("start & end indices: [" SIZE_FORMAT ", " SIZE_FORMAT ")",
-               _firstIndex, _nextIndex);
-  for (curSpool = _spoolHead; curSpool != _spoolTail && curSpool != NULL;
-       curSpool = curSpool->nextSpoolBlock) {
-    curSpool->print_on(st);
-    st->print_cr(" active ");
-    i++;
-  }
-  for (curSpool = _spoolTail; curSpool != NULL;
-       curSpool = curSpool->nextSpoolBlock) {
-    curSpool->print_on(st);
-    st->print_cr(" inactive ");
-    i++;
-  }
-  for (curSpool = _spareSpool; curSpool != NULL;
-       curSpool = curSpool->nextSpoolBlock) {
-    curSpool->print_on(st);
-    st->print_cr(" free ");
-    i++;
-  }
-  st->print_cr(SIZE_FORMAT " header spooling blocks", i);
-}
-
-void SpoolBlock::print_on(outputStream* st) const {
-  st->print("[" PTR_FORMAT "," PTR_FORMAT "), " SIZE_FORMAT " HeapWords -> " PTR_FORMAT,
-            this, (HeapWord*)displacedHdr + bufferSize,
-            bufferSize, nextSpoolBlock);
-}
-
 ///////////////////////////////////////////////////////////////////////////
 // CFLS_LAB
 ///////////////////////////////////////////////////////////////////////////
diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp
index d937de86156..933d62c70ff 100644
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp
@@ -33,140 +33,6 @@ class UpwardsObjectClosure;
 class ObjectClosureCareful;
 class Klass;
 
-class PromotedObject VALUE_OBJ_CLASS_SPEC {
- private:
-  enum {
-    promoted_mask  = right_n_bits(2),   // i.e. 0x3
-    displaced_mark = nth_bit(2),        // i.e. 0x4
-    next_mask      = ~(right_n_bits(3)) // i.e. ~(0x7)
-  };
-  intptr_t _next;
- public:
-  inline PromotedObject* next() const {
-    return (PromotedObject*)(_next & next_mask);
-  }
-  inline void setNext(PromotedObject* x) {
-    assert(((intptr_t)x & ~next_mask) == 0,
-           "Conflict in bit usage, "
-           " or insufficient alignment of objects");
-    _next |= (intptr_t)x;
-  }
-  inline void setPromotedMark() {
-    _next |= promoted_mask;
-  }
-  inline bool hasPromotedMark() const {
-    return (_next & promoted_mask) == promoted_mask;
-  }
-  inline void setDisplacedMark() {
-    _next |= displaced_mark;
-  }
-  inline bool hasDisplacedMark() const {
-    return (_next & displaced_mark) != 0;
-  }
-  inline void clearNext()        { _next = 0; }
-  debug_only(void *next_addr() { return (void *) &_next; })
-};
-
-class SpoolBlock: public FreeChunk {
-  friend class PromotionInfo;
- protected:
-  SpoolBlock*  nextSpoolBlock;
-  size_t       bufferSize;        // number of usable words in this block
-  markOop*     displacedHdr;      // the displaced headers start here
-
-  // Note about bufferSize: it denotes the number of entries available plus 1;
-  // legal indices range from 1 through BufferSize - 1.  See the verification
-  // code verify() that counts the number of displaced headers spooled.
-  size_t computeBufferSize() {
-    return (size() * sizeof(HeapWord) - sizeof(*this)) / sizeof(markOop);
-  }
-
- public:
-  void init() {
-    bufferSize = computeBufferSize();
-    displacedHdr = (markOop*)&displacedHdr;
-    nextSpoolBlock = NULL;
-  }
-
-  void print_on(outputStream* st) const;
-  void print() const { print_on(gclog_or_tty); }
-};
-
-class PromotionInfo VALUE_OBJ_CLASS_SPEC {
-  bool            _tracking;      // set if tracking
-  CompactibleFreeListSpace* _space; // the space to which this belongs
-  PromotedObject* _promoHead;     // head of list of promoted objects
-  PromotedObject* _promoTail;     // tail of list of promoted objects
-  SpoolBlock*     _spoolHead;     // first spooling block
-  SpoolBlock*     _spoolTail;     // last  non-full spooling block or null
-  SpoolBlock*     _splice_point;  // when _spoolTail is null, holds list tail
-  SpoolBlock*     _spareSpool;    // free spool buffer
-  size_t          _firstIndex;    // first active index in
-                                  // first spooling block (_spoolHead)
-  size_t          _nextIndex;     // last active index + 1 in last
-                                  // spooling block (_spoolTail)
- private:
-  // ensure that spooling space exists; return true if there is spooling space
-  bool ensure_spooling_space_work();
-
- public:
-  PromotionInfo() :
-    _tracking(0), _space(NULL),
-    _promoHead(NULL), _promoTail(NULL),
-    _spoolHead(NULL), _spoolTail(NULL),
-    _spareSpool(NULL), _firstIndex(1),
-    _nextIndex(1) {}
-
-  bool noPromotions() const {
-    assert(_promoHead != NULL || _promoTail == NULL, "list inconsistency");
-    return _promoHead == NULL;
-  }
-  void startTrackingPromotions();
-  void stopTrackingPromotions(uint worker_id = 0);
-  bool tracking() const          { return _tracking;  }
-  void track(PromotedObject* trackOop);      // keep track of a promoted oop
-  // The following variant must be used when trackOop is not fully
-  // initialized and has a NULL klass:
-  void track(PromotedObject* trackOop, klassOop klassOfOop); // keep track of a promoted oop
-  void setSpace(CompactibleFreeListSpace* sp) { _space = sp; }
-  CompactibleFreeListSpace* space() const     { return _space; }
-  markOop nextDisplacedHeader(); // get next header & forward spool pointer
-  void    saveDisplacedHeader(markOop hdr);
-                                 // save header and forward spool
-
-  inline size_t refillSize() const;
-
-  SpoolBlock* getSpoolBlock();   // return a free spooling block
-  inline bool has_spooling_space() {
-    return _spoolTail != NULL && _spoolTail->bufferSize > _nextIndex;
-  }
-  // ensure that spooling space exists
-  bool ensure_spooling_space() {
-    return has_spooling_space() || ensure_spooling_space_work();
-  }
-  #define PROMOTED_OOPS_ITERATE_DECL(OopClosureType, nv_suffix)  \
-    void promoted_oops_iterate##nv_suffix(OopClosureType* cl);
-  ALL_SINCE_SAVE_MARKS_CLOSURES(PROMOTED_OOPS_ITERATE_DECL)
-  #undef PROMOTED_OOPS_ITERATE_DECL
-  void promoted_oops_iterate(OopsInGenClosure* cl) {
-    promoted_oops_iterate_v(cl);
-  }
-  void verify()  const;
-  void reset() {
-    _promoHead = NULL;
-    _promoTail = NULL;
-    _spoolHead = NULL;
-    _spoolTail = NULL;
-    _spareSpool = NULL;
-    _firstIndex = 0;
-    _nextIndex = 0;
-
-  }
-
-  void print_on(outputStream* st) const;
-  void print_statistics(uint worker_id) const;
-};
-
 class LinearAllocBlock VALUE_OBJ_CLASS_SPEC {
  public:
   LinearAllocBlock() : _ptr(0), _word_size(0), _refillSize(0),
@@ -557,6 +423,12 @@ class CompactibleFreeListSpace: public CompactibleSpace {
   // promoted since the most recent call to save_marks() on
   // this generation and has not subsequently been iterated
   // over (using oop_since_save_marks_iterate() above).
+  // This property holds only for single-threaded collections,
+  // and is typically used for Cheney scans; for MT scavenges,
+  // the property holds for all objects promoted during that
+  // scavenge for the duration of the scavenge and is used
+  // by card-scanning to avoid scanning objects (being) promoted
+  // during that scavenge.
   bool obj_allocated_since_save_marks(const oop obj) const {
     assert(is_in_reserved(obj), "Wrong space?");
     return ((PromotedObject*)obj)->hasPromotedMark();
diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp
index a7d284fad66..932559115f6 100644
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp
@@ -1364,7 +1364,7 @@ ConcurrentMarkSweepGeneration::par_promote(int thread_num,
   obj->set_mark(m);
 
   // Now we can track the promoted object, if necessary.  We take care
-  // To delay the transition from uninitialized to full object
+  // to delay the transition from uninitialized to full object
   // (i.e., insertion of klass pointer) until after, so that it
   // atomically becomes a promoted object.
   if (promoInfo->tracking()) {
diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/promotionInfo.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/promotionInfo.cpp
new file mode 100644
index 00000000000..aed28a229f6
--- /dev/null
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/promotionInfo.cpp
@@ -0,0 +1,360 @@
+/*
+ * Copyright 2001-2009 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
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+# include "incls/_precompiled.incl"
+# include "incls/_promotionInfo.cpp.incl"
+
+/////////////////////////////////////////////////////////////////////////
+//// PromotionInfo
+/////////////////////////////////////////////////////////////////////////
+
+
+//////////////////////////////////////////////////////////////////////////////
+// We go over the list of promoted objects, removing each from the list,
+// and applying the closure (this may, in turn, add more elements to
+// the tail of the promoted list, and these newly added objects will
+// also be processed) until the list is empty.
+// To aid verification and debugging, in the non-product builds
+// we actually forward _promoHead each time we process a promoted oop.
+// Note that this is not necessary in general (i.e. when we don't need to
+// call PromotionInfo::verify()) because oop_iterate can only add to the
+// end of _promoTail, and never needs to look at _promoHead.
+
+#define PROMOTED_OOPS_ITERATE_DEFN(OopClosureType, nv_suffix)               \
+                                                                            \
+void PromotionInfo::promoted_oops_iterate##nv_suffix(OopClosureType* cl) {  \
+  NOT_PRODUCT(verify());                                                    \
+  PromotedObject *curObj, *nextObj;                                         \
+  for (curObj = _promoHead; curObj != NULL; curObj = nextObj) {             \
+    if ((nextObj = curObj->next()) == NULL) {                               \
+      /* protect ourselves against additions due to closure application     \
+         below by resetting the list.  */                                   \
+      assert(_promoTail == curObj, "Should have been the tail");            \
+      _promoHead = _promoTail = NULL;                                       \
+    }                                                                       \
+    if (curObj->hasDisplacedMark()) {                                       \
+      /* restore displaced header */                                        \
+      oop(curObj)->set_mark(nextDisplacedHeader());                         \
+    } else {                                                                \
+      /* restore prototypical header */                                     \
+      oop(curObj)->init_mark();                                             \
+    }                                                                       \
+    /* The "promoted_mark" should now not be set */                         \
+    assert(!curObj->hasPromotedMark(),                                      \
+           "Should have been cleared by restoring displaced mark-word");    \
+    NOT_PRODUCT(_promoHead = nextObj);                                      \
+    if (cl != NULL) oop(curObj)->oop_iterate(cl);                           \
+    if (nextObj == NULL) { /* start at head of list reset above */          \
+      nextObj = _promoHead;                                                 \
+    }                                                                       \
+  }                                                                         \
+  assert(noPromotions(), "post-condition violation");                       \
+  assert(_promoHead == NULL && _promoTail == NULL, "emptied promoted list");\
+  assert(_spoolHead == _spoolTail, "emptied spooling buffers");             \
+  assert(_firstIndex == _nextIndex, "empty buffer");                        \
+}
+
+// This should have been ALL_SINCE_...() just like the others,
+// but, because the body of the method above is somehwat longer,
+// the MSVC compiler cannot cope; as a workaround, we split the
+// macro into its 3 constituent parts below (see original macro
+// definition in specializedOopClosures.hpp).
+SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG(PROMOTED_OOPS_ITERATE_DEFN)
+PROMOTED_OOPS_ITERATE_DEFN(OopsInGenClosure,_v)
+
+
+// Return the next displaced header, incrementing the pointer and
+// recycling spool area as necessary.
+markOop PromotionInfo::nextDisplacedHeader() {
+  assert(_spoolHead != NULL, "promotionInfo inconsistency");
+  assert(_spoolHead != _spoolTail || _firstIndex < _nextIndex,
+         "Empty spool space: no displaced header can be fetched");
+  assert(_spoolHead->bufferSize > _firstIndex, "Off by one error at head?");
+  markOop hdr = _spoolHead->displacedHdr[_firstIndex];
+  // Spool forward
+  if (++_firstIndex == _spoolHead->bufferSize) { // last location in this block
+    // forward to next block, recycling this block into spare spool buffer
+    SpoolBlock* tmp = _spoolHead->nextSpoolBlock;
+    assert(_spoolHead != _spoolTail, "Spooling storage mix-up");
+    _spoolHead->nextSpoolBlock = _spareSpool;
+    _spareSpool = _spoolHead;
+    _spoolHead = tmp;
+    _firstIndex = 1;
+    NOT_PRODUCT(
+      if (_spoolHead == NULL) {  // all buffers fully consumed
+        assert(_spoolTail == NULL && _nextIndex == 1,
+               "spool buffers processing inconsistency");
+      }
+    )
+  }
+  return hdr;
+}
+
+void PromotionInfo::track(PromotedObject* trackOop) {
+  track(trackOop, oop(trackOop)->klass());
+}
+
+void PromotionInfo::track(PromotedObject* trackOop, klassOop klassOfOop) {
+  // make a copy of header as it may need to be spooled
+  markOop mark = oop(trackOop)->mark();
+  trackOop->clearNext();
+  if (mark->must_be_preserved_for_cms_scavenge(klassOfOop)) {
+    // save non-prototypical header, and mark oop
+    saveDisplacedHeader(mark);
+    trackOop->setDisplacedMark();
+  } else {
+    // we'd like to assert something like the following:
+    // assert(mark == markOopDesc::prototype(), "consistency check");
+    // ... but the above won't work because the age bits have not (yet) been
+    // cleared. The remainder of the check would be identical to the
+    // condition checked in must_be_preserved() above, so we don't really
+    // have anything useful to check here!
+  }
+  if (_promoTail != NULL) {
+    assert(_promoHead != NULL, "List consistency");
+    _promoTail->setNext(trackOop);
+    _promoTail = trackOop;
+  } else {
+    assert(_promoHead == NULL, "List consistency");
+    _promoHead = _promoTail = trackOop;
+  }
+  // Mask as newly promoted, so we can skip over such objects
+  // when scanning dirty cards
+  assert(!trackOop->hasPromotedMark(), "Should not have been marked");
+  trackOop->setPromotedMark();
+}
+
+// Save the given displaced header, incrementing the pointer and
+// obtaining more spool area as necessary.
+void PromotionInfo::saveDisplacedHeader(markOop hdr) {
+  assert(_spoolHead != NULL && _spoolTail != NULL,
+         "promotionInfo inconsistency");
+  assert(_spoolTail->bufferSize > _nextIndex, "Off by one error at tail?");
+  _spoolTail->displacedHdr[_nextIndex] = hdr;
+  // Spool forward
+  if (++_nextIndex == _spoolTail->bufferSize) { // last location in this block
+    // get a new spooling block
+    assert(_spoolTail->nextSpoolBlock == NULL, "tail should terminate spool list");
+    _splice_point = _spoolTail;                   // save for splicing
+    _spoolTail->nextSpoolBlock = getSpoolBlock(); // might fail
+    _spoolTail = _spoolTail->nextSpoolBlock;      // might become NULL ...
+    // ... but will attempt filling before next promotion attempt
+    _nextIndex = 1;
+  }
+}
+
+// Ensure that spooling space exists. Return false if spooling space
+// could not be obtained.
+bool PromotionInfo::ensure_spooling_space_work() {
+  assert(!has_spooling_space(), "Only call when there is no spooling space");
+  // Try and obtain more spooling space
+  SpoolBlock* newSpool = getSpoolBlock();
+  assert(newSpool == NULL ||
+         (newSpool->bufferSize != 0 && newSpool->nextSpoolBlock == NULL),
+        "getSpoolBlock() sanity check");
+  if (newSpool == NULL) {
+    return false;
+  }
+  _nextIndex = 1;
+  if (_spoolTail == NULL) {
+    _spoolTail = newSpool;
+    if (_spoolHead == NULL) {
+      _spoolHead = newSpool;
+      _firstIndex = 1;
+    } else {
+      assert(_splice_point != NULL && _splice_point->nextSpoolBlock == NULL,
+             "Splice point invariant");
+      // Extra check that _splice_point is connected to list
+      #ifdef ASSERT
+      {
+        SpoolBlock* blk = _spoolHead;
+        for (; blk->nextSpoolBlock != NULL;
+             blk = blk->nextSpoolBlock);
+        assert(blk != NULL && blk == _splice_point,
+               "Splice point incorrect");
+      }
+      #endif // ASSERT
+      _splice_point->nextSpoolBlock = newSpool;
+    }
+  } else {
+    assert(_spoolHead != NULL, "spool list consistency");
+    _spoolTail->nextSpoolBlock = newSpool;
+    _spoolTail = newSpool;
+  }
+  return true;
+}
+
+// Get a free spool buffer from the free pool, getting a new block
+// from the heap if necessary.
+SpoolBlock* PromotionInfo::getSpoolBlock() {
+  SpoolBlock* res;
+  if ((res = _spareSpool) != NULL) {
+    _spareSpool = _spareSpool->nextSpoolBlock;
+    res->nextSpoolBlock = NULL;
+  } else {  // spare spool exhausted, get some from heap
+    res = (SpoolBlock*)(space()->allocateScratch(refillSize()));
+    if (res != NULL) {
+      res->init();
+    }
+  }
+  assert(res == NULL || res->nextSpoolBlock == NULL, "postcondition");
+  return res;
+}
+
+void PromotionInfo::startTrackingPromotions() {
+  assert(_spoolHead == _spoolTail && _firstIndex == _nextIndex,
+         "spooling inconsistency?");
+  _firstIndex = _nextIndex = 1;
+  _tracking = true;
+}
+
+#define CMSPrintPromoBlockInfo 1
+
+void PromotionInfo::stopTrackingPromotions(uint worker_id) {
+  assert(_spoolHead == _spoolTail && _firstIndex == _nextIndex,
+         "spooling inconsistency?");
+  _firstIndex = _nextIndex = 1;
+  _tracking = false;
+  if (CMSPrintPromoBlockInfo > 1) {
+    print_statistics(worker_id);
+  }
+}
+
+void PromotionInfo::print_statistics(uint worker_id) const {
+  assert(_spoolHead == _spoolTail && _firstIndex == _nextIndex,
+         "Else will undercount");
+  assert(CMSPrintPromoBlockInfo > 0, "Else unnecessary call");
+  // Count the number of blocks and slots in the free pool
+  size_t slots  = 0;
+  size_t blocks = 0;
+  for (SpoolBlock* cur_spool = _spareSpool;
+       cur_spool != NULL;
+       cur_spool = cur_spool->nextSpoolBlock) {
+    // the first entry is just a self-pointer; indices 1 through
+    // bufferSize - 1 are occupied (thus, bufferSize - 1 slots).
+    guarantee((void*)cur_spool->displacedHdr == (void*)&cur_spool->displacedHdr,
+              "first entry of displacedHdr should be self-referential");
+    slots += cur_spool->bufferSize - 1;
+    blocks++;
+  }
+  if (_spoolHead != NULL) {
+    slots += _spoolHead->bufferSize - 1;
+    blocks++;
+  }
+  gclog_or_tty->print_cr(" [worker %d] promo_blocks = %d, promo_slots = %d ",
+                         worker_id, blocks, slots);
+}
+
+// When _spoolTail is not NULL, then the slot <_spoolTail, _nextIndex>
+// points to the next slot available for filling.
+// The set of slots holding displaced headers are then all those in the
+// right-open interval denoted by:
+//
+//    [ <_spoolHead, _firstIndex>, <_spoolTail, _nextIndex> )
+//
+// When _spoolTail is NULL, then the set of slots with displaced headers
+// is all those starting at the slot <_spoolHead, _firstIndex> and
+// going up to the last slot of last block in the linked list.
+// In this lartter case, _splice_point points to the tail block of
+// this linked list of blocks holding displaced headers.
+void PromotionInfo::verify() const {
+  // Verify the following:
+  // 1. the number of displaced headers matches the number of promoted
+  //    objects that have displaced headers
+  // 2. each promoted object lies in this space
+  debug_only(
+    PromotedObject* junk = NULL;
+    assert(junk->next_addr() == (void*)(oop(junk)->mark_addr()),
+           "Offset of PromotedObject::_next is expected to align with "
+           "  the OopDesc::_mark within OopDesc");
+  )
+  // FIXME: guarantee????
+  guarantee(_spoolHead == NULL || _spoolTail != NULL ||
+            _splice_point != NULL, "list consistency");
+  guarantee(_promoHead == NULL || _promoTail != NULL, "list consistency");
+  // count the number of objects with displaced headers
+  size_t numObjsWithDisplacedHdrs = 0;
+  for (PromotedObject* curObj = _promoHead; curObj != NULL; curObj = curObj->next()) {
+    guarantee(space()->is_in_reserved((HeapWord*)curObj), "Containment");
+    // the last promoted object may fail the mark() != NULL test of is_oop().
+    guarantee(curObj->next() == NULL || oop(curObj)->is_oop(), "must be an oop");
+    if (curObj->hasDisplacedMark()) {
+      numObjsWithDisplacedHdrs++;
+    }
+  }
+  // Count the number of displaced headers
+  size_t numDisplacedHdrs = 0;
+  for (SpoolBlock* curSpool = _spoolHead;
+       curSpool != _spoolTail && curSpool != NULL;
+       curSpool = curSpool->nextSpoolBlock) {
+    // the first entry is just a self-pointer; indices 1 through
+    // bufferSize - 1 are occupied (thus, bufferSize - 1 slots).
+    guarantee((void*)curSpool->displacedHdr == (void*)&curSpool->displacedHdr,
+              "first entry of displacedHdr should be self-referential");
+    numDisplacedHdrs += curSpool->bufferSize - 1;
+  }
+  guarantee((_spoolHead == _spoolTail) == (numDisplacedHdrs == 0),
+            "internal consistency");
+  guarantee(_spoolTail != NULL || _nextIndex == 1,
+            "Inconsistency between _spoolTail and _nextIndex");
+  // We overcounted (_firstIndex-1) worth of slots in block
+  // _spoolHead and we undercounted (_nextIndex-1) worth of
+  // slots in block _spoolTail. We make an appropriate
+  // adjustment by subtracting the first and adding the
+  // second:  - (_firstIndex - 1) + (_nextIndex - 1)
+  numDisplacedHdrs += (_nextIndex - _firstIndex);
+  guarantee(numDisplacedHdrs == numObjsWithDisplacedHdrs, "Displaced hdr count");
+}
+
+void PromotionInfo::print_on(outputStream* st) const {
+  SpoolBlock* curSpool = NULL;
+  size_t i = 0;
+  st->print_cr("start & end indices: [" SIZE_FORMAT ", " SIZE_FORMAT ")",
+               _firstIndex, _nextIndex);
+  for (curSpool = _spoolHead; curSpool != _spoolTail && curSpool != NULL;
+       curSpool = curSpool->nextSpoolBlock) {
+    curSpool->print_on(st);
+    st->print_cr(" active ");
+    i++;
+  }
+  for (curSpool = _spoolTail; curSpool != NULL;
+       curSpool = curSpool->nextSpoolBlock) {
+    curSpool->print_on(st);
+    st->print_cr(" inactive ");
+    i++;
+  }
+  for (curSpool = _spareSpool; curSpool != NULL;
+       curSpool = curSpool->nextSpoolBlock) {
+    curSpool->print_on(st);
+    st->print_cr(" free ");
+    i++;
+  }
+  st->print_cr(SIZE_FORMAT " header spooling blocks", i);
+}
+
+void SpoolBlock::print_on(outputStream* st) const {
+  st->print("[" PTR_FORMAT "," PTR_FORMAT "), " SIZE_FORMAT " HeapWords -> " PTR_FORMAT,
+            this, (HeapWord*)displacedHdr + bufferSize,
+            bufferSize, nextSpoolBlock);
+}
diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/promotionInfo.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/promotionInfo.hpp
new file mode 100644
index 00000000000..d49e307ea97
--- /dev/null
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/promotionInfo.hpp
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2001-2009 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
+ * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+// Forward declarations
+class CompactibleFreeListSpace;
+
+class PromotedObject VALUE_OBJ_CLASS_SPEC {
+ private:
+  enum {
+    promoted_mask  = right_n_bits(2),   // i.e. 0x3
+    displaced_mark = nth_bit(2),        // i.e. 0x4
+    next_mask      = ~(right_n_bits(3)) // i.e. ~(0x7)
+  };
+  intptr_t _next;
+ public:
+  inline PromotedObject* next() const {
+    return (PromotedObject*)(_next & next_mask);
+  }
+  inline void setNext(PromotedObject* x) {
+    assert(((intptr_t)x & ~next_mask) == 0,
+           "Conflict in bit usage, "
+           " or insufficient alignment of objects");
+    _next |= (intptr_t)x;
+  }
+  inline void setPromotedMark() {
+    _next |= promoted_mask;
+  }
+  inline bool hasPromotedMark() const {
+    return (_next & promoted_mask) == promoted_mask;
+  }
+  inline void setDisplacedMark() {
+    _next |= displaced_mark;
+  }
+  inline bool hasDisplacedMark() const {
+    return (_next & displaced_mark) != 0;
+  }
+  inline void clearNext()        { _next = 0; }
+  debug_only(void *next_addr() { return (void *) &_next; })
+};
+
+class SpoolBlock: public FreeChunk {
+  friend class PromotionInfo;
+ protected:
+  SpoolBlock*  nextSpoolBlock;
+  size_t       bufferSize;        // number of usable words in this block
+  markOop*     displacedHdr;      // the displaced headers start here
+
+  // Note about bufferSize: it denotes the number of entries available plus 1;
+  // legal indices range from 1 through BufferSize - 1.  See the verification
+  // code verify() that counts the number of displaced headers spooled.
+  size_t computeBufferSize() {
+    return (size() * sizeof(HeapWord) - sizeof(*this)) / sizeof(markOop);
+  }
+
+ public:
+  void init() {
+    bufferSize = computeBufferSize();
+    displacedHdr = (markOop*)&displacedHdr;
+    nextSpoolBlock = NULL;
+  }
+
+  void print_on(outputStream* st) const;
+  void print() const { print_on(gclog_or_tty); }
+};
+
+class PromotionInfo VALUE_OBJ_CLASS_SPEC {
+  bool            _tracking;      // set if tracking
+  CompactibleFreeListSpace* _space; // the space to which this belongs
+  PromotedObject* _promoHead;     // head of list of promoted objects
+  PromotedObject* _promoTail;     // tail of list of promoted objects
+  SpoolBlock*     _spoolHead;     // first spooling block
+  SpoolBlock*     _spoolTail;     // last  non-full spooling block or null
+  SpoolBlock*     _splice_point;  // when _spoolTail is null, holds list tail
+  SpoolBlock*     _spareSpool;    // free spool buffer
+  size_t          _firstIndex;    // first active index in
+                                  // first spooling block (_spoolHead)
+  size_t          _nextIndex;     // last active index + 1 in last
+                                  // spooling block (_spoolTail)
+ private:
+  // ensure that spooling space exists; return true if there is spooling space
+  bool ensure_spooling_space_work();
+
+ public:
+  PromotionInfo() :
+    _tracking(0), _space(NULL),
+    _promoHead(NULL), _promoTail(NULL),
+    _spoolHead(NULL), _spoolTail(NULL),
+    _spareSpool(NULL), _firstIndex(1),
+    _nextIndex(1) {}
+
+  bool noPromotions() const {
+    assert(_promoHead != NULL || _promoTail == NULL, "list inconsistency");
+    return _promoHead == NULL;
+  }
+  void startTrackingPromotions();
+  void stopTrackingPromotions(uint worker_id = 0);
+  bool tracking() const          { return _tracking;  }
+  void track(PromotedObject* trackOop);      // keep track of a promoted oop
+  // The following variant must be used when trackOop is not fully
+  // initialized and has a NULL klass:
+  void track(PromotedObject* trackOop, klassOop klassOfOop); // keep track of a promoted oop
+  void setSpace(CompactibleFreeListSpace* sp) { _space = sp; }
+  CompactibleFreeListSpace* space() const     { return _space; }
+  markOop nextDisplacedHeader(); // get next header & forward spool pointer
+  void    saveDisplacedHeader(markOop hdr);
+                                 // save header and forward spool
+
+  inline size_t refillSize() const;
+
+  SpoolBlock* getSpoolBlock();   // return a free spooling block
+  inline bool has_spooling_space() {
+    return _spoolTail != NULL && _spoolTail->bufferSize > _nextIndex;
+  }
+  // ensure that spooling space exists
+  bool ensure_spooling_space() {
+    return has_spooling_space() || ensure_spooling_space_work();
+  }
+  #define PROMOTED_OOPS_ITERATE_DECL(OopClosureType, nv_suffix)  \
+    void promoted_oops_iterate##nv_suffix(OopClosureType* cl);
+  ALL_SINCE_SAVE_MARKS_CLOSURES(PROMOTED_OOPS_ITERATE_DECL)
+  #undef PROMOTED_OOPS_ITERATE_DECL
+  void promoted_oops_iterate(OopsInGenClosure* cl) {
+    promoted_oops_iterate_v(cl);
+  }
+  void verify()  const;
+  void reset() {
+    _promoHead = NULL;
+    _promoTail = NULL;
+    _spoolHead = NULL;
+    _spoolTail = NULL;
+    _spareSpool = NULL;
+    _firstIndex = 0;
+    _nextIndex = 0;
+
+  }
+
+  void print_on(outputStream* st) const;
+  void print_statistics(uint worker_id) const;
+};
+
diff --git a/hotspot/src/share/vm/gc_implementation/includeDB_gc_concurrentMarkSweep b/hotspot/src/share/vm/gc_implementation/includeDB_gc_concurrentMarkSweep
index c5a7a386b60..9dd05b3a895 100644
--- a/hotspot/src/share/vm/gc_implementation/includeDB_gc_concurrentMarkSweep
+++ b/hotspot/src/share/vm/gc_implementation/includeDB_gc_concurrentMarkSweep
@@ -122,6 +122,7 @@ compactibleFreeListSpace.cpp            vmThread.hpp
 
 compactibleFreeListSpace.hpp            binaryTreeDictionary.hpp
 compactibleFreeListSpace.hpp            freeList.hpp
+compactibleFreeListSpace.hpp            promotionInfo.hpp
 compactibleFreeListSpace.hpp            space.hpp
 
 compactingPermGenGen.cpp                concurrentMarkSweepGeneration.inline.hpp
@@ -225,6 +226,14 @@ freeList.cpp                            vmThread.hpp
 
 freeList.hpp                            allocationStats.hpp
 
+promotionInfo.cpp                       compactibleFreeListSpace.hpp
+promotionInfo.cpp                       markOop.inline.hpp
+promotionInfo.cpp                       oop.inline.hpp
+promotionInfo.cpp                       promotionInfo.hpp
+
+promotionInfo.hpp                       allocation.hpp
+promotionInfo.hpp                       freeChunk.hpp
+
 vmCMSOperations.cpp			concurrentMarkSweepGeneration.inline.hpp
 vmCMSOperations.cpp			concurrentMarkSweepThread.hpp
 vmCMSOperations.cpp			dtrace.hpp

From 8afbd9a53e8f3f9f71356871b9743c68bd5eea7d Mon Sep 17 00:00:00 2001
From: Tom Rodriguez 
Date: Mon, 10 May 2010 14:58:38 -0700
Subject: [PATCH 44/54] 6951190: assert(!klass_is_exact(),"only non-exact
 klass") while building JDK

Reviewed-by: kvn
---
 hotspot/src/share/vm/opto/library_call.cpp | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp
index eaa2a06ebb4..709e31ab878 100644
--- a/hotspot/src/share/vm/opto/library_call.cpp
+++ b/hotspot/src/share/vm/opto/library_call.cpp
@@ -809,8 +809,7 @@ Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1, Node* cnt1
   Node* no_ctrl = NULL;
 
   ciInstanceKlass* klass = env()->String_klass();
-  const TypeInstPtr* string_type =
-        TypeInstPtr::make(TypePtr::BotPTR, klass, false, NULL, 0);
+  const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass);
 
   const TypeAryPtr* value_type =
         TypeAryPtr::make(TypePtr::NotNull,
@@ -883,8 +882,7 @@ bool LibraryCallKit::inline_string_compareTo() {
   }
 
   ciInstanceKlass* klass = env()->String_klass();
-  const TypeInstPtr* string_type =
-    TypeInstPtr::make(TypePtr::BotPTR, klass, false, NULL, 0);
+  const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass);
   Node* no_ctrl = NULL;
 
   // Get counts for string and argument
@@ -958,14 +956,16 @@ bool LibraryCallKit::inline_string_equals() {
     }
   }
 
-  const TypeInstPtr* string_type =
-    TypeInstPtr::make(TypePtr::BotPTR, klass, false, NULL, 0);
+  const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass);
 
   Node* no_ctrl = NULL;
   Node* receiver_cnt;
   Node* argument_cnt;
 
   if (!stopped()) {
+    // Properly cast the argument to String
+    argument = _gvn.transform(new (C, 2) CheckCastPPNode(control(), argument, string_type));
+
     // Get counts for string and argument
     Node* receiver_cnta = basic_plus_adr(receiver, receiver, count_offset);
     receiver_cnt  = make_load(no_ctrl, receiver_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
@@ -1090,7 +1090,7 @@ Node* LibraryCallKit::string_indexOf(Node* string_object, ciTypeArray* target_ar
   const int offset_offset = java_lang_String::offset_offset_in_bytes();
 
   ciInstanceKlass* klass = env()->String_klass();
-  const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::BotPTR, klass, false, NULL, 0);
+  const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass);
   const TypeAryPtr*  source_type = TypeAryPtr::make(TypePtr::NotNull, TypeAry::make(TypeInt::CHAR,TypeInt::POS), ciTypeArrayKlass::make(T_CHAR), true, 0);
 
   Node* sourceOffseta = basic_plus_adr(string_object, string_object, offset_offset);
@@ -1199,8 +1199,7 @@ bool LibraryCallKit::inline_string_indexOf() {
     Node* no_ctrl  = NULL;
 
     ciInstanceKlass* klass = env()->String_klass();
-    const TypeInstPtr* string_type =
-      TypeInstPtr::make(TypePtr::BotPTR, klass, false, NULL, 0);
+    const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass);
 
     // Get counts for string and substr
     Node* source_cnta = basic_plus_adr(receiver, receiver, count_offset);

From b8491bb9fedf0953277aa6aefea97fca24a6fc32 Mon Sep 17 00:00:00 2001
From: Gary Benson 
Date: Wed, 12 May 2010 03:49:52 -0700
Subject: [PATCH 45/54] 6951784: Zero deoptimizer changes

The way Zero currently handles deoptimization can lead to methods being freed while they are still being executed.

Reviewed-by: twisti
---
 .../src/cpu/zero/vm/cppInterpreter_zero.cpp   | 38 +++++++++++--------
 .../src/cpu/zero/vm/cppInterpreter_zero.hpp   |  8 ++--
 hotspot/src/cpu/zero/vm/entry_zero.hpp        | 30 ++++++++++-----
 3 files changed, 47 insertions(+), 29 deletions(-)

diff --git a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp
index 3d6748e4935..325502ea200 100644
--- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp
+++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp
@@ -37,15 +37,18 @@
   thread->reset_last_Java_frame();              \
   fixup_after_potential_safepoint()
 
-void CppInterpreter::normal_entry(methodOop method, intptr_t UNUSED, TRAPS) {
+int CppInterpreter::normal_entry(methodOop method, intptr_t UNUSED, TRAPS) {
   JavaThread *thread = (JavaThread *) THREAD;
 
   // Allocate and initialize our frame.
-  InterpreterFrame *frame = InterpreterFrame::build(method, CHECK);
+  InterpreterFrame *frame = InterpreterFrame::build(method, CHECK_0);
   thread->push_zero_frame(frame);
 
   // Execute those bytecodes!
   main_loop(0, THREAD);
+
+  // No deoptimized frames on the stack
+  return 0;
 }
 
 void CppInterpreter::main_loop(int recurse, TRAPS) {
@@ -165,7 +168,7 @@ void CppInterpreter::main_loop(int recurse, TRAPS) {
     stack->push(result[-i]);
 }
 
-void CppInterpreter::native_entry(methodOop method, intptr_t UNUSED, TRAPS) {
+int CppInterpreter::native_entry(methodOop method, intptr_t UNUSED, TRAPS) {
   // Make sure method is native and not abstract
   assert(method->is_native() && !method->is_abstract(), "should be");
 
@@ -173,7 +176,7 @@ void CppInterpreter::native_entry(methodOop method, intptr_t UNUSED, TRAPS) {
   ZeroStack *stack = thread->zero_stack();
 
   // Allocate and initialize our frame
-  InterpreterFrame *frame = InterpreterFrame::build(method, CHECK);
+  InterpreterFrame *frame = InterpreterFrame::build(method, CHECK_0);
   thread->push_zero_frame(frame);
   interpreterState istate = frame->interpreter_state();
   intptr_t *locals = istate->locals();
@@ -430,25 +433,26 @@ void CppInterpreter::native_entry(methodOop method, intptr_t UNUSED, TRAPS) {
       ShouldNotReachHere();
     }
   }
+
+  // No deoptimized frames on the stack
+  return 0;
 }
 
-void CppInterpreter::accessor_entry(methodOop method, intptr_t UNUSED, TRAPS) {
+int CppInterpreter::accessor_entry(methodOop method, intptr_t UNUSED, TRAPS) {
   JavaThread *thread = (JavaThread *) THREAD;
   ZeroStack *stack = thread->zero_stack();
   intptr_t *locals = stack->sp();
 
   // Drop into the slow path if we need a safepoint check
   if (SafepointSynchronize::do_call_back()) {
-    normal_entry(method, 0, THREAD);
-    return;
+    return normal_entry(method, 0, THREAD);
   }
 
   // Load the object pointer and drop into the slow path
   // if we have a NullPointerException
   oop object = LOCALS_OBJECT(0);
   if (object == NULL) {
-    normal_entry(method, 0, THREAD);
-    return;
+    return normal_entry(method, 0, THREAD);
   }
 
   // Read the field index from the bytecode, which looks like this:
@@ -470,15 +474,14 @@ void CppInterpreter::accessor_entry(methodOop method, intptr_t UNUSED, TRAPS) {
   constantPoolCacheOop cache = method->constants()->cache();
   ConstantPoolCacheEntry* entry = cache->entry_at(index);
   if (!entry->is_resolved(Bytecodes::_getfield)) {
-    normal_entry(method, 0, THREAD);
-    return;
+    return normal_entry(method, 0, THREAD);
   }
 
   // Get the result and push it onto the stack
   switch (entry->flag_state()) {
   case ltos:
   case dtos:
-    stack->overflow_check(1, CHECK);
+    stack->overflow_check(1, CHECK_0);
     stack->alloc(wordSize);
     break;
   }
@@ -558,20 +561,25 @@ void CppInterpreter::accessor_entry(methodOop method, intptr_t UNUSED, TRAPS) {
       ShouldNotReachHere();
     }
   }
+
+  // No deoptimized frames on the stack
+  return 0;
 }
 
-void CppInterpreter::empty_entry(methodOop method, intptr_t UNUSED, TRAPS) {
+int CppInterpreter::empty_entry(methodOop method, intptr_t UNUSED, TRAPS) {
   JavaThread *thread = (JavaThread *) THREAD;
   ZeroStack *stack = thread->zero_stack();
 
   // Drop into the slow path if we need a safepoint check
   if (SafepointSynchronize::do_call_back()) {
-    normal_entry(method, 0, THREAD);
-    return;
+    return normal_entry(method, 0, THREAD);
   }
 
   // Pop our parameters
   stack->set_sp(stack->sp() + method->size_of_parameters());
+
+  // No deoptimized frames on the stack
+  return 0;
 }
 
 InterpreterFrame *InterpreterFrame::build(const methodOop method, TRAPS) {
diff --git a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.hpp b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.hpp
index 69a4efc68cc..96f4e564a93 100644
--- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.hpp
+++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.hpp
@@ -29,10 +29,10 @@
 
  public:
   // Method entries
-  static void normal_entry(methodOop method, intptr_t UNUSED, TRAPS);
-  static void native_entry(methodOop method, intptr_t UNUSED, TRAPS);
-  static void accessor_entry(methodOop method, intptr_t UNUSED, TRAPS);
-  static void empty_entry(methodOop method, intptr_t UNUSED, TRAPS);
+  static int normal_entry(methodOop method, intptr_t UNUSED, TRAPS);
+  static int native_entry(methodOop method, intptr_t UNUSED, TRAPS);
+  static int accessor_entry(methodOop method, intptr_t UNUSED, TRAPS);
+  static int empty_entry(methodOop method, intptr_t UNUSED, TRAPS);
 
  public:
   // Main loop of normal_entry
diff --git a/hotspot/src/cpu/zero/vm/entry_zero.hpp b/hotspot/src/cpu/zero/vm/entry_zero.hpp
index 12f7e554b1a..8ba27238373 100644
--- a/hotspot/src/cpu/zero/vm/entry_zero.hpp
+++ b/hotspot/src/cpu/zero/vm/entry_zero.hpp
@@ -1,6 +1,6 @@
 /*
  * Copyright 2003-2007 Sun Microsystems, Inc.  All Rights Reserved.
- * Copyright 2008, 2009 Red Hat, Inc.
+ * Copyright 2008, 2009, 2010 Red Hat, Inc.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -41,20 +41,30 @@ class ZeroEntry {
   }
 
  private:
-  typedef void (*NormalEntryFunc)(methodOop method,
-                                  intptr_t  base_pc,
-                                  TRAPS);
-  typedef void (*OSREntryFunc)(methodOop method,
-                               address   osr_buf,
-                               intptr_t  base_pc,
-                               TRAPS);
+  typedef int (*NormalEntryFunc)(methodOop method,
+                                 intptr_t  base_pc,
+                                 TRAPS);
+  typedef int (*OSREntryFunc)(methodOop method,
+                              address   osr_buf,
+                              intptr_t  base_pc,
+                              TRAPS);
 
  public:
   void invoke(methodOop method, TRAPS) const {
-    ((NormalEntryFunc) entry_point())(method, (intptr_t) this, THREAD);
+    maybe_deoptimize(
+      ((NormalEntryFunc) entry_point())(method, (intptr_t) this, THREAD),
+      THREAD);
   }
   void invoke_osr(methodOop method, address osr_buf, TRAPS) const {
-    ((OSREntryFunc) entry_point())(method, osr_buf, (intptr_t) this, THREAD);
+    maybe_deoptimize(
+      ((OSREntryFunc) entry_point())(method, osr_buf, (intptr_t) this, THREAD),
+      THREAD);
+  }
+
+ private:
+  static void maybe_deoptimize(int deoptimized_frames, TRAPS) {
+    if (deoptimized_frames)
+      CppInterpreter::main_loop(deoptimized_frames - 1, THREAD);
   }
 
  public:

From df4f3b6c420e44651daf0da25f70ee8690e43d41 Mon Sep 17 00:00:00 2001
From: Gary Benson 
Date: Wed, 12 May 2010 10:28:13 -0700
Subject: [PATCH 46/54] 6951923: some uses of fatal1 were missed by 6888954

Reviewed-by: jcoomes
---
 hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp b/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp
index b9a140a5136..5e2ff0a91bd 100644
--- a/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp
+++ b/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp
@@ -288,7 +288,7 @@ static void current_stack_region(address *bottom, size_t *size) {
       vm_exit_out_of_memory(0, "pthread_getattr_np");
     }
     else {
-      fatal1("pthread_getattr_np failed with errno = %d", res);
+      fatal(err_msg("pthread_getattr_np failed with errno = %d", res));
     }
   }
 
@@ -296,7 +296,7 @@ static void current_stack_region(address *bottom, size_t *size) {
   size_t stack_bytes;
   res = pthread_attr_getstack(&attr, (void **) &stack_bottom, &stack_bytes);
   if (res != 0) {
-    fatal1("pthread_attr_getstack failed with errno = %d", res);
+    fatal(err_msg("pthread_attr_getstack failed with errno = %d", res));
   }
   address stack_top = stack_bottom + stack_bytes;
 
@@ -308,7 +308,7 @@ static void current_stack_region(address *bottom, size_t *size) {
   size_t guard_bytes;
   res = pthread_attr_getguardsize(&attr, &guard_bytes);
   if (res != 0) {
-    fatal1("pthread_attr_getguardsize failed with errno = %d", res);
+    fatal(err_msg("pthread_attr_getguardsize failed with errno = %d", res));
   }
   int guard_pages = align_size_up(guard_bytes, page_bytes) / page_bytes;
   assert(guard_bytes == guard_pages * page_bytes, "unaligned guard");

From 9c93404ddea826ea632b161083d0d1b9914160b0 Mon Sep 17 00:00:00 2001
From: Michael Wilkerson 
Date: Thu, 13 May 2010 13:22:08 -0700
Subject: [PATCH 47/54] Added tag jdk7-b93 for changeset 30b170e85ca5

---
 .hgtags-top-repo | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.hgtags-top-repo b/.hgtags-top-repo
index 9616468e283..1f88fddf975 100644
--- a/.hgtags-top-repo
+++ b/.hgtags-top-repo
@@ -67,3 +67,4 @@ cf26288a114be67c39f2758959ce50b60f5ae330 jdk7-b85
 425ba3efabbfe0b188105c10aaf7c3c8fa8d1a38 jdk7-b90
 97d8b6c659c29c8493a8b2b72c2796a021a8cf79 jdk7-b91
 5f5c33d417f3a14706b09a4a95e65fa7b6fa54d6 jdk7-b92
+5fc102ff48f0e787ce9cc77249841d5ff0941b75 jdk7-b93

From 9d2e4e10222c8d71ab537f62c112de0f7b6c67a2 Mon Sep 17 00:00:00 2001
From: Michael Wilkerson 
Date: Thu, 13 May 2010 13:22:12 -0700
Subject: [PATCH 48/54] Added tag jdk7-b93 for changeset 886a48579400

---
 hotspot/.hgtags | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hotspot/.hgtags b/hotspot/.hgtags
index 1506a9033be..ae8d002a376 100644
--- a/hotspot/.hgtags
+++ b/hotspot/.hgtags
@@ -93,3 +93,4 @@ e7e7e36ccdb5d56edd47e5744351202d38f3b7ad jdk7-b87
 e0a1a502e402dbe7bf2d9102b4084a7e79a99a9b jdk7-b91
 25f53b53aaa3eb8b2d5391a1e8de9a76ae1dd8a2 hs18-b03
 3221d1887d30341bedfdac1dbf365ea41beff20f jdk7-b92
+9d865fc2f644fdd9a0108fd6407944ee610aadd9 jdk7-b93

From 24b484a01574addcba10b2b29185ab01f40d76d2 Mon Sep 17 00:00:00 2001
From: Michael Wilkerson 
Date: Thu, 13 May 2010 13:22:22 -0700
Subject: [PATCH 49/54] Added tag jdk7-b93 for changeset e415207ac256

---
 jdk/.hgtags | 1 +
 1 file changed, 1 insertion(+)

diff --git a/jdk/.hgtags b/jdk/.hgtags
index 44a2cf3239e..ec3ff96ec96 100644
--- a/jdk/.hgtags
+++ b/jdk/.hgtags
@@ -67,3 +67,4 @@ b3c69282f6d3c90ec21056cd1ab70dc0c895b069 jdk7-b88
 7f90d0b9dbb7ab4c60d0b0233e4e77fb4fac597c jdk7-b90
 08a31cab971fcad4695e913d0f3be7bde3a90747 jdk7-b91
 f2dce7210cc00453c23e53edeec7156f112ca382 jdk7-b92
+219b84b9533ae4fe3c6c2083f8a8962cb579f1de jdk7-b93

From f52963c1bccc92437c5d485d9538e5d9c94737ab Mon Sep 17 00:00:00 2001
From: Erik Trimble 
Date: Thu, 13 May 2010 14:47:21 -0700
Subject: [PATCH 50/54] 6952178: Fork HS18 to HS19 - renumber Major and build
 numbers of JVM

Update the Major and build numbers for HS19 fork

Reviewed-by: jcoomes
---
 hotspot/make/hotspot_version | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hotspot/make/hotspot_version b/hotspot/make/hotspot_version
index 840d867917e..38634354f5f 100644
--- a/hotspot/make/hotspot_version
+++ b/hotspot/make/hotspot_version
@@ -33,9 +33,9 @@
 # Don't put quotes (fail windows build).
 HOTSPOT_VM_COPYRIGHT=Copyright 2010
 
-HS_MAJOR_VER=18
+HS_MAJOR_VER=19
 HS_MINOR_VER=0
-HS_BUILD_NUMBER=04
+HS_BUILD_NUMBER=01
 
 JDK_MAJOR_VER=1
 JDK_MINOR_VER=7

From 5545514e602ec90fcc1632095b1f270e56f260fb Mon Sep 17 00:00:00 2001
From: Anthony Petrov 
Date: Tue, 18 May 2010 19:35:41 +0400
Subject: [PATCH 51/54] 6953275: Many Swing tests are failing because of a GTK
 lib

Reviewed-by: art, dcherepanov
---
 jdk/src/solaris/native/sun/awt/gtk2_interface.c | 13 ++++++++-----
 jdk/src/solaris/native/sun/awt/gtk2_interface.h |  1 -
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/jdk/src/solaris/native/sun/awt/gtk2_interface.c b/jdk/src/solaris/native/sun/awt/gtk2_interface.c
index dfa7ef1dfb4..ee1c3cc7856 100644
--- a/jdk/src/solaris/native/sun/awt/gtk2_interface.c
+++ b/jdk/src/solaris/native/sun/awt/gtk2_interface.c
@@ -77,6 +77,7 @@ const gint DEFAULT    = 1 << 10;
 
 static void *gtk2_libhandle = NULL;
 static void *gthread_libhandle = NULL;
+static gboolean flag_g_thread_get_initialized = FALSE;
 static jmp_buf j;
 
 /* Widgets */
@@ -436,8 +437,10 @@ void gtk2_file_chooser_load()
     fp_gtk_file_chooser_set_filter = dl_symbol("gtk_file_chooser_set_filter");
     fp_gtk_file_chooser_get_type = dl_symbol("gtk_file_chooser_get_type");
     fp_gtk_file_filter_new = dl_symbol("gtk_file_filter_new");
-    fp_gtk_file_chooser_set_do_overwrite_confirmation = dl_symbol(
-            "gtk_file_chooser_set_do_overwrite_confirmation");
+    if (fp_gtk_check_version(2, 8, 0) == NULL) {
+        fp_gtk_file_chooser_set_do_overwrite_confirmation = dl_symbol(
+                "gtk_file_chooser_set_do_overwrite_confirmation");
+    }
     fp_gtk_file_chooser_set_select_multiple = dl_symbol(
             "gtk_file_chooser_set_select_multiple");
     fp_gtk_file_chooser_get_current_folder = dl_symbol(
@@ -641,8 +644,6 @@ gboolean gtk2_load()
         /**
          * GLib thread system
          */
-        fp_g_thread_get_initialized = dl_symbol_gthread(
-                "g_thread_get_initialized");
         fp_g_thread_init = dl_symbol_gthread("g_thread_init");
         fp_gdk_threads_init = dl_symbol("gdk_threads_init");
         fp_gdk_threads_enter = dl_symbol("gdk_threads_enter");
@@ -744,7 +745,9 @@ gboolean gtk2_load()
 
     if (fp_gtk_check_version(2, 2, 0) == NULL) {
         // Init the thread system to use GLib in a thread-safe mode
-        if (!fp_g_thread_get_initialized()) {
+        if (!flag_g_thread_get_initialized) {
+            flag_g_thread_get_initialized = TRUE;
+
             fp_g_thread_init(NULL);
 
             //According the GTK documentation, gdk_threads_init() should be
diff --git a/jdk/src/solaris/native/sun/awt/gtk2_interface.h b/jdk/src/solaris/native/sun/awt/gtk2_interface.h
index 95ca3cecaad..fc401c1bc12 100644
--- a/jdk/src/solaris/native/sun/awt/gtk2_interface.h
+++ b/jdk/src/solaris/native/sun/awt/gtk2_interface.h
@@ -786,7 +786,6 @@ void (*fp_gtk_main)(void);
 guint (*fp_gtk_main_level)(void);
 
 
-gboolean (*fp_g_thread_get_initialized)(void);
 void (*fp_g_thread_init)(GThreadFunctions *vtable);
 void (*fp_gdk_threads_init)(void);
 void (*fp_gdk_threads_enter)(void);

From 184c523bdb842259671c3747f8b9e3d6cbb0d8b6 Mon Sep 17 00:00:00 2001
From: Phil Race 
Date: Wed, 19 May 2010 09:44:19 -0700
Subject: [PATCH 52/54] 6903970: VS2008/VS2010 build fails in make/sun/jkernel
 because of "afxres.h" missing

Reviewed-by: ohair, art
---
 README-builds.html | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/README-builds.html b/README-builds.html
index 41da91d1f8f..0b6fd25722b 100644
--- a/README-builds.html
+++ b/README-builds.html
@@ -970,9 +970,9 @@ including non-open portions.
 So for now you should be able to build with either VS2003 or VS2010.
 We do not guarantee that VS2008 will work, although there is sufficient
 makefile support to make at least basic JDK builds plausible.
-Visual Studio 2010 Express compilers are likely to be able to build all the
-"open" sources, with only small adjustments, but this has yet to be made
-to work. Also we have not yet seen the 7.1 Windows SDK with the 64 bit
+Visual Studio 2010 Express compilers are now able to build all the
+open source repositories, but this is 32 bit only, since
+we have not yet seen the 7.1 Windows SDK with the 64 bit
 compilers. END WARNING.
 

The 32-bit OpenJDK Windows build From ca5f8bd9bb540cfb36c8e77e3991ac7a0968689a Mon Sep 17 00:00:00 2001 From: Phil Race Date: Wed, 19 May 2010 09:45:05 -0700 Subject: [PATCH 53/54] 6903970: VS2008/VS2010 build fails in make/sun/jkernel because of "afxres.h" missing Reviewed-by: ohair, art --- jdk/make/common/shared/Defs-windows.gmk | 12 ++++++++---- jdk/make/sun/jkernel/Makefile | 7 +++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/jdk/make/common/shared/Defs-windows.gmk b/jdk/make/common/shared/Defs-windows.gmk index c632f3d1579..13c3964eab3 100644 --- a/jdk/make/common/shared/Defs-windows.gmk +++ b/jdk/make/common/shared/Defs-windows.gmk @@ -287,11 +287,15 @@ ifeq ($(ARCH_DATA_MODEL), 32) # Assume VS100, then VS90, then VS80, then VS71 _redist_sdk :=$(call FullPath,$(_msvc_dir)/redist/x86/Microsoft.VC100.CRT) ifeq ($(_redist_sdk),) - _redist_sdk :=$(call FullPath,$(_msvc_dir)/redist/x86/Microsoft.VC90.CRT) - ifeq ($(_redist_sdk),) - _redist_sdk :=$(call FullPath,$(_msvc_dir)/redist/x86/Microsoft.VC80.CRT) + ifneq ($(VS100COMNTOOLS),) + _redist_sdk :=c:/windows/system32 + else + _redist_sdk :=$(call FullPath,$(_msvc_dir)/redist/x86/Microsoft.VC90.CRT) ifeq ($(_redist_sdk),) - _redist_sdk :=$(call FullPath,$(_msvc_dir)/../SDK/v1.1/Bin) + _redist_sdk :=$(call FullPath,$(_msvc_dir)/redist/x86/Microsoft.VC80.CRT) + ifeq ($(_redist_sdk),) + _redist_sdk :=$(call FullPath,$(_msvc_dir)/../SDK/v1.1/Bin) + endif endif endif endif diff --git a/jdk/make/sun/jkernel/Makefile b/jdk/make/sun/jkernel/Makefile index 7a7a6a3645f..74643c13532 100644 --- a/jdk/make/sun/jkernel/Makefile +++ b/jdk/make/sun/jkernel/Makefile @@ -52,6 +52,11 @@ ifeq ($(ARCH_DATA_MODEL), 32) ifeq ($(PLATFORM), windows) +# If this is the VS Express compiler it will lack vc/atlmfc/ +ATL_MFC_DIR :=$(call DirExists,$(COMPILER_PATH)/../atlmfc,,) + +ifneq ($(ATL_MFC_DIR),) + include FILES_c_windows.gmk vpath %.cpp $(PLATFORM_SRC)/native/sun/jkernel @@ -67,6 +72,8 @@ endif endif +endif + # # Resources # From 56be4c0b46a02f684b6b8d551b7007c2d3f928dd Mon Sep 17 00:00:00 2001 From: Phil Race Date: Wed, 19 May 2010 10:21:41 -0700 Subject: [PATCH 54/54] 6953588: hotspot\src\share\vm\interpreter\bytecodes.cpp doesn't compile with VS2010 on AMD64 Reviewed-by: dcubed --- hotspot/src/share/vm/interpreter/bytecodes.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hotspot/src/share/vm/interpreter/bytecodes.cpp b/hotspot/src/share/vm/interpreter/bytecodes.cpp index cb2a7ecb234..1a270e78644 100644 --- a/hotspot/src/share/vm/interpreter/bytecodes.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodes.cpp @@ -26,11 +26,13 @@ #include "incls/_bytecodes.cpp.incl" +#if defined(WIN32) && (defined(_MSC_VER) && (_MSC_VER < 1600)) // Windows AMD64 Compiler Hangs compiling this file // unless optimization is off #ifdef _M_AMD64 #pragma optimize ("", off) #endif +#endif bool Bytecodes::_is_initialized = false;