35 lines
19 KiB
HTML
35 lines
19 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width, initial-scale=1.0"/><title>Memory layout of Julia Objects · The Julia Language</title><script>(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
|
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
|
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
|
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
|
|
|
|
ga('create', 'UA-28835595-6', 'auto');
|
|
ga('send', 'pageview');
|
|
</script><link href="https://cdnjs.cloudflare.com/ajax/libs/normalize/4.2.0/normalize.min.css" rel="stylesheet" type="text/css"/><link href="https://fonts.googleapis.com/css?family=Lato|Roboto+Mono" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet" type="text/css"/><script>documenterBaseURL=".."</script><script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.2.0/require.min.js" data-main="../assets/documenter.js"></script><script src="../siteinfo.js"></script><script src="../../versions.js"></script><link href="../assets/highlightjs/default.css" rel="stylesheet" type="text/css"/><link href="../assets/documenter.css" rel="stylesheet" type="text/css"/></head><body><nav class="toc"><a href="../index.html"><img class="logo" src="../assets/logo.png" alt="The Julia Language logo"/></a><h1>The Julia Language</h1><select id="version-selector" onChange="window.location.href=this.value" style="visibility: hidden"></select><form class="search" action="../search.html"><input id="search-query" name="q" type="text" placeholder="Search docs"/></form><ul><li><a class="toctext" href="../index.html">Home</a></li><li><span class="toctext">Manual</span><ul><li><a class="toctext" href="../manual/introduction.html">Introduction</a></li><li><a class="toctext" href="../manual/getting-started.html">Getting Started</a></li><li><a class="toctext" href="../manual/variables.html">Variables</a></li><li><a class="toctext" href="../manual/integers-and-floating-point-numbers.html">Integers and Floating-Point Numbers</a></li><li><a class="toctext" href="../manual/mathematical-operations.html">Mathematical Operations and Elementary Functions</a></li><li><a class="toctext" href="../manual/complex-and-rational-numbers.html">Complex and Rational Numbers</a></li><li><a class="toctext" href="../manual/strings.html">Strings</a></li><li><a class="toctext" href="../manual/functions.html">Functions</a></li><li><a class="toctext" href="../manual/control-flow.html">Control Flow</a></li><li><a class="toctext" href="../manual/variables-and-scoping.html">Scope of Variables</a></li><li><a class="toctext" href="../manual/types.html">Types</a></li><li><a class="toctext" href="../manual/methods.html">Methods</a></li><li><a class="toctext" href="../manual/constructors.html">Constructors</a></li><li><a class="toctext" href="../manual/conversion-and-promotion.html">Conversion and Promotion</a></li><li><a class="toctext" href="../manual/interfaces.html">Interfaces</a></li><li><a class="toctext" href="../manual/modules.html">Modules</a></li><li><a class="toctext" href="../manual/documentation.html">Documentation</a></li><li><a class="toctext" href="../manual/metaprogramming.html">Metaprogramming</a></li><li><a class="toctext" href="../manual/arrays.html">Multi-dimensional Arrays</a></li><li><a class="toctext" href="../manual/linear-algebra.html">Linear algebra</a></li><li><a class="toctext" href="../manual/networking-and-streams.html">Networking and Streams</a></li><li><a class="toctext" href="../manual/parallel-computing.html">Parallel Computing</a></li><li><a class="toctext" href="../manual/dates.html">Date and DateTime</a></li><li><a class="toctext" href="../manual/interacting-with-julia.html">Interacting With Julia</a></li><li><a class="toctext" href="../manual/running-external-programs.html">Running External Programs</a></li><li><a class="toctext" href="../manual/calling-c-and-fortran-code.html">Calling C and Fortran Code</a></li><li><a class="toctext" href="../manual/handling-operating-system-variation.html">Handling Operating System Variation</a></li><li><a class="toctext" href="../manual/environment-variables.html">Environment Variables</a></li><li><a class="toctext" href="../manual/embedding.html">Embedding Julia</a></li><li><a class="toctext" href="../manual/packages.html">Packages</a></li><li><a class="toctext" href="../manual/profile.html">Profiling</a></li><li><a class="toctext" href="../manual/stacktraces.html">Stack Traces</a></li><li><a class="toctext" href="../manual/performance-tips.html">Performance Tips</a></li><li><a class="toctext" href="../manual/workflow-tips.html">Workflow Tips</a></li><li><a class="toctext" href="../manual/style-guide.html">Style Guide</a></li><li><a class="toctext" href="../manual/faq.html">Frequently Asked Questions</a></li><li><a class="toctext" href="../manual/noteworthy-differences.html">Noteworthy Differences from other Languages</a></li><li><a class="toctext" href="../manual/unicode-input.html">Unicode Input</a></li></ul></li><li><span class="toctext">Standard Library</span><ul><li><a class="toctext" href="../stdlib/base.html">Essentials</a></li><li><a class="toctext" href="../stdlib/collections.html">Collections and Data Structures</a></li><li><a class="toctext" href="../stdlib/math.html">Mathematics</a></li><li><a class="toctext" href="../stdlib/numbers.html">Numbers</a></li><li><a class="toctext" href="../stdlib/strings.html">Strings</a></li><li><a class="toctext" href="../stdlib/arrays.html">Arrays</a></li><li><a class="toctext" href="../stdlib/parallel.html">Tasks and Parallel Computing</a></li><li><a class="toctext" href="../stdlib/linalg.html">Linear Algebra</a></li><li><a class="toctext" href="../stdlib/constants.html">Constants</a></li><li><a class="toctext" href="../stdlib/file.html">Filesystem</a></li><li><a class="toctext" href="../stdlib/io-network.html">I/O and Network</a></li><li><a class="toctext" href="../stdlib/punctuation.html">Punctuation</a></li><li><a class="toctext" href="../stdlib/sort.html">Sorting and Related Functions</a></li><li><a class="toctext" href="../stdlib/pkg.html">Package Manager Functions</a></li><li><a class="toctext" href="../stdlib/dates.html">Dates and Time</a></li><li><a class="toctext" href="../stdlib/iterators.html">Iteration utilities</a></li><li><a class="toctext" href="../stdlib/test.html">Unit Testing</a></li><li><a class="toctext" href="../stdlib/c.html">C Interface</a></li><li><a class="toctext" href="../stdlib/libc.html">C Standard Library</a></li><li><a class="toctext" href="../stdlib/libdl.html">Dynamic Linker</a></li><li><a class="toctext" href="../stdlib/profile.html">Profiling</a></li><li><a class="toctext" href="../stdlib/stacktraces.html">StackTraces</a></li><li><a class="toctext" href="../stdlib/simd-types.html">SIMD Support</a></li></ul></li><li><span class="toctext">Developer Documentation</span><ul><li><a class="toctext" href="reflection.html">Reflection and introspection</a></li><li><span class="toctext">Documentation of Julia's Internals</span><ul><li><a class="toctext" href="init.html">Initialization of the Julia runtime</a></li><li><a class="toctext" href="ast.html">Julia ASTs</a></li><li><a class="toctext" href="types.html">More about types</a></li><li class="current"><a class="toctext" href="object.html">Memory layout of Julia Objects</a><ul class="internal"><li><a class="toctext" href="#Object-layout-(jl_value_t)-1">Object layout (jl_value_t)</a></li><li><a class="toctext" href="#Garbage-collector-mark-bits-1">Garbage collector mark bits</a></li><li><a class="toctext" href="#Object-allocation-1">Object allocation</a></li></ul></li><li><a class="toctext" href="eval.html">Eval of Julia code</a></li><li><a class="toctext" href="callconv.html">Calling Conventions</a></li><li><a class="toctext" href="compiler.html">High-level Overview of the Native-Code Generation Process</a></li><li><a class="toctext" href="functions.html">Julia Functions</a></li><li><a class="toctext" href="cartesian.html">Base.Cartesian</a></li><li><a class="toctext" href="meta.html">Talking to the compiler (the <code>:meta</code> mechanism)</a></li><li><a class="toctext" href="subarrays.html">SubArrays</a></li><li><a class="toctext" href="sysimg.html">System Image Building</a></li><li><a class="toctext" href="llvm.html">Working with LLVM</a></li><li><a class="toctext" href="stdio.html">printf() and stdio in the Julia runtime</a></li><li><a class="toctext" href="boundscheck.html">Bounds checking</a></li><li><a class="toctext" href="locks.html">Proper maintenance and care of multi-threading locks</a></li><li><a class="toctext" href="offset-arrays.html">Arrays with custom indices</a></li><li><a class="toctext" href="libgit2.html">Base.LibGit2</a></li><li><a class="toctext" href="require.html">Module loading</a></li></ul></li><li><span class="toctext">Developing/debugging Julia's C code</span><ul><li><a class="toctext" href="backtraces.html">Reporting and analyzing crashes (segfaults)</a></li><li><a class="toctext" href="debuggingtips.html">gdb debugging tips</a></li><li><a class="toctext" href="valgrind.html">Using Valgrind with Julia</a></li><li><a class="toctext" href="sanitizers.html">Sanitizer support</a></li></ul></li></ul></li></ul></nav><article id="docs"><header><nav><ul><li>Developer Documentation</li><li>Documentation of Julia's Internals</li><li><a href="object.html">Memory layout of Julia Objects</a></li></ul><a class="edit-page" href="https://github.com/JuliaLang/julia/tree/d386e40c17d43b79fc89d3e579fc04547241787c/doc/src/devdocs/object.md"><span class="fa"></span> Edit on GitHub</a></nav><hr/><div id="topbar"><span>Memory layout of Julia Objects</span><a class="fa fa-bars" href="#"></a></div></header><h1><a class="nav-anchor" id="Memory-layout-of-Julia-Objects-1" href="#Memory-layout-of-Julia-Objects-1">Memory layout of Julia Objects</a></h1><h2><a class="nav-anchor" id="Object-layout-(jl_value_t)-1" href="#Object-layout-(jl_value_t)-1">Object layout (jl_value_t)</a></h2><p>The <code>jl_value_t</code> struct is the name for a block of memory owned by the Julia Garbage Collector, representing the data associated with a Julia object in memory. Absent any type information, it is simply an opaque pointer:</p><pre><code class="language-c">typedef struct jl_value_t* jl_pvalue_t;</code></pre><p>Each <code>jl_value_t</code> struct is contained in a <code>jl_typetag_t</code> struct that contains metadata information about the Julia object, such as its type and garbage collector (gc) reachability:</p><pre><code class="language-c">typedef struct {
|
|
opaque metadata;
|
|
jl_value_t value;
|
|
} jl_typetag_t;</code></pre><p>The type of any Julia object is an instance of a leaf <code>jl_datatype_t</code> object. The <code>jl_typeof()</code> function can be used to query for it:</p><pre><code class="language-c">jl_value_t *jl_typeof(jl_value_t *v);</code></pre><p>The layout of the object depends on its type. Reflection methods can be used to inspect that layout. A field can be accessed by calling one of the get-field methods:</p><pre><code class="language-c">jl_value_t *jl_get_nth_field_checked(jl_value_t *v, size_t i);
|
|
jl_value_t *jl_get_field(jl_value_t *o, char *fld);</code></pre><p>If the field types are known, a priori, to be all pointers, the values can also be extracted directly as an array access:</p><pre><code class="language-c">jl_value_t *v = value->fieldptr[n];</code></pre><p>As an example, a "boxed" <code>uint16_t</code> is stored as follows:</p><pre><code class="language-c">struct {
|
|
opaque metadata;
|
|
struct {
|
|
uint16_t data; // -- 2 bytes
|
|
} jl_value_t;
|
|
};</code></pre><p>This object is created by <code>jl_box_uint16()</code>. Note that the <code>jl_value_t</code> pointer references the data portion, not the metadata at the top of the struct.</p><p>A value may be stored "unboxed" in many circumstances (just the data, without the metadata, and possibly not even stored but just kept in registers), so it is unsafe to assume that the address of a box is a unique identifier. The "egal" test (corresponding to the <code>===</code> function in Julia), should instead be used to compare two unknown objects for equivalence:</p><pre><code class="language-c">int jl_egal(jl_value_t *a, jl_value_t *b);</code></pre><p>This optimization should be relatively transparent to the API, since the object will be "boxed" on-demand, whenever a <code>jl_value_t</code> pointer is needed.</p><p>Note that modification of a <code>jl_value_t</code> pointer in memory is permitted only if the object is mutable. Otherwise, modification of the value may corrupt the program and the result will be undefined. The mutability property of a value can be queried for with:</p><pre><code class="language-c">int jl_is_mutable(jl_value_t *v);</code></pre><p>If the object being stored is a <code>jl_value_t</code>, the Julia garbage collector must be notified also:</p><pre><code class="language-c">void jl_gc_wb(jl_value_t *parent, jl_value_t *ptr);</code></pre><p>However, the <a href="../manual/embedding.html#Embedding-Julia-1">Embedding Julia</a> section of the manual is also required reading at this point, for covering other details of boxing and unboxing various types, and understanding the gc interactions.</p><p>Mirror structs for some of the built-in types are <a href="https://github.com/JuliaLang/julia/blob/master/src/julia.h">defined in <code>julia.h</code></a>. The corresponding global <code>jl_datatype_t</code> objects are created by <a href="https://github.com/JuliaLang/julia/blob/master/src/jltypes.c"><code>jl_init_types</code> in <code>jltypes.c</code></a>.</p><h2><a class="nav-anchor" id="Garbage-collector-mark-bits-1" href="#Garbage-collector-mark-bits-1">Garbage collector mark bits</a></h2><p>The garbage collector uses several bits from the metadata portion of the <code>jl_typetag_t</code> to track each object in the system. Further details about this algorithm can be found in the comments of the <a href="https://github.com/JuliaLang/julia/blob/master/src/gc.c">garbage collector implementation in <code>gc.c</code></a>.</p><h2><a class="nav-anchor" id="Object-allocation-1" href="#Object-allocation-1">Object allocation</a></h2><p>Most new objects are allocated by <code>jl_new_structv()</code>:</p><pre><code class="language-c">jl_value_t *jl_new_struct(jl_datatype_t *type, ...);
|
|
jl_value_t *jl_new_structv(jl_datatype_t *type, jl_value_t **args, uint32_t na);</code></pre><p>Although, <a href="../stdlib/base.html#Base.isbits"><code>isbits</code></a> objects can be also constructed directly from memory:</p><pre><code class="language-c">jl_value_t *jl_new_bits(jl_value_t *bt, void *data)</code></pre><p>And some objects have special constructors that must be used instead of the above functions:</p><p>Types:</p><pre><code class="language-c">jl_datatype_t *jl_apply_type(jl_datatype_t *tc, jl_tuple_t *params);
|
|
jl_datatype_t *jl_apply_array_type(jl_datatype_t *type, size_t dim);
|
|
jl_uniontype_t *jl_new_uniontype(jl_tuple_t *types);</code></pre><p>While these are the most commonly used options, there are more low-level constructors too, which you can find declared in <a href="https://github.com/JuliaLang/julia/blob/master/src/julia.h"><code>julia.h</code></a>. These are used in <code>jl_init_types()</code> to create the initial types needed to bootstrap the creation of the Julia system image.</p><p>Tuples:</p><pre><code class="language-c">jl_tuple_t *jl_tuple(size_t n, ...);
|
|
jl_tuple_t *jl_tuplev(size_t n, jl_value_t **v);
|
|
jl_tuple_t *jl_alloc_tuple(size_t n);</code></pre><p>The representation of tuples is highly unique in the Julia object representation ecosystem. In some cases, a <a href="../stdlib/base.html#Core.tuple"><code>Base.tuple()</code></a> object may be an array of pointers to the objects contained by the tuple equivalent to:</p><pre><code class="language-c">typedef struct {
|
|
size_t length;
|
|
jl_value_t *data[length];
|
|
} jl_tuple_t;</code></pre><p>However, in other cases, the tuple may be converted to an anonymous <a href="../stdlib/base.html#Base.isbits"><code>isbits</code></a> type and stored unboxed, or it may not stored at all (if it is not being used in a generic context as a <code>jl_value_t*</code>).</p><p>Symbols:</p><pre><code class="language-c">jl_sym_t *jl_symbol(const char *str);</code></pre><p>Functions and MethodInstance:</p><pre><code class="language-c">jl_function_t *jl_new_generic_function(jl_sym_t *name);
|
|
jl_method_instance_t *jl_new_method_instance(jl_value_t *ast, jl_tuple_t *sparams);</code></pre><p>Arrays:</p><pre><code class="language-c">jl_array_t *jl_new_array(jl_value_t *atype, jl_tuple_t *dims);
|
|
jl_array_t *jl_new_arrayv(jl_value_t *atype, ...);
|
|
jl_array_t *jl_alloc_array_1d(jl_value_t *atype, size_t nr);
|
|
jl_array_t *jl_alloc_array_2d(jl_value_t *atype, size_t nr, size_t nc);
|
|
jl_array_t *jl_alloc_array_3d(jl_value_t *atype, size_t nr, size_t nc, size_t z);
|
|
jl_array_t *jl_alloc_vec_any(size_t n);</code></pre><p>Note that many of these have alternative allocation functions for various special-purposes. The list here reflects the more common usages, but a more complete list can be found by reading the <a href="https://github.com/JuliaLang/julia/blob/master/src/julia.h"><code>julia.h</code> header file</a>.</p><p>Internal to Julia, storage is typically allocated by <code>newstruct()</code> (or <code>newobj()</code> for the special types):</p><pre><code class="language-c">jl_value_t *newstruct(jl_value_t *type);
|
|
jl_value_t *newobj(jl_value_t *type, size_t nfields);</code></pre><p>And at the lowest level, memory is getting allocated by a call to the garbage collector (in <code>gc.c</code>), then tagged with its type:</p><pre><code class="language-c">jl_value_t *jl_gc_allocobj(size_t nbytes);
|
|
void jl_set_typeof(jl_value_t *v, jl_datatype_t *type);</code></pre><p>Note that all objects are allocated in multiples of 4 bytes and aligned to the platform pointer size. Memory is allocated from a pool for smaller objects, or directly with <code>malloc()</code> for large objects.</p><div class="admonition sidebar"><div class="admonition-title">Singleton Types</div><div class="admonition-text"><p>Singleton types have only one instance and no data fields. Singleton instances have a size of 0 bytes, and consist only of their metadata. e.g. <code>nothing::Void</code>.</p><p>See <a href="../manual/types.html#man-singleton-types-1">Singleton Types</a> and <a href="../manual/faq.html#Nothingness-and-missing-values-1">Nothingness and missing values</a></p></div></div><footer><hr/><a class="previous" href="types.html"><span class="direction">Previous</span><span class="title">More about types</span></a><a class="next" href="eval.html"><span class="direction">Next</span><span class="title">Eval of Julia code</span></a></footer></article></body></html>
|