Index: src/json-parser.h |
diff --git a/src/json-parser.h b/src/json-parser.h |
index d3148c9e21ed295fb8d8bace1924eb080be2e680..29932492dc54d30e884fdd941c3f6dc2b511a9ac 100644 |
--- a/src/json-parser.h |
+++ b/src/json-parser.h |
@@ -182,6 +182,9 @@ class JsonParser BASE_EMBEDDED { |
private: |
Zone* zone() { return &zone_; } |
+ void CommitStateToJsonObject(Handle<JSObject> json_object, Handle<Map> map, |
+ ZoneList<Handle<Object> >* properties); |
+ |
Handle<String> source_; |
int source_length_; |
Handle<SeqOneByteString> seq_source_; |
@@ -410,13 +413,7 @@ Handle<Object> JsonParser<seq_one_byte>::ParseJsonObject() { |
} |
// Commit the intermediate state to the object and stop transitioning. |
- JSObject::AllocateStorageForMap(json_object, map); |
- int length = properties.length(); |
- for (int i = 0; i < length; i++) { |
- Handle<Object> value = properties[i]; |
- FieldIndex index = FieldIndex::ForPropertyIndex(*map, i); |
- json_object->FastPropertyAtPut(index, *value); |
- } |
+ CommitStateToJsonObject(json_object, map, &properties); |
} else { |
key = ParseJsonInternalizedString(); |
if (key.is_null() || c0_ != ':') return ReportUnexpectedCharacter(); |
@@ -434,19 +431,50 @@ Handle<Object> JsonParser<seq_one_byte>::ParseJsonObject() { |
// If we transitioned until the very end, transition the map now. |
if (transitioning) { |
- JSObject::AllocateStorageForMap(json_object, map); |
- int length = properties.length(); |
- for (int i = 0; i < length; i++) { |
- Handle<Object> value = properties[i]; |
- FieldIndex index = FieldIndex::ForPropertyIndex(*map, i); |
- json_object->FastPropertyAtPut(index, *value); |
- } |
+ CommitStateToJsonObject(json_object, map, &properties); |
} |
} |
AdvanceSkipWhitespace(); |
return scope.CloseAndEscape(json_object); |
} |
+ |
+template <bool seq_one_byte> |
+void JsonParser<seq_one_byte>::CommitStateToJsonObject( |
+ Handle<JSObject> json_object, Handle<Map> map, |
+ ZoneList<Handle<Object> >* properties) { |
+ JSObject::AllocateStorageForMap(json_object, map); |
+ DCHECK(!json_object->map()->is_dictionary_map()); |
+ |
+ DisallowHeapAllocation no_gc; |
+ Factory* factory = isolate()->factory(); |
+ // If the |json_object|'s map is exactly the same as |map| then the |
+ // |properties| values correspond to the |map| and nothing more has to be |
+ // done. But if the |json_object|'s map is different then we have to |
+ // iterate descriptors to ensure that properties still correspond to the |
+ // map. |
+ bool slow_case = json_object->map() != *map; |
+ DescriptorArray* descriptors = NULL; |
+ |
+ int length = properties->length(); |
+ if (slow_case) { |
+ descriptors = json_object->map()->instance_descriptors(); |
+ DCHECK(json_object->map()->NumberOfOwnDescriptors() == length); |
+ } |
+ for (int i = 0; i < length; i++) { |
+ Handle<Object> value = (*properties)[i]; |
+ if (slow_case && value->IsMutableHeapNumber() && |
+ !descriptors->GetDetails(i).representation().IsDouble()) { |
+ // Turn mutable heap numbers into immutable if the field representation |
+ // is not double. |
+ HeapNumber::cast(*value)->set_map(*factory->heap_number_map()); |
+ } |
+ FieldIndex index = FieldIndex::ForPropertyIndex(*map, i); |
+ json_object->FastPropertyAtPut(index, *value); |
+ } |
+} |
+ |
+ |
// Parse a JSON array. Position must be right at '['. |
template <bool seq_one_byte> |
Handle<Object> JsonParser<seq_one_byte>::ParseJsonArray() { |