/** * Copyright (c) 2012-2016 André Bargull * Alle Rechte vorbehalten / All Rights Reserved. Use is subject to license terms. * * <https://github.com/anba/es6draft> */ package com.github.anba.es6draft.runtime.internal; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandleInfo; import java.lang.invoke.MethodHandles; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import com.github.anba.es6draft.compiler.assembler.Code; /** * */ public final class DebugInfo { private final ArrayList<Method> methods = new ArrayList<>(); /** * */ public static final class Method { private final MethodHandle handle; private MethodHandleInfo info; Method(MethodHandle handle) { this.handle = handle; } private MethodHandleInfo info() { if (info == null) { info = MethodHandles.publicLookup().revealDirect(handle); } return info; } /** * Returns the class that declares this method. * * @return the declaring class */ public Class<?> getDeclaringClass() { return info().getDeclaringClass(); } /** * Returns the method name. * * @return the method name */ public String getName() { return info().getName(); } @Override public String toString() { return String.format("class=%s, method=%s", getDeclaringClass(), getName()); } /** * Returns the disassembled bytecode. * * @return the disassembled bytecode */ public String disassemble() { byte[] bytes; try { // classBytes is an internal field created in Compiler#defineAndLoad Field classBytes = getDeclaringClass().getDeclaredField("classBytes"); classBytes.setAccessible(true); bytes = (byte[]) classBytes.get(null); } catch (ReflectiveOperationException e) { throw new RuntimeException(e); } return Code.methodToByteCode(bytes, getName()); } } // called from generated code public void addMethod(MethodHandle handle) { methods.add(new Method(handle)); } /** * Returns the list of generated methods. * * @return the list of generated methods */ public List<Method> getMethods() { return methods; } }