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

commits at source.squeak.org commits at source.squeak.org
Fri Oct 10 13:46:11 UTC 2014


Bert Freudenberg uploaded a new version of VMMakerJS to project VM Maker:
http://source.squeak.org/VMMaker/VMMakerJS-bf.5.mcz

==================== Summary ====================

Name: VMMakerJS-bf.5
Author: bf
Time: 6 October 2014, 4:26:33.104 pm
UUID: be6d96b8-621f-4ef1-b2b2-566790b1b5e6
Ancestors: VMMakerJS-bf.4

Make BitBltPlugin translate. Still buggy though.

=============== Diff against VMMakerJS-bf.4 ===============

Item was changed:
  ----- Method: JSCodeGenerator>>addClassVarsFor: (in category 'public') -----
  addClassVarsFor: aClass
  	"Add the class variables for the given class to the code base as constants."
  	| val node |
  	aClass classPool associationsDo: [:assoc | 
  		val := assoc value.
+ 		(useSymbolicConstants and:[self isJSLiteral: val])
- 		(useSymbolicConstants and:[self isCLiteral: val])
  			ifTrue:[node := TDefineNode new setName: assoc key asString value: assoc value]
  			ifFalse:[node := TConstantNode new setValue: assoc value].
  		constants at: assoc key asString put: node].
  !

Item was changed:
  ----- Method: JSCodeGenerator>>addPoolVarsFor: (in category 'public') -----
  addPoolVarsFor: aClass 
  	"Add the pool variables for the given class to the code base as constants."
  
  	(aClass sharedPools reject: [:pool| pools includes: pool]) do:
  		[:pool |
  		pools add: pool.
  		pool bindingsDo: [:assoc | | val node |
  			val := assoc value.
+ 			node := (useSymbolicConstants and:[self isJSLiteral: val])
- 			node := (useSymbolicConstants and:[self isCLiteral: val])
  						ifTrue:[TDefineNode new setName: assoc key asString value: assoc value]
  						ifFalse:[TConstantNode new setValue: assoc value].
  			constants at: assoc key asString put: node]].!

Item was removed:
- ----- Method: JSCodeGenerator>>cFunctionNameFor: (in category 'JS code generator') -----
- cFunctionNameFor: aSelector
- 	"Create a C function name from the given selector by omitting colons
- 	and prefixing with the plugin name if the method is exported."
- 	^aSelector copyWithout: $:!

Item was removed:
- ----- Method: JSCodeGenerator>>cLiteralFor: (in category 'JS code generator') -----
- cLiteralFor: anObject
- 	"Return a string representing the C literal value for the given object."
- 	(anObject isKindOf: Integer) ifTrue: [^ anObject printString].
- 	(anObject isKindOf: String) ifTrue: [^ '"', anObject, '"' ].
- 	(anObject isKindOf: Float) ifTrue: [^ anObject printString ].
- 	anObject == nil ifTrue: [^ 'null' ].
- 	anObject == true ifTrue: [^ 'true' ].
- 	anObject == false ifTrue: [^ 'false' ].
- 	self error:
- 		'Warning: A Smalltalk literal could not be translated into a C constant: ', anObject printString.
- 	^'"XXX UNTRANSLATABLE CONSTANT XXX"'!

Item was removed:
- ----- Method: JSCodeGenerator>>emitDefaultMacrosOn: (in category 'JS code generator') -----
- emitDefaultMacrosOn: aStream
- 	"Emit macros to provide default implementations of certain functions used by
- 	the interpreter. If not previously defined in config.h they will be defined here.
- 	The definitions will be available to any module that includes sqMemoryAccess.h.
- 	The default macros are chosen for backward compatibility with existing platform
- 	support code."
- 
- 	"Reduce the obscurity of these macros by flagging some selectors to
- 	make this method show up as a sender."
- 
- 	self flag: #assert:.
- 	"If assert() has not been defined e.g. by sqAssert.h, then use the standard clib version"
- 	aStream cr;
- 		nextPutAll: '#ifndef assert'; cr;
- 		nextPutAll: ' #include <assert.h>'; cr;
- 		nextPutAll: '#endif'; cr.
- 
- 	self flag: #allocateMemory:minimum:imageFile:headerSize:.
- 	aStream cr;
- 		nextPutAll: '#ifndef allocateMemoryMinimumImageFileHeaderSize'; cr;
- 		nextPutAll: ' /* Called by Interpreter>>allocateMemory:minimum:imageFile:headerSize: */'; cr;
- 		nextPutAll: ' /* Default definition if not previously defined in config.h */'; cr;
- 		nextPutAll: ' #define allocateMemoryMinimumImageFileHeaderSize(',
- 						'heapSize, minimumMemory, fileStream, headerSize) \'; cr;
- 		nextPutAll: '    sqAllocateMemory(minimumMemory, heapSize)'; cr;
- 		nextPutAll: '#endif'; cr.
- 
- 	self flag: #sqImage:read:size:length:.
- 	aStream cr;
- 		nextPutAll: '#ifndef sqImageFileReadEntireImage'; cr;
- 		nextPutAll: ' /* Called by Interpreter>>sqImage:read:size:length: */'; cr;
- 		nextPutAll: ' /* Default definition if not previously defined in config.h */'; cr;
- 		nextPutAll: ' #define sqImageFileReadEntireImage(memoryAddress, ',
- 						'elementSize,  length, fileStream) \'; cr;
- 		nextPutAll: '    sqImageFileRead(memoryAddress, elementSize,  length, fileStream)'; cr;
- 		nextPutAll: '#endif'; cr.
- 
- 	self flag: #error:.
- 	aStream cr;
- 		nextPutAll: '#ifndef error'; cr;
- 		nextPutAll: ' /* error() function called from Interpreter */'; cr;
- 		nextPutAll: ' /* Default definition if not previously defined in config.h */'; cr;
- 		nextPutAll: ' #define error(str) defaultErrorProc(str)'; cr;
- 		nextPutAll: '#endif'; cr.
- 
- 	self flag: #primitiveMicrosecondClock; flag: #ioMicroSecondClock.
- 	aStream cr;
- 		nextPutAll: '#ifndef ioMicroSecondClock'; cr;
- 		nextPutAll: ' /* Called by Interpreter>>primitiveMicrosecondClock and GC methods */'; cr;
- 		nextPutAll: ' /* Default definition if not previously defined in config.h */'; cr;
- 		nextPutAll: ' #define ioMicroSecondClock ioMSecs'; cr;
- 		nextPutAll: '#endif'; cr.
- 
- 	self flag: #primitiveUtcWithOffset; flag: #setMicroSeconds:andOffset:.
- 	aStream cr;
- 		nextPutAll: '#ifndef ioUtcWithOffset'; cr;
- 		nextPutAll: ' /* Called by Interpreter>>primitiveUtcWithOffset */'; cr;
- 		nextPutAll: ' /* Default definition if not previously defined in config.h */'; cr;
- 		nextPutAll: ' #define ioUtcWithOffset(clock, offset) setMicroSecondsandOffset(clock, offset)'; cr;
- 		nextPutAll: '#endif'; cr.
- !

Item was changed:
  ----- Method: JSCodeGenerator>>emitJSConstantsOn: (in category 'JS code generator') -----
  emitJSConstantsOn: aStream
  	"Store the global variable declarations on the given stream."
  	| unused constList node |
  	unused := constants keys asSet.
  	methods do: [ :meth |
  		meth parseTree nodesDo: [ :n |
  			n isConstant ifTrue: [ unused remove: n name ifAbsent: []]]].
  	constList := constants keys reject: [ :any | unused includes: any].
  	constList isEmpty ifTrue: [^self].
  	aStream nextPutAll: '/*** Constants ***/';
  		 cr.
  	constList asSortedCollection do: [ :varName |
  		node := constants at: varName.
  		node name isEmpty ifFalse: [
  			aStream nextPutAll: 'var '.
  			aStream nextPutAll: node name.
  			aStream nextPutAll: ' = '.
+ 			aStream nextPutAll: (self jsLiteralFor: node value).
- 			aStream nextPutAll: (self cLiteralFor: node value).
  			aStream nextPut: $;.
  			aStream cr
  		].
  	].
  	aStream cr.!

Item was removed:
- ----- Method: JSCodeGenerator>>emitJSHeaderForPrimitivesOn: (in category 'JS code generator') -----
- emitJSHeaderForPrimitivesOn: aStream
- 	"Write a C file header for compiled primitives onto the given stream."
- 
- 	aStream
- 		nextPutAll: '/* Automatically generated from Squeak (';
- 		nextPutAll: VMMaker versionString;
- 		nextPutAll: ') on '.
- 	Time dateAndTimeNow do: [:e | aStream nextPutAll: e asString; nextPut: Character space].
- 	aStream
- 		nextPutAll: '*/';
- 		cr; cr;
- 		nextPutAll: '#include "sq.h"'; cr; cr.
- 
- 	"Additional header files"
- 	headerFiles do:[:hdr|
- 		aStream nextPutAll:'#include '; nextPutAll: hdr; cr].
- 
- 	aStream nextPutAll: '
- #include "sqMemoryAccess.h"
- 
- /*** Imported Functions/Variables ***/
- extern sqInt stackValue(sqInt);
- extern sqInt stackIntegerValue(sqInt);
- extern sqInt successFlag;
- 
- /* allows accessing Strings in both C and Smalltalk */
- #define asciiValue(c) c
- '.
- 	aStream cr.!

Item was changed:
  ----- Method: JSCodeGenerator>>emitJSHeaderOn: (in category 'JS code generator') -----
  emitJSHeaderOn: aStream
+ 	self halt.!
- 	"Write a C file header onto the given stream."
- 
- 	aStream nextPutAll: '/* '.
- 	aStream nextPutAll: VMMaker headerNotice.
- 	aStream nextPutAll: ' */'; cr.
- 	self emitGlobalStructFlagOn: aStream.
- 	aStream nextPutAll: '#include "sq.h"'; cr.
- 
- 	"Additional header files"
- 	headerFiles do:[:hdr|
- 		aStream nextPutAll:'#include '; nextPutAll: hdr; cr].
- 
- 	"Default definitions for optional functions, provided for backward compatibility"
- 	self emitDefaultMacrosOn: aStream.
- 
- 	aStream nextPutAll: '
- #include "sqMemoryAccess.h"
- 
- sqInt printCallStack(void);
- void defaultErrorProc(char *s) {
- 	/* Print an error message and exit. */
- 	static sqInt printingStack = false;
- 
- 	printf("\n%s\n\n", s);
- 	if (!!printingStack) {
- 		/* flag prevents recursive error when trying to print a broken stack */
- 		printingStack = true;
- 		printCallStack();
- 	}
- 	exit(-1);
- }
- '.
- 	aStream cr.!

Item was changed:
  ----- Method: JSCodeGenerator>>emitJSTestBlock:on: (in category 'JS code generator') -----
  emitJSTestBlock: aBlockNode on: aStream
+ 	"Emit JS code for the given block node to be used as a loop test."
- 	"Emit C code for the given block node to be used as a loop test."
  
  	aBlockNode statements size > 1 ifTrue: [
  		aBlockNode emitJSCodeOn: aStream level: 0 generator: self.
  	] ifFalse: [
  		aBlockNode statements first asExpression emitJSCodeOn: aStream level: 0 generator: self.
  	].!

Item was changed:
  ----- Method: JSCodeGenerator>>emitJSVariablesOn: (in category 'JS code generator') -----
  emitJSVariablesOn: aStream 
  	"Store the global variable declarations on the given stream."
  	aStream nextPutAll: '/*** Variables ***/'; cr.
  	variables asSortedCollection
  		do: [:var | 	| varString varDecl |
  			varString := var asString.
  			aStream nextPutAll: 'var ', varString.
  			varDecl := variableDeclarations at: varString ifAbsent: [''].
  			(varDecl includes: $=)
+ 				ifTrue: [ | const |
+ 					const := ((varDecl copyAfter: $=) replaceAll: ${ with: $[) replaceAll: $} with: $].
+ 					aStream nextPutAll: ' =', const]
+ 				ifFalse: [(varDecl includesAnyOf: '*[')
+ 					ifTrue: [(varDecl includes: $[)
+ 						ifTrue: [ | size |
+ 							size := (varDecl copyAfter: $[) copyUpTo: $].
+ 							size ifEmpty: [self halt].
+ 							aStream nextPutAll: ' = new Array(', size, ')']
+ 						ifFalse: [aStream nextPutAll: ' = null']]
- 				ifTrue: [aStream nextPutAll: ' =', (varDecl copyAfter: $=)]
- 				ifFalse: [(varDecl includes: $*)
- 					ifTrue: [aStream nextPutAll: ' = null']
  					ifFalse: [aStream nextPutAll: ' = 0']].
  			aStream nextPutAll: ';'; cr].
  	aStream cr.
  !

Item was added:
+ ----- Method: JSCodeGenerator>>generateAbs:on:indent: (in category 'JS translation') -----
+ generateAbs: msgNode on: aStream indent: level
+ 	"Generate the JS code for the negated message onto the given stream."
+ 
+ 	aStream nextPutAll: 'Math.abs('.
+ 	self emitJSExpression: msgNode receiver on: aStream.
+ 	aStream nextPutAll: ')'.
+ !

Item was changed:
  ----- Method: JSCodeGenerator>>generateAsSymbol:on:indent: (in category 'JS translation') -----
  generateAsSymbol: msgNode on: aStream indent: level
  	"Generate the JS code for this message onto the given stream.
  	 The receiver is expected to be a JSConstantNode."
  
+ 	aStream nextPutAll: (self jsFunctionNameFor: msgNode receiver nameOrValue)!
- 	aStream nextPutAll: (self cFunctionNameFor: msgNode receiver nameOrValue)!

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: [
  			aStream nextPutAll: ' >>> ', arg value negated printString.
  		] ifFalse: [
  			aStream nextPutAll: ' << ', arg value printString.
  		].
  	] ifFalse: [
  		"bit shift amount is an expression"
+ 		aStream nextPutAll: 'SHIFT('.
- 		self error: 'need to add BITSHIFT to emitJSHeaderOn:'.
- 		aStream nextPutAll: 'BITSHIFT('.
  		self emitJSExpression: rcvr on: aStream.
  		aStream nextPutAll: ', '.
  		self emitJSExpression: arg on: aStream.
  		aStream nextPutAll: ')'.
  	].!

Item was added:
+ ----- Method: JSCodeGenerator>>generateByteAtPointer:on:indent: (in category 'JS hacks') -----
+ generateByteAtPointer: msgNode on: aStream indent: level
+ 	msgNode args first asString = 'sourcePtr + charIndex - 1'
+ 		ifTrue: [^aStream nextPutAll: 'sourcePtr[charIndex - 1]'].
+ 	self halt
+ 	!

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 = 'int *' ifTrue: [^aStream nextPutAll: '.wordsAsInt32Array()'].
  		cType = 'float *' ifTrue: [^aStream nextPutAll: '.wordsAsFloat32Array()'].
  		self halt.
  	] ifFalse: [
+ 		((#('double' 'float') includes: cType) or: ['sqInt (*)(*)'match: cType])
+ 			ifFalse: [self halt].
- 		(#('double' 'float') includes: cType) ifFalse: [self halt].
  		self emitJSExpression: expr on: aStream.
  	]
  !

Item was added:
+ ----- Method: JSCodeGenerator>>generateDstLongAt:on:indent: (in category 'JS hacks') -----
+ generateDstLongAt: msgNode on: aStream indent: level
+ 	aStream nextPutAll: 'destBits['.
+ 	msgNode args first emitJSCodeAsExpressionOn: aStream level: level generator: self.
+ 	aStream nextPutAll: ' >>> 2]'.
+ 	
+ !

Item was added:
+ ----- Method: JSCodeGenerator>>generateDstLongAtPut:on:indent: (in category 'JS hacks') -----
+ generateDstLongAtPut: msgNode on: aStream indent: level
+ 	aStream nextPutAll: 'destBits['.
+ 	msgNode args first emitJSCodeAsExpressionOn: aStream level: level generator: self.
+ 	aStream nextPutAll: ' >>> 2] = '.
+ 	msgNode args second emitJSCodeOn: aStream level: level generator: self.
+ 	
+ !

Item was changed:
  ----- Method: JSCodeGenerator>>generateEqual:on:indent: (in category 'JS translation') -----
  generateEqual: msgNode on: aStream indent: level
  	"Generate the JS code for this message onto the given stream."
  	| argNode test |
  	argNode :=  msgNode args first.
+ 	"quick test for nil, true, false"
  	argNode isInterpreterProxyConstant ifTrue: [
  		test := #(isNil isTrue isFalse) at: (#(nilObject trueObject falseObject) indexOf: argNode selector).
  		self emitJSExpression: msgNode receiver on: aStream.
  		^aStream nextPut: $.; nextPutAll: test].
+ 	"cannot compare pointers to 0"
+ 	(argNode isConstantNull or: [argNode isConstantZero and: [self isPointer: msgNode receiver]]) ifTrue: [
+ 		aStream nextPutAll: '!!'.
+ 		^self emitJSExpression: msgNode receiver on: aStream].
  	self emitJSExpression: msgNode receiver on: aStream.
  	aStream nextPutAll: ' === '.
  	self emitJSExpression: argNode on: aStream.!

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: [
+ 		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 changed:
  ----- Method: JSCodeGenerator>>generateIfFalse:on:indent: (in category 'JS translation') -----
  generateIfFalse: msgNode on: aStream indent: level
  	"Generate the JS code for this message onto the given stream."
  
  	(self nilOrBooleanConstantReceiverOf: msgNode)
  		ifNil:
+ 			[aStream nextPutAll: 'if ('.
+ 			self generateNot: (TSendNode new
+ 					setSelector: #not receiver: msgNode receiver arguments: #())
+ 				on: aStream indent: level + 1.
+ 			aStream nextPutAll: ') {'; cr.
- 			[aStream nextPutAll: 'if (!!('.
- 			msgNode receiver emitJSCodeAsExpressionOn: aStream level: level + 1 generator: self.
- 			aStream nextPutAll: ')) {'; cr.
  			msgNode args last emitJSCodeOn: aStream level: level + 1 generator: self.
  			level timesRepeat: [aStream tab].
  			aStream nextPut: $}]
  		ifNotNil:
  			[:const |
  			const ifFalse:
  				[msgNode args first emitJSCodeOn: aStream level: level generator: self]]!

Item was changed:
  ----- Method: JSCodeGenerator>>generateInlineCppIfDef:on:indent: (in category 'JS translation') -----
  generateInlineCppIfDef: msgNode on: aStream indent: level
  	"Generate the C code for this message onto the given stream."
  
+ 	aStream nextPutAll: '// skipping ifdef ', msgNode args first value!
- 	| comment |
- self halt.
- 	aStream cr; nextPutAll: '# ifdef ', msgNode args first value.
- 	comment := msgNode args third value.
- 	(comment isKindOf: String)
- 		ifTrue: [aStream nextPutAll: '  // ', comment]
- 		ifFalse: ["nil argument, ignore it"].
- 	aStream cr.
- 	msgNode isExpression
- 		ifTrue:
- 			[aStream tab: level + 1; nextPut: $(.
- 			msgNode args fourth asExpression
- 				emitJSCodeOn: aStream level: level + 1 generator: self.
- 			aStream nextPut: $); cr]
- 		ifFalse:
- 			[msgNode args fourth
- 				emitJSCodeOn: aStream level: level generator: self].
- 	aStream nextPutAll: '# endif  // ', msgNode args first value; cr; tab: level!

Item was changed:
  ----- Method: JSCodeGenerator>>generateInlineCppIfDefElse:on:indent: (in category 'JS translation') -----
  generateInlineCppIfDefElse: msgNode on: aStream indent: level
  	"Generate the C code for this message onto the given stream."
  
+ 	| alternateBlock alternateBlockIsNil |
+ 	aStream nextPutAll: '// skipping ifdef ', msgNode args first value; cr.
+ 
- 	| comment alternateBlock alternateBlockIsNil |
- self halt.
- 	aStream cr; nextPutAll: '# ifdef ', msgNode args first value.
- 	comment := msgNode args third value.
- 	(comment isKindOf: String)
- 		ifTrue: [aStream nextPutAll: '  // ', comment]
- 		ifFalse: ["nil argument, ignore it"].
- 	aStream cr.
- 	msgNode isExpression
- 		ifTrue:
- 			[aStream tab: level + 1; nextPut: $(.
- 			msgNode args fourth asExpression
- 				emitJSCodeOn: aStream level: level + 1 generator: self.
- 			aStream nextPut: $); cr]
- 		ifFalse:
- 			[msgNode args fourth
- 				emitJSCodeOn: aStream level: level generator: self].
  	alternateBlock := msgNode args fifth.
  	alternateBlockIsNil := true. "check for nil #else clause"
  	alternateBlock nodesDo: [:n |
  		(n ~= alternateBlock and: [n name ~= 'nil'])
  			ifTrue: [alternateBlockIsNil := false ]].
  	(alternateBlockIsNil) ifFalse:
+ 		[msgNode isExpression
- 		[aStream nextPutAll: '# else'; cr.
- 		msgNode isExpression
  			ifTrue:
  				[aStream tab: level + 1; nextPut: $(.
  				alternateBlock asExpression
  					emitJSCodeOn: aStream level: level + 1 generator: self.
  				aStream nextPut: $); cr]
  			ifFalse:
  				[alternateBlock
  					emitJSCodeOn: aStream level: level generator: self]].
+ 
- 	aStream nextPutAll: '# endif  // ', msgNode args first value; cr; tab: level
  !

Item was changed:
  ----- Method: JSCodeGenerator>>generateIntAtPointer:on:indent: (in category 'JS hacks') -----
  generateIntAtPointer: msgNode on: aStream indent: level
  	msgNode args first asString = 'self cCoerce: argPtr + i to: ''char*'''
  		ifTrue: [^aStream nextPutAll: 'argPtr[i]'].
  	self halt
- 	
- 
  	!

Item was changed:
  ----- Method: JSCodeGenerator>>generateIsNil:on:indent: (in category 'JS translation') -----
  generateIsNil: msgNode on: aStream indent: level
  	"Generate the JS code for this message onto the given stream."
  
+ 	aStream nextPutAll: '!!'.
  	self emitJSExpression: msgNode receiver on: aStream.
+ !
- 	aStream nextPutAll: ' === '.
- 	aStream nextPutAll: (self cLiteralFor: nil).!

Item was added:
+ ----- Method: JSCodeGenerator>>generateIsWordsOrBytes:on:indent: (in category 'JS hacks') -----
+ generateIsWordsOrBytes: msgNode on: aStream indent: level
+ 	msgNode args first emitJSCodeOn: aStream level: level generator: self.
+ 	aStream nextPutAll: '.isWordsOrBytes()'.
+ !

Item was changed:
  ----- Method: JSCodeGenerator>>generateJSCodeForCcode:on:indent: (in category 'JS translation') -----
  generateJSCodeForCcode: cCode on: aStream indent: level
  	cCode = '' ifTrue: [^self].
  	aStream nextPutAll: (cCodeTranslationDict at: cCode ifAbsent: [
+ 		('opTable[*] = (void *)*' match: cCode)
+ 			ifTrue: [cCode copyReplaceAll: '(void *)' with: ''] ifFalse: [
+ 		('fn(*Handle, &*Pitch, *)' match: cCode)
+ 			ifTrue: [(cCode copyReplaceAll: '&' with: 'function(p){') copyReplaceAll: 'Pitch' with: 'Pitch = p}'] ifFalse: [
+ 		(' ((*)querySurfaceFn)*(handle, &destWidth, &destHeight, &destDepth, &destMSB)' match: cCode)
+ 			ifTrue: [ 'querySurfaceFn(handle, function(w, h, d, m){destWidth = w; destHeight = h; destDepth = d; destMSB = m; })'] ifFalse: [
+ 		(' ((*)querySurfaceFn)*(handle, &sourceWidth, &sourceHeight, &sourceDepth, &sourceMSB)' match: cCode)
+ 			ifTrue: [ 'querySurfaceFn(handle, function(w, h, d, m){sourceWidth = w; sourceHeight = h; sourceDepth = d; sourceMSB = m; })'] ifFalse: [
+ 		(#('fn(destHandle, affectedL, affectedT, affectedR-affectedL, affectedB-affectedT)',
+ 			'fn(sourceHandle, 0, 0, 0, 0)') includes: cCode)
+ 			ifTrue: [cCode] ifFalse: [
  		"See initializeCTranslationDictionary"
+ 		self error: 'C: ' , cCode]]]]]])
- 		self error: 'C: ' , cCode]).
  !

Item was added:
+ ----- Method: JSCodeGenerator>>generateLong32At:on:indent: (in category 'JS hacks') -----
+ generateLong32At: msgNode on: aStream indent: level
+ 	| expr index |
+ 	expr := msgNode args first.
+ 	(expr isSend and: [expr selector = #+]) ifFalse: [self halt].
+ 	expr receiver emitJSCodeOn: aStream level: level generator: self.
+ 	index := expr args first.
+ 	aStream nextPut: $[.
+ 	index isTimesFour
+ 		ifTrue: [index receiver emitJSCodeOn: aStream level: level generator: self]
+ 		ifFalse: [
+ 			index emitJSCodeAsExpressionOn: aStream level: level generator: self.
+ 			aStream nextPutAll: ' >>> 2'].
+ 	aStream nextPut: $].
+ !

Item was changed:
  ----- Method: JSCodeGenerator>>generateNot:on:indent: (in category 'JS translation') -----
  generateNot: msgNode on: aStream indent: level
  	"Generate the JS code for this message onto the given stream."
+ 	| expr |
+ 	expr := msgNode receiver.
+ 	"generate (a !!= b) instead of !!(a == b)"
+ 	expr isEqualityTest ifTrue: [
+ 		^(msgNode selector includes: $~)
+ 			ifTrue: [self generateEqual: expr on: aStream indent: level]
+ 			ifFalse: [self generateNotEqual: expr on: aStream indent: level]].
+ 	"eliminate not not"
+ 	(expr isSend and: [expr selector = #not]) ifTrue: [
+ 		^self emitJSExpression: expr receiver on: aStream].
- 
  	aStream nextPutAll: '!!'.
+ 	self emitJSExpression: expr on: aStream.!
- 	self emitJSExpression: msgNode receiver on: aStream.!

Item was changed:
  ----- Method: JSCodeGenerator>>generateNotEqual:on:indent: (in category 'JS translation') -----
  generateNotEqual: msgNode on: aStream indent: level
  	"Generate the JS code for this message onto the given stream."
  	| argNode test |
  	argNode :=  msgNode args first.
+ 	"quick test for nil, true, false"
  	argNode isInterpreterProxyConstant ifTrue: [
  		test := #(isNil isTrue isFalse) at: (#(nilObject trueObject falseObject) indexOf: argNode selector).
  		aStream nextPut: $!!.
  		self emitJSExpression: msgNode receiver on: aStream.
  		^aStream nextPut: $.; nextPutAll: test].
+ 	"cannot compare pointers to 0"
+ 	(argNode isConstantNull or: [argNode isConstantZero and: [self isPointer: msgNode receiver]]) ifTrue: [
+ 		aStream nextPutAll: '!!!!'.
+ 		^self emitJSExpression: msgNode receiver on: aStream].
  	self emitJSExpression: msgNode receiver on: aStream.
  	aStream nextPutAll: ' !!== '.
  	self emitJSExpression: msgNode args first on: aStream.!

Item was changed:
  ----- Method: JSCodeGenerator>>generateNotNil:on:indent: (in category 'JS translation') -----
  generateNotNil: msgNode on: aStream indent: level
  	"Generate the JS code for this message onto the given stream."
  
+ 	aStream nextPutAll: '!!!!'.
  	self emitJSExpression: msgNode receiver on: aStream.
+ !
- 	aStream nextPutAll: ' !!== '.
- 	aStream nextPutAll: (self cLiteralFor: nil).!

Item was added:
+ ----- Method: JSCodeGenerator>>generateOopForPointer:on:indent: (in category 'JS hacks') -----
+ generateOopForPointer: msgNode on: aStream indent: level
+ 	| arg |
+ 	arg := msgNode args first asString.
+ 	arg = 'interpreterProxy firstIndexableField: destBits'
+ 		ifTrue: [^aStream nextPutAll: 'destBits.wordsOrBytes()'].
+ 	arg = 'interpreterProxy firstIndexableField: sourceBits'
+ 		ifTrue: [^aStream nextPutAll: 'sourceBits.wordsOrBytes()'].
+ 	arg =  'interpreterProxy firstIndexableField: halftoneBits'
+ 		ifTrue: [^aStream nextPutAll: 'halftoneBits.wordsOrBytes()'].
+ 	arg =  'interpreterProxy firstIndexableField: sourceMapOop'
+ 		ifTrue: [^aStream nextPutAll: 'sourceMapOop.wordsOrBytes()'].
+ 	self halt
+ !

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 emitJSExpression: msgNode receiver on: aStream.
+ 		aStream nextPutAll: ' + '].
- 	self checkNonPointer: msgNode receiver op: '+'.
- 	self checkNonPointer: msgNode args first op: '+'.
- 	self emitJSExpression: msgNode receiver on: aStream.
- 	aStream nextPutAll: ' + '.
  	self emitJSExpression: msgNode args first on: aStream.!

Item was changed:
  ----- Method: JSCodeGenerator>>generateSignedBitShift:on:indent: (in category 'JS translation') -----
  generateSignedBitShift: msgNode on: aStream indent: level
  	"Generate the JS code for signedBitShift: 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: [
+ 			arg value < -31 ifTrue: [self error: 'cannot shift by more than 31']. 
  			aStream nextPutAll: ' >> ', arg value negated printString.
  		] ifFalse: [
+ 			arg value > 31 ifTrue: [self error: 'cannot shift by more than 31']. 
  			aStream nextPutAll: ' << ', arg value printString.
  		].
  	] ifFalse: [
  		self error: 'non-constant signed shift not implemented yet'
  	].!

Item was changed:
  ----- Method: JSCodeGenerator>>generateSlotSizeOf:on:indent: (in category 'JS hacks') -----
  generateSlotSizeOf: msgNode on: aStream indent: level
+ 	aStream nextPutAll: 'SIZEOF('.
- 	aStream nextPutAll: 'SLOTSIZEOF('.
  	msgNode args first emitJSCodeOn: aStream level: level generator: self.
  	aStream nextPut: $).
  !

Item was added:
+ ----- Method: JSCodeGenerator>>generateSrcLongAt:on:indent: (in category 'JS hacks') -----
+ generateSrcLongAt: msgNode on: aStream indent: level
+ 	aStream nextPutAll: 'sourceBits['.
+ 	msgNode args first emitJSCodeAsExpressionOn: aStream level: level generator: self.
+ 	aStream nextPutAll: ' >>> 2]'.
+ 	
+ !

Item was added:
+ ----- Method: JSCodeGenerator>>ignoredMethods (in category 'public') -----
+ ignoredMethods
+ 	^#(dstLongAt: dstLongAt:put: srcLongAt:)!

Item was changed:
  ----- 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			#generateAbs: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:
+ 	#isWordsOrBytes:					#generateIsWordsOrBytes: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'
  		'sqrt(result)'												'Math.sqrt(result)'
  		'sqrt(len)'													'Math.sqrt(len)'
  	).
  	1 to: pairs size by: 2 do: [:i |
  		cCodeTranslationDict at: (pairs at: i) put: (pairs at: i + 1)].
  !

Item was removed:
- ----- Method: JSCodeGenerator>>isCLiteral: (in category 'JS code generator') -----
- isCLiteral: anObject
- 	(anObject isKindOf: Integer) ifTrue: [^true].
- 	(anObject isKindOf: String) ifTrue: [^true].
- 	(anObject isKindOf: Float) ifTrue: [^true].
- 	anObject == nil ifTrue: [^true].
- 	anObject == true ifTrue: [^true].
- 	anObject == false ifTrue: [^true].
- 	^false!

Item was added:
+ ----- Method: JSCodeGenerator>>isJSLiteral: (in category 'JS code generator') -----
+ isJSLiteral: anObject
+ 	(anObject isKindOf: Integer) ifTrue: [^true].
+ 	(anObject isKindOf: String) ifTrue: [^true].
+ 	(anObject isKindOf: Float) ifTrue: [^true].
+ 	anObject == nil ifTrue: [^true].
+ 	anObject == true ifTrue: [^true].
+ 	anObject == false ifTrue: [^true].
+ 	^false!

Item was added:
+ ----- Method: JSCodeGenerator>>jsFunctionNameFor: (in category 'JS code generator') -----
+ jsFunctionNameFor: aSelector
+ 	"Create a JS function name from the given selector by omitting colons
+ 	and prefixing with the plugin name if the method is exported."
+ 	^aSelector copyWithout: $:!

Item was added:
+ ----- Method: JSCodeGenerator>>jsLiteralFor: (in category 'JS code generator') -----
+ jsLiteralFor: anObject
+ 	"Return a string representing theJS literal value for the given object."
+ 	(anObject isKindOf: Integer) ifTrue: [^ anObject printString].
+ 	(anObject isKindOf: String) ifTrue: [^ '"', anObject, '"' ].
+ 	(anObject isKindOf: Float) ifTrue: [^ anObject printString ].
+ 	anObject == nil ifTrue: [^ 'null' ].
+ 	anObject == true ifTrue: [^ 'true' ].
+ 	anObject == false ifTrue: [^ 'false' ].
+ 	self error:
+ 		'Warning: A Smalltalk literal could not be translated into a JS constant: ', anObject printString.
+ 	^'"XXX UNTRANSLATABLE CONSTANT XXX"'!

Item was changed:
  ----- Method: JSCodeGenerator>>prepareMethodsInlined:doAssertions: (in category 'JS code generator') -----
  prepareMethodsInlined: inlineFlag doAssertions: assertionFlag
  	"Prepare to emit JS code for all methods in the code base. All inlined method calls should be expanded. Answer a list of methods to be emitted as C code."
  
  	| verbose methodList |
  	"method preparation"
  	verbose := false.
+ 	self pruneMethods: self ignoredMethods.
  	self prepareMethods.
  	verbose ifTrue: [
  		self printUnboundCallWarnings.
  		self printUnboundVariableReferenceWarnings.
  		Transcript cr.
  	].
  	self checkAbstractMethods.
  	assertionFlag ifFalse: [ self removeAssertions ].
  	self doInlining: inlineFlag.
  
  	"code generation"
  
  	methodList := methods asSortedCollection: [ :m1 :m2 | m1 selector < m2 selector ].
  	"clean out no longer valid variable names and then handle any global
  		variable usage in each method"
  	methodList do: [:m | self checkForGlobalUsage: m removeUnusedTemps in: m].
  	self localizeGlobalVariables.
  	^ preparedMethodList := methodList
  !

Item was changed:
  ----- Method: JSMethod>>emitJSFunctionHeader:generator:newlineBeforeName: (in category 'JS code generation') -----
  emitJSFunctionHeader: aStream generator: aCodeGen newlineBeforeName: newlineBeforeName "<Boolean>"
  	"Emit a JS function header for this method onto the given stream."
  
  	aStream nextPutAll: 'function'.
  	newlineBeforeName ifTrue: [aStream cr] ifFalse: [aStream space].
  	(returnType last = $)
+ 	and: [returnType includesSubString: (aCodeGen jsFunctionNameFor: self selectorForCodeGeneration)]) ifTrue:
- 	and: [returnType includesSubString: (aCodeGen cFunctionNameFor: self selectorForCodeGeneration)]) ifTrue:
  		["Hack fix for e.g. <returnTypeC: 'void (*setInterruptCheckChain(void (*aFunction)(void)))()'>"
  		 ^self].
  	aStream
+ 		nextPutAll: (aCodeGen jsFunctionNameFor: self selectorForCodeGeneration);
- 		nextPutAll: (aCodeGen cFunctionNameFor: self selectorForCodeGeneration);
  		nextPut: $(.
  	args
  		do: [:arg | aStream nextPutAll: (aCodeGen returnPrefixFromVariable: arg)]
  		separatedBy: [ aStream nextPutAll: ', ' ].
  	aStream nextPut: $)!

Item was changed:
  ----- Method: JSMethod>>emitJSHeaderOn:generator: (in category 'JS code generation') -----
  emitJSHeaderOn: aStream generator: aCodeGen
  	"Emit a C function header for this method onto the given stream."
  
  	aStream cr. 
  	self emitJSFunctionHeader: aStream generator: aCodeGen.
  	aStream nextPutAll: ' {'; cr.
  	self emitGlobalStructReferenceOn: aStream.
+ 	locals do: [ :var | | varDecl |
+ 		aStream nextPutAll: '	var ', (aCodeGen returnPrefixFromVariable: var).
+ 		varDecl := declarations at: var asString ifAbsent: [''].
+ 		(varDecl includes: $=)
+ 			ifTrue: [ | const |
+ 				const := ((varDecl copyAfter: $=) replaceAll: ${ with: $[) replaceAll: $} with: $].
+ 				aStream nextPutAll: ' =', const]
+ 			ifFalse: [(varDecl includes: $[)
+ 					ifTrue: [ | size |
+ 						size := (varDecl copyAfter: $[) copyUpTo: $].
+ 						size ifEmpty: [self halt].
+ 						aStream nextPutAll: ' = new Array(', size, ')']].
+ 		aStream nextPutAll: ';'; cr
- 	locals do: [ :var |
- 		aStream nextPutAll: '	var ', (aCodeGen returnPrefixFromVariable: var), ';'; cr.
  	].
  	locals isEmpty ifFalse: [ aStream cr ].!

Item was changed:
  ----- Method: JSMethod>>emitProxyFunctionPrototype:generator: (in category 'JS code generation') -----
  emitProxyFunctionPrototype: aStream generator: aCodeGen
  	"Emit an indirect C function header for this method onto the given stream."
  
  	| arg |
  	aStream nextPutAll: returnType; space.
+ 	aStream nextPutAll: '(*', (aCodeGen jsFunctionNameFor: self selectorForCodeGeneration), ')('.
- 	aStream nextPutAll: '(*', (aCodeGen cFunctionNameFor: self selectorForCodeGeneration), ')('.
  	args isEmpty ifTrue: [ aStream nextPutAll: 'void' ].
  	1 to: args size do: [ :i |
  		arg := args at: i.
  		(declarations includesKey: arg) ifTrue: [
  			aStream nextPutAll: (declarations at: arg).
  		] ifFalse: [
  			aStream nextPutAll: 'sqInt ', (args at: i).
  		].
  		i < args size ifTrue: [ aStream nextPutAll: ', ' ].
  	].
  	aStream nextPutAll: ')'.!

Item was removed:
- ----- Method: JSPluginCodeGenerator>>emitJSHeaderForPrimitivesOn: (in category 'JS code generator') -----
- emitJSHeaderForPrimitivesOn: aStream
- 	"Write a JS file header for compiled primitives onto the given stream."
- 
- 	self emitJSHeaderOn: aStream.
- !

Item was changed:
  ----- Method: JSPluginCodeGenerator>>emitJSHeaderOn: (in category 'JS code generator') -----
  emitJSHeaderOn: aStream
  	"Write a JS file header onto the given stream."
  
  	aStream nextPutAll: '/* '.
+ 	aStream nextPutAll: (VMMaker headerNotice copyReplaceAll: ' C ' with: ' JS ').
- 	aStream nextPutAll: VMMaker headerNotice.
  	aStream nextPutAll: ' */';cr.
  	aStream nextPutAll: (self fileHeaderVersionStampForSourceClass: vmClass).
  	aStream nextPutAll: '
  module("users.bert.SqueakJS.plugins.', pluginName, '").requires("users.bert.SqueakJS.vm").toRun(function() {
  
  var VM_PROXY_MAJOR = ', InterpreterPrimitives vmProxyMajorVersion, ';
  var VM_PROXY_MINOR = ', InterpreterPrimitives vmProxyMinorVersion, ';
  
  /*** Functions ***/
  function CLASSOF(obj) { return typeof obj === "number" ? interpreterProxy.classSmallInteger() : obj.sqClass }
+ function SIZEOF(obj) { return obj.pointers ? obj.pointers.length : obj.words ? obj.words.length : obj.bytes ? obj.bytes.length : 0 }
+ function BYTESIZEOF(obj) { return obj.bytes ? obj.bytes.length : obj.words ? obj.words.length * 4 : 0 }
- function SLOTSIZEOF(obj) { return obj.bytes ? obj.bytes.length : obj.words ? obj.words.length : obj.pointers ? obj.pointers.length : 0 }
- function BYTESIZEOF(obj) { return obj.bytes ? obj.bytes.length : 0 }
  function DIV(a, b) { return Math.floor(a / b) | 0; }   // integer division
  function MOD(a, b) { return a - DIV(a, b) * b | 0; }   // signed modulus
+ function SHL(a, b) { return b > 31 ? 0 : a << b; }     // fix JS shift
+ function SHR(a, b) { return b > 31 ? 0 : a >>> b; }    // fix JS shift
+ function SHIFT(a, b) { return b < 0 ? (b < -31 ? 0 : a >>> (0-b) ) : (b > 31 ? 0 : b << a); }
- function SHL(a, b) { return b > 31 ? 0 : a << b ; }    // fix JS shift
- function SHR(a, b) { return b > 31 ? 0 : a >>> b ; }   // fix JS shift
  
  '.!

Item was changed:
  ----- Method: JSPluginCodeGenerator>>generateCodeStringForPrimitives (in category 'public') -----
  generateCodeStringForPrimitives
  "TPR - moved down from JSCodeGenerator"
  	| s methodList |
  	s := ReadWriteStream on: (String new: 1000).
  	methodList := methods asSortedCollection: [:m1 :m2 | m1 selector < m2 selector].
+ 	self emitJSHeaderOn: s.
- 	self emitJSHeaderForPrimitivesOn: s.
  	self emitJSConstantsOn: s.
  	self emitJSVariablesOn: s.
  	methodList do: [:m | m emitJSCodeOn: s generator: self].
  	self emitExportsOn: s.
  	^ s contents
  !

Item was changed:
  ----- Method: JSSmartSyntaxPluginCodeGenerator>>generateAsPositiveIntegerObj:on:indent: (in category 'translating builtins') -----
  generateAsPositiveIntegerObj: aNode on: aStream indent: anInteger
  
+ 	aStream nextPutAll: 'interpreterProxy.positive32BitIntegerFor('.
- 	aStream nextPutAll: 'interpreterProxy->positive32BitIntegerFor('.
  	self emitJSExpression: aNode receiver on: aStream.
  	aStream nextPutAll: ')'.!

Item was removed:
- ----- Method: JSSmartSyntaxPluginCodeGenerator>>generateIsWordsOrBytes:on:indent: (in category 'translating builtins') -----
- generateIsWordsOrBytes: aNode on: aStream indent: anInteger
- 
- 	aStream nextPutAll: 'interpreterProxy->isWordsOrBytes('.
- 	self emitJSExpression: aNode receiver on: aStream.
- 	aStream nextPutAll: ')'.!

Item was changed:
  ----- Method: TConstantNode>>emitJSCodeOn:level:generator: (in category '*vmmakerjs') -----
  emitJSCodeOn: aStream level: level generator: aCodeGen
  	"Emit a C literal."
  
+ 	aStream nextPutAll: (aCodeGen jsLiteralFor: value).!
- 	aStream nextPutAll: (aCodeGen cLiteralFor: value).!

Item was added:
+ ----- Method: TConstantNode>>isConstantZero (in category '*vmmakerjs') -----
+ isConstantZero
+ 	^ value = 0!

Item was added:
+ ----- Method: TParseNode>>isBitBltPtr (in category '*vmmakerjs') -----
+ isBitBltPtr
+ 	^false!

Item was added:
+ ----- Method: TParseNode>>isConstantNull (in category '*vmmakerjs') -----
+ isConstantNull
+ 	^false!

Item was added:
+ ----- Method: TParseNode>>isConstantZero (in category '*vmmakerjs') -----
+ isConstantZero
+ 	^false!

Item was added:
+ ----- Method: TParseNode>>isEqualityTest (in category '*vmmakerjs') -----
+ isEqualityTest
+ 	^false!

Item was added:
+ ----- Method: TParseNode>>isTimesFour (in category '*vmmakerjs') -----
+ isTimesFour
+ 	^false!

Item was changed:
  ----- Method: TSendNode>>emitJSCodeAsFunctionCallOn:level:generator: (in category '*vmmakerjs') -----
  emitJSCodeAsFunctionCallOn: aStream level: level generator: aCodeGen
  
+ 	"Translate this message send into a JS function call"
- 	"Translate this message send into a C function call"
  	"Special case for pluggable modules. Replace messages to interpreterProxy
  	 by interpreterProxy->message(..) if the message is not builtin"
  	(aCodeGen isGeneratingPluginCode
  	 and: [receiver isVariable
  	 and: ['interpreterProxy' = receiver name
  	 and: [self isBuiltinOperator not]]]) ifTrue:
  		[aStream nextPutAll:'interpreterProxy.'].
+ 	"Translate this message send into a JS function call."
+ 	aStream nextPutAll: (aCodeGen jsFunctionNameFor: selector); nextPut: $(.
- 	"Translate this message send into a C function call."
- 	aStream nextPutAll: (aCodeGen cFunctionNameFor: selector); nextPut: $(.
  	"Only include the receiver as the first argument in certain cases.
  	 The receiver is always included if it is an expression.
  	 If it is a variable:
  		 If the vmClass says it is an implicit variable, don't include it.
  		 If the variable is 'self' and the method being called is not in
  		 the method set (i.e. it is some external code), don't include it."
  	(self shouldIncludeReceiverAsFirstArgument: aCodeGen) ifTrue:
  		[receiver emitJSCodeOn: aStream level: level generator: aCodeGen.
  		arguments isEmpty ifFalse:
  			[aStream nextPutAll: ', ']].
  	arguments do:
  		[ :arg| arg emitJSCodeAsArgumentOn: aStream level: level generator: aCodeGen]
  		separatedBy: [aStream nextPut: $,; space].
  	aStream nextPut: $)!

Item was changed:
  ----- Method: TSendNode>>emitJSCodeAsPointerDereferenceOn:level:generator: (in category '*vmmakerjs') -----
  emitJSCodeAsPointerDereferenceOn: aStream level: level generator: aCodeGen
  	"If appropriate, translate this message send as a pointer dereference"
  
  	(self isStructSend: aCodeGen) ifFalse:
  		[^false].
  
  	aStream nextPut: $(.
  	receiver  emitJSCodeAsExpressionOn: aStream level: 0 generator: aCodeGen.
  	aStream nextPut: $-; nextPut: $>.
+ 	aStream nextPutAll: (aCodeGen jsFunctionNameFor: selector).
- 	aStream nextPutAll: (aCodeGen cFunctionNameFor: selector).
  	arguments isEmpty ifFalse:
  		[self assert: arguments size = 1.
  		 aStream nextPutAll: ' = '.
  		 arguments first emitJSCodeAsExpressionOn: aStream level: level generator: aCodeGen].
  	aStream nextPut: $).
  	^true!

Item was added:
+ ----- Method: TSendNode>>isEqualityTest (in category '*vmmakerjs') -----
+ isEqualityTest
+ 	^#(= == ~= ~~) includes: self selector!

Item was added:
+ ----- Method: TSendNode>>isTimesFour (in category '*vmmakerjs') -----
+ isTimesFour
+ 	^self args first isConstant and:
+ 		[(self selector = #* and: [self args first value = 4])
+ 		or: [self selector = #<< and: [self args first value = 2]]]!

Item was changed:
  ----- Method: TVariableNode>>emitJSCodeOn:level:generator: (in category '*vmmakerjs') -----
  emitJSCodeOn: aStream level: level generator: aCodeGen
  
  	name = 'nil'
+ 		ifTrue: [ aStream nextPutAll: (aCodeGen jsLiteralFor: nil) ]
- 		ifTrue: [ aStream nextPutAll: (aCodeGen cLiteralFor: nil) ]
  		ifFalse: [ aStream nextPutAll: (aCodeGen returnPrefixFromVariable: name) ].!

Item was added:
+ ----- Method: TVariableNode>>isBitBltPtr (in category '*vmmakerjs') -----
+ isBitBltPtr
+ 	^#('sourceBits' 'destBits') includes: self name!

Item was added:
+ ----- Method: TVariableNode>>isConstantNull (in category '*vmmakerjs') -----
+ isConstantNull
+ 	^ name = 'nil'!



More information about the Vm-dev mailing list