Add signed/unsigned 8-bit and 16-bit Representations to Crankshaft

R=yangguo@chromium.org

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@17588 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
danno@chromium.org 2013-11-08 11:50:23 +00:00
parent 94eb5904a6
commit 1222255b9c
18 changed files with 562 additions and 80 deletions

View 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.

View 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) {

View 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,

View 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;

View 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);
}

View 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() ||

View 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);
}

View 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()) {

View File

@ -2432,7 +2432,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);

View 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]);

View 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);

View 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;

View 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 {

View 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',
@ -121,6 +122,7 @@
'test-code-stubs-ia32.cc',
'test-cpu-ia32.cc',
'test-disasm-ia32.cc',
'test-macro-assembler-ia32.cc',
'test-log-stack-tracer.cc'
],
}],

View File

@ -132,5 +132,99 @@ TEST(CopyBytes) {
}
typedef int (*F0)();
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);
// Call the function from C++.
F0 f = FUNCTION_CAST<F0>(buffer);
int32_t result = Simulator::current(Isolate::Current())->Call(
FUNCTION_ADDR(f), 4, 0, 0, 0, 0);
CHECK_EQ(0, result);
}
#undef __

View File

@ -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 __

View 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));

View File

@ -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());
}