1 16 19 20 package com.sun.org.apache.xalan.internal.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 com.sun.org.apache.bcel.internal.generic.Instruction; 28 import com.sun.org.apache.bcel.internal.generic.BranchHandle; 29 import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; 30 import com.sun.org.apache.bcel.internal.generic.DUP; 31 import com.sun.org.apache.bcel.internal.generic.GOTO_W; 32 import com.sun.org.apache.bcel.internal.generic.IFLT; 33 import com.sun.org.apache.bcel.internal.generic.ILOAD; 34 import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE; 35 import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL; 36 import com.sun.org.apache.bcel.internal.generic.ISTORE; 37 import com.sun.org.apache.bcel.internal.generic.InstructionHandle; 38 import com.sun.org.apache.bcel.internal.generic.InstructionList; 39 import com.sun.org.apache.bcel.internal.generic.LocalVariableGen; 40 import com.sun.org.apache.bcel.internal.generic.SWITCH; 41 import com.sun.org.apache.bcel.internal.generic.TargetLostException; 42 import com.sun.org.apache.bcel.internal.util.InstructionFinder; 43 import com.sun.org.apache.xalan.internal.xsltc.DOM; 44 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator; 45 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator; 46 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.NamedMethodGenerator; 47 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util; 48 import com.sun.org.apache.xalan.internal.xsltc.dom.Axis; 49 import com.sun.org.apache.xml.internal.dtm.DTM; 50 51 62 final class Mode implements Constants { 63 64 67 private final QName _name; 68 69 72 private final Stylesheet _stylesheet; 73 74 77 private final String _methodName; 78 79 82 private Vector _templates; 83 84 87 private Vector _childNodeGroup = null; 88 89 92 private TestSeq _childNodeTestSeq = null; 93 94 97 private Vector _attribNodeGroup = null; 98 99 102 private TestSeq _attribNodeTestSeq = null; 103 104 107 private Vector _idxGroup = null; 108 109 112 private TestSeq _idxTestSeq = null; 113 114 117 private Vector [] _patternGroups; 118 119 122 private TestSeq[] _testSeq; 123 124 130 private Hashtable _preCompiled = new Hashtable (); 131 132 135 private Hashtable _neededTemplates = new Hashtable (); 136 137 140 private Hashtable _namedTemplates = new Hashtable (); 141 142 145 private Hashtable _templateIHs = new Hashtable (); 146 147 150 private Hashtable _templateILs = new Hashtable (); 151 152 155 private LocationPathPattern _rootPattern = null; 156 157 161 private Hashtable _importLevels = null; 162 163 166 private Hashtable _keys = null; 167 168 171 private int _currentIndex; 172 173 181 public Mode(QName name, Stylesheet stylesheet, String suffix) { 182 _name = name; 183 _stylesheet = stylesheet; 184 _methodName = APPLY_TEMPLATES + suffix; 185 _templates = new Vector (); 186 _patternGroups = new Vector [32]; 187 } 188 189 196 public String functionName() { 197 return _methodName; 198 } 199 200 public String functionName(int min, int max) { 201 if (_importLevels == null) { 202 _importLevels = new Hashtable (); 203 } 204 _importLevels.put(new Integer (max), new Integer (min)); 205 return _methodName + '_' + max; 206 } 207 208 211 public void addInstructionList(Pattern pattern, 212 InstructionList ilist) 213 { 214 _preCompiled.put(pattern, ilist); 215 } 216 217 221 public InstructionList getInstructionList(Pattern pattern) { 222 return (InstructionList) _preCompiled.get(pattern); 223 } 224 225 228 private String getClassName() { 229 return _stylesheet.getClassName(); 230 } 231 232 public Stylesheet getStylesheet() { 233 return _stylesheet; 234 } 235 236 public void addTemplate(Template template) { 237 _templates.addElement(template); 238 } 239 240 private Vector quicksort(Vector templates, int p, int r) { 241 if (p < r) { 242 final int q = partition(templates, p, r); 243 quicksort(templates, p, q); 244 quicksort(templates, q + 1, r); 245 } 246 return templates; 247 } 248 249 private int partition(Vector templates, int p, int r) { 250 final Template x = (Template)templates.elementAt(p); 251 int i = p - 1; 252 int j = r + 1; 253 while (true) { 254 while (x.compareTo((Template)templates.elementAt(--j)) > 0); 255 while (x.compareTo((Template)templates.elementAt(++i)) < 0); 256 if (i < j) { 257 templates.set(j, templates.set(i, templates.elementAt(j))); 258 } 259 else { 260 return j; 261 } 262 } 263 } 264 265 268 public void processPatterns(Hashtable keys) { 269 _keys = keys; 270 271 280 281 _templates = quicksort(_templates, 0, _templates.size() - 1); 282 283 292 293 final Enumeration templates = _templates.elements(); 295 while (templates.hasMoreElements()) { 296 final Template template = (Template)templates.nextElement(); 298 299 304 if (template.isNamed() && !template.disabled()) { 305 _namedTemplates.put(template, this); 306 } 307 308 final Pattern pattern = template.getPattern(); 310 if (pattern != null) { 311 flattenAlternative(pattern, template, keys); 312 } 313 } 314 prepareTestSequences(); 315 } 316 317 322 private void flattenAlternative(Pattern pattern, 323 Template template, 324 Hashtable keys) { 325 if (pattern instanceof IdKeyPattern) { 329 final IdKeyPattern idkey = (IdKeyPattern)pattern; 330 idkey.setTemplate(template); 331 if (_idxGroup == null) _idxGroup = new Vector (); 332 _idxGroup.add(pattern); 333 } 334 else if (pattern instanceof AlternativePattern) { 336 final AlternativePattern alt = (AlternativePattern)pattern; 337 flattenAlternative(alt.getLeft(), template, keys); 338 flattenAlternative(alt.getRight(), template, keys); 339 } 340 else if (pattern instanceof LocationPathPattern) { 342 final LocationPathPattern lpp = (LocationPathPattern)pattern; 343 lpp.setTemplate(template); 344 addPatternToGroup(lpp); 345 } 346 } 347 348 352 private void addPatternToGroup(final LocationPathPattern lpp) { 353 if (lpp instanceof IdKeyPattern) { 355 addPattern(-1, lpp); 356 } 357 else { 359 final StepPattern kernel = lpp.getKernelPattern(); 361 if (kernel != null) { 362 addPattern(kernel.getNodeType(), lpp); 363 } 364 else if (_rootPattern == null || 365 lpp.noSmallerThan(_rootPattern)) { 366 _rootPattern = lpp; 367 } 368 } 369 } 370 371 374 private void addPattern(int kernelType, LocationPathPattern pattern) { 375 final int oldLength = _patternGroups.length; 377 if (kernelType >= oldLength) { 378 Vector [] newGroups = new Vector [kernelType * 2]; 379 System.arraycopy(_patternGroups, 0, newGroups, 0, oldLength); 380 _patternGroups = newGroups; 381 } 382 383 Vector patterns; 385 386 if (kernelType == DOM.NO_TYPE) { 387 if (pattern.getAxis() == Axis.ATTRIBUTE) { 388 patterns = (_attribNodeGroup == null) ? 389 (_attribNodeGroup = new Vector (2)) : _attribNodeGroup; 390 } 391 else { 392 patterns = (_childNodeGroup == null) ? 393 (_childNodeGroup = new Vector (2)) : _childNodeGroup; 394 } 395 } 396 else { 397 patterns = (_patternGroups[kernelType] == null) ? 398 (_patternGroups[kernelType] = new Vector (2)) : 399 _patternGroups[kernelType]; 400 } 401 402 if (patterns.size() == 0) { 403 patterns.addElement(pattern); 404 } 405 else { 406 boolean inserted = false; 407 for (int i = 0; i < patterns.size(); i++) { 408 final LocationPathPattern lppToCompare = 409 (LocationPathPattern)patterns.elementAt(i); 410 411 if (pattern.noSmallerThan(lppToCompare)) { 412 inserted = true; 413 patterns.insertElementAt(pattern, i); 414 break; 415 } 416 } 417 if (inserted == false) { 418 patterns.addElement(pattern); 419 } 420 } 421 } 422 423 427 private void completeTestSequences(int nodeType, Vector patterns) { 428 if (patterns != null) { 429 if (_patternGroups[nodeType] == null) { 430 _patternGroups[nodeType] = patterns; 431 } 432 else { 433 final int m = patterns.size(); 434 for (int j = 0; j < m; j++) { 435 addPattern(nodeType, 436 (LocationPathPattern) patterns.elementAt(j)); 437 } 438 } 439 } 440 } 441 442 447 private void prepareTestSequences() { 448 final Vector starGroup = _patternGroups[DTM.ELEMENT_NODE]; 449 final Vector atStarGroup = _patternGroups[DTM.ATTRIBUTE_NODE]; 450 451 completeTestSequences(DTM.TEXT_NODE, _childNodeGroup); 453 454 completeTestSequences(DTM.ELEMENT_NODE, _childNodeGroup); 456 457 completeTestSequences(DTM.PROCESSING_INSTRUCTION_NODE, _childNodeGroup); 459 460 completeTestSequences(DTM.COMMENT_NODE, _childNodeGroup); 462 463 completeTestSequences(DTM.ATTRIBUTE_NODE, _attribNodeGroup); 465 466 final Vector names = _stylesheet.getXSLTC().getNamesIndex(); 467 if (starGroup != null || atStarGroup != null || 468 _childNodeGroup != null || _attribNodeGroup != null) 469 { 470 final int n = _patternGroups.length; 471 472 for (int i = DTM.NTYPES; i < n; i++) { 474 if (_patternGroups[i] == null) continue; 475 476 final String name = (String ) names.elementAt(i - DTM.NTYPES); 477 478 if (isAttributeName(name)) { 479 completeTestSequences(i, atStarGroup); 481 482 completeTestSequences(i, _attribNodeGroup); 484 } 485 else { 486 completeTestSequences(i, starGroup); 488 489 completeTestSequences(i, _childNodeGroup); 491 } 492 } 493 } 494 495 _testSeq = new TestSeq[DTM.NTYPES + names.size()]; 496 497 final int n = _patternGroups.length; 498 for (int i = 0; i < n; i++) { 499 final Vector patterns = _patternGroups[i]; 500 if (patterns != null) { 501 final TestSeq testSeq = new TestSeq(patterns, i, this); 502 testSeq.reduce(); 504 _testSeq[i] = testSeq; 505 testSeq.findTemplates(_neededTemplates); 506 } 507 } 508 509 if (_childNodeGroup != null && _childNodeGroup.size() > 0) { 510 _childNodeTestSeq = new TestSeq(_childNodeGroup, -1, this); 511 _childNodeTestSeq.reduce(); 512 _childNodeTestSeq.findTemplates(_neededTemplates); 513 } 514 515 522 523 if (_idxGroup != null && _idxGroup.size() > 0) { 524 _idxTestSeq = new TestSeq(_idxGroup, this); 525 _idxTestSeq.reduce(); 526 _idxTestSeq.findTemplates(_neededTemplates); 527 } 528 529 if (_rootPattern != null) { 530 _neededTemplates.put(_rootPattern.getTemplate(), this); 532 } 533 } 534 535 private void compileNamedTemplate(Template template, 536 ClassGenerator classGen) { 537 final ConstantPoolGen cpg = classGen.getConstantPool(); 538 final InstructionList il = new InstructionList(); 539 String methodName = Util.escape(template.getName().toString()); 540 541 int numParams = 0; 542 if (template.isSimpleNamedTemplate()) { 543 Vector parameters = template.getParameters(); 544 numParams = parameters.size(); 545 } 546 547 com.sun.org.apache.bcel.internal.generic.Type[] types = 549 new com.sun.org.apache.bcel.internal.generic.Type[4 + numParams]; 550 String [] names = new String [4 + numParams]; 551 types[0] = Util.getJCRefType(DOM_INTF_SIG); 552 types[1] = Util.getJCRefType(NODE_ITERATOR_SIG); 553 types[2] = Util.getJCRefType(TRANSLET_OUTPUT_SIG); 554 types[3] = com.sun.org.apache.bcel.internal.generic.Type.INT; 555 names[0] = DOCUMENT_PNAME; 556 names[1] = ITERATOR_PNAME; 557 names[2] = TRANSLET_OUTPUT_PNAME; 558 names[3] = NODE_PNAME; 559 560 for (int i = 4; i < 4 + numParams; i++) { 564 types[i] = Util.getJCRefType(OBJECT_SIG); 565 names[i] = "param" + String.valueOf(i-4); 566 } 567 568 NamedMethodGenerator methodGen = 569 new NamedMethodGenerator(ACC_PUBLIC, 570 com.sun.org.apache.bcel.internal.generic.Type.VOID, 571 types, names, methodName, 572 getClassName(), il, cpg); 573 574 il.append(template.compile(classGen, methodGen)); 575 il.append(RETURN); 576 577 methodGen.stripAttributes(true); 578 methodGen.setMaxLocals(); 579 methodGen.setMaxStack(); 580 methodGen.removeNOPs(); 581 classGen.addMethod(methodGen.getMethod()); 582 } 583 584 private void compileTemplates(ClassGenerator classGen, 585 MethodGenerator methodGen, 586 InstructionHandle next) 587 { 588 Enumeration templates = _namedTemplates.keys(); 589 while (templates.hasMoreElements()) { 590 final Template template = (Template)templates.nextElement(); 591 compileNamedTemplate(template, classGen); 592 } 593 594 templates = _neededTemplates.keys(); 595 while (templates.hasMoreElements()) { 596 final Template template = (Template)templates.nextElement(); 597 if (template.hasContents()) { 598 InstructionList til = template.compile(classGen, methodGen); 600 til.append(new GOTO_W(next)); 601 _templateILs.put(template, til); 602 _templateIHs.put(template, til.getStart()); 603 } 604 else { 605 _templateIHs.put(template, next); 607 } 608 } 609 } 610 611 private void appendTemplateCode(InstructionList body) { 612 final Enumeration templates = _neededTemplates.keys(); 613 while (templates.hasMoreElements()) { 614 final Object iList = 615 _templateILs.get(templates.nextElement()); 616 if (iList != null) { 617 body.append((InstructionList)iList); 618 } 619 } 620 } 621 622 private void appendTestSequences(InstructionList body) { 623 final int n = _testSeq.length; 624 for (int i = 0; i < n; i++) { 625 final TestSeq testSeq = _testSeq[i]; 626 if (testSeq != null) { 627 InstructionList il = testSeq.getInstructionList(); 628 if (il != null) 629 body.append(il); 630 } 632 } 633 } 634 635 public static void compileGetChildren(ClassGenerator classGen, 636 MethodGenerator methodGen, 637 int node) { 638 final ConstantPoolGen cpg = classGen.getConstantPool(); 639 final InstructionList il = methodGen.getInstructionList(); 640 final int git = cpg.addInterfaceMethodref(DOM_INTF, 641 GET_CHILDREN, 642 GET_CHILDREN_SIG); 643 il.append(methodGen.loadDOM()); 644 il.append(new ILOAD(node)); 645 il.append(new INVOKEINTERFACE(git, 2)); 646 } 647 648 651 private InstructionList compileDefaultRecursion(ClassGenerator classGen, 652 MethodGenerator methodGen, 653 InstructionHandle next) { 654 final ConstantPoolGen cpg = classGen.getConstantPool(); 655 final InstructionList il = new InstructionList(); 656 final String applyTemplatesSig = classGen.getApplyTemplatesSig(); 657 final int git = cpg.addInterfaceMethodref(DOM_INTF, 658 GET_CHILDREN, 659 GET_CHILDREN_SIG); 660 final int applyTemplates = cpg.addMethodref(getClassName(), 661 functionName(), 662 applyTemplatesSig); 663 il.append(classGen.loadTranslet()); 664 il.append(methodGen.loadDOM()); 665 666 il.append(methodGen.loadDOM()); 667 il.append(new ILOAD(_currentIndex)); 668 il.append(new INVOKEINTERFACE(git, 2)); 669 il.append(methodGen.loadHandler()); 670 il.append(new INVOKEVIRTUAL(applyTemplates)); 671 il.append(new GOTO_W(next)); 672 return il; 673 } 674 675 679 private InstructionList compileDefaultText(ClassGenerator classGen, 680 MethodGenerator methodGen, 681 InstructionHandle next) { 682 final ConstantPoolGen cpg = classGen.getConstantPool(); 683 final InstructionList il = new InstructionList(); 684 685 final int chars = cpg.addInterfaceMethodref(DOM_INTF, 686 CHARACTERS, 687 CHARACTERS_SIG); 688 il.append(methodGen.loadDOM()); 689 il.append(new ILOAD(_currentIndex)); 690 il.append(methodGen.loadHandler()); 691 il.append(new INVOKEINTERFACE(chars, 3)); 692 il.append(new GOTO_W(next)); 693 return il; 694 } 695 696 private InstructionList compileNamespaces(ClassGenerator classGen, 697 MethodGenerator methodGen, 698 boolean[] isNamespace, 699 boolean[] isAttribute, 700 boolean attrFlag, 701 InstructionHandle defaultTarget) { 702 final XSLTC xsltc = classGen.getParser().getXSLTC(); 703 final ConstantPoolGen cpg = classGen.getConstantPool(); 704 705 final Vector namespaces = xsltc.getNamespaceIndex(); 707 final Vector names = xsltc.getNamesIndex(); 708 final int namespaceCount = namespaces.size() + 1; 709 final int namesCount = names.size(); 710 711 final InstructionList il = new InstructionList(); 712 final int[] types = new int[namespaceCount]; 713 final InstructionHandle[] targets = new InstructionHandle[types.length]; 714 715 if (namespaceCount > 0) { 716 boolean compiled = false; 717 718 for (int i = 0; i < namespaceCount; i++) { 720 targets[i] = defaultTarget; 721 types[i] = i; 722 } 723 724 for (int i = DTM.NTYPES; i < (DTM.NTYPES+namesCount); i++) { 726 if ((isNamespace[i]) && (isAttribute[i] == attrFlag)) { 727 String name = (String )names.elementAt(i-DTM.NTYPES); 728 String namespace = name.substring(0,name.lastIndexOf(':')); 729 final int type = xsltc.registerNamespace(namespace); 730 731 if ((i < _testSeq.length) && 732 (_testSeq[i] != null)) { 733 targets[type] = 734 (_testSeq[i]).compile(classGen, 735 methodGen, 736 defaultTarget); 737 compiled = true; 738 } 739 } 740 } 741 742 if (!compiled) return(null); 744 745 final int getNS = cpg.addInterfaceMethodref(DOM_INTF, 747 "getNamespaceType", 748 "(I)I"); 749 il.append(methodGen.loadDOM()); 750 il.append(new ILOAD(_currentIndex)); 751 il.append(new INVOKEINTERFACE(getNS, 2)); 752 il.append(new SWITCH(types, targets, defaultTarget)); 753 return(il); 754 } 755 else { 756 return(null); 757 } 758 } 759 760 764 public void compileApplyTemplates(ClassGenerator classGen) { 765 final XSLTC xsltc = classGen.getParser().getXSLTC(); 766 final ConstantPoolGen cpg = classGen.getConstantPool(); 767 final Vector names = xsltc.getNamesIndex(); 768 769 final com.sun.org.apache.bcel.internal.generic.Type[] argTypes = 771 new com.sun.org.apache.bcel.internal.generic.Type[3]; 772 argTypes[0] = Util.getJCRefType(DOM_INTF_SIG); 773 argTypes[1] = Util.getJCRefType(NODE_ITERATOR_SIG); 774 argTypes[2] = Util.getJCRefType(TRANSLET_OUTPUT_SIG); 775 776 final String [] argNames = new String [3]; 777 argNames[0] = DOCUMENT_PNAME; 778 argNames[1] = ITERATOR_PNAME; 779 argNames[2] = TRANSLET_OUTPUT_PNAME; 780 781 final InstructionList mainIL = new InstructionList(); 782 final MethodGenerator methodGen = 783 new MethodGenerator(ACC_PUBLIC | ACC_FINAL, 784 com.sun.org.apache.bcel.internal.generic.Type.VOID, 785 argTypes, argNames, functionName(), 786 getClassName(), mainIL, 787 classGen.getConstantPool()); 788 methodGen.addException("com.sun.org.apache.xalan.internal.xsltc.TransletException"); 789 790 final LocalVariableGen current; 792 current = methodGen.addLocalVariable2("current", 793 com.sun.org.apache.bcel.internal.generic.Type.INT, 794 mainIL.getEnd()); 795 _currentIndex = current.getIndex(); 796 797 final InstructionList body = new InstructionList(); 800 body.append(NOP); 801 802 final InstructionList ilLoop = new InstructionList(); 805 ilLoop.append(methodGen.loadIterator()); 806 ilLoop.append(methodGen.nextNode()); 807 ilLoop.append(DUP); 808 ilLoop.append(new ISTORE(_currentIndex)); 809 810 final BranchHandle ifeq = ilLoop.append(new IFLT(null)); 813 final BranchHandle loop = ilLoop.append(new GOTO_W(null)); 814 ifeq.setTarget(ilLoop.append(RETURN)); final InstructionHandle ihLoop = ilLoop.getStart(); 816 817 InstructionList ilRecurse = 819 compileDefaultRecursion(classGen, methodGen, ihLoop); 820 InstructionHandle ihRecurse = ilRecurse.getStart(); 821 822 InstructionList ilText = 824 compileDefaultText(classGen, methodGen, ihLoop); 825 InstructionHandle ihText = ilText.getStart(); 826 827 final int[] types = new int[DTM.NTYPES + names.size()]; 829 for (int i = 0; i < types.length; i++) { 830 types[i] = i; 831 } 832 833 final boolean[] isAttribute = new boolean[types.length]; 835 final boolean[] isNamespace = new boolean[types.length]; 836 for (int i = 0; i < names.size(); i++) { 837 final String name = (String )names.elementAt(i); 838 isAttribute[i + DTM.NTYPES] = isAttributeName(name); 839 isNamespace[i + DTM.NTYPES] = isNamespaceName(name); 840 } 841 842 compileTemplates(classGen, methodGen, ihLoop); 844 845 final TestSeq elemTest = _testSeq[DTM.ELEMENT_NODE]; 847 InstructionHandle ihElem = ihRecurse; 848 if (elemTest != null) 849 ihElem = elemTest.compile(classGen, methodGen, ihRecurse); 850 851 final TestSeq attrTest = _testSeq[DTM.ATTRIBUTE_NODE]; 853 InstructionHandle ihAttr = ihText; 854 if (attrTest != null) 855 ihAttr = attrTest.compile(classGen, methodGen, ihAttr); 856 857 InstructionList ilKey = null; 859 if (_idxTestSeq != null) { 860 loop.setTarget(_idxTestSeq.compile(classGen, methodGen, body.getStart())); 861 ilKey = _idxTestSeq.getInstructionList(); 862 } 863 else { 864 loop.setTarget(body.getStart()); 865 } 866 867 if (_childNodeTestSeq != null) { 870 double nodePrio = _childNodeTestSeq.getPriority(); 872 int nodePos = _childNodeTestSeq.getPosition(); 873 double elemPrio = (0 - Double.MAX_VALUE); 874 int elemPos = Integer.MIN_VALUE; 875 876 if (elemTest != null) { 877 elemPrio = elemTest.getPriority(); 878 elemPos = elemTest.getPosition(); 879 } 880 if (elemPrio == Double.NaN || elemPrio < nodePrio || 881 (elemPrio == nodePrio && elemPos < nodePos)) 882 { 883 ihElem = _childNodeTestSeq.compile(classGen, methodGen, ihLoop); 884 } 885 886 final TestSeq textTest = _testSeq[DTM.TEXT_NODE]; 888 double textPrio = (0 - Double.MAX_VALUE); 889 int textPos = Integer.MIN_VALUE; 890 891 if (textTest != null) { 892 textPrio = textTest.getPriority(); 893 textPos = textTest.getPosition(); 894 } 895 if (textPrio == Double.NaN || textPrio < nodePrio || 896 (textPrio == nodePrio && textPos < nodePos)) 897 { 898 ihText = _childNodeTestSeq.compile(classGen, methodGen, ihLoop); 899 _testSeq[DTM.TEXT_NODE] = _childNodeTestSeq; 900 } 901 } 902 903 InstructionHandle elemNamespaceHandle = ihElem; 905 InstructionList nsElem = compileNamespaces(classGen, methodGen, 906 isNamespace, isAttribute, 907 false, ihElem); 908 if (nsElem != null) elemNamespaceHandle = nsElem.getStart(); 909 910 InstructionHandle attrNamespaceHandle = ihAttr; 912 InstructionList nsAttr = compileNamespaces(classGen, methodGen, 913 isNamespace, isAttribute, 914 true, ihAttr); 915 if (nsAttr != null) attrNamespaceHandle = nsAttr.getStart(); 916 917 final InstructionHandle[] targets = new InstructionHandle[types.length]; 919 for (int i = DTM.NTYPES; i < targets.length; i++) { 920 final TestSeq testSeq = _testSeq[i]; 921 if (isNamespace[i]) { 923 if (isAttribute[i]) 924 targets[i] = attrNamespaceHandle; 925 else 926 targets[i] = elemNamespaceHandle; 927 } 928 else if (testSeq != null) { 930 if (isAttribute[i]) 931 targets[i] = testSeq.compile(classGen, methodGen, 932 attrNamespaceHandle); 933 else 934 targets[i] = testSeq.compile(classGen, methodGen, 935 elemNamespaceHandle); 936 } 937 else { 938 targets[i] = ihLoop; 939 } 940 } 941 942 943 targets[DTM.ROOT_NODE] = _rootPattern != null 945 ? getTemplateInstructionHandle(_rootPattern.getTemplate()) 946 : ihRecurse; 947 948 targets[DTM.DOCUMENT_NODE] = _rootPattern != null 950 ? getTemplateInstructionHandle(_rootPattern.getTemplate()) 951 : ihRecurse; 952 953 targets[DTM.TEXT_NODE] = _testSeq[DTM.TEXT_NODE] != null 955 ? _testSeq[DTM.TEXT_NODE].compile(classGen, methodGen, ihText) 956 : ihText; 957 958 targets[DTM.NAMESPACE_NODE] = ihLoop; 960 961 targets[DTM.ELEMENT_NODE] = elemNamespaceHandle; 963 964 targets[DTM.ATTRIBUTE_NODE] = attrNamespaceHandle; 966 967 InstructionHandle ihPI = ihLoop; 969 if (_childNodeTestSeq != null) ihPI = ihElem; 970 if (_testSeq[DTM.PROCESSING_INSTRUCTION_NODE] != null) 971 targets[DTM.PROCESSING_INSTRUCTION_NODE] = 972 _testSeq[DTM.PROCESSING_INSTRUCTION_NODE]. 973 compile(classGen, methodGen, ihPI); 974 else 975 targets[DTM.PROCESSING_INSTRUCTION_NODE] = ihPI; 976 977 InstructionHandle ihComment = ihLoop; 979 if (_childNodeTestSeq != null) ihComment = ihElem; 980 targets[DTM.COMMENT_NODE] = _testSeq[DTM.COMMENT_NODE] != null 981 ? _testSeq[DTM.COMMENT_NODE].compile(classGen, methodGen, ihComment) 982 : ihComment; 983 984 targets[DTM.CDATA_SECTION_NODE] = ihLoop; 986 987 targets[DTM.DOCUMENT_FRAGMENT_NODE] = ihLoop; 989 990 targets[DTM.DOCUMENT_TYPE_NODE] = ihLoop; 992 993 targets[DTM.ENTITY_NODE] = ihLoop; 995 996 targets[DTM.ENTITY_REFERENCE_NODE] = ihLoop; 998 999 targets[DTM.NOTATION_NODE] = ihLoop; 1001 1002 1003 for (int i = DTM.NTYPES; i < targets.length; i++) { 1005 final TestSeq testSeq = _testSeq[i]; 1006 if ((testSeq == null) || (isNamespace[i])) { 1008 if (isAttribute[i]) 1009 targets[i] = attrNamespaceHandle; 1010 else 1011 targets[i] = elemNamespaceHandle; 1012 } 1013 else { 1015 if (isAttribute[i]) 1016 targets[i] = testSeq.compile(classGen, methodGen, 1017 attrNamespaceHandle); 1018 else 1019 targets[i] = testSeq.compile(classGen, methodGen, 1020 elemNamespaceHandle); 1021 } 1022 } 1023 1024 if (ilKey != null) body.insert(ilKey); 1025 1026 final int getType = cpg.addInterfaceMethodref(DOM_INTF, 1028 "getExpandedTypeID", 1029 "(I)I"); 1030 body.append(methodGen.loadDOM()); 1031 body.append(new ILOAD(_currentIndex)); 1032 body.append(new INVOKEINTERFACE(getType, 2)); 1033 1034 InstructionHandle disp = body.append(new SWITCH(types, targets, ihLoop)); 1036 1037 appendTestSequences(body); 1039 appendTemplateCode(body); 1041 1042 if (nsElem != null) body.append(nsElem); 1044 if (nsAttr != null) body.append(nsAttr); 1046 1047 body.append(ilRecurse); 1049 body.append(ilText); 1051 1052 mainIL.append(new GOTO_W(ihLoop)); 1054 mainIL.append(body); 1055 mainIL.append(ilLoop); 1057 1058 peepHoleOptimization(methodGen); 1059 methodGen.stripAttributes(true); 1060 1061 methodGen.setMaxLocals(); 1062 methodGen.setMaxStack(); 1063 methodGen.removeNOPs(); 1064 classGen.addMethod(methodGen.getMethod()); 1065 1066 if (_importLevels != null) { 1068 Enumeration levels = _importLevels.keys(); 1069 while (levels.hasMoreElements()) { 1070 Integer max = (Integer )levels.nextElement(); 1071 Integer min = (Integer )_importLevels.get(max); 1072 compileApplyImports(classGen, min.intValue(), max.intValue()); 1073 } 1074 } 1075 } 1076 1077 private void compileTemplateCalls(ClassGenerator classGen, 1078 MethodGenerator methodGen, 1079 InstructionHandle next, int min, int max){ 1080 Enumeration templates = _neededTemplates.keys(); 1081 while (templates.hasMoreElements()) { 1082 final Template template = (Template)templates.nextElement(); 1083 final int prec = template.getImportPrecedence(); 1084 if ((prec >= min) && (prec < max)) { 1085 if (template.hasContents()) { 1086 InstructionList til = template.compile(classGen, methodGen); 1087 til.append(new GOTO_W(next)); 1088 _templateILs.put(template, til); 1089 _templateIHs.put(template, til.getStart()); 1090 } 1091 else { 1092 _templateIHs.put(template, next); 1094 } 1095 } 1096 } 1097 } 1098 1099 1100 public void compileApplyImports(ClassGenerator classGen, int min, int max) { 1101 final XSLTC xsltc = classGen.getParser().getXSLTC(); 1102 final ConstantPoolGen cpg = classGen.getConstantPool(); 1103 final Vector names = xsltc.getNamesIndex(); 1104 1105 _namedTemplates = new Hashtable (); 1107 _neededTemplates = new Hashtable (); 1108 _templateIHs = new Hashtable (); 1109 _templateILs = new Hashtable (); 1110 _patternGroups = new Vector [32]; 1111 _rootPattern = null; 1112 1113 Vector oldTemplates = _templates; 1115 1116 _templates = new Vector (); 1118 final Enumeration templates = oldTemplates.elements(); 1119 while (templates.hasMoreElements()) { 1120 final Template template = (Template)templates.nextElement(); 1121 final int prec = template.getImportPrecedence(); 1122 if ((prec >= min) && (prec < max)) addTemplate(template); 1123 } 1124 1125 processPatterns(_keys); 1127 1128 final com.sun.org.apache.bcel.internal.generic.Type[] argTypes = 1130 new com.sun.org.apache.bcel.internal.generic.Type[3]; 1131 argTypes[0] = Util.getJCRefType(DOM_INTF_SIG); 1132 argTypes[1] = Util.getJCRefType(NODE_ITERATOR_SIG); 1133 argTypes[2] = Util.getJCRefType(TRANSLET_OUTPUT_SIG); 1134 1135 final String [] argNames = new String [3]; 1136 argNames[0] = DOCUMENT_PNAME; 1137 argNames[1] = ITERATOR_PNAME; 1138 argNames[2] = TRANSLET_OUTPUT_PNAME; 1139 1140 final InstructionList mainIL = new InstructionList(); 1141 final MethodGenerator methodGen = 1142 new MethodGenerator(ACC_PUBLIC | ACC_FINAL, 1143 com.sun.org.apache.bcel.internal.generic.Type.VOID, 1144 argTypes, argNames, functionName()+'_'+max, 1145 getClassName(), mainIL, 1146 classGen.getConstantPool()); 1147 methodGen.addException("com.sun.org.apache.xalan.internal.xsltc.TransletException"); 1148 1149 final LocalVariableGen current; 1151 current = methodGen.addLocalVariable2("current", 1152 com.sun.org.apache.bcel.internal.generic.Type.INT, 1153 mainIL.getEnd()); 1154 _currentIndex = current.getIndex(); 1155 1156 final InstructionList body = new InstructionList(); 1159 body.append(NOP); 1160 1161 final InstructionList ilLoop = new InstructionList(); 1164 ilLoop.append(methodGen.loadIterator()); 1165 ilLoop.append(methodGen.nextNode()); 1166 ilLoop.append(DUP); 1167 ilLoop.append(new ISTORE(_currentIndex)); 1168 1169 final BranchHandle ifeq = ilLoop.append(new IFLT(null)); 1172 final BranchHandle loop = ilLoop.append(new GOTO_W(null)); 1173 ifeq.setTarget(ilLoop.append(RETURN)); final InstructionHandle ihLoop = ilLoop.getStart(); 1175 1176 InstructionList ilRecurse = 1178 compileDefaultRecursion(classGen, methodGen, ihLoop); 1179 InstructionHandle ihRecurse = ilRecurse.getStart(); 1180 1181 InstructionList ilText = 1183 compileDefaultText(classGen, methodGen, ihLoop); 1184 InstructionHandle ihText = ilText.getStart(); 1185 1186 final int[] types = new int[DTM.NTYPES + names.size()]; 1188 for (int i = 0; i < types.length; i++) { 1189 types[i] = i; 1190 } 1191 1192 final boolean[] isAttribute = new boolean[types.length]; 1193 final boolean[] isNamespace = new boolean[types.length]; 1194 for (int i = 0; i < names.size(); i++) { 1195 final String name = (String )names.elementAt(i); 1196 isAttribute[i+DTM.NTYPES] = isAttributeName(name); 1197 isNamespace[i+DTM.NTYPES] = isNamespaceName(name); 1198 } 1199 1200 compileTemplateCalls(classGen, methodGen, ihLoop, min, max); 1202 1203 final TestSeq elemTest = _testSeq[DTM.ELEMENT_NODE]; 1205 InstructionHandle ihElem = ihRecurse; 1206 if (elemTest != null) { 1207 ihElem = elemTest.compile(classGen, methodGen, ihLoop); 1208 } 1209 1210 final TestSeq attrTest = _testSeq[DTM.ATTRIBUTE_NODE]; 1212 InstructionHandle ihAttr = ihLoop; 1213 if (attrTest != null) { 1214 ihAttr = attrTest.compile(classGen, methodGen, ihAttr); 1215 } 1216 1217 InstructionList ilKey = null; 1219 if (_idxTestSeq != null) { 1220 loop.setTarget(_idxTestSeq.compile(classGen, methodGen, body.getStart())); 1221 ilKey = _idxTestSeq.getInstructionList(); 1222 } 1223 else { 1224 loop.setTarget(body.getStart()); 1225 } 1226 1227 if (_childNodeTestSeq != null) { 1230 double nodePrio = _childNodeTestSeq.getPriority(); 1232 int nodePos = _childNodeTestSeq.getPosition(); 1233 double elemPrio = (0 - Double.MAX_VALUE); 1234 int elemPos = Integer.MIN_VALUE; 1235 1236 if (elemTest != null) { 1237 elemPrio = elemTest.getPriority(); 1238 elemPos = elemTest.getPosition(); 1239 } 1240 1241 if (elemPrio == Double.NaN || elemPrio < nodePrio || 1242 (elemPrio == nodePrio && elemPos < nodePos)) 1243 { 1244 ihElem = _childNodeTestSeq.compile(classGen, methodGen, ihLoop); 1245 } 1246 1247 final TestSeq textTest = _testSeq[DTM.TEXT_NODE]; 1249 double textPrio = (0 - Double.MAX_VALUE); 1250 int textPos = Integer.MIN_VALUE; 1251 1252 if (textTest != null) { 1253 textPrio = textTest.getPriority(); 1254 textPos = textTest.getPosition(); 1255 } 1256 1257 if (textPrio == Double.NaN || textPrio < nodePrio || 1258 (textPrio == nodePrio && textPos < nodePos)) 1259 { 1260 ihText = _childNodeTestSeq.compile(classGen, methodGen, ihLoop); 1261 _testSeq[DTM.TEXT_NODE] = _childNodeTestSeq; 1262 } 1263 } 1264 1265 InstructionHandle elemNamespaceHandle = ihElem; 1267 InstructionList nsElem = compileNamespaces(classGen, methodGen, 1268 isNamespace, isAttribute, 1269 false, ihElem); 1270 if (nsElem != null) elemNamespaceHandle = nsElem.getStart(); 1271 1272 InstructionList nsAttr = compileNamespaces(classGen, methodGen, 1274 isNamespace, isAttribute, 1275 true, ihAttr); 1276 InstructionHandle attrNamespaceHandle = ihAttr; 1277 if (nsAttr != null) attrNamespaceHandle = nsAttr.getStart(); 1278 1279 final InstructionHandle[] targets = new InstructionHandle[types.length]; 1281 for (int i = DTM.NTYPES; i < targets.length; i++) { 1282 final TestSeq testSeq = _testSeq[i]; 1283 if (isNamespace[i]) { 1285 if (isAttribute[i]) 1286 targets[i] = attrNamespaceHandle; 1287 else 1288 targets[i] = elemNamespaceHandle; 1289 } 1290 else if (testSeq != null) { 1292 if (isAttribute[i]) 1293 targets[i] = testSeq.compile(classGen, methodGen, 1294 attrNamespaceHandle); 1295 else 1296 targets[i] = testSeq.compile(classGen, methodGen, 1297 elemNamespaceHandle); 1298 } 1299 else { 1300 targets[i] = ihLoop; 1301 } 1302 } 1303 1304 targets[DTM.ROOT_NODE] = _rootPattern != null 1306 ? getTemplateInstructionHandle(_rootPattern.getTemplate()) 1307 : ihRecurse; 1308 targets[DTM.DOCUMENT_NODE] = _rootPattern != null 1310 ? getTemplateInstructionHandle(_rootPattern.getTemplate()) 1311 : ihRecurse; 1313 targets[DTM.TEXT_NODE] = _testSeq[DTM.TEXT_NODE] != null 1315 ? _testSeq[DTM.TEXT_NODE].compile(classGen, methodGen, ihText) 1316 : ihText; 1317 1318 targets[DTM.NAMESPACE_NODE] = ihLoop; 1320 1321 targets[DTM.ELEMENT_NODE] = elemNamespaceHandle; 1323 1324 targets[DTM.ATTRIBUTE_NODE] = attrNamespaceHandle; 1326 1327 InstructionHandle ihPI = ihLoop; 1329 if (_childNodeTestSeq != null) ihPI = ihElem; 1330 if (_testSeq[DTM.PROCESSING_INSTRUCTION_NODE] != null) { 1331 targets[DTM.PROCESSING_INSTRUCTION_NODE] = 1332 _testSeq[DTM.PROCESSING_INSTRUCTION_NODE]. 1333 compile(classGen, methodGen, ihPI); 1334 } 1335 else { 1336 targets[DTM.PROCESSING_INSTRUCTION_NODE] = ihPI; 1337 } 1338 1339 InstructionHandle ihComment = ihLoop; 1341 if (_childNodeTestSeq != null) ihComment = ihElem; 1342 targets[DTM.COMMENT_NODE] = _testSeq[DTM.COMMENT_NODE] != null 1343 ? _testSeq[DTM.COMMENT_NODE].compile(classGen, methodGen, ihComment) 1344 : ihComment; 1345 1346 targets[DTM.CDATA_SECTION_NODE] = ihLoop; 1348 1349 targets[DTM.DOCUMENT_FRAGMENT_NODE] = ihLoop; 1351 1352 targets[DTM.DOCUMENT_TYPE_NODE] = ihLoop; 1354 1355 targets[DTM.ENTITY_NODE] = ihLoop; 1357 1358 targets[DTM.ENTITY_REFERENCE_NODE] = ihLoop; 1360 1361 targets[DTM.NOTATION_NODE] = ihLoop; 1363 1364 1365 1366 for (int i = DTM.NTYPES; i < targets.length; i++) { 1368 final TestSeq testSeq = _testSeq[i]; 1369 if ((testSeq == null) || (isNamespace[i])) { 1371 if (isAttribute[i]) 1372 targets[i] = attrNamespaceHandle; 1373 else 1374 targets[i] = elemNamespaceHandle; 1375 } 1376 else { 1378 if (isAttribute[i]) 1379 targets[i] = testSeq.compile(classGen, methodGen, 1380 attrNamespaceHandle); 1381 else 1382 targets[i] = testSeq.compile(classGen, methodGen, 1383 elemNamespaceHandle); 1384 } 1385 } 1386 1387 if (ilKey != null) body.insert(ilKey); 1388 1389 final int getType = cpg.addInterfaceMethodref(DOM_INTF, 1391 "getExpandedTypeID", 1392 "(I)I"); 1393 body.append(methodGen.loadDOM()); 1394 body.append(new ILOAD(_currentIndex)); 1395 body.append(new INVOKEINTERFACE(getType, 2)); 1396 1397 InstructionHandle disp = body.append(new SWITCH(types,targets,ihLoop)); 1399 1400 appendTestSequences(body); 1402 appendTemplateCode(body); 1404 1405 if (nsElem != null) body.append(nsElem); 1407 if (nsAttr != null) body.append(nsAttr); 1409 1410 body.append(ilRecurse); 1412 body.append(ilText); 1414 1415 mainIL.append(new GOTO_W(ihLoop)); 1417 mainIL.append(body); 1418 mainIL.append(ilLoop); 1420 1421 peepHoleOptimization(methodGen); 1422 methodGen.stripAttributes(true); 1423 1424 methodGen.setMaxLocals(); 1425 methodGen.setMaxStack(); 1426 methodGen.removeNOPs(); 1427 classGen.addMethod(methodGen.getMethod()); 1428 1429 _templates = oldTemplates; 1431 } 1432 1433 1436 private void peepHoleOptimization(MethodGenerator methodGen) { 1437 InstructionList il = methodGen.getInstructionList(); 1438 InstructionFinder find = new InstructionFinder(il); 1439 InstructionHandle ih; 1440 String pattern; 1441 1442 pattern = "LoadInstruction POP"; 1444 for (Iterator iter = find.search(pattern); iter.hasNext();) { 1445 InstructionHandle[] match = (InstructionHandle[]) iter.next(); 1446 try { 1447 if (!match[0].hasTargeters() && !match[1].hasTargeters()) { 1448 il.delete(match[0], match[1]); 1449 } 1450 } 1451 catch (TargetLostException e) { 1452 } 1454 } 1455 1456 pattern = "ILOAD ILOAD SWAP ISTORE"; 1458 for (Iterator iter = find.search(pattern); iter.hasNext();) { 1459 InstructionHandle[] match = (InstructionHandle[]) iter.next(); 1460 try { 1461 com.sun.org.apache.bcel.internal.generic.ILOAD iload1 = 1462 (com.sun.org.apache.bcel.internal.generic.ILOAD) match[0].getInstruction(); 1463 com.sun.org.apache.bcel.internal.generic.ILOAD iload2 = 1464 (com.sun.org.apache.bcel.internal.generic.ILOAD) match[1].getInstruction(); 1465 com.sun.org.apache.bcel.internal.generic.ISTORE istore = 1466 (com.sun.org.apache.bcel.internal.generic.ISTORE) match[3].getInstruction(); 1467 1468 if (!match[1].hasTargeters() && 1469 !match[2].hasTargeters() && 1470 !match[3].hasTargeters() && 1471 iload1.getIndex() == iload2.getIndex() && 1472 iload2.getIndex() == istore.getIndex()) 1473 { 1474 il.delete(match[1], match[3]); 1475 } 1476 } 1477 catch (TargetLostException e) { 1478 } 1480 } 1481 1482 pattern = "LoadInstruction LoadInstruction SWAP"; 1484 for (Iterator iter = find.search(pattern); iter.hasNext();) { 1485 InstructionHandle[] match = (InstructionHandle[])iter.next(); 1486 try { 1487 if (!match[0].hasTargeters() && 1488 !match[1].hasTargeters() && 1489 !match[2].hasTargeters()) 1490 { 1491 Instruction load_m = match[1].getInstruction(); 1492 il.insert(match[0], load_m); 1493 il.delete(match[1], match[2]); 1494 } 1495 } 1496 catch (TargetLostException e) { 1497 } 1499 } 1500 1501 pattern = "ALOAD ALOAD"; 1503 for (Iterator iter = find.search(pattern); iter.hasNext();) { 1504 InstructionHandle[] match = (InstructionHandle[])iter.next(); 1505 try { 1506 if (!match[1].hasTargeters()) { 1507 com.sun.org.apache.bcel.internal.generic.ALOAD aload1 = 1508 (com.sun.org.apache.bcel.internal.generic.ALOAD) match[0].getInstruction(); 1509 com.sun.org.apache.bcel.internal.generic.ALOAD aload2 = 1510 (com.sun.org.apache.bcel.internal.generic.ALOAD) match[1].getInstruction(); 1511 1512 if (aload1.getIndex() == aload2.getIndex()) { 1513 il.insert(match[1], new DUP()); 1514 il.delete(match[1]); 1515 } 1516 } 1517 } 1518 catch (TargetLostException e) { 1519 } 1521 } 1522 } 1523 1524 public InstructionHandle getTemplateInstructionHandle(Template template) { 1525 return (InstructionHandle)_templateIHs.get(template); 1526 } 1527 1528 1531 private static boolean isAttributeName(String qname) { 1532 final int col = qname.lastIndexOf(':') + 1; 1533 return (qname.charAt(col) == '@'); 1534 } 1535 1536 1540 private static boolean isNamespaceName(String qname) { 1541 final int col = qname.lastIndexOf(':'); 1542 return (col > -1 && qname.charAt(qname.length()-1) == '*'); 1543 } 1544} 1545 | Popular Tags |