From cfcf469617f468a60715b5d51508a13b86356eb3 Mon Sep 17 00:00:00 2001 From: Gary Frost <frost.gary@gmail.com> Date: Thu, 1 Nov 2012 18:57:09 +0000 Subject: [PATCH] Issue #74 checkin Thanks eric for the patch --- .../src/java/com/amd/aparapi/Entrypoint.java | 133 +++++++++++------- .../java/com/amd/aparapi/KernelWriter.java | 3 + 2 files changed, 87 insertions(+), 49 deletions(-) diff --git a/com.amd.aparapi/src/java/com/amd/aparapi/Entrypoint.java b/com.amd.aparapi/src/java/com/amd/aparapi/Entrypoint.java index e9b7608a..34868697 100644 --- a/com.amd.aparapi/src/java/com/amd/aparapi/Entrypoint.java +++ b/com.amd.aparapi/src/java/com/amd/aparapi/Entrypoint.java @@ -64,6 +64,7 @@ import com.amd.aparapi.InstructionSet.AssignToField; import com.amd.aparapi.InstructionSet.I_ARRAYLENGTH; import com.amd.aparapi.InstructionSet.I_GETFIELD; import com.amd.aparapi.InstructionSet.I_INVOKESPECIAL; +import com.amd.aparapi.InstructionSet.I_INVOKESTATIC; import com.amd.aparapi.InstructionSet.I_INVOKEVIRTUAL; import com.amd.aparapi.InstructionSet.MethodCall; import com.amd.aparapi.InstructionSet.TypeSpec; @@ -230,7 +231,10 @@ class Entrypoint{ /* * Update the list of object array member classes and all the superclasses - * of those classes and the fields in each class + * of those classes and the fields in each class. + * + * It is important to have only one ClassModel for each class used in the kernel + * and only one MethodModel per method, so comparison operations work properly. */ ClassModel getOrUpdateAllClassAccesses(String className) throws AparapiException { ClassModel memberClassModel = allFieldsClasses.get(className); @@ -392,6 +396,61 @@ class Entrypoint{ } } } + + /* + * Find a suitable call target in the kernel class, supers, object members or static calls + */ + ClassModelMethod resolveCalledMethod(MethodCall methodCall, ClassModel classModel) throws AparapiException { + MethodEntry methodEntry = methodCall.getConstantPoolMethodEntry(); + int thisClassIndex = classModel.getThisClassConstantPoolIndex();//arf + boolean isMapped = (thisClassIndex != methodEntry.getClassIndex()) && Kernel.isMappedMethod(methodEntry); + if (logger.isLoggable(Level.FINE)) { + if (methodCall instanceof I_INVOKESPECIAL) { + logger.fine("Method call to super: " + methodEntry); + } else if (thisClassIndex != methodEntry.getClassIndex()) { + logger.fine("Method call to ??: " + methodEntry + ", isMappedMethod=" + isMapped); + } else { + logger.fine("Method call in kernel class: " + methodEntry); + } + } + + ClassModelMethod m = classModel.getMethod(methodEntry, (methodCall instanceof I_INVOKESPECIAL) ? true : false); + + // Did not find method in this class or supers. Look for data member object arrays + if (m == null && !isMapped) { + m = resolveAccessorCandidate(methodCall, methodEntry); + } + + // Look for a intra-object call in a object member + if (m == null && !isMapped) { + for (ClassModel c : allFieldsClasses.values()) { + if (c.getClassWeAreModelling().getName() + .equals(methodEntry.getClassEntry().getNameUTF8Entry().getUTF8().replace('/', '.'))) { + m = c.getMethod(methodEntry, (methodCall instanceof I_INVOKESPECIAL) ? true : false); + assert m != null; + break; + } + } + } + + // Look for static call to some other class + if ((m == null) && !isMapped && (methodCall instanceof I_INVOKESTATIC)) { + String otherClassName = methodEntry.getClassEntry().getNameUTF8Entry().getUTF8().replace('/', '.'); + ClassModel otherClassModel = getOrUpdateAllClassAccesses(otherClassName); + + //if (logger.isLoggable(Level.FINE)) { + // logger.fine("Looking for: " + methodEntry + " in other class " + otherClass.getName()); + //} + // false because INVOKESPECIAL not allowed here + m = otherClassModel.getMethod(methodEntry, false); + } + + if (logger.isLoggable(Level.INFO)) { + logger.fine("Selected method for: " + methodEntry + " is " + m); + } + + return m; + } Entrypoint(ClassModel _classModel, MethodModel _methodModel, Object _k) throws AparapiException { classModel = _classModel; @@ -401,7 +460,6 @@ class Entrypoint{ Map<ClassModelMethod, MethodModel> methodMap = new LinkedHashMap<ClassModelMethod, MethodModel>(); boolean discovered = true; - int thisClassIndex = _classModel.getThisClassConstantPoolIndex();//arf // Record which pragmas we need to enable if (methodModel.requiresDoublePragma()) { @@ -418,31 +476,15 @@ class Entrypoint{ } } + // Collect all methods called directly from kernel's run method for (MethodCall methodCall : methodModel.getMethodCalls()) { - MethodEntry methodEntry = methodCall.getConstantPoolMethodEntry(); - if (logger.isLoggable(Level.FINE)) { - if (methodCall instanceof I_INVOKESPECIAL) { - logger.fine("Method call to super: " + methodEntry); - } else if (thisClassIndex != methodEntry.getClassIndex()) { - logger.fine("Method call to ??: " + methodEntry); - } else { - logger.fine("Method call in kernel class: " + methodEntry); - } - } - - ClassModelMethod m = classModel.getMethod(methodEntry, (methodCall instanceof I_INVOKESPECIAL) ? true : false); - - // Did not find method in this class or supers. Look for data member object arrays - if (m == null) { - m = resolveAccessorCandidate(methodCall, methodEntry); - } - + ClassModelMethod m = resolveCalledMethod(methodCall, classModel); if (m != null && !methodMap.keySet().contains(m)) { MethodModel target = new MethodModel(m, this); methodMap.put(m, target); methodModel.getCalledMethods().add(target); discovered = true; - } + } } // methodMap now contains a list of method called by run itself(). @@ -451,31 +493,7 @@ class Entrypoint{ discovered = false; for (MethodModel mm : new ArrayList<MethodModel>(methodMap.values())) { for (MethodCall methodCall : mm.getMethodCalls()) { - MethodEntry methodEntry = methodCall.getConstantPoolMethodEntry(); - - if (logger.isLoggable(Level.FINE)) { - logger.fine("Looking for: " + methodEntry + " called by " + mm.getMethod().getName()); - } - - ClassModelMethod m = classModel.getMethod(methodEntry, (methodCall instanceof I_INVOKESPECIAL) ? true : false); - - // Did not find method in this class or supers. Look for data member object arrays - if (m == null) { - m = resolveAccessorCandidate(methodCall, methodEntry); - } - - // Look for a intra-object call in a object member - if (m == null) { - for (ClassModel c : allFieldsClasses.values()) { - if (c.getClassWeAreModelling().getName() - .equals(methodEntry.getClassEntry().getNameUTF8Entry().getUTF8().replace('/', '.'))) { - m = c.getMethod(methodEntry, (methodCall instanceof I_INVOKESPECIAL) ? true : false); - assert m != null; - break; - } - } - } - + ClassModelMethod m = resolveCalledMethod(methodCall, classModel); if (m != null) { MethodModel target = null; if (methodMap.keySet().contains(m)) { @@ -484,7 +502,7 @@ class Entrypoint{ // then when we reverse the collection (below) we get the method // declarations in the correct order. We are trying to avoid creating forward references target = methodMap.remove(m); - if (logger.isLoggable(Level.FINE)) { + if (logger.isLoggable(Level.FINEST)) { logger.fine("repositioning : " + m.getClassModel().getClassWeAreModelling().getName() + " " + m.getName() + " " + m.getDescriptor()); } @@ -826,9 +844,11 @@ class Entrypoint{ */ MethodModel getCallTarget(MethodEntry _methodEntry, boolean _isSpecial) { ClassModelMethod target = getClassModel().getMethod(_methodEntry, _isSpecial); + boolean isMapped = Kernel.isMappedMethod(_methodEntry); if (logger.isLoggable(Level.FINE) && target == null) { - logger.info("Did not find call target: " + _methodEntry + " in " + getClassModel().getClassWeAreModelling().getName()); + logger.fine("Did not find call target: " + _methodEntry + " in " + + getClassModel().getClassWeAreModelling().getName() + " isMapped=" + isMapped); } if (target == null) { @@ -837,7 +857,7 @@ class Entrypoint{ String entryClassNameInDotForm = _methodEntry.getClassEntry().getNameUTF8Entry().getUTF8().replace('/', '.'); if (entryClassNameInDotForm.equals(memberObjClass.getClassWeAreModelling().getName())) { if (logger.isLoggable(Level.FINE)) { - logger.info("Searching for call target: " + _methodEntry + " in " + logger.fine("Searching for call target: " + _methodEntry + " in " + memberObjClass.getClassWeAreModelling().getName()); } @@ -859,6 +879,21 @@ class Entrypoint{ } } } + + // Search for static calls to other classes + for (MethodModel m : calledMethods) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Searching for call target: " + _methodEntry + " in " + m.getName()); + } + if (m.getMethod().getName().equals(_methodEntry.getNameAndTypeEntry().getNameUTF8Entry().getUTF8()) + && m.getMethod().getDescriptor().equals(_methodEntry.getNameAndTypeEntry().getDescriptorUTF8Entry().getUTF8())) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Found " + m.getMethod().getClassModel().getClassWeAreModelling().getName() + + "." + m.getMethod().getName() + " " + m.getMethod().getDescriptor()); + } + return m; + } + } assert target == null : "Should not have missed a method in calledMethods"; diff --git a/com.amd.aparapi/src/java/com/amd/aparapi/KernelWriter.java b/com.amd.aparapi/src/java/com/amd/aparapi/KernelWriter.java index ef9146b6..2f6ff442 100644 --- a/com.amd.aparapi/src/java/com/amd/aparapi/KernelWriter.java +++ b/com.amd.aparapi/src/java/com/amd/aparapi/KernelWriter.java @@ -216,12 +216,15 @@ abstract class KernelWriter extends BlockWriter{ if (intrinsicMapping == null) { assert entryPoint != null : "entryPoint should not be null"; boolean isSpecial = _methodCall instanceof I_INVOKESPECIAL; + boolean isMapped = Kernel.isMappedMethod(_methodEntry); MethodModel m = entryPoint.getCallTarget(_methodEntry, isSpecial); if (m != null) { write(m.getName()); } else { // Must be a library call like rsqrt + assert isMapped : _methodEntry + " should be mapped method!"; + write(methodName); isIntrinsic = true; } -- GitLab