Revision: 17079
Author:   [email protected]
Date:     Wed Oct  2 13:27:53 2013 UTC
Log:      Add support to load/store byte fields.

This adds a new Byte representation and support for zero-extended
loads in HLoadNamedField and truncated stores in HStoreNamedField.

[email protected]

Review URL: https://codereview.chromium.org/25696004
http://code.google.com/p/v8/source/detail?r=17079

Modified:
 /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
 /branches/bleeding_edge/src/hydrogen-instructions.cc
 /branches/bleeding_edge/src/hydrogen-instructions.h
 /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc
 /branches/bleeding_edge/src/property-details.h
 /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc
 /branches/bleeding_edge/src/x64/lithium-x64.cc
 /branches/bleeding_edge/src/x64/macro-assembler-x64.cc
 /branches/bleeding_edge/src/x64/macro-assembler-x64.h

=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Wed Oct 2 11:43:41 2013 UTC +++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Wed Oct 2 13:27:53 2013 UTC
@@ -3042,7 +3042,12 @@

   if (access.IsExternalMemory()) {
     Register result = ToRegister(instr->result());
-    __ ldr(result, MemOperand(object, offset));
+    MemOperand operand = MemOperand(object, offset);
+    if (access.representation().IsByte()) {
+      __ ldrb(result, operand);
+    } else {
+      __ ldr(result, operand);
+    }
     return;
   }

@@ -3053,11 +3058,15 @@
   }

   Register result = ToRegister(instr->result());
-  if (access.IsInobject()) {
-    __ ldr(result, FieldMemOperand(object, offset));
-  } else {
+  if (!access.IsInobject()) {
     __ ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
-    __ ldr(result, FieldMemOperand(result, offset));
+    object = result;
+  }
+  MemOperand operand = FieldMemOperand(object, offset);
+  if (access.representation().IsByte()) {
+    __ ldrb(result, operand);
+  } else {
+    __ ldr(result, operand);
   }
 }

@@ -4163,7 +4172,12 @@

   if (access.IsExternalMemory()) {
     Register value = ToRegister(instr->value());
-    __ str(value, MemOperand(object, offset));
+    MemOperand operand = MemOperand(object, offset);
+    if (representation.IsByte()) {
+      __ strb(value, operand);
+    } else {
+      __ str(value, operand);
+    }
     return;
   }

@@ -4208,7 +4222,12 @@
       instr->hydrogen()->value()->IsHeapObject()
           ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
   if (access.IsInobject()) {
-    __ str(value, FieldMemOperand(object, offset));
+    MemOperand operand = FieldMemOperand(object, offset);
+    if (representation.IsByte()) {
+      __ strb(value, operand);
+    } else {
+      __ str(value, operand);
+    }
     if (instr->hydrogen()->NeedsWriteBarrier()) {
       // Update the write barrier for the object for in-object properties.
       __ RecordWriteField(object,
@@ -4222,7 +4241,12 @@
     }
   } else {
     __ ldr(scratch, FieldMemOperand(object, JSObject::kPropertiesOffset));
-    __ str(value, FieldMemOperand(scratch, offset));
+    MemOperand operand = FieldMemOperand(scratch, offset);
+    if (representation.IsByte()) {
+      __ strb(value, operand);
+    } else {
+      __ str(value, operand);
+    }
     if (instr->hydrogen()->NeedsWriteBarrier()) {
       // Update the write barrier for the properties array.
       // object is used as a scratch register.
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.cc Wed Oct 2 11:43:41 2013 UTC +++ /branches/bleeding_edge/src/hydrogen-instructions.cc Wed Oct 2 13:27:53 2013 UTC
@@ -2829,6 +2829,9 @@


 Range* HLoadNamedField::InferRange(Zone* zone) {
+  if (access().representation().IsByte()) {
+    return new(zone) Range(0, 255);
+  }
   if (access().IsStringLength()) {
     return new(zone) Range(0, String::kMaxLength);
   }
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.h Wed Oct 2 12:16:57 2013 UTC +++ /branches/bleeding_edge/src/hydrogen-instructions.h Wed Oct 2 13:27:53 2013 UTC
@@ -5934,7 +5934,9 @@
     SetOperandAt(0, object);

     Representation representation = access.representation();
-    if (representation.IsSmi()) {
+    if (representation.IsByte()) {
+      set_representation(Representation::Integer32());
+    } else if (representation.IsSmi()) {
       set_type(HType::Smi());
       set_representation(representation);
     } else if (representation.IsDouble() ||
@@ -6232,11 +6234,14 @@
     if (index == 0 && access().IsExternalMemory()) {
       // object must be external in case of external memory access
       return Representation::External();
-    } else if (index == 1 &&
-        (field_representation().IsDouble() ||
-         field_representation().IsSmi() ||
-         field_representation().IsInteger32())) {
-      return field_representation();
+    } else if (index == 1) {
+      if (field_representation().IsByte() ||
+          field_representation().IsInteger32()) {
+        return Representation::Integer32();
+      } else if (field_representation().IsDouble() ||
+                 field_representation().IsSmi()) {
+        return field_representation();
+      }
     }
     return Representation::Tagged();
   }
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Wed Oct 2 11:43:41 2013 UTC +++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Wed Oct 2 13:27:53 2013 UTC
@@ -3225,12 +3225,15 @@

   if (access.IsExternalMemory()) {
     Register result = ToRegister(instr->result());
-    if (instr->object()->IsConstantOperand()) {
-      ExternalReference external_reference = ToExternalReference(
-          LConstantOperand::cast(instr->object()));
-      __ mov(result, MemOperand::StaticVariable(external_reference));
+    MemOperand operand = instr->object()->IsConstantOperand()
+        ? MemOperand::StaticVariable(ToExternalReference(
+                LConstantOperand::cast(instr->object())))
+        : MemOperand(ToRegister(instr->object()), offset);
+    if (access.representation().IsByte()) {
+      ASSERT(instr->hydrogen()->representation().IsInteger32());
+      __ movzx_b(result, operand);
     } else {
-      __ mov(result, MemOperand(ToRegister(instr->object()), offset));
+      __ mov(result, operand);
     }
     return;
   }
@@ -3249,11 +3252,15 @@
   }

   Register result = ToRegister(instr->result());
-  if (access.IsInobject()) {
+  if (!access.IsInobject()) {
+    __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset));
+    object = result;
+  }
+  if (access.representation().IsByte()) {
+    ASSERT(instr->hydrogen()->representation().IsInteger32());
+    __ movzx_b(result, FieldOperand(object, offset));
+  } else {
     __ mov(result, FieldOperand(object, offset));
-  } else {
-    __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset));
-    __ mov(result, FieldOperand(result, offset));
   }
 }

@@ -4429,10 +4436,18 @@
         : MemOperand(ToRegister(instr->object()), offset);
     if (instr->value()->IsConstantOperand()) {
LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
-      __ mov(operand, Immediate(ToInteger32(operand_value)));
+      if (representation.IsByte()) {
+        __ mov_b(operand, ToInteger32(operand_value));
+      } else {
+        __ mov(operand, Immediate(ToInteger32(operand_value)));
+      }
     } else {
       Register value = ToRegister(instr->value());
-      __ mov(operand, value);
+      if (representation.IsByte()) {
+        __ mov_b(operand, value);
+      } else {
+        __ mov(operand, value);
+      }
     }
     return;
   }
@@ -4505,17 +4520,28 @@
__ mov(write_register, FieldOperand(object, JSObject::kPropertiesOffset));
   }

+  MemOperand operand = FieldOperand(write_register, offset);
   if (instr->value()->IsConstantOperand()) {
LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
     if (operand_value->IsRegister()) {
- __ mov(FieldOperand(write_register, offset), ToRegister(operand_value));
+      Register value = ToRegister(operand_value);
+      if (representation.IsByte()) {
+        __ mov_b(operand, value);
+      } else {
+        __ mov(operand, value);
+      }
     } else {
       Handle<Object> handle_value = ToHandle(operand_value);
       ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
-      __ mov(FieldOperand(write_register, offset), handle_value);
+      __ mov(operand, handle_value);
     }
   } else {
- __ mov(FieldOperand(write_register, offset), ToRegister(instr->value()));
+    Register value = ToRegister(instr->value());
+    if (representation.IsByte()) {
+      __ mov_b(operand, value);
+    } else {
+      __ mov(operand, value);
+    }
   }

   if (instr->hydrogen()->NeedsWriteBarrier()) {
=======================================
--- /branches/bleeding_edge/src/property-details.h Tue Aug 27 14:09:26 2013 UTC +++ /branches/bleeding_edge/src/property-details.h Wed Oct 2 13:27:53 2013 UTC
@@ -82,6 +82,7 @@
  public:
   enum Kind {
     kNone,
+    kByte,
     kSmi,
     kInteger32,
     kDouble,
@@ -95,6 +96,7 @@

   static Representation None() { return Representation(kNone); }
   static Representation Tagged() { return Representation(kTagged); }
+  static Representation Byte() { return Representation(kByte); }
   static Representation Smi() { return Representation(kSmi); }
   static Representation Integer32() { return Representation(kInteger32); }
   static Representation Double() { return Representation(kDouble); }
@@ -139,6 +141,7 @@

   Kind kind() const { return static_cast<Kind>(kind_); }
   bool IsNone() const { return kind_ == kNone; }
+  bool IsByte() const { return kind_ == kByte; }
   bool IsTagged() const { return kind_ == kTagged; }
   bool IsSmi() const { return kind_ == kSmi; }
   bool IsSmiOrTagged() const { return IsSmi() || IsTagged(); }
@@ -148,7 +151,7 @@
   bool IsHeapObject() const { return kind_ == kHeapObject; }
   bool IsExternal() const { return kind_ == kExternal; }
   bool IsSpecialization() const {
-    return kind_ == kInteger32 || kind_ == kDouble || kind_ == kSmi;
+    return IsByte() || IsSmi() || IsInteger32() || IsDouble();
   }
   const char* Mnemonic() const;

=======================================
--- /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Wed Oct 2 11:43:41 2013 UTC +++ /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Wed Oct 2 13:27:53 2013 UTC
@@ -2726,14 +2726,13 @@
   int offset = access.offset();

   if (access.IsExternalMemory()) {
-    ASSERT(!access.representation().IsInteger32());
     Register result = ToRegister(instr->result());
     if (instr->object()->IsConstantOperand()) {
       ASSERT(result.is(rax));
__ load_rax(ToExternalReference(LConstantOperand::cast(instr->object())));
     } else {
       Register object = ToRegister(instr->object());
-      __ movq(result, MemOperand(object, offset));
+      __ Load(result, MemOperand(object, offset), access.representation());
     }
     return;
   }
@@ -2747,20 +2746,11 @@
   }

   Register result = ToRegister(instr->result());
-  if (access.IsInobject()) {
-    if (access.representation().IsInteger32()) {
-      __ movl(result, FieldOperand(object, offset));
-    } else {
-      __ movq(result, FieldOperand(object, offset));
-    }
-  } else {
+  if (!access.IsInobject()) {
     __ movq(result, FieldOperand(object, JSObject::kPropertiesOffset));
-    if (access.representation().IsInteger32()) {
-      __ movl(result, FieldOperand(result, offset));
-    } else {
-      __ movq(result, FieldOperand(result, offset));
-    }
+    object = result;
   }
+  __ Load(result, FieldOperand(object, offset), access.representation());
 }


@@ -3878,16 +3868,16 @@
   int offset = access.offset();

   if (access.IsExternalMemory()) {
-    ASSERT(!access.representation().IsInteger32());
     ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
     Register value = ToRegister(instr->value());
     if (instr->object()->IsConstantOperand()) {
       ASSERT(value.is(rax));
+      ASSERT(!access.representation().IsSpecialization());
       LConstantOperand* object = LConstantOperand::cast(instr->object());
       __ store_rax(ToExternalReference(object));
     } else {
       Register object = ToRegister(instr->object());
-      __ movq(MemOperand(object, offset), value);
+      __ Store(MemOperand(object, offset), value, representation);
     }
     return;
   }
@@ -3956,24 +3946,16 @@
   if (instr->value()->IsConstantOperand()) {
LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
     if (operand_value->IsRegister()) {
-      if (access.representation().IsInteger32()) {
-        __ movl(FieldOperand(write_register, offset),
-                ToRegister(operand_value));
-      } else {
-        __ movq(FieldOperand(write_register, offset),
-                ToRegister(operand_value));
-      }
+      Register value = ToRegister(operand_value);
+ __ Store(FieldOperand(write_register, offset), value, representation);
     } else {
       Handle<Object> handle_value = ToHandle(operand_value);
       ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
       __ Move(FieldOperand(write_register, offset), handle_value);
     }
   } else {
-    if (access.representation().IsInteger32()) {
- __ movl(FieldOperand(write_register, offset), ToRegister(instr->value()));
-    } else {
- __ movq(FieldOperand(write_register, offset), ToRegister(instr->value()));
-    }
+    Register value = ToRegister(instr->value());
+    __ Store(FieldOperand(write_register, offset), value, representation);
   }

   if (instr->hydrogen()->NeedsWriteBarrier()) {
=======================================
--- /branches/bleeding_edge/src/x64/lithium-x64.cc Wed Oct 2 11:43:41 2013 UTC +++ /branches/bleeding_edge/src/x64/lithium-x64.cc Wed Oct 2 13:27:53 2013 UTC
@@ -2068,7 +2068,14 @@


 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
- if (instr->access().IsExternalMemory() && instr->access().offset() == 0) {
+  // Use the special mov rax, moffs64 encoding for external
+  // memory accesses with 64-bit word-sized values.
+  if (instr->access().IsExternalMemory() &&
+      instr->access().offset() == 0 &&
+      (instr->access().representation().IsSmi() ||
+       instr->access().representation().IsTagged() ||
+       instr->access().representation().IsHeapObject() ||
+       instr->access().representation().IsExternal())) {
     LOperand* obj = UseRegisterOrConstantAtStart(instr->object());
     return DefineFixed(new(zone()) LLoadNamedField(obj), rax);
   }
=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Wed Oct 2 11:46:01 2013 UTC +++ /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Wed Oct 2 13:27:53 2013 UTC
@@ -945,6 +945,28 @@
   xorps(dst, dst);
   cvtlsi2sd(dst, src);
 }
+
+
+void MacroAssembler::Load(Register dst, const Operand& src, Representation r) {
+  if (r.IsByte()) {
+    movzxbl(dst, src);
+  } else if (r.IsInteger32()) {
+    movl(dst, src);
+  } else {
+    movq(dst, src);
+  }
+}
+
+
+void MacroAssembler::Store(const Operand& dst, Register src, Representation r) {
+  if (r.IsByte()) {
+    movb(dst, src);
+  } else if (r.IsInteger32()) {
+    movl(dst, src);
+  } else {
+    movq(dst, src);
+  }
+}


 void MacroAssembler::Set(Register dst, int64_t x) {
=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.h Wed Oct 2 11:46:01 2013 UTC +++ /branches/bleeding_edge/src/x64/macro-assembler-x64.h Wed Oct 2 13:27:53 2013 UTC
@@ -781,6 +781,10 @@
// ---------------------------------------------------------------------------
   // Macro instructions.

+  // Load/store with specific representation.
+  void Load(Register dst, const Operand& src, Representation r);
+  void Store(const Operand& dst, Register src, Representation r);
+
   // Load a register with a long value as efficiently as possible.
   void Set(Register dst, int64_t x);
   void Set(const Operand& dst, int64_t x);

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to