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:
parent
df860eda5c
commit
ab26d8356c
41
src/api.cc
41
src/api.cc
@ -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,
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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";
|
||||
}
|
||||
|
@ -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).
|
||||
|
@ -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");
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user