mollusk 019f8e3064 Add: julia-0.6.2
Former-commit-id: ccc667cf67d569f3fb3df39aa57c2134755a7551
2018-02-10 10:27:19 -07:00

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&#39;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&#39;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&#39;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-&gt;fieldptr[n];</code></pre><p>As an example, a &quot;boxed&quot; <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 &quot;unboxed&quot; 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 &quot;egal&quot; 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 &quot;boxed&quot; 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>