a906a6f1e5898c675e8c75a98536f90bf62bcbcc
1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2015 Julien Pagès <julien.pages@lirmm.fr>
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 # Optimization of the nitvm
18 module vm_optimizations
22 redef class AAttrFormExpr
23 # Position of the attribute in attribute table
25 # The relative position of this attribute if perfect hashing is used,
26 # The absolute position of this attribute if SST is used
29 # Indicate the status of the optimization for this node
32 # 1: SST (direct access) can be used
33 # 2: PH (multiple inheritance implementation) must be used
36 # Identifier of the class which introduced the attribute
39 # Optimize this attribute access
40 # * `mproperty` The attribute which is accessed
41 # * `recv` The receiver (The object) of the access
42 protected fun optimize
(mproperty
: MAttribute, recv
: MutableInstance)
44 if mproperty
.intro_mclassdef
.mclass
.positions_attributes
[recv
.mtype
.as(MClassType).mclass
] != -1 then
45 # if this attribute class has an unique position for this receiver, then use direct access
46 offset
= mproperty
.absolute_offset
49 # Otherwise, perfect hashing must be used
50 id
= mproperty
.intro_mclassdef
.mclass
.vtable
.id
51 offset
= mproperty
.offset
60 # TODO : a workaround for now
61 if not v
isa VirtualMachine then return super
63 var recv
= v
.expr
(self.n_expr
)
64 if recv
== null then return null
65 if recv
.mtype
isa MNullType then fatal
(v
, "Receiver is null")
66 var mproperty
= self.mproperty
.as(not null)
68 assert recv
isa MutableInstance
69 if status
== 0 then optimize
(mproperty
, recv
)
74 i
= v
.read_attribute_sst
(recv
.internal_attributes
, offset
)
77 i
= v
.read_attribute_ph
(recv
.internal_attributes
, recv
.vtable
.internal_vtable
, recv
.vtable
.mask
, id
, offset
)
80 # If we get a `MInit` value, throw an error
81 if i
== v
.initialization_value
then
82 v
.fatal
("Uninitialized attribute {mproperty.name}")
90 redef class AAttrAssignExpr
93 # TODO : a workaround for now
94 if not v
isa VirtualMachine then
99 var recv
= v
.expr
(self.n_expr
)
100 if recv
== null then return
101 if recv
.mtype
isa MNullType then fatal
(v
, "Receiver is null")
102 var i
= v
.expr
(self.n_value
)
103 if i
== null then return
104 var mproperty
= self.mproperty
.as(not null)
106 assert recv
isa MutableInstance
107 if status
== 0 then optimize
(mproperty
, recv
)
110 v
.write_attribute_sst
(recv
.internal_attributes
, offset
, i
)
112 v
.write_attribute_ph
(recv
.internal_attributes
, recv
.vtable
.internal_vtable
,
113 recv
.vtable
.mask
, id
, offset
, i
)
118 # Add informations to optimize some method calls
120 # Position of the method in virtual table
122 # The relative position of this MMethod if perfect hashing is used,
123 # The absolute position of this MMethod if SST is used
126 # Indicate the status of the optimization for this node
129 # 1: SST (direct access) can be used
130 # 2: PH (multiple inheritance implementation) must be used
133 # Identifier of the class which introduced the MMethod
136 # Optimize a method dispatch
137 fun optimize
(recv
: Instance)
139 if mproperty
.intro_mclassdef
.mclass
.positions_methods
[recv
.mtype
.as(MClassType).mclass
] != -1 then
140 offset
= mproperty
.absolute_offset
143 offset
= mproperty
.offset
146 id
= mproperty
.intro_mclassdef
.mclass
.vtable
.id
151 # Identifier of the target class type
154 # If the Cohen test is used, the position of the target id in vtable
157 # Indicate the status of the optimization for this node
159 # 0 : the default value
160 # 1 : this test can be implemented with direct access
161 # 2 : this test must be implemented with perfect hashing
166 # TODO : a workaround for now
167 if not v
isa VirtualMachine then return super
169 var recv
= v
.expr
(self.n_expr
)
170 if recv
== null then return null
172 if status
== 0 then optimize
(v
, recv
.mtype
, self.cast_type
.as(not null))
173 var mtype
= v
.unanchor_type
(self.cast_type
.as(not null))
175 # If this test can be optimized, directly call appropriate subtyping methods
176 if status
== 1 and recv
.mtype
isa MClassType then
178 return v
.bool_instance
(v
.inter_is_subtype_sst
(id
, position
, recv
.mtype
.as(MClassType).mclass
.vtable
.internal_vtable
))
179 else if status
== 2 and recv
.mtype
isa MClassType then
181 return v
.bool_instance
(v
.inter_is_subtype_ph
(id
, recv
.vtable
.mask
, recv
.mtype
.as(MClassType).mclass
.vtable
.internal_vtable
))
183 # Use the slow path (default)
184 return v
.bool_instance
(v
.is_subtype
(recv
.mtype
, mtype
))
188 # Optimize a `AIsaExpr`
189 # `source` the source type of the expression
190 # `target` the target type of the subtyping test
191 private fun optimize
(v
: VirtualMachine, source
: MType, target
: MType)
193 # If the source class and target class are not classic classes (non-generics) then return
194 if not source
isa MClassType or not target
isa MClassType or target
isa MGenericType then
198 if not target
.mclass
.loaded
then return
200 # Try to get the position of the target type in source's structures
201 var value
= source
.mclass
.positions_methods
.get_or_null
(target
.mclass
)
203 if value
!= null then
205 # Store informations for Cohen test
206 position
= target
.mclass
.color
209 # We use perfect hashing
213 id
= target
.mclass
.vtable
.id
217 redef class AAsCastExpr
218 # Identifier of the target class type
221 # If the Cohen test is used, the position of the target id in vtable
224 # Indicate the status of the optimization for this node
226 # 0 : the default value
227 # 1 : this test can be implemented with direct access
228 # 2 : this test must be implemented with perfect hashing
233 # TODO : a workaround for now
234 if not v
isa VirtualMachine then return super
236 var recv
= v
.expr
(self.n_expr
)
237 if recv
== null then return null
239 if status
== 0 then optimize
(v
, recv
.mtype
, self.mtype
.as(not null))
241 var mtype
= self.mtype
.as(not null)
242 var amtype
= v
.unanchor_type
(mtype
)
245 if status
== 1 and recv
.mtype
isa MClassType then
247 res
= v
.inter_is_subtype_sst
(id
, position
, recv
.mtype
.as(MClassType).mclass
.vtable
.internal_vtable
)
248 else if status
== 2 and recv
.mtype
isa MClassType then
250 res
= v
.inter_is_subtype_ph
(id
, recv
.vtable
.mask
, recv
.mtype
.as(MClassType).mclass
.vtable
.internal_vtable
)
252 # Use the slow path (default)
253 res
= v
.is_subtype
(recv
.mtype
, amtype
)
257 fatal
(v
, "Cast failed. Expected `{amtype}`, got `{recv.mtype}`")
262 # Optimize a `AAsCastExpr`
263 # * `source` the source type of the expression
264 # * `target` the target type of the subtyping test
265 private fun optimize
(v
: VirtualMachine, source
: MType, target
: MType)
267 # If the source class and target class are not classic classes (non-generics) then return
268 if not source
isa MClassType or not target
isa MClassType or target
isa MGenericType then
272 if not target
.mclass
.loaded
then return
274 # Try to get the position of the target type in source's structures
275 var value
= source
.mclass
.positions_methods
.get_or_null
(target
.mclass
)
277 if value
!= null then
279 # Store informations for Cohen test
280 position
= target
.mclass
.color
283 # We use perfect hashing
287 id
= target
.mclass
.vtable
.id