OSDN Git Service

Revert "Don't use the compiler driver for method resolution."
authorNicolas Geoffray <ngeoffray@google.com>
Tue, 1 Dec 2015 16:28:10 +0000 (16:28 +0000)
committerNicolas Geoffray <ngeoffray@google.com>
Tue, 1 Dec 2015 16:28:10 +0000 (16:28 +0000)
Fails 425 in debuggable mode.

This reverts commit 4db0bf9c4db6a09716c3388b7d2f88d534470339.

Change-Id: I346df8f75674564fc4fb241c60f23e250fc7f0a7

27 files changed:
compiler/optimizing/builder.cc
compiler/optimizing/builder.h
compiler/optimizing/code_generator_arm.cc
compiler/optimizing/code_generator_arm64.cc
compiler/optimizing/code_generator_mips64.cc
compiler/optimizing/code_generator_x86.cc
compiler/optimizing/code_generator_x86_64.cc
compiler/optimizing/graph_visualizer.cc
compiler/optimizing/inliner.cc
compiler/optimizing/intrinsics.cc
compiler/optimizing/nodes.h
compiler/optimizing/sharpening.cc
runtime/entrypoints/entrypoint_utils-inl.h
test/464-checker-inline-sharpen-calls/src/Main.java
test/492-checker-inline-invoke-interface/expected.txt
test/492-checker-inline-invoke-interface/src/Main.java
test/536-checker-intrinsic-optimization/src/Main.java
test/551-invoke-super/expected.txt [deleted file]
test/551-invoke-super/info.txt [deleted file]
test/551-invoke-super/smali/invokesuper.smali [deleted file]
test/551-invoke-super/smali/superclass.smali [deleted file]
test/551-invoke-super/src/Main.java [deleted file]
test/552-invoke-non-existent-super/expected.txt [deleted file]
test/552-invoke-non-existent-super/info.txt [deleted file]
test/552-invoke-non-existent-super/smali/invokesuper.smali [deleted file]
test/552-invoke-non-existent-super/smali/superclass.smali [deleted file]
test/552-invoke-non-existent-super/src/Main.java [deleted file]

index 8e75bdc..d7754e8 100644 (file)
@@ -735,79 +735,6 @@ static InvokeType GetInvokeTypeFromOpCode(Instruction::Code opcode) {
   }
 }
 
-ArtMethod* HGraphBuilder::ResolveMethod(uint16_t method_idx, InvokeType invoke_type) {
-  ScopedObjectAccess soa(Thread::Current());
-  StackHandleScope<2> hs(soa.Self());
-
-  ClassLinker* class_linker = dex_compilation_unit_->GetClassLinker();
-  Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
-      soa.Decode<mirror::ClassLoader*>(dex_compilation_unit_->GetClassLoader())));
-  Handle<mirror::Class> compiling_class(hs.NewHandle(GetCompilingClass()));
-
-  ArtMethod* resolved_method = class_linker->ResolveMethod(
-      *dex_compilation_unit_->GetDexFile(),
-      method_idx,
-      dex_compilation_unit_->GetDexCache(),
-      class_loader,
-      /* referrer */ nullptr,
-      invoke_type);
-
-  if (UNLIKELY(resolved_method == nullptr)) {
-    // Clean up any exception left by type resolution.
-    soa.Self()->ClearException();
-    return nullptr;
-  }
-
-  // Check access. The class linker has a fast path for looking into the dex cache
-  // and does not check the access if it hits it.
-  if (compiling_class.Get() == nullptr) {
-    if (!resolved_method->IsPublic()) {
-      return nullptr;
-    }
-  } else if (!compiling_class->CanAccessResolvedMethod(resolved_method->GetDeclaringClass(),
-                                                       resolved_method,
-                                                       dex_compilation_unit_->GetDexCache().Get(),
-                                                       method_idx)) {
-    return nullptr;
-  }
-
-  // We have to special case the invoke-super case, as ClassLinker::ResolveMethod does not.
-  // We need to look at the referrer's super class vtable.
-  if (invoke_type == kSuper) {
-    if (compiling_class.Get() == nullptr) {
-      // Invoking a super method requires knowing the actual super class. If we did not resolve
-      // the compiling method's declaring class (which only happens for ahead of time compilation),
-      // bail out.
-      DCHECK(Runtime::Current()->IsAotCompiler());
-      return nullptr;
-    }
-    uint16_t vtable_index = resolved_method->GetMethodIndex();
-    ArtMethod* actual_method = compiling_class->GetSuperClass()->GetVTableEntry(
-        vtable_index, class_linker->GetImagePointerSize());
-    if (actual_method != resolved_method &&
-        !IsSameDexFile(*resolved_method->GetDexFile(), *dex_compilation_unit_->GetDexFile())) {
-      // TODO: The actual method could still be referenced in the current dex file, so we
-      // could try locating it.
-      // TODO: Remove the dex_file restriction.
-      return nullptr;
-    }
-    if (!actual_method->IsInvokable()) {
-      // Fail if the actual method cannot be invoked. Otherwise, the runtime resolution stub
-      // could resolve the callee to the wrong method.
-      return nullptr;
-    }
-    resolved_method = actual_method;
-  }
-
-  // Check for incompatible class changes. The class linker has a fast path for
-  // looking into the dex cache and does not check incompatible class changes if it hits it.
-  if (resolved_method->CheckIncompatibleClassChange(invoke_type)) {
-    return nullptr;
-  }
-
-  return resolved_method;
-}
-
 bool HGraphBuilder::BuildInvoke(const Instruction& instruction,
                                 uint32_t dex_pc,
                                 uint32_t method_idx,
@@ -815,18 +742,22 @@ bool HGraphBuilder::BuildInvoke(const Instruction& instruction,
                                 bool is_range,
                                 uint32_t* args,
                                 uint32_t register_index) {
-  InvokeType invoke_type = GetInvokeTypeFromOpCode(instruction.Opcode());
+  InvokeType original_invoke_type = GetInvokeTypeFromOpCode(instruction.Opcode());
+  InvokeType optimized_invoke_type = original_invoke_type;
   const char* descriptor = dex_file_->GetMethodShorty(method_idx);
   Primitive::Type return_type = Primitive::GetType(descriptor[0]);
 
   // Remove the return type from the 'proto'.
   size_t number_of_arguments = strlen(descriptor) - 1;
-  if (invoke_type != kStatic) {  // instance call
+  if (original_invoke_type != kStatic) {  // instance call
     // One extra argument for 'this'.
     number_of_arguments++;
   }
 
   MethodReference target_method(dex_file_, method_idx);
+  int32_t table_index = 0;
+  uintptr_t direct_code = 0;
+  uintptr_t direct_method = 0;
 
   // Special handling for string init.
   int32_t string_init_offset = 0;
@@ -849,7 +780,7 @@ bool HGraphBuilder::BuildInvoke(const Instruction& instruction,
         method_idx,
         target_method,
         dispatch_info,
-        invoke_type,
+        original_invoke_type,
         kStatic /* optimized_invoke_type */,
         HInvokeStaticOrDirect::ClinitCheckRequirement::kImplicit);
     return HandleStringInit(invoke,
@@ -860,16 +791,23 @@ bool HGraphBuilder::BuildInvoke(const Instruction& instruction,
                             descriptor);
   }
 
-  ArtMethod* resolved_method = ResolveMethod(method_idx, invoke_type);
-
-  if (resolved_method == nullptr) {
+  // Handle unresolved methods.
+  if (!compiler_driver_->ComputeInvokeInfo(dex_compilation_unit_,
+                                           dex_pc,
+                                           true /* update_stats */,
+                                           true /* enable_devirtualization */,
+                                           &optimized_invoke_type,
+                                           &target_method,
+                                           &table_index,
+                                           &direct_code,
+                                           &direct_method)) {
     MaybeRecordStat(MethodCompilationStat::kUnresolvedMethod);
     HInvoke* invoke = new (arena_) HInvokeUnresolved(arena_,
                                                      number_of_arguments,
                                                      return_type,
                                                      dex_pc,
                                                      method_idx,
-                                                     invoke_type);
+                                                     original_invoke_type);
     return HandleInvoke(invoke,
                         number_of_vreg_arguments,
                         args,
@@ -879,26 +817,21 @@ bool HGraphBuilder::BuildInvoke(const Instruction& instruction,
                         nullptr /* clinit_check */);
   }
 
+  // Handle resolved methods (non string init).
+
+  DCHECK(optimized_invoke_type != kSuper);
+
   // Potential class initialization check, in the case of a static method call.
   HClinitCheck* clinit_check = nullptr;
   HInvoke* invoke = nullptr;
 
-  if (invoke_type == kDirect || invoke_type == kStatic || invoke_type == kSuper) {
+  if (optimized_invoke_type == kDirect || optimized_invoke_type == kStatic) {
     // By default, consider that the called method implicitly requires
     // an initialization check of its declaring method.
     HInvokeStaticOrDirect::ClinitCheckRequirement clinit_check_requirement
         = HInvokeStaticOrDirect::ClinitCheckRequirement::kImplicit;
-    ScopedObjectAccess soa(Thread::Current());
-    if (invoke_type == kStatic) {
-      clinit_check = ProcessClinitCheckForInvoke(
-          dex_pc, resolved_method, method_idx, &clinit_check_requirement);
-    } else if (invoke_type == kSuper) {
-      if (IsSameDexFile(*resolved_method->GetDexFile(), *dex_compilation_unit_->GetDexFile())) {
-        // Update the target method to the one resolved. Note that this may be a no-op if
-        // we resolved to the method referenced by the instruction.
-        method_idx = resolved_method->GetDexMethodIndex();
-        target_method = MethodReference(dex_file_, method_idx);
-      }
+    if (optimized_invoke_type == kStatic) {
+      clinit_check = ProcessClinitCheckForInvoke(dex_pc, method_idx, &clinit_check_requirement);
     }
 
     HInvokeStaticOrDirect::DispatchInfo dispatch_info = {
@@ -914,26 +847,24 @@ bool HGraphBuilder::BuildInvoke(const Instruction& instruction,
                                                 method_idx,
                                                 target_method,
                                                 dispatch_info,
-                                                invoke_type,
-                                                invoke_type,
+                                                original_invoke_type,
+                                                optimized_invoke_type,
                                                 clinit_check_requirement);
-  } else if (invoke_type == kVirtual) {
-    ScopedObjectAccess soa(Thread::Current());  // Needed for the method index
+  } else if (optimized_invoke_type == kVirtual) {
     invoke = new (arena_) HInvokeVirtual(arena_,
                                          number_of_arguments,
                                          return_type,
                                          dex_pc,
                                          method_idx,
-                                         resolved_method->GetMethodIndex());
+                                         table_index);
   } else {
-    DCHECK_EQ(invoke_type, kInterface);
-    ScopedObjectAccess soa(Thread::Current());  // Needed for the method index
+    DCHECK_EQ(optimized_invoke_type, kInterface);
     invoke = new (arena_) HInvokeInterface(arena_,
                                            number_of_arguments,
                                            return_type,
                                            dex_pc,
                                            method_idx,
-                                           resolved_method->GetDexMethodIndex());
+                                           table_index);
   }
 
   return HandleInvoke(invoke,
@@ -1031,18 +962,23 @@ bool HGraphBuilder::IsInitialized(Handle<mirror::Class> cls) const {
 
 HClinitCheck* HGraphBuilder::ProcessClinitCheckForInvoke(
       uint32_t dex_pc,
-      ArtMethod* resolved_method,
       uint32_t method_idx,
       HInvokeStaticOrDirect::ClinitCheckRequirement* clinit_check_requirement) {
-  const DexFile& outer_dex_file = *outer_compilation_unit_->GetDexFile();
-  Thread* self = Thread::Current();
-  StackHandleScope<4> hs(self);
+  ScopedObjectAccess soa(Thread::Current());
+  StackHandleScope<5> hs(soa.Self());
   Handle<mirror::DexCache> dex_cache(hs.NewHandle(
       dex_compilation_unit_->GetClassLinker()->FindDexCache(
-          self, *dex_compilation_unit_->GetDexFile())));
+          soa.Self(), *dex_compilation_unit_->GetDexFile())));
+  Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
+      soa.Decode<mirror::ClassLoader*>(dex_compilation_unit_->GetClassLoader())));
+  ArtMethod* resolved_method = compiler_driver_->ResolveMethod(
+      soa, dex_cache, class_loader, dex_compilation_unit_, method_idx, InvokeType::kStatic);
+
+  DCHECK(resolved_method != nullptr);
+
+  const DexFile& outer_dex_file = *outer_compilation_unit_->GetDexFile();
   Handle<mirror::DexCache> outer_dex_cache(hs.NewHandle(
-      outer_compilation_unit_->GetClassLinker()->FindDexCache(
-          self, outer_dex_file)));
+      outer_compilation_unit_->GetClassLinker()->FindDexCache(soa.Self(), outer_dex_file)));
   Handle<mirror::Class> outer_class(hs.NewHandle(GetOutermostCompilingClass()));
   Handle<mirror::Class> resolved_method_class(hs.NewHandle(resolved_method->GetDeclaringClass()));
 
index c3979f3..5ada93f 100644 (file)
@@ -305,10 +305,8 @@ class HGraphBuilder : public ValueObject {
 
   HClinitCheck* ProcessClinitCheckForInvoke(
       uint32_t dex_pc,
-      ArtMethod* method,
       uint32_t method_idx,
-      HInvokeStaticOrDirect::ClinitCheckRequirement* clinit_check_requirement)
-      SHARED_REQUIRES(Locks::mutator_lock_);
+      HInvokeStaticOrDirect::ClinitCheckRequirement* clinit_check_requirement);
 
   // Build a HNewInstance instruction.
   bool BuildNewInstance(uint16_t type_index, uint32_t dex_pc);
@@ -317,10 +315,6 @@ class HGraphBuilder : public ValueObject {
   bool IsInitialized(Handle<mirror::Class> cls) const
       SHARED_REQUIRES(Locks::mutator_lock_);
 
-  // Try to resolve a method using the class linker. Return null if a method could
-  // not be resolved.
-  ArtMethod* ResolveMethod(uint16_t method_idx, InvokeType invoke_type);
-
   ArenaAllocator* const arena_;
 
   // A list of the size of the dex code holding block information for
index 0063aef..a98d9c6 100644 (file)
@@ -5943,16 +5943,12 @@ void CodeGeneratorARM::GenerateVirtualCall(HInvokeVirtual* invoke, Location temp
   Register temp = temp_location.AsRegister<Register>();
   uint32_t method_offset = mirror::Class::EmbeddedVTableEntryOffset(
       invoke->GetVTableIndex(), kArmPointerSize).Uint32Value();
-
-  // Use the calling convention instead of the location of the receiver, as
-  // intrinsics may have put the receiver in a different register. In the intrinsics
-  // slow path, the arguments have been moved to the right place, so here we are
-  // guaranteed that the receiver is the first register of the calling convention.
-  InvokeDexCallingConvention calling_convention;
-  Register receiver = calling_convention.GetRegisterAt(0);
+  LocationSummary* locations = invoke->GetLocations();
+  Location receiver = locations->InAt(0);
   uint32_t class_offset = mirror::Object::ClassOffset().Int32Value();
+  DCHECK(receiver.IsRegister());
   // /* HeapReference<Class> */ temp = receiver->klass_
-  __ LoadFromOffset(kLoadWord, temp, receiver, class_offset);
+  __ LoadFromOffset(kLoadWord, temp, receiver.AsRegister<Register>(), class_offset);
   MaybeRecordImplicitNullCheck(invoke);
   // Instead of simply (possibly) unpoisoning `temp` here, we should
   // emit a read barrier for the previous class reference load.
index 04acd9d..ac16268 100644 (file)
@@ -3618,12 +3618,8 @@ void CodeGeneratorARM64::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invok
 }
 
 void CodeGeneratorARM64::GenerateVirtualCall(HInvokeVirtual* invoke, Location temp_in) {
-  // Use the calling convention instead of the location of the receiver, as
-  // intrinsics may have put the receiver in a different register. In the intrinsics
-  // slow path, the arguments have been moved to the right place, so here we are
-  // guaranteed that the receiver is the first register of the calling convention.
-  InvokeDexCallingConvention calling_convention;
-  Register receiver = calling_convention.GetRegisterAt(0);
+  LocationSummary* locations = invoke->GetLocations();
+  Location receiver = locations->InAt(0);
   Register temp = XRegisterFrom(temp_in);
   size_t method_offset = mirror::Class::EmbeddedVTableEntryOffset(
       invoke->GetVTableIndex(), kArm64PointerSize).SizeValue();
@@ -3634,10 +3630,11 @@ void CodeGeneratorARM64::GenerateVirtualCall(HInvokeVirtual* invoke, Location te
 
   DCHECK(receiver.IsRegister());
   // /* HeapReference<Class> */ temp = receiver->klass_
-  __ Ldr(temp.W(), HeapOperandFrom(LocationFrom(receiver), class_offset));
+  __ Ldr(temp.W(), HeapOperandFrom(receiver, class_offset));
   MaybeRecordImplicitNullCheck(invoke);
   // Instead of simply (possibly) unpoisoning `temp` here, we should
   // emit a read barrier for the previous class reference load.
+  // However this is not required in practice, as this is an
   // intermediate/temporary reference and because the current
   // concurrent copying collector keeps the from-space memory
   // intact/accessible until the end of the marking phase (the
index bc5eb31..934f24b 100644 (file)
@@ -2986,13 +2986,8 @@ void InstructionCodeGeneratorMIPS64::VisitInvokeStaticOrDirect(HInvokeStaticOrDi
 }
 
 void CodeGeneratorMIPS64::GenerateVirtualCall(HInvokeVirtual* invoke, Location temp_location) {
-  // Use the calling convention instead of the location of the receiver, as
-  // intrinsics may have put the receiver in a different register. In the intrinsics
-  // slow path, the arguments have been moved to the right place, so here we are
-  // guaranteed that the receiver is the first register of the calling convention.
-  InvokeDexCallingConvention calling_convention;
-  GpuRegister receiver = calling_convention.GetRegisterAt(0);
-
+  LocationSummary* locations = invoke->GetLocations();
+  Location receiver = locations->InAt(0);
   GpuRegister temp = temp_location.AsRegister<GpuRegister>();
   size_t method_offset = mirror::Class::EmbeddedVTableEntryOffset(
       invoke->GetVTableIndex(), kMips64PointerSize).SizeValue();
@@ -3000,7 +2995,8 @@ void CodeGeneratorMIPS64::GenerateVirtualCall(HInvokeVirtual* invoke, Location t
   Offset entry_point = ArtMethod::EntryPointFromQuickCompiledCodeOffset(kMips64WordSize);
 
   // temp = object->GetClass();
-  __ LoadFromOffset(kLoadUnsignedWord, temp, receiver, class_offset);
+  DCHECK(receiver.IsRegister());
+  __ LoadFromOffset(kLoadUnsignedWord, temp, receiver.AsRegister<GpuRegister>(), class_offset);
   MaybeRecordImplicitNullCheck(invoke);
   // temp = temp->GetMethodAt(method_offset);
   __ LoadFromOffset(kLoadDoubleword, temp, temp, method_offset);
index a8ed06c..1fc09a8 100644 (file)
@@ -1970,11 +1970,6 @@ void InstructionCodeGeneratorX86::VisitInvokeStaticOrDirect(HInvokeStaticOrDirec
 }
 
 void LocationsBuilderX86::VisitInvokeVirtual(HInvokeVirtual* invoke) {
-  IntrinsicLocationsBuilderX86 intrinsic(codegen_);
-  if (intrinsic.TryDispatch(invoke)) {
-    return;
-  }
-
   HandleInvoke(invoke);
 }
 
@@ -4156,16 +4151,12 @@ void CodeGeneratorX86::GenerateVirtualCall(HInvokeVirtual* invoke, Location temp
   Register temp = temp_in.AsRegister<Register>();
   uint32_t method_offset = mirror::Class::EmbeddedVTableEntryOffset(
       invoke->GetVTableIndex(), kX86PointerSize).Uint32Value();
-
-  // Use the calling convention instead of the location of the receiver, as
-  // intrinsics may have put the receiver in a different register. In the intrinsics
-  // slow path, the arguments have been moved to the right place, so here we are
-  // guaranteed that the receiver is the first register of the calling convention.
-  InvokeDexCallingConvention calling_convention;
-  Register receiver = calling_convention.GetRegisterAt(0);
+  LocationSummary* locations = invoke->GetLocations();
+  Location receiver = locations->InAt(0);
   uint32_t class_offset = mirror::Object::ClassOffset().Int32Value();
+  DCHECK(receiver.IsRegister());
   // /* HeapReference<Class> */ temp = receiver->klass_
-  __ movl(temp, Address(receiver, class_offset));
+  __ movl(temp, Address(receiver.AsRegister<Register>(), class_offset));
   MaybeRecordImplicitNullCheck(invoke);
   // Instead of simply (possibly) unpoisoning `temp` here, we should
   // emit a read barrier for the previous class reference load.
index 4618be9..534ee1c 100644 (file)
@@ -802,17 +802,12 @@ void CodeGeneratorX86_64::GenerateVirtualCall(HInvokeVirtual* invoke, Location t
   CpuRegister temp = temp_in.AsRegister<CpuRegister>();
   size_t method_offset = mirror::Class::EmbeddedVTableEntryOffset(
       invoke->GetVTableIndex(), kX86_64PointerSize).SizeValue();
-
-  // Use the calling convention instead of the location of the receiver, as
-  // intrinsics may have put the receiver in a different register. In the intrinsics
-  // slow path, the arguments have been moved to the right place, so here we are
-  // guaranteed that the receiver is the first register of the calling convention.
-  InvokeDexCallingConvention calling_convention;
-  Register receiver = calling_convention.GetRegisterAt(0);
-
+  LocationSummary* locations = invoke->GetLocations();
+  Location receiver = locations->InAt(0);
   size_t class_offset = mirror::Object::ClassOffset().SizeValue();
+  DCHECK(receiver.IsRegister());
   // /* HeapReference<Class> */ temp = receiver->klass_
-  __ movl(temp, Address(CpuRegister(receiver), class_offset));
+  __ movl(temp, Address(receiver.AsRegister<CpuRegister>(), class_offset));
   MaybeRecordImplicitNullCheck(invoke);
   // Instead of simply (possibly) unpoisoning `temp` here, we should
   // emit a read barrier for the previous class reference load.
index 2bff213..48bcd10 100644 (file)
@@ -402,11 +402,6 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor {
     }
   }
 
-  void VisitInvokeVirtual(HInvokeVirtual* invoke) OVERRIDE {
-    VisitInvoke(invoke);
-    StartAttributeStream("intrinsic") << invoke->GetIntrinsic();
-  }
-
   void VisitUnresolvedInstanceFieldGet(HUnresolvedInstanceFieldGet* field_access) OVERRIDE {
     StartAttributeStream("field_type") << field_access->GetFieldType();
   }
index 6d93be3..0363f20 100644 (file)
@@ -192,10 +192,6 @@ bool HInliner::TryInline(HInvoke* invoke_instruction) {
   // We can query the dex cache directly. The verifier has populated it already.
   ArtMethod* resolved_method;
   if (invoke_instruction->IsInvokeStaticOrDirect()) {
-    if (invoke_instruction->AsInvokeStaticOrDirect()->IsStringInit()) {
-      VLOG(compiler) << "Not inlining a String.<init> method";
-      return false;
-    }
     MethodReference ref = invoke_instruction->AsInvokeStaticOrDirect()->GetTargetMethod();
     mirror::DexCache* const dex_cache = (&caller_dex_file == ref.dex_file)
         ? caller_compilation_unit_.GetDexCache().Get()
index 8340811..b01324e 100644 (file)
@@ -384,7 +384,7 @@ static bool CheckInvokeType(Intrinsics intrinsic, HInvoke* invoke, const DexFile
   // InvokeStaticOrDirect.
   InvokeType intrinsic_type = GetIntrinsicInvokeType(intrinsic);
   InvokeType invoke_type = invoke->IsInvokeStaticOrDirect() ?
-      invoke->AsInvokeStaticOrDirect()->GetOptimizedInvokeType() :
+      invoke->AsInvokeStaticOrDirect()->GetInvokeType() :
       invoke->IsInvokeVirtual() ? kVirtual : kSuper;
   switch (intrinsic_type) {
     case kStatic:
index 2c2fc8c..d5110a7 100644 (file)
@@ -3418,7 +3418,7 @@ class HInvokeStaticOrDirect : public HInvoke {
                         MethodReference target_method,
                         DispatchInfo dispatch_info,
                         InvokeType original_invoke_type,
-                        InvokeType optimized_invoke_type,
+                        InvokeType invoke_type,
                         ClinitCheckRequirement clinit_check_requirement)
       : HInvoke(arena,
                 number_of_arguments,
@@ -3432,7 +3432,7 @@ class HInvokeStaticOrDirect : public HInvoke {
                 dex_pc,
                 method_index,
                 original_invoke_type),
-        optimized_invoke_type_(optimized_invoke_type),
+        invoke_type_(invoke_type),
         clinit_check_requirement_(clinit_check_requirement),
         target_method_(target_method),
         dispatch_info_(dispatch_info) { }
@@ -3478,11 +3478,7 @@ class HInvokeStaticOrDirect : public HInvoke {
   // platform-specific special input, such as PC-relative addressing base.
   uint32_t GetSpecialInputIndex() const { return GetNumberOfArguments(); }
 
-  InvokeType GetOptimizedInvokeType() const { return optimized_invoke_type_; }
-  void SetOptimizedInvokeType(InvokeType invoke_type) {
-    optimized_invoke_type_ = invoke_type;
-  }
-
+  InvokeType GetInvokeType() const { return invoke_type_; }
   MethodLoadKind GetMethodLoadKind() const { return dispatch_info_.method_load_kind; }
   CodePtrLocation GetCodePtrLocation() const { return dispatch_info_.code_ptr_location; }
   bool IsRecursive() const { return GetMethodLoadKind() == MethodLoadKind::kRecursive; }
@@ -3505,7 +3501,6 @@ class HInvokeStaticOrDirect : public HInvoke {
   }
   bool HasDirectCodePtr() const { return GetCodePtrLocation() == CodePtrLocation::kCallDirect; }
   MethodReference GetTargetMethod() const { return target_method_; }
-  void SetTargetMethod(MethodReference method) { target_method_ = method; }
 
   int32_t GetStringInitOffset() const {
     DCHECK(IsStringInit());
@@ -3531,7 +3526,7 @@ class HInvokeStaticOrDirect : public HInvoke {
 
   // Is this instruction a call to a static method?
   bool IsStatic() const {
-    return GetOriginalInvokeType() == kStatic;
+    return GetInvokeType() == kStatic;
   }
 
   // Remove the HClinitCheck or the replacement HLoadClass (set as last input by
@@ -3604,7 +3599,7 @@ class HInvokeStaticOrDirect : public HInvoke {
   void RemoveInputAt(size_t index);
 
  private:
-  InvokeType optimized_invoke_type_;
+  const InvokeType invoke_type_;
   ClinitCheckRequirement clinit_check_requirement_;
   // The target method may refer to different dex file or method index than the original
   // invoke. This happens for sharpened calls and for calls where a method was redeclared
index 5e1d1d9..a128079 100644 (file)
@@ -49,8 +49,7 @@ void HSharpening::ProcessInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) {
   }
 
   // TODO: Avoid CompilerDriver.
-  InvokeType original_invoke_type = invoke->GetOriginalInvokeType();
-  InvokeType optimized_invoke_type = original_invoke_type;
+  InvokeType invoke_type = invoke->GetOriginalInvokeType();
   MethodReference target_method(&graph_->GetDexFile(), invoke->GetDexMethodIndex());
   int vtable_idx;
   uintptr_t direct_code, direct_method;
@@ -59,18 +58,15 @@ void HSharpening::ProcessInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) {
       invoke->GetDexPc(),
       false /* update_stats: already updated in builder */,
       true /* enable_devirtualization */,
-      &optimized_invoke_type,
+      &invoke_type,
       &target_method,
       &vtable_idx,
       &direct_code,
       &direct_method);
-  if (!success) {
-    // TODO: try using kDexCachePcRelative. It's always a valid method load
-    // kind as long as it's supported by the codegen
-    return;
-  }
-  invoke->SetOptimizedInvokeType(optimized_invoke_type);
-  invoke->SetTargetMethod(target_method);
+  DCHECK(success);
+  DCHECK_EQ(invoke_type, invoke->GetInvokeType());
+  DCHECK_EQ(target_method.dex_file, invoke->GetTargetMethod().dex_file);
+  DCHECK_EQ(target_method.dex_method_index, invoke->GetTargetMethod().dex_method_index);
 
   HInvokeStaticOrDirect::MethodLoadKind method_load_kind;
   HInvokeStaticOrDirect::CodePtrLocation code_ptr_location;
index dccb1da..21e4e44 100644 (file)
@@ -598,12 +598,8 @@ inline ArtMethod* FindMethodFast(uint32_t method_idx, mirror::Object* this_objec
   } else if (type == kStatic || type == kDirect) {
     return resolved_method;
   } else if (type == kSuper) {
-    mirror::Class* super_class = referrer->GetDeclaringClass()->GetSuperClass();
-    if (resolved_method->GetMethodIndex() >= super_class->GetVTableLength()) {
-      // The super class does not have the method.
-      return nullptr;
-    }
-    return super_class->GetVTableEntry(resolved_method->GetMethodIndex(), sizeof(void*));
+    return referrer->GetDeclaringClass()->GetSuperClass()->GetVTableEntry(
+        resolved_method->GetMethodIndex(), sizeof(void*));
   } else {
     DCHECK(type == kVirtual);
     return this_object->GetClass()->GetVTableEntry(
index 5080f14..6dce96c 100644 (file)
@@ -19,25 +19,23 @@ public final class Main {
   public void invokeVirtual() {
   }
 
-  /// CHECK-START: void Main.inlineSharpenInvokeVirtual(Main) builder (after)
-  /// CHECK-DAG:     <<Invoke:v\d+>>  InvokeVirtual
+  /// CHECK-START: void Main.inlineSharpenInvokeVirtual(Main) inliner (before)
+  /// CHECK-DAG:     <<Invoke:v\d+>>  InvokeStaticOrDirect
   /// CHECK-DAG:                      ReturnVoid
 
   /// CHECK-START: void Main.inlineSharpenInvokeVirtual(Main) inliner (after)
-  /// CHECK-NOT:                      InvokeVirtual
   /// CHECK-NOT:                      InvokeStaticOrDirect
 
   public static void inlineSharpenInvokeVirtual(Main m) {
     m.invokeVirtual();
   }
 
-  /// CHECK-START: int Main.inlineSharpenStringInvoke() ssa_builder (after)
-  /// CHECK-DAG:     <<Invoke:i\d+>>  InvokeVirtual
+  /// CHECK-START: int Main.inlineSharpenStringInvoke() inliner (before)
+  /// CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
   /// CHECK-DAG:                      Return [<<Invoke>>]
 
   /// CHECK-START: int Main.inlineSharpenStringInvoke() inliner (after)
   /// CHECK-NOT:                      InvokeStaticOrDirect
-  /// CHECK-NOT:                      InvokeVirtual
 
   /// CHECK-START: int Main.inlineSharpenStringInvoke() inliner (after)
   /// CHECK-DAG:     <<Field:i\d+>>   InstanceFieldGet
index 42b331f..b0014d7 100644 (file)
@@ -2,4 +2,4 @@ Hello from clinit
 java.lang.Exception
        at ForceStatic.<clinit>(Main.java:24)
        at Main.$inline$foo(Main.java:31)
-       at Main.main(Main.java:50)
+       at Main.main(Main.java:48)
index a8b6307..9a45485 100644 (file)
@@ -31,17 +31,15 @@ public class Main implements Itf {
     int a = ForceStatic.field;
   }
 
-  /// CHECK-START: void Main.main(java.lang.String[]) ssa_builder (after)
+  /// CHECK-START: void Main.main(java.lang.String[]) inliner (before)
+  /// CHECK:           InvokeStaticOrDirect
   /// CHECK:           InvokeStaticOrDirect
-  /// CHECK:           InvokeInterface
 
   /// CHECK-START: void Main.main(java.lang.String[]) inliner (before)
   /// CHECK-NOT:       ClinitCheck
 
   /// CHECK-START: void Main.main(java.lang.String[]) inliner (after)
   /// CHECK-NOT:       InvokeStaticOrDirect
-  /// CHECK-NOT:       InvokeVirtual
-  /// CHECK-NOT:       InvokeInterface
 
   /// CHECK-START: void Main.main(java.lang.String[]) inliner (after)
   /// CHECK:           ClinitCheck
index 3f65d5a..1b784ae 100644 (file)
@@ -35,7 +35,7 @@ public class Main {
   }
 
   /// CHECK-START: boolean Main.stringEqualsNull() register (after)
-  /// CHECK:      <<Invoke:z\d+>> InvokeVirtual
+  /// CHECK:      <<Invoke:z\d+>> InvokeStaticOrDirect
   /// CHECK:      Return [<<Invoke>>]
   public static boolean stringEqualsNull() {
     String o = (String)myObject;
@@ -47,7 +47,7 @@ public class Main {
   }
 
   /// CHECK-START-X86: boolean Main.stringArgumentNotNull(java.lang.Object) disassembly (after)
-  /// CHECK:          InvokeVirtual
+  /// CHECK:          InvokeStaticOrDirect
   /// CHECK-NOT:      test
   public static boolean stringArgumentNotNull(Object obj) {
     obj.getClass();
@@ -56,7 +56,7 @@ public class Main {
 
   // Test is very brittle as it depends on the order we emit instructions.
   /// CHECK-START-X86: boolean Main.stringArgumentIsString() disassembly (after)
-  /// CHECK:      InvokeVirtual
+  /// CHECK:      InvokeStaticOrDirect
   /// CHECK:      test
   /// CHECK:      jz/eq
   // Check that we don't try to compare the classes.
diff --git a/test/551-invoke-super/expected.txt b/test/551-invoke-super/expected.txt
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/test/551-invoke-super/info.txt b/test/551-invoke-super/info.txt
deleted file mode 100644 (file)
index 864ddfe..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Tests the invoke-super opcode when resolving to an abstract method.
diff --git a/test/551-invoke-super/smali/invokesuper.smali b/test/551-invoke-super/smali/invokesuper.smali
deleted file mode 100644 (file)
index ad3c218..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#
-# 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.
-
-
-.class public LInvokeSuper;
-.super LSuperClass;
-
-.method public constructor <init>()V
-.registers 1
-    invoke-direct {v0}, LSuperClass;-><init>()V
-    return-void
-.end method
-
-
-.method public run()I
-.registers 2
-    # Do an invoke super on a non-super class to force complex resolution.
-    invoke-super {v1}, LInvokeSuper;->returnInt()I
-    move-result v0
-    return v0
-.end method
-
-
-.method public returnInt()I
-.registers 2
-    const v0, 777
-    return v0
-.end method
diff --git a/test/551-invoke-super/smali/superclass.smali b/test/551-invoke-super/smali/superclass.smali
deleted file mode 100644 (file)
index 47fbee7..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-#
-# 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.
-
-.class abstract public LSuperClass;
-.super Ljava/lang/Object;
-
-.method public constructor <init>()V
-.registers 1
-    invoke-direct {v0}, Ljava/lang/Object;-><init>()V
-    return-void
-.end method
-
-.method abstract public returnInt()I
-.end method
diff --git a/test/551-invoke-super/src/Main.java b/test/551-invoke-super/src/Main.java
deleted file mode 100644 (file)
index 3a30184..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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.
- */
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-public class Main {
-  // Workaround for b/18051191.
-  class InnerClass {}
-
-  public static void main(String[] args) throws Exception {
-    Class<?> c = Class.forName("InvokeSuper");
-    try {
-      Method m = c.getMethod("run");
-      m.invoke(c.newInstance(), new Object[0]);
-      throw new Error("Expected AbstractMethodError");
-    } catch (InvocationTargetException e) {
-      if (!(e.getCause() instanceof AbstractMethodError)) {
-        throw new Error("Expected AbstractMethodError");
-      }
-    }
-  }
-}
diff --git a/test/552-invoke-non-existent-super/expected.txt b/test/552-invoke-non-existent-super/expected.txt
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/test/552-invoke-non-existent-super/info.txt b/test/552-invoke-non-existent-super/info.txt
deleted file mode 100644 (file)
index c5428d4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Tests the invoke-super opcode when the super class does not have the method.
diff --git a/test/552-invoke-non-existent-super/smali/invokesuper.smali b/test/552-invoke-non-existent-super/smali/invokesuper.smali
deleted file mode 100644 (file)
index ad3c218..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#
-# 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.
-
-
-.class public LInvokeSuper;
-.super LSuperClass;
-
-.method public constructor <init>()V
-.registers 1
-    invoke-direct {v0}, LSuperClass;-><init>()V
-    return-void
-.end method
-
-
-.method public run()I
-.registers 2
-    # Do an invoke super on a non-super class to force complex resolution.
-    invoke-super {v1}, LInvokeSuper;->returnInt()I
-    move-result v0
-    return v0
-.end method
-
-
-.method public returnInt()I
-.registers 2
-    const v0, 777
-    return v0
-.end method
diff --git a/test/552-invoke-non-existent-super/smali/superclass.smali b/test/552-invoke-non-existent-super/smali/superclass.smali
deleted file mode 100644 (file)
index 21d961e..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#
-# 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.
-
-.class abstract public LSuperClass;
-.super Ljava/lang/Object;
-
-.method public constructor <init>()V
-.registers 1
-    invoke-direct {v0}, Ljava/lang/Object;-><init>()V
-    return-void
-.end method
diff --git a/test/552-invoke-non-existent-super/src/Main.java b/test/552-invoke-non-existent-super/src/Main.java
deleted file mode 100644 (file)
index c264471..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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.
- */
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-public class Main {
-  // Workaround for b/18051191.
-  class InnerClass {}
-
-  public static void main(String[] args) throws Exception {
-    Class<?> c = Class.forName("InvokeSuper");
-    try {
-      Method m = c.getMethod("run");
-      m.invoke(c.newInstance(), new Object[0]);
-      throw new Error("Expected NoSuchMethodError");
-    } catch (InvocationTargetException e) {
-      if (!(e.getCause() instanceof NoSuchMethodError)) {
-        throw new Error("Expected NoSuchMethodError");
-      }
-    }
-  }
-}