Method.st
changeset 56 be0ed17e6f85
parent 49 f1c2d75f2eb6
child 68 59faa75185ba
equal deleted inserted replaced
55:4a82f332c3f8 56:be0ed17e6f85
    21 Method comment:'
    21 Method comment:'
    22 
    22 
    23 COPYRIGHT (c) 1989 by Claus Gittinger
    23 COPYRIGHT (c) 1989 by Claus Gittinger
    24              All Rights Reserved
    24              All Rights Reserved
    25 
    25 
    26 $Header: /cvs/stx/stx/libbasic/Method.st,v 1.10 1994-02-05 12:22:08 claus Exp $
    26 $Header: /cvs/stx/stx/libbasic/Method.st,v 1.11 1994-02-25 13:00:39 claus Exp $
    27 written spring 89 by claus
    27 written spring 89 by claus
    28 '!
    28 '!
    29 
    29 
    30 !Method class methodsFor:'documentation'!
    30 !Method class methodsFor:'documentation'!
    31 
    31 
   231 
   231 
   232 flags:newFlags
   232 flags:newFlags
   233     "set the flags (number of method variables, stacksize)
   233     "set the flags (number of method variables, stacksize)
   234      - for use by the compiler only"
   234      - for use by the compiler only"
   235 
   235 
   236     flags := newFlags
   236     "protect myself a bit - putting in an object would crash me ..."
       
   237     (newFlags isMemberOf:SmallInteger) ifTrue:[
       
   238         flags := newFlags
       
   239     ]
   237 !
   240 !
   238 
   241 
   239 dynamic:aBoolean
   242 dynamic:aBoolean
   240     "set the flag bit stating that the machine code was created
   243     "set the flag bit stating that the machine code was created
   241      dynamically and should be flushed on image-restart.
   244      dynamically and should be flushed on image-restart.
   242      - for use by compiler only."
   245      - for use by compiler only."
   243 
   246 
   244     |newFlags|
   247 %{  /* NOCONTEXT */
   245 
   248     int f = _intVal(_INST(flags));
   246     newFlags := flags.
   249 
   247 %{
       
   248     /* made this a primitive to get define in stc.h */
   250     /* made this a primitive to get define in stc.h */
   249     if (aBoolean == true)
   251     if (aBoolean == true)
   250         newFlags = _MKSMALLINT(_intVal(newFlags) | F_DYNAMIC);
   252         f = f | F_DYNAMIC;
   251     else
   253     else
   252         newFlags = _MKSMALLINT(_intVal(newFlags) & ~F_DYNAMIC);
   254         f = f & ~F_DYNAMIC;
   253 %}
   255     _INST(flags) = _MKSMALLINT(f);
   254 .
   256 %}
   255     flags := newFlags
       
   256 !
   257 !
   257 
   258 
   258 numberOfMethodArgs:aNumber
   259 numberOfMethodArgs:aNumber
   259     "currently, the number of arguments is NOT remembered in
   260     "currently, the number of arguments is NOT remembered in
   260      methods, but this will be added soon to allow for more checking
   261      methods, but this will be added soon to allow for more checking
   263      The limitation in the max. number of arguments is due to the
   264      The limitation in the max. number of arguments is due to the
   264      missing SENDxx functions in the VM. This too will be removed
   265      missing SENDxx functions in the VM. This too will be removed
   265      in a later release, allowing any number of arguments.
   266      in a later release, allowing any number of arguments.
   266      - for use by compiler only."
   267      - for use by compiler only."
   267 
   268 
   268     aNumber > self class maxNumberOfArguments ifTrue:[
   269     (aNumber between:0 and:self class maxNumberOfArguments) ifFalse:[
   269         self error:('methods support a maximum of ' ,
   270         self error:('ST/X only supports up to a maximum of ' ,
   270                     self class maxNumberOfArguments printString ,
   271                     self class maxNumberOfArguments printString ,
   271                     ' arguments')
   272                     ' method arguments').
   272     ]
   273         ^ self
       
   274     ].
       
   275 %{
       
   276     /* made this a primitive to get define in stc.h */
       
   277 #ifdef F_NARGS
       
   278     _INST(flags) = _MKSMALLINT( (_intVal(_INST(flags)) & ~F_NARGS) | (_intVal(aNumber) << F_NARGSHIFT) );
       
   279 #endif
       
   280 %}
   273 !
   281 !
   274      
   282      
   275 numberOfMethodArgs
   283 numberOfMethodArgs
   276     "return the number of arguments, the method expects." 
   284     "return the number of arguments, the method expects." 
   277 
   285 
       
   286 %{  /* NOCONTEXT */
       
   287     /* made this a primitive to get define in stc.h */
       
   288 
       
   289 #ifdef F_NARGS
       
   290     RETURN (_MKSMALLINT((_intVal(_INST(flags)) & F_NARGS) >> F_NARGSHIFT));
       
   291 #endif
       
   292 %}
       
   293 .
   278     "
   294     "
   279      The current implementation simply counts the arguments from
   295      The old implementation simply counted the arguments from
   280      the methods source - future versions will include this information
   296      the methods source - new versions include this information
   281      in the flag instVar, for more protection in #perform:"
   297      in the flag instVar, for more protection in #perform:"
   282 
   298 
   283     ^ self methodArgNames size
   299     ^ self methodArgNames size
   284 !
   300 !
   285 
   301 
   286 numberOfMethodVars:aNumber
   302 numberOfMethodVars:aNumber
   287     "set the number of method variables. 
   303     "set the number of method variables - for use by compiler only.
   288      Warning: playing around here with incorrect values 
   304      Warning: playing around here with incorrect values may crash smalltalk badly."
   289               may crash smalltalk badly.
   305 
   290      - for use by compiler only."
   306 %{  /* NOCONTEXT */
   291 
   307     int f = _intVal(_INST(flags));
   292     |newFlags|
   308 
   293 
       
   294     newFlags := flags.
       
   295 %{
       
   296     /* made this a primitive to get define in stc.h */
   309     /* made this a primitive to get define in stc.h */
   297     newFlags = _MKSMALLINT((_intVal(newFlags) & ~F_NVARS)
   310     if (_isSmallInteger(aNumber)) {
   298                            | (_intVal(aNumber) << F_NVARSHIFT));
   311         f = (f & ~F_NVARS) | (_intVal(aNumber) << F_NVARSHIFT);
   299 %}
   312         _INST(flags) = _MKSMALLINT(f);
   300 .
   313     }
   301     flags := newFlags
   314 %}
   302 !
   315 !
   303 
   316 
   304 numberOfMethodVars
   317 numberOfMethodVars
   305     "return the number of method local variables. 
   318     "return the number of method local variables. 
   306      Do not depend on the returned value - future optimizations
   319      Do not depend on the returned value - future optimizations
   308      - for debugging only."
   321      - for debugging only."
   309 
   322 
   310 %{  /* NOCONTEXT */
   323 %{  /* NOCONTEXT */
   311     /* made this a primitive to get define in stc.h */
   324     /* made this a primitive to get define in stc.h */
   312 
   325 
   313     int flagBits = _intVal(_INST(flags));
   326     RETURN (_MKSMALLINT((_intVal(_INST(flags)) & F_NVARS) >> F_NVARSHIFT));
   314 
       
   315     RETURN (_MKSMALLINT((flagBits & F_NVARS) >> F_NVARSHIFT));
       
   316 %}
   327 %}
   317 !
   328 !
   318 
   329 
   319 stackSize:aNumber
   330 stackSize:aNumber
   320     "set the depth of the local stack.
   331     "set the depth of the local stack - for use by compiler only.
   321      Warning: playing around here with incorrect values 
   332      Warning: playing around here with incorrect values may crash smalltalk badly.
   322               may crash smalltalk badly.
   333               (if the runtime library was compiled with DEBUG, a bad stack will be
   323      - for use by compiler only."
   334                cought and trigger an error though)"
   324 
   335 
   325     |newFlags|
   336 %{  /* NOCONTEXT */
   326 
   337     int f = _intVal(_INST(flags));
   327     newFlags := flags.
   338 
   328 %{
       
   329     /* made this a primitive to get define in stc.h */
   339     /* made this a primitive to get define in stc.h */
   330     newFlags = _MKSMALLINT((_intVal(newFlags) & ~F_NSTACK) 
   340     if (_isSmallInteger(aNumber)) {
   331                            | (_intVal(aNumber) << F_NSTACKSHIFT));
   341         f = (f & ~F_NSTACK) | (_intVal(aNumber) << F_NSTACKSHIFT);
   332 %}
   342         _INST(flags) = _MKSMALLINT(f);
   333 .
   343     }
   334     flags := newFlags
   344 %}
   335 !
   345 !
   336 
   346 
   337 stackSize
   347 stackSize
   338     "return the number of temporaries needed as stack in the context. 
   348     "return the number of temporaries needed as stack in the context. 
   339      Do not depend on the returned value - future optimizations
   349      Do not depend on the returned value - future optimizations
   341      - for debugging only."
   351      - for debugging only."
   342 
   352 
   343 %{  /* NOCONTEXT */
   353 %{  /* NOCONTEXT */
   344     /* made this a primitive to get define in stc.h */
   354     /* made this a primitive to get define in stc.h */
   345 
   355 
   346     int flagBits = _intVal(_INST(flags));
   356     RETURN (_MKSMALLINT((_intVal(_INST(flags)) & F_NSTACK) >> F_NSTACKSHIFT));
   347 
       
   348     RETURN (_MKSMALLINT((flagBits & F_NSTACK) >> F_NSTACKSHIFT));
       
   349 %}
   357 %}
   350 ! !
   358 ! !
   351 
   359 
   352 !Method methodsFor:'queries'!
   360 !Method methodsFor:'queries'!
   353 
   361 
   354 containingClass
   362 containingClass
   355     "return the class I am defined in 
   363     "return the class I am defined in. 
   356      - stupid, there is no information of the containing class 
   364      Since there is no information of the containing class 
   357        in the method, so we have to search here."
   365      in the method, we have to search here."
   358 
   366 
   359     Smalltalk allBehaviorsDo:[:aClass |
   367     Smalltalk allBehaviorsDo:[:aClass |
   360         (aClass containsMethod:self) ifTrue:[^ aClass]
   368         (aClass containsMethod:self) ifTrue:[^ aClass].
       
   369         (aClass class containsMethod:self) ifTrue:[^ aClass class]
   361     ].
   370     ].
   362     ^ nil
   371     ^ nil
   363 !
   372 !
   364 
   373 
   365 methodArgNames
   374 methodArgNames
   511      traditional function call.
   520      traditional function call.
   512      This method is provided for debugging- and breakpoint-support 
   521      This method is provided for debugging- and breakpoint-support 
   513      (replacing a method by a stup and recalling the original),
   522      (replacing a method by a stup and recalling the original),
   514      not for general use. 
   523      not for general use. 
   515      The receiver must be a method compiled in anObjects class or one of its 
   524      The receiver must be a method compiled in anObjects class or one of its 
   516      superclasses
   525      superclasses and also, the number of arguments given must match the methods
       
   526      expectations -
   517      - otherwise strange things (and also strange crashes) can occur.
   527      - otherwise strange things (and also strange crashes) can occur.
   518      The system is NOT always detecting a wrong method/receiver combination.
   528      The system is NOT always detecting a wrong method/receiver combination.
   519      BE WARNED."
   529      BE WARNED."
   520 
   530 
   521 %{
   531 %{
   523     OBJ searchClass;
   533     OBJ searchClass;
   524     static struct inlineCache dummy = _DUMMYILC0;
   534     static struct inlineCache dummy = _DUMMYILC0;
   525     int nargs;
   535     int nargs;
   526     OBJ *ap;
   536     OBJ *ap;
   527 
   537 
   528     if (_isArray(argArray)) {
   538     if (__isArray(argArray)) {
   529         nargs = _arraySize(argArray);
   539         nargs = _arraySize(argArray);
   530         ap = _ArrayInstPtr(argArray)->a_element;
   540         ap = _ArrayInstPtr(argArray)->a_element;
   531     } else {
   541     } else {
   532         if (argArray == nil) {
   542         if (argArray == nil) {
   533             nargs = 0;
   543             nargs = 0;
   596     ].
   606     ].
   597     ^ self error:'too many arguments'
   607     ^ self error:'too many arguments'
   598 
   608 
   599     "(Float compiledMethodAt:#+) valueWithReceiver:1.0 arguments:#(2.0)"
   609     "(Float compiledMethodAt:#+) valueWithReceiver:1.0 arguments:#(2.0)"
   600     "the next example is a wrong one - which is detected by True's method ..."
   610     "the next example is a wrong one - which is detected by True's method ..."
   601     "(True compiledMethodAt:#printString) valueWithReceiver:false arguments:nilfalse"
   611     "(True compiledMethodAt:#printString) valueWithReceiver:false arguments:nil"
   602 ! !
   612 ! !
   603 
   613 
   604 !Method methodsFor:'printing'!
   614 !Method methodsFor:'printing'!
   605 
   615 
   606 printOn:aStream
   616 printOn:aStream
   607     "put a printed representation of the receiver onto aStream"
   617     "put a printed representation of the receiver onto aStream.
   608 
   618      Since methods do not store their class/selector, we have to search
   609     |homeClass|
   619      for it here."
   610 
   620 
   611     homeClass := self containingClass.
   621     |myClass|
   612     homeClass notNil ifTrue:[
   622 
   613         aStream nextPutAll:'a Method in '.
   623     aStream nextPutAll:'a Method('.
   614         homeClass name printOn:aStream.
   624     myClass := self containingClass.
       
   625     myClass notNil ifTrue:[
       
   626         myClass name printOn:aStream.
   615         aStream nextPutAll:' '.
   627         aStream nextPutAll:' '.
   616         (homeClass selectorForMethod:self) printOn:aStream
   628         (myClass selectorForMethod:self) printOn:aStream
   617     ] ifFalse:[
   629     ] ifFalse:[
   618         aStream nextPutAll:'a Method'
   630         aStream nextPutAll:'???'
   619     ]
   631     ].
       
   632     aStream nextPut:$)
   620 ! !
   633 ! !
   621 
   634 
   622 !Method methodsFor:'binary storage'!
   635 !Method methodsFor:'binary storage'!
   623 
   636 
   624 storeBinaryDefinitionOn: stream manager: manager
   637 storeBinaryDefinitionOn: stream manager: manager
   625     "can only store bytecode - machine code is lost"
   638     "can only store bytecode - machine code is not storable.
   626 
   639      If the receiver method is a built-in (i.e. machine coded)
   627     |temporaryMethod cls|
   640      method, a temporary interpreted byte code method is created,
       
   641      and that bytecode stored. 
       
   642      This works only, if the source of the method is available"
       
   643 
       
   644     |temporaryMethod cls source|
   628 
   645 
   629     byteCode isNil ifTrue:[
   646     byteCode isNil ifTrue:[
   630         cls := self containingClass.
   647         cls := self containingClass.
   631         temporaryMethod := cls compiler compile:(self source)
   648         source := self source.
   632                                        forClass:cls
   649         source notNil ifTrue:[
   633                                      inCategory:(self category)
   650             temporaryMethod := cls compiler compile:(self source)
   634                                       notifying:nil
   651                                            forClass:cls
   635                                         install:false.
   652                                          inCategory:(self category)
   636         ^ temporaryMethod storeBinaryDefinitionOn: stream manager: manager
   653                                           notifying:nil
       
   654                                             install:false.
       
   655             ^ temporaryMethod storeBinaryDefinitionOn:stream manager:manager
       
   656         ].
       
   657         self error:'store of built-in method failed (no source for compilation)'
   637     ].
   658     ].
   638     ^ super storeBinaryDefinitionOn: stream manager: manager
   659     ^ super storeBinaryDefinitionOn: stream manager: manager
   639 ! !
   660 ! !
   640 
   661 
   641 !Method methodsFor:'binary fileOut'!
   662 !Method methodsFor:'obsolete binary fileOut'!
   642 
   663 
   643 binaryFileOutLiteralsOn:aStream
   664 binaryFileOutLiteralsOn:aStream
   644     |index n|
   665     |index n|
   645 
   666 
   646     literals isNil ifTrue:[
   667     literals isNil ifTrue:[
   666                 ] ifFalse:[
   687                 ] ifFalse:[
   667                     lit isBehavior ifTrue:[
   688                     lit isBehavior ifTrue:[
   668                         aStream nextPutAll:'(Smalltalk at:#'.
   689                         aStream nextPutAll:'(Smalltalk at:#'.
   669                         n := lit name.
   690                         n := lit name.
   670                         lit isMeta ifTrue:[
   691                         lit isMeta ifTrue:[
   671                             n := (n copyFrom:1 to:(n size - 5)) , ') class'
   692                             n := (n copyTo:(n size - 5)) , ') class'
   672                         ] ifFalse:[
   693                         ] ifFalse:[
   673                             n := n , ')'
   694                             n := n , ')'
   674                         ].
   695                         ].
   675                         aStream nextPutAll:n
   696                         aStream nextPutAll:n
   676                     ] ifFalse:[
   697                     ] ifFalse:[