[VM-dev] Can we be a JavaScript engine?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

[VM-dev] Can we be a JavaScript engine?

Denis Kudriashov
 
Hi.

It is just a question from the space :)

I wonder, can we be a JavaScript engine? Like replacing nodeJs with Pharo/Squeak.
I imagine that JS prototypes can be easily supported by anonymous classes. What is missing? 

Best regards,
Denis
Reply | Threaded
Open this post in threaded view
|

Re: [VM-dev] Can we be a JavaScript engine?

Clément Béra
 


On Tue, Feb 20, 2018 at 3:56 PM, Denis Kudriashov <[hidden email]> wrote:
 
Hi.

It is just a question from the space :)

I wonder, can we be a JavaScript engine? Like replacing nodeJs with Pharo/Squeak.
I imagine that JS prototypes can be easily supported by anonymous classes. What is missing? 

Not really. Efficient prototypes requires deep VM changes in memory representation of objects. 
 

Best regards,
Denis




--
Clément Béra
Pharo consortium engineer
Bâtiment B 40, avenue Halley 59650 Villeneuve d'Ascq
Reply | Threaded
Open this post in threaded view
|

Re: [VM-dev] Can we be a JavaScript engine?

Denis Kudriashov
 


2018-02-20 16:04 GMT+01:00 Clément Bera <[hidden email]>:
 


On Tue, Feb 20, 2018 at 3:56 PM, Denis Kudriashov <[hidden email]> wrote:
 
Hi.

It is just a question from the space :)

I wonder, can we be a JavaScript engine? Like replacing nodeJs with Pharo/Squeak.
I imagine that JS prototypes can be easily supported by anonymous classes. What is missing? 

Not really. Efficient prototypes requires deep VM changes in memory representation of objects. 
 
Performance is another question. 
But we can only measure it if we will be able to run JS code.

 

Best regards,
Denis




--
Clément Béra
Pharo consortium engineer
Bâtiment B 40, avenue Halley 59650 Villeneuve d'Ascq


Reply | Threaded
Open this post in threaded view
|

Re: [VM-dev] Can we be a JavaScript engine?

henry
 
Personally I am looking for a distributable language, computable is Squeak and Java, as the basis for mobile code. Code should be relocatable between these environments, relying on promise-based IPC. Could JavaScript be the right answer? I wrote a JavaScript compiler in Java, since lost. Perhaps a restricted scope JavaScript would be helpful. Is there another language that would be more suitable for this promise-land? I agree, for myself performance is secondary to having mobile code between language environments.

Thank you.

Sent from ProtonMail Mobile


On Tue, Feb 20, 2018 at 10:44, Denis Kudriashov <[hidden email]> wrote:


2018-02-20 16:04 GMT+01:00 Clément Bera <[hidden email]>:
 


On Tue, Feb 20, 2018 at 3:56 PM, Denis Kudriashov <[hidden email]> wrote:
 
Hi.

It is just a question from the space :)

I wonder, can we be a JavaScript engine? Like replacing nodeJs with Pharo/Squeak.
I imagine that JS prototypes can be easily supported by anonymous classes. What is missing? 

Not really. Efficient prototypes requires deep VM changes in memory representation of objects. 
 
Performance is another question. 
But we can only measure it if we will be able to run JS code.

 

Best regards,
Denis




--
Clément Béra
Pharo consortium engineer
Bâtiment B 40, avenue Halley 59650 Villeneuve d'Ascq


Reply | Threaded
Open this post in threaded view
|

Re: [VM-dev] Can we be a JavaScript engine?

Denis Kudriashov
In reply to this post by Denis Kudriashov
 
Java can do it. I found https://ringojs.org and Oracle Nashorn

2018-02-20 16:44 GMT+01:00 Denis Kudriashov <[hidden email]>:


2018-02-20 16:04 GMT+01:00 Clément Bera <[hidden email]>:
 


On Tue, Feb 20, 2018 at 3:56 PM, Denis Kudriashov <[hidden email]> wrote:
 
Hi.

It is just a question from the space :)

I wonder, can we be a JavaScript engine? Like replacing nodeJs with Pharo/Squeak.
I imagine that JS prototypes can be easily supported by anonymous classes. What is missing? 

Not really. Efficient prototypes requires deep VM changes in memory representation of objects. 
 
Performance is another question. 
But we can only measure it if we will be able to run JS code.

 

Best regards,
Denis




--
Clément Béra
Pharo consortium engineer
Bâtiment B 40, avenue Halley 59650 Villeneuve d'Ascq



Reply | Threaded
Open this post in threaded view
|

Re: [VM-dev] Can we be a JavaScript engine?

Eliot Miranda-2
In reply to this post by Denis Kudriashov
 
Hi Denis,

On Tue, Feb 20, 2018 at 6:56 AM, Denis Kudriashov <[hidden email]> wrote:
 
Hi.

It is just a question from the space :)

I wonder, can we be a JavaScript engine? Like replacing nodeJs with Pharo/Squeak.
I imagine that JS prototypes can be easily supported by anonymous classes. What is missing? 

Well, Vassili Bykov and I did a JavaScript implementation above VisualWorks in 2005 is.  One can do a very good job.  There are three strong ideas one can use.  The first two are Vassili's, the last is Claus Gittinger's.

Vassili's ideas were to 
a) analyse constructors and map the accessors in constructors to inst var offsets.  If one does inst var access by property lookup (an object is a dictionary from field name to field) performance will be very poor.  If one can analyze a constructor and map each field to an inst var offset performance can be much better.

b) the first field of any object is the prototype slot which points to the prototype or nil.  An inst var holding nil means "unbound".  Therefore a new JavaScript object will have all its fields unbound.  To access an object's field Vassili minted special accessors, one for each offset.  They can't be written directly in Smalltalk but can be expressed using Smalltalk bytecodes.  They look like this, where instVarAt: is actually a bytecode that fetches that inst var from the receiver

    | current value |
    current := self.
    [current isNil ifTrue: [self error: 'field not found'].
     value := current instVarAt: N. "N is the offset of the inst var this accessor should return"
     value ~~ nil ifTrue: [^value].
     current := current instVarAt: 0] repeat

or in bytecode:

pushReceiver
popIntoTemp: 0 "set current to be the receiver"
L1:
pushTemp: N inVectorAt: 0.  "fetch Nth field of current"
dup
pushConstant: nil  "if Nth field is non-nil (is bound) answer it"
send: ~~
jumpFalseTo: L2
returnTop
L2:
pop  "discard nil"
pushTemp: 0 inVectorAt: 0.  "fetch prototype field of current"
dup
pushTemp: 0 "if prototype is nil, slot is not found"
pushConstant: nil
send: ==
jumpFalseTo: L3
self
send: errorFieldNotFound
pop
L3:
popIntoTemp: 0 "set current to be the current's prototype"
jumpTo: L1
returnSelf

    
We used a class per constructor, and were able to get performance about 4x of Netscape's VM at the time.

Claus' idea is to create a circular instance, an object whose class is the object itself.   The idea follows from the fact that if one has the changeClass/adoptInstance primitive one can create a prototype by creating an Array whose first three fields are laid out like a Behavior's fields, superclass/prototype, methodDictionsry, format, and whose subsequent fields are the inst vars of the object.  One then uses adoptInstance/change class primitive to change the class of the Array to itself, so that it is an instance of itself; it has its own methods in its methodDictionary, its superclass field is now the prototype.  The format field must specify a pointer object with N inst vars.  If using this scheme to implement JavaScript objects, then slot 4 (immediately after format) is probably the sot for dynamically added properties.  And of course one would implement prototype creation in a special primitive rather than using the standard adoptInstance: primitive.

Using tricks like these one can get reasonably high performance.  In fact, at Cadence we have a JavaScript implementation which is has evolved from Vassili's two ideas.  The implementation is in Newspeak running above the 64-bit Spur VM.


_,,,^..^,,,_
best, Eliot
Reply | Threaded
Open this post in threaded view
|

Re: [VM-dev] Can we be a JavaScript engine?

Denis Kudriashov
 
Thank's Eliot.
It is very interesting.

2018-02-20 21:51 GMT+01:00 Eliot Miranda <[hidden email]>:
 
Hi Denis,

On Tue, Feb 20, 2018 at 6:56 AM, Denis Kudriashov <[hidden email]> wrote:
 
Hi.

It is just a question from the space :)

I wonder, can we be a JavaScript engine? Like replacing nodeJs with Pharo/Squeak.
I imagine that JS prototypes can be easily supported by anonymous classes. What is missing? 

Well, Vassili Bykov and I did a JavaScript implementation above VisualWorks in 2005 is.  One can do a very good job.  There are three strong ideas one can use.  The first two are Vassili's, the last is Claus Gittinger's.

Vassili's ideas were to 
a) analyse constructors and map the accessors in constructors to inst var offsets.  If one does inst var access by property lookup (an object is a dictionary from field name to field) performance will be very poor.  If one can analyze a constructor and map each field to an inst var offset performance can be much better.

b) the first field of any object is the prototype slot which points to the prototype or nil.  An inst var holding nil means "unbound".  Therefore a new JavaScript object will have all its fields unbound.  To access an object's field Vassili minted special accessors, one for each offset.  They can't be written directly in Smalltalk but can be expressed using Smalltalk bytecodes.  They look like this, where instVarAt: is actually a bytecode that fetches that inst var from the receiver

    | current value |
    current := self.
    [current isNil ifTrue: [self error: 'field not found'].
     value := current instVarAt: N. "N is the offset of the inst var this accessor should return"
     value ~~ nil ifTrue: [^value].
     current := current instVarAt: 0] repeat

or in bytecode:

pushReceiver
popIntoTemp: 0 "set current to be the receiver"
L1:
pushTemp: N inVectorAt: 0.  "fetch Nth field of current"
dup
pushConstant: nil  "if Nth field is non-nil (is bound) answer it"
send: ~~
jumpFalseTo: L2
returnTop
L2:
pop  "discard nil"
pushTemp: 0 inVectorAt: 0.  "fetch prototype field of current"
dup
pushTemp: 0 "if prototype is nil, slot is not found"
pushConstant: nil
send: ==
jumpFalseTo: L3
self
send: errorFieldNotFound
pop
L3:
popIntoTemp: 0 "set current to be the current's prototype"
jumpTo: L1
returnSelf

    
We used a class per constructor, and were able to get performance about 4x of Netscape's VM at the time.

Claus' idea is to create a circular instance, an object whose class is the object itself.   The idea follows from the fact that if one has the changeClass/adoptInstance primitive one can create a prototype by creating an Array whose first three fields are laid out like a Behavior's fields, superclass/prototype, methodDictionsry, format, and whose subsequent fields are the inst vars of the object.  One then uses adoptInstance/change class primitive to change the class of the Array to itself, so that it is an instance of itself; it has its own methods in its methodDictionary, its superclass field is now the prototype.  The format field must specify a pointer object with N inst vars.  If using this scheme to implement JavaScript objects, then slot 4 (immediately after format) is probably the sot for dynamically added properties.  And of course one would implement prototype creation in a special primitive rather than using the standard adoptInstance: primitive.

Using tricks like these one can get reasonably high performance.  In fact, at Cadence we have a JavaScript implementation which is has evolved from Vassili's two ideas.  The implementation is in Newspeak running above the 64-bit Spur VM.


_,,,^..^,,,_
best, Eliot