[turbofan] Materialize JSFunction from frame if possible.
authorbmeurer <bmeurer@chromium.org>
Thu, 9 Apr 2015 07:41:06 +0000 (00:41 -0700)
committerCommit bot <commit-bot@chromium.org>
Thu, 9 Apr 2015 07:41:13 +0000 (07:41 +0000)
This reduces the overhead of recursive calls when context specialization
is enabled. Based on this it might be possible to further reduce the
overhead by also specializing the call itself.

As a drive-by-fix, port the fast context materialization optimization to
arm and arm64, that was previously only supported on x64 and ia32.

R=svenpanne@chromium.org

Review URL: https://codereview.chromium.org/1072743002

Cr-Commit-Position: refs/heads/master@{#27686}

src/compiler/arm/code-generator-arm.cc
src/compiler/arm64/code-generator-arm64.cc
src/compiler/ia32/code-generator-ia32.cc
src/compiler/x64/code-generator-x64.cc

index 6ea5e1bde2c22347b16eeeededd3d657f163cc46..059dadd5e021c37ed805c54d4b625543bb47ca73 100644 (file)
@@ -1015,9 +1015,24 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
         case Constant::kExternalReference:
           __ mov(dst, Operand(src.ToExternalReference()));
           break;
-        case Constant::kHeapObject:
-          __ Move(dst, src.ToHeapObject());
+        case Constant::kHeapObject: {
+          Handle<HeapObject> src_object = src.ToHeapObject();
+          if (info()->IsOptimizing() &&
+              src_object.is_identical_to(info()->context())) {
+            // Loading the context from the frame is way cheaper than
+            // materializing the actual context heap object address.
+            __ ldr(dst, MemOperand(fp, StandardFrameConstants::kContextOffset));
+          } else if (info()->IsOptimizing() &&
+                     src_object.is_identical_to(info()->closure())) {
+            // Loading the JSFunction from the frame is way cheaper than
+            // materializing the actual JSFunction heap object address.
+            __ ldr(dst,
+                   MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+          } else {
+            __ Move(dst, src_object);
+          }
           break;
+        }
         case Constant::kRpoNumber:
           UNREACHABLE();  // TODO(dcarney): loading RPO constants on arm.
           break;
index 762b57a6bc2a8778bdd4f0a3b368e155e1a92953..c0f22b70636ba0c54b8dff29de08af5394040485 100644 (file)
@@ -1126,7 +1126,21 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
       Register dst = destination->IsRegister() ? g.ToRegister(destination)
                                                : scope.AcquireX();
       if (src.type() == Constant::kHeapObject) {
-        __ LoadObject(dst, src.ToHeapObject());
+        Handle<HeapObject> src_object = src.ToHeapObject();
+        if (info()->IsOptimizing() &&
+            src_object.is_identical_to(info()->context())) {
+          // Loading the context from the frame is way cheaper than
+          // materializing the actual context heap object address.
+          __ Ldr(dst, MemOperand(fp, StandardFrameConstants::kContextOffset));
+        } else if (info()->IsOptimizing() &&
+                   src_object.is_identical_to(info()->closure())) {
+          // Loading the JSFunction from the frame is way cheaper than
+          // materializing the actual JSFunction heap object address.
+          __ Ldr(dst,
+                 MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+        } else {
+          __ LoadObject(dst, src_object);
+        }
       } else {
         __ Mov(dst, g.ToImmediate(source));
       }
index 447a8e3b1c75d7302a76c97ccf30543b44efbc57..298f53cca6337bcbba9f3cf6182f4a256555aa1f 100644 (file)
@@ -1273,6 +1273,19 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
           __ push(Operand(ebp, StandardFrameConstants::kContextOffset));
           __ pop(dst);
         }
+      } else if (info()->IsOptimizing() &&
+                 src.is_identical_to(info()->closure())) {
+        // Loading the JSFunction from the frame is way cheaper than
+        // materializing the actual JSFunction heap object address.
+        if (destination->IsRegister()) {
+          Register dst = g.ToRegister(destination);
+          __ mov(dst, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
+        } else {
+          DCHECK(destination->IsStackSlot());
+          Operand dst = g.ToOperand(destination);
+          __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
+          __ pop(dst);
+        }
       } else if (destination->IsRegister()) {
         Register dst = g.ToRegister(destination);
         __ LoadHeapObject(dst, src);
index 443f1b1efdd4676d601da77cc02c2f5e0971cc6a..b684ab3ad1bd5159c9b8ad197b3bad4d66895fff 100644 (file)
@@ -1464,6 +1464,12 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
             // Loading the context from the frame is way cheaper than
             // materializing the actual context heap object address.
             __ movp(dst, Operand(rbp, StandardFrameConstants::kContextOffset));
+          } else if (info()->IsOptimizing() &&
+                     src_object.is_identical_to(info()->closure())) {
+            // Loading the JSFunction from the frame is way cheaper than
+            // materializing the actual JSFunction heap object address.
+            __ movp(dst,
+                    Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
           } else {
             __ Move(dst, src_object);
           }