[Mono-list] asp.net or php

Paolo Molaro lupus@ximian.com
Mon, 26 Jan 2004 14:10:14 +0100


On 01/22/04 Alan Knowles wrote:
> I left off at the point of attempting a PHP->C# mapping, as compiling 
> down to opcodes was a bit complex given the extreme complexity of 
> auto-typecasting (eg. array(1,2,3) == true evals to true!, where as 
> array(1,2,3) == 1 evals to false...) in PHP.

Most of those issues become quite easy to generate code for once
you delegate it to, for example, a virtual function call. I assume PHP
has a sort of boolean type different from an integer type, given your
description of the semantics of that compare. In this case you'd
have the following virtual functions:

	bool CompareEQ (PHPBool val);
	bool CompareEQ (PHPInt val);
	bool CompareEQ (PHPVar val);

Each of those functions will do the right thing that is required by the
semantics, like, for an array, returning always false when comparing
with an integer, returning true when compared with a boolean true if the
array is non-empty or whatever the semantics is in that case for PHP.
In the compiler you just have to load the arguments to the method and
emit the call:
	ldloc 1
	ldloc 2
	callvirt bool CompareEQ (...)
That will simplify code generation a lot, since you won't have to emit
all the instructions that implement the semantics each time a comparison
is made (and you can implement them in a nice language like C#, instead
of ilasm emitted with Reflection.Emit).
Note: if the compiler knows the type of the argument to compare (like
it's the case with the example above) it can emit the CompareEQ (PHPBool val)
call, instead of the more general CompareEQ (PHPVar val) (whose
implementation will require checking the type of the argument).
The number of virtual functions specialized for each type depends on the
semantics for the language and on the speed tradeoffs: more specialized
methods will be faster, but will require a little more time to implement
(and they will require the compiler to be a little bit smarter to take
advantage of them).

> One concern was that the zend engine uses a simple struct to represent 
> all variables, which appears to be very effecient way to deal with types 
> in a non-fixed type language like PHP. It is one of the potential 
> advantages of parrot over .Net, as a better target for PHP. (eg. adding 
> opcodes or native types to the opcode runtime may be more feasible..)

A few weeks ago there was a thread on the parrot list on that very
topic, spurred by a few questions from Sterling. He showed the code
produced by his prototype compiler and the parrot folks helped pinpoint
the issues with the code and proposed the changes to make the code
run better on parrot and still respect the PHP semantics. The code was a
loop where, at avery other iteration, the type of a variable changed
from int to float and viceversa. Indeed the parrot implementation
was at least three times as fast as the PHP one. I cooked up the code to
implement the same loop with the same semantics using C# and running in
mono (using the virtual call implementation trick detailed above) and mono 
was significantly faster than parrot (30-40%, IIRC).
So, the fact that a variable can change type on the fly is not an hindrance
for a CLR-based implementation: the tecnique to implement it is easy to
implement and is very efficient (at least speed-wise). Memory-wise I
haven't measured how much memory a parrot PMC takes and I don't know
how small the structure Zend uses is (my guess is it's not smaller than
8 bytes on 32 bit systems, probably at least 12?): in the sample code I
wrote the object was 16 bytes (8 of which are the the MonoObject
overhead). So, it may be that the memory used by mono is a little more,
but in most cases this is not a high price to pay for the faster execution
and the interoperability that mono and the CLR provide.

lupus

-- 
-----------------------------------------------------------------
lupus@debian.org                                     debian/rules
lupus@ximian.com                             Monkeys do it better