// We got a map in register r0. Get the enumeration cache from it.
__ bind(&use_cache);
__ LoadInstanceDescriptors(r0, r1, r2);
- __ ldr(r1, FieldMemOperand(r1, DescriptorArray::kEnumerationIndexOffset));
+ __ ldr(r1, FieldMemOperand(r1, DescriptorArray::kLastAddedOffset));
__ ldr(r2, FieldMemOperand(r1, DescriptorArray::kEnumCacheBridgeCacheOffset));
// Set up the four remaining stack slots.
Register scratch = ToRegister(instr->scratch());
__ LoadInstanceDescriptors(map, result, scratch);
__ ldr(result,
- FieldMemOperand(result, DescriptorArray::kEnumerationIndexOffset));
+ FieldMemOperand(result, DescriptorArray::kLastAddedOffset));
__ ldr(result,
FieldMemOperand(result, FixedArray::SizeFor(instr->idx())));
__ cmp(result, Operand(0));
// Check that there is an enum cache in the non-empty instance
// descriptors (r3). This is the case if the next enumeration
// index field does not contain a smi.
- ldr(r3, FieldMemOperand(r3, DescriptorArray::kEnumerationIndexOffset));
+ ldr(r3, FieldMemOperand(r3, DescriptorArray::kLastAddedOffset));
JumpIfSmi(r3, call_runtime);
// For all objects but the receiver, check that the cache is empty.
DescriptorArray::WhitenessWitness witness(*descriptors);
+ int index = 0;
+
{ // Add length.
Handle<Foreign> f(factory()->NewForeign(&Accessors::FunctionLength));
- CallbacksDescriptor d(*factory()->length_symbol(), *f, attribs);
- descriptors->Set(0, &d, witness);
+ CallbacksDescriptor d(*factory()->length_symbol(), *f, attribs, index + 1);
+ descriptors->Set(index, &d, witness);
+ ++index;
}
{ // Add name.
Handle<Foreign> f(factory()->NewForeign(&Accessors::FunctionName));
- CallbacksDescriptor d(*factory()->name_symbol(), *f, attribs);
- descriptors->Set(1, &d, witness);
+ CallbacksDescriptor d(*factory()->name_symbol(), *f, attribs, index + 1);
+ descriptors->Set(index, &d, witness);
+ ++index;
}
{ // Add arguments.
Handle<Foreign> f(factory()->NewForeign(&Accessors::FunctionArguments));
- CallbacksDescriptor d(*factory()->arguments_symbol(), *f, attribs);
- descriptors->Set(2, &d, witness);
+ CallbacksDescriptor d(
+ *factory()->arguments_symbol(), *f, attribs, index + 1);
+ descriptors->Set(index, &d, witness);
+ ++index;
}
{ // Add caller.
Handle<Foreign> f(factory()->NewForeign(&Accessors::FunctionCaller));
- CallbacksDescriptor d(*factory()->caller_symbol(), *f, attribs);
- descriptors->Set(3, &d, witness);
+ CallbacksDescriptor d(*factory()->caller_symbol(), *f, attribs, index + 1);
+ descriptors->Set(index, &d, witness);
+ ++index;
}
if (prototypeMode != DONT_ADD_PROTOTYPE) {
// Add prototype.
attribs = static_cast<PropertyAttributes>(attribs & ~READ_ONLY);
}
Handle<Foreign> f(factory()->NewForeign(&Accessors::FunctionPrototype));
- CallbacksDescriptor d(*factory()->prototype_symbol(), *f, attribs);
- descriptors->Set(4, &d, witness);
+ CallbacksDescriptor d(
+ *factory()->prototype_symbol(), *f, attribs, index + 1);
+ descriptors->Set(index, &d, witness);
}
+
descriptors->Sort(witness);
return descriptors;
}
DescriptorArray::WhitenessWitness witness(*descriptors);
+ int index = 0;
{ // Add length.
Handle<Foreign> f(factory()->NewForeign(&Accessors::FunctionLength));
- CallbacksDescriptor d(*factory()->length_symbol(), *f, attribs);
- descriptors->Set(0, &d, witness);
+ CallbacksDescriptor d(*factory()->length_symbol(), *f, attribs, index + 1);
+ descriptors->Set(index, &d, witness);
+ ++index;
}
{ // Add name.
Handle<Foreign> f(factory()->NewForeign(&Accessors::FunctionName));
- CallbacksDescriptor d(*factory()->name_symbol(), *f, attribs);
- descriptors->Set(1, &d, witness);
+ CallbacksDescriptor d(*factory()->name_symbol(), *f, attribs, index + 1);
+ descriptors->Set(index, &d, witness);
+ ++index;
}
{ // Add arguments.
Handle<AccessorPair> arguments(factory()->NewAccessorPair());
- CallbacksDescriptor d(*factory()->arguments_symbol(), *arguments, attribs);
- descriptors->Set(2, &d, witness);
+ CallbacksDescriptor d(
+ *factory()->arguments_symbol(), *arguments, attribs, index + 1);
+ descriptors->Set(index, &d, witness);
+ ++index;
}
{ // Add caller.
Handle<AccessorPair> caller(factory()->NewAccessorPair());
- CallbacksDescriptor d(*factory()->caller_symbol(), *caller, attribs);
- descriptors->Set(3, &d, witness);
+ CallbacksDescriptor d(
+ *factory()->caller_symbol(), *caller, attribs, index + 1);
+ descriptors->Set(index, &d, witness);
+ ++index;
}
if (prototypeMode != DONT_ADD_PROTOTYPE) {
attribs = static_cast<PropertyAttributes>(attribs | READ_ONLY);
}
Handle<Foreign> f(factory()->NewForeign(&Accessors::FunctionPrototype));
- CallbacksDescriptor d(*factory()->prototype_symbol(), *f, attribs);
- descriptors->Set(4, &d, witness);
+ CallbacksDescriptor d(
+ *factory()->prototype_symbol(), *f, attribs, index + 1);
+ descriptors->Set(index, &d, witness);
}
descriptors->Sort(witness);
DescriptorArray::WhitenessWitness witness(*descriptors);
PropertyAttributes final =
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
- int enum_index = 0;
+ int index = 0;
{
// ECMA-262, section 15.10.7.1.
FieldDescriptor field(heap->source_symbol(),
JSRegExp::kSourceFieldIndex,
final,
- enum_index++);
- descriptors->Set(0, &field, witness);
+ index + 1);
+ descriptors->Set(index, &field, witness);
+ ++index;
}
{
// ECMA-262, section 15.10.7.2.
FieldDescriptor field(heap->global_symbol(),
JSRegExp::kGlobalFieldIndex,
final,
- enum_index++);
- descriptors->Set(1, &field, witness);
+ index + 1);
+ descriptors->Set(index, &field, witness);
+ ++index;
}
{
// ECMA-262, section 15.10.7.3.
FieldDescriptor field(heap->ignore_case_symbol(),
JSRegExp::kIgnoreCaseFieldIndex,
final,
- enum_index++);
- descriptors->Set(2, &field, witness);
+ index + 1);
+ descriptors->Set(index, &field, witness);
+ ++index;
}
{
// ECMA-262, section 15.10.7.4.
FieldDescriptor field(heap->multiline_symbol(),
JSRegExp::kMultilineFieldIndex,
final,
- enum_index++);
- descriptors->Set(3, &field, witness);
+ index + 1);
+ descriptors->Set(index, &field, witness);
+ ++index;
}
{
// ECMA-262, section 15.10.7.5.
FieldDescriptor field(heap->last_index_symbol(),
JSRegExp::kLastIndexFieldIndex,
writable,
- enum_index++);
- descriptors->Set(4, &field, witness);
+ index + 1);
+ descriptors->Set(index, &field, witness);
}
- descriptors->SetNextEnumerationIndex(enum_index);
descriptors->Sort(witness);
initial_map->set_inobject_properties(5);
// Create the descriptor array for the arguments object.
Handle<DescriptorArray> descriptors = factory->NewDescriptorArray(3);
DescriptorArray::WhitenessWitness witness(*descriptors);
+ int index = 0;
{ // length
- FieldDescriptor d(*factory->length_symbol(), 0, DONT_ENUM);
- descriptors->Set(0, &d, witness);
+ FieldDescriptor d(*factory->length_symbol(), 0, DONT_ENUM, index + 1);
+ descriptors->Set(index, &d, witness);
+ ++index;
}
{ // callee
- CallbacksDescriptor d(*factory->callee_symbol(), *callee, attributes);
- descriptors->Set(1, &d, witness);
+ CallbacksDescriptor d(*factory->callee_symbol(),
+ *callee,
+ attributes,
+ index + 1);
+ descriptors->Set(index, &d, witness);
+ ++index;
}
{ // caller
- CallbacksDescriptor d(*factory->caller_symbol(), *caller, attributes);
- descriptors->Set(2, &d, witness);
+ CallbacksDescriptor d(*factory->caller_symbol(),
+ *caller,
+ attributes,
+ index + 1);
+ descriptors->Set(index, &d, witness);
}
descriptors->Sort(witness);
JSFunction* array_function = global_context()->array_function();
Handle<DescriptorArray> array_descriptors(
array_function->initial_map()->instance_descriptors());
- int index = array_descriptors->SearchWithCache(heap()->length_symbol());
+ int old = array_descriptors->SearchWithCache(heap()->length_symbol());
MaybeObject* copy_result =
- reresult_descriptors->CopyFrom(0, *array_descriptors, index, witness);
+ reresult_descriptors->CopyFrom(0, *array_descriptors, old, witness);
if (copy_result->IsFailure()) return false;
- int enum_index = 0;
+ int index = 1;
{
FieldDescriptor index_field(heap()->index_symbol(),
JSRegExpResult::kIndexIndex,
NONE,
- enum_index++);
- reresult_descriptors->Set(1, &index_field, witness);
+ index + 1);
+ reresult_descriptors->Set(index, &index_field, witness);
+ ++index;
}
{
FieldDescriptor input_field(heap()->input_symbol(),
JSRegExpResult::kInputIndex,
NONE,
- enum_index++);
- reresult_descriptors->Set(2, &input_field, witness);
+ index + 1);
+ reresult_descriptors->Set(index, &input_field, witness);
}
reresult_descriptors->Sort(witness);
String* key,
Object* value,
PropertyAttributes attributes) {
- CallbacksDescriptor desc(key, value, attributes);
+ CallbacksDescriptor desc(key, value, attributes, 0);
MaybeObject* obj = array->CopyInsert(&desc);
return obj;
}
// Fill in new callback descriptors. Process the callbacks from
// back to front so that the last callback with a given name takes
// precedence over previously added callbacks with that name.
+ int added_descriptor_count = descriptor_count;
+ int next_enum = array->NextEnumerationIndex();
for (int i = nof_callbacks - 1; i >= 0; i--) {
Handle<AccessorInfo> entry =
Handle<AccessorInfo>(AccessorInfo::cast(callbacks.get(i)));
Handle<String> key =
SymbolFromString(Handle<String>(String::cast(entry->name())));
// Check if a descriptor with this name already exists before writing.
- if (LinearSearch(*result, EXPECT_UNSORTED, *key, descriptor_count) ==
+ if (LinearSearch(*result, EXPECT_UNSORTED, *key, added_descriptor_count) ==
DescriptorArray::kNotFound) {
- CallbacksDescriptor desc(*key, *entry, entry->property_attributes());
- result->Set(descriptor_count, &desc, witness);
- descriptor_count++;
+ CallbacksDescriptor desc(*key,
+ *entry,
+ entry->property_attributes(),
+ next_enum++);
+ result->Set(added_descriptor_count, &desc, witness);
+ added_descriptor_count++;
}
}
+ // Return the old descriptor array if there were no new elements.
+ if (added_descriptor_count == descriptor_count) return array;
+
// If duplicates were detected, allocate a result of the right size
// and transfer the elements.
- if (descriptor_count < result->length()) {
- Handle<DescriptorArray> new_result = NewDescriptorArray(descriptor_count);
- for (int i = 0; i < descriptor_count; i++) {
+ if (added_descriptor_count < result->length()) {
+ Handle<DescriptorArray> new_result =
+ NewDescriptorArray(added_descriptor_count);
+ for (int i = 0; i < added_descriptor_count; i++) {
DescriptorArray::CopyFrom(new_result, i, result, i, witness);
}
result = new_result;
// Sort the result before returning.
result->Sort(witness);
+ ASSERT(result->NextEnumerationIndex() == next_enum);
return result;
}
for (int i = 0; i < count; i++) {
String* name = fun->shared()->GetThisPropertyAssignmentName(i);
ASSERT(name->IsSymbol());
- FieldDescriptor field(name, i, NONE);
- field.SetEnumerationIndex(i);
+ FieldDescriptor field(name, i, NONE, i + 1);
descriptors->Set(i, &field, witness);
}
- descriptors->SetNextEnumerationIndex(count);
descriptors->SortUnchecked(witness);
// The descriptors may contain duplicates because the compiler does not
// We got a map in register eax. Get the enumeration cache from it.
__ bind(&use_cache);
__ LoadInstanceDescriptors(eax, ecx);
- __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumerationIndexOffset));
+ __ mov(ecx, FieldOperand(ecx, DescriptorArray::kLastAddedOffset));
__ mov(edx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset));
// Set up the four remaining stack slots.
Register result = ToRegister(instr->result());
__ LoadInstanceDescriptors(map, result);
__ mov(result,
- FieldOperand(result, DescriptorArray::kEnumerationIndexOffset));
+ FieldOperand(result, DescriptorArray::kLastAddedOffset));
__ mov(result,
FieldOperand(result, FixedArray::SizeFor(instr->idx())));
__ test(result, result);
// Check that there is an enum cache in the non-empty instance
// descriptors (edx). This is the case if the next enumeration
// index field does not contain a smi.
- mov(edx, FieldOperand(edx, DescriptorArray::kEnumerationIndexOffset));
+ mov(edx, FieldOperand(edx, DescriptorArray::kLastAddedOffset));
JumpIfSmi(edx, call_runtime);
// For all objects but the receiver, check that the cache is empty.
Handle<Map> transition(Map::cast(value));
DescriptorArray* target_descriptors = transition->instance_descriptors();
- int descriptor = target_descriptors->SearchWithCache(*name);
- ASSERT(descriptor != DescriptorArray::kNotFound);
+ int descriptor = target_descriptors->LastAdded();
PropertyDetails details = target_descriptors->GetDetails(descriptor);
if (details.type() != FIELD || details.attributes() != NONE) return;
Handle<Map> transition(Map::cast(value));
DescriptorArray* target_descriptors = transition->instance_descriptors();
- int descriptor = target_descriptors->SearchWithCache(*name);
- ASSERT(descriptor != DescriptorArray::kNotFound);
+ int descriptor = target_descriptors->LastAdded();
PropertyDetails details = target_descriptors->GetDetails(descriptor);
if (details.type() == FIELD && details.attributes() == NONE) {
const WhitenessWitness&) {
// Range check.
ASSERT(descriptor_number < number_of_descriptors());
+ ASSERT(desc->GetDetails().index() > 0);
NoIncrementalWriteBarrierSet(this,
ToKeyIndex(descriptor_number),
int index = map()->NextFreePropertyIndex();
// Allocate new instance descriptors with (name, index) added
- FieldDescriptor new_field(name, index, attributes);
+ FieldDescriptor new_field(name, index, attributes, 0);
DescriptorArray* new_descriptors;
{ MaybeObject* maybe_new_descriptors =
old_descriptors->CopyInsert(&new_field);
}
}
- // Only allow map transition if the object isn't the global object and there
- // is not a transition for the name, or there's a transition for the name but
- // it's unrelated to properties.
- int descriptor_index = old_descriptors->SearchWithCache(name);
-
- // Element transitions are stored in the descriptor for property "", which is
- // not a identifier and should have forced a switch to slow properties above.
- bool can_insert_transition = descriptor_index == DescriptorArray::kNotFound;
+ // Only allow map transition if the object isn't the global object.
bool allow_map_transition =
- can_insert_transition &&
(isolate->context()->global_context()->object_function()->map() != map());
+ ASSERT(old_descriptors->Search(name) == DescriptorArray::kNotFound);
ASSERT(index < map()->inobject_properties() ||
(index - map()->inobject_properties()) < properties()->length() ||
map()->unused_property_fields() == 0);
JSFunction* function,
PropertyAttributes attributes) {
// Allocate new instance descriptors with (name, function) added
- ConstantFunctionDescriptor d(name, function, attributes);
+ ConstantFunctionDescriptor d(name, function, attributes, 0);
DescriptorArray* new_descriptors;
{ MaybeObject* maybe_new_descriptors =
map()->instance_descriptors()->CopyInsert(&d);
}
int index = map()->NextFreePropertyIndex();
- FieldDescriptor new_field(name, index, attributes);
+ FieldDescriptor new_field(name, index, attributes, 0);
// Make a new DescriptorArray replacing an entry with FieldDescriptor.
Object* descriptors_unchecked;
{ MaybeObject* maybe_descriptors_unchecked =
Map* transition_map = Map::cast(transition);
DescriptorArray* descriptors = transition_map->instance_descriptors();
- int descriptor = descriptors->SearchWithCache(*name);
+ int descriptor = descriptors->LastAdded();
PropertyDetails details = descriptors->GetDetails(descriptor);
ASSERT(details.type() == FIELD || details.type() == CONSTANT_FUNCTION);
Map* transition_map = Map::cast(transition);
DescriptorArray* descriptors = transition_map->instance_descriptors();
- int descriptor = descriptors->Search(name);
+ int descriptor = descriptors->LastAdded();
PropertyDetails details = descriptors->GetDetails(descriptor);
ASSERT(details.type() == FIELD || details.type() == CONSTANT_FUNCTION);
// step 2: create a copy of the descriptors, incl. the new getter/setter pair
Map* map1 = obj->map();
- CallbacksDescriptor callbacks_descr2(name, accessors2, attributes);
+ CallbacksDescriptor callbacks_descr2(name, accessors2, attributes, 0);
DescriptorArray* descriptors2;
{ MaybeObject* maybe_descriptors2 =
map1->instance_descriptors()->CopyInsert(&callbacks_descr2);
Object* accessor,
PropertyAttributes attributes ) {
DescriptorArray* descs = Map::cast(map)->instance_descriptors();
- int number = descs->SearchWithCache(name);
+ int number = descs->LastAdded();
ASSERT(number != DescriptorArray::kNotFound);
Object* target_accessor =
AccessorPair::cast(descs->GetCallbacksObject(number))->get(component);
// step 2: create a copy of the descriptors, incl. the new getter/setter pair
Map* map2 = obj->map();
- CallbacksDescriptor callbacks_descr3(name, accessors3, attributes);
+ CallbacksDescriptor callbacks_descr3(name, accessors3, attributes, 0);
DescriptorArray* descriptors3;
{ MaybeObject* maybe_descriptors3 =
map2->instance_descriptors()->CopyInsert(&callbacks_descr3);
if (!maybe_array->To(&result)) return maybe_array;
}
- result->set(kEnumerationIndexIndex,
- Smi::FromInt(PropertyDetails::kInitialIndex));
+ result->set(kLastAddedIndex, Smi::FromInt(-1));
result->set(kTransitionsIndex, Smi::FromInt(0));
return result;
}
ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength);
ASSERT(new_index_cache->IsSmi() || new_index_cache->IsFixedArray());
if (HasEnumCache()) {
- FixedArray::cast(get(kEnumerationIndexIndex))->
+ FixedArray::cast(get(kLastAddedIndex))->
set(kEnumCacheBridgeCacheIndex, new_cache);
- FixedArray::cast(get(kEnumerationIndexIndex))->
+ FixedArray::cast(get(kLastAddedIndex))->
set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache);
} else {
if (IsEmpty()) return; // Do nothing for empty descriptor array.
FixedArray::cast(bridge_storage)->
set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache);
NoWriteBarrierSet(FixedArray::cast(bridge_storage),
- kEnumCacheBridgeEnumIndex,
- get(kEnumerationIndexIndex));
- set(kEnumerationIndexIndex, bridge_storage);
+ kEnumCacheBridgeLastAdded,
+ get(kLastAddedIndex));
+ set(kLastAddedIndex, bridge_storage);
}
}
// Set the enumeration index in the descriptors and set the enumeration index
// in the result.
- int enumeration_index = NextEnumerationIndex();
if (keep_enumeration_index) {
descriptor->SetEnumerationIndex(GetDetails(index).index());
} else {
- descriptor->SetEnumerationIndex(enumeration_index);
- ++enumeration_index;
+ descriptor->SetEnumerationIndex(NextEnumerationIndex());
}
- new_descriptors->SetNextEnumerationIndex(enumeration_index);
// Copy the descriptors, inserting or replacing a descriptor.
int to_index = 0;
ASSERT(insertion_index < new_descriptors->number_of_descriptors());
new_descriptors->Set(insertion_index, descriptor, witness);
+ if (!replacing) {
+ new_descriptors->SetLastAdded(insertion_index);
+ } else {
+ new_descriptors->SetLastAdded(LastAdded());
+ }
ASSERT(to_index == new_descriptors->number_of_descriptors());
SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates());
new_descriptors->CopyFrom(i, this, i, witness);
if (copy_result->IsFailure()) return copy_result;
}
+ new_descriptors->SetLastAdded(LastAdded());
}
- new_descriptors->SetNextEnumerationIndex(NextEnumerationIndex());
+
return new_descriptors;
}
void DescriptorArray::SortUnchecked(const WhitenessWitness& witness) {
// In-place heap sort.
int len = number_of_descriptors();
+ // Nothing to sort.
+ if (len == 0) return;
// Bottom-up max-heap construction.
// Index of the last node with children
parent_index = child_index;
}
}
+
+ int last_enum_index = -1;
+ int last_added = -1;
+ for (int i = 0; i < len; ++i) {
+ int current_enum = GetDetails(i).index();
+ if (current_enum > last_enum_index) {
+ last_added = i;
+ last_enum_index = current_enum;
+ }
+ }
+ SetLastAdded(last_added);
+
+ ASSERT(LastAdded() != -1);
}
JSFunction::cast(value),
details.attributes(),
details.index());
- descriptors->Set(next_descriptor++, &d, witness);
+ descriptors->Set(next_descriptor, &d, witness);
} else if (type == NORMAL) {
if (current_offset < inobject_props) {
obj->InObjectPropertyAtPut(current_offset,
current_offset++,
details.attributes(),
details.index());
- descriptors->Set(next_descriptor++, &d, witness);
+ descriptors->Set(next_descriptor, &d, witness);
} else if (type == CALLBACKS) {
if (value->IsAccessorPair()) {
MaybeObject* maybe_copy =
value,
details.attributes(),
details.index());
- descriptors->Set(next_descriptor++, &d, witness);
+ descriptors->Set(next_descriptor, &d, witness);
} else {
UNREACHABLE();
}
+ ++next_descriptor;
}
}
ASSERT(current_offset == number_of_fields);
obj->set_properties(FixedArray::cast(fields));
ASSERT(obj->IsJSObject());
- descriptors->SetNextEnumerationIndex(NextEnumerationIndex());
// Check that it really works.
ASSERT(obj->HasFastProperties());
inline int number_of_entries() { return number_of_descriptors(); }
- int NextEnumerationIndex() {
- if (IsEmpty()) return PropertyDetails::kInitialIndex;
- Object* obj = get(kEnumerationIndexIndex);
+ int LastAdded() {
+ ASSERT(!IsEmpty());
+ Object* obj = get(kLastAddedIndex);
if (obj->IsSmi()) {
return Smi::cast(obj)->value();
} else {
- Object* index = FixedArray::cast(obj)->get(kEnumCacheBridgeEnumIndex);
+ Object* index = FixedArray::cast(obj)->get(kEnumCacheBridgeLastAdded);
return Smi::cast(index)->value();
}
}
- // Set next enumeration index and flush any enum cache.
- void SetNextEnumerationIndex(int value) {
- if (!IsEmpty()) {
- set(kEnumerationIndexIndex, Smi::FromInt(value));
+ int NextEnumerationIndex() {
+ if (number_of_descriptors() == 0) {
+ return PropertyDetails::kInitialIndex;
}
+ return GetDetails(LastAdded()).index() + 1;
}
+
+ // Set index of the last added descriptor and flush any enum cache.
+ void SetLastAdded(int index) {
+ ASSERT(!IsEmpty() || index > 0);
+ set(kLastAddedIndex, Smi::FromInt(index));
+ }
+
bool HasEnumCache() {
- return !IsEmpty() && !get(kEnumerationIndexIndex)->IsSmi();
+ return !IsEmpty() && !get(kLastAddedIndex)->IsSmi();
}
Object* GetEnumCache() {
ASSERT(HasEnumCache());
- FixedArray* bridge = FixedArray::cast(get(kEnumerationIndexIndex));
+ FixedArray* bridge = FixedArray::cast(get(kLastAddedIndex));
return bridge->get(kEnumCacheBridgeCacheIndex);
}
Object** GetEnumCacheSlot() {
ASSERT(HasEnumCache());
return HeapObject::RawField(reinterpret_cast<HeapObject*>(this),
- kEnumerationIndexOffset);
+ kLastAddedOffset);
}
Object** GetTransitionsSlot() {
static const int kNotFound = -1;
static const int kBackPointerStorageIndex = 0;
- static const int kEnumerationIndexIndex = 1;
+ static const int kLastAddedIndex = 1;
static const int kTransitionsIndex = 2;
static const int kFirstIndex = 3;
// The length of the "bridge" to the enum cache.
static const int kEnumCacheBridgeLength = 3;
- static const int kEnumCacheBridgeEnumIndex = 0;
+ static const int kEnumCacheBridgeLastAdded = 0;
static const int kEnumCacheBridgeCacheIndex = 1;
static const int kEnumCacheBridgeIndicesCacheIndex = 2;
// Layout description.
static const int kBackPointerStorageOffset = FixedArray::kHeaderSize;
- static const int kEnumerationIndexOffset = kBackPointerStorageOffset +
- kPointerSize;
- static const int kTransitionsOffset = kEnumerationIndexOffset + kPointerSize;
+ static const int kLastAddedOffset = kBackPointerStorageOffset +
+ kPointerSize;
+ static const int kTransitionsOffset = kLastAddedOffset + kPointerSize;
static const int kFirstOffset = kTransitionsOffset + kPointerSize;
// Layout description for the bridge array.
- static const int kEnumCacheBridgeEnumOffset = FixedArray::kHeaderSize;
+ static const int kEnumCacheBridgeLastAddedOffset = FixedArray::kHeaderSize;
static const int kEnumCacheBridgeCacheOffset =
- kEnumCacheBridgeEnumOffset + kPointerSize;
+ kEnumCacheBridgeLastAddedOffset + kPointerSize;
// Layout of descriptor.
static const int kDescriptorKey = 0;
// Accessors for next enumeration index.
void SetNextEnumerationIndex(int index) {
+ ASSERT(index != 0);
this->set(kNextEnumerationIndexIndex, Smi::FromInt(index));
}
Object* value,
PropertyAttributes attributes,
PropertyType type,
- int index = 0)
+ int index)
: key_(key),
value_(value),
details_(attributes, type, index) { }
FieldDescriptor(String* key,
int field_index,
PropertyAttributes attributes,
- int index = 0)
+ int index)
: Descriptor(key, Smi::FromInt(field_index), attributes, FIELD, index) {}
};
ConstantFunctionDescriptor(String* key,
JSFunction* function,
PropertyAttributes attributes,
- int index = 0)
+ int index)
: Descriptor(key, function, attributes, CONSTANT_FUNCTION, index) {}
};
CallbacksDescriptor(String* key,
Object* foreign,
PropertyAttributes attributes,
- int index = 0)
+ int index)
: Descriptor(key, foreign, attributes, CALLBACKS, index) {}
};
PropertyDetails TransitionArray::GetTargetDetails(int transition_number) {
Map* map = GetTargetMap(transition_number);
DescriptorArray* descriptors = map->instance_descriptors();
- String* key = GetKey(transition_number);
- int descriptor = descriptors->SearchWithCache(key);
+ int descriptor = descriptors->LastAdded();
ASSERT(descriptor != DescriptorArray::kNotFound);
return descriptors->GetDetails(descriptor);
}
// We got a map in register rax. Get the enumeration cache from it.
__ bind(&use_cache);
__ LoadInstanceDescriptors(rax, rcx);
- __ movq(rcx, FieldOperand(rcx, DescriptorArray::kEnumerationIndexOffset));
+ __ movq(rcx, FieldOperand(rcx, DescriptorArray::kLastAddedOffset));
__ movq(rdx, FieldOperand(rcx, DescriptorArray::kEnumCacheBridgeCacheOffset));
// Set up the four remaining stack slots.
Register result = ToRegister(instr->result());
__ LoadInstanceDescriptors(map, result);
__ movq(result,
- FieldOperand(result, DescriptorArray::kEnumerationIndexOffset));
+ FieldOperand(result, DescriptorArray::kLastAddedOffset));
__ movq(result,
FieldOperand(result, FixedArray::SizeFor(instr->idx())));
Condition cc = masm()->CheckSmi(result);
// Check that there is an enum cache in the non-empty instance
// descriptors (rdx). This is the case if the next enumeration
// index field does not contain a smi.
- movq(rdx, FieldOperand(rdx, DescriptorArray::kEnumerationIndexOffset));
+ movq(rdx, FieldOperand(rdx, DescriptorArray::kLastAddedOffset));
JumpIfSmi(rdx, call_runtime);
// For all objects but the receiver, check that the cache is empty.