Index: src/objects.cc |
=================================================================== |
--- src/objects.cc (revision 10404) |
+++ src/objects.cc (working copy) |
@@ -1,4 +1,4 @@ |
-// Copyright 2011 the V8 project authors. All rights reserved. |
+// Copyright 2012 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: |
@@ -246,8 +246,8 @@ |
} |
// __defineGetter__ callback |
- if (structure->IsFixedArray()) { |
- Object* getter = FixedArray::cast(structure)->get(kGetterIndex); |
+ if (structure->IsAccessorPair()) { |
+ Object* getter = AccessorPair::cast(structure)->getter(); |
if (getter->IsSpecFunction()) { |
// TODO(rossberg): nicer would be to cast to some JSCallable here... |
return GetPropertyWithDefinedGetter(receiver, JSReceiver::cast(getter)); |
@@ -485,6 +485,16 @@ |
} |
+Handle<Object> JSObject::SetNormalizedProperty(Handle<JSObject> object, |
+ Handle<String> key, |
+ Handle<Object> value, |
+ PropertyDetails details) { |
+ CALL_HEAP_FUNCTION(object->GetIsolate(), |
+ object->SetNormalizedProperty(*key, *value, details), |
+ Object); |
+} |
+ |
+ |
MaybeObject* JSObject::SetNormalizedProperty(String* name, |
Object* value, |
PropertyDetails details) { |
@@ -1961,6 +1971,17 @@ |
} |
+Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object, |
+ Handle<String> key, |
+ Handle<Object> value, |
+ PropertyAttributes attributes, |
+ StrictModeFlag strict_mode) { |
+ CALL_HEAP_FUNCTION(object->GetIsolate(), |
+ object->SetProperty(*key, *value, attributes, strict_mode), |
+ Object); |
+} |
+ |
+ |
MaybeObject* JSReceiver::SetProperty(String* name, |
Object* value, |
PropertyAttributes attributes, |
@@ -2018,8 +2039,8 @@ |
return *value_handle; |
} |
- if (structure->IsFixedArray()) { |
- Object* setter = FixedArray::cast(structure)->get(kSetterIndex); |
+ if (structure->IsAccessorPair()) { |
+ Object* setter = AccessorPair::cast(structure)->setter(); |
if (setter->IsSpecFunction()) { |
// TODO(rossberg): nicer would be to cast to some JSCallable here... |
return SetPropertyWithDefinedSetter(JSReceiver::cast(setter), value); |
@@ -2107,9 +2128,10 @@ |
if (!JSObject::cast(pt)->HasDictionaryElements()) { |
continue; |
} |
- NumberDictionary* dictionary = JSObject::cast(pt)->element_dictionary(); |
+ SeededNumberDictionary* dictionary = |
+ JSObject::cast(pt)->element_dictionary(); |
int entry = dictionary->FindEntry(index); |
- if (entry != NumberDictionary::kNotFound) { |
+ if (entry != SeededNumberDictionary::kNotFound) { |
PropertyDetails details = dictionary->DetailsAt(entry); |
if (details.type() == CALLBACKS) { |
*found = true; |
@@ -2342,7 +2364,9 @@ |
if (details.type() == ELEMENTS_TRANSITION) { |
return descriptors->GetValue(index); |
} else { |
- *safe_to_add_transition = false; |
+ if (safe_to_add_transition != NULL) { |
+ *safe_to_add_transition = false; |
+ } |
} |
} |
return NULL; |
@@ -3024,6 +3048,18 @@ |
// Note that this method cannot be used to set the prototype of a function |
// because ConvertDescriptorToField() which is called in "case CALLBACKS:" |
// doesn't handle function prototypes correctly. |
+Handle<Object> JSObject::SetLocalPropertyIgnoreAttributes( |
+ Handle<JSObject> object, |
+ Handle<String> key, |
+ Handle<Object> value, |
+ PropertyAttributes attributes) { |
+ CALL_HEAP_FUNCTION( |
+ object->GetIsolate(), |
+ object->SetLocalPropertyIgnoreAttributes(*key, *value, attributes), |
+ Object); |
+} |
+ |
+ |
MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes( |
String* name, |
Object* value, |
@@ -3314,6 +3350,15 @@ |
} |
+void JSObject::NormalizeProperties(Handle<JSObject> object, |
+ PropertyNormalizationMode mode, |
+ int expected_additional_properties) { |
+ CALL_HEAP_FUNCTION_VOID(object->GetIsolate(), |
+ object->NormalizeProperties( |
+ mode, expected_additional_properties)); |
+} |
+ |
+ |
MaybeObject* JSObject::NormalizeProperties(PropertyNormalizationMode mode, |
int expected_additional_properties) { |
if (!HasFastProperties()) return this; |
@@ -3436,6 +3481,14 @@ |
} |
+void JSObject::TransformToFastProperties(Handle<JSObject> object, |
+ int unused_property_fields) { |
+ CALL_HEAP_FUNCTION_VOID( |
+ object->GetIsolate(), |
+ object->TransformToFastProperties(unused_property_fields)); |
+} |
+ |
+ |
MaybeObject* JSObject::TransformToFastProperties(int unused_property_fields) { |
if (HasFastProperties()) return this; |
ASSERT(!IsGlobalObject()); |
@@ -3444,6 +3497,14 @@ |
} |
+Handle<SeededNumberDictionary> JSObject::NormalizeElements( |
+ Handle<JSObject> object) { |
+ CALL_HEAP_FUNCTION(object->GetIsolate(), |
+ object->NormalizeElements(), |
+ SeededNumberDictionary); |
+} |
+ |
+ |
MaybeObject* JSObject::NormalizeElements() { |
ASSERT(!HasExternalArrayElements()); |
@@ -3468,11 +3529,11 @@ |
int old_capacity = 0; |
int used_elements = 0; |
GetElementsCapacityAndUsage(&old_capacity, &used_elements); |
- NumberDictionary* dictionary = NULL; |
+ SeededNumberDictionary* dictionary = NULL; |
{ Object* object; |
- MaybeObject* maybe = NumberDictionary::Allocate(used_elements); |
+ MaybeObject* maybe = SeededNumberDictionary::Allocate(used_elements); |
if (!maybe->ToObject(&object)) return maybe; |
- dictionary = NumberDictionary::cast(object); |
+ dictionary = SeededNumberDictionary::cast(object); |
} |
// Copy the elements to the new backing store. |
@@ -3503,7 +3564,7 @@ |
MaybeObject* maybe_result = |
dictionary->AddNumberEntry(i, value, details); |
if (!maybe_result->ToObject(&result)) return maybe_result; |
- dictionary = NumberDictionary::cast(result); |
+ dictionary = SeededNumberDictionary::cast(result); |
} |
} |
@@ -3560,6 +3621,14 @@ |
} |
+int JSObject::GetIdentityHash(Handle<JSObject> obj) { |
+ CALL_AND_RETRY(obj->GetIsolate(), |
+ obj->GetIdentityHash(ALLOW_CREATION), |
+ return Smi::cast(__object__)->value(), |
+ return 0); |
+} |
+ |
+ |
MaybeObject* JSObject::GetIdentityHash(CreationFlag flag) { |
Object* stored_value = GetHiddenProperty(GetHeap()->identity_hash_symbol()); |
if (stored_value->IsSmi()) return stored_value; |
@@ -3612,6 +3681,15 @@ |
} |
+Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> obj, |
+ Handle<String> key, |
+ Handle<Object> value) { |
+ CALL_HEAP_FUNCTION(obj->GetIsolate(), |
+ obj->SetHiddenProperty(*key, *value), |
+ Object); |
+} |
+ |
+ |
MaybeObject* JSObject::SetHiddenProperty(String* key, Object* value) { |
if (IsJSGlobalProxy()) { |
// For a proxy, use the prototype as target object. |
@@ -3839,6 +3917,14 @@ |
} |
+Handle<Object> JSObject::DeleteElement(Handle<JSObject> obj, |
+ uint32_t index) { |
+ CALL_HEAP_FUNCTION(obj->GetIsolate(), |
+ obj->DeleteElement(index, JSObject::NORMAL_DELETION), |
+ Object); |
+} |
+ |
+ |
MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) { |
Isolate* isolate = GetIsolate(); |
// Check access rights if needed. |
@@ -3867,22 +3953,14 @@ |
} |
-MaybeObject* JSReceiver::DeleteProperty(String* name, DeleteMode mode) { |
- if (IsJSProxy()) { |
- return JSProxy::cast(this)->DeletePropertyWithHandler(name, mode); |
- } |
- return JSObject::cast(this)->DeleteProperty(name, mode); |
+Handle<Object> JSObject::DeleteProperty(Handle<JSObject> obj, |
+ Handle<String> prop) { |
+ CALL_HEAP_FUNCTION(obj->GetIsolate(), |
+ obj->DeleteProperty(*prop, JSObject::NORMAL_DELETION), |
+ Object); |
} |
-MaybeObject* JSReceiver::DeleteElement(uint32_t index, DeleteMode mode) { |
- if (IsJSProxy()) { |
- return JSProxy::cast(this)->DeleteElementWithHandler(index, mode); |
- } |
- return JSObject::cast(this)->DeleteElement(index, mode); |
-} |
- |
- |
MaybeObject* JSObject::DeleteProperty(String* name, DeleteMode mode) { |
Isolate* isolate = GetIsolate(); |
// ECMA-262, 3rd, 8.6.2.5 |
@@ -3940,6 +4018,22 @@ |
} |
+MaybeObject* JSReceiver::DeleteElement(uint32_t index, DeleteMode mode) { |
+ if (IsJSProxy()) { |
+ return JSProxy::cast(this)->DeleteElementWithHandler(index, mode); |
+ } |
+ return JSObject::cast(this)->DeleteElement(index, mode); |
+} |
+ |
+ |
+MaybeObject* JSReceiver::DeleteProperty(String* name, DeleteMode mode) { |
+ if (IsJSProxy()) { |
+ return JSProxy::cast(this)->DeletePropertyWithHandler(name, mode); |
+ } |
+ return JSObject::cast(this)->DeleteProperty(name, mode); |
+} |
+ |
+ |
bool JSObject::ReferencesObjectFromElements(FixedArray* elements, |
ElementsKind kind, |
Object* object) { |
@@ -3954,7 +4048,8 @@ |
if (!element->IsTheHole() && element == object) return true; |
} |
} else { |
- Object* key = NumberDictionary::cast(elements)->SlowReverseLookup(object); |
+ Object* key = |
+ SeededNumberDictionary::cast(elements)->SlowReverseLookup(object); |
if (!key->IsUndefined()) return true; |
} |
return false; |
@@ -4066,6 +4161,11 @@ |
} |
+Handle<Object> JSObject::PreventExtensions(Handle<JSObject> object) { |
+ CALL_HEAP_FUNCTION(object->GetIsolate(), object->PreventExtensions(), Object); |
+} |
+ |
+ |
MaybeObject* JSObject::PreventExtensions() { |
Isolate* isolate = GetIsolate(); |
if (IsAccessCheckNeeded() && |
@@ -4095,9 +4195,9 @@ |
} |
// If there are fast elements we normalize. |
- NumberDictionary* dictionary = NULL; |
+ SeededNumberDictionary* dictionary = NULL; |
{ MaybeObject* maybe = NormalizeElements(); |
- if (!maybe->To<NumberDictionary>(&dictionary)) return maybe; |
+ if (!maybe->To<SeededNumberDictionary>(&dictionary)) return maybe; |
} |
ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); |
// Make sure that we never go back to fast case. |
@@ -4257,21 +4357,21 @@ |
// Search for a getter or setter in an elements dictionary and update its |
-// attributes. Returns either undefined if the element is non-deletable, or |
-// the getter/setter pair (fixed array) if there is an existing one, or the |
-// hole value if the element does not exist or is a normal non-getter/setter |
-// data element. |
-static Object* UpdateGetterSetterInDictionary(NumberDictionary* dictionary, |
- uint32_t index, |
- PropertyAttributes attributes, |
- Heap* heap) { |
+// attributes. Returns either undefined if the element is non-deletable, or the |
+// getter/setter pair if there is an existing one, or the hole value if the |
+// element does not exist or is a normal non-getter/setter data element. |
+static Object* UpdateGetterSetterInDictionary( |
+ SeededNumberDictionary* dictionary, |
+ uint32_t index, |
+ PropertyAttributes attributes, |
+ Heap* heap) { |
int entry = dictionary->FindEntry(index); |
- if (entry != NumberDictionary::kNotFound) { |
+ if (entry != SeededNumberDictionary::kNotFound) { |
Object* result = dictionary->ValueAt(entry); |
PropertyDetails details = dictionary->DetailsAt(entry); |
// TODO(mstarzinger): We should check for details.IsDontDelete() here once |
// we only call into the runtime once to set both getter and setter. |
- if (details.type() == CALLBACKS && result->IsFixedArray()) { |
+ if (details.type() == CALLBACKS && result->IsAccessorPair()) { |
if (details.attributes() != attributes) { |
dictionary->DetailsAtPut(entry, |
PropertyDetails(attributes, CALLBACKS, index)); |
@@ -4338,7 +4438,8 @@ |
if (probe == NULL || probe->IsTheHole()) { |
FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
if (arguments->IsDictionary()) { |
- NumberDictionary* dictionary = NumberDictionary::cast(arguments); |
+ SeededNumberDictionary* dictionary = |
+ SeededNumberDictionary::cast(arguments); |
probe = UpdateGetterSetterInDictionary(dictionary, |
index, |
attributes, |
@@ -4359,7 +4460,7 @@ |
if (result.type() == CALLBACKS) { |
Object* obj = result.GetCallbackObject(); |
// Need to preserve old getters/setters. |
- if (obj->IsFixedArray()) { |
+ if (obj->IsAccessorPair()) { |
// Use set to update attributes. |
return SetPropertyCallback(name, obj, attributes); |
} |
@@ -4367,16 +4468,15 @@ |
} |
} |
- // Allocate the fixed array to hold getter and setter. |
- Object* structure; |
- { MaybeObject* maybe_structure = heap->AllocateFixedArray(2, TENURED); |
- if (!maybe_structure->ToObject(&structure)) return maybe_structure; |
+ AccessorPair* accessors; |
+ { MaybeObject* maybe_accessors = heap->AllocateAccessorPair(); |
+ if (!maybe_accessors->To<AccessorPair>(&accessors)) return maybe_accessors; |
} |
if (is_element) { |
- return SetElementCallback(index, structure, attributes); |
+ return SetElementCallback(index, accessors, attributes); |
} else { |
- return SetPropertyCallback(name, structure, attributes); |
+ return SetPropertyCallback(name, accessors, attributes); |
} |
} |
@@ -4411,11 +4511,11 @@ |
PropertyDetails details = PropertyDetails(attributes, CALLBACKS); |
// Normalize elements to make this operation simple. |
- NumberDictionary* dictionary = NULL; |
+ SeededNumberDictionary* dictionary = NULL; |
{ Object* result; |
MaybeObject* maybe = NormalizeElements(); |
if (!maybe->ToObject(&result)) return maybe; |
- dictionary = NumberDictionary::cast(result); |
+ dictionary = SeededNumberDictionary::cast(result); |
} |
ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); |
@@ -4423,7 +4523,7 @@ |
{ Object* result; |
MaybeObject* maybe = dictionary->Set(index, structure, details); |
if (!maybe->ToObject(&result)) return maybe; |
- dictionary = NumberDictionary::cast(result); |
+ dictionary = SeededNumberDictionary::cast(result); |
} |
dictionary->set_requires_slow_elements(); |
@@ -4512,12 +4612,16 @@ |
fun, attributes); |
} |
- Object* array; |
- { MaybeObject* maybe_array = DefineGetterSetter(name, attributes); |
- if (!maybe_array->ToObject(&array)) return maybe_array; |
+ Object* accessors; |
+ { MaybeObject* maybe_accessors = DefineGetterSetter(name, attributes); |
+ if (!maybe_accessors->To<Object>(&accessors)) return maybe_accessors; |
} |
- if (array->IsUndefined()) return array; |
- FixedArray::cast(array)->set(is_getter ? 0 : 1, fun); |
+ if (accessors->IsUndefined()) return accessors; |
+ if (is_getter) { |
+ AccessorPair::cast(accessors)->set_getter(fun); |
+ } else { |
+ AccessorPair::cast(accessors)->set_setter(fun); |
+ } |
return this; |
} |
@@ -4621,11 +4725,6 @@ |
} |
// Make the lookup and include prototypes. |
- // Introducing constants below makes static constants usage purely static |
- // and avoids linker errors in debug build using gcc. |
- const int getter_index = kGetterIndex; |
- const int setter_index = kSetterIndex; |
- int accessor_index = is_getter ? getter_index : setter_index; |
uint32_t index = 0; |
if (name->AsArrayIndex(&index)) { |
for (Object* obj = this; |
@@ -4633,14 +4732,15 @@ |
obj = JSObject::cast(obj)->GetPrototype()) { |
JSObject* js_object = JSObject::cast(obj); |
if (js_object->HasDictionaryElements()) { |
- NumberDictionary* dictionary = js_object->element_dictionary(); |
+ SeededNumberDictionary* dictionary = js_object->element_dictionary(); |
int entry = dictionary->FindEntry(index); |
- if (entry != NumberDictionary::kNotFound) { |
+ if (entry != SeededNumberDictionary::kNotFound) { |
Object* element = dictionary->ValueAt(entry); |
PropertyDetails details = dictionary->DetailsAt(entry); |
if (details.type() == CALLBACKS) { |
- if (element->IsFixedArray()) { |
- return FixedArray::cast(element)->get(accessor_index); |
+ if (element->IsAccessorPair()) { |
+ AccessorPair* accessors = AccessorPair::cast(element); |
+ return is_getter ? accessors->getter() : accessors->setter(); |
} |
} |
} |
@@ -4656,8 +4756,9 @@ |
if (result.IsReadOnly()) return heap->undefined_value(); |
if (result.type() == CALLBACKS) { |
Object* obj = result.GetCallbackObject(); |
- if (obj->IsFixedArray()) { |
- return FixedArray::cast(obj)->get(accessor_index); |
+ if (obj->IsAccessorPair()) { |
+ AccessorPair* accessors = AccessorPair::cast(obj); |
+ return is_getter ? accessors->getter() : accessors->setter(); |
} |
} |
} |
@@ -6833,14 +6934,14 @@ |
if (StringShape(this).IsSequentialAscii()) { |
field = HashSequentialString(SeqAsciiString::cast(this)->GetChars(), |
len, |
- GetHeap()->StringHashSeed()); |
+ GetHeap()->HashSeed()); |
} else if (StringShape(this).IsSequentialTwoByte()) { |
field = HashSequentialString(SeqTwoByteString::cast(this)->GetChars(), |
len, |
- GetHeap()->StringHashSeed()); |
+ GetHeap()->HashSeed()); |
} else { |
StringInputBuffer buffer(this); |
- field = ComputeHashField(&buffer, len, GetHeap()->StringHashSeed()); |
+ field = ComputeHashField(&buffer, len, GetHeap()->HashSeed()); |
} |
// Store the hash code in the object. |
@@ -8171,7 +8272,7 @@ |
} |
-static void CopySlowElementsToFast(NumberDictionary* source, |
+static void CopySlowElementsToFast(SeededNumberDictionary* source, |
FixedArray* destination, |
WriteBarrierMode mode) { |
int destination_length = destination->length(); |
@@ -8237,7 +8338,7 @@ |
case DICTIONARY_ELEMENTS: { |
AssertNoAllocation no_gc; |
WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc); |
- CopySlowElementsToFast(NumberDictionary::cast(old_elements_raw), |
+ CopySlowElementsToFast(SeededNumberDictionary::cast(old_elements_raw), |
new_elements, |
mode); |
set_map_and_elements(new_map, new_elements); |
@@ -8251,7 +8352,7 @@ |
FixedArray* parameter_map = FixedArray::cast(old_elements_raw); |
FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
if (arguments->IsDictionary()) { |
- CopySlowElementsToFast(NumberDictionary::cast(arguments), |
+ CopySlowElementsToFast(SeededNumberDictionary::cast(arguments), |
new_elements, |
mode); |
} else { |
@@ -8347,7 +8448,7 @@ |
break; |
} |
case DICTIONARY_ELEMENTS: { |
- elems->Initialize(NumberDictionary::cast(old_elements)); |
+ elems->Initialize(SeededNumberDictionary::cast(old_elements)); |
break; |
} |
default: |
@@ -8607,7 +8708,7 @@ |
} |
case DICTIONARY_ELEMENTS: { |
if (element_dictionary()->FindEntry(index) |
- != NumberDictionary::kNotFound) { |
+ != SeededNumberDictionary::kNotFound) { |
return true; |
} |
break; |
@@ -8745,7 +8846,7 @@ |
} |
case DICTIONARY_ELEMENTS: { |
if (element_dictionary()->FindEntry(index) != |
- NumberDictionary::kNotFound) { |
+ SeededNumberDictionary::kNotFound) { |
return DICTIONARY_ELEMENT; |
} |
break; |
@@ -8762,8 +8863,9 @@ |
// If not aliased, check the arguments. |
FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
if (arguments->IsDictionary()) { |
- NumberDictionary* dictionary = NumberDictionary::cast(arguments); |
- if (dictionary->FindEntry(index) != NumberDictionary::kNotFound) { |
+ SeededNumberDictionary* dictionary = |
+ SeededNumberDictionary::cast(arguments); |
+ if (dictionary->FindEntry(index) != SeededNumberDictionary::kNotFound) { |
return DICTIONARY_ELEMENT; |
} |
} else { |
@@ -8792,8 +8894,8 @@ |
return true; |
} |
} else { |
- if (NumberDictionary::cast(elements)->FindEntry(index) != |
- NumberDictionary::kNotFound) { |
+ if (SeededNumberDictionary::cast(elements)->FindEntry(index) != |
+ SeededNumberDictionary::kNotFound) { |
return true; |
} |
} |
@@ -8860,7 +8962,7 @@ |
} |
case DICTIONARY_ELEMENTS: { |
if (element_dictionary()->FindEntry(index) |
- != NumberDictionary::kNotFound) { |
+ != SeededNumberDictionary::kNotFound) { |
return true; |
} |
break; |
@@ -8964,8 +9066,8 @@ |
} |
// __defineGetter__ callback |
- if (structure->IsFixedArray()) { |
- Object* getter = FixedArray::cast(structure)->get(kGetterIndex); |
+ if (structure->IsAccessorPair()) { |
+ Object* getter = AccessorPair::cast(structure)->getter(); |
if (getter->IsSpecFunction()) { |
// TODO(rossberg): nicer would be to cast to some JSCallable here... |
return GetPropertyWithDefinedGetter(receiver, JSReceiver::cast(getter)); |
@@ -9021,8 +9123,8 @@ |
return *value_handle; |
} |
- if (structure->IsFixedArray()) { |
- Handle<Object> setter(FixedArray::cast(structure)->get(kSetterIndex)); |
+ if (structure->IsAccessorPair()) { |
+ Handle<Object> setter(AccessorPair::cast(structure)->setter()); |
if (setter->IsSpecFunction()) { |
// TODO(rossberg): nicer would be to cast to some JSCallable here... |
return SetPropertyWithDefinedSetter(JSReceiver::cast(*setter), value); |
@@ -9183,15 +9285,15 @@ |
FixedArray* elements = FixedArray::cast(this->elements()); |
bool is_arguments = |
(elements->map() == heap->non_strict_arguments_elements_map()); |
- NumberDictionary* dictionary = NULL; |
+ SeededNumberDictionary* dictionary = NULL; |
if (is_arguments) { |
- dictionary = NumberDictionary::cast(elements->get(1)); |
+ dictionary = SeededNumberDictionary::cast(elements->get(1)); |
} else { |
- dictionary = NumberDictionary::cast(elements); |
+ dictionary = SeededNumberDictionary::cast(elements); |
} |
int entry = dictionary->FindEntry(index); |
- if (entry != NumberDictionary::kNotFound) { |
+ if (entry != SeededNumberDictionary::kNotFound) { |
Object* element = dictionary->ValueAt(entry); |
PropertyDetails details = dictionary->DetailsAt(entry); |
if (details.type() == CALLBACKS) { |
@@ -9236,13 +9338,13 @@ |
FixedArrayBase* new_dictionary; |
MaybeObject* maybe = dictionary->AtNumberPut(index, value); |
if (!maybe->To<FixedArrayBase>(&new_dictionary)) return maybe; |
- if (dictionary != NumberDictionary::cast(new_dictionary)) { |
+ if (dictionary != SeededNumberDictionary::cast(new_dictionary)) { |
if (is_arguments) { |
elements->set(1, new_dictionary); |
} else { |
set_elements(new_dictionary); |
} |
- dictionary = NumberDictionary::cast(new_dictionary); |
+ dictionary = SeededNumberDictionary::cast(new_dictionary); |
} |
} |
@@ -9388,6 +9490,35 @@ |
} |
+Handle<Object> JSObject::SetOwnElement(Handle<JSObject> object, |
+ uint32_t index, |
+ Handle<Object> value, |
+ StrictModeFlag strict_mode) { |
+ ASSERT(!object->HasExternalArrayElements()); |
+ CALL_HEAP_FUNCTION(object->GetIsolate(), |
+ object->SetElement(index, *value, strict_mode, false), |
+ Object); |
+} |
+ |
+ |
+Handle<Object> JSObject::SetElement(Handle<JSObject> object, |
+ uint32_t index, |
+ Handle<Object> value, |
+ StrictModeFlag strict_mode) { |
+ if (object->HasExternalArrayElements()) { |
+ if (!value->IsSmi() && !value->IsHeapNumber() && !value->IsUndefined()) { |
+ bool has_exception; |
+ Handle<Object> number = Execution::ToNumber(value, &has_exception); |
+ if (has_exception) return Handle<Object>(); |
+ value = number; |
+ } |
+ } |
+ CALL_HEAP_FUNCTION(object->GetIsolate(), |
+ object->SetElement(index, *value, strict_mode, true), |
+ Object); |
+} |
+ |
+ |
MaybeObject* JSObject::SetElement(uint32_t index, |
Object* value, |
StrictModeFlag strict_mode, |
@@ -9510,6 +9641,14 @@ |
} |
+Handle<Object> JSObject::TransitionElementsKind(Handle<JSObject> object, |
+ ElementsKind to_kind) { |
+ CALL_HEAP_FUNCTION(object->GetIsolate(), |
+ object->TransitionElementsKind(to_kind), |
+ Object); |
+} |
+ |
+ |
MUST_USE_RESULT MaybeObject* JSObject::TransitionElementsKind( |
ElementsKind to_kind) { |
ElementsKind from_kind = map()->elements_kind(); |
@@ -9653,7 +9792,8 @@ |
FixedArray::cast(FixedArray::cast(backing_store_base)->get(1)); |
backing_store = FixedArray::cast(backing_store_base); |
if (backing_store->IsDictionary()) { |
- NumberDictionary* dictionary = NumberDictionary::cast(backing_store); |
+ SeededNumberDictionary* dictionary = |
+ SeededNumberDictionary::cast(backing_store); |
*capacity = dictionary->Capacity(); |
*used = dictionary->NumberOfElements(); |
break; |
@@ -9668,8 +9808,8 @@ |
} |
break; |
case DICTIONARY_ELEMENTS: { |
- NumberDictionary* dictionary = |
- NumberDictionary::cast(FixedArray::cast(elements())); |
+ SeededNumberDictionary* dictionary = |
+ SeededNumberDictionary::cast(FixedArray::cast(elements())); |
*capacity = dictionary->Capacity(); |
*used = dictionary->NumberOfElements(); |
break; |
@@ -9714,8 +9854,8 @@ |
int old_capacity = 0; |
int used_elements = 0; |
GetElementsCapacityAndUsage(&old_capacity, &used_elements); |
- int dictionary_size = NumberDictionary::ComputeCapacity(used_elements) * |
- NumberDictionary::kEntrySize; |
+ int dictionary_size = SeededNumberDictionary::ComputeCapacity(used_elements) * |
+ SeededNumberDictionary::kEntrySize; |
return 3 * dictionary_size <= new_capacity; |
} |
@@ -9729,11 +9869,11 @@ |
if (IsAccessCheckNeeded()) return false; |
FixedArray* elements = FixedArray::cast(this->elements()); |
- NumberDictionary* dictionary = NULL; |
+ SeededNumberDictionary* dictionary = NULL; |
if (elements->map() == GetHeap()->non_strict_arguments_elements_map()) { |
- dictionary = NumberDictionary::cast(elements->get(1)); |
+ dictionary = SeededNumberDictionary::cast(elements->get(1)); |
} else { |
- dictionary = NumberDictionary::cast(elements); |
+ dictionary = SeededNumberDictionary::cast(elements); |
} |
// If an element has been added at a very high index in the elements |
// dictionary, we cannot go back to fast case. |
@@ -9748,7 +9888,7 @@ |
array_size = dictionary->max_number_key(); |
} |
uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) * |
- NumberDictionary::kEntrySize; |
+ SeededNumberDictionary::kEntrySize; |
return 2 * dictionary_size >= array_size; |
} |
@@ -9758,7 +9898,8 @@ |
*has_smi_only_elements = false; |
if (FLAG_unbox_double_arrays) { |
ASSERT(HasDictionaryElements()); |
- NumberDictionary* dictionary = NumberDictionary::cast(elements()); |
+ SeededNumberDictionary* dictionary = |
+ SeededNumberDictionary::cast(elements()); |
bool found_double = false; |
for (int i = 0; i < dictionary->Capacity(); i++) { |
Object* key = dictionary->KeyAt(i); |
@@ -9978,7 +10119,7 @@ |
} |
case DICTIONARY_ELEMENTS: { |
return element_dictionary()->FindEntry(index) |
- != NumberDictionary::kNotFound; |
+ != SeededNumberDictionary::kNotFound; |
} |
case NON_STRICT_ARGUMENTS_ELEMENTS: |
UNIMPLEMENTED(); |
@@ -10247,7 +10388,7 @@ |
if (storage != NULL) { |
element_dictionary()->CopyKeysTo(storage, |
filter, |
- NumberDictionary::SORTED); |
+ SeededNumberDictionary::SORTED); |
} |
counter += element_dictionary()->NumberOfElementsFilterAttributes(filter); |
break; |
@@ -10259,9 +10400,11 @@ |
if (arguments->IsDictionary()) { |
// Copy the keys from arguments first, because Dictionary::CopyKeysTo |
// will insert in storage starting at index 0. |
- NumberDictionary* dictionary = NumberDictionary::cast(arguments); |
+ SeededNumberDictionary* dictionary = |
+ SeededNumberDictionary::cast(arguments); |
if (storage != NULL) { |
- dictionary->CopyKeysTo(storage, filter, NumberDictionary::UNSORTED); |
+ dictionary->CopyKeysTo( |
+ storage, filter, SeededNumberDictionary::UNSORTED); |
} |
counter += dictionary->NumberOfElementsFilterAttributes(filter); |
for (int i = 0; i < mapped_length; ++i) { |
@@ -10585,7 +10728,7 @@ |
uint32_t Hash() { |
ASSERT(length_ >= 0); |
ASSERT(from_ + length_ <= string_->length()); |
- StringHasher hasher(length_, string_->GetHeap()->StringHashSeed()); |
+ StringHasher hasher(length_, string_->GetHeap()->HashSeed()); |
// Very long strings have a trivial hash that doesn't inspect the |
// string contents. |
@@ -10794,7 +10937,7 @@ |
uint32_t from_index = EntryToIndex(i); |
Object* k = get(from_index); |
if (IsKey(k)) { |
- uint32_t hash = Shape::HashForObject(key, k); |
+ uint32_t hash = HashTable<Shape, Key>::HashForObject(key, k); |
uint32_t insertion_index = |
EntryToIndex(new_table->FindInsertionEntry(hash)); |
for (int j = 0; j < Shape::kEntrySize; j++) { |
@@ -10892,38 +11035,46 @@ |
template class Dictionary<StringDictionaryShape, String*>; |
-template class Dictionary<NumberDictionaryShape, uint32_t>; |
+template class Dictionary<SeededNumberDictionaryShape, uint32_t>; |
-template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>::Allocate( |
- int); |
+template class Dictionary<UnseededNumberDictionaryShape, uint32_t>; |
+template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>:: |
+ Allocate(int at_least_space_for); |
+ |
+template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>:: |
+ Allocate(int at_least_space_for); |
+ |
template MaybeObject* Dictionary<StringDictionaryShape, String*>::Allocate( |
int); |
-template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>::AtPut( |
+template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::AtPut( |
uint32_t, Object*); |
-template Object* Dictionary<NumberDictionaryShape, uint32_t>::SlowReverseLookup( |
- Object*); |
+template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>:: |
+ AtPut(uint32_t, Object*); |
+template Object* Dictionary<UnseededNumberDictionaryShape, uint32_t>:: |
+ SlowReverseLookup(Object* value); |
+ |
template Object* Dictionary<StringDictionaryShape, String*>::SlowReverseLookup( |
Object*); |
-template void Dictionary<NumberDictionaryShape, uint32_t>::CopyKeysTo( |
+template void Dictionary<SeededNumberDictionaryShape, uint32_t>::CopyKeysTo( |
FixedArray*, |
PropertyAttributes, |
- Dictionary<NumberDictionaryShape, uint32_t>::SortMode); |
+ Dictionary<SeededNumberDictionaryShape, uint32_t>::SortMode); |
template Object* Dictionary<StringDictionaryShape, String*>::DeleteProperty( |
int, JSObject::DeleteMode); |
-template Object* Dictionary<NumberDictionaryShape, uint32_t>::DeleteProperty( |
- int, JSObject::DeleteMode); |
+template Object* Dictionary<SeededNumberDictionaryShape, uint32_t>:: |
+ DeleteProperty(int, JSObject::DeleteMode); |
template MaybeObject* Dictionary<StringDictionaryShape, String*>::Shrink( |
String*); |
-template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>::Shrink( |
+template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::Shrink( |
uint32_t); |
template void Dictionary<StringDictionaryShape, String*>::CopyKeysTo( |
@@ -10942,32 +11093,41 @@ |
Dictionary<StringDictionaryShape, String*>::GenerateNewEnumerationIndices(); |
template int |
-Dictionary<NumberDictionaryShape, uint32_t>::NumberOfElementsFilterAttributes( |
- PropertyAttributes); |
+Dictionary<SeededNumberDictionaryShape, uint32_t>:: |
+ NumberOfElementsFilterAttributes(PropertyAttributes); |
-template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>::Add( |
+template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::Add( |
uint32_t, Object*, PropertyDetails); |
-template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>:: |
+template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>::Add( |
+ uint32_t, Object*, PropertyDetails); |
+ |
+template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>:: |
EnsureCapacity(int, uint32_t); |
+template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>:: |
+ EnsureCapacity(int, uint32_t); |
+ |
template MaybeObject* Dictionary<StringDictionaryShape, String*>:: |
EnsureCapacity(int, String*); |
-template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>::AddEntry( |
- uint32_t, Object*, PropertyDetails, uint32_t); |
+template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>:: |
+ AddEntry(uint32_t, Object*, PropertyDetails, uint32_t); |
+template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>:: |
+ AddEntry(uint32_t, Object*, PropertyDetails, uint32_t); |
+ |
template MaybeObject* Dictionary<StringDictionaryShape, String*>::AddEntry( |
String*, Object*, PropertyDetails, uint32_t); |
template |
-int Dictionary<NumberDictionaryShape, uint32_t>::NumberOfEnumElements(); |
+int Dictionary<SeededNumberDictionaryShape, uint32_t>::NumberOfEnumElements(); |
template |
int Dictionary<StringDictionaryShape, String*>::NumberOfEnumElements(); |
template |
-int HashTable<NumberDictionaryShape, uint32_t>::FindEntry(uint32_t); |
+int HashTable<SeededNumberDictionaryShape, uint32_t>::FindEntry(uint32_t); |
// Collates undefined and unexisting elements below limit from position |
@@ -10977,7 +11137,7 @@ |
// Must stay in dictionary mode, either because of requires_slow_elements, |
// or because we are not going to sort (and therefore compact) all of the |
// elements. |
- NumberDictionary* dict = element_dictionary(); |
+ SeededNumberDictionary* dict = element_dictionary(); |
HeapNumber* result_double = NULL; |
if (limit > static_cast<uint32_t>(Smi::kMaxValue)) { |
// Allocate space for result before we start mutating the object. |
@@ -10990,10 +11150,10 @@ |
Object* obj; |
{ MaybeObject* maybe_obj = |
- NumberDictionary::Allocate(dict->NumberOfElements()); |
+ SeededNumberDictionary::Allocate(dict->NumberOfElements()); |
if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
} |
- NumberDictionary* new_dict = NumberDictionary::cast(obj); |
+ SeededNumberDictionary* new_dict = SeededNumberDictionary::cast(obj); |
AssertNoAllocation no_alloc; |
@@ -11077,7 +11237,7 @@ |
if (HasDictionaryElements()) { |
// Convert to fast elements containing only the existing properties. |
// Ordering is irrelevant, since we are going to sort anyway. |
- NumberDictionary* dict = element_dictionary(); |
+ SeededNumberDictionary* dict = element_dictionary(); |
if (IsJSArray() || dict->requires_slow_elements() || |
dict->max_number_key() >= limit) { |
return PrepareSlowElementsForSort(limit); |
@@ -11444,7 +11604,7 @@ |
hash += hash << 3; |
hash ^= hash >> 11; |
hash += hash << 15; |
- if ((hash & String::kHashBitMask) == 0) hash = 27; |
+ if ((hash & String::kHashBitMask) == 0) hash = String::kZeroHash; |
#ifdef DEBUG |
StringHasher hasher(2, seed); |
hasher.AddCharacter(c1); |
@@ -11503,7 +11663,7 @@ |
bool SymbolTable::LookupTwoCharsSymbolIfExists(uint32_t c1, |
uint32_t c2, |
String** symbol) { |
- TwoCharHashTableKey key(c1, c2, GetHeap()->StringHashSeed()); |
+ TwoCharHashTableKey key(c1, c2, GetHeap()->HashSeed()); |
int entry = FindEntry(&key); |
if (entry == kNotFound) { |
return false; |
@@ -11518,14 +11678,14 @@ |
MaybeObject* SymbolTable::LookupSymbol(Vector<const char> str, |
Object** s) { |
- Utf8SymbolKey key(str, GetHeap()->StringHashSeed()); |
+ Utf8SymbolKey key(str, GetHeap()->HashSeed()); |
return LookupKey(&key, s); |
} |
MaybeObject* SymbolTable::LookupAsciiSymbol(Vector<const char> str, |
Object** s) { |
- AsciiSymbolKey key(str, GetHeap()->StringHashSeed()); |
+ AsciiSymbolKey key(str, GetHeap()->HashSeed()); |
return LookupKey(&key, s); |
} |
@@ -11534,14 +11694,14 @@ |
int from, |
int length, |
Object** s) { |
- SubStringAsciiSymbolKey key(str, from, length, GetHeap()->StringHashSeed()); |
+ SubStringAsciiSymbolKey key(str, from, length, GetHeap()->HashSeed()); |
return LookupKey(&key, s); |
} |
MaybeObject* SymbolTable::LookupTwoByteSymbol(Vector<const uc16> str, |
Object** s) { |
- TwoByteSymbolKey key(str, GetHeap()->StringHashSeed()); |
+ TwoByteSymbolKey key(str, GetHeap()->HashSeed()); |
return LookupKey(&key, s); |
} |
@@ -11880,8 +12040,9 @@ |
if (!maybe_k->ToObject(&k)) return maybe_k; |
} |
PropertyDetails details = PropertyDetails(NONE, NORMAL); |
- return Dictionary<Shape, Key>::cast(obj)-> |
- AddEntry(key, value, details, Shape::Hash(key)); |
+ |
+ return Dictionary<Shape, Key>::cast(obj)->AddEntry(key, value, details, |
+ Dictionary<Shape, Key>::Hash(key)); |
} |
@@ -11896,8 +12057,9 @@ |
{ MaybeObject* maybe_obj = EnsureCapacity(1, key); |
if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
} |
- return Dictionary<Shape, Key>::cast(obj)-> |
- AddEntry(key, value, details, Shape::Hash(key)); |
+ |
+ return Dictionary<Shape, Key>::cast(obj)->AddEntry(key, value, details, |
+ Dictionary<Shape, Key>::Hash(key)); |
} |
@@ -11930,7 +12092,7 @@ |
} |
-void NumberDictionary::UpdateMaxNumberKey(uint32_t key) { |
+void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key) { |
// If the dictionary requires slow elements an element has already |
// been added at a high index. |
if (requires_slow_elements()) return; |
@@ -11949,31 +12111,65 @@ |
} |
-MaybeObject* NumberDictionary::AddNumberEntry(uint32_t key, |
- Object* value, |
- PropertyDetails details) { |
+MaybeObject* SeededNumberDictionary::AddNumberEntry(uint32_t key, |
+ Object* value, |
+ PropertyDetails details) { |
UpdateMaxNumberKey(key); |
SLOW_ASSERT(this->FindEntry(key) == kNotFound); |
return Add(key, value, details); |
} |
-MaybeObject* NumberDictionary::AtNumberPut(uint32_t key, Object* value) { |
+MaybeObject* UnseededNumberDictionary::AddNumberEntry(uint32_t key, |
+ Object* value) { |
+ SLOW_ASSERT(this->FindEntry(key) == kNotFound); |
+ return Add(key, value, PropertyDetails(NONE, NORMAL)); |
+} |
+ |
+ |
+MaybeObject* SeededNumberDictionary::AtNumberPut(uint32_t key, Object* value) { |
UpdateMaxNumberKey(key); |
return AtPut(key, value); |
} |
-MaybeObject* NumberDictionary::Set(uint32_t key, |
- Object* value, |
- PropertyDetails details) { |
+MaybeObject* UnseededNumberDictionary::AtNumberPut(uint32_t key, |
+ Object* value) { |
+ return AtPut(key, value); |
+} |
+ |
+ |
+Handle<SeededNumberDictionary> SeededNumberDictionary::Set( |
+ Handle<SeededNumberDictionary> dictionary, |
+ uint32_t index, |
+ Handle<Object> value, |
+ PropertyDetails details) { |
+ CALL_HEAP_FUNCTION(dictionary->GetIsolate(), |
+ dictionary->Set(index, *value, details), |
+ SeededNumberDictionary); |
+} |
+ |
+ |
+Handle<UnseededNumberDictionary> UnseededNumberDictionary::Set( |
+ Handle<UnseededNumberDictionary> dictionary, |
+ uint32_t index, |
+ Handle<Object> value) { |
+ CALL_HEAP_FUNCTION(dictionary->GetIsolate(), |
+ dictionary->Set(index, *value), |
+ UnseededNumberDictionary); |
+} |
+ |
+ |
+MaybeObject* SeededNumberDictionary::Set(uint32_t key, |
+ Object* value, |
+ PropertyDetails details) { |
int entry = FindEntry(key); |
if (entry == kNotFound) return AddNumberEntry(key, value, details); |
// Preserve enumeration index. |
details = PropertyDetails(details.attributes(), |
details.type(), |
DetailsAt(entry).index()); |
- MaybeObject* maybe_object_key = NumberDictionaryShape::AsObject(key); |
+ MaybeObject* maybe_object_key = SeededNumberDictionaryShape::AsObject(key); |
Object* object_key; |
if (!maybe_object_key->ToObject(&object_key)) return maybe_object_key; |
SetEntry(entry, object_key, value, details); |
@@ -11981,7 +12177,19 @@ |
} |
+MaybeObject* UnseededNumberDictionary::Set(uint32_t key, |
+ Object* value) { |
+ int entry = FindEntry(key); |
+ if (entry == kNotFound) return AddNumberEntry(key, value); |
+ MaybeObject* maybe_object_key = UnseededNumberDictionaryShape::AsObject(key); |
+ Object* object_key; |
+ if (!maybe_object_key->ToObject(&object_key)) return maybe_object_key; |
+ SetEntry(entry, object_key, value); |
+ return this; |
+} |
+ |
+ |
template<typename Shape, typename Key> |
int Dictionary<Shape, Key>::NumberOfElementsFilterAttributes( |
PropertyAttributes filter) { |