Skip to content

[GR-68065] Retained size computation errors when using a custom instrument #11785

@lucas-mpc-brant

Description

@lucas-mpc-brant

Describe GraalVM and your environment :

  • GraalVM version or commit id if built from source: [21.0.8+12.1]
  • CE or EE: [EE]
  • JDK version: [e.g.: 21.0.8]
  • OS and OS Version: [Linux (ubuntu 22.04.4)]
  • Architecture: [x86]

Describe the issue
we've implemented a custom instrument and are experiencing some memory calculation issues when running some guest code. Its not exactly clear what is causing it and there's a bunch of requirements for it to happen (must be executing a ProxyExecutable in guest code, instrument must be saving input values, etc). The errors look like this:

[sandbox] WARNING: [thread-37] [instrument-1] [context-1] [memory-limit-checker-invocation-53] Retained size computation task threw an exception for context!
Caused by: java.lang.AssertionError: com.oracle.truffle.polyglot.PolyglotEngineImpl should not be reachable
	at com.oracle.truffle.polyglot.ObjectSizeCalculator.isContextHeapBoundary(ObjectSizeCalculator.java:321)
	at com.oracle.truffle.polyglot.ObjectSizeCalculator.canProceed(ObjectSizeCalculator.java:369)
	at com.oracle.truffle.polyglot.ObjectSizeCalculator.enqueueOrStop(ObjectSizeCalculator.java:122)
	at com.oracle.truffle.polyglot.ObjectSizeCalculator$ObjectClassInfo.visit(ObjectSizeCalculator.java:543)
	at com.oracle.truffle.polyglot.ObjectSizeCalculator.visit(ObjectSizeCalculator.java:284)
	at com.oracle.truffle.polyglot.ObjectSizeCalculator.calculateObjectSize(ObjectSizeCalculator.java:245)
	at com.oracle.truffle.polyglot.PolyglotContextImpl.calculateHeapSize(PolyglotContextImpl.java:2495)
	at com.oracle.truffle.polyglot.EngineAccessor$EngineImpl.calculateContextHeapSize(EngineAccessor.java:1841)
	at com.oracle.truffle.api.instrumentation.TruffleInstrument$Env.calculateContextHeapSize(TruffleInstrument.java:1269)
	at com.oracle.truffle.sandbox.enterprise.m.a(stripped:146)
	at com.oracle.truffle.sandbox.enterprise.m.ax(stripped:35)
	at com.oracle.truffle.sandbox.enterprise.m.call(stripped:19)
	at java.base/java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:317)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java)
	at --- Async.Stack.Trace --- (captured by IntelliJ IDEA debugger)
	at java.base/java.util.concurrent.FutureTask.<init>(FutureTask.java:132)
	at java.base/java.util.concurrent.AbstractExecutorService.newTaskFor(AbstractExecutorService.java:113)
	at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:144)
	at com.oracle.truffle.sandbox.enterprise.h.a(stripped:673)
	at com.oracle.truffle.sandbox.enterprise.l.a(stripped:133)
	at com.oracle.truffle.sandbox.enterprise.l.aq(stripped:93)

Code snippet or code repository that reproduces the issue

public class ReproducerTest {

    private static Engine sharedEngine;

    @BeforeAll
    static void setup() {
        sharedEngine = Engine.newBuilder()
                .allowExperimentalOptions(true)
                .option("sandbox.MaxHeapMemory", "1MB")
                .option("sandbox.AllocatedBytesCheckFactor", "0.25")
                .option("sandbox.TraceLimits", "true")
                .option("sandbox.UseLowMemoryTrigger", "false")
                .build();
    }

    @Test
    void testInstrumentMemoryError() {
        try (final Context context = Context.newBuilder("js")
                .engine(sharedEngine) // Associate with the shared engine
                .build()) {

            final ProxyExecutable proxyExecutable = args -> args;

            context.getBindings("js").putMember("myFunc", proxyExecutable);
            final BugInstrument instrument = context.getEngine().getInstruments().get("BugInstrument").lookup(BugInstrument.class);
            instrument.startInstrumentation();

            final String script = """
                    (() => {
                      const largeMapObject = new Map([
                      ["userSettings", {
                        theme: "dark",
                        notifications: {
                          email: true,
                          sms: false,
                          push: true
                        },
                        privacy: {
                          dataSharing: false,
                          locationTracking: true
                        }
                      }],
                      ["productCatalog", {
                        categories: [
                          { id: "cat1", name: "Electronics", products: [
                            { sku: "ELEC001", name: "Laptop X1", price: 1200.00, inStock: 15, specs: { cpu: "Intel i7", ram: "16GB" } },
                            { sku: "ELEC002", name: "Smartphone Pro", price: 899.99, inStock: 50, specs: { os: "Android", camera: "48MP" } },
                            { sku: "ELEC003", name: "Smartwatch Z", price: 299.00, inStock: 30, specs: { display: "AMOLED", batteryLife: "2 days" } }
                          ]},
                          { id: "cat2", name: "Books", products: [
                            { sku: "BOOK001", name: "The Alchemist", author: "Paulo Coelho", price: 15.50, inStock: 100 },
                            { sku: "BOOK002", name: "1984", author: "George Orwell", price: 12.00, inStock: 75 },
                            { sku: "BOOK003", name: "Sapiens", author: "Yuval Noah Harari", price: 20.00, inStock: 60 }
                          ]}
                        ]
                      }],
                      ["orderHistory", [
                        {
                          orderId: "ORD001",
                          date: "2024-07-15",
                          customer: { id: "CUST001", name: "Alice Smith" },
                          items: [
                            { sku: "ELEC001", name: "Laptop X1", quantity: 1, price: 1200.00 },
                            { sku: "BOOK001", name: "The Alchemist", quantity: 2, price: 15.50 }
                          ],
                          total: 1231.00,
                          status: "completed"
                        },
                        {
                          orderId: "ORD002",
                          date: "2024-07-18",
                          customer: { id: "CUST002", name: "Bob Johnson" },
                          items: [
                            { sku: "ELEC002", name: "Smartphone Pro", quantity: 1, price: 899.99 }
                          ],
                          total: 899.99,
                          status: "pending"
                        }
                      ]],
                      ["blogPosts", [
                        {
                          postId: "BLOG001",
                          title: "The Future of AI",
                          author: "Jane Doe",
                          date: "2024-07-01",
                          tags: ["AI", "Technology", "Innovation"],
                          content: "Lorem ipsum dolor sit amet, consectetur adipiscing elit..."
                        },
                        {
                          postId: "BLOG002",
                          title: "Healthy Eating Habits",
                          author: "John Smith",
                          date: "2024-06-20",
                          tags: ["Health", "Nutrition"],
                          content: "Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua..."
                        }
                      ]],
                      ["analyticsData", {
                        pageViews: {
                          "/home": 15000,
                          "/products": 10000,
                          "/about": 5000,
                          "/contact": 2000
                        },
                        userDemographics: {
                          ageGroups: {
                            "18-24": 2000,
                            "25-34": 5000,
                            "35-44": 4000,
                            "45+": 3000
                          },
                          gender: {
                            male: 7000,
                            female: 8000
                          }
                        },
                        trafficSources: {
                          direct: 7000,
                          search: 5000,
                          social: 3000,
                          referral: 1000
                        }
                      }],
                      ["inventoryManagement", {
                        warehouses: [
                          { id: "WH001", name: "Main Warehouse", location: "New York", capacity: 100000, currentStock: 75000 },
                          { id: "WH002", name: "West Coast Depot", location: "Los Angeles", capacity: 50000, currentStock: 30000 }
                        ],
                        suppliers: [
                          { id: "SUP001", name: "Tech Suppliers Inc.", contact: "[email protected]" },
                          { id: "SUP002", name: "Book Distributors LLC", contact: "[email protected]" }
                        ],
                        stockAlerts: [
                          { sku: "ELEC001", threshold: 10, current: 15, status: "ok" },
                          { sku: "BOOK002", threshold: 20, current: 75, status: "ok" }
                        ]
                      }]
                    ]);
                    
                    //might be intermittent, increasing the amount of loops should improve consistency.
                    for(let i = 0; i < 10; i++) {
                        myFunc(largeMapObject)
                    }

                    })();
                    """;

            final Source source = Source.newBuilder("js", script, "teste").build();
            context.eval(source);
        } catch (final IOException e) {
            throw new RuntimeException(e);
        }
    }

    @TruffleInstrument.Registration(id = "BugInstrument", services = BugInstrument.class)
    static class BugInstrument extends TruffleInstrument {
        private Env env;
        private EventBinding<ExecutionEventNodeFactory> binding;

        @Override
        protected void onCreate(final Env env) {
            this.env = env;
            env.registerService(this);
        }

        public void startInstrumentation() {
            final SourceSectionFilter filter = SourceSectionFilter.newBuilder().tagIs(StandardTags.CallTag.class).build();

            this.binding = this.env.getInstrumenter()
                    .attachExecutionEventFactory(filter, SourceSectionFilter.ANY, context -> new ExecutionEventNode() {
                        @Override
                        protected void onInputValue(final VirtualFrame frame, final EventContext inputContext, final int inputIndex, final Object inputValue) {
                            this.saveInputValue(frame, inputIndex, inputValue);
                        }
                    });
        }

        @Override
        protected void onDispose(final Env env) {
            if (this.binding != null) {
                this.binding.dispose();
            }
        }
    }
}

Steps to reproduce the issue
1- Run the JUnit test

Expected behavior
I'd expect no errors when running this instrument.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions