Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index 4d70b32147318bdd8f27add24dac5245c1dd8230..fc6596ccd404af15056f923097049f35da83883d 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -2894,6 +2894,84 @@ MaybeObject* JSObject::NormalizeElements() { |
} |
+MaybeObject* JSObject::GetHiddenProperties(bool create_if_needed) { |
+ Isolate* isolate = GetIsolate(); |
+ Heap* heap = isolate->heap(); |
+ if (HasFastProperties()) { |
+ // If the object has fast properties, check whether the first slot |
+ // in the descriptor array matches the hidden symbol. Since the |
+ // hidden symbols hash code is zero (and no other string has hash |
+ // code zero) it will always occupy the first entry if present. |
+ DescriptorArray* descriptors = map()->instance_descriptors(); |
+ if ((descriptors->number_of_descriptors() > 0) && |
+ (descriptors->GetKey(0) == heap->hidden_symbol()) && |
+ descriptors->IsProperty(0)) { |
+ ASSERT(descriptors->GetType(0) == FIELD); |
+ return FastPropertyAt(descriptors->GetFieldIndex(0)); |
+ } |
+ } |
+ |
+ // Only attempt to find the hidden properties in the local object and not |
+ // in the prototype chain. Note that HasLocalProperty() can cause a GC in |
+ // the general case in the presence of interceptors. |
+ if (!HasHiddenPropertiesObject()) { |
+ // Hidden properties object not found. Allocate a new hidden properties |
+ // object if requested. Otherwise return the undefined value. |
+ if (create_if_needed) { |
+ Object* hidden_obj; |
+ { MaybeObject* maybe_obj = heap->AllocateJSObject( |
+ isolate->context()->global_context()->object_function()); |
+ if (!maybe_obj->ToObject(&hidden_obj)) return maybe_obj; |
+ } |
+ return SetHiddenPropertiesObject(hidden_obj); |
+ } else { |
+ return heap->undefined_value(); |
+ } |
+ } |
+ return GetHiddenPropertiesObject(); |
+} |
+ |
+ |
+MaybeObject* JSObject::GetIdentityHash() { |
+ Isolate* isolate = GetIsolate(); |
+ Object* hidden_props_obj; |
+ { MaybeObject* maybe_obj = GetHiddenProperties(true); |
+ if (!maybe_obj->ToObject(&hidden_props_obj)) return maybe_obj; |
+ } |
+ if (!hidden_props_obj->IsJSObject()) { |
+ // We failed to create hidden properties. That's a detached |
+ // global proxy. |
+ ASSERT(hidden_props_obj->IsUndefined()); |
+ return Smi::FromInt(0); |
+ } |
+ JSObject* hidden_props = JSObject::cast(hidden_props_obj); |
+ String* hash_symbol = isolate->heap()->identity_hash_symbol(); |
+ if (hidden_props->HasLocalProperty(hash_symbol)) { |
+ MaybeObject* hash = hidden_props->GetProperty(hash_symbol); |
+ return Smi::cast(hash->ToObjectChecked()); |
+ } |
+ |
+ int hash_value; |
+ int attempts = 0; |
+ do { |
+ // Generate a random 32-bit hash value but limit range to fit |
+ // within a smi. |
+ hash_value = V8::Random(isolate) & Smi::kMaxValue; |
+ attempts++; |
+ } while (hash_value == 0 && attempts < 30); |
+ hash_value = hash_value != 0 ? hash_value : 1; // never return 0 |
+ |
+ Smi* hash = Smi::FromInt(hash_value); |
+ { MaybeObject* result = hidden_props->SetLocalPropertyIgnoreAttributes( |
+ hash_symbol, |
+ hash, |
+ static_cast<PropertyAttributes>(None)); |
+ if (result->IsFailure()) return result; |
+ } |
+ return hash; |
+} |
+ |
+ |
MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name, |
DeleteMode mode) { |
// Check local property, ignore interceptor. |
@@ -10138,12 +10216,17 @@ template class Dictionary<StringDictionaryShape, String*>; |
template class Dictionary<NumberDictionaryShape, uint32_t>; |
+template class Dictionary<ObjectDictionaryShape, JSObject*>; |
+ |
template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>::Allocate( |
int); |
template MaybeObject* Dictionary<StringDictionaryShape, String*>::Allocate( |
int); |
+template MaybeObject* Dictionary<ObjectDictionaryShape, JSObject*>::Allocate( |
+ int); |
+ |
template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>::AtPut( |
uint32_t, Object*); |
@@ -10181,6 +10264,9 @@ Dictionary<StringDictionaryShape, String*>::NumberOfElementsFilterAttributes( |
template MaybeObject* Dictionary<StringDictionaryShape, String*>::Add( |
String*, Object*, PropertyDetails); |
+template MaybeObject* Dictionary<ObjectDictionaryShape, JSObject*>::Add( |
+ JSObject*, Object*, PropertyDetails); |
+ |
template MaybeObject* |
Dictionary<StringDictionaryShape, String*>::GenerateNewEnumerationIndices(); |
@@ -11140,7 +11226,8 @@ MaybeObject* Dictionary<Shape, Key>::AddEntry(Key key, |
} |
SetEntry(entry, k, value, details); |
ASSERT((Dictionary<Shape, Key>::KeyAt(entry)->IsNumber() |
- || Dictionary<Shape, Key>::KeyAt(entry)->IsString())); |
+ || Dictionary<Shape, Key>::KeyAt(entry)->IsString() |
+ || Dictionary<Shape, Key>::KeyAt(entry)->IsJSObject())); |
HashTable<Shape, Key>::ElementAdded(); |
return this; |
} |
@@ -11445,6 +11532,15 @@ MaybeObject* StringDictionary::TransformPropertiesToFastFor( |
} |
+MaybeObject* ObjectDictionary::AddChecked(JSObject* key, Object* value) { |
+ // Make sure the key object has an identity hash code. |
+ MaybeObject* maybe_hash = key->GetIdentityHash(); |
+ if (maybe_hash->IsFailure()) return maybe_hash; |
+ PropertyDetails details(NONE, NORMAL); |
+ return Add(key, value, details); |
+} |
+ |
+ |
#ifdef ENABLE_DEBUGGER_SUPPORT |
// Check if there is a break point at this code position. |
bool DebugInfo::HasBreakPoint(int code_position) { |