Example #1
0
 public static String scriptToClass(String name) {
   if (name.equals("-e")) {
     return "DashE";
   } else {
     return JavaNameMangler.mangledFilenameForStartupClasspath(name);
   }
 }
 public JITClassGenerator(
     String className,
     String methodName,
     String key,
     Ruby ruby,
     DefaultMethod method,
     JITCounts counts) {
   this.packageName = JITCompiler.RUBY_JIT_PREFIX;
   if (RubyInstanceConfig.JAVA_VERSION == Opcodes.V1_7) {
     // recent Java 7 seems to have a bug that leaks definitions across cousin classloaders
     // so we force the class name to be unique to this runtime
     digestString = getHashForString(key) + Math.abs(ruby.hashCode());
   } else {
     digestString = getHashForString(key);
   }
   this.className =
       packageName
           + "/"
           + className.replace('.', '/')
           + CLASS_METHOD_DELIMITER
           + JavaNameMangler.mangleMethodName(methodName)
           + "_"
           + digestString;
   this.name = this.className.replaceAll("/", ".");
   this.bodyNode = method.getBodyNode();
   this.argsNode = method.getArgsNode();
   this.methodName = methodName;
   filename = calculateFilename(argsNode, bodyNode);
   staticScope = method.getStaticScope();
   asmCompiler = new StandardASMCompiler(this.className, filename);
   this.ruby = ruby;
   this.counts = counts;
 }
Example #3
0
  public static CallSite bootstrap(MethodHandles.Lookup lookup, String name, MethodType type) {
    String[] nameComponents = name.split(":");
    String methodName = JavaNameMangler.demangleMethodName(nameComponents[1]);
    CallType callType =
        nameComponents[0].equals("callFunctional") ? CallType.FUNCTIONAL : CallType.VARIABLE;
    InvokeSite site = new SelfInvokeSite(type, methodName, callType);

    return InvokeSite.bootstrap(site, lookup);
  }
  public static CallSite bootstrap(
      MethodHandles.Lookup lookup, String name, MethodType type, String splatmapString) {
    String[] targetAndMethod = name.split(":");
    String superName = JavaNameMangler.demangleMethodName(targetAndMethod[1]);

    InvokeSite site;

    switch (targetAndMethod[0]) {
      case "invokeInstanceSuper":
        site = new InstanceSuperInvokeSite(type, superName, splatmapString);
        break;
      case "invokeClassSuper":
        site = new ClassSuperInvokeSite(type, superName, splatmapString);
        break;
      default:
        throw new RuntimeException("invalid super call: " + name);
    }

    return InvokeSite.bootstrap(site, lookup);
  }
Example #5
0
  private RubyStackTraceElement[] transformBacktrace(Map<String, String> boundMethods) {
    List<RubyStackTraceElement> trace = new ArrayList<RubyStackTraceElement>(javaTrace.length);
    // used for duplicating the previous Ruby frame when masking native calls
    boolean dupFrame = false;
    String dupFrameName = null;
    // a running index into the Ruby backtrace stack, incremented for each
    // interpreter frame we encounter in the Java backtrace.
    int rubyFrameIndex = rubyTrace == null ? -1 : rubyTrace.length - 1;
    // no Java trace, can't generate hybrid trace
    // TODO: Perhaps just generate the interpreter trace? Is this path ever hit?
    if (javaTrace == null) {
      return null;
    }
    for (int i = 0; i < javaTrace.length; i++) {
      StackTraceElement element = javaTrace[i];
      if (element.getFileName() != null
          && (element.getFileName().endsWith(".rb")
              || element.getFileName().equals("-e")
              || element.getClassName().startsWith(JITCompiler.RUBY_JIT_PREFIX + ".")
              || element.getMethodName().contains("$RUBY$")
              || element.getMethodName().contains("__file__"))) {
        if (element.getLineNumber() == -1) {
          continue;
        }
        String methodName = element.getMethodName();
        String className = element.getClassName();
        // FIXME: Formalize jitted method structure so this isn't quite as hacky
        if (className.startsWith(JITCompiler.RUBY_JIT_PREFIX)) {
          // pull out and demangle the method name
          methodName =
              className.substring(
                  JITCompiler.RUBY_JIT_PREFIX.length() + 1, className.lastIndexOf("_"));
          methodName = JavaNameMangler.demangleMethodName(methodName);
          RubyStackTraceElement rubyElement =
              new RubyStackTraceElement(
                  className, methodName, element.getFileName(), element.getLineNumber(), false);
          // dup if masking native and previous frame was native
          if (maskNative && dupFrame) {
            dupFrame = false;
            trace.add(
                new RubyStackTraceElement(
                    rubyElement.getClassName(),
                    dupFrameName,
                    rubyElement.getFileName(),
                    rubyElement.getLineNumber(),
                    rubyElement.isBinding()));
          }
          trace.add(rubyElement);
          // if it's a synthetic call, use it but gobble up parent calls
          // TODO: need to formalize this better
          if (element.getMethodName().contains("$RUBY$SYNTHETIC")) {
            // gobble up at least one parent, and keep going if there's more synthetic frames
            while (element.getMethodName().indexOf("$RUBY$SYNTHETIC") != -1
                && ++i < javaTrace.length) {
              element = javaTrace[i];
            }
          }
          continue;
        }
        int RUBYindex = methodName.indexOf("$RUBY$");
        if (RUBYindex >= 0) {
          // if it's a synthetic call, use it but gobble up parent calls
          // TODO: need to formalize this better
          methodName = methodName.substring(RUBYindex);
          if (methodName.startsWith("$RUBY$SYNTHETIC")) {
            methodName = methodName.substring("$RUBY$SYNTHETIC".length());
            methodName = JavaNameMangler.demangleMethodName(methodName);
            if (methodName.equals("__file__")) {
              methodName = "(root)";
            }
            RubyStackTraceElement rubyElement =
                new RubyStackTraceElement(
                    className, methodName, element.getFileName(), element.getLineNumber(), false);
            // dup if masking native and previous frame was native
            if (maskNative && dupFrame) {
              dupFrame = false;
              trace.add(
                  new RubyStackTraceElement(
                      rubyElement.getClassName(),
                      dupFrameName,
                      rubyElement.getFileName(),
                      rubyElement.getLineNumber(),
                      rubyElement.isBinding()));
            }
            trace.add(rubyElement);
            // gobble up at least one parent, and keep going if there's more synthetic frames
            while (element.getMethodName().indexOf("$RUBY$SYNTHETIC") != -1
                && ++i < javaTrace.length) {
              element = javaTrace[i];
            }
            continue;
          }
          methodName = methodName.substring("$RUBY$".length());
          methodName = JavaNameMangler.demangleMethodName(methodName);
          RubyStackTraceElement rubyElement =
              new RubyStackTraceElement(
                  className, methodName, element.getFileName(), element.getLineNumber(), false);
          // dup if masking native and previous frame was native
          if (maskNative && dupFrame) {
            dupFrame = false;
            trace.add(
                new RubyStackTraceElement(
                    rubyElement.getClassName(),
                    dupFrameName,
                    rubyElement.getFileName(),
                    rubyElement.getLineNumber(),
                    rubyElement.isBinding()));
          }
          trace.add(rubyElement);
          continue;
        }
        if (methodName.equals("__file__")
            && !element.getFileName().endsWith("AbstractScript.java")) {
          methodName = "(root)";
          RubyStackTraceElement rubyElement =
              new RubyStackTraceElement(
                  className, methodName, element.getFileName(), element.getLineNumber(), false);
          // dup if masking native and previous frame was native
          if (maskNative && dupFrame) {
            dupFrame = false;
            trace.add(
                new RubyStackTraceElement(
                    rubyElement.getClassName(),
                    dupFrameName,
                    rubyElement.getFileName(),
                    rubyElement.getLineNumber(),
                    rubyElement.isBinding()));
          }
          trace.add(rubyElement);
          continue;
        }
      }
      String dotClassMethod = element.getClassName() + "." + element.getMethodName();
      String rubyName = null;
      if (fullTrace || (rubyName = boundMethods.get(dotClassMethod)) != null) {
        String filename = element.getFileName();

        // stick package on the beginning
        if (filename == null) {
          filename = element.getClassName().replaceAll("\\.", "/");
        } else {
          int lastDot = element.getClassName().lastIndexOf('.');
          if (lastDot != -1) {
            filename =
                element.getClassName().substring(0, lastDot + 1).replaceAll("\\.", "/") + filename;
          }
        }
        if (maskNative) {
          // for Kernel#caller, don't show .java frames in the trace
          dupFrame = true;
          dupFrameName = rubyName;
          continue;
        } else {
          if (rubyName == null) rubyName = element.getMethodName();
          trace.add(
              new RubyStackTraceElement(
                  element.getClassName(), rubyName, filename, element.getLineNumber(), false));
        }
        // if not full trace, we're done; don't check interpreted marker
        if (!fullTrace) {
          continue;
        }
      }
      String classMethod = element.getClassName() + "." + element.getMethodName();
      FrameType frameType = FrameType.INTERPRETED_FRAMES.get(classMethod);
      if (frameType != null && rubyFrameIndex >= 0) {
        // Frame matches one of our markers for "interpreted" calls
        BacktraceElement rubyFrame = rubyTrace[rubyFrameIndex];
        RubyStackTraceElement rubyElement =
            new RubyStackTraceElement(
                rubyFrame.klass, rubyFrame.method, rubyFrame.filename, rubyFrame.line + 1, false);
        // dup if masking native and previous frame was native
        if (maskNative && dupFrame) {
          dupFrame = false;
          trace.add(
              new RubyStackTraceElement(
                  rubyElement.getClassName(),
                  dupFrameName,
                  rubyElement.getFileName(),
                  rubyElement.getLineNumber(),
                  rubyElement.isBinding()));
        }
        trace.add(rubyElement);
        rubyFrameIndex--;
        continue;
      }
    }
    RubyStackTraceElement[] rubyStackTrace = new RubyStackTraceElement[trace.size()];
    return (RubyStackTraceElement[]) trace.toArray(rubyStackTrace);
  }