# Thursday, 01 August 2002
« No Title | Main | No Title »
No Title

Zoltan commented on the div issue:

I believe the reason the CLR throws an exception in this case is that the div CIL opcode is compiled down to the idiv x86 opcode, which raises a hardware exception in case of overflow. A div opcode which does not throw an exception would be much slower, since it would have to be implemented by a series of x86 opcodes.

You're correct. I mistakenly believed that the x86 idiv instruction didn't throw an exception on overflow, but it does (it doesn't in real-mode, which is what I remembered). Still, it would be trivial in the x86 overflow exception handler to detect that it is handling this case and then resume execution after the idiv instruction with the correct results in the registers. This wouldn't make any performance difference for the common case, only the exceptional case would be a little slower.

Stuart commented:

Horrible hacky proposed solution: implement idiv using the broken div, but add an exception handler to every java method that uses idiv that tests for the pathological case and somehow resumes in the right place.

Two problems with this approach: 1) OverflowException can also be caused by trying to allocate a new array with a negative size, so I would somehow have to detect this. 2) Resuming after the exception is very hard (you cannot jump into a try block in .NET, so I'd have to generate lots of code, which would also make to common case slower).

Or just wrap map java (x/y) to try{x/y} catch(OverflowException e) {x}. How much execution overhead is there for a try-catch in the non-exception case?

This is an interesting suggestion. *writing some C# microbenchmarks* Here is the code I cooked up:

 public static void Main(string[] args)
 {
  int d = args.Length + 1;
  int n = (args.Length - 1) * -1;
  int start = Environment.TickCount;
  for(int i = 0; i < 10000000; i++)
  {
   try
   {
    n = n / d;
   }
   catch(OverflowException)
   {
    n = int.MinValue;
   }
  }
  int end = Environment.TickCount;
  Console.WriteLine(end - start);
  start = Environment.TickCount;
  for(int i = 0; i < 10000000; i++)
  {
   if(d == -1)
   {
    n = n * d;
   }
   else
   {
    n = n / d;
   }
  }
  end = Environment.TickCount;
  Console.WriteLine(end - start);
 }
On my system there is almost no difference between these two methods, so I think I'll go for the explicit test, because of the additional complexity of moving the stack into the try block.
Thursday, 01 August 2002 10:43:40 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
Name
E-mail
Home page

I apologize for the lameness of this, but the comment spam was driving me nuts. In order to be able to post a comment, you need to answer a simple question. Hopefully this question is easy enough not to annoy serious commenters, but hard enough to keep the spammers away.

Anti-Spam Question: What method on java.lang.System returns an object's original hashcode (i.e. the one that would be returned by java.lang.Object.hashCode() if it wasn't overridden)? (case is significant)

Answer:  
Comment (HTML not allowed)  

Live Comment Preview