Commit b2e8d72b authored by whesse@chromium.org's avatar whesse@chromium.org

Revert r8619 because of Webkit failures.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8628 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent f1860fbd
......@@ -3085,7 +3085,39 @@ int v8::Object::GetIdentityHash() {
ENTER_V8(isolate);
i::HandleScope scope(isolate);
i::Handle<i::JSObject> self = Utils::OpenHandle(this);
return i::GetIdentityHash(self)->value();
i::Handle<i::Object> hidden_props_obj(i::GetHiddenProperties(self, true));
if (!hidden_props_obj->IsJSObject()) {
// We failed to create hidden properties. That's a detached
// global proxy.
ASSERT(hidden_props_obj->IsUndefined());
return 0;
}
i::Handle<i::JSObject> hidden_props =
i::Handle<i::JSObject>::cast(hidden_props_obj);
i::Handle<i::String> hash_symbol = isolate->factory()->identity_hash_symbol();
if (hidden_props->HasLocalProperty(*hash_symbol)) {
i::Handle<i::Object> hash = i::GetProperty(hidden_props, hash_symbol);
CHECK(!hash.is_null());
CHECK(hash->IsSmi());
return i::Smi::cast(*hash)->value();
}
int hash_value;
int attempts = 0;
do {
// Generate a random 32-bit hash value but limit range to fit
// within a smi.
hash_value = i::V8::Random(self->GetIsolate()) & i::Smi::kMaxValue;
attempts++;
} while (hash_value == 0 && attempts < 30);
hash_value = hash_value != 0 ? hash_value : 1; // never return 0
CHECK(!i::SetLocalPropertyIgnoreAttributes(
hidden_props,
hash_symbol,
i::Handle<i::Object>(i::Smi::FromInt(hash_value)),
static_cast<PropertyAttributes>(None)).is_null());
return hash_value;
}
......
......@@ -427,14 +427,38 @@ Handle<Object> GetHiddenProperties(Handle<JSObject> obj,
Object* holder = obj->BypassGlobalProxy();
if (holder->IsUndefined()) return isolate->factory()->undefined_value();
obj = Handle<JSObject>(JSObject::cast(holder), isolate);
CALL_HEAP_FUNCTION(isolate,
obj->GetHiddenProperties(create_if_needed),
Object);
}
if (obj->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 = obj->map()->instance_descriptors();
if ((descriptors->number_of_descriptors() > 0) &&
(descriptors->GetKey(0) == isolate->heap()->hidden_symbol()) &&
descriptors->IsProperty(0)) {
ASSERT(descriptors->GetType(0) == FIELD);
return Handle<Object>(obj->FastPropertyAt(descriptors->GetFieldIndex(0)),
isolate);
}
}
Handle<Smi> GetIdentityHash(Handle<JSObject> obj) {
CALL_HEAP_FUNCTION(obj->GetIsolate(), obj->GetIdentityHash(), Smi);
// 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 (!obj->HasHiddenPropertiesObject()) {
// Hidden properties object not found. Allocate a new hidden properties
// object if requested. Otherwise return the undefined value.
if (create_if_needed) {
Handle<Object> hidden_obj =
isolate->factory()->NewJSObject(isolate->object_function());
CALL_HEAP_FUNCTION(isolate,
obj->SetHiddenPropertiesObject(*hidden_obj), Object);
} else {
return isolate->factory()->undefined_value();
}
}
return Handle<Object>(obj->GetHiddenPropertiesObject(), isolate);
}
......
......@@ -268,8 +268,6 @@ Handle<Object> SetPrototype(Handle<JSObject> obj, Handle<Object> value);
// will be allocated. Otherwise the Heap::undefined_value is returned.
Handle<Object> GetHiddenProperties(Handle<JSObject> obj, bool create_if_needed);
Handle<Smi> GetIdentityHash(Handle<JSObject> obj);
Handle<Object> DeleteElement(Handle<JSObject> obj, uint32_t index);
Handle<Object> DeleteProperty(Handle<JSObject> obj, Handle<String> prop);
......
......@@ -4302,32 +4302,6 @@ MaybeObject* StringDictionaryShape::AsObject(String* key) {
}
bool ObjectDictionaryShape::IsMatch(JSObject* key, Object* other) {
ASSERT(other->IsJSObject());
return key == JSObject::cast(other);
}
uint32_t ObjectDictionaryShape::Hash(JSObject* key) {
MaybeObject* maybe_hash = key->GetIdentityHash();
ASSERT(!maybe_hash->IsFailure());
return Smi::cast(maybe_hash->ToObjectUnchecked())->value();
}
uint32_t ObjectDictionaryShape::HashForObject(JSObject* key, Object* other) {
ASSERT(other->IsJSObject());
MaybeObject* maybe_hash = JSObject::cast(other)->GetIdentityHash();
ASSERT(!maybe_hash->IsFailure());
return Smi::cast(maybe_hash->ToObjectUnchecked())->value();
}
MaybeObject* ObjectDictionaryShape::AsObject(JSObject* key) {
return key;
}
void Map::ClearCodeCache(Heap* heap) {
// No write barrier is needed since empty_fixed_array is not in new space.
// Please note this function is used during marking:
......
......@@ -2890,84 +2890,6 @@ 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.
......@@ -10213,17 +10135,12 @@ 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*);
......@@ -10261,9 +10178,6 @@ 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();
......@@ -11223,8 +11137,7 @@ 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)->IsJSObject()));
|| Dictionary<Shape, Key>::KeyAt(entry)->IsString()));
HashTable<Shape, Key>::ElementAdded();
return this;
}
......@@ -11529,15 +11442,6 @@ 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) {
......
......@@ -1640,11 +1640,6 @@ class JSObject: public JSReceiver {
MUST_USE_RESULT inline MaybeObject* SetHiddenPropertiesObject(
Object* hidden_obj);
MUST_USE_RESULT MaybeObject* GetHiddenProperties(bool create_if_needed);
// Retrieves a permanent object identity hash code.
MUST_USE_RESULT MaybeObject* GetIdentityHash();
MUST_USE_RESULT MaybeObject* DeleteProperty(String* name, DeleteMode mode);
MUST_USE_RESULT MaybeObject* DeleteElement(uint32_t index, DeleteMode mode);
......@@ -2926,29 +2921,6 @@ class NumberDictionary: public Dictionary<NumberDictionaryShape, uint32_t> {
};
class ObjectDictionaryShape {
public:
static inline bool IsMatch(JSObject* key, Object* other);
static inline uint32_t Hash(JSObject* key);
static inline uint32_t HashForObject(JSObject* key, Object* object);
MUST_USE_RESULT static inline MaybeObject* AsObject(JSObject* key);
static const int kPrefixSize = 2;
static const int kEntrySize = 3;
static const bool kIsEnumerable = false;
};
class ObjectDictionary: public Dictionary<ObjectDictionaryShape, JSObject*> {
public:
static inline ObjectDictionary* cast(Object* obj) {
ASSERT(obj->IsDictionary());
return reinterpret_cast<ObjectDictionary*>(obj);
}
MUST_USE_RESULT MaybeObject* AddChecked(JSObject* key, Object* value);
};
// JSFunctionResultCache caches results of some JSFunction invocation.
// It is a fixed array with fixed structure:
// [0]: factory function
......
......@@ -51,7 +51,6 @@ SOURCES = {
'test-debug.cc',
'test-decls.cc',
'test-deoptimization.cc',
'test-dictionary.cc',
'test-diy-fp.cc',
'test-double.cc',
'test-dtoa.cc',
......
......@@ -56,7 +56,6 @@
'test-debug.cc',
'test-decls.cc',
'test-deoptimization.cc',
'test-dictionary.cc',
'test-diy-fp.cc',
'test-double.cc',
'test-dtoa.cc',
......
// 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:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "v8.h"
#include "api.h"
#include "debug.h"
#include "execution.h"
#include "factory.h"
#include "macro-assembler.h"
#include "objects.h"
#include "global-handles.h"
#include "cctest.h"
using namespace v8::internal;
static Handle<ObjectDictionary> NewObjectDictionary(int at_least_space_for) {
ASSERT(0 <= at_least_space_for);
CALL_HEAP_FUNCTION(Isolate::Current(),
ObjectDictionary::Allocate(at_least_space_for),
ObjectDictionary);
}
TEST(ObjectDictionary) {
v8::HandleScope scope;
LocalContext context;
Handle<ObjectDictionary> dict = NewObjectDictionary(23);
Handle<JSObject> a = FACTORY->NewJSArray(7);
Handle<JSObject> b = FACTORY->NewJSArray(11);
MaybeObject* result = dict->AddChecked(*a, *b);
CHECK(!result->IsFailure());
CHECK_NE(dict->FindEntry(*a), ObjectDictionary::kNotFound);
CHECK_EQ(dict->FindEntry(*b), ObjectDictionary::kNotFound);
// Keys still have to be valid after objects were moved.
HEAP->CollectGarbage(NEW_SPACE);
CHECK_NE(dict->FindEntry(*a), ObjectDictionary::kNotFound);
CHECK_EQ(dict->FindEntry(*b), ObjectDictionary::kNotFound);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment