summaryrefslogtreecommitdiff
path: root/runtime/entrypoints/entrypoint_utils-inl.h
diff options
context:
space:
mode:
author David Brazdil <dbrazdil@google.com> 2016-01-15 09:35:13 +0000
committer David Brazdil <dbrazdil@google.com> 2016-01-19 11:29:20 +0000
commit65902e86b91f984061657bd8cacf239edb53c39d (patch)
tree42d2b7b9a4004b0b02c44df5f8dda14d51fb7366 /runtime/entrypoints/entrypoint_utils-inl.h
parent14c2d9fd6fba4732d1a43e3288c818b8e0e049fa (diff)
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.<init>). 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.<init> 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
Diffstat (limited to 'runtime/entrypoints/entrypoint_utils-inl.h')
-rw-r--r--runtime/entrypoints/entrypoint_utils-inl.h17
1 files changed, 13 insertions, 4 deletions
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.<init> 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 =