Key external array map transitions on ElementsKind instead of ExternalArrayType

R=jkummrow@chromium.org
BUG=none
TEST=none

Review URL: http://codereview.chromium.org/7787007

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9214 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
danno@chromium.org 2011-09-09 14:47:37 +00:00
parent df860eda5c
commit ab26d8356c
11 changed files with 101 additions and 100 deletions

View File

@ -3266,6 +3266,42 @@ bool v8::Object::DeleteHiddenValue(v8::Handle<v8::String> key) {
namespace {
static i::ElementsKind GetElementsKindFromExternalArrayType(
ExternalArrayType array_type) {
switch (array_type) {
case kExternalByteArray:
return i::EXTERNAL_BYTE_ELEMENTS;
break;
case kExternalUnsignedByteArray:
return i::EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
break;
case kExternalShortArray:
return i::EXTERNAL_SHORT_ELEMENTS;
break;
case kExternalUnsignedShortArray:
return i::EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
break;
case kExternalIntArray:
return i::EXTERNAL_INT_ELEMENTS;
break;
case kExternalUnsignedIntArray:
return i::EXTERNAL_UNSIGNED_INT_ELEMENTS;
break;
case kExternalFloatArray:
return i::EXTERNAL_FLOAT_ELEMENTS;
break;
case kExternalDoubleArray:
return i::EXTERNAL_DOUBLE_ELEMENTS;
break;
case kExternalPixelArray:
return i::EXTERNAL_PIXEL_ELEMENTS;
break;
}
UNREACHABLE();
return i::DICTIONARY_ELEMENTS;
}
void PrepareExternalArrayElements(i::Handle<i::JSObject> object,
void* data,
ExternalArrayType array_type,
@ -3284,9 +3320,9 @@ void PrepareExternalArrayElements(i::Handle<i::JSObject> object,
elements->map() != isolate->heap()->MapForExternalArrayType(array_type);
if (cant_reuse_map) {
i::Handle<i::Map> external_array_map =
isolate->factory()->GetExternalArrayElementsMap(
isolate->factory()->GetElementsTransitionMap(
i::Handle<i::Map>(object->map()),
array_type,
GetElementsKindFromExternalArrayType(array_type),
object->HasFastProperties());
object->set_map(*external_array_map);
}
@ -3348,6 +3384,7 @@ int v8::Object::GetIndexedPropertiesPixelDataLength() {
}
}
void v8::Object::SetIndexedPropertiesToExternalArrayData(
void* data,
ExternalArrayType array_type,

View File

@ -2062,7 +2062,7 @@ void Genesis::TransferNamedProperties(Handle<JSObject> from,
break;
}
case MAP_TRANSITION:
case EXTERNAL_ARRAY_TRANSITION:
case ELEMENTS_TRANSITION:
case CONSTANT_TRANSITION:
case NULL_DESCRIPTOR:
// Ignore non-properties.

View File

@ -465,13 +465,13 @@ Handle<Map> Factory::GetSlowElementsMap(Handle<Map> src) {
}
Handle<Map> Factory::GetExternalArrayElementsMap(
Handle<Map> Factory::GetElementsTransitionMap(
Handle<Map> src,
ExternalArrayType array_type,
ElementsKind elements_kind,
bool safe_to_add_transition) {
CALL_HEAP_FUNCTION(isolate(),
src->GetExternalArrayElementsMap(array_type,
safe_to_add_transition),
src->GetElementsTransitionMap(elements_kind,
safe_to_add_transition),
Map);
}

View File

@ -219,9 +219,9 @@ class Factory {
Handle<Map> GetSlowElementsMap(Handle<Map> map);
Handle<Map> GetExternalArrayElementsMap(Handle<Map> map,
ExternalArrayType array_type,
bool safe_to_add_transition);
Handle<Map> GetElementsTransitionMap(Handle<Map> map,
ElementsKind elements_kind,
bool safe_to_add_transition);
Handle<FixedArray> CopyFixedArray(Handle<FixedArray> array);

View File

@ -2000,7 +2000,7 @@ bool DescriptorArray::IsProperty(int descriptor_number) {
bool DescriptorArray::IsTransition(int descriptor_number) {
PropertyType t = GetType(descriptor_number);
return t == MAP_TRANSITION || t == CONSTANT_TRANSITION ||
t == EXTERNAL_ARRAY_TRANSITION;
t == ELEMENTS_TRANSITION;
}

View File

@ -591,7 +591,7 @@ MaybeObject* Object::GetProperty(Object* receiver,
return holder->GetPropertyWithInterceptor(recvr, name, attributes);
}
case MAP_TRANSITION:
case EXTERNAL_ARRAY_TRANSITION:
case ELEMENTS_TRANSITION:
case CONSTANT_TRANSITION:
case NULL_DESCRIPTOR:
break;
@ -1435,13 +1435,12 @@ MaybeObject* JSObject::AddFastProperty(String* name,
// it's unrelated to properties.
int descriptor_index = old_descriptors->Search(name);
// External array transitions are stored in the descriptor for property "",
// which is not a identifier and should have forced a switch to slow
// properties above.
// Element transitions are stored in the descriptor for property "", which is
// not a identifier and should have forced a switch to slow properties above.
ASSERT(descriptor_index == DescriptorArray::kNotFound ||
old_descriptors->GetType(descriptor_index) != EXTERNAL_ARRAY_TRANSITION);
old_descriptors->GetType(descriptor_index) != ELEMENTS_TRANSITION);
bool can_insert_transition = descriptor_index == DescriptorArray::kNotFound ||
old_descriptors->GetType(descriptor_index) == EXTERNAL_ARRAY_TRANSITION;
old_descriptors->GetType(descriptor_index) == ELEMENTS_TRANSITION;
bool allow_map_transition =
can_insert_transition &&
(isolate->context()->global_context()->object_function()->map() != map());
@ -1989,61 +1988,25 @@ void Map::LookupInDescriptors(JSObject* holder,
}
static ElementsKind GetElementsKindFromExternalArrayType(
ExternalArrayType array_type) {
switch (array_type) {
case kExternalByteArray:
return EXTERNAL_BYTE_ELEMENTS;
break;
case kExternalUnsignedByteArray:
return EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
break;
case kExternalShortArray:
return EXTERNAL_SHORT_ELEMENTS;
break;
case kExternalUnsignedShortArray:
return EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
break;
case kExternalIntArray:
return EXTERNAL_INT_ELEMENTS;
break;
case kExternalUnsignedIntArray:
return EXTERNAL_UNSIGNED_INT_ELEMENTS;
break;
case kExternalFloatArray:
return EXTERNAL_FLOAT_ELEMENTS;
break;
case kExternalDoubleArray:
return EXTERNAL_DOUBLE_ELEMENTS;
break;
case kExternalPixelArray:
return EXTERNAL_PIXEL_ELEMENTS;
break;
}
UNREACHABLE();
return DICTIONARY_ELEMENTS;
}
MaybeObject* Map::GetExternalArrayElementsMap(ExternalArrayType array_type,
bool safe_to_add_transition) {
MaybeObject* Map::GetElementsTransitionMap(ElementsKind elements_kind,
bool safe_to_add_transition) {
Heap* current_heap = heap();
DescriptorArray* descriptors = instance_descriptors();
String* external_array_sentinel_name = current_heap->empty_symbol();
String* elements_transition_sentinel_name = current_heap->empty_symbol();
if (safe_to_add_transition) {
// It's only safe to manipulate the descriptor array if it would be
// safe to add a transition.
ASSERT(!is_shared()); // no transitions can be added to shared maps.
// Check if the external array transition already exists.
// Check if the elements transition already exists.
DescriptorLookupCache* cache =
current_heap->isolate()->descriptor_lookup_cache();
int index = cache->Lookup(descriptors, external_array_sentinel_name);
int index = cache->Lookup(descriptors, elements_transition_sentinel_name);
if (index == DescriptorLookupCache::kAbsent) {
index = descriptors->Search(external_array_sentinel_name);
index = descriptors->Search(elements_transition_sentinel_name);
cache->Update(descriptors,
external_array_sentinel_name,
elements_transition_sentinel_name,
index);
}
@ -2051,8 +2014,8 @@ MaybeObject* Map::GetExternalArrayElementsMap(ExternalArrayType array_type,
// return it.
if (index != DescriptorArray::kNotFound) {
PropertyDetails details(PropertyDetails(descriptors->GetDetails(index)));
if (details.type() == EXTERNAL_ARRAY_TRANSITION &&
details.array_type() == array_type) {
if (details.type() == ELEMENTS_TRANSITION &&
details.elements_kind() == elements_kind) {
return descriptors->GetValue(index);
} else {
safe_to_add_transition = false;
@ -2060,28 +2023,29 @@ MaybeObject* Map::GetExternalArrayElementsMap(ExternalArrayType array_type,
}
}
// No transition to an existing external array map. Make a new one.
// No transition to an existing map for the given ElementsKind. Make a new
// one.
Object* obj;
{ MaybeObject* maybe_map = CopyDropTransitions();
if (!maybe_map->ToObject(&obj)) return maybe_map;
}
Map* new_map = Map::cast(obj);
new_map->set_elements_kind(GetElementsKindFromExternalArrayType(array_type));
new_map->set_elements_kind(elements_kind);
GetIsolate()->counters()->map_to_external_array_elements()->Increment();
// Only remember the map transition if the object's map is NOT equal to the
// global object_function's map and there is not an already existing
// non-matching external array transition.
// non-matching element transition.
bool allow_map_transition =
safe_to_add_transition &&
(GetIsolate()->context()->global_context()->object_function()->map() !=
map());
if (allow_map_transition) {
// Allocate new instance descriptors for the old map with map transition.
ExternalArrayTransitionDescriptor desc(external_array_sentinel_name,
Map::cast(new_map),
array_type);
ElementsTransitionDescriptor desc(elements_transition_sentinel_name,
Map::cast(new_map),
elements_kind);
Object* new_descriptors;
MaybeObject* maybe_new_descriptors = descriptors->CopyInsert(
&desc,
@ -2498,7 +2462,7 @@ MaybeObject* JSObject::SetPropertyForResult(LookupResult* result,
return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
}
case NULL_DESCRIPTOR:
case EXTERNAL_ARRAY_TRANSITION:
case ELEMENTS_TRANSITION:
return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
default:
UNREACHABLE();
@ -2586,7 +2550,7 @@ MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes(
// if the value is a function.
return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
case NULL_DESCRIPTOR:
case EXTERNAL_ARRAY_TRANSITION:
case ELEMENTS_TRANSITION:
return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
default:
UNREACHABLE();
@ -2867,7 +2831,7 @@ MaybeObject* JSObject::NormalizeProperties(PropertyNormalizationMode mode,
case CONSTANT_TRANSITION:
case NULL_DESCRIPTOR:
case INTERCEPTOR:
case EXTERNAL_ARRAY_TRANSITION:
case ELEMENTS_TRANSITION:
break;
default:
UNREACHABLE();
@ -6212,7 +6176,7 @@ void Map::CreateBackPointers() {
DescriptorArray* descriptors = instance_descriptors();
for (int i = 0; i < descriptors->number_of_descriptors(); i++) {
if (descriptors->GetType(i) == MAP_TRANSITION ||
descriptors->GetType(i) == EXTERNAL_ARRAY_TRANSITION ||
descriptors->GetType(i) == ELEMENTS_TRANSITION ||
descriptors->GetType(i) == CONSTANT_TRANSITION) {
// Get target.
Map* target = Map::cast(descriptors->GetValue(i));
@ -6255,7 +6219,7 @@ void Map::ClearNonLiveTransitions(Heap* heap, Object* real_prototype) {
// non-live object.
PropertyDetails details(Smi::cast(contents->get(i + 1)));
if (details.type() == MAP_TRANSITION ||
details.type() == EXTERNAL_ARRAY_TRANSITION ||
details.type() == ELEMENTS_TRANSITION ||
details.type() == CONSTANT_TRANSITION) {
Map* target = reinterpret_cast<Map*>(contents->get(i));
ASSERT(target->IsHeapObject());
@ -7144,7 +7108,7 @@ const char* Code::PropertyType2String(PropertyType type) {
case HANDLER: return "HANDLER";
case INTERCEPTOR: return "INTERCEPTOR";
case MAP_TRANSITION: return "MAP_TRANSITION";
case EXTERNAL_ARRAY_TRANSITION: return "EXTERNAL_ARRAY_TRANSITION";
case ELEMENTS_TRANSITION: return "ELEMENTS_TRANSITION";
case CONSTANT_TRANSITION: return "CONSTANT_TRANSITION";
case NULL_DESCRIPTOR: return "NULL_DESCRIPTOR";
}

View File

@ -174,7 +174,7 @@ class PropertyDetails BASE_EMBEDDED {
PropertyDetails(PropertyAttributes attributes,
PropertyType type,
int index = 0) {
ASSERT(type != EXTERNAL_ARRAY_TRANSITION);
ASSERT(type != ELEMENTS_TRANSITION);
ASSERT(TypeField::is_valid(type));
ASSERT(AttributesField::is_valid(attributes));
ASSERT(StorageField::is_valid(index));
@ -190,19 +190,19 @@ class PropertyDetails BASE_EMBEDDED {
PropertyDetails(PropertyAttributes attributes,
PropertyType type,
ExternalArrayType array_type) {
ASSERT(type == EXTERNAL_ARRAY_TRANSITION);
ElementsKind elements_kind) {
ASSERT(type == ELEMENTS_TRANSITION);
ASSERT(TypeField::is_valid(type));
ASSERT(AttributesField::is_valid(attributes));
ASSERT(StorageField::is_valid(static_cast<int>(array_type)));
ASSERT(StorageField::is_valid(static_cast<int>(elements_kind)));
value_ = TypeField::encode(type)
| AttributesField::encode(attributes)
| StorageField::encode(static_cast<int>(array_type));
| StorageField::encode(static_cast<int>(elements_kind));
ASSERT(type == this->type());
ASSERT(attributes == this->attributes());
ASSERT(array_type == this->array_type());
ASSERT(elements_kind == this->elements_kind());
}
// Conversion for storing details as Object*.
@ -215,7 +215,7 @@ class PropertyDetails BASE_EMBEDDED {
PropertyType t = type();
ASSERT(t != INTERCEPTOR);
return t == MAP_TRANSITION || t == CONSTANT_TRANSITION ||
t == EXTERNAL_ARRAY_TRANSITION;
t == ELEMENTS_TRANSITION;
}
bool IsProperty() {
@ -226,9 +226,9 @@ class PropertyDetails BASE_EMBEDDED {
int index() { return StorageField::decode(value_); }
ExternalArrayType array_type() {
ASSERT(type() == EXTERNAL_ARRAY_TRANSITION);
return static_cast<ExternalArrayType>(StorageField::decode(value_));
ElementsKind elements_kind() {
ASSERT(type() == ELEMENTS_TRANSITION);
return static_cast<ElementsKind>(StorageField::decode(value_));
}
inline PropertyDetails AsDeleted();
@ -4154,9 +4154,9 @@ class Map: public HeapObject {
MUST_USE_RESULT inline MaybeObject* GetSlowElementsMap();
// Returns a new map with all transitions dropped from the descriptors and the
// ElementsKind set to one of the value corresponding to array_type.
MUST_USE_RESULT MaybeObject* GetExternalArrayElementsMap(
ExternalArrayType array_type,
// ElementsKind set.
MUST_USE_RESULT MaybeObject* GetElementsTransitionMap(
ElementsKind elements_kind,
bool safe_to_add_transition);
// Returns the property index for name (only valid for FAST MODE).

View File

@ -1,4 +1,4 @@
// Copyright 2006-2008 the V8 project authors. All rights reserved.
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@ -52,8 +52,8 @@ void LookupResult::Print(FILE* out) {
GetTransitionMap()->Print(out);
PrintF(out, "\n");
break;
case EXTERNAL_ARRAY_TRANSITION:
PrintF(out, " -type = external array transition\n");
case ELEMENTS_TRANSITION:
PrintF(out, " -type = elements transition\n");
PrintF(out, " -map:\n");
GetTransitionMap()->Print(out);
PrintF(out, "\n");

View File

@ -1,4 +1,4 @@
// Copyright 2006-2008 the V8 project authors. All rights reserved.
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@ -112,14 +112,14 @@ class MapTransitionDescriptor: public Descriptor {
: Descriptor(key, map, attributes, MAP_TRANSITION) { }
};
class ExternalArrayTransitionDescriptor: public Descriptor {
class ElementsTransitionDescriptor: public Descriptor {
public:
ExternalArrayTransitionDescriptor(String* key,
Map* map,
ExternalArrayType array_type)
ElementsTransitionDescriptor(String* key,
Map* map,
ElementsKind elements_kind)
: Descriptor(key, map, PropertyDetails(NONE,
EXTERNAL_ARRAY_TRANSITION,
array_type)) { }
ELEMENTS_TRANSITION,
elements_kind)) { }
};
// Marks a field name in a map so that adding the field is guaranteed
@ -281,7 +281,7 @@ class LookupResult BASE_EMBEDDED {
Map* GetTransitionMap() {
ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
ASSERT(type() == MAP_TRANSITION || type() == CONSTANT_TRANSITION ||
type() == EXTERNAL_ARRAY_TRANSITION);
type() == ELEMENTS_TRANSITION);
return Map::cast(GetValue());
}

View File

@ -10145,7 +10145,7 @@ static MaybeObject* DebugLookupResultValue(Heap* heap,
}
case INTERCEPTOR:
case MAP_TRANSITION:
case EXTERNAL_ARRAY_TRANSITION:
case ELEMENTS_TRANSITION:
case CONSTANT_TRANSITION:
case NULL_DESCRIPTOR:
return heap->undefined_value();

View File

@ -334,7 +334,7 @@ enum PropertyType {
HANDLER = 4, // only in lookup results, not in descriptors
INTERCEPTOR = 5, // only in lookup results, not in descriptors
MAP_TRANSITION = 6, // only in fast mode
EXTERNAL_ARRAY_TRANSITION = 7,
ELEMENTS_TRANSITION = 7,
CONSTANT_TRANSITION = 8, // only in fast mode
NULL_DESCRIPTOR = 9, // only in fast mode
// All properties before MAP_TRANSITION are real.