Revision: 9396
Author: [email protected]
Date: Thu Sep 22 06:54:53 2011
Log: Implement identity hashes for proxies.
[email protected]
BUG=v8:1543,v8:1565
TEST=
Review URL: http://codereview.chromium.org/7754015
http://code.google.com/p/v8/source/detail?r=9396
Added:
/branches/bleeding_edge/test/mjsunit/harmony/proxies-hash.js
Modified:
/branches/bleeding_edge/src/api.cc
/branches/bleeding_edge/src/handles.cc
/branches/bleeding_edge/src/handles.h
/branches/bleeding_edge/src/heap.cc
/branches/bleeding_edge/src/heap.h
/branches/bleeding_edge/src/objects-debug.cc
/branches/bleeding_edge/src/objects-inl.h
/branches/bleeding_edge/src/objects-printer.cc
/branches/bleeding_edge/src/objects.cc
/branches/bleeding_edge/src/objects.h
/branches/bleeding_edge/src/runtime.cc
/branches/bleeding_edge/test/mjsunit/harmony/proxies.js
=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/harmony/proxies-hash.js Thu Sep 22
06:54:53 2011
@@ -0,0 +1,66 @@
+// 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.
+
+// Flags: --harmony-proxies --harmony-weakmaps
+
+
+// Helper.
+
+function TestWithProxies(test, handler) {
+ test(handler, Proxy.create)
+ test(handler, function(h) {return Proxy.createFunction(h, function()
{})})
+}
+
+
+// Weak maps.
+
+function TestWeakMap(fix) {
+ TestWithProxies(TestWeakMap2, fix)
+}
+
+function TestWeakMap2(fix, create) {
+ var handler = {fix: function() { return {} }}
+ var p1 = create(handler)
+ var p2 = create(handler)
+ var p3 = create(handler)
+ fix(p3)
+
+ var m = new WeakMap
+ m.set(p1, 123);
+ m.set(p2, 321);
+ assertSame(123, m.get(p1));
+ assertSame(321, m.get(p2));
+
+ fix(p1)
+ fix(p2)
+ assertSame(123, m.get(p1));
+ assertSame(321, m.get(p2));
+}
+
+TestWeakMap(Object.seal)
+TestWeakMap(Object.freeze)
+TestWeakMap(Object.preventExtensions)
=======================================
--- /branches/bleeding_edge/src/api.cc Wed Sep 21 06:28:09 2011
+++ /branches/bleeding_edge/src/api.cc Thu Sep 22 06:54:53 2011
@@ -3209,7 +3209,7 @@
i::Handle<i::JSObject> self = Utils::OpenHandle(this);
i::Handle<i::Object> hidden_props(i::GetHiddenProperties(
self,
- i::JSObject::ALLOW_CREATION));
+ i::ALLOW_CREATION));
i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
EXCEPTION_PREAMBLE(isolate);
@@ -3233,7 +3233,7 @@
i::Handle<i::JSObject> self = Utils::OpenHandle(this);
i::Handle<i::Object> hidden_props(i::GetHiddenProperties(
self,
- i::JSObject::OMIT_CREATION));
+ i::OMIT_CREATION));
if (hidden_props->IsUndefined()) {
return v8::Local<v8::Value>();
}
@@ -3257,7 +3257,7 @@
i::Handle<i::JSObject> self = Utils::OpenHandle(this);
i::Handle<i::Object> hidden_props(i::GetHiddenProperties(
self,
- i::JSObject::OMIT_CREATION));
+ i::OMIT_CREATION));
if (hidden_props->IsUndefined()) {
return true;
}
=======================================
--- /branches/bleeding_edge/src/handles.cc Tue Sep 13 05:53:28 2011
+++ /branches/bleeding_edge/src/handles.cc Thu Sep 22 06:54:53 2011
@@ -421,17 +421,16 @@
}
-Handle<Object> GetHiddenProperties(Handle<JSObject> obj,
- JSObject::HiddenPropertiesFlag flag) {
+Handle<Object> GetHiddenProperties(Handle<JSObject> obj, CreationFlag
flag) {
CALL_HEAP_FUNCTION(obj->GetIsolate(),
obj->GetHiddenProperties(flag),
Object);
}
-int GetIdentityHash(Handle<JSObject> obj) {
+int GetIdentityHash(Handle<JSReceiver> obj) {
CALL_AND_RETRY(obj->GetIsolate(),
- obj->GetIdentityHash(JSObject::ALLOW_CREATION),
+ obj->GetIdentityHash(ALLOW_CREATION),
return Smi::cast(__object__)->value(),
return 0);
}
@@ -886,7 +885,7 @@
Handle<ObjectHashTable> PutIntoObjectHashTable(Handle<ObjectHashTable>
table,
- Handle<JSObject> key,
+ Handle<JSReceiver> key,
Handle<Object> value) {
CALL_HEAP_FUNCTION(table->GetIsolate(),
table->Put(*key, *value),
=======================================
--- /branches/bleeding_edge/src/handles.h Tue Sep 13 05:53:28 2011
+++ /branches/bleeding_edge/src/handles.h Thu Sep 22 06:54:53 2011
@@ -267,10 +267,9 @@
// properties and HiddenPropertiesFlag::ALLOW_CREATION is passed, then a
new
// hidden property object will be allocated. Otherwise
Heap::undefined_value
// is returned.
-Handle<Object> GetHiddenProperties(Handle<JSObject> obj,
- JSObject::HiddenPropertiesFlag flag);
-
-int GetIdentityHash(Handle<JSObject> obj);
+Handle<Object> GetHiddenProperties(Handle<JSObject> obj, CreationFlag
flag);
+
+int GetIdentityHash(Handle<JSReceiver> obj);
Handle<Object> DeleteElement(Handle<JSObject> obj, uint32_t index);
Handle<Object> DeleteProperty(Handle<JSObject> obj, Handle<String> prop);
@@ -348,7 +347,7 @@
Handle<Object> PreventExtensions(Handle<JSObject> object);
Handle<ObjectHashTable> PutIntoObjectHashTable(Handle<ObjectHashTable>
table,
- Handle<JSObject> key,
+ Handle<JSReceiver> key,
Handle<Object> value);
// Does lazy compilation of the given function. Returns true on success and
=======================================
--- /branches/bleeding_edge/src/heap.cc Thu Sep 22 05:57:54 2011
+++ /branches/bleeding_edge/src/heap.cc Thu Sep 22 06:54:53 2011
@@ -3565,6 +3565,7 @@
if (!maybe_result->To<JSProxy>(&result)) return maybe_result;
result->InitializeBody(map->instance_size(), Smi::FromInt(0));
result->set_handler(handler);
+ result->set_hash(undefined_value());
return result;
}
@@ -3588,6 +3589,7 @@
if (!maybe_result->To<JSFunctionProxy>(&result)) return maybe_result;
result->InitializeBody(map->instance_size(), Smi::FromInt(0));
result->set_handler(handler);
+ result->set_hash(undefined_value());
result->set_call_trap(call_trap);
result->set_construct_trap(construct_trap);
return result;
@@ -3737,13 +3739,16 @@
MaybeObject* Heap::ReinitializeJSReceiver(
JSReceiver* object, InstanceType type, int size) {
- ASSERT(type >= FIRST_JS_RECEIVER_TYPE);
+ ASSERT(type >= FIRST_JS_OBJECT_TYPE);
+
+ // Save identity hash.
+ MaybeObject* maybe_hash = object->GetIdentityHash(OMIT_CREATION);
// Allocate fresh map.
// TODO(rossberg): Once we optimize proxies, cache these maps.
Map* map;
- MaybeObject* maybe_map_obj = AllocateMap(type, size);
- if (!maybe_map_obj->To<Map>(&map)) return maybe_map_obj;
+ MaybeObject* maybe = AllocateMap(type, size);
+ if (!maybe->To<Map>(&map)) return maybe;
// Check that the receiver has at least the size of the fresh object.
int size_difference = object->map()->instance_size() -
map->instance_size();
@@ -3760,24 +3765,24 @@
// Reset the map for the object.
object->set_map(map);
+ JSObject* jsobj = JSObject::cast(object);
// Reinitialize the object from the constructor map.
- InitializeJSObjectFromMap(JSObject::cast(object),
- FixedArray::cast(properties), map);
+ InitializeJSObjectFromMap(jsobj, FixedArray::cast(properties), map);
// Functions require some minimal initialization.
if (type == JS_FUNCTION_TYPE) {
map->set_function_with_prototype(true);
String* name;
- MaybeObject* maybe_name = LookupAsciiSymbol("<freezing call trap>");
- if (!maybe_name->To<String>(&name)) return maybe_name;
+ maybe = LookupAsciiSymbol("<freezing call trap>");
+ if (!maybe->To<String>(&name)) return maybe;
SharedFunctionInfo* shared;
- MaybeObject* maybe_shared = AllocateSharedFunctionInfo(name);
- if (!maybe_shared->To<SharedFunctionInfo>(&shared)) return
maybe_shared;
+ maybe = AllocateSharedFunctionInfo(name);
+ if (!maybe->To<SharedFunctionInfo>(&shared)) return maybe;
JSFunction* func;
- MaybeObject* maybe_func =
- InitializeFunction(JSFunction::cast(object), shared,
the_hole_value());
- if (!maybe_func->To<JSFunction>(&func)) return maybe_func;
+ maybe = InitializeFunction(
+ JSFunction::cast(object), shared, the_hole_value());
+ if (!maybe->To<JSFunction>(&func)) return maybe;
func->set_context(isolate()->context()->global_context());
}
@@ -3786,6 +3791,13 @@
CreateFillerObjectAt(
object->address() + map->instance_size(), size_difference);
}
+
+ // Inherit identity, if it was present.
+ Object* hash;
+ if (maybe_hash->To<Object>(&hash) && hash->IsSmi()) {
+ maybe = jsobj->SetIdentityHash(hash, ALLOW_CREATION);
+ if (maybe->IsFailure()) return maybe;
+ }
return object;
}
=======================================
--- /branches/bleeding_edge/src/heap.h Thu Sep 22 04:30:04 2011
+++ /branches/bleeding_edge/src/heap.h Thu Sep 22 06:54:53 2011
@@ -495,6 +495,7 @@
// size, but keeping the original prototype. The receiver must have at
least
// the size of the new object. The object is reinitialized and behaves
as an
// object that has been freshly allocated.
+ // Returns failure if an error occured, otherwise object.
MUST_USE_RESULT MaybeObject* ReinitializeJSReceiver(JSReceiver* object,
InstanceType type,
int size);
=======================================
--- /branches/bleeding_edge/src/objects-debug.cc Thu Sep 22 04:30:04 2011
+++ /branches/bleeding_edge/src/objects-debug.cc Thu Sep 22 06:54:53 2011
@@ -546,13 +546,14 @@
void JSProxy::JSProxyVerify() {
- ASSERT(IsJSProxy());
+ CHECK(IsJSProxy());
VerifyPointer(handler());
+ ASSERT(hash()->IsSmi() || hash()->IsUndefined());
}
void JSFunctionProxy::JSFunctionProxyVerify() {
- ASSERT(IsJSFunctionProxy());
+ CHECK(IsJSFunctionProxy());
JSProxyVerify();
VerifyPointer(call_trap());
VerifyPointer(construct_trap());
=======================================
--- /branches/bleeding_edge/src/objects-inl.h Thu Sep 22 04:30:04 2011
+++ /branches/bleeding_edge/src/objects-inl.h Thu Sep 22 06:54:53 2011
@@ -3834,6 +3834,7 @@
ACCESSORS(JSProxy, handler, Object, kHandlerOffset)
+ACCESSORS(JSProxy, hash, Object, kHashOffset)
ACCESSORS(JSFunctionProxy, call_trap, Object, kCallTrapOffset)
ACCESSORS(JSFunctionProxy, construct_trap, Object, kConstructTrapOffset)
@@ -4307,6 +4308,13 @@
}
return this;
}
+
+
+MaybeObject* JSReceiver::GetIdentityHash(CreationFlag flag) {
+ return IsJSProxy()
+ ? JSProxy::cast(this)->GetIdentityHash(flag)
+ : JSObject::cast(this)->GetIdentityHash(flag);
+}
bool JSObject::HasHiddenPropertiesObject() {
@@ -4461,27 +4469,27 @@
}
-bool ObjectHashTableShape::IsMatch(JSObject* key, Object* other) {
- return key == JSObject::cast(other);
+bool ObjectHashTableShape::IsMatch(JSReceiver* key, Object* other) {
+ return key == JSReceiver::cast(other);
}
-uint32_t ObjectHashTableShape::Hash(JSObject* key) {
- MaybeObject* maybe_hash = key->GetIdentityHash(JSObject::OMIT_CREATION);
+uint32_t ObjectHashTableShape::Hash(JSReceiver* key) {
+ MaybeObject* maybe_hash = key->GetIdentityHash(OMIT_CREATION);
ASSERT(!maybe_hash->IsFailure());
return Smi::cast(maybe_hash->ToObjectUnchecked())->value();
}
-uint32_t ObjectHashTableShape::HashForObject(JSObject* key, Object* other)
{
- MaybeObject* maybe_hash = JSObject::cast(other)->GetIdentityHash(
- JSObject::OMIT_CREATION);
+uint32_t ObjectHashTableShape::HashForObject(JSReceiver* key, Object*
other) {
+ MaybeObject* maybe_hash =
+ JSReceiver::cast(other)->GetIdentityHash(OMIT_CREATION);
ASSERT(!maybe_hash->IsFailure());
return Smi::cast(maybe_hash->ToObjectUnchecked())->value();
}
-MaybeObject* ObjectHashTableShape::AsObject(JSObject* key) {
+MaybeObject* ObjectHashTableShape::AsObject(JSReceiver* key) {
return key;
}
=======================================
--- /branches/bleeding_edge/src/objects-printer.cc Thu Sep 22 04:30:04 2011
+++ /branches/bleeding_edge/src/objects-printer.cc Thu Sep 22 06:54:53 2011
@@ -671,6 +671,8 @@
PrintF(out, " - map = 0x%p\n", reinterpret_cast<void*>(map()));
PrintF(out, " - handler = ");
handler()->Print(out);
+ PrintF(out, " - hash = ");
+ hash()->Print(out);
PrintF(out, "\n");
}
=======================================
--- /branches/bleeding_edge/src/objects.cc Thu Sep 22 05:57:54 2011
+++ /branches/bleeding_edge/src/objects.cc Thu Sep 22 06:54:53 2011
@@ -3139,7 +3139,7 @@
}
-MaybeObject* JSObject::GetHiddenProperties(HiddenPropertiesFlag flag) {
+MaybeObject* JSObject::GetHiddenProperties(CreationFlag flag) {
Isolate* isolate = GetIsolate();
Heap* heap = isolate->heap();
Object* holder = BypassGlobalProxy();
@@ -3179,8 +3179,36 @@
}
-MaybeObject* JSObject::GetIdentityHash(HiddenPropertiesFlag flag) {
+Smi* JSReceiver::GenerateIdentityHash() {
Isolate* isolate = GetIsolate();
+
+ 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
+
+ return Smi::FromInt(hash_value);
+}
+
+
+MaybeObject* JSObject::SetIdentityHash(Object* hash, CreationFlag flag) {
+ JSObject* hidden_props;
+ MaybeObject* maybe = GetHiddenProperties(flag);
+ if (!maybe->To<JSObject>(&hidden_props)) return maybe;
+ maybe = hidden_props->SetLocalPropertyIgnoreAttributes(
+ GetHeap()->identity_hash_symbol(), hash, NONE);
+ if (maybe->IsFailure()) return maybe;
+ return this;
+}
+
+
+MaybeObject* JSObject::GetIdentityHash(CreationFlag flag) {
+ Isolate* isolate = GetIsolate();
Object* hidden_props_obj;
{ MaybeObject* maybe_obj = GetHiddenProperties(flag);
if (!maybe_obj->ToObject(&hidden_props_obj)) return maybe_obj;
@@ -3203,17 +3231,7 @@
}
}
- 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);
+ Smi* hash = GenerateIdentityHash();
{ MaybeObject* result = hidden_props->SetLocalPropertyIgnoreAttributes(
hash_symbol,
hash,
@@ -3222,6 +3240,16 @@
}
return hash;
}
+
+
+MaybeObject* JSProxy::GetIdentityHash(CreationFlag flag) {
+ Object* hash = this->hash();
+ if (!hash->IsSmi() && flag == ALLOW_CREATION) {
+ hash = GenerateIdentityHash();
+ set_hash(hash);
+ }
+ return hash;
+}
MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name,
@@ -11542,9 +11570,9 @@
}
-Object* ObjectHashTable::Lookup(JSObject* key) {
+Object* ObjectHashTable::Lookup(JSReceiver* key) {
// If the object does not have an identity hash, it was never used as a
key.
- MaybeObject* maybe_hash = key->GetIdentityHash(JSObject::OMIT_CREATION);
+ MaybeObject* maybe_hash = key->GetIdentityHash(OMIT_CREATION);
if (maybe_hash->IsFailure()) return GetHeap()->undefined_value();
int entry = FindEntry(key);
if (entry == kNotFound) return GetHeap()->undefined_value();
@@ -11552,10 +11580,10 @@
}
-MaybeObject* ObjectHashTable::Put(JSObject* key, Object* value) {
+MaybeObject* ObjectHashTable::Put(JSReceiver* key, Object* value) {
// Make sure the key object has an identity hash code.
int hash;
- { MaybeObject* maybe_hash =
key->GetIdentityHash(JSObject::ALLOW_CREATION);
+ { MaybeObject* maybe_hash = key->GetIdentityHash(ALLOW_CREATION);
if (maybe_hash->IsFailure()) return maybe_hash;
hash = Smi::cast(maybe_hash->ToObjectUnchecked())->value();
}
@@ -11585,7 +11613,7 @@
}
-void ObjectHashTable::AddEntry(int entry, JSObject* key, Object* value) {
+void ObjectHashTable::AddEntry(int entry, JSReceiver* key, Object* value) {
set(EntryToIndex(entry), key);
set(EntryToIndex(entry) + 1, value);
ElementAdded();
=======================================
--- /branches/bleeding_edge/src/objects.h Thu Sep 22 04:30:04 2011
+++ /branches/bleeding_edge/src/objects.h Thu Sep 22 06:54:53 2011
@@ -282,6 +282,13 @@
};
+// Indicates whether a get method should implicitly create the object
looked up.
+enum CreationFlag {
+ ALLOW_CREATION,
+ OMIT_CREATION
+};
+
+
// Instance size sentinel for objects of variable size.
static const int kVariableSizeSentinel = 0;
@@ -1386,11 +1393,18 @@
MUST_USE_RESULT MaybeObject* SetPrototype(Object* value,
bool skip_hidden_prototypes);
+ // Retrieves a permanent object identity hash code. The undefined value
might
+ // be returned in case no has been created yet and OMIT_CREATION was
used.
+ inline MUST_USE_RESULT MaybeObject* GetIdentityHash(CreationFlag flag);
+
// Lookup a property. If found, the result is valid and has
// detailed information.
void LocalLookup(String* name, LookupResult* result);
void Lookup(String* name, LookupResult* result);
+ protected:
+ Smi* GenerateIdentityHash();
+
private:
PropertyAttributes GetPropertyAttribute(JSReceiver* receiver,
LookupResult* result,
@@ -1596,22 +1610,15 @@
MUST_USE_RESULT inline MaybeObject* SetHiddenPropertiesObject(
Object* hidden_obj);
- // Indicates whether the hidden properties object should be created.
- enum HiddenPropertiesFlag { ALLOW_CREATION, OMIT_CREATION };
-
// Retrieves the hidden properties object.
//
// The undefined value might be returned in case no hidden properties
object
// is present and creation was omitted.
inline bool HasHiddenProperties();
- MUST_USE_RESULT MaybeObject* GetHiddenProperties(HiddenPropertiesFlag
flag);
-
- // Retrieves a permanent object identity hash code.
- //
- // The identity hash is stored as a hidden property. The undefined value
might
- // be returned in case no hidden properties object is present and
creation was
- // omitted.
- MUST_USE_RESULT MaybeObject* GetIdentityHash(HiddenPropertiesFlag flag);
+ MUST_USE_RESULT MaybeObject* GetHiddenProperties(CreationFlag flag);
+
+ MUST_USE_RESULT MaybeObject* GetIdentityHash(CreationFlag flag);
+ MUST_USE_RESULT MaybeObject* SetIdentityHash(Object* hash, CreationFlag
flag);
MUST_USE_RESULT MaybeObject* DeleteProperty(String* name, DeleteMode
mode);
MUST_USE_RESULT MaybeObject* DeleteElement(uint32_t index, DeleteMode
mode);
@@ -2925,10 +2932,10 @@
class ObjectHashTableShape {
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 inline bool IsMatch(JSReceiver* key, Object* other);
+ static inline uint32_t Hash(JSReceiver* key);
+ static inline uint32_t HashForObject(JSReceiver* key, Object* object);
+ MUST_USE_RESULT static inline MaybeObject* AsObject(JSReceiver* key);
static const int kPrefixSize = 0;
static const int kEntrySize = 2;
};
@@ -2936,7 +2943,7 @@
// ObjectHashTable maps keys that are JavaScript objects to object values
by
// using the identity hash of the key for hashing purposes.
-class ObjectHashTable: public HashTable<ObjectHashTableShape, JSObject*> {
+class ObjectHashTable: public HashTable<ObjectHashTableShape, JSReceiver*>
{
public:
static inline ObjectHashTable* cast(Object* obj) {
ASSERT(obj->IsHashTable());
@@ -2945,16 +2952,16 @@
// Looks up the value associated with the given key. The undefined value
is
// returned in case the key is not present.
- Object* Lookup(JSObject* key);
+ Object* Lookup(JSReceiver* key);
// Adds (or overwrites) the value associated with the given key. Mapping
a
// key to the undefined value causes removal of the whole entry.
- MUST_USE_RESULT MaybeObject* Put(JSObject* key, Object* value);
+ MUST_USE_RESULT MaybeObject* Put(JSReceiver* key, Object* value);
private:
friend class MarkCompactCollector;
- void AddEntry(int entry, JSObject* key, Object* value);
+ void AddEntry(int entry, JSReceiver* key, Object* value);
void RemoveEntry(int entry, Heap* heap);
inline void RemoveEntry(int entry);
@@ -6677,6 +6684,9 @@
// [handler]: The handler property.
DECL_ACCESSORS(handler, Object)
+ // [hash]: The hash code property (undefined if not initialized yet).
+ DECL_ACCESSORS(hash, Object)
+
// Casting.
static inline JSProxy* cast(Object* obj);
@@ -6723,6 +6733,8 @@
JSReceiver* receiver,
uint32_t index);
+ MUST_USE_RESULT MaybeObject* GetIdentityHash(CreationFlag flag);
+
// Turn this into an (empty) JSObject.
void Fix();
@@ -6751,7 +6763,8 @@
// size as a virgin JSObject. This is essential for becoming a JSObject
// upon freeze.
static const int kHandlerOffset = HeapObject::kHeaderSize;
- static const int kPaddingOffset = kHandlerOffset + kPointerSize;
+ static const int kHashOffset = kHandlerOffset + kPointerSize;
+ static const int kPaddingOffset = kHashOffset + kPointerSize;
static const int kSize = JSObject::kHeaderSize;
static const int kHeaderSize = kPaddingOffset;
static const int kPaddingSize = kSize - kPaddingOffset;
@@ -6759,7 +6772,7 @@
STATIC_CHECK(kPaddingSize >= 0);
typedef FixedBodyDescriptor<kHandlerOffset,
- kHandlerOffset + kPointerSize,
+ kPaddingOffset,
kSize> BodyDescriptor;
private:
@@ -6790,7 +6803,7 @@
#endif
// Layout description.
- static const int kCallTrapOffset = kHandlerOffset + kPointerSize;
+ static const int kCallTrapOffset = JSProxy::kPaddingOffset;
static const int kConstructTrapOffset = kCallTrapOffset + kPointerSize;
static const int kPaddingOffset = kConstructTrapOffset + kPointerSize;
static const int kSize = JSFunction::kSize;
=======================================
--- /branches/bleeding_edge/src/runtime.cc Thu Sep 22 04:30:04 2011
+++ /branches/bleeding_edge/src/runtime.cc Thu Sep 22 06:54:53 2011
@@ -714,9 +714,7 @@
NoHandleAllocation ha;
ASSERT(args.length() == 2);
CONVERT_ARG_CHECKED(JSWeakMap, weakmap, 0);
- // TODO(mstarzinger): Currently we cannot use JSProxy objects as keys
- // because they cannot be cast to JSObject to get an identity hash code.
- CONVERT_ARG_CHECKED(JSObject, key, 1);
+ CONVERT_ARG_CHECKED(JSReceiver, key, 1);
return weakmap->table()->Lookup(*key);
}
@@ -725,8 +723,7 @@
HandleScope scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_CHECKED(JSWeakMap, weakmap, 0);
- // TODO(mstarzinger): See Runtime_WeakMapGet above.
- CONVERT_ARG_CHECKED(JSObject, key, 1);
+ CONVERT_ARG_CHECKED(JSReceiver, key, 1);
Handle<Object> value(args[2]);
Handle<ObjectHashTable> table(weakmap->table());
Handle<ObjectHashTable> new_table = PutIntoObjectHashTable(table, key,
value);
=======================================
--- /branches/bleeding_edge/test/mjsunit/harmony/proxies.js Thu Sep 22
03:45:37 2011
+++ /branches/bleeding_edge/test/mjsunit/harmony/proxies.js Thu Sep 22
06:54:53 2011
@@ -1,4 +1,4 @@
-// Copyright 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:
@@ -1665,7 +1665,6 @@
// Fixing (Object.freeze, Object.seal, Object.preventExtensions,
// Object.isFrozen, Object.isSealed, Object.isExtensible)
-// TODO(rossberg): use TestWithProxies to include function proxies
function TestFix(names, handler) {
var proto = {p: 77}
var assertFixing = function(o, s, f, e) {
@@ -2020,8 +2019,8 @@
function TestCall(isStrict, callTrap) {
assertEquals(42, callTrap(5, 37))
-// TODO(rossberg): unrelated bug: this does not succeed for optimized code.
-// assertEquals(isStrict ? undefined : global_object, receiver)
+ // TODO(rossberg): unrelated bug: this does not succeed for optimized
code.
+ // assertEquals(isStrict ? undefined : global_object, receiver)
var f = Proxy.createFunction({}, callTrap)
receiver = 333
@@ -2048,8 +2047,8 @@
var f = CreateFrozen({}, callTrap)
receiver = 333
assertEquals(42, f(11, 31))
-// TODO(rossberg): unrelated bug: this does not succeed for optimized code.
-// assertEquals(isStrict ? undefined : global, receiver)
+ // TODO(rossberg): unrelated bug: this does not succeed for optimized
code.
+ // assertEquals(isStrict ? undefined : global, receiver)
receiver = 333
assertEquals(42, Function.prototype.call.call(f, o, 20, 22))
assertEquals(o, receiver)
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev