• 1k likes • 1.01k Views
Learn about identifying type-3 clones, automating their detection, and extracting methods for code optimization.
E N D
Efficient Method Extraction for Automatic Elimination of Type-3 Clones Shay Menaia AdvancedSoftware Tools Seminar TAU 21/1/13
Agenda • Clones and method extraction • Examples • Evaluation on real type-3 clones • Node-based bucketing • Slide-based bucketing • Empirical evaluation
Clone Types Duplicated source code caused by copy & paste • Type 1 • Identical code fragments except for variations in whitespace, layout and comments • Type 2 • Syntactically identical fragments except for variations in identifiers, literals, types, whitespace, layout and comments • Type 3 • Copied fragments with further modifications such as changed, added or removed statements, in addition to variations in identifiers, literals, types, whitespace, layout and comments
Clone Detection & Extraction • Once clones are found, still need to extract method • For each method containing the clone: extract the clone • Call the extracted clone from each original method • Automation for finding & extracting clones is useful for: • Improving maintenance • Reduce defects • Reduce source code size • Improve design
Clone Example • Example: • Upper: from Eclipse Java compiler’s org.eclipse.jdt.internal.compiler.codegen.ConstantPool class • Lower: from Eclipse Java compiler’s org.eclipse.jdt.internal.eval.CodeSnippetConstantPool class • The clones were taken from • Tiarks, R., Koschke, R., Falke, R.: An extended assessment of type-3 clones as detected by state-of-the-art tools. Software Quality Journal 19(2), 295–331 (2011)
Type-1 clones Introduction - Clones
Type-2 clones Introduction - Clones
Type-3 clones Introduction - Clones
Method Extraction (for Clone Elimination) • Input: • A set of non-contiguous statements to be extracted from a method • Desired output: • The original method with a method call instead of the selected statements • A new method with the selected statements • Goal: • Same extracted method for all copies • Transform type-3 clones to type-1 clones
Clone Extraction Transformation • RaghavanKomondoor & Susan Horwitz • Version 1: POPL 2000 Semantics-Preserving Procedure Extraction • Arrange the code to allow extraction of the selected nodes • No code duplication • Fails a lot • Exponential time complexity • Version 2: IWPC 2003 Effective, Automatic Procedure Extraction • 3-Buckets • Duplicates predicates • Polynomial time complexity • Never fails • But might promote a whole method
Example • The following example will be discussed throughout the presentation publicintliteralIndexForJavaLangObjectGetClass() { int index, nameAndTypeIndex, classIndex; 1: index = wellKnownMethods[GETCLASS_OBJECT_METHOD]; 2: if (index == 0) { 3: classIndex = literalIndexForJavaLangObject(); 4: nameAndTypeIndex = wellKnownMethodNameAndTypes [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE]; 5: if (nameAndTypeIndex == 0) { 6: intnameIndex = literalIndex(QualifiedNamesConstants.GetClass); 7: inttypeIndex = literalIndex(QualifiedNamesConstants.GetClassSignature); 8: nameAndTypeIndex = wellKnownMethodNameAndTypes [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE] = currentIndex++; 9: writeU1(NameAndTypeTag); 10: writeU2(nameIndex); 11: writeU2(typeIndex); } 12: index = wellKnownMethods[GETCLASS_OBJECT_METHOD] = currentIndex++; 13: writeU1(MethodRefTag); 14: writeU2(classIndex); 15: writeU2(nameAndTypeIndex); } 16: return index;}
Example #1 • Extracting the following lines: publicintliteralIndexForJavaLangObjectGetClass() { int index, nameAndTypeIndex, classIndex; 1: index = wellKnownMethods[GETCLASS_OBJECT_METHOD]; 2: if (index == 0) { 3: classIndex = literalIndexForJavaLangObject(); 4: nameAndTypeIndex = wellKnownMethodNameAndTypes [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE]; 5: ++ if (nameAndTypeIndex == 0) { 6: intnameIndex = literalIndex(QualifiedNamesConstants.GetClass); 7: inttypeIndex = literalIndex(QualifiedNamesConstants.GetClassSignature); 8: nameAndTypeIndex = wellKnownMethodNameAndTypes [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE] = currentIndex++; 9: ++ writeU1(NameAndTypeTag); 10: ++ writeU2(nameIndex); 11: ++ writeU2(typeIndex); } 12: index = wellKnownMethods[GETCLASS_OBJECT_METHOD] = currentIndex++; 13: writeU1(MethodRefTag); 14: writeU2(classIndex); 15: writeU2(nameAndTypeIndex); } 16: return index;}
Example #1 publicintliteralIndexForJavaLangObjectGetClass() { int index, nameAndTypeIndex, classIndex; 1: index = wellKnownMethods[GETCLASS_OBJECT_METHOD]; 2: if (index == 0) { 3: classIndex = literalIndexForJavaLangObject(); 4: nameAndTypeIndex = wellKnownMethodNameAndTypes [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE]; 5: ++ if (nameAndTypeIndex == 0) { 6: intnameIndex = literalIndex(QualifiedNamesConstants.GetClass); 7: inttypeIndex = literalIndex(QualifiedNamesConstants.GetClassSignature); 8: nameAndTypeIndex = wellKnownMethodNameAndTypes [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE] = currentIndex++; 9: ++ writeU1(NameAndTypeTag); 10: ++ writeU2(nameIndex); 11: ++ writeU2(typeIndex); } 12: index = wellKnownMethods[GETCLASS_OBJECT_METHOD] = currentIndex++; 13: writeU1(MethodRefTag); 14: writeU2(classIndex); 15: writeU2(nameAndTypeIndex); } 16: return index;} Code for extraction
Example #1 publicintliteralIndexForJavaLangObjectGetClass() { int index, nameAndTypeIndex, classIndex; 1: index = wellKnownMethods[GETCLASS_OBJECT_METHOD]; 2: if (index == 0) { 3: classIndex = literalIndexForJavaLangObject(); 4: nameAndTypeIndex = wellKnownMethodNameAndTypes [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE]; 5: ++ if (nameAndTypeIndex == 0) { 6: intnameIndex = literalIndex(QualifiedNamesConstants.GetClass); 7: inttypeIndex = literalIndex(QualifiedNamesConstants.GetClassSignature); 8: nameAndTypeIndex = wellKnownMethodNameAndTypes [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE] = currentIndex++; 9: ++ writeU1(NameAndTypeTag); 10: ++ writeU2(nameIndex); 11: ++ writeU2(typeIndex); } 12: index = wellKnownMethods[GETCLASS_OBJECT_METHOD] = currentIndex++; 13: writeU1(MethodRefTag); 14: writeU2(classIndex); 15: writeU2(nameAndTypeIndex); } 16: return index;} Must be placed before the marked statements
Example #1 • publicintliteralIndexForJavaLangObjectGetClass() { • int index, nameAndTypeIndex, classIndex, nameIndex=0; • 1: index = wellKnownMethods[GETCLASS_OBJECT_METHOD]; • 2: if (index == 0) { • 3: classIndex = literalIndexForJavaLangObject(); • 4: nameAndTypeIndex = wellKnownMethodNameAndTypes • [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE]; • 5:if (nameAndTypeIndex == 0) { • 6: nameIndex= literalIndex(QualifiedNamesConstants.GetClass);} • 5: ++ if (nameAndTypeIndex == 0) { • 7: inttypeIndex = literalIndex(QualifiedNamesConstants.GetClassSignature); • 8: nameAndTypeIndex = wellKnownMethodNameAndTypes • [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE] = currentIndex++; • 9: ++ writeU1(NameAndTypeTag); • 10: ++ writeU2(nameIndex); • 11: ++ writeU2(typeIndex); } • 12: index = wellKnownMethods[GETCLASS_OBJECT_METHOD] = currentIndex++; • 13: writeU1(MethodRefTag); • 14: writeU2(classIndex); • 15: writeU2(nameAndTypeIndex); } • 16: return index;} Must be placed before the marked statements
Example #1 • publicintliteralIndexForJavaLangObjectGetClass() { • int index, nameAndTypeIndex, classIndex, nameIndex=0; • 1: index = wellKnownMethods[GETCLASS_OBJECT_METHOD]; • 2: if (index == 0) { • 3: classIndex = literalIndexForJavaLangObject(); • 4: nameAndTypeIndex = wellKnownMethodNameAndTypes • [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE]; • 5:if (nameAndTypeIndex == 0) { • 6: nameIndex= literalIndex(QualifiedNamesConstants.GetClass);} • 5: ++ if (nameAndTypeIndex == 0) { • 7: inttypeIndex = literalIndex(QualifiedNamesConstants.GetClassSignature); • 8: nameAndTypeIndex = wellKnownMethodNameAndTypes • [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE] = currentIndex++; • 9: ++ writeU1(NameAndTypeTag); • 10: ++ writeU2(nameIndex); • 11: ++ writeU2(typeIndex); } • 12: index = wellKnownMethods[GETCLASS_OBJECT_METHOD] = currentIndex++; • 13: writeU1(MethodRefTag); • 14: writeU2(classIndex); • 15: writeU2(nameAndTypeIndex); } • 16: return index;} Must be placed before the marked statements
Example #1 • publicintliteralIndexForJavaLangObjectGetClass() { • int index, nameAndTypeIndex, classIndex, nameIndex=0, typeIndex=0; • 1: index = wellKnownMethods[GETCLASS_OBJECT_METHOD]; • 2: if (index == 0) { • 3: classIndex = literalIndexForJavaLangObject(); • 4: nameAndTypeIndex = wellKnownMethodNameAndTypes • [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE]; • 5:if (nameAndTypeIndex == 0) { • 6: nameIndex= literalIndex(QualifiedNamesConstants.GetClass); • 7: typeIndex= literalIndex(QualifiedNamesConstants.GetClassSignature);} • 5: ++ if (nameAndTypeIndex == 0) { • 8: nameAndTypeIndex = wellKnownMethodNameAndTypes • [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE] = currentIndex++; • 9: ++ writeU1(NameAndTypeTag); • 10: ++ writeU2(nameIndex); • 11: ++ writeU2(typeIndex); } • 12: index = wellKnownMethods[GETCLASS_OBJECT_METHOD] = currentIndex++; • 13: writeU1(MethodRefTag); • 14: writeU2(classIndex); • 15: writeU2(nameAndTypeIndex); } • 16: return index;} Must be placed before the marked statements
Example #1 • publicintliteralIndexForJavaLangObjectGetClass() { • int index, nameAndTypeIndex, classIndex,nameIndex=0, typeIndex=0; • 1: index = wellKnownMethods[GETCLASS_OBJECT_METHOD]; • 2: if (index == 0) { • 3: classIndex = literalIndexForJavaLangObject(); • 4: nameAndTypeIndex = wellKnownMethodNameAndTypes • [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE]; • 5:if (nameAndTypeIndex == 0) { • 6: nameIndex= literalIndex(QualifiedNamesConstants.GetClass); • 7: typeIndex= literalIndex(QualifiedNamesConstants.GetClassSignature);} • 5: ++ if (nameAndTypeIndex == 0) { • 8: nameAndTypeIndex = wellKnownMethodNameAndTypes • [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE] = currentIndex++; • 9: ++ writeU1(NameAndTypeTag); • 10: ++ writeU2(nameIndex); • 11: ++ writeU2(typeIndex); } • 12: index = wellKnownMethods[GETCLASS_OBJECT_METHOD] = currentIndex++; • 13: writeU1(MethodRefTag); • 14: writeU2(classIndex); • 15: writeU2(nameAndTypeIndex); } • 16: return index;} Must be placed after the marked statements
Example #1 • publicintliteralIndexForJavaLangObjectGetClass() { • int index, nameAndTypeIndex, classIndex,nameIndex=0, typeIndex=0; • 1: index = wellKnownMethods[GETCLASS_OBJECT_METHOD]; • 2: if (index == 0) { • 3: classIndex = literalIndexForJavaLangObject(); • 4: nameAndTypeIndex = wellKnownMethodNameAndTypes • [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE]; • 5:if (nameAndTypeIndex == 0) { • 6: nameIndex= literalIndex(QualifiedNamesConstants.GetClass); • 7: typeIndex= literalIndex(QualifiedNamesConstants.GetClassSignature);} • 5: ++ if (nameAndTypeIndex == 0) { • 9: ++ writeU1(NameAndTypeTag); • 10: ++ writeU2(nameIndex); • 11: ++ writeU2(typeIndex); } • 5:if (nameAndTypeIndex == 0) { • 8: nameAndTypeIndex = wellKnownMethodNameAndTypes • [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE] = currentIndex++;} • 12: index = wellKnownMethods[GETCLASS_OBJECT_METHOD] = currentIndex++; • 13: writeU1(MethodRefTag); • 14: writeU2(classIndex); • 15: writeU2(nameAndTypeIndex); } • 16: return index;} Must be placed after the marked statements
Example #1 • publicintliteralIndexForJavaLangObjectGetClass() { • int index, nameAndTypeIndex, classIndex,nameIndex=0, typeIndex=0; • 1: index = wellKnownMethods[GETCLASS_OBJECT_METHOD]; • 2: if (index == 0) { • 3: classIndex = literalIndexForJavaLangObject(); • 4: nameAndTypeIndex = wellKnownMethodNameAndTypes • [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE]; • 5:if (nameAndTypeIndex == 0) { • 6: nameIndex= literalIndex(QualifiedNamesConstants.GetClass); • 7: typeIndex= literalIndex(QualifiedNamesConstants.GetClassSignature);} • 5: ++ if (nameAndTypeIndex == 0) { • 9: ++ writeU1(NameAndTypeTag); • 10: ++ writeU2(nameIndex); • 11: ++ writeU2(typeIndex); } • 5:if (nameAndTypeIndex == 0) { • 8: nameAndTypeIndex = wellKnownMethodNameAndTypes • [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE] = currentIndex++;} • 12: index = wellKnownMethods[GETCLASS_OBJECT_METHOD] = currentIndex++; • 13: writeU1(MethodRefTag); • 14: writeU2(classIndex); • 15: writeU2(nameAndTypeIndex); } • 16: return index;} The code can be extracted
Example #1 • The 2nd copy of the clone publicintliteralIndexForJavaLangReflectArrayNewInstance() { int index, nameAndTypeIndex, classIndex; 1: index = wellKnownMethods[NEWINSTANCE_ARRAY_METHOD]; 2: if (index == 0) { 3: classIndex = literalIndexForJavaLangReflectArray(); 4: nameAndTypeIndex = wellKnownMethodNameAndTypes[ARRAY_NEWINSTANCE_METHOD_NAME_AND_TYPE]; 5: ++ if(nameAndTypeIndex == 0) { 6: intnameIndex = literalIndex(ARRAY_NEWINSTANCE_NAME); 7: inttypeIndex = literalIndex(ARRAY_NEWINSTANCE_SIGNATURE); 8: nameAndTypeIndex = wellKnownMethodNameAndTypes [ARRAY_NEWINSTANCE_METHOD_NAME_AND_TYPE] = currentIndex++; 9: ++ writeU1(NameAndTypeTag); 10:++ writeU2(nameIndex); 11:++ writeU2(typeIndex); } 12: index = wellKnownMethods[NEWINSTANCE_ARRAY_METHOD] = currentIndex++; 13: writeU1(MethodRefTag); 14: writeU2(classIndex); 15: writeU2(nameAndTypeIndex); } 16: return index; }
Example #1 • The 2nd copy of the clone • publicintliteralIndexForJavaLangReflectArrayNewInstance() { • int index, nameAndTypeIndex, classIndex, nameIndex=0, typeIndex=0; • 1: index = wellKnownMethods[NEWINSTANCE_ARRAY_METHOD]; • 2: if (index == 0) { • 3: classIndex = literalIndexForJavaLangReflectArray(); • 4: nameAndTypeIndex = wellKnownMethodNameAndTypes[ARRAY_NEWINSTANCE_METHOD_NAME_AND_TYPE]; • 5: if(nameAndTypeIndex == 0) { • 6: nameIndex= literalIndex(ARRAY_NEWINSTANCE_NAME); • 7: typeIndex= literalIndex(ARRAY_NEWINSTANCE_SIGNATURE);} • 5: ++ if(nameAndTypeIndex == 0) { • 9: ++ writeU1(NameAndTypeTag); • 10:++ writeU2(nameIndex); • 11:++ writeU2(typeIndex); } • 5: if (nameAndTypeIndex == 0) { • 8: nameAndTypeIndex = wellKnownMethodNameAndTypes • [ARRAY_NEWINSTANCE_METHOD_NAME_AND_TYPE] = currentIndex++;} • 12: index = wellKnownMethods[NEWINSTANCE_ARRAY_METHOD] = currentIndex++; • 13: writeU1(MethodRefTag); • 14: writeU2(classIndex); • 15: writeU2(nameAndTypeIndex); } • 16: return index; }
Example #1 • Method extraction in eclipse
Example #2 • Extracting the following statements: publicintliteralIndexForJavaLangObjectGetClass() { int index, nameAndTypeIndex, classIndex; 1: index = wellKnownMethods[GETCLASS_OBJECT_METHOD]; 2: if (index == 0) { 3: classIndex = literalIndexForJavaLangObject(); 4: nameAndTypeIndex = wellKnownMethodNameAndTypes [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE]; 5: ++if (nameAndTypeIndex == 0) { 6: intnameIndex = literalIndex(QualifiedNamesConstants.GetClass); 7: inttypeIndex = literalIndex(QualifiedNamesConstants.GetClassSignature); 8: nameAndTypeIndex = wellKnownMethodNameAndTypes [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE] = currentIndex++; 9: ++ writeU1(NameAndTypeTag); 10:++ writeU2(nameIndex); 11:++ writeU2(typeIndex); } 12: index = wellKnownMethods[GETCLASS_OBJECT_METHOD] = currentIndex++; 13:++ writeU1(MethodRefTag); 14:++ writeU2(classIndex); 15:++ writeU2(nameAndTypeIndex); } 16: return index;}
Example #2 • Extracting the following statements: publicintliteralIndexForJavaLangObjectGetClass() { int index, nameAndTypeIndex, classIndex; 1: index = wellKnownMethods[GETCLASS_OBJECT_METHOD]; 2: if (index == 0) { 3: classIndex = literalIndexForJavaLangObject(); 4: nameAndTypeIndex = wellKnownMethodNameAndTypes [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE]; 5: ++ if (nameAndTypeIndex == 0) { 6: intnameIndex = literalIndex(QualifiedNamesConstants.GetClass); 7: inttypeIndex = literalIndex(QualifiedNamesConstants.GetClassSignature); 8: nameAndTypeIndex = wellKnownMethodNameAndTypes [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE] = currentIndex++; 9: ++ writeU1(NameAndTypeTag); 10:++ writeU2(nameIndex); 11:++ writeU2(typeIndex); } 12: index = wellKnownMethods[GETCLASS_OBJECT_METHOD] = currentIndex++; 13:++ writeU1(MethodRefTag); 14:++ writeU2(classIndex); 15:++ writeU2(nameAndTypeIndex); } 16: return index;} Code for extraction
Example #2 publicintliteralIndexForJavaLangObjectGetClass() { int index, nameAndTypeIndex, classIndex; 1: index = wellKnownMethods[GETCLASS_OBJECT_METHOD]; 2: if (index == 0) { 3: classIndex = literalIndexForJavaLangObject(); 4: nameAndTypeIndex = wellKnownMethodNameAndTypes [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE]; 5:++ if (nameAndTypeIndex == 0) { 6: intnameIndex = literalIndex(QualifiedNamesConstants.GetClass); 7: inttypeIndex = literalIndex(QualifiedNamesConstants.GetClassSignature); 8: nameAndTypeIndex = wellKnownMethodNameAndTypes [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE] = currentIndex++; 9: ++ writeU1(NameAndTypeTag); 10:++ writeU2(nameIndex); 11:++ writeU2(typeIndex); } 12: index = wellKnownMethods[GETCLASS_OBJECT_METHOD] = currentIndex++; 13:++ writeU1(MethodRefTag); 14:++ writeU2(classIndex); 15:++ writeU2(nameAndTypeIndex); } 16: return index;} Must be placed before the marked statements
Example #2 • publicintliteralIndexForJavaLangObjectGetClass() { • int index, nameAndTypeIndex, classIndex,nameIndex=0, typeIndex=0; • 1: index = wellKnownMethods[GETCLASS_OBJECT_METHOD]; • 2: if (index == 0) { • 3: classIndex = literalIndexForJavaLangObject(); • 4: nameAndTypeIndex = wellKnownMethodNameAndTypes • [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE]; • 5: if (nameAndTypeIndex == 0) { • 6: nameIndex = literalIndex(QualifiedNamesConstants.GetClass); • 7: typeIndex= literalIndex(QualifiedNamesConstants.GetClassSignature);} • 5: ++if (nameAndTypeIndex == 0) { • 8: nameAndTypeIndex = wellKnownMethodNameAndTypes • [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE] = currentIndex++; • 9: ++ writeU1(NameAndTypeTag); • 10:++ writeU2(nameIndex); • 11:++ writeU2(typeIndex); } • 12: index = wellKnownMethods[GETCLASS_OBJECT_METHOD] = currentIndex++; • 13:++ writeU1(MethodRefTag); • 14:++ writeU2(classIndex); • 15:++ writeU2(nameAndTypeIndex); } • 16: return index;}
Example #2 • publicintliteralIndexForJavaLangObjectGetClass() { • int index, nameAndTypeIndex, classIndex,nameIndex=0, typeIndex=0; • 1: index = wellKnownMethods[GETCLASS_OBJECT_METHOD]; • 2: if (index == 0) { • 3: classIndex = literalIndexForJavaLangObject(); • 4: nameAndTypeIndex = wellKnownMethodNameAndTypes • [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE]; • 5: if (nameAndTypeIndex == 0) { • 6: nameIndex = literalIndex(QualifiedNamesConstants.GetClass); • 7: typeIndex= literalIndex(QualifiedNamesConstants.GetClassSignature);} • 5: ++if (nameAndTypeIndex == 0) { • 8: +++ nameAndTypeIndex = wellKnownMethodNameAndTypes • [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE] = currentIndex++; • 9: ++ writeU1(NameAndTypeTag); • 10:++ writeU2(nameIndex); • 11:++ writeU2(typeIndex); } • 12: index = wellKnownMethods[GETCLASS_OBJECT_METHOD] = currentIndex++; • 13:++ writeU1(MethodRefTag); • 14:++ writeU2(classIndex); • 15:++ writeU2(nameAndTypeIndex); } • 16: return index;} Cannot be moved • Uses nameAndTypeIndex
Example #2 • publicintliteralIndexForJavaLangObjectGetClass() { • int index, nameAndTypeIndex, classIndex,nameIndex=0, typeIndex=0; • 1: index = wellKnownMethods[GETCLASS_OBJECT_METHOD]; • 2: if (index == 0) { • 3: classIndex = literalIndexForJavaLangObject(); • 4: nameAndTypeIndex = wellKnownMethodNameAndTypes • [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE]; • 5: if (nameAndTypeIndex == 0) { • 6: nameIndex = literalIndex(QualifiedNamesConstants.GetClass); • 7: typeIndex= literalIndex(QualifiedNamesConstants.GetClassSignature);} • 5: ++if (nameAndTypeIndex == 0) { • 8: +++ nameAndTypeIndex = wellKnownMethodNameAndTypes • [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE] = currentIndex++; • 9: ++ writeU1(NameAndTypeTag); • 10:++ writeU2(nameIndex); • 11:++ writeU2(typeIndex); } • 12: index = wellKnownMethods[GETCLASS_OBJECT_METHOD] = currentIndex++; • 13:++ writeU1(MethodRefTag); • 14:++ writeU2(classIndex); • 15:++ writeU2(nameAndTypeIndex); } • 16: return index;} Must be placed after the marked statements
Example #2 • publicintliteralIndexForJavaLangObjectGetClass() { • int index, nameAndTypeIndex, classIndex,nameIndex=0, typeIndex=0; • 1: index = wellKnownMethods[GETCLASS_OBJECT_METHOD]; • 2: if (index == 0) { • 3: classIndex = literalIndexForJavaLangObject(); • 4: nameAndTypeIndex = wellKnownMethodNameAndTypes • [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE]; • 5: if (nameAndTypeIndex == 0) { • 6: nameIndex = literalIndex(QualifiedNamesConstants.GetClass); • 7: typeIndex= literalIndex(QualifiedNamesConstants.GetClassSignature);} • 5: ++if (nameAndTypeIndex == 0) { • 8: +++ nameAndTypeIndex = wellKnownMethodNameAndTypes • [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE] = currentIndex++; • 9: ++ writeU1(NameAndTypeTag); • 10:++ writeU2(nameIndex); • 11:++ writeU2(typeIndex); } • 13:++ writeU1(MethodRefTag); • 14:++ writeU2(classIndex); • 15:++ writeU2(nameAndTypeIndex); • 12: index = wellKnownMethods[GETCLASS_OBJECT_METHOD] = currentIndex++;} • 16: return index;}
Example #2 • Now the code can be extracted • publicintliteralIndexForJavaLangObjectGetClass() { • int index, nameAndTypeIndex, classIndex,nameIndex=0, typeIndex=0; • 1: index = wellKnownMethods[GETCLASS_OBJECT_METHOD]; • 2: if (index == 0) { • 3: classIndex = literalIndexForJavaLangObject(); • 4: nameAndTypeIndex = wellKnownMethodNameAndTypes • [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE]; • 5: if (nameAndTypeIndex == 0) { • 6: nameIndex = literalIndex(QualifiedNamesConstants.GetClass); • 7: typeIndex= literalIndex(QualifiedNamesConstants.GetClassSignature);} • 5: ++if (nameAndTypeIndex == 0) { • 8: +++ nameAndTypeIndex = wellKnownMethodNameAndTypes • [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE] = currentIndex++; • 9: ++ writeU1(NameAndTypeTag); • 10:++ writeU2(nameIndex); • 11:++ writeU2(typeIndex); } • 13:++ writeU1(MethodRefTag); • 14:++ writeU2(classIndex); • 15:++ writeU2(nameAndTypeIndex); • 12: index = wellKnownMethods[GETCLASS_OBJECT_METHOD] = currentIndex++;} • 16: return index;}
Example #2 • The 2nd copy of the clone publicintliteralIndexForJavaLangReflectArrayNewInstance() { int index, nameAndTypeIndex, classIndex; 1: index = wellKnownMethods[NEWINSTANCE_ARRAY_METHOD]; 2: if (index == 0) { 3: classIndex = literalIndexForJavaLangReflectArray(); 4: nameAndTypeIndex = wellKnownMethodNameAndTypes[ARRAY_NEWINSTANCE_METHOD_NAME_AND_TYPE]; 5: ++ if(nameAndTypeIndex == 0) { 6: intnameIndex = literalIndex(ARRAY_NEWINSTANCE_NAME); 7: inttypeIndex = literalIndex(ARRAY_NEWINSTANCE_SIGNATURE); 8: nameAndTypeIndex = wellKnownMethodNameAndTypes [ARRAY_NEWINSTANCE_METHOD_NAME_AND_TYPE] = currentIndex++; 9: ++ writeU1(NameAndTypeTag); 10:++ writeU2(nameIndex); 11:++ writeU2(typeIndex); } 12: index = wellKnownMethods[NEWINSTANCE_ARRAY_METHOD] = currentIndex++; 13:++ writeU1(MethodRefTag); 14:++ writeU2(classIndex); 15:++ writeU2(nameAndTypeIndex); } 16: return index; }
Example #2 • The 2nd copy of the clone • publicintliteralIndexForJavaLangReflectArrayNewInstance() { • int index, nameAndTypeIndex, classIndex, nameIndex=0, typeIndex=0 ; • 1: index = wellKnownMethods[NEWINSTANCE_ARRAY_METHOD]; • 2: if (index == 0) { • 3: classIndex = literalIndexForJavaLangReflectArray(); • 4: nameAndTypeIndex = wellKnownMethodNameAndTypes[ARRAY_NEWINSTANCE_METHOD_NAME_AND_TYPE]; • 5: if (nameAndTypeIndex == 0) { • 6: nameIndex= literalIndex(ARRAY_NEWINSTANCE_NAME); • 7: typeIndex= literalIndex(ARRAY_NEWINSTANCE_SIGNATURE);} • 5: ++ if(nameAndTypeIndex == 0) { • 8: +++ nameAndTypeIndex = wellKnownMethodNameAndTypes • [ARRAY_NEWINSTANCE_METHOD_NAME_AND_TYPE] = currentIndex++; • 9: ++ writeU1(NameAndTypeTag); • 10:++ writeU2(nameIndex); • 11:++ writeU2(typeIndex); } • 13:++ writeU1(MethodRefTag); • 14:++ writeU2(classIndex); • 15:++ writeU2(nameAndTypeIndex); • 12: index = wellKnownMethods[NEWINSTANCE_ARRAY_METHOD] = currentIndex++;} • 16: return index; }
Example #2 • Method extraction in eclipse
Example #3 publicintliteralIndexForJavaLangObjectGetClass() { int index, nameAndTypeIndex, classIndex; 1: index = wellKnownMethods[GETCLASS_OBJECT_METHOD]; 2: if (index == 0) { 3: classIndex = literalIndexForJavaLangObject(); 4: nameAndTypeIndex = wellKnownMethodNameAndTypes [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE]; 5: ++if (nameAndTypeIndex == 0) { 6: intnameIndex = literalIndex(QualifiedNamesConstants.GetClass); 7: inttypeIndex = literalIndex(QualifiedNamesConstants.GetClassSignature); 8: nameAndTypeIndex = wellKnownMethodNameAndTypes [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE] = currentIndex++; 9: ++ writeU1(NameAndTypeTag); 10:++ writeU2(nameIndex); 11:++ writeU2(typeIndex); } 12: index = wellKnownMethods[GETCLASS_OBJECT_METHOD] = currentIndex++; 13:++ writeU1(MethodRefTag); 14:++ writeU2(classIndex); 15: writeU2(nameAndTypeIndex); } 16: return index;}
Example #3 publicintliteralIndexForJavaLangObjectGetClass() { int index, nameAndTypeIndex, classIndex; 1: index = wellKnownMethods[GETCLASS_OBJECT_METHOD]; 2: if (index == 0) { 3: classIndex = literalIndexForJavaLangObject(); 4: nameAndTypeIndex = wellKnownMethodNameAndTypes [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE]; 5: ++if (nameAndTypeIndex == 0) { 6: intnameIndex = literalIndex(QualifiedNamesConstants.GetClass); 7: inttypeIndex = literalIndex(QualifiedNamesConstants.GetClassSignature); 8: nameAndTypeIndex = wellKnownMethodNameAndTypes [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE] = currentIndex++; 9: ++ writeU1(NameAndTypeTag); 10:++ writeU2(nameIndex); 11:++ writeU2(typeIndex); } 12: index = wellKnownMethods[GETCLASS_OBJECT_METHOD] = currentIndex++; 13:++ writeU1(MethodRefTag); 14:++ writeU2(classIndex); 15: writeU2(nameAndTypeIndex); } 16: return index;} Code for extraction
Example #3 • Same as Example #2 except 8 publicintliteralIndexForJavaLangObjectGetClass() { int index, nameAndTypeIndex, classIndex; 1: index = wellKnownMethods[GETCLASS_OBJECT_METHOD]; 2: if (index == 0) { 3: classIndex = literalIndexForJavaLangObject(); 4: nameAndTypeIndex = wellKnownMethodNameAndTypes [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE]; 5: ++if (nameAndTypeIndex == 0) { 6: intnameIndex = literalIndex(QualifiedNamesConstants.GetClass); 7: inttypeIndex = literalIndex(QualifiedNamesConstants.GetClassSignature); 8: nameAndTypeIndex = wellKnownMethodNameAndTypes [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE] = currentIndex++; 9: ++ writeU1(NameAndTypeTag); 10:++ writeU2(nameIndex); 11:++ writeU2(typeIndex); } 12: index = wellKnownMethods[GETCLASS_OBJECT_METHOD] = currentIndex++; 13:++ writeU1(MethodRefTag); 14:++ writeU2(classIndex); 15: writeU2(nameAndTypeIndex); } 16: return index;} Can be placed after the marked statements
Example #3 • The code after • publicintliteralIndexForJavaLangObjectGetClass() { • int index, nameAndTypeIndex, classIndex, nameIndex=0, typeIndex=0; • 1: index = wellKnownMethods[GETCLASS_OBJECT_METHOD]; • 2: if (index == 0) { • 3: classIndex = literalIndexForJavaLangObject(); • 4: nameAndTypeIndex = wellKnownMethodNameAndTypes • [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE]; • 5: if (nameAndTypeIndex == 0) { • 6: nameIndex= literalIndex(QualifiedNamesConstants.GetClass); • 7: typeIndex= literalIndex(QualifiedNamesConstants.GetClassSignature);} • 5: ++if (nameAndTypeIndex == 0) { • 9:++ writeU1(NameAndTypeTag); • 10:++ writeU2(nameIndex); • 11:++ writeU2(typeIndex); } • 13:++ writeU1(MethodRefTag); • 14:++ writeU2(classIndex); • 5: if (nameAndTypeIndex == 0) { • 8: nameAndTypeIndex = wellKnownMethodNameAndTypes • [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE] = currentIndex++;} • 12: index = wellKnownMethods[GETCLASS_OBJECT_METHOD] = currentIndex++; • 15: writeU2(nameAndTypeIndex); } • 16: return index;} Code to be extracted
Example #3 • The 2nd copy of the clone • publicintliteralIndexForJavaLangReflectArrayNewInstance() { • int index, nameAndTypeIndex, classIndex,nameIndex=0, typeIndex=0 ; • 1: index = wellKnownMethods[NEWINSTANCE_ARRAY_METHOD]; • 2: if (index == 0) { • 3: classIndex = literalIndexForJavaLangReflectArray(); • 4: nameAndTypeIndex = wellKnownMethodNameAndTypes[ARRAY_NEWINSTANCE_METHOD_NAME_AND_TYPE]; • 5: if (nameAndTypeIndex == 0) { • 6: nameIndex= literalIndex(ARRAY_NEWINSTANCE_NAME); • 7: typeIndex= literalIndex(ARRAY_NEWINSTANCE_SIGNATURE);} • 5: ++ if(nameAndTypeIndex == 0) { • 9: ++ writeU1(NameAndTypeTag); • 10:++ writeU2(nameIndex); • 11:++ writeU2(typeIndex); } • 13:++ writeU1(MethodRefTag); • 14:++ writeU2(classIndex); • 5: if(nameAndTypeIndex == 0) { • 8: nameAndTypeIndex= wellKnownMethodNameAndTypes • [ARRAY_NEWINSTANCE_METHOD_NAME_AND_TYPE] = currentIndex++;} • 15: writeU2(nameAndTypeIndex); • 12: index = wellKnownMethods[NEWINSTANCE_ARRAY_METHOD] = currentIndex++;} • 16: return index; } Code to be extracted
Example #3 • Method extraction in eclipse
Agenda • Clones and method extraction • Examples • Evaluation on real type-3 clones • Node-based bucketing • Slide-based bucketing • Empirical evaluation
Empirical Evaluation • Source • Real type-3 clones taken from the Java portion of the Tiarksbenchmark • Confirmed 110 clone pairs (out of 404) from 4 Java projects • Reported start and end lines in each instance • Which statements should be marked? • Our choice: mark identical statements for each clone instance • Goal • Turn the type-3 clones into type-1 clones
Empirical Evaluation • Evaluation on Type-3 Clones • In brackets: the number of distinct cases
Empirical Evaluation • No promotion • Legend: |N| = # of statements, |M| = # of initially marked statements
Empirical Evaluation • With promotion • Legend: |N| = # of statements, |M| = # of initially marked statements
Agenda • Clones and method extraction • Examples • Evaluation on real type-3 clones • Node-based bucketing • Slide-based bucketing • Empirical evaluation
Background • Control dependence • Data dependence • Flow • Anti • Output • PDG
Example • Reminder publicintliteralIndexForJavaLangObjectGetClass() { int index, nameAndTypeIndex, classIndex; 1: index = wellKnownMethods[GETCLASS_OBJECT_METHOD]; 2: if (index == 0) { 3: classIndex = literalIndexForJavaLangObject(); 4: nameAndTypeIndex = wellKnownMethodNameAndTypes [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE]; 5: if (nameAndTypeIndex == 0) { 6: intnameIndex = literalIndex(QualifiedNamesConstants.GetClass); 7: inttypeIndex = literalIndex(QualifiedNamesConstants.GetClassSignature); 8: nameAndTypeIndex = wellKnownMethodNameAndTypes [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE] = currentIndex++; 9: writeU1(NameAndTypeTag); 10: writeU2(nameIndex); 11: writeU2(typeIndex); } 12: index = wellKnownMethods[GETCLASS_OBJECT_METHOD] = currentIndex++; 13: writeU1(MethodRefTag); 14: writeU2(classIndex); 15: writeU2(nameAndTypeIndex); } 16: return index;}
Control Dependence Graph entry publicintliteralIndexForJavaLangObjectGetClass() { int index, nameAndTypeIndex, classIndex; 1: index = wellKnownMethods[GETCLASS_OBJECT_METHOD]; 2: if (index == 0) { 3: classIndex = literalIndexForJavaLangObject(); 4: nameAndTypeIndex = wellKnownMethodNameAndTypes [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE]; 5: if (nameAndTypeIndex == 0) { 6: intnameIndex = literalIndex(QualifiedNamesConstants.GetClass); 7: inttypeIndex = literalIndex(QualifiedNamesConstants.GetClassSignature); 8: nameAndTypeIndex = wellKnownMethodNameAndTypes [GETCLASS_OBJECT_METHOD_NAME_AND_TYPE] = currentIndex++; 9: writeU1(NameAndTypeTag); 10: writeU2(nameIndex); 11: writeU2(typeIndex); } 12: index = wellKnownMethods[GETCLASS_OBJECT_METHOD] = currentIndex++; 13: writeU1(MethodRefTag); 14: writeU2(classIndex); 15: writeU2(nameAndTypeIndex); } 16: return index;} 1 2 16 3 4 5 12 13 14 15 6 7 8 9 10 11