Implement in-heap backing store for typed arrays.

This adds a fixed array sub-type that will represent a backing store for
typed arrays allocated with TypedArray(length) construtor.

R=mvstanton@chromium.org, verwaest@chromium.org

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18646 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
dslomov@chromium.org 2014-01-16 14:18:37 +00:00
parent c8475cf1b1
commit 0c960c2e96
39 changed files with 1603 additions and 644 deletions

View File

@ -5394,7 +5394,7 @@ class Internals {
static const int kNullValueRootIndex = 7;
static const int kTrueValueRootIndex = 8;
static const int kFalseValueRootIndex = 9;
static const int kEmptyStringRootIndex = 136;
static const int kEmptyStringRootIndex = 145;
static const int kNodeClassIdOffset = 1 * kApiPointerSize;
static const int kNodeFlagsOffset = 1 * kApiPointerSize + 3;
@ -5405,7 +5405,7 @@ class Internals {
static const int kNodeIsIndependentShift = 4;
static const int kNodeIsPartiallyDependentShift = 5;
static const int kJSObjectType = 0xb2;
static const int kJSObjectType = 0xbb;
static const int kFirstNonstringType = 0x80;
static const int kOddballType = 0x83;
static const int kForeignType = 0x87;

View File

@ -2110,7 +2110,7 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
LLoadKeyed* result = NULL;
if (!instr->is_external()) {
if (!instr->is_typed_elements()) {
LOperand* obj = NULL;
if (instr->representation().IsDouble()) {
obj = UseRegister(instr->elements());
@ -2122,20 +2122,19 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
} else {
ASSERT(
(instr->representation().IsInteger32() &&
(elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
(elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
!IsDoubleOrFloatElementsKind(instr->elements_kind())) ||
(instr->representation().IsDouble() &&
((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
(elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
LOperand* external_pointer = UseRegister(instr->elements());
result = new(zone()) LLoadKeyed(external_pointer, key);
IsDoubleOrFloatElementsKind(instr->elements_kind())));
LOperand* backing_store = UseRegister(instr->elements());
result = new(zone()) LLoadKeyed(backing_store, key);
}
DefineAsRegister(result);
// An unsigned int array load might overflow and cause a deopt, make sure it
// has an environment.
bool can_deoptimize = instr->RequiresHoleCheck() ||
(elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS);
elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS ||
elements_kind == UINT32_ELEMENTS;
return can_deoptimize ? AssignEnvironment(result) : result;
}
@ -2152,7 +2151,7 @@ LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
if (!instr->is_external()) {
if (!instr->is_typed_elements()) {
ASSERT(instr->elements()->representation().IsTagged());
bool needs_write_barrier = instr->NeedsWriteBarrier();
LOperand* object = NULL;
@ -2181,16 +2180,17 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
ASSERT(
(instr->value()->representation().IsInteger32() &&
(instr->elements_kind() != EXTERNAL_FLOAT_ELEMENTS) &&
(instr->elements_kind() != EXTERNAL_DOUBLE_ELEMENTS)) ||
!IsDoubleOrFloatElementsKind(instr->elements_kind())) ||
(instr->value()->representation().IsDouble() &&
((instr->elements_kind() == EXTERNAL_FLOAT_ELEMENTS) ||
(instr->elements_kind() == EXTERNAL_DOUBLE_ELEMENTS))));
ASSERT(instr->elements()->representation().IsExternal());
IsDoubleOrFloatElementsKind(instr->elements_kind())));
ASSERT((instr->is_fixed_typed_array() &&
instr->elements()->representation().IsTagged()) ||
(instr->is_external() &&
instr->elements()->representation().IsExternal()));
LOperand* val = UseRegister(instr->value());
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
LOperand* external_pointer = UseRegister(instr->elements());
return new(zone()) LStoreKeyed(external_pointer, key, val);
LOperand* backing_store = UseRegister(instr->elements());
return new(zone()) LStoreKeyed(backing_store, key, val);
}

View File

@ -1595,6 +1595,12 @@ class LLoadKeyed V8_FINAL : public LTemplateInstruction<1, 2, 0> {
bool is_external() const {
return hydrogen()->is_external();
}
bool is_fixed_typed_array() const {
return hydrogen()->is_fixed_typed_array();
}
bool is_typed_elements() const {
return is_external() || is_fixed_typed_array();
}
DECLARE_CONCRETE_INSTRUCTION(LoadKeyed, "load-keyed")
DECLARE_HYDROGEN_ACCESSOR(LoadKeyed)
@ -2227,6 +2233,12 @@ class LStoreKeyed V8_FINAL : public LTemplateInstruction<0, 3, 0> {
}
bool is_external() const { return hydrogen()->is_external(); }
bool is_fixed_typed_array() const {
return hydrogen()->is_fixed_typed_array();
}
bool is_typed_elements() const {
return is_external() || is_fixed_typed_array();
}
LOperand* elements() { return inputs_[0]; }
LOperand* key() { return inputs_[1]; }
LOperand* value() { return inputs_[2]; }

View File

@ -3220,20 +3220,28 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
int element_size_shift = ElementsKindToShiftSize(elements_kind);
int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
? (element_size_shift - kSmiTagSize) : element_size_shift;
int additional_offset = instr->additional_index() << element_size_shift;
int additional_offset = IsFixedTypedArrayElementsKind(elements_kind)
? FixedTypedArrayBase::kDataOffset - kHeapObjectTag
: 0;
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
elements_kind == FLOAT32_ELEMENTS ||
elements_kind == EXTERNAL_DOUBLE_ELEMENTS ||
elements_kind == FLOAT64_ELEMENTS) {
int base_offset =
(instr->additional_index() << element_size_shift) + additional_offset;
DwVfpRegister result = ToDoubleRegister(instr->result());
Operand operand = key_is_constant
? Operand(constant_key << element_size_shift)
: Operand(key, LSL, shift_size);
__ add(scratch0(), external_pointer, operand);
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
__ vldr(double_scratch0().low(), scratch0(), additional_offset);
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
elements_kind == FLOAT32_ELEMENTS) {
__ vldr(double_scratch0().low(), scratch0(), base_offset);
__ vcvt_f64_f32(result, double_scratch0().low());
} else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS
__ vldr(result, scratch0(), additional_offset);
} else { // loading doubles, not floats.
__ vldr(result, scratch0(), base_offset);
}
} else {
Register result = ToRegister(instr->result());
@ -3243,28 +3251,37 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
instr->additional_index(), additional_offset);
switch (elements_kind) {
case EXTERNAL_BYTE_ELEMENTS:
case INT8_ELEMENTS:
__ ldrsb(result, mem_operand);
break;
case EXTERNAL_PIXEL_ELEMENTS:
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
case UINT8_ELEMENTS:
case UINT8_CLAMPED_ELEMENTS:
__ ldrb(result, mem_operand);
break;
case EXTERNAL_SHORT_ELEMENTS:
case INT16_ELEMENTS:
__ ldrsh(result, mem_operand);
break;
case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
case UINT16_ELEMENTS:
__ ldrh(result, mem_operand);
break;
case EXTERNAL_INT_ELEMENTS:
case INT32_ELEMENTS:
__ ldr(result, mem_operand);
break;
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
case UINT32_ELEMENTS:
__ ldr(result, mem_operand);
if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
__ cmp(result, Operand(0x80000000));
DeoptimizeIf(cs, instr->environment());
}
break;
case FLOAT32_ELEMENTS:
case FLOAT64_ELEMENTS:
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
case FAST_HOLEY_DOUBLE_ELEMENTS:
@ -3362,7 +3379,7 @@ void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
if (instr->is_external()) {
if (instr->is_typed_elements()) {
DoLoadKeyedExternalArray(instr);
} else if (instr->hydrogen()->representation().IsDouble()) {
DoLoadKeyedFixedDoubleArray(instr);
@ -3380,14 +3397,26 @@ MemOperand LCodeGen::PrepareKeyedOperand(Register key,
int shift_size,
int additional_index,
int additional_offset) {
if (additional_index != 0 && !key_is_constant) {
additional_index *= 1 << (element_size - shift_size);
__ add(scratch0(), key, Operand(additional_index));
}
int base_offset = (additional_index << element_size) + additional_offset;
if (key_is_constant) {
return MemOperand(base,
(constant_key << element_size) + additional_offset);
base_offset + (constant_key << element_size));
}
if (additional_offset != 0) {
__ mov(scratch0(), Operand(base_offset));
if (shift_size >= 0) {
__ add(scratch0(), scratch0(), Operand(key, LSL, shift_size));
} else {
ASSERT_EQ(-1, shift_size);
__ add(scratch0(), scratch0(), Operand(key, LSR, 1));
}
return MemOperand(base, scratch0());
}
if (additional_index != 0) {
additional_index *= 1 << (element_size - shift_size);
__ add(scratch0(), key, Operand(additional_index));
}
if (additional_index == 0) {
@ -4255,10 +4284,16 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
int element_size_shift = ElementsKindToShiftSize(elements_kind);
int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
? (element_size_shift - kSmiTagSize) : element_size_shift;
int additional_offset = instr->additional_index() << element_size_shift;
int additional_offset = IsFixedTypedArrayElementsKind(elements_kind)
? FixedTypedArrayBase::kDataOffset - kHeapObjectTag
: 0;
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
elements_kind == FLOAT32_ELEMENTS ||
elements_kind == EXTERNAL_DOUBLE_ELEMENTS ||
elements_kind == FLOAT64_ELEMENTS) {
int base_offset =
(instr->additional_index() << element_size_shift) + additional_offset;
Register address = scratch0();
DwVfpRegister value(ToDoubleRegister(instr->value()));
if (key_is_constant) {
@ -4271,11 +4306,12 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
} else {
__ add(address, external_pointer, Operand(key, LSL, shift_size));
}
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
elements_kind == FLOAT32_ELEMENTS) {
__ vcvt_f32_f64(double_scratch0().low(), value);
__ vstr(double_scratch0().low(), address, additional_offset);
} else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS
__ vstr(value, address, additional_offset);
__ vstr(double_scratch0().low(), address, base_offset);
} else { // Storing doubles, not floats.
__ vstr(value, address, base_offset);
}
} else {
Register value(ToRegister(instr->value()));
@ -4287,16 +4323,25 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
case EXTERNAL_PIXEL_ELEMENTS:
case EXTERNAL_BYTE_ELEMENTS:
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
case UINT8_ELEMENTS:
case UINT8_CLAMPED_ELEMENTS:
case INT8_ELEMENTS:
__ strb(value, mem_operand);
break;
case EXTERNAL_SHORT_ELEMENTS:
case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
case INT16_ELEMENTS:
case UINT16_ELEMENTS:
__ strh(value, mem_operand);
break;
case EXTERNAL_INT_ELEMENTS:
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
case INT32_ELEMENTS:
case UINT32_ELEMENTS:
__ str(value, mem_operand);
break;
case FLOAT32_ELEMENTS:
case FLOAT64_ELEMENTS:
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
case FAST_DOUBLE_ELEMENTS:
@ -4406,7 +4451,7 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) {
// By cases: external, fast double
if (instr->is_external()) {
if (instr->is_typed_elements()) {
DoStoreKeyedExternalArray(instr);
} else if (instr->hydrogen()->value()->representation().IsDouble()) {
DoStoreKeyedFixedDoubleArray(instr);

View File

@ -570,6 +570,15 @@ void KeyedStoreElementStub::Generate(MacroAssembler* masm) {
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
case EXTERNAL_PIXEL_ELEMENTS:
case UINT8_ELEMENTS:
case INT8_ELEMENTS:
case UINT16_ELEMENTS:
case INT16_ELEMENTS:
case UINT32_ELEMENTS:
case INT32_ELEMENTS:
case FLOAT32_ELEMENTS:
case FLOAT64_ELEMENTS:
case UINT8_CLAMPED_ELEMENTS:
UNREACHABLE();
break;
case DICTIONARY_ELEMENTS:

View File

@ -40,17 +40,26 @@ int ElementsKindToShiftSize(ElementsKind elements_kind) {
case EXTERNAL_BYTE_ELEMENTS:
case EXTERNAL_PIXEL_ELEMENTS:
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
case UINT8_ELEMENTS:
case INT8_ELEMENTS:
case UINT8_CLAMPED_ELEMENTS:
return 0;
case EXTERNAL_SHORT_ELEMENTS:
case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
case UINT16_ELEMENTS:
case INT16_ELEMENTS:
return 1;
case EXTERNAL_INT_ELEMENTS:
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
case EXTERNAL_FLOAT_ELEMENTS:
case UINT32_ELEMENTS:
case INT32_ELEMENTS:
case FLOAT32_ELEMENTS:
return 2;
case EXTERNAL_DOUBLE_ELEMENTS:
case FAST_DOUBLE_ELEMENTS:
case FAST_HOLEY_DOUBLE_ELEMENTS:
case FLOAT64_ELEMENTS:
return 3;
case FAST_SMI_ELEMENTS:
case FAST_ELEMENTS:

View File

@ -63,13 +63,26 @@ enum ElementsKind {
EXTERNAL_DOUBLE_ELEMENTS,
EXTERNAL_PIXEL_ELEMENTS,
// Fixed typed arrays
UINT8_ELEMENTS,
INT8_ELEMENTS,
UINT16_ELEMENTS,
INT16_ELEMENTS,
UINT32_ELEMENTS,
INT32_ELEMENTS,
FLOAT32_ELEMENTS,
FLOAT64_ELEMENTS,
UINT8_CLAMPED_ELEMENTS,
// Derived constants from ElementsKind
FIRST_ELEMENTS_KIND = FAST_SMI_ELEMENTS,
LAST_ELEMENTS_KIND = EXTERNAL_PIXEL_ELEMENTS,
LAST_ELEMENTS_KIND = UINT8_CLAMPED_ELEMENTS,
FIRST_FAST_ELEMENTS_KIND = FAST_SMI_ELEMENTS,
LAST_FAST_ELEMENTS_KIND = FAST_HOLEY_DOUBLE_ELEMENTS,
FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND = EXTERNAL_BYTE_ELEMENTS,
LAST_EXTERNAL_ARRAY_ELEMENTS_KIND = EXTERNAL_PIXEL_ELEMENTS,
FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND = UINT8_ELEMENTS,
LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND = UINT8_CLAMPED_ELEMENTS,
TERMINAL_FAST_ELEMENTS_KIND = FAST_HOLEY_ELEMENTS
};
@ -103,6 +116,12 @@ inline bool IsExternalArrayElementsKind(ElementsKind kind) {
}
inline bool IsFixedTypedArrayElementsKind(ElementsKind kind) {
return kind >= FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND &&
kind <= LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND;
}
inline bool IsFastElementsKind(ElementsKind kind) {
ASSERT(FIRST_FAST_ELEMENTS_KIND == 0);
return kind <= FAST_HOLEY_DOUBLE_ELEMENTS;
@ -121,9 +140,15 @@ inline bool IsExternalFloatOrDoubleElementsKind(ElementsKind kind) {
}
inline bool IsFixedFloatElementsKind(ElementsKind kind) {
return kind == FLOAT32_ELEMENTS || kind == FLOAT64_ELEMENTS;
}
inline bool IsDoubleOrFloatElementsKind(ElementsKind kind) {
return IsFastDoubleElementsKind(kind) ||
IsExternalFloatOrDoubleElementsKind(kind);
IsExternalFloatOrDoubleElementsKind(kind) ||
IsFixedFloatElementsKind(kind);
}

View File

@ -48,7 +48,7 @@
// - FastDoubleElementsAccessor
// - FastPackedDoubleElementsAccessor
// - FastHoleyDoubleElementsAccessor
// - ExternalElementsAccessor (abstract)
// - TypedElementsAccessor (abstract)
// - ExternalByteElementsAccessor
// - ExternalUnsignedByteElementsAccessor
// - ExternalShortElementsAccessor
@ -58,6 +58,15 @@
// - ExternalFloatElementsAccessor
// - ExternalDoubleElementsAccessor
// - PixelElementsAccessor
// - FixedUint8ArrayAccessor
// - FixedInt8ArrayAccessor
// - FixedUint16ArrayAccessor
// - FixedInt16ArrayAccessor
// - FixedUint32ArrayAccessor
// - FixedInt32ArrayAccessor
// - FixedFloat32ArrayAccessor
// - FixedFloat64ArrayAccessor
// - FixedUint8ClampedArrayAccessor
// - DictionaryElementsAccessor
// - NonStrictArgumentsElementsAccessor
@ -104,7 +113,17 @@ static const int kPackedSizeNotKnown = -1;
EXTERNAL_FLOAT_ELEMENTS, ExternalFloatArray) \
V(ExternalDoubleElementsAccessor, \
EXTERNAL_DOUBLE_ELEMENTS, ExternalDoubleArray) \
V(PixelElementsAccessor, EXTERNAL_PIXEL_ELEMENTS, ExternalPixelArray)
V(PixelElementsAccessor, EXTERNAL_PIXEL_ELEMENTS, ExternalPixelArray) \
V(FixedUint8ArrayAccessor, UINT8_ELEMENTS, FixedUint8Array) \
V(FixedInt8ArrayAccessor, INT8_ELEMENTS, FixedInt8Array) \
V(FixedUint16ArrayAccessor, UINT16_ELEMENTS, FixedUint16Array) \
V(FixedInt16ArrayAccessor, INT16_ELEMENTS, FixedInt16Array) \
V(FixedUint32ArrayAccessor, UINT32_ELEMENTS, FixedUint32Array) \
V(FixedInt32ArrayAccessor, INT32_ELEMENTS, FixedInt32Array) \
V(FixedFloat32ArrayAccessor, FLOAT32_ELEMENTS, FixedFloat32Array) \
V(FixedFloat64ArrayAccessor, FLOAT64_ELEMENTS, FixedFloat64Array) \
V(FixedUint8ClampedArrayAccessor, UINT8_CLAMPED_ELEMENTS, \
FixedUint8ClampedArray)
template<ElementsKind Kind> class ElementsKindTraits {
@ -1096,6 +1115,26 @@ static inline ElementsKind ElementsKindForArray(FixedArrayBase* array) {
return EXTERNAL_DOUBLE_ELEMENTS;
case EXTERNAL_PIXEL_ARRAY_TYPE:
return EXTERNAL_PIXEL_ELEMENTS;
case FIXED_UINT8_ARRAY_TYPE:
return UINT8_ELEMENTS;
case FIXED_INT8_ARRAY_TYPE:
return INT8_ELEMENTS;
case FIXED_UINT16_ARRAY_TYPE:
return UINT16_ELEMENTS;
case FIXED_INT16_ARRAY_TYPE:
return INT16_ELEMENTS;
case FIXED_UINT32_ARRAY_TYPE:
return UINT32_ELEMENTS;
case FIXED_INT32_ARRAY_TYPE:
return INT32_ELEMENTS;
case FIXED_FLOAT32_ARRAY_TYPE:
return FLOAT32_ELEMENTS;
case FIXED_FLOAT64_ARRAY_TYPE:
return FLOAT64_ELEMENTS;
case FIXED_UINT8_CLAMPED_ARRAY_TYPE:
return UINT8_CLAMPED_ELEMENTS;
default:
UNREACHABLE();
}
@ -1158,6 +1197,15 @@ class FastSmiOrObjectElementsAccessor
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
case EXTERNAL_PIXEL_ELEMENTS:
case UINT8_ELEMENTS:
case INT8_ELEMENTS:
case UINT16_ELEMENTS:
case INT16_ELEMENTS:
case UINT32_ELEMENTS:
case INT32_ELEMENTS:
case FLOAT32_ELEMENTS:
case FLOAT64_ELEMENTS:
case UINT8_CLAMPED_ELEMENTS:
UNREACHABLE();
}
return NULL;
@ -1283,6 +1331,15 @@ class FastDoubleElementsAccessor
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
case EXTERNAL_PIXEL_ELEMENTS:
case UINT8_ELEMENTS:
case INT8_ELEMENTS:
case UINT16_ELEMENTS:
case INT16_ELEMENTS:
case UINT32_ELEMENTS:
case INT32_ELEMENTS:
case FLOAT32_ELEMENTS:
case FLOAT64_ELEMENTS:
case UINT8_CLAMPED_ELEMENTS:
UNREACHABLE();
}
return to->GetHeap()->undefined_value();
@ -1320,20 +1377,20 @@ class FastHoleyDoubleElementsAccessor
// Super class for all external element arrays.
template<typename ExternalElementsAccessorSubclass,
template<typename AccessorSubclass,
ElementsKind Kind>
class ExternalElementsAccessor
: public ElementsAccessorBase<ExternalElementsAccessorSubclass,
class TypedElementsAccessor
: public ElementsAccessorBase<AccessorSubclass,
ElementsKindTraits<Kind> > {
public:
explicit ExternalElementsAccessor(const char* name)
: ElementsAccessorBase<ExternalElementsAccessorSubclass,
explicit TypedElementsAccessor(const char* name)
: ElementsAccessorBase<AccessorSubclass,
ElementsKindTraits<Kind> >(name) {}
protected:
typedef typename ElementsKindTraits<Kind>::BackingStore BackingStore;
friend class ElementsAccessorBase<ExternalElementsAccessorSubclass,
friend class ElementsAccessorBase<AccessorSubclass,
ElementsKindTraits<Kind> >;
MUST_USE_RESULT static MaybeObject* GetImpl(Object* receiver,
@ -1341,7 +1398,7 @@ class ExternalElementsAccessor
uint32_t key,
FixedArrayBase* backing_store) {
return
key < ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store)
key < AccessorSubclass::GetCapacityImpl(backing_store)
? BackingStore::cast(backing_store)->get(key)
: backing_store->GetHeap()->undefined_value();
}
@ -1352,7 +1409,7 @@ class ExternalElementsAccessor
uint32_t key,
FixedArrayBase* backing_store) {
return
key < ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store)
key < AccessorSubclass::GetCapacityImpl(backing_store)
? NONE : ABSENT;
}
@ -1362,7 +1419,7 @@ class ExternalElementsAccessor
uint32_t key,
FixedArrayBase* backing_store) {
return
key < ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store)
key < AccessorSubclass::GetCapacityImpl(backing_store)
? FIELD : NONEXISTENT;
}
@ -1387,102 +1444,176 @@ class ExternalElementsAccessor
uint32_t key,
FixedArrayBase* backing_store) {
uint32_t capacity =
ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store);
AccessorSubclass::GetCapacityImpl(backing_store);
return key < capacity;
}
};
class ExternalByteElementsAccessor
: public ExternalElementsAccessor<ExternalByteElementsAccessor,
: public TypedElementsAccessor<ExternalByteElementsAccessor,
EXTERNAL_BYTE_ELEMENTS> {
public:
explicit ExternalByteElementsAccessor(const char* name)
: ExternalElementsAccessor<ExternalByteElementsAccessor,
: TypedElementsAccessor<ExternalByteElementsAccessor,
EXTERNAL_BYTE_ELEMENTS>(name) {}
};
class ExternalUnsignedByteElementsAccessor
: public ExternalElementsAccessor<ExternalUnsignedByteElementsAccessor,
: public TypedElementsAccessor<ExternalUnsignedByteElementsAccessor,
EXTERNAL_UNSIGNED_BYTE_ELEMENTS> {
public:
explicit ExternalUnsignedByteElementsAccessor(const char* name)
: ExternalElementsAccessor<ExternalUnsignedByteElementsAccessor,
: TypedElementsAccessor<ExternalUnsignedByteElementsAccessor,
EXTERNAL_UNSIGNED_BYTE_ELEMENTS>(name) {}
};
class ExternalShortElementsAccessor
: public ExternalElementsAccessor<ExternalShortElementsAccessor,
: public TypedElementsAccessor<ExternalShortElementsAccessor,
EXTERNAL_SHORT_ELEMENTS> {
public:
explicit ExternalShortElementsAccessor(const char* name)
: ExternalElementsAccessor<ExternalShortElementsAccessor,
: TypedElementsAccessor<ExternalShortElementsAccessor,
EXTERNAL_SHORT_ELEMENTS>(name) {}
};
class ExternalUnsignedShortElementsAccessor
: public ExternalElementsAccessor<ExternalUnsignedShortElementsAccessor,
: public TypedElementsAccessor<ExternalUnsignedShortElementsAccessor,
EXTERNAL_UNSIGNED_SHORT_ELEMENTS> {
public:
explicit ExternalUnsignedShortElementsAccessor(const char* name)
: ExternalElementsAccessor<ExternalUnsignedShortElementsAccessor,
: TypedElementsAccessor<ExternalUnsignedShortElementsAccessor,
EXTERNAL_UNSIGNED_SHORT_ELEMENTS>(name) {}
};
class ExternalIntElementsAccessor
: public ExternalElementsAccessor<ExternalIntElementsAccessor,
: public TypedElementsAccessor<ExternalIntElementsAccessor,
EXTERNAL_INT_ELEMENTS> {
public:
explicit ExternalIntElementsAccessor(const char* name)
: ExternalElementsAccessor<ExternalIntElementsAccessor,
: TypedElementsAccessor<ExternalIntElementsAccessor,
EXTERNAL_INT_ELEMENTS>(name) {}
};
class ExternalUnsignedIntElementsAccessor
: public ExternalElementsAccessor<ExternalUnsignedIntElementsAccessor,
: public TypedElementsAccessor<ExternalUnsignedIntElementsAccessor,
EXTERNAL_UNSIGNED_INT_ELEMENTS> {
public:
explicit ExternalUnsignedIntElementsAccessor(const char* name)
: ExternalElementsAccessor<ExternalUnsignedIntElementsAccessor,
: TypedElementsAccessor<ExternalUnsignedIntElementsAccessor,
EXTERNAL_UNSIGNED_INT_ELEMENTS>(name) {}
};
class ExternalFloatElementsAccessor
: public ExternalElementsAccessor<ExternalFloatElementsAccessor,
: public TypedElementsAccessor<ExternalFloatElementsAccessor,
EXTERNAL_FLOAT_ELEMENTS> {
public:
explicit ExternalFloatElementsAccessor(const char* name)
: ExternalElementsAccessor<ExternalFloatElementsAccessor,
: TypedElementsAccessor<ExternalFloatElementsAccessor,
EXTERNAL_FLOAT_ELEMENTS>(name) {}
};
class ExternalDoubleElementsAccessor
: public ExternalElementsAccessor<ExternalDoubleElementsAccessor,
: public TypedElementsAccessor<ExternalDoubleElementsAccessor,
EXTERNAL_DOUBLE_ELEMENTS> {
public:
explicit ExternalDoubleElementsAccessor(const char* name)
: ExternalElementsAccessor<ExternalDoubleElementsAccessor,
: TypedElementsAccessor<ExternalDoubleElementsAccessor,
EXTERNAL_DOUBLE_ELEMENTS>(name) {}
};
class PixelElementsAccessor
: public ExternalElementsAccessor<PixelElementsAccessor,
: public TypedElementsAccessor<PixelElementsAccessor,
EXTERNAL_PIXEL_ELEMENTS> {
public:
explicit PixelElementsAccessor(const char* name)
: ExternalElementsAccessor<PixelElementsAccessor,
: TypedElementsAccessor<PixelElementsAccessor,
EXTERNAL_PIXEL_ELEMENTS>(name) {}
};
class FixedUint8ArrayAccessor
: public TypedElementsAccessor<FixedUint8ArrayAccessor,
UINT8_ELEMENTS> {
public:
explicit FixedUint8ArrayAccessor(const char* name)
: TypedElementsAccessor<FixedUint8ArrayAccessor,
UINT8_ELEMENTS>(name) {}
};
class FixedUint8ClampedArrayAccessor
: public TypedElementsAccessor<FixedUint8ClampedArrayAccessor,
UINT8_CLAMPED_ELEMENTS> {
public:
explicit FixedUint8ClampedArrayAccessor(const char* name)
: TypedElementsAccessor<FixedUint8ClampedArrayAccessor,
UINT8_CLAMPED_ELEMENTS>(name) {}
};
class FixedInt8ArrayAccessor
: public TypedElementsAccessor<FixedInt8ArrayAccessor,
INT8_ELEMENTS> {
public:
explicit FixedInt8ArrayAccessor(const char* name)
: TypedElementsAccessor<FixedInt8ArrayAccessor,
INT8_ELEMENTS>(name) {}
};
class FixedUint16ArrayAccessor
: public TypedElementsAccessor<FixedUint16ArrayAccessor,
UINT16_ELEMENTS> {
public:
explicit FixedUint16ArrayAccessor(const char* name)
: TypedElementsAccessor<FixedUint16ArrayAccessor,
UINT16_ELEMENTS>(name) {}
};
class FixedInt16ArrayAccessor
: public TypedElementsAccessor<FixedInt16ArrayAccessor,
INT16_ELEMENTS> {
public:
explicit FixedInt16ArrayAccessor(const char* name)
: TypedElementsAccessor<FixedInt16ArrayAccessor,
INT16_ELEMENTS>(name) {}
};
class FixedUint32ArrayAccessor
: public TypedElementsAccessor<FixedUint32ArrayAccessor,
UINT32_ELEMENTS> {
public:
explicit FixedUint32ArrayAccessor(const char* name)
: TypedElementsAccessor<FixedUint32ArrayAccessor,
UINT32_ELEMENTS>(name) {}
};
class FixedInt32ArrayAccessor
: public TypedElementsAccessor<FixedInt32ArrayAccessor,
INT32_ELEMENTS> {
public:
explicit FixedInt32ArrayAccessor(const char* name)
: TypedElementsAccessor<FixedInt32ArrayAccessor,
INT32_ELEMENTS>(name) {}
};
class FixedFloat32ArrayAccessor
: public TypedElementsAccessor<FixedFloat32ArrayAccessor,
FLOAT32_ELEMENTS> {
public:
explicit FixedFloat32ArrayAccessor(const char* name)
: TypedElementsAccessor<FixedFloat32ArrayAccessor,
FLOAT32_ELEMENTS>(name) {}
};
class FixedFloat64ArrayAccessor
: public TypedElementsAccessor<FixedFloat64ArrayAccessor,
FLOAT64_ELEMENTS> {
public:
explicit FixedFloat64ArrayAccessor(const char* name)
: TypedElementsAccessor<FixedFloat64ArrayAccessor,
FLOAT64_ELEMENTS>(name) {}
};
class DictionaryElementsAccessor
: public ElementsAccessorBase<DictionaryElementsAccessor,
ElementsKindTraits<DICTIONARY_ELEMENTS> > {

View File

@ -729,7 +729,7 @@ Handle<ExternalArray> Factory::NewExternalArray(int length,
ExternalArrayType array_type,
void* external_pointer,
PretenureFlag pretenure) {
ASSERT(0 <= length);
ASSERT(0 <= length && length <= Smi::kMaxValue);
CALL_HEAP_FUNCTION(
isolate(),
isolate()->heap()->AllocateExternalArray(length,
@ -740,6 +740,20 @@ Handle<ExternalArray> Factory::NewExternalArray(int length,
}
Handle<FixedTypedArrayBase> Factory::NewFixedTypedArray(
int length,
ExternalArrayType array_type,
PretenureFlag pretenure) {
ASSERT(0 <= length && length <= Smi::kMaxValue);
CALL_HEAP_FUNCTION(
isolate(),
isolate()->heap()->AllocateFixedTypedArray(length,
array_type,
pretenure),
FixedTypedArrayBase);
}
Handle<Cell> Factory::NewCell(Handle<Object> value) {
AllowDeferredHandleDereference convert_to_cell;
CALL_HEAP_FUNCTION(

View File

@ -257,6 +257,11 @@ class Factory {
void* external_pointer,
PretenureFlag pretenure = NOT_TENURED);
Handle<FixedTypedArrayBase> NewFixedTypedArray(
int length,
ExternalArrayType array_type,
PretenureFlag pretenure = NOT_TENURED);
Handle<Cell> NewCell(Handle<Object> value);
Handle<PropertyCell> NewPropertyCellWithHole();

View File

@ -31,6 +31,7 @@
#include <cmath>
#include "heap.h"
#include "heap-profiler.h"
#include "isolate.h"
#include "list-inl.h"
#include "objects.h"
@ -666,7 +667,7 @@ Isolate* Heap::isolate() {
} \
if (__maybe_object__->IsRetryAfterGC()) { \
/* TODO(1181417): Fix this. */ \
v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY_LAST", true); \
v8::internal::Heap::FatalProcessOutOfMemory("CALL_AND_RETRY_LAST", true);\
} \
RETURN_EMPTY; \
} while (false)
@ -678,7 +679,7 @@ Isolate* Heap::isolate() {
FUNCTION_CALL, \
RETURN_VALUE, \
RETURN_EMPTY, \
v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY", true))
v8::internal::Heap::FatalProcessOutOfMemory("CALL_AND_RETRY", true))
#define CALL_HEAP_FUNCTION(ISOLATE, FUNCTION_CALL, TYPE) \
CALL_AND_RETRY_OR_DIE(ISOLATE, \

View File

@ -2778,33 +2778,23 @@ bool Heap::CreateInitialMaps() {
constant_pool_array_map()->set_prototype(null_value());
constant_pool_array_map()->set_constructor(null_value());
{ MaybeObject* maybe_obj =
AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
if (!maybe_obj->ToObject(&obj)) return false;
{ // Map allocation
#define ALLOCATE_MAP(instance_type, size, field_name) \
{ Map* map; \
if (!AllocateMap((instance_type), size)->To(&map)) return false; \
set_##field_name##_map(map); \
}
set_fixed_cow_array_map(Map::cast(obj));
#define ALLOCATE_VARSIZE_MAP(instance_type, field_name) \
ALLOCATE_MAP(instance_type, kVariableSizeSentinel, field_name)
ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, fixed_cow_array)
ASSERT(fixed_array_map() != fixed_cow_array_map());
{ MaybeObject* maybe_obj =
AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_scope_info_map(Map::cast(obj));
{ MaybeObject* maybe_obj = AllocateMap(HEAP_NUMBER_TYPE, HeapNumber::kSize);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_heap_number_map(Map::cast(obj));
{ MaybeObject* maybe_obj = AllocateMap(SYMBOL_TYPE, Symbol::kSize);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_symbol_map(Map::cast(obj));
{ MaybeObject* maybe_obj = AllocateMap(FOREIGN_TYPE, Foreign::kSize);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_foreign_map(Map::cast(obj));
ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, scope_info)
ALLOCATE_MAP(HEAP_NUMBER_TYPE, HeapNumber::kSize, heap_number)
ALLOCATE_MAP(SYMBOL_TYPE, Symbol::kSize, symbol)
ALLOCATE_MAP(FOREIGN_TYPE, Foreign::kSize, foreign)
for (unsigned i = 0; i < ARRAY_SIZE(string_type_table); i++) {
const StringTypeTable& entry = string_type_table[i];
@ -2814,255 +2804,110 @@ bool Heap::CreateInitialMaps() {
roots_[entry.index] = Map::cast(obj);
}
{ MaybeObject* maybe_obj = AllocateMap(STRING_TYPE, kVariableSizeSentinel);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_undetectable_string_map(Map::cast(obj));
Map::cast(obj)->set_is_undetectable();
ALLOCATE_VARSIZE_MAP(STRING_TYPE, undetectable_string)
undetectable_string_map()->set_is_undetectable();
{ MaybeObject* maybe_obj =
AllocateMap(ASCII_STRING_TYPE, kVariableSizeSentinel);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_undetectable_ascii_string_map(Map::cast(obj));
Map::cast(obj)->set_is_undetectable();
ALLOCATE_VARSIZE_MAP(ASCII_STRING_TYPE, undetectable_ascii_string);
undetectable_ascii_string_map()->set_is_undetectable();
{ MaybeObject* maybe_obj =
AllocateMap(FIXED_DOUBLE_ARRAY_TYPE, kVariableSizeSentinel);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_fixed_double_array_map(Map::cast(obj));
ALLOCATE_VARSIZE_MAP(FIXED_DOUBLE_ARRAY_TYPE, fixed_double_array)
ALLOCATE_VARSIZE_MAP(BYTE_ARRAY_TYPE, byte_array)
ALLOCATE_VARSIZE_MAP(FREE_SPACE_TYPE, free_space)
{ MaybeObject* maybe_obj =
AllocateMap(BYTE_ARRAY_TYPE, kVariableSizeSentinel);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_byte_array_map(Map::cast(obj));
#define ALLOCATE_EXTERNAL_ARRAY_MAP(TYPE, type) \
ALLOCATE_MAP(EXTERNAL_##TYPE##_ARRAY_TYPE, ExternalArray::kAlignedSize, \
external_##type##_array)
{ MaybeObject* maybe_obj =
AllocateMap(FREE_SPACE_TYPE, kVariableSizeSentinel);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_free_space_map(Map::cast(obj));
ALLOCATE_EXTERNAL_ARRAY_MAP(PIXEL, pixel)
ALLOCATE_EXTERNAL_ARRAY_MAP(BYTE, byte)
ALLOCATE_EXTERNAL_ARRAY_MAP(UNSIGNED_BYTE, unsigned_byte)
ALLOCATE_EXTERNAL_ARRAY_MAP(SHORT, short) // NOLINT
ALLOCATE_EXTERNAL_ARRAY_MAP(UNSIGNED_SHORT, unsigned_short)
ALLOCATE_EXTERNAL_ARRAY_MAP(INT, int)
ALLOCATE_EXTERNAL_ARRAY_MAP(UNSIGNED_INT, unsigned_int)
ALLOCATE_EXTERNAL_ARRAY_MAP(FLOAT, float)
ALLOCATE_EXTERNAL_ARRAY_MAP(DOUBLE, double)
#undef ALLOCATE_EXTERNAL_ARRAY_MAP
{ MaybeObject* maybe_obj = AllocateByteArray(0, TENURED);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_empty_byte_array(ByteArray::cast(obj));
ALLOCATE_VARSIZE_MAP(FIXED_UINT8_ARRAY_TYPE, fixed_uint8_array)
ALLOCATE_VARSIZE_MAP(FIXED_UINT8_CLAMPED_ARRAY_TYPE,
fixed_uint8_clamped_array)
ALLOCATE_VARSIZE_MAP(FIXED_INT8_ARRAY_TYPE, fixed_int8_array)
ALLOCATE_VARSIZE_MAP(FIXED_UINT16_ARRAY_TYPE, fixed_uint16_array)
ALLOCATE_VARSIZE_MAP(FIXED_INT16_ARRAY_TYPE, fixed_int16_array)
ALLOCATE_VARSIZE_MAP(FIXED_UINT32_ARRAY_TYPE, fixed_uint32_array)
ALLOCATE_VARSIZE_MAP(FIXED_INT32_ARRAY_TYPE, fixed_int32_array)
ALLOCATE_VARSIZE_MAP(FIXED_FLOAT32_ARRAY_TYPE, fixed_float32_array)
ALLOCATE_VARSIZE_MAP(FIXED_FLOAT64_ARRAY_TYPE, fixed_float64_array)
{ MaybeObject* maybe_obj =
AllocateMap(EXTERNAL_PIXEL_ARRAY_TYPE, ExternalArray::kAlignedSize);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_external_pixel_array_map(Map::cast(obj));
ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, non_strict_arguments_elements)
{ MaybeObject* maybe_obj = AllocateMap(EXTERNAL_BYTE_ARRAY_TYPE,
ExternalArray::kAlignedSize);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_external_byte_array_map(Map::cast(obj));
ALLOCATE_VARSIZE_MAP(CODE_TYPE, code)
{ MaybeObject* maybe_obj = AllocateMap(EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE,
ExternalArray::kAlignedSize);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_external_unsigned_byte_array_map(Map::cast(obj));
ALLOCATE_MAP(CELL_TYPE, Cell::kSize, cell)
ALLOCATE_MAP(PROPERTY_CELL_TYPE, PropertyCell::kSize, global_property_cell)
ALLOCATE_MAP(FILLER_TYPE, kPointerSize, one_pointer_filler)
ALLOCATE_MAP(FILLER_TYPE, 2 * kPointerSize, two_pointer_filler)
{ MaybeObject* maybe_obj = AllocateMap(EXTERNAL_SHORT_ARRAY_TYPE,
ExternalArray::kAlignedSize);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_external_short_array_map(Map::cast(obj));
{ MaybeObject* maybe_obj = AllocateMap(EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE,
ExternalArray::kAlignedSize);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_external_unsigned_short_array_map(Map::cast(obj));
{ MaybeObject* maybe_obj = AllocateMap(EXTERNAL_INT_ARRAY_TYPE,
ExternalArray::kAlignedSize);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_external_int_array_map(Map::cast(obj));
{ MaybeObject* maybe_obj = AllocateMap(EXTERNAL_UNSIGNED_INT_ARRAY_TYPE,
ExternalArray::kAlignedSize);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_external_unsigned_int_array_map(Map::cast(obj));
{ MaybeObject* maybe_obj = AllocateMap(EXTERNAL_FLOAT_ARRAY_TYPE,
ExternalArray::kAlignedSize);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_external_float_array_map(Map::cast(obj));
{ MaybeObject* maybe_obj =
AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_non_strict_arguments_elements_map(Map::cast(obj));
{ MaybeObject* maybe_obj = AllocateMap(EXTERNAL_DOUBLE_ARRAY_TYPE,
ExternalArray::kAlignedSize);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_external_double_array_map(Map::cast(obj));
{ MaybeObject* maybe_obj = AllocateEmptyExternalArray(kExternalByteArray);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_empty_external_byte_array(ExternalArray::cast(obj));
{ MaybeObject* maybe_obj =
AllocateEmptyExternalArray(kExternalUnsignedByteArray);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_empty_external_unsigned_byte_array(ExternalArray::cast(obj));
{ MaybeObject* maybe_obj = AllocateEmptyExternalArray(kExternalShortArray);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_empty_external_short_array(ExternalArray::cast(obj));
{ MaybeObject* maybe_obj = AllocateEmptyExternalArray(
kExternalUnsignedShortArray);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_empty_external_unsigned_short_array(ExternalArray::cast(obj));
{ MaybeObject* maybe_obj = AllocateEmptyExternalArray(kExternalIntArray);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_empty_external_int_array(ExternalArray::cast(obj));
{ MaybeObject* maybe_obj =
AllocateEmptyExternalArray(kExternalUnsignedIntArray);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_empty_external_unsigned_int_array(ExternalArray::cast(obj));
{ MaybeObject* maybe_obj = AllocateEmptyExternalArray(kExternalFloatArray);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_empty_external_float_array(ExternalArray::cast(obj));
{ MaybeObject* maybe_obj = AllocateEmptyExternalArray(kExternalDoubleArray);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_empty_external_double_array(ExternalArray::cast(obj));
{ MaybeObject* maybe_obj = AllocateEmptyExternalArray(kExternalPixelArray);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_empty_external_pixel_array(ExternalArray::cast(obj));
{ MaybeObject* maybe_obj = AllocateMap(CODE_TYPE, kVariableSizeSentinel);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_code_map(Map::cast(obj));
{ MaybeObject* maybe_obj = AllocateMap(CELL_TYPE, Cell::kSize);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_cell_map(Map::cast(obj));
{ MaybeObject* maybe_obj = AllocateMap(PROPERTY_CELL_TYPE,
PropertyCell::kSize);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_global_property_cell_map(Map::cast(obj));
{ MaybeObject* maybe_obj = AllocateMap(FILLER_TYPE, kPointerSize);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_one_pointer_filler_map(Map::cast(obj));
{ MaybeObject* maybe_obj = AllocateMap(FILLER_TYPE, 2 * kPointerSize);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_two_pointer_filler_map(Map::cast(obj));
for (unsigned i = 0; i < ARRAY_SIZE(struct_table); i++) {
const StructTable& entry = struct_table[i];
{ MaybeObject* maybe_obj = AllocateMap(entry.type, entry.size);
if (!maybe_obj->ToObject(&obj)) return false;
}
roots_[entry.index] = Map::cast(obj);
Map* map;
if (!AllocateMap(entry.type, entry.size)->To(&map))
return false;
roots_[entry.index] = map;
}
{ MaybeObject* maybe_obj =
AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_hash_table_map(Map::cast(obj));
ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, hash_table)
{ MaybeObject* maybe_obj =
AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_function_context_map(Map::cast(obj));
ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, function_context)
ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, catch_context)
ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, with_context)
ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, block_context)
ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, module_context)
ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, global_context)
{ MaybeObject* maybe_obj =
AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_catch_context_map(Map::cast(obj));
ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, native_context)
native_context_map()->set_dictionary_map(true);
native_context_map()->set_visitor_id(
StaticVisitorBase::kVisitNativeContext);
{ MaybeObject* maybe_obj =
AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_with_context_map(Map::cast(obj));
ALLOCATE_MAP(SHARED_FUNCTION_INFO_TYPE, SharedFunctionInfo::kAlignedSize,
shared_function_info)
{ MaybeObject* maybe_obj =
AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
if (!maybe_obj->ToObject(&obj)) return false;
ALLOCATE_MAP(JS_MESSAGE_OBJECT_TYPE, JSMessageObject::kSize,
message_object)
ALLOCATE_MAP(JS_OBJECT_TYPE, JSObject::kHeaderSize + kPointerSize,
external)
external_map()->set_is_extensible(false);
#undef ALLOCATE_VARSIZE_MAP
#undef ALLOCATE_MAP
}
set_block_context_map(Map::cast(obj));
{ MaybeObject* maybe_obj =
AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
if (!maybe_obj->ToObject(&obj)) return false;
{ // Empty arrays
{ ByteArray* byte_array;
if (!AllocateByteArray(0, TENURED)->To(&byte_array)) return false;
set_empty_byte_array(byte_array);
}
set_module_context_map(Map::cast(obj));
{ MaybeObject* maybe_obj =
AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
if (!maybe_obj->ToObject(&obj)) return false;
#define ALLOCATE_EMPTY_EXTERNAL_ARRAY(Type, type) \
{ ExternalArray* obj; \
if (!AllocateEmptyExternalArray(kExternal##Type##Array)->To(&obj)) \
return false; \
set_empty_external_##type##_array(obj); \
}
set_global_context_map(Map::cast(obj));
{ MaybeObject* maybe_obj =
AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
if (!maybe_obj->ToObject(&obj)) return false;
ALLOCATE_EMPTY_EXTERNAL_ARRAY(Byte, byte)
ALLOCATE_EMPTY_EXTERNAL_ARRAY(UnsignedByte, unsigned_byte)
ALLOCATE_EMPTY_EXTERNAL_ARRAY(Short, short) // NOLINT
ALLOCATE_EMPTY_EXTERNAL_ARRAY(UnsignedShort, unsigned_short)
ALLOCATE_EMPTY_EXTERNAL_ARRAY(Int, int)
ALLOCATE_EMPTY_EXTERNAL_ARRAY(UnsignedInt, unsigned_int)
ALLOCATE_EMPTY_EXTERNAL_ARRAY(Float, float)
ALLOCATE_EMPTY_EXTERNAL_ARRAY(Double, double)
ALLOCATE_EMPTY_EXTERNAL_ARRAY(Pixel, pixel)
#undef ALLOCATE_EMPTY_EXTERNAL_ARRAY
}
Map* native_context_map = Map::cast(obj);
native_context_map->set_dictionary_map(true);
native_context_map->set_visitor_id(StaticVisitorBase::kVisitNativeContext);
set_native_context_map(native_context_map);
{ MaybeObject* maybe_obj = AllocateMap(SHARED_FUNCTION_INFO_TYPE,
SharedFunctionInfo::kAlignedSize);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_shared_function_info_map(Map::cast(obj));
{ MaybeObject* maybe_obj = AllocateMap(JS_MESSAGE_OBJECT_TYPE,
JSMessageObject::kSize);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_message_object_map(Map::cast(obj));
Map* external_map;
{ MaybeObject* maybe_obj =
AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize + kPointerSize);
if (!maybe_obj->To(&external_map)) return false;
}
external_map->set_is_extensible(false);
set_external_map(external_map);
ASSERT(!InNewSpace(empty_fixed_array()));
return true;
}
@ -3771,6 +3616,39 @@ Heap::RootListIndex Heap::RootIndexForExternalArrayType(
}
Map* Heap::MapForFixedTypedArray(ExternalArrayType array_type) {
return Map::cast(roots_[RootIndexForFixedTypedArray(array_type)]);
}
Heap::RootListIndex Heap::RootIndexForFixedTypedArray(
ExternalArrayType array_type) {
switch (array_type) {
case kExternalByteArray:
return kFixedInt8ArrayMapRootIndex;
case kExternalUnsignedByteArray:
return kFixedUint8ArrayMapRootIndex;
case kExternalShortArray:
return kFixedInt16ArrayMapRootIndex;
case kExternalUnsignedShortArray:
return kFixedUint16ArrayMapRootIndex;
case kExternalIntArray:
return kFixedInt32ArrayMapRootIndex;
case kExternalUnsignedIntArray:
return kFixedUint32ArrayMapRootIndex;
case kExternalFloatArray:
return kFixedFloat32ArrayMapRootIndex;
case kExternalDoubleArray:
return kFixedFloat64ArrayMapRootIndex;
case kExternalPixelArray:
return kFixedUint8ClampedArrayMapRootIndex;
default:
UNREACHABLE();
return kUndefinedValueRootIndex;
}
}
Heap::RootListIndex Heap::RootIndexForEmptyExternalArray(
ElementsKind elementsKind) {
switch (elementsKind) {
@ -4029,6 +3907,84 @@ MaybeObject* Heap::AllocateExternalArray(int length,
return result;
}
static void ForFixedTypedArray(ExternalArrayType array_type,
int* element_size,
ElementsKind* element_kind) {
switch (array_type) {
case kExternalUnsignedByteArray:
*element_size = 1;
*element_kind = UINT8_ELEMENTS;
return;
case kExternalByteArray:
*element_size = 1;
*element_kind = INT8_ELEMENTS;
return;
case kExternalUnsignedShortArray:
*element_size = 2;
*element_kind = UINT16_ELEMENTS;
return;
case kExternalShortArray:
*element_size = 2;
*element_kind = INT16_ELEMENTS;
return;
case kExternalUnsignedIntArray:
*element_size = 4;
*element_kind = UINT32_ELEMENTS;
return;
case kExternalIntArray:
*element_size = 4;
*element_kind = INT32_ELEMENTS;
return;
case kExternalFloatArray:
*element_size = 4;
*element_kind = FLOAT32_ELEMENTS;
return;
case kExternalDoubleArray:
*element_size = 8;
*element_kind = FLOAT64_ELEMENTS;
return;
case kExternalPixelArray:
*element_size = 1;
*element_kind = UINT8_CLAMPED_ELEMENTS;
return;
default:
*element_size = 0; // Bogus
*element_kind = UINT8_ELEMENTS; // Bogus
UNREACHABLE();
}
}
MaybeObject* Heap::AllocateFixedTypedArray(int length,
ExternalArrayType array_type,
PretenureFlag pretenure) {
int element_size;
ElementsKind elements_kind;
ForFixedTypedArray(array_type, &element_size, &elements_kind);
int size = OBJECT_POINTER_ALIGN(
length * element_size + FixedTypedArrayBase::kDataOffset);
#ifndef V8_HOST_ARCH_64_BIT
if (array_type == kExternalDoubleArray) {
size += kPointerSize;
}
#endif
AllocationSpace space = SelectSpace(size, OLD_DATA_SPACE, pretenure);
HeapObject* object;
MaybeObject* maybe_object = AllocateRaw(size, space, OLD_DATA_SPACE);
if (!maybe_object->To(&object)) return maybe_object;
if (array_type == kExternalDoubleArray) {
object = EnsureDoubleAligned(this, object, size);
}
FixedTypedArrayBase* elements =
reinterpret_cast<FixedTypedArrayBase*>(object);
elements->set_map(MapForFixedTypedArray(array_type));
elements->set_length(length);
return elements;
}
MaybeObject* Heap::CreateCode(const CodeDesc& desc,
Code::Flags flags,
@ -6822,6 +6778,10 @@ void Heap::EnsureWeakObjectToCodeTable() {
}
void Heap::FatalProcessOutOfMemory(const char* location, bool take_snapshot) {
v8::internal::V8::FatalProcessOutOfMemory(location, take_snapshot);
}
#ifdef DEBUG
class PrintHandleVisitor: public ObjectVisitor {

View File

@ -156,6 +156,15 @@ namespace internal {
V(ExternalArray, empty_external_double_array, EmptyExternalDoubleArray) \
V(ExternalArray, empty_external_pixel_array, \
EmptyExternalPixelArray) \
V(Map, fixed_uint8_array_map, FixedUint8ArrayMap) \
V(Map, fixed_int8_array_map, FixedInt8ArrayMap) \
V(Map, fixed_uint16_array_map, FixedUint16ArrayMap) \
V(Map, fixed_int16_array_map, FixedInt16ArrayMap) \
V(Map, fixed_uint32_array_map, FixedUint32ArrayMap) \
V(Map, fixed_int32_array_map, FixedInt32ArrayMap) \
V(Map, fixed_float32_array_map, FixedFloat32ArrayMap) \
V(Map, fixed_float64_array_map, FixedFloat64ArrayMap) \
V(Map, fixed_uint8_clamped_array_map, FixedUint8ClampedArrayMap) \
V(Map, non_strict_arguments_elements_map, NonStrictArgumentsElementsMap) \
V(Map, function_context_map, FunctionContextMap) \
V(Map, catch_context_map, CatchContextMap) \
@ -875,6 +884,15 @@ class Heap {
void* external_pointer,
PretenureFlag pretenure);
// Allocates a fixed typed array of the specified length and type.
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed.
// Please note this does not perform a garbage collection.
MUST_USE_RESULT MaybeObject* AllocateFixedTypedArray(
int length,
ExternalArrayType array_type,
PretenureFlag pretenure);
// Allocate a symbol in old space.
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed.
@ -1561,6 +1579,10 @@ class Heap {
MUST_USE_RESULT MaybeObject* Uint32ToString(
uint32_t value, bool check_number_string_cache = true);
Map* MapForFixedTypedArray(ExternalArrayType array_type);
RootListIndex RootIndexForFixedTypedArray(
ExternalArrayType array_type);
Map* MapForExternalArrayType(ExternalArrayType array_type);
RootListIndex RootIndexForExternalArrayType(
ExternalArrayType array_type);
@ -1843,6 +1865,9 @@ class Heap {
void EnsureWeakObjectToCodeTable();
static void FatalProcessOutOfMemory(const char* location,
bool take_snapshot = false);
private:
Heap();

View File

@ -207,7 +207,8 @@ class LChunkBuilder;
V(InobjectFields) \
V(OsrEntries) \
V(ExternalMemory) \
V(StringChars)
V(StringChars) \
V(TypedArrayElements)
#define DECLARE_ABSTRACT_INSTRUCTION(type) \
@ -6366,6 +6367,12 @@ class HLoadKeyed V8_FINAL
bool is_external() const {
return IsExternalArrayElementsKind(elements_kind());
}
bool is_fixed_typed_array() const {
return IsFixedTypedArrayElementsKind(elements_kind());
}
bool is_typed_elements() const {
return is_external() || is_fixed_typed_array();
}
HValue* elements() { return OperandAt(0); }
HValue* key() { return OperandAt(1); }
HValue* dependency() {
@ -6396,6 +6403,7 @@ class HLoadKeyed V8_FINAL
virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
// kind_fast: tagged[int32] (none)
// kind_double: tagged[int32] (none)
// kind_fixed_typed_array: tagged[int32] (none)
// kind_external: external[int32] (none)
if (index == 0) {
return is_external() ? Representation::External()
@ -6446,7 +6454,7 @@ class HLoadKeyed V8_FINAL
SetOperandAt(1, key);
SetOperandAt(2, dependency != NULL ? dependency : obj);
if (!is_external()) {
if (!is_typed_elements()) {
// I can detect the case between storing double (holey and fast) and
// smi/object by looking at elements_kind_.
ASSERT(IsFastSmiOrObjectElementsKind(elements_kind) ||
@ -6473,13 +6481,21 @@ class HLoadKeyed V8_FINAL
}
} else {
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
elements_kind == EXTERNAL_DOUBLE_ELEMENTS ||
elements_kind == FLOAT32_ELEMENTS ||
elements_kind == FLOAT64_ELEMENTS) {
set_representation(Representation::Double());
} else {
set_representation(Representation::Integer32());
}
if (is_external()) {
SetGVNFlag(kDependsOnExternalMemory);
} else if (is_fixed_typed_array()) {
SetGVNFlag(kDependsOnTypedArrayElements);
} else {
UNREACHABLE();
}
// Native code could change the specialized array.
SetGVNFlag(kDependsOnCalls);
}
@ -6741,6 +6757,7 @@ class HStoreKeyed V8_FINAL
// kind_fast: tagged[int32] = tagged
// kind_double: tagged[int32] = double
// kind_smi : tagged[int32] = smi
// kind_fixed_typed_array: tagged[int32] = (double | int32)
// kind_external: external[int32] = (double | int32)
if (index == 0) {
return is_external() ? Representation::External()
@ -6761,7 +6778,8 @@ class HStoreKeyed V8_FINAL
return Representation::Smi();
}
return is_external() ? Representation::Integer32()
return is_external() || is_fixed_typed_array()
? Representation::Integer32()
: Representation::Tagged();
}
@ -6769,6 +6787,14 @@ class HStoreKeyed V8_FINAL
return IsExternalArrayElementsKind(elements_kind());
}
bool is_fixed_typed_array() const {
return IsFixedTypedArrayElementsKind(elements_kind());
}
bool is_typed_elements() const {
return is_external() || is_fixed_typed_array();
}
virtual Representation observed_input_representation(int index) V8_OVERRIDE {
if (index < 2) return RequiredInputRepresentation(index);
if (IsUninitialized()) {
@ -6783,7 +6809,7 @@ class HStoreKeyed V8_FINAL
if (IsFastSmiElementsKind(elements_kind())) {
return Representation::Smi();
}
if (is_external()) {
if (is_typed_elements()) {
return Representation::Integer32();
}
// For fast object elements kinds, don't assume anything.
@ -6868,13 +6894,18 @@ class HStoreKeyed V8_FINAL
SetGVNFlag(kChangesDoubleArrayElements);
} else if (IsFastSmiElementsKind(elements_kind)) {
SetGVNFlag(kChangesArrayElements);
} else if (is_fixed_typed_array()) {
SetGVNFlag(kChangesTypedArrayElements);
SetFlag(kAllowUndefinedAsNaN);
} else {
SetGVNFlag(kChangesArrayElements);
}
// EXTERNAL_{UNSIGNED_,}{BYTE,SHORT,INT}_ELEMENTS are truncating.
if (elements_kind >= EXTERNAL_BYTE_ELEMENTS &&
elements_kind <= EXTERNAL_UNSIGNED_INT_ELEMENTS) {
if ((elements_kind >= EXTERNAL_BYTE_ELEMENTS &&
elements_kind <= EXTERNAL_UNSIGNED_INT_ELEMENTS) ||
(elements_kind >= UINT8_ELEMENTS &&
elements_kind <= INT32_ELEMENTS)) {
SetFlag(kTruncatingToInt32);
}
}

View File

@ -2078,7 +2078,9 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
bool is_store,
LoadKeyedHoleMode load_mode,
KeyedAccessStoreMode store_mode) {
ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array);
ASSERT((!IsExternalArrayElementsKind(elements_kind) &&
!IsFixedTypedArrayElementsKind(elements_kind)) ||
!is_js_array);
// No GVNFlag is necessary for ElementsKind if there is an explicit dependency
// on a HElementsTransition instruction. The flag can also be removed if the
// map to check has FAST_HOLEY_ELEMENTS, since there can be no further
@ -2108,11 +2110,17 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
}
length->set_type(HType::Smi());
HValue* checked_key = NULL;
if (IsExternalArrayElementsKind(elements_kind) ||
IsFixedTypedArrayElementsKind(elements_kind)) {
HValue* backing_store;
if (IsExternalArrayElementsKind(elements_kind)) {
backing_store =
Add<HLoadExternalArrayPointer>(elements);
} else {
backing_store = elements;
}
if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
NoObservableSideEffectsScope no_effects(this);
HLoadExternalArrayPointer* external_elements =
Add<HLoadExternalArrayPointer>(elements);
IfBuilder length_checker(this);
length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT);
length_checker.Then();
@ -2121,7 +2129,7 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
key, graph()->GetConstant0(), Token::GTE);
negative_checker.Then();
HInstruction* result = AddElementAccess(
external_elements, key, val, bounds_check, elements_kind, is_store);
backing_store, key, val, bounds_check, elements_kind, is_store);
negative_checker.ElseDeopt("Negative key encountered");
negative_checker.End();
length_checker.End();
@ -2129,10 +2137,8 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
} else {
ASSERT(store_mode == STANDARD_STORE);
checked_key = Add<HBoundsCheck>(key, length);
HLoadExternalArrayPointer* external_elements =
Add<HLoadExternalArrayPointer>(elements);
return AddElementAccess(
external_elements, checked_key, val,
backing_store, checked_key, val,
checked_object, elements_kind, is_store);
}
}
@ -2313,7 +2319,8 @@ HInstruction* HGraphBuilder::AddElementAccess(
LoadKeyedHoleMode load_mode) {
if (is_store) {
ASSERT(val != NULL);
if (elements_kind == EXTERNAL_PIXEL_ELEMENTS) {
if (elements_kind == EXTERNAL_PIXEL_ELEMENTS ||
elements_kind == UINT8_CLAMPED_ELEMENTS) {
val = Add<HClampToUint8>(val);
}
return Add<HStoreKeyed>(elements, checked_key, val, elements_kind,
@ -2327,7 +2334,8 @@ HInstruction* HGraphBuilder::AddElementAccess(
HLoadKeyed* load = Add<HLoadKeyed>(
elements, checked_key, dependency, elements_kind, load_mode);
if (FLAG_opt_safe_uint32_operations &&
elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) {
(elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS ||
elements_kind == UINT32_ELEMENTS)) {
graph()->RecordUint32Instruction(load);
}
return load;

View File

@ -3421,7 +3421,8 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
elements_kind,
0,
instr->additional_index()));
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
elements_kind == FLOAT32_ELEMENTS) {
if (CpuFeatures::IsSupported(SSE2)) {
CpuFeatureScope scope(masm(), SSE2);
XMMRegister result(ToDoubleRegister(instr->result()));
@ -3430,7 +3431,8 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
} else {
X87Mov(ToX87Register(instr->result()), operand, kX87FloatOperand);
}
} else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
} else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS ||
elements_kind == FLOAT64_ELEMENTS) {
if (CpuFeatures::IsSupported(SSE2)) {
CpuFeatureScope scope(masm(), SSE2);
__ movsd(ToDoubleRegister(instr->result()), operand);
@ -3441,22 +3443,29 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
Register result(ToRegister(instr->result()));
switch (elements_kind) {
case EXTERNAL_BYTE_ELEMENTS:
case INT8_ELEMENTS:
__ movsx_b(result, operand);
break;
case EXTERNAL_PIXEL_ELEMENTS:
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
case UINT8_ELEMENTS:
case UINT8_CLAMPED_ELEMENTS:
__ movzx_b(result, operand);
break;
case EXTERNAL_SHORT_ELEMENTS:
case INT16_ELEMENTS:
__ movsx_w(result, operand);
break;
case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
case UINT16_ELEMENTS:
__ movzx_w(result, operand);
break;
case EXTERNAL_INT_ELEMENTS:
case INT32_ELEMENTS:
__ mov(result, operand);
break;
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
case UINT32_ELEMENTS:
__ mov(result, operand);
if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
__ test(result, Operand(result));
@ -3465,6 +3474,8 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
break;
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
case FLOAT32_ELEMENTS:
case FLOAT64_ELEMENTS:
case FAST_SMI_ELEMENTS:
case FAST_ELEMENTS:
case FAST_DOUBLE_ELEMENTS:
@ -3537,7 +3548,7 @@ void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
if (instr->is_external()) {
if (instr->is_typed_elements()) {
DoLoadKeyedExternalArray(instr);
} else if (instr->hydrogen()->representation().IsDouble()) {
DoLoadKeyedFixedDoubleArray(instr);
@ -3556,6 +3567,9 @@ Operand LCodeGen::BuildFastArrayOperand(
uint32_t additional_index) {
Register elements_pointer_reg = ToRegister(elements_pointer);
int element_shift_size = ElementsKindToShiftSize(elements_kind);
if (IsFixedTypedArrayElementsKind(elements_kind)) {
offset += FixedTypedArrayBase::kDataOffset - kHeapObjectTag;
}
int shift_size = element_shift_size;
if (key->IsConstantOperand()) {
int constant_value = ToInteger32(LConstantOperand::cast(key));
@ -4538,7 +4552,8 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
elements_kind,
0,
instr->additional_index()));
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
elements_kind == FLOAT32_ELEMENTS) {
if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
CpuFeatureScope scope(masm(), SSE2);
XMMRegister xmm_scratch = double_scratch0();
@ -4548,7 +4563,8 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
__ fld(0);
__ fstp_s(operand);
}
} else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
} else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS ||
elements_kind == FLOAT64_ELEMENTS) {
if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
CpuFeatureScope scope(masm(), SSE2);
__ movsd(operand, ToDoubleRegister(instr->value()));
@ -4561,18 +4577,27 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
case EXTERNAL_PIXEL_ELEMENTS:
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
case EXTERNAL_BYTE_ELEMENTS:
case UINT8_ELEMENTS:
case INT8_ELEMENTS:
case UINT8_CLAMPED_ELEMENTS:
__ mov_b(operand, value);
break;
case EXTERNAL_SHORT_ELEMENTS:
case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
case UINT16_ELEMENTS:
case INT16_ELEMENTS:
__ mov_w(operand, value);
break;
case EXTERNAL_INT_ELEMENTS:
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
case UINT32_ELEMENTS:
case INT32_ELEMENTS:
__ mov(operand, value);
break;
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
case FLOAT32_ELEMENTS:
case FLOAT64_ELEMENTS:
case FAST_SMI_ELEMENTS:
case FAST_ELEMENTS:
case FAST_DOUBLE_ELEMENTS:
@ -4710,7 +4735,7 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) {
// By cases...external, fast-double, fast
if (instr->is_external()) {
if (instr->is_typed_elements()) {
DoStoreKeyedExternalArray(instr);
} else if (instr->hydrogen()->value()->representation().IsDouble()) {
DoStoreKeyedFixedDoubleArray(instr);

View File

@ -2153,19 +2153,17 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
: UseRegisterOrConstantAtStart(instr->key());
LLoadKeyed* result = NULL;
if (!instr->is_external()) {
if (!instr->is_typed_elements()) {
LOperand* obj = UseRegisterAtStart(instr->elements());
result = new(zone()) LLoadKeyed(obj, key);
} else {
ASSERT(
(instr->representation().IsInteger32() &&
(elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
(elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
!(IsDoubleOrFloatElementsKind(instr->elements_kind()))) ||
(instr->representation().IsDouble() &&
((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
(elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
LOperand* external_pointer = UseRegister(instr->elements());
result = new(zone()) LLoadKeyed(external_pointer, key);
(IsDoubleOrFloatElementsKind(instr->elements_kind()))));
LOperand* backing_store = UseRegister(instr->elements());
result = new(zone()) LLoadKeyed(backing_store, key);
}
DefineAsRegister(result);
@ -2195,7 +2193,10 @@ LOperand* LChunkBuilder::GetStoreKeyedValueOperand(HStoreKeyed* instr) {
bool val_is_fixed_register =
elements_kind == EXTERNAL_BYTE_ELEMENTS ||
elements_kind == EXTERNAL_UNSIGNED_BYTE_ELEMENTS ||
elements_kind == EXTERNAL_PIXEL_ELEMENTS;
elements_kind == EXTERNAL_PIXEL_ELEMENTS ||
elements_kind == UINT8_ELEMENTS ||
elements_kind == INT8_ELEMENTS ||
elements_kind == UINT8_CLAMPED_ELEMENTS;
if (val_is_fixed_register) {
return UseFixed(instr->value(), eax);
}
@ -2210,7 +2211,7 @@ LOperand* LChunkBuilder::GetStoreKeyedValueOperand(HStoreKeyed* instr) {
LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
if (!instr->is_external()) {
if (!instr->is_typed_elements()) {
ASSERT(instr->elements()->representation().IsTagged());
ASSERT(instr->key()->representation().IsInteger32() ||
instr->key()->representation().IsSmi());
@ -2242,23 +2243,22 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
ElementsKind elements_kind = instr->elements_kind();
ASSERT(
(instr->value()->representation().IsInteger32() &&
(elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
(elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
!IsDoubleOrFloatElementsKind(elements_kind)) ||
(instr->value()->representation().IsDouble() &&
((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
(elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
ASSERT(instr->elements()->representation().IsExternal());
IsDoubleOrFloatElementsKind(elements_kind)));
ASSERT((instr->is_fixed_typed_array() &&
instr->elements()->representation().IsTagged()) ||
(instr->is_external() &&
instr->elements()->representation().IsExternal()));
LOperand* external_pointer = UseRegister(instr->elements());
LOperand* backing_store = UseRegister(instr->elements());
LOperand* val = GetStoreKeyedValueOperand(instr);
bool clobbers_key = ExternalArrayOpRequiresTemp(
instr->key()->representation(), elements_kind);
LOperand* key = clobbers_key
? UseTempRegister(instr->key())
: UseRegisterOrConstantAtStart(instr->key());
return new(zone()) LStoreKeyed(external_pointer,
key,
val);
return new(zone()) LStoreKeyed(backing_store, key, val);
}

View File

@ -1581,6 +1581,12 @@ class LLoadKeyed V8_FINAL : public LTemplateInstruction<1, 2, 0> {
bool is_external() const {
return hydrogen()->is_external();
}
bool is_fixed_typed_array() const {
return hydrogen()->is_fixed_typed_array();
}
bool is_typed_elements() const {
return is_external() || is_fixed_typed_array();
}
DECLARE_CONCRETE_INSTRUCTION(LoadKeyed, "load-keyed")
DECLARE_HYDROGEN_ACCESSOR(LoadKeyed)
@ -1602,7 +1608,10 @@ inline static bool ExternalArrayOpRequiresTemp(
return key_representation.IsSmi() &&
(elements_kind == EXTERNAL_BYTE_ELEMENTS ||
elements_kind == EXTERNAL_UNSIGNED_BYTE_ELEMENTS ||
elements_kind == EXTERNAL_PIXEL_ELEMENTS);
elements_kind == EXTERNAL_PIXEL_ELEMENTS ||
elements_kind == UINT8_ELEMENTS ||
elements_kind == INT8_ELEMENTS ||
elements_kind == UINT8_CLAMPED_ELEMENTS);
}
@ -2232,6 +2241,12 @@ class LStoreKeyed V8_FINAL : public LTemplateInstruction<0, 3, 0> {
}
bool is_external() const { return hydrogen()->is_external(); }
bool is_fixed_typed_array() const {
return hydrogen()->is_fixed_typed_array();
}
bool is_typed_elements() const {
return is_external() || is_fixed_typed_array();
}
LOperand* elements() { return inputs_[0]; }
LOperand* key() { return inputs_[1]; }
LOperand* value() { return inputs_[2]; }

View File

@ -1845,7 +1845,8 @@ Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver,
if (store_mode != STANDARD_STORE) {
int external_arrays = 0;
for (int i = 0; i < target_receiver_maps.length(); ++i) {
if (target_receiver_maps[i]->has_external_array_elements()) {
if (target_receiver_maps[i]->has_external_array_elements() ||
target_receiver_maps[i]->has_fixed_typed_array_elements()) {
external_arrays++;
}
}

View File

@ -132,6 +132,33 @@ void HeapObject::HeapObjectVerify() {
case EXTERNAL_DOUBLE_ARRAY_TYPE:
ExternalDoubleArray::cast(this)->ExternalDoubleArrayVerify();
break;
case FIXED_UINT8_ARRAY_TYPE:
FixedUint8Array::cast(this)->FixedTypedArrayVerify();
break;
case FIXED_INT8_ARRAY_TYPE:
FixedInt8Array::cast(this)->FixedTypedArrayVerify();
break;
case FIXED_UINT16_ARRAY_TYPE:
FixedUint16Array::cast(this)->FixedTypedArrayVerify();
break;
case FIXED_INT16_ARRAY_TYPE:
FixedInt16Array::cast(this)->FixedTypedArrayVerify();
break;
case FIXED_UINT32_ARRAY_TYPE:
FixedUint32Array::cast(this)->FixedTypedArrayVerify();
break;
case FIXED_INT32_ARRAY_TYPE:
FixedInt32Array::cast(this)->FixedTypedArrayVerify();
break;
case FIXED_FLOAT32_ARRAY_TYPE:
FixedFloat32Array::cast(this)->FixedTypedArrayVerify();
break;
case FIXED_FLOAT64_ARRAY_TYPE:
FixedFloat64Array::cast(this)->FixedTypedArrayVerify();
break;
case FIXED_UINT8_CLAMPED_ARRAY_TYPE:
FixedUint8ClampedArray::cast(this)->FixedTypedArrayVerify();
break;
case CODE_TYPE:
Code::cast(this)->CodeVerify();
break;
@ -307,6 +334,14 @@ void ExternalDoubleArray::ExternalDoubleArrayVerify() {
}
template <class Traits>
void FixedTypedArray<Traits>::FixedTypedArrayVerify() {
CHECK(IsHeapObject() &&
HeapObject::cast(this)->map()->instance_type() ==
Traits::kInstanceType);
}
bool JSObject::ElementsAreSafeToExamine() {
return (FLAG_use_gvn && FLAG_use_allocation_folding) ||
reinterpret_cast<Map*>(elements()) !=
@ -1087,9 +1122,18 @@ void JSObject::IncrementSpillStatistics(SpillInformation* info) {
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
case EXTERNAL_PIXEL_ELEMENTS: {
case EXTERNAL_PIXEL_ELEMENTS:
case UINT8_ELEMENTS:
case INT8_ELEMENTS:
case UINT16_ELEMENTS:
case INT16_ELEMENTS:
case UINT32_ELEMENTS:
case INT32_ELEMENTS:
case FLOAT32_ELEMENTS:
case FLOAT64_ELEMENTS:
case UINT8_CLAMPED_ELEMENTS: {
info->number_of_objects_with_fast_elements_++;
ExternalPixelArray* e = ExternalPixelArray::cast(elements());
FixedArrayBase* e = FixedArrayBase::cast(elements());
info->number_of_fast_used_elements_ += e->length();
break;
}

View File

@ -41,6 +41,7 @@
#include "conversions-inl.h"
#include "heap.h"
#include "isolate.h"
#include "heap-inl.h"
#include "property.h"
#include "spaces.h"
#include "store-buffer.h"
@ -86,6 +87,13 @@ PropertyDetails PropertyDetails::AsDeleted() {
}
#define FIXED_TYPED_ARRAY_CAST_ACCESSOR(type) \
template<> \
type* type::cast(Object* object) { \
SLOW_ASSERT(object->Is##type()); \
return reinterpret_cast<type*>(object); \
}
#define INT_ACCESSORS(holder, name, offset) \
int holder::name() { return READ_INT_FIELD(this, offset); } \
void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
@ -134,7 +142,8 @@ PropertyDetails PropertyDetails::AsDeleted() {
bool Object::IsFixedArrayBase() {
return IsFixedArray() || IsFixedDoubleArray() || IsConstantPoolArray();
return IsFixedArray() || IsFixedDoubleArray() || IsConstantPoolArray() ||
IsFixedTypedArrayBase() || IsExternalArray();
}
@ -262,7 +271,8 @@ bool Object::IsExternalTwoByteString() {
bool Object::HasValidElements() {
// Dictionary is covered under FixedArray.
return IsFixedArray() || IsFixedDoubleArray() || IsExternalArray();
return IsFixedArray() || IsFixedDoubleArray() || IsExternalArray() ||
IsFixedTypedArrayBase();
}
@ -488,6 +498,27 @@ TYPE_CHECKER(ExternalFloatArray, EXTERNAL_FLOAT_ARRAY_TYPE)
TYPE_CHECKER(ExternalDoubleArray, EXTERNAL_DOUBLE_ARRAY_TYPE)
bool Object::IsFixedTypedArrayBase() {
if (!Object::IsHeapObject()) return false;
InstanceType instance_type =
HeapObject::cast(this)->map()->instance_type();
return (instance_type >= FIRST_FIXED_TYPED_ARRAY_TYPE &&
instance_type <= LAST_FIXED_TYPED_ARRAY_TYPE);
}
TYPE_CHECKER(FixedUint8Array, FIXED_UINT8_ARRAY_TYPE)
TYPE_CHECKER(FixedInt8Array, FIXED_INT8_ARRAY_TYPE)
TYPE_CHECKER(FixedUint16Array, FIXED_UINT16_ARRAY_TYPE)
TYPE_CHECKER(FixedInt16Array, FIXED_INT16_ARRAY_TYPE)
TYPE_CHECKER(FixedUint32Array, FIXED_UINT32_ARRAY_TYPE)
TYPE_CHECKER(FixedInt32Array, FIXED_INT32_ARRAY_TYPE)
TYPE_CHECKER(FixedFloat32Array, FIXED_FLOAT32_ARRAY_TYPE)
TYPE_CHECKER(FixedFloat64Array, FIXED_FLOAT64_ARRAY_TYPE)
TYPE_CHECKER(FixedUint8ClampedArray, FIXED_UINT8_CLAMPED_ARRAY_TYPE)
bool MaybeObject::IsFailure() {
return HAS_FAILURE_TAG(this);
}
@ -1955,8 +1986,7 @@ void Object::VerifyApiCallResultType() {
FixedArrayBase* FixedArrayBase::cast(Object* object) {
ASSERT(object->IsFixedArray() || object->IsFixedDoubleArray() ||
object->IsConstantPoolArray());
ASSERT(object->IsFixedArrayBase());
return reinterpret_cast<FixedArrayBase*>(object);
}
@ -2635,6 +2665,7 @@ void SeededNumberDictionary::set_requires_slow_elements() {
CAST_ACCESSOR(FixedArray)
CAST_ACCESSOR(FixedDoubleArray)
CAST_ACCESSOR(FixedTypedArrayBase)
CAST_ACCESSOR(ConstantPoolArray)
CAST_ACCESSOR(DescriptorArray)
CAST_ACCESSOR(DeoptimizationInputData)
@ -2704,6 +2735,14 @@ CAST_ACCESSOR(ExternalPixelArray)
CAST_ACCESSOR(Struct)
CAST_ACCESSOR(AccessorInfo)
template <class Traits>
FixedTypedArray<Traits>* FixedTypedArray<Traits>::cast(Object* object) {
SLOW_ASSERT(object->IsHeapObject() &&
HeapObject::cast(object)->map()->instance_type() ==
Traits::kInstanceType);
return reinterpret_cast<FixedTypedArray<Traits>*>(object);
}
#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
STRUCT_LIST(MAKE_STRUCT_CAST)
@ -3479,6 +3518,133 @@ void ExternalDoubleArray::set(int index, double value) {
}
int FixedTypedArrayBase::size() {
InstanceType instance_type = map()->instance_type();
int element_size;
switch (instance_type) {
case FIXED_UINT8_ARRAY_TYPE:
case FIXED_INT8_ARRAY_TYPE:
case FIXED_UINT8_CLAMPED_ARRAY_TYPE:
element_size = 1;
break;
case FIXED_UINT16_ARRAY_TYPE:
case FIXED_INT16_ARRAY_TYPE:
element_size = 2;
break;
case FIXED_UINT32_ARRAY_TYPE:
case FIXED_INT32_ARRAY_TYPE:
case FIXED_FLOAT32_ARRAY_TYPE:
element_size = 4;
break;
case FIXED_FLOAT64_ARRAY_TYPE:
element_size = 8;
break;
default:
UNREACHABLE();
return 0;
}
return OBJECT_POINTER_ALIGN(kDataOffset + length() * element_size);
}
template <class Traits>
typename Traits::ElementType FixedTypedArray<Traits>::get_scalar(int index) {
ASSERT((index >= 0) && (index < this->length()));
ElementType* ptr = reinterpret_cast<ElementType*>(
FIELD_ADDR(this, kDataOffset));
return ptr[index];
}
template <class Traits>
void FixedTypedArray<Traits>::set(int index, ElementType value) {
ASSERT((index >= 0) && (index < this->length()));
ElementType* ptr = reinterpret_cast<ElementType*>(
FIELD_ADDR(this, kDataOffset));
ptr[index] = value;
}
template <class Traits>
MaybeObject* FixedTypedArray<Traits>::get(int index) {
return Traits::ToObject(GetHeap(), get_scalar(index));
}
template <class Traits>
MaybeObject* FixedTypedArray<Traits>::SetValue(uint32_t index, Object* value) {
ElementType cast_value = Traits::defaultValue();
if (index < static_cast<uint32_t>(length())) {
if (value->IsSmi()) {
int int_value = Smi::cast(value)->value();
cast_value = static_cast<ElementType>(int_value);
} else if (value->IsHeapNumber()) {
double double_value = HeapNumber::cast(value)->value();
cast_value = static_cast<ElementType>(DoubleToInt32(double_value));
} else {
// Clamp undefined to the default value. All other types have been
// converted to a number type further up in the call chain.
ASSERT(value->IsUndefined());
}
set(index, cast_value);
}
return Traits::ToObject(GetHeap(), cast_value);
}
template <class Traits>
Handle<Object> FixedTypedArray<Traits>::SetValue(
Handle<FixedTypedArray<Traits> > array,
uint32_t index,
Handle<Object> value) {
CALL_HEAP_FUNCTION(array->GetIsolate(),
array->SetValue(index, *value),
Object);
}
MaybeObject* Uint8ArrayTraits::ToObject(Heap*, uint8_t scalar) {
return Smi::FromInt(scalar);
}
MaybeObject* Uint8ClampedArrayTraits::ToObject(Heap*, uint8_t scalar) {
return Smi::FromInt(scalar);
}
MaybeObject* Int8ArrayTraits::ToObject(Heap*, int8_t scalar) {
return Smi::FromInt(scalar);
}
MaybeObject* Uint16ArrayTraits::ToObject(Heap*, uint16_t scalar) {
return Smi::FromInt(scalar);
}
MaybeObject* Int16ArrayTraits::ToObject(Heap*, int16_t scalar) {
return Smi::FromInt(scalar);
}
MaybeObject* Uint32ArrayTraits::ToObject(Heap* heap, uint32_t scalar) {
return heap->NumberFromUint32(scalar);
}
MaybeObject* Int32ArrayTraits::ToObject(Heap* heap, int32_t scalar) {
return heap->NumberFromInt32(scalar);
}
MaybeObject* Float32ArrayTraits::ToObject(Heap* heap, float scalar) {
return heap->NumberFromDouble(scalar);
}
MaybeObject* Float64ArrayTraits::ToObject(Heap* heap, double scalar) {
return heap->NumberFromDouble(scalar);
}
int Map::visitor_id() {
return READ_BYTE_FIELD(this, kVisitorIdOffset);
}
@ -3539,6 +3705,10 @@ int HeapObject::SizeFromMap(Map* map) {
reinterpret_cast<ConstantPoolArray*>(this)->count_of_ptr_entries(),
reinterpret_cast<ConstantPoolArray*>(this)->count_of_int32_entries());
}
if (instance_type >= FIRST_FIXED_TYPED_ARRAY_TYPE &&
instance_type <= LAST_FIXED_TYPED_ARRAY_TYPE) {
return reinterpret_cast<FixedTypedArrayBase*>(this)->size();
}
ASSERT(instance_type == CODE_TYPE);
return reinterpret_cast<Code*>(this)->CodeSize();
}
@ -5707,6 +5877,13 @@ EXTERNAL_ELEMENTS_CHECK(Double,
EXTERNAL_ELEMENTS_CHECK(Pixel, EXTERNAL_PIXEL_ARRAY_TYPE)
bool JSObject::HasFixedTypedArrayElements() {
HeapObject* array = elements();
ASSERT(array != NULL);
return array->IsFixedTypedArrayBase();
}
bool JSObject::HasNamedInterceptor() {
return map()->has_named_interceptor();
}

View File

@ -136,6 +136,24 @@ void HeapObject::HeapObjectPrint(FILE* out) {
case EXTERNAL_DOUBLE_ARRAY_TYPE:
ExternalDoubleArray::cast(this)->ExternalDoubleArrayPrint(out);
break;
#define PRINT_FIXED_TYPED_ARRAY(Type) \
case Fixed##Type##Array::kInstanceType: \
Fixed##Type##Array::cast(this)->FixedTypedArrayPrint(out); \
break;
PRINT_FIXED_TYPED_ARRAY(Uint8)
PRINT_FIXED_TYPED_ARRAY(Int8)
PRINT_FIXED_TYPED_ARRAY(Uint16)
PRINT_FIXED_TYPED_ARRAY(Int16)
PRINT_FIXED_TYPED_ARRAY(Uint32)
PRINT_FIXED_TYPED_ARRAY(Int32)
PRINT_FIXED_TYPED_ARRAY(Float32)
PRINT_FIXED_TYPED_ARRAY(Float64)
PRINT_FIXED_TYPED_ARRAY(Uint8Clamped)
#undef PPINT_FIXED_TYPED_ARRAY
case FILLER_TYPE:
PrintF(out, "filler");
break;
@ -285,6 +303,11 @@ void ExternalDoubleArray::ExternalDoubleArrayPrint(FILE* out) {
PrintF(out, "external double array");
}
template <class Traits>
void FixedTypedArray<Traits>::FixedTypedArrayPrint(FILE* out) {
PrintF(out, "fixed %s", Traits::Designator());
}
void JSObject::PrintProperties(FILE* out) {
if (HasFastProperties()) {
@ -324,6 +347,24 @@ void JSObject::PrintProperties(FILE* out) {
}
template<class T>
static void DoPrintElements(FILE *out, Object* object) {
T* p = T::cast(object);
for (int i = 0; i < p->length(); i++) {
PrintF(out, " %d: %d\n", i, p->get_scalar(i));
}
}
template<class T>
static void DoPrintDoubleElements(FILE* out, Object* object) {
T* p = T::cast(object);
for (int i = 0; i < p->length(); i++) {
PrintF(out, " %d: %f\n", i, p->get_scalar(i));
}
}
void JSObject::PrintElements(FILE* out) {
// Don't call GetElementsKind, its validation code can cause the printer to
// fail when debugging.
@ -357,72 +398,47 @@ void JSObject::PrintElements(FILE* out) {
}
break;
}
case EXTERNAL_PIXEL_ELEMENTS: {
ExternalPixelArray* p = ExternalPixelArray::cast(elements());
for (int i = 0; i < p->length(); i++) {
PrintF(out, " %d: %d\n", i, p->get_scalar(i));
#define PRINT_ELEMENTS(Kind, Type) \
case Kind: { \
DoPrintElements<Type>(out, elements()); \
break; \
}
break;
}
case EXTERNAL_BYTE_ELEMENTS: {
ExternalByteArray* p = ExternalByteArray::cast(elements());
for (int i = 0; i < p->length(); i++) {
PrintF(out, " %d: %d\n", i, static_cast<int>(p->get_scalar(i)));
}
break;
}
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
ExternalUnsignedByteArray* p =
ExternalUnsignedByteArray::cast(elements());
for (int i = 0; i < p->length(); i++) {
PrintF(out, " %d: %d\n", i, static_cast<int>(p->get_scalar(i)));
}
break;
}
case EXTERNAL_SHORT_ELEMENTS: {
ExternalShortArray* p = ExternalShortArray::cast(elements());
for (int i = 0; i < p->length(); i++) {
PrintF(out, " %d: %d\n", i, static_cast<int>(p->get_scalar(i)));
}
break;
}
case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
ExternalUnsignedShortArray* p =
ExternalUnsignedShortArray::cast(elements());
for (int i = 0; i < p->length(); i++) {
PrintF(out, " %d: %d\n", i, static_cast<int>(p->get_scalar(i)));
}
break;
}
case EXTERNAL_INT_ELEMENTS: {
ExternalIntArray* p = ExternalIntArray::cast(elements());
for (int i = 0; i < p->length(); i++) {
PrintF(out, " %d: %d\n", i, static_cast<int>(p->get_scalar(i)));
}
break;
}
case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
ExternalUnsignedIntArray* p =
ExternalUnsignedIntArray::cast(elements());
for (int i = 0; i < p->length(); i++) {
PrintF(out, " %d: %d\n", i, static_cast<int>(p->get_scalar(i)));
}
break;
}
case EXTERNAL_FLOAT_ELEMENTS: {
ExternalFloatArray* p = ExternalFloatArray::cast(elements());
for (int i = 0; i < p->length(); i++) {
PrintF(out, " %d: %f\n", i, p->get_scalar(i));
}
break;
}
case EXTERNAL_DOUBLE_ELEMENTS: {
ExternalDoubleArray* p = ExternalDoubleArray::cast(elements());
for (int i = 0; i < p->length(); i++) {
PrintF(out, " %d: %f\n", i, p->get_scalar(i));
}
break;
#define PRINT_DOUBLE_ELEMENTS(Kind, Type) \
case Kind: { \
DoPrintDoubleElements<Type>(out, elements()); \
break; \
}
PRINT_ELEMENTS(EXTERNAL_PIXEL_ELEMENTS, ExternalPixelArray)
PRINT_ELEMENTS(EXTERNAL_BYTE_ELEMENTS, ExternalByteArray)
PRINT_ELEMENTS(EXTERNAL_UNSIGNED_BYTE_ELEMENTS,
ExternalUnsignedByteArray)
PRINT_ELEMENTS(EXTERNAL_SHORT_ELEMENTS, ExternalShortArray)
PRINT_ELEMENTS(EXTERNAL_UNSIGNED_SHORT_ELEMENTS,
ExternalUnsignedShortArray)
PRINT_ELEMENTS(EXTERNAL_INT_ELEMENTS, ExternalIntArray)
PRINT_ELEMENTS(EXTERNAL_UNSIGNED_INT_ELEMENTS,
ExternalUnsignedIntArray)
PRINT_DOUBLE_ELEMENTS(EXTERNAL_FLOAT_ELEMENTS, ExternalFloatArray)
PRINT_DOUBLE_ELEMENTS(EXTERNAL_DOUBLE_ELEMENTS, ExternalDoubleArray)
PRINT_ELEMENTS(UINT8_ELEMENTS, FixedUint8Array)
PRINT_ELEMENTS(UINT8_CLAMPED_ELEMENTS, FixedUint8ClampedArray)
PRINT_ELEMENTS(INT8_ELEMENTS, FixedInt8Array)
PRINT_ELEMENTS(UINT16_ELEMENTS, FixedUint16Array)
PRINT_ELEMENTS(INT16_ELEMENTS, FixedInt16Array)
PRINT_ELEMENTS(UINT32_ELEMENTS, FixedUint32Array)
PRINT_ELEMENTS(INT32_ELEMENTS, FixedInt32Array)
PRINT_DOUBLE_ELEMENTS(FLOAT32_ELEMENTS, FixedFloat32Array)
PRINT_DOUBLE_ELEMENTS(FLOAT64_ELEMENTS, FixedFloat64Array)
#undef PRINT_DOUBLE_ELEMENTS
#undef PRINT_ELEMENTS
case DICTIONARY_ELEMENTS:
elements()->Print(out);
break;

View File

@ -60,6 +60,7 @@ void StaticNewSpaceVisitor<StaticVisitor>::Initialize() {
int>::Visit);
table_.Register(kVisitFixedDoubleArray, &VisitFixedDoubleArray);
table_.Register(kVisitFixedTypedArray, &VisitFixedTypedArray);
table_.Register(kVisitNativeContext,
&FixedBodyVisitor<StaticVisitor,
@ -185,6 +186,8 @@ void StaticMarkingVisitor<StaticVisitor>::Initialize() {
table_.Register(kVisitFixedDoubleArray, &DataObjectVisitor::Visit);
table_.Register(kVisitFixedTypedArray, &DataObjectVisitor::Visit);
table_.Register(kVisitConstantPoolArray, &VisitConstantPoolArray);
table_.Register(kVisitNativeContext, &VisitNativeContext);

View File

@ -184,6 +184,17 @@ StaticVisitorBase::VisitorId StaticVisitorBase::GetVisitorId(
kVisitDataObjectGeneric,
instance_size);
case FIXED_UINT8_ARRAY_TYPE:
case FIXED_INT8_ARRAY_TYPE:
case FIXED_UINT16_ARRAY_TYPE:
case FIXED_INT16_ARRAY_TYPE:
case FIXED_UINT32_ARRAY_TYPE:
case FIXED_INT32_ARRAY_TYPE:
case FIXED_FLOAT32_ARRAY_TYPE:
case FIXED_FLOAT64_ARRAY_TYPE:
case FIXED_UINT8_CLAMPED_ARRAY_TYPE:
return kVisitFixedTypedArray;
#define MAKE_STRUCT_CASE(NAME, Name, name) \
case NAME##_TYPE:
STRUCT_LIST(MAKE_STRUCT_CASE)

View File

@ -54,6 +54,7 @@ class StaticVisitorBase : public AllStatic {
V(FreeSpace) \
V(FixedArray) \
V(FixedDoubleArray) \
V(FixedTypedArray) \
V(ConstantPoolArray) \
V(NativeContext) \
V(AllocationSite) \
@ -322,6 +323,10 @@ class StaticNewSpaceVisitor : public StaticVisitorBase {
return FixedDoubleArray::SizeFor(length);
}
INLINE(static int VisitFixedTypedArray(Map* map, HeapObject* object)) {
return reinterpret_cast<FixedTypedArrayBase*>(object)->size();
}
INLINE(static int VisitJSObject(Map* map, HeapObject* object)) {
return JSObjectVisitor::Visit(map, object);
}

View File

@ -1677,6 +1677,10 @@ void HeapObject::HeapObjectShortPrint(StringStream* accumulator) {
accumulator->Add("<ExternalDoubleArray[%u]>",
ExternalDoubleArray::cast(this)->length());
break;
case FIXED_UINT8_ARRAY_TYPE:
accumulator->Add("<FixedUint8Array[%u]>",
FixedUint8Array::cast(this)->length());
break;
case SHARED_FUNCTION_INFO_TYPE: {
SharedFunctionInfo* shared = SharedFunctionInfo::cast(this);
SmartArrayPointer<char> debug_name =
@ -1866,6 +1870,15 @@ void HeapObject::IterateBody(InstanceType type, int object_size,
case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
case EXTERNAL_FLOAT_ARRAY_TYPE:
case EXTERNAL_DOUBLE_ARRAY_TYPE:
case FIXED_INT8_ARRAY_TYPE:
case FIXED_UINT8_ARRAY_TYPE:
case FIXED_INT16_ARRAY_TYPE:
case FIXED_UINT16_ARRAY_TYPE:
case FIXED_INT32_ARRAY_TYPE:
case FIXED_UINT32_ARRAY_TYPE:
case FIXED_FLOAT32_ARRAY_TYPE:
case FIXED_FLOAT64_ARRAY_TYPE:
case FIXED_UINT8_CLAMPED_ARRAY_TYPE:
break;
case SHARED_FUNCTION_INFO_TYPE: {
SharedFunctionInfo::BodyDescriptor::IterateBody(this, v);
@ -5377,6 +5390,15 @@ bool JSObject::ReferencesObject(Object* obj) {
case EXTERNAL_DOUBLE_ELEMENTS:
case FAST_DOUBLE_ELEMENTS:
case FAST_HOLEY_DOUBLE_ELEMENTS:
case UINT8_ELEMENTS:
case INT8_ELEMENTS:
case UINT16_ELEMENTS:
case INT16_ELEMENTS:
case UINT32_ELEMENTS:
case INT32_ELEMENTS:
case FLOAT32_ELEMENTS:
case FLOAT64_ELEMENTS:
case UINT8_CLAMPED_ELEMENTS:
// Raw pixels and external arrays do not reference other
// objects.
break;
@ -5869,6 +5891,15 @@ Handle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
case EXTERNAL_DOUBLE_ELEMENTS:
case FAST_DOUBLE_ELEMENTS:
case FAST_HOLEY_DOUBLE_ELEMENTS:
case UINT8_ELEMENTS:
case INT8_ELEMENTS:
case UINT16_ELEMENTS:
case INT16_ELEMENTS:
case UINT32_ELEMENTS:
case INT32_ELEMENTS:
case FLOAT32_ELEMENTS:
case FLOAT64_ELEMENTS:
case UINT8_CLAMPED_ELEMENTS:
// No contained objects, nothing to do.
break;
}
@ -6106,6 +6137,15 @@ void JSObject::DefineElementAccessor(Handle<JSObject> object,
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
case UINT8_ELEMENTS:
case INT8_ELEMENTS:
case UINT16_ELEMENTS:
case INT16_ELEMENTS:
case UINT32_ELEMENTS:
case INT32_ELEMENTS:
case FLOAT32_ELEMENTS:
case FLOAT64_ELEMENTS:
case UINT8_CLAMPED_ELEMENTS:
// Ignore getters and setters on pixel and external array elements.
return;
case DICTIONARY_ELEMENTS:
@ -6564,6 +6604,15 @@ Handle<Object> JSObject::SetAccessor(Handle<JSObject> object,
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
case UINT8_ELEMENTS:
case INT8_ELEMENTS:
case UINT16_ELEMENTS:
case INT16_ELEMENTS:
case UINT32_ELEMENTS:
case INT32_ELEMENTS:
case FLOAT32_ELEMENTS:
case FLOAT64_ELEMENTS:
case UINT8_CLAMPED_ELEMENTS:
// Ignore getters and setters on pixel and external array
// elements.
return factory->undefined_value();
@ -12721,6 +12770,51 @@ Handle<Object> JSObject::SetElementWithoutInterceptor(
ExternalDoubleArray::cast(object->elements()));
return ExternalDoubleArray::SetValue(array, index, value);
}
case UINT8_ELEMENTS: {
Handle<FixedUint8Array> array(
FixedUint8Array::cast(object->elements()));
return FixedUint8Array::SetValue(array, index, value);
}
case UINT8_CLAMPED_ELEMENTS: {
Handle<FixedUint8ClampedArray> array(
FixedUint8ClampedArray::cast(object->elements()));
return FixedUint8ClampedArray::SetValue(array, index, value);
}
case INT8_ELEMENTS: {
Handle<FixedInt8Array> array(
FixedInt8Array::cast(object->elements()));
return FixedInt8Array::SetValue(array, index, value);
}
case UINT16_ELEMENTS: {
Handle<FixedUint16Array> array(
FixedUint16Array::cast(object->elements()));
return FixedUint16Array::SetValue(array, index, value);
}
case INT16_ELEMENTS: {
Handle<FixedInt16Array> array(
FixedInt16Array::cast(object->elements()));
return FixedInt16Array::SetValue(array, index, value);
}
case UINT32_ELEMENTS: {
Handle<FixedUint32Array> array(
FixedUint32Array::cast(object->elements()));
return FixedUint32Array::SetValue(array, index, value);
}
case INT32_ELEMENTS: {
Handle<FixedInt32Array> array(
FixedInt32Array::cast(object->elements()));
return FixedInt32Array::SetValue(array, index, value);
}
case FLOAT32_ELEMENTS: {
Handle<FixedFloat32Array> array(
FixedFloat32Array::cast(object->elements()));
return FixedFloat32Array::SetValue(array, index, value);
}
case FLOAT64_ELEMENTS: {
Handle<FixedFloat64Array> array(
FixedFloat64Array::cast(object->elements()));
return FixedFloat64Array::SetValue(array, index, value);
}
case DICTIONARY_ELEMENTS:
return SetDictionaryElement(object, index, value, attributes, strict_mode,
check_prototype,
@ -13132,13 +13226,23 @@ void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) {
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
case EXTERNAL_PIXEL_ELEMENTS:
case UINT8_ELEMENTS:
case INT8_ELEMENTS:
case UINT16_ELEMENTS:
case INT16_ELEMENTS:
case UINT32_ELEMENTS:
case INT32_ELEMENTS:
case FLOAT32_ELEMENTS:
case FLOAT64_ELEMENTS:
case UINT8_CLAMPED_ELEMENTS: {
// External arrays are considered 100% used.
ExternalArray* external_array = ExternalArray::cast(elements());
FixedArrayBase* external_array = FixedArrayBase::cast(elements());
*capacity = external_array->length();
*used = external_array->length();
break;
}
}
}
bool JSObject::ShouldConvertToSlowElements(int new_capacity) {
@ -13644,8 +13748,17 @@ int JSObject::GetLocalElementKeys(FixedArray* storage,
case EXTERNAL_INT_ELEMENTS:
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS: {
int length = ExternalArray::cast(elements())->length();
case EXTERNAL_DOUBLE_ELEMENTS:
case UINT8_ELEMENTS:
case INT8_ELEMENTS:
case UINT16_ELEMENTS:
case INT16_ELEMENTS:
case UINT32_ELEMENTS:
case INT32_ELEMENTS:
case FLOAT32_ELEMENTS:
case FLOAT64_ELEMENTS:
case UINT8_CLAMPED_ELEMENTS: {
int length = FixedArrayBase::cast(elements())->length();
while (counter < length) {
if (storage != NULL) {
storage->set(counter, Smi::FromInt(counter));

View File

@ -386,6 +386,17 @@ const int kStubMinorKeyBits = kBitsPerInt - kSmiTagSize - kStubMajorKeyBits;
V(EXTERNAL_FLOAT_ARRAY_TYPE) \
V(EXTERNAL_DOUBLE_ARRAY_TYPE) \
V(EXTERNAL_PIXEL_ARRAY_TYPE) \
\
V(FIXED_INT8_ARRAY_TYPE) \
V(FIXED_UINT8_ARRAY_TYPE) \
V(FIXED_INT16_ARRAY_TYPE) \
V(FIXED_UINT16_ARRAY_TYPE) \
V(FIXED_INT32_ARRAY_TYPE) \
V(FIXED_UINT32_ARRAY_TYPE) \
V(FIXED_FLOAT32_ARRAY_TYPE) \
V(FIXED_FLOAT64_ARRAY_TYPE) \
V(FIXED_UINT8_CLAMPED_ARRAY_TYPE) \
\
V(FILLER_TYPE) \
\
V(DECLARED_ACCESSOR_DESCRIPTOR_TYPE) \
@ -720,6 +731,17 @@ enum InstanceType {
EXTERNAL_FLOAT_ARRAY_TYPE,
EXTERNAL_DOUBLE_ARRAY_TYPE,
EXTERNAL_PIXEL_ARRAY_TYPE, // LAST_EXTERNAL_ARRAY_TYPE
FIXED_INT8_ARRAY_TYPE, // FIRST_FIXED_TYPED_ARRAY_TYPE
FIXED_UINT8_ARRAY_TYPE,
FIXED_INT16_ARRAY_TYPE,
FIXED_UINT16_ARRAY_TYPE,
FIXED_INT32_ARRAY_TYPE,
FIXED_UINT32_ARRAY_TYPE,
FIXED_FLOAT32_ARRAY_TYPE,
FIXED_FLOAT64_ARRAY_TYPE,
FIXED_UINT8_CLAMPED_ARRAY_TYPE, // LAST_FIXED_TYPED_ARRAY_TYPE
FIXED_DOUBLE_ARRAY_TYPE,
FILLER_TYPE, // LAST_DATA_TYPE
@ -797,6 +819,9 @@ enum InstanceType {
// Boundaries for testing for an external array.
FIRST_EXTERNAL_ARRAY_TYPE = EXTERNAL_BYTE_ARRAY_TYPE,
LAST_EXTERNAL_ARRAY_TYPE = EXTERNAL_PIXEL_ARRAY_TYPE,
// Boundaries for testing for a fixed typed array.
FIRST_FIXED_TYPED_ARRAY_TYPE = FIXED_INT8_ARRAY_TYPE,
LAST_FIXED_TYPED_ARRAY_TYPE = FIXED_UINT8_CLAMPED_ARRAY_TYPE,
// Boundary for promotion to old data space/old pointer space.
LAST_DATA_TYPE = FILLER_TYPE,
// Boundary for objects represented as JSReceiver (i.e. JSObject or JSProxy).
@ -989,6 +1014,16 @@ class MaybeObject BASE_EMBEDDED {
V(ExternalFloatArray) \
V(ExternalDoubleArray) \
V(ExternalPixelArray) \
V(FixedTypedArrayBase) \
V(FixedUint8Array) \
V(FixedInt8Array) \
V(FixedUint16Array) \
V(FixedInt16Array) \
V(FixedUint32Array) \
V(FixedInt32Array) \
V(FixedFloat32Array) \
V(FixedFloat64Array) \
V(FixedUint8ClampedArray) \
V(ByteArray) \
V(FreeSpace) \
V(JSReceiver) \
@ -2109,6 +2144,7 @@ class JSObject: public JSReceiver {
inline bool HasFastHoleyElements();
inline bool HasNonStrictArgumentsElements();
inline bool HasDictionaryElements();
inline bool HasExternalPixelElements();
inline bool HasExternalArrayElements();
inline bool HasExternalByteElements();
@ -2119,6 +2155,9 @@ class JSObject: public JSReceiver {
inline bool HasExternalUnsignedIntElements();
inline bool HasExternalFloatElements();
inline bool HasExternalDoubleElements();
inline bool HasFixedTypedArrayElements();
bool HasFastArgumentsElements();
bool HasDictionaryArgumentsElements();
inline SeededNumberDictionary* element_dictionary(); // Gets slow elements.
@ -4828,6 +4867,76 @@ class ExternalDoubleArray: public ExternalArray {
};
class FixedTypedArrayBase: public FixedArrayBase {
public:
// Casting:
static inline FixedTypedArrayBase* cast(Object* obj);
static const int kDataOffset = kHeaderSize;
inline int size();
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(FixedTypedArrayBase);
};
template <class Traits>
class FixedTypedArray: public FixedTypedArrayBase {
public:
typedef typename Traits::ElementType ElementType;
static const InstanceType kInstanceType = Traits::kInstanceType;
// Casting:
static inline FixedTypedArray<Traits>* cast(Object* obj);
static inline int SizeFor(int length) {
return kDataOffset + length * sizeof(ElementType);
}
inline ElementType get_scalar(int index);
MUST_USE_RESULT inline MaybeObject* get(int index);
inline void set(int index, ElementType value);
// This accessor applies the correct conversion from Smi, HeapNumber
// and undefined.
MUST_USE_RESULT MaybeObject* SetValue(uint32_t index, Object* value);
static Handle<Object> SetValue(Handle<FixedTypedArray<Traits> > array,
uint32_t index,
Handle<Object> value);
DECLARE_PRINTER(FixedTypedArray)
DECLARE_VERIFIER(FixedTypedArray)
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(FixedTypedArray);
};
#define FIXED_TYPED_ARRAY_TRAITS(Type, type, TYPE, elementType) \
class Type##ArrayTraits { \
public: \
typedef elementType ElementType; \
static const InstanceType kInstanceType = FIXED_##TYPE##_ARRAY_TYPE; \
static const char* Designator() { return #type " array"; } \
static inline MaybeObject* ToObject(Heap* heap, elementType scalar); \
static elementType defaultValue() { return 0; } \
}; \
\
typedef FixedTypedArray<Type##ArrayTraits> Fixed##Type##Array;
FIXED_TYPED_ARRAY_TRAITS(Uint8, uint8, UINT8, uint8_t)
FIXED_TYPED_ARRAY_TRAITS(Int8, int8, INT8, int8_t)
FIXED_TYPED_ARRAY_TRAITS(Uint16, uint16, UINT16, uint16_t)
FIXED_TYPED_ARRAY_TRAITS(Int16, int16, INT16, int16_t)
FIXED_TYPED_ARRAY_TRAITS(Uint32, uint32, UINT32, uint32_t)
FIXED_TYPED_ARRAY_TRAITS(Int32, int32, INT32, int32_t)
FIXED_TYPED_ARRAY_TRAITS(Float32, float32, FLOAT32, float)
FIXED_TYPED_ARRAY_TRAITS(Float64, float64, FLOAT64, double)
FIXED_TYPED_ARRAY_TRAITS(Uint8Clamped, uint8_clamped, UINT8_CLAMPED, uint8_t)
#undef FIXED_TYPED_ARRAY_TRAITS
// DeoptimizationInputData is a fixed array used to hold the deoptimization
// data for code generated by the Hydrogen/Lithium compiler. It also
// contains information about functions that were inlined. If N different
@ -5837,6 +5946,10 @@ class Map: public HeapObject {
return IsExternalArrayElementsKind(elements_kind());
}
inline bool has_fixed_typed_array_elements() {
return IsFixedTypedArrayElementsKind(elements_kind());
}
inline bool has_dictionary_elements() {
return IsDictionaryElementsKind(elements_kind());
}

View File

@ -5218,7 +5218,8 @@ Handle<Object> Runtime::SetObjectProperty(Isolate* isolate,
}
js_object->ValidateElements();
if (js_object->HasExternalArrayElements()) {
if (js_object->HasExternalArrayElements() ||
js_object->HasFixedTypedArrayElements()) {
if (!value->IsNumber() && !value->IsUndefined()) {
bool has_exception;
Handle<Object> number =
@ -10007,6 +10008,15 @@ static uint32_t EstimateElementCount(Handle<JSArray> array) {
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
case EXTERNAL_PIXEL_ELEMENTS:
case UINT8_ELEMENTS:
case INT8_ELEMENTS:
case UINT16_ELEMENTS:
case INT16_ELEMENTS:
case UINT32_ELEMENTS:
case INT32_ELEMENTS:
case FLOAT32_ELEMENTS:
case FLOAT64_ELEMENTS:
case UINT8_CLAMPED_ELEMENTS:
// External arrays are always dense.
return length;
}

View File

@ -1676,7 +1676,8 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
Handle<Map> receiver_map) {
ElementsKind elements_kind = receiver_map->elements_kind();
if (receiver_map->has_fast_elements() ||
receiver_map->has_external_array_elements()) {
receiver_map->has_external_array_elements() ||
receiver_map->has_fixed_typed_array_elements()) {
Handle<Code> stub = KeyedLoadFastElementStub(
receiver_map->instance_type() == JS_ARRAY_TYPE,
elements_kind).GetCode(isolate());
@ -1701,7 +1702,8 @@ Handle<Code> KeyedStoreStubCompiler::CompileStoreElement(
bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE;
Handle<Code> stub;
if (receiver_map->has_fast_elements() ||
receiver_map->has_external_array_elements()) {
receiver_map->has_external_array_elements() ||
receiver_map->has_fixed_typed_array_elements()) {
stub = KeyedStoreFastElementStub(
is_jsarray,
elements_kind,
@ -1799,7 +1801,8 @@ void KeyedLoadStubCompiler::CompileElementHandlers(MapHandleList* receiver_maps,
ElementsKind elements_kind = receiver_map->elements_kind();
if (IsFastElementsKind(elements_kind) ||
IsExternalArrayElementsKind(elements_kind)) {
IsExternalArrayElementsKind(elements_kind) ||
IsFixedTypedArrayElementsKind(elements_kind)) {
cached_stub =
KeyedLoadFastElementStub(is_js_array,
elements_kind).GetCode(isolate());
@ -1842,7 +1845,8 @@ Handle<Code> KeyedStoreStubCompiler::CompileStoreElementPolymorphic(
cached_stub = isolate()->builtins()->KeyedStoreIC_Slow();
} else {
if (receiver_map->has_fast_elements() ||
receiver_map->has_external_array_elements()) {
receiver_map->has_external_array_elements() ||
receiver_map->has_fixed_typed_array_elements()) {
cached_stub = KeyedStoreFastElementStub(
is_js_array,
elements_kind,

View File

@ -2963,39 +2963,51 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
__ movsxlq(key_reg, key_reg);
}
}
int base_offset = instr->is_fixed_typed_array()
? FixedTypedArrayBase::kDataOffset - kHeapObjectTag
: 0;
Operand operand(BuildFastArrayOperand(
instr->elements(),
key,
elements_kind,
0,
base_offset,
instr->additional_index()));
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
elements_kind == FLOAT32_ELEMENTS) {
XMMRegister result(ToDoubleRegister(instr->result()));
__ movss(result, operand);
__ cvtss2sd(result, result);
} else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
} else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS ||
elements_kind == FLOAT64_ELEMENTS) {
__ movsd(ToDoubleRegister(instr->result()), operand);
} else {
Register result(ToRegister(instr->result()));
switch (elements_kind) {
case EXTERNAL_BYTE_ELEMENTS:
case INT8_ELEMENTS:
__ movsxbq(result, operand);
break;
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
case EXTERNAL_PIXEL_ELEMENTS:
case UINT8_ELEMENTS:
case UINT8_CLAMPED_ELEMENTS:
__ movzxbq(result, operand);
break;
case EXTERNAL_SHORT_ELEMENTS:
case INT16_ELEMENTS:
__ movsxwq(result, operand);
break;
case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
case UINT16_ELEMENTS:
__ movzxwq(result, operand);
break;
case EXTERNAL_INT_ELEMENTS:
case INT32_ELEMENTS:
__ movsxlq(result, operand);
break;
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
case UINT32_ELEMENTS:
__ movl(result, operand);
if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
__ testl(result, result);
@ -3004,6 +3016,8 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
break;
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
case FLOAT32_ELEMENTS:
case FLOAT64_ELEMENTS:
case FAST_ELEMENTS:
case FAST_SMI_ELEMENTS:
case FAST_DOUBLE_ELEMENTS:
@ -3111,7 +3125,7 @@ void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
if (instr->is_external()) {
if (instr->is_typed_elements()) {
DoLoadKeyedExternalArray(instr);
} else if (instr->hydrogen()->representation().IsDouble()) {
DoLoadKeyedFixedDoubleArray(instr);
@ -4142,18 +4156,23 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
__ movsxlq(key_reg, key_reg);
}
}
int base_offset = instr->is_fixed_typed_array()
? FixedTypedArrayBase::kDataOffset - kHeapObjectTag
: 0;
Operand operand(BuildFastArrayOperand(
instr->elements(),
key,
elements_kind,
0,
base_offset,
instr->additional_index()));
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
elements_kind == FLOAT32_ELEMENTS) {
XMMRegister value(ToDoubleRegister(instr->value()));
__ cvtsd2ss(value, value);
__ movss(operand, value);
} else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
} else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS ||
elements_kind == FLOAT64_ELEMENTS) {
__ movsd(operand, ToDoubleRegister(instr->value()));
} else {
Register value(ToRegister(instr->value()));
@ -4161,18 +4180,27 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
case EXTERNAL_PIXEL_ELEMENTS:
case EXTERNAL_BYTE_ELEMENTS:
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
case INT8_ELEMENTS:
case UINT8_ELEMENTS:
case UINT8_CLAMPED_ELEMENTS:
__ movb(operand, value);
break;
case EXTERNAL_SHORT_ELEMENTS:
case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
case INT16_ELEMENTS:
case UINT16_ELEMENTS:
__ movw(operand, value);
break;
case EXTERNAL_INT_ELEMENTS:
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
case INT32_ELEMENTS:
case UINT32_ELEMENTS:
__ movl(operand, value);
break;
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
case FLOAT32_ELEMENTS:
case FLOAT64_ELEMENTS:
case FAST_ELEMENTS:
case FAST_SMI_ELEMENTS:
case FAST_DOUBLE_ELEMENTS:
@ -4304,7 +4332,7 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) {
if (instr->is_external()) {
if (instr->is_typed_elements()) {
DoStoreKeyedExternalArray(instr);
} else if (instr->hydrogen()->value()->representation().IsDouble()) {
DoStoreKeyedFixedDoubleArray(instr);

View File

@ -2033,24 +2033,23 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
LLoadKeyed* result = NULL;
if (!instr->is_external()) {
if (!instr->is_typed_elements()) {
LOperand* obj = UseRegisterAtStart(instr->elements());
result = new(zone()) LLoadKeyed(obj, key);
} else {
ASSERT(
(instr->representation().IsInteger32() &&
(elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
(elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
!(IsDoubleOrFloatElementsKind(instr->elements_kind()))) ||
(instr->representation().IsDouble() &&
((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
(elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
LOperand* external_pointer = UseRegister(instr->elements());
result = new(zone()) LLoadKeyed(external_pointer, key);
(IsDoubleOrFloatElementsKind(instr->elements_kind()))));
LOperand* backing_store = UseRegister(instr->elements());
result = new(zone()) LLoadKeyed(backing_store, key);
}
DefineAsRegister(result);
bool can_deoptimize = instr->RequiresHoleCheck() ||
(elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS);
(elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) ||
(elements_kind == UINT32_ELEMENTS);
// An unsigned int array load might overflow and cause a deopt, make sure it
// has an environment.
return can_deoptimize ? AssignEnvironment(result) : result;
@ -2071,7 +2070,7 @@ LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
ElementsKind elements_kind = instr->elements_kind();
if (!instr->is_external()) {
if (!instr->is_typed_elements()) {
ASSERT(instr->elements()->representation().IsTagged());
bool needs_write_barrier = instr->NeedsWriteBarrier();
LOperand* object = NULL;
@ -2102,20 +2101,22 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
ASSERT(
(instr->value()->representation().IsInteger32() &&
(elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
(elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
!IsDoubleOrFloatElementsKind(elements_kind)) ||
(instr->value()->representation().IsDouble() &&
((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
(elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
ASSERT(instr->elements()->representation().IsExternal());
IsDoubleOrFloatElementsKind(elements_kind)));
ASSERT((instr->is_fixed_typed_array() &&
instr->elements()->representation().IsTagged()) ||
(instr->is_external() &&
instr->elements()->representation().IsExternal()));
bool val_is_temp_register =
elements_kind == EXTERNAL_PIXEL_ELEMENTS ||
elements_kind == EXTERNAL_FLOAT_ELEMENTS;
elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
elements_kind == FLOAT32_ELEMENTS;
LOperand* val = val_is_temp_register ? UseTempRegister(instr->value())
: UseRegister(instr->value());
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
LOperand* external_pointer = UseRegister(instr->elements());
return new(zone()) LStoreKeyed(external_pointer, key, val);
LOperand* backing_store = UseRegister(instr->elements());
return new(zone()) LStoreKeyed(backing_store, key, val);
}

View File

@ -1540,6 +1540,12 @@ class LLoadKeyed V8_FINAL : public LTemplateInstruction<1, 2, 0> {
bool is_external() const {
return hydrogen()->is_external();
}
bool is_fixed_typed_array() const {
return hydrogen()->is_fixed_typed_array();
}
bool is_typed_elements() const {
return is_external() || is_fixed_typed_array();
}
LOperand* elements() { return inputs_[0]; }
LOperand* key() { return inputs_[1]; }
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
@ -2167,6 +2173,12 @@ class LStoreKeyed V8_FINAL : public LTemplateInstruction<0, 3, 0> {
}
bool is_external() const { return hydrogen()->is_external(); }
bool is_fixed_typed_array() const {
return hydrogen()->is_fixed_typed_array();
}
bool is_typed_elements() const {
return is_external() || is_fixed_typed_array();
}
LOperand* elements() { return inputs_[0]; }
LOperand* key() { return inputs_[1]; }
LOperand* value() { return inputs_[2]; }

View File

@ -16113,14 +16113,6 @@ static void ObjectWithExternalArrayTestHelper(
result = CompileRun("ext_array[1]");
CHECK_EQ(1, result->Int32Value());
// Check pass through of assigned smis
result = CompileRun("var sum = 0;"
"for (var i = 0; i < 8; i++) {"
" sum += ext_array[i] = ext_array[i] = -i;"
"}"
"sum;");
CHECK_EQ(-28, result->Int32Value());
// Check assigned smis
result = CompileRun("for (var i = 0; i < 8; i++) {"
" ext_array[i] = i;"
@ -16130,7 +16122,16 @@ static void ObjectWithExternalArrayTestHelper(
" sum += ext_array[i];"
"}"
"sum;");
CHECK_EQ(28, result->Int32Value());
// Check pass through of assigned smis
result = CompileRun("var sum = 0;"
"for (var i = 0; i < 8; i++) {"
" sum += ext_array[i] = ext_array[i] = -i;"
"}"
"sum;");
CHECK_EQ(-28, result->Int32Value());
// Check assigned smis in reverse order
result = CompileRun("for (var i = 8; --i >= 0; ) {"
@ -16398,6 +16399,111 @@ static void ObjectWithExternalArrayTestHelper(
}
template <class FixedTypedArrayClass,
i::ElementsKind elements_kind,
class ElementType>
static void FixedTypedArrayTestHelper(
v8::ExternalArrayType array_type,
ElementType low,
ElementType high) {
i::FLAG_allow_natives_syntax = true;
LocalContext context;
i::Isolate* isolate = CcTest::i_isolate();
i::Factory* factory = isolate->factory();
v8::HandleScope scope(context->GetIsolate());
const int kElementCount = 260;
i::Handle<FixedTypedArrayClass> fixed_array =
i::Handle<FixedTypedArrayClass>::cast(
factory->NewFixedTypedArray(kElementCount, array_type));
CHECK_EQ(FixedTypedArrayClass::kInstanceType,
fixed_array->map()->instance_type());
CHECK_EQ(kElementCount, fixed_array->length());
CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
for (int i = 0; i < kElementCount; i++) {
fixed_array->set(i, static_cast<ElementType>(i));
}
// Force GC to trigger verification.
CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
for (int i = 0; i < kElementCount; i++) {
CHECK_EQ(static_cast<int64_t>(static_cast<ElementType>(i)),
static_cast<int64_t>(fixed_array->get_scalar(i)));
}
v8::Handle<v8::Object> obj = v8::Object::New(CcTest::isolate());
i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
i::Handle<i::Map> fixed_array_map =
isolate->factory()->GetElementsTransitionMap(jsobj, elements_kind);
jsobj->set_map(*fixed_array_map);
jsobj->set_elements(*fixed_array);
ObjectWithExternalArrayTestHelper<FixedTypedArrayClass, ElementType>(
context.local(), obj, kElementCount, array_type, low, high);
}
THREADED_TEST(FixedUint8Array) {
FixedTypedArrayTestHelper<i::FixedUint8Array, i::UINT8_ELEMENTS, uint8_t>(
v8::kExternalUnsignedByteArray,
0x0, 0xFF);
}
THREADED_TEST(FixedUint8ClampedArray) {
FixedTypedArrayTestHelper<i::FixedUint8ClampedArray,
i::UINT8_CLAMPED_ELEMENTS, uint8_t>(
v8::kExternalPixelArray,
0x0, 0xFF);
}
THREADED_TEST(FixedInt8Array) {
FixedTypedArrayTestHelper<i::FixedInt8Array, i::INT8_ELEMENTS, int8_t>(
v8::kExternalByteArray,
-0x80, 0x7F);
}
THREADED_TEST(FixedUint16Array) {
FixedTypedArrayTestHelper<i::FixedUint16Array, i::UINT16_ELEMENTS, uint16_t>(
v8::kExternalUnsignedShortArray,
0x0, 0xFFFF);
}
THREADED_TEST(FixedInt16Array) {
FixedTypedArrayTestHelper<i::FixedInt16Array, i::INT16_ELEMENTS, int16_t>(
v8::kExternalShortArray,
-0x8000, 0x7FFF);
}
THREADED_TEST(FixedUint32Array) {
FixedTypedArrayTestHelper<i::FixedUint32Array, i::UINT32_ELEMENTS, uint32_t>(
v8::kExternalUnsignedIntArray,
0x0, 0xFFFFFFFF);
}
THREADED_TEST(FixedInt32Array) {
FixedTypedArrayTestHelper<i::FixedInt32Array, i::INT32_ELEMENTS, int32_t>(
v8::kExternalIntArray,
-0x80000000, 0x7FFFFFFF);
}
THREADED_TEST(FixedFloat32Array) {
FixedTypedArrayTestHelper<i::FixedFloat32Array, i::FLOAT32_ELEMENTS, float>(
v8::kExternalFloatArray,
-500, 500);
}
THREADED_TEST(FixedFloat64Array) {
FixedTypedArrayTestHelper<i::FixedFloat64Array, i::FLOAT64_ELEMENTS, float>(
v8::kExternalDoubleArray,
-500, 500);
}
template <class ExternalArrayClass, class ElementType>
static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
int64_t low,