Exemplo n.º 1
0
    @SuppressWarnings("unchecked")
    protected void compile() {
      if (bytecode != null) return;

      // check if we have a cached compiled version on disk
      String codeCache = RubyInstanceConfig.JIT_CODE_CACHE;
      File cachedClassFile = new File(codeCache + "/" + className + ".class");

      if (codeCache != null && cachedClassFile.exists()) {
        FileInputStream fis = null;
        try {
          if (RubyInstanceConfig.JIT_LOADING_DEBUG)
            LOG.info("loading cached code from: " + cachedClassFile);
          fis = new FileInputStream(cachedClassFile);
          bytecode = new byte[(int) fis.getChannel().size()];
          fis.read(bytecode);
          name = new ClassReader(bytecode).getClassName();
          return;
        } catch (Exception e) {
          // ignore and proceed to compile
        } finally {
          try {
            fis.close();
          } catch (Exception e) {
          }
        }
      }

      // Time the compilation
      long start = System.nanoTime();

      asmCompiler.startScript(staticScope);
      final ASTCompiler compiler = ruby.getInstanceConfig().newCompiler();

      CompilerCallback args =
          new CompilerCallback() {
            public void call(BodyCompiler context) {
              compiler.compileArgs(argsNode, context, true);
            }
          };

      ASTInspector inspector = new ASTInspector();
      if (ruby.getInstanceConfig().isJitDumping()) {
        inspector = new ASTInspector(className, true);
      }
      // check args first, since body inspection can depend on args
      inspector.inspect(argsNode);
      inspector.inspect(bodyNode);

      BodyCompiler methodCompiler;
      if (bodyNode != null) {
        // we have a body, do a full-on method
        methodCompiler = asmCompiler.startFileMethod(args, staticScope, inspector);
        compiler.compileBody(bodyNode, methodCompiler, true);
      } else {
        // If we don't have a body, check for required or opt args
        // if opt args, they could have side effects
        // if required args, need to raise errors if too few args passed
        // otherwise, method does nothing, make it a nop
        if (argsNode != null
            && (argsNode.getRequiredArgsCount() > 0 || argsNode.getOptionalArgsCount() > 0)) {
          methodCompiler = asmCompiler.startFileMethod(args, staticScope, inspector);
          methodCompiler.loadNil();
        } else {
          methodCompiler = asmCompiler.startFileMethod(null, staticScope, inspector);
          methodCompiler.loadNil();
          jitCallConfig = CallConfiguration.FrameNoneScopeNone;
        }
      }
      methodCompiler.endBody();
      asmCompiler.endScript(false, false);

      // if we haven't already decided on a do-nothing call
      if (jitCallConfig == null) {
        jitCallConfig = inspector.getCallConfig();
      }

      bytecode = asmCompiler.getClassByteArray();
      if (ruby.getInstanceConfig().isJitDumping()) {
        TraceClassVisitor tcv = new TraceClassVisitor(new PrintWriter(System.out));
        new ClassReader(bytecode).accept(tcv, 0);
      }

      if (bytecode.length > ruby.getInstanceConfig().getJitMaxSize()) {
        bytecode = null;
        throw new NotCompilableException(
            "JITed method size exceeds configured max of "
                + ruby.getInstanceConfig().getJitMaxSize());
      }

      if (codeCache != null) {
        JITCompiler.saveToCodeCache(ruby, bytecode, packageName, cachedClassFile);
      }

      counts.compiledCount.incrementAndGet();
      counts.compileTime.addAndGet(System.nanoTime() - start);
      counts.codeSize.addAndGet(bytecode.length);
      counts.averageCompileTime.set(counts.compileTime.get() / counts.compiledCount.get());
      counts.averageCodeSize.set(counts.codeSize.get() / counts.compiledCount.get());
      synchronized (counts) {
        if (counts.largestCodeSize.get() < bytecode.length) {
          counts.largestCodeSize.set(bytecode.length);
        }
      }
    }
Exemplo n.º 2
0
 /**
  * Calculates expression value with object as a context for path expressions.
  *
  * @since 1.1
  */
 public Object evaluate(Object o) {
   return ASTCompiler.compile(this).evaluateASTChain(o);
 }