Reland 17588: Add signed/unsigned 8-bit and 16-bit Representations to Crankshaft
authordanno@chromium.org <danno@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 8 Nov 2013 17:35:58 +0000 (17:35 +0000)
committerdanno@chromium.org <danno@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 8 Nov 2013 17:35:58 +0000 (17:35 +0000)
R=ulan@chromium.org

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@17606 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

18 files changed:
src/arm/lithium-codegen-arm.cc
src/arm/macro-assembler-arm.cc
src/arm/macro-assembler-arm.h
src/globals.h
src/hydrogen-instructions.cc
src/hydrogen-instructions.h
src/hydrogen-load-elimination.cc
src/ia32/lithium-codegen-ia32.cc
src/ia32/lithium-ia32.cc
src/ia32/macro-assembler-ia32.cc
src/ia32/macro-assembler-ia32.h
src/property-details.h
src/x64/macro-assembler-x64.cc
test/cctest/cctest.gyp
test/cctest/test-macro-assembler-arm.cc
test/cctest/test-macro-assembler-ia32.cc [new file with mode: 0644]
test/cctest/test-macro-assembler-x64.cc
test/cctest/test-representation.cc [new file with mode: 0644]

index dbfb73a..8049b68 100644 (file)
@@ -3080,11 +3080,7 @@ void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
   if (access.IsExternalMemory()) {
     Register result = ToRegister(instr->result());
     MemOperand operand = MemOperand(object, offset);
-    if (access.representation().IsByte()) {
-      __ ldrb(result, operand);
-    } else {
-      __ ldr(result, operand);
-    }
+    __ Load(result, operand, access.representation());
     return;
   }
 
@@ -3100,11 +3096,7 @@ void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
     object = result;
   }
   MemOperand operand = FieldMemOperand(object, offset);
-  if (access.representation().IsByte()) {
-    __ ldrb(result, operand);
-  } else {
-    __ ldr(result, operand);
-  }
+  __ Load(result, operand, access.representation());
 }
 
 
@@ -4207,11 +4199,7 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
   if (access.IsExternalMemory()) {
     Register value = ToRegister(instr->value());
     MemOperand operand = MemOperand(object, offset);
-    if (representation.IsByte()) {
-      __ strb(value, operand);
-    } else {
-      __ str(value, operand);
-    }
+    __ Store(value, operand, representation);
     return;
   }
 
@@ -4257,11 +4245,7 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
           ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
   if (access.IsInobject()) {
     MemOperand operand = FieldMemOperand(object, offset);
-    if (representation.IsByte()) {
-      __ strb(value, operand);
-    } else {
-      __ str(value, operand);
-    }
+    __ Store(value, operand, representation);
     if (instr->hydrogen()->NeedsWriteBarrier()) {
       // Update the write barrier for the object for in-object properties.
       __ RecordWriteField(object,
@@ -4276,11 +4260,7 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
   } else {
     __ ldr(scratch, FieldMemOperand(object, JSObject::kPropertiesOffset));
     MemOperand operand = FieldMemOperand(scratch, offset);
-    if (representation.IsByte()) {
-      __ strb(value, operand);
-    } else {
-      __ str(value, operand);
-    }
+    __ Store(value, operand, representation);
     if (instr->hydrogen()->NeedsWriteBarrier()) {
       // Update the write barrier for the properties array.
       // object is used as a scratch register.
index 7a5bef8..82066a6 100644 (file)
@@ -384,6 +384,38 @@ void MacroAssembler::Usat(Register dst, int satpos, const Operand& src,
 }
 
 
+void MacroAssembler::Load(Register dst,
+                          const MemOperand& src,
+                          Representation r) {
+  ASSERT(!r.IsDouble());
+  if (r.IsInteger8()) {
+    ldrsb(dst, src);
+  } else if (r.IsUInteger8()) {
+    ldrb(dst, src);
+  } else if (r.IsInteger16()) {
+    ldrsh(dst, src);
+  } else if (r.IsUInteger16()) {
+    ldrh(dst, src);
+  } else {
+    ldr(dst, src);
+  }
+}
+
+
+void MacroAssembler::Store(Register src,
+                           const MemOperand& dst,
+                           Representation r) {
+  ASSERT(!r.IsDouble());
+  if (r.IsInteger8() || r.IsUInteger8()) {
+    strb(src, dst);
+  } else if (r.IsInteger16() || r.IsUInteger16()) {
+    strh(src, dst);
+  } else {
+    str(src, dst);
+  }
+}
+
+
 void MacroAssembler::LoadRoot(Register destination,
                               Heap::RootListIndex index,
                               Condition cond) {
index 6fb7434..97b2575 100644 (file)
@@ -161,6 +161,9 @@ class MacroAssembler: public Assembler {
   void Move(Register dst, Register src, Condition cond = al);
   void Move(DwVfpRegister dst, DwVfpRegister src);
 
+  void Load(Register dst, const MemOperand& src, Representation r);
+  void Store(Register src, const MemOperand& dst, Representation r);
+
   // Load an object from the root table.
   void LoadRoot(Register destination,
                 Heap::RootListIndex index,
index 3456030..1db48a1 100644 (file)
@@ -226,6 +226,14 @@ const int MB = KB * KB;
 const int GB = KB * KB * KB;
 const int kMaxInt = 0x7FFFFFFF;
 const int kMinInt = -kMaxInt - 1;
+const int kMaxInt8 = (1 << 7) - 1;
+const int kMinInt8 = -(1 << 7);
+const int kMaxUInt8 = (1 << 8) - 1;
+const int kMinUInt8 = 0;
+const int kMaxInt16 = (1 << 15) - 1;
+const int kMinInt16 = -(1 << 15);
+const int kMaxUInt16 = (1 << 16) - 1;
+const int kMinUInt16 = 0;
 
 const uint32_t kMaxUInt32 = 0xFFFFFFFFu;
 
index 02abf0b..79962db 100644 (file)
@@ -2856,8 +2856,17 @@ Range* HShl::InferRange(Zone* zone) {
 
 
 Range* HLoadNamedField::InferRange(Zone* zone) {
-  if (access().representation().IsByte()) {
-    return new(zone) Range(0, 255);
+  if (access().representation().IsInteger8()) {
+    return new(zone) Range(kMinInt8, kMaxInt8);
+  }
+  if (access().representation().IsUInteger8()) {
+    return new(zone) Range(kMinUInt8, kMaxUInt8);
+  }
+  if (access().representation().IsInteger16()) {
+    return new(zone) Range(kMinInt16, kMaxInt16);
+  }
+  if (access().representation().IsUInteger16()) {
+    return new(zone) Range(kMinUInt16, kMaxUInt16);
   }
   if (access().IsStringLength()) {
     return new(zone) Range(0, String::kMaxLength);
@@ -2868,16 +2877,15 @@ Range* HLoadNamedField::InferRange(Zone* zone) {
 
 Range* HLoadKeyed::InferRange(Zone* zone) {
   switch (elements_kind()) {
-    case EXTERNAL_PIXEL_ELEMENTS:
-      return new(zone) Range(0, 255);
     case EXTERNAL_BYTE_ELEMENTS:
-      return new(zone) Range(-128, 127);
+      return new(zone) Range(kMinInt8, kMaxInt8);
     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
-      return new(zone) Range(0, 255);
+    case EXTERNAL_PIXEL_ELEMENTS:
+      return new(zone) Range(kMinUInt8, kMaxUInt8);
     case EXTERNAL_SHORT_ELEMENTS:
-      return new(zone) Range(-32768, 32767);
+      return new(zone) Range(kMinInt16, kMaxInt16);
     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
-      return new(zone) Range(0, 65535);
+      return new(zone) Range(kMinUInt16, kMaxUInt16);
     default:
       return HValue::InferRange(zone);
   }
index 02af875..b9c0ca9 100644 (file)
@@ -5860,7 +5860,7 @@ class HObjectAccess V8_FINAL {
   static HObjectAccess ForMapInstanceSize() {
     return HObjectAccess(kInobject,
                          Map::kInstanceSizeOffset,
-                         Representation::Byte());
+                         Representation::UInteger8());
   }
 
   static HObjectAccess ForPropertyCellValue() {
@@ -5938,8 +5938,8 @@ class HObjectAccess V8_FINAL {
   }
 
   class PortionField : public BitField<Portion, 0, 3> {};
-  class RepresentationField : public BitField<Representation::Kind, 3, 3> {};
-  class OffsetField : public BitField<int, 6, 26> {};
+  class RepresentationField : public BitField<Representation::Kind, 3, 4> {};
+  class OffsetField : public BitField<int, 7, 25> {};
 
   uint32_t value_;  // encodes portion, representation, and offset
   Handle<String> name_;
@@ -5992,7 +5992,10 @@ class HLoadNamedField V8_FINAL : public HTemplateInstruction<1> {
     SetOperandAt(0, object);
 
     Representation representation = access.representation();
-    if (representation.IsByte()) {
+    if (representation.IsInteger8() ||
+        representation.IsUInteger8() ||
+        representation.IsInteger16() ||
+        representation.IsUInteger16()) {
       set_representation(Representation::Integer32());
     } else if (representation.IsSmi()) {
       set_type(HType::Smi());
@@ -6302,7 +6305,10 @@ class HStoreNamedField V8_FINAL : public HTemplateInstruction<3> {
       // object must be external in case of external memory access
       return Representation::External();
     } else if (index == 1) {
-      if (field_representation().IsByte() ||
+      if (field_representation().IsInteger8() ||
+          field_representation().IsUInteger8() ||
+          field_representation().IsInteger16() ||
+          field_representation().IsUInteger16() ||
           field_representation().IsInteger32()) {
         return Representation::Integer32();
       } else if (field_representation().IsDouble() ||
index 3337188..f37de90 100644 (file)
@@ -272,9 +272,7 @@ class HLoadEliminationTable : public ZoneObject {
         KillFieldInternal(object, field, NULL);
 
         // Kill the next field in case of overlap.
-        int size = kPointerSize;
-        if (access.representation().IsByte()) size = 1;
-        else if (access.representation().IsInteger32()) size = 4;
+        int size = access.representation().size();
         int next_field = (offset + size - 1) / kPointerSize;
         if (next_field != field) KillFieldInternal(object, next_field, NULL);
       }
index 691feb3..89df802 100644 (file)
@@ -3273,12 +3273,7 @@ void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
         ? 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, operand);
-    }
+    __ Load(result, operand, access.representation());
     return;
   }
 
@@ -3300,12 +3295,7 @@ void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
     __ 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));
-  }
+  __ Load(result, FieldOperand(object, offset), access.representation());
 }
 
 
@@ -4478,16 +4468,11 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
             ToExternalReference(LConstantOperand::cast(instr->object())))
         : MemOperand(ToRegister(instr->object()), offset);
     if (instr->value()->IsConstantOperand()) {
-      ASSERT(!representation.IsByte());
       LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
       __ mov(operand, Immediate(ToInteger32(operand_value)));
     } else {
       Register value = ToRegister(instr->value());
-      if (representation.IsByte()) {
-        __ mov_b(operand, value);
-      } else {
-        __ mov(operand, value);
-      }
+      __ Store(value, operand, representation);
     }
     return;
   }
@@ -4565,11 +4550,7 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
     LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
     if (operand_value->IsRegister()) {
       Register value = ToRegister(operand_value);
-      if (representation.IsByte()) {
-        __ mov_b(operand, value);
-      } else {
-        __ mov(operand, value);
-      }
+      __ Store(value, operand, representation);
     } else {
       Handle<Object> handle_value = ToHandle(operand_value);
       ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
@@ -4577,11 +4558,7 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
     }
   } else {
     Register value = ToRegister(instr->value());
-    if (representation.IsByte()) {
-      __ mov_b(operand, value);
-    } else {
-      __ mov(operand, value);
-    }
+    __ Store(value, operand, representation);
   }
 
   if (instr->hydrogen()->NeedsWriteBarrier()) {
index 48d8c45..632b065 100644 (file)
@@ -2434,7 +2434,8 @@ LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
       !(FLAG_track_double_fields && instr->field_representation().IsDouble());
 
   LOperand* val;
-  if (instr->field_representation().IsByte()) {
+  if (instr->field_representation().IsInteger8() ||
+      instr->field_representation().IsUInteger8()) {
     // mov_b requires a byte register (i.e. any of eax, ebx, ecx, edx).
     // Just force the value to be in eax and we're safe here.
     val = UseFixed(instr->value(), eax);
index 235e38c..c673727 100644 (file)
@@ -56,6 +56,34 @@ MacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size)
 }
 
 
+void MacroAssembler::Load(Register dst, const Operand& src, Representation r) {
+  ASSERT(!r.IsDouble());
+  if (r.IsInteger8()) {
+    movsx_b(dst, src);
+  } else if (r.IsUInteger8()) {
+    movzx_b(dst, src);
+  } else if (r.IsInteger16()) {
+    movsx_w(dst, src);
+  } else if (r.IsUInteger16()) {
+    movzx_w(dst, src);
+  } else {
+    mov(dst, src);
+  }
+}
+
+
+void MacroAssembler::Store(Register src, const Operand& dst, Representation r) {
+  ASSERT(!r.IsDouble());
+  if (r.IsInteger8() || r.IsUInteger8()) {
+    mov_b(dst, src);
+  } else if (r.IsInteger16() || r.IsUInteger16()) {
+    mov_w(dst, src);
+  } else {
+    mov(dst, src);
+  }
+}
+
+
 void MacroAssembler::LoadRoot(Register destination, Heap::RootListIndex index) {
   if (isolate()->heap()->RootCanBeTreatedAsConstant(index)) {
     Handle<Object> value(&isolate()->heap()->roots_array_start()[index]);
index 5f1e428..29bb78d 100644 (file)
@@ -61,6 +61,9 @@ class MacroAssembler: public Assembler {
   // macro assembler.
   MacroAssembler(Isolate* isolate, void* buffer, int size);
 
+  void Load(Register dst, const Operand& src, Representation r);
+  void Store(Register src, const Operand& dst, Representation r);
+
   // Operations on roots in the root-array.
   void LoadRoot(Register destination, Heap::RootListIndex index);
   void StoreRoot(Register source, Register scratch, Heap::RootListIndex index);
index 659fbd1..92e4f81 100644 (file)
@@ -82,7 +82,10 @@ class Representation {
  public:
   enum Kind {
     kNone,
-    kByte,
+    kInteger8,
+    kUInteger8,
+    kInteger16,
+    kUInteger16,
     kSmi,
     kInteger32,
     kDouble,
@@ -96,7 +99,12 @@ class Representation {
 
   static Representation None() { return Representation(kNone); }
   static Representation Tagged() { return Representation(kTagged); }
-  static Representation Byte() { return Representation(kByte); }
+  static Representation Integer8() { return Representation(kInteger8); }
+  static Representation UInteger8() { return Representation(kUInteger8); }
+  static Representation Integer16() { return Representation(kInteger16); }
+  static Representation UInteger16() {
+    return Representation(kUInteger16);
+  }
   static Representation Smi() { return Representation(kSmi); }
   static Representation Integer32() { return Representation(kInteger32); }
   static Representation Double() { return Representation(kDouble); }
@@ -126,6 +134,8 @@ class Representation {
     ASSERT(kind_ != kExternal);
     ASSERT(other.kind_ != kExternal);
     if (IsHeapObject()) return other.IsDouble() || other.IsNone();
+    if (kind_ == kUInteger8 && other.kind_ == kInteger8) return false;
+    if (kind_ == kUInteger16 && other.kind_ == kInteger16) return false;
     return kind_ > other.kind_;
   }
 
@@ -139,9 +149,26 @@ class Representation {
     return Representation::Tagged();
   }
 
+  int size() const {
+    ASSERT(!IsNone());
+    if (IsInteger8() || IsUInteger8()) {
+      return sizeof(uint8_t);
+    }
+    if (IsInteger16() || IsUInteger16()) {
+      return sizeof(uint16_t);
+    }
+    if (IsInteger32()) {
+      return sizeof(uint32_t);
+    }
+    return kPointerSize;
+  }
+
   Kind kind() const { return static_cast<Kind>(kind_); }
   bool IsNone() const { return kind_ == kNone; }
-  bool IsByte() const { return kind_ == kByte; }
+  bool IsInteger8() const { return kind_ == kInteger8; }
+  bool IsUInteger8() const { return kind_ == kUInteger8; }
+  bool IsInteger16() const { return kind_ == kInteger16; }
+  bool IsUInteger16() const { return kind_ == kUInteger16; }
   bool IsTagged() const { return kind_ == kTagged; }
   bool IsSmi() const { return kind_ == kSmi; }
   bool IsSmiOrTagged() const { return IsSmi() || IsTagged(); }
@@ -151,7 +178,9 @@ class Representation {
   bool IsHeapObject() const { return kind_ == kHeapObject; }
   bool IsExternal() const { return kind_ == kExternal; }
   bool IsSpecialization() const {
-    return IsByte() || IsSmi() || IsInteger32() || IsDouble();
+    return IsInteger8() || IsUInteger8() ||
+      IsInteger16() || IsUInteger16() ||
+      IsSmi() || IsInteger32() || IsDouble();
   }
   const char* Mnemonic() const;
 
@@ -256,8 +285,8 @@ class PropertyDetails BASE_EMBEDDED {
 
   // Bit fields for fast objects.
   class DescriptorPointer:        public BitField<uint32_t,           6, 11> {};
-  class RepresentationField:      public BitField<uint32_t,          17,  3> {};
-  class FieldIndexField:          public BitField<uint32_t,          20, 11> {};
+  class RepresentationField:      public BitField<uint32_t,          17,  4> {};
+  class FieldIndexField:          public BitField<uint32_t,          21, 10> {};
 
   static const int kInitialIndex = 1;
 
index d91f0cf..9e8568c 100644 (file)
@@ -940,8 +940,14 @@ void MacroAssembler::Cvtlsi2sd(XMMRegister dst, const Operand& src) {
 
 void MacroAssembler::Load(Register dst, const Operand& src, Representation r) {
   ASSERT(!r.IsDouble());
-  if (r.IsByte()) {
+  if (r.IsInteger8()) {
+    movsxbq(dst, src);
+  } else if (r.IsUInteger8()) {
     movzxbl(dst, src);
+  } else if (r.IsInteger16()) {
+    movsxwq(dst, src);
+  } else if (r.IsUInteger16()) {
+    movzxwl(dst, src);
   } else if (r.IsInteger32()) {
     movl(dst, src);
   } else {
@@ -952,8 +958,10 @@ void MacroAssembler::Load(Register dst, const Operand& src, Representation r) {
 
 void MacroAssembler::Store(const Operand& dst, Register src, Representation r) {
   ASSERT(!r.IsDouble());
-  if (r.IsByte()) {
+  if (r.IsInteger8() || r.IsUInteger8()) {
     movb(dst, src);
+  } else if (r.IsInteger16() || r.IsUInteger16()) {
+    movw(dst, src);
   } else if (r.IsInteger32()) {
     movl(dst, src);
   } else {
index 1c7dad7..2017d61 100644 (file)
@@ -94,6 +94,7 @@
         'test-random-number-generator.cc',
         'test-regexp.cc',
         'test-reloc-info.cc',
+        'test-representation.cc',
         'test-semaphore.cc',
         'test-serialize.cc',
         'test-socket.cc',
             'test-code-stubs-ia32.cc',
             'test-cpu-ia32.cc',
             'test-disasm-ia32.cc',
+            'test-macro-assembler-ia32.cc',
             'test-log-stack-tracer.cc'
           ],
         }],
index 77f7abb..377450a 100644 (file)
@@ -132,5 +132,102 @@ TEST(CopyBytes) {
 }
 
 
+typedef int (*F5)(void*, void*, void*, void*, void*);
+
+
+TEST(LoadAndStoreWithRepresentation) {
+  v8::internal::V8::Initialize(NULL);
+
+  // Allocate an executable page of memory.
+  size_t actual_size;
+  byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
+                                                 &actual_size,
+                                                 true));
+  CHECK(buffer);
+  Isolate* isolate = CcTest::i_isolate();
+  HandleScope handles(isolate);
+  MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
+  MacroAssembler* masm = &assembler;  // Create a pointer for the __ macro.
+  masm->set_allow_stub_calls(false);
+  __ sub(sp, sp, Operand(1 * kPointerSize));
+  Label exit;
+
+  // Test 1.
+  __ mov(r0, Operand(1));  // Test number.
+  __ mov(r1, Operand(0));
+  __ str(r1, MemOperand(sp, 0 * kPointerSize));
+  __ mov(r2, Operand(-1));
+  __ Store(r2, MemOperand(sp, 0 * kPointerSize), Representation::UInteger8());
+  __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
+  __ mov(r2, Operand(255));
+  __ cmp(r3, r2);
+  __ b(ne, &exit);
+  __ mov(r2, Operand(255));
+  __ Load(r3, MemOperand(sp, 0 * kPointerSize), Representation::UInteger8());
+  __ cmp(r3, r2);
+  __ b(ne, &exit);
+
+  // Test 2.
+  __ mov(r0, Operand(2));  // Test number.
+  __ mov(r1, Operand(0));
+  __ str(r1, MemOperand(sp, 0 * kPointerSize));
+  __ mov(r2, Operand(-1));
+  __ Store(r2, MemOperand(sp, 0 * kPointerSize), Representation::Integer8());
+  __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
+  __ mov(r2, Operand(255));
+  __ cmp(r3, r2);
+  __ b(ne, &exit);
+  __ mov(r2, Operand(-1));
+  __ Load(r3, MemOperand(sp, 0 * kPointerSize), Representation::Integer8());
+  __ cmp(r3, r2);
+  __ b(ne, &exit);
+
+  // Test 3.
+  __ mov(r0, Operand(3));  // Test number.
+  __ mov(r1, Operand(0));
+  __ str(r1, MemOperand(sp, 0 * kPointerSize));
+  __ mov(r2, Operand(-1));
+  __ Store(r2, MemOperand(sp, 0 * kPointerSize), Representation::UInteger16());
+  __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
+  __ mov(r2, Operand(65535));
+  __ cmp(r3, r2);
+  __ b(ne, &exit);
+  __ mov(r2, Operand(65535));
+  __ Load(r3, MemOperand(sp, 0 * kPointerSize), Representation::UInteger16());
+  __ cmp(r3, r2);
+  __ b(ne, &exit);
+
+  // Test 4.
+  __ mov(r0, Operand(4));  // Test number.
+  __ mov(r1, Operand(0));
+  __ str(r1, MemOperand(sp, 0 * kPointerSize));
+  __ mov(r2, Operand(-1));
+  __ Store(r2, MemOperand(sp, 0 * kPointerSize), Representation::Integer16());
+  __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
+  __ mov(r2, Operand(65535));
+  __ cmp(r3, r2);
+  __ b(ne, &exit);
+  __ mov(r2, Operand(-1));
+  __ Load(r3, MemOperand(sp, 0 * kPointerSize), Representation::Integer16());
+  __ cmp(r3, r2);
+  __ b(ne, &exit);
+
+  __ mov(r0, Operand(0));  // Success.
+  __ bind(&exit);
+  __ add(sp, sp, Operand(1 * kPointerSize));
+  __ bx(lr);
+
+  CodeDesc desc;
+  masm->GetCode(&desc);
+  Object* code = isolate->heap()->CreateCode(
+      desc,
+      Code::ComputeFlags(Code::STUB),
+      Handle<Code>())->ToObjectChecked();
+  CHECK(code->IsCode());
+
+  // Call the function from C++.
+  F5 f = FUNCTION_CAST<F5>(Code::cast(code)->entry());
+  CHECK_EQ(0, CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0));
+}
 
 #undef __
diff --git a/test/cctest/test-macro-assembler-ia32.cc b/test/cctest/test-macro-assembler-ia32.cc
new file mode 100644 (file)
index 0000000..4c817dc
--- /dev/null
@@ -0,0 +1,140 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <stdlib.h>
+
+#include "v8.h"
+
+#include "macro-assembler.h"
+#include "factory.h"
+#include "platform.h"
+#include "serialize.h"
+#include "cctest.h"
+
+using namespace v8::internal;
+
+#if __GNUC__
+#define STDCALL  __attribute__((stdcall))
+#else
+#define STDCALL  __stdcall
+#endif
+
+typedef int STDCALL F0Type();
+typedef F0Type* F0;
+
+#define __ masm->
+
+
+TEST(LoadAndStoreWithRepresentation) {
+  v8::internal::V8::Initialize(NULL);
+
+  // Allocate an executable page of memory.
+  size_t actual_size;
+  byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
+                                                 &actual_size,
+                                                 true));
+  CHECK(buffer);
+  Isolate* isolate = CcTest::i_isolate();
+  HandleScope handles(isolate);
+  MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size));
+  MacroAssembler* masm = &assembler;  // Create a pointer for the __ macro.
+  masm->set_allow_stub_calls(false);
+  __ push(ebx);
+  __ push(edx);
+  __ sub(esp, Immediate(1 * kPointerSize));
+  Label exit;
+
+  // Test 1.
+  __ mov(eax, Immediate(1));  // Test number.
+  __ mov(Operand(esp, 0 * kPointerSize), Immediate(0));
+  __ mov(ebx, Immediate(-1));
+  __ Store(ebx, Operand(esp, 0 * kPointerSize), Representation::UInteger8());
+  __ mov(ebx, Operand(esp, 0 * kPointerSize));
+  __ mov(edx, Immediate(255));
+  __ cmp(ebx, edx);
+  __ j(not_equal, &exit);
+  __ Load(ebx, Operand(esp, 0 * kPointerSize), Representation::UInteger8());
+  __ cmp(ebx, edx);
+  __ j(not_equal, &exit);
+
+
+  // Test 2.
+  __ mov(eax, Immediate(2));  // Test number.
+  __ mov(Operand(esp, 0 * kPointerSize), Immediate(0));
+  __ mov(ebx, Immediate(-1));
+  __ Store(ebx, Operand(esp, 0 * kPointerSize), Representation::Integer8());
+  __ mov(ebx, Operand(esp, 0 * kPointerSize));
+  __ mov(edx, Immediate(255));
+  __ cmp(ebx, edx);
+  __ j(not_equal, &exit);
+  __ Load(ebx, Operand(esp, 0 * kPointerSize), Representation::Integer8());
+  __ mov(edx, Immediate(-1));
+  __ cmp(ebx, edx);
+  __ j(not_equal, &exit);
+
+  // Test 3.
+  __ mov(eax, Immediate(3));  // Test number.
+  __ mov(Operand(esp, 0 * kPointerSize), Immediate(0));
+  __ mov(ebx, Immediate(-1));
+  __ Store(ebx, Operand(esp, 0 * kPointerSize), Representation::Integer16());
+  __ mov(ebx, Operand(esp, 0 * kPointerSize));
+  __ mov(edx, Immediate(65535));
+  __ cmp(ebx, edx);
+  __ j(not_equal, &exit);
+  __ Load(edx, Operand(esp, 0 * kPointerSize), Representation::Integer16());
+  __ mov(ebx, Immediate(-1));
+  __ cmp(ebx, edx);
+  __ j(not_equal, &exit);
+
+  // Test 4.
+  __ mov(eax, Immediate(4));  // Test number.
+  __ mov(Operand(esp, 0 * kPointerSize), Immediate(0));
+  __ mov(ebx, Immediate(-1));
+  __ Store(ebx, Operand(esp, 0 * kPointerSize), Representation::UInteger16());
+  __ mov(ebx, Operand(esp, 0 * kPointerSize));
+  __ mov(edx, Immediate(65535));
+  __ cmp(ebx, edx);
+  __ j(not_equal, &exit);
+  __ Load(edx, Operand(esp, 0 * kPointerSize), Representation::UInteger16());
+  __ cmp(ebx, edx);
+  __ j(not_equal, &exit);
+
+  __ xor_(eax, eax);  // Success.
+  __ bind(&exit);
+  __ add(esp, Immediate(1 * kPointerSize));
+  __ pop(edx);
+  __ pop(ebx);
+  __ ret(0);
+
+  CodeDesc desc;
+  masm->GetCode(&desc);
+  // Call the function from C++.
+  int result = FUNCTION_CAST<F0>(buffer)();
+  CHECK_EQ(0, result);
+}
+
+#undef __
index 8262ab6..3d28fc0 100644 (file)
@@ -2704,12 +2704,12 @@ TEST(LoadAndStoreWithRepresentation) {
   __ movq(rax, Immediate(1));  // Test number.
   __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
   __ movq(rcx, Immediate(-1));
-  __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::Byte());
+  __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::UInteger8());
   __ movq(rcx, Operand(rsp, 0 * kPointerSize));
   __ movl(rdx, Immediate(255));
   __ cmpq(rcx, rdx);
   __ j(not_equal, &exit);
-  __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::Byte());
+  __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::UInteger8());
   __ cmpq(rcx, rdx);
   __ j(not_equal, &exit);
 
@@ -2778,6 +2778,47 @@ TEST(LoadAndStoreWithRepresentation) {
   __ cmpq(rcx, rdx);
   __ j(not_equal, &exit);
 
+  // Test 7.
+  __ movq(rax, Immediate(7));  // Test number.
+  __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
+  __ movq(rcx, Immediate(-1));
+  __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::Integer8());
+  __ movq(rcx, Operand(rsp, 0 * kPointerSize));
+  __ movl(rdx, Immediate(255));
+  __ cmpq(rcx, rdx);
+  __ j(not_equal, &exit);
+  __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::Integer8());
+  __ movq(rcx, Immediate(-1));
+  __ cmpq(rcx, rdx);
+  __ j(not_equal, &exit);
+
+  // Test 8.
+  __ movq(rax, Immediate(8));  // Test number.
+  __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
+  __ movq(rcx, Immediate(-1));
+  __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::Integer16());
+  __ movq(rcx, Operand(rsp, 0 * kPointerSize));
+  __ movl(rdx, Immediate(65535));
+  __ cmpq(rcx, rdx);
+  __ j(not_equal, &exit);
+  __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::Integer16());
+  __ movq(rcx, Immediate(-1));
+  __ cmpq(rcx, rdx);
+  __ j(not_equal, &exit);
+
+  // Test 9.
+  __ movq(rax, Immediate(9));  // Test number.
+  __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
+  __ movq(rcx, Immediate(-1));
+  __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::UInteger16());
+  __ movq(rcx, Operand(rsp, 0 * kPointerSize));
+  __ movl(rdx, Immediate(65535));
+  __ cmpq(rcx, rdx);
+  __ j(not_equal, &exit);
+  __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::UInteger16());
+  __ cmpq(rcx, rdx);
+  __ j(not_equal, &exit);
+
   __ xor_(rax, rax);  // Success.
   __ bind(&exit);
   __ addq(rsp, Immediate(1 * kPointerSize));
diff --git a/test/cctest/test-representation.cc b/test/cctest/test-representation.cc
new file mode 100644 (file)
index 0000000..15321f3
--- /dev/null
@@ -0,0 +1,124 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "cctest.h"
+#include "types.h"
+#include "property-details.h"
+
+using namespace v8::internal;
+
+
+void TestPairPositive(Representation more_general,
+              Representation less_general) {
+  CHECK(more_general.is_more_general_than(less_general));
+}
+
+
+void TestPairNegative(Representation more_general,
+              Representation less_general) {
+  CHECK(!more_general.is_more_general_than(less_general));
+}
+
+
+TEST(RepresentationMoreGeneralThan) {
+  TestPairNegative(Representation::None(), Representation::None());
+  TestPairPositive(Representation::Integer8(), Representation::None());
+  TestPairPositive(Representation::UInteger8(), Representation::None());
+  TestPairPositive(Representation::Integer16(), Representation::None());
+  TestPairPositive(Representation::UInteger16(), Representation::None());
+  TestPairPositive(Representation::Smi(), Representation::None());
+  TestPairPositive(Representation::Integer32(), Representation::None());
+  TestPairPositive(Representation::HeapObject(), Representation::None());
+  TestPairPositive(Representation::Double(), Representation::None());
+  TestPairPositive(Representation::Tagged(), Representation::None());
+
+  TestPairNegative(Representation::None(), Representation::Integer8());
+  TestPairNegative(Representation::Integer8(), Representation::Integer8());
+  TestPairNegative(Representation::UInteger8(), Representation::Integer8());
+  TestPairPositive(Representation::Integer16(), Representation::Integer8());
+  TestPairPositive(Representation::UInteger16(), Representation::Integer8());
+  TestPairPositive(Representation::Smi(), Representation::Integer8());
+  TestPairPositive(Representation::Integer32(), Representation::Integer8());
+  TestPairNegative(Representation::HeapObject(), Representation::Integer8());
+  TestPairPositive(Representation::Double(), Representation::Integer8());
+  TestPairPositive(Representation::Tagged(), Representation::Integer8());
+
+  TestPairNegative(Representation::None(), Representation::UInteger8());
+  TestPairNegative(Representation::Integer8(), Representation::UInteger8());
+  TestPairNegative(Representation::UInteger8(), Representation::UInteger8());
+  TestPairPositive(Representation::Integer16(), Representation::UInteger8());
+  TestPairPositive(Representation::UInteger16(), Representation::UInteger8());
+  TestPairPositive(Representation::Smi(), Representation::UInteger8());
+  TestPairPositive(Representation::Integer32(), Representation::UInteger8());
+  TestPairNegative(Representation::HeapObject(), Representation::UInteger8());
+  TestPairPositive(Representation::Double(), Representation::UInteger8());
+  TestPairPositive(Representation::Tagged(), Representation::UInteger8());
+
+  TestPairNegative(Representation::None(), Representation::Integer16());
+  TestPairNegative(Representation::Integer8(), Representation::Integer16());
+  TestPairNegative(Representation::UInteger8(), Representation::Integer16());
+  TestPairNegative(Representation::Integer16(), Representation::Integer16());
+  TestPairNegative(Representation::UInteger16(), Representation::Integer16());
+  TestPairPositive(Representation::Smi(), Representation::Integer16());
+  TestPairPositive(Representation::Integer32(), Representation::Integer16());
+  TestPairNegative(Representation::HeapObject(), Representation::Integer16());
+  TestPairPositive(Representation::Double(), Representation::Integer16());
+  TestPairPositive(Representation::Tagged(), Representation::Integer16());
+
+  TestPairNegative(Representation::None(), Representation::UInteger16());
+  TestPairNegative(Representation::Integer8(), Representation::UInteger16());
+  TestPairNegative(Representation::UInteger8(), Representation::UInteger16());
+  TestPairNegative(Representation::Integer16(), Representation::UInteger16());
+  TestPairNegative(Representation::UInteger16(), Representation::UInteger16());
+  TestPairPositive(Representation::Smi(), Representation::UInteger16());
+  TestPairPositive(Representation::Integer32(), Representation::UInteger16());
+  TestPairNegative(Representation::HeapObject(), Representation::UInteger16());
+  TestPairPositive(Representation::Double(), Representation::UInteger16());
+  TestPairPositive(Representation::Tagged(), Representation::UInteger16());
+
+  TestPairNegative(Representation::None(), Representation::Smi());
+  TestPairNegative(Representation::Integer8(), Representation::Smi());
+  TestPairNegative(Representation::UInteger8(), Representation::Smi());
+  TestPairNegative(Representation::Integer16(), Representation::Smi());
+  TestPairNegative(Representation::UInteger16(), Representation::Smi());
+  TestPairNegative(Representation::Smi(), Representation::Smi());
+  TestPairPositive(Representation::Integer32(), Representation::Smi());
+  TestPairNegative(Representation::HeapObject(), Representation::Smi());
+  TestPairPositive(Representation::Double(), Representation::Smi());
+  TestPairPositive(Representation::Tagged(), Representation::Smi());
+
+  TestPairNegative(Representation::None(), Representation::Integer32());
+  TestPairNegative(Representation::Integer8(), Representation::Integer32());
+  TestPairNegative(Representation::UInteger8(), Representation::Integer32());
+  TestPairNegative(Representation::Integer16(), Representation::Integer32());
+  TestPairNegative(Representation::UInteger16(), Representation::Integer32());
+  TestPairNegative(Representation::Smi(), Representation::Integer32());
+  TestPairNegative(Representation::Integer32(), Representation::Integer32());
+  TestPairNegative(Representation::HeapObject(), Representation::Integer32());
+  TestPairPositive(Representation::Double(), Representation::Integer32());
+  TestPairPositive(Representation::Tagged(), Representation::Integer32());
+}