Bert Freudenberg uploaded a new version of VMMakerJS to project VM Maker: http://source.squeak.org/VMMaker/VMMakerJS-bf.16.mcz ==================== Summary ==================== Name: VMMakerJS-bf.16 Author: bf Time: 13 November 2014, 7:08:06.162 pm UUID: aa9fd3da-7901-4c62-ae34-c166f1492d3b Ancestors: VMMakerJS-bf.15 Balloon2D needs pointer arithmetic. Fake it. How? If p is a 'pointer' to an Int32Array, then p += offset becomes p = new Int32Array(p.buffer, p.byteOffset + 4 * offset) This is actually more efficient than it looks. The Int32Array is just an object holding a buffer, and offset. Allocating this is cheap, and it's going to be GC'ed quickly. The resulting plugin is actually twice as fast as my home-grown one. =============== Diff against VMMakerJS-bf.15 =============== Item was changed: ----- Method: JSCodeGenerator class>>translateAllPluginsIn: (in category 'utilities') ----- translateAllPluginsIn: aDirectory self beActiveDuring: [ #( ADPCMCodecPlugin + BalloonEnginePlugin "BMPReadWriterPlugin -- not working yet" BitBltSimulation + "DSAPlugin --not working yet" - DSAPlugin DeflatePlugin FFTPlugin FloatArrayPlugin + GeniePlugin "-- not working yet" - "GeniePlugin -- not working yet" JPEGReaderPlugin KedamaPlugin KedamaPlugin2 KlattSynthesizerPlugin LargeIntegersPlugin Matrix2x3Plugin MiscPrimitivePlugin ScratchPlugin SoundGenerationPlugin StarSqueakPlugin ) do: [:pluginName | self environment at: pluginName ifPresent: [:plugin | plugin translateInDirectory: aDirectory doInlining: false]] displayingProgress: 'Generating JS plugins'].! Item was changed: ----- Method: JSCodeGenerator>>checkNonPointer:op: (in category 'private') ----- checkNonPointer: node op: op + self ifPointerVar: node then: [:type | + self halt: 'cannot do ', op, ' with ', type]! - node isVariable - ifTrue: [(self typeOfVariable: node name) ifNotNil: [:type | - (type includes: $*) ifTrue: [self halt: 'cannot do ', op, ' with ', type]]].! Item was changed: ----- Method: JSCodeGenerator>>generateAt:on:indent: (in category 'JS translation') ----- generateAt: msgNode on: aStream indent: level "Generate the JS code for this message onto the given stream." + | arrayNode indexNode subtractOne complex coerceTo | - | arrayNode indexNode subtractOne complex | arrayNode := msgNode receiver. + (arrayNode isSend and: [arrayNode selector = #cCoerce:to: and: [arrayNode args first isVariable]]) ifTrue: [ + coerceTo := (arrayNode args second value) copyWithout: $ . + arrayNode := arrayNode args first. + aStream nextPutAll: '(']. indexNode := msgNode args first. subtractOne := self isOneBasedArray: arrayNode name in: currentMethod. (subtractOne and: [indexNode isPlusOne]) ifTrue: [ subtractOne := false. indexNode := indexNode receiver. "remove + 1" ]. complex := subtractOne and: [indexNode isLeafOrFunc not]. self emitJSExpression: arrayNode on: aStream. aStream nextPut: $[. complex ifTrue: [aStream nextPut: $(]. indexNode emitJSCodeAsExpressionOn: aStream level: level + 1 generator: self. complex ifTrue: [aStream nextPut: $)]. subtractOne ifTrue: [aStream nextPutAll: ' - 1']. + aStream nextPut: $]. + coerceTo ifNotNil: [ + coerceTo = 'int*' ifFalse: [self halt]. + aStream nextPutAll: '|0)']. + ! - aStream nextPut: $].! Item was changed: ----- Method: JSCodeGenerator>>generateAtPut:on:indent: (in category 'JS translation') ----- generateAtPut: msgNode on: aStream indent: level "Generate the JS code for this message onto the given stream." | putExpr incExpr | + (msgNode receiver isSend and: [msgNode receiver selector = #cCoerce:to:]) ifTrue: [ + msgNode receiver args asString = '{deltaST . ''int *''}' + ifTrue: [msgNode receiver: msgNode receiver args first]]. "HACK!!" self generateAt: msgNode on: aStream indent: level. (putExpr := msgNode args last) isPlusOne ifTrue: [ ((incExpr := putExpr receiver) isSend and: [incExpr selector = #at: and: [ incExpr receiver asString = msgNode receiver asString and: [ incExpr args first asString = msgNode args first asString]]]) ifTrue: [^aStream nextPutAll: '++'.]]. aStream nextPutAll: ' = '. self emitJSExpression: putExpr on: aStream! Item was changed: ----- Method: JSCodeGenerator>>generateBitShift:on:indent: (in category 'JS translation') ----- generateBitShift: msgNode on: aStream indent: level "Generate the JS code for this message onto the given stream." | arg rcvr | arg := msgNode args first. rcvr := msgNode receiver. arg isConstant ifTrue: [ "bit shift amount is a constant" - self emitJSExpression: rcvr on: aStream. arg value < 0 ifTrue: [ + "skip unneeded coercion to unsigned" + (rcvr isSend and: [rcvr selector = #cCoerce:to: and: [rcvr args second value = 'unsigned']]) + ifTrue: [self emitJSExpression: rcvr args first on: aStream] + ifFalse: [self emitJSExpression: rcvr on: aStream]. aStream nextPutAll: ' >>> ', arg value negated printString. ] ifFalse: [ + self emitJSExpression: rcvr on: aStream. aStream nextPutAll: ' << ', arg value printString. ]. ] ifFalse: [ "bit shift amount is an expression" aStream nextPutAll: 'SHIFT('. self emitJSExpression: rcvr on: aStream. aStream nextPutAll: ', '. self emitJSExpression: arg on: aStream. aStream nextPutAll: ')'. ].! Item was changed: ----- Method: JSCodeGenerator>>generateCCoercion:on:indent: (in category 'JS translation') ----- generateCCoercion: msgNode on: aStream indent: level "Generate the JS code for this message onto the given stream." | expr cType |. expr := msgNode args first. cType := msgNode args second value. (expr isSend and: [expr receiver name = 'interpreterProxy' and: [expr selector = #firstIndexableField:]]) ifTrue: [ cType := msgNode args second value. self emitJSExpression: expr args first on: aStream. cType = 'unsigned char *' ifTrue: [^aStream nextPutAll: '.bytes']. cType = 'unsigned int *' ifTrue: [^aStream nextPutAll: '.words']. cType = 'int *' ifTrue: [^aStream nextPutAll: '.wordsAsInt32Array()']. cType = 'short *' ifTrue: [^aStream nextPutAll: '.wordsAsInt16Array()']. cType = 'float *' ifTrue: [^aStream nextPutAll: '.wordsAsFloat32Array()']. cType = 'double *' ifTrue: [^aStream nextPutAll: '.wordsAsFloat64Array()']. self halt. ] ifFalse: [ + (#('int') includes: cType) ifTrue: [ - (#('int' 'unsigned int') includes: cType) ifTrue: [ aStream nextPutAll: '('. self emitJSExpression: expr on: aStream. ^aStream nextPutAll: '|0)']. + (#('unsigned int' 'unsigned' ) includes: cType) ifTrue: [ + aStream nextPutAll: '('. + self emitJSExpression: expr on: aStream. + ^ aStream nextPutAll: '>>>0)']. + ((#('double' 'float') includes: cType) or: [('sqInt (*)(*)'match: cType) + or: [#(transformPoint:into:) includes: currentMethod selector]]) - ((#('double' 'float') includes: cType) or: ['sqInt (*)(*)'match: cType]) ifFalse: [self halt]. self emitJSExpression: expr on: aStream. ] ! Item was changed: ----- Method: JSCodeGenerator>>generateDivide:on:indent: (in category 'JS translation') ----- generateDivide: msgNode on: aStream indent: level "Generate the JS code for this message onto the given stream." | rcvr arg divisor | rcvr := msgNode receiver. arg := msgNode args first. msgNode selector == #/ ifTrue: [ + (#('Matrix2x3Plugin' 'ScratchPlugin' 'FloatArrayPlugin' 'KedamaPlugin' 'KedamaPlugin2' 'FFTPlugin' 'Klatt' 'B2DPlugin') includes: self pluginName) ifFalse: [self halt: msgNode]. - (#('Matrix2x3Plugin' 'ScratchPlugin' 'FloatArrayPlugin' 'KedamaPlugin' 'KedamaPlugin2' 'FFTPlugin' 'Klatt') includes: self pluginName) ifFalse: [self halt]. self emitJSExpression: rcvr on: aStream. aStream nextPutAll: ' / '. ^self emitJSExpression: arg on: aStream]. (arg isConstant and: [UseRightShiftForDivide and: [(divisor := arg value) isInteger and: [divisor isPowerOfTwo and: [divisor > 0 and: [divisor <= (1 bitShift: 31)]]]]]) ifTrue: [ "use signed (arithmetic) right shift instead of divide" self emitJSExpression: rcvr on: aStream. aStream nextPutAll: ' >> ', (divisor log: 2) asInteger printString. ] ifFalse: [ "use float divide and coerce to integer" aStream nextPutAll: 'DIV('. self emitJSExpression: rcvr on: aStream. aStream nextPutAll: ', '. self emitJSExpression: arg on: aStream. aStream nextPutAll: ')'. ]. ! Item was changed: ----- Method: JSCodeGenerator>>generateFirstIndexableField:on:indent: (in category 'JS hacks') ----- generateFirstIndexableField: msgNode on: aStream indent: level | parent cType accessor | self oneBasedArrays: false. "HACK: detect cType from parent node" parent := thisContext sender sender sender. cType := parent method == (TAssignmentNode>>#emitJSCodeOn:level:generator:) ifTrue: [self typeOfVariable: parent receiver variable name] ifFalse: [ parent method == (TSendNode>>#emitJSCodeAsFunctionCallOn:level:generator:) ifTrue: [self typeOfArgument: (parent receiver args indexOf: msgNode) in: parent receiver selector] ifFalse: [ msgNode asString = 'interpreterProxy firstIndexableField: mapOop' ifTrue: ['unsigned int*'] ifFalse: [ msgNode asString = 'interpreterProxy firstIndexableField: blockOop' ifTrue: ['int*'] ifFalse: [ + parent method == (TReturnNode>>#emitJSCodeOn:level:generator:) + ifTrue: [currentMethod returnType] ifFalse: [ + self halt]]]]]. - self halt]]]]. cType ifNotNil: [ cType := cType copyReplaceAll: ' *' with: '* '. accessor := (cType beginsWith: 'unsigned char*') ifTrue: ['.bytes'] ifFalse: [(cType beginsWith: 'unsigned int*') ifTrue: ['.words'] ifFalse: [(cType beginsWith: 'int*') ifTrue: ['.wordsAsInt32Array()'] ifFalse: [(cType beginsWith: 'char*') ifTrue: ['.bytes'] ifFalse: [(cType beginsWith: 'float*') ifTrue: ['.wordsAsFloat32Array()'] ifFalse: [self halt: 'need to handle ', cType]]]]]. accessor ifNotNil: [msgNode args first emitJSCodeOn: aStream level: level generator: self. ^aStream nextPutAll: accessor]]. "generic code below, not needed ever hopefully" aStream nextPutAll: 'interpreterProxy.'. ^ msgNode emitJSCodeAsFunctionCallOn: aStream level: level generator: self! Item was added: + ----- Method: JSCodeGenerator>>generateLoadPointInt:on:indent: (in category 'JS hacks') ----- + generateLoadPointInt: msgNode on: aStream indent: level + aStream nextPutAll: '('. + self emitJSExpression: msgNode args second on: aStream. + aStream nextPutAll: '['. + self emitJSExpression: msgNode args first on: aStream. + aStream nextPutAll: ']|0)'. + ! Item was added: + ----- Method: JSCodeGenerator>>generateLoadPointShort:on:indent: (in category 'JS hacks') ----- + generateLoadPointShort: msgNode on: aStream indent: level + msgNode args second isVariable ifFalse: [self halt]. + msgNode args second name = 'points' ifFalse: [self halt]. + aStream nextPutAll: '(points.int16Array || (points.int16Array = new Int16Array(points.buffer, points.byteOffset)))['. + msgNode args first emitJSCodeAsExpressionOn: aStream level: 0 generator: self. + aStream nextPutAll: ']'. + ! Item was added: + ----- Method: JSCodeGenerator>>generateMakeUnsignedFrom:on:indent: (in category 'JS hacks') ----- + generateMakeUnsignedFrom: msgNode on: aStream indent: level + "Generate the JS code for this message onto the given stream." + | expr type coerce | + msgNode args size = 1 ifFalse: [self halt]. + expr := msgNode args first. + (expr isSend and: [expr selector = #at:]) + ifFalse: [^self emitJSExpression: expr on: aStream]. + coerce := expr receiver. + (coerce isSend and: [coerce selector = #cCoerce:to:]) + ifFalse: [^self emitJSExpression: expr on: aStream]. + type := (coerce args second value) copyWithout: $ . + type = 'int*' ifFalse: [self halt]. + self emitJSExpression: coerce args first on: aStream. + aStream nextPut: $[. + expr args first emitJSCodeAsExpressionOn: aStream level: 0 generator: self. + aStream nextPut: $]. + ! Item was changed: ----- Method: JSCodeGenerator>>generatePlus:on:indent: (in category 'JS translation') ----- generatePlus: msgNode on: aStream indent: level "Generate the JS code for this message onto the given stream." msgNode receiver isBitBltPtr ifFalse: [ - self checkNonPointer: msgNode receiver op: '+'. self checkNonPointer: msgNode args first op: '+'. + self ifPointerVar: msgNode receiver then: [:type | + (self generatePointerPlus: msgNode type: type on: aStream indent: level) + ifTrue: [^self]. + self halt: 'cannot do + with ', type]. self emitJSExpression: msgNode receiver on: aStream. aStream nextPutAll: ' + ']. self emitJSExpression: msgNode args first on: aStream.! Item was added: + ----- Method: JSCodeGenerator>>generatePointerPlus:type:on:indent: (in category 'JS translation') ----- + generatePointerPlus: msgNode type: type on: aStream indent: level + "Generate the JS code for this message onto the given stream." + (#('B2DPlugin' 'GeniePlugin') includes: self pluginName) ifFalse: [self halt]. + msgNode emitJSPointerArithmetic: type on: aStream level: level generator: self type: type top: true. + ^true + ! Item was added: + ----- Method: JSCodeGenerator>>ifPointerVar:then: (in category 'private') ----- + ifPointerVar: node then: aBlock + (node isSend and: [node selector = #+]) ifTrue: [ + ^self ifPointerVar: node receiver then: aBlock]. + node isVariable ifTrue: [ + (self typeOfVariable: node name) ifNotNil: [:type | + (type includes: $*) ifTrue: [aBlock value: type]]]. + ! Item was changed: ----- Method: JSCodeGenerator>>initialize (in category 'public') ----- initialize translationDict := Dictionary new. inlineList := Array new. constants := Dictionary new: 100. variables := OrderedCollection new: 100. variableDeclarations := Dictionary new: 100. methods := Dictionary new: 500. macros := Dictionary new. + self initializeJSTranslationDictionary. - self initializeCTranslationDictionary. receiverDict := Dictionary new. headerFiles := OrderedCollection new. globalVariableUsage := Dictionary new. useSymbolicConstants := true. generateDeadCode := false. scopeStack := OrderedCollection new. logger := (ProvideAnswerNotification new tag: #logger; signal) ifNil: [Transcript]. pools := IdentitySet new. abstractDeclarations := IdentitySet new. uncheckedAbstractMethods := OrderedCollection new. ! Item was removed: - ----- Method: JSCodeGenerator>>initializeCTranslationDictionary (in category 'JS translation') ----- - initializeCTranslationDictionary - "Initialize the dictionary mapping message names to actions for C code generation." - - | pairs | - translationDict := Dictionary new: 200. - pairs := #( - #& #generateAnd:on:indent: - #| #generateOr:on:indent: - #and: #generateSequentialAnd:on:indent: - #or: #generateSequentialOr:on:indent: - #not #generateNot:on:indent: - - #+ #generatePlus:on:indent: - #- #generateMinus:on:indent: - #negated #generateNegated:on:indent: - #abs #generateMath:on:indent: - #sqrt #generateMath:on:indent: - #sin #generateMath:on:indent: - #cos #generateMath:on:indent: - #tan #generateMath:on:indent: - #atan #generateMath:on:indent: - #exp #generateMath:on:indent: - #log #generateMath:on:indent: - #* #generateTimes:on:indent: - #/ #generateDivide:on:indent: - #// #generateDivide:on:indent: - #\\ #generateModulo:on:indent: - #<< #generateShiftLeft:on:indent: - #>> #generateShiftRight:on:indent: - #min: #generateMin:on:indent: - #max: #generateMax:on:indent: - #between:and: #generateBetweenAnd:on:indent: - - #bitAnd: #generateBitAnd:on:indent: - #bitOr: #generateBitOr:on:indent: - #bitXor: #generateBitXor:on:indent: - #bitShift: #generateBitShift:on:indent: - #signedBitShift: #generateSignedBitShift:on:indent: - #bitInvert32 #generateBitInvert32:on:indent: - #bitClear: #generateBitClear:on:indent: - - #< #generateLessThan:on:indent: - #<= #generateLessThanOrEqual:on:indent: - #= #generateEqual:on:indent: - #> #generateGreaterThan:on:indent: - #>= #generateGreaterThanOrEqual:on:indent: - #~= #generateNotEqual:on:indent: - #== #generateEqual:on:indent: - #~~ #generateNotEqual:on:indent: - #isNil #generateIsNil:on:indent: - #notNil #generateNotNil:on:indent: - - #whileTrue: #generateWhileTrue:on:indent: - #whileFalse: #generateWhileFalse:on:indent: - #whileTrue #generateDoWhileTrue:on:indent: - #whileFalse #generateDoWhileFalse:on:indent: - #to:do: #generateToDo:on:indent: - #to:by:do: #generateToByDo:on:indent: - #repeat #generateRepeat:on:indent: - - #ifTrue: #generateIfTrue:on:indent: - #ifFalse: #generateIfFalse:on:indent: - #ifTrue:ifFalse: #generateIfTrueIfFalse:on:indent: - #ifFalse:ifTrue: #generateIfFalseIfTrue:on:indent: - - #at: #generateAt:on:indent: - #at:put: #generateAtPut:on:indent: - #basicAt: #generateAt:on:indent: - #basicAt:put: #generateAtPut:on:indent: - - #integerValueOf: #generateIntegerValueOf:on:indent: - #integerObjectOf: #generateIntegerObjectOf:on:indent: - #isIntegerObject: #generateIsIntegerObject:on:indent: - #cCode: #generateInlineCCode:on:indent: - #cCode:inSmalltalk: #generateInlineCCode:on:indent: - #cPreprocessorDirective: #generateInlineCPreprocessorDirective:on:indent: - #preprocessorExpression: #generateInlineCppDirective:on:indent: - #isDefined:inSmalltalk:comment:ifTrue: #generateInlineCppIfDef:on:indent: - #isDefined:inSmalltalk:comment:ifTrue:ifFalse: #generateInlineCppIfDefElse:on:indent: - #isDefinedTrueExpression:inSmalltalk:comment:ifTrue:ifFalse: #generateInlineCppIfElse:on:indent: - #cCoerce:to: #generateCCoercion:on:indent: - #cCoerceSimple:to: #generateCCoercion:on:indent: - #addressOf: #generateAddressOf:on:indent: - #signedIntFromLong #generateSignedIntFromLong:on:indent: - #signedIntToLong #generateSignedIntToLong:on:indent: - #signedIntFromShort #generateSignedIntFromShort:on:indent: - #signedIntToShort #generateSignedIntToShort:on:indent: - #preIncrement #generatePreIncrement:on:indent: - #preDecrement #generatePreDecrement:on:indent: - #inline: #generateInlineDirective:on:indent: - #asFloat #generateAsFloat:on:indent: - #asInteger #generateAsInteger:on:indent: - #asUnsignedInteger #generateAsUnsignedInteger:on:indent: - #asSymbol #generateAsSymbol:on:indent: - #anyMask: #generateBitAnd:on:indent: - #raisedTo: #generateRaisedTo:on:indent: - #touch: #generateTouch:on:indent: - #bytesPerWord #generateBytesPerWord:on:indent: - #baseHeaderSize #generateBaseHeaderSize:on:indent: - - #sharedCodeNamed:inCase: #generateSharedCodeDirective:on:indent: - - #perform: #generatePerform:on:indent: - #perform:with: #generatePerform:on:indent: - #perform:with:with: #generatePerform:on:indent: - #perform:with:with:with: #generatePerform:on:indent: - #perform:with:with:with:with: #generatePerform:on:indent: - #perform:with:with:with:with:with: #generatePerform:on:indent: - - #shouldNotImplement #generateSmalltalkMetaError:on:indent: - #shouldBeImplemented #generateSmalltalkMetaError:on:indent: - - "optimized interpreterProxy calls" - #firstIndexableField: #generateFirstIndexableField:on:indent: - #slotSizeOf: #generateSlotSizeOf:on:indent: - #stSizeOf: #generateSlotSizeOf:on:indent: - #byteSizeOfBytes: #generateByteSizeOf:on:indent: - #byteSizeOf: #generateByteSizeOf:on:indent: - #fetchClassOf: #generateFetchClassOf:on:indent: - #superclassOf: #generateSuperclassOf:on:indent: - #instanceSizeOf: #generateInstanceSizeOf:on:indent: - #is:KindOf: #generateIsKindOf:on:indent: - #isFloatObject: #generateIsFloatObject:on:indent: - #cDigitCopyFrom:to:len: #generateCDigitCopy:on:indent: - #sizeOfSTArrayFromCPrimitive: #generateSizeOfSTArrayFromCPrimitive:on:indent: - #asciiValue #generateIdentityUnary:on:indent: - #primitiveFail #generateInterpreterProxyCall:on:indent: - #intAtPointer: #generateIntAtPointer:on:indent: - #byteAtPointer: #generateByteAtPointer:on:indent: - #oopForPointer: #generateOopForPointer:on:indent: - #long32At: #generateLong32At:on:indent: - #srcLongAt: #generateSrcLongAt:on:indent: - #dstLongAt: #generateDstLongAt:on:indent: - #dstLongAt:put: #generateDstLongAtPut:on:indent: - ). - - 1 to: pairs size by: 2 do: [:i | - translationDict at: (pairs at: i) put: (pairs at: i + 1)]. - - pairs := #( - #ifTrue: #generateIfTrueAsArgument:on:indent: - #ifFalse: #generateIfFalseAsArgument:on:indent: - #ifTrue:ifFalse: #generateIfTrueIfFalseAsArgument:on:indent: - #ifFalse:ifTrue: #generateIfFalseIfTrueAsArgument:on:indent: - #cCode: #generateInlineCCodeAsArgument:on:indent: - #cCode:inSmalltalk: #generateInlineCCodeAsArgument:on:indent: - ). - - asArgumentTranslationDict := Dictionary new: 8. - 1 to: pairs size by: 2 do: [:i | - asArgumentTranslationDict at: (pairs at: i) put: (pairs at: i + 1)]. - - cCodeTranslationDict := Dictionary new: 8. - pairs := #( - 'fprintf(stderr, "\n%s: %s", moduleName, s)' 'console.log(moduleName + ": " + s)' - 'interpreterProxy->majorVersion() == VM_PROXY_MAJOR' 'interpreterProxy.majorVersion() == VM_PROXY_MAJOR' - 'interpreterProxy->minorVersion() >= VM_PROXY_MINOR' 'interpreterProxy.minorVersion() >= VM_PROXY_MINOR' - 'rand()' 'Math.random()' - '*src++' 'src[_src++]' - '*dst++ = max' 'dst[_dst++] = max' - 'src++' '_src++' - '*dst++ = *src; src += 2' 'dst[_dst++] = src[_src]; _src += 2' - 'tX' 'tX' - 'tY' 'tY' - ). - 1 to: pairs size by: 2 do: [:i | - cCodeTranslationDict at: (pairs at: i) put: (pairs at: i + 1)]. - ! Item was added: + ----- Method: JSCodeGenerator>>initializeJSTranslationDictionary (in category 'JS translation') ----- + initializeJSTranslationDictionary + "Initialize the dictionary mapping message names to actions for JS code generation." + + | pairs | + translationDict := Dictionary new: 200. + pairs := #( + #& #generateAnd:on:indent: + #| #generateOr:on:indent: + #and: #generateSequentialAnd:on:indent: + #or: #generateSequentialOr:on:indent: + #not #generateNot:on:indent: + + #+ #generatePlus:on:indent: + #- #generateMinus:on:indent: + #negated #generateNegated:on:indent: + #abs #generateMath:on:indent: + #sqrt #generateMath:on:indent: + #sin #generateMath:on:indent: + #cos #generateMath:on:indent: + #tan #generateMath:on:indent: + #atan #generateMath:on:indent: + #exp #generateMath:on:indent: + #log #generateMath:on:indent: + #* #generateTimes:on:indent: + #/ #generateDivide:on:indent: + #// #generateDivide:on:indent: + #\\ #generateModulo:on:indent: + #<< #generateShiftLeft:on:indent: + #>> #generateShiftRight:on:indent: + #min: #generateMin:on:indent: + #max: #generateMax:on:indent: + #between:and: #generateBetweenAnd:on:indent: + + #bitAnd: #generateBitAnd:on:indent: + #bitOr: #generateBitOr:on:indent: + #bitXor: #generateBitXor:on:indent: + #bitShift: #generateBitShift:on:indent: + #signedBitShift: #generateSignedBitShift:on:indent: + #bitInvert32 #generateBitInvert32:on:indent: + #bitClear: #generateBitClear:on:indent: + + #< #generateLessThan:on:indent: + #<= #generateLessThanOrEqual:on:indent: + #= #generateEqual:on:indent: + #> #generateGreaterThan:on:indent: + #>= #generateGreaterThanOrEqual:on:indent: + #~= #generateNotEqual:on:indent: + #== #generateEqual:on:indent: + #~~ #generateNotEqual:on:indent: + #isNil #generateIsNil:on:indent: + #notNil #generateNotNil:on:indent: + + #whileTrue: #generateWhileTrue:on:indent: + #whileFalse: #generateWhileFalse:on:indent: + #whileTrue #generateDoWhileTrue:on:indent: + #whileFalse #generateDoWhileFalse:on:indent: + #to:do: #generateToDo:on:indent: + #to:by:do: #generateToByDo:on:indent: + #repeat #generateRepeat:on:indent: + + #ifTrue: #generateIfTrue:on:indent: + #ifFalse: #generateIfFalse:on:indent: + #ifTrue:ifFalse: #generateIfTrueIfFalse:on:indent: + #ifFalse:ifTrue: #generateIfFalseIfTrue:on:indent: + + #at: #generateAt:on:indent: + #at:put: #generateAtPut:on:indent: + #basicAt: #generateAt:on:indent: + #basicAt:put: #generateAtPut:on:indent: + + #integerValueOf: #generateIntegerValueOf:on:indent: + #integerObjectOf: #generateIntegerObjectOf:on:indent: + #isIntegerObject: #generateIsIntegerObject:on:indent: + #cCode: #generateInlineCCode:on:indent: + #cCode:inSmalltalk: #generateInlineCCode:on:indent: + #cPreprocessorDirective: #generateInlineCPreprocessorDirective:on:indent: + #preprocessorExpression: #generateInlineCppDirective:on:indent: + #isDefined:inSmalltalk:comment:ifTrue: #generateInlineCppIfDef:on:indent: + #isDefined:inSmalltalk:comment:ifTrue:ifFalse: #generateInlineCppIfDefElse:on:indent: + #isDefinedTrueExpression:inSmalltalk:comment:ifTrue:ifFalse: #generateInlineCppIfElse:on:indent: + #cCoerce:to: #generateCCoercion:on:indent: + #cCoerceSimple:to: #generateCCoercion:on:indent: + #addressOf: #generateAddressOf:on:indent: + #signedIntFromLong #generateSignedIntFromLong:on:indent: + #signedIntToLong #generateSignedIntToLong:on:indent: + #signedIntFromShort #generateSignedIntFromShort:on:indent: + #signedIntToShort #generateSignedIntToShort:on:indent: + #preIncrement #generatePreIncrement:on:indent: + #preDecrement #generatePreDecrement:on:indent: + #inline: #generateInlineDirective:on:indent: + #asFloat #generateAsFloat:on:indent: + #asInteger #generateAsInteger:on:indent: + #asUnsignedInteger #generateAsUnsignedInteger:on:indent: + #asSymbol #generateAsSymbol:on:indent: + #anyMask: #generateBitAnd:on:indent: + #raisedTo: #generateRaisedTo:on:indent: + #touch: #generateTouch:on:indent: + #bytesPerWord #generateBytesPerWord:on:indent: + #baseHeaderSize #generateBaseHeaderSize:on:indent: + + #sharedCodeNamed:inCase: #generateSharedCodeDirective:on:indent: + + #perform: #generatePerform:on:indent: + #perform:with: #generatePerform:on:indent: + #perform:with:with: #generatePerform:on:indent: + #perform:with:with:with: #generatePerform:on:indent: + #perform:with:with:with:with: #generatePerform:on:indent: + #perform:with:with:with:with:with: #generatePerform:on:indent: + + #shouldNotImplement #generateSmalltalkMetaError:on:indent: + #shouldBeImplemented #generateSmalltalkMetaError:on:indent: + + "optimized interpreterProxy calls" + #firstIndexableField: #generateFirstIndexableField:on:indent: + #slotSizeOf: #generateSlotSizeOf:on:indent: + #stSizeOf: #generateSlotSizeOf:on:indent: + #byteSizeOfBytes: #generateByteSizeOf:on:indent: + #byteSizeOf: #generateByteSizeOf:on:indent: + #fetchClassOf: #generateFetchClassOf:on:indent: + #superclassOf: #generateSuperclassOf:on:indent: + #instanceSizeOf: #generateInstanceSizeOf:on:indent: + #is:KindOf: #generateIsKindOf:on:indent: + #isFloatObject: #generateIsFloatObject:on:indent: + #cDigitCopyFrom:to:len: #generateCDigitCopy:on:indent: + #sizeOfSTArrayFromCPrimitive: #generateSizeOfSTArrayFromCPrimitive:on:indent: + #asciiValue #generateIdentityUnary:on:indent: + #primitiveFail #generateInterpreterProxyCall:on:indent: + #intAtPointer: #generateIntAtPointer:on:indent: + #byteAtPointer: #generateByteAtPointer:on:indent: + #oopForPointer: #generateOopForPointer:on:indent: + #long32At: #generateLong32At:on:indent: + #srcLongAt: #generateSrcLongAt:on:indent: + #dstLongAt: #generateDstLongAt:on:indent: + #dstLongAt:put: #generateDstLongAtPut:on:indent: + ). + + 1 to: pairs size by: 2 do: [:i | + translationDict at: (pairs at: i) put: (pairs at: i + 1)]. + + pairs := #( + #ifTrue: #generateIfTrueAsArgument:on:indent: + #ifFalse: #generateIfFalseAsArgument:on:indent: + #ifTrue:ifFalse: #generateIfTrueIfFalseAsArgument:on:indent: + #ifFalse:ifTrue: #generateIfFalseIfTrueAsArgument:on:indent: + #cCode: #generateInlineCCodeAsArgument:on:indent: + #cCode:inSmalltalk: #generateInlineCCodeAsArgument:on:indent: + ). + + asArgumentTranslationDict := Dictionary new: 8. + 1 to: pairs size by: 2 do: [:i | + asArgumentTranslationDict at: (pairs at: i) put: (pairs at: i + 1)]. + + cCodeTranslationDict := Dictionary new: 8. + pairs := #( + 'fprintf(stderr, "\n%s: %s", moduleName, s)' 'console.log(moduleName + ": " + s)' + 'interpreterProxy->majorVersion() == VM_PROXY_MAJOR' 'interpreterProxy.majorVersion() == VM_PROXY_MAJOR' + 'interpreterProxy->minorVersion() >= VM_PROXY_MINOR' 'interpreterProxy.minorVersion() >= VM_PROXY_MINOR' + 'rand()' 'Math.random()' + '*src++' 'src[_src++]' + '*dst++ = max' 'dst[_dst++] = max' + 'src++' '_src++' + '*dst++ = *src; src += 2' 'dst[_dst++] = src[_src]; _src += 2' + 'tX' 'tX' + 'tY' 'tY' + '((sqInt (*)(sqInt, sqInt, sqInt))copyBitsFn)(x0, x1, yValue)' 'copyBitsFn(x0, x1, yValue)' + '((sqInt (*)(sqInt))loadBBFn)(bbObj)' 'loadBBFn(bbObj)' + ). + 1 to: pairs size by: 2 do: [:i | + cCodeTranslationDict at: (pairs at: i) put: (pairs at: i + 1)]. + ! Item was changed: ----- Method: JSCodeGenerator>>isPointer: (in category 'private') ----- isPointer: node + self ifPointerVar: node then: [:type | ^true]. - node isVariable ifFalse: [^false]. - (self typeOfVariable: node name) ifNotNil: [:type | ^type includes: $*]. ^false! Item was changed: ----- Method: JSMethod>>emitJSCodeOn:generator: (in category 'JS code generation') ----- emitJSCodeOn: aStream generator: aCodeGen "Emit JS code for this method onto the given stream. All calls to inlined methods should already have been expanded." aCodeGen currentMethod: self. aCodeGen pushScope: declarations while: [ self emitJSCommentOn: aStream. "place method comment before function" self emitJSHeaderOn: aStream generator: aCodeGen. + (self emitJSSpecialOn: aStream level: 1 generator: aCodeGen) + ifFalse: [parseTree emitJSCodeOn: aStream level: 1 generator: aCodeGen]. - parseTree emitJSCodeOn: aStream level: 1 generator: aCodeGen. aStream nextPutAll: '}'; cr]! Item was added: + ----- Method: JSMethod>>emitJSSpecialOn:level:generator: (in category 'JS hacks') ----- + emitJSSpecialOn: aStream level: level generator: aCodeGen + | expr type | + aCodeGen pluginName = 'B2DPlugin' ifFalse: [^false]. + (returnType includes: $*) ifFalse: [^false]. + parseTree statements first isReturn ifFalse: [^false]. + expr := parseTree statements first expression. + expr isSend ifFalse: [^false]. + type := returnType. + expr selector = #cCoerce:to: ifTrue: [ + type = expr args second value ifFalse: [self halt]. + expr := expr args first. + ]. + expr selector = #+ ifFalse: [^false]. + aStream tab: level; nextPutAll: 'return '. + expr emitJSPointerArithmetic: type on: aStream level: level generator: aCodeGen type: type top: true. + aStream nextPutAll: ';'; cr. + ^true + ! Item was changed: ----- Method: JSPluginCodeGenerator>>ignoredMethods (in category 'public') ----- ignoredMethods pluginName = 'BitBltPlugin' ifTrue: [ ^#(dstLongAt: dstLongAt:put: srcLongAt:)]. pluginName = 'ScratchPlugin' ifTrue: [ ^(ScratchPlugin organization listAtCategoryNamed: 'serial port'), (ScratchPlugin organization listAtCategoryNamed: 'os functions')]. + pluginName = 'B2DPlugin' ifTrue: [ + ^self translatedMethodsB2DPlugin collect: [:ea | ea key]]. ^super ignoredMethods! Item was added: + ----- Method: JSPluginCodeGenerator>>overrideJSTranslationDictionary (in category 'public') ----- + overrideJSTranslationDictionary + | sel | + sel := (#translatedMethods, self pluginName) asSymbol. + (self respondsTo: sel) ifFalse: [^self]. + (self perform: sel) associationsDo: [:assoc | + translationDict at: assoc key put: assoc value]. + ! Item was changed: ----- Method: JSPluginCodeGenerator>>pluginName: (in category 'public') ----- pluginName: aString "TPR - moved from JSCodeGenerator" "Set the plugin name when generating plugins." + pluginName := aString. + self overrideJSTranslationDictionary.! - pluginName := aString.! Item was added: + ----- Method: JSPluginCodeGenerator>>translatedMethodsB2DPlugin (in category 'public') ----- + translatedMethodsB2DPlugin + "see senders of translatedMethods" + ^{ + #makeUnsignedFrom: -> #generateMakeUnsignedFrom:on:indent:. + #loadPointIntAt:from: -> #generateLoadPointInt:on:indent:. + #loadPointShortAt:from: -> #generateLoadPointShort:on:indent:. + }! Item was removed: - ----- Method: JSSmartSyntaxPluginCodeGenerator>>initializeCTranslationDictionary (in category 'translating builtins') ----- - initializeCTranslationDictionary - "Initialize the dictionary mapping message names to actions for C code generation." - - | pairs | - super initializeCTranslationDictionary. - pairs := #( - #asCInt #generateAsCInt:on:indent: - #asCUnsigned #generateAsCUnsigned:on:indent: - #asCBoolean #generateAsCBoolean:on:indent: - #asCDouble #generateAsCDouble:on:indent: - - #asSmallIntegerObj #generateAsSmallIntegerObj:on:indent: - #asPositiveIntegerObj #generateAsPositiveIntegerObj:on:indent: - #asBooleanObj #generateAsBooleanObj:on:indent: - #asFloatObj #generateAsFloatObj:on:indent: - - #asIf:var: #generateAsIfVar:on:indent: - #asIf:var:asValue: #generateAsIfVarAsValue:on:indent: - #asIf:var:put: #generateAsIfVarPut:on:indent: - #field: #generateField:on:indent: - #field:put: #generateFieldPut:on:indent: - - #class #generateClass:on:indent: - - #stSize #generateStSize:on:indent: - #stAt: #generateStAt:on:indent: - #stAt:put: #generateStAtPut:on:indent: - - #asCharPtr #generateAsCharPtr:on:indent: - #asIntPtr #generateAsIntPtr:on:indent: - #cPtrAsOop #generateCPtrAsOop:on:indent: - #next #generateNext:on:indent: - - #asOop: #generateAsOop:on:indent: - #asValue: #generateAsValue:on:indent: - - #isFloat #generateIsFloat:on:indent: - #isIndexable #generateIsIndexable:on:indent: - #isIntegerOop #generateIsIntegerOop:on:indent: - #isIntegerValue #generateIsIntegerValue:on:indent: - #FloatOop #generateIsFloatValue:on:indent: - #isWords #generateIsWords:on:indent: - #isWordsOrBytes #generateIsWordsOrBytes:on:indent: - #isPointers #generateIsPointers:on:indent: - #isNil #generateIsNil:on:indent: - #isMemberOf: #generateIsMemberOf:on:indent: - #isKindOf: #generateIsKindOf:on:indent: - - #fromStack: #generateFromStack:on:indent: - #clone #generateClone:on:indent - #new #generateNew:on:indent - #new: #generateNewSize:on:indent - #superclass #generateSuperclass:on:indent: - #remapOop:in: #generateRemapOopIn:on:indent: - #debugCode: #generateDebugCode:on:indent: - ). - - 1 to: pairs size by: 2 do: [:i | - translationDict at: (pairs at: i) put: (pairs at: i + 1)]. - ! Item was added: + ----- Method: JSSmartSyntaxPluginCodeGenerator>>initializeJSTranslationDictionary (in category 'translating builtins') ----- + initializeJSTranslationDictionary + "Initialize the dictionary mapping message names to actions for C code generation." + + | pairs | + super initializeJSTranslationDictionary. + pairs := #( + #asCInt #generateAsCInt:on:indent: + #asCUnsigned #generateAsCUnsigned:on:indent: + #asCBoolean #generateAsCBoolean:on:indent: + #asCDouble #generateAsCDouble:on:indent: + + #asSmallIntegerObj #generateAsSmallIntegerObj:on:indent: + #asPositiveIntegerObj #generateAsPositiveIntegerObj:on:indent: + #asBooleanObj #generateAsBooleanObj:on:indent: + #asFloatObj #generateAsFloatObj:on:indent: + + #asIf:var: #generateAsIfVar:on:indent: + #asIf:var:asValue: #generateAsIfVarAsValue:on:indent: + #asIf:var:put: #generateAsIfVarPut:on:indent: + #field: #generateField:on:indent: + #field:put: #generateFieldPut:on:indent: + + #class #generateClass:on:indent: + + #stSize #generateStSize:on:indent: + #stAt: #generateStAt:on:indent: + #stAt:put: #generateStAtPut:on:indent: + + #asCharPtr #generateAsCharPtr:on:indent: + #asIntPtr #generateAsIntPtr:on:indent: + #cPtrAsOop #generateCPtrAsOop:on:indent: + #next #generateNext:on:indent: + + #asOop: #generateAsOop:on:indent: + #asValue: #generateAsValue:on:indent: + + #isFloat #generateIsFloat:on:indent: + #isIndexable #generateIsIndexable:on:indent: + #isIntegerOop #generateIsIntegerOop:on:indent: + #isIntegerValue #generateIsIntegerValue:on:indent: + #FloatOop #generateIsFloatValue:on:indent: + #isWords #generateIsWords:on:indent: + #isWordsOrBytes #generateIsWordsOrBytes:on:indent: + #isPointers #generateIsPointers:on:indent: + #isNil #generateIsNil:on:indent: + #isMemberOf: #generateIsMemberOf:on:indent: + #isKindOf: #generateIsKindOf:on:indent: + + #fromStack: #generateFromStack:on:indent: + #clone #generateClone:on:indent + #new #generateNew:on:indent + #new: #generateNewSize:on:indent + #superclass #generateSuperclass:on:indent: + #remapOop:in: #generateRemapOopIn:on:indent: + #debugCode: #generateDebugCode:on:indent: + ). + + 1 to: pairs size by: 2 do: [:i | + translationDict at: (pairs at: i) put: (pairs at: i + 1)]. + ! Item was changed: ----- Method: TAssignmentNode>>emitJSCodeOn:level:generator: (in category '*vmmakerjs') ----- emitJSCodeOn: aStream level: level generator: aCodeGen expression isSwitch ifTrue: [^expression emitJSCodeOn: aStream addToEndOfCases: self level: level generator: aCodeGen]. + (self isVariableUpdatingAssignment and: [(aCodeGen isPointer: variable) not]) - self isVariableUpdatingAssignment ifTrue: [(expression args first isConstant and: [expression args first value = 1]) ifTrue: [aStream nextPutAll: expression selector, expression selector. variable emitJSCodeOn: aStream level: level generator: aCodeGen] ifFalse: [ variable emitJSCodeOn: aStream level: level generator: aCodeGen. aStream nextPutAll: ' ', expression selector, '= '. expression args first emitJSCodeAsArgumentOn: aStream level: level generator: aCodeGen]] ifFalse: [ | coerceToInt | coerceToInt := (variable isFloatIn: aCodeGen) not and: [expression isFloatIn: aCodeGen]. variable emitJSCodeOn: aStream level: level generator: aCodeGen. aStream nextPutAll: ' = '. expression emitJSCodeAsArgumentOn: aStream level: level generator: aCodeGen. coerceToInt ifTrue: [aStream nextPutAll: '|0'].]! Item was added: + ----- Method: TSendNode>>emitJSPointerArithmetic:on:level:generator:type:top: (in category '*vmmakerjs') ----- + emitJSPointerArithmetic: type on: aStream level: level generator: aGenerator type: cType top: top + (selector = #+) ifFalse: [self halt]. + receiver isVariable + ifTrue: [ | typeAndSize | + typeAndSize := ({'int' -> #('Int32Array' 4). 'float' -> #('Float32Array' 4)} as: Dictionary) + at: ((cType copyUpTo: $*) copyWithout: $ ). + aStream nextPutAll: ('new {1}({2}.buffer, {2}.byteOffset + {3} * (' + format: {typeAndSize first. receiver name. typeAndSize second})] + ifFalse: [receiver emitJSPointerArithmetic: type on: aStream level: level generator: aGenerator type: cType top: false. + aStream nextPutAll: ' + ']. + aGenerator emitJSExpression: arguments first on: aStream. + top ifTrue: [aStream nextPutAll: '))'].! |
Free forum by Nabble | Edit this page |