question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

"XXX is not a function" - dead code elemination issue?

See original GitHub issue

Prolog

I have forked the teavm-libgdx project and updated TeaVM + libgdx. The Invaders demo works but I have problem with Super Jumper demo.

Issue

Many methods simply disappear from the Matrix4 class in output code. This results in error: cbgm_Matrix4_tmpMat.$setToTranslation is not a function Indeed, cbgm_Matrix4_tmpMat has only few methods:

  • idt
  • mul
  • set
  • setToLookAt
  • setToOrtho
  • setToOrtho2D
  • ctor

Here’s a screenshots presenting both the exception and list of methods:

image

There is Matrix4Emulator class which is supposed to replace whole original Matrix4 class from libgdx.

The replacing code is a bit different from original but I’ve println-ed all removals and adds of methods/fields, all logs are OK.

The replaceClass() method: https://github.com/Namek/teavm-libgdx/blob/master---repro_issues/core/src/main/java/org/teavm/libgdx/plugin/OverlayTransformer.java#L83-L109

Important bits:

    public OverlayTransformer(){
        Reflections reflections = new Reflections("org.teavm.libgdx.emu");

        Set<Class<?>> annotated = reflections.getTypesAnnotatedWith(Emulate.class);
        for(Class<?> type : annotated){
            Emulate em = type.getAnnotation(Emulate.class);
            Class<?> toEmulate = em.value();
            emulations.put(toEmulate.getTypeName(), type);
        }

        annotated = reflections.getTypesAnnotatedWith(Replace.class);
        for(Class<?> type : annotated){
            Replace em = type.getAnnotation(Replace.class);
            Class<?> toEmulate = em.value();
            replacements.put(toEmulate.getTypeName(), type);
        }
    }

    private void replaceClass(final ClassHolder cls, final ClassReader emuCls) {
        ClassRefsRenamer renamer = new ClassRefsRenamer(referenceCache, preimage ->
                preimage.equals(emuCls.getName()) ? cls.getName() : preimage);
        for (FieldHolder field : cls.getFields().toArray(new FieldHolder[0])) {
            cls.removeField(field);
        }
        for (MethodHolder method : cls.getMethods().toArray(new MethodHolder[0])) {
            cls.removeMethod(method);
        }
        for (FieldReader field : emuCls.getFields()) {
            cls.addField(ModelUtils.copyField(field));
        }
        for (MethodReader method : emuCls.getMethods()) {
            cls.addMethod(renamer.rename(ModelUtils.copyMethod(method)));
        }
    }

Discussion

If that’s dead code elemination then it definitely is wrong about the setToTranslation method because it’s used in the same class, in the method setToLookAt (visible on screenshot).

What can I do about it? If that’s DCE, as a workaround, can I enforce not deleting methods?

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:1
  • Comments:7 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
konsoletypercommented, Aug 7, 2019

It’s not a bug of TeaVM, it’s expected behaviour. Somewhere after 0.5.x I added a bit more restrictive behaviour: when type gets into field, it’s filtered against field type. This was performance optimization of DCE. Unfortunately, this broken some code, which has bugs, but which worked fine with 0.5.x. And OverlayTransformer is the code that contained bug. The behaviour was following. Consider you have code:

static final Matrix4Emulator tmpMat = new Matrix4Emulator();

this code is turned into field declaration

static final Matrix4Emulator tmpMat;

and <clinit> method (which is created by Java compiler internally for all class initializers):

static <clinit>() {
    tmpMat = new Matrix4Emulator();
}

After processing with OverlayTransformer you get following code:

    tmpMat = new Matrix4();

however, tmpMat is still Matrix4Emulator. When DCE calculates the set of possible real types of tmpMat, it processes this line and matches real type (Matrix4) against declared type (Matrix4Emulator), and since these types are different (and Matrix4Emulator is not a supertype for Matrix4), DCE filters out this type. DCE ends up with empty set of types of tmpMat, which means that any virtual call to any method on tmpMat has not effect and does not include any method into reachable set.

0reactions
Namekcommented, Aug 7, 2019

OverlayTransformer

Just found out myself the lacking renamer. I ended up with:

cls.addField(renamer.rename(ModelUtils.copyField(field)));

That worked. Thanks!

Is it bug?

I don’t really understand the exact path of DCE removing this method while still linking to it. Just to make sure before closing the issue, is it a bug of TeaVM or it is not?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Is v8 capable of dead code elimination, based on the value of ...
V8's optimizing compiler supports dead code elimination, so yes, under the right circumstances, a conditional branch that can never be taken ...
Read more >
CSS-in-JS 101: All you need to know - GitHub
No global namespace; Full isolation; No non-deterministic resolution; Clear dependencies; Dead code elimination; Variables, Passing variable from JS to CSS ...
Read more >
Is it possible to strip unused functions?
Anyway, there is an issue with the linker and debugging. ... Dead code elimination != unused function removal. Fortunately C30 does both.
Read more >
[LLVMdev] Live code elimination problem in code generation
[LLVMdev] Live code elimination problem in code generation ... loop: : : set P0 <- xxx ( P0: a physical register for a...
Read more >
A Floating GCC Optimization - The Pharo Dev
This small function is just taking a long value (64bit integer), then it shifts the value and stores it in a temporary variable...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found