← All topics

19 articles in the notebook

MSIL.

Unsafe reference arithmetic in .NET

A closer look at CompilerServices.Unsafe as the modern alternative to the fixed statement: doing reference arithmetic on GC-managed memory without pinning, what "unsafe" really means, and what the CLR does and doesn't promise you.

Why C# multidimensional arrays are slow

int[,] looks like the natural choice and performs like the wrong one. Digging into IL and JIT output to show what actually happens when you access single-dimensional, multidimensional and jagged arrays — and why the rectangular one loses.

Faster C# array access

Every array access in .NET pays for a bounds check — unless you convince the compiler it can skip it. I read the JIT'ed x64 assembly and benchmark tricks that make plain array access 18-34% faster.

sizeof() vs Marshal.SizeOf()

sizeof() compiles to a constant; Marshal.SizeOf() measures the marshaled struct at runtime. What each one really returns, what it costs, and when to use which — with IL to prove it.

Cost of method wrapper

What does a method that just calls another method actually cost? Using the == operator vs IEquatable.Equals as the guinea pig, I benchmark wrapper calls across compilers, JITs and runtimes — and read the disassembly to see why.

Bug in Mono.Cecil

Mono.Cecil kept producing broken assemblies with branches jumping out of the method — until Jb Evain explained the magic: call Body.Simplify() before modifying and Body.Optimize() after. Not a bug after all.

Small milestone reach today

The full event pipeline works end to end: pressing a button in the test app sends an event through the ScriptEngine, into the queue, and out to the correct compiled script. Screenshot included.

ScriptEngine - Events

Builtin commands are easy — incoming events need planning. An EventHandler translates OpenSim happenings into LSL-compatible events, and an Event Queue Manager executes them on a separate thread so the server never blocks.

ScriptEngine

The architecture for OpenSim script support: a dynamically loaded ScriptEngine assembly that hooks the server's events, a compiler that turns LSL into .NET assemblies, and the loading pipeline between them.

Frames, heap and code pointers

LSL bytecode is full of pointers — static frames, heap, jump targets — all referring to positions inside a 16k LSO file. Here is my plan for mapping them onto dictionaries and two-pass MSIL label generation.

Stack issues

Direct translation from the LSO stack to the .NET stack falls apart: LSO doesn't always tell you the datatype, and .NET wants its stack served in a very particular order. The fix: my own stack in a base class the compiled scripts inherit from.

LSL scripting support - Progress report

The converter can now take LSL bytecode all the way to a compiled .NET .dll on disk, with events visible in Visual Studio and llSay mapped to Console.WriteLine. Messy code, but the goal is simply "Version 1: Functional".

Making some progress

Found the "final bug" in the LSL bytecode parser and compiled my first small function to a working .dll. One opcode and one builtin command supported — it's a start, and it works!

.Net CLR Runtime

Can LSL bytecode map onto .NET CLR? Yes — and here is the biggest Hello World I have ever written, generated at run-time with ILGenerator and OpCodes.

LSO / LSL ByteCode

The plan for OpenSim script support: read compiled LSL bytecode, convert it to .NET bytecode and let the JIT produce native code, with AppDomains providing the sandbox. Blazing fast execution inside the .NET VM.