Skip to content

Commit

Permalink
Doc changes, made it somewhat node.js friendly.
Browse files Browse the repository at this point in the history
  • Loading branch information
mbebenita committed May 14, 2012
1 parent e371bd7 commit 78a39b5
Show file tree
Hide file tree
Showing 10 changed files with 1,904 additions and 1,795 deletions.
Binary file added docs/images/arrays.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/fork.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/heap.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/mozilla.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
68 changes: 53 additions & 15 deletions docs/index.html
Expand Up @@ -14,17 +14,17 @@
console.info(x);
}
</script>
<script src="jc/util.js"></script>
<script>
var options = new OptionSet("option(s)");
</script>
<script src="vendor/jquery-1.6.4.js"></script>
<script src="jc/modules.js"></script>
<script src="jc/util.js"></script>
<script src="jc/esprima.js"></script>
<script src="jc/escodegen.js"></script>
<script src="jc/compiler.js"></script>
<script src="jc/memory.js"></script>
<body>
<a href="https://github.com/mbebenita/Mvm"><img style="position: absolute; top: 0; right: 0; border: 0;" src="images/fork.png" alt="Fork me on GitHub"></a>
<a href="http://mozilla.org"><img width="118" height="68" style="position: absolute; top: 0; left: 50; border: 0;" src="images/mozilla.png" alt="Mozilla"></a>
<br>
<div class="container">
<h1>*JS : Low-Level JavaScript</h1>
<p>
Expand All @@ -35,12 +35,15 @@ <h1>*JS : Low-Level JavaScript</h1>
The research goal here is to explore low-level statically typed features in a high-level dynamically typed language.
Think of it as inline assembly in C, or the <tt>unsafe</tt> keyword in C#. It's not pretty, but it gets the job done.
</p>
<p>
We're exploring a similar approach in CoffeeScript as well, check out <a href="http://syg.github.com/heap.coffee/">heap.coffee</a>.
</p>
<p>
This is an interactive tutorial, code is compiled as you type.
To execute a piece of code press <tt>Ctrl-R</tt> or <tt>Cmd-Enter</tt>.
</p>

<h4>Variables</h4>
<h2>Variables</h2>
<p>
Unlike JavaScript, *JS variable declarations are block scoped (only the <tt>let</tt> keyword is allowed) and can be annotated with type information.
Untyped variable declarations are defaulted to the <tt>dyn</tt> type.
Expand Down Expand Up @@ -76,13 +79,13 @@ <h4>Variables</h4>

</pre>

<h4> Data Types and Arithmetic</h4>
<h2> Data Types and Arithmetic</h2>
<p>
*JS has 6 integral types: <tt>int -> i32</tt>, <tt>uint -> u32</tt>, <tt>i16</tt>, <tt>u16</tt>, <tt>i8</tt>,
<tt>u8</tt>, which behave as they do in C, and two additional types: <tt>num</tt> (the JavaScript number type)
and <tt>dyn</tt> (any type) which are used to interoperate with the JavaScript type system.
Arithmetic operations usually produce the <tt>num</tt> type even if their operands are integral types.
*JS emits the appropriate coersions for assignments and cast operations.
*JS emits the appropriate coercions for assignments and cast operations.
</p>

<pre class="example">
Expand All @@ -103,7 +106,7 @@ <h4> Data Types and Arithmetic</h4>
let int x = 3;
let int y = 2;

// Arithmetic follows JavaScript semantics, coersions only happen during
// Arithmetic follows JavaScript semantics, coercions only happen during
// assignments and cast operations, so beware.

trace("Result is not an integer: " + x / y);
Expand Down Expand Up @@ -193,7 +196,7 @@ <h4>Functions</h4>
car("123", 2, 123.456);

// The type system is not smart enough to track types that leak into the dynamic
// type system. Safety is your responsability.
// type system. Safety is your responsibility.
let val = car;

// Calling 'var' is not safe.
Expand Down Expand Up @@ -222,7 +225,7 @@ <h4>Functions</h4>
</pre>


<h4>Objects and Memory</h4>
<h2>Objects and Memory</h2>

<p>
*JS has two object models: C style <tt>malloc</tt> and <tt>free</tt>, and the JavaScript object model.
Expand All @@ -242,8 +245,13 @@ <h4>Objects and Memory</h4>
</pre>
<p>
This is inefficient for several reasons. Objects in JavaScript are not cheap, they need to carry around lots of extra information and can be
many times larger than their C style counterparts, moreover property access is slow. In *JS you can write a much more space efficient linked
list using pointers and structs. The code below uses <tt>malloc</tt> to manage memory (more on that later).
many times larger than their C style counterparts, moreover property access can be slow.
Chaining several property accesses together <tt>x.y.z.w</tt> usually results in several memory indirections, in *JS this compiles into a single memory access with a computed offset.
<br>
Usually, when you use a garbage collector you can design a very fast bump allocator which is probably more efficient than *JS's <tt>malloc</tt>, but nothing is free, you pay for it later during
garbage collection. If you have explicit control over memory, you can always do better (if you put in the effort).

In *JS you can write a much more space efficient linked list using pointers and structs.
<!-- With great power comes great responsibility, so what is malloc'ed must be freed, even in JavaScript. -->
</p>

Expand Down Expand Up @@ -298,8 +306,38 @@ <h4>Objects and Memory</h4>

</pre>

<h3>Memory</h3>
<p>
*JS manages memory using <a href="https://developer.mozilla.org/en/JavaScript_typed_arrays">Typed Arrays</a>. It allocates one large <tt>ArrayBuffer</tt> ahead of time,
and creates several typed array views on this buffer, one for each of the primitive data types.
For instance: <tt>U4</tt>, <tt>U2</tt> and <tt>U1</tt> for <tt>u32</tt>, <tt>u16</tt> and <tt>u8</tt> respectively (see figure below).
(For a more in-depth discussion, see how <a href="https://github.com/kripken/emscripten/wiki/Code-Generation-Modes">Emscripten</a> does it.)
This really is the same thing as the scaled/indexed addressing mode in x86.
The only drawback is that you can't read unaligned data, but this is actually a good thing, since unaligned access is usually slower, or not even possible on some platforms.

<img src="images/arrays.png" style="display: block; margin-left: auto; margin-right: auto;">
</p>
<h3>Pointers</h3>
<p>
Since our managed memory is actually byte addressable, there is no reason to store pointers as byte addresses, instead we store them as indices, implicitly scaled by their own base type.
For example, the pointer dereference <tt>*p</tt>, where <tt>p</tt> is of type <tt>int*</tt>, gets compiled into <tt>U4[p]</tt>.
(Had we stored pointers as byte addresses, we would have compiled it to <tt>U32[p >> 2]</tt>.)
This eliminates address computations at each memory access, but requires that we perform pointer conversions whenever we cast from one pointer type to another, see below:
</p>

<pre class="example">
let int * x = (void *) 8;
let u16 * y = x;
let int z = *x + *y;
</pre>

<h3>Malloc & Free</h3>
<p>
<tt>malloc</tt> and <tt>free</tt> are themselves implemented in *JS, see below:
The *JS memory allocator, transcribed from the K&R C implementation, is itself implemented in *JS. For now, we allocate one large chunk of memory <tt>32 MB</tt> and let
<tt>malloc</tt> and <tt>free</tt> manage it. We reserve the first two words in memory for the Heap Pointer <tt>HP</tt> that points to the latest allocated page by <tt>sbrk</tt>
and the Stack Pointer <tt>SP</tt> which always points to the top of the stack. The heap grows downward (towards higher addresses) and the stack grows upward.
For now, when the two meet we run out of memory, but we could resize the array buffer copy the heap over and resume.
<img src="images/heap.png" style="display: block; margin-left: auto; margin-right: auto;">
</p>

<pre class="example">
Expand Down Expand Up @@ -473,7 +511,7 @@ <h4>Acknowledgements</h4>
var result = document.getElementById("ex:" + number + ":result");
try {
var node = esprima.parse(this.getValue(), {loc: true});
compile(node, "EX_" + number);
compiler.compile(node, "EX_" + number);
result.innerHTML = escodegen.generate(node, {base: "", indent: " "});
} catch (x) {
result.innerHTML = x.message;
Expand Down Expand Up @@ -528,7 +566,7 @@ <h4>Acknowledgements</h4>
result.innerHTML += "Parser: " + (new Date() - start) + " ms, ";

start = new Date();
node = compile(node, "EX_" + number);
node = compiler.compile(node, "EX_" + number);
result.innerHTML += "Compiler: " + (new Date() - start) + " ms, ";

start = new Date();
Expand Down
7 changes: 2 additions & 5 deletions docs/tests.html
Expand Up @@ -15,9 +15,6 @@
}
</script>
<script src="jc/util.js"></script>
<script>
var options = new OptionSet("option(s)");
</script>
<script src="vendor/jquery-1.6.4.js"></script>
<script src="jc/modules.js"></script>
<script src="jc/esprima.js"></script>
Expand Down Expand Up @@ -69,7 +66,7 @@
var result = document.getElementById("ex:" + number + ":result");
try {
var node = esprima.parse(this.getValue(), {loc: true});
compile(node, "EX_" + number);
compiler.compile(node, "EX_" + number);
result.innerHTML = escodegen.generate(node, {base: "", indent: " "});
} catch (x) {
result.innerHTML = x.message;
Expand Down Expand Up @@ -133,7 +130,7 @@
result.innerHTML += "Parser: " + (new Date() - start) + " ms, ";

start = new Date();
node = compile(node, "EX_" + number);
node = compiler.compile(node, "EX_" + number);
result.innerHTML += "Compiler: " + (new Date() - start) + " ms, ";

start = new Date();
Expand Down

0 comments on commit 78a39b5

Please sign in to comment.