Author: [email protected]
Date: Fri Mar 6 00:11:28 2009
New Revision: 1430
Modified:
branches/experimental/global/src/bootstrapper.cc
branches/experimental/global/src/factory.cc
branches/experimental/global/src/factory.h
branches/experimental/global/src/heap.cc
branches/experimental/global/src/heap.h
branches/experimental/global/src/ic-arm.cc
branches/experimental/global/src/ic-ia32.cc
branches/experimental/global/src/objects-debug.cc
branches/experimental/global/src/objects-inl.h
branches/experimental/global/src/objects.cc
branches/experimental/global/src/objects.h
branches/experimental/global/src/property.h
branches/experimental/global/src/runtime.cc
Log:
Changed the property representation in JS global objects so
each property value is stored in a wrapper object.
This is the runtime part of speeding up global property access.
Review URL: http://codereview.chromium.org/40166
Modified: branches/experimental/global/src/bootstrapper.cc
==============================================================================
--- branches/experimental/global/src/bootstrapper.cc (original)
+++ branches/experimental/global/src/bootstrapper.cc Fri Mar 6 00:11:28
2009
@@ -578,8 +578,7 @@
js_global_function->initial_map()->set_is_hidden_prototype();
SetExpectedNofProperties(js_global_function, 100);
- object = Handle<JSGlobalObject>::cast(
- Factory::NewJSObject(js_global_function, TENURED));
+ object = Factory::NewJSGlobalObject(js_global_function);
}
// Set the global context for the global object.
@@ -1352,6 +1351,9 @@
// Set the property.
Handle<String> key = Handle<String>(String::cast(raw_key));
Handle<Object> value = Handle<Object>(properties->ValueAt(i));
+ if (value->IsJSGlobalPropertyCell()) {
+ value =
Handle<Object>(JSGlobalPropertyCell::cast(*value)->value());
+ }
PropertyDetails details = properties->DetailsAt(i);
SetProperty(to, key, value, details.attributes());
}
Modified: branches/experimental/global/src/factory.cc
==============================================================================
--- branches/experimental/global/src/factory.cc (original)
+++ branches/experimental/global/src/factory.cc Fri Mar 6 00:11:28 2009
@@ -589,6 +589,14 @@
}
+Handle<JSGlobalObject> Factory::NewJSGlobalObject(
+ Handle<JSFunction> constructor) {
+ CALL_HEAP_FUNCTION(Heap::AllocateJSGlobalObject(*constructor),
+ JSGlobalObject);
+}
+
+
+
Handle<JSObject> Factory::NewJSObjectFromMap(Handle<Map> map) {
CALL_HEAP_FUNCTION(Heap::AllocateJSObjectFromMap(*map, NOT_TENURED),
JSObject);
Modified: branches/experimental/global/src/factory.h
==============================================================================
--- branches/experimental/global/src/factory.h (original)
+++ branches/experimental/global/src/factory.h Fri Mar 6 00:11:28 2009
@@ -182,6 +182,10 @@
static Handle<JSObject> NewJSObject(Handle<JSFunction> constructor,
PretenureFlag pretenure =
NOT_TENURED);
+ // JS global objects are pretenured.
+ static Handle<JSGlobalObject> NewJSGlobalObject(
+ Handle<JSFunction> constructor);
+
// JS objects are pretenured when allocated by the bootstrapper and
// runtime.
static Handle<JSObject> NewJSObjectFromMap(Handle<Map> map);
Modified: branches/experimental/global/src/heap.cc
==============================================================================
--- branches/experimental/global/src/heap.cc (original)
+++ branches/experimental/global/src/heap.cc Fri Mar 6 00:11:28 2009
@@ -927,6 +927,11 @@
if (obj->IsFailure()) return false;
oddball_map_ = Map::cast(obj);
+ obj = AllocatePartialMap(JS_GLOBAL_PROPERTY_CELL_TYPE,
+ JSGlobalPropertyCell::kSize);
+ if (obj->IsFailure()) return false;
+ global_property_value_map_ = Map::cast(obj);
+
// Allocate the empty array
obj = AllocateEmptyFixedArray();
if (obj->IsFailure()) return false;
@@ -952,6 +957,10 @@
oddball_map()->set_instance_descriptors(empty_descriptor_array());
oddball_map()->set_code_cache(empty_fixed_array());
+ global_property_value_map()->set_instance_descriptors(
+ empty_descriptor_array());
+ global_property_value_map()->set_code_cache(empty_fixed_array());
+
// Fix prototype object for existing maps.
meta_map()->set_prototype(null_value());
meta_map()->set_constructor(null_value());
@@ -961,6 +970,9 @@
oddball_map()->set_prototype(null_value());
oddball_map()->set_constructor(null_value());
+ global_property_value_map()->set_prototype(null_value());
+ global_property_value_map()->set_constructor(null_value());
+
obj = AllocateMap(HEAP_NUMBER_TYPE, HeapNumber::kSize);
if (obj->IsFailure()) return false;
heap_number_map_ = Map::cast(obj);
@@ -1087,6 +1099,17 @@
}
+Object* Heap::AllocateJSGlobalPropertyCell(Object* value) {
+ Object* result = AllocateRaw(JSGlobalPropertyCell::kSize,
+ OLD_POINTER_SPACE,
+ OLD_POINTER_SPACE);
+ if (result->IsFailure()) return result;
+ HeapObject::cast(result)->set_map(global_property_value_map());
+ JSGlobalPropertyCell::cast(result)->set_value(value);
+ return result;
+}
+
+
Object* Heap::CreateOddball(Map* map,
const char* to_string,
Object* to_number) {
@@ -1871,7 +1894,34 @@
Map::cast(initial_map)->set_constructor(constructor);
}
// Allocate the object based on the constructors initial map.
- return AllocateJSObjectFromMap(constructor->initial_map(), pretenure);
+ Object* result =
+ AllocateJSObjectFromMap(constructor->initial_map(), pretenure);
+ // Make sure result is NOT a JS global object if valid.
+ ASSERT(result->IsFailure() || !result->IsJSGlobalObject());
+ return result;
+}
+
+
+Object* Heap::AllocateJSGlobalObject(JSFunction* constructor) {
+ ASSERT(constructor->has_initial_map());
+ // Make sure no field properties are described in the initial map.
+ // This guarantees us that normalizing the properties does not
+ // require us to change property values to JSGlobalPropertyCells.
+ ASSERT(constructor->initial_map()->NextFreePropertyIndex() == 0);
+
+ // Allocate the object based on the constructors initial map.
+ Object* result = AllocateJSObjectFromMap(constructor->initial_map(),
TENURED);
+ if (result->IsFailure()) return result;
+
+ // Normalize the result.
+ JSObject* global = JSObject::cast(result);
+ result = global->NormalizeProperties(CLEAR_INOBJECT_PROPERTIES);
+ if (result->IsFailure()) return result;
+
+ // Make sure result is NOT a JS global object if valid.
+ ASSERT(global->IsJSGlobalObject());
+ ASSERT(!global->HasFastProperties());
+ return global;
}
Modified: branches/experimental/global/src/heap.h
==============================================================================
--- branches/experimental/global/src/heap.h (original)
+++ branches/experimental/global/src/heap.h Fri Mar 6 00:11:28 2009
@@ -96,6 +96,7 @@
V(Map, global_context_map) \
V(Map, code_map) \
V(Map, oddball_map) \
+ V(Map, global_property_value_map) \
V(Map, boilerplate_function_map) \
V(Map, shared_function_info_map) \
V(Map, proxy_map) \
@@ -281,6 +282,12 @@
static Object* AllocateJSObject(JSFunction* constructor,
PretenureFlag pretenure = NOT_TENURED);
+ // Allocates and initializes a new JS global object based on a
constructor.
+ // Returns Failure::RetryAfterGC(requested_bytes, space) if the
allocation
+ // failed.
+ // Please note this does not perform a garbage collection.
+ static Object* AllocateJSGlobalObject(JSFunction* constructor);
+
// Returns a deep copy of the JavaScript object.
// Properties and elements are copied too.
// Returns failure if allocation failed.
@@ -400,6 +407,12 @@
// failed.
// Please note this does not perform a garbage collection.
static Object* AllocateByteArray(int length);
+
+ // Allocate a tenured JS global property cell.
+ // Returns Failure::RetryAfterGC(requested_bytes, space) if the
allocation
+ // failed.
+ // Please note this does not perform a garbage collection.
+ static Object* AllocateJSGlobalPropertyCell(Object* value);
// Allocates a fixed array initialized with undefined values
// Returns Failure::RetryAfterGC(requested_bytes, space) if the
allocation
Modified: branches/experimental/global/src/ic-arm.cc
==============================================================================
--- branches/experimental/global/src/ic-arm.cc (original)
+++ branches/experimental/global/src/ic-arm.cc Fri Mar 6 00:11:28 2009
@@ -71,6 +71,11 @@
// Jump to miss if the interceptor bit is set.
__ b(ne, miss);
+ // Bail out if we have a JS global object.
+ __ ldr(t0, FieldMemOperand(t1, JSObject::kMapOffset));
+ __ ldrb(t0, FieldMemOperand(t0, Map::kInstanceTypeOffset));
+ __ cmp(t0, Operand(JS_GLOBAL_OBJECT_TYPE));
+ __ b(eq, miss);
// Check that the properties array is a dictionary.
__ ldr(t0, FieldMemOperand(t1, JSObject::kPropertiesOffset));
Modified: branches/experimental/global/src/ic-ia32.cc
==============================================================================
--- branches/experimental/global/src/ic-ia32.cc (original)
+++ branches/experimental/global/src/ic-ia32.cc Fri Mar 6 00:11:28 2009
@@ -65,8 +65,14 @@
// Test the has_named_interceptor bit in the map.
__ test(FieldOperand(r0, Map::kInstanceAttributesOffset),
Immediate(1 << (Map::kHasNamedInterceptor + (3 * 8))));
+
// Jump to miss if the interceptor bit is set.
__ j(not_zero, miss_label, not_taken);
+
+ // Bail out if we have a JS global object.
+ __ movzx_b(r0, FieldOperand(r0, Map::kInstanceTypeOffset));
+ __ cmp(r0, JS_GLOBAL_OBJECT_TYPE);
+ __ j(equal, miss_label, not_taken);
// Check that the properties array is a dictionary.
__ mov(r0, FieldOperand(r1, JSObject::kPropertiesOffset));
Modified: branches/experimental/global/src/objects-debug.cc
==============================================================================
--- branches/experimental/global/src/objects-debug.cc (original)
+++ branches/experimental/global/src/objects-debug.cc Fri Mar 6 00:11:28
2009
@@ -150,7 +150,9 @@
case SHARED_FUNCTION_INFO_TYPE:
SharedFunctionInfo::cast(this)->SharedFunctionInfoPrint();
break;
-
+ case JS_GLOBAL_PROPERTY_CELL_TYPE:
+ JSGlobalPropertyCell::cast(this)->JSGlobalPropertyCellPrint();
+ break;
#define MAKE_STRUCT_CASE(NAME, Name, name) \
case NAME##_TYPE: \
Name::cast(this)->Name##Print(); \
@@ -212,6 +214,9 @@
case JS_BUILTINS_OBJECT_TYPE:
JSBuiltinsObject::cast(this)->JSBuiltinsObjectVerify();
break;
+ case JS_GLOBAL_PROPERTY_CELL_TYPE:
+ JSGlobalPropertyCell::cast(this)->JSGlobalPropertyCellVerify();
+ break;
case JS_ARRAY_TYPE:
JSArray::cast(this)->JSArrayVerify();
break;
@@ -390,6 +395,7 @@
case JS_OBJECT_TYPE: return "JS_OBJECT";
case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
return "JS_CONTEXT_EXTENSION_OBJECT";
case ODDBALL_TYPE: return "ODDBALL";
+ case JS_GLOBAL_PROPERTY_CELL_TYPE: return "JS_GLOBAL_PROPERTY_CELL";
case SHARED_FUNCTION_INFO_TYPE: return "SHARED_FUNCTION_INFO";
case JS_FUNCTION_TYPE: return "JS_FUNCTION";
case CODE_TYPE: return "CODE";
@@ -652,6 +658,17 @@
int value = Smi::cast(number)->value();
ASSERT(value == 0 || value == 1 || value == -1);
}
+}
+
+
+void JSGlobalPropertyCell::JSGlobalPropertyCellVerify() {
+ CHECK(IsJSGlobalPropertyCell());
+ VerifyObjectField(kValueOffset);
+}
+
+
+void JSGlobalPropertyCell::JSGlobalPropertyCellPrint() {
+ HeapObject::PrintHeader("JSGlobalPropertyCell");
}
Modified: branches/experimental/global/src/objects-inl.h
==============================================================================
--- branches/experimental/global/src/objects-inl.h (original)
+++ branches/experimental/global/src/objects-inl.h Fri Mar 6 00:11:28 2009
@@ -395,6 +395,13 @@
}
+bool Object::IsJSGlobalPropertyCell() {
+ return Object::IsHeapObject()
+ && HeapObject::cast(this)->map()->instance_type()
+ == JS_GLOBAL_PROPERTY_CELL_TYPE;
+}
+
+
bool Object::IsSharedFunctionInfo() {
return Object::IsHeapObject() &&
(HeapObject::cast(this)->map()->instance_type() ==
@@ -1008,6 +1015,8 @@
ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
+ACCESSORS(JSGlobalPropertyCell, value, Object, kValueOffset)
+
int JSObject::GetHeaderSize() {
switch (map()->instance_type()) {
case JS_GLOBAL_PROXY_TYPE:
@@ -1353,6 +1362,7 @@
CAST_ACCESSOR(HeapObject)
CAST_ACCESSOR(HeapNumber)
CAST_ACCESSOR(Oddball)
+CAST_ACCESSOR(JSGlobalPropertyCell)
CAST_ACCESSOR(SharedFunctionInfo)
CAST_ACCESSOR(Map)
CAST_ACCESSOR(JSFunction)
Modified: branches/experimental/global/src/objects.cc
==============================================================================
--- branches/experimental/global/src/objects.cc (original)
+++ branches/experimental/global/src/objects.cc Fri Mar 6 00:11:28 2009
@@ -405,6 +405,63 @@
}
+Object* JSObject::GetNormalizedProperty(LookupResult* result) {
+ ASSERT(!HasFastProperties());
+ Object* value =
property_dictionary()->ValueAt(result->GetDictionaryEntry());
+ if (IsJSGlobalObject()) {
+ value = JSGlobalPropertyCell::cast(value)->value();
+ }
+ ASSERT(!value->IsJSGlobalPropertyCell());
+ return value;
+}
+
+
+Object* JSObject::SetNormalizedProperty(LookupResult* result, Object*
value) {
+ ASSERT(!HasFastProperties());
+ if (IsJSGlobalObject()) {
+ JSGlobalPropertyCell* cell =
+ JSGlobalPropertyCell::cast(
+ property_dictionary()->ValueAt(result->GetDictionaryEntry()));
+ cell->set_value(value);
+ } else {
+ property_dictionary()->ValueAtPut(result->GetDictionaryEntry(), value);
+ }
+ return value;
+}
+
+
+Object* JSObject::SetNormalizedProperty(String* name,
+ Object* value,
+ PropertyDetails details) {
+ ASSERT(!HasFastProperties());
+ int entry = property_dictionary()->FindStringEntry(name);
+ Object* store_value = value;
+ if (entry == -1) {
+ if (IsJSGlobalObject()) {
+ store_value = Heap::AllocateJSGlobalPropertyCell(value);
+ }
+ if (store_value->IsFailure()) return store_value;
+ Object* dict =
+ property_dictionary()->AddStringEntry(name, store_value, details);
+ if (dict->IsFailure()) return dict;
+ set_properties(Dictionary::cast(dict));
+ return value;
+ }
+ // Preserve enumeration index.
+ details = PropertyDetails(details.attributes(),
+ details.type(),
+
property_dictionary()->DetailsAt(entry).index());
+ if (IsJSGlobalObject()) {
+ JSGlobalPropertyCell* cell =
+ JSGlobalPropertyCell::cast(property_dictionary()->ValueAt(entry));
+ cell->set_value(value);
+ store_value = cell;
+ }
+ property_dictionary()->SetStringEntry(entry, name, store_value, details);
+ return value;
+}
+
+
Object* Object::GetProperty(Object* receiver,
LookupResult* result,
String* name,
@@ -455,8 +512,7 @@
JSObject* holder = result->holder();
switch (result->type()) {
case NORMAL:
- value =
-
holder->property_dictionary()->ValueAt(result->GetDictionaryEntry());
+ value = holder->GetNormalizedProperty(result);
ASSERT(!value->IsTheHole() || result->IsReadOnly());
return value->IsTheHole() ? Heap::undefined_value() : value;
case FIELD:
@@ -958,6 +1014,10 @@
case PROXY_TYPE:
accumulator->Add("<Proxy>");
break;
+ case JS_GLOBAL_PROPERTY_CELL_TYPE:
+ accumulator->Add("Cell for ");
+ JSGlobalPropertyCell::cast(this)->value()->ShortPrint(accumulator);
+ break;
default:
accumulator->Add("<Other heap object (%d)>", map()->instance_type());
break;
@@ -1050,6 +1110,10 @@
case CODE_TYPE:
reinterpret_cast<Code*>(this)->CodeIterateBody(v);
break;
+ case JS_GLOBAL_PROPERTY_CELL_TYPE:
+ reinterpret_cast<JSGlobalPropertyCell*>(this)
+ ->JSGlobalPropertyCellIterateBody(v);
+ break;
case HEAP_NUMBER_TYPE:
case FILLER_TYPE:
case BYTE_ARRAY_TYPE:
@@ -1258,6 +1322,10 @@
Object* value,
PropertyAttributes attributes) {
PropertyDetails details = PropertyDetails(attributes, NORMAL);
+ if (IsJSGlobalObject()) {
+ value = Heap::AllocateJSGlobalPropertyCell(value);
+ if (value->IsFailure()) return value;
+ }
Object* result = property_dictionary()->AddStringEntry(name, value,
details);
if (result->IsFailure()) return result;
if (property_dictionary() != result) {
@@ -1315,15 +1383,10 @@
if (old_details.IsTransition()) new_index = 0;
PropertyDetails new_details(attributes, NORMAL, old_details.index());
- Object* result =
- property_dictionary()->SetOrAddStringEntry(name, value, new_details);
- if (result->IsFailure()) return result;
- if (property_dictionary() != result) {
- set_properties(Dictionary::cast(result));
- }
- return value;
+ return SetNormalizedProperty(name, value, new_details);
}
+
Object* JSObject::ConvertDescriptorToFieldAndMapTransition(
String* name,
Object* new_value,
@@ -1578,7 +1641,11 @@
if (entry != DescriptorArray::kNotFound) {
// Make sure to disallow caching for uninitialized constants
// found in the dictionary-mode objects.
- if (property_dictionary()->ValueAt(entry)->IsTheHole()) {
+ Object* value = property_dictionary()->ValueAt(entry);
+ if (IsJSGlobalObject()) {
+ value = JSGlobalPropertyCell::cast(value)->value();
+ }
+ if (value->IsTheHole()) {
result->DisallowCaching();
}
result->DictionaryResult(this, entry);
@@ -1710,8 +1777,7 @@
// transition or null descriptor and there are no setters in the
prototypes.
switch (result->type()) {
case NORMAL:
- property_dictionary()->ValueAtPut(result->GetDictionaryEntry(),
value);
- return value;
+ return SetNormalizedProperty(result, value);
case FIELD:
return FastPropertyAtPut(result->GetFieldIndex(), value);
case MAP_TRANSITION:
@@ -1780,8 +1846,7 @@
// Check of IsReadOnly removed from here in clone.
switch (result->type()) {
case NORMAL:
- property_dictionary()->ValueAtPut(result->GetDictionaryEntry(),
value);
- return value;
+ return SetNormalizedProperty(result, value);
case FIELD:
return FastPropertyAtPut(result->GetFieldIndex(), value);
case MAP_TRANSITION:
@@ -1971,6 +2036,10 @@
PropertyDetails d =
PropertyDetails(details.attributes(), NORMAL, details.index());
Object* value = r.GetConstantFunction();
+ if (IsJSGlobalObject()) {
+ value = Heap::AllocateJSGlobalPropertyCell(value);
+ if (value->IsFailure()) return value;
+ }
Object* result = dictionary->AddStringEntry(r.GetKey(), value, d);
if (result->IsFailure()) return result;
dictionary = Dictionary::cast(result);
@@ -1980,6 +2049,10 @@
PropertyDetails d =
PropertyDetails(details.attributes(), NORMAL, details.index());
Object* value = FastPropertyAt(r.GetFieldIndex());
+ if (IsJSGlobalObject()) {
+ value = Heap::AllocateJSGlobalPropertyCell(value);
+ if (value->IsFailure()) return value;
+ }
Object* result = dictionary->AddStringEntry(r.GetKey(), value, d);
if (result->IsFailure()) return result;
dictionary = Dictionary::cast(result);
@@ -1989,6 +2062,10 @@
PropertyDetails d =
PropertyDetails(details.attributes(), CALLBACKS,
details.index());
Object* value = r.GetCallbacksObject();
+ if (IsJSGlobalObject()) {
+ value = Heap::AllocateJSGlobalPropertyCell(value);
+ if (value->IsFailure()) return value;
+ }
Object* result = dictionary->AddStringEntry(r.GetKey(), value, d);
if (result->IsFailure()) return result;
dictionary = Dictionary::cast(result);
@@ -2048,6 +2125,7 @@
Object* JSObject::TransformToFastProperties(int unused_property_fields) {
if (HasFastProperties()) return this;
+ ASSERT(!IsJSGlobalObject());
return property_dictionary()->
TransformPropertiesToFastFor(this, unused_property_fields);
}
@@ -2537,13 +2615,7 @@
// Update the dictionary with the new CALLBACKS property.
PropertyDetails details = PropertyDetails(attributes, CALLBACKS);
- Object* dict =
- property_dictionary()->SetOrAddStringEntry(name, array, details);
- if (dict->IsFailure()) return dict;
-
- // Set the potential new dictionary on the object.
- set_properties(Dictionary::cast(dict));
- return array;
+ return SetNormalizedProperty(name, array, details);
}
@@ -3861,6 +3933,11 @@
}
+void JSGlobalPropertyCell::JSGlobalPropertyCellIterateBody(ObjectVisitor*
v) {
+ IteratePointers(v, kValueOffset, kValueOffset + kPointerSize);
+}
+
+
uint16_t ConsString::ConsStringGet(int index) {
ASSERT(index >= 0 && index < this->length());
@@ -6738,12 +6815,6 @@
}
-Object* Dictionary::AtStringPut(String* key, Object* value) {
- StringKey k(key);
- return AtPut(&k, value);
-}
-
-
Object* Dictionary::AtNumberPut(uint32_t key, Object* value) {
NumberKey k(key);
UpdateMaxNumberKey(key);
@@ -6751,12 +6822,10 @@
}
-Object* Dictionary::SetOrAddStringEntry(String* key,
- Object* value,
- PropertyDetails details) {
- StringKey k(key);
- int entry = FindEntry(&k);
- if (entry == -1) return AddStringEntry(key, value, details);
+Object* Dictionary::SetStringEntry(int entry,
+ String* key,
+ Object* value,
+ PropertyDetails details) {
// Preserve enumeration index.
details = PropertyDetails(details.attributes(),
details.type(),
@@ -6843,8 +6912,12 @@
int capacity = Capacity();
for (int i = 0; i < capacity; i++) {
Object* k = KeyAt(i);
- if (IsKey(k) && ValueAt(i) == value) {
- return k;
+ if (IsKey(k)) {
+ Object* e = ValueAt(i);
+ if (e->IsJSGlobalPropertyCell()) {
+ e = JSGlobalPropertyCell::cast(e)->value();
+ }
+ if (e == value) return k;
}
}
return Heap::undefined_value();
Modified: branches/experimental/global/src/objects.h
==============================================================================
--- branches/experimental/global/src/objects.h (original)
+++ branches/experimental/global/src/objects.h Fri Mar 6 00:11:28 2009
@@ -158,7 +158,7 @@
// constants can be embedded in generated code.
class TypeField: public BitField<PropertyType, 0, 3> {};
class AttributesField: public BitField<PropertyAttributes, 3, 3> {};
- class IndexField: public BitField<uint32_t, 6, 32-6> {};
+ class IndexField: public BitField<uint32_t, 6, 31-6> {};
static const int kInitialIndex = 1;
@@ -258,6 +258,7 @@
V(HEAP_NUMBER_TYPE) \
V(FIXED_ARRAY_TYPE) \
V(CODE_TYPE) \
+ V(JS_GLOBAL_PROPERTY_CELL_TYPE) \
V(ODDBALL_TYPE) \
V(PROXY_TYPE) \
V(BYTE_ARRAY_TYPE) \
@@ -516,6 +517,7 @@
FIXED_ARRAY_TYPE,
CODE_TYPE,
ODDBALL_TYPE,
+ JS_GLOBAL_PROPERTY_CELL_TYPE,
PROXY_TYPE,
BYTE_ARRAY_TYPE,
FILLER_TYPE,
@@ -654,6 +656,7 @@
inline bool IsJSGlobalProxy();
inline bool IsUndetectableObject();
inline bool IsAccessCheckNeeded();
+ inline bool IsJSGlobalPropertyCell();
// Returns true if this object is an instance of the specified
// function template.
@@ -1174,6 +1177,20 @@
Object* value,
PropertyAttributes
attributes);
+ // Retrieve a value in a normalized object given a lookup result.
+ // Handles the special representation of JS global objects.
+ Object* GetNormalizedProperty(LookupResult* result);
+
+ // Sets the property value in a normalized object given a lookup result.
+ // Handles the special representation of JS global objects.
+ Object* SetNormalizedProperty(LookupResult* result, Object* value);
+
+ // Sets the property value in a normalized object given (key, value,
details).
+ // Handles the special representation of JS global objects.
+ Object* SetNormalizedProperty(String* name,
+ Object* value,
+ PropertyDetails details);
+
// Sets a property that currently has lazy loading.
Object* SetLazyProperty(LookupResult* result,
String* name,
@@ -1938,7 +1955,9 @@
class Dictionary: public DictionaryBase {
public:
// Returns the value at entry.
- Object* ValueAt(int entry) { return get(EntryToIndex(entry)+1); }
+ Object* ValueAt(int entry) {
+ return get(EntryToIndex(entry)+1);
+ }
// Set the value for entry.
void ValueAtPut(int entry, Object* value) {
@@ -1975,16 +1994,16 @@
Object* DeleteProperty(int entry);
// Type specific at put (default NONE attributes is used when adding).
- Object* AtStringPut(String* key, Object* value);
Object* AtNumberPut(uint32_t key, Object* value);
Object* AddStringEntry(String* key, Object* value, PropertyDetails
details);
Object* AddNumberEntry(uint32_t key, Object* value, PropertyDetails
details);
// Set and existing string entry or add a new one if needed.
- Object* SetOrAddStringEntry(String* key,
- Object* value,
- PropertyDetails details);
+ Object* SetStringEntry(int entry,
+ String* key,
+ Object* value,
+ PropertyDetails details);
// Returns the number of elements in the dictionary filtering out
properties
// with the specified attributes.
@@ -3729,6 +3748,31 @@
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Oddball);
};
+
+
+class JSGlobalPropertyCell: public HeapObject {
+ public:
+ // [value]: value of the global property.
+ DECL_ACCESSORS(value, Object)
+
+ // Casting.
+ static inline JSGlobalPropertyCell* cast(Object* obj);
+
+ // Dispatched behavior.
+ void JSGlobalPropertyCellIterateBody(ObjectVisitor* v);
+#ifdef DEBUG
+ void JSGlobalPropertyCellVerify();
+ void JSGlobalPropertyCellPrint();
+#endif
+
+ // Layout description.
+ static const int kValueOffset = HeapObject::kHeaderSize;
+ static const int kSize = kValueOffset + kPointerSize;
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalPropertyCell);
+};
+
// Proxy describes objects pointing from JavaScript to C structures.
Modified: branches/experimental/global/src/property.h
==============================================================================
--- branches/experimental/global/src/property.h (original)
+++ branches/experimental/global/src/property.h Fri Mar 6 00:11:28 2009
@@ -294,7 +294,7 @@
}
// In the dictionary case, the data is held in the value field.
ASSERT(lookup_type_ == DICTIONARY_TYPE);
- return holder()->property_dictionary()->ValueAt(GetDictionaryEntry());
+ return holder()->GetNormalizedProperty(this);
}
private:
Modified: branches/experimental/global/src/runtime.cc
==============================================================================
--- branches/experimental/global/src/runtime.cc (original)
+++ branches/experimental/global/src/runtime.cc Fri Mar 6 00:11:28 2009
@@ -420,9 +420,6 @@
// property as read-only, so we don't either.
PropertyAttributes base = is_eval ? NONE : DONT_DELETE;
- // Only optimize the object if we intend to add more than 5 properties.
- OptimizedObjectForAddingMultipleProperties ba(global, pairs->length()/2
> 5);
-
// Traverse the name/value pairs and set the properties.
int length = pairs->length();
for (int i = 0; i < length; i += 2) {
@@ -734,10 +731,8 @@
properties->set(index, *value);
}
} else if (type == NORMAL) {
- Dictionary* dictionary = global->property_dictionary();
- int entry = lookup.GetDictionaryEntry();
- if (dictionary->ValueAt(entry)->IsTheHole()) {
- dictionary->ValueAtPut(entry, *value);
+ if (global->GetNormalizedProperty(&lookup)->IsTheHole()) {
+ global->SetNormalizedProperty(&lookup, *value);
}
} else {
// Ignore re-initialization of constants that have already been
@@ -827,10 +822,8 @@
properties->set(index, *value);
}
} else if (type == NORMAL) {
- Dictionary* dictionary = context_ext->property_dictionary();
- int entry = lookup.GetDictionaryEntry();
- if (dictionary->ValueAt(entry)->IsTheHole()) {
- dictionary->ValueAtPut(entry, *value);
+ if (context_ext->GetNormalizedProperty(&lookup)->IsTheHole()) {
+ context_ext->SetNormalizedProperty(&lookup, *value);
}
} else {
// We should not reach here. Any real, named property should be
@@ -1881,7 +1874,11 @@
int entry = dictionary->FindStringEntry(key);
if ((entry != DescriptorArray::kNotFound) &&
(dictionary->DetailsAt(entry).type() == NORMAL)) {
- return dictionary->ValueAt(entry);
+ Object* value = dictionary->ValueAt(entry);
+ if (receiver->IsJSGlobalObject()) {
+ value = JSGlobalPropertyCell::cast(value)->value();
+ }
+ return value;
}
}
}
@@ -3426,6 +3423,7 @@
ASSERT(args.length() == 1);
Object* constructor = args[0];
+
if (constructor->IsJSFunction()) {
JSFunction* function = JSFunction::cast(constructor);
@@ -4627,15 +4625,12 @@
bool* caught_exception) {
Object* value;
switch (result->type()) {
- case NORMAL: {
- Dictionary* dict =
- JSObject::cast(result->holder())->property_dictionary();
- value = dict->ValueAt(result->GetDictionaryEntry());
+ case NORMAL:
+ value = result->holder()->GetNormalizedProperty(result);
if (value->IsTheHole()) {
return Heap::undefined_value();
}
return value;
- }
case FIELD:
value =
JSObject::cast(
--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---