diff options
52 files changed, 686 insertions, 324 deletions
diff --git a/dexdump/dexdump.cc b/dexdump/dexdump.cc index f8274e2f9a..e9b64028de 100644 --- a/dexdump/dexdump.cc +++ b/dexdump/dexdump.cc @@ -123,8 +123,7 @@ static const char* primitiveTypeLabel(char typeChar) { /* * Converts a type descriptor to human-readable "dotted" form. For * example, "Ljava/lang/String;" becomes "java.lang.String", and - * "[I" becomes "int[]". Also converts '$' to '.', which means this - * form can't be converted back to a descriptor. + * "[I" becomes "int[]". */ static std::unique_ptr<char[]> descriptorToDot(const char* str) { int targetLen = strlen(str); @@ -157,7 +156,7 @@ static std::unique_ptr<char[]> descriptorToDot(const char* str) { int i = 0; for (; i < targetLen; i++) { const char ch = str[offset + i]; - newStr[i] = (ch == '/' || ch == '$') ? '.' : ch; + newStr[i] = (ch == '/') ? '.' : ch; } // for // Add the appropriate number of brackets for arrays. @@ -171,10 +170,9 @@ static std::unique_ptr<char[]> descriptorToDot(const char* str) { } /* - * Converts the class name portion of a type descriptor to human-readable - * "dotted" form. For example, "Ljava/lang/String;" becomes "String". + * Retrieves the class name portion of a type descriptor. */ -static std::unique_ptr<char[]> descriptorClassToDot(const char* str) { +static std::unique_ptr<char[]> descriptorClassToName(const char* str) { // Reduce to just the class name prefix. const char* lastSlash = strrchr(str, '/'); if (lastSlash == nullptr) { @@ -187,8 +185,7 @@ static std::unique_ptr<char[]> descriptorClassToDot(const char* str) { const int targetLen = strlen(lastSlash); std::unique_ptr<char[]> newStr(new char[targetLen]); for (int i = 0; i < targetLen - 1; i++) { - const char ch = lastSlash[i]; - newStr[i] = ch == '$' ? '.' : ch; + newStr[i] = lastSlash[i]; } // for newStr[targetLen - 1] = '\0'; return newStr; @@ -1250,7 +1247,7 @@ static void dumpMethod(const ClassAccessor::Method& method, int i) { // Method name and prototype. if (constructor) { - std::unique_ptr<char[]> dot(descriptorClassToDot(backDescriptor)); + std::unique_ptr<char[]> dot(descriptorClassToName(backDescriptor)); fprintf(gOutFile, "<constructor name=\"%s\"\n", dot.get()); dot = descriptorToDot(backDescriptor); fprintf(gOutFile, " type=\"%s\"\n", dot.get()); @@ -1469,7 +1466,7 @@ static void dumpClass(const DexFile* pDexFile, int idx, char** pLastPackage) { } fprintf(gOutFile, " Interfaces -\n"); } else { - std::unique_ptr<char[]> dot(descriptorClassToDot(classDescriptor)); + std::unique_ptr<char[]> dot(descriptorClassToName(classDescriptor)); fprintf(gOutFile, "<class name=\"%s\"\n", dot.get()); if (superclassDescriptor != nullptr) { dot = descriptorToDot(superclassDescriptor); diff --git a/dexlayout/dexlayout.cc b/dexlayout/dexlayout.cc index d6dd9d1829..bd7a301a56 100644 --- a/dexlayout/dexlayout.cc +++ b/dexlayout/dexlayout.cc @@ -71,26 +71,10 @@ static inline uint16_t Get2LE(unsigned char const* src) { } /* - * Converts a type descriptor to human-readable "dotted" form. For - * example, "Ljava/lang/String;" becomes "java.lang.String", and - * "[I" becomes "int[]". Also converts '$' to '.', which means this - * form can't be converted back to a descriptor. - */ -static std::string DescriptorToDotWrapper(const char* descriptor) { - std::string result = DescriptorToDot(descriptor); - size_t found = result.find('$'); - while (found != std::string::npos) { - result[found] = '.'; - found = result.find('$', found); - } - return result; -} - -/* * Converts the class name portion of a type descriptor to human-readable * "dotted" form. For example, "Ljava/lang/String;" becomes "String". */ -static std::string DescriptorClassToDot(const char* str) { +static std::string DescriptorClassToName(const char* str) { std::string descriptor(str); // Reduce to just the class name prefix. size_t last_slash = descriptor.rfind('/'); @@ -104,13 +88,6 @@ static std::string DescriptorClassToDot(const char* str) { size_t size = descriptor.size() - 1 - last_slash; std::string result(descriptor.substr(last_slash, size)); - // Replace '$' with '.'. - size_t dollar_sign = result.find('$'); - while (dollar_sign != std::string::npos) { - result[dollar_sign] = '.'; - dollar_sign = result.find('$', dollar_sign); - } - return result; } @@ -786,7 +763,7 @@ void DexLayout::DumpInterface(const dex_ir::TypeId* type_item, int i) { if (options_.output_format_ == kOutputPlain) { fprintf(out_file_, " #%d : '%s'\n", i, interface_name); } else { - std::string dot(DescriptorToDotWrapper(interface_name)); + std::string dot(DescriptorToDot(interface_name)); fprintf(out_file_, "<implements name=\"%s\">\n</implements>\n", dot.c_str()); } } @@ -1044,7 +1021,7 @@ void DexLayout::DumpBytecodes(uint32_t idx, const dex_ir::CodeItem* code, uint32 const char* back_descriptor = method_id->Class()->GetStringId()->Data(); // Generate header. - std::string dot(DescriptorToDotWrapper(back_descriptor)); + std::string dot(DescriptorToDot(back_descriptor)); fprintf(out_file_, "%06x: |[%06x] %s.%s:%s\n", code_offset, code_offset, dot.c_str(), name, type_descriptor.c_str()); @@ -1212,9 +1189,9 @@ void DexLayout::DumpMethod(uint32_t idx, uint32_t flags, const dex_ir::CodeItem* // Method name and prototype. if (constructor) { - std::string dot(DescriptorClassToDot(back_descriptor)); + std::string dot(DescriptorClassToName(back_descriptor)); fprintf(out_file_, "<constructor name=\"%s\"\n", dot.c_str()); - dot = DescriptorToDotWrapper(back_descriptor); + dot = DescriptorToDot(back_descriptor); fprintf(out_file_, " type=\"%s\"\n", dot.c_str()); } else { fprintf(out_file_, "<method name=\"%s\"\n", name); @@ -1223,7 +1200,7 @@ void DexLayout::DumpMethod(uint32_t idx, uint32_t flags, const dex_ir::CodeItem* LOG(ERROR) << "bad method type descriptor '" << type_descriptor << "'"; goto bail; } - std::string dot(DescriptorToDotWrapper(return_type + 1)); + std::string dot(DescriptorToDot(return_type + 1)); fprintf(out_file_, " return=\"%s\"\n", dot.c_str()); fprintf(out_file_, " abstract=%s\n", QuotedBool((flags & kAccAbstract) != 0)); fprintf(out_file_, " native=%s\n", QuotedBool((flags & kAccNative) != 0)); @@ -1265,7 +1242,7 @@ void DexLayout::DumpMethod(uint32_t idx, uint32_t flags, const dex_ir::CodeItem* } // Null terminate and display. *cp++ = '\0'; - std::string dot(DescriptorToDotWrapper(tmp_buf)); + std::string dot(DescriptorToDot(tmp_buf)); fprintf(out_file_, "<parameter name=\"arg%d\" type=\"%s\">\n" "</parameter>\n", arg_num++, dot.c_str()); } // while @@ -1309,7 +1286,7 @@ void DexLayout::DumpSField(uint32_t idx, uint32_t flags, int i, dex_ir::EncodedV } } else if (options_.output_format_ == kOutputXml) { fprintf(out_file_, "<field name=\"%s\"\n", name); - std::string dot(DescriptorToDotWrapper(type_descriptor)); + std::string dot(DescriptorToDot(type_descriptor)); fprintf(out_file_, " type=\"%s\"\n", dot.c_str()); fprintf(out_file_, " transient=%s\n", QuotedBool((flags & kAccTransient) != 0)); fprintf(out_file_, " volatile=%s\n", QuotedBool((flags & kAccVolatile) != 0)); @@ -1415,10 +1392,10 @@ void DexLayout::DumpClass(int idx, char** last_package) { } fprintf(out_file_, " Interfaces -\n"); } else { - std::string dot(DescriptorClassToDot(class_descriptor)); + std::string dot(DescriptorClassToName(class_descriptor)); fprintf(out_file_, "<class name=\"%s\"\n", dot.c_str()); if (superclass_descriptor != nullptr) { - dot = DescriptorToDotWrapper(superclass_descriptor); + dot = DescriptorToDot(superclass_descriptor); fprintf(out_file_, " extends=\"%s\"\n", dot.c_str()); } fprintf(out_file_, " interface=%s\n", diff --git a/runtime/gc/collector/concurrent_copying.cc b/runtime/gc/collector/concurrent_copying.cc index fdd0b62d3e..c7a5f79cb2 100644 --- a/runtime/gc/collector/concurrent_copying.cc +++ b/runtime/gc/collector/concurrent_copying.cc @@ -2152,7 +2152,7 @@ void ConcurrentCopying::AssertToSpaceInvariant(mirror::Object* obj, LOG(FATAL_WITHOUT_ABORT) << "Non-free regions:"; region_space_->DumpNonFreeRegions(LOG_STREAM(FATAL_WITHOUT_ABORT)); PrintFileToLog("/proc/self/maps", LogSeverity::FATAL_WITHOUT_ABORT); - MemMap::DumpMaps(LOG_STREAM(FATAL_WITHOUT_ABORT), true); + MemMap::DumpMaps(LOG_STREAM(FATAL_WITHOUT_ABORT), /* terse */ true); LOG(FATAL) << "Invalid reference " << ref << " referenced from object " << obj << " at offset " << offset; } @@ -2245,7 +2245,7 @@ void ConcurrentCopying::AssertToSpaceInvariant(GcRootSource* gc_root_source, LOG(FATAL_WITHOUT_ABORT) << "Non-free regions:"; region_space_->DumpNonFreeRegions(LOG_STREAM(FATAL_WITHOUT_ABORT)); PrintFileToLog("/proc/self/maps", LogSeverity::FATAL_WITHOUT_ABORT); - MemMap::DumpMaps(LOG_STREAM(FATAL_WITHOUT_ABORT), true); + MemMap::DumpMaps(LOG_STREAM(FATAL_WITHOUT_ABORT), /* terse */ true); LOG(FATAL) << "Invalid reference " << ref; } } else { diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc index 997d3b6f87..58a75ee189 100644 --- a/runtime/gc/collector/mark_sweep.cc +++ b/runtime/gc/collector/mark_sweep.cc @@ -446,7 +446,7 @@ class MarkSweep::MarkObjectSlowPath { !large_object_space->Contains(obj)))) { // Lowest priority logging first: PrintFileToLog("/proc/self/maps", LogSeverity::FATAL_WITHOUT_ABORT); - MemMap::DumpMaps(LOG_STREAM(FATAL_WITHOUT_ABORT), true); + MemMap::DumpMaps(LOG_STREAM(FATAL_WITHOUT_ABORT), /* terse */ true); // Buffer the output in the string stream since it is more important than the stack traces // and we want it to have log priority. The stack traces are printed from Runtime::Abort // which is called from LOG(FATAL) but before the abort message. diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc index 7913354433..bf06cf9758 100644 --- a/runtime/gc/heap.cc +++ b/runtime/gc/heap.cc @@ -642,7 +642,7 @@ Heap::Heap(size_t initial_size, bool no_gap = MemMap::CheckNoGaps(*first_space->GetMemMap(), *non_moving_space_->GetMemMap()); if (!no_gap) { PrintFileToLog("/proc/self/maps", LogSeverity::ERROR); - MemMap::DumpMaps(LOG_STREAM(ERROR), true); + MemMap::DumpMaps(LOG_STREAM(ERROR), /* terse */ true); LOG(FATAL) << "There's a gap between the image space and the non-moving space"; } } diff --git a/runtime/gc/verification.cc b/runtime/gc/verification.cc index fb5db1147f..d6a2fa0cb5 100644 --- a/runtime/gc/verification.cc +++ b/runtime/gc/verification.cc @@ -87,7 +87,7 @@ void Verification::LogHeapCorruption(ObjPtr<mirror::Object> holder, bool fatal) const { // Lowest priority logging first: PrintFileToLog("/proc/self/maps", android::base::LogSeverity::FATAL_WITHOUT_ABORT); - MemMap::DumpMaps(LOG_STREAM(FATAL_WITHOUT_ABORT), true); + MemMap::DumpMaps(LOG_STREAM(FATAL_WITHOUT_ABORT), /* terse */ true); // Buffer the output in the string stream since it is more important than the stack traces // and we want it to have log priority. The stack traces are printed from Runtime::Abort // which is called from LOG(FATAL) but before the abort message. diff --git a/runtime/interpreter/mterp/arm/instruction_end.S b/runtime/interpreter/mterp/arm/instruction_end.S index 32c725c7d9..f90ebd0221 100644 --- a/runtime/interpreter/mterp/arm/instruction_end.S +++ b/runtime/interpreter/mterp/arm/instruction_end.S @@ -1,3 +1,5 @@ + .type artMterpAsmInstructionEnd, #object + .hidden artMterpAsmInstructionEnd .global artMterpAsmInstructionEnd artMterpAsmInstructionEnd: diff --git a/runtime/interpreter/mterp/arm/instruction_end_alt.S b/runtime/interpreter/mterp/arm/instruction_end_alt.S index f90916fc02..0b66dbb947 100644 --- a/runtime/interpreter/mterp/arm/instruction_end_alt.S +++ b/runtime/interpreter/mterp/arm/instruction_end_alt.S @@ -1,3 +1,5 @@ + .type artMterpAsmAltInstructionEnd, #object + .hidden artMterpAsmAltInstructionEnd .global artMterpAsmAltInstructionEnd artMterpAsmAltInstructionEnd: diff --git a/runtime/interpreter/mterp/arm/instruction_end_sister.S b/runtime/interpreter/mterp/arm/instruction_end_sister.S index c5f4886697..71c0300f6d 100644 --- a/runtime/interpreter/mterp/arm/instruction_end_sister.S +++ b/runtime/interpreter/mterp/arm/instruction_end_sister.S @@ -1,3 +1,5 @@ + .type artMterpAsmSisterEnd, #object + .hidden artMterpAsmSisterEnd .global artMterpAsmSisterEnd artMterpAsmSisterEnd: diff --git a/runtime/interpreter/mterp/arm/instruction_start.S b/runtime/interpreter/mterp/arm/instruction_start.S index 8874c20540..b7e9cf51e4 100644 --- a/runtime/interpreter/mterp/arm/instruction_start.S +++ b/runtime/interpreter/mterp/arm/instruction_start.S @@ -1,4 +1,6 @@ + .type artMterpAsmInstructionStart, #object + .hidden artMterpAsmInstructionStart .global artMterpAsmInstructionStart artMterpAsmInstructionStart = .L_op_nop .text diff --git a/runtime/interpreter/mterp/arm/instruction_start_alt.S b/runtime/interpreter/mterp/arm/instruction_start_alt.S index 0c9ffdb7d6..7a67ba064c 100644 --- a/runtime/interpreter/mterp/arm/instruction_start_alt.S +++ b/runtime/interpreter/mterp/arm/instruction_start_alt.S @@ -1,4 +1,6 @@ + .type artMterpAsmAltInstructionStart, #object + .hidden artMterpAsmAltInstructionStart .global artMterpAsmAltInstructionStart artMterpAsmAltInstructionStart = .L_ALT_op_nop .text diff --git a/runtime/interpreter/mterp/arm/instruction_start_sister.S b/runtime/interpreter/mterp/arm/instruction_start_sister.S index 2ec51f7261..0036061605 100644 --- a/runtime/interpreter/mterp/arm/instruction_start_sister.S +++ b/runtime/interpreter/mterp/arm/instruction_start_sister.S @@ -1,4 +1,6 @@ + .type artMterpAsmSisterStart, #object + .hidden artMterpAsmSisterStart .global artMterpAsmSisterStart .text .balign 4 diff --git a/runtime/interpreter/mterp/arm64/instruction_end.S b/runtime/interpreter/mterp/arm64/instruction_end.S index 32c725c7d9..f90ebd0221 100644 --- a/runtime/interpreter/mterp/arm64/instruction_end.S +++ b/runtime/interpreter/mterp/arm64/instruction_end.S @@ -1,3 +1,5 @@ + .type artMterpAsmInstructionEnd, #object + .hidden artMterpAsmInstructionEnd .global artMterpAsmInstructionEnd artMterpAsmInstructionEnd: diff --git a/runtime/interpreter/mterp/arm64/instruction_end_alt.S b/runtime/interpreter/mterp/arm64/instruction_end_alt.S index f90916fc02..0b66dbb947 100644 --- a/runtime/interpreter/mterp/arm64/instruction_end_alt.S +++ b/runtime/interpreter/mterp/arm64/instruction_end_alt.S @@ -1,3 +1,5 @@ + .type artMterpAsmAltInstructionEnd, #object + .hidden artMterpAsmAltInstructionEnd .global artMterpAsmAltInstructionEnd artMterpAsmAltInstructionEnd: diff --git a/runtime/interpreter/mterp/arm64/instruction_end_sister.S b/runtime/interpreter/mterp/arm64/instruction_end_sister.S index c5f4886697..71c0300f6d 100644 --- a/runtime/interpreter/mterp/arm64/instruction_end_sister.S +++ b/runtime/interpreter/mterp/arm64/instruction_end_sister.S @@ -1,3 +1,5 @@ + .type artMterpAsmSisterEnd, #object + .hidden artMterpAsmSisterEnd .global artMterpAsmSisterEnd artMterpAsmSisterEnd: diff --git a/runtime/interpreter/mterp/arm64/instruction_start.S b/runtime/interpreter/mterp/arm64/instruction_start.S index 8874c20540..b7e9cf51e4 100644 --- a/runtime/interpreter/mterp/arm64/instruction_start.S +++ b/runtime/interpreter/mterp/arm64/instruction_start.S @@ -1,4 +1,6 @@ + .type artMterpAsmInstructionStart, #object + .hidden artMterpAsmInstructionStart .global artMterpAsmInstructionStart artMterpAsmInstructionStart = .L_op_nop .text diff --git a/runtime/interpreter/mterp/arm64/instruction_start_alt.S b/runtime/interpreter/mterp/arm64/instruction_start_alt.S index 0c9ffdb7d6..7a67ba064c 100644 --- a/runtime/interpreter/mterp/arm64/instruction_start_alt.S +++ b/runtime/interpreter/mterp/arm64/instruction_start_alt.S @@ -1,4 +1,6 @@ + .type artMterpAsmAltInstructionStart, #object + .hidden artMterpAsmAltInstructionStart .global artMterpAsmAltInstructionStart artMterpAsmAltInstructionStart = .L_ALT_op_nop .text diff --git a/runtime/interpreter/mterp/arm64/instruction_start_sister.S b/runtime/interpreter/mterp/arm64/instruction_start_sister.S index 2ec51f7261..0036061605 100644 --- a/runtime/interpreter/mterp/arm64/instruction_start_sister.S +++ b/runtime/interpreter/mterp/arm64/instruction_start_sister.S @@ -1,4 +1,6 @@ + .type artMterpAsmSisterStart, #object + .hidden artMterpAsmSisterStart .global artMterpAsmSisterStart .text .balign 4 diff --git a/runtime/interpreter/mterp/out/mterp_arm.S b/runtime/interpreter/mterp/out/mterp_arm.S index b73067f64a..394a84924c 100644 --- a/runtime/interpreter/mterp/out/mterp_arm.S +++ b/runtime/interpreter/mterp/out/mterp_arm.S @@ -398,6 +398,8 @@ ENTRY ExecuteMterpImpl /* File: arm/instruction_start.S */ + .type artMterpAsmInstructionStart, #object + .hidden artMterpAsmInstructionStart .global artMterpAsmInstructionStart artMterpAsmInstructionStart = .L_op_nop .text @@ -7513,6 +7515,8 @@ constvalop_long_to_double: .balign 128 /* File: arm/instruction_end.S */ + .type artMterpAsmInstructionEnd, #object + .hidden artMterpAsmInstructionEnd .global artMterpAsmInstructionEnd artMterpAsmInstructionEnd: @@ -7524,6 +7528,8 @@ artMterpAsmInstructionEnd: */ /* File: arm/instruction_start_sister.S */ + .type artMterpAsmSisterStart, #object + .hidden artMterpAsmSisterStart .global artMterpAsmSisterStart .text .balign 4 @@ -7593,11 +7599,15 @@ d2l_maybeNaN: bx lr @ return 0 for NaN /* File: arm/instruction_end_sister.S */ + .type artMterpAsmSisterEnd, #object + .hidden artMterpAsmSisterEnd .global artMterpAsmSisterEnd artMterpAsmSisterEnd: /* File: arm/instruction_start_alt.S */ + .type artMterpAsmAltInstructionStart, #object + .hidden artMterpAsmAltInstructionStart .global artMterpAsmAltInstructionStart artMterpAsmAltInstructionStart = .L_ALT_op_nop .text @@ -12213,6 +12223,8 @@ artMterpAsmAltInstructionStart = .L_ALT_op_nop .balign 128 /* File: arm/instruction_end_alt.S */ + .type artMterpAsmAltInstructionEnd, #object + .hidden artMterpAsmAltInstructionEnd .global artMterpAsmAltInstructionEnd artMterpAsmAltInstructionEnd: diff --git a/runtime/interpreter/mterp/out/mterp_arm64.S b/runtime/interpreter/mterp/out/mterp_arm64.S index 770b109f41..5f4aa4f256 100644 --- a/runtime/interpreter/mterp/out/mterp_arm64.S +++ b/runtime/interpreter/mterp/out/mterp_arm64.S @@ -429,6 +429,8 @@ ENTRY ExecuteMterpImpl /* File: arm64/instruction_start.S */ + .type artMterpAsmInstructionStart, #object + .hidden artMterpAsmInstructionStart .global artMterpAsmInstructionStart artMterpAsmInstructionStart = .L_op_nop .text @@ -7078,6 +7080,8 @@ artMterpAsmInstructionStart = .L_op_nop .balign 128 /* File: arm64/instruction_end.S */ + .type artMterpAsmInstructionEnd, #object + .hidden artMterpAsmInstructionEnd .global artMterpAsmInstructionEnd artMterpAsmInstructionEnd: @@ -7089,6 +7093,8 @@ artMterpAsmInstructionEnd: */ /* File: arm64/instruction_start_sister.S */ + .type artMterpAsmSisterStart, #object + .hidden artMterpAsmSisterStart .global artMterpAsmSisterStart .text .balign 4 @@ -7096,6 +7102,8 @@ artMterpAsmSisterStart: /* File: arm64/instruction_end_sister.S */ + .type artMterpAsmSisterEnd, #object + .hidden artMterpAsmSisterEnd .global artMterpAsmSisterEnd artMterpAsmSisterEnd: @@ -7409,6 +7417,8 @@ MterpProfileActive: /* File: arm64/instruction_start_alt.S */ + .type artMterpAsmAltInstructionStart, #object + .hidden artMterpAsmAltInstructionStart .global artMterpAsmAltInstructionStart artMterpAsmAltInstructionStart = .L_ALT_op_nop .text @@ -11768,6 +11778,8 @@ artMterpAsmAltInstructionStart = .L_ALT_op_nop .balign 128 /* File: arm64/instruction_end_alt.S */ + .type artMterpAsmAltInstructionEnd, #object + .hidden artMterpAsmAltInstructionEnd .global artMterpAsmAltInstructionEnd artMterpAsmAltInstructionEnd: diff --git a/runtime/interpreter/mterp/out/mterp_x86.S b/runtime/interpreter/mterp/out/mterp_x86.S index c78eb4942a..3f709199b9 100644 --- a/runtime/interpreter/mterp/out/mterp_x86.S +++ b/runtime/interpreter/mterp/out/mterp_x86.S @@ -103,6 +103,7 @@ unspecified registers or condition codes. #if defined(__APPLE__) #define MACRO_LITERAL(value) $(value) #define FUNCTION_TYPE(name) + #define OBJECT_TYPE(name) #define SIZE(start,end) // Mac OS' symbols have an _ prefix. #define SYMBOL(name) _ ## name @@ -110,6 +111,7 @@ unspecified registers or condition codes. #else #define MACRO_LITERAL(value) $value #define FUNCTION_TYPE(name) .type name, @function + #define OBJECT_TYPE(name) .type name, @object #define SIZE(start,end) .size start, .-end #define SYMBOL(name) name #define ASM_HIDDEN .hidden @@ -407,6 +409,8 @@ SYMBOL(ExecuteMterpImpl): /* File: x86/instruction_start.S */ + OBJECT_TYPE(artMterpAsmInstructionStart) + ASM_HIDDEN SYMBOL(artMterpAsmInstructionStart) .global SYMBOL(artMterpAsmInstructionStart) SYMBOL(artMterpAsmInstructionStart) = .L_op_nop .text @@ -6473,6 +6477,8 @@ SYMBOL(artMterpAsmInstructionStart) = .L_op_nop .balign 128 /* File: x86/instruction_end.S */ + OBJECT_TYPE(artMterpAsmInstructionEnd) + ASM_HIDDEN SYMBOL(artMterpAsmInstructionEnd) .global SYMBOL(artMterpAsmInstructionEnd) SYMBOL(artMterpAsmInstructionEnd): @@ -6484,6 +6490,8 @@ SYMBOL(artMterpAsmInstructionEnd): */ /* File: x86/instruction_start_sister.S */ + OBJECT_TYPE(artMterpAsmSisterStart) + ASM_HIDDEN SYMBOL(artMterpAsmSisterStart) .global SYMBOL(artMterpAsmSisterStart) .text .balign 4 @@ -6491,11 +6499,15 @@ SYMBOL(artMterpAsmSisterStart): /* File: x86/instruction_end_sister.S */ + OBJECT_TYPE(artMterpAsmSisterEnd) + ASM_HIDDEN SYMBOL(artMterpAsmSisterEnd) .global SYMBOL(artMterpAsmSisterEnd) SYMBOL(artMterpAsmSisterEnd): /* File: x86/instruction_start_alt.S */ + OBJECT_TYPE(artMterpAsmAltInstructionStart) + ASM_HIDDEN SYMBOL(artMterpAsmAltInstructionStart) .global SYMBOL(artMterpAsmAltInstructionStart) .text SYMBOL(artMterpAsmAltInstructionStart) = .L_ALT_op_nop @@ -12647,6 +12659,8 @@ SYMBOL(artMterpAsmAltInstructionStart) = .L_ALT_op_nop .balign 128 /* File: x86/instruction_end_alt.S */ + OBJECT_TYPE(artMterpAsmAltInstructionEnd) + ASM_HIDDEN SYMBOL(artMterpAsmAltInstructionEnd) .global SYMBOL(artMterpAsmAltInstructionEnd) SYMBOL(artMterpAsmAltInstructionEnd): diff --git a/runtime/interpreter/mterp/out/mterp_x86_64.S b/runtime/interpreter/mterp/out/mterp_x86_64.S index 524dce412e..89d56372af 100644 --- a/runtime/interpreter/mterp/out/mterp_x86_64.S +++ b/runtime/interpreter/mterp/out/mterp_x86_64.S @@ -99,6 +99,7 @@ unspecified registers or condition codes. #if defined(__APPLE__) #define MACRO_LITERAL(value) $(value) #define FUNCTION_TYPE(name) + #define OBJECT_TYPE(name) #define SIZE(start,end) // Mac OS' symbols have an _ prefix. #define SYMBOL(name) _ ## name @@ -106,6 +107,7 @@ unspecified registers or condition codes. #else #define MACRO_LITERAL(value) $value #define FUNCTION_TYPE(name) .type name, @function + #define OBJECT_TYPE(name) .type name, @object #define SIZE(start,end) .size start, .-end #define SYMBOL(name) name #define ASM_HIDDEN .hidden @@ -389,6 +391,8 @@ SYMBOL(ExecuteMterpImpl): /* File: x86_64/instruction_start.S */ + OBJECT_TYPE(artMterpAsmInstructionStart) + ASM_HIDDEN SYMBOL(artMterpAsmInstructionStart) .global SYMBOL(artMterpAsmInstructionStart) SYMBOL(artMterpAsmInstructionStart) = .L_op_nop .text @@ -6220,6 +6224,8 @@ movswl %ax, %eax .balign 128 /* File: x86_64/instruction_end.S */ + OBJECT_TYPE(artMterpAsmInstructionEnd) + ASM_HIDDEN SYMBOL(artMterpAsmInstructionEnd) .global SYMBOL(artMterpAsmInstructionEnd) SYMBOL(artMterpAsmInstructionEnd): @@ -6231,6 +6237,8 @@ SYMBOL(artMterpAsmInstructionEnd): */ /* File: x86_64/instruction_start_sister.S */ + OBJECT_TYPE(artMterpAsmSisterStart) + ASM_HIDDEN SYMBOL(artMterpAsmSisterStart) .global SYMBOL(artMterpAsmSisterStart) .text .balign 4 @@ -6238,11 +6246,15 @@ SYMBOL(artMterpAsmSisterStart): /* File: x86_64/instruction_end_sister.S */ + OBJECT_TYPE(artMterpAsmSisterEnd) + ASM_HIDDEN SYMBOL(artMterpAsmSisterEnd) .global SYMBOL(artMterpAsmSisterEnd) SYMBOL(artMterpAsmSisterEnd): /* File: x86_64/instruction_start_alt.S */ + OBJECT_TYPE(artMterpAsmAltInstructionStart) + ASM_HIDDEN SYMBOL(artMterpAsmAltInstructionStart) .global SYMBOL(artMterpAsmAltInstructionStart) .text SYMBOL(artMterpAsmAltInstructionStart) = .L_ALT_op_nop @@ -11882,6 +11894,8 @@ SYMBOL(artMterpAsmAltInstructionStart) = .L_ALT_op_nop .balign 128 /* File: x86_64/instruction_end_alt.S */ + OBJECT_TYPE(artMterpAsmAltInstructionEnd) + ASM_HIDDEN SYMBOL(artMterpAsmAltInstructionEnd) .global SYMBOL(artMterpAsmAltInstructionEnd) SYMBOL(artMterpAsmAltInstructionEnd): diff --git a/runtime/interpreter/mterp/x86/header.S b/runtime/interpreter/mterp/x86/header.S index 6f31228005..a79db27abf 100644 --- a/runtime/interpreter/mterp/x86/header.S +++ b/runtime/interpreter/mterp/x86/header.S @@ -96,6 +96,7 @@ unspecified registers or condition codes. #if defined(__APPLE__) #define MACRO_LITERAL(value) $$(value) #define FUNCTION_TYPE(name) + #define OBJECT_TYPE(name) #define SIZE(start,end) // Mac OS' symbols have an _ prefix. #define SYMBOL(name) _ ## name @@ -103,6 +104,7 @@ unspecified registers or condition codes. #else #define MACRO_LITERAL(value) $$value #define FUNCTION_TYPE(name) .type name, @function + #define OBJECT_TYPE(name) .type name, @object #define SIZE(start,end) .size start, .-end #define SYMBOL(name) name #define ASM_HIDDEN .hidden diff --git a/runtime/interpreter/mterp/x86/instruction_end.S b/runtime/interpreter/mterp/x86/instruction_end.S index 3a02a212e6..94587f83b7 100644 --- a/runtime/interpreter/mterp/x86/instruction_end.S +++ b/runtime/interpreter/mterp/x86/instruction_end.S @@ -1,3 +1,5 @@ + OBJECT_TYPE(artMterpAsmInstructionEnd) + ASM_HIDDEN SYMBOL(artMterpAsmInstructionEnd) .global SYMBOL(artMterpAsmInstructionEnd) SYMBOL(artMterpAsmInstructionEnd): diff --git a/runtime/interpreter/mterp/x86/instruction_end_alt.S b/runtime/interpreter/mterp/x86/instruction_end_alt.S index 33c2b8e2a0..7757bce9a7 100644 --- a/runtime/interpreter/mterp/x86/instruction_end_alt.S +++ b/runtime/interpreter/mterp/x86/instruction_end_alt.S @@ -1,3 +1,5 @@ + OBJECT_TYPE(artMterpAsmAltInstructionEnd) + ASM_HIDDEN SYMBOL(artMterpAsmAltInstructionEnd) .global SYMBOL(artMterpAsmAltInstructionEnd) SYMBOL(artMterpAsmAltInstructionEnd): diff --git a/runtime/interpreter/mterp/x86/instruction_end_sister.S b/runtime/interpreter/mterp/x86/instruction_end_sister.S index ea14b11ede..8eb79accdf 100644 --- a/runtime/interpreter/mterp/x86/instruction_end_sister.S +++ b/runtime/interpreter/mterp/x86/instruction_end_sister.S @@ -1,3 +1,5 @@ + OBJECT_TYPE(artMterpAsmSisterEnd) + ASM_HIDDEN SYMBOL(artMterpAsmSisterEnd) .global SYMBOL(artMterpAsmSisterEnd) SYMBOL(artMterpAsmSisterEnd): diff --git a/runtime/interpreter/mterp/x86/instruction_start.S b/runtime/interpreter/mterp/x86/instruction_start.S index ca711de00c..5d29a81993 100644 --- a/runtime/interpreter/mterp/x86/instruction_start.S +++ b/runtime/interpreter/mterp/x86/instruction_start.S @@ -1,4 +1,6 @@ + OBJECT_TYPE(artMterpAsmInstructionStart) + ASM_HIDDEN SYMBOL(artMterpAsmInstructionStart) .global SYMBOL(artMterpAsmInstructionStart) SYMBOL(artMterpAsmInstructionStart) = .L_op_nop .text diff --git a/runtime/interpreter/mterp/x86/instruction_start_alt.S b/runtime/interpreter/mterp/x86/instruction_start_alt.S index 9272a6a7b0..8dcf5bfaf9 100644 --- a/runtime/interpreter/mterp/x86/instruction_start_alt.S +++ b/runtime/interpreter/mterp/x86/instruction_start_alt.S @@ -1,4 +1,6 @@ + OBJECT_TYPE(artMterpAsmAltInstructionStart) + ASM_HIDDEN SYMBOL(artMterpAsmAltInstructionStart) .global SYMBOL(artMterpAsmAltInstructionStart) .text SYMBOL(artMterpAsmAltInstructionStart) = .L_ALT_op_nop diff --git a/runtime/interpreter/mterp/x86/instruction_start_sister.S b/runtime/interpreter/mterp/x86/instruction_start_sister.S index b9ac994d32..796e98b09a 100644 --- a/runtime/interpreter/mterp/x86/instruction_start_sister.S +++ b/runtime/interpreter/mterp/x86/instruction_start_sister.S @@ -1,4 +1,6 @@ + OBJECT_TYPE(artMterpAsmSisterStart) + ASM_HIDDEN SYMBOL(artMterpAsmSisterStart) .global SYMBOL(artMterpAsmSisterStart) .text .balign 4 diff --git a/runtime/interpreter/mterp/x86_64/header.S b/runtime/interpreter/mterp/x86_64/header.S index 4ebe95e987..0332ce272c 100644 --- a/runtime/interpreter/mterp/x86_64/header.S +++ b/runtime/interpreter/mterp/x86_64/header.S @@ -92,6 +92,7 @@ unspecified registers or condition codes. #if defined(__APPLE__) #define MACRO_LITERAL(value) $$(value) #define FUNCTION_TYPE(name) + #define OBJECT_TYPE(name) #define SIZE(start,end) // Mac OS' symbols have an _ prefix. #define SYMBOL(name) _ ## name @@ -99,6 +100,7 @@ unspecified registers or condition codes. #else #define MACRO_LITERAL(value) $$value #define FUNCTION_TYPE(name) .type name, @function + #define OBJECT_TYPE(name) .type name, @object #define SIZE(start,end) .size start, .-end #define SYMBOL(name) name #define ASM_HIDDEN .hidden diff --git a/runtime/interpreter/mterp/x86_64/instruction_end.S b/runtime/interpreter/mterp/x86_64/instruction_end.S index 3a02a212e6..94587f83b7 100644 --- a/runtime/interpreter/mterp/x86_64/instruction_end.S +++ b/runtime/interpreter/mterp/x86_64/instruction_end.S @@ -1,3 +1,5 @@ + OBJECT_TYPE(artMterpAsmInstructionEnd) + ASM_HIDDEN SYMBOL(artMterpAsmInstructionEnd) .global SYMBOL(artMterpAsmInstructionEnd) SYMBOL(artMterpAsmInstructionEnd): diff --git a/runtime/interpreter/mterp/x86_64/instruction_end_alt.S b/runtime/interpreter/mterp/x86_64/instruction_end_alt.S index 33c2b8e2a0..7757bce9a7 100644 --- a/runtime/interpreter/mterp/x86_64/instruction_end_alt.S +++ b/runtime/interpreter/mterp/x86_64/instruction_end_alt.S @@ -1,3 +1,5 @@ + OBJECT_TYPE(artMterpAsmAltInstructionEnd) + ASM_HIDDEN SYMBOL(artMterpAsmAltInstructionEnd) .global SYMBOL(artMterpAsmAltInstructionEnd) SYMBOL(artMterpAsmAltInstructionEnd): diff --git a/runtime/interpreter/mterp/x86_64/instruction_end_sister.S b/runtime/interpreter/mterp/x86_64/instruction_end_sister.S index ea14b11ede..8eb79accdf 100644 --- a/runtime/interpreter/mterp/x86_64/instruction_end_sister.S +++ b/runtime/interpreter/mterp/x86_64/instruction_end_sister.S @@ -1,3 +1,5 @@ + OBJECT_TYPE(artMterpAsmSisterEnd) + ASM_HIDDEN SYMBOL(artMterpAsmSisterEnd) .global SYMBOL(artMterpAsmSisterEnd) SYMBOL(artMterpAsmSisterEnd): diff --git a/runtime/interpreter/mterp/x86_64/instruction_start.S b/runtime/interpreter/mterp/x86_64/instruction_start.S index ca711de00c..5d29a81993 100644 --- a/runtime/interpreter/mterp/x86_64/instruction_start.S +++ b/runtime/interpreter/mterp/x86_64/instruction_start.S @@ -1,4 +1,6 @@ + OBJECT_TYPE(artMterpAsmInstructionStart) + ASM_HIDDEN SYMBOL(artMterpAsmInstructionStart) .global SYMBOL(artMterpAsmInstructionStart) SYMBOL(artMterpAsmInstructionStart) = .L_op_nop .text diff --git a/runtime/interpreter/mterp/x86_64/instruction_start_alt.S b/runtime/interpreter/mterp/x86_64/instruction_start_alt.S index 9272a6a7b0..8dcf5bfaf9 100644 --- a/runtime/interpreter/mterp/x86_64/instruction_start_alt.S +++ b/runtime/interpreter/mterp/x86_64/instruction_start_alt.S @@ -1,4 +1,6 @@ + OBJECT_TYPE(artMterpAsmAltInstructionStart) + ASM_HIDDEN SYMBOL(artMterpAsmAltInstructionStart) .global SYMBOL(artMterpAsmAltInstructionStart) .text SYMBOL(artMterpAsmAltInstructionStart) = .L_ALT_op_nop diff --git a/runtime/interpreter/mterp/x86_64/instruction_start_sister.S b/runtime/interpreter/mterp/x86_64/instruction_start_sister.S index b9ac994d32..796e98b09a 100644 --- a/runtime/interpreter/mterp/x86_64/instruction_start_sister.S +++ b/runtime/interpreter/mterp/x86_64/instruction_start_sister.S @@ -1,4 +1,6 @@ + OBJECT_TYPE(artMterpAsmSisterStart) + ASM_HIDDEN SYMBOL(artMterpAsmSisterStart) .global SYMBOL(artMterpAsmSisterStart) .text .balign 4 diff --git a/test/565-checker-condition-liveness/src/Main.java b/test/565-checker-condition-liveness/src/Main.java index 374e136885..25ec3f53b1 100644 --- a/test/565-checker-condition-liveness/src/Main.java +++ b/test/565-checker-condition-liveness/src/Main.java @@ -30,26 +30,52 @@ public class Main { public static int p(float arg) { return (arg > 5.0f) ? 0 : -1; } + + /// CHECK-START-{ARM,ARM64}: void Main.testThrowIntoCatchBlock(int, java.lang.Object, int[]) liveness (after) + /// CHECK-DAG: <<IntArg:i\d+>> ParameterValue env_uses:[23,25] + /// CHECK-DAG: <<RefArg:l\d+>> ParameterValue env_uses:[11,23,25] + /// CHECK-DAG: <<Array:l\d+>> ParameterValue env_uses:[11,23,25] + /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 env_uses:[23,25] + /// CHECK-DAG: SuspendCheck env:[[_,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:10 + /// CHECK-DAG: NullCheck env:[[<<Const1>>,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:20 + /// CHECK-DAG: ArrayLength liveness:22 + /// CHECK-DAG: BoundsCheck env:[[<<Const1>>,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:24 + /// CHECK-DAG: TryBoundary + + /// CHECK-START-{ARM,ARM64}-DEBUGGABLE: void Main.testThrowIntoCatchBlock(int, java.lang.Object, int[]) liveness (after) + /// CHECK-DAG: <<IntArg:i\d+>> ParameterValue env_uses:[11,23,25] + /// CHECK-DAG: <<RefArg:l\d+>> ParameterValue env_uses:[11,23,25] + /// CHECK-DAG: <<Array:l\d+>> ParameterValue env_uses:[11,23,25] + /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 env_uses:[23,25] + /// CHECK-DAG: SuspendCheck env:[[_,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:10 + /// CHECK-DAG: NullCheck env:[[<<Const1>>,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:20 + /// CHECK-DAG: ArrayLength liveness:22 + /// CHECK-DAG: BoundsCheck env:[[<<Const1>>,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:24 + /// CHECK-DAG: TryBoundary - /// CHECK-START: void Main.testThrowIntoCatchBlock(int, java.lang.Object, int[]) liveness (after) + // X86 and X86_64 generate at use site the ArrayLength, meaning only the BoundsCheck will have environment uses. + /// CHECK-START-{X86,X86_64}: void Main.testThrowIntoCatchBlock(int, java.lang.Object, int[]) liveness (after) /// CHECK-DAG: <<IntArg:i\d+>> ParameterValue env_uses:[25] /// CHECK-DAG: <<RefArg:l\d+>> ParameterValue env_uses:[11,25] /// CHECK-DAG: <<Array:l\d+>> ParameterValue env_uses:[11,25] /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 env_uses:[25] /// CHECK-DAG: SuspendCheck env:[[_,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:10 /// CHECK-DAG: NullCheck env:[[<<Const1>>,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:20 + /// CHECK-DAG: ArrayLength liveness:22 /// CHECK-DAG: BoundsCheck env:[[<<Const1>>,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:24 /// CHECK-DAG: TryBoundary - /// CHECK-START-DEBUGGABLE: void Main.testThrowIntoCatchBlock(int, java.lang.Object, int[]) liveness (after) + /// CHECK-START-{X86,X86_64}-DEBUGGABLE: void Main.testThrowIntoCatchBlock(int, java.lang.Object, int[]) liveness (after) /// CHECK-DAG: <<IntArg:i\d+>> ParameterValue env_uses:[11,25] /// CHECK-DAG: <<RefArg:l\d+>> ParameterValue env_uses:[11,25] /// CHECK-DAG: <<Array:l\d+>> ParameterValue env_uses:[11,25] /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 env_uses:[25] /// CHECK-DAG: SuspendCheck env:[[_,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:10 /// CHECK-DAG: NullCheck env:[[<<Const1>>,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:20 + /// CHECK-DAG: ArrayLength liveness:22 /// CHECK-DAG: BoundsCheck env:[[<<Const1>>,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:24 /// CHECK-DAG: TryBoundary + // // A value live at a throwing instruction in a try block may be copied by // the exception handler to its location at the top of the catch block. @@ -60,22 +86,44 @@ public class Main { } } - /// CHECK-START: void Main.testBoundsCheck(int, java.lang.Object, int[]) liveness (after) + /// CHECK-START-{ARM,ARM64}: void Main.testBoundsCheck(int, java.lang.Object, int[]) liveness (after) + /// CHECK-DAG: <<IntArg:i\d+>> ParameterValue env_uses:[] + /// CHECK-DAG: <<RefArg:l\d+>> ParameterValue env_uses:[11,19,21] + /// CHECK-DAG: <<Array:l\d+>> ParameterValue env_uses:[11,19,21] + /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 env_uses:[] + /// CHECK-DAG: SuspendCheck env:[[_,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:10 + /// CHECK-DAG: NullCheck env:[[<<Const1>>,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:16 + /// CHECK-DAG: ArrayLength liveness:18 + /// CHECK-DAG: BoundsCheck env:[[<<Const1>>,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:20 + + /// CHECK-START-{ARM,ARM64}-DEBUGGABLE: void Main.testBoundsCheck(int, java.lang.Object, int[]) liveness (after) + /// CHECK-DAG: <<IntArg:i\d+>> ParameterValue env_uses:[11,19,21] + /// CHECK-DAG: <<RefArg:l\d+>> ParameterValue env_uses:[11,19,21] + /// CHECK-DAG: <<Array:l\d+>> ParameterValue env_uses:[11,19,21] + /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 env_uses:[19,21] + /// CHECK-DAG: SuspendCheck env:[[_,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:10 + /// CHECK-DAG: NullCheck env:[[<<Const1>>,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:16 + /// CHECK-DAG: ArrayLength liveness:18 + /// CHECK-DAG: BoundsCheck env:[[<<Const1>>,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:20 + + /// CHECK-START-{X86,X86_64}: void Main.testBoundsCheck(int, java.lang.Object, int[]) liveness (after) /// CHECK-DAG: <<IntArg:i\d+>> ParameterValue env_uses:[] /// CHECK-DAG: <<RefArg:l\d+>> ParameterValue env_uses:[11,21] /// CHECK-DAG: <<Array:l\d+>> ParameterValue env_uses:[11,21] /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 env_uses:[] /// CHECK-DAG: SuspendCheck env:[[_,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:10 /// CHECK-DAG: NullCheck env:[[<<Const1>>,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:16 + /// CHECK-DAG: ArrayLength liveness:18 /// CHECK-DAG: BoundsCheck env:[[<<Const1>>,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:20 - /// CHECK-START-DEBUGGABLE: void Main.testBoundsCheck(int, java.lang.Object, int[]) liveness (after) + /// CHECK-START-{X86,X86_64}-DEBUGGABLE: void Main.testBoundsCheck(int, java.lang.Object, int[]) liveness (after) /// CHECK-DAG: <<IntArg:i\d+>> ParameterValue env_uses:[11,21] /// CHECK-DAG: <<RefArg:l\d+>> ParameterValue env_uses:[11,21] /// CHECK-DAG: <<Array:l\d+>> ParameterValue env_uses:[11,21] /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 env_uses:[21] /// CHECK-DAG: SuspendCheck env:[[_,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:10 /// CHECK-DAG: NullCheck env:[[<<Const1>>,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:16 + /// CHECK-DAG: ArrayLength liveness:18 /// CHECK-DAG: BoundsCheck env:[[<<Const1>>,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:20 public static void testBoundsCheck(int x, Object y, int[] a) { a[1] = x; @@ -90,12 +138,22 @@ public class Main { /// CHECK-DAG: NullCheck env:[[<<Const0>>,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:18 /// CHECK-DAG: ArrayLength liveness:20 /// CHECK-DAG: Deoptimize env:[[<<Const0>>,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:24 + + /// CHECK-START-{ARM,ARM64}-DEBUGGABLE: void Main.testDeoptimize(int, java.lang.Object, int[]) liveness (after) + /// CHECK-DAG: <<IntArg:i\d+>> ParameterValue env_uses:[13,21,25] + /// CHECK-DAG: <<RefArg:l\d+>> ParameterValue env_uses:[13,21,25] + /// CHECK-DAG: <<Array:l\d+>> ParameterValue env_uses:[13,21,25] + /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 env_uses:[21,25] + /// CHECK-DAG: SuspendCheck env:[[_,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:12 + /// CHECK-DAG: NullCheck env:[[<<Const0>>,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:18 + /// CHECK-DAG: ArrayLength liveness:20 + /// CHECK-DAG: Deoptimize env:[[<<Const0>>,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:24 - /// CHECK-START-DEBUGGABLE: void Main.testDeoptimize(int, java.lang.Object, int[]) liveness (after) + /// CHECK-START-{X86,X86_64}-DEBUGGABLE: void Main.testDeoptimize(int, java.lang.Object, int[]) liveness (after) /// CHECK-DAG: <<IntArg:i\d+>> ParameterValue env_uses:[13,21,25] /// CHECK-DAG: <<RefArg:l\d+>> ParameterValue env_uses:[13,21,25] /// CHECK-DAG: <<Array:l\d+>> ParameterValue env_uses:[13,21,25] - /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 env_uses:[19,25] + /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 env_uses:[21,25] /// CHECK-DAG: SuspendCheck env:[[_,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:12 /// CHECK-DAG: NullCheck env:[[<<Const0>>,<<IntArg>>,<<RefArg>>,<<Array>>]] liveness:18 /// CHECK-DAG: ArrayLength liveness:20 diff --git a/test/dexdump/bytecodes.txt b/test/dexdump/bytecodes.txt index e1a381ec09..1ed66e8a10 100644 --- a/test/dexdump/bytecodes.txt +++ b/test/dexdump/bytecodes.txt @@ -176,7 +176,7 @@ Class #3 - ins : 1 outs : 1 insns size : 4 16-bit code units -0009a8: |[0009a8] com.google.android.test.R.attr.<init>:()V +0009a8: |[0009a8] com.google.android.test.R$attr.<init>:()V 0009b8: 7010 1900 0000 |0000: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@0019 0009be: 0e00 |0003: return-void catches : (none) @@ -228,7 +228,7 @@ Class #4 - ins : 1 outs : 1 insns size : 4 16-bit code units -0009c0: |[0009c0] com.google.android.test.R.drawable.<init>:()V +0009c0: |[0009c0] com.google.android.test.R$drawable.<init>:()V 0009d0: 7010 1900 0000 |0000: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@0019 0009d6: 0e00 |0003: return-void catches : (none) diff --git a/test/dexdump/bytecodes.xml b/test/dexdump/bytecodes.xml index d08c2e929c..d4ee3a7eee 100755 --- a/test/dexdump/bytecodes.xml +++ b/test/dexdump/bytecodes.xml @@ -71,7 +71,7 @@ > </constructor> </class> -<class name="R.attr" +<class name="R$attr" extends="java.lang.Object" interface="false" abstract="false" @@ -79,15 +79,15 @@ final="true" visibility="public" > -<constructor name="R.attr" - type="com.google.android.test.R.attr" +<constructor name="R$attr" + type="com.google.android.test.R$attr" static="false" final="false" visibility="public" > </constructor> </class> -<class name="R.drawable" +<class name="R$drawable" extends="java.lang.Object" interface="false" abstract="false" @@ -105,8 +105,8 @@ value="2130837504" > </field> -<constructor name="R.drawable" - type="com.google.android.test.R.drawable" +<constructor name="R$drawable" + type="com.google.android.test.R$drawable" static="false" final="false" visibility="public" diff --git a/test/dexdump/checkers.xml b/test/dexdump/checkers.xml index 4e56ea2d66..3d3bac2d69 100755 --- a/test/dexdump/checkers.xml +++ b/test/dexdump/checkers.xml @@ -181,7 +181,7 @@ final="true" visibility="public" > -<parameter name="arg0" type="android.content.SharedPreferences.Editor"> +<parameter name="arg0" type="android.content.SharedPreferences$Editor"> </parameter> </method> <method name="a" diff --git a/test/dexdump/invoke-custom.txt b/test/dexdump/invoke-custom.txt index cfab248168..1bfa0532b2 100644 --- a/test/dexdump/invoke-custom.txt +++ b/test/dexdump/invoke-custom.txt @@ -58,7 +58,7 @@ Class #0 - ins : 2 outs : 2 insns size : 4 16-bit code units -001b18: |[001b18] TestBadBootstrapArguments.TestersConstantCallSite.<init>:(Ljava/lang/invoke/MethodHandle;)V +001b18: |[001b18] TestBadBootstrapArguments$TestersConstantCallSite.<init>:(Ljava/lang/invoke/MethodHandle;)V 001b28: 7020 d200 1000 |0000: invoke-direct {v0, v1}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2 001b2e: 0e00 |0003: return-void catches : (none) @@ -537,7 +537,7 @@ Class #2 - ins : 2 outs : 1 insns size : 4 16-bit code units -002abc: |[002abc] TestInvocationKinds.Widget.<init>:(I)V +002abc: |[002abc] TestInvocationKinds$Widget.<init>:(I)V 002acc: 7010 bf00 0000 |0000: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@00bf 002ad2: 0e00 |0003: return-void catches : (none) @@ -586,7 +586,7 @@ Class #3 - ins : 1 outs : 1 insns size : 4 16-bit code units -002ee8: |[002ee8] TestInvokeCustomWithConcurrentThreads.1.<init>:()V +002ee8: |[002ee8] TestInvokeCustomWithConcurrentThreads$1.<init>:()V 002ef8: 7010 cf00 0000 |0000: invoke-direct {v0}, Ljava/lang/ThreadLocal;.<init>:()V // method@00cf 002efe: 0e00 |0003: return-void catches : (none) @@ -605,7 +605,7 @@ Class #3 - ins : 1 outs : 1 insns size : 13 16-bit code units -002ea0: |[002ea0] TestInvokeCustomWithConcurrentThreads.1.initialValue:()Ljava/lang/Integer; +002ea0: |[002ea0] TestInvokeCustomWithConcurrentThreads$1.initialValue:()Ljava/lang/Integer; 002eb0: 7100 6500 0000 |0000: invoke-static {}, LTestInvokeCustomWithConcurrentThreads;.access$000:()Ljava/util/concurrent/atomic/AtomicInteger; // method@0065 002eb6: 0c00 |0003: move-result-object v0 002eb8: 6e10 f100 0000 |0004: invoke-virtual {v0}, Ljava/util/concurrent/atomic/AtomicInteger;.getAndIncrement:()I // method@00f1 @@ -628,7 +628,7 @@ Class #3 - ins : 1 outs : 1 insns size : 5 16-bit code units -002ecc: |[002ecc] TestInvokeCustomWithConcurrentThreads.1.initialValue:()Ljava/lang/Object; +002ecc: |[002ecc] TestInvokeCustomWithConcurrentThreads$1.initialValue:()Ljava/lang/Object; 002edc: 6e10 6100 0100 |0000: invoke-virtual {v1}, LTestInvokeCustomWithConcurrentThreads$1;.initialValue:()Ljava/lang/Integer; // method@0061 002ee2: 0c00 |0003: move-result-object v0 002ee4: 1100 |0004: return-object v0 @@ -16,28 +16,9 @@ # shell dialect that should work on the host (e.g. bash), and # Android (e.g. mksh). -# Globals -ART_BINARY=dalvikvm -DELETE_ANDROID_DATA="no" -LAUNCH_WRAPPER= -LIBART=libart.so -JIT_PROFILE="no" -ALLOW_DEFAULT_JDWP="no" -VERBOSE="no" -CLEAN_OAT_FILES="yes" -EXTRA_OPTIONS=() - -# Follow all sym links to get the program name. -if [ z"$BASH_SOURCE" != z ]; then - PROG_NAME="$BASH_SOURCE" -else - PROG_NAME="$0" -fi -while [ -h "$PROG_NAME" ]; do - # On Mac OS, readlink -f doesn't work. - PROG_NAME="$(readlink "$PROG_NAME")" -done - +###################################### +# Functions +###################################### function find_libdir() { # Get the actual file, $1 is the ART_BINARY_PATH and may be a symbolic link. # Use realpath instead of readlink because Android does not have a readlink. @@ -48,29 +29,6 @@ function find_libdir() { fi } -function replace_compiler_filter_with_quicken() { - ARGS_WITH_QUICKEN=("$@") - - found="false" - ((index=0)) - while ((index <= $#)); do - what="${ARGS_WITH_QUICKEN[$index]}" - - case "$what" in - --compiler-filter=*) - ARGS_WITH_QUICKEN[$index]="--compiler-filter=quicken" - found="true" - ;; - esac - - ((index++)) - shift - done - if [ "$found" != "true" ]; then - ARGS_WITH_QUICKEN=(-Xcompiler-option --compiler-filter=quicken "${ARGS_WITH_QUICKEN[@]}") - fi -} - function usage() { cat 1>&2 <<EOF Usage: art [OPTIONS] [--] [ART_OPTIONS] CLASS @@ -224,19 +182,81 @@ function detect_boot_image_location() { echo "$image_location" } -# If android logging is not explicitly set, only print warnings and errors. -if [ -z "$ANDROID_LOG_TAGS" ]; then - ANDROID_LOG_TAGS='*:w' -fi +function run_dex2oat() { + CLASS_LOADER_CONTEXT= + for dex_file in "${DEX2OAT_CLASSPATH[@]}" + do + while [ -h "$dex_file" ]; do + # On Mac OS, readlink -f doesn't work. + dex_file="$(readlink "$dex_file")" + done + # Create oat file directory. + verbose_run mkdir -p $(dirname "$dex_file")/oat/$ISA + local oat_file=$(basename "$dex_file") + local oat_file=$(dirname "$dex_file")/oat/$ISA/${oat_file%.*}.odex + # When running dex2oat use the exact same context as when running dalvikvm. + # (see run_art function) + verbose_run ANDROID_DATA=$ANDROID_DATA \ + ANDROID_ROOT=$ANDROID_ROOT \ + LD_LIBRARY_PATH=$LD_LIBRARY_PATH \ + PATH=$ANDROID_ROOT/bin:$PATH \ + LD_USE_LOAD_BIAS=1 \ + ANDROID_LOG_TAGS=$ANDROID_LOG_TAGS \ + $DEX2OAT_BINARY_PATH \ + --runtime-arg -Xnorelocate \ + --boot-image=$DEX2OAT_BOOT_IMAGE \ + --instruction-set=$ISA \ + --class-loader-context="PCL[$CLASS_LOADER_CONTEXT]" \ + "${DEX2OAT_FLAGS[@]}" \ + --dex-file=$dex_file \ + --oat-file=$oat_file + if [[ ! -z $CLASS_LOADER_CONTEXT ]]; then + CLASS_LOADER_CONTEXT+=":" + fi + CLASS_LOADER_CONTEXT+="$dex_file" + done +} + +# Extract the dex2oat flags from the list of arguments. +# -Xcompiler-options arguments are stored in DEX2OAT_FLAGS array +# -cp argument is split by ':' and stored in DEX2OAT_CLASSPATH +# -Ximage argument is stored in DEX2OAT_BOOT_IMAGE +function extract_dex2oat_flags() { + while [ $# -gt 0 ]; do + case $1 in + -Xcompiler-option) + DEX2OAT_FLAGS+=("$2") + shift + ;; + -Ximage:*) + DEX2OAT_BOOT_IMAGE=$1 + # Remove '-Ximage:' from the argument. + DEX2OAT_BOOT_IMAGE=${DEX2OAT_BOOT_IMAGE##-Ximage:} + ;; + -cp) + # Reset any previously parsed classpath, just like dalvikvm + # only supports one -cp argument. + DEX2OAT_CLASSPATH=() + # TODO: support -classpath and CLASSPATH + local oifs=$IFS + IFS=':' + for classpath_elem in $2 + do + DEX2OAT_CLASSPATH+=("$classpath_elem") + done + shift + IFS=$oifs + ;; + esac + shift + done +} # Runs dalvikvm, returns its exit code. # (Oat directories are cleaned up in between runs) function run_art() { - local image_location="$(detect_boot_image_location)" local ret - # First cleanup any left-over 'oat' files from the last time dalvikvm was run. - cleanup_oat_directory_for_classpath "$@" # Run dalvikvm. verbose_run ANDROID_DATA="$ANDROID_DATA" \ ANDROID_ROOT="$ANDROID_ROOT" \ @@ -247,7 +267,7 @@ function run_art() { $LAUNCH_WRAPPER $ART_BINARY_PATH $lib \ -XXlib:"$LIBART" \ -Xnorelocate \ - -Ximage:"$image_location" \ + -Ximage:"$DEFAULT_IMAGE_LOCATION" \ "$@" ret=$? @@ -258,6 +278,23 @@ function run_art() { return $ret } +###################################### +# Globals +###################################### +ART_BINARY=dalvikvm +DEX2OAT_BINARY=dex2oat +DELETE_ANDROID_DATA="no" +LAUNCH_WRAPPER= +LIBART=libart.so +JIT_PROFILE="no" +ALLOW_DEFAULT_JDWP="no" +VERBOSE="no" +CLEAN_OAT_FILES="yes" +EXTRA_OPTIONS=() +DEX2OAT_FLAGS=() +DEX2OAT_CLASSPATH=() + +# Parse arguments while [[ "$1" = "-"* ]]; do case "$1" in --) @@ -275,6 +312,7 @@ while [[ "$1" = "-"* ]]; do ;& # Fallthrough --debug) LIBART="libartd.so" + DEX2OAT_BINARY=dex2oatd # Expect that debug mode wants all checks. EXTRA_OPTIONS+=(-XX:SlowDebug=true) ;; @@ -329,9 +367,21 @@ if [ $# -eq 0 ]; then exit 1 fi +# Follow all sym links to get the program name. +if [ z"$BASH_SOURCE" != z ]; then + PROG_NAME="$BASH_SOURCE" +else + PROG_NAME="$0" +fi +while [ -h "$PROG_NAME" ]; do + # On Mac OS, readlink -f doesn't work. + PROG_NAME="$(readlink "$PROG_NAME")" +done + PROG_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)" ANDROID_ROOT=$PROG_DIR/.. ART_BINARY_PATH=$ANDROID_ROOT/bin/$ART_BINARY +ISA=$($ART_BINARY_PATH -showversion | (read art version number isa && echo $isa)) if [ ! -x "$ART_BINARY_PATH" ]; then cat 1>&2 <<EOF @@ -341,8 +391,31 @@ EOF exit 1 fi +DEX2OAT_BINARY_PATH=$ANDROID_ROOT/bin/$DEX2OAT_BINARY + +if [ ! -x "$DEX2OAT_BINARY_PATH" ]; then + echo "Warning: Android Compiler not found: $DEX2OAT_BINARY_PATH" +fi + +###################################### +# Main program +###################################### + +# If android logging is not explicitly set, only print warnings and errors. +if [ -z "$ANDROID_LOG_TAGS" ]; then + ANDROID_LOG_TAGS='*:w' +fi + LIBDIR="$(find_libdir $ART_BINARY_PATH)" LD_LIBRARY_PATH=$ANDROID_ROOT/$LIBDIR +DEFAULT_IMAGE_LOCATION="$(detect_boot_image_location)" +DEX2OAT_BOOT_IMAGE="$DEFAULT_IMAGE_LOCATION" + +# Extract the dex2oat flags from the list of arguments. +# -Xcompiler-options arguments are stored in DEX2OAT_FLAGS array +# -cp argument is split by ':' and stored in DEX2OAT_CLASSPATH +# -Ximage argument is stored in DEX2OAT_BOOTIMAGE +extract_dex2oat_flags "$@" # If ANDROID_DATA is the system ANDROID_DATA or is not set, use our own, # and ensure we delete it at the end. @@ -360,31 +433,34 @@ fi if [ "$PERF" != "" ]; then LAUNCH_WRAPPER="perf record -g --call-graph dwarf -F 10000 -o $ANDROID_DATA/perf.data -e cycles:u $LAUNCH_WRAPPER" - EXTRA_OPTIONS+=(-Xcompiler-option --generate-debug-info) + DEX2OAT_FLAGS+=(--generate-debug-info) fi if [ "$ALLOW_DEFAULT_JDWP" = "no" ]; then EXTRA_OPTIONS+=(-XjdwpProvider:none) fi +# First cleanup any left-over 'oat' files from the last time dalvikvm was run. +cleanup_oat_directory_for_classpath "$@" + +# Protect additional arguments in quotes to preserve whitespaces (used by +# run-jdwp-test.sh when running on device), '$' (may be used as part of +# classpath) and other special characters when evaluated. +EXTRA_OPTIONS+=("$@") + if [ "$JIT_PROFILE" = "yes" ]; then # Create the profile. The runtime expects profiles to be created before # execution. PROFILE_PATH="$ANDROID_DATA/primary.prof" touch "$PROFILE_PATH" - # Replace the compiler filter with quicken so that we - # can capture the profile. - ARGS_WITH_QUICKEN= - replace_compiler_filter_with_quicken "$@" - run_art -Xjitsaveprofilinginfo \ -Xps-min-methods-to-save:1 \ -Xps-min-classes-to-save:1 \ -Xps-min-notification-before-wake:10 \ -Xps-profile-path:$PROFILE_PATH \ -Xusejit:true \ - "${ARGS_WITH_QUICKEN[@]}" \ + ${EXTRA_OPTIONS[@]} \ &> "$ANDROID_DATA/profile_gen.log" EXIT_STATUS=$? @@ -400,13 +476,20 @@ if [ "$JIT_PROFILE" = "yes" ]; then rm -rf "$ANDROID_DATA/dalvik-cache" # Append arguments so next invocation of run_art uses the profile. - EXTRA_OPTIONS+=(-Xcompiler-option --profile-file="$PROFILE_PATH") + DEX2OAT_FLAGS+=(--profile-file="$PROFILE_PATH") fi -# Protect additional arguments in quotes to preserve whitespaces (used by -# run-jdwp-test.sh when running on device), '$' (may be used as part of -# classpath) and other special characters when evaluated. -EXTRA_OPTIONS+=("$@") +if [ -x "$DEX2OAT_BINARY_PATH" ]; then + # Run dex2oat before launching ART to generate the oat files for the classpath. + run_dex2oat +fi + +# Do not continue if the dex2oat failed. +EXIT_STATUS=$? +if [ $EXIT_STATUS != 0 ]; then + echo "Failed dex2oat invocation" >&2 + exit $EXIT_STATUS +fi run_art "${EXTRA_OPTIONS[@]}" EXIT_STATUS=$? diff --git a/tools/dexanalyze/Android.bp b/tools/dexanalyze/Android.bp index 9515ca5c50..a85bf562af 100644 --- a/tools/dexanalyze/Android.bp +++ b/tools/dexanalyze/Android.bp @@ -22,6 +22,7 @@ cc_defaults { "dexanalyze.cc", "dexanalyze_bytecode.cc", "dexanalyze_experiments.cc", + "dexanalyze_strings.cc", ], target: { android: { diff --git a/tools/dexanalyze/dexanalyze.cc b/tools/dexanalyze/dexanalyze.cc index 841719b821..040f41ba5d 100644 --- a/tools/dexanalyze/dexanalyze.cc +++ b/tools/dexanalyze/dexanalyze.cc @@ -23,6 +23,7 @@ #include "dexanalyze_bytecode.h" #include "dexanalyze_experiments.h" +#include "dexanalyze_strings.h" #include "dex/code_item_accessors-inl.h" #include "dex/dex_file.h" #include "dex/dex_file_loader.h" diff --git a/tools/dexanalyze/dexanalyze_bytecode.cc b/tools/dexanalyze/dexanalyze_bytecode.cc index 0bb3f911a2..e6e58c0ecc 100644 --- a/tools/dexanalyze/dexanalyze_bytecode.cc +++ b/tools/dexanalyze/dexanalyze_bytecode.cc @@ -50,6 +50,53 @@ static inline SafeMap<T, U> SortByOrder(const SafeMap<T, U>& usage, Order order) return ret; } +template <typename A, typename B> +std::ostream& operator <<(std::ostream& os, const std::pair<A, B>& pair) { + return os << "{" << pair.first << ", " << pair.second << "}"; +} + +template <typename T, typename... Args, template <typename...> class ArrayType> +SafeMap<size_t, T> MakeUsageMap(const ArrayType<T, Args...>& array) { + SafeMap<size_t, T> ret; + for (size_t i = 0; i < array.size(); ++i) { + if (array[i] > 0) { + ret.Put(i, array[i]); + } + } + return ret; +} + +template <typename T, typename U, typename... Args, template <typename...> class Map> +void PrintMostUsed(std::ostream& os, + const Map<T, U, Args...>& usage, + size_t max_count, + std::function<void(std::ostream& os, T)> printer = + [](std::ostream& os, T v) { + os << v; + }) { + std::vector<std::pair<U, T>> sorted; + uint64_t total = 0u; + for (const auto& pair : usage) { + sorted.emplace_back(pair.second, pair.first); + total += pair.second; + } + std::sort(sorted.rbegin(), sorted.rend()); + uint64_t other = 0u; + for (auto&& pair : sorted) { + if (max_count > 0) { + os << Percent(pair.first, total) << " : "; + printer(os, pair.second); + os << "\n"; + --max_count; + } else { + other += pair.first; + } + } + if (other != 0u) { + os << "other: " << Percent(other, total) << "\n"; + } +} + static inline std::ostream& operator<<(std::ostream& os, const std::vector<uint8_t>& bytes) { os << std::hex; for (const uint8_t& c : bytes) { @@ -125,32 +172,42 @@ void NewRegisterInstructions::Dump(std::ostream& os, uint64_t total_size) const std::vector<std::pair<size_t, std::vector<uint8_t>>> pairs; for (auto&& pair : instruction_freq_) { if (pair.second > 0 && !pair.first.empty()) { - // Savings exclude one byte per occurrence and one occurence from having the macro + // Savings exclude one byte per occurrence and one occurrence from having the macro // dictionary. pairs.emplace_back((pair.second - 1) * (pair.first.size() - 1), pair.first); } } std::sort(pairs.rbegin(), pairs.rend()); static constexpr size_t kMaxMacros = 128; + static constexpr size_t kMaxPrintedMacros = 32; uint64_t top_instructions_savings = 0u; for (size_t i = 0; i < kMaxMacros && i < pairs.size(); ++i) { top_instructions_savings += pairs[i].first; } if (verbose_level_ >= VerboseLevel::kNormal) { + os << "Move result register distribution" << "\n"; + PrintMostUsed(os, MakeUsageMap(move_result_reg_), 16); + os << "First arg register usage\n"; + std::function<void(std::ostream& os, size_t)> printer = [&](std::ostream& os, size_t idx) { + os << Instruction::Name(static_cast<Instruction::Code>(idx)); + }; + PrintMostUsed(os, MakeUsageMap(first_arg_reg_count_), 16, printer); + os << "Most used field linkage pairs\n"; + PrintMostUsed(os, field_linkage_counts_, 32); + os << "Current extended " << extended_field_ << "\n"; + os << "Most used method linkage pairs\n"; + PrintMostUsed(os, method_linkage_counts_, 32); + os << "Current extended " << extended_method_ << "\n"; os << "Top " << kMaxMacros << " instruction bytecode sizes and hex dump" << "\n"; for (size_t i = 0; i < kMaxMacros && i < pairs.size(); ++i) { auto bytes = pairs[i].second; // Remove opcode bytes. bytes.erase(bytes.begin()); - os << Percent(pairs[i].first, total_size) << " " - << Instruction::Name(static_cast<Instruction::Code>(pairs[i].second[0])) - << "(" << bytes << ")\n"; - } - os << "Move result register distribution" << "\n"; - const size_t move_result_total = - std::accumulate(move_result_reg_.begin(), move_result_reg_.end(), 0u); - for (size_t i = 0; i < move_result_reg_.size(); ++i) { - os << i << ": " << Percent(move_result_reg_[i], move_result_total) << "\n"; + if (i < kMaxPrintedMacros) { + os << Percent(pairs[i].first, total_size) << " " + << Instruction::Name(static_cast<Instruction::Code>(pairs[i].second[0])) + << "(" << bytes << ")\n"; + } } } os << "Top instructions 1b macro savings " @@ -164,10 +221,7 @@ void NewRegisterInstructions::ProcessCodeItem(const DexFile& dex_file, std::map<size_t, TypeLinkage>& types) { TypeLinkage& current_type = types[current_class_type.index_]; bool skip_next = false; - for (auto inst = code_item.begin(); ; ++inst) { - if (inst == code_item.end()) { - break; - } + for (auto inst = code_item.begin(); inst != code_item.end(); ++inst) { if (verbose_level_ >= VerboseLevel::kEverything) { std::cout << std::endl; std::cout << inst->DumpString(nullptr); @@ -182,6 +236,7 @@ void NewRegisterInstructions::ProcessCodeItem(const DexFile& dex_file, bool is_iget = false; const Instruction::Code opcode = inst->Opcode(); Instruction::Code new_opcode = opcode; + ++opcode_count_[opcode]; switch (opcode) { case Instruction::IGET: case Instruction::IGET_WIDE: @@ -209,18 +264,18 @@ void NewRegisterInstructions::ProcessCodeItem(const DexFile& dex_file, uint32_t receiver = inst->VRegB_22c(); uint32_t first_arg_reg = code_item.RegistersSize() - code_item.InsSize(); uint32_t out_reg = inst->VRegA_22c(); - if (Enabled(kExperimentInstanceFieldSelf) && - first_arg_reg == receiver && - holder_type == current_class_type) { - if (count_types) { - ++current_type.fields_.FindOrAdd(dex_field_idx)->second; - } else { - uint32_t field_idx = types[holder_type.index_].fields_.Get(dex_field_idx); - ExtendPrefix(&out_reg, &field_idx); - CHECK(InstNibbles(new_opcode, {out_reg, field_idx})); - continue; - } - } else if (Enabled(kExperimentInstanceField)) { + if (Enabled(kExperimentInstanceFieldSelf) && + first_arg_reg == receiver && + holder_type == current_class_type) { + if (count_types) { + ++current_type.fields_.FindOrAdd(dex_field_idx)->second; + } else { + uint32_t field_idx = types[holder_type.index_].fields_.Get(dex_field_idx); + ExtendPrefix(&out_reg, &field_idx); + CHECK(InstNibbles(new_opcode, {out_reg, field_idx})); + continue; + } + } else if (Enabled(kExperimentInstanceField)) { if (count_types) { ++current_type.types_.FindOrAdd(holder_type.index_)->second; ++types[holder_type.index_].fields_.FindOrAdd(dex_field_idx)->second; @@ -288,7 +343,8 @@ void NewRegisterInstructions::ProcessCodeItem(const DexFile& dex_file, } else { uint32_t type_idx = current_type.types_.Get(holder_type.index_); uint32_t field_idx = types[holder_type.index_].fields_.Get(dex_field_idx); - ExtendPrefix(&type_idx, &field_idx); + ++field_linkage_counts_[std::make_pair(type_idx, field_idx)]; + extended_field_ += ExtendPrefix(&type_idx, &field_idx) ? 1u : 0u; if (InstNibbles(new_opcode, {out_reg >> 4, out_reg & 0xF, type_idx, field_idx})) { continue; } @@ -313,6 +369,7 @@ void NewRegisterInstructions::ProcessCodeItem(const DexFile& dex_file, } else { uint32_t args[6] = {}; uint32_t arg_count = inst->GetVarArgs(args); + const uint32_t first_arg_reg = code_item.RegistersSize() - code_item.InsSize(); bool next_move_result = false; uint32_t dest_reg = 0; @@ -330,6 +387,7 @@ void NewRegisterInstructions::ProcessCodeItem(const DexFile& dex_file, uint32_t type_idx = current_type.types_.Get(receiver_type.index_); uint32_t local_idx = types[receiver_type.index_].methods_.Get(method_idx); + ++method_linkage_counts_[std::make_pair(type_idx, local_idx)]; // If true, we always put the return value in r0. static constexpr bool kMoveToDestReg = true; @@ -338,15 +396,21 @@ void NewRegisterInstructions::ProcessCodeItem(const DexFile& dex_file, if (kMoveToDestReg && arg_count % 2 == 1) { // Use the extra nibble to sneak in part of the type index. new_args.push_back(local_idx >> 4); - local_idx ^= local_idx & 0xF0; + local_idx &= ~0xF0; } - ExtendPrefix(&type_idx, &local_idx); + extended_method_ += ExtendPrefix(&type_idx, &local_idx) ? 1u : 0u; new_args.push_back(type_idx); new_args.push_back(local_idx); if (!kMoveToDestReg) { ExtendPrefix(&dest_reg, &local_idx); new_args.push_back(dest_reg); } + for (size_t i = 0; i < arg_count; ++i) { + if (args[i] == first_arg_reg) { + ++first_arg_reg_count_[opcode]; + break; + } + } new_args.insert(new_args.end(), args, args + arg_count); if (InstNibbles(opcode, new_args)) { skip_next = next_move_result; @@ -467,18 +531,18 @@ void NewRegisterInstructions::Add(Instruction::Code opcode, const Instruction& i ++instruction_freq_[std::vector<uint8_t>(buffer_.begin() + buffer_start, buffer_.end())]; } -void NewRegisterInstructions::ExtendPrefix(uint32_t* value1, uint32_t* value2) { +bool NewRegisterInstructions::ExtendPrefix(uint32_t* value1, uint32_t* value2) { if (*value1 < 16 && *value2 < 16) { - return; + return false; } if ((*value1 >> 4) == 1 && *value2 < 16) { InstNibbles(0xE5, {}); *value1 ^= 1u << 4; - return; + return true; } else if ((*value2 >> 4) == 1 && *value1 < 16) { InstNibbles(0xE6, {}); *value2 ^= 1u << 4; - return; + return true; } if (*value1 < 256 && *value2 < 256) { // Extend each value by 4 bits. @@ -495,6 +559,7 @@ void NewRegisterInstructions::ExtendPrefix(uint32_t* value1, uint32_t* value2) { } *value1 &= 0xF; *value2 &= 0XF; + return true; } bool NewRegisterInstructions::InstNibbles(uint8_t opcode, const std::vector<uint32_t>& args) { diff --git a/tools/dexanalyze/dexanalyze_bytecode.h b/tools/dexanalyze/dexanalyze_bytecode.h index db009b03b8..015801f516 100644 --- a/tools/dexanalyze/dexanalyze_bytecode.h +++ b/tools/dexanalyze/dexanalyze_bytecode.h @@ -54,7 +54,11 @@ struct TypeLinkage { class NewRegisterInstructions : public Experiment { public: - explicit NewRegisterInstructions(uint64_t experiments) : experiments_(experiments) {} + explicit NewRegisterInstructions(uint64_t experiments) + : experiments_(experiments), + move_result_reg_(256), + first_arg_reg_count_(256), + opcode_count_(256) {} void ProcessDexFiles(const std::vector<std::unique_ptr<const DexFile>>& dex_files); void Dump(std::ostream& os, uint64_t total_size) const; @@ -65,7 +69,7 @@ class NewRegisterInstructions : public Experiment { std::map<size_t, TypeLinkage>& types); void Add(Instruction::Code opcode, const Instruction& inst); bool InstNibbles(uint8_t opcode, const std::vector<uint32_t>& args); - void ExtendPrefix(uint32_t* value1, uint32_t* value2); + bool ExtendPrefix(uint32_t* value1, uint32_t* value2); bool Enabled(BytecodeExperiment experiment) const { return experiments_ & (1u << static_cast<uint64_t>(experiment)); } @@ -76,7 +80,13 @@ class NewRegisterInstructions : public Experiment { uint64_t deduped_size_ = 0u; uint64_t dex_code_bytes_ = 0u; uint64_t experiments_ = std::numeric_limits<uint64_t>::max(); - std::array<size_t, 256> move_result_reg_; + uint64_t extended_field_ = 0u; + uint64_t extended_method_ = 0u; + std::vector<size_t> move_result_reg_; + std::vector<size_t> first_arg_reg_count_; + std::vector<size_t> opcode_count_; + std::map<std::pair<uint32_t, uint32_t>, size_t> method_linkage_counts_; + std::map<std::pair<uint32_t, uint32_t>, size_t> field_linkage_counts_; std::map<std::vector<uint8_t>, size_t> instruction_freq_; // Output instruction buffer. std::vector<uint8_t> buffer_; diff --git a/tools/dexanalyze/dexanalyze_experiments.cc b/tools/dexanalyze/dexanalyze_experiments.cc index 1f6fe4694e..b124f433b3 100644 --- a/tools/dexanalyze/dexanalyze_experiments.cc +++ b/tools/dexanalyze/dexanalyze_experiments.cc @@ -208,137 +208,6 @@ void AnalyzeDebugInfo::Dump(std::ostream& os, uint64_t total_size) const { << Percent(total_unique_non_header_bytes_, total_size) << "\n"; } -void AnalyzeStrings::ProcessDexFiles(const std::vector<std::unique_ptr<const DexFile>>& dex_files) { - std::set<std::string> unique_strings; - for (const std::unique_ptr<const DexFile>& dex_file : dex_files) { - for (size_t i = 0; i < dex_file->NumStringIds(); ++i) { - uint32_t length = 0; - const char* data = dex_file->StringDataAndUtf16LengthByIdx(dex::StringIndex(i), &length); - // Analyze if the string has any UTF16 chars. - bool have_wide_char = false; - const char* ptr = data; - for (size_t j = 0; j < length; ++j) { - have_wide_char = have_wide_char || GetUtf16FromUtf8(&ptr) >= 0x100; - } - if (have_wide_char) { - wide_string_bytes_ += 2 * length; - } else { - ascii_string_bytes_ += length; - } - string_data_bytes_ += ptr - data; - unique_strings.insert(data); - } - } - // Unique strings only since we want to exclude savings from multidex duplication. - std::vector<std::string> strings(unique_strings.begin(), unique_strings.end()); - unique_strings.clear(); - - // Tunable parameters. - static const size_t kMinPrefixLen = 1; - static const size_t kMaxPrefixLen = 255; - static const size_t kPrefixConstantCost = 4; - static const size_t kPrefixIndexCost = 2; - - // Calculate total shared prefix. - std::vector<size_t> shared_len; - prefixes_.clear(); - for (size_t i = 0; i < strings.size(); ++i) { - size_t best_len = 0; - if (i > 0) { - best_len = std::max(best_len, PrefixLen(strings[i], strings[i - 1])); - } - if (i < strings.size() - 1) { - best_len = std::max(best_len, PrefixLen(strings[i], strings[i + 1])); - } - best_len = std::min(best_len, kMaxPrefixLen); - std::string prefix; - if (best_len >= kMinPrefixLen) { - prefix = strings[i].substr(0, best_len); - ++prefixes_[prefix]; - } - total_prefix_index_cost_ += kPrefixIndexCost; - } - // Optimize the result by moving long prefixes to shorter ones if it causes savings. - while (true) { - bool have_savings = false; - auto it = prefixes_.begin(); - std::vector<std::string> longest; - for (const auto& pair : prefixes_) { - longest.push_back(pair.first); - } - std::sort(longest.begin(), longest.end(), [](const std::string& a, const std::string& b) { - return a.length() > b.length(); - }); - // Do longest first since this provides the best results. - for (const std::string& s : longest) { - it = prefixes_.find(s); - CHECK(it != prefixes_.end()); - const std::string& prefix = it->first; - int64_t best_savings = 0u; - int64_t best_len = -1; - for (int64_t len = prefix.length() - 1; len >= 0; --len) { - auto found = prefixes_.find(prefix.substr(0, len)); - if (len != 0 && found == prefixes_.end()) { - continue; - } - // Calculate savings from downgrading the prefix. - int64_t savings = kPrefixConstantCost + prefix.length() - - (prefix.length() - len) * it->second; - if (savings > best_savings) { - best_savings = savings; - best_len = len; - break; - } - } - if (best_len != -1) { - prefixes_[prefix.substr(0, best_len)] += it->second; - it = prefixes_.erase(it); - optimization_savings_ += best_savings; - have_savings = true; - } else { - ++it; - } - } - if (!have_savings) { - break; - } - } - total_num_prefixes_ += prefixes_.size(); - for (const auto& pair : prefixes_) { - // 4 bytes for an offset, one for length. - total_prefix_dict_ += pair.first.length(); - total_prefix_table_ += kPrefixConstantCost; - total_prefix_savings_ += pair.first.length() * pair.second; - } -} - -void AnalyzeStrings::Dump(std::ostream& os, uint64_t total_size) const { - os << "Total string data bytes " << Percent(string_data_bytes_, total_size) << "\n"; - os << "UTF-16 string data bytes " << Percent(wide_string_bytes_, total_size) << "\n"; - os << "ASCII string data bytes " << Percent(ascii_string_bytes_, total_size) << "\n"; - - // Prefix based strings. - os << "Total shared prefix bytes " << Percent(total_prefix_savings_, total_size) << "\n"; - os << "Prefix dictionary cost " << Percent(total_prefix_dict_, total_size) << "\n"; - os << "Prefix table cost " << Percent(total_prefix_table_, total_size) << "\n"; - os << "Prefix index cost " << Percent(total_prefix_index_cost_, total_size) << "\n"; - int64_t net_savings = total_prefix_savings_; - net_savings -= total_prefix_dict_; - net_savings -= total_prefix_table_; - net_savings -= total_prefix_index_cost_; - os << "Prefix dictionary elements " << total_num_prefixes_ << "\n"; - os << "Optimization savings " << Percent(optimization_savings_, total_size) << "\n"; - os << "Prefix net savings " << Percent(net_savings, total_size) << "\n"; - if (verbose_level_ >= VerboseLevel::kEverything) { - std::vector<std::pair<std::string, size_t>> pairs(prefixes_.begin(), prefixes_.end()); - // Sort lexicographically. - std::sort(pairs.begin(), pairs.end()); - for (const auto& pair : pairs) { - os << pair.first << " : " << pair.second << "\n"; - } - } -} - void CountDexIndices::ProcessDexFiles( const std::vector<std::unique_ptr<const DexFile>>& dex_files) { std::set<std::string> unique_field_names; diff --git a/tools/dexanalyze/dexanalyze_experiments.h b/tools/dexanalyze/dexanalyze_experiments.h index 4e66b3cf3b..3542d959ba 100644 --- a/tools/dexanalyze/dexanalyze_experiments.h +++ b/tools/dexanalyze/dexanalyze_experiments.h @@ -62,25 +62,6 @@ class Experiment { VerboseLevel verbose_level_ = VerboseLevel::kNormal; }; -// Analyze string data and strings accessed from code. -class AnalyzeStrings : public Experiment { - public: - void ProcessDexFiles(const std::vector<std::unique_ptr<const DexFile>>& dex_files) OVERRIDE; - void Dump(std::ostream& os, uint64_t total_size) const OVERRIDE; - - private: - int64_t wide_string_bytes_ = 0u; - int64_t ascii_string_bytes_ = 0u; - int64_t string_data_bytes_ = 0u; - int64_t total_prefix_savings_ = 0u; - int64_t total_prefix_dict_ = 0u; - int64_t total_prefix_table_ = 0u; - int64_t total_prefix_index_cost_ = 0u; - int64_t total_num_prefixes_ = 0u; - int64_t optimization_savings_ = 0u; - std::unordered_map<std::string, size_t> prefixes_; -}; - // Analyze debug info sizes. class AnalyzeDebugInfo : public Experiment { public: diff --git a/tools/dexanalyze/dexanalyze_strings.cc b/tools/dexanalyze/dexanalyze_strings.cc new file mode 100644 index 0000000000..9f67ff431a --- /dev/null +++ b/tools/dexanalyze/dexanalyze_strings.cc @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "dexanalyze_strings.h" + +#include <algorithm> +#include <iomanip> +#include <iostream> + +#include "dex/class_accessor-inl.h" +#include "dex/code_item_accessors-inl.h" +#include "dex/dex_instruction-inl.h" + +namespace art { +namespace dexanalyze { + +void AnalyzeStrings::ProcessDexFiles(const std::vector<std::unique_ptr<const DexFile>>& dex_files) { + std::set<std::string> unique_strings; + for (const std::unique_ptr<const DexFile>& dex_file : dex_files) { + for (size_t i = 0; i < dex_file->NumStringIds(); ++i) { + uint32_t length = 0; + const char* data = dex_file->StringDataAndUtf16LengthByIdx(dex::StringIndex(i), &length); + // Analyze if the string has any UTF16 chars. + bool have_wide_char = false; + const char* ptr = data; + for (size_t j = 0; j < length; ++j) { + have_wide_char = have_wide_char || GetUtf16FromUtf8(&ptr) >= 0x100; + } + if (have_wide_char) { + wide_string_bytes_ += 2 * length; + } else { + ascii_string_bytes_ += length; + } + string_data_bytes_ += ptr - data; + unique_strings.insert(data); + } + } + // Unique strings only since we want to exclude savings from multidex duplication. + std::vector<std::string> strings(unique_strings.begin(), unique_strings.end()); + unique_strings.clear(); + + // Tunable parameters. + static const size_t kMinPrefixLen = 1; + static const size_t kMaxPrefixLen = 255; + static const size_t kPrefixConstantCost = 4; + static const size_t kPrefixIndexCost = 2; + + // Calculate total shared prefix. + std::vector<size_t> shared_len; + prefixes_.clear(); + for (size_t i = 0; i < strings.size(); ++i) { + size_t best_len = 0; + if (i > 0) { + best_len = std::max(best_len, PrefixLen(strings[i], strings[i - 1])); + } + if (i < strings.size() - 1) { + best_len = std::max(best_len, PrefixLen(strings[i], strings[i + 1])); + } + best_len = std::min(best_len, kMaxPrefixLen); + std::string prefix; + if (best_len >= kMinPrefixLen) { + prefix = strings[i].substr(0, best_len); + ++prefixes_[prefix]; + } + total_prefix_index_cost_ += kPrefixIndexCost; + } + // Optimize the result by moving long prefixes to shorter ones if it causes savings. + while (true) { + bool have_savings = false; + auto it = prefixes_.begin(); + std::vector<std::string> longest; + for (const auto& pair : prefixes_) { + longest.push_back(pair.first); + } + std::sort(longest.begin(), longest.end(), [](const std::string& a, const std::string& b) { + return a.length() > b.length(); + }); + // Do longest first since this provides the best results. + for (const std::string& s : longest) { + it = prefixes_.find(s); + CHECK(it != prefixes_.end()); + const std::string& prefix = it->first; + int64_t best_savings = 0u; + int64_t best_len = -1; + for (int64_t len = prefix.length() - 1; len >= 0; --len) { + auto found = prefixes_.find(prefix.substr(0, len)); + if (len != 0 && found == prefixes_.end()) { + continue; + } + // Calculate savings from downgrading the prefix. + int64_t savings = kPrefixConstantCost + prefix.length() - + (prefix.length() - len) * it->second; + if (savings > best_savings) { + best_savings = savings; + best_len = len; + break; + } + } + if (best_len != -1) { + prefixes_[prefix.substr(0, best_len)] += it->second; + it = prefixes_.erase(it); + optimization_savings_ += best_savings; + have_savings = true; + } else { + ++it; + } + } + if (!have_savings) { + break; + } + } + total_num_prefixes_ += prefixes_.size(); + for (const auto& pair : prefixes_) { + // 4 bytes for an offset, one for length. + total_prefix_dict_ += pair.first.length(); + total_prefix_table_ += kPrefixConstantCost; + total_prefix_savings_ += pair.first.length() * pair.second; + } +} + +void AnalyzeStrings::Dump(std::ostream& os, uint64_t total_size) const { + os << "Total string data bytes " << Percent(string_data_bytes_, total_size) << "\n"; + os << "UTF-16 string data bytes " << Percent(wide_string_bytes_, total_size) << "\n"; + os << "ASCII string data bytes " << Percent(ascii_string_bytes_, total_size) << "\n"; + + // Prefix based strings. + os << "Total shared prefix bytes " << Percent(total_prefix_savings_, total_size) << "\n"; + os << "Prefix dictionary cost " << Percent(total_prefix_dict_, total_size) << "\n"; + os << "Prefix table cost " << Percent(total_prefix_table_, total_size) << "\n"; + os << "Prefix index cost " << Percent(total_prefix_index_cost_, total_size) << "\n"; + int64_t net_savings = total_prefix_savings_; + net_savings -= total_prefix_dict_; + net_savings -= total_prefix_table_; + net_savings -= total_prefix_index_cost_; + os << "Prefix dictionary elements " << total_num_prefixes_ << "\n"; + os << "Optimization savings " << Percent(optimization_savings_, total_size) << "\n"; + os << "Prefix net savings " << Percent(net_savings, total_size) << "\n"; + if (verbose_level_ >= VerboseLevel::kEverything) { + std::vector<std::pair<std::string, size_t>> pairs(prefixes_.begin(), prefixes_.end()); + // Sort lexicographically. + std::sort(pairs.begin(), pairs.end()); + for (const auto& pair : pairs) { + os << pair.first << " : " << pair.second << "\n"; + } + } +} + +} // namespace dexanalyze +} // namespace art diff --git a/tools/dexanalyze/dexanalyze_strings.h b/tools/dexanalyze/dexanalyze_strings.h new file mode 100644 index 0000000000..a5c202e31f --- /dev/null +++ b/tools/dexanalyze/dexanalyze_strings.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_TOOLS_DEXANALYZE_DEXANALYZE_STRINGS_H_ +#define ART_TOOLS_DEXANALYZE_DEXANALYZE_STRINGS_H_ + +#include <array> +#include <vector> +#include <map> + +#include "base/safe_map.h" +#include "dexanalyze_experiments.h" +#include "dex/code_item_accessors.h" +#include "dex/utf-inl.h" + +namespace art { +namespace dexanalyze { + +// Analyze string data and strings accessed from code. +class AnalyzeStrings : public Experiment { + public: + void ProcessDexFiles(const std::vector<std::unique_ptr<const DexFile>>& dex_files) OVERRIDE; + void Dump(std::ostream& os, uint64_t total_size) const OVERRIDE; + + private: + int64_t wide_string_bytes_ = 0u; + int64_t ascii_string_bytes_ = 0u; + int64_t string_data_bytes_ = 0u; + int64_t total_prefix_savings_ = 0u; + int64_t total_prefix_dict_ = 0u; + int64_t total_prefix_table_ = 0u; + int64_t total_prefix_index_cost_ = 0u; + int64_t total_num_prefixes_ = 0u; + int64_t optimization_savings_ = 0u; + std::unordered_map<std::string, size_t> prefixes_; +}; + +} // namespace dexanalyze +} // namespace art + +#endif // ART_TOOLS_DEXANALYZE_DEXANALYZE_STRINGS_H_ diff --git a/tools/golem/build-target.sh b/tools/golem/build-target.sh index 921a8cbe36..45c9125930 100755 --- a/tools/golem/build-target.sh +++ b/tools/golem/build-target.sh @@ -367,7 +367,7 @@ if [[ "$make_tarball" == "make_tarball" ]]; then dirs_rooted+=("$root_dir/$tar_dir") done - execute tar -czf "${tarball}" "${dirs_rooted[@]}" --exclude .git --exclude .gitignore + execute tar -czf "${tarball}" --exclude ".git" --exclude ".gitignore" "${dirs_rooted[@]}" tar_result=$? if [[ $tar_result -ne 0 ]]; then [[ -f $tarball ]] && rm $tarball diff --git a/tools/run-jdwp-tests.sh b/tools/run-jdwp-tests.sh index a435f2e03e..b0b5810dcc 100755 --- a/tools/run-jdwp-tests.sh +++ b/tools/run-jdwp-tests.sh @@ -311,10 +311,10 @@ if [[ "$plugin" != "" ]]; then vm_args="$vm_args --vm-arg $plugin" fi -if $use_jit; then - vm_args="$vm_args --vm-arg -Xcompiler-option --vm-arg --compiler-filter=quicken" - debuggee_args="$debuggee_args -Xcompiler-option --compiler-filter=quicken" -fi +# Because we're running debuggable, we discard any AOT code. +# Therefore we run de2oat with 'quicken' to avoid spending time compiling. +vm_args="$vm_args --vm-arg -Xcompiler-option --vm-arg --compiler-filter=quicken" +debuggee_args="$debuggee_args -Xcompiler-option --compiler-filter=quicken" if $instant_jit; then debuggee_args="$debuggee_args -Xjitthreshold:0" |