[Vm-dev] VM Maker: VMMakerJS-bf.3.mcz
commits at source.squeak.org
commits at source.squeak.org
Fri Oct 10 13:45:29 UTC 2014
Bert Freudenberg uploaded a new version of VMMakerJS to project VM Maker:
http://source.squeak.org/VMMaker/VMMakerJS-bf.3.mcz
==================== Summary ====================
Name: VMMakerJS-bf.3
Author: bf
Time: 5 October 2014, 8:07:33.092 pm
UUID: 56bbf351-57a9-49f7-a87f-29db307aba10
Ancestors: VMMakerJS-bf.2
Init vars, optimize inc, handle more types.
Can generate ZipPlugin now.
=============== Diff against VMMakerJS-bf.2 ===============
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: '#define '.
aStream nextPutAll: node name.
+ aStream nextPutAll: ' = '.
- aStream space.
aStream nextPutAll: (self cLiteralFor: node value).
+ aStream nextPut: $;.
aStream cr
].
].
aStream cr.!
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: [aStream nextPutAll: ' =', (varDecl copyAfter: $=)]
+ ifFalse: [(varDecl includes: $*)
+ ifTrue: [aStream nextPutAll: ' = null']
+ ifFalse: [aStream nextPutAll: ' = 0']].
- ifTrue: [aStream nextPutAll: ' =', (varDecl copyAfter: $=)].
aStream nextPutAll: ';'; cr].
aStream cr.
!
Item was changed:
----- Method: JSCodeGenerator>>emitVmmVersionOn: (in category 'JS code generator') -----
emitVmmVersionOn: aStream
"Emit a version string macro suitable for identifying source code version
of this interpreter. This is expected to be used in conjunction with a similar
identifier for platform source code version, such the the VM can identify
the source code version for its platform source and matching VMMaker source."
+ aStream nextPutAll: 'var VMMAKER_VERSION = "';
- aStream nextPutAll: '#define VMMAKER_VERSION "';
nextPutAll: VMMaker versionString;
nextPut: $";
cr
!
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 |
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!
- self emitJSExpression: msgNode args last on: aStream!
Item was added:
+ ----- Method: JSCodeGenerator>>generateByteSizeOf:on:indent: (in category 'JS hacks') -----
+ generateByteSizeOf: msgNode on: aStream indent: level
+ aStream nextPutAll: 'BYTESIZEOF('.
+ msgNode args first emitJSCodeOn: aStream level: level generator: self.
+ aStream nextPutAll: ')'.
+ !
Item was removed:
- ----- Method: JSCodeGenerator>>generateByteSizeOfBytes:on:indent: (in category 'JS hacks') -----
- generateByteSizeOfBytes: msgNode on: aStream indent: level
- msgNode args first emitJSCodeOn: aStream level: level generator: self.
- aStream nextPutAll: '.bytes ? '.
- msgNode args first emitJSCodeOn: aStream level: level generator: self.
- aStream nextPutAll: '.bytes.length : 0'.
- !
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.
+ argNode isInterpreterProxyConstant ifTrue: [
+ test := #(isNil isTrue isFalse) at: (#(nilObject trueObject falseObject) indexOf: argNode selector).
+ self emitJSExpression: msgNode receiver on: aStream.
+ ^aStream nextPut: $.; nextPutAll: test].
-
self emitJSExpression: msgNode receiver on: aStream.
aStream nextPutAll: ' === '.
+ self emitJSExpression: argNode on: aStream.!
- self emitJSExpression: msgNode args first on: aStream.!
Item was changed:
----- Method: JSCodeGenerator>>generateFetchClassOf:on:indent: (in category 'JS hacks') -----
generateFetchClassOf: msgNode on: aStream indent: level
+ aStream nextPutAll: 'CLASSOF('.
- aStream nextPut: $(.
msgNode args first emitJSCodeOn: aStream level: level generator: self.
- aStream nextPutAll: '.sqClass ? '.
- msgNode args first emitJSCodeOn: aStream level: level generator: self.
- aStream nextPutAll: '.sqClass : interpreterProxy.classSmallInteger()'.
aStream nextPut: $).
!
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: [
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: [self halt: 'need to handle ', cType]]]].
- accessor := (cType beginsWith: 'unsigned char *') ifTrue: ['.bytes']
- ifFalse: [(cType beginsWith: 'char *') ifTrue: ['.bytes']
- 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>>generateInstanceSizeOf:on:indent: (in category 'JS hacks') -----
+ generateInstanceSizeOf: msgNode on: aStream indent: level
+ msgNode args first emitJSCodeOn: aStream level: level generator: self.
+ aStream nextPutAll: '.classInstSize()'.
+ !
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.
+ 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].
-
self emitJSExpression: msgNode receiver on: aStream.
aStream nextPutAll: ' !!== '.
self emitJSExpression: msgNode args first on: aStream.!
Item was changed:
----- Method: JSCodeGenerator>>generateSlotSizeOf:on:indent: (in category 'JS hacks') -----
generateSlotSizeOf: msgNode on: aStream indent: level
+ aStream nextPutAll: 'SLOTSIZEOF('.
- aStream nextPut: $(.
msgNode args first emitJSCodeOn: aStream level: level generator: self.
- aStream nextPutAll: '.bytes ? '.
- msgNode args first emitJSCodeOn: aStream level: level generator: self.
- aStream nextPutAll: '.bytes.length : '.
- msgNode args first emitJSCodeOn: aStream level: level generator: self.
- aStream nextPutAll: '.words ? '.
- msgNode args first emitJSCodeOn: aStream level: level generator: self.
- aStream nextPutAll: '.words.length : interpreterProxy.'.
- msgNode emitJSCodeAsFunctionCallOn: aStream level: level generator: self.
aStream nextPut: $).
!
Item was added:
+ ----- Method: JSCodeGenerator>>generateSuperclassOf:on:indent: (in category 'JS hacks') -----
+ generateSuperclassOf: msgNode on: aStream indent: level
+ msgNode args first emitJSCodeOn: aStream level: level generator: self.
+ aStream nextPutAll: '.superclass()'.
+ !
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:
#* #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:
+ #byteSizeOfBytes: #generateByteSizeOf:on:indent:
+ #byteSizeOf: #generateByteSizeOf:on:indent:
- #byteSizeOfBytes: #generateByteSizeOfBytes:on:indent:
#fetchClassOf: #generateFetchClassOf:on:indent:
+ #superclassOf: #generateSuperclassOf:on:indent:
+ #instanceSizeOf: #generateInstanceSizeOf:on:indent:
#is:KindOf: #generateIsKindOf:on:indent:
#cDigitCopyFrom:to:len: #generateCDigitCopy:on:indent:
#sizeOfSTArrayFromCPrimitive: #generateSizeOfSTArrayFromCPrimitive:on:indent:
#asciiValue #generateIdentityUnary:on:indent:
#primitiveFail #generateInterpreterProxyCall: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'
).
1 to: pairs size by: 2 do: [:i |
cCodeTranslationDict at: (pairs at: i) put: (pairs at: i + 1)].
!
Item was changed:
----- Method: JSCodeGenerator>>printInt:on: (in category 'private') -----
printInt: int on: aStream
aStream print: int.
+ !
- (int between: -2147483648 and: 2147483647)
- ifFalse: [(int between: 2147483648 and: 4294967295)
- ifTrue: [aStream nextPut: $U]
- ifFalse: [aStream nextPut: $L]]!
Item was changed:
----- Method: JSCodeGenerator>>var:type:array: (in category 'public') -----
var: varName type: type array: array
+ "use this in preference to #var:declareC: when possible. This produces a JS statment of the form
+ var fooArray = [1,2,3]
- "use this in preference to #var:declareC: when possible. This produces a C statment of the form
- int * fooArray[]={1,2,3}
See also #var:type: for simple var decls"
self
var: varName
declareC: (String streamContents: [:s |
s nextPutAll: type.
s space.
s nextPutAll: varName.
+ s nextPutAll: ' = ['.
- s nextPutAll: '[] = {'.
self printArray: array on: s.
+ s nextPut: $]])!
- s nextPut: $}])!
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.
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 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
'.!
Item was removed:
- ----- Method: JSPluginCodeGenerator>>storeVirtualMachineProxyHeader:on: (in category 'private') -----
- storeVirtualMachineProxyHeader: categoryList on: fileName
- "Store the interpreter definitions on the given file"
- | stream |
- stream := FileStream newFileNamed: fileName.
- stream nextPutAll:
- '#ifndef _SqueakVM_H
- #define _SqueakVM_H
-
- /* Increment the following number if you change the order of
- functions listed or if you remove functions */
- #define VM_PROXY_MAJOR 1
-
- /* Increment the following number if you add functions at the end */
- #define VM_PROXY_MINOR 0
-
- typedef struct VirtualMachine {
- int (*minorVersion) (void);
- int (*majorVersion) (void);
- '.
-
- categoryList do:[:assoc|
- stream cr; crtab; nextPutAll:'/* InterpreterProxy methodsFor: ''',assoc key, ''' */'; cr; crtab.
- assoc value asSortedCollection do:[:sel|
- (methods at: sel) emitProxyFunctionPrototype: stream generator: self.
- stream nextPutAll: ';'; crtab]].
-
- stream nextPutAll:'
- } VirtualMachine;
-
- #endif /* _SqueakVM_H */
- '.
- stream close.!
Item was removed:
- ----- Method: JSPluginCodeGenerator>>storeVirtualMachineProxyImplementation:on: (in category 'private') -----
- storeVirtualMachineProxyImplementation: categoryList on: fileName
- "Store the interpreter definitions on the given file"
- | stream |
- stream := FileStream newFileNamed: fileName.
- stream nextPutAll:'
- #include <math.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- #include "sqVirtualMachine.h"'; cr;cr.
- stream nextPutAll:'/*** Function prototypes ***/'.
-
- categoryList do:[:assoc|
- stream cr; cr; nextPutAll:'/* InterpreterProxy methodsFor: ''',assoc key, ''' */'; cr.
- assoc value asSortedCollection do:[:sel|
- (methods at: sel) emitJSFunctionHeader: stream generator: self.
- stream nextPutAll: ';'; cr]].
-
- stream cr; nextPutAll:'struct VirtualMachine *VM = NULL;'; cr.
- stream cr; nextPutAll:
- 'static int majorVersion(void) {
- return VM_PROXY_MAJOR;
- }
-
- static int minorVersion(void) {
- return VM_PROXY_MINOR;
- }
-
- struct VirtualMachine* sqGetInterpreterProxy(void)
- {
- if(VM) return VM;
- VM = (struct VirtualMachine *) calloc(1, sizeof(VirtualMachine));
- /* Initialize Function pointers */
- VM->majorVersion = majorVersion;
- VM->minorVersion = minorVersion;
- '.
- categoryList do:[:assoc|
- stream cr; crtab; nextPutAll:'/* InterpreterProxy methodsFor: ''',assoc key, ''' */'; crtab.
- assoc value asSortedCollection do:[:sel|
- stream nextPutAll:'VM->';
- nextPutAll: (self cFunctionNameFor: sel);
- nextPutAll:' = ';
- nextPutAll: (self cFunctionNameFor: sel);
- nextPutAll:';';
- crtab]].
-
- stream cr; crtab; nextPutAll:'return VM;'; cr; nextPutAll:'}'; cr.
- stream close.!
Item was removed:
- ----- Method: JSSmartSyntaxPluginMethod>>emitJSHeaderOn:generator: (in category 'generating JS code') -----
- 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.
- locals do: [ :var |
- aStream nextPutAll: ' var ', (aCodeGen returnPrefixFromVariable: var), ';'; cr.
- ].
- locals isEmpty ifFalse: [ aStream cr ].!
Item was added:
+ ----- Method: TParseNode>>isInterpreterProxyConstant (in category '*vmmakerjs') -----
+ isInterpreterProxyConstant
+ ^false!
Item was added:
+ ----- Method: TSendNode>>isInterpreterProxyConstant (in category '*vmmakerjs') -----
+ isInterpreterProxyConstant
+ ^#(nilObject trueObject falseObject) includes: self selector!
More information about the Vm-dev
mailing list