Object eval(final Class scriptClass, final ScriptContext context) throws ScriptException {
        final Binding binding = new Binding(context.getBindings(ScriptContext.ENGINE_SCOPE)) {
            @Override
            public Object getVariable(String name) {
                synchronized (context) {
                    int scope = context.getAttributesScope(name);
                    if (scope != -1) {
                        return context.getAttribute(name, scope);
                    }
                    // Redirect script output to context writer, if out var is not already provided
                    if ("out".equals(name)) {
                        final Writer writer = context.getWriter();
                        if (writer != null) {
                            return (writer instanceof PrintWriter) ?
                                    (PrintWriter) writer :
                                    new PrintWriter(writer, true);
                        }
                    }
                    // Provide access to engine context, if context var is not already provided
                    if ("context".equals(name)) {
                        return context;
                    }
                }
                throw new MissingPropertyException(name, getClass());
            }

            @Override
            public void setVariable(String name, Object value) {
                synchronized (context) {
                    int scope = context.getAttributesScope(name);
                    if (scope == -1) {
                        scope = ScriptContext.ENGINE_SCOPE;
                    }
                    context.setAttribute(name, value, scope);
                }
            }
        };

        try {
            // if this class is not an instance of Script, it's a full-blown class then simply return that class
            if (!Script.class.isAssignableFrom(scriptClass)) {
                return scriptClass;
            } else {
                final Script scriptObject = InvokerHelper.createScript(scriptClass, binding);

                if (globalFunctionCacheEnabled) {
                    for (Method m : scriptClass.getMethods()) {
                        final String name = m.getName();
                        globalClosures.put(name, new MethodClosure(scriptObject, name));
                    }
                }

                final MetaClass oldMetaClass = scriptObject.getMetaClass();
                scriptObject.setMetaClass(new DelegatingMetaClass(oldMetaClass) {
                    @Override
                    public Object invokeMethod(final Object object, final String name, final Object args) {
                        if (args == null) {
                            return invokeMethod(object, name, MetaClassHelper.EMPTY_ARRAY);
                        } else if (args instanceof Tuple) {
                            return invokeMethod(object, name, ((Tuple) args).toArray());
                        } else if (args instanceof Object[]) {
                            return invokeMethod(object, name, (Object[]) args);
                        } else {
                            return invokeMethod(object, name, new Object[]{args});
                        }
                    }

                    @Override
                    public Object invokeMethod(final Object object, final String name, final Object args[]) {
                        try {
                            return super.invokeMethod(object, name, args);
                        } catch (MissingMethodException mme) {
                            return callGlobal(name, args, context);
                        }
                    }

                    @Override
                    public Object invokeStaticMethod(final Object object, final String name, final Object args[]) {
                        try {
                            return super.invokeStaticMethod(object, name, args);
                        } catch (MissingMethodException mme) {
                            return callGlobal(name, args, context);
                        }
                    }
                });

                final Object o = scriptObject.run();

                // if interpreter mode is enable then local vars of the script are promoted to engine scope bindings.
                if (interpreterModeEnabled) {
                    final Map<String, Object> localVars = (Map<String, Object>) context.getAttribute(COLLECTED_BOUND_VARS_MAP_VARNAME);
                    if (localVars != null) {
                        localVars.entrySet().forEach(e -> {
                            // closures need to be cached for later use
                            if (globalFunctionCacheEnabled && e.getValue() instanceof Closure)
                                globalClosures.put(e.getKey(), (Closure) e.getValue());

                            context.setAttribute(e.getKey(), e.getValue(), ScriptContext.ENGINE_SCOPE);
                        });

                        // get rid of the temporary collected vars
                        context.removeAttribute(COLLECTED_BOUND_VARS_MAP_VARNAME, ScriptContext.ENGINE_SCOPE);
                        localVars.clear();
                    }
                }

                return o;
            }
        } catch (Exception e) {
            throw new ScriptException(e);
        }
    }
Gets the total number of nanoseconds that the cache spent compiling scripts.
gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngine.java