/[eiffelstudio]/branches/CAT_mono/Src/Eiffel/eiffel/genericity/cl_type_i.e
ViewVC logotype

Contents of /branches/CAT_mono/Src/Eiffel/eiffel/genericity/cl_type_i.e

Parent Directory Parent Directory | Revision Log Revision Log


Revision 39713 - (show annotations)
Fri Oct 17 19:27:17 2003 UTC (16 years, 4 months ago) by manus
Original Path: trunk/Src/bench/Eiffel/eiffel/genericity/cl_type_i.e
File size: 13997 byte(s)
Fixed eweasel bug `freez026'. By previously fixing the way we handle
creation of generic type using anchored in their specification (e.g. A [like f])
we introduced a bug of type result caching. Indeed before when a `typarr'
had an anchor it contained either LIKE_ARG_TYPE, LIKE_CURRENT_TYPE,
LIKE_PFEATURE_TYPE or LIKE_FEATURE_TYPE. In such cases the C runtime
was preventing the caching of the information.
Now since we do not generate the LIKE_XX constants, but force a computation
of the value in the generated code the caching mechanism was not prevented
therefore in such cases it was giving the proper result the first time around
but not the second time around if the `anchors' were different.

To prevent this we tell the runtime if it can cache it by providing a non NULL
buffer, it cannot if we pass NULL.
To find out if we can pass a non-NULL or NULL, we simply find out if the
generic type is `is_explicit'. When it is `is_explicit, it is known for not
changing during the whole life of the application and we pass a non NULL buffer.
When it is not `is_explicit' then the value would have to be recomputed
each time it is queried, therefore we pass a NULL buffer.

To improve performance in non multithreaded mode we always mark the `typarr'
a static structure. As only one thread at the time can modify it if the
generic type is not explicit. In multithreaded mode, this is not the case
and therefore it is not `static'.

FIXME: we might be better off using `uint16' as on some platforms unsigned
operation are much faster than signed one. The second advantage will be to
increase the number of possible dynamic types from ~32000 to ~65000.

1 indexing
2 description: "Type class."
3 date: "$Date$"
4 revision: "$Revision$"
5
6 class CL_TYPE_I
7
8 inherit
9 TYPE_I
10 redefine
11 is_reference,
12 is_true_expanded,
13 is_separate,
14 is_valid,
15 is_explicit,
16 is_external,
17 same_as,
18 c_type,
19 instantiation_in,
20 complete_instantiation_in,
21 conforms_to_array,
22 generated_id,
23 generate_cid,
24 make_gen_type_byte_code,
25 generate_cid_array,
26 generate_cid_init,
27 generate_gen_type_il,
28 generate_expanded_creation
29 end
30
31 DEBUG_OUTPUT
32 export
33 {NONE} all
34 end
35
36 SHARED_IL_CASING
37 export
38 {NONE} all
39 end
40
41 SHARED_GENERATION
42 export
43 {NONE} all
44 end
45
46 SHARED_DECLARATIONS
47 export
48 {NONE} all
49 end
50
51 create
52 make
53
54 feature {NONE} -- Initialization
55
56 make (id: INTEGER) is
57 -- Create new instance of `Current' with `class_id'
58 -- assigned with `id'.
59 require
60 valid_id: id > 0
61 do
62 class_id := id
63 ensure
64 class_id_set: class_id = id
65 end
66
67 feature -- Access
68
69 class_id: INTEGER
70 -- Base class id of the type class
71
72 meta_generic: META_GENERIC is
73 -- Meta generic array describing the type class
74 do
75 -- No meta generic in non-generic type
76 end
77
78 cr_info : CREATE_INFO
79 -- Additional information for the creation
80 -- of generic types with anchored parameters
81
82 true_generics : ARRAY [TYPE_I] is
83 -- Array of generics: no mapping reference -> REFERENCE_I
84 do
85 -- Non generic types don't have them
86 end
87
88 base_class: CLASS_C is
89 -- Base class associated to the class type
90 do
91 Result := System.class_of_id (class_id)
92 end
93
94 type_a: CL_TYPE_A is
95 do
96 create Result.make (class_id)
97 Result.set_is_true_expanded (is_true_expanded)
98 Result.set_is_separate (is_separate)
99 end
100
101 il_type_name (a_prefix: STRING): STRING is
102 -- Class name of current type.
103 local
104 l_class_c: like base_class
105 l_is_precompiled: BOOLEAN
106 l_cl_type: like associated_class_type
107 do
108 l_class_c := base_class
109 if l_class_c.is_external then
110 Result := clone (l_class_c.external_class_name)
111 else
112 l_is_precompiled := l_class_c.is_precompiled
113 if l_is_precompiled then
114 l_cl_type := associated_class_type
115 l_is_precompiled := l_cl_type.is_precompiled
116 if l_is_precompiled then
117 Result := associated_class_type.il_type_name (a_prefix)
118 end
119 end
120 if not l_is_precompiled then
121 Result := internal_il_type_name (clone (l_class_c.name), a_prefix)
122 end
123 end
124 end
125
126 instantiation_in (other: GEN_TYPE_I): CL_TYPE_I is
127 -- Instantiation of Current in context of `other'
128 require else
129 True
130 do
131 Result := Current
132 end
133
134 complete_instantiation_in (other: GEN_TYPE_I): CL_TYPE_I is
135 -- Instantiation of Current in context of `other'
136 require else
137 True
138 do
139 Result := Current
140 end
141
142 description: ATTR_DESC is
143 -- Type description for skeletons
144 local
145 exp: EXPANDED_DESC
146 ref: REFERENCE_DESC
147 do
148 if is_true_expanded then
149 create exp
150 is_true_expanded := False
151 exp.set_class_type (base_class.types.search_item (Current))
152 is_true_expanded := True
153 exp.set_type_i (Current)
154 Result := exp
155 elseif is_separate then
156 -- FIXME
157 Result := c_type.description
158 else
159 Result := c_type.description
160 end
161
162 ref ?= Result
163 if ref /= Void then
164 ref.set_type_i (Current)
165 end
166 end
167
168 c_type: TYPE_C is
169 -- Associated C type
170 do
171 Result := Reference_c_type
172 end
173
174 associated_class_type: CLASS_TYPE is
175 -- Associated class type
176 require
177 -- has: has_associated_class_type
178 do
179 if is_true_expanded then
180 is_true_expanded := False
181 Result := base_class.types.search_item (Current)
182 is_true_expanded := True
183 elseif is_separate then
184 is_separate := False
185 Result := base_class.types.search_item (Current)
186 is_separate := True
187 else
188 Result := base_class.types.search_item (Current)
189 end
190 end
191
192 type_id: INTEGER is
193 -- Type id of the correponding class type
194 do
195 Result := associated_class_type.type_id
196 end
197
198 sk_value: INTEGER is
199 -- Generate SK value associated to the current type.
200 do
201 -- FIXME????: separate
202 if not is_true_expanded then
203 Result := Sk_ref | (type_id - 1)
204 else
205 is_true_expanded := False
206 Result := Sk_exp | (type_id - 1)
207 is_true_expanded := True
208 end
209 end
210
211 cecil_value: INTEGER is
212 do
213 -- FIXME????: separate
214 if not is_true_expanded then
215 Result := Sk_dtype
216 else
217 Result := Sk_exp | class_id
218 end
219 end
220
221 hash_code: INTEGER is
222 -- Hash code for current type
223 do
224 Result := Other_code + class_id
225 end
226
227 feature -- Status
228
229 element_type: INTEGER_8 is
230 -- Void element type
231 do
232 if is_expanded and base_class.is_external then
233 -- We only support expanded for external class at the moment.
234 Result := feature {MD_SIGNATURE_CONSTANTS}.Element_type_valuetype
235 else
236 if class_id = System.system_string_class.compiled_class.class_id then
237 Result := feature {MD_SIGNATURE_CONSTANTS}.Element_type_string
238 elseif class_id = System.system_object_id then
239 Result := feature {MD_SIGNATURE_CONSTANTS}.Element_type_object
240 else
241 Result := feature {MD_SIGNATURE_CONSTANTS}.Element_type_class
242 end
243 end
244 end
245
246 is_true_expanded: BOOLEAN
247 -- Is the type expanded?
248
249 is_separate: BOOLEAN
250 -- Is the type separate?
251
252 is_enum: BOOLEAN is
253 -- Is current type an IL enum type?
254 -- Useful to find out if some call optimization can be done
255 -- in FEATURE_B.
256 require
257 il_generation: System.il_generation
258 do
259 Result := is_true_expanded and then base_class.is_enum
260 end
261
262 is_external: BOOLEAN is
263 -- Is current type an IL enum type?
264 -- Useful to find out if some call optimization can be done
265 -- in FEATURE_B.
266 do
267 Result := base_class.is_external
268 end
269
270 is_valid: BOOLEAN is
271 -- Is the base class still in the system and matches its specification?
272 do
273 Result := base_class /= Void and then (base_class.generics = Void)
274 end
275
276 is_reference: BOOLEAN is
277 -- Is the type a reference type ?
278 do
279 Result := not is_true_expanded
280 end;
281
282 is_explicit: BOOLEAN is
283 -- Is Current type fixed at compile time?
284 do
285 if cr_info /= Void then
286 Result := cr_info.is_explicit
287 else
288 Result := True
289 end
290 end
291
292 has_associated_class_type: BOOLEAN is
293 -- Has `Current' an associated class type?
294 do
295 if is_true_expanded then
296 is_true_expanded := False
297 Result := base_class.types.has_type (Current)
298 is_true_expanded := True
299 elseif is_separate then
300 is_separate := False
301 Result := base_class.types.has_type (Current)
302 is_separate := True
303 else
304 Result := base_class.types.has_type (Current)
305 end
306 end
307
308 same_as (other: TYPE_I): BOOLEAN is
309 -- Is `other' equal to Current ?
310 local
311 other_cl_type: CL_TYPE_I
312 do
313 other_cl_type ?= other
314 Result := other_cl_type /= Void -- FIXME
315 and then other_cl_type.class_id = class_id
316 and then other_cl_type.is_true_expanded = is_true_expanded
317 and then other_cl_type.is_separate = is_separate
318 and then other_cl_type.meta_generic = Void
319 and then other_cl_type.true_generics = Void
320 end
321
322 feature -- Setting
323
324 set_is_true_expanded (b: BOOLEAN) is
325 -- Assign `b' to `is_true_expanded'.
326 do
327 is_true_expanded := b
328 ensure
329 is_true_expanded_set: is_true_expanded = b
330 end
331
332 set_is_separate (b: BOOLEAN) is
333 -- Assign `b' to `is_separate'.
334 do
335 is_separate := b
336 ensure
337 is_separate_set: is_separate = b
338 end
339
340 set_cr_info (cinfo : CREATE_INFO) is
341 -- Set `cr_info' to `cinfo'.
342 require
343 create_info_not_void: cinfo /= Void
344 do
345 cr_info := cinfo
346 ensure
347 cr_info_set : cr_info = cinfo
348 end
349
350 feature -- Formatting
351
352 append_signature (st: STRUCTURED_TEXT) is
353 do
354 if is_true_expanded then
355 st.add_string ("expanded ")
356 elseif is_separate then
357 st.add_string ("separate ")
358 end
359 base_class.append_signature (st)
360 end
361
362 dump (buffer: GENERATION_BUFFER) is
363 do
364 buffer.putstring (debug_output)
365 end
366
367 feature -- C generation
368
369 generate_expanded_creation (byte_code: BYTE_CODE; reg: REGISTRABLE; workbench_mode: BOOLEAN) is
370 -- Generate creation of expanded object associated to Current.
371 local
372 gen_type: GEN_TYPE_I
373 written_class: CLASS_C
374 class_type, written_type: CLASS_TYPE
375 creation_feature: FEATURE_I
376 c_name: STRING
377 buffer: GENERATION_BUFFER
378 do
379 buffer := byte_code.buffer
380
381 gen_type ?= Current
382
383 if gen_type /= Void then
384 byte_code.generate_block_open
385 byte_code.generate_gen_type_conversion (gen_type)
386 end
387 reg.print_register
388 if workbench_mode then
389 -- RTLX is a macro used to create
390 -- expanded types
391 if gen_type /= Void then
392 buffer.putstring (" = RTLX(typres")
393 else
394 buffer.putstring (" = RTLX(RTUD(")
395 buffer.generate_type_id (associated_class_type.static_type_id)
396 buffer.putchar (')')
397 end
398 else
399 if gen_type /= Void then
400 buffer.putstring (" = RTLN(typres")
401 else
402 buffer.putstring (" = RTLN(")
403 buffer.putint (type_id - 1)
404 end
405 class_type := associated_class_type
406 creation_feature := class_type.associated_class.creation_feature
407 if creation_feature /= Void then
408 written_class := System.class_of_id (creation_feature.written_in)
409 if written_class.generics = Void then
410 written_type := written_class.types.first
411 else
412 written_type :=
413 written_class.meta_type (class_type.type).associated_class_type
414 end
415 c_name := Encoder.feature_name (written_type.static_type_id,
416 creation_feature.body_index)
417 buffer.putstring (");")
418 buffer.new_line
419 buffer.putstring (c_name)
420 buffer.putchar ('(')
421 reg.print_register
422 Extern_declarations.add_routine_with_signature (Void_c_type,
423 c_name, <<"EIF_REFERENCE">>)
424 end
425 end
426 buffer.putchar (')')
427 buffer.putchar (';')
428
429 if gen_type /= Void then
430 byte_code.generate_block_close
431 end
432 buffer.new_line
433 end
434
435 generate_cecil_value (buffer: GENERATION_BUFFER) is
436 -- Generate cecil value
437 do
438 -- FIXME????: separate
439 if not is_true_expanded then
440 buffer.putstring ("SK_DTYPE")
441 else
442 buffer.putstring ("SK_EXP + (uint32) ")
443 buffer.putint (associated_class_type.type_id - 1)
444 end
445 end
446
447 feature -- Array optimization
448
449 conforms_to_array: BOOLEAN is
450 do
451 Result := base_class.conform_to (array_class_c)
452 end
453
454 feature {NONE} -- Array optimization
455
456 array_class_c: CLASS_C is
457 once
458 Result := System.array_class.compiled_class
459 end
460
461 feature -- Generic conformance
462
463 generated_id (final_mode : BOOLEAN) : INTEGER is
464
465 do
466 if final_mode then
467 Result := type_id - 1
468 else
469 Result := associated_class_type.static_type_id-1
470 end
471
472 if is_true_expanded then
473 Result := Expanded_level - Result
474 end
475 end
476
477 generate_cid (buffer : GENERATION_BUFFER; final_mode, use_info : BOOLEAN) is
478
479 do
480 if
481 use_info and then (cr_info /= Void)
482 and then not is_expanded
483 then
484 -- It's an anchored type
485 cr_info.generate_cid (buffer, final_mode)
486 else
487 buffer.putint (generated_id (final_mode))
488 buffer.putstring (", ")
489 end
490 end
491
492 make_gen_type_byte_code (ba : BYTE_ARRAY; use_info : BOOLEAN) is
493 do
494 if
495 use_info and then (cr_info /= Void)
496 and then not is_expanded
497 then
498 -- It's an anchored type
499 cr_info.make_gen_type_byte_code (ba)
500 else
501 ba.append_short_integer (generated_id (False))
502 end
503 end
504
505 generate_cid_array (buffer : GENERATION_BUFFER;
506 final_mode, use_info : BOOLEAN; idx_cnt : COUNTER) is
507 local
508 dummy : INTEGER
509 do
510 if
511 use_info and then (cr_info /= Void)
512 and then not is_expanded
513 then
514 -- It's an anchored type
515 cr_info.generate_cid_array (buffer, final_mode, idx_cnt)
516 else
517 buffer.putint (generated_id (final_mode))
518 buffer.putstring (", ")
519
520 -- Increment counter
521 dummy := idx_cnt.next
522 end
523 end
524
525 generate_cid_init (buffer : GENERATION_BUFFER;
526 final_mode, use_info : BOOLEAN; idx_cnt : COUNTER) is
527 local
528 dummy : INTEGER
529 do
530 if
531 use_info and then (cr_info /= Void)
532 and then not is_expanded
533 then
534 -- It's an anchored type
535 cr_info.generate_cid_init (buffer, final_mode, idx_cnt)
536 else
537 dummy := idx_cnt.next
538 end
539 end
540
541 feature -- Generic conformance for IL
542
543 generate_gen_type_il (il_generator: IL_CODE_GENERATOR; use_info : BOOLEAN) is
544 -- `use_info' is true iff we generate code for a
545 -- creation instruction.
546 do
547 if use_info and then cr_info /= Void then
548 -- It's an anchored type, we call feature
549 -- that will tell us the real type of the
550 -- anchor in the context of Current.
551 cr_info.generate_il_type
552 else
553 il_generator.generate_class_type_instance (Current)
554 end
555 end
556
557 feature -- Output
558
559 debug_output: STRING is
560 -- String that should be displayed in debugger to represent `Current'.
561 do
562 create Result.make (32)
563 if is_true_expanded then
564 Result.append ("expanded ")
565 elseif is_separate then
566 Result.append ("separate ")
567 end
568 Result.append (base_class.name_in_upper)
569 end
570
571 feature {NONE} -- Implementation
572
573 internal_il_type_name (a_base_name, a_prefix: STRING): STRING is
574 -- Full type name of `a_base_name' using `a_prefix' in IL code generation
575 -- with namespace specification
576 require
577 a_base_name_not_void: a_base_name /= Void
578 local
579 l_name: STRING
580 do
581 Result := a_base_name
582 l_name := base_class.lace_class.actual_namespace
583 if a_prefix /= Void then
584 if l_name.is_empty then
585 l_name := a_prefix + "."
586 else
587 l_name := il_casing.namespace_casing (System.dotnet_naming_convention,
588 l_name) + "." + a_prefix + "."
589 end
590 else
591 if not l_name.is_empty then
592 l_name := il_casing.namespace_casing (System.dotnet_naming_convention,
593 l_name) + "."
594 end
595 end
596 Result := l_name + il_casing.pascal_casing (System.dotnet_naming_convention,
597 Result, feature {IL_CASING_CONVERSION}.upper_case)
598 ensure
599 internal_il_type_name_not_void: Result /= Void
600 internal_il_type_name_not_empty: not Result.is_empty
601 end
602
603 end

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.23