diff --git a/src/json-parser.h b/src/json-parser.h index 8eb4f67f22..0b8cb769ca 100644 --- a/src/json-parser.h +++ b/src/json-parser.h @@ -289,6 +289,8 @@ Handle JsonParser::ParseJsonValue() { // Parse a JSON object. Position must be right at '{'. template Handle JsonParser::ParseJsonObject() { + int current_index = 0; + Handle prototype; Handle object_constructor( isolate()->native_context()->object_function()); Handle json_object = @@ -309,15 +311,20 @@ Handle JsonParser::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; diff --git a/src/objects-inl.h b/src/objects-inl.h index e769c15e89..b434a91b16 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -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 object, + Handle key) { + if (!object->map()->HasTransitionArray()) return false; + Handle 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 target(transitions->GetTarget(transition)); + JSObject::AddFastPropertyUsingMap(object, target); + return true; +} + + ACCESSORS(Oddball, to_string, String, kToStringOffset) ACCESSORS(Oddball, to_number, Object, kToNumberOffset) diff --git a/src/objects.cc b/src/objects.cc index c9e34d587d..1735175571 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -2794,6 +2794,14 @@ MUST_USE_RESULT Handle JSProxy::CallTrap(const char* name, } +void JSObject::AddFastPropertyUsingMap(Handle object, + Handle map) { + CALL_HEAP_FUNCTION_VOID( + object->GetIsolate(), + object->AddFastPropertyUsingMap(*map)); +} + + MaybeObject* JSObject::SetPropertyForResult(LookupResult* result, String* name_raw, Object* value_raw, diff --git a/src/objects.h b/src/objects.h index 91cafddcdc..56b54323f0 100644 --- a/src/objects.h +++ b/src/objects.h @@ -1621,6 +1621,16 @@ class JSObject: public JSReceiver { Handle 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 object, + Handle 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 object, Handle map); + inline MUST_USE_RESULT MaybeObject* AddFastPropertyUsingMap(Map* map); + // Can cause GC. MUST_USE_RESULT MaybeObject* SetLocalPropertyIgnoreAttributes( String* key,