Sfoglia il codice sorgente

Inlining more selectors

Nicolas Petton 11 anni fa
parent
commit
e819f7d4c2
8 ha cambiato i file con 1321 aggiunte e 626 eliminazioni
  1. 296 166
      js/Compiler-IR.deploy.js
  2. 303 173
      js/Compiler-IR.js
  3. 266 117
      js/Compiler-Inlining.deploy.js
  4. 319 120
      js/Compiler-Inlining.js
  5. 22 23
      js/boot.js
  6. 1 1
      js/init.js
  7. 10 0
      st/Compiler-IR.st
  8. 104 26
      st/Compiler-Inlining.st

File diff suppressed because it is too large
+ 296 - 166
js/Compiler-IR.deploy.js


File diff suppressed because it is too large
+ 303 - 173
js/Compiler-IR.js


+ 266 - 117
js/Compiler-Inlining.deploy.js

@@ -4,7 +4,7 @@ smalltalk.addMethod(
 "_accept_",
 smalltalk.method({
 selector: "accept:",
-fn: function (aVisitor){
+fn: function (aVisitor) {
 var self=this;
 return smalltalk.send(aVisitor,"_visitIRInlinedAssignment_",[self]);
 }
@@ -15,7 +15,7 @@ smalltalk.addMethod(
 "_isInlined",
 smalltalk.method({
 selector: "isInlined",
-fn: function (){
+fn: function () {
 var self=this;
 return true;
 }
@@ -29,10 +29,10 @@ smalltalk.addMethod(
 "_accept_",
 smalltalk.method({
 selector: "accept:",
-fn: function (aVisitor){
+fn: function (aVisitor) {
 var self=this;
 smalltalk.send(aVisitor,"_visitIRInlinedClosure_",[self]);
-return self}
+return self;}
 }),
 smalltalk.IRInlinedClosure);
 
@@ -40,7 +40,7 @@ smalltalk.addMethod(
 "_isInlined",
 smalltalk.method({
 selector: "isInlined",
-fn: function (){
+fn: function () {
 var self=this;
 return true;
 }
@@ -54,7 +54,7 @@ smalltalk.addMethod(
 "_accept_",
 smalltalk.method({
 selector: "accept:",
-fn: function (aVisitor){
+fn: function (aVisitor) {
 var self=this;
 return smalltalk.send(aVisitor,"_visitIRInlinedReturn_",[self]);
 }
@@ -65,7 +65,7 @@ smalltalk.addMethod(
 "_isInlined",
 smalltalk.method({
 selector: "isInlined",
-fn: function (){
+fn: function () {
 var self=this;
 return true;
 }
@@ -79,7 +79,7 @@ smalltalk.addMethod(
 "_accept_",
 smalltalk.method({
 selector: "accept:",
-fn: function (aVisitor){
+fn: function (aVisitor) {
 var self=this;
 return smalltalk.send(aVisitor,"_visitIRInlinedNonLocalReturn_",[self]);
 }
@@ -90,7 +90,7 @@ smalltalk.addMethod(
 "_isInlined",
 smalltalk.method({
 selector: "isInlined",
-fn: function (){
+fn: function () {
 var self=this;
 return true;
 }
@@ -104,10 +104,10 @@ smalltalk.addMethod(
 "_accept_",
 smalltalk.method({
 selector: "accept:",
-fn: function (aVisitor){
+fn: function (aVisitor) {
 var self=this;
 smalltalk.send(aVisitor,"_visitInlinedSend_",[self]);
-return self}
+return self;}
 }),
 smalltalk.IRInlinedSend);
 
@@ -115,7 +115,7 @@ smalltalk.addMethod(
 "_isInlined",
 smalltalk.method({
 selector: "isInlined",
-fn: function (){
+fn: function () {
 var self=this;
 return true;
 }
@@ -129,38 +129,66 @@ smalltalk.addMethod(
 "_accept_",
 smalltalk.method({
 selector: "accept:",
-fn: function (aVisitor){
+fn: function (aVisitor) {
 var self=this;
 smalltalk.send(aVisitor,"_visitIRInlinedIfFalse_",[self]);
-return self}
+return self;}
 }),
 smalltalk.IRInlinedIfFalse);
 
 
 
+smalltalk.addClass('IRInlinedIfNil', smalltalk.IRInlinedSend, [], 'Compiler-Inlining');
+smalltalk.addMethod(
+"_accept_",
+smalltalk.method({
+selector: "accept:",
+fn: function (aVisitor) {
+var self=this;
+smalltalk.send(aVisitor,"_visitIRInlinedIfNil_",[self]);
+return self;}
+}),
+smalltalk.IRInlinedIfNil);
+
+
+
 smalltalk.addClass('IRInlinedIfTrue', smalltalk.IRInlinedSend, [], 'Compiler-Inlining');
 smalltalk.addMethod(
 "_accept_",
 smalltalk.method({
 selector: "accept:",
-fn: function (aVisitor){
+fn: function (aVisitor) {
 var self=this;
 smalltalk.send(aVisitor,"_visitIRInlinedIfTrue_",[self]);
-return self}
+return self;}
 }),
 smalltalk.IRInlinedIfTrue);
 
 
 
+smalltalk.addClass('IRInlinedIfTrueIfFalse', smalltalk.IRInlinedSend, [], 'Compiler-Inlining');
+smalltalk.addMethod(
+"_accept_",
+smalltalk.method({
+selector: "accept:",
+fn: function (aVisitor) {
+var self=this;
+smalltalk.send(aVisitor,"_visitIRInlinedIfTrueIfFalse_",[self]);
+return self;}
+}),
+smalltalk.IRInlinedIfTrueIfFalse);
+
+
+
 smalltalk.addClass('IRInlinedSequence', smalltalk.IRBlockSequence, [], 'Compiler-Inlining');
 smalltalk.addMethod(
 "_accept_",
 smalltalk.method({
 selector: "accept:",
-fn: function (aVisitor){
+fn: function (aVisitor) {
 var self=this;
 smalltalk.send(aVisitor,"_visitIRInlinedSequence_",[self]);
-return self}
+return self;}
 }),
 smalltalk.IRInlinedSequence);
 
@@ -168,7 +196,7 @@ smalltalk.addMethod(
 "_isInlined",
 smalltalk.method({
 selector: "isInlined",
-fn: function (){
+fn: function () {
 var self=this;
 return true;
 }
@@ -182,7 +210,7 @@ smalltalk.addMethod(
 "_accept_",
 smalltalk.method({
 selector: "accept:",
-fn: function (aVisitor){
+fn: function (aVisitor) {
 var self=this;
 return smalltalk.send(aVisitor,"_visitIRAssigningInlinedSequence_",[self]);
 }
@@ -193,7 +221,7 @@ smalltalk.addMethod(
 "_assignTo",
 smalltalk.method({
 selector: "assignTo",
-fn: function (){
+fn: function () {
 var self=this;
 return self["@assignTo"];
 }
@@ -204,10 +232,10 @@ smalltalk.addMethod(
 "_assignTo_",
 smalltalk.method({
 selector: "assignTo:",
-fn: function (anIRInstruction){
+fn: function (anIRInstruction) {
 var self=this;
 self["@assignTo"]=anIRInstruction;
-return self}
+return self;}
 }),
 smalltalk.IRAssigningInlinedSequence);
 
@@ -218,7 +246,7 @@ smalltalk.addMethod(
 "_accept_",
 smalltalk.method({
 selector: "accept:",
-fn: function (aVisitor){
+fn: function (aVisitor) {
 var self=this;
 return smalltalk.send(aVisitor,"_visitIRReturningInlinedSequence_",[self]);
 }
@@ -232,7 +260,7 @@ smalltalk.addMethod(
 "_accept_",
 smalltalk.method({
 selector: "accept:",
-fn: function (aVisitor){
+fn: function (aVisitor) {
 var self=this;
 return smalltalk.send(aVisitor,"_visitIRNonLocalReturningInlinedSequence_",[self]);
 }
@@ -246,7 +274,7 @@ smalltalk.addMethod(
 "_assignmentInliner",
 smalltalk.method({
 selector: "assignmentInliner",
-fn: function (){
+fn: function () {
 var self=this;
 var $1,$2;
 $1=smalltalk.send((smalltalk.IRAssignmentInliner || IRAssignmentInliner),"_new",[]);
@@ -261,7 +289,7 @@ smalltalk.addMethod(
 "_nonLocalReturnInliner",
 smalltalk.method({
 selector: "nonLocalReturnInliner",
-fn: function (){
+fn: function () {
 var self=this;
 var $1,$2;
 $1=smalltalk.send((smalltalk.IRNonLocalReturnInliner || IRNonLocalReturnInliner),"_new",[]);
@@ -276,7 +304,7 @@ smalltalk.addMethod(
 "_returnInliner",
 smalltalk.method({
 selector: "returnInliner",
-fn: function (){
+fn: function () {
 var self=this;
 var $1,$2;
 $1=smalltalk.send((smalltalk.IRReturnInliner || IRReturnInliner),"_new",[]);
@@ -291,7 +319,7 @@ smalltalk.addMethod(
 "_sendInliner",
 smalltalk.method({
 selector: "sendInliner",
-fn: function (){
+fn: function () {
 var self=this;
 var $1,$2;
 $1=smalltalk.send((smalltalk.IRSendInliner || IRSendInliner),"_new",[]);
@@ -306,7 +334,7 @@ smalltalk.addMethod(
 "_shouldInlineAssignment_",
 smalltalk.method({
 selector: "shouldInlineAssignment:",
-fn: function (anIRAssignment){
+fn: function (anIRAssignment) {
 var self=this;
 return smalltalk.send(smalltalk.send(smalltalk.send(anIRAssignment,"_isInlined",[]),"_not",[]),"_and_",[(function(){
 return smalltalk.send(smalltalk.send(smalltalk.send(smalltalk.send(anIRAssignment,"_instructions",[]),"_last",[]),"_isSend",[]),"_and_",[(function(){
@@ -321,7 +349,7 @@ smalltalk.addMethod(
 "_shouldInlineReturn_",
 smalltalk.method({
 selector: "shouldInlineReturn:",
-fn: function (anIRReturn){
+fn: function (anIRReturn) {
 var self=this;
 return smalltalk.send(smalltalk.send(smalltalk.send(anIRReturn,"_isInlined",[]),"_not",[]),"_and_",[(function(){
 return smalltalk.send(smalltalk.send(smalltalk.send(smalltalk.send(anIRReturn,"_instructions",[]),"_first",[]),"_isSend",[]),"_and_",[(function(){
@@ -336,7 +364,7 @@ smalltalk.addMethod(
 "_shouldInlineSend_",
 smalltalk.method({
 selector: "shouldInlineSend:",
-fn: function (anIRSend){
+fn: function (anIRSend) {
 var self=this;
 return smalltalk.send(smalltalk.send(smalltalk.send(anIRSend,"_isInlined",[]),"_not",[]),"_and_",[(function(){
 return smalltalk.send((smalltalk.IRSendInliner || IRSendInliner),"_shouldInline_",[anIRSend]);
@@ -349,7 +377,7 @@ smalltalk.addMethod(
 "_transformNonLocalReturn_",
 smalltalk.method({
 selector: "transformNonLocalReturn:",
-fn: function (anIRNonLocalReturn){
+fn: function (anIRNonLocalReturn) {
 var self=this;
 var $1,$2;
 var localReturn;
@@ -375,7 +403,7 @@ smalltalk.addMethod(
 "_visitIRAssignment_",
 smalltalk.method({
 selector: "visitIRAssignment:",
-fn: function (anIRAssignment){
+fn: function (anIRAssignment) {
 var self=this;
 return smalltalk.send(smalltalk.send(self,"_shouldInlineAssignment_",[anIRAssignment]),"_ifTrue_ifFalse_",[(function(){
 return smalltalk.send(smalltalk.send(self,"_assignmentInliner",[]),"_inlineAssignment_",[anIRAssignment]);
@@ -390,7 +418,7 @@ smalltalk.addMethod(
 "_visitIRNonLocalReturn_",
 smalltalk.method({
 selector: "visitIRNonLocalReturn:",
-fn: function (anIRNonLocalReturn){
+fn: function (anIRNonLocalReturn) {
 var self=this;
 return smalltalk.send(smalltalk.send(self,"_shouldInlineReturn_",[anIRNonLocalReturn]),"_ifTrue_ifFalse_",[(function(){
 return smalltalk.send(smalltalk.send(self,"_nonLocalReturnInliner",[]),"_inlineReturn_",[anIRNonLocalReturn]);
@@ -405,7 +433,7 @@ smalltalk.addMethod(
 "_visitIRReturn_",
 smalltalk.method({
 selector: "visitIRReturn:",
-fn: function (anIRReturn){
+fn: function (anIRReturn) {
 var self=this;
 return smalltalk.send(smalltalk.send(self,"_shouldInlineReturn_",[anIRReturn]),"_ifTrue_ifFalse_",[(function(){
 return smalltalk.send(smalltalk.send(self,"_returnInliner",[]),"_inlineReturn_",[anIRReturn]);
@@ -420,7 +448,7 @@ smalltalk.addMethod(
 "_visitIRSend_",
 smalltalk.method({
 selector: "visitIRSend:",
-fn: function (anIRSend){
+fn: function (anIRSend) {
 var self=this;
 return smalltalk.send(smalltalk.send(self,"_shouldInlineSend_",[anIRSend]),"_ifTrue_ifFalse_",[(function(){
 return smalltalk.send(smalltalk.send(self,"_sendInliner",[]),"_inlineSend_",[anIRSend]);
@@ -438,7 +466,7 @@ smalltalk.addMethod(
 "_visitIRAssigningInlinedSequence_",
 smalltalk.method({
 selector: "visitIRAssigningInlinedSequence:",
-fn: function (anIRInlinedSequence){
+fn: function (anIRInlinedSequence) {
 var self=this;
 var $1,$2;
 smalltalk.send(smalltalk.send(smalltalk.send(anIRInlinedSequence,"_instructions",[]),"_allButLast",[]),"_do_",[(function(each){
@@ -457,7 +485,7 @@ return smalltalk.send(self,"_visit_",[smalltalk.send(smalltalk.send(anIRInlinedS
 return smalltalk.send(self,"_visit_",[smalltalk.send(smalltalk.send(anIRInlinedSequence,"_instructions",[]),"_last",[])]);
 })]);
 })]);
-return self}
+return self;}
 }),
 smalltalk.IRInliningJSTranslator);
 
@@ -465,10 +493,10 @@ smalltalk.addMethod(
 "_visitIRInlinedAssignment_",
 smalltalk.method({
 selector: "visitIRInlinedAssignment:",
-fn: function (anIRInlinedAssignment){
+fn: function (anIRInlinedAssignment) {
 var self=this;
 smalltalk.send(self,"_visit_",[smalltalk.send(smalltalk.send(anIRInlinedAssignment,"_instructions",[]),"_last",[])]);
-return self}
+return self;}
 }),
 smalltalk.IRInliningJSTranslator);
 
@@ -476,12 +504,12 @@ smalltalk.addMethod(
 "_visitIRInlinedClosure_",
 smalltalk.method({
 selector: "visitIRInlinedClosure:",
-fn: function (anIRInlinedClosure){
+fn: function (anIRInlinedClosure) {
 var self=this;
 smalltalk.send(smalltalk.send(anIRInlinedClosure,"_instructions",[]),"_do_",[(function(each){
 return smalltalk.send(self,"_visit_",[each]);
 })]);
-return self}
+return self;}
 }),
 smalltalk.IRInliningJSTranslator);
 
@@ -489,7 +517,7 @@ smalltalk.addMethod(
 "_visitIRInlinedIfFalse_",
 smalltalk.method({
 selector: "visitIRInlinedIfFalse:",
-fn: function (anIRInlinedIfFalse){
+fn: function (anIRInlinedIfFalse) {
 var self=this;
 smalltalk.send(smalltalk.send(self,"_stream",[]),"_nextPutIf_with_",[(function(){
 smalltalk.send(smalltalk.send(self,"_stream",[]),"_nextPutAll_",["! smalltalk.assert("]);
@@ -498,7 +526,24 @@ return smalltalk.send(smalltalk.send(self,"_stream",[]),"_nextPutAll_",[")"]);
 }),(function(){
 return smalltalk.send(self,"_visit_",[smalltalk.send(smalltalk.send(anIRInlinedIfFalse,"_instructions",[]),"_last",[])]);
 })]);
-return self}
+return self;}
+}),
+smalltalk.IRInliningJSTranslator);
+
+smalltalk.addMethod(
+"_visitIRInlinedIfNil_",
+smalltalk.method({
+selector: "visitIRInlinedIfNil:",
+fn: function (anIRInlinedIfNil) {
+var self=this;
+smalltalk.send(smalltalk.send(self,"_stream",[]),"_nextPutIf_with_",[(function(){
+smalltalk.send(smalltalk.send(self,"_stream",[]),"_nextPutAll_",["($receiver = "]);
+smalltalk.send(self,"_visit_",[smalltalk.send(smalltalk.send(anIRInlinedIfNil,"_instructions",[]),"_first",[])]);
+return smalltalk.send(smalltalk.send(self,"_stream",[]),"_nextPutAll_",[") == nil || $receiver == undefined"]);
+}),(function(){
+return smalltalk.send(self,"_visit_",[smalltalk.send(smalltalk.send(anIRInlinedIfNil,"_instructions",[]),"_last",[])]);
+})]);
+return self;}
 }),
 smalltalk.IRInliningJSTranslator);
 
@@ -506,7 +551,7 @@ smalltalk.addMethod(
 "_visitIRInlinedIfTrue_",
 smalltalk.method({
 selector: "visitIRInlinedIfTrue:",
-fn: function (anIRInlinedIfTrue){
+fn: function (anIRInlinedIfTrue) {
 var self=this;
 smalltalk.send(smalltalk.send(self,"_stream",[]),"_nextPutIf_with_",[(function(){
 smalltalk.send(smalltalk.send(self,"_stream",[]),"_nextPutAll_",["smalltalk.assert("]);
@@ -515,7 +560,26 @@ return smalltalk.send(smalltalk.send(self,"_stream",[]),"_nextPutAll_",[")"]);
 }),(function(){
 return smalltalk.send(self,"_visit_",[smalltalk.send(smalltalk.send(anIRInlinedIfTrue,"_instructions",[]),"_last",[])]);
 })]);
-return self}
+return self;}
+}),
+smalltalk.IRInliningJSTranslator);
+
+smalltalk.addMethod(
+"_visitIRInlinedIfTrueIfFalse_",
+smalltalk.method({
+selector: "visitIRInlinedIfTrueIfFalse:",
+fn: function (anIRInlinedIfTrueIfFalse) {
+var self=this;
+smalltalk.send(smalltalk.send(self,"_stream",[]),"_nextPutIfElse_with_with_",[(function(){
+smalltalk.send(smalltalk.send(self,"_stream",[]),"_nextPutAll_",["smalltalk.assert("]);
+smalltalk.send(self,"_visit_",[smalltalk.send(smalltalk.send(anIRInlinedIfTrueIfFalse,"_instructions",[]),"_first",[])]);
+return smalltalk.send(smalltalk.send(self,"_stream",[]),"_nextPutAll_",[")"]);
+}),(function(){
+return smalltalk.send(self,"_visit_",[smalltalk.send(smalltalk.send(anIRInlinedIfTrueIfFalse,"_instructions",[]),"_second",[])]);
+}),(function(){
+return smalltalk.send(self,"_visit_",[smalltalk.send(smalltalk.send(anIRInlinedIfTrueIfFalse,"_instructions",[]),"_third",[])]);
+})]);
+return self;}
 }),
 smalltalk.IRInliningJSTranslator);
 
@@ -523,14 +587,14 @@ smalltalk.addMethod(
 "_visitIRInlinedNonLocalReturn_",
 smalltalk.method({
 selector: "visitIRInlinedNonLocalReturn:",
-fn: function (anIRInlinedReturn){
+fn: function (anIRInlinedReturn) {
 var self=this;
 smalltalk.send(smalltalk.send(self,"_stream",[]),"_nextPutStatementWith_",[(function(){
 return smalltalk.send(self,"_visit_",[smalltalk.send(smalltalk.send(anIRInlinedReturn,"_instructions",[]),"_last",[])]);
 })]);
 smalltalk.send(smalltalk.send(self,"_stream",[]),"_nextPutNonLocalReturnWith_",[(function(){
 })]);
-return self}
+return self;}
 }),
 smalltalk.IRInliningJSTranslator);
 
@@ -538,10 +602,10 @@ smalltalk.addMethod(
 "_visitIRInlinedReturn_",
 smalltalk.method({
 selector: "visitIRInlinedReturn:",
-fn: function (anIRInlinedReturn){
+fn: function (anIRInlinedReturn) {
 var self=this;
 smalltalk.send(self,"_visit_",[smalltalk.send(smalltalk.send(anIRInlinedReturn,"_instructions",[]),"_last",[])]);
-return self}
+return self;}
 }),
 smalltalk.IRInliningJSTranslator);
 
@@ -549,14 +613,14 @@ smalltalk.addMethod(
 "_visitIRInlinedSequence_",
 smalltalk.method({
 selector: "visitIRInlinedSequence:",
-fn: function (anIRInlinedSequence){
+fn: function (anIRInlinedSequence) {
 var self=this;
 smalltalk.send(smalltalk.send(anIRInlinedSequence,"_instructions",[]),"_do_",[(function(each){
 return smalltalk.send(smalltalk.send(self,"_stream",[]),"_nextPutStatementWith_",[(function(){
 return smalltalk.send(self,"_visit_",[each]);
 })]);
 })]);
-return self}
+return self;}
 }),
 smalltalk.IRInliningJSTranslator);
 
@@ -564,7 +628,7 @@ smalltalk.addMethod(
 "_visitIRNonLocalReturningInlinedSequence_",
 smalltalk.method({
 selector: "visitIRNonLocalReturningInlinedSequence:",
-fn: function (anIRInlinedSequence){
+fn: function (anIRInlinedSequence) {
 var self=this;
 smalltalk.send(smalltalk.send(smalltalk.send(anIRInlinedSequence,"_instructions",[]),"_allButLast",[]),"_do_",[(function(each){
 return smalltalk.send(smalltalk.send(self,"_stream",[]),"_nextPutStatementWith_",[(function(){
@@ -580,7 +644,7 @@ return smalltalk.send(self,"_visit_",[smalltalk.send(smalltalk.send(anIRInlinedS
 return smalltalk.send(self,"_visit_",[smalltalk.send(smalltalk.send(anIRInlinedSequence,"_instructions",[]),"_last",[])]);
 })]);
 })]);
-return self}
+return self;}
 }),
 smalltalk.IRInliningJSTranslator);
 
@@ -588,7 +652,7 @@ smalltalk.addMethod(
 "_visitIRReturningInlinedSequence_",
 smalltalk.method({
 selector: "visitIRReturningInlinedSequence:",
-fn: function (anIRInlinedSequence){
+fn: function (anIRInlinedSequence) {
 var self=this;
 smalltalk.send(smalltalk.send(smalltalk.send(anIRInlinedSequence,"_instructions",[]),"_allButLast",[]),"_do_",[(function(each){
 return smalltalk.send(smalltalk.send(self,"_stream",[]),"_nextPutStatementWith_",[(function(){
@@ -603,7 +667,7 @@ return smalltalk.send(self,"_visit_",[smalltalk.send(smalltalk.send(anIRInlinedS
 return smalltalk.send(self,"_visit_",[smalltalk.send(smalltalk.send(anIRInlinedSequence,"_instructions",[]),"_last",[])]);
 })]);
 })]);
-return self}
+return self;}
 }),
 smalltalk.IRInliningJSTranslator);
 
@@ -614,23 +678,31 @@ smalltalk.addMethod(
 "_ifFalse_",
 smalltalk.method({
 selector: "ifFalse:",
-fn: function (anIRInstruction){
+fn: function (anIRInstruction) {
 var self=this;
-var $1;
-var inlinedSend;
-var inlinedClosure;
-if(! smalltalk.assert(smalltalk.send(anIRInstruction,"_isClosure",[]))){
-smalltalk.send(self,"_inliningError_",["Message argument should be a block"]);
-};
-if(! smalltalk.assert(smalltalk.send(smalltalk.send(smalltalk.send(anIRInstruction,"_arguments",[]),"_size",[]),"__eq",[(0)]))){
-smalltalk.send(self,"_inliningError_",["Inlined block should have zero argument"]);
-};
-inlinedClosure=smalltalk.send(self,"_inlineClosure_",[anIRInstruction]);
-inlinedSend=smalltalk.send((smalltalk.IRInlinedIfFalse || IRInlinedIfFalse),"_new",[]);
-smalltalk.send(inlinedSend,"_add_",[smalltalk.send(smalltalk.send(smalltalk.send(self,"_send",[]),"_instructions",[]),"_first",[])]);
-$1=smalltalk.send(inlinedSend,"_add_",[inlinedClosure]);
-smalltalk.send(smalltalk.send(self,"_send",[]),"_replaceWith_",[inlinedSend]);
-return inlinedSend;
+return smalltalk.send(self,"_inlinedSend_with_",[smalltalk.send((smalltalk.IRInlinedIfFalse || IRInlinedIfFalse),"_new",[]),anIRInstruction]);
+}
+}),
+smalltalk.IRSendInliner);
+
+smalltalk.addMethod(
+"_ifFalse_ifTrue_",
+smalltalk.method({
+selector: "ifFalse:ifTrue:",
+fn: function (anIRInstruction, anotherIRInstruction) {
+var self=this;
+return smalltalk.send(self,"_perform_withArguments_",[smalltalk.symbolFor("ifTrue:ifFalse:"),[anotherIRInstruction,anIRInstruction]]);
+}
+}),
+smalltalk.IRSendInliner);
+
+smalltalk.addMethod(
+"_ifNil_",
+smalltalk.method({
+selector: "ifNil:",
+fn: function (anIRInstruction) {
+var self=this;
+return smalltalk.send(self,"_inlinedSend_with_",[smalltalk.send((smalltalk.IRInlinedIfNil || IRInlinedIfNil),"_new",[]),anIRInstruction]);
 }
 }),
 smalltalk.IRSendInliner);
@@ -639,23 +711,20 @@ smalltalk.addMethod(
 "_ifTrue_",
 smalltalk.method({
 selector: "ifTrue:",
-fn: function (anIRInstruction){
+fn: function (anIRInstruction) {
 var self=this;
-var $1;
-var inlinedSend;
-var inlinedClosure;
-if(! smalltalk.assert(smalltalk.send(anIRInstruction,"_isClosure",[]))){
-smalltalk.send(self,"_inliningError_",["Message argument should be a block"]);
-};
-if(! smalltalk.assert(smalltalk.send(smalltalk.send(smalltalk.send(anIRInstruction,"_arguments",[]),"_size",[]),"__eq",[(0)]))){
-smalltalk.send(self,"_inliningError_",["Inlined block should have zero argument"]);
-};
-inlinedClosure=smalltalk.send(self,"_inlineClosure_",[anIRInstruction]);
-inlinedSend=smalltalk.send((smalltalk.IRInlinedIfTrue || IRInlinedIfTrue),"_new",[]);
-smalltalk.send(inlinedSend,"_add_",[smalltalk.send(smalltalk.send(smalltalk.send(self,"_send",[]),"_instructions",[]),"_first",[])]);
-$1=smalltalk.send(inlinedSend,"_add_",[inlinedClosure]);
-smalltalk.send(smalltalk.send(self,"_send",[]),"_replaceWith_",[inlinedSend]);
-return inlinedSend;
+return smalltalk.send(self,"_inlinedSend_with_",[smalltalk.send((smalltalk.IRInlinedIfTrue || IRInlinedIfTrue),"_new",[]),anIRInstruction]);
+}
+}),
+smalltalk.IRSendInliner);
+
+smalltalk.addMethod(
+"_ifTrue_ifFalse_",
+smalltalk.method({
+selector: "ifTrue:ifFalse:",
+fn: function (anIRInstruction, anotherIRInstruction) {
+var self=this;
+return smalltalk.send(self,"_inlinedSend_with_with_",[smalltalk.send((smalltalk.IRInlinedIfTrueIfFalse || IRInlinedIfTrueIfFalse),"_new",[]),anIRInstruction,anotherIRInstruction]);
 }
 }),
 smalltalk.IRSendInliner);
@@ -664,7 +733,7 @@ smalltalk.addMethod(
 "_inlineClosure_",
 smalltalk.method({
 selector: "inlineClosure:",
-fn: function (anIRClosure){
+fn: function (anIRClosure) {
 var self=this;
 var inlinedClosure;
 var sequence;
@@ -694,11 +763,36 @@ return inlinedClosure;
 }),
 smalltalk.IRSendInliner);
 
+smalltalk.addMethod(
+"_inlineMessageBlock_with_",
+smalltalk.method({
+selector: "inlineMessageBlock:with:",
+fn: function (anIRInstruction, anotherIRInstruction) {
+var self=this;
+var $1;
+var inlinedSend;
+var inlinedClosure;
+if(! smalltalk.assert(smalltalk.send(anIRInstruction,"_isClosure",[]))){
+smalltalk.send(self,"_inliningError_",["Message argument should be a block"]);
+};
+if(! smalltalk.assert(smalltalk.send(smalltalk.send(smalltalk.send(anIRInstruction,"_arguments",[]),"_size",[]),"__eq",[(0)]))){
+smalltalk.send(self,"_inliningError_",["Inlined block should have zero argument"]);
+};
+inlinedClosure=smalltalk.send(self,"_inlineClosure_",[anIRInstruction]);
+inlinedSend=anotherIRInstruction;
+smalltalk.send(inlinedSend,"_add_",[smalltalk.send(smalltalk.send(smalltalk.send(self,"_send",[]),"_instructions",[]),"_first",[])]);
+$1=smalltalk.send(inlinedSend,"_add_",[inlinedClosure]);
+smalltalk.send(smalltalk.send(self,"_send",[]),"_replaceWith_",[inlinedSend]);
+return inlinedSend;
+}
+}),
+smalltalk.IRSendInliner);
+
 smalltalk.addMethod(
 "_inlineSend_",
 smalltalk.method({
 selector: "inlineSend:",
-fn: function (anIRSend){
+fn: function (anIRSend) {
 var self=this;
 smalltalk.send(self,"_send_",[anIRSend]);
 return smalltalk.send(self,"_perform_withArguments_",[smalltalk.send(smalltalk.send(self,"_send",[]),"_selector",[]),smalltalk.send(smalltalk.send(smalltalk.send(self,"_send",[]),"_instructions",[]),"_allButFirst",[])]);
@@ -710,18 +804,73 @@ smalltalk.addMethod(
 "_inlinedClosure",
 smalltalk.method({
 selector: "inlinedClosure",
-fn: function (){
+fn: function () {
 var self=this;
 return smalltalk.send((smalltalk.IRInlinedClosure || IRInlinedClosure),"_new",[]);
 }
 }),
 smalltalk.IRSendInliner);
 
+smalltalk.addMethod(
+"_inlinedSend_with_",
+smalltalk.method({
+selector: "inlinedSend:with:",
+fn: function (inlinedSend, anIRInstruction) {
+var self=this;
+var $1;
+var inlinedClosure;
+if(! smalltalk.assert(smalltalk.send(anIRInstruction,"_isClosure",[]))){
+smalltalk.send(self,"_inliningError_",["Message argument should be a block"]);
+};
+if(! smalltalk.assert(smalltalk.send(smalltalk.send(smalltalk.send(anIRInstruction,"_arguments",[]),"_size",[]),"__eq",[(0)]))){
+smalltalk.send(self,"_inliningError_",["Inlined block should have zero argument"]);
+};
+inlinedClosure=smalltalk.send(self,"_inlineClosure_",[anIRInstruction]);
+smalltalk.send(inlinedSend,"_add_",[smalltalk.send(smalltalk.send(smalltalk.send(self,"_send",[]),"_instructions",[]),"_first",[])]);
+$1=smalltalk.send(inlinedSend,"_add_",[inlinedClosure]);
+smalltalk.send(smalltalk.send(self,"_send",[]),"_replaceWith_",[inlinedSend]);
+return inlinedSend;
+}
+}),
+smalltalk.IRSendInliner);
+
+smalltalk.addMethod(
+"_inlinedSend_with_with_",
+smalltalk.method({
+selector: "inlinedSend:with:with:",
+fn: function (inlinedSend, anIRInstruction, anotherIRInstruction) {
+var self=this;
+var $1;
+var inlinedClosure1;
+var inclinedClosure2;
+if(! smalltalk.assert(smalltalk.send(anIRInstruction,"_isClosure",[]))){
+smalltalk.send(self,"_inliningError_",["Message argument should be a block"]);
+};
+if(! smalltalk.assert(smalltalk.send(smalltalk.send(smalltalk.send(anIRInstruction,"_arguments",[]),"_size",[]),"__eq",[(0)]))){
+smalltalk.send(self,"_inliningError_",["Inlined block should have zero argument"]);
+};
+if(! smalltalk.assert(smalltalk.send(anotherIRInstruction,"_isClosure",[]))){
+smalltalk.send(self,"_inliningError_",["Message argument should be a block"]);
+};
+if(! smalltalk.assert(smalltalk.send(smalltalk.send(smalltalk.send(anotherIRInstruction,"_arguments",[]),"_size",[]),"__eq",[(0)]))){
+smalltalk.send(self,"_inliningError_",["Inlined block should have zero argument"]);
+};
+inlinedClosure=smalltalk.send(self,"_inlineClosure_",[anIRInstruction]);
+inlinedClosure2=smalltalk.send(self,"_inlineClosure_",[anotherIRInstruction]);
+smalltalk.send(inlinedSend,"_add_",[smalltalk.send(smalltalk.send(smalltalk.send(self,"_send",[]),"_instructions",[]),"_first",[])]);
+smalltalk.send(inlinedSend,"_add_",[inlinedClosure]);
+$1=smalltalk.send(inlinedSend,"_add_",[inlinedClosure2]);
+smalltalk.send(smalltalk.send(self,"_send",[]),"_replaceWith_",[inlinedSend]);
+return inlinedSend;
+}
+}),
+smalltalk.IRSendInliner);
+
 smalltalk.addMethod(
 "_inlinedSequence",
 smalltalk.method({
 selector: "inlinedSequence",
-fn: function (){
+fn: function () {
 var self=this;
 return smalltalk.send((smalltalk.IRInlinedSequence || IRInlinedSequence),"_new",[]);
 }
@@ -732,10 +881,10 @@ smalltalk.addMethod(
 "_inliningError_",
 smalltalk.method({
 selector: "inliningError:",
-fn: function (aString){
+fn: function (aString) {
 var self=this;
 smalltalk.send((smalltalk.InliningError || InliningError),"_signal_",[aString]);
-return self}
+return self;}
 }),
 smalltalk.IRSendInliner);
 
@@ -743,7 +892,7 @@ smalltalk.addMethod(
 "_send",
 smalltalk.method({
 selector: "send",
-fn: function (){
+fn: function () {
 var self=this;
 return self["@send"];
 }
@@ -754,10 +903,10 @@ smalltalk.addMethod(
 "_send_",
 smalltalk.method({
 selector: "send:",
-fn: function (anIRSend){
+fn: function (anIRSend) {
 var self=this;
 self["@send"]=anIRSend;
-return self}
+return self;}
 }),
 smalltalk.IRSendInliner);
 
@@ -765,7 +914,7 @@ smalltalk.addMethod(
 "_translator",
 smalltalk.method({
 selector: "translator",
-fn: function (){
+fn: function () {
 var self=this;
 return self["@translator"];
 }
@@ -776,10 +925,10 @@ smalltalk.addMethod(
 "_translator_",
 smalltalk.method({
 selector: "translator:",
-fn: function (anASTTranslator){
+fn: function (anASTTranslator) {
 var self=this;
 self["@translator"]=anASTTranslator;
-return self}
+return self;}
 }),
 smalltalk.IRSendInliner);
 
@@ -788,9 +937,9 @@ smalltalk.addMethod(
 "_inlinedSelectors",
 smalltalk.method({
 selector: "inlinedSelectors",
-fn: function (){
+fn: function () {
 var self=this;
-return ["ifTrue:", "ifFalse:"];
+return ["ifTrue:", "ifFalse:", "ifTrue:ifFalse:", "ifFalse:ifTrue:", "ifNil:"];
 }
 }),
 smalltalk.IRSendInliner.klass);
@@ -799,7 +948,7 @@ smalltalk.addMethod(
 "_shouldInline_",
 smalltalk.method({
 selector: "shouldInline:",
-fn: function (anIRInstruction){
+fn: function (anIRInstruction) {
 var self=this;
 var $early={};
 try {
@@ -824,7 +973,7 @@ smalltalk.addMethod(
 "_assignment",
 smalltalk.method({
 selector: "assignment",
-fn: function (){
+fn: function () {
 var self=this;
 return self["@assignment"];
 }
@@ -835,10 +984,10 @@ smalltalk.addMethod(
 "_assignment_",
 smalltalk.method({
 selector: "assignment:",
-fn: function (aNode){
+fn: function (aNode) {
 var self=this;
 self["@assignment"]=aNode;
-return self}
+return self;}
 }),
 smalltalk.IRAssignmentInliner);
 
@@ -846,7 +995,7 @@ smalltalk.addMethod(
 "_inlineAssignment_",
 smalltalk.method({
 selector: "inlineAssignment:",
-fn: function (anIRAssignment){
+fn: function (anIRAssignment) {
 var self=this;
 var inlinedAssignment;
 smalltalk.send(self,"_assignment_",[anIRAssignment]);
@@ -865,7 +1014,7 @@ smalltalk.addMethod(
 "_inlinedSequence",
 smalltalk.method({
 selector: "inlinedSequence",
-fn: function (){
+fn: function () {
 var self=this;
 var $1,$2;
 $1=smalltalk.send((smalltalk.IRAssigningInlinedSequence || IRAssigningInlinedSequence),"_new",[]);
@@ -883,7 +1032,7 @@ smalltalk.addMethod(
 "_inlineReturn_",
 smalltalk.method({
 selector: "inlineReturn:",
-fn: function (anIRReturn){
+fn: function (anIRReturn) {
 var self=this;
 var return_;
 return_=smalltalk.send(self,"_inlinedReturn",[]);
@@ -901,7 +1050,7 @@ smalltalk.addMethod(
 "_inlinedReturn",
 smalltalk.method({
 selector: "inlinedReturn",
-fn: function (){
+fn: function () {
 var self=this;
 return smalltalk.send((smalltalk.IRInlinedReturn || IRInlinedReturn),"_new",[]);
 }
@@ -912,7 +1061,7 @@ smalltalk.addMethod(
 "_inlinedSequence",
 smalltalk.method({
 selector: "inlinedSequence",
-fn: function (){
+fn: function () {
 var self=this;
 return smalltalk.send((smalltalk.IRReturningInlinedSequence || IRReturningInlinedSequence),"_new",[]);
 }
@@ -926,7 +1075,7 @@ smalltalk.addMethod(
 "_inlinedReturn",
 smalltalk.method({
 selector: "inlinedReturn",
-fn: function (){
+fn: function () {
 var self=this;
 return smalltalk.send((smalltalk.IRInlinedNonLocalReturn || IRInlinedNonLocalReturn),"_new",[]);
 }
@@ -937,7 +1086,7 @@ smalltalk.addMethod(
 "_inlinedSequence",
 smalltalk.method({
 selector: "inlinedSequence",
-fn: function (){
+fn: function () {
 var self=this;
 return smalltalk.send((smalltalk.IRNonLocalReturningInlinedSequence || IRNonLocalReturningInlinedSequence),"_new",[]);
 }
@@ -951,7 +1100,7 @@ smalltalk.addMethod(
 "_compileNode_",
 smalltalk.method({
 selector: "compileNode:",
-fn: function (aNode){
+fn: function (aNode) {
 var self=this;
 var $1,$2;
 var ir;
@@ -971,7 +1120,7 @@ smalltalk.addMethod(
 "_inliner",
 smalltalk.method({
 selector: "inliner",
-fn: function (){
+fn: function () {
 var self=this;
 return smalltalk.send((smalltalk.IRInliner || IRInliner),"_new",[]);
 }
@@ -982,7 +1131,7 @@ smalltalk.addMethod(
 "_irTranslator",
 smalltalk.method({
 selector: "irTranslator",
-fn: function (){
+fn: function () {
 var self=this;
 return smalltalk.send((smalltalk.IRInliningJSTranslator || IRInliningJSTranslator),"_new",[]);
 }

File diff suppressed because it is too large
+ 319 - 120
js/Compiler-Inlining.js


+ 22 - 23
js/boot.js

@@ -172,33 +172,33 @@ function Smalltalk(){
 	   metaclasses. */
 	   
 	st.init = function(klass) {
-		st.initSubTree(klass);
+		st.initClass(klass);
 		if(klass.klass && !klass.meta) {
-			st.initSubTree(klass.klass);
+			st.initClass(klass.klass);
 		}
 	};
 
-	st.initSubTree = function(klass) {
+	st.initClass = function(klass) {
 		var subclasses = st.subclasses(klass);
-		var methods, proto = klass.fn.prototype;
+		var methods, prototype = klass.fn.prototype;
 
 		if(klass.superclass && klass.superclass !== nil) {
 			methods = st.methods(klass.superclass);
 
 			//Methods linking
-			for(var keys=Object.keys(methods),i=0,l=keys.length; i<l; ++i) {
-				var k = keys[i];
-				if(!proto.methods[k]) {
-					proto.inheritedMethods[k] = methods[k];
-					Object.defineProperty(proto, methods[k].jsSelector, {
-						value: methods[k].fn, configurable: true, writable: true
+			for(var keys = Object.keys(methods), i=0; i<keys.length; i++) {
+				var key = keys[i];
+				if(!prototype.methods[key]) {
+					prototype.inheritedMethods[key] = methods[key];
+					Object.defineProperty(prototype, methods[key].jsSelector, {
+						value: methods[key].fn, configurable: true, writable: true
 					});
 				}
 			}
 		}
 
-		for(var i=0;i<subclasses.length;i++) {
-			st.initSubTree(subclasses[i]);
+		for(var i=0; i<subclasses.length; i++) {
+			st.initClass(subclasses[i]);
 		}
 	};
 
@@ -218,7 +218,7 @@ function Smalltalk(){
 
 	st.classes = function() {
 		var classes = [], names = Object.keys(st), l = names.length;
-		for (var i=0; i<l; ++i) {
+		for (var i=0; i<l; i++) {
 			var name = names[i];
 			if (name.search(/^[A-Z]/) !== -1) {
 				classes.push(st[name]);
@@ -232,13 +232,13 @@ function Smalltalk(){
 
 	st.methods = function(klass) {
 		var methods = {};
-		var copyFrom = klass.fn.prototype.methods;
-		for(var i=0, k=Object.keys(copyFrom), l=k.length; i<l; ++i) {
-			methods[k[i]] = copyFrom[k[i]];
+		inheritedMethods = klass.fn.prototype.inheritedMethods;
+		for(var i=0, keys=Object.keys(inheritedMethods); i<keys.length; i++) {
+			methods[keys[i]] = inheritedMethods[keys[i]];
 		}
-		copyFrom = klass.fn.prototype.inheritedMethods;
-		for(var i=0, k=Object.keys(copyFrom), l=k.length; i<l; ++i) {
-			methods[k[i]] = copyFrom[k[i]];
+		var inheritedMethods = klass.fn.prototype.methods;
+		for(var i=0, keys=Object.keys(inheritedMethods); i<keys.length; i++) {
+			methods[keys[i]] = inheritedMethods[keys[i]];
 		}
 		return methods;
 	};
@@ -249,8 +249,8 @@ function Smalltalk(){
 	st.subclasses = function(klass) {
 		var subclasses = [];
 		var classes = st.classes();
-		for(var i=0, l=classes.length; i<l; ++i) {
-			var c = classes[i]
+		for(var i=0; i < classes.length; i++) {
+			var c = classes[i];
 			if(c.fn) {
 				//Classes
 				if(c.superclass === klass) {
@@ -304,7 +304,7 @@ function Smalltalk(){
 	};
 
 	/* Add a class to the smalltalk object, creating a new one if needed.
-	   Package is lazily created if it does not exist with given name.*/
+	   A Package is lazily created if it does not exist with given name. */
 
 	st.addClass = function(className, superclass, iVarNames, pkgName) {
 		var pkg = st.addPackage(pkgName);
@@ -372,7 +372,6 @@ function Smalltalk(){
 	   (See the Smalltalk class ErrorHandler and its subclasses */
 
 	function handleError(error) {
-        //Do not handle continuation exceptions
         if(!error.cc) {
 		    smalltalk.ErrorHandler._current()._handleError_(error);
         }

+ 1 - 1
js/init.js

@@ -1,4 +1,4 @@
-smalltalk.initSubTree(smalltalk.Object); //metaclasses are in through Class
+smalltalk.init(smalltalk.Object); //metaclasses are in through Class
 smalltalk.classes()._do_(function(each) {
 	each._initialize()});
 

+ 10 - 0
st/Compiler-IR.st

@@ -947,6 +947,16 @@ nextPutIf: aBlock with: anotherBlock
 	stream nextPutAll: '}'
 !
 
+nextPutIfElse: aBlock with: ifBlock with: elseBlock
+	stream nextPutAll: 'if('.
+	aBlock value.
+	stream nextPutAll: '){'; lf.
+	ifBlock value.
+	stream nextPutAll: '} else {'; lf.
+	elseBlock value.
+	stream nextPutAll: '}'
+!
+
 nextPutMethodDeclaration: aMethod with: aBlock
 	stream 
 		nextPutAll: 'smalltalk.method({'; lf;

+ 104 - 26
st/Compiler-Inlining.st

@@ -99,6 +99,16 @@ accept: aVisitor
 	aVisitor visitIRInlinedIfFalse: self
 ! !
 
+IRInlinedSend subclass: #IRInlinedIfNil
+	instanceVariableNames: ''
+	package: 'Compiler-Inlining'!
+
+!IRInlinedIfNil methodsFor: 'visiting'!
+
+accept: aVisitor
+	aVisitor visitIRInlinedIfNil: self
+! !
+
 IRInlinedSend subclass: #IRInlinedIfTrue
 	instanceVariableNames: ''
 	package: 'Compiler-Inlining'!
@@ -109,6 +119,16 @@ accept: aVisitor
 	aVisitor visitIRInlinedIfTrue: self
 ! !
 
+IRInlinedSend subclass: #IRInlinedIfTrueIfFalse
+	instanceVariableNames: ''
+	package: 'Compiler-Inlining'!
+
+!IRInlinedIfTrueIfFalse methodsFor: 'visiting'!
+
+accept: aVisitor
+	aVisitor visitIRInlinedIfTrueIfFalse: self
+! !
+
 IRBlockSequence subclass: #IRInlinedSequence
 	instanceVariableNames: ''
 	package: 'Compiler-Inlining'!
@@ -300,6 +320,14 @@ visitIRInlinedIfFalse: anIRInlinedIfFalse
 		with: [ self visit: anIRInlinedIfFalse instructions last ]
 !
 
+visitIRInlinedIfNil: anIRInlinedIfNil
+	self stream nextPutIf: [ 
+		self stream nextPutAll: '($receiver = '. 
+		self visit: anIRInlinedIfNil instructions first.
+		self stream nextPutAll: ') == nil || $receiver == undefined' ]
+		with: [ self visit: anIRInlinedIfNil instructions last ]
+!
+
 visitIRInlinedIfTrue: anIRInlinedIfTrue
 	self stream nextPutIf: [ 
 		self stream nextPutAll: 'smalltalk.assert('. 
@@ -308,6 +336,16 @@ visitIRInlinedIfTrue: anIRInlinedIfTrue
 		with: [ self visit: anIRInlinedIfTrue instructions last ]
 !
 
+visitIRInlinedIfTrueIfFalse: anIRInlinedIfTrueIfFalse
+	self stream 
+		nextPutIfElse: [ 
+			self stream nextPutAll: 'smalltalk.assert('. 
+			self visit: anIRInlinedIfTrueIfFalse instructions first.
+			self stream nextPutAll: ')' ]
+		with: [ self visit: anIRInlinedIfTrueIfFalse instructions second ]
+		with: [ self visit: anIRInlinedIfTrueIfFalse instructions third ]
+!
+
 visitIRInlinedNonLocalReturn: anIRInlinedReturn
 	self stream nextPutStatementWith: [
 		self visit: anIRInlinedReturn instructions last ].
@@ -392,37 +430,23 @@ inlinedSequence
 !IRSendInliner methodsFor: 'inlining'!
 
 ifFalse: anIRInstruction
-	| inlinedSend inlinedClosure |
-
-	anIRInstruction isClosure ifFalse: [ self inliningError: 'Message argument should be a block' ].
-	anIRInstruction arguments size = 0 ifFalse: [ self inliningError: 'Inlined block should have zero argument' ].
-
-	inlinedClosure := self inlineClosure: anIRInstruction.
+	^ self inlinedSend: IRInlinedIfFalse new with: anIRInstruction
+!
 
-	inlinedSend := IRInlinedIfFalse new.
-	inlinedSend
-		add: self send instructions first;
-		add: inlinedClosure.
+ifFalse: anIRInstruction ifTrue: anotherIRInstruction
+	^ self perform: #ifTrue:ifFalse: withArguments: { anotherIRInstruction. anIRInstruction }
+!
 
-	self send replaceWith: inlinedSend.
-	^ inlinedSend
+ifNil: anIRInstruction
+	^ self inlinedSend: IRInlinedIfNil new with: anIRInstruction
 !
 
 ifTrue: anIRInstruction
-	| inlinedSend inlinedClosure |
-
-	anIRInstruction isClosure ifFalse: [ self inliningError: 'Message argument should be a block' ].
-	anIRInstruction arguments size = 0 ifFalse: [ self inliningError: 'Inlined block should have zero argument' ].
-
-	inlinedClosure := self inlineClosure: anIRInstruction.
-
-	inlinedSend := IRInlinedIfTrue new.
-	inlinedSend
-		add: self send instructions first;
-		add: inlinedClosure.
+	^ self inlinedSend: IRInlinedIfTrue new with: anIRInstruction
+!
 
-	self send replaceWith: inlinedSend.
-	^ inlinedSend
+ifTrue: anIRInstruction ifFalse: anotherIRInstruction
+	^ self inlinedSend: IRInlinedIfTrueIfFalse new with: anIRInstruction with: anotherIRInstruction
 !
 
 inlineClosure: anIRClosure
@@ -452,15 +476,69 @@ inlineClosure: anIRClosure
 	^ inlinedClosure
 !
 
+inlineMessageBlock: anIRInstruction with: anotherIRInstruction
+	| inlinedSend inlinedClosure |
+
+	anIRInstruction isClosure ifFalse: [ self inliningError: 'Message argument should be a block' ].
+	anIRInstruction arguments size = 0 ifFalse: [ self inliningError: 'Inlined block should have zero argument' ].
+
+	inlinedClosure := self inlineClosure: anIRInstruction.
+
+	inlinedSend := anotherIRInstruction.
+	inlinedSend
+		add: self send instructions first;
+		add: inlinedClosure.
+
+	self send replaceWith: inlinedSend.
+	^ inlinedSend
+!
+
 inlineSend: anIRSend
 	self send: anIRSend.
 	^ self perform: self send selector withArguments: self send instructions allButFirst
+!
+
+inlinedSend: inlinedSend with: anIRInstruction
+	| inlinedClosure |
+
+	anIRInstruction isClosure ifFalse: [ self inliningError: 'Message argument should be a block' ].
+	anIRInstruction arguments size = 0 ifFalse: [ self inliningError: 'Inlined block should have zero argument' ].
+
+	inlinedClosure := self inlineClosure: anIRInstruction.
+
+	inlinedSend
+		add: self send instructions first;
+		add: inlinedClosure.
+
+	self send replaceWith: inlinedSend.
+	^ inlinedSend
+!
+
+inlinedSend: inlinedSend with: anIRInstruction with: anotherIRInstruction
+	| inlinedClosure1 inclinedClosure2 |
+
+	anIRInstruction isClosure ifFalse: [ self inliningError: 'Message argument should be a block' ].
+	anIRInstruction arguments size = 0 ifFalse: [ self inliningError: 'Inlined block should have zero argument' ].
+
+	anotherIRInstruction isClosure ifFalse: [ self inliningError: 'Message argument should be a block' ].
+	anotherIRInstruction arguments size = 0 ifFalse: [ self inliningError: 'Inlined block should have zero argument' ].
+
+	inlinedClosure := self inlineClosure: anIRInstruction.
+	inlinedClosure2 := self inlineClosure: anotherIRInstruction.
+
+	inlinedSend
+		add: self send instructions first;
+		add: inlinedClosure;
+		add: inlinedClosure2.
+
+	self send replaceWith: inlinedSend.
+	^ inlinedSend
 ! !
 
 !IRSendInliner class methodsFor: 'accessing'!
 
 inlinedSelectors
-	^ #('ifTrue:' 'ifFalse:')
+	^ #('ifTrue:' 'ifFalse:' 'ifTrue:ifFalse:' 'ifFalse:ifTrue:' 'ifNil:')
 !
 
 shouldInline: anIRInstruction

Some files were not shown because too many files changed in this diff