1292:-> 9A <offlow><offhigh><seglow><seghigh> with <seglow><seghigh> normally being defined as an address that must be fixed up at load time depending on the address where the code has been placed. 2. The Geos linker turns this into something else: INT 8xh -> CD 8x DB <seghigh>,<offlow>,<offhigh> Note that this is again five bytes, so it can be fixed up "in place". Now the problem is that an interrupt requires two bytes, while a CALL FAR instruction only needs one. As a result, the 32-bit vector (<seg><ofs>) must be compressed into 24 bits. This is achieved by two things: First, the <seg> address is encoded as a "handle" to the segment, whose lowest
1297:
up the absolute address of the segment, and forward the call, after having done its virtual memory loading thing... Return from the call will also pass through the corresponding unlocking code. The low nibble of the interrupt vector (80h–8Fh) holds bit 4 through 7 of the segment handle. Bit 0 to 3 of a segment handle are (by definition of a Geos handle) always 0. all Geos API run through the "overlay" scheme : when a Geos application is loaded into memory, the loader will automatically replace calls to functions in the system libraries by the corresponding INT-based calls. Anyway, these are not constant, but depend on the handle assigned to the library's code segment. Geos was originally intended to be converted to
499:
method selector. When the method call site is reached during execution, it just calls the address in the cache. (In a dynamic code generator, this call is a direct call as the direct address is back patched by cache miss logic.) Prologue code in the called method then compares the cached class with the actual object class, and if they don't match, execution branches to a cache miss handler to find the correct method in the class. A fast implementation may have multiple cache entries and it often only takes a couple of instructions to get execution to the correct method on an initial cache miss. The common case will be a cached class match, and execution will just continue in the method.
1333:
and then switch to the different interrupt handlers internally. For example: 1234h:0000h 1233h:0010h 1232h:0020h 1231h:0030h 1230h:0040h all point to exactly the same entry point. If you hook INT 21h onto 1234h:0000h and INT 2Fh onto 1233h:0010h, and so on, they would all go through the same "loophole", but you would still be able to distinguish between them and branch into the different handlers internally. Think of a "compressed" entry point into a
548:
424:(vtable) that defines the name-to-implementation mapping for a given class as a set of member function pointers. This is purely an implementation detail, as the C++ specification does not mention vtables. Instances of that type will then store a pointer to this table as part of their instance data, complicating scenarios when
1332:
in case of such mangled pointers many years ago Axel and I were thinking about a way how to use *one* entry point into a driver for multiple interrupt vectors (as this would save us a lot of space for the multiple entry points and the more or less identical startup/exit framing code in all of them),
1152:
Trait objects perform dynamic dispatch When we use trait objects, Rust must use dynamic dispatch. The compiler doesn't know all the types that might be used with the code that's using trait objects, so it doesn't know which method implemented on which type to call. Instead, at runtime, Rust uses the
498:
that makes method dispatch very fast. Inline caching basically stores the previous destination method address and object class of the call site (or multiple pairs for multi-way caching). The cached method is initialized with the most common target method (or just the cache miss handler), based on the
1296:
is always zero. This saves four bits. In addition the remaining four bits go into the low nibble of the interrupt vector, thus creating anything from INT 80h to 8Fh. The interrupt handler for all those vectors is the same. It will "unpack" the address from the three-and-a-half byte notation, look
456:
This decouples the supported interfaces from the underlying data structures. Each compiled library needn't know the full range of interfaces supported in order to correctly use a type, just the specific vtable layout that they require. Code can pass around different interfaces to the same piece of
1274:
needs 16 interrupts is because the scheme is used to convert inter-segment ("far") function calls into interrupts, without changing the size of the code. The reason this is done so that "something" (the kernel) can hook itself into every inter-segment call made by a Geos application and make sure
394:
Normally, in a typed language, the dispatch mechanism will be performed based on the type of the arguments (most commonly based on the type of the receiver of a message). Languages with weak or no typing systems often carry a dispatch table as part of the object data for each object. This allows
236:
associates a name with an operation. A polymorphic operation has several implementations, all associated with the same name. Bindings can be made at compile time or (with late binding) at run time. With dynamic dispatch, one particular implementation of an operation is chosen at run time. While
179:
Object-oriented systems model a problem as a set of interacting objects that enact operations referred to by name. Polymorphism is the phenomenon wherein somewhat interchangeable objects each expose an operation of the same name but possibly differing in behavior. As an example, a
486:
Smalltalk uses a type-based message dispatcher. Each instance has a single type whose definition contains the methods. When an instance receives a message, the dispatcher looks up the corresponding method in the message-to-method map for the type and then invokes the method.
490:
Because a type can have a chain of base types, this look-up can be expensive. A naive implementation of
Smalltalk's mechanism would seem to have a significantly higher overhead than that of C++ and this overhead would be incurred for every message that an object receives.
1153:
pointers inside the trait object to know which method to call. This lookup incurs a runtime cost that doesn't occur with static dispatch. Dynamic dispatch also prevents the compiler from choosing to inline a method's code, which in turn prevents some optimizations.
390:
A language may be implemented with different dynamic dispatch mechanisms. The choices of the dynamic dispatch mechanism offered by a language to a large extent alter the programming paradigms that are available or are most natural to use within a given language.
506:
As
Smalltalk is a reflective language, many implementations allow mutating individual objects into objects with dynamically generated method lookup tables. This allows altering object behavior on a per object basis. A whole category of languages known as
432:
Type overloading does not produce dynamic dispatch in C++ as the language considers the types of the message parameters part of the formal message name. This means that the message name the programmer sees is not the formal name used for binding.
1349:), which consumes much more memory if you hook many interrupts. We came to the result that this would most probably not be save in practise because you never know if other drivers normalize or denormalize pointers, for what reasons ever.
502:
Out-of-line caching can also be used in the method invocation logic, using the object class and method selector. In one design, the class and method selector are hashed, and used as an index into a method dispatch cache table.
1287:
loader, but one that can be added without requiring explicit support from the compiler or the application. What happens is something like this: 1. The real mode compiler generates an instruction like this: CALL
428:
is used. Since C++ does not support late binding, the virtual table in a C++ object cannot be modified at runtime, which limits the potential set of dispatch targets to a finite set chosen at compile time.
468:
with additional associated information. The additional information may be a vtable pointer for dynamic dispatch described above, but is more commonly the associated object's size to describe e.g. a
1371:
processors, containing both a deliberately denormalized pointer to a shared code entry point and some info to still distinguish the different callers in the shared code. While, in an
457:
data to different functions. This versatility comes at the expense of extra data with each object reference, which is problematic if many such references are stored persistently.
212:
message to an object of unknown type, leaving it to the run-time support system to dispatch the message to the right object. The object enacts whichever behavior it implements.
453:, a more versatile variation of early binding is used. Vtable pointers are carried with object references as 'fat pointers' ('interfaces' in Go, or 'trait objects' in Rust).
1341:
loading. This works as long as no program starts doing segment:offset magics. Contrast this with the opposite approach to have multiple entry points (maybe even supporting
413:
C++ uses early binding and offers both dynamic and static dispatch. The default form of dispatch is static. To get dynamic dispatch the programmer must declare a method as
237:
dynamic dispatch does not imply late binding, late binding does imply dynamic dispatch, since the implementation of a late-bound operation is not known until run time.
225:. The purpose of dynamic dispatch is to defer the selection of an appropriate implementation until the run time type of a parameter (or multiple parameters) is known.
1258:
192:
method that can be used to write a personnel record to storage. Their implementations differ. A program holds a reference to an object which may be either a
1409:
200:
object. Which it is may have been determined by a run-time setting, and at this stage, the program may not know or care which. When the program calls
251:
The choice of which version of a method to call may be based either on a single object, or on a combination of objects. The former is called
1320:
1397:
354:
By contrast, some languages dispatch methods or functions based on the combination of operands; in the division case, the types of the
1447:
519:. Careful design of the method dispatch caching allows even prototype-based languages to have high-performance method dispatch.
1452:
139:
1423:
1145:
169:
1235:
1116:
1246:
1364:
1289:
161:
31:
1375:, pointer-normalizing 3rd-party instances (in other drivers or applications) cannot be ruled out completely on
1346:
465:
405:
Dynamic dispatch will always incur an overhead so some languages offer static dispatch for particular methods.
268:
19:
This article is about the selection of an implementation of a polymorphic operation. For dynamic binding, see
535:
523:
284:
165:
379:
375:
276:
527:
512:
508:
446:
264:
173:
450:
132:
1019:
442:
1200:
1099:
1091:
ECOOP’95 — Object-Oriented
Programming, 9th European Conference, Åarhus, Denmark, August 7–11, 1995
1074:
1372:
1312:
61:
1379:, the scheme can be used safely on internal interfaces to avoid redundant entry code sequences.)
1195:
1094:
1069:
288:
1166:
204:
on the object, something needs to choose which behavior gets enacted. If one thinks of OOP as
1284:
1137:
125:
1089:
Driesen, Karel; Hölzle, Urs; Vitek, Jan (1995). "Message
Dispatch on Pipelined Processors".
1024:
425:
421:
344:
52:
47:
1387:
8:
75:
38:
1305:
only being a "legacy option" almost every single line of assembly code is ready for it
1219:
113:
1254:
1231:
1141:
1112:
1034:
246:
108:
1132:
Klabnik, Steve; Nichols, Carol (2023) . "17. Object-oriented programming features".
1415:
1376:
1338:
1250:
1104:
336:
153:
93:
70:
420:
C++ compilers typically implement dynamic dispatch with a data structure called a
1245:
Groeber, Marcus; Di
Geronimo, Jr., Edward "Ed"; Paul, Matthias R. (2002-03-02) .
1039:
1029:
319:
where the parameters are optional. This is thought of as sending a message named
217:
205:
103:
1298:
1276:
1227:
495:
340:
1441:
1383:
1108:
476:
1392:
1068:(Technical report). Vol. TR-CS-94-02. Australian National University.
1044:
233:
229:
222:
20:
16:
Selecting which implementation of a method or function to call at run time
1353:
531:
371:
272:
221:, in which the implementation of a polymorphic operation is selected at
172:. It is commonly employed in, and considered a prime characteristic of,
516:
280:
255:
and is directly supported by common object-oriented languages such as
1361:
1302:
256:
84:
1334:
1271:
547:
1293:
1192:
Message
Dispatch in Dynamically-Typed Object-Oriented Languages
399:
as each instance may map a given message to a separate method.
1093:. Lecture Notes in Computer Science. Vol. 952. Springer.
494:
Real
Smalltalk implementations often use a technique known as
1357:
260:
903:// speak() will be able to accept anything deriving from Pet
287:. In these and similar languages, one may call a method for
1244:
1194:(Master thesis). University of New Mexico. pp. 16–17.
370:. Examples of languages that support multiple dispatch are
1368:
1342:
1280:
1082:
1313:"Re: [fd-dev] ANNOUNCE: CuteMouse 2.0 alpha 1"
160:
is the process of selecting which implementation of a
208:
to objects, then in this example the program sends a
1125:
1088:
1057:
522:Many other dynamically typed languages, including
511:has grown from this, the most famous of which are
436:
331:. An implementation will be chosen based only on
1439:
240:
1275:that the proper code segments are loaded from
1136:(2 ed.). San Francisco, California, USA:
1131:
385:
366:operation will be performed. This is known as
1066:Dynamic Dispatch in Object-Oriented Languages
1063:
645:# pet can either be an instance of Cat or Dog
133:
1183:
481:
723:// make Pet an abstract virtual base class
140:
126:
1199:
1098:
1073:
1064:Milton, Scott; Schmidt, Heinz W. (1994).
642:# Dynamically dispatches the speak method
402:Some languages offer a hybrid approach.
1218:
1440:
1413:
1382:
1283:terms, this would be comparable to an
1189:
408:
347:), disregarding the type or value of
1310:
541:
228:Dynamic dispatch is different from
13:
1212:
14:
1464:
710:
232:(also known as dynamic binding).
1311:Paul, Matthias R. (2002-04-11).
546:
215:Dynamic dispatch contrasts with
1448:Polymorphism (computer science)
1426:from the original on 2022-07-11
1400:from the original on 2022-06-08
1323:from the original on 2020-02-21
1261:from the original on 2019-04-20
437:Go, Rust and Nim implementation
1290:<segment>:<offset>
1159:
1:
1453:Method (computer programming)
1134:The Rust Programming Language
1050:
176:(OOP) languages and systems.
241:Single and multiple dispatch
7:
1352:(NB. Something similar to "
1247:"GEOS/NDO info for RBIL62?"
1224:Inside the C++ Object Model
1013:
386:Dynamic dispatch mechanisms
291:with syntax that resembles
174:object-oriented programming
99:Single and dynamic dispatch
10:
1469:
1347:Interrupt Sharing Protocol
474:
244:
18:
1365:segment:offset addressing
1020:Function multi-versioning
509:prototype-based languages
362:together determine which
1109:10.1007/3-540-49538-X_13
714:
552:
538:use similar approaches.
482:Smalltalk implementation
293:
168:or function) to call at
1416:"A Fat Pointer Library"
1414:Holden, Daniel (2015).
1255:comp.os.geos.programmer
1190:MĂĽller, Martin (1995).
62:Parametric polymorphism
422:virtual function table
1388:"C's Biggest Mistake"
1301:very early on , with
1138:No Starch Press, Inc.
1279:and locked down. In
1156:(xxix+1+527+3 pages)
1025:Function overloading
426:multiple inheritance
314:# dividend / divisor
53:Operator overloading
48:Function overloading
1420:Cello: High Level C
1356:" specifically for
1220:Lippman, Stanley B.
1140:pp. 375–396 .
464:simply refers to a
188:object both have a
76:Generic programming
39:Ad hoc polymorphism
1171:The Rust Reference
409:C++ implementation
397:instance behaviour
114:Predicate dispatch
1377:public interfaces
1147:978-1-7185-0310-6
1035:Method overriding
542:Example in Python
368:multiple dispatch
335:'s type (perhaps
247:Multiple dispatch
150:
149:
109:Multiple dispatch
1460:
1434:
1432:
1431:
1408:
1406:
1405:
1351:
1329:
1328:
1307:
1267:
1266:
1241:
1206:
1205:
1203:
1187:
1181:
1180:
1178:
1177:
1163:
1157:
1155:
1129:
1123:
1122:
1102:
1086:
1080:
1079:
1077:
1061:
1009:
1006:
1003:
1000:
997:
994:
991:
988:
985:
982:
979:
976:
973:
970:
967:
964:
961:
958:
955:
952:
949:
946:
943:
940:
937:
934:
931:
928:
925:
922:
919:
916:
913:
910:
907:
904:
901:
898:
895:
892:
889:
886:
883:
880:
877:
874:
871:
868:
865:
862:
859:
856:
853:
850:
847:
844:
841:
838:
835:
832:
829:
826:
823:
820:
817:
814:
811:
808:
805:
802:
799:
796:
793:
790:
787:
784:
781:
778:
775:
772:
769:
766:
763:
760:
757:
754:
751:
748:
745:
742:
739:
736:
733:
730:
727:
724:
721:
720:<iostream>
718:
706:
703:
700:
697:
694:
691:
688:
685:
682:
679:
676:
673:
670:
667:
664:
661:
658:
655:
652:
649:
646:
643:
640:
637:
634:
631:
628:
625:
622:
621:"Woof"
619:
616:
613:
610:
607:
604:
601:
598:
595:
592:
589:
586:
585:"Meow"
583:
580:
577:
574:
571:
568:
565:
562:
559:
556:
550:
416:
365:
361:
357:
350:
334:
330:
326:
322:
315:
312:
309:
306:
303:
300:
297:
211:
206:sending messages
203:
199:
195:
191:
187:
183:
158:dynamic dispatch
154:computer science
142:
135:
128:
94:Virtual function
71:Generic function
28:
27:
1468:
1467:
1463:
1462:
1461:
1459:
1458:
1457:
1438:
1437:
1429:
1427:
1403:
1401:
1326:
1324:
1264:
1262:
1238:
1215:
1213:Further reading
1210:
1209:
1188:
1184:
1175:
1173:
1167:"Trait objects"
1165:
1164:
1160:
1150:. p. 384:
1148:
1130:
1126:
1119:
1087:
1083:
1062:
1058:
1053:
1040:Double dispatch
1030:Message passing
1016:
1011:
1010:
1007:
1004:
1001:
998:
995:
992:
989:
986:
983:
980:
977:
974:
971:
968:
965:
962:
959:
956:
953:
950:
947:
944:
941:
938:
935:
932:
929:
926:
923:
920:
917:
914:
911:
908:
905:
902:
899:
896:
893:
890:
887:
884:
881:
878:
875:
872:
869:
866:
863:
860:
857:
854:
851:
848:
845:
842:
839:
836:
833:
830:
827:
824:
821:
818:
815:
812:
809:
806:
803:
800:
797:
794:
791:
788:
785:
782:
779:
776:
773:
770:
767:
764:
761:
758:
755:
752:
749:
746:
743:
740:
737:
734:
731:
728:
725:
722:
719:
716:
713:
708:
707:
704:
701:
698:
695:
692:
689:
686:
683:
680:
677:
674:
671:
668:
665:
662:
659:
656:
653:
650:
647:
644:
641:
638:
635:
632:
629:
626:
623:
620:
617:
614:
611:
608:
605:
602:
599:
596:
593:
590:
587:
584:
581:
578:
575:
572:
569:
566:
563:
560:
557:
554:
544:
484:
479:
439:
414:
411:
388:
363:
359:
355:
348:
332:
328:
324:
323:with parameter
320:
317:
316:
313:
310:
307:
304:
301:
298:
295:
253:single dispatch
249:
243:
218:static dispatch
209:
201:
197:
193:
189:
185:
181:
146:
104:Double dispatch
24:
17:
12:
11:
5:
1466:
1456:
1455:
1450:
1436:
1435:
1411:
1386:(2009-12-22).
1384:Bright, Walter
1380:
1308:
1299:protected mode
1277:virtual memory
1242:
1236:
1228:Addison-Wesley
1214:
1211:
1208:
1207:
1201:10.1.1.55.1782
1182:
1158:
1146:
1124:
1117:
1100:10.1.1.122.281
1081:
1075:10.1.1.33.4292
1055:
1054:
1052:
1049:
1048:
1047:
1042:
1037:
1032:
1027:
1022:
1015:
1012:
715:
712:
711:Example in C++
709:
553:
543:
540:
496:inline caching
483:
480:
438:
435:
410:
407:
387:
384:
341:floating point
294:
245:Main article:
242:
239:
148:
147:
145:
144:
137:
130:
122:
119:
118:
117:
116:
111:
106:
101:
96:
88:
87:
81:
80:
79:
78:
73:
65:
64:
58:
57:
56:
55:
50:
42:
41:
35:
34:
15:
9:
6:
4:
3:
2:
1465:
1454:
1451:
1449:
1446:
1445:
1443:
1425:
1421:
1417:
1412:
1410:
1399:
1395:
1394:
1389:
1385:
1381:
1378:
1374:
1370:
1366:
1363:
1359:
1355:
1350:
1348:
1344:
1340:
1336:
1322:
1318:
1314:
1309:
1306:
1304:
1300:
1295:
1291:
1286:
1282:
1278:
1273:
1260:
1256:
1252:
1248:
1243:
1239:
1237:0-201-83454-5
1233:
1229:
1225:
1221:
1217:
1216:
1202:
1197:
1193:
1186:
1172:
1168:
1162:
1154:
1149:
1143:
1139:
1135:
1128:
1120:
1118:3-540-49538-X
1114:
1110:
1106:
1101:
1096:
1092:
1085:
1076:
1071:
1067:
1060:
1056:
1046:
1043:
1041:
1038:
1036:
1033:
1031:
1028:
1026:
1023:
1021:
1018:
1017:
551:
549:
539:
537:
533:
529:
525:
520:
518:
514:
510:
504:
500:
497:
492:
488:
478:
477:Smart pointer
473:
471:
467:
463:
458:
454:
452:
448:
444:
434:
430:
427:
423:
418:
406:
403:
400:
398:
392:
383:
381:
377:
373:
369:
352:
346:
342:
338:
292:
290:
286:
282:
278:
274:
270:
266:
262:
258:
254:
248:
238:
235:
231:
226:
224:
220:
219:
213:
207:
184:object and a
177:
175:
171:
167:
163:
159:
155:
143:
138:
136:
131:
129:
124:
123:
121:
120:
115:
112:
110:
107:
105:
102:
100:
97:
95:
92:
91:
90:
89:
86:
83:
82:
77:
74:
72:
69:
68:
67:
66:
63:
60:
59:
54:
51:
49:
46:
45:
44:
43:
40:
37:
36:
33:
30:
29:
26:
22:
1428:. Retrieved
1419:
1402:. Retrieved
1393:Digital Mars
1391:
1354:fat pointers
1331:
1325:. Retrieved
1316:
1269:
1263:. Retrieved
1223:
1191:
1185:
1174:. Retrieved
1170:
1161:
1151:
1133:
1127:
1090:
1084:
1065:
1059:
1045:Name binding
545:
521:
505:
501:
493:
489:
485:
469:
461:
459:
455:
440:
431:
419:
412:
404:
401:
396:
393:
389:
367:
353:
318:
252:
250:
234:Name binding
230:late binding
227:
223:compile time
216:
214:
196:object or a
178:
157:
151:
98:
32:Polymorphism
25:
21:Late binding
1373:open system
1317:freedos-dev
1270:The reason
885:"Meow!
816:"Woof!
532:Objective-C
462:fat pointer
372:Common Lisp
273:Objective-C
210:StoreRecord
202:StoreRecord
190:StoreRecord
164:operation (
162:polymorphic
1442:Categories
1430:2022-07-11
1404:2022-07-11
1327:2020-02-21
1265:2019-04-20
1176:2023-04-27
1051:References
517:JavaScript
475:See also:
281:JavaScript
1362:real-mode
1337:stub for
1303:real mode
1251:Newsgroup
1196:CiteSeerX
1095:CiteSeerX
1070:CiteSeerX
460:The term
257:Smalltalk
85:Subtyping
1424:Archived
1398:Archived
1321:Archived
1259:Archived
1222:(1996).
1014:See also
882:<<
867:override
813:<<
798:override
717:#include
356:dividend
337:rational
333:dividend
329:dividend
296:dividend
289:division
198:Database
186:Database
170:run time
1285:overlay
1253::
741:virtual
466:pointer
415:virtual
360:divisor
349:divisor
325:divisor
308:divisor
1294:nibble
1234:
1198:
1144:
1115:
1097:
1072:
999:return
891:"
852:public
843:public
822:"
783:public
774:public
735:public
536:Groovy
524:Python
378:, and
364:divide
345:matrix
321:divide
302:divide
285:Python
283:, and
166:method
1358:Intel
993:simba
987:speak
975:speak
969:simba
936:speak
918:&
909:speak
861:speak
834:class
792:speak
765:class
747:speak
726:class
696:speak
672:speak
654:speak
630:speak
615:print
603:speak
591:class
579:print
567:speak
555:class
470:slice
380:Julia
376:Dylan
277:Swift
1272:Geos
1232:ISBN
1142:ISBN
1113:ISBN
981:fido
960:fido
948:main
906:void
879:cout
858:void
810:cout
789:void
744:void
609:self
573:self
534:and
528:Ruby
515:and
513:Self
449:and
447:Rust
358:and
265:Java
194:File
182:File
1369:x86
1367:on
1360:'s
1345:'s
1343:IBM
1339:HMA
1335:A20
1281:DOS
1105:doi
966:Cat
957:Dog
945:int
939:();
930:pet
921:pet
915:Pet
873:std
846:Pet
837:Cat
804:std
777:Pet
768:Dog
729:Pet
702:dog
690:Dog
684:dog
678:cat
666:Cat
660:cat
648:pet
636:pet
627:def
600:def
594:Dog
564:def
558:Cat
451:Nim
441:In
327:to
261:C++
152:In
1444::
1422:.
1418:.
1396:.
1390:.
1330:.
1319:.
1315:.
1268:.
1257:.
1249:.
1230:.
1226:.
1169:.
1111:.
1103:.
996:);
984:);
951:()
900:};
888:\n
876:::
864:()
831:};
819:\n
807:::
795:()
762:};
750:()
693:()
669:()
657:()
639:):
612:):
576:):
530:,
526:,
472:.
445:,
443:Go
417:.
382:.
374:,
351:.
343:,
339:,
279:,
275:,
271:,
269:C#
267:,
263:,
259:,
156:,
1433:.
1407:.
1240:.
1204:.
1179:.
1121:.
1107::
1078:.
1008:}
1005:;
1002:0
990:(
978:(
972:;
963:;
954:{
942:}
933:.
927:{
924:)
912:(
897:}
894:;
870:{
855::
849:{
840::
828:}
825:;
801:{
786::
780:{
771::
759:;
756:0
753:=
738::
732:{
705:)
699:(
687:=
681:)
675:(
663:=
651:.
633:(
624:)
618:(
606:(
597::
588:)
582:(
570:(
561::
311:)
305:(
299:.
141:e
134:t
127:v
23:.
Text is available under the Creative Commons Attribution-ShareAlike License. Additional terms may apply.