From michael.haupt at oracle.com Sun Aug 2 14:31:04 2015 From: michael.haupt at oracle.com (Michael Haupt) Date: Sun, 2 Aug 2015 16:31:04 +0200 Subject: [9] RFR: 8060717: [TESTBUG] Improve test coverage of MethodHandles.explicitCastArguments() In-Reply-To: <55BBA449.1030603@oracle.com> References: <55BBA449.1030603@oracle.com> Message-ID: <0B7B1F71-0BE3-400E-A6C2-5FD01E13777A@oracle.com> Hi Konstantin, > Am 31.07.2015 um 18:37 schrieb Konstantin Shefov : > Please review a test improvement. Covered more cases for MethodHandles.explicitCastArguments(). > > Bug: https://bugs.openjdk.java.net/browse/JDK-8060717 > Webrev: http://cr.openjdk.java.net/~kshefov/8060717/webrev.00/ note that mine is a lower-case review and does not count, but: thumbs up. The level of detail at which the API is tested improves significantly with these changes. Best, Michael -- Dr. Michael Haupt | Principal Member of Technical Staff Phone: +49 331 200 7277 | Fax: +49 331 200 7561 Oracle Java Platform Group | LangTools Team | Nashorn Oracle Deutschland B.V. & Co. KG, Schiffbauergasse 14 | 14467 Potsdam, Germany Oracle is committed to developing practices and products that help protect the environment -------------- next part -------------- An HTML attachment was scrubbed... URL: From konstantin.shefov at oracle.com Mon Aug 3 15:06:53 2015 From: konstantin.shefov at oracle.com (Konstantin Shefov) Date: Mon, 03 Aug 2015 18:06:53 +0300 Subject: [9] RFR: 8060717: [TESTBUG] Improve test coverage of MethodHandles.explicitCastArguments() In-Reply-To: <0B7B1F71-0BE3-400E-A6C2-5FD01E13777A@oracle.com> References: <55BBA449.1030603@oracle.com> <0B7B1F71-0BE3-400E-A6C2-5FD01E13777A@oracle.com> Message-ID: <55BF838D.7080202@oracle.com> Michael, thanks for reviewing! Vladimir, could you take a look, please? -Konstantin On 08/02/2015 05:31 PM, Michael Haupt wrote: > Hi Konstantin, > >> Am 31.07.2015 um 18:37 schrieb Konstantin Shefov >> >: >> Please review a test improvement. Covered more cases for >> MethodHandles.explicitCastArguments(). >> >> Bug: https://bugs.openjdk.java.net/browse/JDK-8060717 >> Webrev: http://cr.openjdk.java.net/~kshefov/8060717/webrev.00/ >> > > note that mine is a lower-case review and does not count, but: thumbs > up. The level of detail at which the API is tested improves > significantly with these changes. > > Best, > > Michael > > -- > > Oracle > Dr. Michael Haupt | Principal Member of Technical Staff > Phone: +49 331 200 7277 | Fax: +49 331 200 7561 > OracleJava Platform Group | LangTools Team | Nashorn > Oracle Deutschland B.V. & Co. KG, Schiffbauergasse 14 | 14467 Potsdam, > Germany > Green Oracle Oracle is committed > to developing practices and products that help protect the environment > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From konstantin.shefov at oracle.com Thu Aug 6 09:52:19 2015 From: konstantin.shefov at oracle.com (Konstantin Shefov) Date: Thu, 06 Aug 2015 12:52:19 +0300 Subject: [9] RFR: 8060717: [TESTBUG] Improve test coverage of MethodHandles.explicitCastArguments() In-Reply-To: <55BF838D.7080202@oracle.com> References: <55BBA449.1030603@oracle.com> <0B7B1F71-0BE3-400E-A6C2-5FD01E13777A@oracle.com> <55BF838D.7080202@oracle.com> Message-ID: <55C32E53.1050704@oracle.com> Kindly reminder On 08/03/2015 06:06 PM, Konstantin Shefov wrote: > Michael, thanks for reviewing! > > Vladimir, could you take a look, please? > > -Konstantin > > On 08/02/2015 05:31 PM, Michael Haupt wrote: >> Hi Konstantin, >> >>> Am 31.07.2015 um 18:37 schrieb Konstantin Shefov >>> >: >>> Please review a test improvement. Covered more cases for >>> MethodHandles.explicitCastArguments(). >>> >>> Bug: https://bugs.openjdk.java.net/browse/JDK-8060717 >>> Webrev: http://cr.openjdk.java.net/~kshefov/8060717/webrev.00/ >>> >> >> note that mine is a lower-case review and does not count, but: thumbs >> up. The level of detail at which the API is tested improves >> significantly with these changes. >> >> Best, >> >> Michael >> >> -- >> >> Oracle >> Dr. Michael Haupt | Principal Member of Technical Staff >> Phone: +49 331 200 7277 | Fax: +49 331 200 7561 >> OracleJava Platform Group | LangTools Team | Nashorn >> Oracle Deutschland B.V. & Co. KG, Schiffbauergasse 14 | 14467 >> Potsdam, Germany >> Green Oracle Oracle is committed >> to developing practices and products that help protect the environment >> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From headius at headius.com Thu Aug 6 18:26:43 2015 From: headius at headius.com (Charles Oliver Nutter) Date: Thu, 6 Aug 2015 13:26:43 -0500 Subject: ClassValue rooting objects after it goes away? Message-ID: Pardon me if this has been discussed before, but we had a bug (with fix) reported today that seems to indicate that the JVM is rooting objects put into a ClassValue even if the ClassValue goes away. Here's the pull request: https://github.com/jruby/jruby/pull/3228 And here's one example of the root trace leading back to our JRuby runtime. All the roots appear to be VM-level code: https://dl.dropboxusercontent.com/u/9213410/class-values-leak.png Is this expected? If we have to stuff a WeakReference into the ClassValue it seriously diminishes its utility to us. - Charlie From forax at univ-mlv.fr Thu Aug 6 20:24:55 2015 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Thu, 06 Aug 2015 20:24:55 +0000 Subject: ClassValue rooting objects after it goes away? In-Reply-To: References: Message-ID: <61D7FA84-4758-478E-877A-AF811AC4CD16@univ-mlv.fr> No, it's not expected ! R?mi Le 6 ao?t 2015 20:26:43 CEST, Charles Oliver Nutter a ?crit : >Pardon me if this has been discussed before, but we had a bug (with >fix) reported today that seems to indicate that the JVM is rooting >objects put into a ClassValue even if the ClassValue goes away. > >Here's the pull request: https://github.com/jruby/jruby/pull/3228 > >And here's one example of the root trace leading back to our JRuby >runtime. All the roots appear to be VM-level code: > >https://dl.dropboxusercontent.com/u/9213410/class-values-leak.png > >Is this expected? If we have to stuff a WeakReference into the >ClassValue it seriously diminishes its utility to us. > >- Charlie >_______________________________________________ >mlvm-dev mailing list >mlvm-dev at openjdk.java.net >http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev From michael.haupt at oracle.com Fri Aug 7 11:04:02 2015 From: michael.haupt at oracle.com (Michael Haupt) Date: Fri, 7 Aug 2015 13:04:02 +0200 Subject: ClassValue rooting objects after it goes away? In-Reply-To: References: Message-ID: <3A83C9E2-184B-47D7-8F66-D817E98295DC@oracle.com> Hi Charles, the pull request mentions a class named Java7ClassValue - does this mean it's a Java 7 issue or is it reproducible on 8 and maybe even 9? Names can be misleading. ;-) To clarify: by what means is the ClassValue removed in the JRuby implementation? I agree this should not happen. Best, Michael > Am 06.08.2015 um 20:26 schrieb Charles Oliver Nutter : > > Pardon me if this has been discussed before, but we had a bug (with > fix) reported today that seems to indicate that the JVM is rooting > objects put into a ClassValue even if the ClassValue goes away. > > Here's the pull request: https://github.com/jruby/jruby/pull/3228 > > And here's one example of the root trace leading back to our JRuby > runtime. All the roots appear to be VM-level code: > > https://dl.dropboxusercontent.com/u/9213410/class-values-leak.png > > Is this expected? If we have to stuff a WeakReference into the > ClassValue it seriously diminishes its utility to us. > > - Charlie -- Dr. Michael Haupt | Principal Member of Technical Staff Phone: +49 331 200 7277 | Fax: +49 331 200 7561 Oracle Java Platform Group | LangTools Team | Nashorn Oracle Deutschland B.V. & Co. KG, Schiffbauergasse 14 | 14467 Potsdam, Germany Oracle is committed to developing practices and products that help protect the environment -------------- next part -------------- An HTML attachment was scrubbed... URL: From john.r.rose at oracle.com Tue Aug 25 22:30:00 2015 From: john.r.rose at oracle.com (John Rose) Date: Tue, 25 Aug 2015 15:30:00 -0700 Subject: What can we improve in JSR292 for Java 9? In-Reply-To: References: Message-ID: <7DD02FD4-A140-450E-B40D-E3F1BF754392@oracle.com> On Feb 25, 2015, at 6:29 PM, John Rose wrote: > > Maybe this is general enough: > > MHs.loop(init, predicate, body)(*a) > => { let i = init(*a); while (predicate(i, *a)) { i = body(i, *a); } return i; } > > ...where the type of i depends on init, and if init returns void then you > have a classic side-effect-only loop. FTR, I've been thinking more about this one, with help from Michael Haupt. The above loop is pretty good, except for a couple of things: 'i' ought to be tuple of loop-varying values, and the exit path needs a more general post-processing step, a "finalizer" that corresponds to the initializers that set up the loop variables. A generalized (linear) loop has two kinds of values flowing within it: loop-invariant and loop-varying. (The control predicate has a special role, but may be classed as loop-varying. The finalizer is also special, and loop-invariant.) Loop-varying values can be inputs, control values (array indices, etc.), and outputs, but can all, I think, be modeled as "step" functions using a common signature. This takes us to something like the C for-loop, but with a sprinkle of tuples, with a finishing bow around it to tie it up: for ((v1,v2,v3,?) = inits; predicate(v1?); (v1?) = step(v1?)) { ? }; return finish(v1?); Loop-local but invariant values can be modeled as non-updated loop variables, as in this C idiom: for (int i, limit = computeLimit(); i < limit; i++) ? Pure side effects can be modeled as void-valued step functions, so we want to allow void as a corner case for loop variable types. (I.e., where there is a step but not a value.) I don't want to make any more special provision for pure side effects (such as a unique Runnable-like "body" for a loop), both because it isn't necessary, and because it encourages sloppy side-effect-driven loops. If we allow each loop variable to have its own predicate and finalizer, we can properly model the effects of ordered guards and special early-exit paths. loop({init*}, {pred*}, {step*}, {fini*}) := lambda (arg*) { let var* = init*(arg*) for (;;) { for ((v,p,s,f) in (var*, pred*, step*, fini*)) if (!p(var*, arg*)) return f(var*, arg*) v = s(var*, arg*) // all vars help update each var } } } All invocations are exact. As a bonus we can easily derive post-checked loops (do-while), and time-shifted index variables (p++) simply by adding more variables and/or steps. Constraints on parameter and return types: - There must be the same number of inits, preds, steps, and finis. - There must be at least one input function (e.g., a pred, so that the loop has a chance to exit). - Parameter lists of the init functions must all be the same. - Parameter lists of the pred, step, and fini functions must all be the same. - Parameter lists of the step functions must be a suffix of the parameter lists of the init functions. - Parameters of the step functions must be the same as the return types of the init functions (with voids removed), followed by the common suffix. - Return types of the predicates must all be boolean. - Return types of the finalizers must all be the same (and can be void). - The return type of each init function must match the return type of the corresponding step function (a "var" type or void). The result, a looping method handle, has a return type taken from the finalizer function(s), and argument types taken from the init functions. The loop has one iteration variable for each non-void init/step function pair. Each step/pred/fini call takes all of the iteration variable values, followed by all the external (loop-invariant) arguments. No throws are caught by the loop; throws cause the loop to terminate abnormally. In some loops, such as "find first match", the predicate naturally follows the step function, because it needs to evaluate the result of the step. To model post-checks (and the classic do/while shape), a second "void-valued" loop variable is required: loop(...) := lambda (arg*) { let (var, _) = (null, void) for (;;) { if (_) return _ // trivial predicate: exit branch never taken var = s(_, arg*) // pick up next search key if (!p(var, arg*)) // did we find it? return f(var, arg*) // extract value from search key as needed _ = _(var, arg*) // void value, no side effect } } This variable-doubling could be compressed out if there were a further boolean (per pred/step pair) which says which order to run them in. To me this seems like too much ad hoc structure; such structure tends to creep over time as we discover other important patterns. I think it would be better to support optionality for common "no op" loop components, as follows: Optionalities: - If an init is null, a constant zero (or null/false/void) function is supplied by inspecting the return type of the corresponding step function. - If a pred is null, a constant "true" function is supplied. - If a step is null, a suitable identity function is supplied by inspecting the return type of the corresponding init function. - If a fini is null, a constant zero function is supplied based on a non-null fini; if all are null then void is assumed. - Missing parameters (of any function) corresponding to loop-invariant arg* values are silently filled in (as if by dropArguments). - Other missing parameters (of loop variables passed to non-init functions) are also silently filled in (as if by dropArguments). - However, all missing parameters must be supplied after the present parameters; they may not be "mixed into" present parameters. The missing-parameter rules are as with GWT and CE; they are easy for the runtime to implement and grossly inconvenient for users if absent. Perhaps they can be made a little more one-sided, by forcing the step functions (if present) to carry all arguments. Concrete type: MethodHandle loop(MethodHandle[] inits, MethodHandle[] preds, MethodHandle[] steps, MethodHandle[] finis); Another possibility would be to allow a free intermixing of any number of steps (var updates) with any other number of pred/fini pairs: MethodHandle loop({MethodHandle init, MethodHandle step || MethodHandle pred, MethodHandle fini}?); But, it is trivial to convert such a structure to the above structure by injecting nulls for the missing pairs, to make up a full set of quadruples. So I think the fixed-quadruple format is general enough without sacrificing expressiveness. Various convenience specializations are possible, but can all be code-generated via the general template. The bytecodes to be generated from the general template are obvious from the formula above, and will JIT well. Here are some examples: MethodHandle finderLoop(MethodHandle body, MethodHandle finder, MethodHandle fini=null); // do () { v = body(a*); } while (!finder(v,a*)); return fini(v,a*); MethodHandle cursorLoop(MethodHandle init, MethodHandle pred, MethodHandle body, MethodHandle step, MethodHandle fini); // for (v=init(a*); pred(v,a*); v=step(v,a*)) { body(v,a*); }; return fini(v,a*); MethodHandle countedLoop(int start=0, MethodHandle limit, int incr=1, MethodHandle init2, MethodHandle pred2, MethodHandle body2, MethodHandle fini=null); // for (v'=start, vlim=limit(a*), v2=init2(a*), v=v'; (v'++) From forax at univ-mlv.fr Wed Aug 26 13:06:40 2015 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Wed, 26 Aug 2015 13:06:40 +0000 Subject: What can we improve in JSR292 for Java 9? In-Reply-To: <7DD02FD4-A140-450E-B40D-E3F1BF754392@oracle.com> References: <7DD02FD4-A140-450E-B40D-E3F1BF754392@oracle.com> Message-ID: <1917D622-27D6-4A07-852F-256E8BC55CAC@univ-mlv.fr> Hi John, comment inlined Le 26 ao?t 2015 00:30:00 CEST, John Rose a ?crit : >On Feb 25, 2015, at 6:29 PM, John Rose wrote: >> >> Maybe this is general enough: >> >> MHs.loop(init, predicate, body)(*a) >> => { let i = init(*a); while (predicate(i, *a)) { i = body(i, *a); >} return i; } >> >> ...where the type of i depends on init, and if init returns void then >you >> have a classic side-effect-only loop. > >FTR, I've been thinking more about this one, with help from Michael >Haupt. > >The above loop is pretty good, except for a couple of things: 'i' ought >to be tuple of loop-varying values, and the exit path needs a more >general post-processing step, a "finalizer" that corresponds to the >initializers that set up the loop variables. > >A generalized (linear) loop has two kinds of values flowing within it: >loop-invariant and loop-varying. (The control predicate has a special >role, but may be classed as loop-varying. The finalizer is also >special, and loop-invariant.) Loop-varying values can be inputs, >control values (array indices, etc.), and outputs, but can all, I >think, be modeled as "step" functions using a common signature. > >This takes us to something like the C for-loop, but with a sprinkle of >tuples, with a finishing bow around it to tie it up: >for ((v1,v2,v3,?) = inits; predicate(v1?); (v1?) = step(v1?)) { ? }; >return finish(v1?); > >Loop-local but invariant values can be modeled as non-updated loop >variables, as in this C idiom: > for (int i, limit = computeLimit(); i < limit; i++) ? > >Pure side effects can be modeled as void-valued step functions, so we >want to allow void as a corner case for loop variable types. (I.e., >where there is a step but not a value.) I don't want to make any more >special provision for pure side effects (such as a unique Runnable-like >"body" for a loop), both because it isn't necessary, and because it >encourages sloppy side-effect-driven loops. > >If we allow each loop variable to have its own predicate and finalizer, >we can properly model the effects of ordered guards and special >early-exit paths. > >loop({init*}, {pred*}, {step*}, {fini*}) := lambda (arg*) { > let var* = init*(arg*) > for (;;) { > for ((v,p,s,f) in (var*, pred*, step*, fini*)) > if (!p(var*, arg*)) > return f(var*, arg*) > v = s(var*, arg*) // all vars help update each var > } > } >} > >All invocations are exact. > >As a bonus we can easily derive post-checked loops (do-while), and >time-shifted index variables (p++) simply by adding more variables >and/or steps. but i think i prefer to have pre and post updates instead of several predicates/finishers. Like this: loop({init*}, {prestep*}, {pred}, {poststep*}, {fini}) := lambda (arg*) { let var* = init*(arg*) for (;;) { foreach v in vars: v = prestep(var*, args*) if (!pred(var*, arg*)) return fini(var*, arg*) foreach v in vars: v = poststep(var*, args*) } it's less powerful but it seems you can encode all your examples of loops too. >Constraints on parameter and return types: >- There must be the same number of inits, preds, steps, and finis. >- There must be at least one input function (e.g., a pred, so that the >loop has a chance to exit). >- Parameter lists of the init functions must all be the same. >- Parameter lists of the pred, step, and fini functions must all be the >same. >- Parameter lists of the step functions must be a suffix of the >parameter lists of the init functions. >- Parameters of the step functions must be the same as the return types >of the init functions (with voids removed), followed by the common >suffix. >- Return types of the predicates must all be boolean. >- Return types of the finalizers must all be the same (and can be >void). >- The return type of each init function must match the return type of >the corresponding step function (a "var" type or void). > >The result, a looping method handle, has a return type taken from the >finalizer function(s), and argument types taken from the init >functions. The loop has one iteration variable for each non-void >init/step function pair. Each step/pred/fini call takes all of the >iteration variable values, followed by all the external >(loop-invariant) arguments. No throws are caught by the loop; throws >cause the loop to terminate abnormally. > >In some loops, such as "find first match", the predicate naturally >follows the step function, because it needs to evaluate the result of >the step. To model post-checks (and the classic do/while shape), a >second "void-valued" loop variable is required: > >loop(...) := lambda (arg*) { > let (var, _) = (null, void) > for (;;) { > if (_) return _ // trivial predicate: exit branch never taken > var = s(_, arg*) // pick up next search key > if (!p(var, arg*)) // did we find it? > return f(var, arg*) // extract value from search key as needed > _ = _(var, arg*) // void value, no side effect > } >} > >This variable-doubling could be compressed out if there were a further >boolean (per pred/step pair) which says which order to run them in. To >me this seems like too much ad hoc structure; such structure tends to >creep over time as we discover other important patterns. I think it >would be better to support optionality for common "no op" loop >components, as follows: > >Optionalities: >- If an init is null, a constant zero (or null/false/void) function is >supplied by inspecting the return type of the corresponding step >function. >- If a pred is null, a constant "true" function is supplied. >- If a step is null, a suitable identity function is supplied by >inspecting the return type of the corresponding init function. >- If a fini is null, a constant zero function is supplied based on a >non-null fini; if all are null then void is assumed. >- Missing parameters (of any function) corresponding to loop-invariant >arg* values are silently filled in (as if by dropArguments). >- Other missing parameters (of loop variables passed to non-init >functions) are also silently filled in (as if by dropArguments). >- However, all missing parameters must be supplied after the present >parameters; they may not be "mixed into" present parameters. > >The missing-parameter rules are as with GWT and CE; they are easy for >the runtime to implement and grossly inconvenient for users if absent. >Perhaps they can be made a little more one-sided, by forcing the step >functions (if present) to carry all arguments. > >Concrete type: > >MethodHandle loop(MethodHandle[] inits, MethodHandle[] preds, >MethodHandle[] steps, MethodHandle[] finis); > >Another possibility would be to allow a free intermixing of any number >of steps (var updates) with any other number of pred/fini pairs: > >MethodHandle loop({MethodHandle init, MethodHandle step || >MethodHandle pred, MethodHandle fini}?); > >But, it is trivial to convert such a structure to the above structure >by injecting nulls for the missing pairs, to make up a full set of >quadruples. So I think the fixed-quadruple format is general enough >without sacrificing expressiveness. > >Various convenience specializations are possible, but can all be >code-generated via the general template. The bytecodes to be generated >from the general template are obvious from the formula above, and will >JIT well. > >Here are some examples: > >MethodHandle finderLoop(MethodHandle body, MethodHandle finder, >MethodHandle fini=null); >// do () { v = body(a*); } while (!finder(v,a*)); return fini(v,a*); > >MethodHandle cursorLoop(MethodHandle init, MethodHandle pred, >MethodHandle body, MethodHandle step, MethodHandle fini); >// for (v=init(a*); pred(v,a*); v=step(v,a*)) { body(v,a*); }; return >fini(v,a*); > >MethodHandle countedLoop(int start=0, MethodHandle limit, int incr=1, >MethodHandle init2, MethodHandle pred2, MethodHandle body2, >MethodHandle fini=null); >// for (v'=start, vlim=limit(a*), v2=init2(a*), v=v'; (v'++)pred2(v,vlim,v2,a*); v=v') { v2=body2(v,vlim,v2,a*); }; return >fini(v,vlim,v2,a*); > >MethodHandle loop(MethodHandle[/*4*/]... quadOfInitPredStepFini); > >(What's your favorite loop? How well does it fit into this scheme?) > >Library functions for loop clauses (encoded as quads) might also be >interesting, but this starts to take us into territory where streams >can do a better job: > >MethodHandle[][] countedLoopClause(int start, MethodHandle limit, int >incr, MethodHandle[] moreClauses?) { >MethodHandle[] setLimitQuad = { limit, /*no pred/step/exit*/ null, >null, null }; >MethodHandle[] checkLimitQuad = { /*no init/pred*/ null, null, >Integer::compareLT, null }; > MethodHandle[][] res = new MethodHandle[2+moreClauses.length][]; > res[0] = setLimitQuad; res[1] = checkLimitQuad; > System.arraycopy(moreClauses, 0, res, 2, moreClauses.length); > return res; >} > >Not so good, that one. > >Anyway, my basic position here is that there ought to be a loop shape >which is (a) general enough to encode the normal special cases, and (b) >easy to generate into bytecodes. If we can build everything from that >one loop shape, our code generation and optimization will be made >easier to implement, hence more effective. > >And, I claim this is a worthwhile puzzle to puzzle on. > >? John R?mi From blackdrag at gmx.org Wed Aug 26 20:40:53 2015 From: blackdrag at gmx.org (Jochen Theodorou) Date: Wed, 26 Aug 2015 22:40:53 +0200 Subject: ClassValue rooting objects after it goes away? In-Reply-To: <3A83C9E2-184B-47D7-8F66-D817E98295DC@oracle.com> References: <3A83C9E2-184B-47D7-8F66-D817E98295DC@oracle.com> Message-ID: <55DE2455.3000006@gmx.org> Am 07.08.2015 13:04, schrieb Michael Haupt: > Hi Charles, > > the pull request mentions a class named Java7ClassValue - does this mean > it's a Java 7 issue or is it reproducible on 8 and maybe even 9? Names > can be misleading. ;-) > > To clarify: by what means is the ClassValue removed in the JRuby > implementation? > > I agree this should not happen. coming back on this and after spending the whole day on debugging a permgen issue (and Cedric actually 3 days) that seems to be related to this. I am not from the Ruby guess, so I will show the Groovy part. We discovered a permgen issue, that prevents the groovy runtime from unloading and the reason turned out to be ClassValue. We get a similar graphic Charles got, only a bit more complex. In my test scenario we load the Groovy runtime in an URLClassLoader, call a method to cause the runtime to initialize and then forget about it, just to do this again in a loop. What happens is that we get into a permgen problem, since the loader cannot be unloaded because ClassValue seems to keep classes from that loader to unload. I tested this with 7_60, 7_65, 8_25, and jdk1.9.0-ea-b68. All have this problem. As a special bonus we have a lot of system classes with added class values... for example all the primitive types. I suspected ClassValue earlier already and made myself a simple test but it seems the simple version is not going to show me what I want. So it is not as simple as having a classloader load a custom ClassValue class and have the classloader not unloading. Guess we will try the WeakReference vesion next as well... not that is a solution for us. bye blackdrag -- Jochen "blackdrag" Theodorou blog: http://blackdragsview.blogspot.com/ From forax at univ-mlv.fr Wed Aug 26 22:54:10 2015 From: forax at univ-mlv.fr (Remi Forax) Date: Thu, 27 Aug 2015 00:54:10 +0200 (CEST) Subject: ClassValue rooting objects after it goes away? In-Reply-To: <55DE2455.3000006@gmx.org> References: <3A83C9E2-184B-47D7-8F66-D817E98295DC@oracle.com> <55DE2455.3000006@gmx.org> Message-ID: <2048864869.651852.1440629650730.JavaMail.zimbra@u-pem.fr> Hi Jochen, what you can try is to use this code written by Jerome Pilliet as replacement of ClassValue (using -Xbootclasspath/p) https://bitbucket.org/jpilliet/libcore-292/src/tip/libdvm/src/main/java/java/lang/ClassValue.java?at=4.4.3.292 to see if you can reproduce your bug or not with this other implementation of ClassValue (under Apache Licence). Note that i hope that this implementation works but it's clearly haven't been battletested, nevertheless if you can not reproduce your issue, it means that this is clearly a bug in the OpenJDK implementation. regards, R?mi ----- Mail original ----- De: "Jochen Theodorou" ?: "Da Vinci Machine Project" Envoy?: Mercredi 26 Ao?t 2015 22:40:53 Objet: Re: ClassValue rooting objects after it goes away? Am 07.08.2015 13:04, schrieb Michael Haupt: > Hi Charles, > > the pull request mentions a class named Java7ClassValue - does this mean > it's a Java 7 issue or is it reproducible on 8 and maybe even 9? Names > can be misleading. ;-) > > To clarify: by what means is the ClassValue removed in the JRuby > implementation? > > I agree this should not happen. coming back on this and after spending the whole day on debugging a permgen issue (and Cedric actually 3 days) that seems to be related to this. I am not from the Ruby guess, so I will show the Groovy part. We discovered a permgen issue, that prevents the groovy runtime from unloading and the reason turned out to be ClassValue. We get a similar graphic Charles got, only a bit more complex. In my test scenario we load the Groovy runtime in an URLClassLoader, call a method to cause the runtime to initialize and then forget about it, just to do this again in a loop. What happens is that we get into a permgen problem, since the loader cannot be unloaded because ClassValue seems to keep classes from that loader to unload. I tested this with 7_60, 7_65, 8_25, and jdk1.9.0-ea-b68. All have this problem. As a special bonus we have a lot of system classes with added class values... for example all the primitive types. I suspected ClassValue earlier already and made myself a simple test but it seems the simple version is not going to show me what I want. So it is not as simple as having a classloader load a custom ClassValue class and have the classloader not unloading. Guess we will try the WeakReference vesion next as well... not that is a solution for us. bye blackdrag -- Jochen "blackdrag" Theodorou blog: http://blackdragsview.blogspot.com/ _______________________________________________ mlvm-dev mailing list mlvm-dev at openjdk.java.net http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev From john.r.rose at oracle.com Wed Aug 26 23:28:20 2015 From: john.r.rose at oracle.com (John Rose) Date: Wed, 26 Aug 2015 16:28:20 -0700 Subject: What can we improve in JSR292 for Java 9? In-Reply-To: <1917D622-27D6-4A07-852F-256E8BC55CAC@univ-mlv.fr> References: <7DD02FD4-A140-450E-B40D-E3F1BF754392@oracle.com> <1917D622-27D6-4A07-852F-256E8BC55CAC@univ-mlv.fr> Message-ID: On Aug 26, 2015, at 6:06 AM, R?mi Forax wrote: > > it's less powerful but it seems you can encode all your examples of loops too. No, I don't think so. Multiple pred/fini pairs implement multiple loop exits. Any loop with an "if-return" in it has an exit distinct from the loop's main test. And each exit requires a different fini function, to encode a special result. The match loop has this multi-exit character: for (int i; i < a.len; i++) { Object e = a[i]; if (ok(e)) return e; // first fini function; could also be e.payload } return null; // second fini function; could also be throwNotFound or Optional.none Sometimes even "&&" type predicate logic expands into multi-exit code, if the loop needs to return a value that encodes which sub-predicate caused the exit. ? John -------------- next part -------------- An HTML attachment was scrubbed... URL: From forax at univ-mlv.fr Thu Aug 27 00:33:01 2015 From: forax at univ-mlv.fr (Remi Forax) Date: Thu, 27 Aug 2015 02:33:01 +0200 (CEST) Subject: What can we improve in JSR292 for Java 9? In-Reply-To: References: <7DD02FD4-A140-450E-B40D-E3F1BF754392@oracle.com> <1917D622-27D6-4A07-852F-256E8BC55CAC@univ-mlv.fr> Message-ID: <475350918.655043.1440635581359.JavaMail.zimbra@u-pem.fr> yes, you're right, so if think i prefer to 'allow a free intermixing of any number of steps (var updates) with any other number of pred/fini pairs' which requires less brain power to understand that the double encoding you are proposing :) Something like: public interface InnerLoopBuilder { // variableIndex in [0..inits.length[ void addVariableUpdate(int variableIndex, MethodHandle step); void addLoopExit(MethodHandle predicate, MethodHandle finisher); } MethodHandle loopMH(MethodHandle[] inits, Consumer consumer) { ... } cheers, R?mi ----- Mail original ----- De: "John Rose" ?: "R?mi Forax" Cc: "Da Vinci Machine Project" Envoy?: Jeudi 27 Ao?t 2015 01:28:20 Objet: Re: What can we improve in JSR292 for Java 9? On Aug 26, 2015, at 6:06 AM, R?mi Forax < forax at univ-mlv.fr > wrote: it's less powerful but it seems you can encode all your examples of loops too. No, I don't think so. Multiple pred/fini pairs implement multiple loop exits. Any loop with an "if-return" in it has an exit distinct from the loop's main test. And each exit requires a different fini function, to encode a special result. The match loop has this multi-exit character: for (int i; i < a.len; i++) { Object e = a[i]; if (ok(e)) return e; // first fini function; could also be e.payload } return null; // second fini function; could also be throwNotFound or Optional.none Sometimes even "&&" type predicate logic expands into multi-exit code, if the loop needs to return a value that encodes which sub-predicate caused the exit. ? John -------------- next part -------------- An HTML attachment was scrubbed... URL: From blackdrag at gmx.org Thu Aug 27 09:28:53 2015 From: blackdrag at gmx.org (Jochen Theodorou) Date: Thu, 27 Aug 2015 11:28:53 +0200 Subject: ClassValue rooting objects after it goes away? In-Reply-To: <2048864869.651852.1440629650730.JavaMail.zimbra@u-pem.fr> References: <3A83C9E2-184B-47D7-8F66-D817E98295DC@oracle.com> <55DE2455.3000006@gmx.org> <2048864869.651852.1440629650730.JavaMail.zimbra@u-pem.fr> Message-ID: <55DED855.9040505@gmx.org> Am 27.08.2015 00:54, schrieb Remi Forax: > Hi Jochen, > what you can try is to use this code written by Jerome Pilliet as replacement of ClassValue (using -Xbootclasspath/p) > https://bitbucket.org/jpilliet/libcore-292/src/tip/libdvm/src/main/java/java/lang/ClassValue.java?at=4.4.3.292 > to see if you can reproduce your bug or not with this other implementation of ClassValue (under Apache Licence). > > Note that i hope that this implementation works but it's clearly haven't been battletested, > nevertheless if you can not reproduce your issue, it means that this is clearly a bug in the OpenJDK implementation. I have not tried that yet. But Henry Tremblay came up with a more simple solution for the testing scenario. Our old ClassValue class was this: public class GroovyClassValueJava7 extends ClassValue implements GroovyClassValue { private final ComputeValue computeValue; private Map, T> cache = new HashMap, T>(); public GroovyClassValueJava7(ComputeValue computeValue){ this.computeValue = computeValue; } @Override protected T computeValue(Class type) { return computeValue.computeValue(type); } } and the suggestion was to move the caching out of ClassValue internals and into a simple map: public class GroovyClassValueJava7 extends ClassValue implements GroovyClassValue { private final ComputeValue computeValue; private Map, T> cache = new HashMap, T>(); public GroovyClassValueJava7(ComputeValue computeValue){ this.computeValue = computeValue; } @Override protected T computeValue(Class type) { return computeValue.computeValue(type); } @Override public T get(Class type) { T t = cache.get(type); if(t == null) { t = computeValue(type); cache.put(type, t); } return t; } @Override public void remove(Class type) { cache.remove(type); } } Of course this is no proper replacement, since it is far from threadsafe and all, but it makes the test scenario work. anyway... doesn't this also mean a OpenJDK bug? bye blackdrag -- Jochen "blackdrag" Theodorou blog: http://blackdragsview.blogspot.com/ From blackdrag at gmx.org Thu Aug 27 09:54:37 2015 From: blackdrag at gmx.org (Jochen Theodorou) Date: Thu, 27 Aug 2015 11:54:37 +0200 Subject: ClassValue rooting objects after it goes away? In-Reply-To: <2048864869.651852.1440629650730.JavaMail.zimbra@u-pem.fr> References: <3A83C9E2-184B-47D7-8F66-D817E98295DC@oracle.com> <55DE2455.3000006@gmx.org> <2048864869.651852.1440629650730.JavaMail.zimbra@u-pem.fr> Message-ID: <55DEDE5D.1090405@gmx.org> Hi, In trying to reproduce the problem outside of Groovy I stumbled over a case case which I think should work public class MyClassValue extends ClassValue { protected Object computeValue(Class type) { Dummy ret = new Dummy(); Dummy.l.add (this); return ret; } } class Dummy { static final ArrayList l = new ArrayList(); } basically this means there will be a hard reference on the ClassValue somewhere. It can be in a static or non-static field, direct or indirect. But this won't collect. If I put for example a WeakReference in between it works again. Finally I also tested to put the hard reference in a third class instead, to avoid this self reference. But it can still not collect. So I currently have the impression that if anything holds a hard reference on the class value that the classloader cannot be collected anymore. Unless I misunderstand something here I see that as a bug bye blackdrag -- Jochen "blackdrag" Theodorou blog: http://blackdragsview.blogspot.com/ From blackdrag at gmx.org Thu Aug 27 11:34:09 2015 From: blackdrag at gmx.org (Jochen Theodorou) Date: Thu, 27 Aug 2015 13:34:09 +0200 Subject: ClassValue rooting objects after it goes away? In-Reply-To: <55DEDE5D.1090405@gmx.org> References: <3A83C9E2-184B-47D7-8F66-D817E98295DC@oracle.com> <55DE2455.3000006@gmx.org> <2048864869.651852.1440629650730.JavaMail.zimbra@u-pem.fr> <55DEDE5D.1090405@gmx.org> Message-ID: <55DEF5B1.8080501@gmx.org> One more thing... Remi, I tried your link with my simplified scenario and it does there not stop the collection of the classloader Am 27.08.2015 11:54, schrieb Jochen Theodorou: > Hi, > > In trying to reproduce the problem outside of Groovy I stumbled over a > case case which I think should work > > public class MyClassValue extends ClassValue { > protected Object computeValue(Class type) { > Dummy ret = new Dummy(); > Dummy.l.add (this); > return ret; > } > } > > class Dummy { > static final ArrayList l = new ArrayList(); > } > > basically this means there will be a hard reference on the ClassValue > somewhere. It can be in a static or non-static field, direct or > indirect. But this won't collect. If I put for example a WeakReference > in between it works again. > > Finally I also tested to put the hard reference in a third class > instead, to avoid this self reference. But it can still not collect. > > So I currently have the impression that if anything holds a hard > reference on the class value that the classloader cannot be collected > anymore. > > Unless I misunderstand something here I see that as a bug > > bye blackdrag > -- Jochen "blackdrag" Theodorou blog: http://blackdragsview.blogspot.com/ From john.r.rose at oracle.com Sat Aug 29 01:40:15 2015 From: john.r.rose at oracle.com (John Rose) Date: Fri, 28 Aug 2015 18:40:15 -0700 Subject: invokespecial-super-init In-Reply-To: <54EEF516.6070800@gmx.org> References: <54EEF516.6070800@gmx.org> Message-ID: The invokespecial-super-init dance is the thing MH's can't quite do, the "super" call every constructor (except Object.). It very hard to secure this pattern; just ask anybody who has worked on (de-)serialization security. But, we can look at it from a more limited point of view which might improve your use case, Jochen. A method handle is supposed to be a fully competent replacement for hardwired bytecodes, and it is, except for invokespecial-super from a constructor. The reason this is hard is that there is no way to constrain such a method handle, once constructed, to operate inside a constructor. And superclasses have a right to expect that you are running their constructor as a unique, non-repeatable part of creating a subclass object. (By "have a right" I really mean "it would be wrong to do the unexpected" by which I also mean "attack surfaces are likely to open up if we do this.) So, is there a way to package up a method handle so that it can only be used as as unique, non-repeatable part of creating a subclass object? Yes, it can: Wire in an unconditional "new instance" operation, and immediately run the "invokespecial super" on the new thing. Now the problem reduces to: Your class (just like its super) has a right to expect that constructor code will be run on every newly-created instance (after the super constructor), before the new object is made available to other code. Can we package up the previous new-invokespecial-super method handle so it can only be used in this way? Well, no, since every constructor *also* has a hardwired call to invokespecial; we are back to the pre-existing new-invokespecial type of MH. There are several possible ways out, but the problem is delicate. The purpose of constructors is to statically mark code that must be executed before any (normally published) reference to an object is reachable by non-class code. If there were a way to statically mark code as "post-super-init" (""?), we could make an agreement with a class that such a method would serve as the equivalent of a constructor, but it would be the caller's responsibility to allocate the new instance *and* call the super init. Allowing bytecode to call this stuff would require a bunch of new verifier rules, in a place where the verifier is already hard to understand. Perhaps a method handle could be allowed to operate where normal bytecode cannot, but you see the problem: Method handles are designed to give a dynamic alternative to things you can already do in bytecode. The "post-super-init" convention can be a private convention within a class, in the special case of Groovy, since Groovy is responsible for generating the whole class, and can trust itself to invoke all necessary initialization code on each new instance. So if you had an new-invokespecial-super MH in a private context within a Groovy-generated class, you could use it to create a "mostly blank" instance, and then fill it in before sharing it with anybody else. Such an invokespecial-super MH could be adequately protected from other users by requiring that "Lookup.findSpecialConstructor" can only work on full-powered lookups, regardless of the accessibility of the super constructor. There are two further problems with this, though. First, constructors have a unique ability and obligation to initialize blank final variables (the non-static ones). So the Lookup.findSpecialConstructor MH has to take an argument, not just for its super-constructor, but also for *each* final variable in the *current* class. (Note that Lookup.findSetter will *not* allow finals to be set, because it cannot prove that the caller is somehow "inside" a constructor, and, even if inside it, is trustably acting on behalf of it.) There are other ways to go, but you can see this problem too: The new-invokespecial operator has to take responsibility for working with the caller to fill in the blank finals. The second further problem is even more delicate. The JVM enforces rules of calling even (sometimes) against the wishes of people who generate class files. We don't fully understand the practical effects of relaxing these rules. Proofs of assertions (such as type correctness and security) require strong premises, and the rigid rules about help provide such premises. An example of a proof-failure would be somebody looking at a class, ensuring that all instances are secure based on the execution of methods, but then fail to notice that the class *also* runs some instances through an alternate path, using new-invokespecial-super, which invalidates the proof by failing to run some crucial setup code. With all that said, there is still wiggle room. For example, one *possible* solution that might help Groovy, while being restrictive enough to avoid the problems above, would be to split methods and sew them together again with method handles. Suppose there were a reliable way to "split" an method into two parts: Everything up to the invokespecial-super- call, and everything afterwards. (Perhaps it must be preceded *only* by load-from-local opcodes.) Call such methods "splittable". Not all will be splittable. Then we could consider allowing a class to replace one of its splittable constructors by a new hybrid consisting of a differently-selected super-constructor, followed by the tail of the splittable constructor. (Note that this neatly handles blank finals.) It would not be valid for any party other than the sub-class itself to perform such a split, but it might, arguably, be reasonable for a class to do such a thing. There are always many defects with such schemes. In this case, there is no robust way to detect that a splittable constructor has in fact been split. (I keep wanting to invent new bytecodes or verifier rules here!) Any rule for splittability is going to be a little hacky, hence hard to understand and use correctly. Specific constructors might be "coupled" strongly to matching super-constructors, in such a way that a mix-and-match will cause surprises, even to the author of the subclass. (Having stuff happen by invisible magic gets old, as soon as you realize you have to vouch for the behavior of code which you can really only see in source form.) Finally (as noted above) MHs are quite robustly understanable from the principle that they are "just another way" to do what bytecodes have already done; violating this principle pushes uncertainties into equivalence proofs about MHs and bytecodes. In the end, I think Groovy may be better off using its ugly bytecode sequence, where every subclass constructor calls (via a switch) every superclass constructor. I hope this helps, although it's kind of disappointing. We ran into same dangerous dance, in the Valhalla bytecode interpreter, and had to fake it from random bits of the MH runtime. ? John On Feb 26, 2015, at 2:27 AM, Jochen Theodorou wrote: > > Am 26.02.2015 01:02, schrieb Charles Oliver Nutter: >> After talking with folks at the Jfokus VM Summit, it seems like >> there's a number of nice-to-have and a few need-to-have features we'd >> like to see get into java.lang.invoke. Vladimir suggested I start a >> thread on these features. > > my biggest request: allow the call of a super constructor (like super(foo,bar)) using MethodHandles an have it understood by the JVM like a normal super constructor call... same for this(...) > > Because what we currently do is annoying and a major pita, plus it bloats the bytecode we have to produce. And let us better not talk about speed or the that small verifier change that made our hack unusable in several java update versions for 7 and 8. > > This has been denied in the past because of security reasons... And given that we need dynamic argument types to determine the constructor to be called, and since that we have to do a call from the runtime in the uncached case, I fully understand why this is not done... just... it would be nice to have a solution that does not require us doing basically a big switch table with several invokespecial calls > > bye Jochen > > -- > Jochen "blackdrag" Theodorou - Groovy Project Tech Lead > blog: http://blackdragsview.blogspot.com/ > german groovy discussion newsgroup: de.comp.lang.misc > For Groovy programming sources visit http://groovy-lang.org > > _______________________________________________ > mlvm-dev mailing list > mlvm-dev at openjdk.java.net > http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev From blackdrag at gmx.org Sat Aug 29 08:42:54 2015 From: blackdrag at gmx.org (Jochen Theodorou) Date: Sat, 29 Aug 2015 10:42:54 +0200 Subject: invokespecial-super-init In-Reply-To: References: <54EEF516.6070800@gmx.org> Message-ID: <55E1708E.30009@gmx.org> hi John, thanks for replying... After having read that, I think part of the problem actually comes from this new-invokespecial-super being split in two bytecodes. It means there can be a lot of things in between, including different paths. This makes the Verifier difficult. The other part is that I need to react to runtime types. Currently this is only possible by using a generic handle, that will install the real target later on... With the problem, that the first call of the target is done from inside the generic handle, instead of the callsite. In terms of object creation, this means I will have access to the object, and in case of super-init-calls it would mean me having access to a not fully initialized class and potentially doing bad things here. And that is even though I don't even need a handle that returns something. But since there is no real connection between slot 0 of the constructor I am in and the generic handle But I wonder if there is really no way around that. Let me construct something crazy here... What would be if we had a dummy object instead? Let us call it GenericInstance for now. Generic Instance is internally connected to the partially generated class, but has no fields or methods offering access to it. The only way to create a GenericInstance would be by a factory method, from the indy API, like findSpecialConstructor or such. I would define the signature that it returns the GenericInstance. The handle itself is supposed to realize a new-"transform arguments"-invokeSpecial kind of sequence. The Verifier thus needs to acknowledge it to do that. And there needs to be code, that takes the result of the GenericInstance and then places the real instance in variable slot 0. Since it is a two fold mechanism I cannot programatically do anything with the GenericInstance object, but to reach it through. Only the part unwrapping it can access the real instance (and also check the class to be sure) and that would be VM code. I think this way splitting the method or have a constructor equivalent is not required... but I am not sure something like GenericInstance can be done. In pure Java probably not bye jochen Am 29.08.2015 03:40, schrieb John Rose: > The invokespecial-super-init dance is the thing MH's can't quite do, the "super" call every constructor (except Object.). > > It very hard to secure this pattern; just ask anybody who has worked on (de-)serialization security. > > But, we can look at it from a more limited point of view which might improve your use case, Jochen. > > A method handle is supposed to be a fully competent replacement for hardwired bytecodes, and it is, except for invokespecial-super from a constructor. The reason this is hard is that there is no way to constrain such a method handle, once constructed, to operate inside a constructor. And superclasses have a right to expect that you are running their constructor as a unique, non-repeatable part of creating a subclass object. (By "have a right" I really mean "it would be wrong to do the unexpected" by which I also mean "attack surfaces are likely to open up if we do this.) > > So, is there a way to package up a method handle so that it can only be used as as unique, non-repeatable part of creating a subclass object? Yes, it can: Wire in an unconditional "new instance" operation, and immediately run the "invokespecial super" on the new thing. > > Now the problem reduces to: Your class (just like its super) has a right to expect that constructor code will be run on every newly-created instance (after the super constructor), before the new object is made available to other code. Can we package up the previous new-invokespecial-super method handle so it can only be used in this way? Well, no, since every constructor *also* has a hardwired call to invokespecial; we are back to the pre-existing new-invokespecial type of MH. > > There are several possible ways out, but the problem is delicate. The purpose of constructors is to statically mark code that must be executed before any (normally published) reference to an object is reachable by non-class code. If there were a way to statically mark code as "post-super-init" (""?), we could make an agreement with a class that such a method would serve as the equivalent of a constructor, but it would be the caller's responsibility to allocate the new instance *and* call the super init. Allowing bytecode to call this stuff would require a bunch of new verifier rules, in a place where the verifier is already hard to understand. Perhaps a method handle could be allowed to operate where normal bytecode cannot, but you see the problem: Method handles are designed to give a dynamic alternative to things you can already do in bytecode. > > The "post-super-init" convention can be a private convention within a class, in the special case of Groovy, since Groovy is responsible for generating the whole class, and can trust itself to invoke all necessary initialization code on each new instance. So if you had an new-invokespecial-super MH in a private context within a Groovy-generated class, you could use it to create a "mostly blank" instance, and then fill it in before sharing it with anybody else. Such an invokespecial-super MH could be adequately protected from other users by requiring that "Lookup.findSpecialConstructor" can only work on full-powered lookups, regardless of the accessibility of the super constructor. > > There are two further problems with this, though. First, constructors have a unique ability and obligation to initialize blank final variables (the non-static ones). So the Lookup.findSpecialConstructor MH has to take an argument, not just for its super-constructor, but also for *each* final variable in the *current* class. (Note that Lookup.findSetter will *not* allow finals to be set, because it cannot prove that the caller is somehow "inside" a constructor, and, even if inside it, is trustably acting on behalf of it.) There are other ways to go, but you can see this problem too: The new-invokespecial operator has to take responsibility for working with the caller to fill in the blank finals. > > The second further problem is even more delicate. The JVM enforces rules of calling even (sometimes) against the wishes of people who generate class files. We don't fully understand the practical effects of relaxing these rules. Proofs of assertions (such as type correctness and security) require strong premises, and the rigid rules about help provide such premises. An example of a proof-failure would be somebody looking at a class, ensuring that all instances are secure based on the execution of methods, but then fail to notice that the class *also* runs some instances through an alternate path, using new-invokespecial-super, which invalidates the proof by failing to run some crucial setup code. > > With all that said, there is still wiggle room. For example, one *possible* solution that might help Groovy, while being restrictive enough to avoid the problems above, would be to split methods and sew them together again with method handles. > > Suppose there were a reliable way to "split" an method into two parts: Everything up to the invokespecial-super- call, and everything afterwards. (Perhaps it must be preceded *only* by load-from-local opcodes.) Call such methods "splittable". Not all will be splittable. Then we could consider allowing a class to replace one of its splittable constructors by a new hybrid consisting of a differently-selected super-constructor, followed by the tail of the splittable constructor. (Note that this neatly handles blank finals.) It would not be valid for any party other than the sub-class itself to perform such a split, but it might, arguably, be reasonable for a class to do such a thing. > > There are always many defects with such schemes. In this case, there is no robust way to detect that a splittable constructor has in fact been split. (I keep wanting to invent new bytecodes or verifier rules here!) Any rule for splittability is going to be a little hacky, hence hard to understand and use correctly. Specific constructors might be "coupled" strongly to matching super-constructors, in such a way that a mix-and-match will cause surprises, even to the author of the subclass. (Having stuff happen by invisible magic gets old, as soon as you realize you have to vouch for the behavior of code which you can really only see in source form.) Finally (as noted above) MHs are quite robustly understanable from the principle that they are "just another way" to do what bytecodes have already done; violating this principle pushes uncertainties into equivalence proofs about MHs and bytecodes. > > In the end, I think Groovy may be better off using its ugly bytecode sequence, where every subclass constructor calls (via a switch) every superclass constructor. > > I hope this helps, although it's kind of disappointing. We ran into same dangerous dance, in the Valhalla bytecode interpreter, and had to fake it from random bits of the MH runtime. > > ? John > > On Feb 26, 2015, at 2:27 AM, Jochen Theodorou wrote: >> >> Am 26.02.2015 01:02, schrieb Charles Oliver Nutter: >>> After talking with folks at the Jfokus VM Summit, it seems like >>> there's a number of nice-to-have and a few need-to-have features we'd >>> like to see get into java.lang.invoke. Vladimir suggested I start a >>> thread on these features. >> >> my biggest request: allow the call of a super constructor (like super(foo,bar)) using MethodHandles an have it understood by the JVM like a normal super constructor call... same for this(...) >> >> Because what we currently do is annoying and a major pita, plus it bloats the bytecode we have to produce. And let us better not talk about speed or the that small verifier change that made our hack unusable in several java update versions for 7 and 8. >> >> This has been denied in the past because of security reasons... And given that we need dynamic argument types to determine the constructor to be called, and since that we have to do a call from the runtime in the uncached case, I fully understand why this is not done... just... it would be nice to have a solution that does not require us doing basically a big switch table with several invokespecial calls >> >> bye Jochen >> >> -- >> Jochen "blackdrag" Theodorou - Groovy Project Tech Lead >> blog: http://blackdragsview.blogspot.com/ >> german groovy discussion newsgroup: de.comp.lang.misc >> For Groovy programming sources visit http://groovy-lang.org >> >> _______________________________________________ >> mlvm-dev mailing list >> mlvm-dev at openjdk.java.net >> http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev > -- Jochen "blackdrag" Theodorou blog: http://blackdragsview.blogspot.com/