VerificationException in string.substring() - caused by double/int confusion?

Sep 12, 2011 at 4:31 PM

I've got some javascript code which does some text looping...

Basically it splits up some long strings like "12,hello,giraffe,etc" into separate parts.

It does this using some simple maths and the .substring() method.

The problem is that somewhere in the calculations, one of my variables gets converted from int to double - and when this happens then the call back in C# fails due to a VerificationException inside Call() in Binder.cs :/

Is this caused by the arguments being substring(0,635.0)  rather than (0,635) or is something else going on here?

Will keep digging

Sep 12, 2011 at 4:34 PM

Just done a quick test... and it's nothing to do with the 635.0 - I get the same error with integers 0,635.

There's a genuine VerificationException going on here somewhere - so maybe two versions of Substring being generated somehow.

Will keep digging...

Sep 12, 2011 at 4:48 PM

Not sure what the problem is... call stack is something like - everything being executed on a single thread now. Have also tried doing this on a single thread without making the script engine reentrant:

  at binder_for_Jurassic.Library.StringInstance.Substring()
   at Jurassic.Compiler.Binder.Call(ScriptEngine engine, Object thisObject, Object[] arguments)
   at Jurassic.Library.ClrFunction.CallLateBound(Object thisObject, Object[] arguments)
   at anonymous()
   at Jurassic.Library.UserDefinedFunction.CallLateBound(Object thisObject, Object[] argumentValues)
   at anonymous()
   at Jurassic.Library.UserDefinedFunction.CallLateBound(Object thisObject, Object[] argumentValues)
   at anonymous()
   at Jurassic.Library.UserDefinedFunction.CallLateBound(Object thisObject, Object[] argumentValues)
   at anonymous()
   at Jurassic.Library.UserDefinedFunction.CallLateBound(Object thisObject, Object[] argumentValues)
   at anonymous()
   at Jurassic.Library.UserDefinedFunction.CallLateBound(Object thisObject, Object[] argumentValues)
   at Jurassic.Library.FunctionInstance.Call(Object thisObj, Object[] arguments)
   at Jurassic.PhoneApp.Yapl.YaplAsync.YaplAsyncExec(FunctionInstance executeFirst, Int32 delay, Object argument, FunctionInstance executeSecond)
   at System.Reflection.RuntimeMethodInfo.InternalInvoke(RuntimeMethodInfo rtmi, Object obj, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture, Boolean isBinderDefault, Assembly caller, Boolean verifyAccess, StackCrawlMark& stackMark)
   at System.Reflection.RuntimeMethodInfo.InternalInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, StackCrawlMark& stackMark)
   at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
   at Jurassic.PhoneApp.Yapl.YaplMethodDispatcher.TryDispatch(String name, Object[] parameters, Object& result)
   at Jurassic.PhoneApp.Yapl.YaplMethodDispatcher.YaplCall(String whichCall, Object[] parameters)
   at binder_for_Jurassic.PhoneApp.Yapl.YaplMethodDispatcher.YaplCall()
   at Jurassic.Compiler.Binder.Call(ScriptEngine engine, Object thisObject, Object[] arguments)
   at Jurassic.Library.ClrFunction.CallLateBound(Object thisObject, Object[] arguments)
   at main()
   at Jurassic.Library.UserDefinedFunction.CallLateBound(Object thisObject, Object[] argumentValues)
   at global_()
   at Jurassic.Compiler.GlobalMethodGenerator.Execute()
   at Jurassic.ScriptEngine.Execute(ScriptSource source)
   at Jurassic.ScriptEngine.Execute(String code)
   at Jurassic.PhoneApp.YaplPage.SetupEngine()
   at Jurassic.PhoneApp.YaplPage..ctor()
Sep 12, 2011 at 5:11 PM
Edited Sep 12, 2011 at 5:11 PM

OK... it's perhaps something to do with WP7 and the built-in methods which take default arguments.

e.g.: the first two lines here succeed, but the third line fails

            _engine.Execute("var test=[12,23,34];test.pop();");
            _engine.Execute("test.push(14,34,23);");
            _engine.Execute("test.slice(1,2);");

Will keep digging...

Sep 12, 2011 at 5:28 PM

And if I change the signature of slice to remove the default parameter, then the verification exception disappears.

i.e. if I change:

 

[JSFunction(Name = "slice", Flags = JSFunctionFlags.HasThisObject, Length = 2)]
        public static ArrayInstance Slice(ObjectInstance thisObj, int start, int end = int.MaxValue)

 

        

to:

[JSFunction(Name = "slice", Flags = JSFunctionFlags.HasThisObject, Length = 2)]
        public static ArrayInstance Slice(ObjectInstance thisObj, int start, int end)
        
Sep 12, 2011 at 8:32 PM

I've been looking at the IL and haven't really spotted anything...

The IL generated by a full compiler looks more like:

L_0002: ldarg.2

L_0003: ldc.i4.0

L_0004: ldelem.ref

L_0005: unbox.any int32

L_000a: ldarg.2

L_000b: ldc.i4.1

L_000c: ldelem.ref

L_000d: unbox.any int32

L_0012: call class [JurassicWP71]Jurassic.Library.ArrayInstance [JurassicWP71]Jurassic.Library.ArrayInstance::Slice(class [JurassicWP71]Jurassic.Library.ObjectInstance, int32, int32)

Which obviously has a little more unboxing than what the generator currently generates...  But tweaking the generator doesn't seem to help...

Still digging... :)