[
https://issues.apache.org/jira/browse/GROOVY-10657?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18140792#comment-18140792
]
ASF GitHub Bot commented on GROOVY-10657:
-----------------------------------------
daniellansun commented on PR #3226:
URL: https://github.com/apache/groovy/pull/3226#issuecomment-6723607542
@blackdrag Thanks, you're right: the temporary in
`testSubscriptAssignment1` is unnecessary. I have removed the receiver and
index temporaries from plain subscript assignment. The receiver, index and RHS
are now evaluated directly in that order as the store arguments, so the
statement form needs neither a temporary nor a null-out.
When an array assignment is used as a value, the RHS is preserved on the
operand stack with `DUP_X2` (or `DUP2_X2` for `long`/`double`), before the
component conversion. A `putAt` assignment expression still needs to preserve
the RHS across the call, since the assignment must return the RHS rather than
`putAt`'s return value. That path retains one temporary and clears it
immediately afterwards; a stack-dup implementation cannot be shared directly
with the classic callsite backend because of its additional `CallSite` stack
operand.
Safe-subscript and compound-assignment evaluation behavior is unchanged. I
added bytecode assertions and regression checks for evaluation order and
assignment results, including primitive/reference arrays and category-2 values.
The targeted tests passed, including an indy-disabled run, as did Checkstyle
and CodeNarc. Full CI is still pending.
> Generated code for overloaded assignment operator prevents garbage collection
> -----------------------------------------------------------------------------
>
> Key: GROOVY-10657
> URL: https://issues.apache.org/jira/browse/GROOVY-10657
> Project: Groovy
> Issue Type: Bug
> Components: Compiler
> Affects Versions: 4.0.3
> Reporter: Jonathan Baxter
> Priority: Major
>
> The groovy code
> {code:java}
> obj["lhs"] = "rhs"{code}
> ostensibly converts to
> {code:java}
> obj.putAt("lhs","rhs")
> {code}
> if {{obj}} has the appropriate {{putAt}} method.
> However , in the process of tracking down a memory leak, I discovered that
> assignment is not exactly equivalent to invocation of the {{putAt}} method.
> Specifically, the code generated by the compiler is equivalent to creating an
> additional temporary variable to hold the rhs of the assignment, and then
> invoking the {{putAt}} method with that temporary variable as its second
> argument:
> {code:java}
> String string = "rhs"
> obj.putAt("lhs",string){code}
> The problem with this is that since {{"rhs"}} now has a live reference
> ({{{}string{}}}), it is not eligible for garbage collection.
> In my particular use case, {{"rhs"}} is a very large object that I would like
> to be automatically garbage collected after the assignment is executed, but
> before the script has finished. But that means I have to use the underlying
> {{putAt}} method rather than the assignment operator, which rather negates
> the benefits of overloading the assignment operator.
> One potential fix would be to simply null out any temporary variables
> constructed by the compiler, so that
> {code:java}
> obj["lhs"] = "rhs"
> {code}
> becomes
> {code:java}
> String string = "rhs"
> obj.putAt("lhs",string)
> string = null <----- "rhs" is now eligible for garbage-collection{code}
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)