pvginkel / jint2 Goto Github PK
View Code? Open in Web Editor NEWJint improved
Jint improved
It may be possible to not have real function objects in certain circumstances:
In this case, don't create a function object; change the signature of the function to make it have real arguments and change calls from JsObject.Execute to a real call.
Currently, when a new schema is created, the existing one is copied to the new one. This is a relatively expensive operation because the whole hashset that is backing the schema needs to be copied.
An alternative would be to change JsSchema into a linked list. A JsSchema then becomes the tail with only the addition or removal (the transition really) is added in the new JsSchema.
The advantage of this scheme is that creating a new schema becomes very cheap. The disadvantage is that a cache miss (the DictionaryCacheSlot) becomes quite expensive. Do performance tests on the V8/Octane benchmarks to find out how many cache misses we normally have, what the impact of polymorphic/megamorphic call sites is.
Change the implementation to be based on the DLR.
Currently, all values are still JsInstance values. This should be changed to native .NET values where possible.
There are two levels to this. Firstly, all variables (locals and lifted) should be typed object and start out as their native values. This means that e.g. a double becomes a boxed double. When an operation is performed on the variable that requires it to become a JsInstance (e.g. a property is set), the boxed double is silently converted to a JsInstance. This means that all operations that could have this effect on a variable should get ref references to the storage location.
The second level is more interesting and is where the real performance gains are. We could do a usage analysis on variables. When we can prove that no operations can be performed on the variable that would require it to become a JsInstance, and the variable keeps it original type all the way through its lifetime, the type of the variable could be its real native type. We may have to add some special support for its initial value, because all variables start out as undefined. This could be solved by making the variables Nullable<> and returning JsUndefined.Instance when the variable hasn't been assigned yet. This could also be optimized away when the variable is definitely assigned.
One thing that should be taken into account is that not all member operations require it to become a JsInstance. E.g. when we execute a method on a variable, this should still work on native variables. Normally, we would get the prototype of the JsInstance to find out how to resolve the method. When the variable is (still) a native value, we could hard code the prototype lookup and resolve members that way.
Where this gets more complicated is when variables are assigned to. If a variable is assigned a new time, and it's not lifted, we may create a new variable for this. The idea here is that when we can prove that the original value of the variable isn't read after the point it's assigned a value of a new type, we can just create a new variable for it (e.g. i`1) and give that a new type.
One thing to also take into account is that it may be a good idea to also allow int as a type for local variables, specifically for these circumstances. One of the major gains you'll see here is for optimizing a "for (var i = 0; i < arr.length; i++)", and that specifically is an int.
ExtractGenericArguments has a bug which prevents ref arguments from working. A new array is returned, and the original array isn't updated.
Currently we have two trees representing the source code: the syntax tree and the bound tree. This was done because it made migration to the IL backend easier, but isn't really necessary.
Remove the syntax tree and instead directly generate the bound tree from the grammar. This depends on #35.
Implement a constant folding phase.
Proxies were moved to Expression trees a while ago, but since we've implemented an IL backend, the proxies should be moved too. After this change, the main assembly can be moved back to .NET 2.0.
"Method can't be used as a constructor" is not implemented.
Because the grammar has "output=AST", it builds an AST. This can disabled by removing that option and some other changes.
There still is a lot of manual IL generation that can be replaced with Expression trees.
Literals are still built from the syntax tree; not the bound tree. Move to building from the bound tree instead.
Currently null and undefined are treated as get members on global. This must be changed so that they use BoundMagicVariable.
Variable aliasing must be implemented to solve the following:
var i = 0;
i = '';
The type marker identifies the above variable as object because it's assigned values of different types. However, this is not necessary because the first assignment of i is never observed. Aliasing must be implemented to alias the second i to a new variable that can have its own native type.
IronJS has a huge number of unit tests. Add these to the project.
Jurassic and the original Jint project (and maybe others) must be added as benchmark engines.
Only a few of the Mozilla tests are executed. There are a lot of them and all of them should be executed.
Introduce integer as an alternative number type. This would allow for better optimizations if the type system can prove that a variable is only used as an integer.
FastHashSet (the types that are generated from it) must be reviewed. It is currently correct and optimized for lookups, but inserts and removals can use a tweak.
All tests from test262 must run. See the Jint-Test262 project for the unit tests for this test suite.
Currently we introduce a lot of blocks and temporaries that later on are taken out again. See whether this can be optimized and whether we can prevent certain blocks/temporaries from being introduced in the first place.
Check all thrown exceptions and clean them up.
Implement a dead code elimination phase. This shouldn't be of much use. However, it currently creates issues with type assignment, e.g.:
var i = 0;
return i;
i = "";
The above sequence makes i Unknown. However, this is not required because the string will never be assigned.
The arguments object currently is always created. When it isn't referenced, two things must happen:
Review the emitted sequence points. Some may be missing or not ideal, and currently a sequence point is emitted for whole functions, which makes debugging irritating.
Add the benchmarks from http://octane-benchmark.googlecode.com/svn/latest/index.html.
Currently, all variables are hoisted to a compiled scope. Variables that don't need to be lifted, don't have to be in a compiled scope. When making this change, also get rid of scopes without variables.
Strict mode is not correctly implemented. Currently the engine takes options to specify whether it should work in EcmaScript5 mode and whether it must work in strict mode. EcmaScript5 must be enabled by default and strict mode must be applied when the program or function specifies the strict flag:
function f() {
'use strict';
}
A side effect of the current implementation is that parsing scripts at the moment does not just depend on the source code of the script which prohibits caching of the compilation result.
Most of the API implementations are still inherited from the original Jint project, and a lot of performance can be gained there. E.g. the RegEx implementation is extremely slow (see e.g. the regexp-dns.js SunSpider test).
There are a number of tests that don't stop; probably because they generate code that goes into an endless loop. These are marked with TODO comments and must be solved.
There are a lot of hard strings in the code and usage of strings and consts for certain names in inconsistent. All const strings should be declared in JsNames and comparison based on strings there should be limited.
The unit tests can be restructured. One of the things that can be changed is that we can make use of test cases. A lot of the tests simply redirect to a specific JavaScript file to execute. This can be replaced by a TestCase attribute that specifies the script to execute.
The generic Marshal methods must be refactored; the generics must be removed and specific implementations must be created instead.
When a compilation is done on the same engine instance for the same source code, a cached compilation must be returned.
Currently, literal syntax trees are also cached. However, this probably isn't of much use and only introduces memory leaks. The thinking here is that when the tree is a literal, it is most likely an eval of a JSON expression, which most likely will never be re-used again. Caching of literal syntax trees should be disabled.
After completing the initial rewrite, create benchmarks against Jint, IronJS, Jurassic and IE8.
Implement delayed emit. There are two major changes that fall under this:
The JQuery scripts don't parse. jquery-1.2.6 on line 699 has an argument name which isn't identified as an argument. The problem is that certain constructs (catch, variable declaration and in this case, for in) declare a variable. However, this is too early and the arguments haven't yet been put into the declared variables collection. Solution is probably to move inserting the arguments into the declared variables collection earlier.
Also check whether a for in actually implies a variable declaration. Currently, besides variable declaration, catch and for in imply a variable declaration. Check whether this is correct.
Add the tests from http://test262.ecmascript.org/ for ECMAScript5 compatibility.
Previously, there was a test in ToPropertyDescriptor that only defined a setter, and PropertyAccessor fails when no setter is provided. Check what's going on here.
It looks like the entire JsScope system can be removed and replaced with compiled scopes. The only exception may be the global scope, because that's used to pass parameters from JintEngine to the application. This however can also be replaced by a different mechanism which is only used to communicate the values from JintEngine to the program and back.
Note that we don't create native variables for parameters that we pass from JintEngine. The reason for this is in the current implementation, we can cache the compilation based only on the compiled text. This means that we will always need an interpreted mechanism for JintEngine parameters.
With this change, the scope stack must also be removed (so also EnterScope, ExitScope and GetScope). This will be replaced by hard linking of the scopes. A scope will get a parent scope field which is used to link scopes upwards. At the beginning of the function, this list will be walked to create local variables that reference all scopes that are used. The last step is to give a hard reference to the current scope to the JsFunction. That way we can completely get rid of the stack and only work with direct references, all strongly typed.
The out parameters construct currently used for out native methods isn't idea. Instead add a ref parameter modifier to the grammar and use that instead.
The V8 earley-boyer.js script fails with an error message.
Variable type speculation must be implemented. We have a type marker phase that determines the hard type of a variable. This is the type the variable must have for the IL to compile. However, through type speculation, we can guess the real type and optimize for that.
E.g., in the following case, the speculator would identify i as being a dictionary object:
var i = f();
i['a'] = 7;
var j = i.a;
The idea here is that operations that you normally perform on a dictionary object are performed on i. In the following example, i will be identified as an array object:
var i = f();
i[0] = 7;
var j = i[0];
When a variable is identified as being e.g. a dictionary object, the variable is replaced with a speculated variable type, with a signature like:
struct DictionaryObjectVariable
{
public JsObject Value { get; set; }
public DictionaryPropertyStore PropertyStore { get; set; }
}
This struct can now get methods that optimize on the value being a dictionary object. Instead of having everything go through JsObject, of the type matches, operations are performed directly on the dictionary property store.
EmitCall should only emit a callvirt on virtual, abstract and interface methods. In all other cases, a normal call is OK.
Currently the only way Jint can interact with .NET types is through the runtime Type system. This should be extended to also support TypeDescriptor.
Check whether the callee parameter is used correctly.
New may only return an object. Check whether this is guaranteed from JsObject.Construct.
A special string type must be introduced that is optimized for concatenation. The idea here is that the following should automatically be optimized:
var result = '';
for (var i = 0; i < 1000; i++)
{
result += i;
}
A way to implement this (the way IronJS does it) is to have an alternative string type. When a concatenation is detected, the new string that is produced isn't a string anymore but instead becomes an object that is prepared for concatenation. The primary impact here is that the current runtime system expects a value to be represented by a single native type. This change would introduce a second native type for string which will complicate things.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.