Changes between Initial Version and Version 1 of SquirrelFish


Ignore:
Timestamp:
Apr 20, 2008 3:55:52 PM (15 years ago)
Author:
mjs@apple.com
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • SquirrelFish

    v1 v1  
     1
     2== squirrelfish ==
     3
     4'''Major bits left over:'''
     5  * Getters and Setters
     6  * toString/valueOf
     7     * It occurs to me that these could both (s|g)etters and toString could be "trivially" handled through the standard js -> native -> js call model -- at least in the short-medium term
     8  * eval
     9
     10'''List of tasks in no order -- pick one, tell everyone what you're doing:
     11'''
     12
     13'''Geoff is working on:
     14'''
     15
     16Re-entry into Machine::privateExecute:
     17  * More indirection in the register file
     18  * Don't overwrite nested register frames when re-entering global execution
     19  * Provide API for re-entering non-global execution (i.e., function callbacks)
     20
     21Arguments object
     22
     23'''Cameron is working on:
     24'''
     25
     26Better code generation. We have been pondering whether to have a separate peephole optimization pass or to incorporate peephole optimization into code generation. Either way, we should look at some code generation algorithms based on tile matching. We also want to choose an approach that will be compatible with planned extensions, e.g. superinstructions.
     27
     28Constant pool GC
     29
     30'''Oliver is working on:
     31'''
     32
     33Making VM throw exceptions for invalid behaviour; Finally blocks.
     34
     35'''Sam is working on (when he sees fit to do so):
     36'''
     37
     38'''Maciej is working on:
     39'''
     40
     41ScopeChain hackery
     42
     43'''You could take something from Geoff, or make something up yourself, or do one of these:'''
     44
     45Leftover opcodes:
     46
     47 * ArgumentsNode
     48 * AssignErrorNode
     49 * BreakpointCheckStatement
     50 * ConstDeclNode
     51 * ConstStatementNode
     52 * ElementNode
     53 * EvalFunctionCallNode
     54 * ParameterNode
     55 * PostDecConstNode
     56 * PostfixErrorNode
     57 * PreDecConstNode
     58 * PrefixErrorNode
     59 * PropertyNode
     60 * ReadModifyConstNode
     61 * ThrowNode
     62 * TryNode
     63
     64Where SunSpider tests currently fail codegen:
     65
     66 * 3d-cube: ungettableGetter
     67 * 3d-morph: ungettableGetter
     68 * 3d-raytrace: crash on failing toObject conversion for base of call (bad Args to constructor)
     69 * access-binary-trees: crash on failing toObject conversion for base of call (bad Args to constructor)
     70 * access-fannkuch: crash on failing toObject conversion for base of call (bad Args to constructor)
     71 * access-nbody: new expr (NBodySystem)
     72 * access-nsieve: ungettableGetter
     73 * bitops-3bit-bits-in-byte: SUCCESS
     74 * bitops-bits-in-byte: SUCCESS
     75 * bitops-bitwise-and: SUCCESS
     76 * bitops-nsieve-bits: ungettableGetter
     77 * controlflow-recursive: ungettableGetter
     78 * crypto-aes: crash on failing toObject conversion for base of call (bad Args to constructor)
     79 * crypto-md5: ungettableGetter
     80 * crypto-sha1: ungettableGetter
     81 * date-format-tofte: local eval - eval(ia[ij] + "()")
     82 * date-format-xparb: bracket call - this[func]()
     83 * math-cordic: ungettableGetter
     84 * math-partial-sums: crash on failing toObject conversion for base of call (bad Args to constructor)
     85 * math-spectral-norm: ungettableGetter
     86 * regexp-dna: regexp literal
     87 * string-base64: crash on failing toObject conversion for base of call (bad Args to constructor)
     88 * string-fasta: crash on failing toObject conversion for base of call (bad Args to constructor)
     89 * string-tagcloud: trying to get from a base register containing 0x0 (bad codegen?)
     90 * string-unpack-code: crash on failing toObject conversion for base of call (bad Args to constructor)
     91 * string-validate-input: regexp literal
     92
     93Harness failures:
     94
     95 * sunspider-analyze-results: KJS::resolve SHOULD NEVER BE REACHED
     96 * sunspider-compare-results: SUCCESS (but not running yet)
     97 * sunspider-standalone-compare: KJS::resolve SHOULD NEVER BE REACHED
     98 * sunspider-standalone-driver: new expr (invoking Array constructor)
     99
     100Optimize dynamic scopes that aren't closures not to save the environment on return
     101
     102Statically detect presence of "with" and/or "catch" in the parser.
     103
     104Evaluation of a script is supposed to produce a value. This requires storing the value of the last value-producing statement to execute. We need to detect the last top-level value-producing statement in a program, and save its value. Basically, that just means passing an explicit "dst" register to its emitCode function.
     105
     106Make const work -- const info has to go in the symbol table, so writes to const vars can turn to no-ops at compile time.
     107
     108Recover lost optimizations:
     109
     110{{{
     111optimized multiscope access
     112optimized access to global built-ins (http://trac.webkit.org/projects/webkit/changeset/31226)
     113static type inference of things like "numeric less than" and "string add"
     114
     115// WARNING: If code generation wants to optimize resolves to parent scopes,
     116// it needs to be aware that, for functions that require activations,
     117// the scope chain is off by one, since the activation hasn't been pushed yet.
     118}}}
     119
     120return inside with needs to pop scopes
     121
     122Is it safe for Lists to store a direct pointer to the register file? What if the register file reallocates?
     123
     124Verify that current function gets marked by virtue of being in the register file
     125
     126Change conservative mark of register file to exact mark -- use zero fill plus type tagging to know whether to mark a register
     127
     128Must mark all scope chains in all active scopes -- can do this by walking up the scopeChain pointers in the register file
     129
     130automatic conversion of "this" to global object doesn't work.
     131
     132phase out implementsCall in favor of all clients using an inline function that calls getCallData.
     133
     134Phase out implementsConstruct in favor of all clients using an inline function that calls getContructData.
     135
     136For memory's sake, functions should probably shrink the register file when they return, but doing so causes a minor performance regression.
     137
     138Turn built-in object construct functions non-virtual, since their callers inside the engine know their types.
     139
     140Pointers to registers and labels become invalid if the register or label vector resizes.
     141
     142Mark constant pools for global and eval code
     143
     144Avoid copying the register file when adding globals by keeping spare capacity at the beginning of the register file, just like at the end.
     145
     146GC mark for possibly uninitialized register file
     147
     148Add relevant files to AllInOneFile.cpp.
     149
     150remove irrelevent files
     151
     152replace resolve_base_and_func:
     153    - statically detect functions that use "this", and emit an "op_fix_this" instruction for them that does the isActivationObject check. normal function calls don't need to do it.
     154    - for built-in functions, have a "thisObject" accessor on List, which lazily fixes up "this", or just fix up "this" in the native function invocation code, since most native functions use "this".
     155    - remove resolve_base_and_func, and use resolve_base_and_value in its place
     156
     157If a nested program overwrites the global slot holding a currently executing function, the function won't be marked during GC
     158
     159What things should go in dedicated local variables? CodeBlock::jsValues? CodeBlock::identifiers?
     160
     161VarStatementNode should just be nixed in favor of AssignmentNode.
     162
     163Remove ::execute, ::evaluate, ::optimizeVariableAccess
     164
     165
     166Future optimizations:
     167
     168Find a way to put pre-capacity at the beginning of the register file, so we can add new global symbols without having to move or copy anything.
     169
     170Use RefPtr to indicate use of register -- moves to un-refed registers should be stripped or consolidated to other instructions.
     171    - i++ => ++i
     172    - less, jtrue => jless
     173
     174optimize out redundant initializations of vars -- often, the var initialization will be dead code. any read of variable before init can statically become "load undefined".
     175
     176
     177    a single run of SunSpider performs 1,191,803 var initializations
     178
     179    -1 means "never happend"
     180   
     181    var buckets: [846461] [40445] [350197] [9412] [7531] [50] [9] [178] [35000] [3] [1022] [3] [4499] [-1] [1353] [-1] [-1] [1851] [-1] [0] [-1] [0] [-1] [0] [-1] [0] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1]
     182
     183    fun buckets: [1297008] [7] [3] [2] [1] [0] [-1] [0] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [0] [-1] [1] [-1] [-1] [0] [-1] [0] [-1] [-1] [-1] [-1] [-1] [999] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] [-1] ]
     184
     185for resolve-evaluate-put, we can have a { DontCare, Clean, Dirty } switch -- get slot and if DontCare, set clean, evaluate, set slot if clean
     186
     187instead of branching to see if you've emitted code, just start out with a stub that does that emitting when invoked.
     188
     189single, shared constant pool
     190
     191At least for loops with fewer iterations it would probably be a win to duplicate the loop condition at the start and end of the loop
     192
     193Perhaps we should have a distinguished "condition code" register for expressions in a boolean context. For relational and logical operators we can output directly to the condition code register, for other opcodes you get an extra instruction. Jump instructions can read implicitly from the condition code. That avoids the less writing to r0, it just puts a bool in the condition code register.
     194
     195Can't you just make all opcodes have variants that use constant table operands directly?
     196
     197A named function expression can just enter its name into the symbol table instead of adding an object to the scope chain.
     198
     199Shrink instructions -- usually, don't need a whole word to store int values. Perhaps use tagging of opcodes to encode the first operand. Special work-around instructions when whole words are needed
     200
     201GCC is crazy:
     202
     203{{{
     204For the program
     205
     206for (var i = 0; i < 100000000; ++i)
     207    ;
     208
     209at r31276 of the squirrelfish branch, adding the line
     210
     211Machine.cpp:354         scopeChain = new (&returnInfo[6]) ScopeChain(function->scope()); // scope chain for this activation
     212
     213causes a ~25% slowdown
     214
     215We should write a reduction of this issue for the compiler team, and see what they have to say
     216}}}
     217
     218
     219
     220{{{
     221Revision 31432 was a 1.4% performance regression because it moved the register vector from a
     222local to a parameter. Making the register vector a data member has the same effect. WTF?
     223}}}
     224
     225{{{
     226Exception handling throw logic has to pass vPC to a function, and assign the result to vPC, eg.
     227  if (!(vPC = throwException(codeBlock, k, scopeChain, registers, r, vPC)))
     228But this causes a 25% regression on the above empty-for-loop test, despite never being hit. 
     229To avoid this we need to do:
     230void* throwTarget;
     231...
     232void Machine::privateExecute(..)
     233{
     234    ...
     235    // in address table initialiser
     236    throwTarget = &&gcc_dependency_hack;
     237    ...
     238    BEGIN_OPCODE(op_throw) {
     239        ...
     240        if (!(exceptionTarget = throwException(codeBlock, k, scopeChain, registers, r, vPC))) { ... }
     241        ...
     242        goto *throwTarget;
     243    }
     244    gcc_dependency_hack:
     245    {
     246        vPC = exceptionTarget;
     247        NEXT_OPCODE;
     248    }
     249}
     250
     251Without this _indirect_ goto we get a 25% regression, if we use a direct goto we still get an 18% regression.
     252
     253}}}
     254