Eagerly follow transitions to existing maps while json parsing.
authorverwaest@chromium.org <verwaest@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 17 Oct 2012 14:09:42 +0000 (14:09 +0000)
committerverwaest@chromium.org <verwaest@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 17 Oct 2012 14:09:42 +0000 (14:09 +0000)
Review URL: https://chromiumcodereview.appspot.com/11184006

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12747 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/json-parser.h
src/objects-inl.h
src/objects.cc
src/objects.h

index 8eb4f67..0b8cb76 100644 (file)
@@ -289,6 +289,8 @@ Handle<Object> JsonParser<seq_ascii>::ParseJsonValue() {
 // Parse a JSON object. Position must be right at '{'.
 template <bool seq_ascii>
 Handle<Object> JsonParser<seq_ascii>::ParseJsonObject() {
+  int current_index = 0;
+  Handle<Object> prototype;
   Handle<JSFunction> object_constructor(
       isolate()->native_context()->object_function());
   Handle<JSObject> json_object =
@@ -309,15 +311,20 @@ Handle<Object> JsonParser<seq_ascii>::ParseJsonObject() {
       if (key->AsArrayIndex(&index)) {
         JSObject::SetOwnElement(json_object, index, value, kNonStrictMode);
       } else if (key->Equals(isolate()->heap()->Proto_symbol())) {
-        SetPrototype(json_object, value);
+        prototype = value;
       } else {
-        JSObject::SetLocalPropertyIgnoreAttributes(
-            json_object, key, value, NONE);
+        if (JSObject::TryTransitionToField(json_object, key)) {
+          json_object->FastPropertyAtPut(current_index++, *value);
+        } else {
+          JSObject::SetLocalPropertyIgnoreAttributes(
+              json_object, key, value, NONE);
+        }
       }
     } while (MatchSkipWhiteSpace(','));
     if (c0_ != '}') {
       return ReportUnexpectedCharacter();
     }
+    if (!prototype.is_null()) SetPrototype(json_object, prototype);
   }
   AdvanceSkipWhitespace();
   return json_object;
index e769c15..b434a91 100644 (file)
@@ -1414,6 +1414,36 @@ MaybeObject* JSObject::ResetElements() {
 }
 
 
+MaybeObject* JSObject::AddFastPropertyUsingMap(Map* map) {
+  ASSERT(this->map()->NumberOfOwnDescriptors() + 1 ==
+         map->NumberOfOwnDescriptors());
+  if (this->map()->unused_property_fields() == 0) {
+    int new_size = properties()->length() + map->unused_property_fields() + 1;
+    FixedArray* new_properties;
+    MaybeObject* maybe_properties = properties()->CopySize(new_size);
+    if (!maybe_properties->To(&new_properties)) return maybe_properties;
+    set_properties(new_properties);
+  }
+  set_map(map);
+  return this;
+}
+
+
+bool JSObject::TryTransitionToField(Handle<JSObject> object,
+                                    Handle<String> key) {
+  if (!object->map()->HasTransitionArray()) return false;
+  Handle<TransitionArray> transitions(object->map()->transitions());
+  int transition = transitions->Search(*key);
+  if (transition == TransitionArray::kNotFound) return false;
+  PropertyDetails target_details = transitions->GetTargetDetails(transition);
+  if (target_details.type() != FIELD) return false;
+  if (target_details.attributes() != NONE) return false;
+  Handle<Map> target(transitions->GetTarget(transition));
+  JSObject::AddFastPropertyUsingMap(object, target);
+  return true;
+}
+
+
 ACCESSORS(Oddball, to_string, String, kToStringOffset)
 ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
 
index c9e34d5..1735175 100644 (file)
@@ -2794,6 +2794,14 @@ MUST_USE_RESULT Handle<Object> JSProxy::CallTrap(const char* name,
 }
 
 
+void JSObject::AddFastPropertyUsingMap(Handle<JSObject> object,
+                                       Handle<Map> map) {
+  CALL_HEAP_FUNCTION_VOID(
+      object->GetIsolate(),
+      object->AddFastPropertyUsingMap(*map));
+}
+
+
 MaybeObject* JSObject::SetPropertyForResult(LookupResult* result,
                                             String* name_raw,
                                             Object* value_raw,
index 91cafdd..56b5432 100644 (file)
@@ -1621,6 +1621,16 @@ class JSObject: public JSReceiver {
       Handle<Object> value,
       PropertyAttributes attributes);
 
+  // Try to follow an existing transition to a field with attributes NONE. The
+  // return value indicates whether the transition was successful.
+  static inline bool TryTransitionToField(Handle<JSObject> object,
+                                          Handle<String> key);
+
+  // Extend the receiver with a single fast property appeared first in the
+  // passed map. This also extends the property backing store if necessary.
+  static void AddFastPropertyUsingMap(Handle<JSObject> object, Handle<Map> map);
+  inline MUST_USE_RESULT MaybeObject* AddFastPropertyUsingMap(Map* map);
+
   // Can cause GC.
   MUST_USE_RESULT MaybeObject* SetLocalPropertyIgnoreAttributes(
       String* key,