All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.glassfish.pfl.dynamic.codegen.spi.notes.txt Maven / Gradle / Ivy

There is a newer version: 5.0.0
Show newest version
#
# Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Distribution License v. 1.0, which is available at
# http://www.eclipse.org/org/documents/edl-v10.php.
#
# SPDX-License-Identifier: BSD-3-Clause
#

Obsolete idea:
    Replace _sourceCode and _ByteCode with a single _generate
    method.

    Idea: we usually want to end up with a class loaded in a 
    ClassLoader somewhere.  But there are a variety of ways 
    to do this.

    Options:
	1. Generate: source, class, or both
	2. generate debug or not (locals and line numbers)
	3. compile source to generate bytecode
	4. generate bytecode directly
	5. If compiling source:
	    - classpath (defaults to current VM classpath)
	    - output dir
	    - source dir

    Encoding as properties and method:

    _generate( Properties )
	// Use ORBClassLoader as default (util for context CL or system CL)
    _generate( Properties, ClassLoader )
	// Use PD of specified ClassLoader?
    _generate( Properties, ClassLoader, ProtectionDomain ) // Do we need this?

    Props (All have com.sun.corba.codegen prefix):
	Generation: direct, direct_with_source, javac (default javac for now)
	SourceOutputDirectory:  (default cwd)
	ClassOutputDirectory:  (default cwd)
	ClassPath:  (default classpath of current VM)
	Debug: on, off (default on)

    Creating a default temporary directory

    File defines a temp file facility, but this is only for files.
    I think we want a similar directory mechanism.
    We can do this as follows:

    1. Use the system property java.io.tmpdir
    2. create an instance of java.rmi.server.UID.
    3. Stringify the UID, which looks something like:

    -1cad2ab7:102d8b6f383:-8000

    or 

    e4b375b:102d8b81237:-8000

    4. Create the directory /tmp/d_ and use that for all
       file generation.
    5. Create /tmp/d_/src and /tmp/d_/classes for
       generated source and class files.

    Should we provide an API for compiling source code?
    I think not.  There are ways to do this already, and we
    just provide a PrintStream for generating the source.

Extending the API for modifying classes.

Class, Method, Local var

ClassInfo contains mostly the correct info.
Just need to make it modifiable in the case of the
interceptor.  Could change:
    - modifiers
    - name
    - superClass
    - impls
Through the ClassGenerator API:
    - add fields
    - add methods
    - add constructors
    - extend initializer
    - rename existing method
    - intercept field access
    - intercept method call

What this really says is just add setters to the API.
How does this actually work?

new CodeGenerator()
set interceptors
byte[] modifyClass( byte[] cls )
    Use ClassReader to read cls with a modifier visitor
    modifier visitor:
	visitClass:
	    - Construct a ClassGenerator corresponding to cls
	    - invoke class interceptor with ClassGenerator
	visitMethod:
	    - This will need to be multi-pass
	    - Can change name, exceptions only
	    - first pass:
		- record all visit calls to be replayed
		- initialize slotAllocator to include all current  
		  local variables as determined from visitLocalVariable
		  calls.
	    - can modify GETFIELD, PUTFIELD instructions through
	      visitFieldInsn
	    - can add local variables 

What about JavaDoc and Annotations?

TODO:

1. Method overload resolution
    PARTIAL algorithm implemented that uses simple first match.
2. More testing
3. Byte code generation for:
    - switch statement
    - add break 
    - operators in expressions
    - cast, instanceof
    - static field access
    - array index
4. Upgrade to latest ASM (probably wait until after ASM 3.0 goes FCS).
5. Remove use of JSR/RET.
6. Revise API into:
    spi.codegen: as is.
    spi.codegen.tree: move AST here, allow for construction of specialized visitors
    impl.codegen: source code visitor (in main branch)
    impl.codegen: byte code visitor (in optional branch)
    May also want to split up Wrapper to make more extensible.
7. Add support for re-opening _initializer().
8. Implement "dangling expression" handler.
    I think this (now) means detect expressions that have never
    been copied.  We actually need to modify NodeBase.copy to simply
    count the number of times copy is called.  We also need to keep a
    list in the ExpressionFactory of all expressions created.  Then when
    a block is ended, check that all expressions created have been copied,
    which means they have been used somewhere.  We also need to check
    when an Expression is used that is was created by the correct ExpressionFactory,
    or else we have an error (I don't want expression hanging around between
    different blocks).
9. Implement short-circuit evaluation of boolean operators.
    Note: consider implementing ternary if expression:
    A && B is equivalent to A ? B : false
    A || B is equivalent to A ? true : B
    then add an _ifExpr( Expression cond, Expression truePart, Expression falsePart ) 
    to Wrapper et al.  Could then replace && and || directly in Wrapper with
    _ifExpr.
    Can we use IfStatement to implement this?
    We can simple change IfStatement from

	class IfStatement extends StatementBase 

    to
	
	class IfStatement extends ExpressionFactory.ExpressionBase implements Statement

    and IfStatement becomes an expression.  The visitors would probably need some 
    adjustment, plus we need to deal with having a Node that is both a Statement and
    an Expression (or perhaps eliminate a separate if statement?).

    But this does not really work: consider

    IfStatement ( Expression cond, Statement truePart, Statement falsePart ) 

    and

    IfExpression ( Expression cond, Expression truePart, Expression falsePart )

    Also note that the stack is a bit different: at the end, and IfExpression leaves
    a value on the stack.  In any case, we just duplicate the simple logic of
    IfStatement for IfExpression in ASMByteCodeVisitor.  But again, I don't think this
    matters.

    This COULD work, if we decided to make every Statement an Expression, some of
    which return void.  But this is not very Java-like, and would imply changing
    the current statement = void _xxx call/expression = _xxx call returning Expression
    design.

10. Convert codegen test suite to TestNG.
11. Consider adding some form of enhanced for loop.
12. Make sure that we check that first statement in constructor is this or super.
13. Finish CodegenProxyCreator and replace BCEL with it.
DONE 14. Reduce/eliminate use of _v, _t.  Changes to Wrapper method return types:
    Type _import
    Expression _data
    Variable _arg
    Variable _catch
    Variable _define

    Note that this will cause Expressions to be reused.
    This means that expression need to be copied (very carefully).
    This is done in NodeBase using the @Copy extensions applied to
    NodeBase (attributes, parent, and delegate).
    This also required a modification in ASMSetupVisitor: make sure
    that requiredEmitterType is correctly set on ALL Variable nodes.
    This was not done correctly in the original: it relied on setting
    the value of requiredEmitterType to GETTER inside 
    BlockStatement.splitVariables.

    NOTE: THAT IS A VERY BAD IDEA!
    One of the design principles of this library is that the construction
    of the AST is totally separated from its use.  So any of the attributes
    needed by ASMSetupVisitor and ASMByteCodeVisitor should only be set up
    in those visitors.  BlockStatement.splitVariables was a general piece
    of code used in a specific way to support a particular visitor.  BAD
    DESIGN!

15. Modify IDLNameTranslator to use ClassInfo instead of Class,
    and MethodInfo instead of Method.
    This requires some other changes:
    - StubInvocationHandlerImpl takes a method as an argument.
      We need to get a MethodInfo object from the Method, and
      use that in the call to IDLNameTranslator to get the giopMethodName.
      We also need to base DynamicMethodMarshaller on MethodInfo instead
      of Method.
    - Similarly, ReflectiveTie._invoke gets a Method from the operation 
      name.  Here we actually need a real method (but not for DMM)
      for the invoke call.

    Plan:
	- IDLNameTranslator uses ClassInfo and MethodInfo.
	- MethodInfo provides access to Method IF the MethodInfo
	  was derived from a Method.
	- DMM only uses MethodInfo.

    This then allows rmic -iiop to directly use IDLNameTranslator to
    generate the appropriate names in the Stubs and Ties.

16. Ways to generate ClassInfo:
    1. From java.lang.Class
    2. From codegen ClassGenerator
    3. From Doclet (see com.sun.javadoc)

    probably want to create a FieldInfo that has implementation that
    reflect java.lang.reflect.Field, impl.codegen.Field, and 
    com.sun.javadoc.FieldDoc (similarly use MethodDoc and ClassDoc).
    (FieldInfo is in place now).

    Note how closely this relates to Gilad's mirrors paper.

17. Move BCEL optimized reflective object copier to codegen
    - continue optimization work
    - investigate transforming ClassLoader that adds useful 
      bits to class for copying (precursor to fast marshalling)

Other features:

18. Line number generation and debugging support.

23. Add line number generation and verify correct line numbers.
    Modify sourceStatementVisitor to annotate the AST with line number
    info while generating a source file, then modify the ASM visitor
    to generate the appropriate information.
    Also need to generate local variable tables.
    How do we verify line numbers?  By using ASM visitor on class file?
24. Tests for error handling:
    1. Detect dangling expressions, multiple expression use
    2. Check that concrete base classes have constructors
    3. check that every constructor starts with this or super
    4. Check that all referenced types exist
    5. Check that all type and variable names are not reserved words.
25. Consider extending model to support simultaneous generation of
    more than one class (needed for mutual recursive reference
    between classes).  
26. Consider extending AST for manipulation/modification of existing
    classes (initial generation -> continual modification)
27. Consider integration with java.lang.Instrument facilities.
28. Add Javadoc support: _javadoc( String... )
29. Support static import
30. Annotation support?




© 2015 - 2025 Weber Informatics LLC | Privacy Policy