summaryrefslogtreecommitdiffstats
path: root/runtime/native
Commit message (Collapse)AuthorAgeFilesLines
* setting RLIMIT to INFINITY.Maunik Shah2016-06-051-1/+14
| | | | | | This is to generate coredumps for processes spawned by zygote Change-Id: Iecc1eb7784373ffaf3ebfdc60d32d2ae0beb3235
* Bugfix: Java char is 16 bits, can not be treated as boolean.Fredrik Roubert2015-07-271-2/+2
| | | | | | | | | | | | | | Using SetFieldBooleanVolatile() and SetFieldBoolean() happens to work for char values that only use the lower 8 bits, but is a mistake that was introduced by the "Add AccessibleObject and Field to mirror" commit: https://android.googlesource.com/platform/art/+/daaf326 (cherry picked from commit 3152c82b0d33e5fb0a4aa964ea58451c72734444) Bug:22772717 Change-Id: Iec02ba3084c992ea239ecef688d7d29c7e21ae16
* Merge "ART stack unwinding fixes for libunwind/gdb/lldb." into mnc-devDavid Srbecky2015-06-191-5/+5
|\
| * ART stack unwinding fixes for libunwind/gdb/lldb.David Srbecky2015-06-191-5/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | dex2oat can already generate unwinding and symbol information which allows tools to create backtrace of mixed native and Java code. This is a cherry pick from aosp/master which fixes several issues. Most notably: * It enables generation of ELF-64 on 64-bit systems (in dex2oat, C compilers already produce ELF-64). Libunwind requires ELF-64 on 64-bit systems for backtraces to work. * It enables loading of ELF files with dlopen. This is required for libunwind to be able to generate backtrace of current process (i.e. the process requesting backtrace of itself). * It adds unit test to test the above (32 vs 64 bit, in-proces vs out-of-process, application code vs framework code). * Some other fixes or clean-ups which should not be of much significance but which are easier to include to make the important CLs cherry-pick cleanly. This is squash of the following commits from aosp/master: 7381010 ART: CFI Test e1bbed2 ART: Blacklist CFI test for non-compiled run-tests aab9f73 ART: Blacklist CFI test for JIT 4437219 ART: Blacklist CFI test for Heap Poisoning a3a49fe Switch to using ELF-64 for 64-bit architectures. 297ed22 Write 64-bit address in DWARF if we are on 64-bit architecture. 24981a1 Set correct size of PT_PHDR ELF segment. 1a146bf Link .dynamic to .dynstr 67a0653 Make some parts of ELF more (pointer) aligned. f50fa82 Enable 64-bit CFI tests. 49e1fab Use dlopen to load oat files. 5dedb80 Add more logging output for dlopen. aa03870 Find the dlopened file using address rather than file path. 82e73dc Release dummy MemMaps corresponding to dlopen. 5c40961 Test that we can unwind framework code. 020c543 Add more log output to the CFI test. 88da3b0 ART: Fix CFI test wrt/ PIC a70e5b9 CFI test: kill the other process in native code. ad5fa8c Support generation of CFI in .debug_frame format. 90688ae Fix build - large frame size of ElfWriterQuick<ElfTypes>::Write. 97dabb7 Fix build breakage in dwarf_test. 388d286 Generate just single ARM mapping symbol. f898087 Split .oat_patches to multiple sections. 491a7fe Fix build - large frame size of ElfWriterQuick<ElfTypes>::Write (again). 8363c77 Add --generate-debug-info flag and remove the other two flags. 461d72a Generate debug info for core.oat files. Bug: 21924613 Change-Id: I3f944a08dd2ed1df4d8a807da4fee423fdd35eb7
* | Fix some java_lang_Class related moving GC bugsMathieu Chartier2015-06-181-10/+10
|/ | | | | | | | | There was some missing handles around mirror::Class*. (cherry picked from commit 05b7226787f1470ad93f6f632fed60f70bc8631e Bug: 21898408 Change-Id: Icb754074dfb469473101d20d6873a5bc3274abc5
* Fix compaction bug in Class_getDeclaredMethodsUncheckedMathieu Chartier2015-06-111-2/+2
| | | | | | | Added handle to fix the bug. Bug: 21638351 Change-Id: I1c3abea33aa825d3a28c1fc5cb415508686ad93e
* Let classloader provide correct LD_LIBRARY_PATHDmitriy Ivanov2015-06-091-31/+8
| | | | | | | | | Rely on BaseDexClassLoader to provide correct LD_LIBRARY_PATH Bug: http://b/21647354 Bug: http://b/21667767 Bug: http://b/8076853 Change-Id: I8c690a2578d5de43be9da964fa5a4c0246aa6eec
* Move mirror::ArtMethod to nativeMathieu Chartier2015-06-029-126/+99
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Optimizing + quick tests are passing, devices boot. TODO: Test and fix bugs in mips64. Saves 16 bytes per most ArtMethod, 7.5MB reduction in system PSS. Some of the savings are from removal of virtual methods and direct methods object arrays. Bug: 19264997 (cherry picked from commit e401d146407d61eeb99f8d6176b2ac13c4df1e33) Change-Id: I622469a0cfa0e7082a2119f3d6a9491eb61e3f3d Fix some ArtMethod related bugs Added root visiting for runtime methods, not currently required since the GcRoots in these methods are null. Added missing GetInterfaceMethodIfProxy in GetMethodLine, fixes --trace run-tests 005, 044. Fixed optimizing compiler bug where we used a normal stack location instead of double on ARM64, this fixes the debuggable tests. TODO: Fix JDWP tests. Bug: 19264997 Change-Id: I7c55f69c61d1b45351fd0dc7185ffe5efad82bd3 ART: Fix casts for 64-bit pointers on 32-bit compiler. Bug: 19264997 Change-Id: Ief45cdd4bae5a43fc8bfdfa7cf744e2c57529457 Fix JDWP tests after ArtMethod change Fixes Throwable::GetStackDepth for exception event detection after internal stack trace representation change. Adds missing ArtMethod::GetInterfaceMethodIfProxy call in case of proxy method. Bug: 19264997 Change-Id: I363e293796848c3ec491c963813f62d868da44d2 Fix accidental IMT and root marking regression Was always using the conflict trampoline. Also included fix for regression in GC time caused by extra roots. Most of the regression was IMT. Fixed bug in DumpGcPerformanceInfo where we would get SIGABRT due to detached thread. EvaluateAndApplyChanges: From ~2500 -> ~1980 GC time: 8.2s -> 7.2s due to 1s less of MarkConcurrentRoots Bug: 19264997 Change-Id: I4333e80a8268c2ed1284f87f25b9f113d4f2c7e0 Fix bogus image test assert Previously we were comparing the size of the non moving space to size of the image file. Now we properly compare the size of the image space against the size of the image file. Bug: 19264997 Change-Id: I7359f1f73ae3df60c5147245935a24431c04808a [MIPS64] Fix art_quick_invoke_stub argument offsets. ArtMethod reference's size got bigger, so we need to move other args and leave enough space for ArtMethod* and 'this' pointer. This fixes mips64 boot. Bug: 19264997 Change-Id: I47198d5f39a4caab30b3b77479d5eedaad5006ab
* Reset libc targetSdkVersionDmitriy Ivanov2015-05-271-0/+9
| | | | | | | | | | This will let libc/linker know which sdk version is targeted by the app. This is needed to work around incorrect DT_NEEDED entries in old apps. Bug: http://b/21364029 Change-Id: I2f2907104106aac6c8831381ca171dc0302e6a9d (cherry picked from commit 15efde2badd80b8b124f8e1444165e4afbac17f0)
* ART: Clean up arm64 kNumberOfXRegisters usage.Vladimir Marko2015-05-262-0/+2
| | | | | | | | | | | | | | | | | | | | | Avoid undefined behavior for arm64 stemming from 1u << 32 in loops with upper bound kNumberOfXRegisters. Create iterators for enumerating bits in an integer either from high to low or from low to high and use them for <arch>Context::FillCalleeSaves() on all architectures. Refactor runtime/utils.{h,cc} by moving all bit-fiddling functions to runtime/base/bit_utils.{h,cc} (together with the new bit iterators) and all time-related functions to runtime/base/time_utils.{h,cc}. Improve test coverage and fix some corner cases for the bit-fiddling functions. Bug: 13925192 (cherry picked from commit 80afd02024d20e60b197d3adfbb43cc303cf29e0) Change-Id: I905257a21de90b5860ebe1e39563758f721eab82
* Also print class for NoSuchFieldExceptionMathieu Chartier2015-05-131-1/+1
| | | | | | | | | | | Example message: Caused by: java.lang.NoSuchFieldException: No field value in class Ljava/lang/String; Added test. Bug: 20881251 Change-Id: I4043cbf26c3077952b6c151da0d0edd980da26b1
* Hold heap bitmap lock in Heap::GetObjectsAllocatedMathieu Chartier2015-05-121-0/+1
| | | | | | | | | | | Fixes a race condition where add and remove space could cause a crash when we iterated over the spaces. TODO: Add a spaces lock or something to guard against this. Bug: 21031927 Change-Id: I7f0d558316f8e9d9f22ffd182e8666355bf50d47
* am 1c324341: am 6108ed86: Merge "Add a flag to StackVisitor for inlining."Nicolas Geoffray2015-05-111-1/+2
|\ | | | | | | | | * commit '1c3243416088c2f2072f6db413cfb3c8bf2dacfb': Add a flag to StackVisitor for inlining.
| * Add a flag to StackVisitor for inlining.Nicolas Geoffray2015-05-111-1/+2
| | | | | | | | | | | | | | | | | | The flag tells whether the stack walk needs to include inlined Java frames. This does not do anything just yet, as we're not inlining anyways. Change-Id: I716e25094fe56fa335ca1f9a398c1bcdba478e73
* | am 5b19928e: am 43e1bc66: Merge "Request full/partial GC type from ↵Hiroshi Yamauchi2015-05-011-2/+2
|\| | | | | | | | | | | | | VMRuntime.requestConcurrentGC()." * commit '5b19928e7adc9749e3d4c306c5955ee14f76717c': Request full/partial GC type from VMRuntime.requestConcurrentGC().
| * Request full/partial GC type from VMRuntime.requestConcurrentGC().Hiroshi Yamauchi2015-05-011-2/+2
| | | | | | | | | | Bug: 20554807 Change-Id: I1cd855507c3f4e191035dbc2c429e1b8b344d81b
* | am 61d7ca87: ART: Whitelist DexPathList constructorAndreas Gampe2015-04-301-4/+11
|\ \ | |/ |/| | | | | * commit '61d7ca870b7afc5400e6f7dd2952ca06ce7f7bac': ART: Whitelist DexPathList$Element constructor
| * ART: Whitelist DexPathList$Element constructorAndreas Gampe2015-04-291-4/+11
| | | | | | | | | | | | | | Temporary whitelist for backwards compatibility. Bug: 20699073 Change-Id: Iba351060441398b9377a8471f0bbe03bb77f8384
| * Fix constructor access check through reflectionSebastien Hertz2015-04-281-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | We must not throw IllegalAccessException if the constructor has been made accessible by a previous call to Constructor.setAccessible, even if the caller cannot access the constructor. Bug: 20639158 (cherry picked from commit 2d2f2a9c665b02ca5139f71e37ca5e08389e4191) Change-Id: Ic5cb54256f11aefcfaa99f2ee85c4a32f30e693a
| * ART: Fix constructor access checkingAndreas Gampe2015-04-271-6/+3
| | | | | | | | | | | | | | Constructor access must be checked. Bug: 20639158 Change-Id: I3c586e9572a748d208bea43aa2349c3ef52a2ee5
* | Fix constructor access check through reflectionSebastien Hertz2015-04-281-2/+2
| | | | | | | | | | | | | | | | | | We must not throw IllegalAccessException if the constructor has been made accessible by a previous call to Constructor.setAccessible, even if the caller cannot access the constructor. Bug: 20639158 Change-Id: I9a34f05cdbb8825ad88b42223743690228e3f03e
* | Fix java_lang_Class newInstance for strings; also quick entrypoints.Jeff Hao2015-04-271-0/+11
| | | | | | | | Change-Id: I35fd23c5a9051e1ffda0ecc2cbafb5d318c7b5e6
* | Merge "ART: Fix constructor access checking"Andreas Gampe2015-04-281-6/+3
|\ \
| * | ART: Fix constructor access checkingAndreas Gampe2015-04-271-6/+3
| |/ | | | | | | | | | | | | | | | | Constructor access must be checked. (cherry picked from commit 0dd76cd3f09f495a1b9a0e4f8712c09ff885c6fd) Bug: 20639158 Change-Id: I3c586e9572a748d208bea43aa2349c3ef52a2ee5
* / Replace String CharArray with internal uint16_t array.Jeff Hao2015-04-277-8/+483
|/ | | | | | | | | | | | Summary of high level changes: - Adds compiler inliner support to identify string init methods - Adds compiler support (quick & optimizing) with new invoke code path that calls method off the thread pointer - Adds thread entrypoints for all string init methods - Adds map to verifier to log when receiver of string init has been copied to other registers. used by compiler and interpreter Change-Id: I797b992a8feb566f9ad73060011ab6f51eb7ce01
* ART: Fix Trace types, check minimum buf sizeAndreas Gampe2015-04-251-1/+2
| | | | | | | | | Also make streaming mode adhere to the given buffer (and fix the case where the buffer is too small for a packet). This is important to not lose too much tracing information when the runtime is destroyed with an unflushed buffer. Change-Id: I6525fe4326ac5c3d7c9cda41c54a2a911ca889b7
* Merge "Move Class.newInstance to native"Mathieu Chartier2015-04-252-31/+96
|\
| * Move Class.newInstance to nativeMathieu Chartier2015-04-252-31/+96
| | | | | | | | | | | | | | | | | | | | | | | | | | | | Avoids 1 allocation and several JNI transitions. Before: Class_classNewInstance: 4462.39 ns; σ=39.42 ns @ 3 trials After: Class_classNewInstance: 1073.39 ns; σ=24.14 ns @ 10 trials Bug: 20269715 Bug: 20566996 Change-Id: Icd52155ce79a978a4d869855bfdfd7735abd8187
* | ART: Add GENERATE_CFI to the ZygoteHooks debug flagsAndreas Gampe2015-04-241-0/+7
|/ | | | | | | Add code to understand the implications of the debug.gencfi system property that forces generation of CFI data. Change-Id: Ida66f8c1567634d05cfdbba1a982be3684e94369
* Replace NULL with nullptrMathieu Chartier2015-04-229-60/+66
| | | | | | | Also fixed some lines that were too long, and a few other minor details. Change-Id: I6efba5fb6e03eb5d0a300fddb2a75bf8e2f175cb
* Class.forName(..., ..., null) fixesBrian Carlstrom2015-04-211-14/+7
| | | | | | | - Add test for Class.forName(..., ..., null) - Simplify VMStack.getClosestUserClassLoader based on new behavior of Class.forName(..., ..., null) Change-Id: I6bc470e20fa177e8a3debe55c90a84eef7ef518e
* Add AbstractMethod, Constructor, MethodMathieu Chartier2015-04-214-39/+243
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Moves functionality to ART from libcore. Precursor to moving ArtMethods to native. Mostly performance improvements. N5 perf before (irrelevant results removed): Class_getConstructor 962.87 =========== Class_getDeclaredMethod 2394.37 ============================ Class_getMethod 2509.20 ============================== Class_newInstance 1999.81 ======================= Method_invokeI 1439.02 ================= Method_invokePreBoxedI 1415.82 ================ Method_invokeStaticI 1456.24 ================= Method_invokeStaticPreBoxedI 1427.32 ================= Method_invokeStaticV 814.47 ========= Method_invokeV 816.56 ========= After: benchmark ns linear runtime Class_getConstructor 1302.04 ================ Class_getDeclaredMethod 1459.01 ================== Class_getMethod 1560.40 =================== Class_newInstance 2029.94 ========================= Method_invokeI 1312.89 ================ Method_invokePreBoxedI 1255.01 =============== Method_invokeStaticI 1289.13 =============== Method_invokeStaticPreBoxedI 1196.52 ============== Method_invokeStaticV 790.82 ========= Method_invokeV 791.73 ========= Performance improvements are more than just fixing regressions introduced in: http://android-review.googlesource.com/#/c/146069/ Bug: 19264997 Change-Id: Ife79c469fdb09f30e3aefcfc3e0ce5ed32303fce
* ART: Streaming trace modeAndreas Gampe2015-04-151-0/+52
| | | | | | | | | | | | | | | | | | | | | | | | | | | Add a streaming mode for tracing. Streaming uses a buffer of 16KB and writes to the output when that buffer gets full. Streaming mode can be enabled with -Xmethod-trace-stream and is currently not exposed otherwise. Add a python script that can parse the streaming format, which simply contains strings for newly encountered threads and methods inline, and create output that can be used with traceview. Add Trace::Pause and Trace::Abort, which can pause and abort tracing. Abort is different from Stop in that it does not write the data. Add code to the zygote hooks JNI implementation that pauses tracing before the fork, making sure that a child cannot clobber the parent's data. Add code to the zygote hooks JNI implementation that aborts old tracing and starts new tracing in the child after the fork. Currently base the output on the pid. This will not work on an unmodified device, as the profiles directory is not generally writable, but we do not have enough information at that point. Consider a scheme that restarts tracing later. Change-Id: I93c7bf87e35af582bdfdd3ecc7c52454514220dd
* Merge "ART: Make the PathClassLoader fast-path recursive"Andreas Gampe2015-04-141-2/+2
|\
| * ART: Make the PathClassLoader fast-path recursiveAndreas Gampe2015-04-141-2/+2
| | | | | | | | | | | | | | | | | | | | Allow an arbitrary nesting of path class-loaders. This will also handle the fake java.lang.BootClassLoader as a class-loader object correctly (which is of some importance to compile-time initialization). Bug: 19781184 Bug: 19542228 Change-Id: I61f0249cf4ec8df08a83ccbd29bcf067619c28c0
* | Merge "getRuntimeStat() support (ART)."Hiroshi Yamauchi2015-04-141-0/+122
|\ \ | |/ |/|
| * getRuntimeStat() support (ART).Hiroshi Yamauchi2015-04-131-0/+122
| | | | | | | | | | | | | | | | | | | | | | Export some runtime stats (currently GC stats) via VMDebug.getRuntimeStat(). Added several new GC stats such as blocking GC counts and GC count histograms. Bug: 19825248 Change-Id: I8ece9ed241dc3982dfd983d7159090ba82940dce
* | Fix DCHECK failures from Class::VisitFieldRootsMathieu Chartier2015-04-131-2/+1
|/ | | | | | | | | | | | | | We now use GetDeclaringClassUnchecked when marking roots to fix flaky test failures. Fixed a race condition in root marking where we could have non zero field array length with a null pointer. Fixed a race condition where we could be marking roots before FixupTemporaryDeclaringClass had finished. The solution is to only do the declaring class CHECK if we are at least resolved. Fixed JDWP tests by changing FieldId / MethodId to be 64 bits. Also some cleanup. Change-Id: Ibac09519860d93c3f68a5cc964bbc91dc10a279a
* ART: Clean up includes.Vladimir Marko2015-04-131-1/+1
| | | | | | | Reduce dependencies to improve incremental build times. Break up circular dependency involving class_linker-inl.h. Change-Id: I4be742c5c2b5cd9855beea86630fd68aab76b0db
* ART: Add Array.createObjectArray to unstarted runtimeAndreas Gampe2015-04-101-4/+2
| | | | | | | Necessary for compile-time initialization of android.text.Layout. Bug: 19542228 Change-Id: I4220c65fcc3a8aaa2765b6f07f1f81c330484244
* Move ArtField to nativeMathieu Chartier2015-04-104-41/+34
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Add linear alloc. Moved ArtField to be native object. Changed image writer to put ArtFields after the mirror section. Savings: 2MB on low ram devices 4MB on normal devices Total PSS measurements before (normal N5, 95s after shell start): Image size: 7729152 bytes 23112 kB: .NonMoving 23212 kB: .NonMoving 22868 kB: .NonMoving 23072 kB: .NonMoving 22836 kB: .NonMoving 19618 kB: .Zygote 19850 kB: .Zygote 19623 kB: .Zygote 19924 kB: .Zygote 19612 kB: .Zygote Avg: 42745.4 kB After: Image size: 7462912 bytes 17440 kB: .NonMoving 16776 kB: .NonMoving 16804 kB: .NonMoving 17812 kB: .NonMoving 16820 kB: .NonMoving 18788 kB: .Zygote 18856 kB: .Zygote 19064 kB: .Zygote 18841 kB: .Zygote 18629 kB: .Zygote 3499 kB: .LinearAlloc 3408 kB: .LinearAlloc 3424 kB: .LinearAlloc 3600 kB: .LinearAlloc 3436 kB: .LinearAlloc Avg: 39439.4 kB No reflection performance changes. Bug: 19264997 Bug: 17643507 Change-Id: I10c73a37913332080aeb978c7c94713bdfe4fe1c
* Merge "Avoid using dex cache array pointers in libart."Vladimir Marko2015-04-102-0/+44
|\
| * Avoid using dex cache array pointers in libart.Vladimir Marko2015-04-102-0/+44
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In preparation for making dex cache arrays native, avoid using them in Java code. This causes a performance regression for our reflection benchmarks. Class_getDeclaredMethod and Class_getMethod take an up to 30% hit, measured using the Quick compiler. We accept this hit at this stage and we will tune the performance after we're done with the larger effort. Companion libcore/ change: https://android-review.googlesource.com/146069 Bug: 20134538 Change-Id: Ibbef3b50043a1311cd40723ed42e1f1c609b8fc1
* | Merge "Rename isDexOptNeededInternal and add kSelfPatchOatNeeded"Richard Uhler2015-04-091-26/+13
|\ \ | |/ |/|
| * Rename isDexOptNeededInternal and add kSelfPatchOatNeededRichard Uhler2015-04-031-26/+13
| | | | | | | | | | | | | | | | | | This change renames isDexOptNeededInternal to getDexOptNeeded and adds another possible result: kSelfPatchOatNeeded. kSelfPatchOatNeeded is returned when there is no odex file to relocate from but there is an oat file that can be relocated in place. Change-Id: Ib9a6373f98474f1242367b5285086251a9d580e5
* | Refactor and improve GC root handlingMathieu Chartier2015-04-061-9/+16
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Changed GcRoot to use compressed references. Changed root visiting to use virtual functions instead of function pointers. Changed root visting interface to be an array of roots instead of a single root at a time. Added buffered root marking helper to avoid dispatch overhead. Root marking seems a bit faster on EvaluateAndApplyChanges due to batch marking. Pause times unaffected. Mips64 is untested but might work, maybe. Before: MarkConcurrentRoots: Sum: 67.678ms 99% C.I. 2us-664.999us Avg: 161.138us Max: 671us After: MarkConcurrentRoots: Sum: 54.806ms 99% C.I. 2us-499.986us Avg: 136.333us Max: 602us Bug: 19264997 Change-Id: I0a71ebb5928f205b9b3f7945b25db6489d5657ca
* | Fix the read barrier builds.Hiroshi Yamauchi2015-04-031-1/+1
|/ | | | | | | | | | A check failure (!UseJit() in ArtMethod::Invoke()) in forced interpret only mode in the eng build with JIT enabled by default on target. A build failure (inl header file issues) in the USE_BAKER_READ_BARRIER build. Change-Id: Ib13632b10864ad8b4691b66971c0ab5d2ae1e675
* Merge "Fix some reflection errors"Mathieu Chartier2015-03-302-4/+7
|\
| * Fix some reflection errorsMathieu Chartier2015-03-292-4/+7
| | | | | | | | | | | | | | | | Fixed incorrectly using 2nd frame instead of 1st in VerifyAccess. Added regression test to ART. Fixed broken setShort, getDeclaredFieldInternal. Change-Id: I4b21d52d998cb768fe9503b8bccec506b7b972e5
* | Merge "ART: Use enums in Trace"Andreas Gampe2015-03-301-3/+9
|\ \ | |/ |/|