problem with Interpreter>>#printNameOfClass:count:

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

problem with Interpreter>>#printNameOfClass:count:

melkyades
 
Hi, this method of Interpreter is used for debugging, and should print the name of the class passed in console:

printNameOfClass: classOop count: cnt
"Details: The count argument is used to avoid a possible infinite recursion if classOop is a corrupted object."

cnt <= 0 ifTrue: [ ^ self print: 'bad class' ].
(self sizeBitsOf: classOop) = (7 * self bytesPerWord) "(Metaclass instSize+1 * 4)"
ifTrue: [self printNameOfClass: (self fetchPointer: 5 "thisClass" ofObject: classOop) 
count: cnt - 1.
self print: ' class']
ifFalse: [self printStringOf: (self fetchPointer: 6 "name" ofObject: classOop)]

it's logic is this: if the classOop is of a normal Class instance, it should use the instance var number six, which corresponds to the class' name. If not, then the classOop represents a Metaclass instance, and then it will fetch inst var number 5, which is the corresponding class, print its name, and then print 'class' to let you distinguish it that it is a metaclass.

The problem of the method is that it determines if it's a class instance or a metaclass instance by looking at the size of the oop, which seems to have changed, at least in pharo (Metaclass instSize+1 * 4 = 36 = 9*bytesPerWord). 

The method could be fixed by changing 7 to 9 then. But it will break if Metaclass changes again. So I have this idea: make it check if the classOop is a metaclass instance. Metaclass class is not a special object, but can be obtained by accessing any special one, like with 

Integer class class

or directly with

nil class class class (!!)

then the proposed code is:

printNameOfClass: classOop count: cnt "Details: The count argument is used to avoid a possible infinite recursion if classOop is a corrupted object." | metaclassClass | cnt <= 0 ifTrue: [ ^ self print: 'bad class' ]. metaclassClass := self fetchClassOf: (self fetchClassOf: (self fetchPointer: ClassInteger ofObject: specialObjectsOop)). metaclassClass = (self fetchClassOf: classOop) "Is it a metaclass?" ifTrue: [self printNameOfClass: (self fetchPointer: 5 "thisClass" ofObject: classOop) count: cnt - 1. self print: ' class'] ifFalse: [self printStringOf: (self fetchPointer: 6 "name" ofObject: classOop)]


I'd also like to have this included too:

printClassOf: oop
"Print the class of the oop in console"
self printNameOfClass: (self fetchClassOf: oop) count: 5. 

which is simple but pretty much useful.

What do you think?

Regards,
           Javier.

--
Javier Pimás
Ciudad de Buenos Aires
Reply | Threaded
Open this post in threaded view
|

Re: problem with Interpreter>>#printNameOfClass:count:

Eliot Miranda-2
 
looks good.  I'll integrate in Cog soon.  BTW, you can use fetchClassOfNonInt: where you know you won't encounter an immediate, hence

printNameOfClass: classOop count: cnt "Details: The count argument is used to avoid a possible infinite recursion if classOop is a corrupted object." | metaclassClass | cnt <= 0 ifTrue: [ ^ self print: 'bad class' ]. metaclassClass := self fetchClassOfNonInt: (self fetchClassOfNonInt: (self fetchPointer: ClassInteger ofObject: specialObjectsOop)). metaclassClass = (self fetchClassOfNonInt: classOop) "Is it a metaclass?" ifTrue: [self printNameOfClass: (self fetchPointer: 5 "thisClass" ofObject: classOop) count: cnt - 1. self print: ' class'] ifFalse: [self printStringOf: (self fetchPointer: 6 "name" ofObject: classOop)]

On Thu, Mar 31, 2011 at 8:51 PM, Javier Pimás <[hidden email]> wrote:
 
Hi, this method of Interpreter is used for debugging, and should print the name of the class passed in console:

printNameOfClass: classOop count: cnt
"Details: The count argument is used to avoid a possible infinite recursion if classOop is a corrupted object."

cnt <= 0 ifTrue: [ ^ self print: 'bad class' ].
(self sizeBitsOf: classOop) = (7 * self bytesPerWord) "(Metaclass instSize+1 * 4)"
ifTrue: [self printNameOfClass: (self fetchPointer: 5 "thisClass" ofObject: classOop) 
count: cnt - 1.
self print: ' class']
ifFalse: [self printStringOf: (self fetchPointer: 6 "name" ofObject: classOop)]

it's logic is this: if the classOop is of a normal Class instance, it should use the instance var number six, which corresponds to the class' name. If not, then the classOop represents a Metaclass instance, and then it will fetch inst var number 5, which is the corresponding class, print its name, and then print 'class' to let you distinguish it that it is a metaclass.

The problem of the method is that it determines if it's a class instance or a metaclass instance by looking at the size of the oop, which seems to have changed, at least in pharo (Metaclass instSize+1 * 4 = 36 = 9*bytesPerWord). 

The method could be fixed by changing 7 to 9 then. But it will break if Metaclass changes again. So I have this idea: make it check if the classOop is a metaclass instance. Metaclass class is not a special object, but can be obtained by accessing any special one, like with 

Integer class class

or directly with

nil class class class (!!)

then the proposed code is:

printNameOfClass: classOop count: cnt "Details: The count argument is used to avoid a possible infinite recursion if classOop is a corrupted object." | metaclassClass | cnt <= 0 ifTrue: [ ^ self print: 'bad class' ]. metaclassClass := self fetchClassOf: (self fetchClassOf: (self fetchPointer: ClassInteger ofObject: specialObjectsOop)). metaclassClass = (self fetchClassOf: classOop) "Is it a metaclass?" ifTrue: [self printNameOfClass: (self fetchPointer: 5 "thisClass" ofObject: classOop) count: cnt - 1. self print: ' class'] ifFalse: [self printStringOf: (self fetchPointer: 6 "name" ofObject: classOop)]


I'd also like to have this included too:

printClassOf: oop
"Print the class of the oop in console"
self printNameOfClass: (self fetchClassOf: oop) count: 5. 

which is simple but pretty much useful.

What do you think?

Regards,
           Javier.

--
Javier Pimás
Ciudad de Buenos Aires


Reply | Threaded
Open this post in threaded view
|

Re: problem with Interpreter>>#printNameOfClass:count:

Mariano Martinez Peck
In reply to this post by melkyades
 


On Fri, Apr 1, 2011 at 5:51 AM, Javier Pimás <[hidden email]> wrote:
 
Hi, this method of Interpreter is used for debugging, and should print the name of the class passed in console:

printNameOfClass: classOop count: cnt
"Details: The count argument is used to avoid a possible infinite recursion if classOop is a corrupted object."

cnt <= 0 ifTrue: [ ^ self print: 'bad class' ].
(self sizeBitsOf: classOop) = (7 * self bytesPerWord) "(Metaclass instSize+1 * 4)"
ifTrue: [self printNameOfClass: (self fetchPointer: 5 "thisClass" ofObject: classOop) 
count: cnt - 1.
self print: ' class']
ifFalse: [self printStringOf: (self fetchPointer: 6 "name" ofObject: classOop)]

it's logic is this: if the classOop is of a normal Class instance, it should use the instance var number six,
 
which corresponds to the class' name. If not, then the classOop represents a Metaclass instance, and then it will fetch inst var number 5, which is the corresponding class, print its name, and then print 'class' to let you distinguish it that it is a metaclass.

The problem of the method is that it determines if it's a class instance or a metaclass instance by looking at the size of the oop, which seems to have changed, at least in pharo (Metaclass instSize+1 * 4 = 36 = 9*bytesPerWord). 

The method could be fixed by changing 7 to 9 then. But it will break if Metaclass changes again.

yes
 
So I have this idea: make it check if the classOop is a metaclass instance. Metaclass class is not a special object, but can be obtained by accessing any special one, like with 

Integer class class

or directly with

nil class class class (!!)

then the proposed code is:

printNameOfClass: classOop count: cnt "Details: The count argument is used to avoid a possible infinite recursion if classOop is a corrupted object." | metaclassClass | cnt <= 0 ifTrue: [ ^ self print: 'bad class' ]. metaclassClass := self fetchClassOf: (self fetchClassOf: (self fetchPointer: ClassInteger ofObject: specialObjectsOop)). metaclassClass = (self fetchClassOf: classOop) "Is it a metaclass?" ifTrue: [self printNameOfClass: (self fetchPointer: 5 "thisClass" ofObject: classOop) count: cnt - 1. self print: ' class'] ifFalse: [self printStringOf: (self fetchPointer: 6 "name" ofObject: classOop)]



Looking at Cog, I think Eliot has already solved this problem:

printNameOfClass: classOop count: cnt
    "Details: The count argument is used to avoid a possible infinite recursion if classOop is a corrupted object."
    <inline: false>
    (classOop = 0 or: [cnt <= 0]) ifTrue: [^self print: 'bad class'].
    ((objectMemory sizeBitsOf: classOop) = metaclassSizeBytes
      and: [metaclassSizeBytes > (thisClassIndex * BytesPerWord)])    "(Metaclass instSize * 4)"
        ifTrue: [self printNameOfClass: (objectMemory fetchPointer: thisClassIndex ofObject: classOop) count: cnt - 1.
                self print: ' class']
        ifFalse: [self printStringOf: (objectMemory fetchPointer: classNameIndex ofObject: classOop)]


And metaclassSizeBytes is set in a "similar" way you proposed:

StackInterpreter >> initializeExtraClassInstVarIndices
    "Initialize metaclassSizeBytes and thisClassIndex which are used in debug printing, and
     classNameIndex which is used not only for debug printing but for is:KindOf: & is:MemberOf:
     via classNameOf:is: (evil but a reality we have to accept)."
    | classArrayObj classArrayClass |
    classNameIndex := 6. "default"
    thisClassIndex := 5. "default"
    classArrayObj := objectMemory splObj: ClassArray.
    classArrayClass := objectMemory fetchClassOfNonInt: classArrayObj.
    metaclassSizeBytes := objectMemory sizeBitsOf: classArrayClass.    "determine actual (Metaclass instSize * 4)"
 ......


So...it is correct to assume that this is solved in Cog ?

Thanks

Mariano


 

I'd also like to have this included too:

printClassOf: oop
"Print the class of the oop in console"
self printNameOfClass: (self fetchClassOf: oop) count: 5. 

which is simple but pretty much useful.

What do you think?

Regards,
           Javier.

--
Javier Pimás
Ciudad de Buenos Aires




--
Mariano
http://marianopeck.wordpress.com