Commit e452c107 authored by yangguo@chromium.org's avatar yangguo@chromium.org

Add fast path for FastProperty objects in JSON.stringify.

R=verwaest@chromium.org
BUG=

Review URL: https://chromiumcodereview.appspot.com/11363078

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12853 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent ea00c51e
......@@ -560,36 +560,68 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject(
JSObject::cast(object->GetPrototype()), isolate_);
ASSERT(object->IsGlobalObject());
}
bool has_exception = false;
Handle<FixedArray> contents =
GetKeysInFixedArrayFor(object, LOCAL_ONLY, &has_exception);
if (has_exception) return EXCEPTION;
Append('{');
bool comma = false;
for (int i = 0; i < contents->length(); i++) {
Object* key = contents->get(i);
Handle<String> key_handle;
Handle<Object> property;
if (key->IsString()) {
key_handle = Handle<String>(String::cast(key), isolate_);
property = GetProperty(object, key_handle);
} else {
ASSERT(key->IsNumber());
key_handle = factory_->NumberToString(Handle<Object>(key, isolate_));
uint32_t index;
if (key->IsSmi()) {
property = Object::GetElement(object, Smi::cast(key)->value());
} else if (key_handle->AsArrayIndex(&index)) {
property = Object::GetElement(object, index);
if (object->HasFastProperties() &&
!object->HasIndexedInterceptor() &&
!object->HasNamedInterceptor() &&
object->elements() == isolate_->heap()->empty_fixed_array()) {
Handle<DescriptorArray> descs(
object->map()->instance_descriptors(), isolate_);
int num_desc = object->map()->NumberOfOwnDescriptors();
Handle<Map> map(object->map());
bool map_changed = false;
for (int i = 0; i < num_desc; i++) {
Handle<String> key(descs->GetKey(i), isolate_);
PropertyDetails details = descs->GetDetails(i);
if (details.IsDontEnum() || details.IsDeleted()) continue;
Handle<Object> property;
if (details.type() == FIELD && !map_changed) {
property = Handle<Object>(
object->FastPropertyAt(descs->GetFieldIndex(i)), isolate_);
} else {
property = GetProperty(object, key);
}
if (property.is_null()) return EXCEPTION;
Result result = SerializeProperty(property, comma, key);
if (!comma && result == SUCCESS) comma = true;
if (result >= EXCEPTION) return result;
if (*map != object->map()) map_changed = true;
}
} else {
bool has_exception = false;
Handle<FixedArray> contents =
GetKeysInFixedArrayFor(object, LOCAL_ONLY, &has_exception);
if (has_exception) return EXCEPTION;
for (int i = 0; i < contents->length(); i++) {
Object* key = contents->get(i);
Handle<String> key_handle;
Handle<Object> property;
if (key->IsString()) {
key_handle = Handle<String>(String::cast(key), isolate_);
property = GetProperty(object, key_handle);
} else {
ASSERT(key->IsNumber());
key_handle = factory_->NumberToString(Handle<Object>(key, isolate_));
uint32_t index;
if (key->IsSmi()) {
property = Object::GetElement(object, Smi::cast(key)->value());
} else if (key_handle->AsArrayIndex(&index)) {
property = Object::GetElement(object, index);
} else {
property = GetProperty(object, key_handle);
}
}
if (property.is_null()) return EXCEPTION;
Result result = SerializeProperty(property, comma, key_handle);
if (!comma && result == SUCCESS) comma = true;
if (result >= EXCEPTION) return result;
}
if (property.is_null()) return EXCEPTION;
Result result = SerializeProperty(property, comma, key_handle);
if (!comma && result == SUCCESS) comma = true;
if (result >= EXCEPTION) return result;
}
Append('}');
StackPop();
current_part_ = handle_scope.CloseAndEscape(current_part_);
......
......@@ -154,3 +154,25 @@ var proxy6 = Proxy.create(handler6);
testStringify('[1,null,true]', [1, proxy6, true]);
testStringify('{"a":1,"c":true}', {a: 1, b: proxy6, c: true});
// Object containing a proxy that changes the parent's properties.
var handler7 = {
get: function(target, name) {
delete parent7.a;
delete parent7.c;
parent7.e = "5";
return name.toUpperCase();
},
enumerate: function(target) {
return ['a', 'b', 'c'];
},
getOwnPropertyDescriptor: function(target, name) {
return { enumerable: true };
}
}
var proxy7 = Proxy.create(handler7);
var parent7 = { a: "1", b: proxy7, c: "3", d: "4" };
assertEquals('{"a":"1","b":{"a":"A","b":"B","c":"C"},"d":"4"}',
JSON.stringify(parent7));
assertEquals('{"b":{"a":"A","b":"B","c":"C"},"d":"4","e":"5"}',
JSON.stringify(parent7));
......@@ -133,3 +133,21 @@ fast_obj.__proto__ = [7, 7, 7, 7];
delete fast_obj[2];
assertTrue(%HasFastObjectElements(fast_obj));
assertEquals("[1,2,7,{}]", JSON.stringify(fast_obj));
var getter_side_effect = { a: 1,
get b() {
delete this.a;
delete this.c;
this.e = 5;
return 2;
},
c: 3,
d: 4 };
assertEquals('{"a":1,"b":2,"d":4}', JSON.stringify(getter_side_effect));
assertEquals('{"b":2,"d":4,"e":5}', JSON.stringify(getter_side_effect));
var non_enum = {};
non_enum.a = 1;
Object.defineProperty(non_enum, "b", { value: 2, enumerable: false });
non_enum.c = 3;
assertEquals('{"a":1,"c":3}', JSON.stringify(non_enum));
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment