OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [ada/] [s-finimp.adb] - Blame information for rev 281

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 281 jeremybenn
------------------------------------------------------------------------------
2
--                                                                          --
3
--                         GNAT RUN-TIME COMPONENTS                         --
4
--                                                                          --
5
--    S Y S T E M . F I N A L I Z A T I O N _ I M P L E M E N T A T I O N   --
6
--                                                                          --
7
--                                 B o d y                                  --
8
--                                                                          --
9
--          Copyright (C) 1992-2009, Free Software Foundation, Inc.         --
10
--                                                                          --
11
-- GNAT is free software;  you can  redistribute it  and/or modify it under --
12
-- terms of the  GNU General Public License as published  by the Free Soft- --
13
-- ware  Foundation;  either version 3,  or (at your option) any later ver- --
14
-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
15
-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
16
-- or FITNESS FOR A PARTICULAR PURPOSE.                                     --
17
--                                                                          --
18
-- As a special exception under Section 7 of GPL version 3, you are granted --
19
-- additional permissions described in the GCC Runtime Library Exception,   --
20
-- version 3.1, as published by the Free Software Foundation.               --
21
--                                                                          --
22
-- You should have received a copy of the GNU General Public License and    --
23
-- a copy of the GCC Runtime Library Exception along with this program;     --
24
-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
25
-- <http://www.gnu.org/licenses/>.                                          --
26
--                                                                          --
27
-- GNAT was originally developed  by the GNAT team at  New York University. --
28
-- Extensive contributions were provided by Ada Core Technologies Inc.      --
29
--                                                                          --
30
------------------------------------------------------------------------------
31
 
32
with Ada.Exceptions;
33
with Ada.Tags;
34
 
35
with System.Soft_Links;
36
 
37
with System.Restrictions;
38
 
39
package body System.Finalization_Implementation is
40
 
41
   use Ada.Exceptions;
42
   use System.Finalization_Root;
43
 
44
   package SSL renames System.Soft_Links;
45
 
46
   use type SSE.Storage_Offset;
47
 
48
   -----------------------
49
   -- Local Subprograms --
50
   -----------------------
51
 
52
   type RC_Ptr is access all Record_Controller;
53
 
54
   function To_RC_Ptr is
55
     new Ada.Unchecked_Conversion (Address, RC_Ptr);
56
 
57
   procedure Raise_From_Controlled_Operation (X : Exception_Occurrence);
58
   pragma Import
59
     (Ada, Raise_From_Controlled_Operation,
60
      "ada__exceptions__raise_from_controlled_operation");
61
   pragma No_Return (Raise_From_Controlled_Operation);
62
   --  Raise Program_Error from an exception that occurred during an Adjust or
63
   --  Finalize operation. We use this rather kludgy Ada Import interface
64
   --  because this procedure is not available in the visible part of the
65
   --  Ada.Exceptions spec.
66
 
67
   procedure Raise_From_Finalize
68
     (L          : Finalizable_Ptr;
69
      From_Abort : Boolean;
70
      E_Occ      : Exception_Occurrence);
71
   --  Deal with an exception raised during finalization of a list. L is a
72
   --  pointer to the list of element not yet finalized. From_Abort is true
73
   --  if the finalization actions come from an abort rather than a normal
74
   --  exit. E_Occ represents the exception being raised.
75
 
76
   function RC_Offset (T : Ada.Tags.Tag) return SSE.Storage_Offset;
77
   pragma Import (Ada, RC_Offset, "ada__tags__get_rc_offset");
78
 
79
   function Parent_Size (Obj : Address; T : Ada.Tags.Tag)
80
     return SSE.Storage_Count;
81
   pragma Import (Ada, Parent_Size, "ada__tags__parent_size");
82
 
83
   function Get_Deep_Controller (Obj : System.Address) return RC_Ptr;
84
   --  Given the address (obj) of a tagged object, return a
85
   --  pointer to the record controller of this object.
86
 
87
   ------------
88
   -- Adjust --
89
   ------------
90
 
91
   overriding procedure Adjust (Object : in out Record_Controller) is
92
 
93
      First_Comp : Finalizable_Ptr;
94
      My_Offset  : constant SSE.Storage_Offset :=
95
                     Object.My_Address - Object'Address;
96
 
97
      procedure Ptr_Adjust (Ptr : in out Finalizable_Ptr);
98
      --  Subtract the offset to the pointer
99
 
100
      procedure Reverse_Adjust (P : Finalizable_Ptr);
101
      --  Adjust the components in the reverse order in which they are stored
102
      --  on the finalization list. (Adjust and Finalization are not done in
103
      --  the same order)
104
 
105
      ----------------
106
      -- Ptr_Adjust --
107
      ----------------
108
 
109
      procedure Ptr_Adjust (Ptr : in out Finalizable_Ptr) is
110
      begin
111
         if Ptr /= null then
112
            Ptr := To_Finalizable_Ptr (To_Addr (Ptr) - My_Offset);
113
         end if;
114
      end Ptr_Adjust;
115
 
116
      --------------------
117
      -- Reverse_Adjust --
118
      --------------------
119
 
120
      procedure Reverse_Adjust (P : Finalizable_Ptr) is
121
      begin
122
         if P /= null then
123
            Ptr_Adjust (P.Next);
124
            Reverse_Adjust (P.Next);
125
            Adjust (P.all);
126
            Object.F := P;   --  Successfully adjusted, so place in list
127
         end if;
128
      end Reverse_Adjust;
129
 
130
   --  Start of processing for Adjust
131
 
132
   begin
133
      --  Adjust the components and their finalization pointers next. We must
134
      --  protect against an exception in some call to Adjust, so we keep
135
      --  pointing to the list of successfully adjusted components, which can
136
      --  be finalized if an exception is raised.
137
 
138
      First_Comp := Object.F;
139
      Object.F := null;               --  nothing adjusted yet.
140
      Ptr_Adjust (First_Comp);        --  set address of first component.
141
      Reverse_Adjust (First_Comp);
142
 
143
      --  Then Adjust the controller itself
144
 
145
      Object.My_Address := Object'Address;
146
 
147
   exception
148
      when others =>
149
         --  Finalize those components that were successfully adjusted, and
150
         --  propagate exception. The object itself is not yet attached to
151
         --  global finalization list, so we cannot rely on the outer call to
152
         --  Clean to take care of these components.
153
 
154
         Finalize (Object);
155
         raise;
156
   end Adjust;
157
 
158
   --------------------------
159
   -- Attach_To_Final_List --
160
   --------------------------
161
 
162
   procedure Attach_To_Final_List
163
     (L       : in out Finalizable_Ptr;
164
      Obj     : in out Finalizable;
165
      Nb_Link : Short_Short_Integer)
166
   is
167
   begin
168
      --  Simple case: attachment to a one way list
169
 
170
      if Nb_Link = 1 then
171
         Obj.Next := L;
172
         L        := Obj'Unchecked_Access;
173
 
174
      --  Dynamically allocated objects: they are attached to a doubly linked
175
      --  list, so that an element can be finalized at any moment by means of
176
      --  an unchecked deallocation. Attachment is protected against
177
      --  multi-threaded access.
178
 
179
      elsif Nb_Link = 2 then
180
 
181
         --  Raise Program_Error if we're trying to allocate an object in a
182
         --  collection whose finalization has already started.
183
 
184
         if L = Collection_Finalization_Started then
185
            raise Program_Error with
186
              "allocation after collection finalization started";
187
         end if;
188
 
189
         Locked_Processing : begin
190
            SSL.Lock_Task.all;
191
            Obj.Next    := L.Next;
192
            Obj.Prev    := L.Next.Prev;
193
            L.Next.Prev := Obj'Unchecked_Access;
194
            L.Next      := Obj'Unchecked_Access;
195
            SSL.Unlock_Task.all;
196
 
197
         exception
198
            when others =>
199
               SSL.Unlock_Task.all;
200
               raise;
201
         end Locked_Processing;
202
 
203
      --  Attachment of arrays to the final list (used only for objects
204
      --  returned by function). Obj, in this case is the last element,
205
      --  but all other elements are already threaded after it. We just
206
      --  attach the rest of the final list at the end of the array list.
207
 
208
      elsif Nb_Link = 3 then
209
         declare
210
            P : Finalizable_Ptr := Obj'Unchecked_Access;
211
 
212
         begin
213
            while P.Next /= null loop
214
               P := P.Next;
215
            end loop;
216
 
217
            P.Next := L;
218
            L := Obj'Unchecked_Access;
219
         end;
220
 
221
      --  Make the object completely unattached (case of a library-level,
222
      --  Finalize_Storage_Only object).
223
 
224
      elsif Nb_Link = 4 then
225
         Obj.Prev := null;
226
         Obj.Next := null;
227
      end if;
228
   end Attach_To_Final_List;
229
 
230
   ---------------------
231
   -- Deep_Tag_Attach --
232
   ----------------------
233
 
234
   procedure Deep_Tag_Attach
235
     (L : in out SFR.Finalizable_Ptr;
236
      A : System.Address;
237
      B : Short_Short_Integer)
238
   is
239
      V          : constant SFR.Finalizable_Ptr := To_Finalizable_Ptr (A);
240
      Controller : constant RC_Ptr := Get_Deep_Controller (A);
241
 
242
   begin
243
      if Controller /= null then
244
         Attach_To_Final_List (L, Controller.all, B);
245
      end if;
246
 
247
      --  Is controlled
248
 
249
      if V.all in Finalizable then
250
         Attach_To_Final_List (L, V.all, B);
251
      end if;
252
   end Deep_Tag_Attach;
253
 
254
   -----------------------------
255
   -- Detach_From_Final_List --
256
   -----------------------------
257
 
258
   --  We know that the detach object is neither at the beginning nor at the
259
   --  end of the list, thanks to the dummy First and Last Elements, but the
260
   --  object may not be attached at all if it is Finalize_Storage_Only
261
 
262
   procedure Detach_From_Final_List (Obj : in out Finalizable) is
263
   begin
264
      --  When objects are not properly attached to a doubly linked list do
265
      --  not try to detach them. The only case where it can happen is when
266
      --  dealing with Finalize_Storage_Only objects which are not always
267
      --  attached to the finalization list.
268
 
269
      if Obj.Next /= null and then Obj.Prev /= null then
270
         SSL.Lock_Task.all;
271
         Obj.Next.Prev := Obj.Prev;
272
         Obj.Prev.Next := Obj.Next;
273
 
274
         --  Reset the pointers so that a new finalization of the same object
275
         --  has no effect on the finalization list.
276
 
277
         Obj.Next := null;
278
         Obj.Prev := null;
279
 
280
         SSL.Unlock_Task.all;
281
      end if;
282
 
283
   exception
284
      when others =>
285
         SSL.Unlock_Task.all;
286
         raise;
287
   end Detach_From_Final_List;
288
 
289
   --------------
290
   -- Finalize --
291
   --------------
292
 
293
   overriding procedure Finalize (Object : in out Limited_Record_Controller) is
294
   begin
295
      Finalize_List (Object.F);
296
   end Finalize;
297
 
298
   --------------------------
299
   -- Finalize_Global_List --
300
   --------------------------
301
 
302
   procedure Finalize_Global_List is
303
   begin
304
      --  There are three case here:
305
 
306
      --  a. the application uses tasks, in which case Finalize_Global_Tasks
307
      --     will defer abort.
308
 
309
      --  b. the application doesn't use tasks but uses other tasking
310
      --     constructs, such as ATCs and protected objects. In this case,
311
      --     the binder will call Finalize_Global_List instead of
312
      --     Finalize_Global_Tasks, letting abort undeferred, and leading
313
      --     to assertion failures in the GNULL
314
 
315
      --  c. the application doesn't use any tasking construct in which case
316
      --     deferring abort isn't necessary.
317
 
318
      --  Until another solution is found to deal with case b, we need to
319
      --  call abort_defer here to pass the checks, but we do not need to
320
      --  undefer abort, since Finalize_Global_List is the last procedure
321
      --  called before exiting the partition.
322
 
323
      SSL.Abort_Defer.all;
324
      Finalize_List (Global_Final_List);
325
   end Finalize_Global_List;
326
 
327
   -------------------
328
   -- Finalize_List --
329
   -------------------
330
 
331
   procedure Finalize_List (L : Finalizable_Ptr) is
332
      P : Finalizable_Ptr := L;
333
      Q : Finalizable_Ptr;
334
 
335
      type Fake_Exception_Occurence is record
336
         Id : Exception_Id;
337
      end record;
338
      type Ptr is access all Fake_Exception_Occurence;
339
 
340
      function To_Ptr is new
341
        Ada.Unchecked_Conversion (Exception_Occurrence_Access, Ptr);
342
 
343
      X :  Exception_Id := Null_Id;
344
 
345
   begin
346
      --  If abort is allowed, we get the current exception before starting
347
      --  to finalize in order to check if we are in the abort case if an
348
      --  exception is raised. When abort is not allowed, avoid accessing the
349
      --  current exception since this can be a pretty costly operation in
350
      --  programs using controlled types heavily.
351
 
352
      if System.Restrictions.Abort_Allowed then
353
         X := To_Ptr (SSL.Get_Current_Excep.all).Id;
354
      end if;
355
 
356
      while P /= null loop
357
         Q := P.Next;
358
         Finalize (P.all);
359
         P := Q;
360
      end loop;
361
 
362
   exception
363
      when E_Occ : others =>
364
         Raise_From_Finalize (
365
           Q,
366
           X = Standard'Abort_Signal'Identity,
367
           E_Occ);
368
   end Finalize_List;
369
 
370
   ------------------
371
   -- Finalize_One --
372
   ------------------
373
 
374
   procedure Finalize_One (Obj : in out  Finalizable) is
375
   begin
376
      Detach_From_Final_List (Obj);
377
      Finalize (Obj);
378
   exception
379
      when E_Occ : others => Raise_From_Finalize (null, False, E_Occ);
380
   end Finalize_One;
381
 
382
   -------------------------
383
   -- Get_Deep_Controller --
384
   -------------------------
385
 
386
   function Get_Deep_Controller (Obj : System.Address) return RC_Ptr is
387
      The_Tag : Ada.Tags.Tag := To_Finalizable_Ptr (Obj)'Tag;
388
      Offset  : SSE.Storage_Offset := RC_Offset (The_Tag);
389
 
390
   begin
391
      --  Fetch the controller from the Parent or above if necessary
392
      --  when there are no controller at this level.
393
 
394
      while Offset = -2 loop
395
         The_Tag := Ada.Tags.Parent_Tag (The_Tag);
396
         Offset  := RC_Offset (The_Tag);
397
      end loop;
398
 
399
      --  No Controlled component case
400
 
401
      if Offset = 0 then
402
         return null;
403
 
404
      --  The _controller Offset is known statically
405
 
406
      elsif Offset > 0 then
407
         return To_RC_Ptr (Obj + Offset);
408
 
409
      --  At this stage, we know that the controller is part of the
410
      --  ancestor corresponding to the tag "The_Tag" and that its parent
411
      --  is variable sized. We assume that the _controller is the first
412
      --  component right after the parent.
413
 
414
      --  ??? note that it may not be true if there are new discriminants
415
 
416
      else --  Offset = -1
417
 
418
         declare
419
            --  define a faked record controller to avoid generating
420
            --  unnecessary expanded code for controlled types
421
 
422
            type Faked_Record_Controller is record
423
               Tag, Prec, Next : Address;
424
            end record;
425
 
426
            --  Reconstruction of a type with characteristics
427
            --  comparable to the original type
428
 
429
            D : constant := SSE.Storage_Offset (Storage_Unit - 1);
430
 
431
            type Parent_Type is new SSE.Storage_Array
432
                   (1 .. (Parent_Size (Obj, The_Tag) + D) /
433
                            SSE.Storage_Offset (Storage_Unit));
434
            for Parent_Type'Alignment use Address'Alignment;
435
 
436
            type Faked_Type_Of_Obj is record
437
               Parent : Parent_Type;
438
               Controller : Faked_Record_Controller;
439
            end record;
440
 
441
            type Obj_Ptr is access all Faked_Type_Of_Obj;
442
            function To_Obj_Ptr is
443
              new Ada.Unchecked_Conversion (Address, Obj_Ptr);
444
 
445
         begin
446
            return To_RC_Ptr (To_Obj_Ptr (Obj).Controller'Address);
447
         end;
448
      end if;
449
   end Get_Deep_Controller;
450
 
451
   ----------------
452
   -- Initialize --
453
   ----------------
454
 
455
   overriding procedure Initialize
456
     (Object : in out Limited_Record_Controller)
457
   is
458
      pragma Warnings (Off, Object);
459
   begin
460
      null;
461
   end Initialize;
462
 
463
   overriding procedure Initialize (Object : in out Record_Controller) is
464
   begin
465
      Object.My_Address := Object'Address;
466
   end Initialize;
467
 
468
   ---------------------
469
   -- Move_Final_List --
470
   ---------------------
471
 
472
   procedure Move_Final_List
473
     (From : in out SFR.Finalizable_Ptr;
474
      To   : Finalizable_Ptr_Ptr)
475
   is
476
   begin
477
      --  This is currently called at the end of the return statement, and the
478
      --  caller does NOT defer aborts. We need to defer aborts to prevent
479
      --  mangling the finalization lists.
480
 
481
      SSL.Abort_Defer.all;
482
 
483
      --  Put the return statement's finalization list onto the caller's one,
484
      --  thus transferring responsibility for finalization of the return
485
      --  object to the caller.
486
 
487
      Attach_To_Final_List (To.all, From.all, Nb_Link => 3);
488
 
489
      --  Empty the return statement's finalization list, so that when the
490
      --  cleanup code executes, there will be nothing to finalize.
491
      From := null;
492
 
493
      SSL.Abort_Undefer.all;
494
   end Move_Final_List;
495
 
496
   -------------------------
497
   -- Raise_From_Finalize --
498
   -------------------------
499
 
500
   procedure Raise_From_Finalize
501
     (L          : Finalizable_Ptr;
502
      From_Abort : Boolean;
503
      E_Occ      : Exception_Occurrence)
504
   is
505
      P : Finalizable_Ptr := L;
506
      Q : Finalizable_Ptr;
507
 
508
   begin
509
      --  We already got an exception. We now finalize the remainder of
510
      --  the list, ignoring all further exceptions.
511
 
512
      while P /= null loop
513
         Q := P.Next;
514
 
515
         begin
516
            Finalize (P.all);
517
         exception
518
            when others => null;
519
         end;
520
 
521
         P := Q;
522
      end loop;
523
 
524
      if From_Abort then
525
         --  If finalization from an Abort, then nothing to do
526
 
527
         null;
528
 
529
      else
530
         --  Else raise Program_Error with an appropriate message
531
 
532
         Raise_From_Controlled_Operation (E_Occ);
533
      end if;
534
   end Raise_From_Finalize;
535
 
536
--  Initialization of package, set Adafinal soft link
537
 
538
begin
539
   SSL.Finalize_Global_List := Finalize_Global_List'Access;
540
end System.Finalization_Implementation;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.