Просмотр исходного кода

Refactor TS compiler to not use the precompile step & also 64bit support

- Reduces headaches
- Expands STE entry size to allow for 64bit values
- Bonus: Adds in function lookup optimization from T2D
James Urquhart 11 лет назад
Родитель
Сommit
1e44586606

+ 71 - 79
Engine/source/console/ast.h

@@ -27,6 +27,7 @@ class ExprEvalState;
 class Namespace;
 class SimObject;
 class SimGroup;
+class CodeStream;
 
 /// Enable this #define if you are seeing the message "precompile size mismatch" in the console.
 /// This will help track down which node type is causing the error. It could be
@@ -77,15 +78,13 @@ struct StmtNode
    /// @name Breaking
    /// @{
 
-   void addBreakCount();
-   void addBreakLine(U32 ip);
+   void addBreakLine(CodeStream &codeStream);
    /// @}
 
    /// @name Compilation
    /// @{
 
-   virtual U32 precompileStmt(U32 loopCount) = 0;
-   virtual U32 compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint) = 0;
+   virtual U32 compileStmt(CodeStream &codeStream, U32 ip) = 0;
    virtual void setPackage(StringTableEntry packageName);
    /// @}
 };
@@ -101,27 +100,26 @@ struct BreakStmtNode : StmtNode
 {
    static BreakStmtNode *alloc( S32 lineNumber );
 
-   U32 precompileStmt(U32 loopCount);
-   U32 compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint);
+   
+   U32 compileStmt(CodeStream &codeStream, U32 ip);
    DBG_STMT_TYPE(BreakStmtNode);
 };
 
 struct ContinueStmtNode : StmtNode
 {
    static ContinueStmtNode *alloc( S32 lineNumber );
-   U32 precompileStmt(U32 loopCount);
-   U32 compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint);
+   
+   U32 compileStmt(CodeStream &codeStream, U32 ip);
    DBG_STMT_TYPE(ContinueStmtNode);
 };
 
 /// A mathematical expression.
 struct ExprNode : StmtNode
 {
-   U32 precompileStmt(U32 loopCount);
-   U32 compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint);
+   
+   U32 compileStmt(CodeStream &codeStream, U32 ip);
 
-   virtual U32 precompile(TypeReq type) = 0;
-   virtual U32 compile(U32 *codeStream, U32 ip, TypeReq type) = 0;
+   virtual U32 compile(CodeStream &codeStream, U32 ip, TypeReq type) = 0;
    virtual TypeReq getPreferredType() = 0;
 };
 
@@ -130,8 +128,8 @@ struct ReturnStmtNode : StmtNode
    ExprNode *expr;
 
    static ReturnStmtNode *alloc( S32 lineNumber, ExprNode *expr );
-   U32 precompileStmt(U32 loopCount);
-   U32 compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint);
+   
+   U32 compileStmt(CodeStream &codeStream, U32 ip);
    DBG_STMT_TYPE(ReturnStmtNode);
 };
 
@@ -147,8 +145,8 @@ struct IfStmtNode : StmtNode
    static IfStmtNode *alloc( S32 lineNumber, ExprNode *testExpr, StmtNode *ifBlock, StmtNode *elseBlock, bool propagateThrough );
    void propagateSwitchExpr(ExprNode *left, bool string);
    ExprNode *getSwitchOR(ExprNode *left, ExprNode *list, bool string);
-   U32 precompileStmt(U32 loopCount);
-   U32 compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint);
+   
+   U32 compileStmt(CodeStream &codeStream, U32 ip);
    DBG_STMT_TYPE(IfStmtNode);
 };
 
@@ -165,8 +163,8 @@ struct LoopStmtNode : StmtNode
    bool integer;
 
    static LoopStmtNode *alloc( S32 lineNumber, ExprNode *testExpr, ExprNode *initExpr, ExprNode *endLoopExpr, StmtNode *loopBlock, bool isDoLoop );
-   U32 precompileStmt(U32 loopCount);
-   U32 compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint);
+   
+   U32 compileStmt(CodeStream &codeStream, U32 ip);
    DBG_STMT_TYPE(LoopStmtNode);
 };
 
@@ -190,8 +188,7 @@ struct IterStmtNode : StmtNode
    
    static IterStmtNode* alloc( S32 lineNumber, StringTableEntry varName, ExprNode* containerExpr, StmtNode* body, bool isStringIter );
    
-   U32 precompileStmt( U32 loopCount );
-   U32 compileStmt( U32* codeStream, U32 ip, U32 continuePoint, U32 breakPoint );
+   U32 compileStmt( CodeStream &codeStream, U32 ip );
 };
 
 /// A binary mathematical expression (ie, left op right).
@@ -205,8 +202,8 @@ struct BinaryExprNode : ExprNode
 struct FloatBinaryExprNode : BinaryExprNode
 {
    static FloatBinaryExprNode *alloc( S32 lineNumber, S32 op, ExprNode *left, ExprNode *right );
-   U32 precompile(TypeReq type);
-   U32 compile(U32 *codeStream, U32 ip, TypeReq type);
+  
+   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    DBG_STMT_TYPE(FloatBinaryExprNode);
 };
@@ -218,8 +215,8 @@ struct ConditionalExprNode : ExprNode
    ExprNode *falseExpr;
    bool integer;
    static ConditionalExprNode *alloc( S32 lineNumber, ExprNode *testExpr, ExprNode *trueExpr, ExprNode *falseExpr );
-   virtual U32 precompile(TypeReq type);
-   virtual U32 compile(U32 *codeStream, U32 ip, TypeReq type);
+   
+   virtual U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
    virtual TypeReq getPreferredType();
    DBG_STMT_TYPE(ConditionalExprNode);
 };
@@ -232,8 +229,8 @@ struct IntBinaryExprNode : BinaryExprNode
    static IntBinaryExprNode *alloc( S32 lineNumber, S32 op, ExprNode *left, ExprNode *right );
 
    void getSubTypeOperand();
-   U32 precompile(TypeReq type);
-   U32 compile(U32 *codeStream, U32 ip, TypeReq type);
+   
+   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    DBG_STMT_TYPE(IntBinaryExprNode);
 };
@@ -242,8 +239,8 @@ struct StreqExprNode : BinaryExprNode
 {
    bool eq;
    static StreqExprNode *alloc( S32 lineNumber, ExprNode *left, ExprNode *right, bool eq );
-   U32 precompile(TypeReq type);
-   U32 compile(U32 *codeStream, U32 ip, TypeReq type);
+   
+   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    DBG_STMT_TYPE(StreqExprNode);
 };
@@ -252,8 +249,8 @@ struct StrcatExprNode : BinaryExprNode
 {
    S32 appendChar;
    static StrcatExprNode *alloc( S32 lineNumber, ExprNode *left, ExprNode *right, S32 appendChar );
-   U32 precompile(TypeReq type);
-   U32 compile(U32 *codeStream, U32 ip, TypeReq type);
+  
+   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    DBG_STMT_TYPE(StrcatExprNode);
 };
@@ -262,8 +259,8 @@ struct CommaCatExprNode : BinaryExprNode
 {
    static CommaCatExprNode *alloc( S32 lineNumber, ExprNode *left, ExprNode *right );
 
-   U32 precompile(TypeReq type);
-   U32 compile(U32 *codeStream, U32 ip, TypeReq type);
+  
+   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    DBG_STMT_TYPE(CommaCatExprNode);
 };
@@ -275,8 +272,8 @@ struct IntUnaryExprNode : ExprNode
    bool integer;
 
    static IntUnaryExprNode *alloc( S32 lineNumber, S32 op, ExprNode *expr );
-   U32 precompile(TypeReq type);
-   U32 compile(U32 *codeStream, U32 ip, TypeReq type);
+  
+   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    DBG_STMT_TYPE(IntUnaryExprNode);
 };
@@ -287,8 +284,8 @@ struct FloatUnaryExprNode : ExprNode
    ExprNode *expr;
 
    static FloatUnaryExprNode *alloc( S32 lineNumber, S32 op, ExprNode *expr );
-   U32 precompile(TypeReq type);
-   U32 compile(U32 *codeStream, U32 ip, TypeReq type);
+  
+   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    DBG_STMT_TYPE(FloatUnaryExprNode);
 };
@@ -299,8 +296,8 @@ struct VarNode : ExprNode
    ExprNode *arrayIndex;
 
    static VarNode *alloc( S32 lineNumber, StringTableEntry varName, ExprNode *arrayIndex );
-   U32 precompile(TypeReq type);
-   U32 compile(U32 *codeStream, U32 ip, TypeReq type);
+  
+   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    DBG_STMT_TYPE(VarNode);
 };
@@ -311,8 +308,8 @@ struct IntNode : ExprNode
    U32 index; // if it's converted to float/string
 
    static IntNode *alloc( S32 lineNumber, S32 value );
-   U32 precompile(TypeReq type);
-   U32 compile(U32 *codeStream, U32 ip, TypeReq type);
+  
+   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    DBG_STMT_TYPE(IntNode);
 };
@@ -323,8 +320,8 @@ struct FloatNode : ExprNode
    U32 index;
 
    static FloatNode *alloc( S32 lineNumber, F64 value );
-   U32 precompile(TypeReq type);
-   U32 compile(U32 *codeStream, U32 ip, TypeReq type);
+  
+   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    DBG_STMT_TYPE(FloatNode);
 };
@@ -338,8 +335,8 @@ struct StrConstNode : ExprNode
    bool doc; // Specifies that this string is a documentation block.
 
    static StrConstNode *alloc( S32 lineNumber, char *str, bool tag, bool doc = false );
-   U32 precompile(TypeReq type);
-   U32 compile(U32 *codeStream, U32 ip, TypeReq type);
+  
+   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    DBG_STMT_TYPE(StrConstNode);
 };
@@ -351,8 +348,8 @@ struct ConstantNode : ExprNode
    U32 index;
 
    static ConstantNode *alloc( S32 lineNumber, StringTableEntry value );
-   U32 precompile(TypeReq type);
-   U32 compile(U32 *codeStream, U32 ip, TypeReq type);
+  
+   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    DBG_STMT_TYPE(ConstantNode);
 };
@@ -365,8 +362,8 @@ struct AssignExprNode : ExprNode
    TypeReq subType;
 
    static AssignExprNode *alloc( S32 lineNumber, StringTableEntry varName, ExprNode *arrayIndex, ExprNode *expr );
-   U32 precompile(TypeReq type);
-   U32 compile(U32 *codeStream, U32 ip, TypeReq type);
+  
+   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    DBG_STMT_TYPE(AssignExprNode);
 };
@@ -389,8 +386,8 @@ struct AssignOpExprNode : ExprNode
    TypeReq subType;
 
    static AssignOpExprNode *alloc( S32 lineNumber, StringTableEntry varName, ExprNode *arrayIndex, ExprNode *expr, S32 op );
-   U32 precompile(TypeReq type);
-   U32 compile(U32 *codeStream, U32 ip, TypeReq type);
+  
+   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    DBG_STMT_TYPE(AssignOpExprNode);
 };
@@ -402,8 +399,8 @@ struct TTagSetStmtNode : StmtNode
    ExprNode *stringExpr;
 
    static TTagSetStmtNode *alloc( S32 lineNumber, StringTableEntry tag, ExprNode *valueExpr, ExprNode *stringExpr );
-   U32 precompileStmt(U32 loopCount);
-   U32 compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint);
+   
+   U32 compileStmt(CodeStream &codeStream, U32 ip);
    DBG_STMT_TYPE(TTagSetStmtNode);
 };
 
@@ -412,8 +409,8 @@ struct TTagDerefNode : ExprNode
    ExprNode *expr;
 
    static TTagDerefNode *alloc( S32 lineNumber, ExprNode *expr );
-   U32 precompile(TypeReq type);
-   U32 compile(U32 *codeStream, U32 ip, TypeReq type);
+  
+   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    DBG_STMT_TYPE(TTagDerefNode);
 };
@@ -423,8 +420,8 @@ struct TTagExprNode : ExprNode
    StringTableEntry tag;
 
    static TTagExprNode *alloc( S32 lineNumber, StringTableEntry tag );
-   U32 precompile(TypeReq type);
-   U32 compile(U32 *codeStream, U32 ip, TypeReq type);
+  
+   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    DBG_STMT_TYPE(TTagExprNode);
 };
@@ -442,8 +439,8 @@ struct FuncCallExprNode : ExprNode
    };
 
    static FuncCallExprNode *alloc( S32 lineNumber, StringTableEntry funcName, StringTableEntry nameSpace, ExprNode *args, bool dot );
-   U32 precompile(TypeReq type);
-   U32 compile(U32 *codeStream, U32 ip, TypeReq type);
+  
+   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    DBG_STMT_TYPE(FuncCallExprNode);
 };
@@ -455,8 +452,8 @@ struct AssertCallExprNode : ExprNode
    U32 messageIndex;
 
    static AssertCallExprNode *alloc( S32 lineNumber, ExprNode *testExpr, const char *message );
-   U32 precompile(TypeReq type);
-   U32 compile(U32 *codeStream, U32 ip, TypeReq type);
+  
+   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    DBG_STMT_TYPE(AssertCallExprNode);
 };
@@ -475,8 +472,8 @@ struct SlotAccessNode : ExprNode
    StringTableEntry slotName;
 
    static SlotAccessNode *alloc( S32 lineNumber, ExprNode *objectExpr, ExprNode *arrayExpr, StringTableEntry slotName );
-   U32 precompile(TypeReq type);
-   U32 compile(U32 *codeStream, U32 ip, TypeReq type);
+  
+   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    DBG_STMT_TYPE(SlotAccessNode);
 };
@@ -495,8 +492,8 @@ struct InternalSlotAccessNode : ExprNode
    bool recurse;
 
    static InternalSlotAccessNode *alloc( S32 lineNumber, ExprNode *objectExpr, ExprNode *slotExpr, bool recurse );
-   U32 precompile(TypeReq type);
-   U32 compile(U32 *codeStream, U32 ip, TypeReq type);
+  
+   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    DBG_STMT_TYPE(InternalSlotAccessNode);
 };
@@ -509,8 +506,8 @@ struct SlotAssignNode : ExprNode
    U32 typeID;
 
    static SlotAssignNode *alloc( S32 lineNumber, ExprNode *objectExpr, ExprNode *arrayExpr, StringTableEntry slotName, ExprNode *valueExpr, U32 typeID = -1 );
-   U32 precompile(TypeReq type);
-   U32 compile(U32 *codeStream, U32 ip, TypeReq type);
+  
+   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    DBG_STMT_TYPE(SlotAssignNode);
 };
@@ -525,8 +522,8 @@ struct SlotAssignOpNode : ExprNode
    TypeReq subType;
 
    static SlotAssignOpNode *alloc( S32 lineNumber, ExprNode *objectExpr, StringTableEntry slotName, ExprNode *arrayExpr, S32 op, ExprNode *valueExpr );
-   U32 precompile(TypeReq type);
-   U32 compile(U32 *codeStream, U32 ip, TypeReq type);
+  
+   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    DBG_STMT_TYPE(SlotAssignOpNode);
 };
@@ -545,10 +542,10 @@ struct ObjectDeclNode : ExprNode
    bool isSingleton;
 
    static ObjectDeclNode *alloc( S32 lineNumber, ExprNode *classNameExpr, ExprNode *objectNameExpr, ExprNode *argList, StringTableEntry parentObject, SlotAssignNode *slotDecls, ObjectDeclNode *subObjects, bool isDatablock, bool classNameInternal, bool isSingleton );
-   U32 precompile(TypeReq type);
+  
    U32 precompileSubObject(bool);
-   U32 compile(U32 *codeStream, U32 ip, TypeReq type);
-   U32 compileSubObject(U32 *codeStream, U32 ip, bool);
+   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
+   U32 compileSubObject(CodeStream &codeStream, U32 ip, bool);
    TypeReq getPreferredType();
    DBG_STMT_TYPE(ObjectDeclNode);
 };
@@ -570,18 +567,13 @@ struct FunctionDeclStmtNode : StmtNode
    U32 argc;
 
    static FunctionDeclStmtNode *alloc( S32 lineNumber, StringTableEntry fnName, StringTableEntry nameSpace, VarNode *args, StmtNode *stmts );
-   U32 precompileStmt(U32 loopCount);
-   U32 compileStmt(U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint);
+   
+   U32 compileStmt(CodeStream &codeStream, U32 ip);
    void setPackage(StringTableEntry packageName);
    DBG_STMT_TYPE(FunctionDeclStmtNode);
 };
 
 extern StmtNode *gStatementList;
-extern void createFunction(const char *fnName, VarNode *args, StmtNode *statements);
-extern ExprEvalState gEvalState;
-extern bool lookupFunction(const char *fnName, VarNode **args, StmtNode **statements);
-typedef const char *(*cfunc)(S32 argc, char **argv);
-extern bool lookupCFunction(const char *fnName, cfunc *f);
-
+extern ExprEvalState gEvalState;;
 
 #endif

Разница между файлами не показана из-за своего большого размера
+ 214 - 417
Engine/source/console/astNodes.cpp


+ 94 - 78
Engine/source/console/codeBlock.cpp

@@ -33,7 +33,6 @@
 using namespace Compiler;
 
 bool           CodeBlock::smInFunction = false;
-U32            CodeBlock::smBreakLineCount = 0;
 CodeBlock *    CodeBlock::smCodeBlockList = NULL;
 CodeBlock *    CodeBlock::smCurrentCodeBlock = NULL;
 ConsoleParser *CodeBlock::smCurrentParser = NULL;
@@ -456,6 +455,8 @@ bool CodeBlock::read(StringTableEntry fileName, Stream &st)
 
 bool CodeBlock::compile(const char *codeFileName, StringTableEntry fileName, const char *inScript, bool overrideNoDso)
 {
+	AssertFatal(Con::isMainThread(), "Compiling code on a secondary thread");
+	
    // This will return true, but return value is ignored
    char *script;
    chompUTF8BOM( inScript, &script );
@@ -464,7 +465,7 @@ bool CodeBlock::compile(const char *codeFileName, StringTableEntry fileName, con
 
    consoleAllocReset();
 
-   STEtoU32 = compileSTEtoU32;
+   STEtoCode = compileSTEtoCode;
 
    gStatementList = NULL;
 
@@ -497,17 +498,23 @@ bool CodeBlock::compile(const char *codeFileName, StringTableEntry fileName, con
    resetTables();
 
    smInFunction = false;
-   smBreakLineCount = 0;
-   setBreakCodeBlock(this);
 
+   CodeStream codeStream;
+   U32 lastIp;
    if(gStatementList)
-      codeSize = precompileBlock(gStatementList, 0) + 1;
+   {
+      lastIp = compileBlock(gStatementList, codeStream, 0) + 1;
+   }
    else
+   {
       codeSize = 1;
-
-   lineBreakPairCount = smBreakLineCount;
-   code = new U32[codeSize + smBreakLineCount * 2];
-   lineBreakPairs = code + codeSize;
+      lastIp = 0;
+   }
+   
+   codeStream.emit(OP_RETURN);
+   codeStream.emitCodeStream(&codeSize, &code, &lineBreakPairs);
+   
+   lineBreakPairCount = codeStream.getNumLineBreaks();
 
    // Write string table data...
    getGlobalStringTable().write(st);
@@ -517,18 +524,10 @@ bool CodeBlock::compile(const char *codeFileName, StringTableEntry fileName, con
    getGlobalFloatTable().write(st);
    getFunctionFloatTable().write(st);
 
-   smBreakLineCount = 0;
-   U32 lastIp;
-   if(gStatementList)
-      lastIp = compileBlock(gStatementList, code, 0, 0, 0);
-   else
-      lastIp = 0;
-
-   if(lastIp != codeSize - 1)
+   if(lastIp != codeSize)
       Con::errorf(ConsoleLogEntry::General, "CodeBlock::compile - precompile size mismatch, a precompile/compile function pair is probably mismatched.");
-
-   code[lastIp++] = OP_RETURN;
-   U32 totSize = codeSize + smBreakLineCount * 2;
+   
+   U32 totSize = codeSize + codeStream.getNumLineBreaks() * 2;
    st.write(codeSize);
    st.write(lineBreakPairCount);
 
@@ -561,11 +560,13 @@ bool CodeBlock::compile(const char *codeFileName, StringTableEntry fileName, con
 
 const char *CodeBlock::compileExec(StringTableEntry fileName, const char *inString, bool noCalls, S32 setFrame)
 {
+	AssertFatal(Con::isMainThread(), "Compiling code on a secondary thread");
+	
    // Check for a UTF8 script file
    char *string;
    chompUTF8BOM( inString, &string );
 
-   STEtoU32 = evalSTEtoU32;
+   STEtoCode = evalSTEtoCode;
    consoleAllocReset();
 
    name = fileName;
@@ -617,12 +618,11 @@ const char *CodeBlock::compileExec(StringTableEntry fileName, const char *inStri
    resetTables();
 
    smInFunction = false;
-   smBreakLineCount = 0;
-   setBreakCodeBlock(this);
-
-   codeSize = precompileBlock(gStatementList, 0) + 1;
+   
+   CodeStream codeStream;
+   U32 lastIp = compileBlock(gStatementList, codeStream, 0);
 
-   lineBreakPairCount = smBreakLineCount;
+   lineBreakPairCount = codeStream.getNumLineBreaks();
 
    globalStrings   = getGlobalStringTable().build();
    globalStringsMaxLen = getGlobalStringTable().totalLen;
@@ -632,20 +632,19 @@ const char *CodeBlock::compileExec(StringTableEntry fileName, const char *inStri
 
    globalFloats    = getGlobalFloatTable().build();
    functionFloats  = getFunctionFloatTable().build();
-
-   code = new U32[codeSize + lineBreakPairCount * 2];
-   lineBreakPairs = code + codeSize;
-
-   smBreakLineCount = 0;
-   U32 lastIp = compileBlock(gStatementList, code, 0, 0, 0);
-   code[lastIp++] = OP_RETURN;
+   
+   codeStream.emit(OP_RETURN);
+   codeStream.emitCodeStream(&codeSize, &code, &lineBreakPairs);
+   
+   
+   dumpInstructions(0, false);
    
    consoleAllocReset();
 
    if(lineBreakPairCount && fileName)
       calcBreakList();
 
-   if(lastIp != codeSize)
+   if(lastIp+1 != codeSize)
       Con::warnf(ConsoleLogEntry::General, "precompile size mismatch, precompile: %d compile: %d", codeSize, lastIp);
 
    return exec(0, fileName, NULL, 0, 0, noCalls, NULL, setFrame);
@@ -674,7 +673,7 @@ String CodeBlock::getFunctionArgs( U32 ip )
    U32 fnArgc = code[ ip + 5 ];
    for( U32 i = 0; i < fnArgc; ++ i )
    {
-      StringTableEntry var = U32toSTE( code[ ip + i + 6 ] );
+      StringTableEntry var = CodeToSTE(code, ip + (i*2) + 6);
       
       if( i != 0 )
          str.append( ", " );
@@ -696,41 +695,52 @@ String CodeBlock::getFunctionArgs( U32 ip )
 void CodeBlock::dumpInstructions( U32 startIp, bool upToReturn )
 {
    U32 ip = startIp;
+   smInFunction = false;
+   U32 endFuncIp = 0;
+   
    while( ip < codeSize )
    {
+      if (ip > endFuncIp)
+      {
+         smInFunction = false;
+      }
+      
       switch( code[ ip ++ ] )
       {
+            
          case OP_FUNC_DECL:
          {
-            StringTableEntry fnName       = U32toSTE(code[ip]);
-            StringTableEntry fnNamespace  = U32toSTE(code[ip+1]);
-            StringTableEntry fnPackage    = U32toSTE(code[ip+2]);
-            bool hasBody = bool(code[ip+3]);
-            U32 newIp = code[ ip + 4 ];
-            U32 argc = code[ ip + 5 ];
+            StringTableEntry fnName       = CodeToSTE(code, ip);
+            StringTableEntry fnNamespace  = CodeToSTE(code, ip+2);
+            StringTableEntry fnPackage    = CodeToSTE(code, ip+4);
+            bool hasBody = bool(code[ip+6]);
+            U32 newIp = code[ ip + 7 ];
+            U32 argc = code[ ip + 8 ];
+            endFuncIp = newIp;
             
             Con::printf( "%i: OP_FUNC_DECL name=%s nspace=%s package=%s hasbody=%i newip=%i argc=%i",
                ip - 1, fnName, fnNamespace, fnPackage, hasBody, newIp, argc );
                
             // Skip args.
                            
-            ip += 6 + argc;
+            ip += 9 + (argc * 2);
+            smInFunction = true;
             break;
          }
             
          case OP_CREATE_OBJECT:
          {
-            StringTableEntry objParent = U32toSTE(code[ip    ]);
-            bool isDataBlock =          code[ip + 1];
-            bool isInternal  =          code[ip + 2];
-            bool isSingleton =          code[ip + 3];
-            U32  lineNumber  =          code[ip + 4];
-            U32 failJump     =          code[ip + 5];
+            StringTableEntry objParent = CodeToSTE(code, ip);
+            bool isDataBlock =          code[ip + 2];
+            bool isInternal  =          code[ip + 3];
+            bool isSingleton =          code[ip + 4];
+            U32  lineNumber  =          code[ip + 5];
+            U32 failJump     =          code[ip + 6];
             
             Con::printf( "%i: OP_CREATE_OBJECT objParent=%s isDataBlock=%i isInternal=%i isSingleton=%i lineNumber=%i failJump=%i",
                ip - 1, objParent, isDataBlock, isInternal, isSingleton, lineNumber, failJump );
 
-            ip += 6;
+            ip += 7;
             break;
          }
 
@@ -957,19 +967,19 @@ void CodeBlock::dumpInstructions( U32 startIp, bool upToReturn )
 
          case OP_SETCURVAR:
          {
-            StringTableEntry var = U32toSTE(code[ip]);
+            StringTableEntry var = CodeToSTE(code, ip);
             
             Con::printf( "%i: OP_SETCURVAR var=%s", ip - 1, var );
-            ip++;
+            ip += 2;
             break;
          }
          
          case OP_SETCURVAR_CREATE:
          {
-            StringTableEntry var = U32toSTE(code[ip]);
+            StringTableEntry var = CodeToSTE(code, ip);
             
             Con::printf( "%i: OP_SETCURVAR_CREATE var=%s", ip - 1, var );
-            ip++;
+            ip += 2;
             break;
          }
          
@@ -1042,9 +1052,10 @@ void CodeBlock::dumpInstructions( U32 startIp, bool upToReturn )
          
          case OP_SETCURFIELD:
          {
-            StringTableEntry curField = U32toSTE(code[ip]);
+            StringTableEntry curField = CodeToSTE(code, ip);
             Con::printf( "%i: OP_SETCURFIELD field=%s", ip - 1, curField );
-            ++ ip;
+            ip += 2;
+            break;
          }
          
          case OP_SETCURFIELD_ARRAY:
@@ -1161,7 +1172,7 @@ void CodeBlock::dumpInstructions( U32 startIp, bool upToReturn )
 
          case OP_LOADIMMED_FLT:
          {
-            F64 val = functionFloats[ code[ ip ] ];
+            F64 val = (smInFunction ? functionFloats : globalFloats)[ code[ ip ] ];
             Con::printf( "%i: OP_LOADIMMED_FLT val=%f", ip - 1, val );
             ++ ip;
             break;
@@ -1169,7 +1180,7 @@ void CodeBlock::dumpInstructions( U32 startIp, bool upToReturn )
 
          case OP_TAG_TO_STR:
          {
-            const char* str = functionStrings + code[ ip ];
+            const char* str = (smInFunction ? functionStrings : globalStrings) + code[ ip ];
             Con::printf( "%i: OP_TAG_TO_STR str=%s", ip - 1, str );
             ++ ip;
             break;
@@ -1177,7 +1188,7 @@ void CodeBlock::dumpInstructions( U32 startIp, bool upToReturn )
          
          case OP_LOADIMMED_STR:
          {
-            const char* str = functionStrings + code[ ip ];
+            const char* str = (smInFunction ? functionStrings : globalStrings) + code[ ip ];
             Con::printf( "%i: OP_LOADIMMED_STR str=%s", ip - 1, str );
             ++ ip;
             break;
@@ -1185,7 +1196,7 @@ void CodeBlock::dumpInstructions( U32 startIp, bool upToReturn )
 
          case OP_DOCBLOCK_STR:
          {
-            const char* str = functionStrings + code[ ip ];
+            const char* str = (smInFunction ? functionStrings : globalStrings) + code[ ip ];
             Con::printf( "%i: OP_DOCBLOCK_STR str=%s", ip - 1, str );
             ++ ip;
             break;
@@ -1193,37 +1204,37 @@ void CodeBlock::dumpInstructions( U32 startIp, bool upToReturn )
          
          case OP_LOADIMMED_IDENT:
          {
-            StringTableEntry str = U32toSTE( code[ ip ] );
+            StringTableEntry str = CodeToSTE(code, ip);
             Con::printf( "%i: OP_LOADIMMED_IDENT str=%s", ip - 1, str );
-            ++ ip;
+            ip += 2;
             break;
          }
 
          case OP_CALLFUNC_RESOLVE:
          {
-            StringTableEntry fnNamespace = U32toSTE(code[ip+1]);
-            StringTableEntry fnName      = U32toSTE(code[ip]);
+            StringTableEntry fnNamespace = CodeToSTE(code, ip+2);
+            StringTableEntry fnName      = CodeToSTE(code, ip);
             U32 callType = code[ip+2];
 
             Con::printf( "%i: OP_CALLFUNC_RESOLVE name=%s nspace=%s callType=%s", ip - 1, fnName, fnNamespace,
                callType == FuncCallExprNode::FunctionCall ? "FunctionCall"
                   : callType == FuncCallExprNode::MethodCall ? "MethodCall" : "ParentCall" );
             
-            ip += 3;
+            ip += 5;
             break;
          }
          
          case OP_CALLFUNC:
          {
-            StringTableEntry fnNamespace = U32toSTE(code[ip+1]);
-            StringTableEntry fnName      = U32toSTE(code[ip]);
-            U32 callType = code[ip+2];
+            StringTableEntry fnNamespace = CodeToSTE(code, ip+2);
+            StringTableEntry fnName      = CodeToSTE(code, ip);
+            U32 callType = code[ip+4];
 
             Con::printf( "%i: OP_CALLFUNC name=%s nspace=%s callType=%s", ip - 1, fnName, fnNamespace,
                callType == FuncCallExprNode::FunctionCall ? "FunctionCall"
                   : callType == FuncCallExprNode::MethodCall ? "MethodCall" : "ParentCall" );
             
-            ip += 3;
+            ip += 5;
             break;
          }
 
@@ -1285,7 +1296,7 @@ void CodeBlock::dumpInstructions( U32 startIp, bool upToReturn )
 
          case OP_ASSERT:
          {
-            const char* message = functionStrings + code[ ip ];
+            const char* message = (smInFunction ? functionStrings : globalStrings) + code[ ip ];
             Con::printf( "%i: OP_ASSERT message=%s", ip - 1, message );
             ++ ip;
             break;
@@ -1299,31 +1310,34 @@ void CodeBlock::dumpInstructions( U32 startIp, bool upToReturn )
          
          case OP_ITER_BEGIN:
          {
-            StringTableEntry varName = U32toSTE( code[ ip ] );
-            U32 failIp = code[ ip + 1 ];
+            StringTableEntry varName = CodeToSTE(code, ip);
+            U32 failIp = code[ ip + 2 ];
             
-            Con::printf( "%i: OP_ITER_BEGIN varName=%s failIp=%i", varName, failIp );
+            Con::printf( "%i: OP_ITER_BEGIN varName=%s failIp=%i", ip - 1, varName, failIp );
 
-            ++ ip;
+            ip += 3;
+            break;
          }
 
          case OP_ITER_BEGIN_STR:
          {
-            StringTableEntry varName = U32toSTE( code[ ip ] );
-            U32 failIp = code[ ip + 1 ];
+            StringTableEntry varName = CodeToSTE(code, ip);
+            U32 failIp = code[ ip + 2 ];
             
-            Con::printf( "%i: OP_ITER_BEGIN varName=%s failIp=%i", varName, failIp );
+            Con::printf( "%i: OP_ITER_BEGIN varName=%s failIp=%i", ip - 1, varName, failIp );
 
-            ip += 2;
+            ip += 3;
+            break;
          }
          
          case OP_ITER:
          {
             U32 breakIp = code[ ip ];
             
-            Con::printf( "%i: OP_ITER breakIp=%i", breakIp );
+            Con::printf( "%i: OP_ITER breakIp=%i", ip - 1, breakIp );
 
             ++ ip;
+            break;
          }
          
          case OP_ITER_END:
@@ -1337,4 +1351,6 @@ void CodeBlock::dumpInstructions( U32 startIp, bool upToReturn )
             break;
       }
    }
+   
+   smInFunction = false;
 }

+ 0 - 1
Engine/source/console/codeBlock.h

@@ -38,7 +38,6 @@ private:
    static CodeBlock* smCurrentCodeBlock;
    
 public:
-   static U32                       smBreakLineCount;
    static bool                      smInFunction;
    static Compiler::ConsoleParser * smCurrentParser;
 

+ 55 - 42
Engine/source/console/compiledEval.cpp

@@ -422,8 +422,8 @@ const char *CodeBlock::exec(U32 ip, const char *functionName, Namespace *thisNam
    if(argv)
    {
       // assume this points into a function decl:
-      U32 fnArgc = code[ip + 5];
-      thisFunctionName = U32toSTE(code[ip]);
+      U32 fnArgc = code[ip + 2 + 6];
+      thisFunctionName = CodeToSTE(code, ip);
       argc = getMin(argc-1, fnArgc); // argv[0] is func name
       if(gEvalState.traceOn)
       {
@@ -458,11 +458,11 @@ const char *CodeBlock::exec(U32 ip, const char *functionName, Namespace *thisNam
       popFrame = true;
       for(i = 0; i < argc; i++)
       {
-         StringTableEntry var = U32toSTE(code[ip + i + 6]);
+         StringTableEntry var = CodeToSTE(code, ip + (2 + 6 + 1) + (i * 2));
          gEvalState.setCurVarNameCreate(var);
          gEvalState.setStringVariable(argv[i+1]);
       }
-      ip = ip + fnArgc + 6;
+      ip = ip + (fnArgc * 2) + (2 + 6 + 1);
       curFloatTable = functionFloats;
       curStringTable = functionStrings;
       curStringTableLen = functionStringsMaxLen;
@@ -559,11 +559,11 @@ breakContinue:
          case OP_FUNC_DECL:
             if(!noCalls)
             {
-               fnName       = U32toSTE(code[ip]);
-               fnNamespace  = U32toSTE(code[ip+1]);
-               fnPackage    = U32toSTE(code[ip+2]);
-               bool hasBody = ( code[ ip + 3 ] & 0x01 ) != 0;
-               U32 lineNumber = code[ ip + 3 ] >> 1;
+               fnName       = CodeToSTE(code, ip);
+               fnNamespace  = CodeToSTE(code, ip+2);
+               fnPackage    = CodeToSTE(code, ip+4);
+               bool hasBody = ( code[ ip + 6 ] & 0x01 ) != 0;
+               U32 lineNumber = code[ ip + 6 ] >> 1;
                
                Namespace::unlinkPackages();
                ns = Namespace::find(fnNamespace, fnPackage);
@@ -586,18 +586,18 @@ breakContinue:
 
                //Con::printf("Adding function %s::%s (%d)", fnNamespace, fnName, ip);
             }
-            ip = code[ip + 4];
+            ip = code[ip + 7];
             break;
 
          case OP_CREATE_OBJECT:
          {
             // Read some useful info.
-            objParent        = U32toSTE(code[ip    ]);
-            bool isDataBlock =          code[ip + 1];
-            bool isInternal  =          code[ip + 2];
-            bool isSingleton =          code[ip + 3];
-            U32  lineNumber  =          code[ip + 4];
-            failJump         =          code[ip + 5];
+            objParent        = CodeToSTE(code, ip);
+            bool isDataBlock =          code[ip + 2];
+            bool isInternal  =          code[ip + 3];
+            bool isSingleton =          code[ip + 4];
+            U32  lineNumber  =          code[ip + 5];
+            failJump         =          code[ip + 6];
                         
             // If we don't allow calls, we certainly don't allow creating objects!
             // Moved this to after failJump is set. Engine was crashing when
@@ -848,7 +848,7 @@ breakContinue:
             }
 
             // Advance the IP past the create info...
-            ip += 6;
+            ip += 7;
             break;
          }
 
@@ -1170,8 +1170,8 @@ breakContinue:
             break;
 
          case OP_SETCURVAR:
-            var = U32toSTE(code[ip]);
-            ip++;
+            var = CodeToSTE(code, ip);
+            ip += 2;
 
             // If a variable is set, then these must be NULL. It is necessary
             // to set this here so that the vector parser can appropriately
@@ -1190,8 +1190,8 @@ breakContinue:
             break;
 
          case OP_SETCURVAR_CREATE:
-            var = U32toSTE(code[ip]);
-            ip++;
+            var = CodeToSTE(code, ip);
+            ip += 2;
 
 			// See OP_SETCURVAR
             prevField = NULL;
@@ -1310,9 +1310,9 @@ breakContinue:
             // Save the previous field for parsing vector fields.
             prevField = curField;
             dStrcpy( prevFieldArray, curFieldArray );
-            curField = U32toSTE(code[ip]);
+            curField = CodeToSTE(code, ip);
             curFieldArray[0] = 0;
-            ip++;
+            ip += 2;
             break;
 
          case OP_SETCURFIELD_ARRAY:
@@ -1504,28 +1504,38 @@ breakContinue:
             break;
 
          case OP_LOADIMMED_IDENT:
-            STR.setStringValue(U32toSTE(code[ip++]));
+            STR.setStringValue(CodeToSTE(code, ip));
+            ip += 2;
             break;
 
          case OP_CALLFUNC_RESOLVE:
             // This deals with a function that is potentially living in a namespace.
-            fnNamespace = U32toSTE(code[ip+1]);
-            fnName      = U32toSTE(code[ip]);
+            fnNamespace = CodeToSTE(code, ip+2);
+            fnName      = CodeToSTE(code, ip);
 
             // Try to look it up.
             ns = Namespace::find(fnNamespace);
             nsEntry = ns->lookup(fnName);
             if(!nsEntry)
             {
-               ip+= 3;
+               ip+= 5;
                Con::warnf(ConsoleLogEntry::General,
                   "%s: Unable to find function %s%s%s",
-                  getFileLine(ip-4), fnNamespace ? fnNamespace : "",
+                  getFileLine(ip-7), fnNamespace ? fnNamespace : "",
                   fnNamespace ? "::" : "", fnName);
                STR.popFrame();
                break;
             }
+            
             // Now fall through to OP_CALLFUNC...
+            // Now, rewrite our code a bit (ie, avoid future lookups) and fall
+            // through to OP_CALLFUNC
+#ifdef TORQUE_64
+            *((U64*)(code+ip+2)) = ((U64)nsEntry);
+#else
+            code[ip+2] = ((U32)nsEntry);
+#endif
+            code[ip-1] = OP_CALLFUNC;
 
          case OP_CALLFUNC:
          {
@@ -1535,7 +1545,7 @@ breakContinue:
             // or just on the object.
             S32 routingId = 0;
 
-            fnName = U32toSTE(code[ip]);
+            fnName = CodeToSTE(code, ip);
 
             //if this is called from inside a function, append the ip and codeptr
             if( gEvalState.getStackDepth() > 0 )
@@ -1544,9 +1554,9 @@ breakContinue:
                gEvalState.getCurrentFrame().ip = ip - 1;
             }
 
-            U32 callType = code[ip+2];
+            U32 callType = code[ip+4];
 
-            ip += 3;
+            ip += 5;
             STR.getArgcArgv(fnName, &callArgc, &callArgv);
 
             const char *componentReturnValue = "";
@@ -1555,9 +1565,12 @@ breakContinue:
             {
                if( !nsEntry )
                {
-                  // We must not have come from OP_CALLFUNC_RESOLVE, so figure out
-                  // our own entry.
-                  nsEntry = Namespace::global()->lookup( fnName );
+#ifdef TORQUE_64
+                  nsEntry = ((Namespace::Entry *) *((U64*)(code+ip-3)));
+#else
+                  nsEntry = ((Namespace::Entry *) *(code+ip-3));
+#endif
+                  ns = NULL;
                }
                ns = NULL;
             }
@@ -1618,7 +1631,7 @@ breakContinue:
             {
                if(!noCalls && !( routingId == MethodOnComponent ) )
                {
-                  Con::warnf(ConsoleLogEntry::General,"%s: Unknown command %s.", getFileLine(ip-4), fnName);
+                  Con::warnf(ConsoleLogEntry::General,"%s: Unknown command %s.", getFileLine(ip-6), fnName);
                   if(callType == FuncCallExprNode::MethodCall)
                   {
                      Con::warnf(ConsoleLogEntry::General, "  Object %s(%d) %s",
@@ -1652,16 +1665,16 @@ breakContinue:
                // which is useful behavior when debugging so I'm ifdefing this out for debug builds.
                if(nsEntry->mToolOnly && ! Con::isCurrentScriptToolScript())
                {
-                  Con::errorf(ConsoleLogEntry::Script, "%s: %s::%s - attempting to call tools only function from outside of tools.", getFileLine(ip-4), nsName, fnName);
+                  Con::errorf(ConsoleLogEntry::Script, "%s: %s::%s - attempting to call tools only function from outside of tools.", getFileLine(ip-6), nsName, fnName);
                }
                else
 #endif
                if((nsEntry->mMinArgs && S32(callArgc) < nsEntry->mMinArgs) || (nsEntry->mMaxArgs && S32(callArgc) > nsEntry->mMaxArgs))
                {
                   Con::warnf(ConsoleLogEntry::Script, "%s: %s::%s - wrong number of arguments (got %i, expected min %i and max %i).",
-                     getFileLine(ip-4), nsName, fnName,
+                     getFileLine(ip-6), nsName, fnName,
                      callArgc, nsEntry->mMinArgs, nsEntry->mMaxArgs);
-                  Con::warnf(ConsoleLogEntry::Script, "%s: usage: %s", getFileLine(ip-4), nsEntry->mUsage);
+                  Con::warnf(ConsoleLogEntry::Script, "%s: usage: %s", getFileLine(ip-6), nsEntry->mUsage);
                   STR.popFrame();
                }
                else
@@ -1725,7 +1738,7 @@ breakContinue:
                      case Namespace::Entry::VoidCallbackType:
                         nsEntry->cb.mVoidCallbackFunc(gEvalState.thisObject, callArgc, callArgv);
                         if( code[ ip ] != OP_STR_TO_NONE && Con::getBoolVariable( "$Con::warnVoidAssignment", true ) )
-                           Con::warnf(ConsoleLogEntry::General, "%s: Call to %s in %s uses result of void function call.", getFileLine(ip-4), fnName, functionName);
+                           Con::warnf(ConsoleLogEntry::General, "%s: Call to %s in %s uses result of void function call.", getFileLine(ip-6), fnName, functionName);
                         
                         STR.popFrame();
                         STR.setStringValue("");
@@ -1844,8 +1857,8 @@ breakContinue:
          
          case OP_ITER_BEGIN:
          {
-            StringTableEntry varName = U32toSTE( code[ ip ] );
-            U32 failIp = code[ ip + 1 ];
+            StringTableEntry varName = CodeToSTE(code, ip);
+            U32 failIp = code[ ip + 2 ];
             
             IterStackRecord& iter = iterStack[ _ITER ];
             
@@ -1880,7 +1893,7 @@ breakContinue:
             
             STR.push();
             
-            ip += 2;
+            ip += 3;
             break;
          }
          

+ 140 - 14
Engine/source/console/compiler.cpp

@@ -60,29 +60,27 @@ namespace Compiler
    CompilerFloatTable  *gCurrentFloatTable,  gGlobalFloatTable,  gFunctionFloatTable;
    DataChunker          gConsoleAllocator;
    CompilerIdentTable   gIdentTable;
-   CodeBlock           *gCurBreakBlock;
 
    //------------------------------------------------------------
 
-
-   CodeBlock *getBreakCodeBlock()         { return gCurBreakBlock; }
-   void setBreakCodeBlock(CodeBlock *cb)  { gCurBreakBlock = cb;   }
-
-   //------------------------------------------------------------
-
-   U32 evalSTEtoU32(StringTableEntry ste, U32)
+   void evalSTEtoCode(StringTableEntry ste, U32 ip, U32 *ptr)
    {
-      return *((U32 *) &ste);
+#ifdef TORQUE_64
+      *((U64*)(ptr) = (U64)ste;
+#else
+      *ptr = (U32)ste;
+#endif
    }
-
-   U32 compileSTEtoU32(StringTableEntry ste, U32 ip)
+   
+   void compileSTEtoCode(StringTableEntry ste, U32 ip, U32 *ptr)
    {
       if(ste)
          getIdentTable().add(ste, ip);
-      return 0;
+      *ptr = 0;
+      *(ptr+1) = 0;
    }
-
-   U32 (*STEtoU32)(StringTableEntry ste, U32 ip) = evalSTEtoU32;
+   
+   void (*STEtoCode)(StringTableEntry ste, U32 ip, U32 *ptr) = evalSTEtoCode;
 
    //------------------------------------------------------------
 
@@ -286,3 +284,131 @@ void CompilerIdentTable::write(Stream &st)
          st.write(el->ip);
    }
 }
+
+//-------------------------------------------------------------------------
+  
+U8 *CodeStream::allocCode(U32 sz)
+{
+   U8 *ptr = NULL;
+   if (mCodeHead)
+   {
+      const U32 bytesLeft = BlockSize - mCodeHead->size;
+      if (bytesLeft > sz)
+      {
+         ptr = mCodeHead->data + mCodeHead->size;
+         mCodeHead->size += sz;
+         return ptr;
+      }
+   }
+   
+   CodeData *data = new CodeData;
+   data->data = (U8*)dMalloc(BlockSize);
+   data->size = sz;
+   data->next = NULL;
+   
+   if (mCodeHead)
+      mCodeHead->next = data;
+   mCodeHead = data;
+   if (mCode == NULL)
+      mCode = data;
+   return data->data;
+}
+  
+//-------------------------------------------------------------------------
+  
+void CodeStream::fixLoop(U32 loopBlockStart, U32 breakPoint, U32 continuePoint)
+{
+   AssertFatal(mFixStack.size() > 0, "Fix stack mismatch");
+   
+   U32 fixStart = mFixStack[mFixStack.size()-1];
+   for (U32 i=fixStart; i<mFixList.size(); i += 2)
+   {
+      FixType type = (FixType)mFixList[i+1];
+      
+      U32 fixedIp = 0;
+      bool valid = true;
+      
+      switch (type)
+      {
+         case FIXTYPE_LOOPBLOCKSTART:
+            fixedIp = loopBlockStart;
+            break;
+         case FIXTYPE_BREAK:
+            fixedIp = breakPoint;
+            break;
+         case FIXTYPE_CONTINUE:
+            fixedIp = continuePoint;
+            break;
+         default:
+            //Con::warnf("Address %u fixed as %u", mFixList[i], mFixList[i+1]);
+            valid = false;
+            break;
+      }
+      
+      if (valid)
+      {
+         patch(mFixList[i], fixedIp);
+      }
+   }
+}
+
+//-------------------------------------------------------------------------
+  
+void CodeStream::emitCodeStream(U32 *size, U32 **stream, U32 **lineBreaks)
+{
+   // Alloc stream
+   U32 numLineBreaks = getNumLineBreaks();
+   *stream = new U32[mCodePos + (numLineBreaks * 2)];
+   dMemset(*stream, '\0', mCodePos + (numLineBreaks * 2));
+   *size = mCodePos;
+   
+   // Dump chunks & line breaks
+   U32 outBytes = mCodePos * sizeof(U32);
+   U8 *outPtr = *((U8**)stream);
+   for (CodeData *itr = mCode; itr != NULL; itr = itr->next)
+   {
+      U32 bytesToCopy = itr->size > outBytes ? outBytes : itr->size;
+      dMemcpy(outPtr, itr->data, bytesToCopy);
+      outPtr += bytesToCopy;
+      outBytes -= bytesToCopy;
+   }
+   
+   *lineBreaks = *stream + mCodePos;
+   dMemcpy(*lineBreaks, mBreakLines.address(), sizeof(U32) * mBreakLines.size());
+   
+   // Apply patches on top
+   for (U32 i=0; i<mPatchList.size(); i++)
+   {
+      PatchEntry &e = mPatchList[i];
+      (*stream)[e.addr] = e.value;
+   }
+}
+  
+//-------------------------------------------------------------------------
+  
+void CodeStream::reset()
+{
+   mCodePos = 0;
+   mFixStack.clear();
+   mFixLoopStack.clear();
+   mFixList.clear();
+   mBreakLines.clear();
+   
+   // Pop down to one code block
+   CodeData *itr = mCode ? mCode->next : NULL;
+   while (itr != NULL)
+   {
+      CodeData *next = itr->next;
+      dFree(itr->data);
+      dFree(itr);
+      itr = next;
+   }
+   
+   if (mCode)
+   {
+      mCode->size = 0;
+      mCode->next = NULL;
+      mCodeHead = mCode;
+   }
+}
+

+ 190 - 20
Engine/source/console/compiler.h

@@ -24,6 +24,12 @@
 #ifndef _COMPILER_H_
 #define _COMPILER_H_
 
+//#define DEBUG_CODESTREAM
+
+#ifdef DEBUG_CODESTREAM
+#include <stdio.h>
+#endif
+
 class Stream;
 class DataChunker;
 
@@ -49,7 +55,7 @@ namespace Compiler
       OP_JMPIFF,
       OP_JMPIF,
       OP_JMPIFNOT_NP,
-      OP_JMPIF_NP,
+      OP_JMPIF_NP,    // 10
       OP_JMP,
       OP_RETURN,
       // fixes a bug when not explicitly returning a value
@@ -60,7 +66,7 @@ namespace Compiler
       OP_CMPLT,
       OP_CMPLE,
       OP_CMPNE,
-      OP_XOR,
+      OP_XOR,         // 20
       OP_MOD,
       OP_BITAND,
       OP_BITOR,
@@ -71,7 +77,7 @@ namespace Compiler
       OP_SHR,
       OP_SHL,
       OP_AND,
-      OP_OR,
+      OP_OR,          // 30
 
       OP_ADD,
       OP_SUB,
@@ -84,7 +90,7 @@ namespace Compiler
       OP_SETCURVAR_ARRAY,
       OP_SETCURVAR_ARRAY_CREATE,
 
-      OP_LOADVAR_UINT,
+      OP_LOADVAR_UINT,// 40
       OP_LOADVAR_FLT,
       OP_LOADVAR_STR,
 
@@ -97,7 +103,7 @@ namespace Compiler
       OP_SETCUROBJECT_INTERNAL,
 
       OP_SETCURFIELD,
-      OP_SETCURFIELD_ARRAY,
+      OP_SETCURFIELD_ARRAY, // 50
       OP_SETCURFIELD_TYPE,
 
       OP_LOADFIELD_UINT,
@@ -110,7 +116,7 @@ namespace Compiler
 
       OP_STR_TO_UINT,
       OP_STR_TO_FLT,
-      OP_STR_TO_NONE,
+      OP_STR_TO_NONE,  // 60
       OP_FLT_TO_UINT,
       OP_FLT_TO_STR,
       OP_FLT_TO_NONE,
@@ -121,7 +127,7 @@ namespace Compiler
       OP_LOADIMMED_UINT,
       OP_LOADIMMED_FLT,
       OP_TAG_TO_STR,
-      OP_LOADIMMED_STR,
+      OP_LOADIMMED_STR, // 70
       OP_DOCBLOCK_STR,
       OP_LOADIMMED_IDENT,
 
@@ -133,7 +139,7 @@ namespace Compiler
       OP_ADVANCE_STR_COMMA,
       OP_ADVANCE_STR_NUL,
       OP_REWIND_STR,
-      OP_TERMINATE_REWIND_STR,
+      OP_TERMINATE_REWIND_STR,  // 80
       OP_COMPARE_STR,
 
       OP_PUSH,
@@ -147,14 +153,14 @@ namespace Compiler
       OP_ITER,             ///< Enter foreach loop.
       OP_ITER_END,         ///< End foreach loop.
 
-      OP_INVALID
+      OP_INVALID   // 90
    };
 
    //------------------------------------------------------------
 
    F64 consoleStringToNumber(const char *str, StringTableEntry file = 0, U32 line = 0);
-   U32 precompileBlock(StmtNode *block, U32 loopCount);
-   U32 compileBlock(StmtNode *block, U32 *codeStream, U32 ip, U32 continuePoint, U32 breakPoint);
+   
+   U32 compileBlock(StmtNode *block, CodeStream &codeStream, U32 ip);
 
    //------------------------------------------------------------
 
@@ -218,15 +224,19 @@ namespace Compiler
 
    //------------------------------------------------------------
 
-   inline StringTableEntry U32toSTE(U32 u)
+   inline StringTableEntry CodeToSTE(U32 *code, U32 ip)
    {
-      return *((StringTableEntry *) &u);
+#ifdef TORQUE_64
+      return (StringTableEntry)(*((U64*)(code+ip)));
+#else
+      return (StringTableEntry)(*(code+ip));
+#endif
    }
 
-   extern U32 (*STEtoU32)(StringTableEntry ste, U32 ip);
-
-   U32 evalSTEtoU32(StringTableEntry ste, U32);
-   U32 compileSTEtoU32(StringTableEntry ste, U32 ip);
+   extern void (*STEtoCode)(StringTableEntry ste, U32 ip, U32 *ptr);
+   
+   void evalSTEtoCode(StringTableEntry ste, U32 ip, U32 *ptr);
+   void compileSTEtoCode(StringTableEntry ste, U32 ip, U32 *ptr);
 
    CompilerStringTable *getCurrentStringTable();
    CompilerStringTable &getGlobalStringTable();
@@ -244,9 +254,6 @@ namespace Compiler
 
    void precompileIdent(StringTableEntry ident);
 
-   CodeBlock *getBreakCodeBlock();
-   void setBreakCodeBlock(CodeBlock *cb);
-
    /// Helper function to reset the float, string, and ident tables to a base
    /// starting state.
    void resetTables();
@@ -257,4 +264,167 @@ namespace Compiler
    extern bool gSyntaxError;
 };
 
+/// Utility class to emit and patch bytecode
+class CodeStream
+{
+public:
+   
+   enum FixType
+   {
+      // For loops
+      FIXTYPE_LOOPBLOCKSTART,
+      FIXTYPE_BREAK,
+      FIXTYPE_CONTINUE
+   };
+   
+   enum Constants
+   {
+      BlockSize = 16384,
+   };
+   
+protected:
+   
+   typedef struct PatchEntry
+   {
+      U32 addr;  ///< Address to patch
+      U32 value; ///< Value to place at addr
+      
+      PatchEntry() {;}
+      PatchEntry(U32 a, U32 v)  : addr(a), value(v) {;}
+   } PatchEntry;
+   
+   typedef struct CodeData
+   {
+      U8 *data;       ///< Allocated data (size is BlockSize)
+      U32 size;       ///< Bytes used in data
+      CodeData *next; ///< Next block
+   };
+   
+   /// @name Emitted code
+   /// {
+   CodeData *mCode;
+   CodeData *mCodeHead;
+   U32 mCodePos;
+   /// }
+   
+   /// @name Code fixing stacks
+   /// {
+   Vector<U32> mFixList;
+   Vector<U32> mFixStack;
+   Vector<bool> mFixLoopStack;
+   Vector<PatchEntry> mPatchList;
+   /// }
+   
+   Vector<U32> mBreakLines; ///< Line numbers
+   
+public:
+
+   CodeStream() : mCode(0), mCodeHead(NULL), mCodePos(0)
+   {
+   }
+   
+   ~CodeStream()
+   {
+      reset();
+      
+      if (mCode)
+         delete mCode;
+   }
+   
+   U8 *allocCode(U32 sz);
+   
+   inline U32 emit(U32 code)
+   {
+      U32 *ptr = (U32*)allocCode(4);
+      *ptr = code;
+#ifdef DEBUG_CODESTREAM
+      printf("code[%u] = %u\n", mCodePos, code);
+#endif
+      return mCodePos++;
+   }
+   
+   inline void patch(U32 addr, U32 code)
+   {
+#ifdef DEBUG_CODESTREAM
+      printf("patch[%u] = %u\n", addr, code);
+#endif
+      mPatchList.push_back(PatchEntry(addr, code));
+   }
+   
+   inline U32 emitSTE(const char *code)
+   {
+      U64 *ptr = (U64*)allocCode(8);
+      *ptr = 0;
+      Compiler::STEtoCode(code, mCodePos, (U32*)ptr);
+#ifdef DEBUG_CODESTREAM
+      printf("code[%u] = %s\n", mCodePos, code);
+#endif
+      mCodePos += 2;
+      return mCodePos-2;
+   }
+   
+   inline U32 tell()
+   {
+      return mCodePos;
+   }
+   
+   inline bool inLoop()
+   {
+      for (U32 i=0; i<mFixLoopStack.size(); i++)
+      {
+         if (mFixLoopStack[i])
+            return true;
+      }
+      return false;
+   }
+   
+   inline U32 emitFix(FixType type)
+   {
+      U32 *ptr = (U32*)allocCode(4);
+      *ptr = (U32)type;
+      
+#ifdef DEBUG_CODESTREAM
+      printf("code[%u] = [FIX:%u]\n", mCodePos, (U32)type);
+#endif
+      
+      mFixList.push_back(mCodePos);
+      mFixList.push_back((U32)type);
+      return mCodePos++;
+   }
+   
+   inline void pushFixScope(bool isLoop)
+   {
+      mFixStack.push_back(mFixList.size());
+      mFixLoopStack.push_back(isLoop);
+   }
+   
+   inline void popFixScope()
+   {
+      AssertFatal(mFixStack.size() > 0, "Fix stack mismatch");
+      
+      U32 newSize = mFixStack[mFixStack.size()-1];
+      while (mFixList.size() > newSize)
+         mFixList.pop_back();
+      mFixStack.pop_back();
+      mFixLoopStack.pop_back();
+   }
+   
+   void fixLoop(U32 loopBlockStart, U32 breakPoint, U32 continuePoint);
+   
+   inline void addBreakLine(U32 lineNumber, U32 ip)
+   {
+      mBreakLines.push_back(lineNumber);
+      mBreakLines.push_back(ip);
+   }
+   
+   inline U32 getNumLineBreaks()
+   {
+      return mBreakLines.size() / 2;
+   }
+   
+   void emitCodeStream(U32 *size, U32 **stream, U32 **lineBreaks);
+   
+   void reset();
+};
+
 #endif

+ 2 - 1
Engine/source/console/console.h

@@ -182,7 +182,8 @@ namespace Con
       /// 09/12/07 - CAF - 43->44 remove newmsg operator
       /// 09/27/07 - RDB - 44->45 Patch from Andreas Kirsch: Added opcode to support correct void return
       /// 01/13/09 - TMS - 45->46 Added script assert
-      DSOVersion = 46,
+      /// 09/07/14 - jamesu - 47->47 64bit support
+      DSOVersion = 47,
 
       MaxLineLength = 512,  ///< Maximum length of a line of console input.
       MaxDataTypes = 256    ///< Maximum number of registered data types.

Некоторые файлы не были показаны из-за большого количества измененных файлов