1 2 12 package com.versant.core.jdo.query.mem; 13 14 import com.versant.core.jdo.query.*; 15 import com.versant.core.jdo.query.MemVisitor; 16 import com.versant.core.common.NotImplementedException; 17 import com.versant.core.common.OID; 18 import com.versant.core.metadata.FieldMetaData; 19 import com.versant.core.metadata.ClassMetaData; 20 import com.versant.core.metadata.MDStatics; 21 import com.versant.core.metadata.MDStaticUtils; 22 23 import java.util.*; 24 import java.math.BigInteger ; 25 import java.math.BigDecimal ; 26 import java.lang.Integer ; 27 28 import com.versant.lib.bcel.generic.*; 29 import com.versant.lib.bcel.Constants; 30 31 import com.versant.core.common.BindingSupportImpl; 32 import com.versant.core.jdo.QueryStateWrapper; 33 34 37 public class ByteCodeQVisitor implements MemVisitor { 38 39 private ClassMetaData candidateClass; 40 private ClassGen cg; 41 private ConstantPoolGen cp; 42 private InstructionList il; 43 private MethodGen mg; 44 private InstructionFactory factory; 45 private Map paramMap; 46 47 private int valueLVCount; 48 49 private final Map varToIndexMap = new HashMap(); 50 51 private boolean first = true; 52 53 private static final int COMP_EQ = 1; 54 private static final int COMP_GE = 2; 55 private static final int COMP_LT = 3; 56 private static final int COMP_GT = 4; 57 private static final int COMP_LE = 5; 58 private static final int COMP_NE = 6; 59 60 private CompiledMemQuery compiledMemQuery; 61 private static final String NAME_Q_STATE_WRAPPER = QueryStateWrapper.class.getName(); 62 private static final String M_NAME_GETSTATE = "getState"; 63 private static final String NAME_COLLECTION = Collection.class.getName(); 64 private static final String NAME_ITERATOR = Iterator.class.getName(); 65 66 67 private static final String NAME_COMPARABLE = Comparable .class.getName(); 68 private static final String NAME_OBJECT = Object .class.getName(); 69 private static final String NAME_NUMBER = Number .class.getName(); 70 71 private static final ObjectType OBJECT_TYPE_COLLECTION = new ObjectType(NAME_COLLECTION); 72 private static final ObjectType OBJECT_TYPE_ITERATOR = new ObjectType(NAME_ITERATOR); 73 private static final ObjectType OBJECT_TYPE_NUMBER = new ObjectType(NAME_NUMBER); 74 private static final Type[] ARG_TYPES_INT = new Type[] {Type.INT}; 75 private static final Type[] ARG_TYPES_OBJECT = new Type[] {Type.OBJECT}; 76 private static final Type[] ARG_TYPES_STRING = new Type[] {Type.STRING}; 77 private static final String NAME_STRING = String .class.getName(); 78 private static final ObjectType OBJECT_TYPE_STRING = new ObjectType(NAME_STRING); 79 private static final ObjectType OBJECT_TYPE_OID = new ObjectType(OID.class.getName()); 80 private static final String NAME_STRING_BUFFER = StringBuffer .class.getName(); 81 private static final ObjectType OBJECT_TYPE_STRING_BUFFER = new ObjectType(NAME_STRING_BUFFER); 82 private static final String NAME_BIG_INT = BigInteger .class.getName(); 83 84 private static final ObjectType RET_TYPE_BIG_INT = new ObjectType(NAME_BIG_INT); 85 private static final Type[] ARG_TYPES_BIG_INT = new Type[] {RET_TYPE_BIG_INT}; 86 private static final String NAME_BIG_DEC = BigDecimal .class.getName(); 87 private static final ObjectType RET_TYPE_BIG_DEC = new ObjectType(NAME_BIG_DEC); 88 private static final Type[] ARG_TYPES_BIG_DEC = new Type[] {RET_TYPE_BIG_DEC}; 89 90 public ByteCodeQVisitor(ClassGen classGen, InstructionFactory instructionFactory, String name, ClassMetaData candidateClass, CompiledMemQuery compiledMemQuery) { 91 this.compiledMemQuery = compiledMemQuery; 92 this.candidateClass = candidateClass; 93 94 cg = classGen; 95 factory = instructionFactory; 96 cp = cg.getConstantPool(); 97 this.il = new InstructionList(); 98 mg = new MethodGen(Constants.ACC_PUBLIC, Type.BOOLEAN, new Type[] {new ObjectType(NAME_Q_STATE_WRAPPER), new ArrayType(Type.OBJECT, 1)}, 101 new String [] {"state", "params"}, "exec", name, il, cp); 104 } 105 106 public void setParamMap(Map paramMap) { 107 this.paramMap = paramMap; 108 } 109 110 public void finish() { 111 il.append(InstructionConstants.IRETURN); 112 mg.removeNOPs(); 113 mg.setMaxLocals(); 114 mg.setMaxStack(); 115 cg.addMethod(mg.getMethod()); 116 il.dispose(); 117 } 118 119 public Field visitNode(Node node, Object obj) { 120 throw new NotImplementedException(); 121 } 122 123 124 127 private VarNode findVar(String name) { 128 VarNode[] vars = compiledMemQuery.vars; 129 if (vars == null) return null; 130 for (int i = vars.length - 1; i >= 0; i--) { 131 VarNode v = vars[i]; 132 if (v.getIdentifier().equals(name)) return v; 133 } 134 return null; 135 } 136 137 143 public Field visitLiteralNode(LiteralNode node, Object obj) { 144 BCField f = new BCField(); 145 switch(node.type){ 146 case LiteralNode.TYPE_STRING: 147 f.bcType = MDStatics.STRING; 148 f.classType = String .class; 149 f.ih = il.append(new PUSH(cp, node.value)); 150 break; 151 case LiteralNode.TYPE_BOOLEAN: 152 f.bcType = MDStatics.BOOLEAN; 153 f.classType = Boolean.TYPE; 154 f.ih = il.append(new PUSH(cp, Boolean.valueOf(node.value))); 155 break; 156 case LiteralNode.TYPE_CHAR: 157 f.bcType = MDStatics.CHAR; 158 f.classType = Character.TYPE; 159 f.ih = il.append(new PUSH(cp, node.value.toCharArray()[0])); 160 break; 161 case LiteralNode.TYPE_LONG: 162 f.bcType = MDStatics.LONG; 163 f.classType = Long.TYPE; 164 f.ih = il.append(new PUSH(cp, Long.parseLong(node.value))); 165 break; 166 case LiteralNode.TYPE_DOUBLE: 167 f.bcType = MDStatics.DOUBLE; 168 f.classType = Double.TYPE; 169 f.ih = il.append(new PUSH(cp, Double.parseDouble(node.value))); 170 break; 171 case LiteralNode.TYPE_NULL: 172 case LiteralNode.TYPE_OTHER: 173 f.bcType = MDStatics.NULL; 174 f.classType = Object .class; 175 break; 181 default: 182 throw BindingSupportImpl.getInstance().runtime("Unkown literal type "+node.type); 183 } 184 return f; 185 } 186 187 193 public Field visitFieldNavNode(FieldNavNode node, Object obj) { 194 return visitStateFieldNavNodeRoot(node, candidateClass); 195 } 196 197 private Field visitStateFieldNavNodeRoot(FieldNavNode node, ClassMetaData currentClass) { 198 Field result = null; 199 FieldMetaData f = null; 200 201 VarNode varNode = findVar(node.lexeme); 202 if (varNode != null) { 203 first = false; 204 Object o = varToIndexMap.get(varNode.getIdentifier()); 205 il.append(new ALOAD(((Integer )o).intValue())); 206 if (node.childList instanceof FieldNavNode) { 207 result = visitStateFieldNavNode((FieldNavNode) node.childList, varNode.getCmd(), null); 208 } else { 209 result = visitFieldNode((FieldNode) node.childList, varNode.getCmd()); 210 } 211 } else { 212 f = currentClass.getFieldMetaData(node.lexeme); 213 if(f == null){ 214 throw BindingSupportImpl.getInstance().runtime("Class "+currentClass+ 215 " does not have a field "+ node.lexeme); 216 } 217 switch(f.category){ 218 case FieldMetaData.CATEGORY_SIMPLE: 219 break; 220 case FieldMetaData.CATEGORY_REF: 221 InstructionHandle ih = null; 222 il.append(new ALOAD(1)); il.append(new PUSH(cp, f.stateFieldNo)); 224 il.append(factory.createInvoke(NAME_Q_STATE_WRAPPER, M_NAME_GETSTATE, 225 new ObjectType(NAME_Q_STATE_WRAPPER), ARG_TYPES_INT, Constants.INVOKEVIRTUAL)); 226 first = false; 227 if (node.childList instanceof FieldNavNode) { 228 result = visitStateFieldNavNode((FieldNavNode) node.childList, f.typeMetaData, ih); 229 } else { 230 result = visitFieldNode((FieldNode) node.childList, f.typeMetaData); 231 } 232 case FieldMetaData.CATEGORY_MAP: 233 break; 234 case FieldMetaData.CATEGORY_COLLECTION: 235 break; 236 case FieldMetaData.CATEGORY_TRANSACTIONAL: 237 break; 238 case FieldMetaData.CATEGORY_ARRAY: 239 break; 240 } 241 } 242 return result; 243 } 244 245 private Field visitStateFieldNavNode(FieldNavNode node, ClassMetaData currentClass, InstructionHandle ih) { 246 Field result = null; 247 FieldMetaData f = currentClass.getFieldMetaData(node.lexeme); 248 if(f == null){ 249 throw BindingSupportImpl.getInstance().runtime("Class "+currentClass+ 250 " does not have a field "+ node.lexeme); 251 } 252 switch(f.category){ 253 case FieldMetaData.CATEGORY_SIMPLE: 254 break; 255 case FieldMetaData.CATEGORY_REF: 256 il.append(new PUSH(cp, f.stateFieldNo)); 257 il.append(factory.createInvoke(NAME_Q_STATE_WRAPPER, M_NAME_GETSTATE, 258 new ObjectType(NAME_Q_STATE_WRAPPER), ARG_TYPES_INT, Constants.INVOKEVIRTUAL)); 259 if (node.childList instanceof FieldNavNode) { 260 result = visitStateFieldNavNode((FieldNavNode) node.childList, f.typeMetaData, ih); 261 } else { 262 result = visitFieldNode((FieldNode) node.childList, f.typeMetaData); 263 } 264 case FieldMetaData.CATEGORY_MAP: 265 break; 266 case FieldMetaData.CATEGORY_COLLECTION: 267 break; 268 case FieldMetaData.CATEGORY_TRANSACTIONAL: 269 break; 270 case FieldMetaData.CATEGORY_ARRAY: 271 break; 272 } 273 return result; 274 } 275 276 281 private String getLVName(MethodNode mNode) { 282 return ((VarNode)mNode.childList.next).getIdentifier(); 283 } 284 285 public Field visitMethodNode(MethodNode node, Object obj) { 286 Field result = null; 287 switch (node.getMethod()) { 288 case MethodNode.CONTAINS: 289 if (node.childList.next instanceof VarNode) { 290 doContainsMethod(node); 291 } else { 292 doContainMethodParam(node); 293 } 294 break; 295 case MethodNode.ENDS_WITH: 296 case MethodNode.STARTS_WITH: 297 doStringWithMethod(node); 298 break; 299 case MethodNode.IS_EMPTY: 300 doIsEmpty(node); 301 break; 302 case MethodNode.CONTAINS_KEY: 303 doContainsKey(node); 304 break; 305 case MethodNode.TO_LOWER_CASE: 306 result = toLowerCase(node); 307 break; 308 default: 309 throw new NotImplementedException(); 310 } 311 return result; 312 } 313 314 private BCField toLowerCase(MethodNode node) { 315 first = true; 316 BCField f = (BCField) node.childList.visit(this, null); 317 il.append(factory.createInvoke(NAME_STRING, "toLowerCase", Type.STRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); 318 return f; 319 } 320 321 private boolean isVarContainsMethodNode(MethodNode node) { 322 if ((node.getMethod() == MethodNode.CONTAINS) 323 && (node.childList.next instanceof VarNode)) { 324 return true; 325 } 326 return false; 327 } 328 329 private void doStringWithMethod(MethodNode node) { 330 String name = node.getName(); 331 BCField fl = (BCField) node.childList.visit(this, null); 332 if (fl.bcType != MDStatics.STRING) { 333 throw BindingSupportImpl.getInstance().invalidOperation("The " + name + " may only be used on a String field"); 334 } 335 node.childList.next.visit(this, null); 336 il.append(factory.createCheckCast(OBJECT_TYPE_STRING)); 337 il.append(factory.createInvoke(NAME_STRING, name, Type.BOOLEAN, ARG_TYPES_STRING, Constants.INVOKEVIRTUAL)); 338 } 339 340 private void doIsEmpty(MethodNode node) { 341 first = true; 342 node.childList.visit(this, null); 343 il.append(factory.createCheckCast(OBJECT_TYPE_COLLECTION)); 344 il.append(factory.createInvoke(NAME_COLLECTION, "isEmpty", Type.BOOLEAN, Type.NO_ARGS, Constants.INVOKEINTERFACE)); 345 } 346 347 private void doContainsKey(MethodNode node) { 348 first = true; 349 node.childList.visit(this, null); 350 try { 351 il.delete(il.getEnd()); 352 } catch (TargetLostException e) { 353 throw BindingSupportImpl.getInstance().internal(e.getMessage(), e); 354 } 355 node.childList.next.visit(this, null); 356 il.append(factory.createInvoke(NAME_Q_STATE_WRAPPER, "containsKey", Type.BOOLEAN, new Type[] {Type.INT, Type.OBJECT}, Constants.INVOKEVIRTUAL)); 357 } 358 359 private void doContainMethodParam(MethodNode node) { 360 first = true; 361 BCField bcField = (BCField) node.childList.visit(this, null); 362 if (Map.class.isAssignableFrom(bcField.classType)) { 363 if (bcField.getFMD().isElementTypePC()) { 364 try { 365 il.delete(il.getEnd()); 366 } catch (TargetLostException e) { 367 throw BindingSupportImpl.getInstance().internal(e.getMessage(), e); 368 } 369 il.append(factory.createInvoke(NAME_Q_STATE_WRAPPER, "getInternalOIDValueCollectionForMap", OBJECT_TYPE_COLLECTION, 370 ARG_TYPES_INT, Constants.INVOKEVIRTUAL)); 371 } else { 372 try { 373 il.delete(il.getEnd()); 374 } catch (TargetLostException e) { 375 throw BindingSupportImpl.getInstance().internal(e.getMessage(), e); 376 } 377 il.append(factory.createInvoke(NAME_Q_STATE_WRAPPER, "getInternalValueCollectionForMap", OBJECT_TYPE_COLLECTION, 378 ARG_TYPES_INT, Constants.INVOKEVIRTUAL)); 379 } 380 bcField = (BCField) node.childList.next.visit(this, null); 381 if (bcField.bcType == MDStatics.NULL) { 382 il.append(InstructionConstants.ACONST_NULL); 383 } 384 il.append(factory.createInvoke(NAME_COLLECTION, "contains", Type.BOOLEAN, ARG_TYPES_OBJECT, Constants.INVOKEINTERFACE)); 385 } else { 386 if (bcField.getFMD().isElementTypePC()) { 387 try { 388 il.delete(il.getEnd()); 389 } catch (TargetLostException e) { 390 throw BindingSupportImpl.getInstance().internal(e.getMessage(), e); 391 } 392 il.append(factory.createInvoke(NAME_Q_STATE_WRAPPER, "getInternalOIDCollection", OBJECT_TYPE_COLLECTION, 393 ARG_TYPES_INT, Constants.INVOKEVIRTUAL)); 394 } else { 395 il.append(factory.createCheckCast(OBJECT_TYPE_COLLECTION)); 396 } 397 bcField = (BCField) node.childList.next.visit(this, null); 398 if (bcField.bcType == MDStatics.NULL) { 399 il.append(InstructionConstants.ACONST_NULL); 400 } 401 il.append(factory.createInvoke(NAME_COLLECTION, "contains", Type.BOOLEAN, ARG_TYPES_OBJECT, Constants.INVOKEINTERFACE)); 402 } 403 } 404 405 private void doContainsMethod(MethodNode node) { 406 GOTO gotoEnd = new GOTO(null); 407 String lv = getLVName(node); 408 409 il.append(InstructionConstants.ACONST_NULL); 411 LocalVariableGen var1 = mg.addLocalVariable(lv, 412 new ObjectType(NAME_Q_STATE_WRAPPER), null, null); 413 int var1Index = var1.getIndex(); 414 varToIndexMap.put(lv, new Integer (var1Index)); 415 il.append(new ASTORE(var1Index)); 416 var1.setStart(il.append(new NOP())); 417 418 first = true; 419 node.childList.visit(this, null); 420 il.append(factory.createCheckCast(OBJECT_TYPE_COLLECTION)); 422 423 LocalVariableGen colLV = mg.addLocalVariable(lv + "Col", OBJECT_TYPE_COLLECTION, null, null); 425 int colLVIndex = colLV.getIndex(); 426 colLV.setStart(il.append(new ASTORE(colLVIndex))); 427 428 il.append(new ALOAD(colLVIndex)); 429 il.append(factory.createInvoke(NAME_COLLECTION, "isEmpty", Type.BOOLEAN, Type.NO_ARGS, Constants.INVOKEINTERFACE)); 430 431 InstructionHandle end = null; 432 433 if (node.next == null) { 434 il.append(InstructionConstants.ICONST_1); 435 il.append(InstructionConstants.IXOR); 436 } else { 437 il.append(InstructionConstants.DUP); 438 IFEQ ifNotEmpty = new IFEQ(null); 439 il.append(ifNotEmpty); 440 il.append(InstructionConstants.POP); 442 il.append(InstructionConstants.ICONST_0); 443 il.append(gotoEnd); 444 445 InstructionHandle createIter = il.append(new ALOAD(colLVIndex)); 447 il.append(factory.createInvoke(NAME_COLLECTION, "iterator", OBJECT_TYPE_ITERATOR, Type.NO_ARGS, Constants.INVOKEINTERFACE)); 448 LocalVariableGen itLV = mg.addLocalVariable(lv + "Iter", OBJECT_TYPE_ITERATOR, null, null); 449 int itLVIndex = itLV.getIndex(); 450 itLV.setStart(il.append(new ASTORE(itLVIndex))); 451 452 GOTO gotoHasNext = new GOTO(null); 453 il.append(gotoHasNext); 454 455 InstructionHandle loadIterForNext = il.append(new ALOAD(itLVIndex)); 456 il.append(factory.createInvoke(NAME_ITERATOR, "next", 457 Type.OBJECT, Type.NO_ARGS, Constants.INVOKEINTERFACE)); 458 il.append(factory.createCheckCast(new ObjectType(NAME_Q_STATE_WRAPPER))); 459 il.append(new ASTORE(var1Index)); 460 461 il.append(InstructionConstants.POP); 464 node.next.visit(this, null); 465 il.append(InstructionConstants.DUP); 466 IFEQ ifNonTrue = new IFEQ(null); 467 il.append(ifNonTrue); 468 GOTO gotoEnd2 = new GOTO(null); 469 il.append(gotoEnd2); 470 471 InstructionHandle loadIterForHasNext = il.append(new ALOAD(itLVIndex)); 473 il.append(factory.createInvoke(NAME_ITERATOR, "hasNext", 474 Type.BOOLEAN, Type.NO_ARGS, Constants.INVOKEINTERFACE)); 475 IFNE ifMore = new IFNE(loadIterForNext); 476 il.append(ifMore); 477 478 gotoHasNext.setTarget(loadIterForHasNext); 479 ifNonTrue.setTarget(loadIterForHasNext); 480 ifNotEmpty.setTarget(createIter); 481 482 end = il.append(new NOP()); 483 gotoEnd2.setTarget(end); 484 gotoEnd.setTarget(end); 485 } 486 487 } 488 489 public Field visitPrimaryExprNode(PrimaryExprNode node, Object obj) { 490 return null; 491 } 492 493 public Field visitFieldNode(FieldNode node, ClassMetaData cmd) { 494 if (cmd == null) { 495 return visitFieldNodeImp(candidateClass.getFieldMetaData(node.lexeme), node); 496 } else { 497 return visitFieldNodeImp(cmd.getFieldMetaData(node.lexeme), node); 498 } 499 } 500 501 private Field visitFieldNodeImp(FieldMetaData fmd, FieldNode node) { 502 BCField field; 503 if (fmd == null) { 504 throw BindingSupportImpl.getInstance().runtime("Class " + candidateClass.qname + " does not have a field: " + node.lexeme); 505 } 506 field = new BCStateField(fmd); 507 if (first) { 508 field.ih = il.append(new ALOAD(1)); first = false; 510 il.append(new PUSH(cp, fmd.stateFieldNo)); 511 } else { 512 field.ih = il.append(new PUSH(cp, fmd.stateFieldNo)); 513 } 514 if (fmd.typeMetaData == null) { 515 if (!fmd.isElementTypePC()) { 516 il.append(factory.createInvoke(NAME_Q_STATE_WRAPPER, fmd.stateGetMethodName, getBCellStateFieldType(fmd), 517 ARG_TYPES_INT, Constants.INVOKEVIRTUAL)); 518 } else { 519 il.append(factory.createInvoke(NAME_Q_STATE_WRAPPER, "getInternalStateCollection", OBJECT_TYPE_COLLECTION, 520 ARG_TYPES_INT, Constants.INVOKEVIRTUAL)); 521 } 522 } else { 523 il.append(factory.createInvoke(NAME_Q_STATE_WRAPPER, "getOID", OBJECT_TYPE_OID, 524 ARG_TYPES_INT, Constants.INVOKEVIRTUAL)); 525 } 526 return field; 527 } 528 529 public Field visitFieldNode(FieldNode node, Object obj) { 530 return visitFieldNodeImp(candidateClass.getFieldMetaData(node.lexeme), node); 531 } 532 533 private static final Type getBCellStateFieldType(FieldMetaData fmd) { 534 switch (fmd.category) { 535 case MDStatics.CATEGORY_SIMPLE: 536 return getTypeFromTypeCode(fmd.typeCode); 537 default: 538 return Type.OBJECT; 539 } 540 } 541 542 private static Type getTypeFromTypeCode(int typeCode) { 543 switch (typeCode) { 544 case MDStatics.INT: 545 return Type.INT; 546 case MDStatics.LONG: 547 return Type.LONG; 548 case MDStatics.SHORT: 549 return Type.SHORT; 550 case MDStatics.STRING: 551 return Type.STRING; 552 case MDStatics.BOOLEAN: 553 return Type.BOOLEAN; 554 case MDStatics.BYTE: 555 return Type.BYTE; 556 case MDStatics.CHAR: 557 return Type.CHAR; 558 case MDStatics.DOUBLE: 559 return Type.DOUBLE; 560 case MDStatics.FLOAT: 561 return Type.FLOAT; 562 default: 563 return Type.OBJECT; 564 } 565 } 566 567 private Field doCompare(BinaryNode node, int type) { 568 Object obj = null; 569 first = true; 570 BCField fl = (BCField) node.getLeft().visit(this, obj); 571 first = true; 572 BCField fr = (BCField) node.getRight().visit(this, obj); 573 InstructionHandle nopHandle = il.append(InstructionConstants.NOP); 574 int widestType = getWidestType(fl.bcType, fr.bcType); 575 576 if (fl.isPrimitive() && fr.isPrimitive()) { 577 promotePrimToPrim(widestType, fl, fr.ih); 578 promotePrimToPrim(widestType, fr, nopHandle); 579 switch (widestType) { 580 case MDStatics.BYTE: 581 case MDStatics.SHORT: 582 case MDStatics.CHAR: 583 case MDStatics.INT: 584 writeIIEq(type); 585 break; 586 case MDStatics.LONG: 587 writeLLEq(type); 588 break; 589 case MDStatics.FLOAT: 590 writeFFEq(type); 591 break; 592 case MDStatics.DOUBLE: 593 writeDDEq(type); 594 break; 595 case MDStatics.BOOLEAN: 596 writeIIEq(type); 597 break; 598 default: 599 throw BindingSupportImpl.getInstance().internal("Comparing field type'" + MDStaticUtils.toSimpleName(fl.bcType) + "' to" 600 + " field type '" + MDStaticUtils.toSimpleName(fl.bcType) + "' is not implemented correctly."); 601 } 602 } else if (!fl.isPrimitive() && !fr.isPrimitive()) { 603 promoteToObjects(widestType, fl, fr.ih); 604 promoteToObjects(widestType, fr, nopHandle); 605 if (fl.bcType == MDStatics.NULL || fr.bcType == MDStatics.NULL) { 606 if (type == COMP_EQ) { 607 IFNONNULL ifnull = new IFNONNULL(null); 608 il.append(ifnull); 609 il.append(InstructionConstants.ICONST_1); 610 GOTO gotoEnd = new GOTO(null); 611 il.append(gotoEnd); 612 InstructionHandle falseHandle = il.append(InstructionConstants.ICONST_0); 613 InstructionHandle endHandle = il.append(InstructionConstants.NOP); 614 ifnull.setTarget(falseHandle); 615 gotoEnd.setTarget(endHandle); 616 } else if (type == COMP_NE) { 617 IFNULL ifnull = new IFNULL(null); 618 il.append(ifnull); 619 il.append(InstructionConstants.ICONST_1); 620 GOTO gotoEnd = new GOTO(null); 621 il.append(gotoEnd); 622 InstructionHandle falseHandle = il.append(InstructionConstants.ICONST_0); 623 InstructionHandle endHandle = il.append(InstructionConstants.NOP); 624 ifnull.setTarget(falseHandle); 625 gotoEnd.setTarget(endHandle); 626 } else { 627 throw BindingSupportImpl.getInstance().invalidOperation("Only '==' and '!=' operators is implemented for comparing to a null value"); 628 } 629 } else if (Comparable .class.isAssignableFrom(fl.classType)) { 630 writeComparable(type); 631 } else { 632 il.append(factory.createInvoke(NAME_OBJECT, "equals", Type.BOOLEAN, 633 ARG_TYPES_OBJECT, Constants.INVOKEVIRTUAL)); 634 } 635 } else { 636 if (widestType == MDStatics.BIGDECIMAL || widestType == MDStatics.BIGINTEGER) { 637 if (fl.isPrimitive()) { 638 promotePrimToBig(widestType, fl, fr.ih); 639 } else { 640 promotePrimToBig(widestType, fr, nopHandle); 641 } 642 writeComparable(type); 643 } else { 644 promoteAllToPrim(widestType, fl, fr.ih); 645 promoteAllToPrim(widestType, fr, nopHandle); 646 switch (widestType) { 647 case MDStatics.BOOLEAN: 648 case MDStatics.BOOLEANW: 649 case MDStatics.BYTE: 650 case MDStatics.BYTEW: 651 case MDStatics.SHORT: 652 case MDStatics.SHORTW: 653 case MDStatics.CHAR: 654 case MDStatics.CHARW: 655 case MDStatics.INT: 656 case MDStatics.INTW: 657 writeIIEq(type); 658 break; 659 case MDStatics.LONG: 660 case MDStatics.LONGW: 661 writeLLEq(type); 662 break; 663 case MDStatics.FLOAT: 664 case MDStatics.FLOATW: 665 writeFFEq(type); 666 break; 667 case MDStatics.DOUBLE: 668 case MDStatics.DOUBLEW: 669 writeDDEq(type); 670 break; 671 default: 672 throw BindingSupportImpl.getInstance().internal("Comparing field type'" + MDStaticUtils.toSimpleName(fl.bcType) + "' to" 673 + " field type '" + MDStaticUtils.toSimpleName(fl.bcType) + "' is not implemented correctly."); 674 } 675 } 676 } 677 return null; 678 } 679 680 681 682 private void writeComparable(int type) { 683 il.append(factory.createInvoke(NAME_COMPARABLE, "compareTo", Type.INT, 684 ARG_TYPES_OBJECT, Constants.INVOKEINTERFACE)); 685 BranchInstruction bInstr = null; 686 switch (type) { 687 case COMP_EQ: 688 bInstr = new IFNE(null); 689 break; 690 case COMP_GE: 691 bInstr = new IFLT(null); 692 break; 693 case COMP_LT: 694 bInstr = new IFGE(null); 695 break; 696 case COMP_GT: 697 bInstr = new IFLE(null); 698 break; 699 case COMP_LE: 700 bInstr = new IFGT(null); 701 break; 702 case COMP_NE: 703 bInstr = new IFEQ(null); 704 break; 705 default: 706 throw BindingSupportImpl.getInstance().internal("No operator of type '" + type + "'"); 707 } 708 il.append(bInstr); 709 il.append(InstructionConstants.ICONST_1); 710 GOTO gotoEnd = new GOTO(null); 711 il.append(gotoEnd); 712 InstructionHandle loadFalse = il.append(InstructionConstants.ICONST_0); 714 InstructionHandle endHandle = il.append(InstructionConstants.NOP); 715 716 bInstr.setTarget(loadFalse); 717 gotoEnd.setTarget(endHandle); 718 } 719 720 public Field visitEqualNode(EqualNode node, Object obj) { 721 return doCompare(node, COMP_EQ); 722 } 723 724 public Field visitNotEqualNode(NotEqualNode node, Object obj) { 725 return doCompare(node, COMP_NE); 726 } 727 728 public Field visitLikeNode(LikeNode node, Object obj) { 729 return null; 730 } 731 732 private void writeIIEq(int compType) { 733 BranchInstruction bInstr = null; 734 switch (compType) { 735 case COMP_EQ: 736 bInstr = new IF_ICMPNE(null); 737 break; 738 case COMP_GE: 739 bInstr = new IF_ICMPLT(null); 740 break; 741 case COMP_LT: 742 bInstr = new IF_ICMPGE(null); 743 break; 744 case COMP_GT: 745 bInstr = new IF_ICMPLE(null); 746 break; 747 case COMP_LE: 748 bInstr = new IF_ICMPGT(null); 749 break; 750 case COMP_NE: 751 bInstr = new IF_ICMPEQ(null); 752 break; 753 default: 754 throw BindingSupportImpl.getInstance().internal("No operator of type '" + compType + "'"); 755 } 756 il.append(bInstr); 757 il.append(InstructionConstants.ICONST_1); 758 GOTO gotoEnd = new GOTO(null); 759 il.append(gotoEnd); 760 InstructionHandle loadFalse = il.append(InstructionConstants.ICONST_0); 762 InstructionHandle endHandle = il.append(InstructionConstants.NOP); 763 764 bInstr.setTarget(loadFalse); 765 gotoEnd.setTarget(endHandle); 766 } 767 768 private void writeDDEq(int compType) { 769 BranchInstruction bInstr = null; 770 il.append(new DCMPL()); 771 switch (compType) { 772 case COMP_EQ: 773 bInstr = new IFNE(null); 774 break; 775 case COMP_GE: 776 bInstr = new IFLT(null); 777 break; 778 case COMP_LT: 779 bInstr = new IFGE(null); 780 break; 781 case COMP_GT: 782 bInstr = new IFLE(null); 783 break; 784 case COMP_LE: 785 bInstr = new IFGT(null); 786 break; 787 case COMP_NE: 788 bInstr = new IFEQ(null); 789 break; 790 default: 791 throw BindingSupportImpl.getInstance().internal("No operator of type '" + compType + "'"); 792 } 793 il.append(bInstr); 794 il.append(InstructionConstants.ICONST_1); 795 GOTO gotoEnd = new GOTO(null); 796 il.append(gotoEnd); 797 InstructionHandle loadFalse = il.append(InstructionConstants.ICONST_0); 799 InstructionHandle endHandle = il.append(InstructionConstants.NOP); 800 801 bInstr.setTarget(loadFalse); 802 gotoEnd.setTarget(endHandle); 803 } 804 805 private void writeFFEq(int compType) { 806 BranchInstruction bInstr = null; 807 il.append(new FCMPL()); 808 switch (compType) { 809 case COMP_EQ: 810 bInstr = new IFNE(null); 811 break; 812 case COMP_GE: 813 bInstr = new IFLT(null); 814 break; 815 case COMP_LT: 816 bInstr = new IFGE(null); 817 break; 818 case COMP_GT: 819 bInstr = new IFLE(null); 820 break; 821 case COMP_LE: 822 bInstr = new IFGT(null); 823 break; 824 case COMP_NE: 825 bInstr = new IFEQ(null); 826 break; 827 default: 828 throw BindingSupportImpl.getInstance().internal("No operator of type '" + compType + "'"); 829 } 830 il.append(bInstr); 831 il.append(InstructionConstants.ICONST_1); 832 GOTO gotoEnd = new GOTO(null); 833 il.append(gotoEnd); 834 InstructionHandle loadFalse = il.append(InstructionConstants.ICONST_0); 836 InstructionHandle endHandle = il.append(InstructionConstants.NOP); 837 838 bInstr.setTarget(loadFalse); 839 gotoEnd.setTarget(endHandle); 840 } 841 842 private void writeLLEq(int type) { 843 BranchInstruction bInstr = null; 844 switch (type) { 845 case COMP_EQ: 846 il.append(new LCMP()); 847 bInstr = new IFNE(null); 848 break; 849 case COMP_GE: 850 il.append(new LCMP()); 851 bInstr = new IFLT(null); 852 break; 853 case COMP_GT: 854 il.append(new LCMP()); 855 bInstr = new IFLE(null); 856 break; 857 case COMP_LE: 858 il.append(new LCMP()); 859 bInstr = new IFGT(null); 860 break; 861 case COMP_LT: 862 il.append(new LCMP()); 863 bInstr = new IFGE(null); 864 break; 865 case COMP_NE: 866 il.append(new LCMP()); 867 bInstr = new IFEQ(null); 868 break; 869 default: 870 throw BindingSupportImpl.getInstance().internal("No operator of type '" + type + "'"); 871 } 872 il.append(bInstr); 873 il.append(InstructionConstants.ICONST_1); 874 GOTO gotoEnd = new GOTO(null); 875 il.append(gotoEnd); 876 InstructionHandle loadFalse = il.append(InstructionConstants.ICONST_0); 878 InstructionHandle endHandle = il.append(InstructionConstants.NOP); 879 880 bInstr.setTarget(loadFalse); 881 gotoEnd.setTarget(endHandle); 882 } 883 884 public Field visitAndNode(AndNode node, Object obj) { 885 List ifFalseList = new ArrayList(); 886 first = true; 887 node.childList.visit(this, obj); 888 889 if (node.childList instanceof MethodNode) { 891 MethodNode mNode = (MethodNode)node.childList; 892 if (isVarContainsMethodNode(mNode)) return null; 893 } 894 895 il.append(InstructionConstants.DUP); 896 IFEQ ifFalse = new IFEQ(null); 897 il.append(ifFalse); 898 899 IFEQ ifFalseVar = null; 900 Node n = node.childList.next; 901 while (n != null) { 902 first = true; 903 il.append(InstructionConstants.POP); 905 n.visit(this, obj); 906 il.append(InstructionConstants.DUP); 907 ifFalseVar = new IFEQ(null); 908 ifFalseList.add(ifFalseVar); 909 il.append(ifFalseVar); 910 n = n.next; 911 } 912 913 InstructionHandle endHandle = il.append(new NOP()); 914 ifFalse.setTarget(endHandle); 915 916 for (int i = 0; i < ifFalseList.size(); i++) { 917 ((IFEQ) ifFalseList.get(i)).setTarget(endHandle); 918 } 919 return null; 920 } 921 922 public Field visitOrNode(OrNode node, Object obj) { 923 List ifFalseList = new ArrayList(); 924 node.childList.visit(this, obj); 925 926 il.append(InstructionConstants.DUP); 927 IFNE ifTrue = new IFNE(null); 928 il.append(ifTrue); 929 IFNE ifTrueVar = null; 931 Node n = node.childList.next; 932 933 while (n != null) { 934 first = true; 935 il.append(InstructionConstants.POP); 937 n.visit(this, obj); 938 il.append(InstructionConstants.DUP); 939 ifTrueVar = new IFNE(null); 940 ifFalseList.add(ifTrueVar); 941 il.append(ifTrueVar); 942 n = n.next; 943 } 944 945 InstructionHandle endHandle = il.append(new NOP()); 946 ifTrue.setTarget(endHandle); 947 948 for (int i = 0; i < ifFalseList.size(); i++) { 949 ((BranchInstruction) ifFalseList.get(i)).setTarget(endHandle); 950 } 951 return null; 952 } 953 954 public Field visitMultiplyNode(MultiplyNode node, Object obj) { 955 BCField result = null; 956 BCField f = (BCField)node.childList.visit(this,obj); 957 BCField fnNext = null; 958 int widestType = 0; 959 960 List fieldsToPromote = new ArrayList(); 961 fieldsToPromote.add(f); 962 for(Node n = node.childList.next ; n != null; n = n.next) { 963 first = true; 964 fnNext = (BCField)n.visit(this, null); 965 fieldsToPromote.add(fnNext); 966 widestType = getWidestType(f.bcType, fnNext.bcType); 967 f = fnNext; 968 } 969 InstructionHandle nopHandle = il.append(InstructionConstants.NOP); 970 int n = fieldsToPromote.size(); 971 int lastIndex = n - 1; 972 for (int i = 0; i < n; i++) { 973 BCField bcField1 = (BCField) fieldsToPromote.get(i); 974 BCField bcField2 = (i == lastIndex) ? null : (BCField) fieldsToPromote.get(i + 1); 975 if (bcField2 == null) { 976 promoteTo(widestType, bcField1, nopHandle); 977 } else { 978 promoteTo(widestType, bcField1, bcField2.ih); 979 } 980 } 981 982 if (fieldsToPromote.size() == 2) { 983 insertMultiply(widestType, nopHandle, node.ops[0]); 984 } else { 985 for (int i = 1; i < n; i++) { 986 if (i == lastIndex) { 987 insertMultiply(widestType, nopHandle, node.ops[i -1]); 988 } else { 989 BCField bcField2 = (BCField) fieldsToPromote.get(i + 1); 990 insertMultiply(widestType, bcField2.ih, node.ops[i -1]); 991 } 992 } 993 } 994 result = new BCField(); 995 result.bcType = widestType; 996 result.classType = MDStaticUtils.toSimpleClass(MDStaticUtils.toSimpleName(widestType)); 997 return result; 998 } 999 1000 public Field visitAddNode(AddNode node, Object obj) { 1001 BCField result = null; 1002 first = true; 1003 BCField f = (BCField)node.childList.visit(this,obj); 1004 BCField fnNext = null; 1005 int widestType = 0; 1006 if (f.bcType == MDStatics.STRING) { 1007 il.append(factory.createNew(NAME_STRING_BUFFER)); 1008 il.append(InstructionConstants.DUP); 1009 il.append(factory.createInvoke(NAME_STRING_BUFFER, "<init>", 1010 Type.VOID, Type.NO_ARGS, 1011 Constants.INVOKESPECIAL)); 1012 LocalVariableGen lg = mg.addLocalVariable("buffer", 1013 OBJECT_TYPE_STRING_BUFFER, null, null); 1014 int bufferIndex = lg.getIndex(); 1015 lg.setStart(il.append(new ASTORE(bufferIndex))); 1016 il.append(new ALOAD(bufferIndex)); 1017 il.append(InstructionConstants.SWAP); 1018 il.append(factory.createInvoke(NAME_STRING_BUFFER, "append", OBJECT_TYPE_STRING_BUFFER, 1019 ARG_TYPES_STRING, Constants.INVOKEVIRTUAL)); 1020 1021 for(Node n = node.childList.next ; n != null; n = n.next) { 1022 first = true; 1023 n.visit(this, null); 1024 il.append(factory.createInvoke(NAME_STRING_BUFFER, "append", OBJECT_TYPE_STRING_BUFFER, 1025 ARG_TYPES_STRING, Constants.INVOKEVIRTUAL)); 1026 } 1027 il.append(factory.createInvoke(NAME_STRING_BUFFER, "toString", Type.STRING, 1028 Type.NO_ARGS, Constants.INVOKEVIRTUAL)); 1029 result = new BCField(); 1030 result.setBcType(MDStatics.STRING); 1031 result.classType = String .class; 1032 } else { 1033 List fieldsToPromote = new ArrayList(); 1034 fieldsToPromote.add(f); 1035 for(Node n = node.childList.next ; n != null; n = n.next) { 1036 first = true; 1037 fnNext = (BCField)n.visit(this, null); 1038 fieldsToPromote.add(fnNext); 1039 widestType = getWidestType(f.bcType, fnNext.bcType); 1040 f = fnNext; 1041 } 1042 InstructionHandle nopHandle = il.append(InstructionConstants.NOP); 1043 int n = fieldsToPromote.size(); 1044 int lastIndex = n - 1; 1045 for (int i = 0; i < n; i++) { 1046 BCField bcField1 = (BCField) fieldsToPromote.get(i); 1047 BCField bcField2 = (i == lastIndex) ? null : (BCField) fieldsToPromote.get(i + 1); 1048 if (bcField2 == null) { 1049 promoteTo(widestType, bcField1, nopHandle); 1050 } else { 1051 promoteTo(widestType, bcField1, bcField2.ih); 1052 } 1053 } 1054 1055 if (fieldsToPromote.size() == 2) { 1056 insertAddOp(widestType, nopHandle, node.ops[0]); 1057 } else { 1058 for (int i = 1; i < n; i++) { 1059 if (i == lastIndex) { 1060 insertAddOp(widestType, nopHandle, node.ops[i -1]); 1061 } else { 1062 BCField bcField2 = (BCField) fieldsToPromote.get(i + 1); 1063 insertAddOp(widestType, bcField2.ih, node.ops[i -1]); 1064 } 1065 } 1066 } 1067 result = new BCField(); 1068 result.bcType = widestType; 1069 result.classType = MDStaticUtils.toSimpleClass(MDStaticUtils.toSimpleName(widestType)); 1070 } 1071 return result; 1072 } 1073 1074 private void insertMultiply(int widestType, InstructionHandle insertHandle, int type) { 1075 if (type == MultiplyNode.OP_TIMES) { 1076 switch (widestType) { 1077 case MDStatics.BYTE: 1078 case MDStatics.SHORT: 1079 case MDStatics.CHAR: 1080 case MDStatics.INT: 1081 il.insert(insertHandle, InstructionConstants.IMUL); 1082 break; 1083 case MDStatics.LONG: 1084 il.insert(insertHandle, InstructionConstants.LMUL); 1085 break; 1086 case MDStatics.FLOAT: 1087 il.insert(insertHandle, InstructionConstants.FMUL); 1088 break; 1089 case MDStatics.DOUBLE: 1090 il.insert(insertHandle, InstructionConstants.DMUL); 1091 break; 1092 case MDStatics.BIGINTEGER: 1093 il.insert(insertHandle, factory.createInvoke(NAME_BIG_INT, "multiply", 1094 RET_TYPE_BIG_INT, ARG_TYPES_BIG_INT, Constants.INVOKEVIRTUAL)); 1095 break; 1096 case MDStatics.BIGDECIMAL: 1097 il.insert(insertHandle, factory.createInvoke(NAME_BIG_DEC, "multiply", 1098 RET_TYPE_BIG_DEC, ARG_TYPES_BIG_DEC, Constants.INVOKEVIRTUAL)); 1099 break; 1100 default: 1101 throw BindingSupportImpl.getInstance().internal("The '*' operator is not implemented correctly for type '" 1102 + MDStaticUtils.toSimpleName(widestType) + "'"); 1103 } 1104 } else { 1105 switch (widestType) { 1106 case MDStatics.BYTE: 1107 case MDStatics.SHORT: 1108 case MDStatics.CHAR: 1109 case MDStatics.INT: 1110 il.insert(insertHandle, InstructionConstants.IDIV); 1111 break; 1112 case MDStatics.LONG: 1113 il.insert(insertHandle, InstructionConstants.LDIV); 1114 break; 1115 case MDStatics.FLOAT: 1116 il.insert(insertHandle, InstructionConstants.FDIV); 1117 break; 1118 case MDStatics.DOUBLE: 1119 il.insert(insertHandle, InstructionConstants.DDIV); 1120 break; 1121 case MDStatics.BIGINTEGER: 1122 il.insert(insertHandle, factory.createInvoke(NAME_BIG_INT, "divide", 1123 RET_TYPE_BIG_INT, ARG_TYPES_BIG_INT, Constants.INVOKEVIRTUAL)); 1124 break; 1125 case MDStatics.BIGDECIMAL: 1126 il.insert(insertHandle, factory.createInvoke(NAME_BIG_DEC, "divide", 1127 RET_TYPE_BIG_DEC, ARG_TYPES_BIG_DEC, Constants.INVOKEVIRTUAL)); 1128 break; 1129 default: 1130 throw BindingSupportImpl.getInstance().internal("The '/' operator is not implemented correctly for type '" 1131 + MDStaticUtils.toSimpleName(widestType) + "'"); 1132 } 1133 } 1134 } 1135 1136 private void insertAddOp(int widestType, InstructionHandle insertHandle, int type) { 1137 if (type == AddNode.OP_PLUS) { 1138 switch (widestType) { 1139 case MDStatics.BYTE: 1140 case MDStatics.SHORT: 1141 case MDStatics.CHAR: 1142 case MDStatics.INT: 1143 il.insert(insertHandle, InstructionConstants.IADD); 1144 break; 1145 case MDStatics.LONG: 1146 il.insert(insertHandle, InstructionConstants.LADD); 1147 break; 1148 case MDStatics.FLOAT: 1149 il.insert(insertHandle, InstructionConstants.FADD); 1150 break; 1151 case MDStatics.DOUBLE: 1152 il.insert(insertHandle, InstructionConstants.DADD); 1153 break; 1154 case MDStatics.BIGINTEGER: 1155 il.insert(insertHandle, factory.createInvoke(NAME_BIG_INT, "add", 1156 RET_TYPE_BIG_INT, ARG_TYPES_BIG_INT, Constants.INVOKEVIRTUAL)); 1157 break; 1158 case MDStatics.BIGDECIMAL: 1159 il.insert(insertHandle, factory.createInvoke(NAME_BIG_DEC, "add", 1160 RET_TYPE_BIG_DEC, ARG_TYPES_BIG_DEC, Constants.INVOKEVIRTUAL)); 1161 break; 1162 default: 1163 throw BindingSupportImpl.getInstance().internal("The '+' operator is not implemented correctly for type '" 1164 + MDStaticUtils.toSimpleName(widestType) + "'"); 1165 } 1166 } else { 1167 switch (widestType) { 1168 case MDStatics.BYTE: 1169 case MDStatics.SHORT: 1170 case MDStatics.CHAR: 1171 case MDStatics.INT: 1172 il.insert(insertHandle, InstructionConstants.ISUB); 1173 break; 1174 case MDStatics.LONG: 1175 il.insert(insertHandle, InstructionConstants.LSUB); 1176 break; 1177 case MDStatics.FLOAT: 1178 il.insert(insertHandle, InstructionConstants.FSUB); 1179 break; 1180 case MDStatics.DOUBLE: 1181 il.insert(insertHandle, InstructionConstants.DSUB); 1182 break; 1183 case MDStatics.BIGINTEGER: 1184 il.insert(insertHandle, factory.createInvoke(NAME_BIG_INT, "subtract", 1185 RET_TYPE_BIG_INT, ARG_TYPES_BIG_INT, Constants.INVOKEVIRTUAL)); 1186 break; 1187 case MDStatics.BIGDECIMAL: 1188 il.insert(insertHandle, factory.createInvoke(NAME_BIG_DEC, "subtract", 1189 RET_TYPE_BIG_DEC, ARG_TYPES_BIG_DEC, Constants.INVOKEVIRTUAL)); 1190 break; 1191 default: 1192 throw BindingSupportImpl.getInstance().internal("The '-' operator is not implemented correctly for type '" 1193 + MDStaticUtils.toSimpleName(widestType) + "'"); 1194 } 1195 } 1196 } 1197 1198 private void promoteTo(int typePromoteTo, BCField otherType, InstructionHandle insertHandle) { 1199 if (otherType.bcType == typePromoteTo) { 1200 if (otherType.bcType == MDStatics.BIGINTEGER) { 1201 il.insert(insertHandle, factory.createCheckCast(RET_TYPE_BIG_INT)); 1203 } else if (otherType.bcType == MDStatics.BIGDECIMAL) { 1204 il.insert(insertHandle, factory.createCheckCast(RET_TYPE_BIG_DEC)); 1206 } 1207 return; 1208 } 1209 switch (typePromoteTo) { 1210 case MDStatics.BYTE: 1211 case MDStatics.SHORT: 1212 case MDStatics.CHAR: 1213 case MDStatics.INT: 1214 if (!otherType.isPrimitive()) { 1215 il.insert(insertHandle, factory.createCheckCast(OBJECT_TYPE_NUMBER)); 1216 il.insert(insertHandle, factory.createInvoke(NAME_NUMBER, "intValue", 1217 Type.INT, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); 1218 } 1219 break; 1220 case MDStatics.LONG: 1221 if (!otherType.isPrimitive()) { 1222 il.insert(insertHandle, factory.createCheckCast(OBJECT_TYPE_NUMBER)); 1223 il.insert(insertHandle, factory.createInvoke(NAME_NUMBER, "longValue", 1224 Type.LONG, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); 1225 } else { 1226 il.insert(insertHandle, InstructionConstants.I2L); 1227 } 1228 break; 1229 case MDStatics.FLOAT: 1230 if (!otherType.isPrimitive()) { 1231 il.insert(insertHandle, factory.createCheckCast(OBJECT_TYPE_NUMBER)); 1232 il.insert(insertHandle, factory.createInvoke(NAME_NUMBER, "floatValue", 1233 Type.FLOAT, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); 1234 } else { 1235 if (otherType.bcType == MDStatics.LONG) { 1236 il.insert(insertHandle, InstructionConstants.L2F); 1237 } else { 1238 il.insert(insertHandle, InstructionConstants.I2F); 1239 } 1240 } 1241 break; 1242 case MDStatics.DOUBLE: 1243 if (!otherType.isPrimitive()) { 1244 il.insert(insertHandle, factory.createCheckCast(OBJECT_TYPE_NUMBER)); 1245 il.insert(insertHandle, factory.createInvoke(NAME_NUMBER, "doubleValue", 1246 Type.DOUBLE, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); 1247 } else { 1248 switch (otherType.bcType) { 1249 case MDStatics.BYTE: 1250 case MDStatics.SHORT: 1251 case MDStatics.CHAR: 1252 case MDStatics.INT: 1253 il.insert(insertHandle, InstructionConstants.I2D); 1254 break; 1255 case MDStatics.LONG: 1256 il.insert(insertHandle, InstructionConstants.L2D); 1257 break; 1258 case MDStatics.FLOAT: 1259 il.insert(insertHandle, InstructionConstants.F2D); 1260 break; 1261 } 1262 } 1263 break; 1264 case MDStatics.BIGINTEGER: 1265 insertBigTypeFromPrim(insertHandle, otherType, NAME_BIG_INT); 1266 break; 1267 case MDStatics.BIGDECIMAL: 1268 insertBigTypeFromPrim(insertHandle, otherType, NAME_BIG_DEC); 1269 break; 1270 default: 1271 throw BindingSupportImpl.getInstance().internal("Promoting to type '" + MDStaticUtils.toSimpleName(typePromoteTo) + "' is not supported"); 1272 } 1273 1274 } 1275 1276 private void insertBigTypeFromObject(InstructionHandle insertHandle, String typeName) { 1277 LocalVariableGen valueOfLV = null; 1278 int colLVIndex; 1279 1280 il.insert(insertHandle, factory.createInvoke(NAME_OBJECT, "toString", 1281 OBJECT_TYPE_STRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); 1282 1283 valueOfLV = mg.addLocalVariable("valueOfString" + valueLVCount++, Type.STRING, null, null); 1285 colLVIndex = valueOfLV.getIndex(); 1286 valueOfLV.setStart(il.insert(insertHandle, new ASTORE(colLVIndex))); 1287 1288 il.insert(insertHandle, factory.createNew(typeName)); 1289 il.insert(insertHandle, InstructionConstants.DUP); 1290 il.insert(insertHandle, new ALOAD(colLVIndex)); 1291 il.insert(insertHandle, factory.createInvoke(typeName, "<init>", 1292 Type.VOID, ARG_TYPES_STRING, Constants.INVOKESPECIAL)); 1293 } 1294 1295 private void insertBigTypeFromPrim(InstructionHandle insertHandle, BCField otherType, String typeName) { 1296 LocalVariableGen valueOfLV; 1297 int colLVIndex; 1298 1299 il.insert(insertHandle, factory.createInvoke(NAME_STRING, "valueOf" , 1300 OBJECT_TYPE_STRING, new Type[] {getTypeFromTypeCode(otherType.bcType)}, Constants.INVOKESTATIC)); 1301 1302 valueOfLV = mg.addLocalVariable("valueOfString" + valueLVCount++, Type.STRING, null, null); 1304 colLVIndex = valueOfLV.getIndex(); 1305 valueOfLV.setStart(il.insert(insertHandle, new ASTORE(colLVIndex))); 1306 1307 il.insert(insertHandle, factory.createNew(typeName)); 1308 il.insert(insertHandle, InstructionConstants.DUP); 1309 il.insert(insertHandle, new ALOAD(colLVIndex)); 1310 il.insert(insertHandle, factory.createInvoke(typeName, "<init>", 1311 Type.VOID, ARG_TYPES_STRING, Constants.INVOKESPECIAL)); 1312 } 1313 1314 1322 private void promoteToObjects(int typePromoteTo, BCField otherType, InstructionHandle insertHandle) { 1323 if (typePromoteTo == otherType.bcType) { 1324 return; 1325 } 1326 switch (typePromoteTo) { 1327 case MDStatics.BIGINTEGER: 1328 insertBigTypeFromObject(insertHandle, NAME_BIG_INT); 1329 break; 1330 case MDStatics.BIGDECIMAL: 1331 insertBigTypeFromObject(insertHandle, NAME_BIG_DEC); 1332 break; 1333 default: 1334 } 1336 1337 } 1338 1339 1346 private void promotePrimToBig(int typePromoteTo, BCField otherType, InstructionHandle insertHandle) { 1347 if (typePromoteTo == otherType.bcType) { 1348 return; 1349 } 1350 switch (typePromoteTo) { 1351 case MDStatics.BIGINTEGER: 1352 insertBigTypeFromPrim(insertHandle, otherType, NAME_BIG_INT); 1353 break; 1354 case MDStatics.BIGDECIMAL: 1355 insertBigTypeFromPrim(insertHandle, otherType, NAME_BIG_DEC); 1356 break; 1357 default: 1358 throw BindingSupportImpl.getInstance().internal("Only 'BigInteger' and 'BigDecimal' is supported"); 1359 } 1360 1361 } 1362 1363 1370 private void promotePrimToPrim(int typePromoteTo, BCField otherType, InstructionHandle insertHandle) { 1371 if (otherType.bcType == typePromoteTo) { 1372 return; 1373 } 1374 switch (typePromoteTo) { 1375 case MDStatics.BYTE: 1376 case MDStatics.SHORT: 1377 case MDStatics.CHAR: 1378 case MDStatics.INT: 1379 break; 1380 case MDStatics.LONG: 1381 il.insert(insertHandle, InstructionConstants.I2L); 1382 break; 1383 case MDStatics.FLOAT: 1384 if (otherType.bcType == MDStatics.LONG) { 1385 il.insert(insertHandle, InstructionConstants.L2F); 1386 } else { 1387 il.insert(insertHandle, InstructionConstants.I2F); 1388 } 1389 break; 1390 case MDStatics.DOUBLE: 1391 switch (otherType.bcType) { 1392 case MDStatics.BYTE: 1393 case MDStatics.SHORT: 1394 case MDStatics.CHAR: 1395 case MDStatics.INT: 1396 il.insert(insertHandle, InstructionConstants.I2D); 1397 break; 1398 case MDStatics.LONG: 1399 il.insert(insertHandle, InstructionConstants.L2D); 1400 break; 1401 case MDStatics.FLOAT: 1402 il.insert(insertHandle, InstructionConstants.F2D); 1403 break; 1404 } 1405 break; 1406 case MDStatics.BOOLEAN: 1407 throw BindingSupportImpl.getInstance().invalidOperation("Promoting between primitives and boolean's is not allowed"); 1408 default: 1409 throw BindingSupportImpl.getInstance().internal("Promoting from type '" 1410 + MDStaticUtils.toSimpleName(otherType.bcType) + "'" 1411 + " to type '" + MDStaticUtils.toSimpleName(typePromoteTo) + "' is not implemented correctly"); 1412 } 1413 1414 } 1415 1416 1422 private void promoteAllToPrim(int typePromoteTo, BCField otherType, InstructionHandle insertHandle) { 1423 if (otherType.bcType == typePromoteTo && otherType.isPrimitive()) { 1424 return; 1425 } 1426 switch (typePromoteTo) { 1427 case MDStatics.BYTE: 1428 case MDStatics.SHORT: 1429 case MDStatics.CHAR: 1430 case MDStatics.INT: 1431 case MDStatics.INTW: 1432 if (!otherType.isPrimitive()) { 1433 il.insert(insertHandle, factory.createCheckCast(OBJECT_TYPE_NUMBER)); 1434 il.insert(insertHandle, factory.createInvoke(NAME_NUMBER, "intValue", 1435 Type.INT, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); 1436 } 1437 break; 1438 case MDStatics.LONG: 1439 case MDStatics.LONGW: 1440 if (!otherType.isPrimitive()) { 1441 il.insert(insertHandle, factory.createCheckCast(OBJECT_TYPE_NUMBER)); 1442 il.insert(insertHandle, factory.createInvoke(NAME_NUMBER, "longValue", 1443 Type.LONG, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); 1444 } else { 1445 il.insert(insertHandle, InstructionConstants.I2L); 1446 } 1447 break; 1448 case MDStatics.FLOAT: 1449 case MDStatics.FLOATW: 1450 if (!otherType.isPrimitive()) { 1451 il.insert(insertHandle, factory.createCheckCast(OBJECT_TYPE_NUMBER)); 1452 il.insert(insertHandle, factory.createInvoke(NAME_NUMBER, "floatValue", 1453 Type.FLOAT, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); 1454 } else { 1455 if (otherType.bcType == MDStatics.LONG) { 1456 il.insert(insertHandle, InstructionConstants.L2F); 1457 } else { 1458 il.insert(insertHandle, InstructionConstants.I2F); 1459 } 1460 } 1461 break; 1462 case MDStatics.DOUBLE: 1463 case MDStatics.DOUBLEW: 1464 if (!otherType.isPrimitive()) { 1465 il.insert(insertHandle, factory.createCheckCast(OBJECT_TYPE_NUMBER)); 1466 il.insert(insertHandle, factory.createInvoke(NAME_NUMBER, "doubleValue", 1467 Type.DOUBLE, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); 1468 } else { 1469 switch (otherType.bcType) { 1470 case MDStatics.BYTE: 1471 case MDStatics.SHORT: 1472 case MDStatics.CHAR: 1473 case MDStatics.INT: 1474 il.insert(insertHandle, InstructionConstants.I2D); 1475 break; 1476 case MDStatics.LONG: 1477 il.insert(insertHandle, InstructionConstants.L2D); 1478 break; 1479 case MDStatics.FLOAT: 1480 il.insert(insertHandle, InstructionConstants.F2D); 1481 break; 1482 } 1483 } 1484 break; 1485 case MDStatics.BOOLEAN: 1486 case MDStatics.BOOLEANW: 1487 if (!otherType.isPrimitive()) { 1488 il.insert(insertHandle, factory.createCheckCast(new ObjectType(Boolean .class.getName()))); 1489 il.insert(insertHandle, factory.createInvoke(Boolean .class.getName(), "booleanValue", 1490 Type.BOOLEAN, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); 1491 } 1492 break; 1493 default: 1494 throw BindingSupportImpl.getInstance().internal("Promoting from type '" 1495 + MDStaticUtils.toSimpleName(otherType.bcType) + "'" 1496 + " to type '" + MDStaticUtils.toSimpleName(typePromoteTo) + "' is not implemented correctly"); 1497 } 1498 1499 } 1500 1501 1507 private int getWidestType(int typeL, int typeR) { 1508 if (typeL == typeR) { 1509 return typeL; 1510 } 1511 int lValue = getWidth(typeL); 1512 int rValue = getWidth(typeR); 1513 if (lValue < rValue) { 1514 return typeR; 1515 } else { 1516 return typeL; 1517 } 1518 } 1519 1520 private int getWidth(int type) { 1521 switch (type) { 1522 case MDStatics.BOOLEAN: 1523 case MDStatics.BOOLEANW: 1524 case MDStatics.BYTE: 1525 case MDStatics.BYTEW: 1526 return 1; 1527 case MDStatics.SHORT: 1528 case MDStatics.SHORTW: 1529 return 1; 1530 case MDStatics.CHAR: 1531 case MDStatics.CHARW: 1532 return 1; 1533 case MDStatics.INT: 1534 case MDStatics.INTW: 1535 return 1; 1536 case MDStatics.LONG: 1537 case MDStatics.LONGW: 1538 return 2; 1539 case MDStatics.FLOAT: 1540 case MDStatics.FLOATW: 1541 return 3; 1542 case MDStatics.DOUBLE: 1543 case MDStatics.DOUBLEW: 1544 return 4; 1545 case MDStatics.BIGINTEGER: 1546 return 8; 1547 case MDStatics.BIGDECIMAL: 1548 return 16; 1549 case MDStatics.NULL: 1550 return -1; 1551 default: 1552 return -1; 1553 } 1554 } 1555 1556 public Field visitUnaryOpNode(UnaryOpNode node, Object obj) { 1557 BCField result = null; 1558 switch (node.op) { 1559 case UnaryOpNode.OP_BANG: 1560 node.childList.visit(this, null); 1561 IFNE ifTrue = new IFNE(null); 1562 il.append(ifTrue); 1563 il.append(InstructionConstants.ICONST_1); 1564 GOTO gotoEnd = new GOTO(null); 1565 il.append(gotoEnd); 1566 InstructionHandle toFalseHandle = il.append(InstructionConstants.ICONST_0); 1567 ifTrue.setTarget(toFalseHandle); 1568 gotoEnd.setTarget(il.append(InstructionConstants.NOP)); 1569 break; 1570 case UnaryOpNode.OP_MINUS: 1571 result = (BCField) node.childList.visit(this, null); 1572 switch (result.bcType) { 1573 case MDStatics.BYTE: 1574 case MDStatics.CHAR: 1575 case MDStatics.SHORT: 1576 case MDStatics.INT: 1577 il.append(InstructionConstants.INEG); 1578 break; 1579 case MDStatics.BYTEW: 1580 case MDStatics.CHARW: 1581 case MDStatics.SHORTW: 1582 case MDStatics.INTW: 1583 il.append(factory.createCheckCast(OBJECT_TYPE_NUMBER)); 1584 il.append(factory.createInvoke(NAME_NUMBER, "intValue", 1585 Type.INT, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); 1586 il.append(InstructionConstants.INEG); 1587 result = new BCField(); 1588 result.classType = Integer.TYPE; 1589 result.bcType = MDStatics.INT; 1590 break; 1591 case MDStatics.LONGW: 1592 il.append(factory.createCheckCast(OBJECT_TYPE_NUMBER)); 1593 il.append(factory.createInvoke(NAME_NUMBER, "longValue", 1594 Type.LONG, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); 1595 result = new BCField(); 1596 result.classType = Long.TYPE; 1597 result.bcType = MDStatics.LONG; 1598 case MDStatics.LONG: 1599 il.append(InstructionConstants.LNEG); 1600 break; 1601 case MDStatics.FLOATW: 1602 il.append(factory.createCheckCast(OBJECT_TYPE_NUMBER)); 1603 il.append(factory.createInvoke(NAME_NUMBER, "floatValue", 1604 Type.FLOAT, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); 1605 result = new BCField(); 1606 result.classType = Float.TYPE; 1607 result.bcType = MDStatics.FLOAT; 1608 case MDStatics.FLOAT: 1609 il.append(InstructionConstants.FNEG); 1610 break; 1611 case MDStatics.DOUBLEW: 1612 il.append(factory.createCheckCast(OBJECT_TYPE_NUMBER)); 1613 il.append(factory.createInvoke(NAME_NUMBER, "doubleValue", 1614 Type.DOUBLE, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); 1615 result = new BCField(); 1616 result.classType = Double.TYPE; 1617 result.bcType = MDStatics.DOUBLE; 1618 case MDStatics.DOUBLE: 1619 il.append(InstructionConstants.DNEG); 1620 break; 1621 default: 1622 throw new NotImplementedException(); 1623 } 1624 break; 1625 case UnaryOpNode.OP_PLUS: 1626 result = (BCField) node.childList.visit(this, null); 1627 break; 1628 case UnaryOpNode.OP_TILDE: 1629 result = (BCField) node.childList.visit(this, null); 1630 InstructionHandle nopHandle = il.append(InstructionConstants.NOP); 1631 promoteAllToPrim(result.bcType, result, nopHandle); 1632 switch (result.bcType) { 1633 case MDStatics.BYTE: 1634 case MDStatics.CHAR: 1635 case MDStatics.SHORT: 1636 case MDStatics.INT: 1637 case MDStatics.BYTEW: 1638 case MDStatics.CHARW: 1639 case MDStatics.SHORTW: 1640 case MDStatics.INTW: 1641 if (result.bcType != MDStatics.INT) { 1642 result = new BCField(); 1643 result.bcType = MDStatics.INT; 1644 result.classType = Integer.TYPE; 1645 } 1646 il.append(InstructionConstants.ICONST_M1); 1647 il.append(InstructionConstants.IXOR); 1648 break; 1649 case MDStatics.LONG: 1650 case MDStatics.LONGW: 1651 if (result.bcType != MDStatics.LONG) { 1652 result = new BCField(); 1653 result.bcType = MDStatics.LONG; 1654 result.classType = Long.TYPE; 1655 } 1656 il.append(new PUSH(cp, -1l)); 1657 il.append(InstructionConstants.LXOR); 1658 break; 1659 default: 1660 throw new NotImplementedException(); 1661 } 1662 break; 1663 default: 1664 throw new NotImplementedException("UnaryNode type '" + node.op + "' is not implemented correctly"); 1665 } 1666 return result; 1667 } 1668 1669 public Field visitCompareOpNode(CompareOpNode node, Object obj) { 1670 return doCompare(node, getCompType(node)); 1671 } 1672 1673 private final int getCompType(CompareOpNode node) { 1674 switch (node.op) { 1675 case CompareOpNode.GT: 1676 return COMP_GT; 1677 case CompareOpNode.LT: 1678 return COMP_LT; 1679 case CompareOpNode.GE: 1680 return COMP_GE; 1681 case CompareOpNode.LE: 1682 return COMP_LE; 1683 default: 1684 throw BindingSupportImpl.getInstance().internal("No operator of type '" + node.op + "'"); 1685 } 1686 } 1687 1688 public Field visitUnaryNode(UnaryNode node, Object obj) { 1689 node.childList.visit(this,obj); 1690 return null; 1691 } 1692 1693 public Field visitBinaryNode(BinaryNode node, Object obj) { 1694 return null; 1695 } 1696 1697 public Field visitMultiNode(Node node, Object obj) { 1698 return null; 1699 } 1700 1701 public Field visitCastNode(CastNode node, Object obj) { 1702 return null; 1703 } 1704 1705 public Field visitParamNode(ParamNode node, Object obj) { 1706 BCField field = null; 1707 Object paramValue = paramMap.get(node.getIdentifier()); 1708 if (paramValue == null) { 1709 field = new BCField(); 1710 field.bcType = MDStatics.NULL; 1711 field.classType = Object .class; 1712 } else { 1713 Class clazz = paramValue.getClass(); 1714 if(OID.class.isAssignableFrom(clazz)) { 1715 field = new BCField(); 1716 field.classType = clazz; 1717 field.bcType = MDStaticUtils.toTypeCode(clazz); 1718 field.ih = il.append(new ALOAD(2)); 1719 il.append(new PUSH(cp, node.getIndex())); 1720 il.append(new AALOAD()); 1721 } else { 1722 field = new BCField(); 1723 field.classType = clazz; 1724 field.bcType = MDStaticUtils.toTypeCode(clazz); 1725 field.ih = il.append(new ALOAD(2)); 1726 il.append(new PUSH(cp, node.getIndex())); 1727 il.append(new AALOAD()); 1728 } 1729 } 1730 return field; 1731 } 1732 1733 public Field visitParamNodeProxy(ParamNodeProxy node, Object obj) { 1734 return node.getParamNode().visit(this, obj); 1735 } 1736 1737 public Field visitArgNode(ArgNode node, Object obj) { 1738 return null; 1739 } 1740 1741 public Field visitArrayNode(ArrayNode node, Object obj) { 1742 return null; 1743 } 1744 1745 public Field visitImportNode(ImportNode node, Object obj) { 1746 return null; 1747 } 1748 1749 public Field visitLeafNode(LeafNode node, Object obj) { 1750 return null; 1751 } 1752 1753 public Field visitOrderNode(OrderNode node, Object obj) { 1754 return null; 1755 } 1756 1757 public Field visitVarNode(VarNode node, Object obj) { 1758 return null; 1759 } 1760 1761 public Field visitVarNodeProxy(VarNodeProxy node, Object obj) { 1762 return node.getVarNode().visit(this, obj); 1763 } 1764 1765 public Field visitReservedFieldNode(ReservedFieldNode node, Object obj) { 1766 return null; 1767 } 1768 1769 1770 private class BCStateField extends BCField { 1771 private InstructionHandle ih; 1772 private FieldMetaData fmd; 1773 1774 public BCStateField(FieldMetaData fmd) { 1775 this.fmd = fmd; 1776 initFromFMD(fmd); 1777 } 1778 1779 private void initFromFMD(FieldMetaData fmd) { 1780 this.classType = fmd.type; 1781 bcType = fmd.typeCode; 1782 1783 } 1784 1785 public BCStateField(InstructionHandle ih) { 1786 this.ih = ih; 1787 } 1788 1789 public InstructionHandle getIh() { 1790 return ih; 1791 } 1792 1793 public void setIh(InstructionHandle ih) { 1794 this.ih = ih; 1795 } 1796 1797 public FieldMetaData getFMD() { 1798 return fmd; 1799 } 1800 } 1801} 1802 | Popular Tags |