Bert Freudenberg uploaded a new version of VMMakerJS to project VM Maker: http://source.squeak.org/VMMaker/VMMakerJS-bf.12.mcz ==================== Summary ==================== Name: VMMakerJS-bf.12 Author: bf Time: 14 October 2014, 3:49:18.236 pm UUID: a24182f0-6780-4782-a772-87ccf9030a78 Ancestors: VMMakerJS-bf.11 Fix inst vars in non-inlined prim methods (specifically, ADPCMCodecPlugin). =============== Diff against VMMakerJS-bf.11 =============== Item was changed: ----- Method: JSCodeGenerator class>>beActiveDuring: (in category 'preferences') ----- beActiveDuring: aBlock | wasActive | wasActive := self isActive. + self isActive: true. aBlock ensure: [self isActive: wasActive].! Item was changed: ----- Method: JSCodeGenerator>>addMethodsForPrimitives: (in category 'public') ----- addMethodsForPrimitives: classAndSelectorList + | sel aClass source verbose meth primInstVars sharedInstVars assignedInstVars | - | sel aClass source verbose meth | classAndSelectorList do:[:classAndSelector | aClass := Smalltalk at: (classAndSelector at: 1) ifAbsent:[nil]. aClass ifNotNil:[ self addAllClassVarsFor: aClass. "TPR - should pool vars also be added here?" "find the method in either the class or the metaclass" sel := classAndSelector at: 2. (aClass includesSelector: sel) ifTrue: [source := aClass sourceCodeAt: sel ifAbsent:[nil]] ifFalse: [source := aClass class sourceCodeAt: sel ifAbsent:[nil]]. ]. source ifNil:[ Transcript cr; show: 'WARNING: Compiled primitive ', classAndSelector first, '>>', classAndSelector last, ' not present'. ] ifNotNil:[ "compile the method source and convert to a suitable translation method " meth := (Compiler new parse: source in: aClass notifying: nil) asTranslationMethodOfClass: self translationMethodClass. (aClass includesSelector: sel) ifTrue: [meth definingClass: aClass] ifFalse: [meth definingClass: aClass class]. meth primitive > 0 ifTrue:[meth preparePrimitiveName]. "for old-style array accessing: meth covertToZeroBasedArrayReferences." meth replaceSizeMessages. self addMethod: meth. ]. ]. "method preparation" verbose := false. self prepareMethods. verbose ifTrue: [self printUnboundCallWarnings. self printUnboundVariableReferenceWarnings. Transcript cr]. "code generation" + "self doInlining: false" - self doInlining: false. + primInstVars := Set new. "inst vars used in primitives" + sharedInstVars := Set new. "inst vars used in non-primitives" + assignedInstVars := Set new. "inst vars modified in non-primitives" methods do:[:m| + m primitive > 0 ifTrue: [ + primInstVars addAll: m freeVariableReferences. + ] ifFalse: [ + sharedInstVars addAll: m freeVariableReferences. + assignedInstVars addAll: m variablesAssignedTo. + ]. + ]. + methods do:[:m| "if this method is supposed to be a primitive (rather than a helper routine), add assorted prolog and epilog items" + m primitive > 0 ifTrue: [ + m preparePrimitivePrologueShared: sharedInstVars assigned: assignedInstVars ]. - m primitive > 0 ifTrue: [m preparePrimitivePrologue]. "check for one-based array access" m oneBasedArrays ifNotNil: [self oneBasedArrays: true]. + ]. + "Add declarations for inst vars used in both prims and non-prims as global" + ((primInstVars intersection: sharedInstVars) difference: variables) do: [:var | + methods do:[:m| + m declarations at: var ifPresent: [:decl | + variableDeclarations at: var + ifPresent: [:existing | + decl = existing ifFalse: [self error: 'decls do not match']] + ifAbsent: [variableDeclarations at: var put: decl]]]. + variables add: var]. + "Add non-shared inst vars as local" + methods do:[:m| + m locals addAll: (m freeVariableReferences difference: sharedInstVars)]. + ! - ].! Item was changed: ----- Method: JSMethod>>freeVariableReferences (in category 'utilities') ----- freeVariableReferences "Answer a collection of variables referenced this method, excluding locals, arguments, and pseudovariables." | refs | refs := Set new. parseTree nodesDo: [ :node | node isVariable ifTrue: [ refs add: node name asString ]. ]. args do: [ :var | refs remove: var asString ifAbsent: [] ]. locals do: [ :var | refs remove: var asString ifAbsent: [] ]. + #('self' 'nil' 'true' 'false' 'null') do: [ :var | refs remove: var ifAbsent: [] ]. - #('self' 'nil' 'true' 'false') do: [ :var | refs remove: var ifAbsent: [] ]. ^ refs asSortedCollection! Item was removed: - ----- Method: JSMethod>>preparePrimitivePrologue (in category 'primitive compilation') ----- - preparePrimitivePrologue - "Add a prolog and postlog to a primitive method. The prolog copies any instance variables referenced by this primitive method into local variables. The postlog copies values of assigned-to variables back into the instance. The names of the new locals are added to the local variables list. - - The declarations dictionary defines the types of any non-integer variables (locals, arguments, or instance variables). In particular, it may specify the types: - - int * -- an array of 32-bit values (e.g., a BitMap) - short * -- an array of 16-bit values (e.g., a SoundBuffer) - char * -- an array of unsigned bytes (e.g., a String) - double -- a double precision floating point number (e.g., 3.14159) - - Undeclared variables are taken to be integers and will be converted from Smalltalk to C ints." - - "Current restrictions: - o method must not contain message sends - o method must not allocate objects - o method must not manipulate raw oops - o method cannot access class variables - o method can only return an integer" - - | prolog postlog instVarsUsed varsAssignedTo instVarList primArgCount varName endsWithReturn aClass | - selector == #setInterpreter: ifTrue:[self halt]. - aClass := definingClass. - prolog := OrderedCollection new. - postlog := OrderedCollection new. - instVarsUsed := self freeVariableReferences asSet. - varsAssignedTo := self variablesAssignedTo asSet. - instVarList := aClass allInstVarNames. - primArgCount := args size. - - "add receiver fetch and arg conversions to prolog" - prolog addAll: self fetchRcvrExpr. - 1 to: args size do: [:argIndex | - varName := args at: argIndex. - prolog addAll: - (self argConversionExprFor: varName stackIndex: args size - argIndex)]. - - "add success check to postlog" - postlog addAll: self checkSuccessExpr. - - "add instance variable fetches to prolog and instance variable stores to postlog" - 1 to: instVarList size do: [:varIndex | - varName := instVarList at: varIndex. - (instVarsUsed includes: varName) ifTrue: [ - locals add: varName. - prolog addAll: (self instVarGetExprFor: varName offset: varIndex - 1). - (varsAssignedTo includes: varName) ifTrue: [ - postlog addAll: (self instVarPutExprFor: varName offset: varIndex - 1)]]]. - prolog addAll: self checkSuccessExpr. - - locals addAllFirst: args. - locals addFirst: 'rcvr'. - args := args class new. - locals asSet size = locals size - ifFalse: [self error: 'local name conflicts with instance variable name']. - endsWithReturn := self endsWithReturn. - self fixUpReturns: primArgCount postlog: postlog. - - endsWithReturn - ifTrue: [parseTree setStatements: prolog, parseTree statements] - ifFalse: [ - postlog addAll: (self popArgsExpr: primArgCount). - parseTree setStatements: prolog, parseTree statements, postlog]. - ! Item was added: + ----- Method: JSMethod>>preparePrimitivePrologueShared:assigned: (in category 'primitive compilation') ----- + preparePrimitivePrologueShared: sharedInstVars assigned: assignedInstVars + "Add a prolog and postlog to a primitive method. The prolog copies any instance variables referenced by this primitive method into local variables. The postlog copies values of assigned-to variables back into the instance. The names of the new locals are added to the local variables list. + + The declarations dictionary defines the types of any non-integer variables (locals, arguments, or instance variables). In particular, it may specify the types: + + int * -- an array of 32-bit values (e.g., a BitMap) + short * -- an array of 16-bit values (e.g., a SoundBuffer) + char * -- an array of unsigned bytes (e.g., a String) + double -- a double precision floating point number (e.g., 3.14159) + + Undeclared variables are taken to be integers and will be converted from Smalltalk to C ints." + + "Current restrictions: + o method must not contain message sends + o method must not allocate objects + o method must not manipulate raw oops + o method cannot access class variables + o method can only return an integer" + + | prolog postlog instVarsUsed varsAssignedTo instVarList primArgCount varName endsWithReturn aClass | + selector == #setInterpreter: ifTrue:[self halt]. + aClass := definingClass. + prolog := OrderedCollection new. + postlog := OrderedCollection new. + instVarsUsed := self freeVariableReferences asSet union: sharedInstVars. + varsAssignedTo := self variablesAssignedTo asSet union: assignedInstVars. + instVarList := aClass allInstVarNames. + primArgCount := args size. + + "add receiver fetch and arg conversions to prolog" + prolog addAll: self fetchRcvrExpr. + 1 to: args size do: [:argIndex | + varName := args at: argIndex. + prolog addAll: + (self argConversionExprFor: varName stackIndex: args size - argIndex)]. + + "add success check to postlog" + postlog addAll: self checkSuccessExpr. + + "add instance variable fetches to prolog and instance variable stores to postlog" + 1 to: instVarList size do: [:varIndex | + varName := instVarList at: varIndex. + (instVarsUsed includes: varName) ifTrue: [ + "locals add: varName. -- since we do not inline, we cannot declare these local since they migth be used by inlined methods" + prolog addAll: (self instVarGetExprFor: varName offset: varIndex - 1). + (varsAssignedTo includes: varName) ifTrue: [ + postlog addAll: (self instVarPutExprFor: varName offset: varIndex - 1)]]]. + prolog addAll: self checkSuccessExpr. + + locals addAllFirst: args. + locals addFirst: 'rcvr'. + args := args class new. + locals asSet size = locals size + ifFalse: [self error: 'local name conflicts with instance variable name']. + endsWithReturn := self endsWithReturn. + self fixUpReturns: primArgCount postlog: postlog. + + endsWithReturn + ifTrue: [parseTree setStatements: prolog, parseTree statements] + ifFalse: [ + postlog addAll: (self popArgsExpr: primArgCount). + parseTree setStatements: prolog, parseTree statements, postlog]. + ! |
Free forum by Nabble | Edit this page |