# HG changeset patch
# User cin
# Date 1382906955 -14400
# Node ID cb13da6e3349abc9c945baa15465a333b88abcbf
# Parent  1ae5b10f7a10bea0b1746802427983f577b2387a
simple loop test
diff -r 1ae5b10f7a10 -r cb13da6e3349 Jint.Runtime/Jint.Runtime.csproj
--- a/Jint.Runtime/Jint.Runtime.csproj	Sun Oct 27 21:20:59 2013 +0400
+++ b/Jint.Runtime/Jint.Runtime.csproj	Mon Oct 28 00:49:15 2013 +0400
@@ -45,7 +45,9 @@
     
     
     
-    
+    
+    
+    
     
     
   
diff -r 1ae5b10f7a10 -r cb13da6e3349 Jint.Runtime/Main.cs
--- a/Jint.Runtime/Main.cs	Sun Oct 27 21:20:59 2013 +0400
+++ b/Jint.Runtime/Main.cs	Mon Oct 28 00:49:15 2013 +0400
@@ -12,12 +12,25 @@
         {
             RuntimeContext runtime = new RuntimeContext();
             runtime.DefineBinaryOperation(Codes.Add, (x, y) => x + y);
+            runtime.DefineCompareOperation((x, y) => x.CompareTo(y));
 
-            var frame = new Frame(4,runtime);
+            var frame = new Frame(5,runtime);
+            frame.SetValue(1, 10000000);
             frame.SetValue(2,0);
             frame.SetValue(3,1);
 
-            var op = new BinaryOp(Codes.Add, 2, 3, 2);
+
+            var code = new LteCmp(2, 1, 4);
+            var body = new BinaryOp(Codes.Add, 2, 3, 2);
+            body.Chain(code);
+            code.Chain(
+                new ConditionOp(
+                    4,
+                    body,
+                    null
+                )
+            );
+                        
 
 			var t = Environment.TickCount;
 
@@ -25,38 +38,33 @@
              *          mov r1, 10 000 000
              *          mov r2, 0
              *          mov r3, 1
-             *          loop
-             *              condition:
-             *                  gte r2, r1
-             *              body:
-             *                  add r2,r3,r2
+             *          lte r2, r1, r4
+             * cmp:
+             *          test r4 { success => body, fail => end }
+             * body:
+             *          add r2,r3,r2
+             *          goto cmp
+             * end:
              */
 
-            for (int i = 0; i < 10000000; i++)
-                op.Invoke(frame);
+            for (IInstruction op = code; op != null; op = op.Invoke(frame))
+                ;
 
-			Console.WriteLine ("vm: {0}, int {1} ms", frame.GetValue(2), Environment.TickCount - t );
+			Console.WriteLine ("vm: {0}, int {1} ms", frame.GetConverted(2), Environment.TickCount - t );
 
             t = Environment.TickCount;
 
-            /*
-             *          mov r1, 10 000 000
-             *          mov r2, 0
-             *          mov r3, 1
-             *          loop
-             *              condition:
-             *                  gte r2, r1
-             *              body:
-             *                  add r2,r3,r2
-             */
-            object count = 0, inc = 1;
+            object count = 0, inc = 1, max = 10000000;
             
-            for (int i = 0; i < 10000000; i++)
+            while(Compare(count,max) <= 0)
                 count = Add(count,inc);
 
             Console.WriteLine("native: {0}, int {1} ms", frame.GetValue(2), Environment.TickCount - t);
 
-			t = Environment.TickCount;
+        }
+
+        public static int Compare(object arg1, object arg2) {
+            return ((int)arg1).CompareTo((int)arg2);
         }
 
         public static object Add(object arg1, object arg2) {
diff -r 1ae5b10f7a10 -r cb13da6e3349 Jint.Runtime/VM/AbstractBox.cs
--- a/Jint.Runtime/VM/AbstractBox.cs	Sun Oct 27 21:20:59 2013 +0400
+++ b/Jint.Runtime/VM/AbstractBox.cs	Mon Oct 28 00:49:15 2013 +0400
@@ -16,7 +16,8 @@
 
         public abstract void InvokeBinaryOperation(Codes code, int arg2, int dest, Frame frame);
         public abstract void InvokeUnaryOperation(Codes code, int dest, Frame frame);
-        public abstract void InvokeCompareOperation(int arg2, int dest, Frame frame);
-        public abstract void InvokeEqualityOperation(int arg2, int dest, Frame frame);
+        public abstract int InvokeCompareOperation(int arg2, Frame frame);
+        public abstract bool InvokeEqualityOperation(int arg2, Frame frame);
+        public abstract T Convert();
     }
 }
diff -r 1ae5b10f7a10 -r cb13da6e3349 Jint.Runtime/VM/Box.cs
--- a/Jint.Runtime/VM/Box.cs	Sun Oct 27 21:20:59 2013 +0400
+++ b/Jint.Runtime/VM/Box.cs	Mon Oct 28 00:49:15 2013 +0400
@@ -3,6 +3,7 @@
 using System.Linq;
 using System.Text;
 using Jint.Runtime.VM.OpCodes;
+using System.ComponentModel;
 
 namespace Jint.Runtime.VM {
     class Box: AbstractBox, IGettter, ISetter {
@@ -10,6 +11,7 @@
         public T holdingValue;
         object[] m_impl;
         RuntimeContext m_runtime;
+        TypeConverter m_converter;
 
         public Box(T value, RuntimeContext runtime): base(typeof(T)) {
             if (runtime == null)
@@ -27,6 +29,14 @@
             }
         }
 
+        TypeConverter TypeConverter {
+            get {
+                if (m_converter == null)
+                    m_converter = TypeDescriptor.GetConverter(typeof(T));
+                return m_converter;
+            }
+        }
+
         public T Get() {
             return holdingValue;
         }
@@ -45,14 +55,18 @@
             frame.SetValue(dest, op(holdingValue));
         }
 
-        public override void InvokeCompareOperation(int arg2, int dest, Frame frame) {
+        public override int InvokeCompareOperation(int arg2, Frame frame) {
             var op = (CompareOperation)Impl[(int)Codes.Cmp];
-            frame.SetValue(dest, op(holdingValue, frame.GetValue(arg2)));
+            return op(holdingValue, frame.GetValue(arg2));
         }
 
-        public override void InvokeEqualityOperation(int arg2, int dest, Frame frame) {
+        public override bool InvokeEqualityOperation(int arg2, Frame frame) {
             var op = (EqualityOperation)Impl[(int)Codes.Cmp];
-            frame.SetValue(dest, op(holdingValue, frame.GetValue(arg2)));
+            return op(holdingValue, frame.GetValue(arg2));
+        }
+
+        public override T2 Convert() {
+            return (T2)TypeConverter.ConvertTo(holdingValue, typeof(T2));
         }
     }
 }
diff -r 1ae5b10f7a10 -r cb13da6e3349 Jint.Runtime/VM/Frame.cs
--- a/Jint.Runtime/VM/Frame.cs	Sun Oct 27 21:20:59 2013 +0400
+++ b/Jint.Runtime/VM/Frame.cs	Mon Oct 28 00:49:15 2013 +0400
@@ -17,6 +17,11 @@
             m_registers = new AbstractBox[size];
         }
 
+        /// 
+        /// Return register at the specified index.
+        /// 
+        /// The index of the register
+        /// The register.
         public AbstractBox this[int index] {
             get {
                 return m_registers[index];
@@ -27,12 +32,12 @@
         }
 
         /// 
-        /// Extracts value stored in the registry specified by the index.
+        /// Extracts value stored in the register specified by the index.
         /// 
         /// This method doesn't do any cast, if the specified type isn't the same as the type of the stored value a type cast exception will occur.
-        /// The type of the value stored in the registry.
-        /// The index of the registry.
-        /// The value stored in the registry.
+        /// The type of the value stored in the register.
+        /// The index of the register.
+        /// The value stored in the register.
         public T GetValue(int index) {
             return ((Box)m_registers[index]).holdingValue;
         }
@@ -41,13 +46,13 @@
         /// Stores a new value in the register specified by the index.
         /// 
         /// 
-        /// If the previous value has the same type as the value being stored in the registry,
-        /// the new value will replace the old one, otherwise the registry will be reallocated to
+        /// If the previous value has the same type as the value being stored in the register,
+        /// the new value will replace the old one, otherwise the register will be reallocated to
         /// store the new value.
         /// 
         /// The type of the value being stored
-        /// The index of the registry where the value will be stored
-        /// The value to be stored in the registry
+        /// The index of the register where the value will be stored
+        /// The value to be stored in the register
         public void SetValue(int index, T value) {
             var reg = m_registers[index] as Box;
             if (reg == null || reg.holdingType != typeof(T))
@@ -55,5 +60,14 @@
             else
                 reg.holdingValue = value;
         }
+
+        public T GetConverted(int index) {
+            var reg = m_registers[index];
+
+            if (reg.holdingType == typeof(T))
+                return ((Box)reg).holdingValue;
+            else
+                return reg.Convert();
+        }
     }
 }
diff -r 1ae5b10f7a10 -r cb13da6e3349 Jint.Runtime/VM/OpCodes/ConditionOp.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Jint.Runtime/VM/OpCodes/ConditionOp.cs	Mon Oct 28 00:49:15 2013 +0400
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Jint.Runtime.VM.OpCodes {
+    class ConditionOp: IInstruction {
+        int m_test;
+        IInstruction m_success;
+        IInstruction m_fail;
+
+        public ConditionOp(int test, IInstruction success, IInstruction fail) {
+            m_test = test;
+            m_success = success;
+            m_fail = fail;
+        }
+
+        public IInstruction Invoke(Frame frame) {
+            return frame.GetConverted(m_test) ? m_success : m_fail;
+        }
+    }
+}
diff -r 1ae5b10f7a10 -r cb13da6e3349 Jint.Runtime/VM/OpCodes/GteCmp.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Jint.Runtime/VM/OpCodes/GteCmp.cs	Mon Oct 28 00:49:15 2013 +0400
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Jint.Runtime.VM.OpCodes {
+    class GteCmp: IInstruction {
+        int m_arg1;
+        int m_arg2;
+        int m_dest;
+        IInstruction m_next;
+
+        public GteCmp(int arg1, int arg2, int dest) {
+            m_arg1 = arg1;
+            m_arg2 = arg2;
+            m_dest = dest;
+        }
+
+        public IInstruction Chain(IInstruction next) {
+            return m_next = next;
+        }
+
+        public IInstruction Invoke(Frame frame) {
+            frame.SetValue(m_dest, frame[m_arg1].InvokeCompareOperation(m_arg2, frame) >= 0);
+            return m_next;
+        }
+    }
+}
diff -r 1ae5b10f7a10 -r cb13da6e3349 Jint.Runtime/VM/OpCodes/Loop.cs
--- a/Jint.Runtime/VM/OpCodes/Loop.cs	Sun Oct 27 21:20:59 2013 +0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Jint.Runtime.VM.OpCodes {
-    class Loop {
-
-    }
-}
diff -r 1ae5b10f7a10 -r cb13da6e3349 Jint.Runtime/VM/OpCodes/LteCmp.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Jint.Runtime/VM/OpCodes/LteCmp.cs	Mon Oct 28 00:49:15 2013 +0400
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Jint.Runtime.VM.OpCodes {
+    class LteCmp: IInstruction {
+        int m_arg1;
+        int m_arg2;
+        int m_dest;
+        IInstruction m_next;
+
+        public LteCmp(int arg1, int arg2, int dest) {
+            m_arg1 = arg1;
+            m_arg2 = arg2;
+            m_dest = dest;
+        }
+
+        public IInstruction Chain(IInstruction next) {
+            return m_next = next;
+        }
+
+        public IInstruction Invoke(Frame frame) {
+            frame.SetValue(m_dest, frame[m_arg1].InvokeCompareOperation(m_arg2, frame) <= 0);
+            return m_next;
+        }
+    }
+}
diff -r 1ae5b10f7a10 -r cb13da6e3349 Jint.Runtime/VM/RuntimeContext.cs
--- a/Jint.Runtime/VM/RuntimeContext.cs	Sun Oct 27 21:20:59 2013 +0400
+++ b/Jint.Runtime/VM/RuntimeContext.cs	Mon Oct 28 00:49:15 2013 +0400
@@ -20,12 +20,21 @@
             return new Box(value, this);
         }
 
-        public void DefineBinaryOperation(Codes code, BinaryOperation op) {
+        object[] GetOrCreateOps(Type type) {
             object[] ops;
-            if (!m_impls.TryGetValue(typeof(T), out ops))
-                ops = m_impls[typeof(T)] = new object[(int)Codes.MaxOp];
+            if (!m_impls.TryGetValue(type, out ops))
+                ops = m_impls[type] = new object[(int)Codes.MaxOp];
+            return ops;
+        }
 
+        public void DefineBinaryOperation(Codes code, BinaryOperation op) {
+            object[] ops = GetOrCreateOps(typeof(T));
             ops[(int)code] = op;
         }
+
+        public void DefineCompareOperation(CompareOperation op) {
+            object[] ops = GetOrCreateOps(typeof(T));
+            ops[(int)Codes.Cmp] = op;
+        }
     }
 }
diff -r 1ae5b10f7a10 -r cb13da6e3349 Jint.suo
Binary file Jint.suo has changed