# HG changeset patch # User jwilhelm # Date 1488216259 -3600 # Node ID 68b17649266b6779d9d181e271e3e65f1400ee97 # Parent e15b96207e471a9bb92a8c7b952d6894218fb7bc# Parent 501b6d07e6ddf42899ae989e5a541d724a832e8b Merge diff -r e15b96207e47 -r 68b17649266b hotspot/src/cpu/arm/vm/c1_Runtime1_arm.cpp --- a/hotspot/src/cpu/arm/vm/c1_Runtime1_arm.cpp Fri Feb 24 19:48:33 2017 +0100 +++ b/hotspot/src/cpu/arm/vm/c1_Runtime1_arm.cpp Mon Feb 27 18:24:19 2017 +0100 @@ -618,7 +618,7 @@ Address buffer(Rthread, in_bytes(JavaThread::dirty_card_queue_offset() + DirtyCardQueue::byte_offset_of_buf())); - AddressLiteral cardtable((address)ct->byte_map_base); + AddressLiteral cardtable((address)ct->byte_map_base, relocInfo::none); assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code"); // save at least the registers that need saving if the runtime is called @@ -645,7 +645,7 @@ // Note: there is a comment in x86 code about not using // ExternalAddress / lea, due to relocation not working // properly for that address. Should be OK for arm, where we - // explicitly specify that 'cartable' has a relocInfo::none + // explicitly specify that 'cardtable' has a relocInfo::none // type. __ lea(r_card_base_1, cardtable); __ add(r_card_addr_0, r_card_base_1, AsmOperand(r_obj_0, lsr, CardTableModRefBS::card_shift)); diff -r e15b96207e47 -r 68b17649266b hotspot/src/share/vm/classfile/classLoaderData.cpp --- a/hotspot/src/share/vm/classfile/classLoaderData.cpp Fri Feb 24 19:48:33 2017 +0100 +++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp Mon Feb 27 18:24:19 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -93,7 +93,7 @@ _keep_alive((is_anonymous || h_class_loader.is_null()) ? 1 : 0), _metaspace(NULL), _unloading(false), _klasses(NULL), _modules(NULL), _packages(NULL), - _claimed(0), _jmethod_ids(NULL), _handles(NULL), _deallocate_list(NULL), + _claimed(0), _jmethod_ids(NULL), _handles(), _deallocate_list(NULL), _next(NULL), _dependencies(dependencies), _metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true, Monitor::_safepoint_check_never)) { @@ -112,6 +112,76 @@ _list_head = oopFactory::new_objectArray(2, CHECK); } +ClassLoaderData::ChunkedHandleList::~ChunkedHandleList() { + Chunk* c = _head; + while (c != NULL) { + Chunk* next = c->_next; + delete c; + c = next; + } +} + +oop* ClassLoaderData::ChunkedHandleList::add(oop o) { + if (_head == NULL || _head->_size == Chunk::CAPACITY) { + Chunk* next = new Chunk(_head); + OrderAccess::release_store_ptr(&_head, next); + } + oop* handle = &_head->_data[_head->_size]; + *handle = o; + OrderAccess::release_store(&_head->_size, _head->_size + 1); + return handle; +} + +inline void ClassLoaderData::ChunkedHandleList::oops_do_chunk(OopClosure* f, Chunk* c, const juint size) { + for (juint i = 0; i < size; i++) { + if (c->_data[i] != NULL) { + f->do_oop(&c->_data[i]); + } + } +} + +void ClassLoaderData::ChunkedHandleList::oops_do(OopClosure* f) { + Chunk* head = (Chunk*) OrderAccess::load_ptr_acquire(&_head); + if (head != NULL) { + // Must be careful when reading size of head + oops_do_chunk(f, head, OrderAccess::load_acquire(&head->_size)); + for (Chunk* c = head->_next; c != NULL; c = c->_next) { + oops_do_chunk(f, c, c->_size); + } + } +} + +#ifdef ASSERT +class VerifyContainsOopClosure : public OopClosure { + oop* _target; + bool _found; + + public: + VerifyContainsOopClosure(oop* target) : _target(target), _found(false) {} + + void do_oop(oop* p) { + if (p == _target) { + _found = true; + } + } + + void do_oop(narrowOop* p) { + // The ChunkedHandleList should not contain any narrowOop + ShouldNotReachHere(); + } + + bool found() const { + return _found; + } +}; + +bool ClassLoaderData::ChunkedHandleList::contains(oop* p) { + VerifyContainsOopClosure cl(p); + oops_do(&cl); + return cl.found(); +} +#endif + bool ClassLoaderData::claim() { if (_claimed == 1) { return false; @@ -146,9 +216,9 @@ f->do_oop(&_class_loader); _dependencies.oops_do(f); - if (_handles != NULL) { - _handles->oops_do(f); - } + + _handles.oops_do(f); + if (klass_closure != NULL) { classes_do(klass_closure); } @@ -484,12 +554,6 @@ _metaspace = NULL; delete m; } - // release the handles - if (_handles != NULL) { - JNIHandleBlock::release_block(_handles); - _handles = NULL; - } - // Clear all the JNI handles for methods // These aren't deallocated and are going to look like a leak, but that's // needed because we can't really get rid of jmethodIDs because we don't @@ -563,19 +627,14 @@ return metaspace; } -JNIHandleBlock* ClassLoaderData::handles() const { return _handles; } -void ClassLoaderData::set_handles(JNIHandleBlock* handles) { _handles = handles; } - jobject ClassLoaderData::add_handle(Handle h) { MutexLockerEx ml(metaspace_lock(), Mutex::_no_safepoint_check_flag); - if (handles() == NULL) { - set_handles(JNIHandleBlock::allocate_block()); - } - return handles()->allocate_handle(h()); + return (jobject) _handles.add(h()); } -void ClassLoaderData::remove_handle(jobject h) { - _handles->release_handle(h); +void ClassLoaderData::remove_handle_unsafe(jobject h) { + assert(_handles.contains((oop*) h), "Got unexpected handle " PTR_FORMAT, p2i((oop*) h)); + *((oop*) h) = NULL; } // Add this metadata pointer to be freed when it's safe. This is only during @@ -645,7 +704,6 @@ p2i(class_loader() != NULL ? class_loader()->klass() : NULL), loader_name()); if (claimed()) out->print(" claimed "); if (is_unloading()) out->print(" unloading "); - out->print(" handles " INTPTR_FORMAT, p2i(handles())); out->cr(); if (metaspace_or_null() != NULL) { out->print_cr("metaspace: " INTPTR_FORMAT, p2i(metaspace_or_null())); diff -r e15b96207e47 -r 68b17649266b hotspot/src/share/vm/classfile/classLoaderData.hpp --- a/hotspot/src/share/vm/classfile/classLoaderData.hpp Fri Feb 24 19:48:33 2017 +0100 +++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp Mon Feb 27 18:24:19 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,7 +52,6 @@ class ClassLoaderData; class JNIMethodBlock; -class JNIHandleBlock; class Metadebug; class ModuleEntry; class PackageEntry; @@ -160,6 +159,34 @@ void oops_do(OopClosure* f); }; + class ChunkedHandleList VALUE_OBJ_CLASS_SPEC { + struct Chunk : public CHeapObj { + static const size_t CAPACITY = 32; + + oop _data[CAPACITY]; + volatile juint _size; + Chunk* _next; + + Chunk(Chunk* c) : _next(c), _size(0) { } + }; + + Chunk* _head; + + void oops_do_chunk(OopClosure* f, Chunk* c, const juint size); + + public: + ChunkedHandleList() : _head(NULL) {} + ~ChunkedHandleList(); + + // Only one thread at a time can add, guarded by ClassLoaderData::metaspace_lock(). + // However, multiple threads can execute oops_do concurrently with add. + oop* add(oop o); +#ifdef ASSERT + bool contains(oop* p); +#endif + void oops_do(OopClosure* f); + }; + friend class ClassLoaderDataGraph; friend class ClassLoaderDataGraphKlassIteratorAtomic; friend class ClassLoaderDataGraphMetaspaceIterator; @@ -185,8 +212,8 @@ volatile int _claimed; // true if claimed, for example during GC traces. // To avoid applying oop closure more than once. // Has to be an int because we cas it. - JNIHandleBlock* _handles; // Handles to constant pool arrays, Modules, etc, which - // have the same life cycle of the corresponding ClassLoader. + ChunkedHandleList _handles; // Handles to constant pool arrays, Modules, etc, which + // have the same life cycle of the corresponding ClassLoader. Klass* volatile _klasses; // The classes defined by the class loader. PackageEntryTable* volatile _packages; // The packages defined by the class loader. @@ -217,9 +244,6 @@ ClassLoaderData(Handle h_class_loader, bool is_anonymous, Dependencies dependencies); ~ClassLoaderData(); - JNIHandleBlock* handles() const; - void set_handles(JNIHandleBlock* handles); - // GC interface. void clear_claimed() { _claimed = 0; } bool claimed() const { return _claimed == 1; } @@ -312,7 +336,7 @@ const char* loader_name(); jobject add_handle(Handle h); - void remove_handle(jobject h); + void remove_handle_unsafe(jobject h); void add_class(Klass* k, bool publicize = true); void remove_class(Klass* k); bool contains_klass(Klass* k); diff -r e15b96207e47 -r 68b17649266b hotspot/src/share/vm/classfile/moduleEntry.cpp --- a/hotspot/src/share/vm/classfile/moduleEntry.cpp Fri Feb 24 19:48:33 2017 +0100 +++ b/hotspot/src/share/vm/classfile/moduleEntry.cpp Mon Feb 27 18:24:19 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -87,11 +87,11 @@ // Set the shared ProtectionDomain atomically void ModuleEntry::set_shared_protection_domain(ClassLoaderData *loader_data, Handle pd_h) { - // Create a JNI handle for the shared ProtectionDomain and save it atomically. - // If someone beats us setting the _pd cache, the created JNI handle is destroyed. + // Create a handle for the shared ProtectionDomain and save it atomically. + // If someone beats us setting the _pd cache, the created handle is destroyed. jobject obj = loader_data->add_handle(pd_h); if (Atomic::cmpxchg_ptr(obj, &_pd, NULL) != NULL) { - loader_data->remove_handle(obj); + loader_data->remove_handle_unsafe(obj); } } diff -r e15b96207e47 -r 68b17649266b hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp --- a/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp Fri Feb 24 19:48:33 2017 +0100 +++ b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp Mon Feb 27 18:24:19 2017 +0100 @@ -305,6 +305,7 @@ static_field(StubRoutines, _crc32c_table_addr, address) \ static_field(StubRoutines, _updateBytesCRC32C, address) \ static_field(StubRoutines, _updateBytesAdler32, address) \ + static_field(StubRoutines, _multiplyToLen, address) \ static_field(StubRoutines, _squareToLen, address) \ static_field(StubRoutines, _mulAdd, address) \ static_field(StubRoutines, _montgomeryMultiply, address) \ diff -r e15b96207e47 -r 68b17649266b hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/ClassSearchTest.java --- a/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/ClassSearchTest.java Fri Feb 24 19:48:33 2017 +0100 +++ b/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/ClassSearchTest.java Mon Feb 27 18:24:19 2017 +0100 @@ -20,10 +20,19 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ + +/** + * @test + * @modules jdk.aot/jdk.tools.jaotc + * jdk.aot/jdk.tools.jaotc.collect + * @run junit/othervm jdk.tools.jaotc.test.collect.ClassSearchTest + */ + package jdk.tools.jaotc.test.collect; import jdk.tools.jaotc.LoadedClass; +import jdk.tools.jaotc.collect.*; import org.junit.Assert; import org.junit.Test; @@ -32,45 +41,90 @@ import java.util.List; import java.util.Set; import java.util.function.BiConsumer; +import java.util.function.BiFunction; public class ClassSearchTest { @Test(expected = InternalError.class) public void itShouldThrowExceptionIfNoProvidersAvailable() { ClassSearch target = new ClassSearch(); SearchPath searchPath = new SearchPath(); - target.search(list("foo"), searchPath); + target.search(list(new SearchFor("foo")), searchPath); } @Test public void itShouldFindAProviderForEachEntry() { Set searched = new HashSet<>(); ClassSearch target = new ClassSearch(); - target.addProvider(new SourceProvider() { - @Override - public ClassSource findSource(String name, SearchPath searchPath) { + target.addProvider(provider("", (name, searchPath) -> { searched.add(name); return new NoopSource(); + })); + target.search(searchForList("foo", "bar", "foobar"), null); + Assert.assertEquals(hashset("foo", "bar", "foobar"), searched); + } + + private SourceProvider provider(String supports, BiFunction fn) { + return new SourceProvider() { + @Override + public ClassSource findSource(String name, SearchPath searchPath) { + return fn.apply(name, searchPath); } - }); - target.search(list("foo", "bar", "foobar"), null); - Assert.assertEquals(hashset("foo", "bar", "foobar"), searched); + + @Override + public boolean supports(String type) { + return supports.equals(type); + } + }; } @Test - public void itShouldSearchAllProviders() { + public void itShouldOnlySearchSupportedProvidersForKnownType() { Set visited = new HashSet<>(); ClassSearch target = new ClassSearch(); - target.addProvider((name, searchPath) -> { + + target.addProvider(provider("jar", (name, searchPath) -> { + visited.add("jar"); + return null; + })); + + target.addProvider(provider("dir", (name, searchPath) -> { + visited.add("dir"); + return null; + })); + + try { + target.search(list(new SearchFor("some", "dir")), null); + } catch (InternalError e) { + // throws because no provider gives a source + } + + Assert.assertEquals(hashset("dir"), visited); + } + + @Test(expected = InternalError.class) + public void itShouldThrowErrorIfMultipleSourcesAreAvailable() { + ClassSearch target = new ClassSearch(); + target.addProvider(provider("", (name, searchPath) -> consumer -> Assert.fail())); + target.addProvider(provider("", (name, searchPath) -> consumer -> Assert.fail())); + + target.search(searchForList("somethign"), null); + } + + @Test + public void itShouldSearchAllProvidersForUnknownType() { + Set visited = new HashSet<>(); + ClassSearch target = new ClassSearch(); + target.addProvider(provider("", (name, searchPath) -> { visited.add("1"); return null; - }); - target.addProvider((name, searchPath) -> { + })); + target.addProvider(provider("", (name, searchPath) -> { visited.add("2"); return null; - }); + })); try { - target.search(list("foo"), null); + target.search(searchForList("foo"), null); } catch (InternalError e) { // throws because no provider gives a source } @@ -85,6 +139,11 @@ ClassSearch target = new ClassSearch(); target.addProvider(new SourceProvider() { @Override + public boolean supports(String type) { + return true; + } + + @Override public ClassSource findSource(String name, SearchPath searchPath) { return new ClassSource() { @Override @@ -101,7 +160,7 @@ } }); - java.util.List search = target.search(list("/tmp/something"), null); + java.util.List search = target.search(searchForList("/tmp/something"), null); Assert.assertEquals(list(new LoadedClass("foo.Bar", null)), search); } @@ -115,8 +174,16 @@ }; ClassSearch target = new ClassSearch(); - target.addProvider((name, searchPath) -> consumer -> consumer.accept("foo.Bar", classLoader)); - target.search(list("foobar"), null); + target.addProvider(provider("", (name, searchPath) -> consumer -> consumer.accept("foo.Bar", classLoader))); + target.search(searchForList("foobar"), null); + } + + private List searchForList(String... entries) { + List list = new ArrayList<>(); + for (String entry : entries) { + list.add(new SearchFor(entry)); + } + return list; } private List list(T... entries) { diff -r e15b96207e47 -r 68b17649266b hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/ClassSourceTest.java --- a/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/ClassSourceTest.java Fri Feb 24 19:48:33 2017 +0100 +++ b/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/ClassSourceTest.java Mon Feb 27 18:24:19 2017 +0100 @@ -20,6 +20,14 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ + +/** + * @test + * @modules jdk.aot/jdk.tools.jaotc + * jdk.aot/jdk.tools.jaotc.collect + * @run junit/othervm jdk.tools.jaotc.test.collect.ClassSourceTest + */ + package jdk.tools.jaotc.test.collect; import org.junit.Assert; diff -r e15b96207e47 -r 68b17649266b hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/FakeFileSupport.java --- a/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/FakeFileSupport.java Fri Feb 24 19:48:33 2017 +0100 +++ b/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/FakeFileSupport.java Mon Feb 27 18:24:19 2017 +0100 @@ -27,6 +27,8 @@ import java.util.HashSet; import java.util.Set; +import jdk.tools.jaotc.collect.FileSupport; + public class FakeFileSupport extends FileSupport { private final Set exists = new HashSet<>(); private final Set directories = new HashSet<>(); diff -r e15b96207e47 -r 68b17649266b hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/FakeSearchPath.java --- a/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/FakeSearchPath.java Fri Feb 24 19:48:33 2017 +0100 +++ b/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/FakeSearchPath.java Mon Feb 27 18:24:19 2017 +0100 @@ -22,6 +22,8 @@ */ package jdk.tools.jaotc.test.collect; +import jdk.tools.jaotc.collect.SearchPath; + import java.nio.file.FileSystem; import java.nio.file.Path; import java.nio.file.Paths; diff -r e15b96207e47 -r 68b17649266b hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/SearchPathTest.java --- a/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/SearchPathTest.java Fri Feb 24 19:48:33 2017 +0100 +++ b/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/SearchPathTest.java Mon Feb 27 18:24:19 2017 +0100 @@ -20,6 +20,17 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ + +/** + * @test + * @modules jdk.aot/jdk.tools.jaotc + * jdk.aot/jdk.tools.jaotc.collect + * + * @build jdk.tools.jaotc.test.collect.Utils + * @build jdk.tools.jaotc.test.collect.FakeFileSupport + * @run junit/othervm jdk.tools.jaotc.test.collect.SearchPathTest + */ + package jdk.tools.jaotc.test.collect; import org.junit.Before; @@ -30,6 +41,8 @@ import java.nio.file.Path; import java.nio.file.Paths; +import jdk.tools.jaotc.collect.*; + import static jdk.tools.jaotc.test.collect.Utils.set; import static org.junit.Assert.*; diff -r e15b96207e47 -r 68b17649266b hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/directory/DirectorySourceProviderTest.java --- a/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/directory/DirectorySourceProviderTest.java Fri Feb 24 19:48:33 2017 +0100 +++ b/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/directory/DirectorySourceProviderTest.java Mon Feb 27 18:24:19 2017 +0100 @@ -21,11 +21,22 @@ * questions. */ +/** + * @test + * @modules jdk.aot/jdk.tools.jaotc + * jdk.aot/jdk.tools.jaotc.collect + * jdk.aot/jdk.tools.jaotc.collect.directory + * @compile ../Utils.java + * @compile ../FakeFileSupport.java + * @run junit/othervm jdk.tools.jaotc.test.collect.directory.DirectorySourceProviderTest + */ + package jdk.tools.jaotc.test.collect.directory; import jdk.tools.jaotc.collect.ClassSource; +import jdk.tools.jaotc.collect.directory.DirectorySourceProvider; import jdk.tools.jaotc.test.collect.FakeFileSupport; -import jdk.tools.jaotc.test.collect.FileSupport; +import jdk.tools.jaotc.collect.FileSupport; import org.junit.Assert; import org.junit.Test; diff -r e15b96207e47 -r 68b17649266b hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/jar/JarSourceProviderTest.java --- a/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/jar/JarSourceProviderTest.java Fri Feb 24 19:48:33 2017 +0100 +++ b/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/jar/JarSourceProviderTest.java Mon Feb 27 18:24:19 2017 +0100 @@ -20,9 +20,23 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ + +/** + * @test + * @modules jdk.aot/jdk.tools.jaotc + * jdk.aot/jdk.tools.jaotc.collect + * jdk.aot/jdk.tools.jaotc.collect.jar + * @compile ../Utils.java + * @compile ../FakeFileSupport.java + * @compile ../FakeSearchPath.java + * + * @run junit/othervm jdk.tools.jaotc.test.collect.jar.JarSourceProviderTest + */ + package jdk.tools.jaotc.test.collect.jar; import jdk.tools.jaotc.collect.ClassSource; +import jdk.tools.jaotc.collect.jar.JarSourceProvider; import jdk.tools.jaotc.test.collect.FakeFileSupport; import jdk.tools.jaotc.test.collect.FakeSearchPath; import org.junit.Assert; diff -r e15b96207e47 -r 68b17649266b hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/module/ModuleSourceProviderTest.java --- a/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/module/ModuleSourceProviderTest.java Fri Feb 24 19:48:33 2017 +0100 +++ b/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/module/ModuleSourceProviderTest.java Mon Feb 27 18:24:19 2017 +0100 @@ -20,15 +20,31 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ + +/** + * @test + * @modules jdk.aot/jdk.tools.jaotc + * jdk.aot/jdk.tools.jaotc.collect + * jdk.aot/jdk.tools.jaotc.collect.module + * @compile ../Utils.java + * @run junit/othervm jdk.tools.jaotc.test.collect.module.ModuleSourceProviderTest + */ + package jdk.tools.jaotc.test.collect.module; -import jdk.tools.jaotc.*; -import jdk.tools.jaotc.test.collect.FakeSearchPath; +import jdk.tools.jaotc.collect.FileSupport; +import jdk.tools.jaotc.collect.module.ModuleSource; +import jdk.tools.jaotc.collect.module.ModuleSourceProvider; import jdk.tools.jaotc.test.collect.Utils; import org.junit.Before; import org.junit.Test; +import java.io.IOException; +import java.nio.file.FileSystem; import java.nio.file.FileSystems; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.function.BiFunction; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; @@ -36,28 +52,42 @@ public class ModuleSourceProviderTest { private ClassLoader classLoader; private ModuleSourceProvider target; + private FileSupport fileSupport; + private BiFunction getSubDirectory = null; @Before public void setUp() { classLoader = new FakeClassLoader(); - target = new ModuleSourceProvider(FileSystems.getDefault(), classLoader); + fileSupport = new FileSupport() { + + @Override + public boolean isDirectory(Path path) { + return true; + } + + @Override + public Path getSubDirectory(FileSystem fileSystem, Path root, Path path) throws IOException { + if (getSubDirectory == null) { + throw new IOException("Nope"); + } + return getSubDirectory.apply(root, path); + } + }; + target = new ModuleSourceProvider(FileSystems.getDefault(), classLoader, fileSupport); } @Test - public void itShouldUseSearchPath() { - FakeSearchPath searchPath = new FakeSearchPath("blah/java.base"); - ModuleSource source = (ModuleSource) target.findSource("java.base", searchPath); - assertEquals(Utils.set("java.base"), searchPath.entries); - assertEquals("blah/java.base", source.getModulePath().toString()); - assertEquals("module:blah/java.base", source.toString()); - } + public void itShouldUseFileSupport() { + getSubDirectory = (root, path) -> { + if (root.toString().equals("modules") && path.toString().equals("test.module")) { + return Paths.get("modules/test.module"); + } + return null; + }; - @Test - public void itShouldReturnNullIfSearchPathReturnsNull() { - FakeSearchPath searchPath = new FakeSearchPath(null); - ModuleSource source = (ModuleSource) target.findSource("jdk.base", searchPath); - assertEquals(Utils.set("jdk.base"), searchPath.entries); - assertNull(source); + ModuleSource source = (ModuleSource) target.findSource("test.module", null); + assertEquals("modules/test.module", source.getModulePath().toString()); + assertEquals("module:modules/test.module", source.toString()); } private static class FakeClassLoader extends ClassLoader {