Changeset 24973

Show
Ignore:
Timestamp:
11/26/08 23:33:40 (4 years ago)
Author:
fujidig
Message:

* モジュール変数のデストラクタ呼び出しを削除
* struct 型の値にクローン情報を持たせるのをやめる
* ユーザ定義関数の呼び出しとreturnを高速化

Location:
lang/javascript/hsp-on-js/trunk/src
Files:
3 modified

Legend:

Unmodified
Added
Removed
  • lang/javascript/hsp-on-js/trunk/src/evaluator.js

    r24735 r24973  
    204204                        } 
    205205                } 
     206                function pushCallingUserdefFuncCode(userDefFunc, argc) { 
     207                        if(!userDefFuncs[userDefFunc.id]) { 
     208                                userDefFuncs[userDefFunc.id] = userDefFunc; 
     209                        } 
     210                        push('var args = [];'); 
     211                        push('var len = stack.length;'); 
     212                        var origArgsCount = 0; 
     213                        var argMax = userDefFunc.paramTypes.length; 
     214                        var recvArgMax = 0; // local を除いた仮引数の数 
     215                        for(var i = 0; i < argMax; i ++) { 
     216                                if(userDefFunc.paramTypes[i] != MPType.LOCALVAR) recvArgMax ++;  
     217                        } 
     218                        if(recvArgMax < argc) { 
     219                                push('throw new HSPError(ErrorCode.TOO_MANY_PARAMETERS);'); 
     220                                return; 
     221                        } 
     222                        for(var i = 0; i < argMax; i ++) { 
     223                                var mptype = userDefFunc.paramTypes[i]; 
     224                                push('var arg = stack[len - '+(argc-origArgsCount)+'];'); 
     225                                switch(mptype) { 
     226                                case MPType.DNUM: 
     227                                        push('args['+i+'] = self.scanArg(arg, "n").toDoubleValue();'); 
     228                                        break; 
     229                                case MPType.INUM: 
     230                                        push('args['+i+'] = arg ? self.scanArg(arg, "n").toIntValue() : new IntValue(0);'); 
     231                                        break; 
     232                                case MPType.LOCALVAR: 
     233                                        push('args['+i+'] = new Variable;'); 
     234                                        continue; 
     235                                case MPType.ARRAYVAR: 
     236                                        push('args['+i+'] = self.scanArg(arg, "v").variable;'); 
     237                                        break; 
     238                                case MPType.SINGLEVAR: 
     239                                        push('args['+i+'] = self.scanArg(arg, "v");'); 
     240                                        break; 
     241                                case MPType.LOCALSTRING: 
     242                                        push('args['+i+'] = self.scanArg(arg, "s").toStrValue();'); 
     243                                        break; 
     244                                case MPType.MODULEVAR: 
     245                                        push('args['+i+'] = new ModVarData(self.scanArg(arg, "v").variable, arg.indices);'); 
     246                                        break; 
     247                                case MPType.IMODULEVAR: 
     248                                        push('args['+i+'] = arg;'); 
     249                                        break; 
     250                                default: 
     251                                        throw new Error('未対応のパラメータタイプ: '+mptype); 
     252                                } 
     253                                origArgsCount ++; 
     254                        } 
     255                        push('stack.length -= '+argc+';'); 
     256                        push('if(self.frameStack.length >= 256) {'); 
     257                        push('    throw new HSPError(ErrorCode.STACK_OVERFLOW);'); 
     258                        push('}'); 
     259                        push('self.frameStack.push(new Frame('+(pc + 1)+', userDefFuncs['+userDefFunc.id+'], args));'); 
     260                        push('self.pc = '+userDefFunc.label.pos+';'); 
     261                } 
    206262                var lines = []; 
    207263                var indent = 0; 
     
    404460                                var userDefFunc = insn.opts[0]; 
    405461                                var argc = insn.opts[1]; 
    406                                 if(!userDefFuncs[userDefFunc.id]) { 
    407                                         userDefFuncs[userDefFunc.id] = userDefFunc; 
    408                                 } 
    409                                 push('self.callUserDefFunc(userDefFuncs['+userDefFunc.id+'], '+ 
    410                                          'Utils.aryPopN(stack, '+argc+'));'); 
    411                                 push('self.pc ++;'); 
     462                                pushCallingUserdefFuncCode(userDefFunc, argc); 
    412463                                push('continue;'); 
    413464                                break; 
     
    453504                                } 
    454505                                var moduleExpr = 'userDefFuncs['+module.id+']'; 
    455                                 push('var args = Utils.aryPopN(stack, '+argc+');'); 
    456                                 push('var agent = self.scanArg(args[0], "a");'); 
     506                                push('var len = stack.length;'); 
     507                                push('var agent = self.scanArg(stack[len - '+argc+'], "a");'); 
    457508                                push('if(agent.getType() != '+VarType.STRUCT+') {'); 
    458509                                push('    agent.variable.dim('+VarType.STRUCT+', 1, 0, 0, 0);'); 
     
    461512                                push('var offset = array.newmod('+moduleExpr+');'); 
    462513                                if(module.constructor) { 
    463                                         push('args[0] = new VariableAgent(agent.variable, [offset]);'); 
    464                                         if(!userDefFuncs[module.constructor.id]) { 
    465                                                 userDefFuncs[module.constructor.id] = module.constructor; 
    466                                         } 
    467                                         push('self.callUserDefFunc(userDefFuncs['+module.constructor.id+'], args);'); 
    468                                         push('self.pc ++;'); 
     514                                        push('stack[len - '+argc+'] = new ModVarData(agent.variable, [offset]);'); 
     515                                        pushCallingUserdefFuncCode(module.constructor, argc); 
    469516                                        push('continue;'); 
    470517                                } else if(argc > 1) { 
     
    473520                                break; 
    474521                        case Instruction.Code.RETURN: 
    475                                 if(insn.opts[0]) { 
    476                                         push('self.return_(stack.pop());'); 
     522                                var existReturnVal = insn.opts[0]; 
     523                                push('if(self.frameStack.length == 0) {'); 
     524                                push('    throw new HSPError(ErrorCode.RETURN_WITHOUT_GOSUB);'); 
     525                                push('}'); 
     526                                push('var frame = self.frameStack.pop();'); 
     527                                if(existReturnVal) { 
     528                                        push('if(frame.userDefFunc && frame.userDefFunc.isCType) {'); 
     529                                        push('    stack[stack.length - 1] = stack[stack.length - 1].toValue();'); 
     530                                        push('} else {'); indent ++ 
     531                                        push('var val = stack.pop();'); 
     532                                        push('switch(val.getType()) {'); 
     533                                        push('case '+VarType.STR+':'); 
     534                                        push('    self.refstr.assign(0, val.toStrValue());'); 
     535                                        push('    break;'); 
     536                                        push('case '+VarType.DOUBLE+':'); 
     537                                        push('    self.refdval.assign(0, val.toDoubleValue());'); 
     538                                        push('    break;'); 
     539                                        push('case '+VarType.INT+':'); 
     540                                        push('    this.stat.assign(0, val.toIntValue());'); 
     541                                        push('    break;'); 
     542                                        push('default:'); 
     543                                        push('    throw new HSPError(ErrorCode.TYPE_MISMATCH);'); 
     544                                        push('}'); 
     545                                        indent --; push('}'); 
    477546                                } else { 
    478                                         push('self.return_();'); 
    479                                 } 
    480                                 push('self.pc ++;'); 
     547                                        push('if(frame.userDefFunc && frame.userDefFunc.isCType) {'); 
     548                                        push('    throw new HSPError(ErrorCode.NORETVAL);'); 
     549                                        push('}'); 
     550                                } 
     551                                push('self.pc = frame.pc;'); 
    481552                                push('continue;'); 
    482553                                break; 
     
    486557                                push('    throw new HSPError(ErrorCode.TYPE_MISMATCH);'); 
    487558                                push('}'); 
    488                                 push('self.deleteStruct(v);'); 
    489                                 push('self.pc ++;'); 
    490                                 push('continue;'); 
     559                                push('agent.assign(StructValue.EMPTY);'); 
    491560                                break; 
    492561                        case Instruction.Code.REPEAT: 
     
    669738                return lines.join("\n"); 
    670739        }, 
    671         callBuiltinFunc: function callBuiltinFunc(insn) { 
    672                 var type = insn.opts[0]; 
    673                 var subid = insn.opts[1]; 
    674                 var argc = insn.opts[2]; 
    675                 var func = BuiltinFuncs[type][subid]; 
    676                 if(!func) { 
    677                         var name = this.getBuiltinFuncName(insn); 
    678                         if(name) { 
    679                                 throw new HSPError(ErrorCode.UNSUPPORTED_FUNCTION, name + ' はサポートされていません'); 
    680                         } else { 
    681                                 throw new HSPError(ErrorCode.UNSUPPORTED_FUNCTION); 
    682                         } 
    683                 } 
    684                 var args = Utils.aryPopN(this.stack, argc); 
    685                 return func.apply(this, args); 
    686         }, 
    687         callUserDefFunc: function callUserDefFunc(userDefFunc, origArgs, callback) { 
    688                 var args = []; 
    689                 var origArgsCount = 0; 
    690                 for(var i = 0; i < userDefFunc.paramTypes.length; i ++) { 
    691                         var mptype = userDefFunc.paramTypes[i]; 
    692                         var arg = origArgs[origArgsCount]; 
    693                         switch(mptype) { 
    694                         case MPType.DNUM: 
    695                                 this.scanArg(arg, 'n', false); 
    696                                 args.push(arg.toDoubleValue()); 
    697                                 origArgsCount ++; 
    698                                 break; 
    699                         case MPType.INUM: 
    700                                 this.scanArg(arg, 'n', true); 
    701                                 args.push(arg ? arg.toIntValue() : new IntValue(0)); 
    702                                 origArgsCount ++; 
    703                                 break; 
    704                         case MPType.LOCALVAR: 
    705                                 args.push(new Variable); 
    706                                 break; 
    707                         case MPType.ARRAYVAR: 
    708                                 this.scanArg(arg, 'v', false); 
    709                                 args.push(arg.variable); 
    710                                 origArgsCount ++; 
    711                                 break; 
    712                         case MPType.SINGLEVAR: 
    713                                 this.scanArg(arg, 'v', false); 
    714                                 args.push(arg); 
    715                                 origArgsCount ++; 
    716                                 break; 
    717                         case MPType.LOCALSTRING: 
    718                                 this.scanArg(arg, 's', false); 
    719                                 args.push(arg.toStrValue()); 
    720                                 origArgsCount ++; 
    721                                 break; 
    722                         case MPType.MODULEVAR: 
    723                         case MPType.IMODULEVAR: 
    724                         case MPType.TMODULEVAR: 
    725                                 this.scanArg(arg, 'v', false); 
    726                                 args.push(new ModVarData(arg.variable, arg.indices)); 
    727                                 origArgsCount ++; 
    728                                 break; 
    729                         default: 
    730                                 throw new HSPError(ErrorCode.INVALID_STRUCT_SOURCE); 
    731                         } 
    732                 } 
    733                 if(origArgsCount < origArgs.length) { 
    734                         throw new HSPError(ErrorCode.TOO_MANY_PARAMETERS); 
    735                 } 
    736                 if(this.frameStack.length >= 256) { 
    737                         throw new HSPError(ErrorCode.STACK_OVERFLOW); 
    738                 } 
    739                 this.frameStack.push(new Frame(this.pc + 1, userDefFunc, args, callback)); 
    740                 this.pc = userDefFunc.label.pos - 1; 
    741         }, 
    742         return_: function return_(val) { 
    743                 if(this.frameStack.length == 0) { 
    744                         throw new HSPError(ErrorCode.RETURN_WITHOUT_GOSUB); 
    745                 } 
    746                 var frame = this.frameStack.pop(); 
    747                 if(frame.userDefFunc && frame.userDefFunc.isCType) { 
    748                         if(!val) throw new HSPError(ErrorCode.NORETVAL); 
    749                         this.stack.push(val.toValue()); 
    750                 } else if(val) { 
    751                         switch(val.getType()) { 
    752                         case VarType.STR: 
    753                                 this.refstr.assign(0, val.toStrValue()); 
    754                                 break; 
    755                         case VarType.DOUBLE: 
    756                                 this.refdval.assign(0, val.toDoubleValue()); 
    757                                 break; 
    758                         case VarType.INT: 
    759                                 this.stat.assign(0, val.toIntValue()); 
    760                                 break; 
    761                         default: 
    762                                 throw new HSPError(ErrorCode.TYPE_MISMATCH); 
    763                         } 
    764                 } 
    765                 this.pc = frame.pc - 1; 
    766                 var runCallback = function() { 
    767                         if(frame.callback) { 
    768                                 var fn = frame.callback(); 
    769                                 while(fn) { 
    770                                         fn = fn(); 
    771                                 } 
    772                         } 
    773                 }; 
    774                 if(frame.userDefFunc) { 
    775                         this.deleteLocalVars(frame.userDefFunc.paramTypes, frame.args, runCallback); 
    776                 } else { 
    777                         runCallback(); 
    778                 } 
    779         }, 
    780740        popIndices: function popIndices(argc) { 
    781741                var indices = Utils.aryPopN(this.stack, argc); 
     
    822782                } 
    823783                return thismod; 
    824         }, 
    825         deleteStruct: function deleteStruct(agent, callback) { 
    826                 var fn = this.deleteStruct0(agent, callback); 
    827                 while(fn) { 
    828                         fn = fn(); 
    829                 } 
    830         }, 
    831         deleteAllStruct: function deleteAllStruct(variable, callback) { 
    832                 var fn = this.deleteAllStruct0(variable, callback); 
    833                 while(fn) { 
    834                         fn = fn(); 
    835                 } 
    836         }, 
    837         deleteStruct0: function deleteStruct0(agent, callback) { 
    838                 this.deleteStructRecursionLevel = 0; 
    839                 var struct = agent.toValue(); 
    840                 var self = this; 
    841                 if(struct.isUsing() != 1) { 
    842                         if(callback) return callback(); 
    843                         return null; 
    844                 } 
    845                 var myCallback = function() { 
    846                         var i = 0; 
    847                         return (function() { 
    848                                 if(++self.deleteStructRecursionLevel >= 128) { 
    849                                         self.deleteStructRecursionLevel = 0; 
    850                                         return arguments.callee; 
    851                                 } 
    852                                 while(i < struct.members.length) { 
    853                                         var member = struct.members[i]; 
    854                                         i ++; 
    855                                         if(member.getType() == VarType.STRUCT) { 
    856                                                 return self.deleteAllStruct0(member, arguments.callee); 
    857                                         } 
    858                                 } 
    859                                 agent.assign(StructValue.EMPTY); 
    860                                 if(callback) return callback(); 
    861                                 return null; 
    862                         })(); 
    863                 } 
    864                 if(struct.module.destructor) { 
    865                         this.callUserDefFunc(struct.module.destructor, [agent], myCallback); 
    866                         return null; 
    867                 } else { 
    868                         return myCallback; 
    869                 } 
    870         }, 
    871         deleteAllStruct0: function deleteAllStruct0(variable, callback) { 
    872                 var i = 0; 
    873                 var self = this; 
    874                 return (function() { 
    875                         while(i < variable.getL0()) { 
    876                                 var agent = new VariableAgent(variable, [i]); 
    877                                 i ++; 
    878                                 if(agent.isUsing() == 1) { 
    879                                         return self.deleteStruct0(agent, arguments.callee); 
    880                                 } 
    881                         } 
    882                         return callback(); 
    883                 })(); 
    884         }, 
    885         deleteLocalVars: function deleteLocalVars(paramTypes, args, callback) { 
    886                 var i = 0; 
    887                 var self = this; 
    888                 (function() { 
    889                         while(i < args.length) { 
    890                                 var paramType = paramTypes[i]; 
    891                                 var arg = args[i]; 
    892                                 i ++; 
    893                                 if(paramType == MPType.LOCALVAR && arg.getType() == VarType.STRUCT) { 
    894                                         self.deleteAllStruct(arg, arguments.callee); 
    895                                         return; 
    896                                 } 
    897                         } 
    898                         callback(); 
    899                         return; 
    900                 })(); 
    901784        }, 
    902785        getBuiltinFuncName: function getBuiltinFuncName(insn) { 
  • lang/javascript/hsp-on-js/trunk/src/struct-array.js

    r23061 r24973  
    99Utils.objectExtend(StructArray.prototype, { 
    1010        assign: function assign(offset, rhs) { 
    11                 this.values[offset] = rhs.toValue().clone(); 
     11                this.values[offset] = rhs.toValue(); 
    1212                if(rhs == StructValue.EMPTY && offset < this.searchFrom) { 
    1313                        this.searchFrom = offset; 
     
    5454                        members[i] = new Variable; 
    5555                } 
    56                 this.values[index] = new StructValue(module, members, false); 
     56                this.values[index] = new StructValue(module, members); 
    5757                return index; 
    5858        } 
  • lang/javascript/hsp-on-js/trunk/src/struct-value.js

    r21962 r24973  
    1 function StructValue(module, members, isClone) { 
     1function StructValue(module, members) { 
    22        this.module = module; 
    33        this.members = members; 
    4         this.isClone = isClone; 
    54} 
    65 
     
    2322        }, 
    2423        isUsing: function isUsing() { 
    25                 if(this.isClone) return 2; 
    2624                return 1; 
    27         }, 
    28         clone: function clone() { 
    29                 if(this.isClone) { 
    30                         return this; 
    31                 } else { 
    32                         return new StructValue(this.module, this.members, true); 
    33                 } 
    3425        } 
    3526}); 
     
    3930StructValue.EMPTY.toString = function() { return '<StructValue: EMPTY>'; }; 
    4031StructValue.EMPTY.isUsing = function() { return false; }; 
    41 StructValue.EMPTY.clone = function() { return this; }; 
    4232 
    4333if(typeof HSPonJS != 'undefined') {