| 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) {
|
|
|