Hi,
One thing I added over the last weeks: support to put links on primitives. 1) fail code. You can put links into the smalltalk code that is executed in case of primitive failure. For all primitive methods, we generate code immediately when setting the link, we do not wait till the method is called. (this is in there since a while). 2) links on the method node itself. What we do here is to wrap the original method. It is interesting how simple this was to do: 1) when generating code for a ReflectiveMethod, check if it is a primitive: compileAndInstallCompiledMethod "we install the old one as the compiler might need it” self installCompiledMethod. compiledMethod isRealPrimitive ifTrue: [ self generatePrimitiveWrapper ]. self recompileAST. self installCompiledMethod. 2) compile a wrapper by building an AST by hand: generatePrimitiveWrapper | wrappedMethod send wrapperMethod | ast compilationContext semanticAnalyzerClass: RFSemanticAnalyzer; astTranslatorClass: RFASTTranslator. ast doSemanticAnalysis. "force semantic analysis" wrappedMethod := ast generate: compiledMethod trailer. send := RBMessageNode receiver: (RBLiteralNode value: wrappedMethod) selector: #valueWithReceiver:arguments: arguments: {RBVariableNode named: #self . RBArrayNode statements: ast variableNodes }. wrapperMethod := RBMethodNode selector: ast selector arguments: ast variableNodes body: (RBReturnNode value: send) asSequenceNode. wrapperMethod methodClass: ast methodClass. wrapperMethod propertyAt: #wrappedPrimitive put: true. ast hasMetalink ifTrue: [wrapperMethod propertyAt: #links put: (ast propertyAt: #links)]. ast := wrapperMethod. This means we copy over the links to the new wrapper. the #wrappedPrimitive marker is there so that, when we destroy the twin when the last link is removed, we remember to unwrap. 3) the compiler plugin that takes the links into account ignores links on MethodNode if it’s a primitive. 4) when getting rid of the Twin (because we remove the last link), we detect if it was a primitive and unwrap: destroyTwin (ast hasProperty: #wrappedPrimitive) ifTrue: [ ast := compiledMethod parseTree]. self recompileAST. self installCompiledMethod. compiledMethod reflectiveMethod: nil. SystemAnnouncer uniqueInstance unsubscribe: self e.g. testBeforeMethodPrimitive | methodNode link | methodNode := (ReflectivityExamples >> #examplePrimitiveMethod) ast. link := MetaLink new metaObject: self; selector: #tagExec. self assert: (ReflectivityExamples>>#examplePrimitiveMethod) isRealPrimitive. methodNode link: link. self assert: methodNode hasMetalink. self assert: (ReflectivityExamples >> #examplePrimitiveMethod) class = CompiledMethod. self assert: tag isNil. self assert: ReflectivityExamples new examplePrimitiveMethod class = ByteString. self deny: (ReflectivityExamples>>#examplePrimitiveMethod) isRealPrimitive. self assert: tag = #yes. self assert: (ReflectivityExamples >> #examplePrimitiveMethod) class = CompiledMethod. link uninstall. self assert: (ReflectivityExamples>>#examplePrimitiveMethod) isRealPrimitive. ReflectivityExamples recompile: #examplePrimitiveMethod Marcus |
Free forum by Nabble | Edit this page |