// checks.
ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
- int index = lookup->GetFieldIndex().field_index();
-
- // Adjust for the number of properties stored in the object. Even in the
- // face of a transition we can use the old map here because the size of the
- // object and the number of in-object properties is not going to change.
- index -= object->map()->inobject_properties();
+ FieldIndex index = lookup->GetFieldIndex();
Representation representation = lookup->representation();
ASSERT(!representation.IsNone());
}
} else if (representation.IsDouble()) {
// Load the double storage.
- if (index < 0) {
- int offset = object->map()->instance_size() + (index * kPointerSize);
- __ ldr(scratch1, FieldMemOperand(receiver_reg, offset));
+ if (index.is_inobject()) {
+ __ ldr(scratch1, FieldMemOperand(receiver_reg, index.offset()));
} else {
__ ldr(scratch1,
FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
- int offset = index * kPointerSize + FixedArray::kHeaderSize;
- __ ldr(scratch1, FieldMemOperand(scratch1, offset));
+ __ ldr(scratch1, FieldMemOperand(scratch1, index.offset()));
}
// Store the value into the storage.
// TODO(verwaest): Share this code as a code stub.
SmiCheck smi_check = representation.IsTagged()
? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
- if (index < 0) {
+ if (index.is_inobject()) {
// Set the property straight into the object.
- int offset = object->map()->instance_size() + (index * kPointerSize);
- __ str(value_reg, FieldMemOperand(receiver_reg, offset));
+ __ str(value_reg, FieldMemOperand(receiver_reg, index.offset()));
if (!representation.IsSmi()) {
// Skip updating write barrier if storing a smi.
// Pass the now unused name_reg as a scratch register.
__ mov(name_reg, value_reg);
__ RecordWriteField(receiver_reg,
- offset,
+ index.offset(),
name_reg,
scratch1,
kLRHasNotBeenSaved,
}
} else {
// Write to the properties array.
- int offset = index * kPointerSize + FixedArray::kHeaderSize;
// Get the properties array
__ ldr(scratch1,
FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
- __ str(value_reg, FieldMemOperand(scratch1, offset));
+ __ str(value_reg, FieldMemOperand(scratch1, index.offset()));
if (!representation.IsSmi()) {
// Skip updating write barrier if storing a smi.
// Ok to clobber receiver_reg and name_reg, since we return.
__ mov(name_reg, value_reg);
__ RecordWriteField(scratch1,
- offset,
+ index.offset(),
name_reg,
receiver_reg,
kLRHasNotBeenSaved,
void LoadStubCompiler::GenerateLoadField(Register reg,
Handle<JSObject> holder,
- PropertyIndex field,
+ FieldIndex field,
Representation representation) {
if (!reg.is(receiver())) __ mov(receiver(), reg);
if (kind() == Code::LOAD_IC) {
- LoadFieldStub stub(isolate(),
- field.is_inobject(holder),
- field.translate(holder),
- representation);
+ LoadFieldStub stub(isolate(), field);
GenerateTailCall(masm(), stub.GetCode());
} else {
- KeyedLoadFieldStub stub(isolate(),
- field.is_inobject(holder),
- field.translate(holder),
- representation);
+ KeyedLoadFieldStub stub(isolate(), field);
GenerateTailCall(masm(), stub.GetCode());
}
}
// checks.
ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
- int index = lookup->GetFieldIndex().field_index();
-
- // Adjust for the number of properties stored in the object. Even in the
- // face of a transition we can use the old map here because the size of the
- // object and the number of in-object properties is not going to change.
- index -= object->map()->inobject_properties();
+ FieldIndex index = lookup->GetFieldIndex();
Representation representation = lookup->representation();
ASSERT(!representation.IsNone());
__ SmiUntagToDouble(temp_double, value_reg, kSpeculativeUntag);
// Load the double storage.
- if (index < 0) {
- int offset = (index * kPointerSize) + object->map()->instance_size();
- __ Ldr(scratch1, FieldMemOperand(receiver_reg, offset));
+ if (index.is_inobject()) {
+ __ Ldr(scratch1, FieldMemOperand(receiver_reg, index.offset()));
} else {
- int offset = (index * kPointerSize) + FixedArray::kHeaderSize;
__ Ldr(scratch1,
FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
- __ Ldr(scratch1, FieldMemOperand(scratch1, offset));
+ __ Ldr(scratch1, FieldMemOperand(scratch1, index.offset()));
}
// Store the value into the storage.
// TODO(verwaest): Share this code as a code stub.
SmiCheck smi_check = representation.IsTagged()
? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
- if (index < 0) {
+ if (index.is_inobject()) {
// Set the property straight into the object.
- int offset = object->map()->instance_size() + (index * kPointerSize);
- __ Str(value_reg, FieldMemOperand(receiver_reg, offset));
+ __ Str(value_reg, FieldMemOperand(receiver_reg, index.offset()));
if (!representation.IsSmi()) {
// Skip updating write barrier if storing a smi.
// Pass the now unused name_reg as a scratch register.
__ Mov(name_reg, value_reg);
__ RecordWriteField(receiver_reg,
- offset,
+ index.offset(),
name_reg,
scratch1,
kLRHasNotBeenSaved,
}
} else {
// Write to the properties array.
- int offset = index * kPointerSize + FixedArray::kHeaderSize;
// Get the properties array
__ Ldr(scratch1,
FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
- __ Str(value_reg, FieldMemOperand(scratch1, offset));
+ __ Str(value_reg, FieldMemOperand(scratch1, index.offset()));
if (!representation.IsSmi()) {
// Skip updating write barrier if storing a smi.
// Ok to clobber receiver_reg and name_reg, since we return.
__ Mov(name_reg, value_reg);
__ RecordWriteField(scratch1,
- offset,
+ index.offset(),
name_reg,
receiver_reg,
kLRHasNotBeenSaved,
void LoadStubCompiler::GenerateLoadField(Register reg,
Handle<JSObject> holder,
- PropertyIndex field,
+ FieldIndex field,
Representation representation) {
__ Mov(receiver(), reg);
if (kind() == Code::LOAD_IC) {
- LoadFieldStub stub(isolate(),
- field.is_inobject(holder),
- field.translate(holder),
- representation);
+ LoadFieldStub stub(isolate(), field);
GenerateTailCall(masm(), stub.GetCode());
} else {
- KeyedLoadFieldStub stub(isolate(),
- field.is_inobject(holder),
- field.translate(holder),
- representation);
+ KeyedLoadFieldStub stub(isolate(), field);
GenerateTailCall(masm(), stub.GetCode());
}
}
LookupResult lookup(isolate);
result->LookupOwn(factory->callee_string(), &lookup);
ASSERT(lookup.IsField());
- ASSERT(lookup.GetFieldIndex().field_index() == Heap::kArgumentsCalleeIndex);
+ ASSERT(lookup.GetFieldIndex().property_index() ==
+ Heap::kArgumentsCalleeIndex);
result->LookupOwn(factory->length_string(), &lookup);
ASSERT(lookup.IsField());
- ASSERT(lookup.GetFieldIndex().field_index() == Heap::kArgumentsLengthIndex);
+ ASSERT(lookup.GetFieldIndex().property_index() ==
+ Heap::kArgumentsLengthIndex);
ASSERT(result->map()->inobject_properties() > Heap::kArgumentsCalleeIndex);
ASSERT(result->map()->inobject_properties() > Heap::kArgumentsLengthIndex);
LookupResult lookup(isolate);
result->LookupOwn(factory->length_string(), &lookup);
ASSERT(lookup.IsField());
- ASSERT(lookup.GetFieldIndex().field_index() == Heap::kArgumentsLengthIndex);
+ ASSERT(lookup.GetFieldIndex().property_index() ==
+ Heap::kArgumentsLengthIndex);
ASSERT(result->map()->inobject_properties() > Heap::kArgumentsLengthIndex);
case FIELD: {
HandleScope inner(isolate());
Handle<Name> key = Handle<Name>(descs->GetKey(i));
- int index = descs->GetFieldIndex(i);
+ FieldIndex index = FieldIndex::ForDescriptor(from->map(), i);
ASSERT(!descs->GetDetails(i).representation().IsDouble());
Handle<Object> value = Handle<Object>(from->RawFastPropertyAt(index),
isolate());
#include "src/v8.h"
#include "src/code-stubs.h"
+#include "src/field-index.h"
#include "src/hydrogen.h"
#include "src/lithium.h"
Isolate* isolate() { return info_.isolate(); }
HLoadNamedField* BuildLoadNamedField(HValue* object,
- Representation representation,
- int offset,
- bool is_inobject);
+ FieldIndex index);
enum ArgumentClass {
NONE,
HLoadNamedField* CodeStubGraphBuilderBase::BuildLoadNamedField(
- HValue* object,
- Representation representation,
- int offset,
- bool is_inobject) {
- HObjectAccess access = is_inobject
+ HValue* object, FieldIndex index) {
+ Representation representation = index.is_double()
+ ? Representation::Double()
+ : Representation::Tagged();
+ int offset = index.offset();
+ HObjectAccess access = index.is_inobject()
? HObjectAccess::ForObservableJSObjectOffset(offset, representation)
: HObjectAccess::ForBackingStoreOffset(offset, representation);
- if (representation.IsDouble()) {
+ if (index.is_double()) {
// Load the heap number.
object = Add<HLoadNamedField>(
object, static_cast<HValue*>(NULL),
template<>
HValue* CodeStubGraphBuilder<LoadFieldStub>::BuildCodeStub() {
- return BuildLoadNamedField(GetParameter(0),
- casted_stub()->representation(),
- casted_stub()->offset(),
- casted_stub()->is_inobject());
+ return BuildLoadNamedField(GetParameter(0), casted_stub()->index());
}
template<>
HValue* CodeStubGraphBuilder<StringLengthStub>::BuildCodeStub() {
- HValue* string = BuildLoadNamedField(
- GetParameter(0), Representation::Tagged(), JSValue::kValueOffset, true);
- return BuildLoadNamedField(
- string, Representation::Tagged(), String::kLengthOffset, true);
+ HValue* string = BuildLoadNamedField(GetParameter(0),
+ FieldIndex::ForInObjectOffset(JSValue::kValueOffset));
+ return BuildLoadNamedField(string,
+ FieldIndex::ForInObjectOffset(String::kLengthOffset));
}
class LoadFieldStub: public HandlerStub {
public:
- LoadFieldStub(Isolate* isolate,
- bool inobject,
- int index, Representation representation)
- : HandlerStub(isolate) {
- Initialize(Code::LOAD_IC, inobject, index, representation);
+ LoadFieldStub(Isolate* isolate, FieldIndex index)
+ : HandlerStub(isolate), index_(index) {
+ Initialize(Code::LOAD_IC);
}
virtual Handle<Code> GenerateCode() V8_OVERRIDE;
return KindBits::decode(bit_field_);
}
- bool is_inobject() {
- return InobjectBits::decode(bit_field_);
- }
-
- int offset() {
- int index = IndexBits::decode(bit_field_);
- int offset = index * kPointerSize;
- if (is_inobject()) return offset;
- return FixedArray::kHeaderSize + offset;
- }
+ FieldIndex index() const { return index_; }
bool unboxed_double() {
- return UnboxedDoubleBits::decode(bit_field_);
+ return index_.is_double();
}
virtual Code::StubType GetStubType() { return Code::FAST; }
protected:
- explicit LoadFieldStub(Isolate* isolate) : HandlerStub(isolate) { }
+ explicit LoadFieldStub(Isolate* isolate);
- void Initialize(Code::Kind kind,
- bool inobject,
- int index,
- Representation representation) {
- bit_field_ = KindBits::encode(kind)
- | InobjectBits::encode(inobject)
- | IndexBits::encode(index)
- | UnboxedDoubleBits::encode(representation.IsDouble());
+ void Initialize(Code::Kind kind) {
+ int property_index_key = index_.GetLoadFieldStubKey();
+ // Save a copy of the essence of the property index into the bit field to
+ // make sure that hashing of unique stubs works correctly..
+ bit_field_ = KindBits::encode(kind) |
+ EncodedLoadFieldByIndexBits::encode(property_index_key);
}
private:
STATIC_ASSERT(KindBits::kSize == 4);
- class InobjectBits: public BitField<bool, 4, 1> {};
- class IndexBits: public BitField<int, 5, 11> {};
- class UnboxedDoubleBits: public BitField<bool, 16, 1> {};
+ class EncodedLoadFieldByIndexBits: public BitField<int, 4, 13> {};
virtual CodeStub::Major MajorKey() { return LoadField; }
+ FieldIndex index_;
};
class KeyedLoadFieldStub: public LoadFieldStub {
public:
- KeyedLoadFieldStub(Isolate* isolate,
- bool inobject,
- int index, Representation representation)
- : LoadFieldStub(isolate) {
- Initialize(Code::KEYED_LOAD_IC, inobject, index, representation);
+ KeyedLoadFieldStub(Isolate* isolate, FieldIndex index)
+ : LoadFieldStub(isolate, index) {
+ Initialize(Code::KEYED_LOAD_IC);
}
virtual void InitializeInterfaceDescriptor(
object->set_elements(FixedArrayBase::cast(*elements));
for (int i = 0; i < length - 3; ++i) {
Handle<Object> value = MaterializeNextValue();
- object->FastPropertyAtPut(i, *value);
+ FieldIndex index = FieldIndex::ForPropertyIndex(object->map(), i);
+ object->FastPropertyAtPut(index, *value);
}
break;
}
object->set_elements(FixedArrayBase::cast(*elements));
for (int i = 0; i < length - 3; ++i) {
Handle<Object> value = GetNext(isolate, lvl + 1);
- object->FastPropertyAtPut(i, *value);
+ FieldIndex index = FieldIndex::ForPropertyIndex(object->map(), i);
+ object->FastPropertyAtPut(index, *value);
}
return object;
}
--- /dev/null
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_FIELD_INDEX_INL_H_
+#define V8_FIELD_INDEX_INL_H_
+
+#include "src/field-index.h"
+
+namespace v8 {
+namespace internal {
+
+
+inline FieldIndex FieldIndex::ForInObjectOffset(int offset, Map* map) {
+ ASSERT((offset % kPointerSize) == 0);
+ int index = offset / kPointerSize;
+ if (map == NULL) {
+ return FieldIndex(true, index, false, index + 1, 0, true);
+ }
+ int first_inobject_offset = map->GetInObjectPropertyOffset(0);
+ if (offset < first_inobject_offset) {
+ return FieldIndex(true, index, false, 0, 0, true);
+ } else {
+ return FieldIndex::ForPropertyIndex(map, offset / kPointerSize);
+ }
+}
+
+
+inline FieldIndex FieldIndex::ForPropertyIndex(Map* map,
+ int property_index,
+ bool is_double) {
+ ASSERT(map->instance_type() >= FIRST_NONSTRING_TYPE);
+ int inobject_properties = map->inobject_properties();
+ bool is_inobject = property_index < inobject_properties;
+ int first_inobject_offset;
+ if (is_inobject) {
+ first_inobject_offset = map->GetInObjectPropertyOffset(0);
+ } else {
+ first_inobject_offset = FixedArray::kHeaderSize;
+ property_index -= inobject_properties;
+ }
+ return FieldIndex(is_inobject,
+ property_index + first_inobject_offset / kPointerSize,
+ is_double, inobject_properties, first_inobject_offset);
+}
+
+
+inline FieldIndex FieldIndex::ForLoadByFieldIndex(Map* map, int orig_index) {
+ int field_index = orig_index;
+ int is_inobject = true;
+ bool is_double = field_index & 1;
+ int first_inobject_offset = 0;
+ field_index >>= 1;
+ if (field_index < 0) {
+ field_index = -(field_index + 1);
+ is_inobject = false;
+ first_inobject_offset = FixedArray::kHeaderSize;
+ field_index += FixedArray::kHeaderSize / kPointerSize;
+ } else {
+ first_inobject_offset = map->GetInObjectPropertyOffset(0);
+ field_index += JSObject::kHeaderSize / kPointerSize;
+ }
+ return FieldIndex(is_inobject, field_index, is_double,
+ map->inobject_properties(), first_inobject_offset);
+}
+
+
+inline FieldIndex FieldIndex::ForDescriptor(Map* map, int descriptor_index) {
+ PropertyDetails details =
+ map->instance_descriptors()->GetDetails(descriptor_index);
+ int field_index =
+ map->instance_descriptors()->GetFieldIndex(descriptor_index);
+ return ForPropertyIndex(map, field_index,
+ details.representation().IsDouble());
+}
+
+
+} } // namespace v8::internal
+
+#endif
--- /dev/null
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/v8.h"
+
+#include "src/field-index.h"
+#include "src/objects.h"
+#include "src/objects-inl.h"
+
+namespace v8 {
+namespace internal {
+
+
+FieldIndex FieldIndex::ForLookupResult(const LookupResult* lookup_result) {
+ Map* map = lookup_result->holder()->map();
+ return ForPropertyIndex(map,
+ lookup_result->GetFieldIndexFromMap(map),
+ lookup_result->representation().IsDouble());
+}
+
+
+} } // namespace v8::internal
--- /dev/null
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_FIELD_INDEX_H_
+#define V8_FIELD_INDEX_H_
+
+#include "src/utils.h"
+#include "src/property-details.h"
+
+namespace v8 {
+namespace internal {
+
+class Map;
+
+// Wrapper class to hold a field index, usually but not necessarily generated
+// from a property index. When available, the wrapper class captures additional
+// information to allow the field index to be translated back into the property
+// index it was originally generated from.
+class FieldIndex V8_FINAL {
+ public:
+ static FieldIndex ForPropertyIndex(Map* map,
+ int index,
+ bool is_double = false);
+ static FieldIndex ForInObjectOffset(int offset, Map* map = NULL);
+ static FieldIndex ForLookupResult(const LookupResult* result);
+ static FieldIndex ForDescriptor(Map* map, int descriptor_index);
+ static FieldIndex ForLoadByFieldIndex(Map* map, int index);
+ static FieldIndex ForKeyedLookupCacheIndex(Map* map, int index) {
+ return ForPropertyIndex(map, index);
+ }
+
+ bool is_inobject() const {
+ return IsInObjectBits::decode(bit_field_);
+ }
+
+ bool is_double() const {
+ return IsDoubleBits::decode(bit_field_);
+ }
+
+ int offset() const {
+ return index() * kPointerSize;
+ }
+
+ int index() const {
+ return IndexBits::decode(bit_field_);
+ }
+
+ int outobject_array_index() const {
+ ASSERT(!is_inobject());
+ return index() - first_inobject_property_offset() / kPointerSize;
+ }
+
+ int property_index() const {
+ ASSERT(!IsHiddenField::decode(bit_field_));
+ int result = index() - first_inobject_property_offset() / kPointerSize;
+ if (!is_inobject()) {
+ result += InObjectPropertyBits::decode(bit_field_);
+ }
+ return result;
+ }
+
+ int GetLoadByFieldIndex() const {
+ // For efficiency, the LoadByFieldIndex instruction takes an index that is
+ // optimized for quick access. If the property is inline, the index is
+ // positive. If it's out-of-line, the encoded index is -raw_index - 1 to
+ // disambiguate the zero out-of-line index from the zero inobject case.
+ // The index itself is shifted up by one bit, the lower-most bit
+ // signifying if the field is a mutable double box (1) or not (0).
+ int result = index() - first_inobject_property_offset() / kPointerSize;
+ if (!is_inobject()) {
+ result = -result - 1;
+ }
+ result <<= 1;
+ return is_double() ? (result | 1) : result;
+ }
+
+ int GetKeyedLookupCacheIndex() const {
+ return property_index();
+ }
+
+ int GetLoadFieldStubKey() const {
+ return bit_field_ &
+ (IsInObjectBits::kMask | IsDoubleBits::kMask | IndexBits::kMask);
+ }
+
+ private:
+ FieldIndex(bool is_inobject, int local_index, bool is_double,
+ int inobject_properties, int first_inobject_property_offset,
+ bool is_hidden = false) {
+ ASSERT((first_inobject_property_offset & (kPointerSize - 1)) == 0);
+ bit_field_ = IsInObjectBits::encode(is_inobject) |
+ IsDoubleBits::encode(is_double) |
+ FirstInobjectPropertyOffsetBits::encode(first_inobject_property_offset) |
+ IsHiddenField::encode(is_hidden) |
+ IndexBits::encode(local_index) |
+ InObjectPropertyBits::encode(inobject_properties);
+ }
+
+ int first_inobject_property_offset() const {
+ ASSERT(!IsHiddenField::decode(bit_field_));
+ return FirstInobjectPropertyOffsetBits::decode(bit_field_);
+ }
+
+ static const int kIndexBitsSize = kDescriptorIndexBitCount + 1;
+
+ class IndexBits: public BitField<int, 0, kIndexBitsSize> {};
+ class IsInObjectBits: public BitField<bool, IndexBits::kNext, 1> {};
+ class IsDoubleBits: public BitField<bool, IsInObjectBits::kNext, 1> {};
+ class InObjectPropertyBits: public BitField<int, IsDoubleBits::kNext,
+ kDescriptorIndexBitCount> {};
+ class FirstInobjectPropertyOffsetBits:
+ public BitField<int, InObjectPropertyBits::kNext, 7> {};
+ class IsHiddenField:
+ public BitField<bool, FirstInobjectPropertyOffsetBits::kNext, 1> {};
+ STATIC_ASSERT(IsHiddenField::kNext <= 32);
+
+ int bit_field_;
+};
+
+} } // namespace v8::internal
+
+#endif
js_obj->GetInObjectPropertyOffset(index));
}
} else {
- Object* value = js_obj->RawFastPropertyAt(index);
+ FieldIndex field_index =
+ FieldIndex::ForDescriptor(js_obj->map(), i);
+ Object* value = js_obj->RawFastPropertyAt(field_index);
if (k != heap_->hidden_string()) {
SetPropertyReference(js_obj, entry, k, value);
} else {
// checks.
ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
- int index = lookup->GetFieldIndex().field_index();
-
- // Adjust for the number of properties stored in the object. Even in the
- // face of a transition we can use the old map here because the size of the
- // object and the number of in-object properties is not going to change.
- index -= object->map()->inobject_properties();
+ FieldIndex index = lookup->GetFieldIndex();
Representation representation = lookup->representation();
ASSERT(!representation.IsNone());
}
} else if (representation.IsDouble()) {
// Load the double storage.
- if (index < 0) {
- int offset = object->map()->instance_size() + (index * kPointerSize);
- __ mov(scratch1, FieldOperand(receiver_reg, offset));
+ if (index.is_inobject()) {
+ __ mov(scratch1, FieldOperand(receiver_reg, index.offset()));
} else {
__ mov(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
- int offset = index * kPointerSize + FixedArray::kHeaderSize;
- __ mov(scratch1, FieldOperand(scratch1, offset));
+ __ mov(scratch1, FieldOperand(scratch1, index.offset()));
}
// Store the value into the storage.
// TODO(verwaest): Share this code as a code stub.
SmiCheck smi_check = representation.IsTagged()
? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
- if (index < 0) {
+ if (index.is_inobject()) {
// Set the property straight into the object.
- int offset = object->map()->instance_size() + (index * kPointerSize);
- __ mov(FieldOperand(receiver_reg, offset), value_reg);
+ __ mov(FieldOperand(receiver_reg, index.offset()), value_reg);
if (!representation.IsSmi()) {
// Update the write barrier for the array address.
// Pass the value being stored in the now unused name_reg.
__ mov(name_reg, value_reg);
__ RecordWriteField(receiver_reg,
- offset,
+ index.offset(),
name_reg,
scratch1,
kDontSaveFPRegs,
}
} else {
// Write to the properties array.
- int offset = index * kPointerSize + FixedArray::kHeaderSize;
// Get the properties array (optimistically).
__ mov(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
- __ mov(FieldOperand(scratch1, offset), value_reg);
+ __ mov(FieldOperand(scratch1, index.offset()), value_reg);
if (!representation.IsSmi()) {
// Update the write barrier for the array address.
// Pass the value being stored in the now unused name_reg.
__ mov(name_reg, value_reg);
__ RecordWriteField(scratch1,
- offset,
+ index.offset(),
name_reg,
receiver_reg,
kDontSaveFPRegs,
void LoadStubCompiler::GenerateLoadField(Register reg,
Handle<JSObject> holder,
- PropertyIndex field,
+ FieldIndex field,
Representation representation) {
if (!reg.is(receiver())) __ mov(receiver(), reg);
if (kind() == Code::LOAD_IC) {
- LoadFieldStub stub(isolate(),
- field.is_inobject(holder),
- field.translate(holder),
- representation);
+ LoadFieldStub stub(isolate(), field);
GenerateTailCall(masm(), stub.GetCode());
} else {
- KeyedLoadFieldStub stub(isolate(),
- field.is_inobject(holder),
- field.translate(holder),
- representation);
+ KeyedLoadFieldStub stub(isolate(), field);
GenerateTailCall(masm(), stub.GetCode());
}
}
}
-Handle<Code> LoadIC::SimpleFieldLoad(int offset,
- bool inobject,
- Representation representation) {
+Handle<Code> LoadIC::SimpleFieldLoad(FieldIndex index) {
if (kind() == Code::LOAD_IC) {
- LoadFieldStub stub(isolate(), inobject, offset, representation);
+ LoadFieldStub stub(isolate(), index);
return stub.GetCode();
} else {
- KeyedLoadFieldStub stub(isolate(), inobject, offset, representation);
+ KeyedLoadFieldStub stub(isolate(), index);
return stub.GetCode();
}
}
InlineCacheHolderFlag cache_holder) {
if (object->IsString() &&
String::Equals(isolate()->factory()->length_string(), name)) {
- int length_index = String::kLengthOffset / kPointerSize;
- return SimpleFieldLoad(length_index);
+ FieldIndex index = FieldIndex::ForInObjectOffset(String::kLengthOffset);
+ return SimpleFieldLoad(index);
}
if (object->IsStringWrapper() &&
switch (lookup->type()) {
case FIELD: {
- PropertyIndex field = lookup->GetFieldIndex();
+ FieldIndex field = lookup->GetFieldIndex();
if (object.is_identical_to(holder)) {
- return SimpleFieldLoad(field.translate(holder),
- field.is_inobject(holder),
- lookup->representation());
+ return SimpleFieldLoad(field);
}
return compiler.CompileLoadField(
type, holder, name, field, lookup->representation());
// Use simple field loads for some well-known callback properties.
if (object->IsJSObject()) {
Handle<JSObject> receiver = Handle<JSObject>::cast(object);
+ Handle<Map> map(receiver->map());
Handle<HeapType> type = IC::MapToType<HeapType>(
handle(receiver->map()), isolate());
int object_offset;
if (Accessors::IsJSObjectFieldAccessor<HeapType>(
type, name, &object_offset)) {
- return SimpleFieldLoad(object_offset / kPointerSize);
+ FieldIndex index = FieldIndex::ForInObjectOffset(
+ object_offset, receiver->map());
+ return SimpleFieldLoad(index);
}
}
return pre_monomorphic_stub(isolate(), extra_ic_state());
}
- Handle<Code> SimpleFieldLoad(int offset,
- bool inobject = true,
- Representation representation =
- Representation::Tagged());
+ Handle<Code> SimpleFieldLoad(FieldIndex index);
static void Clear(Isolate* isolate,
Address address,
int length = properties.length();
for (int i = 0; i < length; i++) {
Handle<Object> value = properties[i];
- json_object->FastPropertyAtPut(i, *value);
+ FieldIndex index = FieldIndex::ForPropertyIndex(*map, i);
+ json_object->FastPropertyAtPut(index, *value);
}
} else {
key = ParseJsonInternalizedString();
int length = properties.length();
for (int i = 0; i < length; i++) {
Handle<Object> value = properties[i];
- json_object->FastPropertyAtPut(i, *value);
+ FieldIndex index = FieldIndex::ForPropertyIndex(*map, i);
+ json_object->FastPropertyAtPut(index, *value);
}
}
}
if (details.IsDontEnum()) continue;
Handle<Object> property;
if (details.type() == FIELD && *map == object->map()) {
- property = Handle<Object>(
- object->RawFastPropertyAt(
- map->instance_descriptors()->GetFieldIndex(i)),
- isolate_);
+ property = Handle<Object>(object->RawFastPropertyAt(
+ FieldIndex::ForDescriptor(*map, i)), isolate_);
} else {
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate_, property,
for (int i = 0; i < map()->NumberOfOwnDescriptors(); i++) {
if (descriptors->GetDetails(i).type() == FIELD) {
Representation r = descriptors->GetDetails(i).representation();
- int field = descriptors->GetFieldIndex(i);
- Object* value = RawFastPropertyAt(field);
+ FieldIndex index = FieldIndex::ForDescriptor(map(), i);
+ Object* value = RawFastPropertyAt(index);
if (r.IsDouble()) ASSERT(value->IsHeapNumber());
if (value->IsUninitialized()) continue;
if (r.IsSmi()) ASSERT(value->IsSmi());
#include "src/objects.h"
#include "src/contexts.h"
#include "src/conversions-inl.h"
+#include "src/field-index-inl.h"
#include "src/heap.h"
#include "src/isolate.h"
#include "src/heap-inl.h"
// Access fast-case object properties at index. The use of these routines
// is needed to correctly distinguish between properties stored in-object and
// properties stored in the properties array.
-Object* JSObject::RawFastPropertyAt(int index) {
- // Adjust for the number of properties stored in the object.
- index -= map()->inobject_properties();
- if (index < 0) {
- int offset = map()->instance_size() + (index * kPointerSize);
- return READ_FIELD(this, offset);
+Object* JSObject::RawFastPropertyAt(FieldIndex index) {
+ if (index.is_inobject()) {
+ return READ_FIELD(this, index.offset());
} else {
- ASSERT(index < properties()->length());
- return properties()->get(index);
+ return properties()->get(index.outobject_array_index());
}
}
-void JSObject::FastPropertyAtPut(int index, Object* value) {
- // Adjust for the number of properties stored in the object.
- index -= map()->inobject_properties();
- if (index < 0) {
- int offset = map()->instance_size() + (index * kPointerSize);
+void JSObject::FastPropertyAtPut(FieldIndex index, Object* value) {
+ if (index.is_inobject()) {
+ int offset = index.offset();
WRITE_FIELD(this, offset, value);
WRITE_BARRIER(GetHeap(), this, offset, value);
} else {
- ASSERT(index < properties()->length());
- properties()->set(index, value);
+ properties()->set(index.outobject_array_index(), value);
}
}
int Map::GetInObjectPropertyOffset(int index) {
// Adjust for the number of properties stored in the object.
index -= inobject_properties();
- ASSERT(index < 0);
+ ASSERT(index <= 0);
return instance_size() + (index * kPointerSize);
}
PrintF(out, ": ");
switch (descs->GetType(i)) {
case FIELD: {
- int index = descs->GetFieldIndex(i);
+ FieldIndex index = FieldIndex::ForDescriptor(map(), i);
RawFastPropertyAt(index)->ShortPrint(out);
- PrintF(out, " (field at offset %d)\n", index);
+ PrintF(out, " (field at offset %d)\n", index.property_index());
break;
}
case CONSTANT:
#include "src/date.h"
#include "src/elements.h"
#include "src/execution.h"
+#include "src/field-index.h"
+#include "src/field-index-inl.h"
#include "src/full-codegen.h"
#include "src/hydrogen.h"
#include "src/isolate-inl.h"
}
case FIELD:
value = JSObject::FastPropertyAt(handle(result->holder(), isolate),
- result->representation(),
- result->GetFieldIndex().field_index());
+ result->representation(), FieldIndex::ForLookupResult(result));
break;
case CONSTANT:
return handle(result->GetConstant(), isolate);
old_details.type() == FIELD);
Object* raw_value = old_details.type() == CONSTANT
? old_descriptors->GetValue(i)
- : object->RawFastPropertyAt(old_descriptors->GetFieldIndex(i));
+ : object->RawFastPropertyAt(FieldIndex::ForDescriptor(*old_map, i));
Handle<Object> value(raw_value, isolate);
if (!old_details.representation().IsDouble() &&
details.representation().IsDouble()) {
// avoid overwriting |one_pointer_filler_map|.
int limit = Min(inobject, number_of_fields);
for (int i = 0; i < limit; i++) {
- object->FastPropertyAtPut(i, array->get(external + i));
+ FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
+ object->FastPropertyAtPut(index, array->get(external + i));
}
// Create filler object past the new instance size.
// occur as fields.
if (result->IsField() &&
result->IsReadOnly() &&
- RawFastPropertyAt(result->GetFieldIndex().field_index())->IsTheHole()) {
+ RawFastPropertyAt(result->GetFieldIndex())->IsTheHole()) {
result->DisallowCaching();
}
return;
ASSERT(details.type() == FIELD);
- int field_index = desc->GetFieldIndex(descriptor);
+ FieldIndex index = FieldIndex::ForDescriptor(map(), descriptor);
if (details.representation().IsDouble()) {
// Nothing more to be done.
if (value->IsUninitialized()) return;
- HeapNumber* box = HeapNumber::cast(RawFastPropertyAt(field_index));
+ HeapNumber* box = HeapNumber::cast(RawFastPropertyAt(index));
box->set_value(value->Number());
} else {
- FastPropertyAtPut(field_index, value);
+ FastPropertyAtPut(index, value);
}
}
}
case FIELD: {
Handle<Name> key(descs->GetKey(i));
+ FieldIndex index = FieldIndex::ForDescriptor(*map, i);
Handle<Object> value(
- object->RawFastPropertyAt(descs->GetFieldIndex(i)), isolate);
+ object->RawFastPropertyAt(index), isolate);
PropertyDetails d =
PropertyDetails(details.attributes(), NORMAL, i + 1);
dictionary = NameDictionary::Add(dictionary, key, value, d);
ASSERT(descriptors->GetType(sorted_index) == FIELD);
ASSERT(descriptors->GetDetails(sorted_index).representation().
IsCompatibleForLoad(Representation::Tagged()));
- return this->RawFastPropertyAt(
- descriptors->GetFieldIndex(sorted_index));
+ FieldIndex index = FieldIndex::ForDescriptor(this->map(),
+ sorted_index);
+ return this->RawFastPropertyAt(index);
} else {
return GetHeap()->undefined_value();
}
Handle<Object> JSObject::FastPropertyAt(Handle<JSObject> object,
Representation representation,
- int index) {
+ FieldIndex index) {
Isolate* isolate = object->GetIsolate();
Handle<Object> raw_value(object->RawFastPropertyAt(index), isolate);
return Object::NewStorageFor(isolate, raw_value, representation);
for (int i = 0; i < limit; i++) {
PropertyDetails details = descriptors->GetDetails(i);
if (details.type() != FIELD) continue;
- int index = descriptors->GetFieldIndex(i);
+ FieldIndex index = FieldIndex::ForDescriptor(copy->map(), i);
Handle<Object> value(object->RawFastPropertyAt(index), isolate);
if (value->IsJSObject()) {
ASSIGN_RETURN_ON_EXCEPTION(
case FIELD:
result = FastPropertyAt(Handle<JSObject>(lookup.holder(), isolate),
lookup.representation(),
- lookup.GetFieldIndex().field_index());
+ lookup.GetFieldIndex());
break;
case CONSTANT:
result = Handle<Object>(lookup.GetConstant(), isolate);
if (details.type() != FIELD) {
indices = Handle<FixedArray>();
} else {
- int field_index = descs->GetFieldIndex(i);
- if (field_index >= map->inobject_properties()) {
- field_index = -(field_index - map->inobject_properties() + 1);
- }
- field_index = field_index << 1;
- if (details.representation().IsDouble()) {
- field_index |= 1;
- }
- indices->set(index, Smi::FromInt(field_index));
+ FieldIndex field_index = FieldIndex::ForDescriptor(*map, i);
+ int load_by_field_index = field_index.GetLoadByFieldIndex();
+ indices->set(index, Smi::FromInt(load_by_field_index));
}
}
index++;
DescriptorArray* descs = map()->instance_descriptors();
for (int i = 0; i < number_of_own_descriptors; i++) {
if (descs->GetType(i) == FIELD) {
- Object* property = RawFastPropertyAt(descs->GetFieldIndex(i));
+ Object* property =
+ RawFastPropertyAt(FieldIndex::ForDescriptor(map(), i));
if (descs->GetDetails(i).representation().IsDouble()) {
ASSERT(property->IsHeapNumber());
if (value->IsNumber() && property->Number() == value->Number()) {
#include "src/assert-scope.h"
#include "src/builtins.h"
#include "src/elements-kind.h"
+#include "src/field-index.h"
#include "src/flags.h"
#include "src/list.h"
#include "src/property-details.h"
// Access fast-case object properties at index.
static Handle<Object> FastPropertyAt(Handle<JSObject> object,
Representation representation,
- int index);
- inline Object* RawFastPropertyAt(int index);
- inline void FastPropertyAtPut(int index, Object* value);
+ FieldIndex index);
+ inline Object* RawFastPropertyAt(FieldIndex index);
+ inline void FastPropertyAtPut(FieldIndex index, Object* value);
void WriteToField(int descriptor, Object* value);
// Access to in object properties.
break;
case FIELD:
PrintF(out, " -type = field\n");
- PrintF(out, " -index = %d\n", GetFieldIndex().field_index());
+ PrintF(out, " -index = %d\n",
+ GetFieldIndex().property_index());
PrintF(out, " -field type:\n");
GetFieldType()->TypePrint(out);
break;
#include "src/isolate.h"
#include "src/factory.h"
+#include "src/field-index.h"
+#include "src/field-index-inl.h"
#include "src/types.h"
namespace v8 {
};
-// Holds a property index value distinguishing if it is a field index or an
-// index inside the object header.
-class PropertyIndex V8_FINAL {
- public:
- static PropertyIndex NewFieldIndex(int index) {
- return PropertyIndex(index, false);
- }
- static PropertyIndex NewHeaderIndex(int index) {
- return PropertyIndex(index, true);
- }
-
- bool is_field_index() { return (index_ & kHeaderIndexBit) == 0; }
- bool is_header_index() { return (index_ & kHeaderIndexBit) != 0; }
-
- int field_index() {
- ASSERT(is_field_index());
- return value();
- }
- int header_index() {
- ASSERT(is_header_index());
- return value();
- }
-
- bool is_inobject(Handle<JSObject> holder) {
- if (is_header_index()) return true;
- return field_index() < holder->map()->inobject_properties();
- }
-
- int translate(Handle<JSObject> holder) {
- if (is_header_index()) return header_index();
- int index = field_index() - holder->map()->inobject_properties();
- if (index >= 0) return index;
- return index + holder->map()->instance_size() / kPointerSize;
- }
-
- private:
- static const int kHeaderIndexBit = 1 << 31;
- static const int kIndexMask = ~kHeaderIndexBit;
-
- int value() { return index_ & kIndexMask; }
-
- PropertyIndex(int index, bool is_header_based)
- : index_(index | (is_header_based ? kHeaderIndexBit : 0)) {
- ASSERT(index <= kIndexMask);
- }
-
- int index_;
-};
-
-
class LookupResult V8_FINAL BASE_EMBEDDED {
public:
explicit LookupResult(Isolate* isolate)
case DICTIONARY_TYPE:
switch (type()) {
case FIELD:
- return holder()->RawFastPropertyAt(GetFieldIndex().field_index());
+ return holder()->RawFastPropertyAt(GetFieldIndex());
case NORMAL: {
Object* value = holder()->property_dictionary()->ValueAt(
GetDictionaryEntry());
return number_;
}
- PropertyIndex GetFieldIndex() const {
+ FieldIndex GetFieldIndex() const {
ASSERT(lookup_type_ == DESCRIPTOR_TYPE ||
lookup_type_ == TRANSITION_TYPE);
- return PropertyIndex::NewFieldIndex(GetFieldIndexFromMap(holder()->map()));
+ return FieldIndex::ForLookupResult(this);
}
int GetLocalFieldIndexFromMap(Map* map) const {
// Strict mode handling not needed (const is disallowed in strict mode).
if (lookup.IsField()) {
FixedArray* properties = global->properties();
- int index = lookup.GetFieldIndex().field_index();
+ int index = lookup.GetFieldIndex().outobject_array_index();
if (properties->get(index)->IsTheHole() || !lookup.IsReadOnly()) {
properties->set(index, *value);
}
if (lookup.IsField()) {
FixedArray* properties = object->properties();
- int index = lookup.GetFieldIndex().field_index();
- if (properties->get(index)->IsTheHole()) {
- properties->set(index, *value);
+ FieldIndex index = lookup.GetFieldIndex();
+ ASSERT(!index.is_inobject());
+ if (properties->get(index.outobject_array_index())->IsTheHole()) {
+ properties->set(index.outobject_array_index(), *value);
}
} else if (lookup.IsNormal()) {
if (object->GetNormalizedProperty(&lookup)->IsTheHole()) {
// Attempt to use lookup cache.
Handle<Map> receiver_map(receiver->map(), isolate);
KeyedLookupCache* keyed_lookup_cache = isolate->keyed_lookup_cache();
- int offset = keyed_lookup_cache->Lookup(receiver_map, key);
- if (offset != -1) {
+ int index = keyed_lookup_cache->Lookup(receiver_map, key);
+ if (index != -1) {
// Doubles are not cached, so raw read the value.
- Object* value = receiver->RawFastPropertyAt(offset);
+ Object* value = receiver->RawFastPropertyAt(
+ FieldIndex::ForKeyedLookupCacheIndex(*receiver_map, index));
return value->IsTheHole()
? isolate->heap()->undefined_value()
: value;
LookupResult result(isolate);
receiver->LookupOwn(key, &result);
if (result.IsField()) {
- int offset = result.GetFieldIndex().field_index();
+ FieldIndex field_index = result.GetFieldIndex();
// Do not track double fields in the keyed lookup cache. Reading
// double values requires boxing.
if (!result.representation().IsDouble()) {
- keyed_lookup_cache->Update(receiver_map, key, offset);
+ keyed_lookup_cache->Update(receiver_map, key,
+ field_index.GetKeyedLookupCacheIndex());
}
AllowHeapAllocation allow_allocation;
- return *JSObject::FastPropertyAt(
- receiver, result.representation(), offset);
+ return *JSObject::FastPropertyAt(receiver, result.representation(),
+ field_index);
}
} else {
// Attempt dictionary lookup.
case FIELD:
value = JSObject::FastPropertyAt(handle(result->holder(), isolate),
result->representation(),
- result->GetFieldIndex().field_index());
+ result->GetFieldIndex());
break;
case CONSTANT:
return handle(result->GetConstant(), isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
CONVERT_ARG_HANDLE_CHECKED(Smi, index, 1);
- int idx = index->value() >> 1;
- int inobject_properties = object->map()->inobject_properties();
- if (idx < 0) {
- idx = -idx + inobject_properties - 1;
- }
- int max_idx = object->properties()->length() + inobject_properties;
- RUNTIME_ASSERT(idx < max_idx);
- Handle<Object> raw_value(object->RawFastPropertyAt(idx), isolate);
+ RUNTIME_ASSERT((index->value() & 1) == 1);
+ FieldIndex field_index =
+ FieldIndex::ForLoadByFieldIndex(object->map(), index->value() >> 1);
+ if (field_index.is_inobject()) {
+ RUNTIME_ASSERT(field_index.property_index() <
+ object->map()->inobject_properties());
+ } else {
+ RUNTIME_ASSERT(field_index.outobject_array_index() <
+ object->properties()->length());
+ }
+ Handle<Object> raw_value(object->RawFastPropertyAt(field_index), isolate);
RUNTIME_ASSERT(raw_value->IsNumber() || raw_value->IsUninitialized());
return *Object::NewStorageFor(isolate, raw_value, Representation::Double());
}
key->ShortPrint();
}
Add(": ");
- Object* value = js_object->RawFastPropertyAt(descs->GetFieldIndex(i));
+ FieldIndex index = FieldIndex::ForDescriptor(map, i);
+ Object* value = js_object->RawFastPropertyAt(index);
Add("%o\n", value);
}
}
Handle<HeapType> type,
Handle<JSObject> holder,
Handle<Name> name,
- PropertyIndex field,
+ FieldIndex field,
Representation representation) {
Register reg = HandlerFrontend(type, receiver(), holder, name);
GenerateLoadField(reg, holder, field, representation);
LookupResult* lookup) {
Handle<JSObject> holder(lookup->holder());
if (lookup->IsField()) {
- PropertyIndex field = lookup->GetFieldIndex();
+ FieldIndex field = lookup->GetFieldIndex();
if (interceptor_holder.is_identical_to(holder)) {
GenerateLoadField(
interceptor_reg, holder, field, lookup->representation());
Handle<Code> CompileLoadField(Handle<HeapType> type,
Handle<JSObject> holder,
Handle<Name> name,
- PropertyIndex index,
+ FieldIndex index,
Representation representation);
Handle<Code> CompileLoadCallback(Handle<HeapType> type,
void GenerateLoadField(Register reg,
Handle<JSObject> holder,
- PropertyIndex field,
+ FieldIndex field,
Representation representation);
void GenerateLoadConstant(Handle<Object> value);
void GenerateLoadCallback(Register reg,
static const U kMask = ((kOne << shift) << size) - (kOne << shift);
static const U kShift = shift;
static const U kSize = size;
+ static const U kNext = kShift + kSize;
// Value for the field with all bits set.
static const T kMax = static_cast<T>((1U << size) - 1);
// checks.
ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
- int index = lookup->GetFieldIndex().field_index();
-
- // Adjust for the number of properties stored in the object. Even in the
- // face of a transition we can use the old map here because the size of the
- // object and the number of in-object properties is not going to change.
- index -= object->map()->inobject_properties();
+ FieldIndex index = lookup->GetFieldIndex();
Representation representation = lookup->representation();
ASSERT(!representation.IsNone());
}
} else if (representation.IsDouble()) {
// Load the double storage.
- if (index < 0) {
- int offset = object->map()->instance_size() + (index * kPointerSize);
- __ movp(scratch1, FieldOperand(receiver_reg, offset));
+ if (index.is_inobject()) {
+ __ movp(scratch1, FieldOperand(receiver_reg, index.offset()));
} else {
__ movp(scratch1,
FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
- int offset = index * kPointerSize + FixedArray::kHeaderSize;
- __ movp(scratch1, FieldOperand(scratch1, offset));
+ __ movp(scratch1, FieldOperand(scratch1, index.offset()));
}
// Store the value into the storage.
// TODO(verwaest): Share this code as a code stub.
SmiCheck smi_check = representation.IsTagged()
? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
- if (index < 0) {
+ if (index.is_inobject()) {
// Set the property straight into the object.
- int offset = object->map()->instance_size() + (index * kPointerSize);
- __ movp(FieldOperand(receiver_reg, offset), value_reg);
+ __ movp(FieldOperand(receiver_reg, index.offset()), value_reg);
if (!representation.IsSmi()) {
// Update the write barrier for the array address.
// Pass the value being stored in the now unused name_reg.
__ movp(name_reg, value_reg);
__ RecordWriteField(
- receiver_reg, offset, name_reg, scratch1, kDontSaveFPRegs,
+ receiver_reg, index.offset(), name_reg, scratch1, kDontSaveFPRegs,
EMIT_REMEMBERED_SET, smi_check);
}
} else {
// Write to the properties array.
- int offset = index * kPointerSize + FixedArray::kHeaderSize;
// Get the properties array (optimistically).
__ movp(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
- __ movp(FieldOperand(scratch1, offset), value_reg);
+ __ movp(FieldOperand(scratch1, index.offset()), value_reg);
if (!representation.IsSmi()) {
// Update the write barrier for the array address.
// Pass the value being stored in the now unused name_reg.
__ movp(name_reg, value_reg);
__ RecordWriteField(
- scratch1, offset, name_reg, receiver_reg, kDontSaveFPRegs,
+ scratch1, index.offset(), name_reg, receiver_reg, kDontSaveFPRegs,
EMIT_REMEMBERED_SET, smi_check);
}
}
void LoadStubCompiler::GenerateLoadField(Register reg,
Handle<JSObject> holder,
- PropertyIndex field,
+ FieldIndex field,
Representation representation) {
if (!reg.is(receiver())) __ movp(receiver(), reg);
if (kind() == Code::LOAD_IC) {
- LoadFieldStub stub(isolate(),
- field.is_inobject(holder),
- field.translate(holder),
- representation);
+ LoadFieldStub stub(isolate(), field);
GenerateTailCall(masm(), stub.GetCode());
} else {
- KeyedLoadFieldStub stub(isolate(),
- field.is_inobject(holder),
- field.translate(holder),
- representation);
+ KeyedLoadFieldStub stub(isolate(), field);
GenerateTailCall(masm(), stub.GetCode());
}
}
CHECK_EQ(0, FixedArray::cast(jsobject->elements())->length());
CHECK_EQ(0, jsobject->properties()->length());
// Create a reference to object in new space in jsobject.
- jsobject->FastPropertyAtPut(-1, array);
+ FieldIndex index = FieldIndex::ForInObjectOffset(
+ JSObject::kHeaderSize - kPointerSize);
+ jsobject->FastPropertyAtPut(index, array);
CHECK_EQ(0, static_cast<int>(*limit_addr - *top_addr));
v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(res));
CHECK(CcTest::heap()->InOldPointerSpace(*o));
- CHECK(CcTest::heap()->InOldPointerSpace(o->RawFastPropertyAt(0)));
- CHECK(CcTest::heap()->InOldDataSpace(o->RawFastPropertyAt(1)));
+ FieldIndex idx1 = FieldIndex::ForPropertyIndex(o->map(), 0);
+ FieldIndex idx2 = FieldIndex::ForPropertyIndex(o->map(), 1);
+ CHECK(CcTest::heap()->InOldPointerSpace(o->RawFastPropertyAt(idx1)));
+ CHECK(CcTest::heap()->InOldDataSpace(o->RawFastPropertyAt(idx2)));
- JSObject* inner_object = reinterpret_cast<JSObject*>(o->RawFastPropertyAt(0));
+ JSObject* inner_object =
+ reinterpret_cast<JSObject*>(o->RawFastPropertyAt(idx1));
CHECK(CcTest::heap()->InOldPointerSpace(inner_object));
- CHECK(CcTest::heap()->InOldDataSpace(inner_object->RawFastPropertyAt(0)));
- CHECK(CcTest::heap()->InOldPointerSpace(inner_object->RawFastPropertyAt(1)));
+ CHECK(CcTest::heap()->InOldDataSpace(inner_object->RawFastPropertyAt(idx1)));
+ CHECK(CcTest::heap()->InOldPointerSpace(
+ inner_object->RawFastPropertyAt(idx2)));
}
CHECK(value->Equals(obj->GetHiddenValue(v8_str("key string"))));
// Check size.
- DescriptorArray* descriptors = internal_obj->map()->instance_descriptors();
+ FieldIndex index = FieldIndex::ForDescriptor(internal_obj->map(), 0);
ObjectHashTable* hashtable = ObjectHashTable::cast(
- internal_obj->RawFastPropertyAt(descriptors->GetFieldIndex(0)));
+ internal_obj->RawFastPropertyAt(index));
// HashTable header (5) and 4 initial entries (8).
CHECK_LE(hashtable->SizeFor(hashtable->length()), 13 * kPointerSize);
}
'../../src/fast-dtoa.cc',
'../../src/fast-dtoa.h',
'../../src/feedback-slots.h',
+ '../../src/field-index.cc',
+ '../../src/field-index.h',
+ '../../src/field-index-inl.h',
'../../src/fixed-dtoa.cc',
'../../src/fixed-dtoa.h',
'../../src/flag-definitions.h',