@@ -110,6 +110,7 @@ export ty_fn_args;
110
110
export kind, kind_implicitly_copyable, kind_send_copy, kind_copyable;
111
111
export kind_noncopyable, kind_const;
112
112
export kind_can_be_copied, kind_can_be_sent, kind_can_be_implicitly_copied;
113
+ export kind_is_safe_for_default_mode;
113
114
export kind_is_owned;
114
115
export proto_kind, kind_lteq, type_kind;
115
116
export operators;
@@ -1371,19 +1372,22 @@ fn type_needs_unwind_cleanup_(cx: ctxt, ty: t,
1371
1372
enum kind { kind_( u32 ) }
1372
1373
1373
1374
/// can be copied (implicitly or explicitly)
1374
- const KIND_MASK_COPY : u32 = 0b00000000000000000000000000000001_u32 ;
1375
+ const KIND_MASK_COPY : u32 = 0b000000000000000000000000001_u32 ;
1375
1376
1376
1377
/// can be sent: no shared box, borrowed ptr (must imply OWNED)
1377
- const KIND_MASK_SEND : u32 = 0b00000000000000000000000000000010_u32 ;
1378
+ const KIND_MASK_SEND : u32 = 0b000000000000000000000000010_u32 ;
1378
1379
1379
1380
/// is owned (no borrowed ptrs)
1380
- const KIND_MASK_OWNED : u32 = 0b00000000000000000000000000000100_u32 ;
1381
+ const KIND_MASK_OWNED : u32 = 0b000000000000000000000000100_u32 ;
1381
1382
1382
1383
/// is deeply immutable
1383
- const KIND_MASK_CONST : u32 = 0b00000000000000000000000000001000_u32 ;
1384
+ const KIND_MASK_CONST : u32 = 0b000000000000000000000001000_u32 ;
1384
1385
1385
1386
/// can be implicitly copied (must imply COPY)
1386
- const KIND_MASK_IMPLICIT : u32 = 0b00000000000000000000000000010000_u32 ;
1387
+ const KIND_MASK_IMPLICIT : u32 = 0b000000000000000000000010000_u32 ;
1388
+
1389
+ /// safe for default mode (subset of KIND_MASK_IMPLICIT)
1390
+ const KIND_MASK_DEFAULT_MODE : u32 = 0b000000000000000000000100000_u32 ;
1387
1391
1388
1392
fn kind_noncopyable( ) -> kind {
1389
1393
kind_( 0u32 )
@@ -1397,10 +1401,22 @@ fn kind_implicitly_copyable() -> kind {
1397
1401
kind_( KIND_MASK_IMPLICIT | KIND_MASK_COPY )
1398
1402
}
1399
1403
1404
+ fn kind_safe_for_default_mode( ) -> kind {
1405
+ // similar to implicit copy, but always includes vectors and strings
1406
+ kind_( KIND_MASK_DEFAULT_MODE | KIND_MASK_IMPLICIT | KIND_MASK_COPY )
1407
+ }
1408
+
1400
1409
fn kind_implicitly_sendable( ) -> kind {
1401
1410
kind_( KIND_MASK_IMPLICIT | KIND_MASK_COPY | KIND_MASK_SEND )
1402
1411
}
1403
1412
1413
+ fn kind_safe_for_default_mode_send( ) -> kind {
1414
+ // similar to implicit copy, but always includes vectors and strings
1415
+ kind_( KIND_MASK_DEFAULT_MODE | KIND_MASK_IMPLICIT |
1416
+ KIND_MASK_COPY | KIND_MASK_SEND )
1417
+ }
1418
+
1419
+
1404
1420
fn kind_send_copy( ) -> kind {
1405
1421
kind_( KIND_MASK_COPY | KIND_MASK_SEND )
1406
1422
}
@@ -1426,7 +1442,7 @@ fn remove_const(k: kind) -> kind {
1426
1442
}
1427
1443
1428
1444
fn remove_implicit( k: kind) -> kind {
1429
- k - kind_( KIND_MASK_IMPLICIT )
1445
+ k - kind_( KIND_MASK_IMPLICIT | KIND_MASK_DEFAULT_MODE )
1430
1446
}
1431
1447
1432
1448
fn remove_send( k: kind) -> kind {
@@ -1462,6 +1478,10 @@ pure fn kind_can_be_implicitly_copied(k: kind) -> bool {
1462
1478
* k & KIND_MASK_IMPLICIT == KIND_MASK_IMPLICIT
1463
1479
}
1464
1480
1481
+ pure fn kind_is_safe_for_default_mode( k: kind) -> bool {
1482
+ * k & KIND_MASK_DEFAULT_MODE == KIND_MASK_DEFAULT_MODE
1483
+ }
1484
+
1465
1485
pure fn kind_can_be_copied( k: kind) -> bool {
1466
1486
* k & KIND_MASK_COPY == KIND_MASK_COPY
1467
1487
}
@@ -1478,9 +1498,9 @@ fn proto_kind(p: proto) -> kind {
1478
1498
alt p {
1479
1499
ast:: proto_any { kind_noncopyable( ) }
1480
1500
ast:: proto_block { kind_noncopyable( ) }
1481
- ast:: proto_box { kind_implicitly_copyable ( ) | kind_owned( ) }
1501
+ ast:: proto_box { kind_safe_for_default_mode ( ) | kind_owned( ) }
1482
1502
ast:: proto_uniq { kind_send_copy( ) | kind_owned( ) }
1483
- ast:: proto_bare { kind_implicitly_sendable ( ) | kind_const( ) |
1503
+ ast:: proto_bare { kind_safe_for_default_mode_send ( ) | kind_const( ) |
1484
1504
kind_owned( ) }
1485
1505
}
1486
1506
}
@@ -1539,11 +1559,11 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
1539
1559
// Insert a default in case we loop back on self recursively.
1540
1560
cx. kind_cache. insert( ty, kind_top( ) ) ;
1541
1561
1542
- let result = alt get( ty) . struct {
1562
+ let mut result = alt get( ty) . struct {
1543
1563
// Scalar and unique types are sendable, constant, and owned
1544
1564
ty_nil | ty_bot | ty_bool | ty_int( _) | ty_uint( _) | ty_float( _) |
1545
1565
ty_ptr( _) {
1546
- kind_implicitly_sendable ( ) | kind_const( ) | kind_owned( )
1566
+ kind_safe_for_default_mode_send ( ) | kind_const( ) | kind_owned( )
1547
1567
}
1548
1568
1549
1569
// Implicit copyability of strs is configurable
@@ -1561,14 +1581,14 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
1561
1581
// Those with refcounts raise noncopyable to copyable,
1562
1582
// lower sendable to copyable. Therefore just set result to copyable.
1563
1583
ty_box( tm) {
1564
- remove_send( mutable_type_kind( cx, tm) | kind_implicitly_copyable ( ) )
1584
+ remove_send( mutable_type_kind( cx, tm) | kind_safe_for_default_mode ( ) )
1565
1585
}
1566
1586
1567
1587
// Iface instances are (for now) like shared boxes, basically
1568
- ty_trait( _, _) { kind_implicitly_copyable ( ) | kind_owned( ) }
1588
+ ty_trait( _, _) { kind_safe_for_default_mode ( ) | kind_owned( ) }
1569
1589
1570
1590
// Region pointers are copyable but NOT owned nor sendable
1571
- ty_rptr( _, _) { kind_implicitly_copyable ( ) }
1591
+ ty_rptr( _, _) { kind_safe_for_default_mode ( ) }
1572
1592
1573
1593
// Unique boxes and vecs have the kind of their contained type,
1574
1594
// but unique boxes can't be implicitly copyable.
@@ -1587,10 +1607,10 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
1587
1607
// contained type, but aren't implicitly copyable. Fixed vectors have
1588
1608
// the kind of the element they contain, taking mutability into account.
1589
1609
ty_evec( tm, vstore_box) {
1590
- remove_send( kind_implicitly_copyable ( ) | mutable_type_kind( cx, tm) )
1610
+ remove_send( kind_safe_for_default_mode ( ) | mutable_type_kind( cx, tm) )
1591
1611
}
1592
1612
ty_evec( tm, vstore_slice( _) ) {
1593
- remove_owned_send( kind_implicitly_copyable ( ) |
1613
+ remove_owned_send( kind_safe_for_default_mode ( ) |
1594
1614
mutable_type_kind( cx, tm) )
1595
1615
}
1596
1616
ty_evec( tm, vstore_fixed( _) ) {
@@ -1599,13 +1619,13 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
1599
1619
1600
1620
// All estrs are copyable; uniques and interiors are sendable.
1601
1621
ty_estr( vstore_box) {
1602
- kind_implicitly_copyable ( ) | kind_const( ) | kind_owned( )
1622
+ kind_safe_for_default_mode ( ) | kind_const( ) | kind_owned( )
1603
1623
}
1604
1624
ty_estr( vstore_slice( _) ) {
1605
- kind_implicitly_copyable ( ) | kind_const( )
1625
+ kind_safe_for_default_mode ( ) | kind_const( )
1606
1626
}
1607
1627
ty_estr( vstore_fixed( _) ) {
1608
- kind_implicitly_sendable ( ) | kind_const( ) | kind_owned( )
1628
+ kind_safe_for_default_mode_send ( ) | kind_const( ) | kind_owned( )
1609
1629
}
1610
1630
1611
1631
// Records lower to the lowest of their members.
@@ -1676,10 +1696,77 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
1676
1696
}
1677
1697
} ;
1678
1698
1699
+ // arbitrary threshold to prevent by-value copying of big records
1700
+ if kind_is_safe_for_default_mode( result) {
1701
+ if type_size( cx, ty) > 4 {
1702
+ result -= kind_( KIND_MASK_DEFAULT_MODE ) ;
1703
+ }
1704
+ }
1705
+
1679
1706
cx. kind_cache. insert( ty, result) ;
1680
1707
ret result;
1681
1708
}
1682
1709
1710
+ /// gives a rough estimate of how much space it takes to represent
1711
+ /// an instance of `ty`. Used for the mode transition.
1712
+ fn type_size( cx: ctxt, ty: t) -> uint {
1713
+ alt get( ty) . struct {
1714
+ ty_nil | ty_bot | ty_bool | ty_int( _) | ty_uint( _) | ty_float( _) |
1715
+ ty_ptr( _) | ty_box( _) | ty_uniq( _) | ty_estr( vstore_uniq) |
1716
+ ty_trait( * ) | ty_rptr( * ) | ty_evec( _, vstore_uniq) |
1717
+ ty_evec( _, vstore_box) | ty_estr( vstore_box) => {
1718
+ 1
1719
+ }
1720
+
1721
+ ty_evec( _, vstore_slice( _) ) |
1722
+ ty_estr( vstore_slice( _) ) |
1723
+ ty_fn( _) => {
1724
+ 2
1725
+ }
1726
+
1727
+ ty_evec( t, vstore_fixed( n) ) => {
1728
+ type_size( cx, t. ty) * n
1729
+ }
1730
+
1731
+ ty_estr( vstore_fixed( n) ) => {
1732
+ n
1733
+ }
1734
+
1735
+ ty_rec( flds) => {
1736
+ flds. foldl( 0 , |s, f| s + type_size( cx, f. mt. ty) )
1737
+ }
1738
+
1739
+ ty_class( did, substs) {
1740
+ let flds = class_items_as_fields( cx, did, substs) ;
1741
+ flds. foldl( 0 , |s, f| s + type_size( cx, f. mt. ty) )
1742
+ }
1743
+
1744
+ ty_tup( tys) {
1745
+ tys. foldl( 0 , |s, t| s + type_size( cx, t) )
1746
+ }
1747
+
1748
+ ty_enum( did, substs) {
1749
+ let variants = substd_enum_variants( cx, did, substs) ;
1750
+ variants. foldl( // find max size of any variant
1751
+ 0 ,
1752
+ |m, v| uint:: max( m,
1753
+ // find size of this variant:
1754
+ v. args. foldl( 0 , |s, a| s + type_size( cx, a) ) ) )
1755
+ }
1756
+
1757
+ ty_param( _) | ty_self {
1758
+ 1
1759
+ }
1760
+
1761
+ ty_var( _) | ty_var_integral( _) {
1762
+ cx. sess. bug( ~"Asked to compute kind of a type variable") ;
1763
+ }
1764
+ ty_type | ty_opaque_closure_ptr( _) | ty_opaque_box | ty_unboxed_vec( _) {
1765
+ cx. sess. bug( ~"Asked to compute kind of fictitious type ") ;
1766
+ }
1767
+ }
1768
+ }
1769
+
1683
1770
// True if instantiating an instance of `r_ty` requires an instance of `r_ty`.
1684
1771
fn is_instantiable( cx: ctxt, r_ty: t) -> bool {
1685
1772
0 commit comments