Commit f9dd3446 authored by bbudge's avatar bbudge Committed by Commit bot

Add new Float32x4 type for SIMD.js.

LOG=N
BUG=v8:4124

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

Cr-Commit-Position: refs/heads/master@{#28797}
parent e59e40a3
...@@ -275,7 +275,8 @@ class V8_EXPORT HeapGraphNode { ...@@ -275,7 +275,8 @@ class V8_EXPORT HeapGraphNode {
// snapshot items together. // snapshot items together.
kConsString = 10, // Concatenated string. A pair of pointers to strings. kConsString = 10, // Concatenated string. A pair of pointers to strings.
kSlicedString = 11, // Sliced string. A fragment of another string. kSlicedString = 11, // Sliced string. A fragment of another string.
kSymbol = 12 // A Symbol (ES6). kSymbol = 12, // A Symbol (ES6).
kSimdValue = 13 // A SIMD value stored in the heap (Proposed ES7).
}; };
/** Returns node type (see HeapGraphNode::Type). */ /** Returns node type (see HeapGraphNode::Type). */
......
...@@ -1923,6 +1923,12 @@ class V8_EXPORT Value : public Data { ...@@ -1923,6 +1923,12 @@ class V8_EXPORT Value : public Data {
*/ */
bool IsFloat64Array() const; bool IsFloat64Array() const;
/**
* Returns true if this value is a SIMD Float32x4.
* This is an experimental feature.
*/
bool IsFloat32x4() const;
/** /**
* Returns true if this value is a DataView. * Returns true if this value is a DataView.
* This is an experimental feature. * This is an experimental feature.
...@@ -6949,10 +6955,10 @@ class Internals { ...@@ -6949,10 +6955,10 @@ class Internals {
static const int kNodeIsIndependentShift = 3; static const int kNodeIsIndependentShift = 3;
static const int kNodeIsPartiallyDependentShift = 4; static const int kNodeIsPartiallyDependentShift = 4;
static const int kJSObjectType = 0xbe; static const int kJSObjectType = 0xbf;
static const int kFirstNonstringType = 0x80; static const int kFirstNonstringType = 0x80;
static const int kOddballType = 0x83; static const int kOddballType = 0x83;
static const int kForeignType = 0x86; static const int kForeignType = 0x87;
static const int kUndefinedOddballKind = 5; static const int kUndefinedOddballKind = 5;
static const int kNullOddballKind = 3; static const int kNullOddballKind = 3;
......
...@@ -1077,6 +1077,14 @@ Handle<HeapNumber> Factory::NewHeapNumber(double value, ...@@ -1077,6 +1077,14 @@ Handle<HeapNumber> Factory::NewHeapNumber(double value,
} }
Handle<Float32x4> Factory::NewFloat32x4(float w, float x, float y, float z,
PretenureFlag pretenure) {
CALL_HEAP_FUNCTION(
isolate(), isolate()->heap()->AllocateFloat32x4(w, x, y, z, pretenure),
Float32x4);
}
Handle<Object> Factory::NewError(const char* maker, Handle<Object> Factory::NewError(const char* maker,
MessageTemplate::Template template_index, MessageTemplate::Template template_index,
Handle<Object> arg0, Handle<Object> arg1, Handle<Object> arg0, Handle<Object> arg1,
......
...@@ -361,6 +361,8 @@ class Factory final { ...@@ -361,6 +361,8 @@ class Factory final {
Handle<HeapNumber> NewHeapNumber(double value, Handle<HeapNumber> NewHeapNumber(double value,
MutableMode mode = IMMUTABLE, MutableMode mode = IMMUTABLE,
PretenureFlag pretenure = NOT_TENURED); PretenureFlag pretenure = NOT_TENURED);
Handle<Float32x4> NewFloat32x4(float w, float x, float y, float z,
PretenureFlag pretenure = NOT_TENURED);
// These objects are used by the api to create env-independent data // These objects are used by the api to create env-independent data
// structures in the heap. // structures in the heap.
......
...@@ -124,6 +124,7 @@ const int kShortSize = sizeof(short); // NOLINT ...@@ -124,6 +124,7 @@ const int kShortSize = sizeof(short); // NOLINT
const int kIntSize = sizeof(int); // NOLINT const int kIntSize = sizeof(int); // NOLINT
const int kInt32Size = sizeof(int32_t); // NOLINT const int kInt32Size = sizeof(int32_t); // NOLINT
const int kInt64Size = sizeof(int64_t); // NOLINT const int kInt64Size = sizeof(int64_t); // NOLINT
const int kFloatSize = sizeof(float); // NOLINT
const int kDoubleSize = sizeof(double); // NOLINT const int kDoubleSize = sizeof(double); // NOLINT
const int kIntptrSize = sizeof(intptr_t); // NOLINT const int kIntptrSize = sizeof(intptr_t); // NOLINT
const int kPointerSize = sizeof(void*); // NOLINT const int kPointerSize = sizeof(void*); // NOLINT
......
...@@ -154,6 +154,7 @@ const char* HeapEntry::TypeAsString() { ...@@ -154,6 +154,7 @@ const char* HeapEntry::TypeAsString() {
case kConsString: return "/concatenated string/"; case kConsString: return "/concatenated string/";
case kSlicedString: return "/sliced string/"; case kSlicedString: return "/sliced string/";
case kSymbol: return "/symbol/"; case kSymbol: return "/symbol/";
case kSimdValue: return "/simd/";
default: return "???"; default: return "???";
} }
} }
...@@ -861,6 +862,8 @@ HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object) { ...@@ -861,6 +862,8 @@ HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object) {
return AddEntry(object, HeapEntry::kArray, ""); return AddEntry(object, HeapEntry::kArray, "");
} else if (object->IsHeapNumber()) { } else if (object->IsHeapNumber()) {
return AddEntry(object, HeapEntry::kHeapNumber, "number"); return AddEntry(object, HeapEntry::kHeapNumber, "number");
} else if (object->IsFloat32x4()) {
return AddEntry(object, HeapEntry::kSimdValue, "simd");
} }
return AddEntry(object, HeapEntry::kHidden, GetSystemEntryName(object)); return AddEntry(object, HeapEntry::kHidden, GetSystemEntryName(object));
} }
......
...@@ -82,7 +82,8 @@ class HeapEntry BASE_EMBEDDED { ...@@ -82,7 +82,8 @@ class HeapEntry BASE_EMBEDDED {
kSynthetic = v8::HeapGraphNode::kSynthetic, kSynthetic = v8::HeapGraphNode::kSynthetic,
kConsString = v8::HeapGraphNode::kConsString, kConsString = v8::HeapGraphNode::kConsString,
kSlicedString = v8::HeapGraphNode::kSlicedString, kSlicedString = v8::HeapGraphNode::kSlicedString,
kSymbol = v8::HeapGraphNode::kSymbol kSymbol = v8::HeapGraphNode::kSymbol,
kSimdValue = v8::HeapGraphNode::kSimdValue
}; };
static const int kNoEntry; static const int kNoEntry;
......
...@@ -2742,6 +2742,7 @@ bool Heap::CreateInitialMaps() { ...@@ -2742,6 +2742,7 @@ bool Heap::CreateInitialMaps() {
ALLOCATE_MAP(HEAP_NUMBER_TYPE, HeapNumber::kSize, heap_number) ALLOCATE_MAP(HEAP_NUMBER_TYPE, HeapNumber::kSize, heap_number)
ALLOCATE_MAP(MUTABLE_HEAP_NUMBER_TYPE, HeapNumber::kSize, ALLOCATE_MAP(MUTABLE_HEAP_NUMBER_TYPE, HeapNumber::kSize,
mutable_heap_number) mutable_heap_number)
ALLOCATE_MAP(FLOAT32X4_TYPE, Float32x4::kSize, float32x4)
ALLOCATE_MAP(SYMBOL_TYPE, Symbol::kSize, symbol) ALLOCATE_MAP(SYMBOL_TYPE, Symbol::kSize, symbol)
ALLOCATE_MAP(FOREIGN_TYPE, Foreign::kSize, foreign) ALLOCATE_MAP(FOREIGN_TYPE, Foreign::kSize, foreign)
...@@ -2891,6 +2892,32 @@ AllocationResult Heap::AllocateHeapNumber(double value, MutableMode mode, ...@@ -2891,6 +2892,32 @@ AllocationResult Heap::AllocateHeapNumber(double value, MutableMode mode,
} }
AllocationResult Heap::AllocateFloat32x4(float w, float x, float y, float z,
PretenureFlag pretenure) {
// Statically ensure that it is safe to allocate SIMD values in paged
// spaces.
int size = Float32x4::kSize;
STATIC_ASSERT(Float32x4::kSize <= Page::kMaxRegularHeapObjectSize);
AllocationSpace space = SelectSpace(size, pretenure);
HeapObject* result;
{
AllocationResult allocation =
AllocateRaw(size, space, OLD_SPACE, kSimd128Unaligned);
if (!allocation.To(&result)) return allocation;
}
result->set_map_no_write_barrier(float32x4_map());
Float32x4* float32x4 = Float32x4::cast(result);
float32x4->set_lane(0, w);
float32x4->set_lane(1, x);
float32x4->set_lane(2, y);
float32x4->set_lane(3, z);
return result;
}
AllocationResult Heap::AllocateCell(Object* value) { AllocationResult Heap::AllocateCell(Object* value) {
int size = Cell::kSize; int size = Cell::kSize;
STATIC_ASSERT(Cell::kSize <= Page::kMaxRegularHeapObjectSize); STATIC_ASSERT(Cell::kSize <= Page::kMaxRegularHeapObjectSize);
......
...@@ -46,6 +46,7 @@ namespace internal { ...@@ -46,6 +46,7 @@ namespace internal {
V(Map, meta_map, MetaMap) \ V(Map, meta_map, MetaMap) \
V(Map, heap_number_map, HeapNumberMap) \ V(Map, heap_number_map, HeapNumberMap) \
V(Map, mutable_heap_number_map, MutableHeapNumberMap) \ V(Map, mutable_heap_number_map, MutableHeapNumberMap) \
V(Map, float32x4_map, Float32x4Map) \
V(Map, native_context_map, NativeContextMap) \ V(Map, native_context_map, NativeContextMap) \
V(Map, fixed_array_map, FixedArrayMap) \ V(Map, fixed_array_map, FixedArrayMap) \
V(Map, code_map, CodeMap) \ V(Map, code_map, CodeMap) \
...@@ -344,6 +345,7 @@ namespace internal { ...@@ -344,6 +345,7 @@ namespace internal {
V(MetaMap) \ V(MetaMap) \
V(HeapNumberMap) \ V(HeapNumberMap) \
V(MutableHeapNumberMap) \ V(MutableHeapNumberMap) \
V(Float32x4Map) \
V(NativeContextMap) \ V(NativeContextMap) \
V(FixedArrayMap) \ V(FixedArrayMap) \
V(CodeMap) \ V(CodeMap) \
...@@ -1602,12 +1604,17 @@ class Heap { ...@@ -1602,12 +1604,17 @@ class Heap {
bool alloc_props = true, bool alloc_props = true,
AllocationSite* allocation_site = NULL); AllocationSite* allocation_site = NULL);
// Allocated a HeapNumber from value. // Allocates a HeapNumber from value.
MUST_USE_RESULT AllocationResult MUST_USE_RESULT AllocationResult
AllocateHeapNumber(double value, MutableMode mode = IMMUTABLE, AllocateHeapNumber(double value, MutableMode mode = IMMUTABLE,
PretenureFlag pretenure = NOT_TENURED); PretenureFlag pretenure = NOT_TENURED);
// Allocate a byte array of the specified length // Allocates a Float32x4 from the given lane values.
MUST_USE_RESULT AllocationResult
AllocateFloat32x4(float w, float x, float y, float z,
PretenureFlag pretenure = NOT_TENURED);
// Allocates a byte array of the specified length
MUST_USE_RESULT AllocationResult MUST_USE_RESULT AllocationResult
AllocateByteArray(int length, PretenureFlag pretenure = NOT_TENURED); AllocateByteArray(int length, PretenureFlag pretenure = NOT_TENURED);
......
...@@ -138,6 +138,7 @@ StaticVisitorBase::VisitorId StaticVisitorBase::GetVisitorId( ...@@ -138,6 +138,7 @@ StaticVisitorBase::VisitorId StaticVisitorBase::GetVisitorId(
case HEAP_NUMBER_TYPE: case HEAP_NUMBER_TYPE:
case MUTABLE_HEAP_NUMBER_TYPE: case MUTABLE_HEAP_NUMBER_TYPE:
case FLOAT32X4_TYPE:
#define EXTERNAL_ARRAY_CASE(Type, type, TYPE, ctype, size) \ #define EXTERNAL_ARRAY_CASE(Type, type, TYPE, ctype, size) \
case EXTERNAL_##TYPE##_ARRAY_TYPE: case EXTERNAL_##TYPE##_ARRAY_TYPE:
......
...@@ -58,6 +58,9 @@ void HeapObject::HeapObjectVerify() { ...@@ -58,6 +58,9 @@ void HeapObject::HeapObjectVerify() {
case MUTABLE_HEAP_NUMBER_TYPE: case MUTABLE_HEAP_NUMBER_TYPE:
HeapNumber::cast(this)->HeapNumberVerify(); HeapNumber::cast(this)->HeapNumberVerify();
break; break;
case FLOAT32X4_TYPE:
Float32x4::cast(this)->Float32x4Verify();
break;
case FIXED_ARRAY_TYPE: case FIXED_ARRAY_TYPE:
FixedArray::cast(this)->FixedArrayVerify(); FixedArray::cast(this)->FixedArrayVerify();
break; break;
...@@ -214,6 +217,9 @@ void HeapNumber::HeapNumberVerify() { ...@@ -214,6 +217,9 @@ void HeapNumber::HeapNumberVerify() {
} }
void Float32x4::Float32x4Verify() { CHECK(IsFloat32x4()); }
void ByteArray::ByteArrayVerify() { void ByteArray::ByteArrayVerify() {
CHECK(IsByteArray()); CHECK(IsByteArray());
} }
......
...@@ -170,6 +170,7 @@ bool Object::IsHeapObject() const { ...@@ -170,6 +170,7 @@ bool Object::IsHeapObject() const {
TYPE_CHECKER(HeapNumber, HEAP_NUMBER_TYPE) TYPE_CHECKER(HeapNumber, HEAP_NUMBER_TYPE)
TYPE_CHECKER(MutableHeapNumber, MUTABLE_HEAP_NUMBER_TYPE) TYPE_CHECKER(MutableHeapNumber, MUTABLE_HEAP_NUMBER_TYPE)
TYPE_CHECKER(Float32x4, FLOAT32X4_TYPE)
TYPE_CHECKER(Symbol, SYMBOL_TYPE) TYPE_CHECKER(Symbol, SYMBOL_TYPE)
...@@ -1321,6 +1322,12 @@ MaybeHandle<Object> JSProxy::SetElementWithHandler(Handle<JSProxy> proxy, ...@@ -1321,6 +1322,12 @@ MaybeHandle<Object> JSProxy::SetElementWithHandler(Handle<JSProxy> proxy,
#define WRITE_INT32_FIELD(p, offset, value) \ #define WRITE_INT32_FIELD(p, offset, value) \
(*reinterpret_cast<int32_t*>(FIELD_ADDR(p, offset)) = value) (*reinterpret_cast<int32_t*>(FIELD_ADDR(p, offset)) = value)
#define READ_FLOAT_FIELD(p, offset) \
(*reinterpret_cast<const float*>(FIELD_ADDR_CONST(p, offset)))
#define WRITE_FLOAT_FIELD(p, offset, value) \
(*reinterpret_cast<float*>(FIELD_ADDR(p, offset)) = value)
#define READ_UINT64_FIELD(p, offset) \ #define READ_UINT64_FIELD(p, offset) \
(*reinterpret_cast<const uint64_t*>(FIELD_ADDR_CONST(p, offset))) (*reinterpret_cast<const uint64_t*>(FIELD_ADDR_CONST(p, offset)))
...@@ -1579,6 +1586,30 @@ int HeapNumber::get_sign() { ...@@ -1579,6 +1586,30 @@ int HeapNumber::get_sign() {
} }
float Float32x4::get_lane(int lane) const {
DCHECK(lane < 4 && lane >= 0);
#if defined(V8_TARGET_LITTLE_ENDIAN)
return READ_FLOAT_FIELD(this, kValueOffset + lane * kFloatSize);
#elif defined(V8_TARGET_BIG_ENDIAN)
return READ_FLOAT_FIELD(this, kValueOffset + (3 - lane) * kFloatSize);
#else
#error Unknown byte ordering
#endif
}
void Float32x4::set_lane(int lane, float value) {
DCHECK(lane < 4 && lane >= 0);
#if defined(V8_TARGET_LITTLE_ENDIAN)
WRITE_FLOAT_FIELD(this, kValueOffset + lane * kFloatSize, value);
#elif defined(V8_TARGET_BIG_ENDIAN)
WRITE_FLOAT_FIELD(this, kValueOffset + (3 - lane) * kFloatSize, value);
#else
#error Unknown byte ordering
#endif
}
ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset) ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
...@@ -2818,6 +2849,7 @@ AllocationAlignment HeapObject::RequiredAlignment() { ...@@ -2818,6 +2849,7 @@ AllocationAlignment HeapObject::RequiredAlignment() {
return kDoubleAligned; return kDoubleAligned;
} }
if (IsHeapNumber()) return kDoubleUnaligned; if (IsHeapNumber()) return kDoubleUnaligned;
if (IsFloat32x4()) return kSimd128Unaligned;
#endif // V8_HOST_ARCH_32_BIT #endif // V8_HOST_ARCH_32_BIT
return kWordAligned; return kWordAligned;
} }
...@@ -3359,6 +3391,7 @@ CAST_ACCESSOR(FixedArray) ...@@ -3359,6 +3391,7 @@ CAST_ACCESSOR(FixedArray)
CAST_ACCESSOR(FixedArrayBase) CAST_ACCESSOR(FixedArrayBase)
CAST_ACCESSOR(FixedDoubleArray) CAST_ACCESSOR(FixedDoubleArray)
CAST_ACCESSOR(FixedTypedArrayBase) CAST_ACCESSOR(FixedTypedArrayBase)
CAST_ACCESSOR(Float32x4)
CAST_ACCESSOR(Foreign) CAST_ACCESSOR(Foreign)
CAST_ACCESSOR(GlobalDictionary) CAST_ACCESSOR(GlobalDictionary)
CAST_ACCESSOR(GlobalObject) CAST_ACCESSOR(GlobalObject)
......
...@@ -60,6 +60,9 @@ void HeapObject::HeapObjectPrint(std::ostream& os) { // NOLINT ...@@ -60,6 +60,9 @@ void HeapObject::HeapObjectPrint(std::ostream& os) { // NOLINT
HeapNumber::cast(this)->HeapNumberPrint(os); HeapNumber::cast(this)->HeapNumberPrint(os);
os << ">"; os << ">";
break; break;
case FLOAT32X4_TYPE:
Float32x4::cast(this)->Float32x4Print(os);
break;
case FIXED_DOUBLE_ARRAY_TYPE: case FIXED_DOUBLE_ARRAY_TYPE:
FixedDoubleArray::cast(this)->FixedDoubleArrayPrint(os); FixedDoubleArray::cast(this)->FixedDoubleArrayPrint(os);
break; break;
......
...@@ -97,6 +97,7 @@ bool Object::BooleanValue() { ...@@ -97,6 +97,7 @@ bool Object::BooleanValue() {
if (IsUndetectableObject()) return false; // Undetectable object is false. if (IsUndetectableObject()) return false; // Undetectable object is false.
if (IsString()) return String::cast(this)->length() != 0; if (IsString()) return String::cast(this)->length() != 0;
if (IsHeapNumber()) return HeapNumber::cast(this)->HeapNumberBooleanValue(); if (IsHeapNumber()) return HeapNumber::cast(this)->HeapNumberBooleanValue();
if (IsFloat32x4()) return true; // Simd value types always evaluate to true.
return true; return true;
} }
...@@ -1400,6 +1401,12 @@ void HeapObject::HeapObjectShortPrint(std::ostream& os) { // NOLINT ...@@ -1400,6 +1401,12 @@ void HeapObject::HeapObjectShortPrint(std::ostream& os) { // NOLINT
os << '>'; os << '>';
break; break;
} }
case FLOAT32X4_TYPE: {
os << "<Float32x4: ";
Float32x4::cast(this)->Float32x4Print(os);
os << ">";
break;
}
case JS_PROXY_TYPE: case JS_PROXY_TYPE:
os << "<JSProxy>"; os << "<JSProxy>";
break; break;
...@@ -1546,6 +1553,7 @@ void HeapObject::IterateBody(InstanceType type, int object_size, ...@@ -1546,6 +1553,7 @@ void HeapObject::IterateBody(InstanceType type, int object_size,
case HEAP_NUMBER_TYPE: case HEAP_NUMBER_TYPE:
case MUTABLE_HEAP_NUMBER_TYPE: case MUTABLE_HEAP_NUMBER_TYPE:
case FLOAT32X4_TYPE:
case FILLER_TYPE: case FILLER_TYPE:
case BYTE_ARRAY_TYPE: case BYTE_ARRAY_TYPE:
case FREE_SPACE_TYPE: case FREE_SPACE_TYPE:
...@@ -1591,6 +1599,12 @@ void HeapNumber::HeapNumberPrint(std::ostream& os) { // NOLINT ...@@ -1591,6 +1599,12 @@ void HeapNumber::HeapNumberPrint(std::ostream& os) { // NOLINT
} }
void Float32x4::Float32x4Print(std::ostream& os) { // NOLINT
os << get_lane(0) << ", " << get_lane(1) << ", " << get_lane(2) << ", "
<< get_lane(3);
}
String* JSReceiver::class_name() { String* JSReceiver::class_name() {
if (IsJSFunction() || IsJSFunctionProxy()) { if (IsJSFunction() || IsJSFunctionProxy()) {
return GetHeap()->Function_string(); return GetHeap()->Function_string();
......
...@@ -121,6 +121,7 @@ ...@@ -121,6 +121,7 @@
// - ExternalTwoByteInternalizedString // - ExternalTwoByteInternalizedString
// - Symbol // - Symbol
// - HeapNumber // - HeapNumber
// - Float32x4
// - Cell // - Cell
// - PropertyCell // - PropertyCell
// - Code // - Code
...@@ -394,6 +395,7 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1; ...@@ -394,6 +395,7 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1;
\ \
V(HEAP_NUMBER_TYPE) \ V(HEAP_NUMBER_TYPE) \
V(MUTABLE_HEAP_NUMBER_TYPE) \ V(MUTABLE_HEAP_NUMBER_TYPE) \
V(FLOAT32X4_TYPE) \
V(FOREIGN_TYPE) \ V(FOREIGN_TYPE) \
V(BYTE_ARRAY_TYPE) \ V(BYTE_ARRAY_TYPE) \
V(FREE_SPACE_TYPE) \ V(FREE_SPACE_TYPE) \
...@@ -690,6 +692,7 @@ enum InstanceType { ...@@ -690,6 +692,7 @@ enum InstanceType {
// objects. // objects.
HEAP_NUMBER_TYPE, HEAP_NUMBER_TYPE,
MUTABLE_HEAP_NUMBER_TYPE, MUTABLE_HEAP_NUMBER_TYPE,
FLOAT32X4_TYPE, // FIRST_SIMD_TYPE, LAST_SIMD_TYPE
FOREIGN_TYPE, FOREIGN_TYPE,
BYTE_ARRAY_TYPE, BYTE_ARRAY_TYPE,
FREE_SPACE_TYPE, FREE_SPACE_TYPE,
...@@ -782,6 +785,9 @@ enum InstanceType { ...@@ -782,6 +785,9 @@ enum InstanceType {
FIRST_UNIQUE_NAME_TYPE = INTERNALIZED_STRING_TYPE, FIRST_UNIQUE_NAME_TYPE = INTERNALIZED_STRING_TYPE,
LAST_UNIQUE_NAME_TYPE = SYMBOL_TYPE, LAST_UNIQUE_NAME_TYPE = SYMBOL_TYPE,
FIRST_NONSTRING_TYPE = SYMBOL_TYPE, FIRST_NONSTRING_TYPE = SYMBOL_TYPE,
// Boundaries for testing for a SIMD type.
FIRST_SIMD_TYPE = FLOAT32X4_TYPE,
LAST_SIMD_TYPE = FLOAT32X4_TYPE,
// Boundaries for testing for an external array. // Boundaries for testing for an external array.
FIRST_EXTERNAL_ARRAY_TYPE = EXTERNAL_INT8_ARRAY_TYPE, FIRST_EXTERNAL_ARRAY_TYPE = EXTERNAL_INT8_ARRAY_TYPE,
LAST_EXTERNAL_ARRAY_TYPE = EXTERNAL_UINT8_CLAMPED_ARRAY_TYPE, LAST_EXTERNAL_ARRAY_TYPE = EXTERNAL_UINT8_CLAMPED_ARRAY_TYPE,
...@@ -948,6 +954,7 @@ template <class C> inline bool Is(Object* obj); ...@@ -948,6 +954,7 @@ template <class C> inline bool Is(Object* obj);
V(FixedFloat32Array) \ V(FixedFloat32Array) \
V(FixedFloat64Array) \ V(FixedFloat64Array) \
V(FixedUint8ClampedArray) \ V(FixedUint8ClampedArray) \
V(Float32x4) \
V(ByteArray) \ V(ByteArray) \
V(FreeSpace) \ V(FreeSpace) \
V(JSReceiver) \ V(JSReceiver) \
...@@ -1610,6 +1617,28 @@ class HeapNumber: public HeapObject { ...@@ -1610,6 +1617,28 @@ class HeapNumber: public HeapObject {
}; };
// The Float32x4 class describes heap allocated SIMD values holding 4 32-bit
// IEEE floats.
class Float32x4 : public HeapObject {
public:
inline float get_lane(int lane) const;
inline void set_lane(int lane, float value);
DECLARE_CAST(Float32x4)
// Dispatched behavior.
void Float32x4Print(std::ostream& os); // NOLINT
DECLARE_VERIFIER(Float32x4)
// Layout description.
static const int kValueOffset = HeapObject::kHeaderSize;
static const int kSize = kValueOffset + kSimd128Size;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Float32x4);
};
enum EnsureElementsMode { enum EnsureElementsMode {
DONT_ALLOW_DOUBLE_ELEMENTS, DONT_ALLOW_DOUBLE_ELEMENTS,
ALLOW_COPIED_DOUBLE_ELEMENTS, ALLOW_COPIED_DOUBLE_ELEMENTS,
......
...@@ -93,6 +93,7 @@ class TestHeap : public i::Heap { ...@@ -93,6 +93,7 @@ class TestHeap : public i::Heap {
using i::Heap::AllocateByteArray; using i::Heap::AllocateByteArray;
using i::Heap::AllocateFixedArray; using i::Heap::AllocateFixedArray;
using i::Heap::AllocateHeapNumber; using i::Heap::AllocateHeapNumber;
using i::Heap::AllocateFloat32x4;
using i::Heap::AllocateJSObject; using i::Heap::AllocateJSObject;
using i::Heap::AllocateJSObjectFromMap; using i::Heap::AllocateJSObjectFromMap;
using i::Heap::AllocateMap; using i::Heap::AllocateMap;
......
...@@ -59,6 +59,7 @@ TEST(HeapMaps) { ...@@ -59,6 +59,7 @@ TEST(HeapMaps) {
Heap* heap = CcTest::heap(); Heap* heap = CcTest::heap();
CheckMap(heap->meta_map(), MAP_TYPE, Map::kSize); CheckMap(heap->meta_map(), MAP_TYPE, Map::kSize);
CheckMap(heap->heap_number_map(), HEAP_NUMBER_TYPE, HeapNumber::kSize); CheckMap(heap->heap_number_map(), HEAP_NUMBER_TYPE, HeapNumber::kSize);
CheckMap(heap->float32x4_map(), FLOAT32X4_TYPE, Float32x4::kSize);
CheckMap(heap->fixed_array_map(), FIXED_ARRAY_TYPE, kVariableSizeSentinel); CheckMap(heap->fixed_array_map(), FIXED_ARRAY_TYPE, kVariableSizeSentinel);
CheckMap(heap->string_map(), STRING_TYPE, kVariableSizeSentinel); CheckMap(heap->string_map(), STRING_TYPE, kVariableSizeSentinel);
} }
...@@ -213,6 +214,60 @@ TEST(HeapObjects) { ...@@ -213,6 +214,60 @@ TEST(HeapObjects) {
} }
template <typename T, typename LANE_TYPE, int LANES>
static void CheckSimdLanes(T* value) {
// Get the original values, and check that all lanes can be set to new values
// without disturbing the other lanes.
LANE_TYPE lane_values[LANES];
for (int i = 0; i < LANES; i++) {
lane_values[i] = value->get_lane(i);
}
for (int i = 0; i < LANES; i++) {
lane_values[i] += 1;
value->set_lane(i, lane_values[i]);
for (int j = 0; j < LANES; j++) {
CHECK_EQ(lane_values[j], value->get_lane(j));
}
}
}
TEST(SimdObjects) {
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
Factory* factory = isolate->factory();
HandleScope sc(isolate);
Handle<Object> value = factory->NewFloat32x4(1, 2, 3, 4);
CHECK(value->IsFloat32x4());
CHECK(value->BooleanValue()); // SIMD values map to true.
Float32x4* float32x4 = *Handle<Float32x4>::cast(value);
CheckSimdLanes<Float32x4, float, 4>(float32x4);
// Check ToString for SIMD values.
// TODO(bbudge): Switch to Check* style function to test ToString().
value = factory->NewFloat32x4(1, 2, 3, 4);
float32x4 = *Handle<Float32x4>::cast(value);
std::ostringstream os;
float32x4->Float32x4Print(os);
CHECK_EQ("1, 2, 3, 4", os.str());
// Check unusual lane values.
float32x4->set_lane(0, 0);
CHECK_EQ(0, float32x4->get_lane(0));
float32x4->set_lane(1, -0.0);
CHECK_EQ(-0.0, float32x4->get_lane(1));
float quiet_NaN = std::numeric_limits<float>::quiet_NaN();
float signaling_NaN = std::numeric_limits<float>::signaling_NaN();
float32x4->set_lane(2, quiet_NaN);
CHECK(std::isnan(float32x4->get_lane(2)));
float32x4->set_lane(3, signaling_NaN);
CHECK(std::isnan(float32x4->get_lane(3)));
}
TEST(Tagging) { TEST(Tagging) {
CcTest::InitializeVM(); CcTest::InitializeVM();
int request = 24; int request = 24;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment