~davewalker/etherpad/ubuntu-unlimited-max-users-and-revisions

« back to all changes in this revision

Viewing changes to infrastructure/rhino1_7R1/src/org/mozilla/javascript/optimizer/Optimizer.java

  • Committer: James Page
  • Date: 2011-04-13 08:00:43 UTC
  • Revision ID: james.page@canonical.com-20110413080043-eee2nq7y1v7cv2mp
* Refactoring to use native Ubuntu Java libraries. 
* debian/control:
  - use openjdk instead of sun's java
  - update maintainer
* debian/etherpad.init.orig, debian/etherpad.upstart:
  - move the init script out of the way
  - create a basic upstart script
  - note that the open office document conversion daemon was dropped
    from the upstart configuration; if this behavior is desired, please
    create a separate upstart job for it
* debian/rules:
  - just use basic dh_installinit, as it will pick up the new upstart job
* New release
* Changed maintainer to Packaging
* Fixed installation scripts
* Initial Release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ***** BEGIN LICENSE BLOCK *****
 
2
 * Version: MPL 1.1/GPL 2.0
 
3
 *
 
4
 * The contents of this file are subject to the Mozilla Public License Version
 
5
 * 1.1 (the "License"); you may not use this file except in compliance with
 
6
 * the License. You may obtain a copy of the License at
 
7
 * http://www.mozilla.org/MPL/
 
8
 *
 
9
 * Software distributed under the License is distributed on an "AS IS" basis,
 
10
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 
11
 * for the specific language governing rights and limitations under the
 
12
 * License.
 
13
 *
 
14
 * The Original Code is Rhino code, released
 
15
 * May 6, 1999.
 
16
 *
 
17
 * The Initial Developer of the Original Code is
 
18
 * Netscape Communications Corporation.
 
19
 * Portions created by the Initial Developer are Copyright (C) 1997-1999
 
20
 * the Initial Developer. All Rights Reserved.
 
21
 *
 
22
 * Contributor(s):
 
23
 *   Norris Boyd
 
24
 *   Roger Lawrence
 
25
 *
 
26
 * Alternatively, the contents of this file may be used under the terms of
 
27
 * the GNU General Public License Version 2 or later (the "GPL"), in which
 
28
 * case the provisions of the GPL are applicable instead of those above. If
 
29
 * you wish to allow use of your version of this file only under the terms of
 
30
 * the GPL and not to allow others to use your version of this file under the
 
31
 * MPL, indicate your decision by deleting the provisions above and replacing
 
32
 * them with the notice and other provisions required by the GPL. If you do
 
33
 * not delete the provisions above, a recipient may use your version of this
 
34
 * file under either the MPL or the GPL.
 
35
 *
 
36
 * ***** END LICENSE BLOCK ***** */
 
37
 
 
38
 
 
39
 
 
40
package org.mozilla.javascript.optimizer;
 
41
 
 
42
import org.mozilla.javascript.*;
 
43
 
 
44
class Optimizer
 
45
{
 
46
 
 
47
    static final int NoType = 0;
 
48
    static final int NumberType = 1;
 
49
    static final int AnyType = 3;
 
50
 
 
51
    // It is assumed that (NumberType | AnyType) == AnyType
 
52
 
 
53
    void optimize(ScriptOrFnNode scriptOrFn)
 
54
    {
 
55
        //  run on one function at a time for now
 
56
        int functionCount = scriptOrFn.getFunctionCount();
 
57
        for (int i = 0; i != functionCount; ++i) {
 
58
            OptFunctionNode f = OptFunctionNode.get(scriptOrFn, i);
 
59
            optimizeFunction(f);
 
60
        }
 
61
    }
 
62
 
 
63
    private void optimizeFunction(OptFunctionNode theFunction)
 
64
    {
 
65
        if (theFunction.fnode.requiresActivation()) return;
 
66
 
 
67
        inDirectCallFunction = theFunction.isTargetOfDirectCall();
 
68
        this.theFunction = theFunction;
 
69
 
 
70
        ObjArray statementsArray = new ObjArray();
 
71
        buildStatementList_r(theFunction.fnode, statementsArray);
 
72
        Node[] theStatementNodes = new Node[statementsArray.size()];
 
73
        statementsArray.toArray(theStatementNodes);
 
74
 
 
75
        Block.runFlowAnalyzes(theFunction, theStatementNodes);
 
76
 
 
77
        if (!theFunction.fnode.requiresActivation()) {
 
78
            /*
 
79
             * Now that we know which local vars are in fact always
 
80
             * Numbers, we re-write the tree to take advantage of
 
81
             * that. Any arithmetic or assignment op involving just
 
82
             * Number typed vars is marked so that the codegen will
 
83
             * generate non-object code.
 
84
             */
 
85
            parameterUsedInNumberContext = false;
 
86
            for (int i = 0; i < theStatementNodes.length; i++) {
 
87
                rewriteForNumberVariables(theStatementNodes[i]);
 
88
            }
 
89
            theFunction.setParameterNumberContext(parameterUsedInNumberContext);
 
90
        }
 
91
 
 
92
    }
 
93
 
 
94
 
 
95
/*
 
96
        Each directCall parameter is passed as a pair of values - an object
 
97
        and a double. The value passed depends on the type of value available at
 
98
        the call site. If a double is available, the object in java/lang/Void.TYPE
 
99
        is passed as the object value, and if an object value is available, then
 
100
        0.0 is passed as the double value.
 
101
 
 
102
        The receiving routine always tests the object value before proceeding.
 
103
        If the parameter is being accessed in a 'Number Context' then the code
 
104
        sequence is :
 
105
        if ("parameter_objectValue" == java/lang/Void.TYPE)
 
106
            ...fine..., use the parameter_doubleValue
 
107
        else
 
108
            toNumber(parameter_objectValue)
 
109
 
 
110
        and if the parameter is being referenced in an Object context, the code is
 
111
        if ("parameter_objectValue" == java/lang/Void.TYPE)
 
112
            new Double(parameter_doubleValue)
 
113
        else
 
114
            ...fine..., use the parameter_objectValue
 
115
 
 
116
        If the receiving code never uses the doubleValue, it is converted on
 
117
        entry to a Double instead.
 
118
*/
 
119
 
 
120
 
 
121
/*
 
122
        We're referencing a node in a Number context (i.e. we'd prefer it
 
123
        was a double value). If the node is a parameter in a directCall
 
124
        function, mark it as being referenced in this context.
 
125
*/
 
126
    private void markDCPNumberContext(Node n)
 
127
    {
 
128
        if (inDirectCallFunction && n.getType() == Token.GETVAR) {
 
129
            int varIndex = theFunction.getVarIndex(n);
 
130
            if (theFunction.isParameter(varIndex)) {
 
131
                parameterUsedInNumberContext = true;
 
132
            }
 
133
        }
 
134
    }
 
135
 
 
136
    private boolean convertParameter(Node n)
 
137
    {
 
138
        if (inDirectCallFunction && n.getType() == Token.GETVAR) {
 
139
            int varIndex = theFunction.getVarIndex(n);
 
140
            if (theFunction.isParameter(varIndex)) {
 
141
                n.removeProp(Node.ISNUMBER_PROP);
 
142
                return true;
 
143
            }
 
144
        }
 
145
        return false;
 
146
    }
 
147
 
 
148
    private int rewriteForNumberVariables(Node n)
 
149
    {
 
150
        switch (n.getType()) {
 
151
            case Token.EXPR_VOID : {
 
152
                    Node child = n.getFirstChild();
 
153
                    int type = rewriteForNumberVariables(child);
 
154
                    if (type == NumberType)
 
155
                        n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH);
 
156
                     return NoType;
 
157
                }
 
158
            case Token.NUMBER :
 
159
                n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH);
 
160
                return NumberType;
 
161
 
 
162
            case Token.GETVAR :
 
163
                {
 
164
                    int varIndex = theFunction.getVarIndex(n);
 
165
                    if (inDirectCallFunction
 
166
                        && theFunction.isParameter(varIndex))
 
167
                    {
 
168
                        n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH);
 
169
                        return NumberType;
 
170
                    }
 
171
                    else if (theFunction.isNumberVar(varIndex)) {
 
172
                        n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH);
 
173
                        return NumberType;
 
174
                    }
 
175
                    return NoType;
 
176
                }
 
177
 
 
178
            case Token.INC :
 
179
            case Token.DEC : {
 
180
                    Node child = n.getFirstChild();
 
181
                    // "child" will be GETVAR or GETPROP or GETELEM
 
182
                    if (child.getType() == Token.GETVAR) {
 
183
                        if (rewriteForNumberVariables(child) == NumberType) {
 
184
                            n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH);
 
185
                            markDCPNumberContext(child);
 
186
                            return NumberType;
 
187
                        }
 
188
                      return NoType;                       
 
189
                    }
 
190
                    else if (child.getType() == Token.GETELEM) {
 
191
                        return rewriteForNumberVariables(child);
 
192
                    }
 
193
                    return NoType;
 
194
                }
 
195
            case Token.SETVAR : {
 
196
                    Node lChild = n.getFirstChild();
 
197
                    Node rChild = lChild.getNext();
 
198
                    int rType = rewriteForNumberVariables(rChild);
 
199
                    int varIndex = theFunction.getVarIndex(n);
 
200
                    if (inDirectCallFunction
 
201
                        && theFunction.isParameter(varIndex))
 
202
                    {
 
203
                        if (rType == NumberType) {
 
204
                            if (!convertParameter(rChild)) {
 
205
                                n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH);
 
206
                                return NumberType;
 
207
                            }
 
208
                            markDCPNumberContext(rChild);
 
209
                            return NoType;
 
210
                        }
 
211
                        else
 
212
                            return rType;
 
213
                    }
 
214
                    else if (theFunction.isNumberVar(varIndex)) {
 
215
                        if (rType != NumberType) {
 
216
                            n.removeChild(rChild);
 
217
                            n.addChildToBack(
 
218
                                new Node(Token.TO_DOUBLE, rChild));
 
219
                        }
 
220
                        n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH);
 
221
                        markDCPNumberContext(rChild);
 
222
                        return NumberType;
 
223
                    }
 
224
                    else {
 
225
                        if (rType == NumberType) {
 
226
                            if (!convertParameter(rChild)) {
 
227
                                n.removeChild(rChild);
 
228
                                n.addChildToBack(
 
229
                                    new Node(Token.TO_OBJECT, rChild));
 
230
                            }
 
231
                        }
 
232
                        return NoType;
 
233
                    }
 
234
                }
 
235
            case Token.LE :
 
236
            case Token.LT :
 
237
            case Token.GE :
 
238
            case Token.GT : {
 
239
                    Node lChild = n.getFirstChild();
 
240
                    Node rChild = lChild.getNext();
 
241
                    int lType = rewriteForNumberVariables(lChild);
 
242
                    int rType = rewriteForNumberVariables(rChild);
 
243
                    markDCPNumberContext(lChild);
 
244
                    markDCPNumberContext(rChild);
 
245
 
 
246
                    if (convertParameter(lChild)) {
 
247
                        if (convertParameter(rChild)) {
 
248
                            return NoType;
 
249
                        } else if (rType == NumberType) {
 
250
                            n.putIntProp(Node.ISNUMBER_PROP, Node.RIGHT);
 
251
                        }
 
252
                    }
 
253
                    else if (convertParameter(rChild)) {
 
254
                        if (lType == NumberType) {
 
255
                            n.putIntProp(Node.ISNUMBER_PROP, Node.LEFT);
 
256
                        }
 
257
                    }
 
258
                    else {
 
259
                        if (lType == NumberType) {
 
260
                            if (rType == NumberType) {
 
261
                                n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH);
 
262
                            }
 
263
                            else {
 
264
                                n.putIntProp(Node.ISNUMBER_PROP, Node.LEFT);
 
265
                            }
 
266
                        }
 
267
                        else {
 
268
                            if (rType == NumberType) {
 
269
                                n.putIntProp(Node.ISNUMBER_PROP, Node.RIGHT);
 
270
                            }
 
271
                        }
 
272
                    }
 
273
                    // we actually build a boolean value
 
274
                    return NoType;
 
275
                }
 
276
 
 
277
            case Token.ADD : {
 
278
                    Node lChild = n.getFirstChild();
 
279
                    Node rChild = lChild.getNext();
 
280
                    int lType = rewriteForNumberVariables(lChild);
 
281
                    int rType = rewriteForNumberVariables(rChild);
 
282
 
 
283
 
 
284
                    if (convertParameter(lChild)) {
 
285
                        if (convertParameter(rChild)) {
 
286
                            return NoType;
 
287
                        }
 
288
                        else {
 
289
                            if (rType == NumberType) {
 
290
                                n.putIntProp(Node.ISNUMBER_PROP, Node.RIGHT);
 
291
                            }
 
292
                        }
 
293
                    }
 
294
                    else {
 
295
                        if (convertParameter(rChild)) {
 
296
                            if (lType == NumberType) {
 
297
                                n.putIntProp(Node.ISNUMBER_PROP, Node.LEFT);
 
298
                            }
 
299
                        }
 
300
                        else {
 
301
                            if (lType == NumberType) {
 
302
                                if (rType == NumberType) {
 
303
                                    n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH);
 
304
                                    return NumberType;
 
305
                                }
 
306
                                else {
 
307
                                    n.putIntProp(Node.ISNUMBER_PROP, Node.LEFT);
 
308
                                }
 
309
                            }
 
310
                            else {
 
311
                                if (rType == NumberType) {
 
312
                                    n.putIntProp(Node.ISNUMBER_PROP,
 
313
                                                 Node.RIGHT);
 
314
                                }
 
315
                            }
 
316
                        }
 
317
                    }
 
318
                    return NoType;
 
319
                }
 
320
 
 
321
            case Token.BITXOR :
 
322
            case Token.BITOR :
 
323
            case Token.BITAND :
 
324
            case Token.RSH :
 
325
            case Token.LSH :
 
326
            case Token.SUB :
 
327
            case Token.MUL :
 
328
            case Token.DIV :
 
329
            case Token.MOD : {
 
330
                    Node lChild = n.getFirstChild();
 
331
                    Node rChild = lChild.getNext();
 
332
                    int lType = rewriteForNumberVariables(lChild);
 
333
                    int rType = rewriteForNumberVariables(rChild);
 
334
                    markDCPNumberContext(lChild);
 
335
                    markDCPNumberContext(rChild);
 
336
                    if (lType == NumberType) {
 
337
                        if (rType == NumberType) {
 
338
                            n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH);
 
339
                            return NumberType;
 
340
                        }
 
341
                        else {
 
342
                            if (!convertParameter(rChild)) {
 
343
                                n.removeChild(rChild);
 
344
                                n.addChildToBack(
 
345
                                    new Node(Token.TO_DOUBLE, rChild));
 
346
                                n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH);
 
347
                            }
 
348
                            return NumberType;
 
349
                        }
 
350
                    }
 
351
                    else {
 
352
                        if (rType == NumberType) {
 
353
                            if (!convertParameter(lChild)) {
 
354
                                n.removeChild(lChild);
 
355
                                n.addChildToFront(
 
356
                                    new Node(Token.TO_DOUBLE, lChild));
 
357
                                n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH);
 
358
                            }
 
359
                            return NumberType;
 
360
                        }
 
361
                        else {
 
362
                            if (!convertParameter(lChild)) {
 
363
                                n.removeChild(lChild);
 
364
                                n.addChildToFront(
 
365
                                    new Node(Token.TO_DOUBLE, lChild));
 
366
                            }
 
367
                            if (!convertParameter(rChild)) {
 
368
                                n.removeChild(rChild);
 
369
                                n.addChildToBack(
 
370
                                    new Node(Token.TO_DOUBLE, rChild));
 
371
                            }
 
372
                            n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH);
 
373
                            return NumberType;
 
374
                        }
 
375
                    }
 
376
                }
 
377
            case Token.SETELEM :
 
378
            case Token.SETELEM_OP : {
 
379
                    Node arrayBase = n.getFirstChild();
 
380
                    Node arrayIndex = arrayBase.getNext();
 
381
                    Node rValue = arrayIndex.getNext();
 
382
                    int baseType = rewriteForNumberVariables(arrayBase);
 
383
                    if (baseType == NumberType) {// can never happen ???
 
384
                        if (!convertParameter(arrayBase)) {
 
385
                            n.removeChild(arrayBase);
 
386
                            n.addChildToFront(
 
387
                                new Node(Token.TO_OBJECT, arrayBase));
 
388
                        }
 
389
                    }
 
390
                    int indexType = rewriteForNumberVariables(arrayIndex);
 
391
                    if (indexType == NumberType) {
 
392
                        // setting the ISNUMBER_PROP signals the codegen
 
393
                        // to use the OptRuntime.setObjectIndex that takes
 
394
                        // a double index
 
395
                        n.putIntProp(Node.ISNUMBER_PROP, Node.LEFT);
 
396
                        markDCPNumberContext(arrayIndex);
 
397
                    }
 
398
                    int rValueType = rewriteForNumberVariables(rValue);
 
399
                    if (rValueType == NumberType) {
 
400
                        if (!convertParameter(rValue)) {
 
401
                            n.removeChild(rValue);
 
402
                            n.addChildToBack(
 
403
                                new Node(Token.TO_OBJECT, rValue));
 
404
                        }
 
405
                    }
 
406
                    return NoType;
 
407
                }
 
408
            case Token.GETELEM : {
 
409
                    Node arrayBase = n.getFirstChild();
 
410
                    Node arrayIndex = arrayBase.getNext();
 
411
                    int baseType = rewriteForNumberVariables(arrayBase);
 
412
                    if (baseType == NumberType) {// can never happen ???
 
413
                        if (!convertParameter(arrayBase)) {
 
414
                            n.removeChild(arrayBase);
 
415
                            n.addChildToFront(
 
416
                                new Node(Token.TO_OBJECT, arrayBase));
 
417
                        }
 
418
                    }
 
419
                    int indexType = rewriteForNumberVariables(arrayIndex);
 
420
                    if (indexType == NumberType) {
 
421
                        if (!convertParameter(arrayIndex)) {
 
422
                            // setting the ISNUMBER_PROP signals the codegen
 
423
                            // to use the OptRuntime.getObjectIndex that takes
 
424
                            // a double index
 
425
                            n.putIntProp(Node.ISNUMBER_PROP, Node.RIGHT);
 
426
                        }
 
427
                    }
 
428
                    return NoType;
 
429
                }
 
430
            case Token.CALL :
 
431
                {
 
432
                    Node child = n.getFirstChild(); // the function node
 
433
                    if (child.getType() == Token.GETELEM) {
 
434
                        // Optimization of x[0]() is not supported
 
435
                        // so bypass GETELEM optimization that
 
436
                        // rewriteForNumberVariables would trigger
 
437
                        rewriteAsObjectChildren(child, child.getFirstChild());
 
438
                    } else {
 
439
                        rewriteForNumberVariables(child);
 
440
                    }
 
441
                    child = child.getNext(); // the first arg
 
442
 
 
443
                    OptFunctionNode target
 
444
                            = (OptFunctionNode)n.getProp(Node.DIRECTCALL_PROP);
 
445
                    if (target != null) {
 
446
/*
 
447
    we leave each child as a Number if it can be. The codegen will
 
448
    handle moving the pairs of parameters.
 
449
*/
 
450
                        while (child != null) {
 
451
                            int type = rewriteForNumberVariables(child);
 
452
                            if (type == NumberType) {
 
453
                                markDCPNumberContext(child);
 
454
                            }
 
455
                            child = child.getNext();
 
456
                        }
 
457
                    } else {
 
458
                        rewriteAsObjectChildren(n, child);
 
459
                    }
 
460
                    return NoType;
 
461
                }
 
462
            default : {
 
463
                    rewriteAsObjectChildren(n, n.getFirstChild());
 
464
                    return NoType;
 
465
                }
 
466
        }
 
467
    }
 
468
 
 
469
    private void rewriteAsObjectChildren(Node n, Node child)
 
470
    {
 
471
        // Force optimized children to be objects
 
472
        while (child != null) {
 
473
            Node nextChild = child.getNext();
 
474
            int type = rewriteForNumberVariables(child);
 
475
            if (type == NumberType) {
 
476
                if (!convertParameter(child)) {
 
477
                    n.removeChild(child);
 
478
                    Node nuChild = new Node(Token.TO_OBJECT, child);
 
479
                    if (nextChild == null)
 
480
                        n.addChildToBack(nuChild);
 
481
                    else
 
482
                        n.addChildBefore(nuChild, nextChild);
 
483
                }
 
484
            }
 
485
            child = nextChild;
 
486
        }
 
487
    }
 
488
 
 
489
    private static void buildStatementList_r(Node node, ObjArray statements)
 
490
    {
 
491
        int type = node.getType();
 
492
        if (type == Token.BLOCK
 
493
            || type == Token.LOCAL_BLOCK
 
494
            || type == Token.LOOP
 
495
            || type == Token.FUNCTION)
 
496
        {
 
497
            Node child = node.getFirstChild();
 
498
            while (child != null) {
 
499
                buildStatementList_r(child, statements);
 
500
                child = child.getNext();
 
501
            }
 
502
        } else {
 
503
            statements.add(node);
 
504
        }
 
505
    }
 
506
 
 
507
    private boolean inDirectCallFunction;
 
508
    OptFunctionNode theFunction;
 
509
    private boolean parameterUsedInNumberContext;
 
510
}