Snap for 11698527 from 4d45b8613f650acb36df41a6e970a9694ae464a2 to mainline-appsearch-release Change-Id: Iddb7532ccd29c651d2d6dcec4618bc9a6ac65ecb
diff --git a/Android.mk b/Android.mk index d560276..5c7f19d 100644 --- a/Android.mk +++ b/Android.mk
@@ -531,7 +531,9 @@ lib64/libicuuc.so \ PRIVATE_STATSD_APEX_DEPENDENCY_LIBS := \ + lib/libstatspull.so \ lib/libstatssocket.so \ + lib64/libstatspull.so \ lib64/libstatssocket.so \ # Extracts files from an APEX into a location. The APEX can be either a .apex
diff --git a/artd/art_standalone_artd_tests.xml b/artd/art_standalone_artd_tests.xml index 8a48b84..468b200 100644 --- a/artd/art_standalone_artd_tests.xml +++ b/artd/art_standalone_artd_tests.xml
@@ -43,7 +43,6 @@ <option name="mainline-module-package-name" value="com.android.art" /> </object> - <!-- Only run tests if the device under test is SDK version 31 (Android 12) or above. --> - <!-- TODO(jiakaiz): Change this to U once `ro.build.version.sdk` is bumped. --> - <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" /> + <!-- Only run tests if the device under test is SDK version 34 (Android 14) or above. --> + <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk34ModuleController" /> </configuration>
diff --git a/build/apex/Android.bp b/build/apex/Android.bp index d5349b6..bf8f461 100644 --- a/build/apex/Android.bp +++ b/build/apex/Android.bp
@@ -326,6 +326,11 @@ apex_defaults { name: "com.android.art-devel-defaults", defaults: ["com.android.art-device-defaults"], + // Use a different manifest for the Debug & Testing ART APEXes (which have + // no prebuilts and are thus always built from sources), with a high version + // number that ensures that these packages can be installed on virtually all + // Android dessert releases. + manifest: "manifest-art-debug.json", native_shared_libs: art_runtime_base_native_device_only_debug_shared_libs + art_runtime_run_test_libs + art_runtime_debug_native_shared_libs + @@ -630,3 +635,53 @@ src: "linker.config.json", installable: false, } + +// sdk module types have 3 (maybe 4 for windows?) variants: linux, android, and common_os. +// common_os depends on the linux/android variants and packages their artifacts into a zip file. +// We want access to that zip file in art_release_zip, so we need to depend on only the common_os +// variant of art-module-host-exports, which is what sdk_genrule does. Since sdk_genrule only has +// 1 variant, we can then depend on it from a different type of genrule like regular genrule. +sdk_genrule { + name: "art-module-host-exports-for-genrule", + defaults: ["art_module_source_build_genrule_defaults"], + srcs: [":art-module-host-exports"], + out: ["art-module-host-exports-current.zip"], + cmd: "cp $(in) $(out)", +} + +// A zip containing ART binaries and ART bootclasspath jars. +// At the time of writing, this is only for Compiler Explorer (https://godbolt.org). +genrule { + name: "art_release_zip", + defaults: ["art_module_source_build_genrule_defaults"], + srcs: [ + ":art-module-host-exports-for-genrule", + ":com.android.art", + ], + out: [ + "art_release.zip", + ], + tools: [ + "deapexer", + "debugfs", + "fsck.erofs", + "merge_zips", + "soong_zip", + ], + cmd: "$(location deapexer) " + + "--debugfs_path $(location debugfs) " + + "--fsckerofs_path $(location fsck.erofs) " + + "extract $(location :com.android.art) $(genDir)/extracted && " + + + "$(location soong_zip) -o $(out).tmp -P bootjars -j " + + "-f $(genDir)/extracted/javalib/core-oj.jar " + + "-f $(genDir)/extracted/javalib/core-libart.jar " + + "-f $(genDir)/extracted/javalib/okhttp.jar " + + "-f $(genDir)/extracted/javalib/bouncycastle.jar " + + "-f $(genDir)/extracted/javalib/apache-xml.jar && " + + + "$(location merge_zips) $(out) $(out).tmp $(location :art-module-host-exports-for-genrule)", + dist: { + targets: ["droidcore"], + }, +}
diff --git a/build/apex/manifest-art-debug.json b/build/apex/manifest-art-debug.json new file mode 100644 index 0000000..5eee90c --- /dev/null +++ b/build/apex/manifest-art-debug.json
@@ -0,0 +1,17 @@ +{ + // LINT.IfChange + "name": "com.android.art", + + // High version number that ensures that packages using this manifest (Debug + // ART APEX, Testing ART APEX) can be installed on virtually all Android + // dessert releases. + "version": 990091000, + + "provideNativeLibs": [ + "libjdwp.so" + ], + "requireNativeLibs": [ + "libicu_jni.so" + ] + // LINT.ThenChange(manifest-art.json) +}
diff --git a/build/apex/manifest-art.json b/build/apex/manifest-art.json index 4f20be6..83e2950 100644 --- a/build/apex/manifest-art.json +++ b/build/apex/manifest-art.json
@@ -1,4 +1,5 @@ { + // LINT.IfChange "name": "com.android.art", // Placeholder module version to be replaced during build. @@ -11,4 +12,5 @@ "requireNativeLibs": [ "libicu_jni.so" ] + // LINT.ThenChange(manifest-art-debug.json) }
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc index fee9091..f50fcf3 100644 --- a/compiler/optimizing/instruction_builder.cc +++ b/compiler/optimizing/instruction_builder.cc
@@ -1364,8 +1364,7 @@ method_reference, resolved_method, resolved_method_reference, - proto_idx, - !graph_->IsDebuggable()); + proto_idx); if (!HandleInvoke(invoke, operands, shorty, /* is_unresolved= */ false)) { return false; }
diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc index d2dbaa3..6307f92 100644 --- a/compiler/optimizing/intrinsics_arm64.cc +++ b/compiler/optimizing/intrinsics_arm64.cc
@@ -700,7 +700,8 @@ bool is_volatile, CodeGeneratorARM64* codegen) { LocationSummary* locations = invoke->GetLocations(); - DCHECK((type == DataType::Type::kInt32) || + DCHECK((type == DataType::Type::kInt8) || + (type == DataType::Type::kInt32) || (type == DataType::Type::kInt64) || (type == DataType::Type::kReference)); Location base_loc = locations->InAt(1); @@ -791,6 +792,9 @@ void IntrinsicLocationsBuilderARM64::VisitUnsafeGetObjectVolatile(HInvoke* invoke) { VisitJdkUnsafeGetObjectVolatile(invoke); } +void IntrinsicLocationsBuilderARM64::VisitUnsafeGetByte(HInvoke* invoke) { + VisitJdkUnsafeGetByte(invoke); +} void IntrinsicLocationsBuilderARM64::VisitJdkUnsafeGet(HInvoke* invoke) { CreateIntIntIntToIntLocations(allocator_, invoke); @@ -819,6 +823,9 @@ void IntrinsicLocationsBuilderARM64::VisitJdkUnsafeGetObjectAcquire(HInvoke* invoke) { CreateIntIntIntToIntLocations(allocator_, invoke); } +void IntrinsicLocationsBuilderARM64::VisitJdkUnsafeGetByte(HInvoke* invoke) { + CreateIntIntIntToIntLocations(allocator_, invoke); +} void IntrinsicCodeGeneratorARM64::VisitUnsafeGet(HInvoke* invoke) { VisitJdkUnsafeGet(invoke); @@ -838,6 +845,9 @@ void IntrinsicCodeGeneratorARM64::VisitUnsafeGetObjectVolatile(HInvoke* invoke) { VisitJdkUnsafeGetObjectVolatile(invoke); } +void IntrinsicCodeGeneratorARM64::VisitUnsafeGetByte(HInvoke* invoke) { + VisitJdkUnsafeGetByte(invoke); +} void IntrinsicCodeGeneratorARM64::VisitJdkUnsafeGet(HInvoke* invoke) { GenUnsafeGet(invoke, DataType::Type::kInt32, /*is_volatile=*/ false, codegen_); @@ -866,6 +876,9 @@ void IntrinsicCodeGeneratorARM64::VisitJdkUnsafeGetObjectAcquire(HInvoke* invoke) { GenUnsafeGet(invoke, DataType::Type::kReference, /*is_volatile=*/ true, codegen_); } +void IntrinsicCodeGeneratorARM64::VisitJdkUnsafeGetByte(HInvoke* invoke) { + GenUnsafeGet(invoke, DataType::Type::kInt8, /*is_volatile=*/ false, codegen_); +} static void CreateIntIntIntIntToVoid(ArenaAllocator* allocator, HInvoke* invoke) { LocationSummary* locations = @@ -903,6 +916,9 @@ void IntrinsicLocationsBuilderARM64::VisitUnsafePutLongVolatile(HInvoke* invoke) { VisitJdkUnsafePutLongVolatile(invoke); } +void IntrinsicLocationsBuilderARM64::VisitUnsafePutByte(HInvoke* invoke) { + VisitJdkUnsafePutByte(invoke); +} void IntrinsicLocationsBuilderARM64::VisitJdkUnsafePut(HInvoke* invoke) { CreateIntIntIntIntToVoid(allocator_, invoke); @@ -940,6 +956,9 @@ void IntrinsicLocationsBuilderARM64::VisitJdkUnsafePutLongRelease(HInvoke* invoke) { CreateIntIntIntIntToVoid(allocator_, invoke); } +void IntrinsicLocationsBuilderARM64::VisitJdkUnsafePutByte(HInvoke* invoke) { + CreateIntIntIntIntToVoid(allocator_, invoke); +} static void GenUnsafePut(HInvoke* invoke, DataType::Type type, @@ -1008,6 +1027,9 @@ void IntrinsicCodeGeneratorARM64::VisitUnsafePutLongVolatile(HInvoke* invoke) { VisitJdkUnsafePutLongVolatile(invoke); } +void IntrinsicCodeGeneratorARM64::VisitUnsafePutByte(HInvoke* invoke) { + VisitJdkUnsafePutByte(invoke); +} void IntrinsicCodeGeneratorARM64::VisitJdkUnsafePut(HInvoke* invoke) { GenUnsafePut(invoke, @@ -1093,6 +1115,13 @@ /*is_ordered=*/ false, codegen_); } +void IntrinsicCodeGeneratorARM64::VisitJdkUnsafePutByte(HInvoke* invoke) { + GenUnsafePut(invoke, + DataType::Type::kInt8, + /*is_volatile=*/ false, + /*is_ordered=*/ false, + codegen_); +} static void CreateUnsafeCASLocations(ArenaAllocator* allocator, HInvoke* invoke) { const bool can_call = gUseReadBarrier && IsUnsafeCASObject(invoke);
diff --git a/compiler/optimizing/intrinsics_arm_vixl.cc b/compiler/optimizing/intrinsics_arm_vixl.cc index 266b5bc..22c51c6 100644 --- a/compiler/optimizing/intrinsics_arm_vixl.cc +++ b/compiler/optimizing/intrinsics_arm_vixl.cc
@@ -2902,6 +2902,14 @@ VisitJdkUnsafeGetObjectVolatile(invoke); } +void IntrinsicLocationsBuilderARMVIXL::VisitUnsafeGetByte(HInvoke* invoke) { + VisitJdkUnsafeGetByte(invoke); +} + +void IntrinsicCodeGeneratorARMVIXL::VisitUnsafeGetByte(HInvoke* invoke) { + VisitJdkUnsafeGetByte(invoke); +} + void IntrinsicLocationsBuilderARMVIXL::VisitJdkUnsafeGet(HInvoke* invoke) { CreateUnsafeGetLocations(invoke, codegen_, DataType::Type::kInt32, /*atomic=*/ false); } @@ -2983,6 +2991,15 @@ invoke, codegen_, DataType::Type::kReference, std::memory_order_acquire, /*atomic=*/ true); } +void IntrinsicLocationsBuilderARMVIXL::VisitJdkUnsafeGetByte(HInvoke* invoke) { + CreateUnsafeGetLocations(invoke, codegen_, DataType::Type::kInt8, /*atomic=*/ false); +} + +void IntrinsicCodeGeneratorARMVIXL::VisitJdkUnsafeGetByte(HInvoke* invoke) { + GenUnsafeGet( + invoke, codegen_, DataType::Type::kInt8, std::memory_order_relaxed, /*atomic=*/ false); +} + static void GenerateIntrinsicSet(CodeGeneratorARMVIXL* codegen, DataType::Type type, std::memory_order order, @@ -3203,6 +3220,14 @@ VisitJdkUnsafePutLongVolatile(invoke); } +void IntrinsicLocationsBuilderARMVIXL::VisitUnsafePutByte(HInvoke* invoke) { + VisitJdkUnsafePutByte(invoke); +} + +void IntrinsicCodeGeneratorARMVIXL::VisitUnsafePutByte(HInvoke* invoke) { + VisitJdkUnsafePutByte(invoke); +} + void IntrinsicLocationsBuilderARMVIXL::VisitJdkUnsafePut(HInvoke* invoke) { CreateUnsafePutLocations(invoke, codegen_, DataType::Type::kInt32, /*atomic=*/ false); } @@ -3215,6 +3240,18 @@ codegen_); } +void IntrinsicLocationsBuilderARMVIXL::VisitJdkUnsafePutByte(HInvoke* invoke) { + CreateUnsafePutLocations(invoke, codegen_, DataType::Type::kInt8, /*atomic=*/ false); +} + +void IntrinsicCodeGeneratorARMVIXL::VisitJdkUnsafePutByte(HInvoke* invoke) { + GenUnsafePut(invoke, + DataType::Type::kInt8, + std::memory_order_relaxed, + /*atomic=*/ false, + codegen_); +} + void IntrinsicLocationsBuilderARMVIXL::VisitJdkUnsafePutOrdered(HInvoke* invoke) { CreateUnsafePutLocations(invoke, codegen_, DataType::Type::kInt32, /*atomic=*/ true); }
diff --git a/compiler/optimizing/intrinsics_x86.cc b/compiler/optimizing/intrinsics_x86.cc index d207220..345e9c6 100644 --- a/compiler/optimizing/intrinsics_x86.cc +++ b/compiler/optimizing/intrinsics_x86.cc
@@ -1691,6 +1691,12 @@ Location output_loc = locations->Out(); switch (type) { + case DataType::Type::kInt8: { + Register output = output_loc.AsRegister<Register>(); + __ movsxb(output, Address(base, offset, ScaleFactor::TIMES_1, 0)); + break; + } + case DataType::Type::kInt32: { Register output = output_loc.AsRegister<Register>(); __ movl(output, Address(base, offset, ScaleFactor::TIMES_1, 0)); @@ -1802,7 +1808,9 @@ void IntrinsicLocationsBuilderX86::VisitUnsafeGetObjectVolatile(HInvoke* invoke) { VisitJdkUnsafeGetObjectVolatile(invoke); } - +void IntrinsicLocationsBuilderX86::VisitUnsafeGetByte(HInvoke* invoke) { + VisitJdkUnsafeGetByte(invoke); +} void IntrinsicCodeGeneratorX86::VisitUnsafeGet(HInvoke* invoke) { VisitJdkUnsafeGet(invoke); @@ -1822,7 +1830,9 @@ void IntrinsicCodeGeneratorX86::VisitUnsafeGetObjectVolatile(HInvoke* invoke) { VisitJdkUnsafeGetObjectVolatile(invoke); } - +void IntrinsicCodeGeneratorX86::VisitUnsafeGetByte(HInvoke* invoke) { + VisitJdkUnsafeGetByte(invoke); +} void IntrinsicLocationsBuilderX86::VisitJdkUnsafeGet(HInvoke* invoke) { CreateIntIntIntToIntLocations( @@ -1856,6 +1866,10 @@ CreateIntIntIntToIntLocations( allocator_, invoke, DataType::Type::kReference, /*is_volatile=*/ true); } +void IntrinsicLocationsBuilderX86::VisitJdkUnsafeGetByte(HInvoke* invoke) { + CreateIntIntIntToIntLocations( + allocator_, invoke, DataType::Type::kInt8, /*is_volatile=*/ false); +} void IntrinsicCodeGeneratorX86::VisitJdkUnsafeGet(HInvoke* invoke) { GenUnsafeGet(invoke, DataType::Type::kInt32, /*is_volatile=*/ false, codegen_); @@ -1884,6 +1898,9 @@ void IntrinsicCodeGeneratorX86::VisitJdkUnsafeGetObjectAcquire(HInvoke* invoke) { GenUnsafeGet(invoke, DataType::Type::kReference, /*is_volatile=*/ true, codegen_); } +void IntrinsicCodeGeneratorX86::VisitJdkUnsafeGetByte(HInvoke* invoke) { + GenUnsafeGet(invoke, DataType::Type::kInt8, /*is_volatile=*/ false, codegen_); +} static void CreateIntIntIntIntToVoidPlusTempsLocations(ArenaAllocator* allocator, DataType::Type type, @@ -1933,6 +1950,9 @@ void IntrinsicLocationsBuilderX86::VisitUnsafePutLongVolatile(HInvoke* invoke) { VisitJdkUnsafePutLongVolatile(invoke); } +void IntrinsicLocationsBuilderX86::VisitUnsafePutByte(HInvoke* invoke) { + VisitJdkUnsafePutByte(invoke); +} void IntrinsicLocationsBuilderX86::VisitJdkUnsafePut(HInvoke* invoke) { CreateIntIntIntIntToVoidPlusTempsLocations( @@ -1982,6 +2002,10 @@ CreateIntIntIntIntToVoidPlusTempsLocations( allocator_, DataType::Type::kInt64, invoke, /*is_volatile=*/ true); } +void IntrinsicLocationsBuilderX86::VisitJdkUnsafePutByte(HInvoke* invoke) { + CreateIntIntIntIntToVoidPlusTempsLocations( + allocator_, DataType::Type::kInt8, invoke, /*is_volatile=*/ false); +} // We don't care for ordered: it requires an AnyStore barrier, which is already given by the x86 // memory model. @@ -2058,6 +2082,9 @@ void IntrinsicCodeGeneratorX86::VisitUnsafePutLongVolatile(HInvoke* invoke) { VisitJdkUnsafePutLongVolatile(invoke); } +void IntrinsicCodeGeneratorX86::VisitUnsafePutByte(HInvoke* invoke) { + VisitJdkUnsafePutByte(invoke); +} void IntrinsicCodeGeneratorX86::VisitJdkUnsafePut(HInvoke* invoke) { GenUnsafePut(invoke->GetLocations(), DataType::Type::kInt32, /*is_volatile=*/ false, codegen_); @@ -2099,6 +2126,9 @@ void IntrinsicCodeGeneratorX86::VisitJdkUnsafePutLongRelease(HInvoke* invoke) { GenUnsafePut(invoke->GetLocations(), DataType::Type::kInt64, /*is_volatile=*/ true, codegen_); } +void IntrinsicCodeGeneratorX86::VisitJdkUnsafePutByte(HInvoke* invoke) { + GenUnsafePut(invoke->GetLocations(), DataType::Type::kInt8, /*is_volatile=*/ false, codegen_); +} static void CreateIntIntIntIntIntToInt(ArenaAllocator* allocator, DataType::Type type,
diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc index 9d0d5f1..56bf5ea 100644 --- a/compiler/optimizing/intrinsics_x86_64.cc +++ b/compiler/optimizing/intrinsics_x86_64.cc
@@ -1883,6 +1883,10 @@ CpuRegister output = output_loc.AsRegister<CpuRegister>(); switch (type) { + case DataType::Type::kInt8: + __ movsxb(output, Address(base, offset, ScaleFactor::TIMES_1, 0)); + break; + case DataType::Type::kInt32: __ movl(output, Address(base, offset, ScaleFactor::TIMES_1, 0)); break; @@ -1965,6 +1969,9 @@ void IntrinsicLocationsBuilderX86_64::VisitUnsafeGetObjectVolatile(HInvoke* invoke) { VisitJdkUnsafeGetObjectVolatile(invoke); } +void IntrinsicLocationsBuilderX86_64::VisitUnsafeGetByte(HInvoke* invoke) { + VisitJdkUnsafeGetByte(invoke); +} void IntrinsicLocationsBuilderX86_64::VisitJdkUnsafeGet(HInvoke* invoke) { CreateIntIntIntToIntLocations(allocator_, invoke); @@ -1993,7 +2000,9 @@ void IntrinsicLocationsBuilderX86_64::VisitJdkUnsafeGetObjectAcquire(HInvoke* invoke) { CreateIntIntIntToIntLocations(allocator_, invoke); } - +void IntrinsicLocationsBuilderX86_64::VisitJdkUnsafeGetByte(HInvoke* invoke) { + CreateIntIntIntToIntLocations(allocator_, invoke); +} void IntrinsicCodeGeneratorX86_64::VisitUnsafeGet(HInvoke* invoke) { VisitJdkUnsafeGet(invoke); @@ -2013,6 +2022,9 @@ void IntrinsicCodeGeneratorX86_64::VisitUnsafeGetObjectVolatile(HInvoke* invoke) { VisitJdkUnsafeGetObjectVolatile(invoke); } +void IntrinsicCodeGeneratorX86_64::VisitUnsafeGetByte(HInvoke* invoke) { + VisitJdkUnsafeGetByte(invoke); +} void IntrinsicCodeGeneratorX86_64::VisitJdkUnsafeGet(HInvoke* invoke) { GenUnsafeGet(invoke, DataType::Type::kInt32, /*is_volatile=*/ false, codegen_); @@ -2041,7 +2053,9 @@ void IntrinsicCodeGeneratorX86_64::VisitJdkUnsafeGetObjectAcquire(HInvoke* invoke) { GenUnsafeGet(invoke, DataType::Type::kReference, /*is_volatile=*/ true, codegen_); } - +void IntrinsicCodeGeneratorX86_64::VisitJdkUnsafeGetByte(HInvoke* invoke) { + GenUnsafeGet(invoke, DataType::Type::kInt8, /*is_volatile=*/false, codegen_); +} static void CreateIntIntIntIntToVoidPlusTempsLocations(ArenaAllocator* allocator, DataType::Type type, @@ -2086,6 +2100,9 @@ void IntrinsicLocationsBuilderX86_64::VisitUnsafePutLongVolatile(HInvoke* invoke) { VisitJdkUnsafePutLongVolatile(invoke); } +void IntrinsicLocationsBuilderX86_64::VisitUnsafePutByte(HInvoke* invoke) { + VisitJdkUnsafePut(invoke); +} void IntrinsicLocationsBuilderX86_64::VisitJdkUnsafePut(HInvoke* invoke) { CreateIntIntIntIntToVoidPlusTempsLocations(allocator_, DataType::Type::kInt32, invoke); @@ -2123,6 +2140,9 @@ void IntrinsicLocationsBuilderX86_64::VisitJdkUnsafePutLongRelease(HInvoke* invoke) { CreateIntIntIntIntToVoidPlusTempsLocations(allocator_, DataType::Type::kInt64, invoke); } +void IntrinsicLocationsBuilderX86_64::VisitJdkUnsafePutByte(HInvoke* invoke) { + CreateIntIntIntIntToVoidPlusTempsLocations(allocator_, DataType::Type::kUint8, invoke); +} // We don't care for ordered: it requires an AnyStore barrier, which is already given by the x86 // memory model. @@ -2185,6 +2205,9 @@ void IntrinsicCodeGeneratorX86_64::VisitUnsafePutLongVolatile(HInvoke* invoke) { VisitJdkUnsafePutLongVolatile(invoke); } +void IntrinsicCodeGeneratorX86_64::VisitUnsafePutByte(HInvoke* invoke) { + VisitJdkUnsafePutByte(invoke); +} void IntrinsicCodeGeneratorX86_64::VisitJdkUnsafePut(HInvoke* invoke) { GenUnsafePut(invoke->GetLocations(), DataType::Type::kInt32, /*is_volatile=*/ false, codegen_); @@ -2226,6 +2249,9 @@ void IntrinsicCodeGeneratorX86_64::VisitJdkUnsafePutLongRelease(HInvoke* invoke) { GenUnsafePut(invoke->GetLocations(), DataType::Type::kInt64, /*is_volatile=*/ true, codegen_); } +void IntrinsicCodeGeneratorX86_64::VisitJdkUnsafePutByte(HInvoke* invoke) { + GenUnsafePut(invoke->GetLocations(), DataType::Type::kInt8, /*is_volatile=*/false, codegen_); +} static void CreateUnsafeCASLocations(ArenaAllocator* allocator, DataType::Type type,
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index 28112d1..e0ff10c 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h
@@ -4859,8 +4859,7 @@ // to pass intrinsic information to the HInvokePolymorphic node. ArtMethod* resolved_method, MethodReference resolved_method_reference, - dex::ProtoIndex proto_idx, - bool enable_intrinsic_opt) + dex::ProtoIndex proto_idx) : HInvoke(kInvokePolymorphic, allocator, number_of_arguments, @@ -4871,9 +4870,8 @@ resolved_method, resolved_method_reference, kPolymorphic, - enable_intrinsic_opt), - proto_idx_(proto_idx) { - } + /* enable_intrinsic_opt= */ true), + proto_idx_(proto_idx) {} bool IsClonable() const override { return true; }
diff --git a/dex2oat/art_standalone_dex2oat_cts_tests.xml b/dex2oat/art_standalone_dex2oat_cts_tests.xml index a47febe..0a38fef 100644 --- a/dex2oat/art_standalone_dex2oat_cts_tests.xml +++ b/dex2oat/art_standalone_dex2oat_cts_tests.xml
@@ -52,8 +52,6 @@ <test class="com.android.tradefed.testtype.GTest" > <option name="native-test-device-path" value="/data/local/tmp/art_standalone_dex2oat_cts_tests" /> <option name="module-name" value="art_standalone_dex2oat_cts_tests" /> - <option name="ld-library-path-32" value="/apex/com.android.art/lib" /> - <option name="ld-library-path-64" value="/apex/com.android.art/lib64" /> </test> <!-- When this test is run in a Mainline context (e.g. with `mts-tradefed`), only enable it if
diff --git a/dex2oat/driver/compiler_driver.cc b/dex2oat/driver/compiler_driver.cc index df7835d..969b8c0 100644 --- a/dex2oat/driver/compiler_driver.cc +++ b/dex2oat/driver/compiler_driver.cc
@@ -2792,7 +2792,7 @@ const size_t java_alloc = heap->GetBytesAllocated(); oss << "arena alloc=" << PrettySize(max_arena_alloc_) << " (" << max_arena_alloc_ << "B)"; oss << " java alloc=" << PrettySize(java_alloc) << " (" << java_alloc << "B)"; -#if defined(__BIONIC__) || defined(__GLIBC__) +#if defined(__BIONIC__) || defined(__GLIBC__) || defined(ANDROID_HOST_MUSL) const struct mallinfo info = mallinfo(); const size_t allocated_space = static_cast<size_t>(info.uordblks); const size_t free_space = static_cast<size_t>(info.fordblks);
diff --git a/libartservice/service/java/com/android/server/art/ArtJni.java b/libartservice/service/java/com/android/server/art/ArtJni.java index 2cc9ea8..f2868eb 100644 --- a/libartservice/service/java/com/android/server/art/ArtJni.java +++ b/libartservice/service/java/com/android/server/art/ArtJni.java
@@ -56,8 +56,17 @@ return validateClassLoaderContextNative(dexPath, classLoaderContext); } + /** + * Returns the name of the Garbage Collector currently in use in the Android Runtime. + */ + @NonNull + public static String getGarbageCollector() { + return getGarbageCollectorNative(); + } + @Nullable private static native String validateDexPathNative(@NonNull String dexPath); @Nullable private static native String validateClassLoaderContextNative( @NonNull String dexPath, @NonNull String classLoaderContext); + @NonNull private static native String getGarbageCollectorNative(); }
diff --git a/libartservice/service/java/com/android/server/art/Debouncer.java b/libartservice/service/java/com/android/server/art/Debouncer.java index 61aea81..2aa7d0a 100644 --- a/libartservice/service/java/com/android/server/art/Debouncer.java +++ b/libartservice/service/java/com/android/server/art/Debouncer.java
@@ -19,6 +19,8 @@ import android.annotation.NonNull; import android.annotation.Nullable; +import com.android.internal.annotations.GuardedBy; + import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; @@ -32,7 +34,8 @@ public class Debouncer { @NonNull private Supplier<ScheduledExecutorService> mScheduledExecutorFactory; private final long mIntervalMs; - @Nullable private ScheduledFuture<?> mCurrentTask = null; + @GuardedBy("this") @Nullable private ScheduledFuture<?> mCurrentTask = null; + @GuardedBy("this") @Nullable private ScheduledExecutorService mExecutor = null; public Debouncer( long intervalMs, @NonNull Supplier<ScheduledExecutorService> scheduledExecutorFactory) { @@ -40,6 +43,23 @@ mIntervalMs = intervalMs; } + private void runTask(@NonNull Runnable command, @NonNull ScheduledExecutorService executor) { + synchronized (this) { + // In rare cases, at this point, another task may have been scheduled on the same + // executor, and `mExecutor` will be null or a new executor when that task is run, but + // that's okay. Either that task won't pass the check below or it will be cancelled. + // For simplicity, every task only shuts down its own executor. + // We only need to guarantee the following: + // - No new task is scheduled on an executor after the executor is shut down. + // - Every executor is eventually shut down. + if (mExecutor == executor) { + mExecutor.shutdown(); + mExecutor = null; + } + } + command.run(); + } + /** * Runs the given command after the interval has passed. If another command comes in during * this interval, the previous one will never run. @@ -48,8 +68,11 @@ if (mCurrentTask != null) { mCurrentTask.cancel(false /* mayInterruptIfRunning */); } - ScheduledExecutorService executor = mScheduledExecutorFactory.get(); - mCurrentTask = executor.schedule(command, mIntervalMs, TimeUnit.MILLISECONDS); - executor.shutdown(); + if (mExecutor == null) { + mExecutor = mScheduledExecutorFactory.get(); + } + ScheduledExecutorService executor = mExecutor; + mCurrentTask = mExecutor.schedule( + () -> runTask(command, executor), mIntervalMs, TimeUnit.MILLISECONDS); } }
diff --git a/libartservice/service/java/com/android/server/art/DexUseManagerLocal.java b/libartservice/service/java/com/android/server/art/DexUseManagerLocal.java index c73f71b..b9d0afe 100644 --- a/libartservice/service/java/com/android/server/art/DexUseManagerLocal.java +++ b/libartservice/service/java/com/android/server/art/DexUseManagerLocal.java
@@ -1173,7 +1173,7 @@ @NonNull public ScheduledExecutorService createScheduledExecutor() { - return Executors.newSingleThreadScheduledExecutor(); + return Executors.newScheduledThreadPool(1 /* corePoolSize */); } @NonNull
diff --git a/libartservice/service/java/com/android/server/art/DumpHelper.java b/libartservice/service/java/com/android/server/art/DumpHelper.java index 2a640ec..70d7f8c 100644 --- a/libartservice/service/java/com/android/server/art/DumpHelper.java +++ b/libartservice/service/java/com/android/server/art/DumpHelper.java
@@ -75,6 +75,7 @@ .stream() .sorted(Comparator.comparing(PackageState::getPackageName)) .forEach(pkgState -> dumpPackage(pw, snapshot, pkgState)); + pw.printf("\nCurrent GC: %s\n", ArtJni.getGarbageCollector()); } /**
diff --git a/libartservice/service/java/com/android/server/art/ReasonMapping.java b/libartservice/service/java/com/android/server/art/ReasonMapping.java index 7c64abf..2a1c81b 100644 --- a/libartservice/service/java/com/android/server/art/ReasonMapping.java +++ b/libartservice/service/java/com/android/server/art/ReasonMapping.java
@@ -188,13 +188,14 @@ /** * Loads the concurrency from the system property, for batch dexopt ({@link - * ArtManagerLocal#dexoptPackages}), or 1 if the system property is not found or cannot be - * parsed. + * ArtManagerLocal#dexoptPackages}). The default is tuned to strike a good balance between + * device load and dexopt coverage, depending on the situation. * * @hide */ public static int getConcurrencyForReason(@NonNull @BatchDexoptReason String reason) { return SystemProperties.getInt("persist.device_config.runtime." + reason + "_concurrency", - SystemProperties.getInt("pm.dexopt." + reason + ".concurrency", 1 /* def */)); + SystemProperties.getInt("pm.dexopt." + reason + ".concurrency", + reason.equals(REASON_BG_DEXOPT) ? 4 : 1 /* def */)); } }
diff --git a/libartservice/service/javatests/com/android/server/art/DebouncerTest.java b/libartservice/service/javatests/com/android/server/art/DebouncerTest.java index bf0bc70..cf6eee4 100644 --- a/libartservice/service/javatests/com/android/server/art/DebouncerTest.java +++ b/libartservice/service/javatests/com/android/server/art/DebouncerTest.java
@@ -61,5 +61,13 @@ mMockClock.advanceTime(1000); assertThat(list).containsExactly(2, 5).inOrder(); + + // Verify that we don't create too many executors, and all the executors we create are + // eventually shut down. + List<MockClock.ScheduledExecutor> executors = mMockClock.getCreatedExecutors(); + assertThat(executors).hasSize(2); + for (MockClock.ScheduledExecutor executor : executors) { + assertThat(executor.isShutdown()).isTrue(); + } } }
diff --git a/libartservice/service/javatests/com/android/server/art/DumpHelperTest.java b/libartservice/service/javatests/com/android/server/art/DumpHelperTest.java index 3833249..5dbe213 100644 --- a/libartservice/service/javatests/com/android/server/art/DumpHelperTest.java +++ b/libartservice/service/javatests/com/android/server/art/DumpHelperTest.java
@@ -62,7 +62,7 @@ @Rule public StaticMockitoRule mockitoRule = - new StaticMockitoRule(SystemProperties.class, Constants.class); + new StaticMockitoRule(SystemProperties.class, Constants.class, ArtJni.class); @Mock private DumpHelper.Injector mInjector; @Mock private ArtManagerLocal mArtManagerLocal; @@ -83,6 +83,8 @@ .when(SystemProperties.get(argThat(arg -> arg.startsWith("ro.dalvik.vm.isa.")))) .thenReturn(""); + lenient().when(ArtJni.getGarbageCollector()).thenReturn("CollectorTypeCMC"); + lenient().when(mInjector.getArtManagerLocal()).thenReturn(mArtManagerLocal); lenient().when(mInjector.getDexUseManager()).thenReturn(mDexUseManagerLocal); lenient().when(mInjector.getArtd()).thenReturn(mArtd); @@ -132,7 +134,9 @@ + " arm: [status=verify] [reason=install] [primary-abi]\n" + " [location is /data/app/bar/oat/arm/base.odex]\n" + " arm64: [status=verify] [reason=install]\n" - + " [location is /data/app/bar/oat/arm64/base.odex]\n"; + + " [location is /data/app/bar/oat/arm64/base.odex]\n" + + "\n" + + "Current GC: CollectorTypeCMC\n"; var stringWriter = new StringWriter(); mDumpHelper.dump(new PrintWriter(stringWriter), mSnapshot);
diff --git a/libartservice/service/javatests/com/android/server/art/testing/MockClock.java b/libartservice/service/javatests/com/android/server/art/testing/MockClock.java index 7b4b23b..fb77f09 100644 --- a/libartservice/service/javatests/com/android/server/art/testing/MockClock.java +++ b/libartservice/service/javatests/com/android/server/art/testing/MockClock.java
@@ -50,6 +50,11 @@ } } + @NonNull + public List<ScheduledExecutor> getCreatedExecutors() { + return mExecutors; + } + public class ScheduledExecutor extends ScheduledThreadPoolExecutor { // The second element of the pair is the scheduled time. @NonNull
diff --git a/libartservice/service/native/service.cc b/libartservice/service/native/service.cc index 7d223e5..5901efd 100644 --- a/libartservice/service/native/service.cc +++ b/libartservice/service/native/service.cc
@@ -24,7 +24,9 @@ #include "android-base/file.h" #include "android-base/result.h" #include "class_loader_context.h" +#include "gc/heap.h" #include "nativehelper/utils.h" +#include "runtime.h" namespace art { namespace service { @@ -76,6 +78,10 @@ return {}; } +std::string GetGarbageCollector() { + return Runtime::Current()->GetHeap()->GetForegroundCollectorName(); +} + extern "C" JNIEXPORT jstring JNICALL Java_com_android_server_art_ArtJni_validateDexPathNative(JNIEnv* env, jobject, jstring j_dex_path) { std::string dex_path(GET_UTF_OR_RETURN(env, j_dex_path)); @@ -116,5 +122,10 @@ return nullptr; } +extern "C" JNIEXPORT jstring JNICALL +Java_com_android_server_art_ArtJni_getGarbageCollectorNative(JNIEnv* env, jobject) { + return CREATE_UTF_OR_RETURN(env, GetGarbageCollector()).release(); +} + } // namespace service } // namespace art
diff --git a/libartservice/service/native/service.h b/libartservice/service/native/service.h index 7f43f17..85c7dcd 100644 --- a/libartservice/service/native/service.h +++ b/libartservice/service/native/service.h
@@ -34,6 +34,8 @@ android::base::Result<void> ValidateDexPath(const std::string& dex_path); +std::string GetGarbageCollector(); + } // namespace service } // namespace art
diff --git a/libartservice/service/native/service_test.cc b/libartservice/service/native/service_test.cc index 8300bf5..d1d429e 100644 --- a/libartservice/service/native/service_test.cc +++ b/libartservice/service/native/service_test.cc
@@ -17,6 +17,7 @@ #include "service.h" #include "android-base/result-gmock.h" +#include "common_runtime_test.h" #include "gtest/gtest.h" namespace art { @@ -106,6 +107,12 @@ HasError(WithMessage("Path '/a/\0/b.apk' has invalid character '\\0'"s))); } +class ArtServiceGcTest : public CommonRuntimeTest {}; + +TEST_F(ArtServiceGcTest, GetGarbageCollector) { + EXPECT_THAT(GetGarbageCollector(), testing::HasSubstr("CollectorType")); +} + } // namespace } // namespace service } // namespace art
diff --git a/libdexfile/dex/dex_file-inl.h b/libdexfile/dex/dex_file-inl.h index d9c5211..cc2f641 100644 --- a/libdexfile/dex/dex_file-inl.h +++ b/libdexfile/dex/dex_file-inl.h
@@ -319,7 +319,14 @@ // Emit what was previously there, if anything if (local_in_reg[reg].is_live_) { local_in_reg[reg].end_address_ = address; - new_local_callback(local_in_reg[reg]); + // Parameters with generic types cannot be encoded in the debug_info_item header. So d8 + // encodes it as null in the header with start and end address as 0. There will be a + // START_LOCAL_EXTENDED that will declare the parameter with correct signature + // Debuggers get confused when they see empty ranges. So don't emit them. + // See b/297843934 for more details. + if (local_in_reg[reg].end_address_ != 0) { + new_local_callback(local_in_reg[reg]); + } } local_in_reg[reg].name_ = index_to_string_data(name_idx);
diff --git a/libnativebridge/tests/Android.bp b/libnativebridge/tests/Android.bp index b2d29f1..dc6965f 100644 --- a/libnativebridge/tests/Android.bp +++ b/libnativebridge/tests/Android.bp
@@ -82,14 +82,13 @@ defaults: ["libnativebridge-test-case-defaults"], } -cc_defaults { - name: "libnativebridge-tests-defaults", +cc_test { + name: "libnativebridge-tests", defaults: [ "art_defaults", "art_test_defaults", ], - // TODO(mast): Split up art_gtest_defaults so that it can be used for the - // following without pulling in lots of libs. + target: { linux: { cflags: [ @@ -100,11 +99,6 @@ ], }, }, -} - -cc_test { - name: "libnativebridge-tests", - defaults: ["libnativebridge-tests-defaults"], // native_bridge.cc doesn't support reloading the native bridge after // unloading, so each test needs to be its own process. @@ -154,35 +148,14 @@ header_libs: ["libbase_headers"], } -// Variant of libnativebridge-tests that is part of CTS to verify backed-by API -// coverage. +// Very basic tests in CTS to verify backed-by API coverage of the exported API +// in libnativebridge.map.txt. cc_test { name: "art_libnativebridge_cts_tests", - defaults: [ - "art_standalone_test_defaults", - "libnativebridge-tests-defaults", - ], - - // TODO(b/189484095): Pick only a subset of the tests in - // libnativebridge-tests that don't require the native bridge lib to be - // loaded, to avoid the problems with test_per_src and pushing the extra - // libnativebridge*-test-case.so files to device through tradefed. - srcs: [ - // ValidNameNativeBridge_test.cpp needs to be first due to global state - // had_error that isn't reset between tests. - "ValidNameNativeBridge_test.cpp", - "NeedsNativeBridge_test.cpp", - "UnavailableNativeBridge_test.cpp", - ], - static_libs: [ - "libdl_android", - "libnativebridge", - ], - shared_libs: [ - "liblog", - ], - header_libs: ["libbase_headers"], - + defaults: ["art_standalone_test_defaults"], + shared_libs: ["libnativebridge"], + static_libs: ["libbase"], + srcs: ["libnativebridge_api_test.cpp"], test_config_template: ":art-gtests-target-standalone-cts-template", test_suites: [ "cts", @@ -194,12 +167,10 @@ cc_test { name: "libnativebridge-lazy-tests", - defaults: ["libnativebridge-tests-defaults"], - host_supported: false, - test_suites: ["device-tests"], + defaults: ["art_standalone_test_defaults"], static_libs: [ "libbase", "libnativebridge_lazy", ], - srcs: ["libnativebridge_lazy_test.cpp"], + srcs: ["libnativebridge_api_test.cpp"], }
diff --git a/libnativebridge/tests/libnativebridge_lazy_test.cpp b/libnativebridge/tests/libnativebridge_api_test.cpp similarity index 74% rename from libnativebridge/tests/libnativebridge_lazy_test.cpp rename to libnativebridge/tests/libnativebridge_api_test.cpp index e1d66f5..037587c 100644 --- a/libnativebridge/tests/libnativebridge_lazy_test.cpp +++ b/libnativebridge/tests/libnativebridge_api_test.cpp
@@ -21,33 +21,34 @@ namespace android { -class NativeBridgeLazyTest : public ::testing::Test {}; +class NativeBridgeApiTest : public ::testing::Test {}; +// Test the exported API in libnativebridge and libnativebridge_lazy. // The testing we can do here is limited since there's no exported API to // actually load the native bridge, but we only need to test the trivial // wrappers. -TEST_F(NativeBridgeLazyTest, NeedsNativeBridge) { +TEST_F(NativeBridgeApiTest, NeedsNativeBridge) { EXPECT_FALSE(NeedsNativeBridge(ABI_STRING)); } -TEST_F(NativeBridgeLazyTest, PreInitializeNativeBridge) { +TEST_F(NativeBridgeApiTest, PreInitializeNativeBridge) { EXPECT_FALSE(PreInitializeNativeBridge(nullptr, "")); } -TEST_F(NativeBridgeLazyTest, NativeBridgeAvailable) { +TEST_F(NativeBridgeApiTest, NativeBridgeAvailable) { EXPECT_FALSE(NativeBridgeAvailable()); } -TEST_F(NativeBridgeLazyTest, NativeBridgeInitialized) { +TEST_F(NativeBridgeApiTest, NativeBridgeInitialized) { EXPECT_FALSE(NativeBridgeInitialized()); } -TEST_F(NativeBridgeLazyTest, NativeBridgeGetTrampoline) { +TEST_F(NativeBridgeApiTest, NativeBridgeGetTrampoline) { EXPECT_EQ(nullptr, NativeBridgeGetTrampoline(nullptr, nullptr, nullptr, 0)); } -TEST_F(NativeBridgeLazyTest, NativeBridgeGetError) { +TEST_F(NativeBridgeApiTest, NativeBridgeGetError) { EXPECT_STREQ("native bridge is not initialized", NativeBridgeGetError()); }
diff --git a/odrefresh/Android.bp b/odrefresh/Android.bp index 809e18d..071d8ba 100644 --- a/odrefresh/Android.bp +++ b/odrefresh/Android.bp
@@ -168,7 +168,10 @@ "odr_metrics_record.cc", "odr_statslog_android.cc", ], - shared_libs: ["libstatssocket"], + shared_libs: [ + "libstatspull", + "libstatssocket", + ], }, host: { srcs: ["odr_statslog_host.cc"],
diff --git a/runtime/Android.bp b/runtime/Android.bp index 1c4b871..2f655b1 100644 --- a/runtime/Android.bp +++ b/runtime/Android.bp
@@ -444,7 +444,8 @@ ], shared_libs: [ "libdl_android", - "libstatssocket", + "libstatspull", // for pulled atoms + "libstatssocket", // for pulled atoms "libz", // For adler32. "heapprofd_client_api", ], @@ -1061,6 +1062,7 @@ export_generated_headers: ["statslog_art.h"], shared_libs: [ "liblog", + "libstatspull", "libstatssocket", "libutils", ],
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 4e18987..a5a9e9c 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc
@@ -2234,7 +2234,10 @@ // boot image method optimization. We need to disable it before doing // ResetCounter below, as counters of shared memory method always hold the // "hot" value. - if (runtime->GetJITOptions()->GetProfileSaverOptions().GetProfileBootClassPath()) { + // For debuggable runtimes we don't use AOT code, so don't use shared memory + // optimization so the methods can be JITed better. + if (runtime->GetJITOptions()->GetProfileSaverOptions().GetProfileBootClassPath() || + runtime->IsJavaDebuggable()) { header.VisitPackedArtMethods([&](ArtMethod& method) REQUIRES_SHARED(Locks::mutator_lock_) { method.ClearMemorySharedMethod(); }, space->Begin(), image_pointer_size_);
diff --git a/runtime/fault_handler.cc b/runtime/fault_handler.cc index 652368c..6f1452e 100644 --- a/runtime/fault_handler.cc +++ b/runtime/fault_handler.cc
@@ -43,12 +43,16 @@ // Static fault manger object accessed by signal handler. FaultManager fault_manager; -// This needs to be NO_INLINE since some debuggers do not read the inline-info to set a breakpoint -// if it isn't. +// These need to be NO_INLINE since some debuggers do not read the inline-info to set a breakpoint +// if they aren't. extern "C" NO_INLINE __attribute__((visibility("default"))) void art_sigsegv_fault() { // Set a breakpoint here to be informed when a SIGSEGV is unhandled by ART. VLOG(signals)<< "Caught unknown SIGSEGV in ART fault handler - chaining to next handler."; } +extern "C" NO_INLINE __attribute__((visibility("default"))) void art_sigbus_fault() { + // Set a breakpoint here to be informed when a SIGBUS is unhandled by ART. + VLOG(signals) << "Caught unknown SIGBUS in ART fault handler - chaining to next handler."; +} // Signal handler called on SIGSEGV. static bool art_sigsegv_handler(int sig, siginfo_t* info, void* context) { @@ -233,7 +237,13 @@ // Simulate a crash in a handler. raise(SIGBUS); #endif - return Runtime::Current()->GetHeap()->MarkCompactCollector()->SigbusHandler(info); + if (Runtime::Current()->GetHeap()->MarkCompactCollector()->SigbusHandler(info)) { + return true; + } + + // Set a breakpoint in this function to catch unhandled signals. + art_sigbus_fault(); + return false; } inline void FaultManager::CheckForUnrecognizedImplicitSuspendCheckInBootImage(
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc index 2d1d393..ab82f14 100644 --- a/runtime/gc/heap.cc +++ b/runtime/gc/heap.cc
@@ -16,20 +16,18 @@ #include "heap.h" +#include <sys/types.h> +#include <unistd.h> + #include <limits> -#include "android-base/thread_annotations.h" -#if defined(__BIONIC__) || defined(__GLIBC__) -#include <malloc.h> // For mallinfo() -#endif #include <memory> #include <random> -#include <unistd.h> -#include <sys/types.h> +#include <sstream> #include <vector> -#include "android-base/stringprintf.h" - #include "allocation_listener.h" +#include "android-base/stringprintf.h" +#include "android-base/thread_annotations.h" #include "art_field-inl.h" #include "backtrace_helper.h" #include "base/allocator.h" @@ -108,6 +106,10 @@ #include "verify_object-inl.h" #include "well_known_classes.h" +#if defined(__BIONIC__) || defined(__GLIBC__) || defined(ANDROID_HOST_MUSL) +#include <malloc.h> // For mallinfo() +#endif + namespace art { #ifdef ART_TARGET_ANDROID @@ -2655,7 +2657,7 @@ size_t Heap::GetNativeBytes() { size_t malloc_bytes; -#if defined(__BIONIC__) || defined(__GLIBC__) +#if defined(__BIONIC__) || defined(__GLIBC__) || defined(ANDROID_HOST_MUSL) IF_GLIBC(size_t mmapped_bytes;) struct mallinfo mi = mallinfo(); // In spite of the documentation, the jemalloc version of this call seems to do what we want, @@ -4758,5 +4760,11 @@ return true; } +std::string Heap::GetForegroundCollectorName() { + std::ostringstream oss; + oss << foreground_collector_type_; + return oss.str(); +} + } // namespace gc } // namespace art
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h index d7f6948..489be37 100644 --- a/runtime/gc/heap.h +++ b/runtime/gc/heap.h
@@ -843,6 +843,7 @@ bool IsMovingGc() const { return IsMovingGc(CurrentCollectorType()); } CollectorType GetForegroundCollectorType() const { return foreground_collector_type_; } + std::string GetForegroundCollectorName(); bool IsGcConcurrentAndMoving() const { if (IsGcConcurrent() && IsMovingGc(collector_type_)) {
diff --git a/runtime/gc/verification.h b/runtime/gc/verification.h index 7a5d01a..a732556 100644 --- a/runtime/gc/verification.h +++ b/runtime/gc/verification.h
@@ -40,7 +40,7 @@ public: explicit Verification(gc::Heap* heap) : heap_(heap) {} - // Dump some reveant to debugging info about an object. + // Dump some debugging-relevant info about an object. std::string DumpObjectInfo(const void* obj, const char* tag) const REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/hidden_api.h b/runtime/hidden_api.h index 281c1f3..531448b 100644 --- a/runtime/hidden_api.h +++ b/runtime/hidden_api.h
@@ -358,9 +358,11 @@ case Intrinsics::kJdkUnsafeGet: case Intrinsics::kJdkUnsafeGetLong: case Intrinsics::kJdkUnsafeGetObject: + case Intrinsics::kJdkUnsafeGetByte: case Intrinsics::kJdkUnsafePutLong: case Intrinsics::kJdkUnsafePut: case Intrinsics::kJdkUnsafePutObject: + case Intrinsics::kJdkUnsafePutByte: return 0u; case Intrinsics::kFP16Ceil: case Intrinsics::kFP16Compare: @@ -376,10 +378,12 @@ case Intrinsics::kFP16Rint: case Intrinsics::kUnsafeGet: case Intrinsics::kUnsafeGetLong: + case Intrinsics::kUnsafeGetByte: case Intrinsics::kUnsafeGetObject: case Intrinsics::kUnsafePutLong: case Intrinsics::kUnsafePut: case Intrinsics::kUnsafePutObject: + case Intrinsics::kUnsafePutByte: return kAccCorePlatformApi; default: // Remaining intrinsics are public API. We DCHECK that in SetIntrinsic().
diff --git a/runtime/intrinsics_list.h b/runtime/intrinsics_list.h index 256cd2e..c4b687e 100644 --- a/runtime/intrinsics_list.h +++ b/runtime/intrinsics_list.h
@@ -221,6 +221,7 @@ V(UnsafeGetObjectVolatile, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getObjectVolatile", "(Ljava/lang/Object;J)Ljava/lang/Object;") \ V(UnsafeGetLong, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getLong", "(Ljava/lang/Object;J)J") \ V(UnsafeGetLongVolatile, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getLongVolatile", "(Ljava/lang/Object;J)J") \ + V(UnsafeGetByte, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getByte", "(Ljava/lang/Object;J)B") \ V(UnsafePut, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putInt", "(Ljava/lang/Object;JI)V") \ V(UnsafePutOrdered, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putOrderedInt", "(Ljava/lang/Object;JI)V") \ V(UnsafePutVolatile, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putIntVolatile", "(Ljava/lang/Object;JI)V") \ @@ -230,6 +231,7 @@ V(UnsafePutLong, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putLong", "(Ljava/lang/Object;JJ)V") \ V(UnsafePutLongOrdered, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putOrderedLong", "(Ljava/lang/Object;JJ)V") \ V(UnsafePutLongVolatile, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putLongVolatile", "(Ljava/lang/Object;JJ)V") \ + V(UnsafePutByte, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "putByte", "(Ljava/lang/Object;JB)V") \ V(UnsafeGetAndAddInt, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getAndAddInt", "(Ljava/lang/Object;JI)I") \ V(UnsafeGetAndAddLong, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getAndAddLong", "(Ljava/lang/Object;JJ)J") \ V(UnsafeGetAndSetInt, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getAndSetInt", "(Ljava/lang/Object;JI)I") \ @@ -253,6 +255,7 @@ V(JdkUnsafeGetLong, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "getLong", "(Ljava/lang/Object;J)J") \ V(JdkUnsafeGetLongVolatile, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "getLongVolatile", "(Ljava/lang/Object;J)J") \ V(JdkUnsafeGetLongAcquire, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "getLongAcquire", "(Ljava/lang/Object;J)J") \ + V(JdkUnsafeGetByte, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "getByte", "(Ljava/lang/Object;J)B") \ V(JdkUnsafePut, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "putInt", "(Ljava/lang/Object;JI)V") \ V(JdkUnsafePutOrdered, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "putOrderedInt", "(Ljava/lang/Object;JI)V") \ V(JdkUnsafePutRelease, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "putIntRelease", "(Ljava/lang/Object;JI)V") \ @@ -265,6 +268,7 @@ V(JdkUnsafePutLongOrdered, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "putOrderedLong", "(Ljava/lang/Object;JJ)V") \ V(JdkUnsafePutLongVolatile, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "putLongVolatile", "(Ljava/lang/Object;JJ)V") \ V(JdkUnsafePutLongRelease, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "putLongRelease", "(Ljava/lang/Object;JJ)V") \ + V(JdkUnsafePutByte, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "putByte", "(Ljava/lang/Object;JB)V") \ V(JdkUnsafeGetAndAddInt, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "getAndAddInt", "(Ljava/lang/Object;JI)I") \ V(JdkUnsafeGetAndAddLong, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "getAndAddLong", "(Ljava/lang/Object;JJ)J") \ V(JdkUnsafeGetAndSetInt, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "getAndSetInt", "(Ljava/lang/Object;JI)I") \
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc index 3472c78..b231cce 100644 --- a/runtime/jit/jit.cc +++ b/runtime/jit/jit.cc
@@ -71,7 +71,7 @@ static constexpr uint32_t kJitSlowStressDefaultOptimizeThreshold = kJitStressDefaultOptimizeThreshold / 2; -static constexpr uint32_t kJitDefaultWarmupThreshold = 0x3fff; +static constexpr uint32_t kJitDefaultWarmupThreshold = 0xffff; // Different warm-up threshold constants. These default to the equivalent warmup thresholds divided // by 2, but can be overridden at the command-line. static constexpr uint32_t kJitStressDefaultWarmupThreshold = kJitDefaultWarmupThreshold / 2;
diff --git a/runtime/metrics/statsd.cc b/runtime/metrics/statsd.cc index 2105bdb..6d96c6f 100644 --- a/runtime/metrics/statsd.cc +++ b/runtime/metrics/statsd.cc
@@ -414,18 +414,30 @@ std::unique_ptr<MetricsBackend> CreateStatsdBackend() { return std::make_unique<StatsdBackend>(); } -void ReportDeviceMetrics() { - Runtime* runtime = Runtime::Current(); - int32_t boot_image_status; - if (runtime->GetHeap()->HasBootImageSpace() && !runtime->HasImageWithProfile()) { - boot_image_status = statsd::ART_DEVICE_DATUM_REPORTED__BOOT_IMAGE_STATUS__STATUS_FULL; - } else if (runtime->GetHeap()->HasBootImageSpace() && - runtime->GetHeap()->GetBootImageSpaces()[0]->GetProfileFiles().empty()) { - boot_image_status = statsd::ART_DEVICE_DATUM_REPORTED__BOOT_IMAGE_STATUS__STATUS_MINIMAL; - } else { - boot_image_status = statsd::ART_DEVICE_DATUM_REPORTED__BOOT_IMAGE_STATUS__STATUS_NONE; +AStatsManager_PullAtomCallbackReturn DeviceStatusCallback(int32_t atom_tag, + AStatsEventList* data, + [[maybe_unused]] void* cookie) { + if (atom_tag == statsd::ART_DEVICE_STATUS) { + Runtime* runtime = Runtime::Current(); + int32_t boot_image_status; + if (runtime->GetHeap()->HasBootImageSpace() && !runtime->HasImageWithProfile()) { + boot_image_status = statsd::ART_DEVICE_DATUM_REPORTED__BOOT_IMAGE_STATUS__STATUS_FULL; + } else if (runtime->GetHeap()->HasBootImageSpace() && + runtime->GetHeap()->GetBootImageSpaces()[0]->GetProfileFiles().empty()) { + boot_image_status = statsd::ART_DEVICE_DATUM_REPORTED__BOOT_IMAGE_STATUS__STATUS_MINIMAL; + } else { + boot_image_status = statsd::ART_DEVICE_DATUM_REPORTED__BOOT_IMAGE_STATUS__STATUS_NONE; + } + statsd::addAStatsEvent(data, atom_tag, boot_image_status); + return AStatsManager_PULL_SUCCESS; } - statsd::stats_write(statsd::ART_DEVICE_DATUM_REPORTED, boot_image_status); + + return AStatsManager_PULL_SKIP; +} + +void SetupCallbackForDeviceStatus() { + AStatsManager_setPullAtomCallback( + statsd::ART_DEVICE_STATUS, /*metadata=*/nullptr, DeviceStatusCallback, /*cookie=*/nullptr); } } // namespace metrics
diff --git a/runtime/metrics/statsd.h b/runtime/metrics/statsd.h index cb84825..77c0f1d 100644 --- a/runtime/metrics/statsd.h +++ b/runtime/metrics/statsd.h
@@ -27,10 +27,10 @@ // Statsd is only supported on Android #ifdef __ANDROID__ std::unique_ptr<MetricsBackend> CreateStatsdBackend(); -void ReportDeviceMetrics(); +void SetupCallbackForDeviceStatus(); #else inline std::unique_ptr<MetricsBackend> CreateStatsdBackend() { return nullptr; } -inline void ReportDeviceMetrics() {} +inline void SetupCallbackForDeviceStatus() {} #endif } // namespace metrics
diff --git a/runtime/monitor.cc b/runtime/monitor.cc index 3fed8d4..ef2a137 100644 --- a/runtime/monitor.cc +++ b/runtime/monitor.cc
@@ -14,12 +14,11 @@ * limitations under the License. */ -#include "monitor-inl.h" +#include <android-base/properties.h> #include <vector> #include "android-base/stringprintf.h" - #include "art_method-inl.h" #include "base/logging.h" // For VLOG. #include "base/mutex.h" @@ -32,9 +31,11 @@ #include "dex/dex_file_types.h" #include "dex/dex_instruction-inl.h" #include "entrypoints/entrypoint_utils-inl.h" +#include "gc/verification-inl.h" #include "lock_word-inl.h" #include "mirror/class-inl.h" #include "mirror/object-inl.h" +#include "monitor-inl.h" #include "object_callbacks.h" #include "scoped_thread_state_change-inl.h" #include "stack.h" @@ -42,7 +43,6 @@ #include "thread_list.h" #include "verifier/method_verifier.h" #include "well_known_classes.h" -#include <android-base/properties.h> static_assert(ART_USE_FUTEXES); @@ -1522,18 +1522,29 @@ // not be optimized out. success = stack_visitor->GetVReg(m, dex_reg, kReferenceVReg, &value); if (success) { - ObjPtr<mirror::Object> o = reinterpret_cast<mirror::Object*>(value); - callback(o, callback_context); - break; + mirror::Object* mp = reinterpret_cast<mirror::Object*>(value); + // TODO(b/299577730) Remove the extra checks here once the underlying bug is fixed. + const gc::Verification* v = Runtime::Current()->GetHeap()->GetVerification(); + if (v->IsValidObject(mp)) { + ObjPtr<mirror::Object> o = mp; + callback(o, callback_context); + break; + } else { + LOG(ERROR) << "Encountered bad lock object: " << std::hex << value << std::dec; + success = false; + } } } - DCHECK(success) << "Failed to find/read reference for monitor-enter at dex pc " - << dex_lock_info.dex_pc - << " in method " - << m->PrettyMethod(); if (!success) { - LOG(WARNING) << "Had a lock reported for dex pc " << dex_lock_info.dex_pc - << " but was not able to fetch a corresponding object!"; + LOG(ERROR) << "Failed to find/read reference for monitor-enter at dex pc " + << dex_lock_info.dex_pc << " in method " << m->PrettyMethod(); + if (kIsDebugBuild) { + // Crash only in debug ART builds. + LOG(FATAL) << "Had a lock reported for a dex pc " + "but was not able to fetch a corresponding object!"; + } else { + LOG(ERROR) << "Held monitor information in stack trace will be incomplete!"; + } } } }
diff --git a/runtime/runtime.cc b/runtime/runtime.cc index 7eff246..e225d9e 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc
@@ -1299,7 +1299,7 @@ if (!odrefresh::UploadStatsIfAvailable(&err)) { LOG(WARNING) << "Failed to upload odrefresh metrics: " << err; } - metrics::ReportDeviceMetrics(); + metrics::SetupCallbackForDeviceStatus(); } if (LIKELY(automatically_set_jni_ids_indirection_) && CanSetJniIdType()) { @@ -3333,10 +3333,12 @@ return callbacks_.get(); } -// Used to patch boot image method entry point to interpreter bridge. -class UpdateEntryPointsClassVisitor : public ClassVisitor { +// Used to update boot image to not use AOT code. This is used when transitioning the runtime to +// java debuggable. This visitor re-initializes the entry points without using AOT code. This also +// disables shared hotness counters so the necessary methods can be JITed more efficiently. +class DeoptimizeBootImageClassVisitor : public ClassVisitor { public: - explicit UpdateEntryPointsClassVisitor(instrumentation::Instrumentation* instrumentation) + explicit DeoptimizeBootImageClassVisitor(instrumentation::Instrumentation* instrumentation) : instrumentation_(instrumentation) {} bool operator()(ObjPtr<mirror::Class> klass) override REQUIRES(Locks::mutator_lock_) { @@ -3370,6 +3372,9 @@ m.ClearPreCompiled(); instrumentation_->InitializeMethodsCode(&m, /*aot_code=*/ nullptr); } + + // Clear MemorySharedAccessFlags so the boot class methods can be JITed better. + m.ClearMemorySharedMethod(); } return true; } @@ -3390,7 +3395,7 @@ // If we've already started and we are setting this runtime to debuggable, // we patch entry points of methods in boot image to interpreter bridge, as // boot image code may be AOT compiled as not debuggable. - UpdateEntryPointsClassVisitor visitor(GetInstrumentation()); + DeoptimizeBootImageClassVisitor visitor(GetInstrumentation()); GetClassLinker()->VisitClasses(&visitor); jit::Jit* jit = GetJit(); if (jit != nullptr) {
diff --git a/runtime/trace.cc b/runtime/trace.cc index 81c86f1..20436d6 100644 --- a/runtime/trace.cc +++ b/runtime/trace.cc
@@ -774,6 +774,15 @@ CHECK_IMPLIES(trace_file == nullptr, output_mode == TraceOutputMode::kDDMS); uint16_t trace_version = GetTraceVersion(clock_source_); + + // We initialize the start_time_ from the timestamp counter. This may not match + // with the monotonic timer but we only use this time to calculate the elapsed + // time from this point which should be the same for both cases. + // We record monotonic time at the start of the trace, because Android Studio + // fetches the monotonic timer from other places and matches these times to + // construct a cpu profile. See b/318052824 for more context. + uint64_t start_time_monotonic = start_time_ + (MicroTime() - GetMicroTime(GetTimestamp())); + if (output_mode == TraceOutputMode::kStreaming) { trace_version |= 0xF0U; } @@ -782,7 +791,7 @@ Append4LE(buf_.get(), kTraceMagicValue); Append2LE(buf_.get() + 4, trace_version); Append2LE(buf_.get() + 6, kTraceHeaderLength); - Append8LE(buf_.get() + 8, start_time_); + Append8LE(buf_.get() + 8, start_time_monotonic); if (trace_version >= kTraceVersionDualClock) { uint16_t record_size = GetRecordSize(clock_source_); Append2LE(buf_.get() + 16, record_size);
diff --git a/test/004-UnsafeTest/src/Main.java b/test/004-UnsafeTest/src/Main.java index 9176e89..cfa3691 100644 --- a/test/004-UnsafeTest/src/Main.java +++ b/test/004-UnsafeTest/src/Main.java
@@ -136,6 +136,14 @@ check(t.objectVar, objectValue, "Unsafe.putObject(Object, long, Object)"); check(unsafe.getObject(t, objectOffset), objectValue, "Unsafe.getObject(Object, long)"); + byte byteValue = 123; + Field byteField = TestClass.class.getDeclaredField("byteVar"); + long byteOffset = unsafe.objectFieldOffset(byteField); + check(unsafe.getByte(t, byteOffset), 0, "Unsafe.getByte(Object, long) - initial"); + unsafe.putByte(t, byteOffset, byteValue); + check(t.byteVar, byteValue, "Unsafe.putByte(Object, long, byte)"); + check(unsafe.getByte(t, byteOffset), byteValue, "Unsafe.getByte(Object, long)"); + if (unsafe.compareAndSwapInt(t, intOffset, 0, 1)) { System.out.println("Unexpectedly succeeding compareAndSwapInt(t, intOffset, 0, 1)"); } @@ -288,6 +296,7 @@ public int intVar = 0; public long longVar = 0; public Object objectVar = null; + public byte byteVar = 0; } private static class TestVolatileClass {
diff --git a/test/1911-get-local-var-table/src/art/Test1911.java b/test/1911-get-local-var-table/src/art/Test1911.java index 4dd9054..3e2eec2 100644 --- a/test/1911-get-local-var-table/src/art/Test1911.java +++ b/test/1911-get-local-var-table/src/art/Test1911.java
@@ -18,8 +18,10 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Executable; +import java.lang.Integer; import java.nio.ByteBuffer; import java.util.Arrays; +import java.util.ArrayList; import java.util.Base64; import java.util.HashSet; import java.util.Set; @@ -27,8 +29,8 @@ public class Test1911 { // Class/dex file containing the following class. // - // CLASS_BYTES generated with java version 1.8.0_45: javac -g art/Target.java - // DEX_BYTES generated with dx version 1.14: dx --dex --output=./classes.dex art/Target.class + // CLASS_BYTES generated with java version 17.0.4.1: javac -g art/Target.java + // DEX_BYTES generated with d8 version 8.3.7-dev: d8 --debug art/Target.class // // package art; // import java.util.ArrayList; @@ -53,58 +55,76 @@ // long q = 3 * p; // doNothing(p, q, o, i); // } + // public void testGenericParameters(ArrayList<Integer> array, int i, Integer val) { + // array.set(i, val); + // } // } public static byte[] CLASS_BYTES = Base64.getDecoder().decode( - "yv66vgAAADQARgoABAAuCQANAC8KAA0AMAcAMQY/0zMzMzMzMwoAMgAzCgA0ADUHADYKAAkALgoA" + - "NwA4CgA5ADoHADsBAAN6enoBAAFJAQAGPGluaXQ+AQAEKEkpVgEABENvZGUBAA9MaW5lTnVtYmVy" + - "VGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQAMTGFydC9UYXJnZXQ7AQADeHh4AQAB" + - "cQEACWRvTm90aGluZwEAFihbTGphdmEvbGFuZy9PYmplY3Q7KVYBAARvYmpzAQATW0xqYXZhL2xh" + - "bmcvT2JqZWN0OwEAC2RvU29tZXRoaW5nAQABRgEAAWkBAAFEAQABegEAAXgBAAF5AQABbwEAEkxq" + - "YXZhL2xhbmcvT2JqZWN0OwEAFUxqYXZhL3V0aWwvQXJyYXlMaXN0OwEAAXABAAFKAQAWTG9jYWxW" + - "YXJpYWJsZVR5cGVUYWJsZQEAKkxqYXZhL3V0aWwvQXJyYXlMaXN0PExqYXZhL2xhbmcvSW50ZWdl" + - "cjs+OwEADVN0YWNrTWFwVGFibGUBAApTb3VyY2VGaWxlAQALVGFyZ2V0LmphdmEMABAAPAwADgAP" + - "DAAZABoBABBqYXZhL2xhbmcvT2JqZWN0BwA9DAA+AD8HAEAMAD4AQQEAE2phdmEvdXRpbC9BcnJh" + - "eUxpc3QHAEIMAD4AQwcARAwAPgBFAQAKYXJ0L1RhcmdldAEAAygpVgEAD2phdmEvbGFuZy9GbG9h" + - "dAEAB3ZhbHVlT2YBABQoRilMamF2YS9sYW5nL0Zsb2F0OwEAEGphdmEvbGFuZy9Eb3VibGUBABUo" + - "RClMamF2YS9sYW5nL0RvdWJsZTsBABFqYXZhL2xhbmcvSW50ZWdlcgEAFihJKUxqYXZhL2xhbmcv" + - "SW50ZWdlcjsBAA5qYXZhL2xhbmcvTG9uZwEAEyhKKUxqYXZhL2xhbmcvTG9uZzsAIQANAAQAAAAB" + - "AAEADgAPAAAAAwABABAAEQABABIAAABYAAIAAwAAAA4qtwABGwdoPSoctQACsQAAAAIAEwAAABIA" + - "BAAAAAUABAAGAAgABwANAAgAFAAAACAAAwAAAA4AFQAWAAAAAAAOABcADwABAAgABgAYAA8AAgCJ" + - "ABkAGgABABIAAAAvAAEAAQAAAAUquAADsQAAAAIAEwAAAAYAAQAAAAkAFAAAAAwAAQAAAAUAGwAc" + - "AAAAAQAdABEAAQASAAABWAAFAAgAAACCBL0ABFkDKlO4AAMbBmA9Az4dHBtoogAvHB1khjgEFAAF" + - "FwSNazkFBb0ABFkDFwS4AAdTWQQYBbgACFO4AAOEAwGn/9C7AARZtwABTrsACVm3AAo6BAcbgDYF" + - "BhUFaIU3Bge9AARZAxUFuAALU1kEFga4AAxTWQUtU1kGGQRTuAADsQAAAAQAEwAAADYADQAAAAsA" + - "CwAMAA8ADQAYAA4AHgAPACcAEAA+AA0ARAASAEwAEwBVABQAWgAVAGEAFgCBABcAFAAAAGYACgAe" + - "ACAAGAAeAAQAJwAXAB8AIAAFABEAMwAhAA8AAwAAAIIAFQAWAAAAAACCACIADwABAA8AcwAjAA8A" + - "AgBMADYAJAAlAAMAVQAtAB8AJgAEAFoAKAAnAA8ABQBhACEAGAAoAAYAKQAAAAwAAQBVAC0AHwAq" + - "AAQAKwAAAAoAAv0AEQEB+gAyAAEALAAAAAIALQ=="); + "yv66vgAAADcAUQoABAA2CQAOADcKAA4AOAcAOQY/0zMzMzMzMwoAOgA7CgA8AD0HAD4KAAkANgoA" + + "PwBACgBBAEIKAAkAQwcARAEAA3p6egEAAUkBAAY8aW5pdD4BAAQoSSlWAQAEQ29kZQEAD0xpbmVO" + + "dW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAAxMYXJ0L1RhcmdldDsBAAN4" + + "eHgBAAFxAQAJZG9Ob3RoaW5nAQAWKFtMamF2YS9sYW5nL09iamVjdDspVgEABG9ianMBABNbTGph" + + "dmEvbGFuZy9PYmplY3Q7AQALZG9Tb21ldGhpbmcBAAFGAQABaQEAAUQBAAF6AQABeAEAAXkBAAFv" + + "AQASTGphdmEvbGFuZy9PYmplY3Q7AQAVTGphdmEvdXRpbC9BcnJheUxpc3Q7AQABcAEAAUoBABZM" + + "b2NhbFZhcmlhYmxlVHlwZVRhYmxlAQAqTGphdmEvdXRpbC9BcnJheUxpc3Q8TGphdmEvbGFuZy9J" + + "bnRlZ2VyOz47AQANU3RhY2tNYXBUYWJsZQEAFXRlc3RHZW5lcmljUGFyYW1ldGVycwEALChMamF2" + + "YS91dGlsL0FycmF5TGlzdDtJTGphdmEvbGFuZy9JbnRlZ2VyOylWAQAFYXJyYXkBAAN2YWwBABNM" + + "amF2YS9sYW5nL0ludGVnZXI7AQAJU2lnbmF0dXJlAQBBKExqYXZhL3V0aWwvQXJyYXlMaXN0PExq" + + "YXZhL2xhbmcvSW50ZWdlcjs+O0lMamF2YS9sYW5nL0ludGVnZXI7KVYBAApTb3VyY2VGaWxlAQAL" + + "VGFyZ2V0LmphdmEMABEARQwADwAQDAAaABsBABBqYXZhL2xhbmcvT2JqZWN0BwBGDABHAEgHAEkM" + + "AEcASgEAE2phdmEvdXRpbC9BcnJheUxpc3QHAEsMAEcATAcATQwARwBODABPAFABAAphcnQvVGFy" + + "Z2V0AQADKClWAQAPamF2YS9sYW5nL0Zsb2F0AQAHdmFsdWVPZgEAFChGKUxqYXZhL2xhbmcvRmxv" + + "YXQ7AQAQamF2YS9sYW5nL0RvdWJsZQEAFShEKUxqYXZhL2xhbmcvRG91YmxlOwEAEWphdmEvbGFu" + + "Zy9JbnRlZ2VyAQAWKEkpTGphdmEvbGFuZy9JbnRlZ2VyOwEADmphdmEvbGFuZy9Mb25nAQATKEop" + + "TGphdmEvbGFuZy9Mb25nOwEAA3NldAEAJyhJTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcv" + + "T2JqZWN0OwAhAA4ABAAAAAEAAQAPABAAAAAEAAEAEQASAAEAEwAAAFgAAgADAAAADiq3AAEbB2g9" + + "Khy1AAKxAAAAAgAUAAAAEgAEAAAACAAEAAkACAAKAA0ACwAVAAAAIAADAAAADgAWABcAAAAAAA4A" + + "GAAQAAEACAAGABkAEAACAIkAGgAbAAEAEwAAAC8AAQABAAAABSq4AAOxAAAAAgAUAAAABgABAAAA" + + "DQAVAAAADAABAAAABQAcAB0AAAABAB4AEgABABMAAAFYAAUACAAAAIIEvQAEWQMqU7gAAxsGYD0D" + + "Ph0cG2iiAC8cHWSGOAQUAAUXBI1rOQUFvQAEWQMXBLgAB1NZBBgFuAAIU7gAA4QDAaf/0LsABFm3" + + "AAFOuwAJWbcACjoEBxuANgUGFQVohTcGB70ABFkDFQW4AAtTWQQWBrgADFNZBS1TWQYZBFO4AAOx" + + "AAAABAAUAAAANgANAAAAEAALABEADwASABgAEwAeABQAJwAVAD4AEgBEABcATAAYAFUAGQBaABoA" + + "YQAbAIEAHAAVAAAAZgAKAB4AIAAZAB8ABAAnABcAIAAhAAUAEQAzACIAEAADAAAAggAWABcAAAAA" + + "AIIAIwAQAAEADwBzACQAEAACAEwANgAlACYAAwBVAC0AIAAnAAQAWgAoACgAEAAFAGEAIQAZACkA" + + "BgAqAAAADAABAFUALQAgACsABAAsAAAACgAC/QARAQH6ADIAAQAtAC4AAgATAAAAZgADAAQAAAAI" + + "KxwttgANV7EAAAADABQAAAAKAAIAAAAfAAcAIAAVAAAAKgAEAAAACAAWABcAAAAAAAgALwAnAAEA" + + "AAAIACAAEAACAAAACAAwADEAAwAqAAAADAABAAAACAAvACsAAQAyAAAAAgAzAAEANAAAAAIANQ=="); public static byte[] DEX_BYTES = Base64.getDecoder().decode( - "ZGV4CjAzNQCQtgjEV631Ma/btYyIy2IzqHWNN+nZiwl0BQAAcAAAAHhWNBIAAAAAAAAAANQEAAAk" + - "AAAAcAAAAA0AAAAAAQAABwAAADQBAAABAAAAiAEAAAkAAACQAQAAAQAAANgBAAB8AwAA+AEAAB4D" + - "AAAmAwAAKQMAACwDAAAvAwAAMgMAADYDAAA6AwAAPgMAAEIDAABQAwAAZAMAAHcDAACMAwAAngMA" + - "ALIDAADJAwAA9QMAAAIEAAAFBAAACQQAAA0EAAAiBAAALQQAADoEAAA9BAAAQAQAAEYEAABJBAAA" + - "TAQAAFIEAABbBAAAXgQAAGMEAABmBAAAaQQAAAEAAAACAAAAAwAAAAQAAAAJAAAACgAAAAsAAAAM" + - "AAAADQAAAA4AAAAPAAAAEgAAABUAAAAFAAAABQAAAPgCAAAGAAAABgAAAAADAAAHAAAABwAAAAgD" + - "AAAIAAAACAAAABADAAASAAAACwAAAAAAAAATAAAACwAAAAgDAAAUAAAACwAAABgDAAAEAAIAIwAA" + - "AAQABQAAAAAABAAGABYAAAAEAAUAFwAAAAUAAAAeAAAABgABAB4AAAAHAAIAHgAAAAgAAwAeAAAA" + - "CQAEAAAAAAAKAAQAAAAAAAQAAAABAAAACQAAAAAAAAARAAAAAAAAAL4EAAAAAAAAAwACAAEAAABu" + - "BAAACAAAAHAQBwABANoAAgRZEAAADgABAAEAAQAAAHsEAAAEAAAAcRABAAAADgAQAAIAAgAAAIEE" + - "AABcAAAAEhkjmQwAEgpNDgkKcRABAAkA2AUPAxIIkgkFDzWYJACRCQUIgpYYCjMzMzMzM9M/iWyt" + - "AAoMEikjmQwAEgpxEAQABgAMC00LCQoSGnEgAwAQAAwLTQsJCnEQAQAJANgICAEo2yIDCQBwEAcA" + - "AwAiAgoAcBAIAAIA3gQPBNoJBAOBlhJJI5kMABIKcRAFAAQADAtNCwkKEhpxIAYAdgAMC00LCQoS" + - "Kk0DCQoSOk0CCQpxEAEACQAOAAEAAAAAAAAAAQAAAAEAAAABAAAAAgAAAAEAAAADAAAAAQAAAAwA" + - "Bjxpbml0PgABRAABRgABSQABSgACTEQAAkxGAAJMSQACTEoADExhcnQvVGFyZ2V0OwASTGphdmEv" + - "bGFuZy9Eb3VibGU7ABFMamF2YS9sYW5nL0Zsb2F0OwATTGphdmEvbGFuZy9JbnRlZ2VyOwAQTGph" + - "dmEvbGFuZy9Mb25nOwASTGphdmEvbGFuZy9PYmplY3Q7ABVMamF2YS91dGlsL0FycmF5TGlzdDsA" + - "KkxqYXZhL3V0aWwvQXJyYXlMaXN0PExqYXZhL2xhbmcvSW50ZWdlcjs+OwALVGFyZ2V0LmphdmEA" + - "AVYAAlZJAAJWTAATW0xqYXZhL2xhbmcvT2JqZWN0OwAJZG9Ob3RoaW5nAAtkb1NvbWV0aGluZwAB" + - "aQABbwAEb2JqcwABcAABcQAEdGhpcwAHdmFsdWVPZgABeAADeHh4AAF5AAF6AAN6enoABQEhBw48" + - "LQMAHQMtAAkBGwcOAAsBIAcOli0DBSIDAQEDCCMDSzwDBh0ChwMAGQEBFAtABQAFBloDAxoKWgQC" + - "GQsRLQMEHAM8AwYdBAEaDwAAAQIBAAEAgYAE+AMBiQGYBAIBsAQADQAAAAAAAAABAAAAAAAAAAEA" + - "AAAkAAAAcAAAAAIAAAANAAAAAAEAAAMAAAAHAAAANAEAAAQAAAABAAAAiAEAAAUAAAAJAAAAkAEA" + - "AAYAAAABAAAA2AEAAAEgAAADAAAA+AEAAAEQAAAFAAAA+AIAAAIgAAAkAAAAHgMAAAMgAAADAAAA" + - "bgQAAAAgAAABAAAAvgQAAAAQAAABAAAA1AQAAA=="); - + "ZGV4CjAzNQAALyjG3vy0POIlfGUh9Q7yf3NFwlp6VbWoBwAAcAAAAHhWNBIAAAAAAAAAAOQGAAAz" + + "AAAAcAAAAA8AAAA8AQAACgAAAHgBAAABAAAA8AEAAAwAAAD4AQAAAQAAAFgCAAAwBQAAeAIAACIE" + + "AAAlBAAAKQQAADEEAAA2BAAAOQQAADwEAAA/BAAAQgQAAEYEAABKBAAATgQAAFMEAABXBAAAZQQA" + + "AIQEAACYBAAAqwQAAMAEAADSBAAA5gQAAP0EAAAUBQAAQAUAAE0FAABQBQAAVAUAAFgFAABeBQAA" + + "YQUAAGUFAAB6BQAAgQUAAIwFAACZBQAAnAUAAKMFAACmBQAArAUAAK8FAACyBQAAtwUAAM4FAADT" + + "BQAA2gUAAOMFAADmBQAA6wUAAO4FAADxBQAA9gUAAAQAAAAFAAAABgAAAAcAAAANAAAADgAAAA8A" + + "AAAQAAAAEQAAABIAAAATAAAAFAAAABgAAAAcAAAAHgAAAAgAAAAGAAAA6AMAAAkAAAAHAAAA8AMA" + + "AAoAAAAIAAAA+AMAAAwAAAAJAAAAAAQAAAsAAAAKAAAACAQAABgAAAAMAAAAAAAAABkAAAAMAAAA" + + "+AMAABsAAAAMAAAAEAQAABoAAAAMAAAAHAQAAB0AAAANAAAA6AMAAAQAAgAxAAAABAAGAAIAAAAE" + + "AAgAIAAAAAQABgAhAAAABAAHACkAAAAGAAkAIwAAAAYAAAAsAAAABwABACwAAAAIAAIALAAAAAkA" + + "AwAsAAAACgAFAAIAAAALAAUAAgAAAAsABAAoAAAABAAAAAEAAAAKAAAAAAAAABcAAADMBgAApgYA" + + "AAAAAAADAAIAAQAAAIwDAAAIAAAAcBAJAAEA2gACBFkQAAAOAAEAAQABAAAAmAMAAAQAAABxEAEA" + + "AAAOAA4AAgACAAAAnQMAAFoAAAASECMBDgASAk0MAQJxEAEAAQDYAQ0DEgOSBAENEiU1QyQAkQQB" + + "A4JEGAYzMzMzMzPTP4lIcSAEAJgArQgIBnEQBgAEAAwGcSAFAJgADAcjVQ4ATQYFAk0HBQBxEAEA" + + "BQDYAwMBKNoiAwoAcBAJAAMAIgQLAHAQCgAEAN4GDQTaBwYDgXdxEAcABgAMCXEgCACHAAwKEksj" + + "uw4ATQkLAk0KCwBNAwsFEjBNBAsAcRABAAsADgAEAAQAAwAAANsDAAAEAAAAbjALACEDDgAIAS8O" + + "PC0DACgDLQANASYOABABLg6WLQMBMAMBAQMDMQNaPAMEKAK0AwgjAQERCwUEBQhABQNaAwMlC1oE" + + "BCMMFy0DBicDPAMHKAQBFw8AHwMAIysOBAEgDBc8AAEAAAAAAAAAAQAAAAEAAAABAAAAAgAAAAEA" + + "AAADAAAAAgAAAAIACgADAAAACwACAAgAAAABAAAADgABKAACKVYABjxpbml0PgADPjtJAAFEAAFG" + + "AAFJAAFKAAJMRAACTEYAAkxJAANMSUwAAkxKAAxMYXJ0L1RhcmdldDsAHUxkYWx2aWsvYW5ub3Rh" + + "dGlvbi9TaWduYXR1cmU7ABJMamF2YS9sYW5nL0RvdWJsZTsAEUxqYXZhL2xhbmcvRmxvYXQ7ABNM" + + "amF2YS9sYW5nL0ludGVnZXI7ABBMamF2YS9sYW5nL0xvbmc7ABJMamF2YS9sYW5nL09iamVjdDsA" + + "FUxqYXZhL3V0aWwvQXJyYXlMaXN0OwAVTGphdmEvdXRpbC9BcnJheUxpc3Q8ACpMamF2YS91dGls" + + "L0FycmF5TGlzdDxMamF2YS9sYW5nL0ludGVnZXI7PjsAC1RhcmdldC5qYXZhAAFWAAJWSQACVkwA" + + "BFZMSUwAAVoAAlpEABNbTGphdmEvbGFuZy9PYmplY3Q7AAVhcnJheQAJZG9Ob3RoaW5nAAtkb1Nv" + + "bWV0aGluZwABaQAFaXNOYU4AAW8ABG9ianMAAXAAAXEAA3NldAAVdGVzdEdlbmVyaWNQYXJhbWV0" + + "ZXJzAAN2YWwABXZhbHVlAAd2YWx1ZU9mAAF4AAN4eHgAAXkAAXoAA3p6egCbAX5+RDh7ImJhY2tl" + + "bmQiOiJkZXgiLCJjb21waWxhdGlvbi1tb2RlIjoiZGVidWciLCJoYXMtY2hlY2tzdW1zIjpmYWxz" + + "ZSwibWluLWFwaSI6MSwic2hhLTEiOiIzMTAxYWQ2Zjc0ZWUyMzI1MjhkZmM2NmEyNjE3YTkzODM4" + + "NGU2NmVhIiwidmVyc2lvbiI6IjguMy43LWRldiJ9AAIFASscBhcAFxUXERcDFxEXAQABAgIAAQCB" + + "gAT4BAGJAZgFAgGwBQEB9AYAAAAAAAEAAACUBgAAwAYAAAAAAAABAAAAAAAAAAMAAADEBgAAEAAA" + + "AAAAAAABAAAAAAAAAAEAAAAzAAAAcAAAAAIAAAAPAAAAPAEAAAMAAAAKAAAAeAEAAAQAAAABAAAA" + + "8AEAAAUAAAAMAAAA+AEAAAYAAAABAAAAWAIAAAEgAAAEAAAAeAIAAAMgAAAEAAAAjAMAAAEQAAAH" + + "AAAA6AMAAAIgAAAzAAAAIgQAAAQgAAABAAAAlAYAAAAgAAABAAAApgYAAAMQAAACAAAAwAYAAAYg" + + "AAABAAAAzAYAAAAQAAABAAAA5AYAAA=="); // The variables of the functions in the above Target class. public static Set<Locals.VariableDescription>[] CONSTRUCTOR_VARIABLES = new Set[] { @@ -149,23 +169,49 @@ 4))), // ART Local variable table new HashSet<>(Arrays.asList( - new Locals.VariableDescription(19, 31, "q", "F", null, 6), - new Locals.VariableDescription(55, 37, "o", "Ljava/lang/Object;", null, 3), - new Locals.VariableDescription(0, 92, "this", "Lart/Target;", null, 14), - new Locals.VariableDescription(12, 80, "z", "I", null, 8), - new Locals.VariableDescription(11, 81, "y", "I", null, 5), - new Locals.VariableDescription(62, 30, "p", "I", null, 4), - new Locals.VariableDescription(0, 92, "x", "I", null, 15), - new Locals.VariableDescription(27, 23, "i", "D", null, 0), - new Locals.VariableDescription(65, 27, "q", "J", null, 6), - new Locals.VariableDescription(60, - 32, + new Locals.VariableDescription(20, 28, "q", "F", null, 4), + new Locals.VariableDescription(56, 34, "o", "Ljava/lang/Object;", null, 3), + new Locals.VariableDescription(0, 90, "this", "Lart/Target;", null, 12), + new Locals.VariableDescription(12, 39, "z", "I", null, 3), + new Locals.VariableDescription(11, 79, "y", "I", null, 1), + new Locals.VariableDescription(63, 27, "p", "I", null, 6), + new Locals.VariableDescription(0, 90, "x", "I", null, 13), + new Locals.VariableDescription(31, 17, "i", "D", null, 8), + new Locals.VariableDescription(66, 24, "q", "J", null, 7), + new Locals.VariableDescription(61, + 29, "i", "Ljava/util/ArrayList;", "Ljava/util/ArrayList<Ljava/lang/Integer;>;", - 2))), + 4))), }; + public static Set<Locals.VariableDescription>[] TEST_GENERIC_PARAMETERS_VARIABLES = new Set[] { + // RI Local variable table + new HashSet<>(Arrays.asList( + new Locals.VariableDescription(0, 8, "this", "Lart/Target;", null, 0), + new Locals.VariableDescription(0, + 8, + "array", + "Ljava/util/ArrayList;", + "Ljava/util/ArrayList<Ljava/lang/Integer;>;", + 1), + new Locals.VariableDescription(0, 8, "i", "I", null, 2), + new Locals.VariableDescription(0, 8, "val", "Ljava/lang/Integer;", null, 3))), + // ART Local variable table + new HashSet<>(Arrays.asList( + new Locals.VariableDescription(0, 4, "this", "Lart/Target;", null, 0), + new Locals.VariableDescription(0, + 4, + "array", + "Ljava/util/ArrayList;", + "Ljava/util/ArrayList<Ljava/lang/Integer;>;", + 1), + new Locals.VariableDescription(0, 4, "i", "I", null, 2), + new Locals.VariableDescription(0, 4, "val", "Ljava/lang/Integer;", null, 3))), + }; + + // Get a classloader that can load the Target class. public static ClassLoader getClassLoader() throws Exception { try { @@ -213,6 +259,9 @@ DO_NOTHING_VARIABLES); CheckLocalVariableTable(target.getDeclaredMethod("doSomething", Integer.TYPE), DO_SOMETHING_VARIABLES); + CheckLocalVariableTable(target.getDeclaredMethod("testGenericParameters", + (new ArrayList<Integer>(0)).getClass(), Integer.TYPE, (new Integer(0)).getClass()), + TEST_GENERIC_PARAMETERS_VARIABLES); } }
diff --git a/test/dexpreopt/dexpreopt_test.cc b/test/dexpreopt/dexpreopt_test.cc index 9641e0a..eac84f5 100644 --- a/test/dexpreopt/dexpreopt_test.cc +++ b/test/dexpreopt/dexpreopt_test.cc
@@ -198,12 +198,7 @@ if (pids.size() != 1) { return Errorf("There should be exactly one `system_server` process, found {}", pids.size()); } - // Unlike boot images, app images don't get unmapped if the runtime rejects them in some cases - // (e.g., CLC mismatch). Therefore, we need to check the PROT_EXEC flag to ensure that they are - // valid. - // The ODEX files always contain executable code because system server jars are compiled with the - // "speed" filter. - return GetMappedFiles(pids[0], ".odex", PROT_EXEC); + return GetMappedFiles(pids[0], ".odex", PROT_READ); } TEST(DexpreoptTest, ForZygote) {
diff --git a/tools/build-linux-x86-host-tools.sh b/tools/build-linux-x86-host-tools.sh new file mode 100755 index 0000000..c0483fa --- /dev/null +++ b/tools/build-linux-x86-host-tools.sh
@@ -0,0 +1,56 @@ + #!/bin/bash +# +# Copyright (C) 2023 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. + +set -e + +if [ ! -e 'build/make/core/Makefile' ]; then + echo "Script $0 needs to be run at the root of the android tree" + exit 1 +fi + +vars="$(build/soong/soong_ui.bash --dumpvars-mode --vars="OUT_DIR DIST_DIR")" +# Assign to a variable and eval that, since bash ignores any error status from +# the command substitution if it's directly on the eval line. +eval $vars + +HOST_BINARIES=( + ${OUT_DIR}/host/linux-x86/bin/dex2oat64 + ${OUT_DIR}/host/linux-x86/bin/dex2oatd64 + ${OUT_DIR}/host/linux-x86/bin/dex2oat + ${OUT_DIR}/host/linux-x86/bin/dex2oatd + ${OUT_DIR}/host/linux-x86/bin/deapexer + ${OUT_DIR}/host/linux-x86/bin/debugfs_static + ${OUT_DIR}/host/linux-x86/bin/oatdump +) + +# Build statically linked musl binaries for linux-x86 hosts without the +# standard glibc implementation. +build/soong/soong_ui.bash --make-mode USE_HOST_MUSL=true BUILD_HOST_static=true ${HOST_BINARIES[*]} +# Zip these binaries in a temporary file +prebuilts/build-tools/linux-x86/bin/soong_zip -o "${DIST_DIR}/temp-host-tools.zip" \ + -j ${HOST_BINARIES[*]/#/-f } + +# Build art_release.zip and copy only art jars in a temporary zip +build/soong/soong_ui.bash --make-mode dist "${DIST_DIR}/art_release.zip" +prebuilts/build-tools/linux-x86/bin/zip2zip -i "${DIST_DIR}/art_release.zip" \ + -o "${DIST_DIR}/temp-art-jars.zip" "bootjars/*" + +# Merge both temporary zips into output zip +prebuilts/build-tools/linux-x86/bin/merge_zips "${DIST_DIR}/art-host-tools-linux-x86.zip" \ + "${DIST_DIR}/temp-host-tools.zip" "${DIST_DIR}/temp-art-jars.zip" + +# Delete temporary zips +rm "${DIST_DIR}/temp-host-tools.zip" "${DIST_DIR}/temp-art-jars.zip"