Tradeoffs around Node::Opcode()?
Vladimir Kozlov
Vladimir.Kozlov at Sun.COM
Tue Mar 10 14:22:06 PDT 2009
Yes, it is history :)
The _opcode field will not work since subclasses will overwrite it.
The _class_id field is not direct map to Opcode, it is bitmap:
n->is_SafePoint() will be true for all ideal Call and SafePoint nodes,
but n->Opcode() == Op_SafePoint only true for SafePointNode.
So we need both.
And yes, I want to fit in a jushort :-)
When I did implementation of _class_id I was also concern about
increasing Node size significantly so I decided to add only 4 bytes:
2 for class_id and 2 for flags.
I also did profiling of Opcode() usage. So only hottest Opcode()
calls were replaced with class_id code. Adding other nodes did not
improve performance.
Vladimir
Peter B. Kessler wrote:
> Cool! Thanks. So much for engineering: we already have *both* the
> virtual dispatch *and* the data slot per instance.
>
> Oh, but those are only the class id's (e.g., Add), rather than the
> opcode (e.g., AddI). It's confusing that they are both referred to as
> Node "classes", e.g., in classes.hpp, opcodes.cpp, etc.
>
> So I guess that begs the question: why *isn't* there an _opcode field,
> initialized in the constructors, like (or instead of) _class_id? Why
> aren't the leaf classes (AddI, etc.) in the _class_id maps? (Other than
> that the _class_id maps want to fit in a jushort. :-) Couldn't one map
> (e.g., with a table) from an opcode to a _class_id, if one wanted to
> spend the time as opposed to the space? Would an inline method to
> access a _class_id table be faster than a virtual dispatch to Opcode()?
>
> A possible answer as to why it is the way it is: "History".
>
> I'm still trying to understand the tradeoffs between space and time.
>
> ... peter
>
> Vladimir Kozlov wrote:
>> Peter,
>>
>> There is already such functionality exactly for such purpose.
>> The field is jushort _class_id; which use enum NodeClasses
>> and initializer in the constructors init_class_id().
>>
>> Vladimir
>>
>> Peter B. Kessler wrote:
>>> A lot of things in class Node are organized around having a dense
>>> integer range to identify the Node. That's Node::Opcode().
>>>
>>> I'm wondering about the engineering around that method.
>>> Node::Opcode() is a virtual call, to get from a Node instance to a
>>> piece of data on the Node subclass of the instance. An alternative
>>> would be to add a data field in Node to hold the opcode, and replace
>>> the virtual Node::Opcode() calls with an inline method to return the
>>> contents of that slot. That trades the virtual dispatch cost for
>>> each call with a space cost in each instance.
>>>
>>> Does anyone have any feeling about whether that's a good tradeoff?
>>> How often is Node::Opcode() called? What effect would it have to
>>> make it run faster? How important is it to minimize the size of Node
>>> instances? (There are other places where effort is expended to keep
>>> Node's small.)
>>>
>>> Thanks for any opinions on this.
>>>
>>> ... peter
>
More information about the hotspot-compiler-dev
mailing list