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
-~----------~----~----~----~------~----~------~--~---

Reply via email to