[Vm-dev] VM Maker: VMMakerJS-bf.16.mcz

commits at source.squeak.org commits at source.squeak.org
Thu Nov 13 23:27:31 UTC 2014


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: '))'].!



More information about the Vm-dev mailing list