diff options
| -rw-r--r-- | build/Android.common_path.mk | 2 | ||||
| -rw-r--r-- | build/Android.gtest.mk | 4 | ||||
| -rw-r--r-- | compiler/optimizing/inliner.cc | 14 | ||||
| -rw-r--r-- | patchoat/patchoat.cc | 111 | ||||
| -rw-r--r-- | patchoat/patchoat.h | 7 | ||||
| -rw-r--r-- | runtime/art_method.cc | 1 | ||||
| -rw-r--r-- | runtime/common_runtime_test.cc | 25 | ||||
| -rw-r--r-- | runtime/common_runtime_test.h | 3 | ||||
| -rw-r--r-- | runtime/common_throws.cc | 100 | ||||
| -rw-r--r-- | runtime/common_throws.h | 8 | ||||
| -rw-r--r-- | runtime/entrypoints/entrypoint_utils.cc | 97 | ||||
| -rw-r--r-- | runtime/entrypoints/entrypoint_utils.h | 2 | ||||
| -rw-r--r-- | runtime/entrypoints/quick/quick_throw_entrypoints.cc | 1 | ||||
| -rw-r--r-- | runtime/interpreter/interpreter.cc | 1 | ||||
| -rw-r--r-- | runtime/reflection.cc | 1 | ||||
| -rw-r--r-- | tools/ahat/README.txt | 8 | ||||
| -rw-r--r-- | tools/ahat/src/AhatHttpHandler.java | 10 | ||||
| -rw-r--r-- | tools/ahat/src/HelpHandler.java | 52 | ||||
| -rw-r--r-- | tools/ahat/src/Main.java | 2 | ||||
| -rw-r--r-- | tools/ahat/src/Menu.java | 38 | ||||
| -rw-r--r-- | tools/ahat/src/OverviewHandler.java | 9 | ||||
| -rw-r--r-- | tools/ahat/src/help.html | 11 | ||||
| -rw-r--r-- | tools/ahat/src/manifest.txt | 2 | ||||
| -rw-r--r-- | tools/libcore_failures.txt | 8 |
24 files changed, 252 insertions, 265 deletions
diff --git a/build/Android.common_path.mk b/build/Android.common_path.mk index 81cd6efbef..ecc9e76b10 100644 --- a/build/Android.common_path.mk +++ b/build/Android.common_path.mk @@ -80,7 +80,7 @@ HOST_CORE_IMG_LOCATION := $(HOST_OUT_JAVA_LIBRARIES)/core.art TARGET_CORE_IMG_LOCATION := $(ART_TARGET_TEST_OUT)/core.art # Jar files for core.art. -TARGET_CORE_JARS := core-oj core-libart conscrypt okhttp bouncycastle +TARGET_CORE_JARS := core-oj core-libart conscrypt okhttp bouncycastle apache-xml HOST_CORE_JARS := $(addsuffix -hostdex,$(TARGET_CORE_JARS)) HOST_CORE_DEX_LOCATIONS := $(foreach jar,$(HOST_CORE_JARS), $(HOST_OUT_JAVA_LIBRARIES)/$(jar).jar) diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk index 99f7a2afb8..3d16c49fe4 100644 --- a/build/Android.gtest.mk +++ b/build/Android.gtest.mk @@ -442,8 +442,8 @@ define define-art-gtest-rule-target $$(ART_TARGET_NATIVETEST_OUT)/$$(TARGET_$(2)ARCH)/$(1) \ $$($(2)TARGET_OUT_SHARED_LIBRARIES)/libjavacore.so \ $$($(2)TARGET_OUT_SHARED_LIBRARIES)/libopenjdk.so \ - $$(TARGET_OUT_JAVA_LIBRARIES)/core-libart.jar \ - $$(TARGET_OUT_JAVA_LIBRARIES)/core-oj.jar + $$(TARGET_OUT_JAVA_LIBRARIES)/core-libart-testdex.jar \ + $$(TARGET_OUT_JAVA_LIBRARIES)/core-oj-testdex.jar .PHONY: $$(gtest_rule) $$(gtest_rule): test-art-target-sync diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc index 7c2b8bc855..48d32999b7 100644 --- a/compiler/optimizing/inliner.cc +++ b/compiler/optimizing/inliner.cc @@ -226,6 +226,7 @@ bool HInliner::TryInline(HInvoke* invoke_instruction) { ClassLinker* class_linker = caller_compilation_unit_.GetClassLinker(); // We can query the dex cache directly. The verifier has populated it already. ArtMethod* resolved_method; + ArtMethod* actual_method = nullptr; if (invoke_instruction->IsInvokeStaticOrDirect()) { if (invoke_instruction->AsInvokeStaticOrDirect()->IsStringInit()) { VLOG(compiler) << "Not inlining a String.<init> method"; @@ -237,9 +238,15 @@ bool HInliner::TryInline(HInvoke* invoke_instruction) { : class_linker->FindDexCache(soa.Self(), *ref.dex_file); resolved_method = dex_cache->GetResolvedMethod( ref.dex_method_index, class_linker->GetImagePointerSize()); + // actual_method == resolved_method for direct or static calls. + actual_method = resolved_method; } else { resolved_method = caller_compilation_unit_.GetDexCache().Get()->GetResolvedMethod( method_index, class_linker->GetImagePointerSize()); + if (resolved_method != nullptr) { + // Check if we can statically find the method. + actual_method = FindVirtualOrInterfaceTarget(invoke_instruction, resolved_method); + } } if (resolved_method == nullptr) { @@ -249,15 +256,10 @@ bool HInliner::TryInline(HInvoke* invoke_instruction) { return false; } - if (invoke_instruction->IsInvokeStaticOrDirect()) { - return TryInline(invoke_instruction, resolved_method); - } - - // Check if we can statically find the method. - ArtMethod* actual_method = FindVirtualOrInterfaceTarget(invoke_instruction, resolved_method); if (actual_method != nullptr) { return TryInline(invoke_instruction, actual_method); } + DCHECK(!invoke_instruction->IsInvokeStaticOrDirect()); // Check if we can use an inline cache. ArtMethod* caller = graph_->GetArtMethod(); diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc index b403abd2b6..3037652c4c 100644 --- a/patchoat/patchoat.cc +++ b/patchoat/patchoat.cc @@ -150,100 +150,6 @@ static bool FinishFile(File* file, bool close) { } } -bool PatchOat::Patch(const std::string& image_location, off_t delta, - File* output_image, InstructionSet isa, - TimingLogger* timings) { - CHECK(Runtime::Current() == nullptr); - CHECK(output_image != nullptr); - CHECK_GE(output_image->Fd(), 0); - CHECK(!image_location.empty()) << "image file must have a filename."; - CHECK_NE(isa, kNone); - - TimingLogger::ScopedTiming t("Runtime Setup", timings); - const char *isa_name = GetInstructionSetString(isa); - std::string image_filename; - if (!LocationToFilename(image_location, isa, &image_filename)) { - LOG(ERROR) << "Unable to find image at location " << image_location; - return false; - } - std::unique_ptr<File> input_image(OS::OpenFileForReading(image_filename.c_str())); - if (input_image.get() == nullptr) { - LOG(ERROR) << "unable to open input image file at " << image_filename - << " for location " << image_location; - return false; - } - - int64_t image_len = input_image->GetLength(); - if (image_len < 0) { - LOG(ERROR) << "Error while getting image length"; - return false; - } - ImageHeader image_header; - if (sizeof(image_header) != input_image->Read(reinterpret_cast<char*>(&image_header), - sizeof(image_header), 0)) { - LOG(ERROR) << "Unable to read image header from image file " << input_image->GetPath(); - return false; - } - - if (image_header.GetStorageMode() != ImageHeader::kStorageModeUncompressed) { - LOG(ERROR) << "Patchoat is not supported with compressed image files " - << input_image->GetPath(); - return false; - } - - /*bool is_image_pic = */IsImagePic(image_header, input_image->GetPath()); - // Nothing special to do right now since the image always needs to get patched. - // Perhaps in some far-off future we may have images with relative addresses that are true-PIC. - - // Set up the runtime - RuntimeOptions options; - NoopCompilerCallbacks callbacks; - options.push_back(std::make_pair("compilercallbacks", &callbacks)); - std::string img = "-Ximage:" + image_location; - options.push_back(std::make_pair(img.c_str(), nullptr)); - options.push_back(std::make_pair("imageinstructionset", reinterpret_cast<const void*>(isa_name))); - options.push_back(std::make_pair("-Xno-sig-chain", nullptr)); - if (!Runtime::Create(options, false)) { - LOG(ERROR) << "Unable to initialize runtime"; - return false; - } - // Runtime::Create acquired the mutator_lock_ that is normally given away when we Runtime::Start, - // give it away now and then switch to a more manageable ScopedObjectAccess. - Thread::Current()->TransitionFromRunnableToSuspended(kNative); - ScopedObjectAccess soa(Thread::Current()); - - t.NewTiming("Image and oat Patching setup"); - // Create the map where we will write the image patches to. - std::string error_msg; - std::unique_ptr<MemMap> image(MemMap::MapFile(image_len, - PROT_READ | PROT_WRITE, - MAP_PRIVATE, - input_image->Fd(), - 0, - /*low_4gb*/false, - input_image->GetPath().c_str(), - &error_msg)); - if (image.get() == nullptr) { - LOG(ERROR) << "unable to map image file " << input_image->GetPath() << " : " << error_msg; - return false; - } - // TODO: Support multi-image when patchoat is only patching images. Ever used? b/26317072 - gc::space::ImageSpace* ispc = Runtime::Current()->GetHeap()->GetBootImageSpaces()[0]; - - PatchOat p(isa, image.release(), ispc->GetLiveBitmap(), ispc->GetMemMap(), delta, timings); - t.NewTiming("Patching files"); - if (!p.PatchImage(true)) { - LOG(ERROR) << "Failed to patch image file " << input_image->GetPath(); - return false; - } - - t.NewTiming("Writing files"); - if (!p.WriteImage(output_image)) { - return false; - } - return true; -} - bool PatchOat::Patch(File* input_oat, const std::string& image_location, off_t delta, File* output_oat, File* output_image, InstructionSet isa, TimingLogger* timings, @@ -765,8 +671,6 @@ bool PatchOat::InHeap(mirror::Object* o) { void PatchOat::PatchVisitor::operator() (mirror::Object* obj, MemberOffset off, bool is_static_unused ATTRIBUTE_UNUSED) const { mirror::Object* referent = obj->GetFieldObject<mirror::Object, kVerifyNone>(off); - // TODO: Modify check for multi-image support? b/26317072 - // DCHECK(patcher_->InHeap(referent)) << "Referent is not in the heap."; mirror::Object* moved_object = patcher_->RelocatedAddressOfPointer(referent); copy_->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(off, moved_object); } @@ -775,8 +679,7 @@ void PatchOat::PatchVisitor::operator() (mirror::Class* cls ATTRIBUTE_UNUSED, mirror::Reference* ref) const { MemberOffset off = mirror::Reference::ReferentOffset(); mirror::Object* referent = ref->GetReferent(); - // TODO: Modify check for multi-image support? b/26317072 - // DCHECK(patcher_->InHeap(referent)) << "Referent is not in the heap."; + DCHECK(patcher_->InHeap(referent)) << "Referent is not in the heap."; mirror::Object* moved_object = patcher_->RelocatedAddressOfPointer(referent); copy_->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(off, moved_object); } @@ -1271,8 +1174,12 @@ static int patchoat(int argc, char **argv) { bool have_image_files = have_output_image; bool have_oat_files = have_output_oat; - if (!have_oat_files && !have_image_files) { - Usage("Must be patching either an oat or an image file or both."); + if (!have_oat_files) { + if (have_image_files) { + Usage("Cannot patch an image file without an oat file"); + } else { + Usage("Must be patching either an oat file or an image file with an oat file."); + } } if (!have_oat_files && !isa_set) { @@ -1507,10 +1414,6 @@ static int patchoat(int argc, char **argv) { output_oat_fd >= 0, // was it opened from FD? new_oat_out); ret = FinishFile(output_oat.get(), ret); - } else if (have_image_files) { - TimingLogger::ScopedTiming pt("patch image", &timings); - ret = PatchOat::Patch(input_image_location, base_delta, output_image.get(), isa, &timings); - ret = FinishFile(output_image.get(), ret); } else { CHECK(false); ret = true; diff --git a/patchoat/patchoat.h b/patchoat/patchoat.h index cb0d14b2c2..ceddc343be 100644 --- a/patchoat/patchoat.h +++ b/patchoat/patchoat.h @@ -133,12 +133,11 @@ class PatchOat { if (obj == nullptr) { return nullptr; } - // TODO: Fix these checks for multi-image. Some may still be valid. b/26317072 - // DCHECK_GT(reinterpret_cast<uintptr_t>(obj), reinterpret_cast<uintptr_t>(heap_->Begin())); - // DCHECK_LT(reinterpret_cast<uintptr_t>(obj), reinterpret_cast<uintptr_t>(heap_->End())); + DCHECK_GT(reinterpret_cast<uintptr_t>(obj), reinterpret_cast<uintptr_t>(heap_->Begin())); + DCHECK_LT(reinterpret_cast<uintptr_t>(obj), reinterpret_cast<uintptr_t>(heap_->End())); uintptr_t heap_off = reinterpret_cast<uintptr_t>(obj) - reinterpret_cast<uintptr_t>(heap_->Begin()); - // DCHECK_LT(heap_off, image_->Size()); + DCHECK_LT(heap_off, image_->Size()); return reinterpret_cast<T*>(image_->Begin() + heap_off); } diff --git a/runtime/art_method.cc b/runtime/art_method.cc index effa1c5d3f..6f36016d25 100644 --- a/runtime/art_method.cc +++ b/runtime/art_method.cc @@ -24,7 +24,6 @@ #include "debugger.h" #include "dex_file-inl.h" #include "dex_instruction.h" -#include "entrypoints/entrypoint_utils.h" #include "entrypoints/runtime_asm_entrypoints.h" #include "gc/accounting/card_table-inl.h" #include "interpreter/interpreter.h" diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc index 403dd4c0df..624abb9f6d 100644 --- a/runtime/common_runtime_test.cc +++ b/runtime/common_runtime_test.cc @@ -436,17 +436,26 @@ void CommonRuntimeTest::TearDown() { } } -std::vector<std::string> CommonRuntimeTest::GetLibCoreDexFileNames() { - return std::vector<std::string>({GetDexFileName("core-oj"), GetDexFileName("core-libart")}); -} - -std::string CommonRuntimeTest::GetDexFileName(const std::string& jar_prefix) { - if (IsHost()) { +static std::string GetDexFileName(const std::string& jar_prefix, bool host) { + std::string path; + if (host) { const char* host_dir = getenv("ANDROID_HOST_OUT"); CHECK(host_dir != nullptr); - return StringPrintf("%s/framework/%s-hostdex.jar", host_dir, jar_prefix.c_str()); + path = host_dir; + } else { + path = GetAndroidRoot(); } - return StringPrintf("%s/framework/%s.jar", GetAndroidRoot(), jar_prefix.c_str()); + + std::string suffix = host + ? "-hostdex" // The host version. + : "-testdex"; // The unstripped target version. + + return StringPrintf("%s/framework/%s%s.jar", path.c_str(), jar_prefix.c_str(), suffix.c_str()); +} + +std::vector<std::string> CommonRuntimeTest::GetLibCoreDexFileNames() { + return std::vector<std::string>({GetDexFileName("core-oj", IsHost()), + GetDexFileName("core-libart", IsHost())}); } std::string CommonRuntimeTest::GetTestAndroidRoot() { diff --git a/runtime/common_runtime_test.h b/runtime/common_runtime_test.h index 8d9e6281c0..7223b6ec6b 100644 --- a/runtime/common_runtime_test.h +++ b/runtime/common_runtime_test.h @@ -118,9 +118,6 @@ class CommonRuntimeTest : public testing::Test { // initializers, initialize well-known classes, and creates the heap thread pool. virtual void FinalizeSetup(); - // Gets the path of the specified dex file for host or target. - static std::string GetDexFileName(const std::string& jar_prefix); - std::string GetTestAndroidRoot(); std::string GetTestDexFileName(const char* name); diff --git a/runtime/common_throws.cc b/runtime/common_throws.cc index d68b463950..40e2b1593e 100644 --- a/runtime/common_throws.cc +++ b/runtime/common_throws.cc @@ -18,6 +18,8 @@ #include <sstream> +#include "ScopedLocalRef.h" + #include "art_field-inl.h" #include "art_method-inl.h" #include "base/logging.h" @@ -522,6 +524,104 @@ void ThrowRuntimeException(const char* fmt, ...) { va_end(args); } +// Stack overflow. + +void ThrowStackOverflowError(Thread* self) { + if (self->IsHandlingStackOverflow()) { + LOG(ERROR) << "Recursive stack overflow."; + // We don't fail here because SetStackEndForStackOverflow will print better diagnostics. + } + + self->SetStackEndForStackOverflow(); // Allow space on the stack for constructor to execute. + JNIEnvExt* env = self->GetJniEnv(); + std::string msg("stack size "); + msg += PrettySize(self->GetStackSize()); + + // Avoid running Java code for exception initialization. + // TODO: Checks to make this a bit less brittle. + + std::string error_msg; + + // Allocate an uninitialized object. + ScopedLocalRef<jobject> exc(env, + env->AllocObject(WellKnownClasses::java_lang_StackOverflowError)); + if (exc.get() != nullptr) { + // "Initialize". + // StackOverflowError -> VirtualMachineError -> Error -> Throwable -> Object. + // Only Throwable has "custom" fields: + // String detailMessage. + // Throwable cause (= this). + // List<Throwable> suppressedExceptions (= Collections.emptyList()). + // Object stackState; + // StackTraceElement[] stackTrace; + // Only Throwable has a non-empty constructor: + // this.stackTrace = EmptyArray.STACK_TRACE_ELEMENT; + // fillInStackTrace(); + + // detailMessage. + // TODO: Use String::FromModifiedUTF...? + ScopedLocalRef<jstring> s(env, env->NewStringUTF(msg.c_str())); + if (s.get() != nullptr) { + env->SetObjectField(exc.get(), WellKnownClasses::java_lang_Throwable_detailMessage, s.get()); + + // cause. + env->SetObjectField(exc.get(), WellKnownClasses::java_lang_Throwable_cause, exc.get()); + + // suppressedExceptions. + ScopedLocalRef<jobject> emptylist(env, env->GetStaticObjectField( + WellKnownClasses::java_util_Collections, + WellKnownClasses::java_util_Collections_EMPTY_LIST)); + CHECK(emptylist.get() != nullptr); + env->SetObjectField(exc.get(), + WellKnownClasses::java_lang_Throwable_suppressedExceptions, + emptylist.get()); + + // stackState is set as result of fillInStackTrace. fillInStackTrace calls + // nativeFillInStackTrace. + ScopedLocalRef<jobject> stack_state_val(env, nullptr); + { + ScopedObjectAccessUnchecked soa(env); + stack_state_val.reset(soa.Self()->CreateInternalStackTrace<false>(soa)); + } + if (stack_state_val.get() != nullptr) { + env->SetObjectField(exc.get(), + WellKnownClasses::java_lang_Throwable_stackState, + stack_state_val.get()); + + // stackTrace. + ScopedLocalRef<jobject> stack_trace_elem(env, env->GetStaticObjectField( + WellKnownClasses::libcore_util_EmptyArray, + WellKnownClasses::libcore_util_EmptyArray_STACK_TRACE_ELEMENT)); + env->SetObjectField(exc.get(), + WellKnownClasses::java_lang_Throwable_stackTrace, + stack_trace_elem.get()); + } else { + error_msg = "Could not create stack trace."; + } + // Throw the exception. + self->SetException(reinterpret_cast<mirror::Throwable*>(self->DecodeJObject(exc.get()))); + } else { + // Could not allocate a string object. + error_msg = "Couldn't throw new StackOverflowError because JNI NewStringUTF failed."; + } + } else { + error_msg = "Could not allocate StackOverflowError object."; + } + + if (!error_msg.empty()) { + LOG(WARNING) << error_msg; + CHECK(self->IsExceptionPending()); + } + + bool explicit_overflow_check = Runtime::Current()->ExplicitStackOverflowChecks(); + self->ResetDefaultStackEnd(); // Return to default stack size. + + // And restore protection if implicit checks are on. + if (!explicit_overflow_check) { + self->ProtectStack(); + } +} + // VerifyError void ThrowVerifyError(mirror::Class* referrer, const char* fmt, ...) { diff --git a/runtime/common_throws.h b/runtime/common_throws.h index 2a0934fb5b..85fe2b3997 100644 --- a/runtime/common_throws.h +++ b/runtime/common_throws.h @@ -154,10 +154,10 @@ void ThrowNegativeArraySizeException(const char* msg) void ThrowNoSuchFieldError(const StringPiece& scope, mirror::Class* c, const StringPiece& type, const StringPiece& name) - SHARED_REQUIRES(Locks::mutator_lock_); + SHARED_REQUIRES(Locks::mutator_lock_) COLD_ATTR; void ThrowNoSuchFieldException(mirror::Class* c, const StringPiece& name) - SHARED_REQUIRES(Locks::mutator_lock_); + SHARED_REQUIRES(Locks::mutator_lock_) COLD_ATTR; // NoSuchMethodError @@ -194,6 +194,10 @@ void ThrowRuntimeException(const char* fmt, ...) __attribute__((__format__(__printf__, 1, 2))) SHARED_REQUIRES(Locks::mutator_lock_) COLD_ATTR; +// Stack overflow. + +void ThrowStackOverflowError(Thread* self) SHARED_REQUIRES(Locks::mutator_lock_) COLD_ATTR; + // VerifyError void ThrowVerifyError(mirror::Class* referrer, const char* fmt, ...) diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc index 915d9ab5e7..b5a55bfa44 100644 --- a/runtime/entrypoints/entrypoint_utils.cc +++ b/runtime/entrypoints/entrypoint_utils.cc @@ -33,7 +33,6 @@ #include "oat_quick_method_header.h" #include "reflection.h" #include "scoped_thread_state_change.h" -#include "ScopedLocalRef.h" #include "well_known_classes.h" namespace art { @@ -120,102 +119,6 @@ mirror::Array* CheckAndAllocArrayFromCodeInstrumented(uint32_t type_idx, heap->GetCurrentAllocator()); } -void ThrowStackOverflowError(Thread* self) { - if (self->IsHandlingStackOverflow()) { - LOG(ERROR) << "Recursive stack overflow."; - // We don't fail here because SetStackEndForStackOverflow will print better diagnostics. - } - - self->SetStackEndForStackOverflow(); // Allow space on the stack for constructor to execute. - JNIEnvExt* env = self->GetJniEnv(); - std::string msg("stack size "); - msg += PrettySize(self->GetStackSize()); - - // Avoid running Java code for exception initialization. - // TODO: Checks to make this a bit less brittle. - - std::string error_msg; - - // Allocate an uninitialized object. - ScopedLocalRef<jobject> exc(env, - env->AllocObject(WellKnownClasses::java_lang_StackOverflowError)); - if (exc.get() != nullptr) { - // "Initialize". - // StackOverflowError -> VirtualMachineError -> Error -> Throwable -> Object. - // Only Throwable has "custom" fields: - // String detailMessage. - // Throwable cause (= this). - // List<Throwable> suppressedExceptions (= Collections.emptyList()). - // Object stackState; - // StackTraceElement[] stackTrace; - // Only Throwable has a non-empty constructor: - // this.stackTrace = EmptyArray.STACK_TRACE_ELEMENT; - // fillInStackTrace(); - - // detailMessage. - // TODO: Use String::FromModifiedUTF...? - ScopedLocalRef<jstring> s(env, env->NewStringUTF(msg.c_str())); - if (s.get() != nullptr) { - env->SetObjectField(exc.get(), WellKnownClasses::java_lang_Throwable_detailMessage, s.get()); - - // cause. - env->SetObjectField(exc.get(), WellKnownClasses::java_lang_Throwable_cause, exc.get()); - - // suppressedExceptions. - ScopedLocalRef<jobject> emptylist(env, env->GetStaticObjectField( - WellKnownClasses::java_util_Collections, - WellKnownClasses::java_util_Collections_EMPTY_LIST)); - CHECK(emptylist.get() != nullptr); - env->SetObjectField(exc.get(), - WellKnownClasses::java_lang_Throwable_suppressedExceptions, - emptylist.get()); - - // stackState is set as result of fillInStackTrace. fillInStackTrace calls - // nativeFillInStackTrace. - ScopedLocalRef<jobject> stack_state_val(env, nullptr); - { - ScopedObjectAccessUnchecked soa(env); - stack_state_val.reset(soa.Self()->CreateInternalStackTrace<false>(soa)); - } - if (stack_state_val.get() != nullptr) { - env->SetObjectField(exc.get(), - WellKnownClasses::java_lang_Throwable_stackState, - stack_state_val.get()); - - // stackTrace. - ScopedLocalRef<jobject> stack_trace_elem(env, env->GetStaticObjectField( - WellKnownClasses::libcore_util_EmptyArray, - WellKnownClasses::libcore_util_EmptyArray_STACK_TRACE_ELEMENT)); - env->SetObjectField(exc.get(), - WellKnownClasses::java_lang_Throwable_stackTrace, - stack_trace_elem.get()); - } else { - error_msg = "Could not create stack trace."; - } - // Throw the exception. - self->SetException(reinterpret_cast<mirror::Throwable*>(self->DecodeJObject(exc.get()))); - } else { - // Could not allocate a string object. - error_msg = "Couldn't throw new StackOverflowError because JNI NewStringUTF failed."; - } - } else { - error_msg = "Could not allocate StackOverflowError object."; - } - - if (!error_msg.empty()) { - LOG(WARNING) << error_msg; - CHECK(self->IsExceptionPending()); - } - - bool explicit_overflow_check = Runtime::Current()->ExplicitStackOverflowChecks(); - self->ResetDefaultStackEnd(); // Return to default stack size. - - // And restore protection if implicit checks are on. - if (!explicit_overflow_check) { - self->ProtectStack(); - } -} - void CheckReferenceResult(mirror::Object* o, Thread* self) { if (o == nullptr) { return; diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h index 0469ee6eb6..a28376fadf 100644 --- a/runtime/entrypoints/entrypoint_utils.h +++ b/runtime/entrypoints/entrypoint_utils.h @@ -158,8 +158,6 @@ inline mirror::Class* ResolveVerifyAndClinit( uint32_t type_idx, ArtMethod* referrer, Thread* self, bool can_run_clinit, bool verify_access) SHARED_REQUIRES(Locks::mutator_lock_); -extern void ThrowStackOverflowError(Thread* self) SHARED_REQUIRES(Locks::mutator_lock_); - inline mirror::String* ResolveStringFromCode(ArtMethod* referrer, uint32_t string_idx) SHARED_REQUIRES(Locks::mutator_lock_); diff --git a/runtime/entrypoints/quick/quick_throw_entrypoints.cc b/runtime/entrypoints/quick/quick_throw_entrypoints.cc index 5a82b3ae2e..5256feae2b 100644 --- a/runtime/entrypoints/quick/quick_throw_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_throw_entrypoints.cc @@ -16,7 +16,6 @@ #include "callee_save_frame.h" #include "common_throws.h" -#include "entrypoints/entrypoint_utils-inl.h" #include "mirror/object-inl.h" #include "thread.h" #include "well_known_classes.h" diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc index 871fad7b80..8d5a61a44b 100644 --- a/runtime/interpreter/interpreter.cc +++ b/runtime/interpreter/interpreter.cc @@ -18,6 +18,7 @@ #include <limits> +#include "common_throws.h" #include "interpreter_common.h" #include "mirror/string-inl.h" #include "scoped_thread_state_change.h" diff --git a/runtime/reflection.cc b/runtime/reflection.cc index 324bd9f580..28c27cd971 100644 --- a/runtime/reflection.cc +++ b/runtime/reflection.cc @@ -21,7 +21,6 @@ #include "class_linker.h" #include "common_throws.h" #include "dex_file-inl.h" -#include "entrypoints/entrypoint_utils.h" #include "indirect_reference_table-inl.h" #include "jni_internal.h" #include "mirror/abstract_method.h" diff --git a/tools/ahat/README.txt b/tools/ahat/README.txt index adc4d03a7a..a3ecf86ab7 100644 --- a/tools/ahat/README.txt +++ b/tools/ahat/README.txt @@ -23,8 +23,6 @@ TODO: - Make sortable by clicking on headers. * For HeapTable with single heap shown, the heap name isn't centered? * Consistently document functions. - * Should help be part of an AhatHandler, that automatically gets the menu and - stylesheet link rather than duplicating that? * Show version number with --version. * Show somewhere where to send bugs. * Include a link to /objects in the overview and menu? @@ -79,6 +77,12 @@ Things to move to perflib: * Instance.isRoot and Instance.getRootTypes. Release History: + 0.3 Dec 15, 2015 + Fix page loading performance by showing a limited number of entries by default. + Fix mismatch between overview and "roots" totals. + Annotate root objects and show their types. + Annotate references with their referents. + 0.2 Oct 20, 2015 Take into account 'count' and 'offset' when displaying strings. diff --git a/tools/ahat/src/AhatHttpHandler.java b/tools/ahat/src/AhatHttpHandler.java index 178747c29a..1d05a66653 100644 --- a/tools/ahat/src/AhatHttpHandler.java +++ b/tools/ahat/src/AhatHttpHandler.java @@ -41,15 +41,7 @@ class AhatHttpHandler implements HttpHandler { PrintStream ps = new PrintStream(exchange.getResponseBody()); try { HtmlDoc doc = new HtmlDoc(ps, DocString.text("ahat"), DocString.uri("style.css")); - DocString menu = new DocString(); - menu.appendLink(DocString.uri("/"), DocString.text("overview")); - menu.append(" - "); - menu.appendLink(DocString.uri("rooted"), DocString.text("rooted")); - menu.append(" - "); - menu.appendLink(DocString.uri("sites"), DocString.text("allocations")); - menu.append(" - "); - menu.appendLink(DocString.uri("help"), DocString.text("help")); - doc.menu(menu); + doc.menu(Menu.getMenu()); mAhatHandler.handle(doc, new Query(exchange.getRequestURI())); doc.close(); } catch (RuntimeException e) { diff --git a/tools/ahat/src/HelpHandler.java b/tools/ahat/src/HelpHandler.java new file mode 100644 index 0000000000..8de3c85f5c --- /dev/null +++ b/tools/ahat/src/HelpHandler.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2015 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. + */ + +package com.android.ahat; + +import com.google.common.io.ByteStreams; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintStream; + +/** + * HelpHandler. + * + * HttpHandler to show the help page. + */ +class HelpHandler implements HttpHandler { + + @Override + public void handle(HttpExchange exchange) throws IOException { + ClassLoader loader = HelpHandler.class.getClassLoader(); + exchange.getResponseHeaders().add("Content-Type", "text/html;charset=utf-8"); + exchange.sendResponseHeaders(200, 0); + PrintStream ps = new PrintStream(exchange.getResponseBody()); + HtmlDoc doc = new HtmlDoc(ps, DocString.text("ahat"), DocString.uri("style.css")); + doc.menu(Menu.getMenu()); + + InputStream is = loader.getResourceAsStream("help.html"); + if (is == null) { + ps.println("No help available."); + } else { + ByteStreams.copy(is, ps); + } + + doc.close(); + ps.close(); + } +} diff --git a/tools/ahat/src/Main.java b/tools/ahat/src/Main.java index ebd49d7e2c..091820f7fc 100644 --- a/tools/ahat/src/Main.java +++ b/tools/ahat/src/Main.java @@ -79,7 +79,7 @@ public class Main { server.createContext("/objects", new AhatHttpHandler(new ObjectsHandler(ahat))); server.createContext("/site", new AhatHttpHandler(new SiteHandler(ahat))); server.createContext("/bitmap", new BitmapHandler(ahat)); - server.createContext("/help", new StaticHandler("help.html", "text/html")); + server.createContext("/help", new HelpHandler()); server.createContext("/style.css", new StaticHandler("style.css", "text/css")); server.setExecutor(Executors.newFixedThreadPool(1)); System.out.println("Server started on localhost:" + port); diff --git a/tools/ahat/src/Menu.java b/tools/ahat/src/Menu.java new file mode 100644 index 0000000000..018e019503 --- /dev/null +++ b/tools/ahat/src/Menu.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2015 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. + */ + +package com.android.ahat; + +/** + * A menu showed in the UI that can be used to jump to common pages. + */ +class Menu { + private static DocString mMenu = + DocString.link(DocString.uri("/"), DocString.text("overview")) + .append(" - ") + .appendLink(DocString.uri("rooted"), DocString.text("rooted")) + .append(" - ") + .appendLink(DocString.uri("sites"), DocString.text("allocations")) + .append(" - ") + .appendLink(DocString.uri("help"), DocString.text("help")); + + /** + * Returns the menu as a DocString. + */ + public static DocString getMenu() { + return mMenu; + } +} diff --git a/tools/ahat/src/OverviewHandler.java b/tools/ahat/src/OverviewHandler.java index 0fe4fba716..720fcb42ff 100644 --- a/tools/ahat/src/OverviewHandler.java +++ b/tools/ahat/src/OverviewHandler.java @@ -48,14 +48,7 @@ class OverviewHandler implements AhatHandler { doc.section("Heap Sizes"); printHeapSizes(doc, query); - - DocString menu = new DocString(); - menu.appendLink(DocString.uri("rooted"), DocString.text("Rooted")); - menu.append(" - "); - menu.appendLink(DocString.uri("site"), DocString.text("Allocations")); - menu.append(" - "); - menu.appendLink(DocString.uri("help"), DocString.text("Help")); - doc.big(menu); + doc.big(Menu.getMenu()); } private void printHeapSizes(Doc doc, Query query) { diff --git a/tools/ahat/src/help.html b/tools/ahat/src/help.html index 92ec37d984..ff04ad2840 100644 --- a/tools/ahat/src/help.html +++ b/tools/ahat/src/help.html @@ -14,17 +14,6 @@ See the License for the specific language governing permissions and limitations under the License. --> -<head> -<link rel="stylesheet" type="text/css" href="style.css"> -</head> - -<div class="menu"> - <a href="/">overview</a> - - <a href="rooted">rooted</a> - - <a href="sites">allocations</a> - - <a href="help">help</a> -</div> - <h1>Help</h1> <h2>Information shown by ahat:</h2> <ul> diff --git a/tools/ahat/src/manifest.txt b/tools/ahat/src/manifest.txt index 421de1715a..368b744f28 100644 --- a/tools/ahat/src/manifest.txt +++ b/tools/ahat/src/manifest.txt @@ -1,4 +1,4 @@ Name: ahat/ Implementation-Title: ahat -Implementation-Version: 0.3 +Implementation-Version: 0.4 Main-Class: com.android.ahat.Main diff --git a/tools/libcore_failures.txt b/tools/libcore_failures.txt index 880be26792..e29bcf3a2d 100644 --- a/tools/libcore_failures.txt +++ b/tools/libcore_failures.txt @@ -248,6 +248,12 @@ modes_variants: [[device, X32]], names: ["org.apache.harmony.tests.java.text.DecimalFormatTest#test_formatDouble_withFieldPosition", "org.apache.harmony.tests.java.text.DecimalFormatTest#test_formatToCharacterIterator_original"] +}, +{ + description: "'cat -' does not work anymore", + result: EXEC_FAILED, + bug: 26395656, + modes: [device], + names: ["org.apache.harmony.tests.java.lang.ProcessTest#test_getOutputStream"] } - ] |