1 16 19 20 package org.apache.xalan.xsltc.compiler; 21 22 import java.util.Enumeration ; 23 import java.util.Hashtable ; 24 import java.util.Iterator ; 25 import java.util.Vector ; 26 27 import org.apache.bcel.generic.BranchHandle; 28 import org.apache.bcel.generic.ConstantPoolGen; 29 import org.apache.bcel.generic.DUP; 30 import org.apache.bcel.generic.GOTO_W; 31 import org.apache.bcel.generic.IFLT; 32 import org.apache.bcel.generic.ILOAD; 33 import org.apache.bcel.generic.INVOKEINTERFACE; 34 import org.apache.bcel.generic.INVOKEVIRTUAL; 35 import org.apache.bcel.generic.ISTORE; 36 import org.apache.bcel.generic.InstructionHandle; 37 import org.apache.bcel.generic.InstructionList; 38 import org.apache.bcel.generic.LocalVariableGen; 39 import org.apache.bcel.generic.SWITCH; 40 import org.apache.bcel.generic.TargetLostException; 41 import org.apache.bcel.util.InstructionFinder; 42 import org.apache.xalan.xsltc.DOM; 43 import org.apache.xalan.xsltc.compiler.util.ClassGenerator; 44 import org.apache.xalan.xsltc.compiler.util.MethodGenerator; 45 import org.apache.xalan.xsltc.compiler.util.NamedMethodGenerator; 46 import org.apache.xalan.xsltc.compiler.util.Util; 47 import org.apache.xalan.xsltc.dom.Axis; 48 import org.apache.xml.dtm.DTM; 49 50 60 final class Mode implements Constants { 61 62 65 private final QName _name; 66 67 70 private final Stylesheet _stylesheet; 71 72 75 private final String _methodName; 76 77 80 private Vector _templates; 81 82 85 private Vector _childNodeGroup = null; 86 87 90 private TestSeq _childNodeTestSeq = null; 91 92 95 private Vector _attribNodeGroup = null; 96 97 100 private TestSeq _attribNodeTestSeq = null; 101 102 105 private Vector _idxGroup = null; 106 107 110 private TestSeq _idxTestSeq = null; 111 112 115 private Vector [] _patternGroups; 116 117 120 private TestSeq[] _testSeq; 121 122 128 private Hashtable _preCompiled = new Hashtable (); 129 130 133 private Hashtable _neededTemplates = new Hashtable (); 134 135 138 private Hashtable _namedTemplates = new Hashtable (); 139 140 143 private Hashtable _templateIHs = new Hashtable (); 144 145 148 private Hashtable _templateILs = new Hashtable (); 149 150 153 private LocationPathPattern _rootPattern = null; 154 155 159 private Hashtable _importLevels = null; 160 161 164 private Hashtable _keys = null; 165 166 169 private int _currentIndex; 170 171 179 public Mode(QName name, Stylesheet stylesheet, String suffix) { 180 _name = name; 181 _stylesheet = stylesheet; 182 _methodName = APPLY_TEMPLATES + suffix; 183 _templates = new Vector (); 184 _patternGroups = new Vector [32]; 185 } 186 187 194 public String functionName() { 195 return _methodName; 196 } 197 198 public String functionName(int min, int max) { 199 if (_importLevels == null) { 200 _importLevels = new Hashtable (); 201 } 202 _importLevels.put(new Integer (max), new Integer (min)); 203 return _methodName + '_' + max; 204 } 205 206 209 public void addInstructionList(Pattern pattern, 210 InstructionList ilist) 211 { 212 _preCompiled.put(pattern, ilist); 213 } 214 215 219 public InstructionList getInstructionList(Pattern pattern) { 220 return (InstructionList) _preCompiled.get(pattern); 221 } 222 223 226 private String getClassName() { 227 return _stylesheet.getClassName(); 228 } 229 230 public Stylesheet getStylesheet() { 231 return _stylesheet; 232 } 233 234 public void addTemplate(Template template) { 235 _templates.addElement(template); 236 } 237 238 private Vector quicksort(Vector templates, int p, int r) { 239 if (p < r) { 240 final int q = partition(templates, p, r); 241 quicksort(templates, p, q); 242 quicksort(templates, q + 1, r); 243 } 244 return templates; 245 } 246 247 private int partition(Vector templates, int p, int r) { 248 final Template x = (Template)templates.elementAt(p); 249 int i = p - 1; 250 int j = r + 1; 251 while (true) { 252 while (x.compareTo((Template)templates.elementAt(--j)) > 0); 253 while (x.compareTo((Template)templates.elementAt(++i)) < 0); 254 if (i < j) { 255 templates.set(j, templates.set(i, templates.elementAt(j))); 256 } 257 else { 258 return j; 259 } 260 } 261 } 262 263 266 public void processPatterns(Hashtable keys) { 267 _keys = keys; 268 269 278 279 _templates = quicksort(_templates, 0, _templates.size() - 1); 280 281 290 291 final Enumeration templates = _templates.elements(); 293 while (templates.hasMoreElements()) { 294 final Template template = (Template)templates.nextElement(); 296 297 302 if (template.isNamed() && !template.disabled()) { 303 _namedTemplates.put(template, this); 304 } 305 306 final Pattern pattern = template.getPattern(); 308 if (pattern != null) { 309 flattenAlternative(pattern, template, keys); 310 } 311 } 312 prepareTestSequences(); 313 } 314 315 320 private void flattenAlternative(Pattern pattern, 321 Template template, 322 Hashtable keys) { 323 if (pattern instanceof IdKeyPattern) { 327 final IdKeyPattern idkey = (IdKeyPattern)pattern; 328 idkey.setTemplate(template); 329 if (_idxGroup == null) _idxGroup = new Vector (); 330 _idxGroup.add(pattern); 331 } 332 else if (pattern instanceof AlternativePattern) { 334 final AlternativePattern alt = (AlternativePattern)pattern; 335 flattenAlternative(alt.getLeft(), template, keys); 336 flattenAlternative(alt.getRight(), template, keys); 337 } 338 else if (pattern instanceof LocationPathPattern) { 340 final LocationPathPattern lpp = (LocationPathPattern)pattern; 341 lpp.setTemplate(template); 342 addPatternToGroup(lpp); 343 } 344 } 345 346 350 private void addPatternToGroup(final LocationPathPattern lpp) { 351 if (lpp instanceof IdKeyPattern) { 353 addPattern(-1, lpp); 354 } 355 else { 357 final StepPattern kernel = lpp.getKernelPattern(); 359 if (kernel != null) { 360 addPattern(kernel.getNodeType(), lpp); 361 } 362 else if (_rootPattern == null || 363 lpp.noSmallerThan(_rootPattern)) { 364 _rootPattern = lpp; 365 } 366 } 367 } 368 369 372 private void addPattern(int kernelType, LocationPathPattern pattern) { 373 final int oldLength = _patternGroups.length; 375 if (kernelType >= oldLength) { 376 Vector [] newGroups = new Vector [kernelType * 2]; 377 System.arraycopy(_patternGroups, 0, newGroups, 0, oldLength); 378 _patternGroups = newGroups; 379 } 380 381 Vector patterns; 383 384 if (kernelType == DOM.NO_TYPE) { 385 if (pattern.getAxis() == Axis.ATTRIBUTE) { 386 patterns = (_attribNodeGroup == null) ? 387 (_attribNodeGroup = new Vector (2)) : _attribNodeGroup; 388 } 389 else { 390 patterns = (_childNodeGroup == null) ? 391 (_childNodeGroup = new Vector (2)) : _childNodeGroup; 392 } 393 } 394 else { 395 patterns = (_patternGroups[kernelType] == null) ? 396 (_patternGroups[kernelType] = new Vector (2)) : 397 _patternGroups[kernelType]; 398 } 399 400 if (patterns.size() == 0) { 401 patterns.addElement(pattern); 402 } 403 else { 404 boolean inserted = false; 405 for (int i = 0; i < patterns.size(); i++) { 406 final LocationPathPattern lppToCompare = 407 (LocationPathPattern)patterns.elementAt(i); 408 409 if (pattern.noSmallerThan(lppToCompare)) { 410 inserted = true; 411 patterns.insertElementAt(pattern, i); 412 break; 413 } 414 } 415 if (inserted == false) { 416 patterns.addElement(pattern); 417 } 418 } 419 } 420 421 425 private void completeTestSequences(int nodeType, Vector patterns) { 426 if (patterns != null) { 427 if (_patternGroups[nodeType] == null) { 428 _patternGroups[nodeType] = patterns; 429 } 430 else { 431 final int m = patterns.size(); 432 for (int j = 0; j < m; j++) { 433 addPattern(nodeType, 434 (LocationPathPattern) patterns.elementAt(j)); 435 } 436 } 437 } 438 } 439 440 445 private void prepareTestSequences() { 446 final Vector starGroup = _patternGroups[DTM.ELEMENT_NODE]; 447 final Vector atStarGroup = _patternGroups[DTM.ATTRIBUTE_NODE]; 448 449 completeTestSequences(DTM.TEXT_NODE, _childNodeGroup); 451 452 completeTestSequences(DTM.ELEMENT_NODE, _childNodeGroup); 454 455 completeTestSequences(DTM.PROCESSING_INSTRUCTION_NODE, _childNodeGroup); 457 458 completeTestSequences(DTM.COMMENT_NODE, _childNodeGroup); 460 461 completeTestSequences(DTM.ATTRIBUTE_NODE, _attribNodeGroup); 463 464 final Vector names = _stylesheet.getXSLTC().getNamesIndex(); 465 if (starGroup != null || atStarGroup != null || 466 _childNodeGroup != null || _attribNodeGroup != null) 467 { 468 final int n = _patternGroups.length; 469 470 for (int i = DTM.NTYPES; i < n; i++) { 472 if (_patternGroups[i] == null) continue; 473 474 final String name = (String ) names.elementAt(i - DTM.NTYPES); 475 476 if (isAttributeName(name)) { 477 completeTestSequences(i, atStarGroup); 479 480 completeTestSequences(i, _attribNodeGroup); 482 } 483 else { 484 completeTestSequences(i, starGroup); 486 487 completeTestSequences(i, _childNodeGroup); 489 } 490 } 491 } 492 493 _testSeq = new TestSeq[DTM.NTYPES + names.size()]; 494 495 final int n = _patternGroups.length; 496 for (int i = 0; i < n; i++) { 497 final Vector patterns = _patternGroups[i]; 498 if (patterns != null) { 499 final TestSeq testSeq = new TestSeq(patterns, i, this); 500 testSeq.reduce(); 502 _testSeq[i] = testSeq; 503 testSeq.findTemplates(_neededTemplates); 504 } 505 } 506 507 if (_childNodeGroup != null && _childNodeGroup.size() > 0) { 508 _childNodeTestSeq = new TestSeq(_childNodeGroup, -1, this); 509 _childNodeTestSeq.reduce(); 510 _childNodeTestSeq.findTemplates(_neededTemplates); 511 } 512 513 520 521 if (_idxGroup != null && _idxGroup.size() > 0) { 522 _idxTestSeq = new TestSeq(_idxGroup, this); 523 _idxTestSeq.reduce(); 524 _idxTestSeq.findTemplates(_neededTemplates); 525 } 526 527 if (_rootPattern != null) { 528 _neededTemplates.put(_rootPattern.getTemplate(), this); 530 } 531 } 532 533 private void compileNamedTemplate(Template template, 534 ClassGenerator classGen) { 535 final ConstantPoolGen cpg = classGen.getConstantPool(); 536 final InstructionList il = new InstructionList(); 537 String methodName = Util.escape(template.getName().toString()); 538 539 int numParams = 0; 540 if (template.isSimpleNamedTemplate()) { 541 Vector parameters = template.getParameters(); 542 numParams = parameters.size(); 543 } 544 545 org.apache.bcel.generic.Type[] types = 547 new org.apache.bcel.generic.Type[4 + numParams]; 548 String [] names = new String [4 + numParams]; 549 types[0] = Util.getJCRefType(DOM_INTF_SIG); 550 types[1] = Util.getJCRefType(NODE_ITERATOR_SIG); 551 types[2] = Util.getJCRefType(TRANSLET_OUTPUT_SIG); 552 types[3] = org.apache.bcel.generic.Type.INT; 553 names[0] = DOCUMENT_PNAME; 554 names[1] = ITERATOR_PNAME; 555 names[2] = TRANSLET_OUTPUT_PNAME; 556 names[3] = NODE_PNAME; 557 558 for (int i = 4; i < 4 + numParams; i++) { 562 types[i] = Util.getJCRefType(OBJECT_SIG); 563 names[i] = "param" + String.valueOf(i-4); 564 } 565 566 NamedMethodGenerator methodGen = 567 new NamedMethodGenerator(ACC_PUBLIC, 568 org.apache.bcel.generic.Type.VOID, 569 types, names, methodName, 570 getClassName(), il, cpg); 571 572 il.append(template.compile(classGen, methodGen)); 573 il.append(RETURN); 574 575 methodGen.stripAttributes(true); 576 methodGen.setMaxLocals(); 577 methodGen.setMaxStack(); 578 methodGen.removeNOPs(); 579 classGen.addMethod(methodGen.getMethod()); 580 } 581 582 private void compileTemplates(ClassGenerator classGen, 583 MethodGenerator methodGen, 584 InstructionHandle next) 585 { 586 Enumeration templates = _namedTemplates.keys(); 587 while (templates.hasMoreElements()) { 588 final Template template = (Template)templates.nextElement(); 589 compileNamedTemplate(template, classGen); 590 } 591 592 templates = _neededTemplates.keys(); 593 while (templates.hasMoreElements()) { 594 final Template template = (Template)templates.nextElement(); 595 if (template.hasContents()) { 596 InstructionList til = template.compile(classGen, methodGen); 598 til.append(new GOTO_W(next)); 599 _templateILs.put(template, til); 600 _templateIHs.put(template, til.getStart()); 601 } 602 else { 603 _templateIHs.put(template, next); 605 } 606 } 607 } 608 609 private void appendTemplateCode(InstructionList body) { 610 final Enumeration templates = _neededTemplates.keys(); 611 while (templates.hasMoreElements()) { 612 final Object iList = 613 _templateILs.get(templates.nextElement()); 614 if (iList != null) { 615 body.append((InstructionList)iList); 616 } 617 } 618 } 619 620 private void appendTestSequences(InstructionList body) { 621 final int n = _testSeq.length; 622 for (int i = 0; i < n; i++) { 623 final TestSeq testSeq = _testSeq[i]; 624 if (testSeq != null) { 625 InstructionList il = testSeq.getInstructionList(); 626 if (il != null) 627 body.append(il); 628 } 630 } 631 } 632 633 public static void compileGetChildren(ClassGenerator classGen, 634 MethodGenerator methodGen, 635 int node) { 636 final ConstantPoolGen cpg = classGen.getConstantPool(); 637 final InstructionList il = methodGen.getInstructionList(); 638 final int git = cpg.addInterfaceMethodref(DOM_INTF, 639 GET_CHILDREN, 640 GET_CHILDREN_SIG); 641 il.append(methodGen.loadDOM()); 642 il.append(new ILOAD(node)); 643 il.append(new INVOKEINTERFACE(git, 2)); 644 } 645 646 649 private InstructionList compileDefaultRecursion(ClassGenerator classGen, 650 MethodGenerator methodGen, 651 InstructionHandle next) { 652 final ConstantPoolGen cpg = classGen.getConstantPool(); 653 final InstructionList il = new InstructionList(); 654 final String applyTemplatesSig = classGen.getApplyTemplatesSig(); 655 final int git = cpg.addInterfaceMethodref(DOM_INTF, 656 GET_CHILDREN, 657 GET_CHILDREN_SIG); 658 final int applyTemplates = cpg.addMethodref(getClassName(), 659 functionName(), 660 applyTemplatesSig); 661 il.append(classGen.loadTranslet()); 662 il.append(methodGen.loadDOM()); 663 664 il.append(methodGen.loadDOM()); 665 il.append(new ILOAD(_currentIndex)); 666 il.append(new INVOKEINTERFACE(git, 2)); 667 il.append(methodGen.loadHandler()); 668 il.append(new INVOKEVIRTUAL(applyTemplates)); 669 il.append(new GOTO_W(next)); 670 return il; 671 } 672 673 677 private InstructionList compileDefaultText(ClassGenerator classGen, 678 MethodGenerator methodGen, 679 InstructionHandle next) { 680 final ConstantPoolGen cpg = classGen.getConstantPool(); 681 final InstructionList il = new InstructionList(); 682 683 final int chars = cpg.addInterfaceMethodref(DOM_INTF, 684 CHARACTERS, 685 CHARACTERS_SIG); 686 il.append(methodGen.loadDOM()); 687 il.append(new ILOAD(_currentIndex)); 688 il.append(methodGen.loadHandler()); 689 il.append(new INVOKEINTERFACE(chars, 3)); 690 il.append(new GOTO_W(next)); 691 return il; 692 } 693 694 private InstructionList compileNamespaces(ClassGenerator classGen, 695 MethodGenerator methodGen, 696 boolean[] isNamespace, 697 boolean[] isAttribute, 698 boolean attrFlag, 699 InstructionHandle defaultTarget) { 700 final XSLTC xsltc = classGen.getParser().getXSLTC(); 701 final ConstantPoolGen cpg = classGen.getConstantPool(); 702 703 final Vector namespaces = xsltc.getNamespaceIndex(); 705 final Vector names = xsltc.getNamesIndex(); 706 final int namespaceCount = namespaces.size() + 1; 707 final int namesCount = names.size(); 708 709 final InstructionList il = new InstructionList(); 710 final int[] types = new int[namespaceCount]; 711 final InstructionHandle[] targets = new InstructionHandle[types.length]; 712 713 if (namespaceCount > 0) { 714 boolean compiled = false; 715 716 for (int i = 0; i < namespaceCount; i++) { 718 targets[i] = defaultTarget; 719 types[i] = i; 720 } 721 722 for (int i = DTM.NTYPES; i < (DTM.NTYPES+namesCount); i++) { 724 if ((isNamespace[i]) && (isAttribute[i] == attrFlag)) { 725 String name = (String )names.elementAt(i-DTM.NTYPES); 726 String namespace = name.substring(0,name.lastIndexOf(':')); 727 final int type = xsltc.registerNamespace(namespace); 728 729 if ((i < _testSeq.length) && 730 (_testSeq[i] != null)) { 731 targets[type] = 732 (_testSeq[i]).compile(classGen, 733 methodGen, 734 defaultTarget); 735 compiled = true; 736 } 737 } 738 } 739 740 if (!compiled) return(null); 742 743 final int getNS = cpg.addInterfaceMethodref(DOM_INTF, 745 "getNamespaceType", 746 "(I)I"); 747 il.append(methodGen.loadDOM()); 748 il.append(new ILOAD(_currentIndex)); 749 il.append(new INVOKEINTERFACE(getNS, 2)); 750 il.append(new SWITCH(types, targets, defaultTarget)); 751 return(il); 752 } 753 else { 754 return(null); 755 } 756 } 757 758 762 public void compileApplyTemplates(ClassGenerator classGen) { 763 final XSLTC xsltc = classGen.getParser().getXSLTC(); 764 final ConstantPoolGen cpg = classGen.getConstantPool(); 765 final Vector names = xsltc.getNamesIndex(); 766 767 final org.apache.bcel.generic.Type[] argTypes = 769 new org.apache.bcel.generic.Type[3]; 770 argTypes[0] = Util.getJCRefType(DOM_INTF_SIG); 771 argTypes[1] = Util.getJCRefType(NODE_ITERATOR_SIG); 772 argTypes[2] = Util.getJCRefType(TRANSLET_OUTPUT_SIG); 773 774 final String [] argNames = new String [3]; 775 argNames[0] = DOCUMENT_PNAME; 776 argNames[1] = ITERATOR_PNAME; 777 argNames[2] = TRANSLET_OUTPUT_PNAME; 778 779 final InstructionList mainIL = new InstructionList(); 780 final MethodGenerator methodGen = 781 new MethodGenerator(ACC_PUBLIC | ACC_FINAL, 782 org.apache.bcel.generic.Type.VOID, 783 argTypes, argNames, functionName(), 784 getClassName(), mainIL, 785 classGen.getConstantPool()); 786 methodGen.addException("org.apache.xalan.xsltc.TransletException"); 787 788 final LocalVariableGen current; 790 current = methodGen.addLocalVariable2("current", 791 org.apache.bcel.generic.Type.INT, 792 mainIL.getEnd()); 793 _currentIndex = current.getIndex(); 794 795 final InstructionList body = new InstructionList(); 798 body.append(NOP); 799 800 final InstructionList ilLoop = new InstructionList(); 803 ilLoop.append(methodGen.loadIterator()); 804 ilLoop.append(methodGen.nextNode()); 805 ilLoop.append(DUP); 806 ilLoop.append(new ISTORE(_currentIndex)); 807 808 final BranchHandle ifeq = ilLoop.append(new IFLT(null)); 811 final BranchHandle loop = ilLoop.append(new GOTO_W(null)); 812 ifeq.setTarget(ilLoop.append(RETURN)); final InstructionHandle ihLoop = ilLoop.getStart(); 814 815 InstructionList ilRecurse = 817 compileDefaultRecursion(classGen, methodGen, ihLoop); 818 InstructionHandle ihRecurse = ilRecurse.getStart(); 819 820 InstructionList ilText = 822 compileDefaultText(classGen, methodGen, ihLoop); 823 InstructionHandle ihText = ilText.getStart(); 824 825 final int[] types = new int[DTM.NTYPES + names.size()]; 827 for (int i = 0; i < types.length; i++) { 828 types[i] = i; 829 } 830 831 final boolean[] isAttribute = new boolean[types.length]; 833 final boolean[] isNamespace = new boolean[types.length]; 834 for (int i = 0; i < names.size(); i++) { 835 final String name = (String )names.elementAt(i); 836 isAttribute[i + DTM.NTYPES] = isAttributeName(name); 837 isNamespace[i + DTM.NTYPES] = isNamespaceName(name); 838 } 839 840 compileTemplates(classGen, methodGen, ihLoop); 842 843 final TestSeq elemTest = _testSeq[DTM.ELEMENT_NODE]; 845 InstructionHandle ihElem = ihRecurse; 846 if (elemTest != null) 847 ihElem = elemTest.compile(classGen, methodGen, ihRecurse); 848 849 final TestSeq attrTest = _testSeq[DTM.ATTRIBUTE_NODE]; 851 InstructionHandle ihAttr = ihText; 852 if (attrTest != null) 853 ihAttr = attrTest.compile(classGen, methodGen, ihAttr); 854 855 InstructionList ilKey = null; 857 if (_idxTestSeq != null) { 858 loop.setTarget(_idxTestSeq.compile(classGen, methodGen, body.getStart())); 859 ilKey = _idxTestSeq.getInstructionList(); 860 } 861 else { 862 loop.setTarget(body.getStart()); 863 } 864 865 if (_childNodeTestSeq != null) { 868 double nodePrio = _childNodeTestSeq.getPriority(); 870 int nodePos = _childNodeTestSeq.getPosition(); 871 double elemPrio = (0 - Double.MAX_VALUE); 872 int elemPos = Integer.MIN_VALUE; 873 874 if (elemTest != null) { 875 elemPrio = elemTest.getPriority(); 876 elemPos = elemTest.getPosition(); 877 } 878 if (elemPrio == Double.NaN || elemPrio < nodePrio || 879 (elemPrio == nodePrio && elemPos < nodePos)) 880 { 881 ihElem = _childNodeTestSeq.compile(classGen, methodGen, ihLoop); 882 } 883 884 final TestSeq textTest = _testSeq[DTM.TEXT_NODE]; 886 double textPrio = (0 - Double.MAX_VALUE); 887 int textPos = Integer.MIN_VALUE; 888 889 if (textTest != null) { 890 textPrio = textTest.getPriority(); 891 textPos = textTest.getPosition(); 892 } 893 if (textPrio == Double.NaN || textPrio < nodePrio || 894 (textPrio == nodePrio && textPos < nodePos)) 895 { 896 ihText = _childNodeTestSeq.compile(classGen, methodGen, ihLoop); 897 _testSeq[DTM.TEXT_NODE] = _childNodeTestSeq; 898 } 899 } 900 901 InstructionHandle elemNamespaceHandle = ihElem; 903 InstructionList nsElem = compileNamespaces(classGen, methodGen, 904 isNamespace, isAttribute, 905 false, ihElem); 906 if (nsElem != null) elemNamespaceHandle = nsElem.getStart(); 907 908 InstructionHandle attrNamespaceHandle = ihAttr; 910 InstructionList nsAttr = compileNamespaces(classGen, methodGen, 911 isNamespace, isAttribute, 912 true, ihAttr); 913 if (nsAttr != null) attrNamespaceHandle = nsAttr.getStart(); 914 915 final InstructionHandle[] targets = new InstructionHandle[types.length]; 917 for (int i = DTM.NTYPES; i < targets.length; i++) { 918 final TestSeq testSeq = _testSeq[i]; 919 if (isNamespace[i]) { 921 if (isAttribute[i]) 922 targets[i] = attrNamespaceHandle; 923 else 924 targets[i] = elemNamespaceHandle; 925 } 926 else if (testSeq != null) { 928 if (isAttribute[i]) 929 targets[i] = testSeq.compile(classGen, methodGen, 930 attrNamespaceHandle); 931 else 932 targets[i] = testSeq.compile(classGen, methodGen, 933 elemNamespaceHandle); 934 } 935 else { 936 targets[i] = ihLoop; 937 } 938 } 939 940 941 targets[DTM.ROOT_NODE] = _rootPattern != null 943 ? getTemplateInstructionHandle(_rootPattern.getTemplate()) 944 : ihRecurse; 945 946 targets[DTM.DOCUMENT_NODE] = _rootPattern != null 948 ? getTemplateInstructionHandle(_rootPattern.getTemplate()) 949 : ihRecurse; 950 951 targets[DTM.TEXT_NODE] = _testSeq[DTM.TEXT_NODE] != null 953 ? _testSeq[DTM.TEXT_NODE].compile(classGen, methodGen, ihText) 954 : ihText; 955 956 targets[DTM.NAMESPACE_NODE] = ihLoop; 958 959 targets[DTM.ELEMENT_NODE] = elemNamespaceHandle; 961 962 targets[DTM.ATTRIBUTE_NODE] = attrNamespaceHandle; 964 965 InstructionHandle ihPI = ihLoop; 967 if (_childNodeTestSeq != null) ihPI = ihElem; 968 if (_testSeq[DTM.PROCESSING_INSTRUCTION_NODE] != null) 969 targets[DTM.PROCESSING_INSTRUCTION_NODE] = 970 _testSeq[DTM.PROCESSING_INSTRUCTION_NODE]. 971 compile(classGen, methodGen, ihPI); 972 else 973 targets[DTM.PROCESSING_INSTRUCTION_NODE] = ihPI; 974 975 InstructionHandle ihComment = ihLoop; 977 if (_childNodeTestSeq != null) ihComment = ihElem; 978 targets[DTM.COMMENT_NODE] = _testSeq[DTM.COMMENT_NODE] != null 979 ? _testSeq[DTM.COMMENT_NODE].compile(classGen, methodGen, ihComment) 980 : ihComment; 981 982 targets[DTM.CDATA_SECTION_NODE] = ihLoop; 984 985 targets[DTM.DOCUMENT_FRAGMENT_NODE] = ihLoop; 987 988 targets[DTM.DOCUMENT_TYPE_NODE] = ihLoop; 990 991 targets[DTM.ENTITY_NODE] = ihLoop; 993 994 targets[DTM.ENTITY_REFERENCE_NODE] = ihLoop; 996 997 targets[DTM.NOTATION_NODE] = ihLoop; 999 1000 1001 for (int i = DTM.NTYPES; i < targets.length; i++) { 1003 final TestSeq testSeq = _testSeq[i]; 1004 if ((testSeq == null) || (isNamespace[i])) { 1006 if (isAttribute[i]) 1007 targets[i] = attrNamespaceHandle; 1008 else 1009 targets[i] = elemNamespaceHandle; 1010 } 1011 else { 1013 if (isAttribute[i]) 1014 targets[i] = testSeq.compile(classGen, methodGen, 1015 attrNamespaceHandle); 1016 else 1017 targets[i] = testSeq.compile(classGen, methodGen, 1018 elemNamespaceHandle); 1019 } 1020 } 1021 1022 if (ilKey != null) body.insert(ilKey); 1023 1024 final int getType = cpg.addInterfaceMethodref(DOM_INTF, 1026 "getExpandedTypeID", 1027 "(I)I"); 1028 body.append(methodGen.loadDOM()); 1029 body.append(new ILOAD(_currentIndex)); 1030 body.append(new INVOKEINTERFACE(getType, 2)); 1031 1032 InstructionHandle disp = body.append(new SWITCH(types, targets, ihLoop)); 1034 1035 appendTestSequences(body); 1037 appendTemplateCode(body); 1039 1040 if (nsElem != null) body.append(nsElem); 1042 if (nsAttr != null) body.append(nsAttr); 1044 1045 body.append(ilRecurse); 1047 body.append(ilText); 1049 1050 mainIL.append(new GOTO_W(ihLoop)); 1052 mainIL.append(body); 1053 mainIL.append(ilLoop); 1055 1056 peepHoleOptimization(methodGen); 1057 methodGen.stripAttributes(true); 1058 1059 methodGen.setMaxLocals(); 1060 methodGen.setMaxStack(); 1061 methodGen.removeNOPs(); 1062 classGen.addMethod(methodGen.getMethod()); 1063 1064 if (_importLevels != null) { 1066 Enumeration levels = _importLevels.keys(); 1067 while (levels.hasMoreElements()) { 1068 Integer max = (Integer )levels.nextElement(); 1069 Integer min = (Integer )_importLevels.get(max); 1070 compileApplyImports(classGen, min.intValue(), max.intValue()); 1071 } 1072 } 1073 } 1074 1075 private void compileTemplateCalls(ClassGenerator classGen, 1076 MethodGenerator methodGen, 1077 InstructionHandle next, int min, int max){ 1078 Enumeration templates = _neededTemplates.keys(); 1079 while (templates.hasMoreElements()) { 1080 final Template template = (Template)templates.nextElement(); 1081 final int prec = template.getImportPrecedence(); 1082 if ((prec >= min) && (prec < max)) { 1083 if (template.hasContents()) { 1084 InstructionList til = template.compile(classGen, methodGen); 1085 til.append(new GOTO_W(next)); 1086 _templateILs.put(template, til); 1087 _templateIHs.put(template, til.getStart()); 1088 } 1089 else { 1090 _templateIHs.put(template, next); 1092 } 1093 } 1094 } 1095 } 1096 1097 1098 public void compileApplyImports(ClassGenerator classGen, int min, int max) { 1099 final XSLTC xsltc = classGen.getParser().getXSLTC(); 1100 final ConstantPoolGen cpg = classGen.getConstantPool(); 1101 final Vector names = xsltc.getNamesIndex(); 1102 1103 _namedTemplates = new Hashtable (); 1105 _neededTemplates = new Hashtable (); 1106 _templateIHs = new Hashtable (); 1107 _templateILs = new Hashtable (); 1108 _patternGroups = new Vector [32]; 1109 _rootPattern = null; 1110 1111 Vector oldTemplates = _templates; 1113 1114 _templates = new Vector (); 1116 final Enumeration templates = oldTemplates.elements(); 1117 while (templates.hasMoreElements()) { 1118 final Template template = (Template)templates.nextElement(); 1119 final int prec = template.getImportPrecedence(); 1120 if ((prec >= min) && (prec < max)) addTemplate(template); 1121 } 1122 1123 processPatterns(_keys); 1125 1126 final org.apache.bcel.generic.Type[] argTypes = 1128 new org.apache.bcel.generic.Type[3]; 1129 argTypes[0] = Util.getJCRefType(DOM_INTF_SIG); 1130 argTypes[1] = Util.getJCRefType(NODE_ITERATOR_SIG); 1131 argTypes[2] = Util.getJCRefType(TRANSLET_OUTPUT_SIG); 1132 1133 final String [] argNames = new String [3]; 1134 argNames[0] = DOCUMENT_PNAME; 1135 argNames[1] = ITERATOR_PNAME; 1136 argNames[2] = TRANSLET_OUTPUT_PNAME; 1137 1138 final InstructionList mainIL = new InstructionList(); 1139 final MethodGenerator methodGen = 1140 new MethodGenerator(ACC_PUBLIC | ACC_FINAL, 1141 org.apache.bcel.generic.Type.VOID, 1142 argTypes, argNames, functionName()+'_'+max, 1143 getClassName(), mainIL, 1144 classGen.getConstantPool()); 1145 methodGen.addException("org.apache.xalan.xsltc.TransletException"); 1146 1147 final LocalVariableGen current; 1149 current = methodGen.addLocalVariable2("current", 1150 org.apache.bcel.generic.Type.INT, 1151 mainIL.getEnd()); 1152 _currentIndex = current.getIndex(); 1153 1154 final InstructionList body = new InstructionList(); 1157 body.append(NOP); 1158 1159 final InstructionList ilLoop = new InstructionList(); 1162 ilLoop.append(methodGen.loadIterator()); 1163 ilLoop.append(methodGen.nextNode()); 1164 ilLoop.append(DUP); 1165 ilLoop.append(new ISTORE(_currentIndex)); 1166 1167 final BranchHandle ifeq = ilLoop.append(new IFLT(null)); 1170 final BranchHandle loop = ilLoop.append(new GOTO_W(null)); 1171 ifeq.setTarget(ilLoop.append(RETURN)); final InstructionHandle ihLoop = ilLoop.getStart(); 1173 1174 InstructionList ilRecurse = 1176 compileDefaultRecursion(classGen, methodGen, ihLoop); 1177 InstructionHandle ihRecurse = ilRecurse.getStart(); 1178 1179 InstructionList ilText = 1181 compileDefaultText(classGen, methodGen, ihLoop); 1182 InstructionHandle ihText = ilText.getStart(); 1183 1184 final int[] types = new int[DTM.NTYPES + names.size()]; 1186 for (int i = 0; i < types.length; i++) { 1187 types[i] = i; 1188 } 1189 1190 final boolean[] isAttribute = new boolean[types.length]; 1191 final boolean[] isNamespace = new boolean[types.length]; 1192 for (int i = 0; i < names.size(); i++) { 1193 final String name = (String )names.elementAt(i); 1194 isAttribute[i+DTM.NTYPES] = isAttributeName(name); 1195 isNamespace[i+DTM.NTYPES] = isNamespaceName(name); 1196 } 1197 1198 compileTemplateCalls(classGen, methodGen, ihLoop, min, max); 1200 1201 final TestSeq elemTest = _testSeq[DTM.ELEMENT_NODE]; 1203 InstructionHandle ihElem = ihRecurse; 1204 if (elemTest != null) { 1205 ihElem = elemTest.compile(classGen, methodGen, ihLoop); 1206 } 1207 1208 final TestSeq attrTest = _testSeq[DTM.ATTRIBUTE_NODE]; 1210 InstructionHandle ihAttr = ihLoop; 1211 if (attrTest != null) { 1212 ihAttr = attrTest.compile(classGen, methodGen, ihAttr); 1213 } 1214 1215 InstructionList ilKey = null; 1217 if (_idxTestSeq != null) { 1218 loop.setTarget(_idxTestSeq.compile(classGen, methodGen, body.getStart())); 1219 ilKey = _idxTestSeq.getInstructionList(); 1220 } 1221 else { 1222 loop.setTarget(body.getStart()); 1223 } 1224 1225 if (_childNodeTestSeq != null) { 1228 double nodePrio = _childNodeTestSeq.getPriority(); 1230 int nodePos = _childNodeTestSeq.getPosition(); 1231 double elemPrio = (0 - Double.MAX_VALUE); 1232 int elemPos = Integer.MIN_VALUE; 1233 1234 if (elemTest != null) { 1235 elemPrio = elemTest.getPriority(); 1236 elemPos = elemTest.getPosition(); 1237 } 1238 1239 if (elemPrio == Double.NaN || elemPrio < nodePrio || 1240 (elemPrio == nodePrio && elemPos < nodePos)) 1241 { 1242 ihElem = _childNodeTestSeq.compile(classGen, methodGen, ihLoop); 1243 } 1244 1245 final TestSeq textTest = _testSeq[DTM.TEXT_NODE]; 1247 double textPrio = (0 - Double.MAX_VALUE); 1248 int textPos = Integer.MIN_VALUE; 1249 1250 if (textTest != null) { 1251 textPrio = textTest.getPriority(); 1252 textPos = textTest.getPosition(); 1253 } 1254 1255 if (textPrio == Double.NaN || textPrio < nodePrio || 1256 (textPrio == nodePrio && textPos < nodePos)) 1257 { 1258 ihText = _childNodeTestSeq.compile(classGen, methodGen, ihLoop); 1259 _testSeq[DTM.TEXT_NODE] = _childNodeTestSeq; 1260 } 1261 } 1262 1263 InstructionHandle elemNamespaceHandle = ihElem; 1265 InstructionList nsElem = compileNamespaces(classGen, methodGen, 1266 isNamespace, isAttribute, 1267 false, ihElem); 1268 if (nsElem != null) elemNamespaceHandle = nsElem.getStart(); 1269 1270 InstructionList nsAttr = compileNamespaces(classGen, methodGen, 1272 isNamespace, isAttribute, 1273 true, ihAttr); 1274 InstructionHandle attrNamespaceHandle = ihAttr; 1275 if (nsAttr != null) attrNamespaceHandle = nsAttr.getStart(); 1276 1277 final InstructionHandle[] targets = new InstructionHandle[types.length]; 1279 for (int i = DTM.NTYPES; i < targets.length; i++) { 1280 final TestSeq testSeq = _testSeq[i]; 1281 if (isNamespace[i]) { 1283 if (isAttribute[i]) 1284 targets[i] = attrNamespaceHandle; 1285 else 1286 targets[i] = elemNamespaceHandle; 1287 } 1288 else if (testSeq != null) { 1290 if (isAttribute[i]) 1291 targets[i] = testSeq.compile(classGen, methodGen, 1292 attrNamespaceHandle); 1293 else 1294 targets[i] = testSeq.compile(classGen, methodGen, 1295 elemNamespaceHandle); 1296 } 1297 else { 1298 targets[i] = ihLoop; 1299 } 1300 } 1301 1302 targets[DTM.ROOT_NODE] = _rootPattern != null 1304 ? getTemplateInstructionHandle(_rootPattern.getTemplate()) 1305 : ihRecurse; 1306 targets[DTM.DOCUMENT_NODE] = _rootPattern != null 1308 ? getTemplateInstructionHandle(_rootPattern.getTemplate()) 1309 : ihRecurse; 1311 targets[DTM.TEXT_NODE] = _testSeq[DTM.TEXT_NODE] != null 1313 ? _testSeq[DTM.TEXT_NODE].compile(classGen, methodGen, ihText) 1314 : ihText; 1315 1316 targets[DTM.NAMESPACE_NODE] = ihLoop; 1318 1319 targets[DTM.ELEMENT_NODE] = elemNamespaceHandle; 1321 1322 targets[DTM.ATTRIBUTE_NODE] = attrNamespaceHandle; 1324 1325 InstructionHandle ihPI = ihLoop; 1327 if (_childNodeTestSeq != null) ihPI = ihElem; 1328 if (_testSeq[DTM.PROCESSING_INSTRUCTION_NODE] != null) { 1329 targets[DTM.PROCESSING_INSTRUCTION_NODE] = 1330 _testSeq[DTM.PROCESSING_INSTRUCTION_NODE]. 1331 compile(classGen, methodGen, ihPI); 1332 } 1333 else { 1334 targets[DTM.PROCESSING_INSTRUCTION_NODE] = ihPI; 1335 } 1336 1337 InstructionHandle ihComment = ihLoop; 1339 if (_childNodeTestSeq != null) ihComment = ihElem; 1340 targets[DTM.COMMENT_NODE] = _testSeq[DTM.COMMENT_NODE] != null 1341 ? _testSeq[DTM.COMMENT_NODE].compile(classGen, methodGen, ihComment) 1342 : ihComment; 1343 1344 targets[DTM.CDATA_SECTION_NODE] = ihLoop; 1346 1347 targets[DTM.DOCUMENT_FRAGMENT_NODE] = ihLoop; 1349 1350 targets[DTM.DOCUMENT_TYPE_NODE] = ihLoop; 1352 1353 targets[DTM.ENTITY_NODE] = ihLoop; 1355 1356 targets[DTM.ENTITY_REFERENCE_NODE] = ihLoop; 1358 1359 targets[DTM.NOTATION_NODE] = ihLoop; 1361 1362 1363 1364 for (int i = DTM.NTYPES; i < targets.length; i++) { 1366 final TestSeq testSeq = _testSeq[i]; 1367 if ((testSeq == null) || (isNamespace[i])) { 1369 if (isAttribute[i]) 1370 targets[i] = attrNamespaceHandle; 1371 else 1372 targets[i] = elemNamespaceHandle; 1373 } 1374 else { 1376 if (isAttribute[i]) 1377 targets[i] = testSeq.compile(classGen, methodGen, 1378 attrNamespaceHandle); 1379 else 1380 targets[i] = testSeq.compile(classGen, methodGen, 1381 elemNamespaceHandle); 1382 } 1383 } 1384 1385 if (ilKey != null) body.insert(ilKey); 1386 1387 final int getType = cpg.addInterfaceMethodref(DOM_INTF, 1389 "getExpandedTypeID", 1390 "(I)I"); 1391 body.append(methodGen.loadDOM()); 1392 body.append(new ILOAD(_currentIndex)); 1393 body.append(new INVOKEINTERFACE(getType, 2)); 1394 1395 InstructionHandle disp = body.append(new SWITCH(types,targets,ihLoop)); 1397 1398 appendTestSequences(body); 1400 appendTemplateCode(body); 1402 1403 if (nsElem != null) body.append(nsElem); 1405 if (nsAttr != null) body.append(nsAttr); 1407 1408 body.append(ilRecurse); 1410 body.append(ilText); 1412 1413 mainIL.append(new GOTO_W(ihLoop)); 1415 mainIL.append(body); 1416 mainIL.append(ilLoop); 1418 1419 peepHoleOptimization(methodGen); 1420 methodGen.stripAttributes(true); 1421 1422 methodGen.setMaxLocals(); 1423 methodGen.setMaxStack(); 1424 methodGen.removeNOPs(); 1425 classGen.addMethod(methodGen.getMethod()); 1426 1427 _templates = oldTemplates; 1429 } 1430 1431 1434 private void peepHoleOptimization(MethodGenerator methodGen) { 1435 InstructionList il = methodGen.getInstructionList(); 1436 InstructionFinder find = new InstructionFinder(il); 1437 InstructionHandle ih; 1438 String pattern; 1439 1440 pattern = "`ALOAD'`POP'`Instruction'"; 1442 for(Iterator iter=find.search(pattern); iter.hasNext();){ 1443 InstructionHandle[] match = (InstructionHandle[])iter.next(); 1444 try { 1445 if ((!match[0].hasTargeters()) && (!match[1].hasTargeters())) { 1446 il.delete(match[0], match[1]); 1447 } 1448 } 1449 catch (TargetLostException e) { 1450 } 1452 } 1453 pattern = "`ILOAD'`ALOAD'`SWAP'`Instruction'"; 1455 for(Iterator iter=find.search(pattern); iter.hasNext();){ 1456 InstructionHandle[] match = (InstructionHandle[])iter.next(); 1457 try { 1458 org.apache.bcel.generic.Instruction iload; 1459 org.apache.bcel.generic.Instruction aload; 1460 if ((!match[0].hasTargeters()) && 1461 (!match[1].hasTargeters()) && 1462 (!match[2].hasTargeters())) { 1463 iload = match[0].getInstruction(); 1464 aload = match[1].getInstruction(); 1465 il.insert(match[0], aload); 1466 il.insert(match[0], iload); 1467 il.delete(match[0], match[2]); 1468 } 1469 } 1470 catch (TargetLostException e) { 1471 } 1473 } 1474 1475 pattern = "`ALOAD_1'`ALOAD_1'`Instruction'"; 1477 for(Iterator iter=find.search(pattern); iter.hasNext();){ 1478 InstructionHandle[] match = (InstructionHandle[])iter.next(); 1479 try { 1480 org.apache.bcel.generic.Instruction iload; 1481 org.apache.bcel.generic.Instruction aload; 1482 if ((!match[0].hasTargeters()) && (!match[1].hasTargeters())) { 1483 il.insert(match[1], new DUP()); 1484 il.delete(match[1]); 1485 } 1486 } 1487 catch (TargetLostException e) { 1488 } 1490 } 1491 1492 } 1493 1494 public InstructionHandle getTemplateInstructionHandle(Template template) { 1495 return (InstructionHandle)_templateIHs.get(template); 1496 } 1497 1498 1501 private static boolean isAttributeName(String qname) { 1502 final int col = qname.lastIndexOf(':') + 1; 1503 return (qname.charAt(col) == '@'); 1504 } 1505 1506 1510 private static boolean isNamespaceName(String qname) { 1511 final int col = qname.lastIndexOf(':'); 1512 return (col > -1 && qname.charAt(qname.length()-1) == '*'); 1513 } 1514} 1515 | Popular Tags |