Stop Coding!

The Unofficial Flex Compiler Blog

How -omit-trace-statements Works… Or Does NOT…

with 18 comments

Flex 4 introduces a new compiler option, –compiler.omit-trace-statements. The purpose of this compiler option is to remove trace() calls from your code when compiling in release (not debug) mode.

How does this work? Well, let’s take a look at the compiler code. First of all, where should you start? Usually, when trying to track down how a compiler option works, one would start from where the compiler option is set. If you have the compiler code, look for a method called 'cfgOmitTraceStatements' in CompilerConfiguration.java. Basically, the fully-qualified compiler option name kinda gives you the hint!

From there, you can search for all the references to 'omitTraceStatements' in the compiler code and eventually, you should end up in a file called NodeFactory.java in the actionscript compiler.

The callExpression method is responsible for constructing a syntax tree node that represents a function call in your code. In fact, almost all methods in NodeFactory.java are helper methods, responsible for syntax tree constructions. You can see in the code that if –omit-trace-statements is true and if the function call is trace(), the callExpression method simply skips the syntax tree node creation and return an empty statement.

Now, this implementation puzzles me!

The problem I have with this implementation is that it is done too early in the compilation. When constructing a syntax tree, the compiler has not yet done any analysis on the code and has not yet resolved the trace() call to the player built-in trace() function. To test my theory, I use a simple example:

When compiled with –omit-trace-statements=false, the test case changes the label text from 'Label' to 'foobar'. That means, the compiler resolves the trace() call to the local function, not the player built-in trace(). Now, turn on the trace statement omission:

The compiler skips over the syntax tree node generation for the click event handler.

I set a breakpoint on the green line above and verified what is being skipped over is in fact the trace() call in the click event handler.

As a result, the compiler generates an incorrect SWF. The label text does not change from 'Label' to 'foobar' when the button is clicked…

Conceptually speaking, I consider the –omit-trace-statements implementation totally busted!

In my opinion, the implementation should be done during code generation. Everything should be resolved right before code generation, so when the compiler traverses the tree one last time, it can use the compiler option there to skip the bytecode generation.

Practically speaking though, the current implementation maybe okay because no one does anything like I did in the trick test case above.

Hope you enjoy the trip down the compiler lane… 🙂

Advertisements

Written by Clement Wong

April 21, 2010 at 1:18 pm

18 Responses

Subscribe to comments with RSS.

  1. “mute” could be a better term then “omit” in this case.

    Another explanation could be added to this post.

    What is generated? MXML files are converted to actionscripts file. Use -keep and look at the code generated before getting compile.

    I see in Flex Builder 3:

    binding = new mx.binding.Binding(this,
    function():String
    {
    var result:* = (trace(‘test’));

    var destination:*;
    [Binding(id=’0′)]
    destination = (trace(‘test’));

    This mean the trace statement is binded to your property label, and MXML conversion do stuff that cannot be easily undone but could be muted along the way.

    Then the compiler does its muting with –compiler.omit-trace-statements.

    I think this function does a good job at “omitting” what is actually in all your traces and quite gracefully by not breaking other stuff (weird binding for example). Unless you put some application logic in trace statement.

    Thanks for the post!

    Guillaume Malartre

    April 21, 2010 at 5:28 pm

  2. Sorry I did not do exactly your click example. My -keep is generated from a simple:

    Guillaume Malartre

    April 21, 2010 at 5:29 pm

  3. Nice catch, but don’t you think it would have been easier to just file a bug? You could have even included a patch since you know the code so well. 🙂

    Paul Reilly

    April 22, 2010 at 9:17 am

    • Ladies and Gentlemen,

      Paul is in the house!! And yes, I gave his comment a big thumbs up!

      Hey Paul,

      I’ll file a bug report shortly. But I tell you what, the more I look at this, the more I dislike the lack of support of this compiler option in Flash Builder. Based on how it’s implemented in the compiler, it is ignored in debug mode. You know in Flash Builder, compilations are always done in debug mode by default. That means, specifying -omit-trace-statements=true alone as the “Additional Compiler Arguments” would not work…

      So this sounds like this option is a release build feature. Yet, when you click “Project” -> “Export Release Build…”, there is nothing for developers to “omit trace statements”. To me, that’s obviously an UI design oversight.

      Clement Wong

      April 22, 2010 at 12:02 pm

  4. What a blunder! Good catch. Tells us something about the quality of the adobe flex releases, I think!

    Tech Per

    April 22, 2010 at 2:20 pm

  5. You could also use the Stripper tool from Apparat to remove traces (typesafe) keeping side effects 🙂

    Joa Ebert

    June 2, 2010 at 3:32 pm

  6. […] Typesafe trace() removal keeping side-effects […]

  7. […] Typesafe trace() removal keeping side-effects […]

    Apparat « AS3开源大全

    August 23, 2010 at 6:52 am

  8. […] Typesafe trace() removal keeping side-effects […]

    Apparat | AS3 Game Gears

    September 7, 2010 at 8:03 am

  9. Does it also break usages like this?

    trace(callMyFunctionWhichDoesStuffAndReturnsSomethingTracable());

    e.g. does it remove the function call?

    Kelvin Luck

    September 8, 2010 at 11:18 am

  10. AFAIK yes. It removes the whole thing.

    Joa Ebert

    September 8, 2010 at 11:36 am

    • I think that’s even worse than the example above then. Again, probably not great practice to call a function with side effects inside a trace statement but the compiler definitely shouldn’t delete potentially useful code!

      Kelvin Luck

      September 8, 2010 at 11:40 am

      • I totally agree with you. I’d put some pressure on Adobe to get this fixed in 4.5. BTW, Joa’s Apparat keeps the side effect.

        Clement Wong

        September 8, 2010 at 11:53 am

  11. Sorry, but to actually use the keyword as the function’s name AND executing a code with side-effects in it is not only not best practice, it is outright stupid. In any other case this implementation poses no problem at all, not even conceptually.

    wlad

    November 4, 2010 at 12:07 pm

  12. It does not prevent people from doing it. And unfortunately you are wrong. Maybe you can not even control it since ActionScript has implicit getters which should not contain side effects but I have seen dozens of LoC where an implicit getter contains a side-effect. Et voila, trace(x.y) is no longer side-effect free without you even knowing.

    Joa Ebert

    November 4, 2010 at 12:11 pm

    • OK, if that’s the case, it is a bit of a conceptual problem, but you’d have to try really hard to actually run into problems and it’s more a problem on the side of the getters than the omit.
      I just think it would be over-engineering to have the compiler to check the whole code first and then omit traces based on the context when in the vast majority of cases the current implementation works fine. But I have to agree, to skip the bytecode genration for the calls to the player’s trace would be better and more safe.

      wlad

      November 5, 2010 at 5:44 am

  13. […] class Communicating between SWFs and across domains List of Flex Compiler Arguments across versions How -omit-trace-statements Works… Or Does NOT… Dispatching Custom Events Passing Arguments with Events RegExr The Event Meta Tag in Actionscript 3 […]


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: