| Index: src/objects.cc
|
| diff --git a/src/objects.cc b/src/objects.cc
|
| index aabb0413a4cb4d60cc1a890e02d8773bc8437fc0..6fa801409b0a1422f1673d017a59ab6a1ee0e842 100644
|
| --- a/src/objects.cc
|
| +++ b/src/objects.cc
|
| @@ -1337,7 +1337,7 @@ Object* JSObject::AddConstantFunctionProperty(String* name,
|
| if (attributes != NONE) {
|
| return function;
|
| }
|
| - ConstTransitionDescriptor mark(name);
|
| + ConstTransitionDescriptor mark(name, Map::cast(new_map));
|
| new_descriptors =
|
| old_map->instance_descriptors()->CopyInsert(&mark, KEEP_TRANSITIONS);
|
| if (new_descriptors->IsFailure()) {
|
| @@ -1695,11 +1695,7 @@ bool JSObject::SetElementWithCallbackSetterInPrototypes(uint32_t index,
|
|
|
| void JSObject::LookupInDescriptor(String* name, LookupResult* result) {
|
| DescriptorArray* descriptors = map()->instance_descriptors();
|
| - int number = DescriptorLookupCache::Lookup(descriptors, name);
|
| - if (number == DescriptorLookupCache::kAbsent) {
|
| - number = descriptors->Search(name);
|
| - DescriptorLookupCache::Update(descriptors, name, number);
|
| - }
|
| + int number = descriptors->SearchWithCache(name);
|
| if (number != DescriptorArray::kNotFound) {
|
| result->DescriptorResult(this, descriptors->GetDetails(number), number);
|
| } else {
|
| @@ -1896,10 +1892,25 @@ Object* JSObject::SetProperty(LookupResult* result,
|
| result->holder());
|
| case INTERCEPTOR:
|
| return SetPropertyWithInterceptor(name, value, attributes);
|
| - case CONSTANT_TRANSITION:
|
| - // Replace with a MAP_TRANSITION to a new map with a FIELD, even
|
| - // if the value is a function.
|
| + case CONSTANT_TRANSITION: {
|
| + // If the same constant function is being added we can simply
|
| + // transition to the target map.
|
| + Map* target_map = result->GetTransitionMap();
|
| + DescriptorArray* target_descriptors = target_map->instance_descriptors();
|
| + int number = target_descriptors->SearchWithCache(name);
|
| + ASSERT(number != DescriptorArray::kNotFound);
|
| + ASSERT(target_descriptors->GetType(number) == CONSTANT_FUNCTION);
|
| + JSFunction* function =
|
| + JSFunction::cast(target_descriptors->GetValue(number));
|
| + ASSERT(!Heap::InNewSpace(function));
|
| + if (value == function) {
|
| + set_map(target_map);
|
| + return value;
|
| + }
|
| + // Otherwise, replace with a MAP_TRANSITION to a new map with a
|
| + // FIELD, even if the value is a constant function.
|
| return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
|
| + }
|
| case NULL_DESCRIPTOR:
|
| return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
|
| default:
|
| @@ -4977,7 +4988,8 @@ void String::PrintOn(FILE* file) {
|
| void Map::CreateBackPointers() {
|
| DescriptorArray* descriptors = instance_descriptors();
|
| for (int i = 0; i < descriptors->number_of_descriptors(); i++) {
|
| - if (descriptors->GetType(i) == MAP_TRANSITION) {
|
| + if (descriptors->GetType(i) == MAP_TRANSITION ||
|
| + descriptors->GetType(i) == CONSTANT_TRANSITION) {
|
| // Get target.
|
| Map* target = Map::cast(descriptors->GetValue(i));
|
| #ifdef DEBUG
|
| @@ -5018,7 +5030,8 @@ void Map::ClearNonLiveTransitions(Object* real_prototype) {
|
| // map is not reached again by following a back pointer from a
|
| // non-live object.
|
| PropertyDetails details(Smi::cast(contents->get(i + 1)));
|
| - if (details.type() == MAP_TRANSITION) {
|
| + if (details.type() == MAP_TRANSITION ||
|
| + details.type() == CONSTANT_TRANSITION) {
|
| Map* target = reinterpret_cast<Map*>(contents->get(i));
|
| ASSERT(target->IsHeapObject());
|
| if (!target->IsMarked()) {
|
|
|