Improving Nasal: Difference between revisions

Jump to navigation Jump to search
m
Line 89: Line 89:
** '''VM:''' Indicate type of variable if wrong type.
** '''VM:''' Indicate type of variable if wrong type.
** '''Both:''' Could we give line ''and'' column?
** '''Both:''' Could we give line ''and'' column?
** Most of these diagnostics could be delegated to Nasal space by using some of our C-space hooks that expose the parser/codegen and VM
* Working with bytecode:
* Working with bytecode:
** Expose to Nasal: {{Done}}
** Expose to Nasal: {{Done}}
** Decompile to text: partial (untested)
** Decompile to text: partial (untested)
** Optimize: not started
** Optimize: not started (it makes only sense to look at optimizations after we're able to instrument/profile a running FG session to come up with hot spots that are executed either frequently, or that are responsible for significant runtime overhead - i.e. due to GC pressure or other issues)
** Working with it: provide Bytecode class: not started
** Working with it: provide Bytecode class: not started (the exposeOpcode() API already exists, most other machinery could be built in scripting space on top of it?)
* Inspect Context: not started, should be easy.
* Inspect Context: not started, should be easy.
* Expose Tokens to Nasal: implemented by Hooray as argument to compile(), should be extended to cover output from lex.c and after blocking in addition to the current after-prec-ing (and before freeing!) support.
* Expose Tokens to Nasal: implemented by Hooray as argument to compile(), should be extended to cover output from lex.c and after blocking in addition to the current after-prec-ing (and before freeing!) support.
** compile() being used by call(), it should be straightforward to also map a call() hash.callback to do the same thing here - so that there's no disparity here.
* Real function name support via assignment:
* Real function name support via assignment:
** Option 1: look at the parse tree and check if the right side of the assignment is a function. If so, go ahead and parse the function with the left side as the "name" of the function instead of falling through to more recursions of genExpr().
** Option 1: look at the parse tree and check if the right side of the assignment is a function. If so, go ahead and parse the function with the left side as the "name" of the function instead of falling through to more recursions of genExpr().
Line 101: Line 103:
*** The right-hand side of an assignment is done before the left-hand side, thus one would have to look ahead to see the assignment, which is clearly illegal for the VM to do.
*** The right-hand side of an assignment is done before the left-hand side, thus one would have to look ahead to see the assignment, which is clearly illegal for the VM to do.
*** Or one could look behind to see a naCode constant being pushed, and give some indication to its naFunc that it now has a name. This I still somewhat illegal, but not dangerous and thus could be done.
*** Or one could look behind to see a naCode constant being pushed, and give some indication to its naFunc that it now has a name. This I still somewhat illegal, but not dangerous and thus could be done.
*** how is this supposed to deal with multiple symbols aliasing the same function ?
** Option 3: abandon <tt>var foo = func(){}</tt> for ECMAscript-like function declaration syntax <tt>function foo() {}</tt>. This would not affect the use of anonymous func expressions but would instead be applicable in cases where we want to say "this function is static (i.e. permanent) and should have a name" (as opposed the the case of temporary storage variables for functions). Regardless of the method used, a name member will have to be added to naFunc's and the VM and error handling procedures will have to be changed according.
** Option 3: abandon <tt>var foo = func(){}</tt> for ECMAscript-like function declaration syntax <tt>function foo() {}</tt>. This would not affect the use of anonymous func expressions but would instead be applicable in cases where we want to say "this function is static (i.e. permanent) and should have a name" (as opposed the the case of temporary storage variables for functions). Regardless of the method used, a name member will have to be added to naFunc's and the VM and error handling procedures will have to be changed according.
* Timing parts of VM: use the callbacks and systime/unit.time to time things. Need hooks into the GC as well. Statistics worth tracking:
* Timing parts of VM: use the callbacks and systime/unit.time to time things. Need hooks into the GC as well. Statistics worth tracking (also look at similar tools like [http://google-perftools.googlecode.com/svn/trunk/doc/cpuprofile.html google perftools]):
** Per function:
** Per function (also handles timers/listeners and other typical FG callbacks):
*** ncalls per frame/cumulative
*** ncalls per frame/cumulative
*** time per call on avg/cumulative
*** time per call on avg/cumulative
Line 110: Line 113:
*** number of naNew() calls
*** number of naNew() calls
*** number & list of names of once-use variables; n that are numbers (i.e. non-GC-managed).
*** number & list of names of once-use variables; n that are numbers (i.e. non-GC-managed).
*** maybe some holistic "GC pressure" percentage over time (5,30,60,300 seconds ?)
*** GC pressure can be computed by looking not just at new allocations, but also at realloc() events and the mark/reap phases
*** for GC stats, we can also easily access 1) size of all allocated naType pools and 2) percentage that's in use  and 3) newBlock() allocations
** Per context/global:
** Per context/global:
*** time spent
*** time spent
*** number of GC invocations:
*** number of GC invocations:
*** naContext leaks (see Andy's comments below)
**** per frame
**** per frame
**** min/max/avg
**** min/max/avg
** Data per function call (not displayed, dumped to a file):
** Data per function call (not displayed, dumped to a file):
*** caller line/name
*** caller line/name
** threading (eventually)
*** locking overhead




Navigation menu