ART: Fix call site resolution
Parameter type resolution should use the target method's DEX file.
Bug: 70166093
Test: art/test/run-test --host 714
Change-Id: Ic4961a905144ee85b36d02476506c4078c6cdf7a
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 32d3040..ae707f0 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -8368,7 +8368,6 @@
mirror::MethodHandle* ClassLinker::ResolveMethodHandleForMethod(
Thread* self,
- const DexFile* const dex_file,
const DexFile::MethodHandleItem& method_handle,
ArtMethod* referrer) {
DexFile::MethodHandleType handle_type =
@@ -8492,19 +8491,20 @@
return nullptr;
}
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache()));
- Handle<mirror::ClassLoader> class_loader(hs.NewHandle(referrer->GetClassLoader()));
int32_t index = 0;
-
if (receiver_count != 0) {
// Insert receiver
method_params->Set(index++, target_method->GetDeclaringClass());
}
-
- DexFileParameterIterator it(*dex_file, target_method->GetPrototype());
+ DexFileParameterIterator it(*target_method->GetDexFile(), target_method->GetPrototype());
+ Handle<mirror::DexCache> target_method_dex_cache(hs.NewHandle(target_method->GetDexCache()));
+ Handle<mirror::ClassLoader> target_method_class_loader(hs.NewHandle(target_method->GetClassLoader()));
while (it.HasNext()) {
+ DCHECK_LT(index, num_params);
const dex::TypeIndex type_idx = it.GetTypeIdx();
- ObjPtr<mirror::Class> klass = ResolveType(type_idx, dex_cache, class_loader);
+ ObjPtr<mirror::Class> klass = ResolveType(type_idx,
+ target_method_dex_cache,
+ target_method_class_loader);
if (nullptr == klass) {
DCHECK(self->IsExceptionPending());
return nullptr;
@@ -8554,7 +8554,7 @@
case DexFile::MethodHandleType::kInvokeConstructor:
case DexFile::MethodHandleType::kInvokeDirect:
case DexFile::MethodHandleType::kInvokeInterface:
- return ResolveMethodHandleForMethod(self, dex_file, method_handle, referrer);
+ return ResolveMethodHandleForMethod(self, method_handle, referrer);
}
}
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 3e3425f..16fa1ce 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -979,7 +979,6 @@
REQUIRES_SHARED(Locks::mutator_lock_);
mirror::MethodHandle* ResolveMethodHandleForMethod(Thread* self,
- const DexFile* const dex_file,
const DexFile::MethodHandleItem& method_handle,
ArtMethod* referrer)
REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index d53da21..12b8c38 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -1183,10 +1183,9 @@
}
Handle<mirror::Object> object(hs.NewHandle(result.GetL()));
-
- // Check the result is not null.
if (UNLIKELY(object.IsNull())) {
- ThrowNullPointerException("CallSite == null");
+ // This will typically be for LambdaMetafactory which is not supported.
+ ThrowNullPointerException("Bootstrap method returned null");
return nullptr;
}
@@ -1202,7 +1201,7 @@
// Check the call site target is not null as we're going to invoke it.
Handle<mirror::MethodHandle> target = hs.NewHandle(call_site->GetTarget());
if (UNLIKELY(target.IsNull())) {
- ThrowNullPointerException("CallSite target == null");
+ ThrowNullPointerException("Target for call-site is null");
return nullptr;
}
diff --git a/test/710-varhandle-creation/src-art/Main.java b/test/710-varhandle-creation/src-art/Main.java
index a737b5b..246aac6 100644
--- a/test/710-varhandle-creation/src-art/Main.java
+++ b/test/710-varhandle-creation/src-art/Main.java
@@ -1,21 +1,17 @@
/*
- * Copyright 2017 Google Inc.
+ * Copyright (C) 2018 The Android Open Source Project
*
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Google designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Google in the LICENSE file that accompanied this code.
+ * 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
*
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 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.invoke.MethodHandles;
diff --git a/test/714-invoke-custom-lambda-metafactory/build b/test/714-invoke-custom-lambda-metafactory/build
new file mode 100644
index 0000000..b5002ba
--- /dev/null
+++ b/test/714-invoke-custom-lambda-metafactory/build
@@ -0,0 +1,22 @@
+#!/bin/bash
+#
+# Copyright 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.
+
+# Make us exit on a failure
+set -e
+
+# Opt-out from desugaring to ensure offending lambda is in the DEX.
+export USE_DESUGAR=false
+./default-build "$@" --experimental method-handles
diff --git a/test/714-invoke-custom-lambda-metafactory/expected.txt b/test/714-invoke-custom-lambda-metafactory/expected.txt
new file mode 100644
index 0000000..cbe9840
--- /dev/null
+++ b/test/714-invoke-custom-lambda-metafactory/expected.txt
@@ -0,0 +1,4 @@
+Exception in thread "main" java.lang.BootstrapMethodError: Exception from call site #0 bootstrap method
+ at Main.main(Main.java:25)
+Caused by: java.lang.NullPointerException: Bootstrap method returned null
+ ... 1 more
diff --git a/test/714-invoke-custom-lambda-metafactory/info.txt b/test/714-invoke-custom-lambda-metafactory/info.txt
new file mode 100644
index 0000000..4ef117b
--- /dev/null
+++ b/test/714-invoke-custom-lambda-metafactory/info.txt
@@ -0,0 +1 @@
+Checks that ART doesn't crash when it encounters LambdaMetafactory.
diff --git a/test/714-invoke-custom-lambda-metafactory/src/Main.java b/test/714-invoke-custom-lambda-metafactory/src/Main.java
new file mode 100644
index 0000000..74e0ad4
--- /dev/null
+++ b/test/714-invoke-custom-lambda-metafactory/src/Main.java
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+
+public class Main {
+ public static void main(String[] args) {
+ int requiredLength = 3;
+ List<String> list = Arrays.asList("A", "B", "C", "D", "EEE");
+ Optional<String> result = list.stream().filter(x -> x.length() >= requiredLength).findAny();
+ if (result.isPresent()) {
+ System.out.println("Result is " + result.get());
+ } else {
+ System.out.println("Result is not there.");
+ }
+ }
+}