869 ] |
869 ] |
870 ] |
870 ] |
871 ]. |
871 ]. |
872 |
872 |
873 selector == #to:do: ifTrue:[ |
873 selector == #to:do: ifTrue:[ |
874 (receiver isConstant |
874 okToInline := true. |
875 and:[receiver type == #Integer]) ifTrue:[ |
875 |
876 (arg1 isConstant |
876 (arg2 isBlock and:[arg2 numArgs == 1]) ifFalse:[ |
877 and:[arg1 type == #Integer]) ifTrue:[ |
877 okToInline := false. |
878 receiver value <= arg1 value ifTrue:[ |
878 ]. |
879 arg2 isBlock ifTrue:[ |
879 okToInline ifTrue:[ |
880 arg2 numArgs == 1 ifTrue:[ |
880 ^ self codeToDoOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler |
881 ^ self codeToDoOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler |
|
882 ] |
|
883 ]. |
|
884 ] |
|
885 ] |
|
886 ] |
881 ] |
887 ]. |
882 ]. |
888 |
883 |
889 isBuiltIn := aCompiler isBuiltIn2ArgSelector:selector forReceiver:receiver. |
884 isBuiltIn := aCompiler isBuiltIn2ArgSelector:selector forReceiver:receiver. |
|
885 ]. |
|
886 |
|
887 (nargs == 3) ifTrue:[ |
|
888 arg1 := argArray at:1. |
|
889 arg2 := argArray at:2. |
|
890 arg3 := argArray at:3. |
|
891 |
|
892 selector == #to:by:do: ifTrue:[ |
|
893 okToInline := true. |
|
894 |
|
895 (arg2 isConstant and:[arg2 type == #Integer]) ifFalse:[ |
|
896 "/ step must be a constant (need to know how to compare) |
|
897 okToInline := false. |
|
898 ]. |
|
899 (arg3 isBlock and:[arg3 numArgs == 1]) ifFalse:[ |
|
900 okToInline := false. |
|
901 ]. |
|
902 okToInline ifTrue:[ |
|
903 ^ self codeToByDoOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler |
|
904 ] |
|
905 ]. |
890 ]. |
906 ]. |
891 |
907 |
892 isBuiltIn ifFalse:[ |
908 isBuiltIn ifFalse:[ |
893 specialCode := aCompiler specialSendCodeFor:selector. |
909 specialCode := aCompiler specialSendCodeFor:selector. |
894 isSpecial := specialCode notNil. |
910 isSpecial := specialCode notNil. |
1405 ] |
1421 ] |
1406 |
1422 |
1407 "Modified: 27.5.1997 / 14:28:49 / cg" |
1423 "Modified: 27.5.1997 / 14:28:49 / cg" |
1408 ! |
1424 ! |
1409 |
1425 |
1410 codeToDoOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler |
1426 codeToByDoOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler |
1411 "generate code for n to:n do:[:unusedArg | ... ]" |
1427 "generate code for a to:b by:c do:[:arg | ... ]" |
1412 |
1428 |
1413 |pos pos2 start stop lateEval theBlock loopVarIndex| |
1429 |pos pos2 start stop step lateEval theBlock loopVarIndex |
1414 |
1430 stepVal stopVarIndex| |
1415 "/ NOTICE: could compile it as a timesRepeat, if |
1431 |
|
1432 "/ NOTICE: could compile it as a timesRepeat-like loop, if |
1416 "/ the loop-counter is not accessed within the loop-block. |
1433 "/ the loop-counter is not accessed within the loop-block. |
1417 "/ This generates somewhat (15%) faster code, but makes |
1434 "/ This generates somewhat (15%) faster code, but makes |
1418 "/ debugging somewhat difficult (no loop-value seen in debugger). |
1435 "/ debugging somewhat difficult (no loop-value seen in debugger). |
1419 |
1436 |
1420 start := receiver. |
1437 start := receiver. |
1421 stop := (argArray at:1). |
1438 stop := (argArray at:1). |
1422 stop isConstant ifFalse:[self halt:'should not happen']. |
1439 step := (argArray at:2). |
1423 (stop evaluate isMemberOf:SmallInteger) ifFalse:[self halt:'should not happen']. |
1440 |
|
1441 "/ stop isConstant ifFalse:[self halt:'should not happen']. |
|
1442 "/ (stop evaluate isMemberOf:SmallInteger) ifFalse:[self halt:'should not happen']. |
|
1443 |
|
1444 step isConstant ifFalse:[self halt:'should not happen']. |
|
1445 stepVal := step evaluate. |
|
1446 (stepVal isMemberOf:SmallInteger) ifFalse:[self halt:'should not happen']. |
1424 |
1447 |
1425 start codeOn:aStream inBlock:b for:aCompiler. |
1448 start codeOn:aStream inBlock:b for:aCompiler. |
1426 |
1449 |
1427 lateEval := false. |
1450 lateEval := false. |
1428 |
1451 |
1436 lateEval ifFalse:[ |
1459 lateEval ifFalse:[ |
1437 aStream nextPut:#dup |
1460 aStream nextPut:#dup |
1438 ]. |
1461 ]. |
1439 ]. |
1462 ]. |
1440 |
1463 |
|
1464 "/ if stop is not constant, and not an argVar, |
|
1465 "/ evaluate it into a temp slot ... |
|
1466 |
|
1467 (stop isConstant and:[stop type == #Integer]) ifFalse:[ |
|
1468 "/ a method/blockArg is constant as well ... |
|
1469 (stop isVariable and:[stop isArgument]) ifFalse:[ |
|
1470 stop codeOn:aStream inBlock:b for:aCompiler. |
|
1471 |
|
1472 b isNil ifTrue:[ |
|
1473 stopVarIndex := aCompiler addTempVar. |
|
1474 aStream nextPut:#storeMethodVar; nextPut:stopVarIndex. |
|
1475 ] ifFalse:[ |
|
1476 stopVarIndex := b addTempVar. |
|
1477 aStream nextPut:#storeBlockVar; nextPut:stopVarIndex. |
|
1478 ]. |
|
1479 ] |
|
1480 ]. |
|
1481 |
1441 pos := aStream position. |
1482 pos := aStream position. |
1442 |
1483 |
1443 aStream nextPut:#dup. |
1484 aStream nextPut:#dup. |
1444 stop codeOn:aStream inBlock:b for:aCompiler. |
1485 stopVarIndex notNil ifTrue:[ |
1445 aStream nextPut:#>. |
1486 b isNil ifTrue:[ |
|
1487 aStream nextPut:#pushMethodVar; nextPut:stopVarIndex. |
|
1488 ] ifFalse:[ |
|
1489 aStream nextPut:#pushBlockVar; nextPut:stopVarIndex. |
|
1490 ] |
|
1491 ] ifFalse:[ |
|
1492 stop codeOn:aStream inBlock:b for:aCompiler. |
|
1493 ]. |
|
1494 stepVal > 0 ifTrue:[ |
|
1495 aStream nextPut:#>. |
|
1496 ] ifFalse:[ |
|
1497 aStream nextPut:#<. |
|
1498 ]. |
1446 (aCompiler hasLineNumber:selector) ifTrue:[ |
1499 (aCompiler hasLineNumber:selector) ifTrue:[ |
1447 aStream nextPut:lineNr. |
1500 aStream nextPut:lineNr. |
1448 ]. |
1501 ]. |
1449 aStream nextPut:#trueJump. |
1502 aStream nextPut:#trueJump. |
1450 pos2 := aStream position. |
1503 pos2 := aStream position. |
1451 aStream nextPut:0. |
1504 aStream nextPut:0. |
1452 |
1505 |
1453 theBlock := argArray at:2. |
1506 theBlock := argArray at:3. |
1454 |
1507 |
1455 "/ need a temporary in the outer context for |
1508 "/ need a temporary in the outer context for |
1456 "/ the loop ... |
1509 "/ the loop ... |
1457 b isNil ifTrue:[ |
1510 b isNil ifTrue:[ |
1458 loopVarIndex := aCompiler addTempVar. |
1511 loopVarIndex := aCompiler addTempVar. |
1465 ]. |
1518 ]. |
1466 theBlock indexOfFirstTemp:loopVarIndex. |
1519 theBlock indexOfFirstTemp:loopVarIndex. |
1467 |
1520 |
1468 theBlock codeInlineOn:aStream inBlock:b valueNeeded:false for:aCompiler. |
1521 theBlock codeInlineOn:aStream inBlock:b valueNeeded:false for:aCompiler. |
1469 |
1522 |
1470 "/ increment counter & jump back. |
1523 "/ increment/decrement counter & jump back. |
1471 |
1524 |
1472 aStream nextPut:#plus1; nextPut:lineNr; nextPut:#jump; nextPut:pos. |
1525 stepVal == 1 ifTrue:[ |
|
1526 aStream nextPut:#plus1; nextPut:lineNr. |
|
1527 ] ifFalse:[ |
|
1528 stepVal == -1 ifTrue:[ |
|
1529 aStream nextPut:#minus1; nextPut:lineNr. |
|
1530 ] ifFalse:[ |
|
1531 step codeOn:aStream inBlock:b for:aCompiler. |
|
1532 aStream nextPut:#+. |
|
1533 (aCompiler hasLineNumber:#+) ifTrue:[ |
|
1534 aStream nextPut:lineNr. |
|
1535 ]. |
|
1536 ] |
|
1537 ]. |
|
1538 |
|
1539 aStream nextPut:#jump; nextPut:pos. |
1473 |
1540 |
1474 (aStream contents) at:pos2 put:(aStream position). |
1541 (aStream contents) at:pos2 put:(aStream position). |
1475 aStream nextPut:#drop. "/ drop run variable |
1542 aStream nextPut:#drop. "/ drop run variable |
1476 lateEval ifTrue:[ |
1543 lateEval ifTrue:[ |
1477 start codeOn:aStream inBlock:b for:aCompiler. |
1544 start codeOn:aStream inBlock:b for:aCompiler. |
1482 |
1549 |
1483 b isNil ifTrue:[ |
1550 b isNil ifTrue:[ |
1484 aCompiler removeTempVar |
1551 aCompiler removeTempVar |
1485 ] ifFalse:[ |
1552 ] ifFalse:[ |
1486 b removeTempVar |
1553 b removeTempVar |
1487 ] |
1554 ]. |
|
1555 |
|
1556 stopVarIndex notNil ifTrue:[ |
|
1557 b isNil ifTrue:[ |
|
1558 aCompiler removeTempVar |
|
1559 ] ifFalse:[ |
|
1560 b removeTempVar |
|
1561 ] |
|
1562 ]. |
|
1563 |
|
1564 "Created: 27.6.1997 / 12:48:18 / cg" |
|
1565 "Modified: 27.6.1997 / 13:43:06 / cg" |
|
1566 ! |
|
1567 |
|
1568 codeToDoOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler |
|
1569 "generate code for n to:n do:[:unusedArg | ... ]" |
|
1570 |
|
1571 |pos pos2 start stop lateEval theBlock loopVarIndex |
|
1572 stopVarIndex| |
|
1573 |
|
1574 "/ NOTICE: could compile it as a timesRepeat, if |
|
1575 "/ the loop-counter is not accessed within the loop-block. |
|
1576 "/ This generates somewhat (15%) faster code, but makes |
|
1577 "/ debugging somewhat difficult (no loop-value seen in debugger). |
|
1578 |
|
1579 start := receiver. |
|
1580 stop := (argArray at:1). |
|
1581 "/ stop isConstant ifFalse:[self halt:'should not happen']. |
|
1582 "/ (stop evaluate isMemberOf:SmallInteger) ifFalse:[self halt:'should not happen']. |
|
1583 |
|
1584 start codeOn:aStream inBlock:b for:aCompiler. |
|
1585 |
|
1586 lateEval := false. |
|
1587 |
|
1588 valueNeeded ifTrue:[ |
|
1589 "/ easily reconstructable - no need to keep on stack |
|
1590 start isConstant ifTrue:[ |
|
1591 (start evaluate isMemberOf:SmallInteger) ifTrue:[ |
|
1592 lateEval := true. |
|
1593 ] |
|
1594 ]. |
|
1595 lateEval ifFalse:[ |
|
1596 aStream nextPut:#dup |
|
1597 ]. |
|
1598 ]. |
|
1599 |
|
1600 "/ if stop is not constant, and not an argVar, |
|
1601 "/ evaluate it into a temp slot ... |
|
1602 |
|
1603 (stop isConstant and:[stop type == #Integer]) ifFalse:[ |
|
1604 "/ a method/blockArg is constant as well ... |
|
1605 (stop isVariable and:[stop isArgument]) ifFalse:[ |
|
1606 stop codeOn:aStream inBlock:b for:aCompiler. |
|
1607 |
|
1608 b isNil ifTrue:[ |
|
1609 stopVarIndex := aCompiler addTempVar. |
|
1610 aStream nextPut:#storeMethodVar; nextPut:stopVarIndex. |
|
1611 ] ifFalse:[ |
|
1612 stopVarIndex := b addTempVar. |
|
1613 aStream nextPut:#storeBlockVar; nextPut:stopVarIndex. |
|
1614 ]. |
|
1615 ] |
|
1616 ]. |
|
1617 |
|
1618 pos := aStream position. |
|
1619 |
|
1620 aStream nextPut:#dup. |
|
1621 stopVarIndex notNil ifTrue:[ |
|
1622 b isNil ifTrue:[ |
|
1623 aStream nextPut:#pushMethodVar; nextPut:stopVarIndex. |
|
1624 ] ifFalse:[ |
|
1625 aStream nextPut:#pushBlockVar; nextPut:stopVarIndex. |
|
1626 ] |
|
1627 ] ifFalse:[ |
|
1628 stop codeOn:aStream inBlock:b for:aCompiler. |
|
1629 ]. |
|
1630 aStream nextPut:#>. |
|
1631 (aCompiler hasLineNumber:selector) ifTrue:[ |
|
1632 aStream nextPut:lineNr. |
|
1633 ]. |
|
1634 aStream nextPut:#trueJump. |
|
1635 pos2 := aStream position. |
|
1636 aStream nextPut:0. |
|
1637 |
|
1638 theBlock := argArray at:2. |
|
1639 |
|
1640 "/ need a temporary in the outer context for |
|
1641 "/ the loop ... |
|
1642 b isNil ifTrue:[ |
|
1643 loopVarIndex := aCompiler addTempVar. |
|
1644 aStream nextPut:#dup. |
|
1645 aStream nextPut:#storeMethodVar; nextPut:loopVarIndex. |
|
1646 ] ifFalse:[ |
|
1647 loopVarIndex := b addTempVar. |
|
1648 aStream nextPut:#dup. |
|
1649 aStream nextPut:#storeBlockVar; nextPut:loopVarIndex. |
|
1650 ]. |
|
1651 theBlock indexOfFirstTemp:loopVarIndex. |
|
1652 |
|
1653 theBlock codeInlineOn:aStream inBlock:b valueNeeded:false for:aCompiler. |
|
1654 |
|
1655 "/ increment counter & jump back. |
|
1656 |
|
1657 aStream nextPut:#plus1; nextPut:lineNr; nextPut:#jump; nextPut:pos. |
|
1658 |
|
1659 (aStream contents) at:pos2 put:(aStream position). |
|
1660 aStream nextPut:#drop. "/ drop run variable |
|
1661 lateEval ifTrue:[ |
|
1662 start codeOn:aStream inBlock:b for:aCompiler. |
|
1663 ]. |
|
1664 |
|
1665 "/ no need to nil-out loop-tempVar to help GC |
|
1666 "/ (its integer, anyway). |
|
1667 |
|
1668 b isNil ifTrue:[ |
|
1669 aCompiler removeTempVar |
|
1670 ] ifFalse:[ |
|
1671 b removeTempVar |
|
1672 ]. |
|
1673 |
|
1674 stopVarIndex notNil ifTrue:[ |
|
1675 b isNil ifTrue:[ |
|
1676 aCompiler removeTempVar |
|
1677 ] ifFalse:[ |
|
1678 b removeTempVar |
|
1679 ] |
|
1680 ]. |
1488 |
1681 |
1489 "Created: 26.6.1997 / 10:58:47 / cg" |
1682 "Created: 26.6.1997 / 10:58:47 / cg" |
1490 "Modified: 26.6.1997 / 11:04:05 / cg" |
1683 "Modified: 27.6.1997 / 13:21:54 / cg" |
1491 ! |
1684 ! |
1492 |
1685 |
1493 codeWhileOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler |
1686 codeWhileOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler |
1494 "generate code for |
1687 "generate code for |
1495 [...] whileXXX:[ ... ] |
1688 [...] whileXXX:[ ... ] |