!IsDoubleOrFloatElementsKind(instr->elements_kind())) ||
(instr->value()->representation().IsDouble() &&
IsDoubleOrFloatElementsKind(instr->elements_kind())));
- DCHECK((instr->is_fixed_typed_array() &&
- instr->elements()->representation().IsTagged()) ||
- (instr->is_external() &&
- instr->elements()->representation().IsExternal()));
+ DCHECK(instr->elements()->representation().IsExternal());
LOperand* val = UseRegister(instr->value());
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
LOperand* backing_store = UseRegister(instr->elements());
!IsDoubleOrFloatElementsKind(instr->elements_kind())) ||
(instr->value()->representation().IsDouble() &&
IsDoubleOrFloatElementsKind(instr->elements_kind())));
- DCHECK((instr->is_fixed_typed_array() &&
- instr->elements()->representation().IsTagged()) ||
- (instr->is_external() &&
- instr->elements()->representation().IsExternal()));
+ DCHECK(instr->elements()->representation().IsExternal());
return new(zone()) LStoreKeyedExternal(elements, key, val, temp);
} else if (instr->value()->representation().IsDouble()) {
void LCodeGen::DoAddE(LAddE* instr) {
Register result = ToRegister(instr->result());
Register left = ToRegister(instr->left());
- Operand right = (instr->right()->IsConstantOperand())
- ? ToInteger32(LConstantOperand::cast(instr->right()))
- : Operand(ToRegister32(instr->right()), SXTW);
+ Operand right = Operand(x0); // Dummy initialization.
+ if (instr->hydrogen()->external_add_type() == AddOfExternalAndTagged) {
+ right = Operand(ToRegister(instr->right()));
+ } else if (instr->right()->IsConstantOperand()) {
+ right = ToInteger32(LConstantOperand::cast(instr->right()));
+ } else {
+ right = Operand(ToRegister32(instr->right()), SXTW);
+ }
DCHECK(!instr->hydrogen()->CheckFlag(HValue::kCanOverflow));
__ Add(result, left, right);
}
+ExternalReference ExternalReference::fixed_typed_array_base_data_offset() {
+ return ExternalReference(reinterpret_cast<void*>(
+ FixedTypedArrayBase::kDataOffset - kHeapObjectTag));
+}
+
+
bool operator==(ExternalReference lhs, ExternalReference rhs) {
return lhs.address() == rhs.address();
}
static ExternalReference stress_deopt_count(Isolate* isolate);
+ static ExternalReference fixed_typed_array_base_data_offset();
+
private:
explicit ExternalReference(void* address)
: address_(address) {}
}
+static bool IsTypedArrayElementsKind(ElementsKind elements_kind) {
+ return IsFixedTypedArrayElementsKind(elements_kind) ||
+ IsExternalArrayElementsKind(elements_kind);
+}
+
+
int GetDefaultHeaderSizeForElementsKind(ElementsKind elements_kind) {
STATIC_ASSERT(FixedArray::kHeaderSize == FixedDoubleArray::kHeaderSize);
- if (IsExternalArrayElementsKind(elements_kind)) {
+ if (IsTypedArrayElementsKind(elements_kind)) {
return 0;
- } else if (IsFixedTypedArrayElementsKind(elements_kind)) {
- return FixedTypedArrayBase::kDataOffset - kHeapObjectTag;
} else {
return FixedArray::kHeaderSize - kHeapObjectTag;
}
}
-static bool IsTypedArrayElementsKind(ElementsKind elements_kind) {
- return IsFixedTypedArrayElementsKind(elements_kind) ||
- IsExternalArrayElementsKind(elements_kind);
-}
-
-
static inline bool IsFastTransitionTarget(ElementsKind elements_kind) {
return IsFastElementsKind(elements_kind) ||
elements_kind == DICTIONARY_ELEMENTS;
object->set_map(MapForFixedTypedArray(array_type));
FixedTypedArrayBase* elements = FixedTypedArrayBase::cast(object);
elements->set_base_pointer(elements, SKIP_WRITE_BARRIER);
+ elements->set_external_pointer(
+ ExternalReference::fixed_typed_array_base_data_offset().address(),
+ SKIP_WRITE_BARRIER);
elements->set_length(length);
if (initialize) memset(elements->DataPtr(), 0, elements->DataSize());
return elements;
right()->representation().IsTagged()));
}
+ ExternalAddType external_add_type() const { return external_add_type_; }
+
DECLARE_CONCRETE_INSTRUCTION(Add)
protected:
DCHECK(left->representation().IsExternal());
DCHECK(right->representation().IsTagged());
SetDependsOnFlag(kNewSpacePromotion);
+ ClearFlag(HValue::kCanOverflow);
+ SetFlag(kHasNoObservableSideEffects);
break;
case NoExternalAdd:
Representation::Tagged());
}
+ static HObjectAccess ForFixedTypedArrayBaseExternalPointer() {
+ return HObjectAccess::ForObservableJSObjectOffset(
+ FixedTypedArrayBase::kExternalPointerOffset,
+ Representation::External());
+ }
+
static HObjectAccess ForStringHashField() {
return HObjectAccess(kInobject,
String::kHashFieldOffset,
Representation RequiredInputRepresentation(int index) override {
// kind_fast: tagged[int32] (none)
// kind_double: tagged[int32] (none)
- // kind_fixed_typed_array: tagged[int32] (none)
+ // kind_fixed_typed_array: external[int32] (none)
// kind_external: external[int32] (none)
if (index == 0) {
- return is_external() ? Representation::External()
- : Representation::Tagged();
+ return is_typed_elements() ? Representation::External()
+ : Representation::Tagged();
}
if (index == 1) {
return ArrayInstructionInterface::KeyedAccessIndexRequirement(
// kind_fixed_typed_array: tagged[int32] = (double | int32)
// kind_external: external[int32] = (double | int32)
if (index == 0) {
- return is_external() ? Representation::External()
- : Representation::Tagged();
+ return is_typed_elements() ? Representation::External()
+ : Representation::Tagged();
} else if (index == 1) {
return ArrayInstructionInterface::KeyedAccessIndexRequirement(
OperandAt(1)->representation());
backing_store = Add<HLoadNamedField>(
elements, nullptr, HObjectAccess::ForExternalArrayExternalPointer());
} else {
- backing_store = elements;
+ HValue* external_pointer = Add<HLoadNamedField>(
+ elements, nullptr,
+ HObjectAccess::ForFixedTypedArrayBaseExternalPointer());
+ HValue* base_pointer = Add<HLoadNamedField>(
+ elements, nullptr,
+ HObjectAccess::ForFixedTypedArrayBaseBasePointer());
+ backing_store = AddUncasted<HAdd>(external_pointer, base_pointer,
+ Strength::WEAK, AddOfExternalAndTagged);
}
if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
NoObservableSideEffectsScope no_effects(this);
Add<HStoreNamedField>(
elements, HObjectAccess::ForFixedTypedArrayBaseBasePointer(), elements);
+ Add<HStoreNamedField>(
+ elements, HObjectAccess::ForFixedTypedArrayBaseExternalPointer(),
+ Add<HConstant>(ExternalReference::fixed_typed_array_base_data_offset()));
+
HValue* filler = Add<HConstant>(static_cast<int32_t>(0));
if (initialize) {
LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement);
+ HValue* backing_store = AddUncasted<HAdd>(
+ Add<HConstant>(ExternalReference::fixed_typed_array_base_data_offset()),
+ elements, Strength::WEAK, AddOfExternalAndTagged);
+
HValue* key = builder.BeginBody(
Add<HConstant>(static_cast<int32_t>(0)),
length, Token::LT);
- Add<HStoreKeyed>(elements, key, filler, fixed_elements_kind);
+ Add<HStoreKeyed>(backing_store, key, filler, fixed_elements_kind);
builder.EndBody();
}
int32_t LCodeGen::ToRepresentation(LConstantOperand* op,
const Representation& r) const {
HConstant* constant = chunk_->LookupConstant(op);
+ if (r.IsExternal()) {
+ return reinterpret_cast<int32_t>(
+ constant->ExternalReferenceValue().address());
+ }
int32_t value = constant->Integer32Value();
if (r.IsInteger32()) return value;
DCHECK(r.IsSmiOrTagged());
if (operand_value->IsRegister()) {
Register value = ToRegister(operand_value);
__ Store(value, operand, representation);
- } else if (representation.IsInteger32()) {
+ } else if (representation.IsInteger32() || representation.IsExternal()) {
Immediate immediate = ToImmediate(operand_value, representation);
DCHECK(!instr->hydrogen()->NeedsWriteBarrier());
__ mov(operand, immediate);
!IsDoubleOrFloatElementsKind(elements_kind)) ||
(instr->value()->representation().IsDouble() &&
IsDoubleOrFloatElementsKind(elements_kind)));
- DCHECK((instr->is_fixed_typed_array() &&
- instr->elements()->representation().IsTagged()) ||
- (instr->is_external() &&
- instr->elements()->representation().IsExternal()));
+ DCHECK(instr->elements()->representation().IsExternal());
LOperand* backing_store = UseRegister(instr->elements());
LOperand* val = GetStoreKeyedValueOperand(instr);
!IsDoubleOrFloatElementsKind(instr->elements_kind())) ||
(instr->value()->representation().IsDouble() &&
IsDoubleOrFloatElementsKind(instr->elements_kind())));
- DCHECK((instr->is_fixed_typed_array() &&
- instr->elements()->representation().IsTagged()) ||
- (instr->is_external() &&
- instr->elements()->representation().IsExternal()));
+ DCHECK(instr->elements()->representation().IsExternal());
LOperand* val = UseRegister(instr->value());
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
LOperand* backing_store = UseRegister(instr->elements());
!IsDoubleOrFloatElementsKind(instr->elements_kind())) ||
(instr->value()->representation().IsDouble() &&
IsDoubleOrFloatElementsKind(instr->elements_kind())));
- DCHECK((instr->is_fixed_typed_array() &&
- instr->elements()->representation().IsTagged()) ||
- (instr->is_external() &&
- instr->elements()->representation().IsExternal()));
+ DCHECK(instr->elements()->representation().IsExternal());
LOperand* val = UseRegister(instr->value());
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
LOperand* backing_store = UseRegister(instr->elements());
ACCESSORS(FixedTypedArrayBase, base_pointer, Object, kBasePointerOffset)
+void* FixedTypedArrayBase::external_pointer() const {
+ intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
+ return reinterpret_cast<void*>(ptr);
+}
+
+
+void FixedTypedArrayBase::set_external_pointer(void* value,
+ WriteBarrierMode mode) {
+ intptr_t ptr = reinterpret_cast<intptr_t>(value);
+ WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
+}
+
+
void* FixedTypedArrayBase::DataPtr() {
- return FIELD_ADDR(this, kDataOffset);
+ return reinterpret_cast<void*>(
+ reinterpret_cast<intptr_t>(base_pointer()) +
+ reinterpret_cast<intptr_t>(external_pointer()));
}
template <class Traits>
typename Traits::ElementType FixedTypedArray<Traits>::get_scalar(int index) {
DCHECK((index >= 0) && (index < this->length()));
- ElementType* ptr = reinterpret_cast<ElementType*>(
- FIELD_ADDR(this, kDataOffset));
+ ElementType* ptr = reinterpret_cast<ElementType*>(DataPtr());
return ptr[index];
}
template <class Traits>
void FixedTypedArray<Traits>::set(int index, ElementType value) {
DCHECK((index >= 0) && (index < this->length()));
- ElementType* ptr = reinterpret_cast<ElementType*>(
- FIELD_ADDR(this, kDataOffset));
+ ElementType* ptr = reinterpret_cast<ElementType*>(DataPtr());
ptr[index] = value;
}
// [base_pointer]: For now, points to the FixedTypedArrayBase itself.
DECL_ACCESSORS(base_pointer, Object)
+ // [external_pointer]: For now, contains the offset between base_pointer and
+ // the start of the data.
+ DECL_ACCESSORS(external_pointer, void)
+
// Dispatched behavior.
inline void FixedTypedArrayBaseIterateBody(ObjectVisitor* v);
DECLARE_CAST(FixedTypedArrayBase)
- static const int kBasePointerOffset =
- FixedArrayBase::kHeaderSize + kPointerSize;
- static const int kHeaderSize = kBasePointerOffset + kPointerSize;
+ static const int kBasePointerOffset = FixedArrayBase::kHeaderSize;
+ static const int kExternalPointerOffset = kBasePointerOffset + kPointerSize;
+ static const int kHeaderSize =
+ DOUBLE_POINTER_ALIGN(kExternalPointerOffset + kPointerSize);
- static const int kDataOffset = DOUBLE_POINTER_ALIGN(kHeaderSize);
+ static const int kDataOffset = kHeaderSize;
inline int size();
!IsDoubleOrFloatElementsKind(instr->elements_kind())) ||
(instr->value()->representation().IsDouble() &&
IsDoubleOrFloatElementsKind(instr->elements_kind())));
- DCHECK((instr->is_fixed_typed_array() &&
- instr->elements()->representation().IsTagged()) ||
- (instr->is_external() &&
- instr->elements()->representation().IsExternal()));
+ DCHECK(instr->elements()->representation().IsExternal());
LOperand* val = UseRegister(instr->value());
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
LOperand* backing_store = UseRegister(instr->elements());
}
+bool LCodeGen::IsExternalConstant(LConstantOperand* op) const {
+ return chunk_->LookupLiteralRepresentation(op).IsExternal();
+}
+
+
bool LCodeGen::IsDehoistedKeyConstant(LConstantOperand* op) const {
return op->IsConstantOperand() &&
chunk_->IsDehoistedKey(chunk_->LookupConstant(op));
__ movl(operand, Immediate(value));
}
+ } else if (IsExternalConstant(operand_value)) {
+ DCHECK(!hinstr->NeedsWriteBarrier());
+ ExternalReference ptr = ToExternalReference(operand_value);
+ __ Move(kScratchRegister, ptr);
+ __ movp(operand, kScratchRegister);
} else {
Handle<Object> handle_value = ToHandle(operand_value);
DCHECK(!hinstr->NeedsWriteBarrier());
Register ToRegister(LOperand* op) const;
XMMRegister ToDoubleRegister(LOperand* op) const;
bool IsInteger32Constant(LConstantOperand* op) const;
+ bool IsExternalConstant(LConstantOperand* op) const;
bool IsDehoistedKeyConstant(LConstantOperand* op) const;
bool IsSmiConstant(LConstantOperand* op) const;
int32_t ToRepresentation(LConstantOperand* op, const Representation& r) const;
!IsDoubleOrFloatElementsKind(elements_kind)) ||
(instr->value()->representation().IsDouble() &&
IsDoubleOrFloatElementsKind(elements_kind)));
- DCHECK((instr->is_fixed_typed_array() &&
- instr->elements()->representation().IsTagged()) ||
- (instr->is_external() &&
- instr->elements()->representation().IsExternal()));
+ DCHECK(instr->elements()->representation().IsExternal());
bool val_is_temp_register =
elements_kind == EXTERNAL_UINT8_CLAMPED_ELEMENTS ||
elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
int32_t LCodeGen::ToRepresentation(LConstantOperand* op,
const Representation& r) const {
HConstant* constant = chunk_->LookupConstant(op);
+ if (r.IsExternal()) {
+ return reinterpret_cast<int32_t>(
+ constant->ExternalReferenceValue().address());
+ }
int32_t value = constant->Integer32Value();
if (r.IsInteger32()) return value;
DCHECK(r.IsSmiOrTagged());
if (operand_value->IsRegister()) {
Register value = ToRegister(operand_value);
__ Store(value, operand, representation);
- } else if (representation.IsInteger32()) {
+ } else if (representation.IsInteger32() || representation.IsExternal()) {
Immediate immediate = ToImmediate(operand_value, representation);
DCHECK(!instr->hydrogen()->NeedsWriteBarrier());
__ mov(operand, immediate);
!IsDoubleOrFloatElementsKind(elements_kind)) ||
(instr->value()->representation().IsDouble() &&
IsDoubleOrFloatElementsKind(elements_kind)));
- DCHECK((instr->is_fixed_typed_array() &&
- instr->elements()->representation().IsTagged()) ||
- (instr->is_external() &&
- instr->elements()->representation().IsExternal()));
+ DCHECK(instr->elements()->representation().IsExternal());
LOperand* backing_store = UseRegister(instr->elements());
LOperand* val = GetStoreKeyedValueOperand(instr);
# Ignore those.
BLACKLISTED = [
+ "fixed_typed_array_base_data_offset",
"page_flags",
"math_exp_constants",
"math_exp_log_table",