[turbofan] Load immortal heap objects from the heap roots.
authorbmeurer <bmeurer@chromium.org>
Tue, 14 Apr 2015 12:50:43 +0000 (05:50 -0700)
committerCommit bot <commit-bot@chromium.org>
Tue, 14 Apr 2015 12:50:37 +0000 (12:50 +0000)
It's cheaper to materialize heap constants by loading from the roots
array instead of embedding the constant into the instruction stream, at
least on x64, arm and arm64.

Drive-by-fix: Also cleanup the materialize constant from frame
optimization.

R=dcarney@chromium.org

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

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

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

index 4c5b2924c58275d1a7fefccf29708956673d401f..21415c4dee6a9e85fd6440637d66f4b8e84b07d4 100644 (file)
@@ -1018,17 +1018,12 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
           break;
         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));
+          Heap::RootListIndex index;
+          int offset;
+          if (IsMaterializableFromFrame(src_object, &offset)) {
+            __ ldr(dst, MemOperand(fp, offset));
+          } else if (IsMaterializableFromRoot(src_object, &index)) {
+            __ LoadRoot(dst, index);
           } else {
             __ Move(dst, src_object);
           }
index 964ef3813102582422c230c6c8ec2d350e469c09..e65a0b7e615a1316eb8cda240b2e5c805a01c470 100644 (file)
@@ -1128,17 +1128,12 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
                                                : scope.AcquireX();
       if (src.type() == 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));
+        Heap::RootListIndex index;
+        int offset;
+        if (IsMaterializableFromFrame(src_object, &offset)) {
+          __ Ldr(dst, MemOperand(fp, offset));
+        } else if (IsMaterializableFromRoot(src_object, &index)) {
+          __ LoadRoot(dst, index);
         } else {
           __ LoadObject(dst, src_object);
         }
index cb2e4c8e42f49e04da1577761b642d13c17ffe55..49441e8f748277403ad9beddb3feaa65fa8d7d31 100644 (file)
@@ -184,6 +184,36 @@ void CodeGenerator::RecordSafepoint(ReferenceMap* references,
 }
 
 
+bool CodeGenerator::IsMaterializableFromFrame(Handle<HeapObject> object,
+                                              int* offset_return) {
+  if (linkage()->GetIncomingDescriptor()->IsJSFunctionCall()) {
+    if (object.is_identical_to(info()->context())) {
+      *offset_return = StandardFrameConstants::kContextOffset;
+      return true;
+    } else if (object.is_identical_to(info()->closure())) {
+      *offset_return = JavaScriptFrameConstants::kFunctionOffset;
+      return true;
+    }
+  }
+  return false;
+}
+
+
+bool CodeGenerator::IsMaterializableFromRoot(
+    Handle<HeapObject> object, Heap::RootListIndex* index_return) {
+  if (linkage()->GetIncomingDescriptor()->IsJSFunctionCall()) {
+#define IMMORTAL_IMMOVABLE_ROOT(Name)                                 \
+  if (*object == isolate()->heap()->root(Heap::k##Name##RootIndex)) { \
+    *index_return = Heap::k##Name##RootIndex;                         \
+    return true;                                                      \
+  }
+    IMMORTAL_IMMOVABLE_ROOT_LIST(IMMORTAL_IMMOVABLE_ROOT)
+#undef IMMORTAL_IMMOVABLE_ROOT
+  }
+  return false;
+}
+
+
 void CodeGenerator::AssembleInstruction(Instruction* instr) {
   AssembleGaps(instr);
   AssembleSourcePosition(instr);
index 641bbed1a1d6498af477f9eddb5a8c1bd1b25b37..9b3c51f97cb89b4d8ac7d48dfc65f1e9450456b2 100644 (file)
@@ -58,6 +58,15 @@ class CodeGenerator FINAL : public GapResolver::Assembler {
   void RecordSafepoint(ReferenceMap* references, Safepoint::Kind kind,
                        int arguments, Safepoint::DeoptMode deopt_mode);
 
+  // Check if a heap object can be materialized by loading from the frame, which
+  // is usually way cheaper than materializing the actual heap object constant.
+  bool IsMaterializableFromFrame(Handle<HeapObject> object, int* offset_return);
+  // Check if a heap object can be materialized by loading from a heap root,
+  // which is cheaper on some platforms than materializing the actual heap
+  // object constant.
+  bool IsMaterializableFromRoot(Handle<HeapObject> object,
+                                Heap::RootListIndex* index_return);
+
   // Assemble code for the specified instruction.
   void AssembleInstruction(Instruction* instr);
   void AssembleSourcePosition(Instruction* instr);
index 76a457b8f6645d82b8c97753511fe4777df111e4..2bb240dea5996f3a3a156a5a9b9263e3460df0a7 100644 (file)
@@ -1309,29 +1309,15 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
     Constant src_constant = g.ToConstant(source);
     if (src_constant.type() == Constant::kHeapObject) {
       Handle<HeapObject> src = src_constant.ToHeapObject();
-      if (info()->IsOptimizing() && src.is_identical_to(info()->context())) {
-        // Loading the context from the frame is way cheaper than materializing
-        // the actual context heap object address.
+      int offset;
+      if (IsMaterializableFromFrame(src, &offset)) {
         if (destination->IsRegister()) {
           Register dst = g.ToRegister(destination);
-          __ mov(dst, Operand(ebp, StandardFrameConstants::kContextOffset));
+          __ mov(dst, Operand(ebp, offset));
         } else {
           DCHECK(destination->IsStackSlot());
           Operand dst = g.ToOperand(destination);
-          __ 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));
+          __ push(Operand(ebp, offset));
           __ pop(dst);
         }
       } else if (destination->IsRegister()) {
index 4213c9f135131957dc51e93505a2b7f4444df20f..f4b90e92624750a8148953cb0dd27dcabfcd62ee 100644 (file)
@@ -1531,17 +1531,12 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
           break;
         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.
-            __ 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));
+          Heap::RootListIndex index;
+          int offset;
+          if (IsMaterializableFromFrame(src_object, &offset)) {
+            __ movp(dst, Operand(rbp, offset));
+          } else if (IsMaterializableFromRoot(src_object, &index)) {
+            __ LoadRoot(dst, index);
           } else {
             __ Move(dst, src_object);
           }