Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The alternative, flat representation of classpath elements #4176

Merged
merged 15 commits into from Dec 5, 2014

Commits on Nov 28, 2014

  1. Abstract over ClassPath and ClassRep

    This commit is intended to create the possibility to plug in into
    the compiler an alternative classpath representation which would be
    possibly more efficient, use less memory etc. Such an implementation
    - at least at the beginning - should exist next to the currently
    existing one and be possible to turn on using a flag.
    
    Several places in the compiler have a direct dependency on the
    classpath implementation. Examples include backend's icode generator
    and reader, SymbolLoaders, ClassfileParser. After closer inspection,
    one realizes that all those places depend only on a very small subset
    of classpath logic: they need to lookup classes from classpath. Hence
    there's introduced ClassFileLookup trait that encapsulates that
    functionality. The ClassPath extends that trait and an alternative
    one also must do it.
    
    There's also added ClassRepresentation - the base trait for ClassRep
    (the inner class of ClassPath). Thanks to that the compiler uses
    a type which is not directly related to the particular classpath
    representation as it was doing until now.
    mpociecha committed Nov 28, 2014
    Copy the full SHA
    7448377 View commit details
    Browse the repository at this point in the history

Commits on Nov 30, 2014

  1. Use new asClassPathString method and create FileUtils for classpath

    The method asClasspathString is now deprecated. Moreover it's moved
    to ClassFileLookup in the case someone was using it in some project
    (an alternative classpath also will support it - just in the case).
    All its usages existing in Scala sources are changed to
    asClassPathString method. The only difference is the name.
    
    Some operations on files or their names are moved from ClassPath to
    the newly created FileUtils dedicated to classpath. It will be
    possible to reuse them when implementing an alternative classpath
    representation. Moreover such allocation-free extension methods like
    the one added in this commit will improve the readability.
    mpociecha committed Nov 30, 2014
    Copy the full SHA
    6b498c3 View commit details
    Browse the repository at this point in the history
  2. Define interface for flat classpath and add package loader using it

    This commit introduces the base trait for flat classpath - an
    alternative classpath representation. In accordance with the idea
    and the experimental implementation of @gkossakowski, this
    representation will try to make the best use of the specificity of
    a given file type instead of using AbstractFile everywhere. It's
    possible as .NET backend is no longer supported and we can focus on
    Java-specific types of files.
    
    FlatClassPath extends ClassFileLookup which provides the common
    interface used also by existing ClassPath.
    
    The new implementation is called flat because it's possible to query
    the whole classpath using just single instance.
    In the case of the old (recursive) representation there's the
    structure of nested classpath objects, where each such an object can
    return only entries from one level of hierarchy but it returns also
    another classpath objects for nested levels included in it.
    
    That's why there's added dedicated PackageLoaderUsingFlatClassPath in
    SymbolLoaders - approaches are different so also the way of loading
    packages has to be different. The new package loader is currently
    unused.
    
    There's added also PackageNameUtils which will provide common methods
    used by classpath implementations for various file types.
    mpociecha committed Nov 30, 2014
    Copy the full SHA
    1545d2a View commit details
    Browse the repository at this point in the history
  3. Add the flat classpath type aggregating flat classpath instances

    There's added AggregateFlatClassPath - an equivalent of
    MergedClassPath from the old implementation. It is supposed to group
    classpath instances handling different files being directories, zips
    or jars.
    
    Unlike in the case of the old (recursive) implementation, there won't
    be a deep, nested hierarchy of classpath instances - just one root
    (aggregate) and a flat structure of its children.
    
    AggregateFlatClassPath ensures the distinction of classpath entries
    and merges corresponding entries for class and source files into one
    entry. This is required as SymbolLoaders class makes use of this kind
    of ClassRepresentation.
    
    There are also added unit tests which check whether
    AggregateFlatClassPath obtains correct entries from classpath
    instances specified in a constructor and whether it preserves the
    ordering in the case of repeated entries. There's added a test type
    of flat classpath using VirtualFiles so it's easy to check the real
    behaviour.
    mpociecha committed Nov 30, 2014
    Copy the full SHA
    af295c5 View commit details
    Browse the repository at this point in the history
  4. Add flat classpath implementation for directories

    There's added the flat classpath implementation for directories using
    java.util.File directly. Since we work with a real directory - not
    the AbstractFile - we don't need to iterate all entries of a file to
    get inner entries of some package. We can just find an adequate
    directory for a package.
    
    There are added implementations for a class- and a sourcepath. Both
    extend DirectoryFileLookup which provides common logic.
    mpociecha committed Nov 30, 2014
    Copy the full SHA
    3b585e9 View commit details
    Browse the repository at this point in the history
  5. Add flat classpath implementation for zip and jar files

    This commit adds an implementation of flat classpath which can handle
    both jar and vanilla zip files. In fact there are two versions - for
    a class- and a sourcepath. Both extend ZipArchiveFileLookup which
    provides common logic.
    
    They use FileZipArchive. @gkossakowski made a comparison of different
    ways of handling zips and jars (e.g. using javac's ZipFileIndex). He
    stated that general efficiency of FileZipArchive, taking into account
    various parameters, is the best.
    
    FileZipArchive is slightly changed. From now it allows to find the
    entry for directory in all directory entries without iterating all
    entries regardless of a type. Thanks to that we can simply find
    a directory for a package - like in the case of DirectoryFileLookup.
    
    There's also added possibility to cache classpath representation of
    classpath elements from jar and zip files across compiler instances.
    The cache is just a map AbstractFile -> FlatClassPath. It should
    reduce the number of created classpath and file instances e.g. in the
    case of many ScalaPresentationCompilers in Scala IDE.
    
    To prevent the possibility to avoid a cache, caches are created as
    a part of factories responsible for the creation of these types of
    the flat classpath.
    mpociecha committed Nov 30, 2014
    Copy the full SHA
    9fe0c8c View commit details
    Browse the repository at this point in the history
  6. Add flat classpath implementation using ManifestResources

    There's added the flat classpath type using ManifestResources,
    closely related to the support for JSR-223 (Scripting for the Java
    Platform). It uses classes listed in the manifest file placed in the
    JAR. It's related to jar files so it's created using
    ZipAndJarFlatClassPathFactory and is cached.
    
    In general currently it's not possible to use it in Scala out of the
    box (without using additional tools such as jarlister) as this
    support is postponed. The old classpath has been properly prepared in
    the PR created by @rjolly scala#2238
    so the new one also got this feature.
    
    ManifestResources is a ZipArchive without a real underlying file
    placed on a disk and in addition implementing some methods declared
    in AbstractFile as unsupported operations. Therefore the
    implementation has to use the iterator. I wanted to have the similar
    behaviour as in the case of directories and zip/jar files - be able
    to get a directory entry for a package without iterating all entries.
    This is achieved by iterating all entries only once and caching
    packages.
    
    This flat classpath type was the last needed one.
    mpociecha committed Nov 30, 2014
    Copy the full SHA
    672c119 View commit details
    Browse the repository at this point in the history
  7. Create base classpath factory and an implementation for the flat cp

    The part of the functionality of a ClassPathContext has been moved
    to the base trait ClassPathFactory so it can be reused by the newly
    created FlatClassPathFactory. This new implementation works in
    similar manner as the ClassPathContext with this difference that it
    just creates instances of flat classpath.
    
    This change doesn't modify the behaviour of the compiler as the
    interface and the way ClassPathContext works didn't change. Moreover
    FlatClassPathFactory is currently unused.
    mpociecha committed Nov 30, 2014
    Copy the full SHA
    bb91785 View commit details
    Browse the repository at this point in the history
  8. Create dedicated path resolver for the flat classpath representation

    This commit adds dedicated FlatClassPathResolver loading classpath
    entries as FlatClassPath.
    
    Most of the common logic from PathResolver for the old classpath has
    been moved to the base, separate class which isn't dependent on
    a particular classpath representation. Thanks to that it was possible
    to reuse it when creating an adequate path resolver for the flat
    classpath representation.
    
    This change doesn't modify the way the compiler works. It also
    doesn't change nothing from the perspective of someone who already
    uses PathResolver in some project or even extends it - at least as
    long as he/she doesn't need to use flat classpath.
    
    There are also added JUnit tests inter alia comparing entries created
    using the old and the new classpath representations (whether the flat
    one created using the new path resolver returns the same entries as
    the recursive one).
    mpociecha committed Nov 30, 2014
    Copy the full SHA
    1cefcb8 View commit details
    Browse the repository at this point in the history

Commits on Dec 1, 2014

  1. Refactor scalap's main

    The structure of scalap's Main has been refactored.
    
    EmptyClasspath is deleted. It looks that it was unused since this
    commit: scala@e594fe5
    
    Also classpath logging is changed and now uses asClassPathString
    method. It was needed to modify one test because of that but it
    won't depend on a particular representation.
    
    There aren't changes in the way scalap works.
    mpociecha committed Dec 1, 2014
    Copy the full SHA
    3f94c77 View commit details
    Browse the repository at this point in the history

Commits on Dec 5, 2014

  1. Integrate flat classpath with the compiler

    This commit integrates with the compiler the whole flat classpath
    representation build next to the recursive one as an alternative.
    
    From now flat classpath really works and can be turned on. There's
    added flag -YclasspathImpl with two options: recursive (the default
    one) and flat.
    
    It was needed to make the dynamic dispatch to the particular
    classpath representation according to the chosen type of a classpath
    representation.
    
    There's added PathResolverFactory which is used instead of a concrete
    implementation of a path resolver. It turned out that only a small
    subset of path resolvers methods is used outside this class in Scala
    sources. Therefore, PathResolverFactory returns an instance of a base
    interface PathResolverResult providing only these used methods.
    
    PathResolverFactory in combination with matches in some other places
    ensures that in all places using classpath we create/get the proper
    representation.
    
    Also the classPath method in Global is modified to use the dynamic
    dispatch. This is very important change as a return type changed to
    the base ClassFileLookup providing subset of old ClassPath public
    methods. It can be problematic if someone was using in his project
    the explicit ClassPath type or public methods which are not provided
    via ClassFileLookup. I tested flat classpath with sbt and Scala IDE
    and there were no problems. Also was looking at sources of some other
    projects like e.g. Scala plugin for IntelliJ and there shouldn't be
    problems, I think, but it would be better to check these changes
    using the community build.
    
    Scalap's Main.scala is changed to be able to use both implementations
    and also to use flags related to the classpath implementation.
    
    The classpath invalidation is modified to work properly with the old
    (recursive) classpath representation after changes made in a Global.
    In the case of the attempt to use the invalidation for the flat cp it
    just throws exception with a message that the flat one currently
    doesn't support the invalidation. And also that's why the partest's
    test for the invalidation has been changed to use (always) the old
    implementation. There's added an adequate comment with TODO to this
    file.
    
    There's added partest test generating various dependencies
    (directories, zips and jars with sources and class files) and testing
    whether the compilation and further running an application works
    correctly, when there are these various types of entries specified as
    -classpath and -sourcepath. It should be a good approximation of real
    use cases.
    mpociecha committed Dec 5, 2014
    Copy the full SHA
    04620a0 View commit details
    Browse the repository at this point in the history
  2. Create possibility to skip flat classpath caching

    There's added -YdisableFlatCpCaching option to ScalaSettings which
    allows user to disable caching of flat representation of classpath
    elements.
    mpociecha committed Dec 5, 2014
    Copy the full SHA
    dfc5c1d View commit details
    Browse the repository at this point in the history
  3. Cleanup and refactoring - semicolons, unused or commented out code

    This commit contains some minor changes made by the way when
    implementing flat classpath.
    
    Sample JUnit test that shows that all pieces of JUnit infrastructure
    work correctly now uses assert method form JUnit as it should do from
    the beginning.
    
    I removed commented out lines which were obvious to me. In the case
    of less obvious commented out lines I added TODOs as someone should
    look at such places some day and clean them up.
    
    I removed also some unnecessary semicolons and unused imports.
    
    Many string concatenations using + have been changed to string
    interpolation.
    
    There's removed unused, private walkIterator method from ZipArchive.
    It seems that it was unused since this commit:
    scala@9d4994b
    However, I had to add an exception for the compatibility checker
    because it was complaining about this change.
    
    I made some trivial corrections/optimisations like use 'findClassFile'
    method instead of 'findClass' in combination with 'binary' to find
    the class file.
    mpociecha committed Dec 5, 2014
    5
    Copy the full SHA
    a8c43dc View commit details
    Browse the repository at this point in the history
  4. Add benchmarks to compare recursive and flat cp representations

    The goal of these changes is to add possibility to:
    - compare an efficiency and a content of both cp implementations
    (ClassPathImplComparator)
    - examine the memory consumption by creating a lot of globals using
    a specified classpath (ClassPathMemoryConsumptionTester) - it can be
    considered as e.g. some approximation of ScalaPresentationCompilers
    in Scala IDE when working with many projects
    
    ClassPathMemoryConsumptionTester is placed in main (I mean not test)
    sources so thanks to that it has properly, out of the box configured
    boot classpath etc. and it's easy to use it, e.g.:
    
    scala scala.tools.nsc.ClassPathMemoryConsumptionTester
    -YclasspathImpl:<implementation_to_test> -cp <some_cp>
    -sourcepath <some_sp> -requiredInstances 50 SomeFileToCompile.scala
    
    At the end it waits for the "exit" command so there can be used some
    profiler like JProfiler to look how the given implementation behaves.
    
    Also flat classpath implementation is set as a default one to test it
    on Jenkins. This particular change must be reverted when all tests
    will pass because for now it's not desirable to make it permanently
    the default representation.
    mpociecha committed Dec 5, 2014
    Copy the full SHA
    959d134 View commit details
    Browse the repository at this point in the history
  5. Turn off flat classpath by default, mark one of its classes as sealed

    This commit addresses code review comments.
    
    The flat classpath is no longer the default classpath representation.
    It was the default one just for the test purposes. For now it's not
    desirable to make it permanently the default representation.
    
    ZipAndJarFileLookupFactory is marked as sealed - it should help to
    limit the ways of creating flat classpath instances for zips and jars.
    mpociecha committed Dec 5, 2014
    Copy the full SHA
    3581187 View commit details
    Browse the repository at this point in the history