Source Code Cross Referenced for Interpreter.java in  » Scripting » rhino » org » mozilla » javascript » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Scripting » rhino » org.mozilla.javascript 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
0002:         *
0003:         * ***** BEGIN LICENSE BLOCK *****
0004:         * Version: MPL 1.1/GPL 2.0
0005:         *
0006:         * The contents of this file are subject to the Mozilla Public License Version
0007:         * 1.1 (the "License"); you may not use this file except in compliance with
0008:         * the License. You may obtain a copy of the License at
0009:         * http://www.mozilla.org/MPL/
0010:         *
0011:         * Software distributed under the License is distributed on an "AS IS" basis,
0012:         * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
0013:         * for the specific language governing rights and limitations under the
0014:         * License.
0015:         *
0016:         * The Original Code is Rhino code, released
0017:         * May 6, 1999.
0018:         *
0019:         * The Initial Developer of the Original Code is
0020:         * Netscape Communications Corporation.
0021:         * Portions created by the Initial Developer are Copyright (C) 1997-2000
0022:         * the Initial Developer. All Rights Reserved.
0023:         *
0024:         * Contributor(s):
0025:         *   Patrick Beard
0026:         *   Norris Boyd
0027:         *   Igor Bukanov
0028:         *   Ethan Hugg
0029:         *   Bob Jervis
0030:         *   Terry Lucas
0031:         *   Roger Lawrence
0032:         *   Milen Nankov
0033:         *   Hannes Wallnoefer
0034:         *
0035:         * Alternatively, the contents of this file may be used under the terms of
0036:         * the GNU General Public License Version 2 or later (the "GPL"), in which
0037:         * case the provisions of the GPL are applicable instead of those above. If
0038:         * you wish to allow use of your version of this file only under the terms of
0039:         * the GPL and not to allow others to use your version of this file under the
0040:         * MPL, indicate your decision by deleting the provisions above and replacing
0041:         * them with the notice and other provisions required by the GPL. If you do
0042:         * not delete the provisions above, a recipient may use your version of this
0043:         * file under either the MPL or the GPL.
0044:         *
0045:         * ***** END LICENSE BLOCK ***** */
0046:
0047:        package org.mozilla.javascript;
0048:
0049:        import java.io.PrintStream;
0050:        import java.io.Serializable;
0051:        import java.util.List;
0052:        import java.util.ArrayList;
0053:
0054:        import org.mozilla.javascript.continuations.Continuation;
0055:        import org.mozilla.javascript.debug.DebugFrame;
0056:
0057:        public class Interpreter implements  Evaluator {
0058:
0059:            // Additional interpreter-specific codes
0060:
0061:            private static final int
0062:
0063:            // Stack: ... value1 -> ... value1 value1
0064:                    Icode_DUP = -1,
0065:
0066:                    // Stack: ... value2 value1 -> ... value2 value1 value2 value1
0067:                    Icode_DUP2 = -2,
0068:
0069:                    // Stack: ... value2 value1 -> ... value1 value2
0070:                    Icode_SWAP = -3,
0071:
0072:                    // Stack: ... value1 -> ...
0073:                    Icode_POP = -4,
0074:
0075:                    // Store stack top into return register and then pop it
0076:                    Icode_POP_RESULT = -5,
0077:
0078:                    // To jump conditionally and pop additional stack value
0079:                    Icode_IFEQ_POP = -6,
0080:
0081:                    // various types of ++/--
0082:                    Icode_VAR_INC_DEC = -7,
0083:                    Icode_NAME_INC_DEC = -8,
0084:                    Icode_PROP_INC_DEC = -9,
0085:                    Icode_ELEM_INC_DEC = -10,
0086:                    Icode_REF_INC_DEC = -11,
0087:
0088:                    // load/save scope from/to local
0089:                    Icode_SCOPE_LOAD = -12,
0090:                    Icode_SCOPE_SAVE = -13,
0091:
0092:                    Icode_TYPEOFNAME = -14,
0093:
0094:                    // helper for function calls
0095:                    Icode_NAME_AND_THIS = -15,
0096:                    Icode_PROP_AND_THIS = -16,
0097:                    Icode_ELEM_AND_THIS = -17,
0098:                    Icode_VALUE_AND_THIS = -18,
0099:
0100:                    // Create closure object for nested functions
0101:                    Icode_CLOSURE_EXPR = -19,
0102:                    Icode_CLOSURE_STMT = -20,
0103:
0104:                    // Special calls
0105:                    Icode_CALLSPECIAL = -21,
0106:
0107:                    // To return undefined value
0108:                    Icode_RETUNDEF = -22,
0109:
0110:                    // Exception handling implementation
0111:                    Icode_GOSUB = -23,
0112:                    Icode_STARTSUB = -24,
0113:                    Icode_RETSUB = -25,
0114:
0115:                    // To indicating a line number change in icodes.
0116:                    Icode_LINE = -26,
0117:
0118:                    // To store shorts and ints inline
0119:                    Icode_SHORTNUMBER = -27,
0120:                    Icode_INTNUMBER = -28,
0121:
0122:                    // To create and populate array to hold values for [] and {} literals
0123:                    Icode_LITERAL_NEW = -29,
0124:                    Icode_LITERAL_SET = -30,
0125:
0126:                    // Array literal with skipped index like [1,,2]
0127:                    Icode_SPARE_ARRAYLIT = -31,
0128:
0129:                    // Load index register to prepare for the following index operation
0130:                    Icode_REG_IND_C0 = -32,
0131:                    Icode_REG_IND_C1 = -33,
0132:                    Icode_REG_IND_C2 = -34,
0133:                    Icode_REG_IND_C3 = -35,
0134:                    Icode_REG_IND_C4 = -36,
0135:                    Icode_REG_IND_C5 = -37,
0136:                    Icode_REG_IND1 = -38,
0137:                    Icode_REG_IND2 = -39,
0138:                    Icode_REG_IND4 = -40,
0139:
0140:                    // Load string register to prepare for the following string operation
0141:                    Icode_REG_STR_C0 = -41,
0142:                    Icode_REG_STR_C1 = -42,
0143:                    Icode_REG_STR_C2 = -43,
0144:                    Icode_REG_STR_C3 = -44,
0145:                    Icode_REG_STR1 = -45,
0146:                    Icode_REG_STR2 = -46,
0147:                    Icode_REG_STR4 = -47,
0148:
0149:                    // Version of getvar/setvar that read var index directly from bytecode
0150:                    Icode_GETVAR1 = -48, Icode_SETVAR1 = -49,
0151:
0152:                    // Load unefined
0153:                    Icode_UNDEF = -50, Icode_ZERO = -51, Icode_ONE = -52,
0154:
0155:                    // entrance and exit from .()
0156:                    Icode_ENTERDQ = -53, Icode_LEAVEDQ = -54,
0157:
0158:                    Icode_TAIL_CALL = -55,
0159:
0160:                    // Clear local to allow GC its context
0161:                    Icode_LOCAL_CLEAR = -56,
0162:
0163:                    // Literal get/set
0164:                    Icode_LITERAL_GETTER = -57, Icode_LITERAL_SETTER = -58,
0165:
0166:                    // const
0167:                    Icode_SETCONST = -59,
0168:                    Icode_SETCONSTVAR = -60,
0169:                    Icode_SETCONSTVAR1 = -61,
0170:
0171:                    // Generator opcodes (along with Token.YIELD)
0172:                    Icode_GENERATOR = -62, Icode_GENERATOR_END = -63,
0173:
0174:                    Icode_DEBUGGER = -64,
0175:
0176:                    // Last icode
0177:                    MIN_ICODE = -64;
0178:
0179:            // data for parsing
0180:
0181:            private CompilerEnvirons compilerEnv;
0182:
0183:            private boolean itsInFunctionFlag;
0184:            private boolean itsInTryFlag;
0185:
0186:            private InterpreterData itsData;
0187:            private ScriptOrFnNode scriptOrFn;
0188:            private int itsICodeTop;
0189:            private int itsStackDepth;
0190:            private int itsLineNumber;
0191:            private int itsDoubleTableTop;
0192:            private ObjToIntMap itsStrings = new ObjToIntMap(20);
0193:            private int itsLocalTop;
0194:
0195:            private static final int MIN_LABEL_TABLE_SIZE = 32;
0196:            private static final int MIN_FIXUP_TABLE_SIZE = 40;
0197:            private int[] itsLabelTable;
0198:            private int itsLabelTableTop;
0199:            // itsFixupTable[i] = (label_index << 32) | fixup_site
0200:            private long[] itsFixupTable;
0201:            private int itsFixupTableTop;
0202:            private ObjArray itsLiteralIds = new ObjArray();
0203:
0204:            private int itsExceptionTableTop;
0205:            private static final int EXCEPTION_TRY_START_SLOT = 0;
0206:            private static final int EXCEPTION_TRY_END_SLOT = 1;
0207:            private static final int EXCEPTION_HANDLER_SLOT = 2;
0208:            private static final int EXCEPTION_TYPE_SLOT = 3;
0209:            private static final int EXCEPTION_LOCAL_SLOT = 4;
0210:            private static final int EXCEPTION_SCOPE_SLOT = 5;
0211:            // SLOT_SIZE: space for try start/end, handler, start, handler type,
0212:            //            exception local and scope local
0213:            private static final int EXCEPTION_SLOT_SIZE = 6;
0214:
0215:            // ECF_ or Expression Context Flags constants: for now only TAIL is available
0216:            private static final int ECF_TAIL = 1 << 0;
0217:
0218:            /**
0219:             * Class to hold data corresponding to one interpreted call stack frame.
0220:             */
0221:            private static class CallFrame implements  Cloneable, Serializable {
0222:                static final long serialVersionUID = -2843792508994958978L;
0223:
0224:                CallFrame parentFrame;
0225:                // amount of stack frames before this one on the interpretation stack
0226:                int frameIndex;
0227:                // If true indicates read-only frame that is a part of continuation
0228:                boolean frozen;
0229:
0230:                InterpretedFunction fnOrScript;
0231:                InterpreterData idata;
0232:
0233:                // Stack structure
0234:                // stack[0 <= i < localShift]: arguments and local variables
0235:                // stack[localShift <= i <= emptyStackTop]: used for local temporaries
0236:                // stack[emptyStackTop < i < stack.length]: stack data
0237:                // sDbl[i]: if stack[i] is UniqueTag.DOUBLE_MARK, sDbl[i] holds the number value
0238:
0239:                Object[] stack;
0240:                int[] stackAttributes;
0241:                double[] sDbl;
0242:                CallFrame varSource; // defaults to this unless continuation frame
0243:                int localShift;
0244:                int emptyStackTop;
0245:
0246:                DebugFrame debuggerFrame;
0247:                boolean useActivation;
0248:
0249:                Scriptable this Obj;
0250:                Scriptable[] scriptRegExps;
0251:
0252:                // The values that change during interpretation
0253:
0254:                Object result;
0255:                double resultDbl;
0256:                int pc;
0257:                int pcPrevBranch;
0258:                int pcSourceLineStart;
0259:                Scriptable scope;
0260:
0261:                int savedStackTop;
0262:                int savedCallOp;
0263:                Object throwable;
0264:
0265:                CallFrame cloneFrozen() {
0266:                    if (!frozen)
0267:                        Kit.codeBug();
0268:
0269:                    CallFrame copy;
0270:                    try {
0271:                        copy = (CallFrame) clone();
0272:                    } catch (CloneNotSupportedException ex) {
0273:                        throw new IllegalStateException();
0274:                    }
0275:
0276:                    // clone stack but keep varSource to point to values
0277:                    // from this frame to share variables.
0278:
0279:                    copy.stack = stack.clone();
0280:                    copy.stackAttributes = stackAttributes.clone();
0281:                    copy.sDbl = sDbl.clone();
0282:
0283:                    copy.frozen = false;
0284:                    return copy;
0285:                }
0286:            }
0287:
0288:            private static final class ContinuationJump implements  Serializable {
0289:                static final long serialVersionUID = 7687739156004308247L;
0290:
0291:                CallFrame capturedFrame;
0292:                CallFrame branchFrame;
0293:                Object result;
0294:                double resultDbl;
0295:
0296:                ContinuationJump(Continuation c, CallFrame current) {
0297:                    this .capturedFrame = (CallFrame) c.getImplementation();
0298:                    if (this .capturedFrame == null || current == null) {
0299:                        // Continuation and current execution does not share
0300:                        // any frames if there is nothing to capture or
0301:                        // if there is no currently executed frames
0302:                        this .branchFrame = null;
0303:                    } else {
0304:                        // Search for branch frame where parent frame chains starting
0305:                        // from captured and current meet.
0306:                        CallFrame chain1 = this .capturedFrame;
0307:                        CallFrame chain2 = current;
0308:
0309:                        // First work parents of chain1 or chain2 until the same
0310:                        // frame depth.
0311:                        int diff = chain1.frameIndex - chain2.frameIndex;
0312:                        if (diff != 0) {
0313:                            if (diff < 0) {
0314:                                // swap to make sure that
0315:                                // chain1.frameIndex > chain2.frameIndex and diff > 0
0316:                                chain1 = current;
0317:                                chain2 = this .capturedFrame;
0318:                                diff = -diff;
0319:                            }
0320:                            do {
0321:                                chain1 = chain1.parentFrame;
0322:                            } while (--diff != 0);
0323:                            if (chain1.frameIndex != chain2.frameIndex)
0324:                                Kit.codeBug();
0325:                        }
0326:
0327:                        // Now walk parents in parallel until a shared frame is found
0328:                        // or until the root is reached.
0329:                        while (chain1 != chain2 && chain1 != null) {
0330:                            chain1 = chain1.parentFrame;
0331:                            chain2 = chain2.parentFrame;
0332:                        }
0333:
0334:                        this .branchFrame = chain1;
0335:                        if (this .branchFrame != null
0336:                                && !this .branchFrame.frozen)
0337:                            Kit.codeBug();
0338:                    }
0339:                }
0340:            }
0341:
0342:            private static CallFrame captureFrameForGenerator(CallFrame frame) {
0343:                frame.frozen = true;
0344:                CallFrame result = frame.cloneFrozen();
0345:                frame.frozen = false;
0346:
0347:                // now isolate this frame from its previous context
0348:                result.parentFrame = null;
0349:                result.frameIndex = 0;
0350:
0351:                return result;
0352:            }
0353:
0354:            static {
0355:                // Checks for byte code consistencies, good compiler can eliminate them
0356:
0357:                if (Token.LAST_BYTECODE_TOKEN > 127) {
0358:                    String str = "Violation of Token.LAST_BYTECODE_TOKEN <= 127";
0359:                    System.err.println(str);
0360:                    throw new IllegalStateException(str);
0361:                }
0362:                if (MIN_ICODE < -128) {
0363:                    String str = "Violation of Interpreter.MIN_ICODE >= -128";
0364:                    System.err.println(str);
0365:                    throw new IllegalStateException(str);
0366:                }
0367:            }
0368:
0369:            private static String bytecodeName(int bytecode) {
0370:                if (!validBytecode(bytecode)) {
0371:                    throw new IllegalArgumentException(String.valueOf(bytecode));
0372:                }
0373:
0374:                if (!Token.printICode) {
0375:                    return String.valueOf(bytecode);
0376:                }
0377:
0378:                if (validTokenCode(bytecode)) {
0379:                    return Token.name(bytecode);
0380:                }
0381:
0382:                switch (bytecode) {
0383:                case Icode_DUP:
0384:                    return "DUP";
0385:                case Icode_DUP2:
0386:                    return "DUP2";
0387:                case Icode_SWAP:
0388:                    return "SWAP";
0389:                case Icode_POP:
0390:                    return "POP";
0391:                case Icode_POP_RESULT:
0392:                    return "POP_RESULT";
0393:                case Icode_IFEQ_POP:
0394:                    return "IFEQ_POP";
0395:                case Icode_VAR_INC_DEC:
0396:                    return "VAR_INC_DEC";
0397:                case Icode_NAME_INC_DEC:
0398:                    return "NAME_INC_DEC";
0399:                case Icode_PROP_INC_DEC:
0400:                    return "PROP_INC_DEC";
0401:                case Icode_ELEM_INC_DEC:
0402:                    return "ELEM_INC_DEC";
0403:                case Icode_REF_INC_DEC:
0404:                    return "REF_INC_DEC";
0405:                case Icode_SCOPE_LOAD:
0406:                    return "SCOPE_LOAD";
0407:                case Icode_SCOPE_SAVE:
0408:                    return "SCOPE_SAVE";
0409:                case Icode_TYPEOFNAME:
0410:                    return "TYPEOFNAME";
0411:                case Icode_NAME_AND_THIS:
0412:                    return "NAME_AND_THIS";
0413:                case Icode_PROP_AND_THIS:
0414:                    return "PROP_AND_THIS";
0415:                case Icode_ELEM_AND_THIS:
0416:                    return "ELEM_AND_THIS";
0417:                case Icode_VALUE_AND_THIS:
0418:                    return "VALUE_AND_THIS";
0419:                case Icode_CLOSURE_EXPR:
0420:                    return "CLOSURE_EXPR";
0421:                case Icode_CLOSURE_STMT:
0422:                    return "CLOSURE_STMT";
0423:                case Icode_CALLSPECIAL:
0424:                    return "CALLSPECIAL";
0425:                case Icode_RETUNDEF:
0426:                    return "RETUNDEF";
0427:                case Icode_GOSUB:
0428:                    return "GOSUB";
0429:                case Icode_STARTSUB:
0430:                    return "STARTSUB";
0431:                case Icode_RETSUB:
0432:                    return "RETSUB";
0433:                case Icode_LINE:
0434:                    return "LINE";
0435:                case Icode_SHORTNUMBER:
0436:                    return "SHORTNUMBER";
0437:                case Icode_INTNUMBER:
0438:                    return "INTNUMBER";
0439:                case Icode_LITERAL_NEW:
0440:                    return "LITERAL_NEW";
0441:                case Icode_LITERAL_SET:
0442:                    return "LITERAL_SET";
0443:                case Icode_SPARE_ARRAYLIT:
0444:                    return "SPARE_ARRAYLIT";
0445:                case Icode_REG_IND_C0:
0446:                    return "REG_IND_C0";
0447:                case Icode_REG_IND_C1:
0448:                    return "REG_IND_C1";
0449:                case Icode_REG_IND_C2:
0450:                    return "REG_IND_C2";
0451:                case Icode_REG_IND_C3:
0452:                    return "REG_IND_C3";
0453:                case Icode_REG_IND_C4:
0454:                    return "REG_IND_C4";
0455:                case Icode_REG_IND_C5:
0456:                    return "REG_IND_C5";
0457:                case Icode_REG_IND1:
0458:                    return "LOAD_IND1";
0459:                case Icode_REG_IND2:
0460:                    return "LOAD_IND2";
0461:                case Icode_REG_IND4:
0462:                    return "LOAD_IND4";
0463:                case Icode_REG_STR_C0:
0464:                    return "REG_STR_C0";
0465:                case Icode_REG_STR_C1:
0466:                    return "REG_STR_C1";
0467:                case Icode_REG_STR_C2:
0468:                    return "REG_STR_C2";
0469:                case Icode_REG_STR_C3:
0470:                    return "REG_STR_C3";
0471:                case Icode_REG_STR1:
0472:                    return "LOAD_STR1";
0473:                case Icode_REG_STR2:
0474:                    return "LOAD_STR2";
0475:                case Icode_REG_STR4:
0476:                    return "LOAD_STR4";
0477:                case Icode_GETVAR1:
0478:                    return "GETVAR1";
0479:                case Icode_SETVAR1:
0480:                    return "SETVAR1";
0481:                case Icode_UNDEF:
0482:                    return "UNDEF";
0483:                case Icode_ZERO:
0484:                    return "ZERO";
0485:                case Icode_ONE:
0486:                    return "ONE";
0487:                case Icode_ENTERDQ:
0488:                    return "ENTERDQ";
0489:                case Icode_LEAVEDQ:
0490:                    return "LEAVEDQ";
0491:                case Icode_TAIL_CALL:
0492:                    return "TAIL_CALL";
0493:                case Icode_LOCAL_CLEAR:
0494:                    return "LOCAL_CLEAR";
0495:                case Icode_LITERAL_GETTER:
0496:                    return "LITERAL_GETTER";
0497:                case Icode_LITERAL_SETTER:
0498:                    return "LITERAL_SETTER";
0499:                case Icode_SETCONST:
0500:                    return "SETCONST";
0501:                case Icode_SETCONSTVAR:
0502:                    return "SETCONSTVAR";
0503:                case Icode_SETCONSTVAR1:
0504:                    return "SETCONSTVAR1";
0505:                case Icode_GENERATOR:
0506:                    return "GENERATOR";
0507:                case Icode_GENERATOR_END:
0508:                    return "GENERATOR_END";
0509:                case Icode_DEBUGGER:
0510:                    return "DEBUGGER";
0511:                }
0512:
0513:                // icode without name
0514:                throw new IllegalStateException(String.valueOf(bytecode));
0515:            }
0516:
0517:            private static boolean validIcode(int icode) {
0518:                return MIN_ICODE <= icode && icode <= -1;
0519:            }
0520:
0521:            private static boolean validTokenCode(int token) {
0522:                return Token.FIRST_BYTECODE_TOKEN <= token
0523:                        && token <= Token.LAST_BYTECODE_TOKEN;
0524:            }
0525:
0526:            private static boolean validBytecode(int bytecode) {
0527:                return validIcode(bytecode) || validTokenCode(bytecode);
0528:            }
0529:
0530:            public Object compile(CompilerEnvirons compilerEnv,
0531:                    ScriptOrFnNode tree, String encodedSource,
0532:                    boolean returnFunction) {
0533:                this .compilerEnv = compilerEnv;
0534:                new NodeTransformer().transform(tree);
0535:
0536:                if (Token.printTrees) {
0537:                    System.out.println(tree.toStringTree(tree));
0538:                }
0539:
0540:                if (returnFunction) {
0541:                    tree = tree.getFunctionNode(0);
0542:                }
0543:
0544:                scriptOrFn = tree;
0545:                itsData = new InterpreterData(compilerEnv.getLanguageVersion(),
0546:                        scriptOrFn.getSourceName(), encodedSource);
0547:                itsData.topLevel = true;
0548:
0549:                if (returnFunction) {
0550:                    generateFunctionICode();
0551:                } else {
0552:                    generateICodeFromTree(scriptOrFn);
0553:                }
0554:
0555:                return itsData;
0556:            }
0557:
0558:            public Script createScriptObject(Object bytecode,
0559:                    Object staticSecurityDomain) {
0560:                if (bytecode != itsData) {
0561:                    Kit.codeBug();
0562:                }
0563:                return InterpretedFunction.createScript(itsData,
0564:                        staticSecurityDomain);
0565:            }
0566:
0567:            public void setEvalScriptFlag(Script script) {
0568:                ((InterpretedFunction) script).idata.evalScriptFlag = true;
0569:            }
0570:
0571:            public Function createFunctionObject(Context cx, Scriptable scope,
0572:                    Object bytecode, Object staticSecurityDomain) {
0573:                if (bytecode != itsData) {
0574:                    Kit.codeBug();
0575:                }
0576:                return InterpretedFunction.createFunction(cx, scope, itsData,
0577:                        staticSecurityDomain);
0578:            }
0579:
0580:            private void generateFunctionICode() {
0581:                itsInFunctionFlag = true;
0582:
0583:                FunctionNode theFunction = (FunctionNode) scriptOrFn;
0584:
0585:                itsData.itsFunctionType = theFunction.getFunctionType();
0586:                itsData.itsNeedsActivation = theFunction.requiresActivation();
0587:                itsData.itsName = theFunction.getFunctionName();
0588:                if (!theFunction.getIgnoreDynamicScope()) {
0589:                    if (compilerEnv.isUseDynamicScope()) {
0590:                        itsData.useDynamicScope = true;
0591:                    }
0592:                }
0593:                if (theFunction.isGenerator()) {
0594:                    addIcode(Icode_GENERATOR);
0595:                    addUint16(theFunction.getBaseLineno() & 0xFFFF);
0596:                }
0597:
0598:                generateICodeFromTree(theFunction.getLastChild());
0599:            }
0600:
0601:            private void generateICodeFromTree(Node tree) {
0602:                generateNestedFunctions();
0603:
0604:                generateRegExpLiterals();
0605:
0606:                visitStatement(tree, 0);
0607:                fixLabelGotos();
0608:                // add RETURN_RESULT only to scripts as function always ends with RETURN
0609:                if (itsData.itsFunctionType == 0) {
0610:                    addToken(Token.RETURN_RESULT);
0611:                }
0612:
0613:                if (itsData.itsICode.length != itsICodeTop) {
0614:                    // Make itsData.itsICode length exactly itsICodeTop to save memory
0615:                    // and catch bugs with jumps beyond icode as early as possible
0616:                    byte[] tmp = new byte[itsICodeTop];
0617:                    System.arraycopy(itsData.itsICode, 0, tmp, 0, itsICodeTop);
0618:                    itsData.itsICode = tmp;
0619:                }
0620:                if (itsStrings.size() == 0) {
0621:                    itsData.itsStringTable = null;
0622:                } else {
0623:                    itsData.itsStringTable = new String[itsStrings.size()];
0624:                    ObjToIntMap.Iterator iter = itsStrings.newIterator();
0625:                    for (iter.start(); !iter.done(); iter.next()) {
0626:                        String str = (String) iter.getKey();
0627:                        int index = iter.getValue();
0628:                        if (itsData.itsStringTable[index] != null)
0629:                            Kit.codeBug();
0630:                        itsData.itsStringTable[index] = str;
0631:                    }
0632:                }
0633:                if (itsDoubleTableTop == 0) {
0634:                    itsData.itsDoubleTable = null;
0635:                } else if (itsData.itsDoubleTable.length != itsDoubleTableTop) {
0636:                    double[] tmp = new double[itsDoubleTableTop];
0637:                    System.arraycopy(itsData.itsDoubleTable, 0, tmp, 0,
0638:                            itsDoubleTableTop);
0639:                    itsData.itsDoubleTable = tmp;
0640:                }
0641:                if (itsExceptionTableTop != 0
0642:                        && itsData.itsExceptionTable.length != itsExceptionTableTop) {
0643:                    int[] tmp = new int[itsExceptionTableTop];
0644:                    System.arraycopy(itsData.itsExceptionTable, 0, tmp, 0,
0645:                            itsExceptionTableTop);
0646:                    itsData.itsExceptionTable = tmp;
0647:                }
0648:
0649:                itsData.itsMaxVars = scriptOrFn.getParamAndVarCount();
0650:                // itsMaxFrameArray: interpret method needs this amount for its
0651:                // stack and sDbl arrays
0652:                itsData.itsMaxFrameArray = itsData.itsMaxVars
0653:                        + itsData.itsMaxLocals + itsData.itsMaxStack;
0654:
0655:                itsData.argNames = scriptOrFn.getParamAndVarNames();
0656:                itsData.argIsConst = scriptOrFn.getParamAndVarConst();
0657:                itsData.argCount = scriptOrFn.getParamCount();
0658:
0659:                itsData.encodedSourceStart = scriptOrFn.getEncodedSourceStart();
0660:                itsData.encodedSourceEnd = scriptOrFn.getEncodedSourceEnd();
0661:
0662:                if (itsLiteralIds.size() != 0) {
0663:                    itsData.literalIds = itsLiteralIds.toArray();
0664:                }
0665:
0666:                if (Token.printICode)
0667:                    dumpICode(itsData);
0668:            }
0669:
0670:            private void generateNestedFunctions() {
0671:                int functionCount = scriptOrFn.getFunctionCount();
0672:                if (functionCount == 0)
0673:                    return;
0674:
0675:                InterpreterData[] array = new InterpreterData[functionCount];
0676:                for (int i = 0; i != functionCount; i++) {
0677:                    FunctionNode def = scriptOrFn.getFunctionNode(i);
0678:                    Interpreter jsi = new Interpreter();
0679:                    jsi.compilerEnv = compilerEnv;
0680:                    jsi.scriptOrFn = def;
0681:                    jsi.itsData = new InterpreterData(itsData);
0682:                    jsi.generateFunctionICode();
0683:                    array[i] = jsi.itsData;
0684:                }
0685:                itsData.itsNestedFunctions = array;
0686:            }
0687:
0688:            private void generateRegExpLiterals() {
0689:                int N = scriptOrFn.getRegexpCount();
0690:                if (N == 0)
0691:                    return;
0692:
0693:                Context cx = Context.getContext();
0694:                RegExpProxy rep = ScriptRuntime.checkRegExpProxy(cx);
0695:                Object[] array = new Object[N];
0696:                for (int i = 0; i != N; i++) {
0697:                    String string = scriptOrFn.getRegexpString(i);
0698:                    String flags = scriptOrFn.getRegexpFlags(i);
0699:                    array[i] = rep.compileRegExp(cx, string, flags);
0700:                }
0701:                itsData.itsRegExpLiterals = array;
0702:            }
0703:
0704:            private void updateLineNumber(Node node) {
0705:                int lineno = node.getLineno();
0706:                if (lineno != itsLineNumber && lineno >= 0) {
0707:                    if (itsData.firstLinePC < 0) {
0708:                        itsData.firstLinePC = lineno;
0709:                    }
0710:                    itsLineNumber = lineno;
0711:                    addIcode(Icode_LINE);
0712:                    addUint16(lineno & 0xFFFF);
0713:                }
0714:            }
0715:
0716:            private RuntimeException badTree(Node node) {
0717:                throw new RuntimeException(node.toString());
0718:            }
0719:
0720:            private void visitStatement(Node node, int initialStackDepth) {
0721:                int type = node.getType();
0722:                Node child = node.getFirstChild();
0723:                switch (type) {
0724:
0725:                case Token.FUNCTION: {
0726:                    int fnIndex = node.getExistingIntProp(Node.FUNCTION_PROP);
0727:                    int fnType = scriptOrFn.getFunctionNode(fnIndex)
0728:                            .getFunctionType();
0729:                    // Only function expressions or function expression
0730:                    // statements need closure code creating new function
0731:                    // object on stack as function statements are initialized
0732:                    // at script/function start.
0733:                    // In addition, function expressions can not be present here
0734:                    // at statement level, they must only be present as expressions.
0735:                    if (fnType == FunctionNode.FUNCTION_EXPRESSION_STATEMENT) {
0736:                        addIndexOp(Icode_CLOSURE_STMT, fnIndex);
0737:                    } else {
0738:                        if (fnType != FunctionNode.FUNCTION_STATEMENT) {
0739:                            throw Kit.codeBug();
0740:                        }
0741:                    }
0742:                    // For function statements or function expression statements
0743:                    // in scripts, we need to ensure that the result of the script
0744:                    // is the function if it is the last statement in the script.
0745:                    // For example, eval("function () {}") should return a
0746:                    // function, not undefined.
0747:                    if (!itsInFunctionFlag) {
0748:                        addIndexOp(Icode_CLOSURE_EXPR, fnIndex);
0749:                        stackChange(1);
0750:                        addIcode(Icode_POP_RESULT);
0751:                        stackChange(-1);
0752:                    }
0753:                }
0754:                    break;
0755:
0756:                case Token.LABEL:
0757:                case Token.LOOP:
0758:                case Token.BLOCK:
0759:                case Token.EMPTY:
0760:                case Token.WITH:
0761:                    updateLineNumber(node);
0762:                case Token.SCRIPT:
0763:                    // fall through
0764:                    while (child != null) {
0765:                        visitStatement(child, initialStackDepth);
0766:                        child = child.getNext();
0767:                    }
0768:                    break;
0769:
0770:                case Token.ENTERWITH:
0771:                    visitExpression(child, 0);
0772:                    addToken(Token.ENTERWITH);
0773:                    stackChange(-1);
0774:                    break;
0775:
0776:                case Token.LEAVEWITH:
0777:                    addToken(Token.LEAVEWITH);
0778:                    break;
0779:
0780:                case Token.LOCAL_BLOCK: {
0781:                    int local = allocLocal();
0782:                    node.putIntProp(Node.LOCAL_PROP, local);
0783:                    updateLineNumber(node);
0784:                    while (child != null) {
0785:                        visitStatement(child, initialStackDepth);
0786:                        child = child.getNext();
0787:                    }
0788:                    addIndexOp(Icode_LOCAL_CLEAR, local);
0789:                    releaseLocal(local);
0790:                }
0791:                    break;
0792:
0793:                case Token.DEBUGGER:
0794:                    addIcode(Icode_DEBUGGER);
0795:                    break;
0796:
0797:                case Token.SWITCH:
0798:                    updateLineNumber(node);
0799:                    // See comments in IRFactory.createSwitch() for description
0800:                    // of SWITCH node
0801:                    {
0802:                        visitExpression(child, 0);
0803:                        for (Node.Jump caseNode = (Node.Jump) child.getNext(); caseNode != null; caseNode = (Node.Jump) caseNode
0804:                                .getNext()) {
0805:                            if (caseNode.getType() != Token.CASE)
0806:                                throw badTree(caseNode);
0807:                            Node test = caseNode.getFirstChild();
0808:                            addIcode(Icode_DUP);
0809:                            stackChange(1);
0810:                            visitExpression(test, 0);
0811:                            addToken(Token.SHEQ);
0812:                            stackChange(-1);
0813:                            // If true, Icode_IFEQ_POP will jump and remove case
0814:                            // value from stack
0815:                            addGoto(caseNode.target, Icode_IFEQ_POP);
0816:                            stackChange(-1);
0817:                        }
0818:                        addIcode(Icode_POP);
0819:                        stackChange(-1);
0820:                    }
0821:                    break;
0822:
0823:                case Token.TARGET:
0824:                    markTargetLabel(node);
0825:                    break;
0826:
0827:                case Token.IFEQ:
0828:                case Token.IFNE: {
0829:                    Node target = ((Node.Jump) node).target;
0830:                    visitExpression(child, 0);
0831:                    addGoto(target, type);
0832:                    stackChange(-1);
0833:                }
0834:                    break;
0835:
0836:                case Token.GOTO: {
0837:                    Node target = ((Node.Jump) node).target;
0838:                    addGoto(target, type);
0839:                }
0840:                    break;
0841:
0842:                case Token.JSR: {
0843:                    Node target = ((Node.Jump) node).target;
0844:                    addGoto(target, Icode_GOSUB);
0845:                }
0846:                    break;
0847:
0848:                case Token.FINALLY: {
0849:                    // Account for incomming GOTOSUB address
0850:                    stackChange(1);
0851:                    int finallyRegister = getLocalBlockRef(node);
0852:                    addIndexOp(Icode_STARTSUB, finallyRegister);
0853:                    stackChange(-1);
0854:                    while (child != null) {
0855:                        visitStatement(child, initialStackDepth);
0856:                        child = child.getNext();
0857:                    }
0858:                    addIndexOp(Icode_RETSUB, finallyRegister);
0859:                }
0860:                    break;
0861:
0862:                case Token.EXPR_VOID:
0863:                case Token.EXPR_RESULT:
0864:                    updateLineNumber(node);
0865:                    visitExpression(child, 0);
0866:                    addIcode((type == Token.EXPR_VOID) ? Icode_POP
0867:                            : Icode_POP_RESULT);
0868:                    stackChange(-1);
0869:                    break;
0870:
0871:                case Token.TRY: {
0872:                    Node.Jump tryNode = (Node.Jump) node;
0873:                    int exceptionObjectLocal = getLocalBlockRef(tryNode);
0874:                    int scopeLocal = allocLocal();
0875:
0876:                    addIndexOp(Icode_SCOPE_SAVE, scopeLocal);
0877:
0878:                    int tryStart = itsICodeTop;
0879:                    boolean savedFlag = itsInTryFlag;
0880:                    itsInTryFlag = true;
0881:                    while (child != null) {
0882:                        visitStatement(child, initialStackDepth);
0883:                        child = child.getNext();
0884:                    }
0885:                    itsInTryFlag = savedFlag;
0886:
0887:                    Node catchTarget = tryNode.target;
0888:                    if (catchTarget != null) {
0889:                        int catchStartPC = itsLabelTable[getTargetLabel(catchTarget)];
0890:                        addExceptionHandler(tryStart, catchStartPC,
0891:                                catchStartPC, false, exceptionObjectLocal,
0892:                                scopeLocal);
0893:                    }
0894:                    Node finallyTarget = tryNode.getFinally();
0895:                    if (finallyTarget != null) {
0896:                        int finallyStartPC = itsLabelTable[getTargetLabel(finallyTarget)];
0897:                        addExceptionHandler(tryStart, finallyStartPC,
0898:                                finallyStartPC, true, exceptionObjectLocal,
0899:                                scopeLocal);
0900:                    }
0901:
0902:                    addIndexOp(Icode_LOCAL_CLEAR, scopeLocal);
0903:                    releaseLocal(scopeLocal);
0904:                }
0905:                    break;
0906:
0907:                case Token.CATCH_SCOPE: {
0908:                    int localIndex = getLocalBlockRef(node);
0909:                    int scopeIndex = node
0910:                            .getExistingIntProp(Node.CATCH_SCOPE_PROP);
0911:                    String name = child.getString();
0912:                    child = child.getNext();
0913:                    visitExpression(child, 0); // load expression object
0914:                    addStringPrefix(name);
0915:                    addIndexPrefix(localIndex);
0916:                    addToken(Token.CATCH_SCOPE);
0917:                    addUint8(scopeIndex != 0 ? 1 : 0);
0918:                    stackChange(-1);
0919:                }
0920:                    break;
0921:
0922:                case Token.THROW:
0923:                    updateLineNumber(node);
0924:                    visitExpression(child, 0);
0925:                    addToken(Token.THROW);
0926:                    addUint16(itsLineNumber & 0xFFFF);
0927:                    stackChange(-1);
0928:                    break;
0929:
0930:                case Token.RETHROW:
0931:                    updateLineNumber(node);
0932:                    addIndexOp(Token.RETHROW, getLocalBlockRef(node));
0933:                    break;
0934:
0935:                case Token.RETURN:
0936:                    updateLineNumber(node);
0937:                    if (node.getIntProp(Node.GENERATOR_END_PROP, 0) != 0) {
0938:                        // We're in a generator, so change RETURN to GENERATOR_END
0939:                        addIcode(Icode_GENERATOR_END);
0940:                        addUint16(itsLineNumber & 0xFFFF);
0941:                    } else if (child != null) {
0942:                        visitExpression(child, ECF_TAIL);
0943:                        addToken(Token.RETURN);
0944:                        stackChange(-1);
0945:                    } else {
0946:                        addIcode(Icode_RETUNDEF);
0947:                    }
0948:                    break;
0949:
0950:                case Token.RETURN_RESULT:
0951:                    updateLineNumber(node);
0952:                    addToken(Token.RETURN_RESULT);
0953:                    break;
0954:
0955:                case Token.ENUM_INIT_KEYS:
0956:                case Token.ENUM_INIT_VALUES:
0957:                case Token.ENUM_INIT_ARRAY:
0958:                    visitExpression(child, 0);
0959:                    addIndexOp(type, getLocalBlockRef(node));
0960:                    stackChange(-1);
0961:                    break;
0962:
0963:                case Icode_GENERATOR:
0964:                    break;
0965:
0966:                default:
0967:                    throw badTree(node);
0968:                }
0969:
0970:                if (itsStackDepth != initialStackDepth) {
0971:                    throw Kit.codeBug();
0972:                }
0973:            }
0974:
0975:            private void visitExpression(Node node, int contextFlags) {
0976:                int type = node.getType();
0977:                Node child = node.getFirstChild();
0978:                int savedStackDepth = itsStackDepth;
0979:                switch (type) {
0980:
0981:                case Token.FUNCTION: {
0982:                    int fnIndex = node.getExistingIntProp(Node.FUNCTION_PROP);
0983:                    FunctionNode fn = scriptOrFn.getFunctionNode(fnIndex);
0984:                    // See comments in visitStatement for Token.FUNCTION case
0985:                    if (fn.getFunctionType() != FunctionNode.FUNCTION_EXPRESSION) {
0986:                        throw Kit.codeBug();
0987:                    }
0988:                    addIndexOp(Icode_CLOSURE_EXPR, fnIndex);
0989:                    stackChange(1);
0990:                }
0991:                    break;
0992:
0993:                case Token.LOCAL_LOAD: {
0994:                    int localIndex = getLocalBlockRef(node);
0995:                    addIndexOp(Token.LOCAL_LOAD, localIndex);
0996:                    stackChange(1);
0997:                }
0998:                    break;
0999:
1000:                case Token.COMMA: {
1001:                    Node lastChild = node.getLastChild();
1002:                    while (child != lastChild) {
1003:                        visitExpression(child, 0);
1004:                        addIcode(Icode_POP);
1005:                        stackChange(-1);
1006:                        child = child.getNext();
1007:                    }
1008:                    // Preserve tail context flag if any
1009:                    visitExpression(child, contextFlags & ECF_TAIL);
1010:                }
1011:                    break;
1012:
1013:                case Token.USE_STACK:
1014:                    // Indicates that stack was modified externally,
1015:                    // like placed catch object
1016:                    stackChange(1);
1017:                    break;
1018:
1019:                case Token.REF_CALL:
1020:                case Token.CALL:
1021:                case Token.NEW: {
1022:                    if (type == Token.NEW) {
1023:                        visitExpression(child, 0);
1024:                    } else {
1025:                        generateCallFunAndThis(child);
1026:                    }
1027:                    int argCount = 0;
1028:                    while ((child = child.getNext()) != null) {
1029:                        visitExpression(child, 0);
1030:                        ++argCount;
1031:                    }
1032:                    int callType = node.getIntProp(Node.SPECIALCALL_PROP,
1033:                            Node.NON_SPECIALCALL);
1034:                    if (callType != Node.NON_SPECIALCALL) {
1035:                        // embed line number and source filename
1036:                        addIndexOp(Icode_CALLSPECIAL, argCount);
1037:                        addUint8(callType);
1038:                        addUint8(type == Token.NEW ? 1 : 0);
1039:                        addUint16(itsLineNumber & 0xFFFF);
1040:                    } else {
1041:                        // Only use the tail call optimization if we're not in a try
1042:                        // or we're not generating debug info (since the
1043:                        // optimization will confuse the debugger)
1044:                        if (type == Token.CALL
1045:                                && (contextFlags & ECF_TAIL) != 0
1046:                                && !compilerEnv.isGenerateDebugInfo()
1047:                                && !itsInTryFlag) {
1048:                            type = Icode_TAIL_CALL;
1049:                        }
1050:                        addIndexOp(type, argCount);
1051:                    }
1052:                    // adjust stack
1053:                    if (type == Token.NEW) {
1054:                        // new: f, args -> result
1055:                        stackChange(-argCount);
1056:                    } else {
1057:                        // call: f, thisObj, args -> result
1058:                        // ref_call: f, thisObj, args -> ref
1059:                        stackChange(-1 - argCount);
1060:                    }
1061:                    if (argCount > itsData.itsMaxCalleeArgs) {
1062:                        itsData.itsMaxCalleeArgs = argCount;
1063:                    }
1064:                }
1065:                    break;
1066:
1067:                case Token.AND:
1068:                case Token.OR: {
1069:                    visitExpression(child, 0);
1070:                    addIcode(Icode_DUP);
1071:                    stackChange(1);
1072:                    int afterSecondJumpStart = itsICodeTop;
1073:                    int jump = (type == Token.AND) ? Token.IFNE : Token.IFEQ;
1074:                    addGotoOp(jump);
1075:                    stackChange(-1);
1076:                    addIcode(Icode_POP);
1077:                    stackChange(-1);
1078:                    child = child.getNext();
1079:                    // Preserve tail context flag if any
1080:                    visitExpression(child, contextFlags & ECF_TAIL);
1081:                    resolveForwardGoto(afterSecondJumpStart);
1082:                }
1083:                    break;
1084:
1085:                case Token.HOOK: {
1086:                    Node ifThen = child.getNext();
1087:                    Node ifElse = ifThen.getNext();
1088:                    visitExpression(child, 0);
1089:                    int elseJumpStart = itsICodeTop;
1090:                    addGotoOp(Token.IFNE);
1091:                    stackChange(-1);
1092:                    // Preserve tail context flag if any
1093:                    visitExpression(ifThen, contextFlags & ECF_TAIL);
1094:                    int afterElseJumpStart = itsICodeTop;
1095:                    addGotoOp(Token.GOTO);
1096:                    resolveForwardGoto(elseJumpStart);
1097:                    itsStackDepth = savedStackDepth;
1098:                    // Preserve tail context flag if any
1099:                    visitExpression(ifElse, contextFlags & ECF_TAIL);
1100:                    resolveForwardGoto(afterElseJumpStart);
1101:                }
1102:                    break;
1103:
1104:                case Token.GETPROP:
1105:                case Token.GETPROPNOWARN:
1106:                    visitExpression(child, 0);
1107:                    child = child.getNext();
1108:                    addStringOp(type, child.getString());
1109:                    break;
1110:
1111:                case Token.GETELEM:
1112:                case Token.DELPROP:
1113:                case Token.BITAND:
1114:                case Token.BITOR:
1115:                case Token.BITXOR:
1116:                case Token.LSH:
1117:                case Token.RSH:
1118:                case Token.URSH:
1119:                case Token.ADD:
1120:                case Token.SUB:
1121:                case Token.MOD:
1122:                case Token.DIV:
1123:                case Token.MUL:
1124:                case Token.EQ:
1125:                case Token.NE:
1126:                case Token.SHEQ:
1127:                case Token.SHNE:
1128:                case Token.IN:
1129:                case Token.INSTANCEOF:
1130:                case Token.LE:
1131:                case Token.LT:
1132:                case Token.GE:
1133:                case Token.GT:
1134:                    visitExpression(child, 0);
1135:                    child = child.getNext();
1136:                    visitExpression(child, 0);
1137:                    addToken(type);
1138:                    stackChange(-1);
1139:                    break;
1140:
1141:                case Token.POS:
1142:                case Token.NEG:
1143:                case Token.NOT:
1144:                case Token.BITNOT:
1145:                case Token.TYPEOF:
1146:                case Token.VOID:
1147:                    visitExpression(child, 0);
1148:                    if (type == Token.VOID) {
1149:                        addIcode(Icode_POP);
1150:                        addIcode(Icode_UNDEF);
1151:                    } else {
1152:                        addToken(type);
1153:                    }
1154:                    break;
1155:
1156:                case Token.GET_REF:
1157:                case Token.DEL_REF:
1158:                    visitExpression(child, 0);
1159:                    addToken(type);
1160:                    break;
1161:
1162:                case Token.SETPROP:
1163:                case Token.SETPROP_OP: {
1164:                    visitExpression(child, 0);
1165:                    child = child.getNext();
1166:                    String property = child.getString();
1167:                    child = child.getNext();
1168:                    if (type == Token.SETPROP_OP) {
1169:                        addIcode(Icode_DUP);
1170:                        stackChange(1);
1171:                        addStringOp(Token.GETPROP, property);
1172:                        // Compensate for the following USE_STACK
1173:                        stackChange(-1);
1174:                    }
1175:                    visitExpression(child, 0);
1176:                    addStringOp(Token.SETPROP, property);
1177:                    stackChange(-1);
1178:                }
1179:                    break;
1180:
1181:                case Token.SETELEM:
1182:                case Token.SETELEM_OP:
1183:                    visitExpression(child, 0);
1184:                    child = child.getNext();
1185:                    visitExpression(child, 0);
1186:                    child = child.getNext();
1187:                    if (type == Token.SETELEM_OP) {
1188:                        addIcode(Icode_DUP2);
1189:                        stackChange(2);
1190:                        addToken(Token.GETELEM);
1191:                        stackChange(-1);
1192:                        // Compensate for the following USE_STACK
1193:                        stackChange(-1);
1194:                    }
1195:                    visitExpression(child, 0);
1196:                    addToken(Token.SETELEM);
1197:                    stackChange(-2);
1198:                    break;
1199:
1200:                case Token.SET_REF:
1201:                case Token.SET_REF_OP:
1202:                    visitExpression(child, 0);
1203:                    child = child.getNext();
1204:                    if (type == Token.SET_REF_OP) {
1205:                        addIcode(Icode_DUP);
1206:                        stackChange(1);
1207:                        addToken(Token.GET_REF);
1208:                        // Compensate for the following USE_STACK
1209:                        stackChange(-1);
1210:                    }
1211:                    visitExpression(child, 0);
1212:                    addToken(Token.SET_REF);
1213:                    stackChange(-1);
1214:                    break;
1215:
1216:                case Token.SETNAME: {
1217:                    String name = child.getString();
1218:                    visitExpression(child, 0);
1219:                    child = child.getNext();
1220:                    visitExpression(child, 0);
1221:                    addStringOp(Token.SETNAME, name);
1222:                    stackChange(-1);
1223:                }
1224:                    break;
1225:
1226:                case Token.SETCONST: {
1227:                    String name = child.getString();
1228:                    visitExpression(child, 0);
1229:                    child = child.getNext();
1230:                    visitExpression(child, 0);
1231:                    addStringOp(Icode_SETCONST, name);
1232:                    stackChange(-1);
1233:                }
1234:                    break;
1235:
1236:                case Token.TYPEOFNAME: {
1237:                    int index = -1;
1238:                    // use typeofname if an activation frame exists
1239:                    // since the vars all exist there instead of in jregs
1240:                    if (itsInFunctionFlag && !itsData.itsNeedsActivation)
1241:                        index = scriptOrFn.getIndexForNameNode(node);
1242:                    if (index == -1) {
1243:                        addStringOp(Icode_TYPEOFNAME, node.getString());
1244:                        stackChange(1);
1245:                    } else {
1246:                        addVarOp(Token.GETVAR, index);
1247:                        stackChange(1);
1248:                        addToken(Token.TYPEOF);
1249:                    }
1250:                }
1251:                    break;
1252:
1253:                case Token.BINDNAME:
1254:                case Token.NAME:
1255:                case Token.STRING:
1256:                    addStringOp(type, node.getString());
1257:                    stackChange(1);
1258:                    break;
1259:
1260:                case Token.INC:
1261:                case Token.DEC:
1262:                    visitIncDec(node, child);
1263:                    break;
1264:
1265:                case Token.NUMBER: {
1266:                    double num = node.getDouble();
1267:                    int inum = (int) num;
1268:                    if (inum == num) {
1269:                        if (inum == 0) {
1270:                            addIcode(Icode_ZERO);
1271:                            // Check for negative zero
1272:                            if (1.0 / num < 0.0) {
1273:                                addToken(Token.NEG);
1274:                            }
1275:                        } else if (inum == 1) {
1276:                            addIcode(Icode_ONE);
1277:                        } else if ((short) inum == inum) {
1278:                            addIcode(Icode_SHORTNUMBER);
1279:                            // write short as uin16 bit pattern
1280:                            addUint16(inum & 0xFFFF);
1281:                        } else {
1282:                            addIcode(Icode_INTNUMBER);
1283:                            addInt(inum);
1284:                        }
1285:                    } else {
1286:                        int index = getDoubleIndex(num);
1287:                        addIndexOp(Token.NUMBER, index);
1288:                    }
1289:                    stackChange(1);
1290:                }
1291:                    break;
1292:
1293:                case Token.GETVAR: {
1294:                    if (itsData.itsNeedsActivation)
1295:                        Kit.codeBug();
1296:                    int index = scriptOrFn.getIndexForNameNode(node);
1297:                    addVarOp(Token.GETVAR, index);
1298:                    stackChange(1);
1299:                }
1300:                    break;
1301:
1302:                case Token.SETVAR: {
1303:                    if (itsData.itsNeedsActivation)
1304:                        Kit.codeBug();
1305:                    int index = scriptOrFn.getIndexForNameNode(child);
1306:                    child = child.getNext();
1307:                    visitExpression(child, 0);
1308:                    addVarOp(Token.SETVAR, index);
1309:                }
1310:                    break;
1311:
1312:                case Token.SETCONSTVAR: {
1313:                    if (itsData.itsNeedsActivation)
1314:                        Kit.codeBug();
1315:                    int index = scriptOrFn.getIndexForNameNode(child);
1316:                    child = child.getNext();
1317:                    visitExpression(child, 0);
1318:                    addVarOp(Token.SETCONSTVAR, index);
1319:                }
1320:                    break;
1321:
1322:                case Token.NULL:
1323:                case Token.THIS:
1324:                case Token.THISFN:
1325:                case Token.FALSE:
1326:                case Token.TRUE:
1327:                    addToken(type);
1328:                    stackChange(1);
1329:                    break;
1330:
1331:                case Token.ENUM_NEXT:
1332:                case Token.ENUM_ID:
1333:                    addIndexOp(type, getLocalBlockRef(node));
1334:                    stackChange(1);
1335:                    break;
1336:
1337:                case Token.REGEXP: {
1338:                    int index = node.getExistingIntProp(Node.REGEXP_PROP);
1339:                    addIndexOp(Token.REGEXP, index);
1340:                    stackChange(1);
1341:                }
1342:                    break;
1343:
1344:                case Token.ARRAYLIT:
1345:                case Token.OBJECTLIT:
1346:                    visitLiteral(node, child);
1347:                    break;
1348:
1349:                case Token.ARRAYCOMP:
1350:                    visitArrayComprehension(node, child, child.getNext());
1351:                    break;
1352:
1353:                case Token.REF_SPECIAL:
1354:                    visitExpression(child, 0);
1355:                    addStringOp(type, (String) node.getProp(Node.NAME_PROP));
1356:                    break;
1357:
1358:                case Token.REF_MEMBER:
1359:                case Token.REF_NS_MEMBER:
1360:                case Token.REF_NAME:
1361:                case Token.REF_NS_NAME: {
1362:                    int memberTypeFlags = node.getIntProp(
1363:                            Node.MEMBER_TYPE_PROP, 0);
1364:                    // generate possible target, possible namespace and member
1365:                    int childCount = 0;
1366:                    do {
1367:                        visitExpression(child, 0);
1368:                        ++childCount;
1369:                        child = child.getNext();
1370:                    } while (child != null);
1371:                    addIndexOp(type, memberTypeFlags);
1372:                    stackChange(1 - childCount);
1373:                }
1374:                    break;
1375:
1376:                case Token.DOTQUERY: {
1377:                    int queryPC;
1378:                    updateLineNumber(node);
1379:                    visitExpression(child, 0);
1380:                    addIcode(Icode_ENTERDQ);
1381:                    stackChange(-1);
1382:                    queryPC = itsICodeTop;
1383:                    visitExpression(child.getNext(), 0);
1384:                    addBackwardGoto(Icode_LEAVEDQ, queryPC);
1385:                }
1386:                    break;
1387:
1388:                case Token.DEFAULTNAMESPACE:
1389:                case Token.ESCXMLATTR:
1390:                case Token.ESCXMLTEXT:
1391:                    visitExpression(child, 0);
1392:                    addToken(type);
1393:                    break;
1394:
1395:                case Token.YIELD:
1396:                    if (child != null) {
1397:                        visitExpression(child, 0);
1398:                    } else {
1399:                        addIcode(Icode_UNDEF);
1400:                        stackChange(1);
1401:                    }
1402:                    addToken(Token.YIELD);
1403:                    addUint16(node.getLineno() & 0xFFFF);
1404:                    break;
1405:
1406:                case Token.WITHEXPR: {
1407:                    Node enterWith = node.getFirstChild();
1408:                    Node with = enterWith.getNext();
1409:                    visitExpression(enterWith.getFirstChild(), 0);
1410:                    addToken(Token.ENTERWITH);
1411:                    stackChange(-1);
1412:                    visitExpression(with.getFirstChild(), 0);
1413:                    addToken(Token.LEAVEWITH);
1414:                    break;
1415:                }
1416:
1417:                default:
1418:                    throw badTree(node);
1419:                }
1420:                if (savedStackDepth + 1 != itsStackDepth) {
1421:                    Kit.codeBug();
1422:                }
1423:            }
1424:
1425:            private void generateCallFunAndThis(Node left) {
1426:                // Generate code to place on stack function and thisObj
1427:                int type = left.getType();
1428:                switch (type) {
1429:                case Token.NAME: {
1430:                    String name = left.getString();
1431:                    // stack: ... -> ... function thisObj
1432:                    addStringOp(Icode_NAME_AND_THIS, name);
1433:                    stackChange(2);
1434:                    break;
1435:                }
1436:                case Token.GETPROP:
1437:                case Token.GETELEM: {
1438:                    Node target = left.getFirstChild();
1439:                    visitExpression(target, 0);
1440:                    Node id = target.getNext();
1441:                    if (type == Token.GETPROP) {
1442:                        String property = id.getString();
1443:                        // stack: ... target -> ... function thisObj
1444:                        addStringOp(Icode_PROP_AND_THIS, property);
1445:                        stackChange(1);
1446:                    } else {
1447:                        visitExpression(id, 0);
1448:                        // stack: ... target id -> ... function thisObj
1449:                        addIcode(Icode_ELEM_AND_THIS);
1450:                    }
1451:                    break;
1452:                }
1453:                default:
1454:                    // Including Token.GETVAR
1455:                    visitExpression(left, 0);
1456:                    // stack: ... value -> ... function thisObj
1457:                    addIcode(Icode_VALUE_AND_THIS);
1458:                    stackChange(1);
1459:                    break;
1460:                }
1461:            }
1462:
1463:            private void visitIncDec(Node node, Node child) {
1464:                int incrDecrMask = node.getExistingIntProp(Node.INCRDECR_PROP);
1465:                int childType = child.getType();
1466:                switch (childType) {
1467:                case Token.GETVAR: {
1468:                    if (itsData.itsNeedsActivation)
1469:                        Kit.codeBug();
1470:                    int i = scriptOrFn.getIndexForNameNode(child);
1471:                    addVarOp(Icode_VAR_INC_DEC, i);
1472:                    addUint8(incrDecrMask);
1473:                    stackChange(1);
1474:                    break;
1475:                }
1476:                case Token.NAME: {
1477:                    String name = child.getString();
1478:                    addStringOp(Icode_NAME_INC_DEC, name);
1479:                    addUint8(incrDecrMask);
1480:                    stackChange(1);
1481:                    break;
1482:                }
1483:                case Token.GETPROP: {
1484:                    Node object = child.getFirstChild();
1485:                    visitExpression(object, 0);
1486:                    String property = object.getNext().getString();
1487:                    addStringOp(Icode_PROP_INC_DEC, property);
1488:                    addUint8(incrDecrMask);
1489:                    break;
1490:                }
1491:                case Token.GETELEM: {
1492:                    Node object = child.getFirstChild();
1493:                    visitExpression(object, 0);
1494:                    Node index = object.getNext();
1495:                    visitExpression(index, 0);
1496:                    addIcode(Icode_ELEM_INC_DEC);
1497:                    addUint8(incrDecrMask);
1498:                    stackChange(-1);
1499:                    break;
1500:                }
1501:                case Token.GET_REF: {
1502:                    Node ref = child.getFirstChild();
1503:                    visitExpression(ref, 0);
1504:                    addIcode(Icode_REF_INC_DEC);
1505:                    addUint8(incrDecrMask);
1506:                    break;
1507:                }
1508:                default: {
1509:                    throw badTree(node);
1510:                }
1511:                }
1512:            }
1513:
1514:            private void visitLiteral(Node node, Node child) {
1515:                int type = node.getType();
1516:                int count;
1517:                Object[] propertyIds = null;
1518:                if (type == Token.ARRAYLIT) {
1519:                    count = 0;
1520:                    for (Node n = child; n != null; n = n.getNext()) {
1521:                        ++count;
1522:                    }
1523:                } else if (type == Token.OBJECTLIT) {
1524:                    propertyIds = (Object[]) node.getProp(Node.OBJECT_IDS_PROP);
1525:                    count = propertyIds.length;
1526:                } else {
1527:                    throw badTree(node);
1528:                }
1529:                addIndexOp(Icode_LITERAL_NEW, count);
1530:                stackChange(2);
1531:                while (child != null) {
1532:                    int childType = child.getType();
1533:                    if (childType == Token.GET) {
1534:                        visitExpression(child.getFirstChild(), 0);
1535:                        addIcode(Icode_LITERAL_GETTER);
1536:                    } else if (childType == Token.SET) {
1537:                        visitExpression(child.getFirstChild(), 0);
1538:                        addIcode(Icode_LITERAL_SETTER);
1539:                    } else {
1540:                        visitExpression(child, 0);
1541:                        addIcode(Icode_LITERAL_SET);
1542:                    }
1543:                    stackChange(-1);
1544:                    child = child.getNext();
1545:                }
1546:                if (type == Token.ARRAYLIT) {
1547:                    int[] skipIndexes = (int[]) node
1548:                            .getProp(Node.SKIP_INDEXES_PROP);
1549:                    if (skipIndexes == null) {
1550:                        addToken(Token.ARRAYLIT);
1551:                    } else {
1552:                        int index = itsLiteralIds.size();
1553:                        itsLiteralIds.add(skipIndexes);
1554:                        addIndexOp(Icode_SPARE_ARRAYLIT, index);
1555:                    }
1556:                } else {
1557:                    int index = itsLiteralIds.size();
1558:                    itsLiteralIds.add(propertyIds);
1559:                    addIndexOp(Token.OBJECTLIT, index);
1560:                }
1561:                stackChange(-1);
1562:            }
1563:
1564:            private void visitArrayComprehension(Node node, Node initStmt,
1565:                    Node expr) {
1566:                // A bit of a hack: array comprehensions are implemented using
1567:                // statement nodes for the iteration, yet they appear in an
1568:                // expression context. So we pass the current stack depth to
1569:                // visitStatement so it can check that the depth is not altered
1570:                // by statements.
1571:                visitStatement(initStmt, itsStackDepth);
1572:                visitExpression(expr, 0);
1573:            }
1574:
1575:            private int getLocalBlockRef(Node node) {
1576:                Node localBlock = (Node) node.getProp(Node.LOCAL_BLOCK_PROP);
1577:                return localBlock.getExistingIntProp(Node.LOCAL_PROP);
1578:            }
1579:
1580:            private int getTargetLabel(Node target) {
1581:                int label = target.labelId();
1582:                if (label != -1) {
1583:                    return label;
1584:                }
1585:                label = itsLabelTableTop;
1586:                if (itsLabelTable == null || label == itsLabelTable.length) {
1587:                    if (itsLabelTable == null) {
1588:                        itsLabelTable = new int[MIN_LABEL_TABLE_SIZE];
1589:                    } else {
1590:                        int[] tmp = new int[itsLabelTable.length * 2];
1591:                        System.arraycopy(itsLabelTable, 0, tmp, 0, label);
1592:                        itsLabelTable = tmp;
1593:                    }
1594:                }
1595:                itsLabelTableTop = label + 1;
1596:                itsLabelTable[label] = -1;
1597:
1598:                target.labelId(label);
1599:                return label;
1600:            }
1601:
1602:            private void markTargetLabel(Node target) {
1603:                int label = getTargetLabel(target);
1604:                if (itsLabelTable[label] != -1) {
1605:                    // Can mark label only once
1606:                    Kit.codeBug();
1607:                }
1608:                itsLabelTable[label] = itsICodeTop;
1609:            }
1610:
1611:            private void addGoto(Node target, int gotoOp) {
1612:                int label = getTargetLabel(target);
1613:                if (!(label < itsLabelTableTop))
1614:                    Kit.codeBug();
1615:                int targetPC = itsLabelTable[label];
1616:
1617:                if (targetPC != -1) {
1618:                    addBackwardGoto(gotoOp, targetPC);
1619:                } else {
1620:                    int gotoPC = itsICodeTop;
1621:                    addGotoOp(gotoOp);
1622:                    int top = itsFixupTableTop;
1623:                    if (itsFixupTable == null || top == itsFixupTable.length) {
1624:                        if (itsFixupTable == null) {
1625:                            itsFixupTable = new long[MIN_FIXUP_TABLE_SIZE];
1626:                        } else {
1627:                            long[] tmp = new long[itsFixupTable.length * 2];
1628:                            System.arraycopy(itsFixupTable, 0, tmp, 0, top);
1629:                            itsFixupTable = tmp;
1630:                        }
1631:                    }
1632:                    itsFixupTableTop = top + 1;
1633:                    itsFixupTable[top] = ((long) label << 32) | gotoPC;
1634:                }
1635:            }
1636:
1637:            private void fixLabelGotos() {
1638:                for (int i = 0; i < itsFixupTableTop; i++) {
1639:                    long fixup = itsFixupTable[i];
1640:                    int label = (int) (fixup >> 32);
1641:                    int jumpSource = (int) fixup;
1642:                    int pc = itsLabelTable[label];
1643:                    if (pc == -1) {
1644:                        // Unlocated label
1645:                        throw Kit.codeBug();
1646:                    }
1647:                    resolveGoto(jumpSource, pc);
1648:                }
1649:                itsFixupTableTop = 0;
1650:            }
1651:
1652:            private void addBackwardGoto(int gotoOp, int jumpPC) {
1653:                int fromPC = itsICodeTop;
1654:                // Ensure that this is a jump backward
1655:                if (fromPC <= jumpPC)
1656:                    throw Kit.codeBug();
1657:                addGotoOp(gotoOp);
1658:                resolveGoto(fromPC, jumpPC);
1659:            }
1660:
1661:            private void resolveForwardGoto(int fromPC) {
1662:                // Ensure that forward jump skips at least self bytecode
1663:                if (itsICodeTop < fromPC + 3)
1664:                    throw Kit.codeBug();
1665:                resolveGoto(fromPC, itsICodeTop);
1666:            }
1667:
1668:            private void resolveGoto(int fromPC, int jumpPC) {
1669:                int offset = jumpPC - fromPC;
1670:                // Ensure that jumps do not overlap
1671:                if (0 <= offset && offset <= 2)
1672:                    throw Kit.codeBug();
1673:                int offsetSite = fromPC + 1;
1674:                if (offset != (short) offset) {
1675:                    if (itsData.longJumps == null) {
1676:                        itsData.longJumps = new UintMap();
1677:                    }
1678:                    itsData.longJumps.put(offsetSite, jumpPC);
1679:                    offset = 0;
1680:                }
1681:                byte[] array = itsData.itsICode;
1682:                array[offsetSite] = (byte) (offset >> 8);
1683:                array[offsetSite + 1] = (byte) offset;
1684:            }
1685:
1686:            private void addToken(int token) {
1687:                if (!validTokenCode(token))
1688:                    throw Kit.codeBug();
1689:                addUint8(token);
1690:            }
1691:
1692:            private void addIcode(int icode) {
1693:                if (!validIcode(icode))
1694:                    throw Kit.codeBug();
1695:                // Write negative icode as uint8 bits
1696:                addUint8(icode & 0xFF);
1697:            }
1698:
1699:            private void addUint8(int value) {
1700:                if ((value & ~0xFF) != 0)
1701:                    throw Kit.codeBug();
1702:                byte[] array = itsData.itsICode;
1703:                int top = itsICodeTop;
1704:                if (top == array.length) {
1705:                    array = increaseICodeCapacity(1);
1706:                }
1707:                array[top] = (byte) value;
1708:                itsICodeTop = top + 1;
1709:            }
1710:
1711:            private void addUint16(int value) {
1712:                if ((value & ~0xFFFF) != 0)
1713:                    throw Kit.codeBug();
1714:                byte[] array = itsData.itsICode;
1715:                int top = itsICodeTop;
1716:                if (top + 2 > array.length) {
1717:                    array = increaseICodeCapacity(2);
1718:                }
1719:                array[top] = (byte) (value >>> 8);
1720:                array[top + 1] = (byte) value;
1721:                itsICodeTop = top + 2;
1722:            }
1723:
1724:            private void addInt(int i) {
1725:                byte[] array = itsData.itsICode;
1726:                int top = itsICodeTop;
1727:                if (top + 4 > array.length) {
1728:                    array = increaseICodeCapacity(4);
1729:                }
1730:                array[top] = (byte) (i >>> 24);
1731:                array[top + 1] = (byte) (i >>> 16);
1732:                array[top + 2] = (byte) (i >>> 8);
1733:                array[top + 3] = (byte) i;
1734:                itsICodeTop = top + 4;
1735:            }
1736:
1737:            private int getDoubleIndex(double num) {
1738:                int index = itsDoubleTableTop;
1739:                if (index == 0) {
1740:                    itsData.itsDoubleTable = new double[64];
1741:                } else if (itsData.itsDoubleTable.length == index) {
1742:                    double[] na = new double[index * 2];
1743:                    System.arraycopy(itsData.itsDoubleTable, 0, na, 0, index);
1744:                    itsData.itsDoubleTable = na;
1745:                }
1746:                itsData.itsDoubleTable[index] = num;
1747:                itsDoubleTableTop = index + 1;
1748:                return index;
1749:            }
1750:
1751:            private void addGotoOp(int gotoOp) {
1752:                byte[] array = itsData.itsICode;
1753:                int top = itsICodeTop;
1754:                if (top + 3 > array.length) {
1755:                    array = increaseICodeCapacity(3);
1756:                }
1757:                array[top] = (byte) gotoOp;
1758:                // Offset would written later
1759:                itsICodeTop = top + 1 + 2;
1760:            }
1761:
1762:            private void addVarOp(int op, int varIndex) {
1763:                switch (op) {
1764:                case Token.SETCONSTVAR:
1765:                    if (varIndex < 128) {
1766:                        addIcode(Icode_SETCONSTVAR1);
1767:                        addUint8(varIndex);
1768:                        return;
1769:                    }
1770:                    addIndexOp(Icode_SETCONSTVAR, varIndex);
1771:                    return;
1772:                case Token.GETVAR:
1773:                case Token.SETVAR:
1774:                    if (varIndex < 128) {
1775:                        addIcode(op == Token.GETVAR ? Icode_GETVAR1
1776:                                : Icode_SETVAR1);
1777:                        addUint8(varIndex);
1778:                        return;
1779:                    }
1780:                    // fallthrough
1781:                case Icode_VAR_INC_DEC:
1782:                    addIndexOp(op, varIndex);
1783:                    return;
1784:                }
1785:                throw Kit.codeBug();
1786:            }
1787:
1788:            private void addStringOp(int op, String str) {
1789:                addStringPrefix(str);
1790:                if (validIcode(op)) {
1791:                    addIcode(op);
1792:                } else {
1793:                    addToken(op);
1794:                }
1795:            }
1796:
1797:            private void addIndexOp(int op, int index) {
1798:                addIndexPrefix(index);
1799:                if (validIcode(op)) {
1800:                    addIcode(op);
1801:                } else {
1802:                    addToken(op);
1803:                }
1804:            }
1805:
1806:            private void addStringPrefix(String str) {
1807:                int index = itsStrings.get(str, -1);
1808:                if (index == -1) {
1809:                    index = itsStrings.size();
1810:                    itsStrings.put(str, index);
1811:                }
1812:                if (index < 4) {
1813:                    addIcode(Icode_REG_STR_C0 - index);
1814:                } else if (index <= 0xFF) {
1815:                    addIcode(Icode_REG_STR1);
1816:                    addUint8(index);
1817:                } else if (index <= 0xFFFF) {
1818:                    addIcode(Icode_REG_STR2);
1819:                    addUint16(index);
1820:                } else {
1821:                    addIcode(Icode_REG_STR4);
1822:                    addInt(index);
1823:                }
1824:            }
1825:
1826:            private void addIndexPrefix(int index) {
1827:                if (index < 0)
1828:                    Kit.codeBug();
1829:                if (index < 6) {
1830:                    addIcode(Icode_REG_IND_C0 - index);
1831:                } else if (index <= 0xFF) {
1832:                    addIcode(Icode_REG_IND1);
1833:                    addUint8(index);
1834:                } else if (index <= 0xFFFF) {
1835:                    addIcode(Icode_REG_IND2);
1836:                    addUint16(index);
1837:                } else {
1838:                    addIcode(Icode_REG_IND4);
1839:                    addInt(index);
1840:                }
1841:            }
1842:
1843:            private void addExceptionHandler(int icodeStart, int icodeEnd,
1844:                    int handlerStart, boolean isFinally,
1845:                    int exceptionObjectLocal, int scopeLocal) {
1846:                int top = itsExceptionTableTop;
1847:                int[] table = itsData.itsExceptionTable;
1848:                if (table == null) {
1849:                    if (top != 0)
1850:                        Kit.codeBug();
1851:                    table = new int[EXCEPTION_SLOT_SIZE * 2];
1852:                    itsData.itsExceptionTable = table;
1853:                } else if (table.length == top) {
1854:                    table = new int[table.length * 2];
1855:                    System.arraycopy(itsData.itsExceptionTable, 0, table, 0,
1856:                            top);
1857:                    itsData.itsExceptionTable = table;
1858:                }
1859:                table[top + EXCEPTION_TRY_START_SLOT] = icodeStart;
1860:                table[top + EXCEPTION_TRY_END_SLOT] = icodeEnd;
1861:                table[top + EXCEPTION_HANDLER_SLOT] = handlerStart;
1862:                table[top + EXCEPTION_TYPE_SLOT] = isFinally ? 1 : 0;
1863:                table[top + EXCEPTION_LOCAL_SLOT] = exceptionObjectLocal;
1864:                table[top + EXCEPTION_SCOPE_SLOT] = scopeLocal;
1865:
1866:                itsExceptionTableTop = top + EXCEPTION_SLOT_SIZE;
1867:            }
1868:
1869:            private byte[] increaseICodeCapacity(int extraSize) {
1870:                int capacity = itsData.itsICode.length;
1871:                int top = itsICodeTop;
1872:                if (top + extraSize <= capacity)
1873:                    throw Kit.codeBug();
1874:                capacity *= 2;
1875:                if (top + extraSize > capacity) {
1876:                    capacity = top + extraSize;
1877:                }
1878:                byte[] array = new byte[capacity];
1879:                System.arraycopy(itsData.itsICode, 0, array, 0, top);
1880:                itsData.itsICode = array;
1881:                return array;
1882:            }
1883:
1884:            private void stackChange(int change) {
1885:                if (change <= 0) {
1886:                    itsStackDepth += change;
1887:                } else {
1888:                    int newDepth = itsStackDepth + change;
1889:                    if (newDepth > itsData.itsMaxStack) {
1890:                        itsData.itsMaxStack = newDepth;
1891:                    }
1892:                    itsStackDepth = newDepth;
1893:                }
1894:            }
1895:
1896:            private int allocLocal() {
1897:                int localSlot = itsLocalTop;
1898:                ++itsLocalTop;
1899:                if (itsLocalTop > itsData.itsMaxLocals) {
1900:                    itsData.itsMaxLocals = itsLocalTop;
1901:                }
1902:                return localSlot;
1903:            }
1904:
1905:            private void releaseLocal(int localSlot) {
1906:                --itsLocalTop;
1907:                if (localSlot != itsLocalTop)
1908:                    Kit.codeBug();
1909:            }
1910:
1911:            private static int getShort(byte[] iCode, int pc) {
1912:                return (iCode[pc] << 8) | (iCode[pc + 1] & 0xFF);
1913:            }
1914:
1915:            private static int getIndex(byte[] iCode, int pc) {
1916:                return ((iCode[pc] & 0xFF) << 8) | (iCode[pc + 1] & 0xFF);
1917:            }
1918:
1919:            private static int getInt(byte[] iCode, int pc) {
1920:                return (iCode[pc] << 24) | ((iCode[pc + 1] & 0xFF) << 16)
1921:                        | ((iCode[pc + 2] & 0xFF) << 8)
1922:                        | (iCode[pc + 3] & 0xFF);
1923:            }
1924:
1925:            private static int getExceptionHandler(CallFrame frame,
1926:                    boolean onlyFinally) {
1927:                int[] exceptionTable = frame.idata.itsExceptionTable;
1928:                if (exceptionTable == null) {
1929:                    // No exception handlers
1930:                    return -1;
1931:                }
1932:
1933:                // Icode switch in the interpreter increments PC immediately
1934:                // and it is necessary to subtract 1 from the saved PC
1935:                // to point it before the start of the next instruction.
1936:                int pc = frame.pc - 1;
1937:
1938:                // OPT: use binary search
1939:                int best = -1, bestStart = 0, bestEnd = 0;
1940:                for (int i = 0; i != exceptionTable.length; i += EXCEPTION_SLOT_SIZE) {
1941:                    int start = exceptionTable[i + EXCEPTION_TRY_START_SLOT];
1942:                    int end = exceptionTable[i + EXCEPTION_TRY_END_SLOT];
1943:                    if (!(start <= pc && pc < end)) {
1944:                        continue;
1945:                    }
1946:                    if (onlyFinally
1947:                            && exceptionTable[i + EXCEPTION_TYPE_SLOT] != 1) {
1948:                        continue;
1949:                    }
1950:                    if (best >= 0) {
1951:                        // Since handlers always nest and they never have shared end
1952:                        // although they can share start  it is sufficient to compare
1953:                        // handlers ends
1954:                        if (bestEnd < end) {
1955:                            continue;
1956:                        }
1957:                        // Check the above assumption
1958:                        if (bestStart > start)
1959:                            Kit.codeBug(); // should be nested
1960:                        if (bestEnd == end)
1961:                            Kit.codeBug(); // no ens sharing
1962:                    }
1963:                    best = i;
1964:                    bestStart = start;
1965:                    bestEnd = end;
1966:                }
1967:                return best;
1968:            }
1969:
1970:            private static void dumpICode(InterpreterData idata) {
1971:                if (!Token.printICode) {
1972:                    return;
1973:                }
1974:
1975:                byte iCode[] = idata.itsICode;
1976:                int iCodeLength = iCode.length;
1977:                String[] strings = idata.itsStringTable;
1978:                PrintStream out = System.out;
1979:                out.println("ICode dump, for " + idata.itsName + ", length = "
1980:                        + iCodeLength);
1981:                out.println("MaxStack = " + idata.itsMaxStack);
1982:
1983:                int indexReg = 0;
1984:                for (int pc = 0; pc < iCodeLength;) {
1985:                    out.flush();
1986:                    out.print(" [" + pc + "] ");
1987:                    int token = iCode[pc];
1988:                    int icodeLength = bytecodeSpan(token);
1989:                    String tname = bytecodeName(token);
1990:                    int old_pc = pc;
1991:                    ++pc;
1992:                    switch (token) {
1993:                    default:
1994:                        if (icodeLength != 1)
1995:                            Kit.codeBug();
1996:                        out.println(tname);
1997:                        break;
1998:
1999:                    case Icode_GOSUB:
2000:                    case Token.GOTO:
2001:                    case Token.IFEQ:
2002:                    case Token.IFNE:
2003:                    case Icode_IFEQ_POP:
2004:                    case Icode_LEAVEDQ: {
2005:                        int newPC = pc + getShort(iCode, pc) - 1;
2006:                        out.println(tname + " " + newPC);
2007:                        pc += 2;
2008:                        break;
2009:                    }
2010:                    case Icode_VAR_INC_DEC:
2011:                    case Icode_NAME_INC_DEC:
2012:                    case Icode_PROP_INC_DEC:
2013:                    case Icode_ELEM_INC_DEC:
2014:                    case Icode_REF_INC_DEC: {
2015:                        int incrDecrType = iCode[pc];
2016:                        out.println(tname + " " + incrDecrType);
2017:                        ++pc;
2018:                        break;
2019:                    }
2020:
2021:                    case Icode_CALLSPECIAL: {
2022:                        int callType = iCode[pc] & 0xFF;
2023:                        boolean isNew = (iCode[pc + 1] != 0);
2024:                        int line = getIndex(iCode, pc + 2);
2025:                        out.println(tname + " " + callType + " " + isNew + " "
2026:                                + indexReg + " " + line);
2027:                        pc += 4;
2028:                        break;
2029:                    }
2030:
2031:                    case Token.CATCH_SCOPE: {
2032:                        boolean afterFisrtFlag = (iCode[pc] != 0);
2033:                        out.println(tname + " " + afterFisrtFlag);
2034:                        ++pc;
2035:                    }
2036:                        break;
2037:                    case Token.REGEXP:
2038:                        out.println(tname + " "
2039:                                + idata.itsRegExpLiterals[indexReg]);
2040:                        break;
2041:                    case Token.OBJECTLIT:
2042:                    case Icode_SPARE_ARRAYLIT:
2043:                        out.println(tname + " " + idata.literalIds[indexReg]);
2044:                        break;
2045:                    case Icode_CLOSURE_EXPR:
2046:                    case Icode_CLOSURE_STMT:
2047:                        out.println(tname + " "
2048:                                + idata.itsNestedFunctions[indexReg]);
2049:                        break;
2050:                    case Token.CALL:
2051:                    case Icode_TAIL_CALL:
2052:                    case Token.REF_CALL:
2053:                    case Token.NEW:
2054:                        out.println(tname + ' ' + indexReg);
2055:                        break;
2056:                    case Token.THROW:
2057:                    case Token.YIELD:
2058:                    case Icode_GENERATOR:
2059:                    case Icode_GENERATOR_END: {
2060:                        int line = getIndex(iCode, pc);
2061:                        out.println(tname + " : " + line);
2062:                        pc += 2;
2063:                        break;
2064:                    }
2065:                    case Icode_SHORTNUMBER: {
2066:                        int value = getShort(iCode, pc);
2067:                        out.println(tname + " " + value);
2068:                        pc += 2;
2069:                        break;
2070:                    }
2071:                    case Icode_INTNUMBER: {
2072:                        int value = getInt(iCode, pc);
2073:                        out.println(tname + " " + value);
2074:                        pc += 4;
2075:                        break;
2076:                    }
2077:                    case Token.NUMBER: {
2078:                        double value = idata.itsDoubleTable[indexReg];
2079:                        out.println(tname + " " + value);
2080:                        break;
2081:                    }
2082:                    case Icode_LINE: {
2083:                        int line = getIndex(iCode, pc);
2084:                        out.println(tname + " : " + line);
2085:                        pc += 2;
2086:                        break;
2087:                    }
2088:                    case Icode_REG_STR1: {
2089:                        String str = strings[0xFF & iCode[pc]];
2090:                        out.println(tname + " \"" + str + '"');
2091:                        ++pc;
2092:                        break;
2093:                    }
2094:                    case Icode_REG_STR2: {
2095:                        String str = strings[getIndex(iCode, pc)];
2096:                        out.println(tname + " \"" + str + '"');
2097:                        pc += 2;
2098:                        break;
2099:                    }
2100:                    case Icode_REG_STR4: {
2101:                        String str = strings[getInt(iCode, pc)];
2102:                        out.println(tname + " \"" + str + '"');
2103:                        pc += 4;
2104:                        break;
2105:                    }
2106:                    case Icode_REG_IND_C0:
2107:                        indexReg = 0;
2108:                        out.println(tname);
2109:                        break;
2110:                    case Icode_REG_IND_C1:
2111:                        indexReg = 1;
2112:                        out.println(tname);
2113:                        break;
2114:                    case Icode_REG_IND_C2:
2115:                        indexReg = 2;
2116:                        out.println(tname);
2117:                        break;
2118:                    case Icode_REG_IND_C3:
2119:                        indexReg = 3;
2120:                        out.println(tname);
2121:                        break;
2122:                    case Icode_REG_IND_C4:
2123:                        indexReg = 4;
2124:                        out.println(tname);
2125:                        break;
2126:                    case Icode_REG_IND_C5:
2127:                        indexReg = 5;
2128:                        out.println(tname);
2129:                        break;
2130:                    case Icode_REG_IND1: {
2131:                        indexReg = 0xFF & iCode[pc];
2132:                        out.println(tname + " " + indexReg);
2133:                        ++pc;
2134:                        break;
2135:                    }
2136:                    case Icode_REG_IND2: {
2137:                        indexReg = getIndex(iCode, pc);
2138:                        out.println(tname + " " + indexReg);
2139:                        pc += 2;
2140:                        break;
2141:                    }
2142:                    case Icode_REG_IND4: {
2143:                        indexReg = getInt(iCode, pc);
2144:                        out.println(tname + " " + indexReg);
2145:                        pc += 4;
2146:                        break;
2147:                    }
2148:                    case Icode_GETVAR1:
2149:                    case Icode_SETVAR1:
2150:                    case Icode_SETCONSTVAR1:
2151:                        indexReg = iCode[pc];
2152:                        out.println(tname + " " + indexReg);
2153:                        ++pc;
2154:                        break;
2155:                    }
2156:                    if (old_pc + icodeLength != pc)
2157:                        Kit.codeBug();
2158:                }
2159:
2160:                int[] table = idata.itsExceptionTable;
2161:                if (table != null) {
2162:                    out.println("Exception handlers: " + table.length
2163:                            / EXCEPTION_SLOT_SIZE);
2164:                    for (int i = 0; i != table.length; i += EXCEPTION_SLOT_SIZE) {
2165:                        int tryStart = table[i + EXCEPTION_TRY_START_SLOT];
2166:                        int tryEnd = table[i + EXCEPTION_TRY_END_SLOT];
2167:                        int handlerStart = table[i + EXCEPTION_HANDLER_SLOT];
2168:                        int type = table[i + EXCEPTION_TYPE_SLOT];
2169:                        int exceptionLocal = table[i + EXCEPTION_LOCAL_SLOT];
2170:                        int scopeLocal = table[i + EXCEPTION_SCOPE_SLOT];
2171:
2172:                        out.println(" tryStart=" + tryStart + " tryEnd="
2173:                                + tryEnd + " handlerStart=" + handlerStart
2174:                                + " type=" + (type == 0 ? "catch" : "finally")
2175:                                + " exceptionLocal=" + exceptionLocal);
2176:                    }
2177:                }
2178:                out.flush();
2179:            }
2180:
2181:            private static int bytecodeSpan(int bytecode) {
2182:                switch (bytecode) {
2183:                case Token.THROW:
2184:                case Token.YIELD:
2185:                case Icode_GENERATOR:
2186:                case Icode_GENERATOR_END:
2187:                    // source line
2188:                    return 1 + 2;
2189:
2190:                case Icode_GOSUB:
2191:                case Token.GOTO:
2192:                case Token.IFEQ:
2193:                case Token.IFNE:
2194:                case Icode_IFEQ_POP:
2195:                case Icode_LEAVEDQ:
2196:                    // target pc offset
2197:                    return 1 + 2;
2198:
2199:                case Icode_CALLSPECIAL:
2200:                    // call type
2201:                    // is new
2202:                    // line number
2203:                    return 1 + 1 + 1 + 2;
2204:
2205:                case Token.CATCH_SCOPE:
2206:                    // scope flag
2207:                    return 1 + 1;
2208:
2209:                case Icode_VAR_INC_DEC:
2210:                case Icode_NAME_INC_DEC:
2211:                case Icode_PROP_INC_DEC:
2212:                case Icode_ELEM_INC_DEC:
2213:                case Icode_REF_INC_DEC:
2214:                    // type of ++/--
2215:                    return 1 + 1;
2216:
2217:                case Icode_SHORTNUMBER:
2218:                    // short number
2219:                    return 1 + 2;
2220:
2221:                case Icode_INTNUMBER:
2222:                    // int number
2223:                    return 1 + 4;
2224:
2225:                case Icode_REG_IND1:
2226:                    // ubyte index
2227:                    return 1 + 1;
2228:
2229:                case Icode_REG_IND2:
2230:                    // ushort index
2231:                    return 1 + 2;
2232:
2233:                case Icode_REG_IND4:
2234:                    // int index
2235:                    return 1 + 4;
2236:
2237:                case Icode_REG_STR1:
2238:                    // ubyte string index
2239:                    return 1 + 1;
2240:
2241:                case Icode_REG_STR2:
2242:                    // ushort string index
2243:                    return 1 + 2;
2244:
2245:                case Icode_REG_STR4:
2246:                    // int string index
2247:                    return 1 + 4;
2248:
2249:                case Icode_GETVAR1:
2250:                case Icode_SETVAR1:
2251:                case Icode_SETCONSTVAR1:
2252:                    // byte var index
2253:                    return 1 + 1;
2254:
2255:                case Icode_LINE:
2256:                    // line number
2257:                    return 1 + 2;
2258:                }
2259:                if (!validBytecode(bytecode))
2260:                    throw Kit.codeBug();
2261:                return 1;
2262:            }
2263:
2264:            static int[] getLineNumbers(InterpreterData data) {
2265:                UintMap presentLines = new UintMap();
2266:
2267:                byte[] iCode = data.itsICode;
2268:                int iCodeLength = iCode.length;
2269:                for (int pc = 0; pc != iCodeLength;) {
2270:                    int bytecode = iCode[pc];
2271:                    int span = bytecodeSpan(bytecode);
2272:                    if (bytecode == Icode_LINE) {
2273:                        if (span != 3)
2274:                            Kit.codeBug();
2275:                        int line = getIndex(iCode, pc + 1);
2276:                        presentLines.put(line, 0);
2277:                    }
2278:                    pc += span;
2279:                }
2280:
2281:                return presentLines.getKeys();
2282:            }
2283:
2284:            public void captureStackInfo(RhinoException ex) {
2285:                Context cx = Context.getCurrentContext();
2286:                if (cx == null || cx.lastInterpreterFrame == null) {
2287:                    // No interpreter invocations
2288:                    ex.interpreterStackInfo = null;
2289:                    ex.interpreterLineData = null;
2290:                    return;
2291:                }
2292:                // has interpreter frame on the stack
2293:                CallFrame[] array;
2294:                if (cx.previousInterpreterInvocations == null
2295:                        || cx.previousInterpreterInvocations.size() == 0) {
2296:                    array = new CallFrame[1];
2297:                } else {
2298:                    int previousCount = cx.previousInterpreterInvocations
2299:                            .size();
2300:                    if (cx.previousInterpreterInvocations.peek() == cx.lastInterpreterFrame) {
2301:                        // It can happen if exception was generated after
2302:                        // frame was pushed to cx.previousInterpreterInvocations
2303:                        // but before assignment to cx.lastInterpreterFrame.
2304:                        // In this case frames has to be ignored.
2305:                        --previousCount;
2306:                    }
2307:                    array = new CallFrame[previousCount + 1];
2308:                    cx.previousInterpreterInvocations.toArray(array);
2309:                }
2310:                array[array.length - 1] = (CallFrame) cx.lastInterpreterFrame;
2311:
2312:                int interpreterFrameCount = 0;
2313:                for (int i = 0; i != array.length; ++i) {
2314:                    interpreterFrameCount += 1 + array[i].frameIndex;
2315:                }
2316:
2317:                int[] linePC = new int[interpreterFrameCount];
2318:                // Fill linePC with pc positions from all interpreter frames.
2319:                // Start from the most nested frame
2320:                int linePCIndex = interpreterFrameCount;
2321:                for (int i = array.length; i != 0;) {
2322:                    --i;
2323:                    CallFrame frame = array[i];
2324:                    while (frame != null) {
2325:                        --linePCIndex;
2326:                        linePC[linePCIndex] = frame.pcSourceLineStart;
2327:                        frame = frame.parentFrame;
2328:                    }
2329:                }
2330:                if (linePCIndex != 0)
2331:                    Kit.codeBug();
2332:
2333:                ex.interpreterStackInfo = array;
2334:                ex.interpreterLineData = linePC;
2335:            }
2336:
2337:            public String getSourcePositionFromStack(Context cx, int[] linep) {
2338:                CallFrame frame = (CallFrame) cx.lastInterpreterFrame;
2339:                InterpreterData idata = frame.idata;
2340:                if (frame.pcSourceLineStart >= 0) {
2341:                    linep[0] = getIndex(idata.itsICode, frame.pcSourceLineStart);
2342:                } else {
2343:                    linep[0] = 0;
2344:                }
2345:                return idata.itsSourceFile;
2346:            }
2347:
2348:            public String getPatchedStack(RhinoException ex,
2349:                    String nativeStackTrace) {
2350:                String tag = "org.mozilla.javascript.Interpreter.interpretLoop";
2351:                StringBuffer sb = new StringBuffer(
2352:                        nativeStackTrace.length() + 1000);
2353:                String lineSeparator = SecurityUtilities
2354:                        .getSystemProperty("line.separator");
2355:
2356:                CallFrame[] array = (CallFrame[]) ex.interpreterStackInfo;
2357:                int[] linePC = ex.interpreterLineData;
2358:                int arrayIndex = array.length;
2359:                int linePCIndex = linePC.length;
2360:                int offset = 0;
2361:                while (arrayIndex != 0) {
2362:                    --arrayIndex;
2363:                    int pos = nativeStackTrace.indexOf(tag, offset);
2364:                    if (pos < 0) {
2365:                        break;
2366:                    }
2367:
2368:                    // Skip tag length
2369:                    pos += tag.length();
2370:                    // Skip until the end of line
2371:                    for (; pos != nativeStackTrace.length(); ++pos) {
2372:                        char c = nativeStackTrace.charAt(pos);
2373:                        if (c == '\n' || c == '\r') {
2374:                            break;
2375:                        }
2376:                    }
2377:                    sb.append(nativeStackTrace.substring(offset, pos));
2378:                    offset = pos;
2379:
2380:                    CallFrame frame = array[arrayIndex];
2381:                    while (frame != null) {
2382:                        if (linePCIndex == 0)
2383:                            Kit.codeBug();
2384:                        --linePCIndex;
2385:                        InterpreterData idata = frame.idata;
2386:                        sb.append(lineSeparator);
2387:                        sb.append("\tat script");
2388:                        if (idata.itsName != null
2389:                                && idata.itsName.length() != 0) {
2390:                            sb.append('.');
2391:                            sb.append(idata.itsName);
2392:                        }
2393:                        sb.append('(');
2394:                        sb.append(idata.itsSourceFile);
2395:                        int pc = linePC[linePCIndex];
2396:                        if (pc >= 0) {
2397:                            // Include line info only if available
2398:                            sb.append(':');
2399:                            sb.append(getIndex(idata.itsICode, pc));
2400:                        }
2401:                        sb.append(')');
2402:                        frame = frame.parentFrame;
2403:                    }
2404:                }
2405:                sb.append(nativeStackTrace.substring(offset));
2406:
2407:                return sb.toString();
2408:            }
2409:
2410:            public List getScriptStack(RhinoException ex) {
2411:                if (ex.interpreterStackInfo == null) {
2412:                    return null;
2413:                }
2414:
2415:                List list = new ArrayList();
2416:                String lineSeparator = SecurityUtilities
2417:                        .getSystemProperty("line.separator");
2418:
2419:                CallFrame[] array = (CallFrame[]) ex.interpreterStackInfo;
2420:                int[] linePC = ex.interpreterLineData;
2421:                int arrayIndex = array.length;
2422:                int linePCIndex = linePC.length;
2423:                while (arrayIndex != 0) {
2424:                    --arrayIndex;
2425:                    StringBuffer sb = new StringBuffer();
2426:                    CallFrame frame = array[arrayIndex];
2427:                    while (frame != null) {
2428:                        if (linePCIndex == 0)
2429:                            Kit.codeBug();
2430:                        --linePCIndex;
2431:                        InterpreterData idata = frame.idata;
2432:                        sb.append("\tat ");
2433:                        sb.append(idata.itsSourceFile);
2434:                        int pc = linePC[linePCIndex];
2435:                        if (pc >= 0) {
2436:                            // Include line info only if available
2437:                            sb.append(':');
2438:                            sb.append(getIndex(idata.itsICode, pc));
2439:                        }
2440:                        if (idata.itsName != null
2441:                                && idata.itsName.length() != 0) {
2442:                            sb.append(" (");
2443:                            sb.append(idata.itsName);
2444:                            sb.append(')');
2445:                        }
2446:                        sb.append(lineSeparator);
2447:                        frame = frame.parentFrame;
2448:                    }
2449:                    list.add(sb.toString());
2450:                }
2451:                return list;
2452:            }
2453:
2454:            static String getEncodedSource(InterpreterData idata) {
2455:                if (idata.encodedSource == null) {
2456:                    return null;
2457:                }
2458:                return idata.encodedSource.substring(idata.encodedSourceStart,
2459:                        idata.encodedSourceEnd);
2460:            }
2461:
2462:            private static void initFunction(Context cx, Scriptable scope,
2463:                    InterpretedFunction parent, int index) {
2464:                InterpretedFunction fn;
2465:                fn = InterpretedFunction.createFunction(cx, scope, parent,
2466:                        index);
2467:                ScriptRuntime.initFunction(cx, scope, fn,
2468:                        fn.idata.itsFunctionType, parent.idata.evalScriptFlag);
2469:            }
2470:
2471:            static Object interpret(InterpretedFunction ifun, Context cx,
2472:                    Scriptable scope, Scriptable this Obj, Object[] args) {
2473:                if (!ScriptRuntime.hasTopCall(cx))
2474:                    Kit.codeBug();
2475:
2476:                if (cx.interpreterSecurityDomain != ifun.securityDomain) {
2477:                    Object savedDomain = cx.interpreterSecurityDomain;
2478:                    cx.interpreterSecurityDomain = ifun.securityDomain;
2479:                    try {
2480:                        return ifun.securityController.callWithDomain(
2481:                                ifun.securityDomain, cx, ifun, scope, this Obj,
2482:                                args);
2483:                    } finally {
2484:                        cx.interpreterSecurityDomain = savedDomain;
2485:                    }
2486:                }
2487:
2488:                CallFrame frame = new CallFrame();
2489:                initFrame(cx, scope, this Obj, args, null, 0, args.length, ifun,
2490:                        null, frame);
2491:
2492:                return interpretLoop(cx, frame, null);
2493:            }
2494:
2495:            static class GeneratorState {
2496:                GeneratorState(int operation, Object value) {
2497:                    this .operation = operation;
2498:                    this .value = value;
2499:                }
2500:
2501:                int operation;
2502:                Object value;
2503:                RuntimeException returnedException;
2504:            }
2505:
2506:            public static Object resumeGenerator(Context cx, Scriptable scope,
2507:                    int operation, Object savedState, Object value) {
2508:                CallFrame frame = (CallFrame) savedState;
2509:                GeneratorState generatorState = new GeneratorState(operation,
2510:                        value);
2511:                if (operation == NativeGenerator.GENERATOR_CLOSE) {
2512:                    try {
2513:                        return interpretLoop(cx, frame, generatorState);
2514:                    } catch (RuntimeException e) {
2515:                        // Only propagate exceptions other than closingException
2516:                        if (e != value)
2517:                            throw e;
2518:                    }
2519:                    return Undefined.instance;
2520:                }
2521:                Object result = interpretLoop(cx, frame, generatorState);
2522:                if (generatorState.returnedException != null)
2523:                    throw generatorState.returnedException;
2524:                return result;
2525:            }
2526:
2527:            public static Object restartContinuation(Continuation c,
2528:                    Context cx, Scriptable scope, Object[] args) {
2529:                if (!ScriptRuntime.hasTopCall(cx)) {
2530:                    return ScriptRuntime.doTopCall(c, cx, scope, null, args);
2531:                }
2532:
2533:                Object arg;
2534:                if (args.length == 0) {
2535:                    arg = Undefined.instance;
2536:                } else {
2537:                    arg = args[0];
2538:                }
2539:
2540:                CallFrame capturedFrame = (CallFrame) c.getImplementation();
2541:                if (capturedFrame == null) {
2542:                    // No frames to restart
2543:                    return arg;
2544:                }
2545:
2546:                ContinuationJump cjump = new ContinuationJump(c, null);
2547:
2548:                cjump.result = arg;
2549:                return interpretLoop(cx, null, cjump);
2550:            }
2551:
2552:            private static Object interpretLoop(Context cx, CallFrame frame,
2553:                    Object throwable) {
2554:                // throwable holds exception object to rethrow or catch
2555:                // It is also used for continuation restart in which case
2556:                // it holds ContinuationJump
2557:
2558:                final Object DBL_MRK = UniqueTag.DOUBLE_MARK;
2559:                final Object undefined = Undefined.instance;
2560:
2561:                final boolean instructionCounting = (cx.instructionThreshold != 0);
2562:                // arbitrary number to add to instructionCount when calling
2563:                // other functions
2564:                final int INVOCATION_COST = 100;
2565:                // arbitrary exception cost for instruction counting
2566:                final int EXCEPTION_COST = 100;
2567:
2568:                String stringReg = null;
2569:                int indexReg = -1;
2570:
2571:                if (cx.lastInterpreterFrame != null) {
2572:                    // save the top frame from the previous interpretLoop
2573:                    // invocation on the stack
2574:                    if (cx.previousInterpreterInvocations == null) {
2575:                        cx.previousInterpreterInvocations = new ObjArray();
2576:                    }
2577:                    cx.previousInterpreterInvocations
2578:                            .push(cx.lastInterpreterFrame);
2579:                }
2580:
2581:                // When restarting continuation throwable is not null and to jump
2582:                // to the code that rewind continuation state indexReg should be set
2583:                // to -1.
2584:                // With the normal call throable == null and indexReg == -1 allows to
2585:                // catch bugs with using indeReg to access array eleemnts before
2586:                // initializing indexReg.
2587:
2588:                GeneratorState generatorState = null;
2589:                if (throwable != null) {
2590:                    if (throwable instanceof  GeneratorState) {
2591:                        generatorState = (GeneratorState) throwable;
2592:
2593:                        // reestablish this call frame
2594:                        enterFrame(cx, frame, ScriptRuntime.emptyArgs, true);
2595:                        throwable = null;
2596:                    } else if (!(throwable instanceof  ContinuationJump)) {
2597:                        // It should be continuation
2598:                        Kit.codeBug();
2599:                    }
2600:                }
2601:
2602:                Object interpreterResult = null;
2603:                double interpreterResultDbl = 0.0;
2604:
2605:                StateLoop: for (;;) {
2606:                    withoutExceptions: try {
2607:
2608:                        if (throwable != null) {
2609:                            // Need to return both 'frame' and 'throwable' from
2610:                            // 'processThrowable', so just added a 'throwable'
2611:                            // member in 'frame'.
2612:                            frame = processThrowable(cx, throwable, frame,
2613:                                    indexReg, instructionCounting);
2614:                            throwable = frame.throwable;
2615:                            frame.throwable = null;
2616:                        } else {
2617:                            if (generatorState == null && frame.frozen)
2618:                                Kit.codeBug();
2619:                        }
2620:
2621:                        // Use local variables for constant values in frame
2622:                        // for faster access
2623:                        Object[] stack = frame.stack;
2624:                        double[] sDbl = frame.sDbl;
2625:                        Object[] vars = frame.varSource.stack;
2626:                        double[] varDbls = frame.varSource.sDbl;
2627:                        int[] varAttributes = frame.varSource.stackAttributes;
2628:                        byte[] iCode = frame.idata.itsICode;
2629:                        String[] strings = frame.idata.itsStringTable;
2630:
2631:                        // Use local for stackTop as well. Since execption handlers
2632:                        // can only exist at statement level where stack is empty,
2633:                        // it is necessary to save/restore stackTop only across
2634:                        // function calls and normal returns.
2635:                        int stackTop = frame.savedStackTop;
2636:
2637:                        // Store new frame in cx which is used for error reporting etc.
2638:                        cx.lastInterpreterFrame = frame;
2639:
2640:                        Loop: for (;;) {
2641:
2642:                            // Exception handler assumes that PC is already incremented
2643:                            // pass the instruction start when it searches the
2644:                            // exception handler
2645:                            int op = iCode[frame.pc++];
2646:                            jumplessRun: {
2647:
2648:                                // Back indent to ease implementation reading
2649:                                switch (op) {
2650:                                case Icode_GENERATOR: {
2651:                                    if (!frame.frozen) {
2652:                                        // First time encountering this opcode: create new generator
2653:                                        // object and return
2654:                                        frame.pc--; // we want to come back here when we resume
2655:                                        CallFrame generatorFrame = captureFrameForGenerator(frame);
2656:                                        generatorFrame.frozen = true;
2657:                                        NativeGenerator generator = new NativeGenerator(
2658:                                                frame.scope,
2659:                                                generatorFrame.fnOrScript,
2660:                                                generatorFrame);
2661:                                        frame.result = generator;
2662:                                        break Loop;
2663:                                    } else {
2664:                                        // We are now resuming execution. Fall through to YIELD case.
2665:                                    }
2666:                                }
2667:                                    // fall through...
2668:                                case Token.YIELD: {
2669:                                    if (!frame.frozen) {
2670:                                        return freezeGenerator(cx, frame,
2671:                                                stackTop, generatorState);
2672:                                    } else {
2673:                                        Object obj = thawGenerator(frame,
2674:                                                stackTop, generatorState, op);
2675:                                        if (obj != Scriptable.NOT_FOUND) {
2676:                                            throwable = obj;
2677:                                            break withoutExceptions;
2678:                                        }
2679:                                        continue Loop;
2680:                                    }
2681:                                }
2682:                                case Icode_GENERATOR_END: {
2683:                                    // throw StopIteration
2684:                                    frame.frozen = true;
2685:                                    int sourceLine = getIndex(iCode, frame.pc);
2686:                                    generatorState.returnedException = new JavaScriptException(
2687:                                            NativeIterator
2688:                                                    .getStopIterationObject(frame.scope),
2689:                                            frame.idata.itsSourceFile,
2690:                                            sourceLine);
2691:                                    break Loop;
2692:                                }
2693:                                case Token.THROW: {
2694:                                    Object value = stack[stackTop];
2695:                                    if (value == DBL_MRK)
2696:                                        value = ScriptRuntime
2697:                                                .wrapNumber(sDbl[stackTop]);
2698:                                    --stackTop;
2699:
2700:                                    int sourceLine = getIndex(iCode, frame.pc);
2701:                                    throwable = new JavaScriptException(value,
2702:                                            frame.idata.itsSourceFile,
2703:                                            sourceLine);
2704:                                    break withoutExceptions;
2705:                                }
2706:                                case Token.RETHROW: {
2707:                                    indexReg += frame.localShift;
2708:                                    throwable = stack[indexReg];
2709:                                    break withoutExceptions;
2710:                                }
2711:                                case Token.GE:
2712:                                case Token.LE:
2713:                                case Token.GT:
2714:                                case Token.LT: {
2715:                                    --stackTop;
2716:                                    Object rhs = stack[stackTop + 1];
2717:                                    Object lhs = stack[stackTop];
2718:                                    boolean valBln;
2719:                                    object_compare: {
2720:                                        number_compare: {
2721:                                            double rDbl, lDbl;
2722:                                            if (rhs == DBL_MRK) {
2723:                                                rDbl = sDbl[stackTop + 1];
2724:                                                lDbl = stack_double(frame,
2725:                                                        stackTop);
2726:                                            } else if (lhs == DBL_MRK) {
2727:                                                rDbl = ScriptRuntime
2728:                                                        .toNumber(rhs);
2729:                                                lDbl = sDbl[stackTop];
2730:                                            } else {
2731:                                                break number_compare;
2732:                                            }
2733:                                            switch (op) {
2734:                                            case Token.GE:
2735:                                                valBln = (lDbl >= rDbl);
2736:                                                break object_compare;
2737:                                            case Token.LE:
2738:                                                valBln = (lDbl <= rDbl);
2739:                                                break object_compare;
2740:                                            case Token.GT:
2741:                                                valBln = (lDbl > rDbl);
2742:                                                break object_compare;
2743:                                            case Token.LT:
2744:                                                valBln = (lDbl < rDbl);
2745:                                                break object_compare;
2746:                                            default:
2747:                                                throw Kit.codeBug();
2748:                                            }
2749:                                        }
2750:                                        switch (op) {
2751:                                        case Token.GE:
2752:                                            valBln = ScriptRuntime.cmp_LE(rhs,
2753:                                                    lhs);
2754:                                            break;
2755:                                        case Token.LE:
2756:                                            valBln = ScriptRuntime.cmp_LE(lhs,
2757:                                                    rhs);
2758:                                            break;
2759:                                        case Token.GT:
2760:                                            valBln = ScriptRuntime.cmp_LT(rhs,
2761:                                                    lhs);
2762:                                            break;
2763:                                        case Token.LT:
2764:                                            valBln = ScriptRuntime.cmp_LT(lhs,
2765:                                                    rhs);
2766:                                            break;
2767:                                        default:
2768:                                            throw Kit.codeBug();
2769:                                        }
2770:                                    }
2771:                                    stack[stackTop] = ScriptRuntime
2772:                                            .wrapBoolean(valBln);
2773:                                    continue Loop;
2774:                                }
2775:                                case Token.IN:
2776:                                case Token.INSTANCEOF: {
2777:                                    Object rhs = stack[stackTop];
2778:                                    if (rhs == DBL_MRK)
2779:                                        rhs = ScriptRuntime
2780:                                                .wrapNumber(sDbl[stackTop]);
2781:                                    --stackTop;
2782:                                    Object lhs = stack[stackTop];
2783:                                    if (lhs == DBL_MRK)
2784:                                        lhs = ScriptRuntime
2785:                                                .wrapNumber(sDbl[stackTop]);
2786:                                    boolean valBln;
2787:                                    if (op == Token.IN) {
2788:                                        valBln = ScriptRuntime.in(lhs, rhs, cx);
2789:                                    } else {
2790:                                        valBln = ScriptRuntime.instanceOf(lhs,
2791:                                                rhs, cx);
2792:                                    }
2793:                                    stack[stackTop] = ScriptRuntime
2794:                                            .wrapBoolean(valBln);
2795:                                    continue Loop;
2796:                                }
2797:                                case Token.EQ:
2798:                                case Token.NE: {
2799:                                    --stackTop;
2800:                                    boolean valBln;
2801:                                    Object rhs = stack[stackTop + 1];
2802:                                    Object lhs = stack[stackTop];
2803:                                    if (rhs == DBL_MRK) {
2804:                                        if (lhs == DBL_MRK) {
2805:                                            valBln = (sDbl[stackTop] == sDbl[stackTop + 1]);
2806:                                        } else {
2807:                                            valBln = ScriptRuntime.eqNumber(
2808:                                                    sDbl[stackTop + 1], lhs);
2809:                                        }
2810:                                    } else {
2811:                                        if (lhs == DBL_MRK) {
2812:                                            valBln = ScriptRuntime.eqNumber(
2813:                                                    sDbl[stackTop], rhs);
2814:                                        } else {
2815:                                            valBln = ScriptRuntime.eq(lhs, rhs);
2816:                                        }
2817:                                    }
2818:                                    valBln ^= (op == Token.NE);
2819:                                    stack[stackTop] = ScriptRuntime
2820:                                            .wrapBoolean(valBln);
2821:                                    continue Loop;
2822:                                }
2823:                                case Token.SHEQ:
2824:                                case Token.SHNE: {
2825:                                    --stackTop;
2826:                                    Object rhs = stack[stackTop + 1];
2827:                                    Object lhs = stack[stackTop];
2828:                                    boolean valBln;
2829:                                    shallow_compare: {
2830:                                        double rdbl, ldbl;
2831:                                        if (rhs == DBL_MRK) {
2832:                                            rdbl = sDbl[stackTop + 1];
2833:                                            if (lhs == DBL_MRK) {
2834:                                                ldbl = sDbl[stackTop];
2835:                                            } else if (lhs instanceof  Number) {
2836:                                                ldbl = ((Number) lhs)
2837:                                                        .doubleValue();
2838:                                            } else {
2839:                                                valBln = false;
2840:                                                break shallow_compare;
2841:                                            }
2842:                                        } else if (lhs == DBL_MRK) {
2843:                                            ldbl = sDbl[stackTop];
2844:                                            if (rhs == DBL_MRK) {
2845:                                                rdbl = sDbl[stackTop + 1];
2846:                                            } else if (rhs instanceof  Number) {
2847:                                                rdbl = ((Number) rhs)
2848:                                                        .doubleValue();
2849:                                            } else {
2850:                                                valBln = false;
2851:                                                break shallow_compare;
2852:                                            }
2853:                                        } else {
2854:                                            valBln = ScriptRuntime.shallowEq(
2855:                                                    lhs, rhs);
2856:                                            break shallow_compare;
2857:                                        }
2858:                                        valBln = (ldbl == rdbl);
2859:                                    }
2860:                                    valBln ^= (op == Token.SHNE);
2861:                                    stack[stackTop] = ScriptRuntime
2862:                                            .wrapBoolean(valBln);
2863:                                    continue Loop;
2864:                                }
2865:                                case Token.IFNE:
2866:                                    if (stack_boolean(frame, stackTop--)) {
2867:                                        frame.pc += 2;
2868:                                        continue Loop;
2869:                                    }
2870:                                    break jumplessRun;
2871:                                case Token.IFEQ:
2872:                                    if (!stack_boolean(frame, stackTop--)) {
2873:                                        frame.pc += 2;
2874:                                        continue Loop;
2875:                                    }
2876:                                    break jumplessRun;
2877:                                case Icode_IFEQ_POP:
2878:                                    if (!stack_boolean(frame, stackTop--)) {
2879:                                        frame.pc += 2;
2880:                                        continue Loop;
2881:                                    }
2882:                                    stack[stackTop--] = null;
2883:                                    break jumplessRun;
2884:                                case Token.GOTO:
2885:                                    break jumplessRun;
2886:                                case Icode_GOSUB:
2887:                                    ++stackTop;
2888:                                    stack[stackTop] = DBL_MRK;
2889:                                    sDbl[stackTop] = frame.pc + 2;
2890:                                    break jumplessRun;
2891:                                case Icode_STARTSUB:
2892:                                    if (stackTop == frame.emptyStackTop + 1) {
2893:                                        // Call from Icode_GOSUB: store return PC address in the local
2894:                                        indexReg += frame.localShift;
2895:                                        stack[indexReg] = stack[stackTop];
2896:                                        sDbl[indexReg] = sDbl[stackTop];
2897:                                        --stackTop;
2898:                                    } else {
2899:                                        // Call from exception handler: exception object is already stored
2900:                                        // in the local
2901:                                        if (stackTop != frame.emptyStackTop)
2902:                                            Kit.codeBug();
2903:                                    }
2904:                                    continue Loop;
2905:                                case Icode_RETSUB: {
2906:                                    // indexReg: local to store return address
2907:                                    if (instructionCounting) {
2908:                                        addInstructionCount(cx, frame, 0);
2909:                                    }
2910:                                    indexReg += frame.localShift;
2911:                                    Object value = stack[indexReg];
2912:                                    if (value != DBL_MRK) {
2913:                                        // Invocation from exception handler, restore object to rethrow
2914:                                        throwable = value;
2915:                                        break withoutExceptions;
2916:                                    }
2917:                                    // Normal return from GOSUB
2918:                                    frame.pc = (int) sDbl[indexReg];
2919:                                    if (instructionCounting) {
2920:                                        frame.pcPrevBranch = frame.pc;
2921:                                    }
2922:                                    continue Loop;
2923:                                }
2924:                                case Icode_POP:
2925:                                    stack[stackTop] = null;
2926:                                    stackTop--;
2927:                                    continue Loop;
2928:                                case Icode_POP_RESULT:
2929:                                    frame.result = stack[stackTop];
2930:                                    frame.resultDbl = sDbl[stackTop];
2931:                                    stack[stackTop] = null;
2932:                                    --stackTop;
2933:                                    continue Loop;
2934:                                case Icode_DUP:
2935:                                    stack[stackTop + 1] = stack[stackTop];
2936:                                    sDbl[stackTop + 1] = sDbl[stackTop];
2937:                                    stackTop++;
2938:                                    continue Loop;
2939:                                case Icode_DUP2:
2940:                                    stack[stackTop + 1] = stack[stackTop - 1];
2941:                                    sDbl[stackTop + 1] = sDbl[stackTop - 1];
2942:                                    stack[stackTop + 2] = stack[stackTop];
2943:                                    sDbl[stackTop + 2] = sDbl[stackTop];
2944:                                    stackTop += 2;
2945:                                    continue Loop;
2946:                                case Icode_SWAP: {
2947:                                    Object o = stack[stackTop];
2948:                                    stack[stackTop] = stack[stackTop - 1];
2949:                                    stack[stackTop - 1] = o;
2950:                                    double d = sDbl[stackTop];
2951:                                    sDbl[stackTop] = sDbl[stackTop - 1];
2952:                                    sDbl[stackTop - 1] = d;
2953:                                    continue Loop;
2954:                                }
2955:                                case Token.RETURN:
2956:                                    frame.result = stack[stackTop];
2957:                                    frame.resultDbl = sDbl[stackTop];
2958:                                    --stackTop;
2959:                                    break Loop;
2960:                                case Token.RETURN_RESULT:
2961:                                    break Loop;
2962:                                case Icode_RETUNDEF:
2963:                                    frame.result = undefined;
2964:                                    break Loop;
2965:                                case Token.BITNOT: {
2966:                                    int rIntValue = stack_int32(frame, stackTop);
2967:                                    stack[stackTop] = DBL_MRK;
2968:                                    sDbl[stackTop] = ~rIntValue;
2969:                                    continue Loop;
2970:                                }
2971:                                case Token.BITAND:
2972:                                case Token.BITOR:
2973:                                case Token.BITXOR:
2974:                                case Token.LSH:
2975:                                case Token.RSH: {
2976:                                    int lIntValue = stack_int32(frame,
2977:                                            stackTop - 1);
2978:                                    int rIntValue = stack_int32(frame, stackTop);
2979:                                    stack[--stackTop] = DBL_MRK;
2980:                                    switch (op) {
2981:                                    case Token.BITAND:
2982:                                        lIntValue &= rIntValue;
2983:                                        break;
2984:                                    case Token.BITOR:
2985:                                        lIntValue |= rIntValue;
2986:                                        break;
2987:                                    case Token.BITXOR:
2988:                                        lIntValue ^= rIntValue;
2989:                                        break;
2990:                                    case Token.LSH:
2991:                                        lIntValue <<= rIntValue;
2992:                                        break;
2993:                                    case Token.RSH:
2994:                                        lIntValue >>= rIntValue;
2995:                                        break;
2996:                                    }
2997:                                    sDbl[stackTop] = lIntValue;
2998:                                    continue Loop;
2999:                                }
3000:                                case Token.URSH: {
3001:                                    double lDbl = stack_double(frame,
3002:                                            stackTop - 1);
3003:                                    int rIntValue = stack_int32(frame, stackTop) & 0x1F;
3004:                                    stack[--stackTop] = DBL_MRK;
3005:                                    sDbl[stackTop] = ScriptRuntime
3006:                                            .toUint32(lDbl) >>> rIntValue;
3007:                                    continue Loop;
3008:                                }
3009:                                case Token.NEG:
3010:                                case Token.POS: {
3011:                                    double rDbl = stack_double(frame, stackTop);
3012:                                    stack[stackTop] = DBL_MRK;
3013:                                    if (op == Token.NEG) {
3014:                                        rDbl = -rDbl;
3015:                                    }
3016:                                    sDbl[stackTop] = rDbl;
3017:                                    continue Loop;
3018:                                }
3019:                                case Token.ADD:
3020:                                    --stackTop;
3021:                                    do_add(stack, sDbl, stackTop, cx);
3022:                                    continue Loop;
3023:                                case Token.SUB:
3024:                                case Token.MUL:
3025:                                case Token.DIV:
3026:                                case Token.MOD: {
3027:                                    double rDbl = stack_double(frame, stackTop);
3028:                                    --stackTop;
3029:                                    double lDbl = stack_double(frame, stackTop);
3030:                                    stack[stackTop] = DBL_MRK;
3031:                                    switch (op) {
3032:                                    case Token.SUB:
3033:                                        lDbl -= rDbl;
3034:                                        break;
3035:                                    case Token.MUL:
3036:                                        lDbl *= rDbl;
3037:                                        break;
3038:                                    case Token.DIV:
3039:                                        lDbl /= rDbl;
3040:                                        break;
3041:                                    case Token.MOD:
3042:                                        lDbl %= rDbl;
3043:                                        break;
3044:                                    }
3045:                                    sDbl[stackTop] = lDbl;
3046:                                    continue Loop;
3047:                                }
3048:                                case Token.NOT:
3049:                                    stack[stackTop] = ScriptRuntime
3050:                                            .wrapBoolean(!stack_boolean(frame,
3051:                                                    stackTop));
3052:                                    continue Loop;
3053:                                case Token.BINDNAME:
3054:                                    stack[++stackTop] = ScriptRuntime.bind(cx,
3055:                                            frame.scope, stringReg);
3056:                                    continue Loop;
3057:                                case Token.SETNAME: {
3058:                                    Object rhs = stack[stackTop];
3059:                                    if (rhs == DBL_MRK)
3060:                                        rhs = ScriptRuntime
3061:                                                .wrapNumber(sDbl[stackTop]);
3062:                                    --stackTop;
3063:                                    Scriptable lhs = (Scriptable) stack[stackTop];
3064:                                    stack[stackTop] = ScriptRuntime.setName(
3065:                                            lhs, rhs, cx, frame.scope,
3066:                                            stringReg);
3067:                                    continue Loop;
3068:                                }
3069:                                case Icode_SETCONST: {
3070:                                    Object rhs = stack[stackTop];
3071:                                    if (rhs == DBL_MRK)
3072:                                        rhs = ScriptRuntime
3073:                                                .wrapNumber(sDbl[stackTop]);
3074:                                    --stackTop;
3075:                                    Scriptable lhs = (Scriptable) stack[stackTop];
3076:                                    stack[stackTop] = ScriptRuntime.setConst(
3077:                                            lhs, rhs, cx, stringReg);
3078:                                    continue Loop;
3079:                                }
3080:                                case Token.DELPROP: {
3081:                                    Object rhs = stack[stackTop];
3082:                                    if (rhs == DBL_MRK)
3083:                                        rhs = ScriptRuntime
3084:                                                .wrapNumber(sDbl[stackTop]);
3085:                                    --stackTop;
3086:                                    Object lhs = stack[stackTop];
3087:                                    if (lhs == DBL_MRK)
3088:                                        lhs = ScriptRuntime
3089:                                                .wrapNumber(sDbl[stackTop]);
3090:                                    stack[stackTop] = ScriptRuntime.delete(lhs,
3091:                                            rhs, cx);
3092:                                    continue Loop;
3093:                                }
3094:                                case Token.GETPROPNOWARN: {
3095:                                    Object lhs = stack[stackTop];
3096:                                    if (lhs == DBL_MRK)
3097:                                        lhs = ScriptRuntime
3098:                                                .wrapNumber(sDbl[stackTop]);
3099:                                    stack[stackTop] = ScriptRuntime
3100:                                            .getObjectPropNoWarn(lhs,
3101:                                                    stringReg, cx);
3102:                                    continue Loop;
3103:                                }
3104:                                case Token.GETPROP: {
3105:                                    Object lhs = stack[stackTop];
3106:                                    if (lhs == DBL_MRK)
3107:                                        lhs = ScriptRuntime
3108:                                                .wrapNumber(sDbl[stackTop]);
3109:                                    stack[stackTop] = ScriptRuntime
3110:                                            .getObjectProp(lhs, stringReg, cx);
3111:                                    continue Loop;
3112:                                }
3113:                                case Token.SETPROP: {
3114:                                    Object rhs = stack[stackTop];
3115:                                    if (rhs == DBL_MRK)
3116:                                        rhs = ScriptRuntime
3117:                                                .wrapNumber(sDbl[stackTop]);
3118:                                    --stackTop;
3119:                                    Object lhs = stack[stackTop];
3120:                                    if (lhs == DBL_MRK)
3121:                                        lhs = ScriptRuntime
3122:                                                .wrapNumber(sDbl[stackTop]);
3123:                                    stack[stackTop] = ScriptRuntime
3124:                                            .setObjectProp(lhs, stringReg, rhs,
3125:                                                    cx);
3126:                                    continue Loop;
3127:                                }
3128:                                case Icode_PROP_INC_DEC: {
3129:                                    Object lhs = stack[stackTop];
3130:                                    if (lhs == DBL_MRK)
3131:                                        lhs = ScriptRuntime
3132:                                                .wrapNumber(sDbl[stackTop]);
3133:                                    stack[stackTop] = ScriptRuntime
3134:                                            .propIncrDecr(lhs, stringReg, cx,
3135:                                                    iCode[frame.pc]);
3136:                                    ++frame.pc;
3137:                                    continue Loop;
3138:                                }
3139:                                case Token.GETELEM: {
3140:                                    --stackTop;
3141:                                    Object lhs = stack[stackTop];
3142:                                    if (lhs == DBL_MRK) {
3143:                                        lhs = ScriptRuntime
3144:                                                .wrapNumber(sDbl[stackTop]);
3145:                                    }
3146:                                    Object value;
3147:                                    Object id = stack[stackTop + 1];
3148:                                    if (id != DBL_MRK) {
3149:                                        value = ScriptRuntime.getObjectElem(
3150:                                                lhs, id, cx);
3151:                                    } else {
3152:                                        double d = sDbl[stackTop + 1];
3153:                                        value = ScriptRuntime.getObjectIndex(
3154:                                                lhs, d, cx);
3155:                                    }
3156:                                    stack[stackTop] = value;
3157:                                    continue Loop;
3158:                                }
3159:                                case Token.SETELEM: {
3160:                                    stackTop -= 2;
3161:                                    Object rhs = stack[stackTop + 2];
3162:                                    if (rhs == DBL_MRK) {
3163:                                        rhs = ScriptRuntime
3164:                                                .wrapNumber(sDbl[stackTop + 2]);
3165:                                    }
3166:                                    Object lhs = stack[stackTop];
3167:                                    if (lhs == DBL_MRK) {
3168:                                        lhs = ScriptRuntime
3169:                                                .wrapNumber(sDbl[stackTop]);
3170:                                    }
3171:                                    Object value;
3172:                                    Object id = stack[stackTop + 1];
3173:                                    if (id != DBL_MRK) {
3174:                                        value = ScriptRuntime.setObjectElem(
3175:                                                lhs, id, rhs, cx);
3176:                                    } else {
3177:                                        double d = sDbl[stackTop + 1];
3178:                                        value = ScriptRuntime.setObjectIndex(
3179:                                                lhs, d, rhs, cx);
3180:                                    }
3181:                                    stack[stackTop] = value;
3182:                                    continue Loop;
3183:                                }
3184:                                case Icode_ELEM_INC_DEC: {
3185:                                    Object rhs = stack[stackTop];
3186:                                    if (rhs == DBL_MRK)
3187:                                        rhs = ScriptRuntime
3188:                                                .wrapNumber(sDbl[stackTop]);
3189:                                    --stackTop;
3190:                                    Object lhs = stack[stackTop];
3191:                                    if (lhs == DBL_MRK)
3192:                                        lhs = ScriptRuntime
3193:                                                .wrapNumber(sDbl[stackTop]);
3194:                                    stack[stackTop] = ScriptRuntime
3195:                                            .elemIncrDecr(lhs, rhs, cx,
3196:                                                    iCode[frame.pc]);
3197:                                    ++frame.pc;
3198:                                    continue Loop;
3199:                                }
3200:                                case Token.GET_REF: {
3201:                                    Ref ref = (Ref) stack[stackTop];
3202:                                    stack[stackTop] = ScriptRuntime.refGet(ref,
3203:                                            cx);
3204:                                    continue Loop;
3205:                                }
3206:                                case Token.SET_REF: {
3207:                                    Object value = stack[stackTop];
3208:                                    if (value == DBL_MRK)
3209:                                        value = ScriptRuntime
3210:                                                .wrapNumber(sDbl[stackTop]);
3211:                                    --stackTop;
3212:                                    Ref ref = (Ref) stack[stackTop];
3213:                                    stack[stackTop] = ScriptRuntime.refSet(ref,
3214:                                            value, cx);
3215:                                    continue Loop;
3216:                                }
3217:                                case Token.DEL_REF: {
3218:                                    Ref ref = (Ref) stack[stackTop];
3219:                                    stack[stackTop] = ScriptRuntime.refDel(ref,
3220:                                            cx);
3221:                                    continue Loop;
3222:                                }
3223:                                case Icode_REF_INC_DEC: {
3224:                                    Ref ref = (Ref) stack[stackTop];
3225:                                    stack[stackTop] = ScriptRuntime
3226:                                            .refIncrDecr(ref, cx,
3227:                                                    iCode[frame.pc]);
3228:                                    ++frame.pc;
3229:                                    continue Loop;
3230:                                }
3231:                                case Token.LOCAL_LOAD:
3232:                                    ++stackTop;
3233:                                    indexReg += frame.localShift;
3234:                                    stack[stackTop] = stack[indexReg];
3235:                                    sDbl[stackTop] = sDbl[indexReg];
3236:                                    continue Loop;
3237:                                case Icode_LOCAL_CLEAR:
3238:                                    indexReg += frame.localShift;
3239:                                    stack[indexReg] = null;
3240:                                    continue Loop;
3241:                                case Icode_NAME_AND_THIS:
3242:                                    // stringReg: name
3243:                                    ++stackTop;
3244:                                    stack[stackTop] = ScriptRuntime
3245:                                            .getNameFunctionAndThis(stringReg,
3246:                                                    cx, frame.scope);
3247:                                    ++stackTop;
3248:                                    stack[stackTop] = ScriptRuntime
3249:                                            .lastStoredScriptable(cx);
3250:                                    continue Loop;
3251:                                case Icode_PROP_AND_THIS: {
3252:                                    Object obj = stack[stackTop];
3253:                                    if (obj == DBL_MRK)
3254:                                        obj = ScriptRuntime
3255:                                                .wrapNumber(sDbl[stackTop]);
3256:                                    // stringReg: property
3257:                                    stack[stackTop] = ScriptRuntime
3258:                                            .getPropFunctionAndThis(obj,
3259:                                                    stringReg, cx);
3260:                                    ++stackTop;
3261:                                    stack[stackTop] = ScriptRuntime
3262:                                            .lastStoredScriptable(cx);
3263:                                    continue Loop;
3264:                                }
3265:                                case Icode_ELEM_AND_THIS: {
3266:                                    Object obj = stack[stackTop - 1];
3267:                                    if (obj == DBL_MRK)
3268:                                        obj = ScriptRuntime
3269:                                                .wrapNumber(sDbl[stackTop - 1]);
3270:                                    Object id = stack[stackTop];
3271:                                    if (id == DBL_MRK)
3272:                                        id = ScriptRuntime
3273:                                                .wrapNumber(sDbl[stackTop]);
3274:                                    stack[stackTop - 1] = ScriptRuntime
3275:                                            .getElemFunctionAndThis(obj, id, cx);
3276:                                    stack[stackTop] = ScriptRuntime
3277:                                            .lastStoredScriptable(cx);
3278:                                    continue Loop;
3279:                                }
3280:                                case Icode_VALUE_AND_THIS: {
3281:                                    Object value = stack[stackTop];
3282:                                    if (value == DBL_MRK)
3283:                                        value = ScriptRuntime
3284:                                                .wrapNumber(sDbl[stackTop]);
3285:                                    stack[stackTop] = ScriptRuntime
3286:                                            .getValueFunctionAndThis(value, cx);
3287:                                    ++stackTop;
3288:                                    stack[stackTop] = ScriptRuntime
3289:                                            .lastStoredScriptable(cx);
3290:                                    continue Loop;
3291:                                }
3292:                                case Icode_CALLSPECIAL: {
3293:                                    if (instructionCounting) {
3294:                                        cx.instructionCount += INVOCATION_COST;
3295:                                    }
3296:                                    int callType = iCode[frame.pc] & 0xFF;
3297:                                    boolean isNew = (iCode[frame.pc + 1] != 0);
3298:                                    int sourceLine = getIndex(iCode,
3299:                                            frame.pc + 2);
3300:
3301:                                    // indexReg: number of arguments
3302:                                    if (isNew) {
3303:                                        // stack change: function arg0 .. argN -> newResult
3304:                                        stackTop -= indexReg;
3305:
3306:                                        Object function = stack[stackTop];
3307:                                        if (function == DBL_MRK)
3308:                                            function = ScriptRuntime
3309:                                                    .wrapNumber(sDbl[stackTop]);
3310:                                        Object[] outArgs = getArgsArray(stack,
3311:                                                sDbl, stackTop + 1, indexReg);
3312:                                        stack[stackTop] = ScriptRuntime
3313:                                                .newSpecial(cx, function,
3314:                                                        outArgs, frame.scope,
3315:                                                        callType);
3316:                                    } else {
3317:                                        // stack change: function thisObj arg0 .. argN -> result
3318:                                        stackTop -= 1 + indexReg;
3319:
3320:                                        // Call code generation ensure that stack here
3321:                                        // is ... Callable Scriptable
3322:                                        Scriptable functionThis = (Scriptable) stack[stackTop + 1];
3323:                                        Callable function = (Callable) stack[stackTop];
3324:                                        Object[] outArgs = getArgsArray(stack,
3325:                                                sDbl, stackTop + 2, indexReg);
3326:                                        stack[stackTop] = ScriptRuntime
3327:                                                .callSpecial(
3328:                                                        cx,
3329:                                                        function,
3330:                                                        functionThis,
3331:                                                        outArgs,
3332:                                                        frame.scope,
3333:                                                        frame.this Obj,
3334:                                                        callType,
3335:                                                        frame.idata.itsSourceFile,
3336:                                                        sourceLine);
3337:                                    }
3338:                                    frame.pc += 4;
3339:                                    continue Loop;
3340:                                }
3341:                                case Token.CALL:
3342:                                case Icode_TAIL_CALL:
3343:                                case Token.REF_CALL: {
3344:                                    if (instructionCounting) {
3345:                                        cx.instructionCount += INVOCATION_COST;
3346:                                    }
3347:                                    // stack change: function thisObj arg0 .. argN -> result
3348:                                    // indexReg: number of arguments
3349:                                    stackTop -= 1 + indexReg;
3350:
3351:                                    // CALL generation ensures that fun and funThisObj
3352:                                    // are already Scriptable and Callable objects respectively
3353:                                    Callable fun = (Callable) stack[stackTop];
3354:                                    Scriptable funThisObj = (Scriptable) stack[stackTop + 1];
3355:                                    if (op == Token.REF_CALL) {
3356:                                        Object[] outArgs = getArgsArray(stack,
3357:                                                sDbl, stackTop + 2, indexReg);
3358:                                        stack[stackTop] = ScriptRuntime
3359:                                                .callRef(fun, funThisObj,
3360:                                                        outArgs, cx);
3361:                                        continue Loop;
3362:                                    }
3363:                                    Scriptable calleeScope = frame.scope;
3364:                                    if (frame.useActivation) {
3365:                                        calleeScope = ScriptableObject
3366:                                                .getTopLevelScope(frame.scope);
3367:                                    }
3368:                                    if (fun instanceof  InterpretedFunction) {
3369:                                        InterpretedFunction ifun = (InterpretedFunction) fun;
3370:                                        if (frame.fnOrScript.securityDomain == ifun.securityDomain) {
3371:                                            CallFrame callParentFrame = frame;
3372:                                            CallFrame calleeFrame = new CallFrame();
3373:                                            if (op == Icode_TAIL_CALL) {
3374:                                                // In principle tail call can re-use the current
3375:                                                // frame and its stack arrays but it is hard to
3376:                                                // do properly. Any exceptions that can legally
3377:                                                // happen during frame re-initialization including
3378:                                                // StackOverflowException during innocent looking
3379:                                                // System.arraycopy may leave the current frame
3380:                                                // data corrupted leading to undefined behaviour
3381:                                                // in the catch code bellow that unwinds JS stack
3382:                                                // on exceptions. Then there is issue about frame release
3383:                                                // end exceptions there.
3384:                                                // To avoid frame allocation a released frame
3385:                                                // can be cached for re-use which would also benefit
3386:                                                // non-tail calls but it is not clear that this caching
3387:                                                // would gain in performance due to potentially
3388:                                                // bad interaction with GC.
3389:                                                callParentFrame = frame.parentFrame;
3390:                                                // Release the current frame. See Bug #344501 to see why
3391:                                                // it is being done here.
3392:                                                exitFrame(cx, frame, null);
3393:                                            }
3394:                                            initFrame(cx, calleeScope,
3395:                                                    funThisObj, stack, sDbl,
3396:                                                    stackTop + 2, indexReg,
3397:                                                    ifun, callParentFrame,
3398:                                                    calleeFrame);
3399:                                            if (op != Icode_TAIL_CALL) {
3400:                                                frame.savedStackTop = stackTop;
3401:                                                frame.savedCallOp = op;
3402:                                            }
3403:                                            frame = calleeFrame;
3404:                                            continue StateLoop;
3405:                                        }
3406:                                    }
3407:
3408:                                    if (fun instanceof  Continuation) {
3409:                                        // Jump to the captured continuation
3410:                                        ContinuationJump cjump;
3411:                                        cjump = new ContinuationJump(
3412:                                                (Continuation) fun, frame);
3413:
3414:                                        // continuation result is the first argument if any
3415:                                        // of contination call
3416:                                        if (indexReg == 0) {
3417:                                            cjump.result = undefined;
3418:                                        } else {
3419:                                            cjump.result = stack[stackTop + 2];
3420:                                            cjump.resultDbl = sDbl[stackTop + 2];
3421:                                        }
3422:
3423:                                        // Start the real unwind job
3424:                                        throwable = cjump;
3425:                                        break withoutExceptions;
3426:                                    }
3427:
3428:                                    if (fun instanceof  IdFunctionObject) {
3429:                                        IdFunctionObject ifun = (IdFunctionObject) fun;
3430:                                        if (Continuation
3431:                                                .isContinuationConstructor(ifun)) {
3432:                                            captureContinuation(cx, frame,
3433:                                                    stackTop);
3434:                                            continue Loop;
3435:                                        }
3436:                                        // Bug 405654 -- make best effort to keep Function.apply and 
3437:                                        // Function.call within this interpreter loop invocation
3438:                                        if (BaseFunction.isApplyOrCall(ifun)) {
3439:                                            Callable applyCallable = ScriptRuntime
3440:                                                    .getCallable(funThisObj);
3441:                                            if (applyCallable instanceof  InterpretedFunction) {
3442:                                                InterpretedFunction iApplyCallable = (InterpretedFunction) applyCallable;
3443:                                                if (frame.fnOrScript.securityDomain == iApplyCallable.securityDomain) {
3444:                                                    frame = initFrameForApplyOrCall(
3445:                                                            cx, frame,
3446:                                                            indexReg, stack,
3447:                                                            sDbl, stackTop, op,
3448:                                                            calleeScope, ifun,
3449:                                                            iApplyCallable);
3450:                                                    continue StateLoop;
3451:                                                }
3452:                                            }
3453:                                        }
3454:                                    }
3455:
3456:                                    stack[stackTop] = fun.call(cx, calleeScope,
3457:                                            funThisObj, getArgsArray(stack,
3458:                                                    sDbl, stackTop + 2,
3459:                                                    indexReg));
3460:
3461:                                    continue Loop;
3462:                                }
3463:                                case Token.NEW: {
3464:                                    if (instructionCounting) {
3465:                                        cx.instructionCount += INVOCATION_COST;
3466:                                    }
3467:                                    // stack change: function arg0 .. argN -> newResult
3468:                                    // indexReg: number of arguments
3469:                                    stackTop -= indexReg;
3470:
3471:                                    Object lhs = stack[stackTop];
3472:                                    if (lhs instanceof  InterpretedFunction) {
3473:                                        InterpretedFunction f = (InterpretedFunction) lhs;
3474:                                        if (frame.fnOrScript.securityDomain == f.securityDomain) {
3475:                                            Scriptable newInstance = f
3476:                                                    .createObject(cx,
3477:                                                            frame.scope);
3478:                                            CallFrame calleeFrame = new CallFrame();
3479:                                            initFrame(cx, frame.scope,
3480:                                                    newInstance, stack, sDbl,
3481:                                                    stackTop + 1, indexReg, f,
3482:                                                    frame, calleeFrame);
3483:
3484:                                            stack[stackTop] = newInstance;
3485:                                            frame.savedStackTop = stackTop;
3486:                                            frame.savedCallOp = op;
3487:                                            frame = calleeFrame;
3488:                                            continue StateLoop;
3489:                                        }
3490:                                    }
3491:                                    if (!(lhs instanceof  Function)) {
3492:                                        if (lhs == DBL_MRK)
3493:                                            lhs = ScriptRuntime
3494:                                                    .wrapNumber(sDbl[stackTop]);
3495:                                        throw ScriptRuntime
3496:                                                .notFunctionError(lhs);
3497:                                    }
3498:                                    Function fun = (Function) lhs;
3499:
3500:                                    if (fun instanceof  IdFunctionObject) {
3501:                                        IdFunctionObject ifun = (IdFunctionObject) fun;
3502:                                        if (Continuation
3503:                                                .isContinuationConstructor(ifun)) {
3504:                                            captureContinuation(cx, frame,
3505:                                                    stackTop);
3506:                                            continue Loop;
3507:                                        }
3508:                                    }
3509:
3510:                                    Object[] outArgs = getArgsArray(stack,
3511:                                            sDbl, stackTop + 1, indexReg);
3512:                                    stack[stackTop] = fun.construct(cx,
3513:                                            frame.scope, outArgs);
3514:                                    continue Loop;
3515:                                }
3516:                                case Token.TYPEOF: {
3517:                                    Object lhs = stack[stackTop];
3518:                                    if (lhs == DBL_MRK)
3519:                                        lhs = ScriptRuntime
3520:                                                .wrapNumber(sDbl[stackTop]);
3521:                                    stack[stackTop] = ScriptRuntime.typeof(lhs);
3522:                                    continue Loop;
3523:                                }
3524:                                case Icode_TYPEOFNAME:
3525:                                    stack[++stackTop] = ScriptRuntime
3526:                                            .typeofName(frame.scope, stringReg);
3527:                                    continue Loop;
3528:                                case Token.STRING:
3529:                                    stack[++stackTop] = stringReg;
3530:                                    continue Loop;
3531:                                case Icode_SHORTNUMBER:
3532:                                    ++stackTop;
3533:                                    stack[stackTop] = DBL_MRK;
3534:                                    sDbl[stackTop] = getShort(iCode, frame.pc);
3535:                                    frame.pc += 2;
3536:                                    continue Loop;
3537:                                case Icode_INTNUMBER:
3538:                                    ++stackTop;
3539:                                    stack[stackTop] = DBL_MRK;
3540:                                    sDbl[stackTop] = getInt(iCode, frame.pc);
3541:                                    frame.pc += 4;
3542:                                    continue Loop;
3543:                                case Token.NUMBER:
3544:                                    ++stackTop;
3545:                                    stack[stackTop] = DBL_MRK;
3546:                                    sDbl[stackTop] = frame.idata.itsDoubleTable[indexReg];
3547:                                    continue Loop;
3548:                                case Token.NAME:
3549:                                    stack[++stackTop] = ScriptRuntime.name(cx,
3550:                                            frame.scope, stringReg);
3551:                                    continue Loop;
3552:                                case Icode_NAME_INC_DEC:
3553:                                    stack[++stackTop] = ScriptRuntime
3554:                                            .nameIncrDecr(frame.scope,
3555:                                                    stringReg, cx,
3556:                                                    iCode[frame.pc]);
3557:                                    ++frame.pc;
3558:                                    continue Loop;
3559:                                case Icode_SETCONSTVAR1:
3560:                                    indexReg = iCode[frame.pc++];
3561:                                    // fallthrough
3562:                                case Token.SETCONSTVAR:
3563:                                    if (!frame.useActivation) {
3564:                                        if ((varAttributes[indexReg] & ScriptableObject.READONLY) == 0) {
3565:                                            throw Context
3566:                                                    .reportRuntimeError1(
3567:                                                            "msg.var.redecl",
3568:                                                            frame.idata.argNames[indexReg]);
3569:                                        }
3570:                                        if ((varAttributes[indexReg] & ScriptableObject.UNINITIALIZED_CONST) != 0) {
3571:                                            vars[indexReg] = stack[stackTop];
3572:                                            varAttributes[indexReg] &= ~ScriptableObject.UNINITIALIZED_CONST;
3573:                                            varDbls[indexReg] = sDbl[stackTop];
3574:                                        }
3575:                                    } else {
3576:                                        Object val = stack[stackTop];
3577:                                        if (val == DBL_MRK)
3578:                                            val = ScriptRuntime
3579:                                                    .wrapNumber(sDbl[stackTop]);
3580:                                        stringReg = frame.idata.argNames[indexReg];
3581:                                        if (frame.scope instanceof  ConstProperties) {
3582:                                            ConstProperties cp = (ConstProperties) frame.scope;
3583:                                            cp.putConst(stringReg, frame.scope,
3584:                                                    val);
3585:                                        } else
3586:                                            throw Kit.codeBug();
3587:                                    }
3588:                                    continue Loop;
3589:                                case Icode_SETVAR1:
3590:                                    indexReg = iCode[frame.pc++];
3591:                                    // fallthrough
3592:                                case Token.SETVAR:
3593:                                    if (!frame.useActivation) {
3594:                                        if ((varAttributes[indexReg] & ScriptableObject.READONLY) == 0) {
3595:                                            vars[indexReg] = stack[stackTop];
3596:                                            varDbls[indexReg] = sDbl[stackTop];
3597:                                        }
3598:                                    } else {
3599:                                        Object val = stack[stackTop];
3600:                                        if (val == DBL_MRK)
3601:                                            val = ScriptRuntime
3602:                                                    .wrapNumber(sDbl[stackTop]);
3603:                                        stringReg = frame.idata.argNames[indexReg];
3604:                                        frame.scope.put(stringReg, frame.scope,
3605:                                                val);
3606:                                    }
3607:                                    continue Loop;
3608:                                case Icode_GETVAR1:
3609:                                    indexReg = iCode[frame.pc++];
3610:                                    // fallthrough
3611:                                case Token.GETVAR:
3612:                                    ++stackTop;
3613:                                    if (!frame.useActivation) {
3614:                                        stack[stackTop] = vars[indexReg];
3615:                                        sDbl[stackTop] = varDbls[indexReg];
3616:                                    } else {
3617:                                        stringReg = frame.idata.argNames[indexReg];
3618:                                        stack[stackTop] = frame.scope.get(
3619:                                                stringReg, frame.scope);
3620:                                    }
3621:                                    continue Loop;
3622:                                case Icode_VAR_INC_DEC: {
3623:                                    // indexReg : varindex
3624:                                    ++stackTop;
3625:                                    int incrDecrMask = iCode[frame.pc];
3626:                                    if (!frame.useActivation) {
3627:                                        stack[stackTop] = DBL_MRK;
3628:                                        Object varValue = vars[indexReg];
3629:                                        double d;
3630:                                        if (varValue == DBL_MRK) {
3631:                                            d = varDbls[indexReg];
3632:                                        } else {
3633:                                            d = ScriptRuntime
3634:                                                    .toNumber(varValue);
3635:                                            vars[indexReg] = DBL_MRK;
3636:                                        }
3637:                                        double d2 = ((incrDecrMask & Node.DECR_FLAG) == 0) ? d + 1.0
3638:                                                : d - 1.0;
3639:                                        varDbls[indexReg] = d2;
3640:                                        sDbl[stackTop] = ((incrDecrMask & Node.POST_FLAG) == 0) ? d2
3641:                                                : d;
3642:                                    } else {
3643:                                        String varName = frame.idata.argNames[indexReg];
3644:                                        stack[stackTop] = ScriptRuntime
3645:                                                .nameIncrDecr(frame.scope,
3646:                                                        varName, cx,
3647:                                                        incrDecrMask);
3648:                                    }
3649:                                    ++frame.pc;
3650:                                    continue Loop;
3651:                                }
3652:                                case Icode_ZERO:
3653:                                    ++stackTop;
3654:                                    stack[stackTop] = DBL_MRK;
3655:                                    sDbl[stackTop] = 0;
3656:                                    continue Loop;
3657:                                case Icode_ONE:
3658:                                    ++stackTop;
3659:                                    stack[stackTop] = DBL_MRK;
3660:                                    sDbl[stackTop] = 1;
3661:                                    continue Loop;
3662:                                case Token.NULL:
3663:                                    stack[++stackTop] = null;
3664:                                    continue Loop;
3665:                                case Token.THIS:
3666:                                    stack[++stackTop] = frame.this Obj;
3667:                                    continue Loop;
3668:                                case Token.THISFN:
3669:                                    stack[++stackTop] = frame.fnOrScript;
3670:                                    continue Loop;
3671:                                case Token.FALSE:
3672:                                    stack[++stackTop] = Boolean.FALSE;
3673:                                    continue Loop;
3674:                                case Token.TRUE:
3675:                                    stack[++stackTop] = Boolean.TRUE;
3676:                                    continue Loop;
3677:                                case Icode_UNDEF:
3678:                                    stack[++stackTop] = undefined;
3679:                                    continue Loop;
3680:                                case Token.ENTERWITH: {
3681:                                    Object lhs = stack[stackTop];
3682:                                    if (lhs == DBL_MRK)
3683:                                        lhs = ScriptRuntime
3684:                                                .wrapNumber(sDbl[stackTop]);
3685:                                    --stackTop;
3686:                                    frame.scope = ScriptRuntime.enterWith(lhs,
3687:                                            cx, frame.scope);
3688:                                    continue Loop;
3689:                                }
3690:                                case Token.LEAVEWITH:
3691:                                    frame.scope = ScriptRuntime
3692:                                            .leaveWith(frame.scope);
3693:                                    continue Loop;
3694:                                case Token.CATCH_SCOPE: {
3695:                                    // stack top: exception object
3696:                                    // stringReg: name of exception variable
3697:                                    // indexReg: local for exception scope
3698:                                    --stackTop;
3699:                                    indexReg += frame.localShift;
3700:
3701:                                    boolean afterFirstScope = (frame.idata.itsICode[frame.pc] != 0);
3702:                                    Throwable caughtException = (Throwable) stack[stackTop + 1];
3703:                                    Scriptable lastCatchScope;
3704:                                    if (!afterFirstScope) {
3705:                                        lastCatchScope = null;
3706:                                    } else {
3707:                                        lastCatchScope = (Scriptable) stack[indexReg];
3708:                                    }
3709:                                    stack[indexReg] = ScriptRuntime
3710:                                            .newCatchScope(caughtException,
3711:                                                    lastCatchScope, stringReg,
3712:                                                    cx, frame.scope);
3713:                                    ++frame.pc;
3714:                                    continue Loop;
3715:                                }
3716:                                case Token.ENUM_INIT_KEYS:
3717:                                case Token.ENUM_INIT_VALUES:
3718:                                case Token.ENUM_INIT_ARRAY: {
3719:                                    Object lhs = stack[stackTop];
3720:                                    if (lhs == DBL_MRK)
3721:                                        lhs = ScriptRuntime
3722:                                                .wrapNumber(sDbl[stackTop]);
3723:                                    --stackTop;
3724:                                    indexReg += frame.localShift;
3725:                                    int enumType = op == Token.ENUM_INIT_KEYS ? ScriptRuntime.ENUMERATE_KEYS
3726:                                            : op == Token.ENUM_INIT_VALUES ? ScriptRuntime.ENUMERATE_VALUES
3727:                                                    : ScriptRuntime.ENUMERATE_ARRAY;
3728:                                    stack[indexReg] = ScriptRuntime.enumInit(
3729:                                            lhs, cx, enumType);
3730:                                    continue Loop;
3731:                                }
3732:                                case Token.ENUM_NEXT:
3733:                                case Token.ENUM_ID: {
3734:                                    indexReg += frame.localShift;
3735:                                    Object val = stack[indexReg];
3736:                                    ++stackTop;
3737:                                    stack[stackTop] = (op == Token.ENUM_NEXT) ? (Object) ScriptRuntime
3738:                                            .enumNext(val)
3739:                                            : (Object) ScriptRuntime.enumId(
3740:                                                    val, cx);
3741:                                    continue Loop;
3742:                                }
3743:                                case Token.REF_SPECIAL: {
3744:                                    //stringReg: name of special property
3745:                                    Object obj = stack[stackTop];
3746:                                    if (obj == DBL_MRK)
3747:                                        obj = ScriptRuntime
3748:                                                .wrapNumber(sDbl[stackTop]);
3749:                                    stack[stackTop] = ScriptRuntime.specialRef(
3750:                                            obj, stringReg, cx);
3751:                                    continue Loop;
3752:                                }
3753:                                case Token.REF_MEMBER: {
3754:                                    //indexReg: flags
3755:                                    Object elem = stack[stackTop];
3756:                                    if (elem == DBL_MRK)
3757:                                        elem = ScriptRuntime
3758:                                                .wrapNumber(sDbl[stackTop]);
3759:                                    --stackTop;
3760:                                    Object obj = stack[stackTop];
3761:                                    if (obj == DBL_MRK)
3762:                                        obj = ScriptRuntime
3763:                                                .wrapNumber(sDbl[stackTop]);
3764:                                    stack[stackTop] = ScriptRuntime.memberRef(
3765:                                            obj, elem, cx, indexReg);
3766:                                    continue Loop;
3767:                                }
3768:                                case Token.REF_NS_MEMBER: {
3769:                                    //indexReg: flags
3770:                                    Object elem = stack[stackTop];
3771:                                    if (elem == DBL_MRK)
3772:                                        elem = ScriptRuntime
3773:                                                .wrapNumber(sDbl[stackTop]);
3774:                                    --stackTop;
3775:                                    Object ns = stack[stackTop];
3776:                                    if (ns == DBL_MRK)
3777:                                        ns = ScriptRuntime
3778:                                                .wrapNumber(sDbl[stackTop]);
3779:                                    --stackTop;
3780:                                    Object obj = stack[stackTop];
3781:                                    if (obj == DBL_MRK)
3782:                                        obj = ScriptRuntime
3783:                                                .wrapNumber(sDbl[stackTop]);
3784:                                    stack[stackTop] = ScriptRuntime.memberRef(
3785:                                            obj, ns, elem, cx, indexReg);
3786:                                    continue Loop;
3787:                                }
3788:                                case Token.REF_NAME: {
3789:                                    //indexReg: flags
3790:                                    Object name = stack[stackTop];
3791:                                    if (name == DBL_MRK)
3792:                                        name = ScriptRuntime
3793:                                                .wrapNumber(sDbl[stackTop]);
3794:                                    stack[stackTop] = ScriptRuntime.nameRef(
3795:                                            name, cx, frame.scope, indexReg);
3796:                                    continue Loop;
3797:                                }
3798:                                case Token.REF_NS_NAME: {
3799:                                    //indexReg: flags
3800:                                    Object name = stack[stackTop];
3801:                                    if (name == DBL_MRK)
3802:                                        name = ScriptRuntime
3803:                                                .wrapNumber(sDbl[stackTop]);
3804:                                    --stackTop;
3805:                                    Object ns = stack[stackTop];
3806:                                    if (ns == DBL_MRK)
3807:                                        ns = ScriptRuntime
3808:                                                .wrapNumber(sDbl[stackTop]);
3809:                                    stack[stackTop] = ScriptRuntime.nameRef(ns,
3810:                                            name, cx, frame.scope, indexReg);
3811:                                    continue Loop;
3812:                                }
3813:                                case Icode_SCOPE_LOAD:
3814:                                    indexReg += frame.localShift;
3815:                                    frame.scope = (Scriptable) stack[indexReg];
3816:                                    continue Loop;
3817:                                case Icode_SCOPE_SAVE:
3818:                                    indexReg += frame.localShift;
3819:                                    stack[indexReg] = frame.scope;
3820:                                    continue Loop;
3821:                                case Icode_CLOSURE_EXPR:
3822:                                    stack[++stackTop] = InterpretedFunction
3823:                                            .createFunction(cx, frame.scope,
3824:                                                    frame.fnOrScript, indexReg);
3825:                                    continue Loop;
3826:                                case Icode_CLOSURE_STMT:
3827:                                    initFunction(cx, frame.scope,
3828:                                            frame.fnOrScript, indexReg);
3829:                                    continue Loop;
3830:                                case Token.REGEXP:
3831:                                    stack[++stackTop] = frame.scriptRegExps[indexReg];
3832:                                    continue Loop;
3833:                                case Icode_LITERAL_NEW:
3834:                                    // indexReg: number of values in the literal
3835:                                    ++stackTop;
3836:                                    stack[stackTop] = new int[indexReg];
3837:                                    ++stackTop;
3838:                                    stack[stackTop] = new Object[indexReg];
3839:                                    sDbl[stackTop] = 0;
3840:                                    continue Loop;
3841:                                case Icode_LITERAL_SET: {
3842:                                    Object value = stack[stackTop];
3843:                                    if (value == DBL_MRK)
3844:                                        value = ScriptRuntime
3845:                                                .wrapNumber(sDbl[stackTop]);
3846:                                    --stackTop;
3847:                                    int i = (int) sDbl[stackTop];
3848:                                    ((Object[]) stack[stackTop])[i] = value;
3849:                                    sDbl[stackTop] = i + 1;
3850:                                    continue Loop;
3851:                                }
3852:                                case Icode_LITERAL_GETTER: {
3853:                                    Object value = stack[stackTop];
3854:                                    --stackTop;
3855:                                    int i = (int) sDbl[stackTop];
3856:                                    ((Object[]) stack[stackTop])[i] = value;
3857:                                    ((int[]) stack[stackTop - 1])[i] = -1;
3858:                                    sDbl[stackTop] = i + 1;
3859:                                    continue Loop;
3860:                                }
3861:                                case Icode_LITERAL_SETTER: {
3862:                                    Object value = stack[stackTop];
3863:                                    --stackTop;
3864:                                    int i = (int) sDbl[stackTop];
3865:                                    ((Object[]) stack[stackTop])[i] = value;
3866:                                    ((int[]) stack[stackTop - 1])[i] = +1;
3867:                                    sDbl[stackTop] = i + 1;
3868:                                    continue Loop;
3869:                                }
3870:                                case Token.ARRAYLIT:
3871:                                case Icode_SPARE_ARRAYLIT:
3872:                                case Token.OBJECTLIT: {
3873:                                    Object[] data = (Object[]) stack[stackTop];
3874:                                    --stackTop;
3875:                                    int[] getterSetters = (int[]) stack[stackTop];
3876:                                    Object val;
3877:                                    if (op == Token.OBJECTLIT) {
3878:                                        Object[] ids = (Object[]) frame.idata.literalIds[indexReg];
3879:                                        val = ScriptRuntime.newObjectLiteral(
3880:                                                ids, data, getterSetters, cx,
3881:                                                frame.scope);
3882:                                    } else {
3883:                                        int[] skipIndexces = null;
3884:                                        if (op == Icode_SPARE_ARRAYLIT) {
3885:                                            skipIndexces = (int[]) frame.idata.literalIds[indexReg];
3886:                                        }
3887:                                        val = ScriptRuntime.newArrayLiteral(
3888:                                                data, skipIndexces, cx,
3889:                                                frame.scope);
3890:                                    }
3891:                                    stack[stackTop] = val;
3892:                                    continue Loop;
3893:                                }
3894:                                case Icode_ENTERDQ: {
3895:                                    Object lhs = stack[stackTop];
3896:                                    if (lhs == DBL_MRK)
3897:                                        lhs = ScriptRuntime
3898:                                                .wrapNumber(sDbl[stackTop]);
3899:                                    --stackTop;
3900:                                    frame.scope = ScriptRuntime.enterDotQuery(
3901:                                            lhs, frame.scope);
3902:                                    continue Loop;
3903:                                }
3904:                                case Icode_LEAVEDQ: {
3905:                                    boolean valBln = stack_boolean(frame,
3906:                                            stackTop);
3907:                                    Object x = ScriptRuntime.updateDotQuery(
3908:                                            valBln, frame.scope);
3909:                                    if (x != null) {
3910:                                        stack[stackTop] = x;
3911:                                        frame.scope = ScriptRuntime
3912:                                                .leaveDotQuery(frame.scope);
3913:                                        frame.pc += 2;
3914:                                        continue Loop;
3915:                                    }
3916:                                    // reset stack and PC to code after ENTERDQ
3917:                                    --stackTop;
3918:                                    break jumplessRun;
3919:                                }
3920:                                case Token.DEFAULTNAMESPACE: {
3921:                                    Object value = stack[stackTop];
3922:                                    if (value == DBL_MRK)
3923:                                        value = ScriptRuntime
3924:                                                .wrapNumber(sDbl[stackTop]);
3925:                                    stack[stackTop] = ScriptRuntime
3926:                                            .setDefaultNamespace(value, cx);
3927:                                    continue Loop;
3928:                                }
3929:                                case Token.ESCXMLATTR: {
3930:                                    Object value = stack[stackTop];
3931:                                    if (value != DBL_MRK) {
3932:                                        stack[stackTop] = ScriptRuntime
3933:                                                .escapeAttributeValue(value, cx);
3934:                                    }
3935:                                    continue Loop;
3936:                                }
3937:                                case Token.ESCXMLTEXT: {
3938:                                    Object value = stack[stackTop];
3939:                                    if (value != DBL_MRK) {
3940:                                        stack[stackTop] = ScriptRuntime
3941:                                                .escapeTextValue(value, cx);
3942:                                    }
3943:                                    continue Loop;
3944:                                }
3945:                                case Icode_DEBUGGER:
3946:                                    if (frame.debuggerFrame != null) {
3947:                                        frame.debuggerFrame
3948:                                                .onDebuggerStatement(cx);
3949:                                    }
3950:                                    break Loop;
3951:                                case Icode_LINE:
3952:                                    frame.pcSourceLineStart = frame.pc;
3953:                                    if (frame.debuggerFrame != null) {
3954:                                        int line = getIndex(iCode, frame.pc);
3955:                                        frame.debuggerFrame.onLineChange(cx,
3956:                                                line);
3957:                                    }
3958:                                    frame.pc += 2;
3959:                                    continue Loop;
3960:                                case Icode_REG_IND_C0:
3961:                                    indexReg = 0;
3962:                                    continue Loop;
3963:                                case Icode_REG_IND_C1:
3964:                                    indexReg = 1;
3965:                                    continue Loop;
3966:                                case Icode_REG_IND_C2:
3967:                                    indexReg = 2;
3968:                                    continue Loop;
3969:                                case Icode_REG_IND_C3:
3970:                                    indexReg = 3;
3971:                                    continue Loop;
3972:                                case Icode_REG_IND_C4:
3973:                                    indexReg = 4;
3974:                                    continue Loop;
3975:                                case Icode_REG_IND_C5:
3976:                                    indexReg = 5;
3977:                                    continue Loop;
3978:                                case Icode_REG_IND1:
3979:                                    indexReg = 0xFF & iCode[frame.pc];
3980:                                    ++frame.pc;
3981:                                    continue Loop;
3982:                                case Icode_REG_IND2:
3983:                                    indexReg = getIndex(iCode, frame.pc);
3984:                                    frame.pc += 2;
3985:                                    continue Loop;
3986:                                case Icode_REG_IND4:
3987:                                    indexReg = getInt(iCode, frame.pc);
3988:                                    frame.pc += 4;
3989:                                    continue Loop;
3990:                                case Icode_REG_STR_C0:
3991:                                    stringReg = strings[0];
3992:                                    continue Loop;
3993:                                case Icode_REG_STR_C1:
3994:                                    stringReg = strings[1];
3995:                                    continue Loop;
3996:                                case Icode_REG_STR_C2:
3997:                                    stringReg = strings[2];
3998:                                    continue Loop;
3999:                                case Icode_REG_STR_C3:
4000:                                    stringReg = strings[3];
4001:                                    continue Loop;
4002:                                case Icode_REG_STR1:
4003:                                    stringReg = strings[0xFF & iCode[frame.pc]];
4004:                                    ++frame.pc;
4005:                                    continue Loop;
4006:                                case Icode_REG_STR2:
4007:                                    stringReg = strings[getIndex(iCode,
4008:                                            frame.pc)];
4009:                                    frame.pc += 2;
4010:                                    continue Loop;
4011:                                case Icode_REG_STR4:
4012:                                    stringReg = strings[getInt(iCode, frame.pc)];
4013:                                    frame.pc += 4;
4014:                                    continue Loop;
4015:                                default:
4016:                                    dumpICode(frame.idata);
4017:                                    throw new RuntimeException(
4018:                                            "Unknown icode : " + op
4019:                                                    + " @ pc : "
4020:                                                    + (frame.pc - 1));
4021:                                } // end of interpreter switch
4022:
4023:                            } // end of jumplessRun label block
4024:
4025:                            // This should be reachable only for jump implementation
4026:                            // when pc points to encoded target offset
4027:                            if (instructionCounting) {
4028:                                addInstructionCount(cx, frame, 2);
4029:                            }
4030:                            int offset = getShort(iCode, frame.pc);
4031:                            if (offset != 0) {
4032:                                // -1 accounts for pc pointing to jump opcode + 1
4033:                                frame.pc += offset - 1;
4034:                            } else {
4035:                                frame.pc = frame.idata.longJumps
4036:                                        .getExistingInt(frame.pc);
4037:                            }
4038:                            if (instructionCounting) {
4039:                                frame.pcPrevBranch = frame.pc;
4040:                            }
4041:                            continue Loop;
4042:
4043:                        } // end of Loop: for
4044:
4045:                        exitFrame(cx, frame, null);
4046:                        interpreterResult = frame.result;
4047:                        interpreterResultDbl = frame.resultDbl;
4048:                        if (frame.parentFrame != null) {
4049:                            frame = frame.parentFrame;
4050:                            if (frame.frozen) {
4051:                                frame = frame.cloneFrozen();
4052:                            }
4053:                            setCallResult(frame, interpreterResult,
4054:                                    interpreterResultDbl);
4055:                            interpreterResult = null; // Help GC
4056:                            continue StateLoop;
4057:                        }
4058:                        break StateLoop;
4059:
4060:                    } // end of interpreter withoutExceptions: try
4061:                    catch (Throwable ex) {
4062:                        if (throwable != null) {
4063:                            // This is serious bug and it is better to track it ASAP
4064:                            ex.printStackTrace(System.err);
4065:                            throw new IllegalStateException();
4066:                        }
4067:                        throwable = ex;
4068:                    }
4069:
4070:                    // This should be reachable only after above catch or from
4071:                    // finally when it needs to propagate exception or from
4072:                    // explicit throw
4073:                    if (throwable == null)
4074:                        Kit.codeBug();
4075:
4076:                    // Exception type
4077:                    final int EX_CATCH_STATE = 2; // Can execute JS catch
4078:                    final int EX_FINALLY_STATE = 1; // Can execute JS finally
4079:                    final int EX_NO_JS_STATE = 0; // Terminate JS execution
4080:
4081:                    int exState;
4082:                    ContinuationJump cjump = null;
4083:
4084:                    if (generatorState != null
4085:                            && generatorState.operation == NativeGenerator.GENERATOR_CLOSE
4086:                            && throwable == generatorState.value) {
4087:                        exState = EX_FINALLY_STATE;
4088:                    } else if (throwable instanceof  JavaScriptException) {
4089:                        exState = EX_CATCH_STATE;
4090:                    } else if (throwable instanceof  EcmaError) {
4091:                        // an offical ECMA error object,
4092:                        exState = EX_CATCH_STATE;
4093:                    } else if (throwable instanceof  EvaluatorException) {
4094:                        exState = EX_CATCH_STATE;
4095:                    } else if (throwable instanceof  RuntimeException) {
4096:                        exState = cx
4097:                                .hasFeature(Context.FEATURE_ENHANCED_JAVA_ACCESS) ? EX_CATCH_STATE
4098:                                : EX_FINALLY_STATE;
4099:                    } else if (throwable instanceof  Error) {
4100:                        exState = cx
4101:                                .hasFeature(Context.FEATURE_ENHANCED_JAVA_ACCESS) ? EX_CATCH_STATE
4102:                                : EX_NO_JS_STATE;
4103:                    } else if (throwable instanceof  ContinuationJump) {
4104:                        // It must be ContinuationJump
4105:                        exState = EX_FINALLY_STATE;
4106:                        cjump = (ContinuationJump) throwable;
4107:                    } else {
4108:                        exState = cx
4109:                                .hasFeature(Context.FEATURE_ENHANCED_JAVA_ACCESS) ? EX_CATCH_STATE
4110:                                : EX_FINALLY_STATE;
4111:                    }
4112:
4113:                    if (instructionCounting) {
4114:                        try {
4115:                            addInstructionCount(cx, frame, EXCEPTION_COST);
4116:                        } catch (RuntimeException ex) {
4117:                            throwable = ex;
4118:                            exState = EX_FINALLY_STATE;
4119:                        } catch (Error ex) {
4120:                            // Error from instruction counting
4121:                            //     => unconditionally terminate JS
4122:                            throwable = ex;
4123:                            cjump = null;
4124:                            exState = EX_NO_JS_STATE;
4125:                        }
4126:                    }
4127:                    if (frame.debuggerFrame != null
4128:                            && throwable instanceof  RuntimeException) {
4129:                        // Call debugger only for RuntimeException
4130:                        RuntimeException rex = (RuntimeException) throwable;
4131:                        try {
4132:                            frame.debuggerFrame.onExceptionThrown(cx, rex);
4133:                        } catch (Throwable ex) {
4134:                            // Any exception from debugger
4135:                            //     => unconditionally terminate JS
4136:                            throwable = ex;
4137:                            cjump = null;
4138:                            exState = EX_NO_JS_STATE;
4139:                        }
4140:                    }
4141:
4142:                    for (;;) {
4143:                        if (exState != EX_NO_JS_STATE) {
4144:                            boolean onlyFinally = (exState != EX_CATCH_STATE);
4145:                            indexReg = getExceptionHandler(frame, onlyFinally);
4146:                            if (indexReg >= 0) {
4147:                                // We caught an exception, restart the loop
4148:                                // with exception pending the processing at the loop
4149:                                // start
4150:                                continue StateLoop;
4151:                            }
4152:                        }
4153:                        // No allowed exception handlers in this frame, unwind
4154:                        // to parent and try to look there
4155:
4156:                        exitFrame(cx, frame, throwable);
4157:
4158:                        frame = frame.parentFrame;
4159:                        if (frame == null) {
4160:                            break;
4161:                        }
4162:                        if (cjump != null && cjump.branchFrame == frame) {
4163:                            // Continuation branch point was hit,
4164:                            // restart the state loop to reenter continuation
4165:                            indexReg = -1;
4166:                            continue StateLoop;
4167:                        }
4168:                    }
4169:
4170:                    // No more frames, rethrow the exception or deal with continuation
4171:                    if (cjump != null) {
4172:                        if (cjump.branchFrame != null) {
4173:                            // The above loop should locate the top frame
4174:                            Kit.codeBug();
4175:                        }
4176:                        if (cjump.capturedFrame != null) {
4177:                            // Restarting detached continuation
4178:                            indexReg = -1;
4179:                            continue StateLoop;
4180:                        }
4181:                        // Return continuation result to the caller
4182:                        interpreterResult = cjump.result;
4183:                        interpreterResultDbl = cjump.resultDbl;
4184:                        throwable = null;
4185:                    }
4186:                    break StateLoop;
4187:
4188:                } // end of StateLoop: for(;;)
4189:
4190:                // Do cleanups/restorations before the final return or throw
4191:
4192:                if (cx.previousInterpreterInvocations != null
4193:                        && cx.previousInterpreterInvocations.size() != 0) {
4194:                    cx.lastInterpreterFrame = cx.previousInterpreterInvocations
4195:                            .pop();
4196:                } else {
4197:                    // It was the last interpreter frame on the stack
4198:                    cx.lastInterpreterFrame = null;
4199:                    // Force GC of the value cx.previousInterpreterInvocations
4200:                    cx.previousInterpreterInvocations = null;
4201:                }
4202:
4203:                if (throwable != null) {
4204:                    if (throwable instanceof  RuntimeException) {
4205:                        throw (RuntimeException) throwable;
4206:                    } else {
4207:                        // Must be instance of Error or code bug
4208:                        throw (Error) throwable;
4209:                    }
4210:                }
4211:
4212:                return (interpreterResult != DBL_MRK) ? interpreterResult
4213:                        : ScriptRuntime.wrapNumber(interpreterResultDbl);
4214:            }
4215:
4216:            private static CallFrame processThrowable(Context cx,
4217:                    Object throwable, CallFrame frame, int indexReg,
4218:                    boolean instructionCounting) {
4219:                // Recovering from exception, indexReg contains
4220:                // the index of handler
4221:
4222:                if (indexReg >= 0) {
4223:                    // Normal exception handler, transfer
4224:                    // control appropriately
4225:
4226:                    if (frame.frozen) {
4227:                        // XXX Deal with exceptios!!!
4228:                        frame = frame.cloneFrozen();
4229:                    }
4230:
4231:                    int[] table = frame.idata.itsExceptionTable;
4232:
4233:                    frame.pc = table[indexReg + EXCEPTION_HANDLER_SLOT];
4234:                    if (instructionCounting) {
4235:                        frame.pcPrevBranch = frame.pc;
4236:                    }
4237:
4238:                    frame.savedStackTop = frame.emptyStackTop;
4239:                    int scopeLocal = frame.localShift
4240:                            + table[indexReg + EXCEPTION_SCOPE_SLOT];
4241:                    int exLocal = frame.localShift
4242:                            + table[indexReg + EXCEPTION_LOCAL_SLOT];
4243:                    frame.scope = (Scriptable) frame.stack[scopeLocal];
4244:                    frame.stack[exLocal] = throwable;
4245:
4246:                    throwable = null;
4247:                } else {
4248:                    // Continuation restoration
4249:                    ContinuationJump cjump = (ContinuationJump) throwable;
4250:
4251:                    // Clear throwable to indicate that exceptions are OK
4252:                    throwable = null;
4253:
4254:                    if (cjump.branchFrame != frame)
4255:                        Kit.codeBug();
4256:
4257:                    // Check that we have at least one frozen frame
4258:                    // in the case of detached continuation restoration:
4259:                    // unwind code ensure that
4260:                    if (cjump.capturedFrame == null)
4261:                        Kit.codeBug();
4262:
4263:                    // Need to rewind branchFrame, capturedFrame
4264:                    // and all frames in between
4265:                    int rewindCount = cjump.capturedFrame.frameIndex + 1;
4266:                    if (cjump.branchFrame != null) {
4267:                        rewindCount -= cjump.branchFrame.frameIndex;
4268:                    }
4269:
4270:                    int enterCount = 0;
4271:                    CallFrame[] enterFrames = null;
4272:
4273:                    CallFrame x = cjump.capturedFrame;
4274:                    for (int i = 0; i != rewindCount; ++i) {
4275:                        if (!x.frozen)
4276:                            Kit.codeBug();
4277:                        if (isFrameEnterExitRequired(x)) {
4278:                            if (enterFrames == null) {
4279:                                // Allocate enough space to store the rest
4280:                                // of rewind frames in case all of them
4281:                                // would require to enter
4282:                                enterFrames = new CallFrame[rewindCount - i];
4283:                            }
4284:                            enterFrames[enterCount] = x;
4285:                            ++enterCount;
4286:                        }
4287:                        x = x.parentFrame;
4288:                    }
4289:
4290:                    while (enterCount != 0) {
4291:                        // execute enter: walk enterFrames in the reverse
4292:                        // order since they were stored starting from
4293:                        // the capturedFrame, not branchFrame
4294:                        --enterCount;
4295:                        x = enterFrames[enterCount];
4296:                        enterFrame(cx, x, ScriptRuntime.emptyArgs, true);
4297:                    }
4298:
4299:                    // Continuation jump is almost done: capturedFrame
4300:                    // points to the call to the function that captured
4301:                    // continuation, so clone capturedFrame and
4302:                    // emulate return that function with the suplied result
4303:                    frame = cjump.capturedFrame.cloneFrozen();
4304:                    setCallResult(frame, cjump.result, cjump.resultDbl);
4305:                    // restart the execution
4306:                }
4307:                frame.throwable = throwable;
4308:                return frame;
4309:            }
4310:
4311:            private static Object freezeGenerator(Context cx, CallFrame frame,
4312:                    int stackTop, GeneratorState generatorState) {
4313:                if (generatorState.operation == NativeGenerator.GENERATOR_CLOSE) {
4314:                    // Error: no yields when generator is closing
4315:                    throw ScriptRuntime.typeError0("msg.yield.closing");
4316:                }
4317:                // return to our caller (which should be a method of NativeGenerator)
4318:                frame.frozen = true;
4319:                frame.result = frame.stack[stackTop];
4320:                frame.resultDbl = frame.sDbl[stackTop];
4321:                frame.savedStackTop = stackTop;
4322:                frame.pc--; // we want to come back here when we resume
4323:                ScriptRuntime.exitActivationFunction(cx);
4324:                return (frame.result != UniqueTag.DOUBLE_MARK) ? frame.result
4325:                        : ScriptRuntime.wrapNumber(frame.resultDbl);
4326:            }
4327:
4328:            private static Object thawGenerator(CallFrame frame, int stackTop,
4329:                    GeneratorState generatorState, int op) {
4330:                // we are resuming execution
4331:                frame.frozen = false;
4332:                int sourceLine = getIndex(frame.idata.itsICode, frame.pc);
4333:                frame.pc += 2; // skip line number data
4334:                if (generatorState.operation == NativeGenerator.GENERATOR_THROW) {
4335:                    // processing a call to <generator>.throw(exception): must
4336:                    // act as if exception was thrown from resumption point
4337:                    return new JavaScriptException(generatorState.value,
4338:                            frame.idata.itsSourceFile, sourceLine);
4339:                }
4340:                if (generatorState.operation == NativeGenerator.GENERATOR_CLOSE) {
4341:                    return generatorState.value;
4342:                }
4343:                if (generatorState.operation != NativeGenerator.GENERATOR_SEND)
4344:                    throw Kit.codeBug();
4345:                if (op == Token.YIELD)
4346:                    frame.stack[stackTop] = generatorState.value;
4347:                return Scriptable.NOT_FOUND;
4348:            }
4349:
4350:            private static CallFrame initFrameForApplyOrCall(Context cx,
4351:                    CallFrame frame, int indexReg, Object[] stack,
4352:                    double[] sDbl, int stackTop, int op,
4353:                    Scriptable calleeScope, IdFunctionObject ifun,
4354:                    InterpretedFunction iApplyCallable) {
4355:                Scriptable applyThis;
4356:                if (indexReg != 0) {
4357:                    applyThis = ScriptRuntime.toObjectOrNull(cx,
4358:                            stack[stackTop + 2]);
4359:                } else {
4360:                    applyThis = null;
4361:                }
4362:                if (applyThis == null) {
4363:                    // This covers the case of args[0] == (null|undefined) as well.
4364:                    applyThis = ScriptRuntime.getTopCallScope(cx);
4365:                }
4366:                if (op == Icode_TAIL_CALL) {
4367:                    exitFrame(cx, frame, null);
4368:                    frame = frame.parentFrame;
4369:                } else {
4370:                    frame.savedStackTop = stackTop;
4371:                    frame.savedCallOp = op;
4372:                }
4373:                CallFrame calleeFrame = new CallFrame();
4374:                if (BaseFunction.isApply(ifun)) {
4375:                    Object[] callArgs = indexReg < 2 ? ScriptRuntime.emptyArgs
4376:                            : ScriptRuntime.getApplyArguments(cx,
4377:                                    stack[stackTop + 3]);
4378:                    initFrame(cx, calleeScope, applyThis, callArgs, null, 0,
4379:                            callArgs.length, iApplyCallable, frame, calleeFrame);
4380:                } else {
4381:                    // Shift args left
4382:                    for (int i = 1; i < indexReg; ++i) {
4383:                        stack[stackTop + 1 + i] = stack[stackTop + 2 + i];
4384:                        sDbl[stackTop + 1 + i] = sDbl[stackTop + 2 + i];
4385:                    }
4386:                    int argCount = indexReg < 2 ? 0 : indexReg - 1;
4387:                    initFrame(cx, calleeScope, applyThis, stack, sDbl,
4388:                            stackTop + 2, argCount, iApplyCallable, frame,
4389:                            calleeFrame);
4390:                }
4391:
4392:                frame = calleeFrame;
4393:                return frame;
4394:            }
4395:
4396:            private static void initFrame(Context cx, Scriptable callerScope,
4397:                    Scriptable this Obj, Object[] args, double[] argsDbl,
4398:                    int argShift, int argCount, InterpretedFunction fnOrScript,
4399:                    CallFrame parentFrame, CallFrame frame) {
4400:                InterpreterData idata = fnOrScript.idata;
4401:
4402:                boolean useActivation = idata.itsNeedsActivation;
4403:                DebugFrame debuggerFrame = null;
4404:                if (cx.debugger != null) {
4405:                    debuggerFrame = cx.debugger.getFrame(cx, idata);
4406:                    if (debuggerFrame != null) {
4407:                        useActivation = true;
4408:                    }
4409:                }
4410:
4411:                if (useActivation) {
4412:                    // Copy args to new array to pass to enterActivationFunction
4413:                    // or debuggerFrame.onEnter
4414:                    if (argsDbl != null) {
4415:                        args = getArgsArray(args, argsDbl, argShift, argCount);
4416:                    }
4417:                    argShift = 0;
4418:                    argsDbl = null;
4419:                }
4420:
4421:                Scriptable scope;
4422:                if (idata.itsFunctionType != 0) {
4423:                    if (!idata.useDynamicScope) {
4424:                        scope = fnOrScript.getParentScope();
4425:                    } else {
4426:                        scope = callerScope;
4427:                    }
4428:
4429:                    if (useActivation) {
4430:                        scope = ScriptRuntime.createFunctionActivation(
4431:                                fnOrScript, scope, args);
4432:                    }
4433:                } else {
4434:                    scope = callerScope;
4435:                    ScriptRuntime.initScript(fnOrScript, this Obj, cx, scope,
4436:                            fnOrScript.idata.evalScriptFlag);
4437:                }
4438:
4439:                if (idata.itsNestedFunctions != null) {
4440:                    if (idata.itsFunctionType != 0 && !idata.itsNeedsActivation)
4441:                        Kit.codeBug();
4442:                    for (int i = 0; i < idata.itsNestedFunctions.length; i++) {
4443:                        InterpreterData fdata = idata.itsNestedFunctions[i];
4444:                        if (fdata.itsFunctionType == FunctionNode.FUNCTION_STATEMENT) {
4445:                            initFunction(cx, scope, fnOrScript, i);
4446:                        }
4447:                    }
4448:                }
4449:
4450:                Scriptable[] scriptRegExps = null;
4451:                if (idata.itsRegExpLiterals != null) {
4452:                    // Wrapped regexps for functions are stored in
4453:                    // InterpretedFunction
4454:                    // but for script which should not contain references to scope
4455:                    // the regexps re-wrapped during each script execution
4456:                    if (idata.itsFunctionType != 0) {
4457:                        scriptRegExps = fnOrScript.functionRegExps;
4458:                    } else {
4459:                        scriptRegExps = fnOrScript.createRegExpWraps(cx, scope);
4460:                    }
4461:                }
4462:
4463:                // Initialize args, vars, locals and stack
4464:
4465:                int emptyStackTop = idata.itsMaxVars + idata.itsMaxLocals - 1;
4466:                int maxFrameArray = idata.itsMaxFrameArray;
4467:                if (maxFrameArray != emptyStackTop + idata.itsMaxStack + 1)
4468:                    Kit.codeBug();
4469:
4470:                Object[] stack;
4471:                int[] stackAttributes;
4472:                double[] sDbl;
4473:                boolean stackReuse;
4474:                if (frame.stack != null && maxFrameArray <= frame.stack.length) {
4475:                    // Reuse stacks from old frame
4476:                    stackReuse = true;
4477:                    stack = frame.stack;
4478:                    stackAttributes = frame.stackAttributes;
4479:                    sDbl = frame.sDbl;
4480:                } else {
4481:                    stackReuse = false;
4482:                    stack = new Object[maxFrameArray];
4483:                    stackAttributes = new int[maxFrameArray];
4484:                    sDbl = new double[maxFrameArray];
4485:                }
4486:
4487:                int varCount = idata.getParamAndVarCount();
4488:                for (int i = 0; i < varCount; i++) {
4489:                    if (idata.getParamOrVarConst(i))
4490:                        stackAttributes[i] = ScriptableObject.CONST;
4491:                }
4492:                int definedArgs = idata.argCount;
4493:                if (definedArgs > argCount) {
4494:                    definedArgs = argCount;
4495:                }
4496:
4497:                // Fill the frame structure
4498:
4499:                frame.parentFrame = parentFrame;
4500:                frame.frameIndex = (parentFrame == null) ? 0
4501:                        : parentFrame.frameIndex + 1;
4502:                if (frame.frameIndex > cx.getMaximumInterpreterStackDepth()) {
4503:                    throw Context
4504:                            .reportRuntimeError("Exceeded maximum stack depth");
4505:                }
4506:                frame.frozen = false;
4507:
4508:                frame.fnOrScript = fnOrScript;
4509:                frame.idata = idata;
4510:
4511:                frame.stack = stack;
4512:                frame.stackAttributes = stackAttributes;
4513:                frame.sDbl = sDbl;
4514:                frame.varSource = frame;
4515:                frame.localShift = idata.itsMaxVars;
4516:                frame.emptyStackTop = emptyStackTop;
4517:
4518:                frame.debuggerFrame = debuggerFrame;
4519:                frame.useActivation = useActivation;
4520:
4521:                frame.this Obj = this Obj;
4522:                frame.scriptRegExps = scriptRegExps;
4523:
4524:                // Initialize initial values of variables that change during
4525:                // interpretation.
4526:                frame.result = Undefined.instance;
4527:                frame.pc = 0;
4528:                frame.pcPrevBranch = 0;
4529:                frame.pcSourceLineStart = idata.firstLinePC;
4530:                frame.scope = scope;
4531:
4532:                frame.savedStackTop = emptyStackTop;
4533:                frame.savedCallOp = 0;
4534:
4535:                System.arraycopy(args, argShift, stack, 0, definedArgs);
4536:                if (argsDbl != null) {
4537:                    System.arraycopy(argsDbl, argShift, sDbl, 0, definedArgs);
4538:                }
4539:                for (int i = definedArgs; i != idata.itsMaxVars; ++i) {
4540:                    stack[i] = Undefined.instance;
4541:                }
4542:                if (stackReuse) {
4543:                    // Clean the stack part and space beyond stack if any
4544:                    // of the old array to allow to GC objects there
4545:                    for (int i = emptyStackTop + 1; i != stack.length; ++i) {
4546:                        stack[i] = null;
4547:                    }
4548:                }
4549:
4550:                enterFrame(cx, frame, args, false);
4551:            }
4552:
4553:            private static boolean isFrameEnterExitRequired(CallFrame frame) {
4554:                return frame.debuggerFrame != null
4555:                        || frame.idata.itsNeedsActivation;
4556:            }
4557:
4558:            private static void enterFrame(Context cx, CallFrame frame,
4559:                    Object[] args, boolean continuationRestart) {
4560:                boolean usesActivation = frame.idata.itsNeedsActivation;
4561:                boolean isDebugged = frame.debuggerFrame != null;
4562:                if (usesActivation || isDebugged) {
4563:                    Scriptable scope = frame.scope;
4564:                    if (scope == null) {
4565:                        Kit.codeBug();
4566:                    } else if (continuationRestart) {
4567:                        // Walk the parent chain of frame.scope until a NativeCall is 
4568:                        // found. Normally, frame.scope is a NativeCall when called 
4569:                        // from initFrame() for a debugged or activatable function. 
4570:                        // However, when called from interpretLoop() as part of
4571:                        // restarting a continuation, it can also be a NativeWith if 
4572:                        // the continuation was captured within a "with" or "catch" 
4573:                        // block ("catch" implicitly uses NativeWith to create a scope 
4574:                        // to expose the exception variable).
4575:                        for (;;) {
4576:                            if (scope instanceof  NativeWith) {
4577:                                scope = scope.getParentScope();
4578:                                if (scope == null
4579:                                        || (frame.parentFrame != null && frame.parentFrame.scope == scope)) {
4580:                                    // If we get here, we didn't find a NativeCall in 
4581:                                    // the call chain before reaching parent frame's 
4582:                                    // scope. This should not be possible.
4583:                                    Kit.codeBug();
4584:                                    break; // Never reached, but keeps the static analyzer happy about "scope" not being null 5 lines above.
4585:                                }
4586:                            } else {
4587:                                break;
4588:                            }
4589:                        }
4590:                    }
4591:                    if (isDebugged) {
4592:                        frame.debuggerFrame.onEnter(cx, scope, frame.this Obj,
4593:                                args);
4594:                    }
4595:                    // Enter activation only when itsNeedsActivation true, 
4596:                    // since debugger should not interfere with activation 
4597:                    // chaining
4598:                    if (usesActivation) {
4599:                        ScriptRuntime.enterActivationFunction(cx, scope);
4600:                    }
4601:                }
4602:            }
4603:
4604:            private static void exitFrame(Context cx, CallFrame frame,
4605:                    Object throwable) {
4606:                if (frame.idata.itsNeedsActivation) {
4607:                    ScriptRuntime.exitActivationFunction(cx);
4608:                }
4609:
4610:                if (frame.debuggerFrame != null) {
4611:                    try {
4612:                        if (throwable instanceof  Throwable) {
4613:                            frame.debuggerFrame.onExit(cx, true, throwable);
4614:                        } else {
4615:                            Object result;
4616:                            ContinuationJump cjump = (ContinuationJump) throwable;
4617:                            if (cjump == null) {
4618:                                result = frame.result;
4619:                            } else {
4620:                                result = cjump.result;
4621:                            }
4622:                            if (result == UniqueTag.DOUBLE_MARK) {
4623:                                double resultDbl;
4624:                                if (cjump == null) {
4625:                                    resultDbl = frame.resultDbl;
4626:                                } else {
4627:                                    resultDbl = cjump.resultDbl;
4628:                                }
4629:                                result = ScriptRuntime.wrapNumber(resultDbl);
4630:                            }
4631:                            frame.debuggerFrame.onExit(cx, false, result);
4632:                        }
4633:                    } catch (Throwable ex) {
4634:                        System.err
4635:                                .println("RHINO USAGE WARNING: onExit terminated with exception");
4636:                        ex.printStackTrace(System.err);
4637:                    }
4638:                }
4639:            }
4640:
4641:            private static void setCallResult(CallFrame frame,
4642:                    Object callResult, double callResultDbl) {
4643:                if (frame.savedCallOp == Token.CALL) {
4644:                    frame.stack[frame.savedStackTop] = callResult;
4645:                    frame.sDbl[frame.savedStackTop] = callResultDbl;
4646:                } else if (frame.savedCallOp == Token.NEW) {
4647:                    // If construct returns scriptable,
4648:                    // then it replaces on stack top saved original instance
4649:                    // of the object.
4650:                    if (callResult instanceof  Scriptable) {
4651:                        frame.stack[frame.savedStackTop] = callResult;
4652:                    }
4653:                } else {
4654:                    Kit.codeBug();
4655:                }
4656:                frame.savedCallOp = 0;
4657:            }
4658:
4659:            private static void captureContinuation(Context cx,
4660:                    CallFrame frame, int stackTop) {
4661:                Continuation c = new Continuation();
4662:                ScriptRuntime.setObjectProtoAndParent(c, ScriptRuntime
4663:                        .getTopCallScope(cx));
4664:
4665:                // Make sure that all frames upstack frames are frozen
4666:                CallFrame x = frame.parentFrame;
4667:                while (x != null && !x.frozen) {
4668:                    x.frozen = true;
4669:                    // Allow to GC unused stack space
4670:                    for (int i = x.savedStackTop + 1; i != x.stack.length; ++i) {
4671:                        // Allow to GC unused stack space
4672:                        x.stack[i] = null;
4673:                        x.stackAttributes[i] = ScriptableObject.EMPTY;
4674:                    }
4675:                    if (x.savedCallOp == Token.CALL) {
4676:                        // the call will always overwrite the stack top with the result
4677:                        x.stack[x.savedStackTop] = null;
4678:                    } else {
4679:                        if (x.savedCallOp != Token.NEW)
4680:                            Kit.codeBug();
4681:                        // the new operator uses stack top to store the constructed
4682:                        // object so it shall not be cleared: see comments in
4683:                        // setCallResult
4684:                    }
4685:                    x = x.parentFrame;
4686:                }
4687:
4688:                c.initImplementation(frame.parentFrame);
4689:                frame.stack[stackTop] = c;
4690:            }
4691:
4692:            private static int stack_int32(CallFrame frame, int i) {
4693:                Object x = frame.stack[i];
4694:                double value;
4695:                if (x == UniqueTag.DOUBLE_MARK) {
4696:                    value = frame.sDbl[i];
4697:                } else {
4698:                    value = ScriptRuntime.toNumber(x);
4699:                }
4700:                return ScriptRuntime.toInt32(value);
4701:            }
4702:
4703:            private static double stack_double(CallFrame frame, int i) {
4704:                Object x = frame.stack[i];
4705:                if (x != UniqueTag.DOUBLE_MARK) {
4706:                    return ScriptRuntime.toNumber(x);
4707:                } else {
4708:                    return frame.sDbl[i];
4709:                }
4710:            }
4711:
4712:            private static boolean stack_boolean(CallFrame frame, int i) {
4713:                Object x = frame.stack[i];
4714:                if (x == Boolean.TRUE) {
4715:                    return true;
4716:                } else if (x == Boolean.FALSE) {
4717:                    return false;
4718:                } else if (x == UniqueTag.DOUBLE_MARK) {
4719:                    double d = frame.sDbl[i];
4720:                    return d == d && d != 0.0;
4721:                } else if (x == null || x == Undefined.instance) {
4722:                    return false;
4723:                } else if (x instanceof  Number) {
4724:                    double d = ((Number) x).doubleValue();
4725:                    return (d == d && d != 0.0);
4726:                } else if (x instanceof  Boolean) {
4727:                    return ((Boolean) x).booleanValue();
4728:                } else {
4729:                    return ScriptRuntime.toBoolean(x);
4730:                }
4731:            }
4732:
4733:            private static void do_add(Object[] stack, double[] sDbl,
4734:                    int stackTop, Context cx) {
4735:                Object rhs = stack[stackTop + 1];
4736:                Object lhs = stack[stackTop];
4737:                double d;
4738:                boolean leftRightOrder;
4739:                if (rhs == UniqueTag.DOUBLE_MARK) {
4740:                    d = sDbl[stackTop + 1];
4741:                    if (lhs == UniqueTag.DOUBLE_MARK) {
4742:                        sDbl[stackTop] += d;
4743:                        return;
4744:                    }
4745:                    leftRightOrder = true;
4746:                    // fallthrough to object + number code
4747:                } else if (lhs == UniqueTag.DOUBLE_MARK) {
4748:                    d = sDbl[stackTop];
4749:                    lhs = rhs;
4750:                    leftRightOrder = false;
4751:                    // fallthrough to object + number code
4752:                } else {
4753:                    if (lhs instanceof  Scriptable || rhs instanceof  Scriptable) {
4754:                        stack[stackTop] = ScriptRuntime.add(lhs, rhs, cx);
4755:                    } else if (lhs instanceof  String) {
4756:                        String lstr = (String) lhs;
4757:                        String rstr = ScriptRuntime.toString(rhs);
4758:                        stack[stackTop] = lstr.concat(rstr);
4759:                    } else if (rhs instanceof  String) {
4760:                        String lstr = ScriptRuntime.toString(lhs);
4761:                        String rstr = (String) rhs;
4762:                        stack[stackTop] = lstr.concat(rstr);
4763:                    } else {
4764:                        double lDbl = (lhs instanceof  Number) ? ((Number) lhs)
4765:                                .doubleValue() : ScriptRuntime.toNumber(lhs);
4766:                        double rDbl = (rhs instanceof  Number) ? ((Number) rhs)
4767:                                .doubleValue() : ScriptRuntime.toNumber(rhs);
4768:                        stack[stackTop] = UniqueTag.DOUBLE_MARK;
4769:                        sDbl[stackTop] = lDbl + rDbl;
4770:                    }
4771:                    return;
4772:                }
4773:
4774:                // handle object(lhs) + number(d) code
4775:                if (lhs instanceof  Scriptable) {
4776:                    rhs = ScriptRuntime.wrapNumber(d);
4777:                    if (!leftRightOrder) {
4778:                        Object tmp = lhs;
4779:                        lhs = rhs;
4780:                        rhs = tmp;
4781:                    }
4782:                    stack[stackTop] = ScriptRuntime.add(lhs, rhs, cx);
4783:                } else if (lhs instanceof  String) {
4784:                    String lstr = (String) lhs;
4785:                    String rstr = ScriptRuntime.toString(d);
4786:                    if (leftRightOrder) {
4787:                        stack[stackTop] = lstr.concat(rstr);
4788:                    } else {
4789:                        stack[stackTop] = rstr.concat(lstr);
4790:                    }
4791:                } else {
4792:                    double lDbl = (lhs instanceof  Number) ? ((Number) lhs)
4793:                            .doubleValue() : ScriptRuntime.toNumber(lhs);
4794:                    stack[stackTop] = UniqueTag.DOUBLE_MARK;
4795:                    sDbl[stackTop] = lDbl + d;
4796:                }
4797:            }
4798:
4799:            private static Object[] getArgsArray(Object[] stack, double[] sDbl,
4800:                    int shift, int count) {
4801:                if (count == 0) {
4802:                    return ScriptRuntime.emptyArgs;
4803:                }
4804:                Object[] args = new Object[count];
4805:                for (int i = 0; i != count; ++i, ++shift) {
4806:                    Object val = stack[shift];
4807:                    if (val == UniqueTag.DOUBLE_MARK) {
4808:                        val = ScriptRuntime.wrapNumber(sDbl[shift]);
4809:                    }
4810:                    args[i] = val;
4811:                }
4812:                return args;
4813:            }
4814:
4815:            private static void addInstructionCount(Context cx,
4816:                    CallFrame frame, int extra) {
4817:                cx.instructionCount += frame.pc - frame.pcPrevBranch + extra;
4818:                if (cx.instructionCount > cx.instructionThreshold) {
4819:                    cx.observeInstructionCount(cx.instructionCount);
4820:                    cx.instructionCount = 0;
4821:                }
4822:            }
4823:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.