summaryrefslogtreecommitdiff
path: root/runtime/class_linker_test.cc
Commit message (Collapse)AuthorAgeFilesLines
* Revert "Lazily allocate DexCache arrays."Orion Hodson2021-02-251-3/+2
| | | | | | | | | | This reverts commit 1214319d27e7fb4c4ff00b39799df6f15288098a. Reason for revert: Post-submit fails Bug: b/181097963 Test: TH Change-Id: I9fd21140f1703d0020458b786f48bd39889a9948
* Lazily allocate DexCache arrays.David Srbecky2021-02-231-2/+3
| | | | | | | | | | | We rarely need the DexCache for compiled code. Delay the allocation in hope we never need it. This reduces DexCache memory usage by ~25% at startup. Test: m test-art-host-gtest Test: test.py -r -b --host Change-Id: I680a59c905c2b821ee954e4b32abd5d24876bd11
* Rewrite ClassLinker::LinkFields().Vladimir Marko2021-01-281-5/+8
| | | | | | | | | | | | | | | | | | | | | | | | Rewrite field offset assignment to avoid heap allocations in most cases. We do one allocation if there are many fields. Rewrite gap filling to prefer small gaps over big ones. This creates more natural field ordering. For example, class A { byte unalign; } class B extends A { long l; byte a, b, c, d, e, f; } would have previously had offsets 12, 10, 14, 9, 11, 13, 15 for fields a, b, c, d, e, f, respectively. Now these are 9, 10, 11, 12, 13, 14, 15 in line with their lexicographical order. Test: m test-art-host-gtest Test: testrunner.py --host --optimizing Test: boots. Bug: 175869411 Change-Id: I558635ac59c959dd85e8a3b015c26a6d90033853
* Remove DexCache arrays from image.David Srbecky2020-12-041-3/+4
| | | | | | | | | | | | | | | | | | Remove the hashtable storage from the image and allocate it at runtime instead (but keep the DexCache object in the image). For compiled code, we have largely moved to using .bss, so the DexCache just costs us unnecessary extra space and dirty pages. For interpreted code, the hashtables are too small and will be overridden many times over at run-time regardless. The next step will be to make DexCache variable-size so it can adapt to both of the extremes (taking minimal amount of memory for compiled code and avoiding cache evictions in interpreter). Test: test.py --host Change-Id: I9f89e8f19829b812cf85dea1a964259ed8b87f4d
* Update language to comply with Android’s inclusive language guidanceIan Pedowitz2020-07-241-1/+1
| | | | | | | | | | | See https://source.android.com/setup/contribute/respectful-code for reference Bug: 161896447 Bug: 161850439 Bug: 161336379 Test: m -j checkbuild cts docs tests Change-Id: I32d869c274a5d9a3dac63221e25874fe685d38c4
* Move implementations from class_root.h to -inl.h .Vladimir Marko2020-05-131-1/+1
| | | | | | | | | | Make it possible to include the definition of enum ClassRoot without pulling in a lot of other headers. Test: m test-art-host-gtest Test: testrunner.py --host --optimizing Test: aosp_taimen-userdebug boots. Change-Id: Ic90fdd70bfe0c5428a5c9a0d7901ea7e15b03488
* ART: Ensure dex caches keep classloader liveAndreas Gampe2020-03-041-0/+1
| | | | | | | | | | Live dex caches must keep their associated classloader live. Otherwise the classloader may get unloaded, attempting to free DexFiles which cannot be unregistered. Test: art/test/testrunner/testrunner.py -b --host Test: m test-art-host-gtest Change-Id: I0eed5b3b46ed681c739d6923a57d0878afbba1a7
* Change j.l.r.Field to use ArtField index instead of dexFileIndexAlex Light2020-02-111-1/+1
| | | | | | | | | | | | | | | Using the dexFileIndex to determine the ArtField a java.lang.reflect.Field object points to requires us to use a dex-cache and to update all existing Field objects if this index changes (for example due to class redefinition). This could be rather slow. This replaces the dex-file index with the index into the declaring class's SFields/IFields arrays where the specified ArtMethod is stored. Bug: 149236640 Test: ./test.py --host Change-Id: I9a7d69903ece0ea94e3b3e93b4c8a872ac4073e8
* Use explicit list of mirrored class when checking CanRedefineAlex Light2019-11-111-0/+1
| | | | | | | | | | | | We were assuming that the ClassRoots contained all the mirror'd classes but this is not the case. Instead we should use an explicit list of the mirror'd classes. Test: ./test.py --host Test: m test-art-host-gtest-class_linker_test64 Bug: 134162467 Change-Id: Idd4c258ee0134e42afd0175b948123ea052704e1
* Revert "Revert "Basic structural redefinition support""Nicolas Geoffray2019-09-181-0/+1
| | | | | | | | | | This reverts commit 5a2301d897294ff4ee6de71f459dc2566dc3fa1a. Bug: 134162467 Reason for revert: Relanding as unclear if issue is due to topic. Change-Id: Ib1d1cf2e9132e30c9649b760ae9ae2d8ceacf843
* Revert "Basic structural redefinition support"Nicolas Geoffray2019-09-181-1/+0
| | | | | | | | | | This reverts commit c971eafeff43e4e26959a6e86b62ab0a8f1a6e1c. Bug: 134162467 Reason for revert: Breaks on redefine-stress Change-Id: I4e38da23d65b5b34b26b5ab537a3583328e078a4
* Basic structural redefinition supportAlex Light2019-09-171-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This adds basic support for adding methods and fields to already loaded classes using redefinition. This 'structural class redefinition' is currently limited to classes without any virtual methods or instance fields. One cannot currently structurally redefine multiple classes at once nor will structural redefinition trigger the standard redefinition events. After structural redefinition all references to the old class, and its fields and methods are atomically updated. Any memory associated with the static fields of the old class is zeroed. Offsets for field access might change. If there are any active stack frames for methods from the redefined class the original (obsolete method) code will continue to execute. The identity hash code of the redefined class will not change. Any locks being held, waited or blocked on by the old class will be transferred to the new class. To use this feature the process must be debuggable and running with -Xopaque-jni-ids:true. For device testing use a wrap.sh that adds the following flags: '-Xopaque-jni-ids:true -Xcompiler-option --debuggable -XjdwpProvider:adbconnection' Structural redefinition only available using the "com.android.art.UNSAFE.class.structurally_redefine_class_direct" extension. This will not trigger the normal class-redefinition events. Only one class may be redefined at a time. NB There are still some holes in this potentially allowing obsolete methods/fields to be visible. Most notably during jni-id, MethodHandle and VarHandle creation as well as potentially other places in the runtime. These holes will be closed by later CLs. Until then the extension to access structural class redefinition will remain tagged as UNSAFE. Test: ./test.py --host --all-compiler Bug: 134162467 Change-Id: I825d3a4bdb9594c0147223ae69f433ce9bbfc307
* Implement ClassStatus::kVisiblyInitialized.Vladimir Marko2019-07-261-3/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Previously all class initialization checks involved a memory barrier to ensure appropriate memory visibility. We change that by introducing the kVisiblyInitialized status which can be checked without a memory barrier. Before we mark a class as visibly initialized, we run a checkpoint on all threads to ensure memory visibility. This is done in batches for up to 32 classes to reduce the overhead. Avoiding memory barriers in the compiled code reduces code size and improves performance. This is also the first step toward fixing a long-standing synchronization bug 18161648. Prebuilt sizes for aosp_taimen-userdebug: - before: arm/boot*.oat: 19150696 arm64/boot*.oat: 22574336 oat/arm64/services.odex: 21929800 - after: arm/boot*.oat: 19134508 (-16KiB) arm64/boot*.oat: 22553664 (-20KiB) oat/arm64/services.odex: 21888760 (-40KiB) Test: m test-art-host-gtest Test: testrunner.py --host --optimizing Test: aosp_taimen-userdebug boots Test: run-gtests.sh -j4 Test: testrunner.py --target --optimizing Test: Manually diff `m dump-oat-boot` output from before with output after this CL without codegen changes, with `sed` replacements for class status. Check that only checksums and the oatdump runtime values of DexCache.dexFile differ. Bug: 18161648 Bug: 36692143 Change-Id: Ida10439d347e680a0abf4674546923374ffaa957
* Revert^2 "Support using opaque JNI ids"Alex Light2019-06-281-0/+3
| | | | | | | | | | | | | | | | | | We weren't handing the fact that encoding jmethodIDs could cause OOM exceptions in some places in reflection.cc. This could lead to attempting to use a null jmethodID as if it were a real id. This issue is fixed by the parent CL. This reverts commit b476a29a2c. This reverts commit 3b2905366c. This Unreverts commit d5d645ffec. This Unreverts commit 21d5994583. Reason for revert: Fixed issue causing 004 debuggable flakes Test: ./test.py --host --jit --debuggable Bug: 134162467 Change-Id: Iece08ab299cd8a20f8382be7be6c3796858e70eb
* Revert "Support using opaque JNI ids"Nicolas Geoffray2019-06-271-3/+0
| | | | | | | | | | This reverts commit 21d5994583c679cd5d8573b5d35dbd659bdca2c7. Bug: 134162467 Reason for revert: Breaks debuggable Change-Id: I9510a6ac208d392ff25ee196a1a519fecd151445
* Support using opaque JNI idsAlex Light2019-06-261-0/+3
| | | | | | | | | | | | | | | | | | | | | | Currently JNI ids (jmethodID & jfieldID) are created by simply casting the corresponding ART structure pointer. This is great for simplicity but means we are prevented from performing operations that could change these pointer values. To support these use-cases add support for loading the runtime with a layer of indirection between these ids and the internal art data types. Currently the JNI id type can be toggled only by passing the new '-Xopaque-jni-ids:{true,false}' flag during startup. This changes the --debuggable test configuration to pass '-Xopaque-jni-ids:true' in order to get test coverage of this feature using the 'art-jit' configuration. Test: ./test.py --host --debuggable Test: ./test.py --host --debuggable --jit-on-first-use Test: ./test/testrunnner/run_build_test_target.py art-jit Bug: 134162467 Change-Id: Id8c8cb9a5b8ff18dc2f40892fae2d344a7214f44
* Clean up creating handles from `this`.Vladimir Marko2019-05-311-1/+1
| | | | | | | | | | | Make these member functions static and take an additional parameter `Handle<.> h_this`. Callers mostly already have a Handle<> to pass, so we avoid an extra StackHandleScope. This pattern was already used for some functions. Test: m test-art-host-gtest Test: testrunner.py --host --optimizing --interpreter Change-Id: I4f4478b0526bcb2f3c23305d3b3cc4a65fff9ff5
* Partially ObjPtr<>-ify Object, fix stale ref in test.Vladimir Marko2019-04-021-7/+6
| | | | | | | Test: m test-art-host-gtest Test: testrunner.py --host --optimizing Bug: 31113334 Change-Id: I0c0bc669c0ab8d99185e662a2fec16f32a42a0a2
* Clean up explicit conversions to ObjPtr<>.Vladimir Marko2019-03-291-6/+5
| | | | | | | | | | | | Add an ObjPtr<>::DownCast() overload that takes a plain pointer and remove unnecessary calls to MakeObjPtr(), usually preceding DownCast(). Move the MakeObjPtr() to common_art_test.h . Test: m test-art-host-gtest Test: testrunner.py --host --optimizing Bug: 31113334 Change-Id: I2a243b6d8f3b2e773396dfc53b659c5f7d9ea44a
* ObjPtr<>-ify method/var handles, fix stale refs in tests.Vladimir Marko2019-03-281-1/+1
| | | | | | | Test: m test-art-host-gtest Test: testrunner.py --host --interpreter Bug: 31113334 Change-Id: I89ea84f7970899643e437161b598d3232a182e98
* Replace StringPiece with std::string_view in profman.Vladimir Marko2019-02-071-1/+1
| | | | | | | | | | | | | | | | | | | | And in dexoptanalyzer and hiddenapi, see below. The parsing helpers in utils.h were mostly unused, only profman was calling one of them, so move that helper to profman and rewrite and fix it, remove the other helpers. This exposed dependency of dexoptanalyzer and hiddenapi on StringPiece indirectly included from utils.h, thus we replace it with std::string_view also in those tools. During the rewrite, avoid using std::string_view::data() as a null terminated string, prefer to fall back to the original null terminated raw option instead. Test: m test-art-host-gtest Test: testrunner.py --host --optimizing Bug: 123750182 Change-Id: Ibeec8069a5d82ea556e03e4577812f94dca6f387
* Replace StringPiece with std::string_view in art/runtime/.Vladimir Marko2019-02-061-2/+3
| | | | | | | | | And in art/test/. Test: m test-art-host-gtest Test: testrunner.py --host --optimizing Bug: 123750182 Change-Id: I14c7cddd7ba4fb2183c643d32a89b594008d8bd0
* Replace StringPiece with std::string_view in Signature.Vladimir Marko2019-02-061-1/+1
| | | | | | | | | | | | And also in Signature-related code. Remove the function DexFile::CreateSignature() which was used only in a test as the test can use method searching functions that take std::string_view instead. Test: m test-art-host-gtest Test: testrunner.py --host --optimizing Bug: 123750182 Change-Id: I3f24c8f4f677e2e40503dbab347df1eb031b4132
* ART: Move Signature to its own headerAndreas Gampe2019-01-031-0/+1
| | | | | | | | Reduce the dependencies on dex_file.h Bug: 119869270 Test: mmma art Change-Id: I1450fe2c3f4a7f5b535ed38cc19cb8a053228541
* ART: Move dex structs into own headerAndreas Gampe2019-01-021-6/+6
| | | | | | | | | Separating out the structs from DexFile allows them to be forward- declared, which reduces the need to include the dex_file header. Bug: 119869270 Test: m Change-Id: I32dde5a632884bca7435cd584b4a81883de2e7b4
* ART: Rewrite EnsureInitialized hit caseAndreas Gampe2018-12-131-1/+2
| | | | | | | | | | | | | | | | | | | | | When an initialized class is found during EnsureInitialized, do not check whether verification was attempted and fix up bits. Instead, ensure that all class-loading paths have that done when eventually getting here. Special runtime-constructed classes (primitives, arrays, proxies) need code to do this work. "Normal" classes have the work done during VerifyClass. Leave a DCHECK in as a state check. Protect state transfers with additional checks. This reduces the overhead of the interpreter which cannot elide initialization checks for static accesses. Bug: 115834172 Test: m test-art-host Change-Id: Iacd6652583364509c37eafe81fed1198abb1b71a
* Keep pointer to original DexFile during JVMTI redefine for hiddenapiDavid Brazdil2018-12-031-0/+4
| | | | | | | | | | | | | JVMTI redefine overwrites the pointer to the class' DexFile which prevents access checks from reading the hiddenapi flags store. Store the pointer in ClassExt together with the original ClassDef index to preserve the access to flags store. Because method/field indices are still lost, the corresponding dex member is found using string comparison of member's name and type. Bug: 119688837 Test: 999-redefine-hiddenapi Change-Id: Ifdf35668e838869a971233bbaae61851014658b1
* Add PreResolved strings dex cache arrayMathieu Chartier2018-10-301-0/+2
| | | | | | | | | | | | For app images, this dex cache may be prepopulated to speed up application startup. This new dex cache array is created when --resolve-startup-const-strings=true. Test: test-art-host Bug: 116059983 Bug: 118385560 Change-Id: I379dc15174281665d7f4ceb106f7fbf51f89b921
* ART: Add object-array-alloc-inl.hAndreas Gampe2018-10-261-0/+1
| | | | | | | | | | In an effort to reduce the (transitive) proliferation of heap-inl add a specific inline header for object array allocation. Bug: 118385392 Test: mmma art Test: m test-art-host Change-Id: I0d7c40ed53708d4c759190961b40f0cac3fe696d
* ART: Add array-alloc-inl.hAndreas Gampe2018-10-251-0/+1
| | | | | | | | | | In an effort to reduce the (transitive) proliferation of heap-inl add a specific inline header for array allocation. Bug: 118385392 Test: mmma art Test: m test-art-host Change-Id: Id3378f40c52fa7ef4297af08cb7509e0c04b94d1
* ART: Refactor for bugprone-argument-commentAndreas Gampe2018-10-231-10/+10
| | | | | | | | Handles runtime. Bug: 116054210 Test: WITH_TIDY=1 mmma art Change-Id: Ibc0d5086809d647f0ce4df5452eb84442d27ecf0
* Remove superfluous 'virtual' specifiers in ART.Roland Levillain2018-08-281-1/+1
| | | | | | | | Remove 'virtual' specifier on methods already bearing the 'override' specifier. Test: mmma art Change-Id: I114930969a5ca048d88de9ecd18e2c6403593e31
* Use 'final' and 'override' specifiers directly in ART.Roland Levillain2018-08-281-2/+2
| | | | | | | | | | | | | | | Remove all uses of macros 'FINAL' and 'OVERRIDE' and replace them with 'final' and 'override' specifiers. Remove all definitions of these macros as well, which were located in these files: - libartbase/base/macros.h - test/913-heaps/heaps.cc - test/ti-agent/ti_macros.h ART is now using C++14; the 'final' and 'override' specifiers have been introduced in C++11. Test: mmma art Change-Id: I256c7758155a71a2940ef2574925a44076feeebf
* Revert "Refactor DexFile ownership"David Sehr2018-07-031-6/+6
| | | | | | | | This reverts commit b095f022a9683a9123018c01e22595cf969fd88b. Reason for revert: Caused huge interpreter performance regression. Change-Id: I0f27f8f234d315807695362bf679ef47f68723f7
* Refactor DexFile ownershipDavid Sehr2018-06-271-6/+6
| | | | | | | | | Avoid bare pointers in DexFileLoader APIs, which caused clang-tidy issues and other problems. Bug: none Test: build and boot Change-Id: Ic277bc83af1997774b42c55d3d631ec940b9c015
* ObjPtr<>-ify array allocations.Vladimir Marko2018-06-011-2/+1
| | | | | | | | | And remove some unnecessary calls to ObjPtr<>::Ptr(). Test: m test-art-host-gtest Test: testrunner.py --host --optimizing Bug: 31113334 Change-Id: Ie313980f7f23b33b0ccea4fa8d5131d643c59080
* ObjPtr<>-ify ClassLinker::FindClass(), fix 1 stale reference use.Vladimir Marko2018-05-311-6/+7
| | | | | | | | | | Thread::CreateAnnotatedStackTrace() was using a stale reference `aste_array_class`. Test: m test-art-host-gtest Test: testrunner.py --host --optimizing Bug: 31113334 Change-Id: I191907c0053456bb57de425aa6ccd9668df818a2
* Refactor ClassRoot/GetClassRoot().Vladimir Marko2018-05-251-4/+4
| | | | | | | | | | | | | Move it outside the ClassLinker, into its own header file, and add retrieval based on a mirror class template argument. Keep the SetClassRoot() as a private member of ClassLinker. Make the new GetClassRoot()s return ObjPtr<>. Test: m test-art-host-gtest Test: testrunner.py --host --optimizing Bug: 31113334 Change-Id: Icbc6b62b41f6ffd65b437297a21eadbb0454e2b7
* ObjPtr<>-ify tests using ClassLinker::FindClass().Vladimir Marko2018-05-231-55/+63
| | | | | | | | | | ClassLinker::FindClass() returns a non-ObjPtr<> reference but it has a lot of uses, so we shall change the uses in a few steps. This change deals with several tests. Test: Rely on TreeHugger. Bug: 31113334 Change-Id: Ib75e20e7ebaff01fb607a09f96675f8cf397ae52
* Move most of runtime/base to libartbase/baseDavid Sehr2018-03-051-0/+57
| | | | | | | | | | | | | | Enforce the layering that code in runtime/base should not depend on runtime by separating it into libartbase. Some of the code in runtime/base depends on the Runtime class, so it cannot be moved yet. Also, some of the tests depend on CommonRuntimeTest, which itself needs to be factored (in a subsequent CL). Bug: 22322814 Test: make -j 50 checkbuild make -j 50 test-art-host Change-Id: I8b096c1e2542f829eb456b4b057c71421b77d7e2
* Create dex subdirectoryDavid Sehr2018-01-051-2/+2
| | | | | | | | | Move all the DexFile related source to a common subdirectory dex/ of runtime. Bug: 71361973 Test: make -j 50 test-art-host Change-Id: I59e984ed660b93e0776556308be3d653722f5223
* Change ClassStatus to fit into 4 bits.Vladimir Marko2018-01-051-4/+4
| | | | | | | | | | | | | | | | | In preparation for extending the type check bit string from 24 to 28 bits, rewrite ClassStatus to fit into 4 bits. Also perform a proper cleanup of the ClassStatus, i.e. change it to an enum class, remove the "Status" word from enumerator names, replace "Max" with "Last" in line with other enumerations and remove aliases from mirror::Class. Test: m test-art-host-gtest Test: testrunner.py --host --optimizing Test: Pixel 2 XL boots. Test: testrunner.py --target --optimizing Bug: 64692057 Bug: 65318848 Change-Id: Iec1610ba5dac2c527b36c12819f132e1a77f2d45
* ART: Add test for ArrayElementVarHandle offsets.Orion Hodson2018-01-021-0/+7
| | | | | | | | Fixes omission in 005ac512de3d734624a5db39bb14b71763ba730d. Test: art/test.py --host -g -j32 Bug: 65872996 Change-Id: I085f8a56661012ca3b5a380d8c644aec88b7e441
* Do not pass DexFile to ClassLinker::Lookup/ResolveType().Vladimir Marko2017-12-121-11/+9
| | | | | | | | | | | | | The DexFile can be easily retrieved from the DexCache, so reduce the number of arguments that need to be passed. Also refactor the code to avoid doing the DexCache lookup twice and avoid unnecessary read barriers in the initial DexCache lookup (also for Lookup/ResolveField()). Test: m test-art-host-gtest Test: testrunner.py --host --optimizing Change-Id: Idea9aa42b6a5bade947e93e330b1abdb9d11b2da
* Do not pass DexFile to ClassLinker::ResolveMethodType().Vladimir Marko2017-12-081-15/+3
| | | | | | | | | The DexFile can be easily retrieved from the DexCache, so reduce the number of arguments that need to be passed. Test: m test-art-host-gtest Test: testrunner.py --host --optimizing Change-Id: I00634b89013b7348460aa73561fa14be7c8cdb7e
* Determine HLoadClass/String load kind early.Vladimir Marko2017-12-081-2/+10
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | This helps save memory by avoiding the allocation of HEnvironment and related objects for AOT references to boot image strings and classes (kBootImage* load kinds) and also for JIT references (kJitTableAddress). Compiling aosp_taimen-userdebug boot image, the most memory hungry method BatteryStats.dumpLocked() needs - before: Used 55105384 bytes of arena memory... ... UseListNode 10009704 Environment 423248 EnvVRegs 20676560 ... - after: Used 50559176 bytes of arena memory... ... UseListNode 8568936 Environment 365680 EnvVRegs 17628704 ... Test: m test-art-host-gtest Test: testrunner.py --host --optimizing --jit Bug: 34053922 Change-Id: I68e73a438e6ac8e8908e6fccf53bbeea8a64a077
* cpplint: Cleanup errorsIgor Murashkin2017-11-081-13/+13
| | | | | | | | | Cleanup errors from upstream cpplint in preparation for moving art's cpplint fork to upstream tip-of-tree cpplint. Test: cd art && mm Bug: 68951293 Change-Id: I15faed4594cbcb8399850f8bdee39d42c0c5b956
* Refactor ArtField::GetType<>() as {Lookup,Resolve}Type().Vladimir Marko2017-11-061-2/+2
| | | | | | | | | And add no thread suspension assertion to LookupType() as well as ArtMethod::LookupResolvedClassFromTypeIndex(). Test: m test-art-host-gtest Test: testrunner.py --host --optimizing Change-Id: If1541ccb0aafeabb6d1dd5566f10afcac98a2ef1
* ART: Add mirror classes for VarHandlesOrion Hodson2017-11-021-0/+38
| | | | | | | | | | Adds mirror classes for VarHandle, FieldVarHandle, ArrayElementVarHandle, ByteArrayViewVarHandle and ByteBufferViewVarHandle. Bug: 65872996 Test: art/test.py --host -g -j32 Change-Id: I34e4b53c21cd969b54003dcfa3527acb963bfec7
* Separate MemMap from DexFile completelyDavid Sehr2017-10-271-0/+1
| | | | | | | | | | Create a container class for holding ownership of MemMap and segregate that functionality to dex_file_loader. This removes the dependency between dex_file.cc and mem_map.cc. Bug: 22322814 Test: make test-art-host Change-Id: I96db6fd10cdbad774c2f1f85c249418a154fbd52