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:
parent
c8475cf1b1
commit
0c960c2e96
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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]; }
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
191
src/elements.cc
191
src/elements.cc
@ -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> > {
|
||||
|
@ -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(
|
||||
|
@ -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();
|
||||
|
@ -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, \
|
||||
|
456
src/heap.cc
456
src/heap.cc
@ -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 {
|
||||
|
25
src/heap.h
25
src/heap.h
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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]; }
|
||||
|
@ -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++;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
119
src/objects.cc
119
src/objects.cc
@ -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));
|
||||
|
113
src/objects.h
113
src/objects.h
@ -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());
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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]; }
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user