From 65902e86b91f984061657bd8cacf239edb53c39d Mon Sep 17 00:00:00 2001 From: David Brazdil Date: Fri, 15 Jan 2016 09:35:13 +0000 Subject: ART: Optimize out redundant NewInstances of String NewInstance of String creates an empty String object before it is replaced by the result of a StringFactory call (String.). If the empty object is never used prior to the call, it can be safely removed (replaced with null in this case). We do not remove the instruction if: - it has a real use (comparison, instanceof, check-cast), or - we are compiling with --debuggable and there is an environment use. If removed and execution deoptimizes before the StringFactory call, the interpreter will see String. being called on a null object. Since the verifier guarantees that the call was made on new-instance in the input bytecode (b/26579108), the interpreter can safely assume that it was optimized out rather than throw NullPointerException. Results (all without --debuggable): - boot.oat: 563/563 removed - Google Maps: 480/480 removed - Google Docs: 819/819 removed Change-Id: I9fdfc50e9dea6299a7327f94327cdfd2b2538079 --- runtime/entrypoints/entrypoint_utils-inl.h | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'runtime/entrypoints/entrypoint_utils-inl.h') diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h index 9a9f42b976..68f2dcbf31 100644 --- a/runtime/entrypoints/entrypoint_utils-inl.h +++ b/runtime/entrypoints/entrypoint_utils-inl.h @@ -410,10 +410,19 @@ inline ArtMethod* FindMethodFromCode(uint32_t method_idx, mirror::Object** this_ DCHECK(self->IsExceptionPending()); // Throw exception and unwind. return nullptr; // Failure. } else if (UNLIKELY(*this_object == nullptr && type != kStatic)) { - // Maintain interpreter-like semantics where NullPointerException is thrown - // after potential NoSuchMethodError from class linker. - ThrowNullPointerExceptionForMethodAccess(method_idx, type); - return nullptr; // Failure. + if (UNLIKELY(resolved_method->GetDeclaringClass()->IsStringClass() && + resolved_method->IsConstructor())) { + // Hack for String init: + // + // We assume that the input of String. in verified code is always + // an unitialized reference. If it is a null constant, it must have been + // optimized out by the compiler. Do not throw NullPointerException. + } else { + // Maintain interpreter-like semantics where NullPointerException is thrown + // after potential NoSuchMethodError from class linker. + ThrowNullPointerExceptionForMethodAccess(method_idx, type); + return nullptr; // Failure. + } } else if (access_check) { mirror::Class* methods_class = resolved_method->GetDeclaringClass(); bool can_access_resolved_method = -- cgit v1.2.3-59-g8ed1b