Move DeepCopy of JSObject from runtime to object.
BUG= Review URL: https://codereview.chromium.org/13527005 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14121 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
01ccd0f602
commit
2545774232
139
src/objects.cc
139
src/objects.cc
@ -4689,6 +4689,145 @@ MaybeObject* JSObject::PreventExtensions() {
|
||||
}
|
||||
|
||||
|
||||
MUST_USE_RESULT MaybeObject* JSObject::DeepCopy(Isolate* isolate) {
|
||||
StackLimitCheck check(isolate);
|
||||
if (check.HasOverflowed()) return isolate->StackOverflow();
|
||||
|
||||
Heap* heap = isolate->heap();
|
||||
Object* result;
|
||||
{ MaybeObject* maybe_result = heap->CopyJSObject(this);
|
||||
if (!maybe_result->ToObject(&result)) return maybe_result;
|
||||
}
|
||||
JSObject* copy = JSObject::cast(result);
|
||||
|
||||
// Deep copy local properties.
|
||||
if (copy->HasFastProperties()) {
|
||||
FixedArray* properties = copy->properties();
|
||||
for (int i = 0; i < properties->length(); i++) {
|
||||
Object* value = properties->get(i);
|
||||
if (value->IsJSObject()) {
|
||||
JSObject* js_object = JSObject::cast(value);
|
||||
{ MaybeObject* maybe_result = js_object->DeepCopy(isolate);
|
||||
if (!maybe_result->ToObject(&result)) return maybe_result;
|
||||
}
|
||||
properties->set(i, result);
|
||||
}
|
||||
}
|
||||
int nof = copy->map()->inobject_properties();
|
||||
for (int i = 0; i < nof; i++) {
|
||||
Object* value = copy->InObjectPropertyAt(i);
|
||||
if (value->IsJSObject()) {
|
||||
JSObject* js_object = JSObject::cast(value);
|
||||
{ MaybeObject* maybe_result = js_object->DeepCopy(isolate);
|
||||
if (!maybe_result->ToObject(&result)) return maybe_result;
|
||||
}
|
||||
copy->InObjectPropertyAtPut(i, result);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
{ MaybeObject* maybe_result =
|
||||
heap->AllocateFixedArray(copy->NumberOfLocalProperties());
|
||||
if (!maybe_result->ToObject(&result)) return maybe_result;
|
||||
}
|
||||
FixedArray* names = FixedArray::cast(result);
|
||||
copy->GetLocalPropertyNames(names, 0);
|
||||
for (int i = 0; i < names->length(); i++) {
|
||||
ASSERT(names->get(i)->IsString());
|
||||
String* key_string = String::cast(names->get(i));
|
||||
PropertyAttributes attributes =
|
||||
copy->GetLocalPropertyAttribute(key_string);
|
||||
// Only deep copy fields from the object literal expression.
|
||||
// In particular, don't try to copy the length attribute of
|
||||
// an array.
|
||||
if (attributes != NONE) continue;
|
||||
Object* value =
|
||||
copy->GetProperty(key_string, &attributes)->ToObjectUnchecked();
|
||||
if (value->IsJSObject()) {
|
||||
JSObject* js_object = JSObject::cast(value);
|
||||
{ MaybeObject* maybe_result = js_object->DeepCopy(isolate);
|
||||
if (!maybe_result->ToObject(&result)) return maybe_result;
|
||||
}
|
||||
{ MaybeObject* maybe_result =
|
||||
// Creating object copy for literals. No strict mode needed.
|
||||
copy->SetProperty(key_string, result, NONE, kNonStrictMode);
|
||||
if (!maybe_result->ToObject(&result)) return maybe_result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Deep copy local elements.
|
||||
// Pixel elements cannot be created using an object literal.
|
||||
ASSERT(!copy->HasExternalArrayElements());
|
||||
switch (copy->GetElementsKind()) {
|
||||
case FAST_SMI_ELEMENTS:
|
||||
case FAST_ELEMENTS:
|
||||
case FAST_HOLEY_SMI_ELEMENTS:
|
||||
case FAST_HOLEY_ELEMENTS: {
|
||||
FixedArray* elements = FixedArray::cast(copy->elements());
|
||||
if (elements->map() == heap->fixed_cow_array_map()) {
|
||||
isolate->counters()->cow_arrays_created_runtime()->Increment();
|
||||
#ifdef DEBUG
|
||||
for (int i = 0; i < elements->length(); i++) {
|
||||
ASSERT(!elements->get(i)->IsJSObject());
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
for (int i = 0; i < elements->length(); i++) {
|
||||
Object* value = elements->get(i);
|
||||
ASSERT(value->IsSmi() ||
|
||||
value->IsTheHole() ||
|
||||
(IsFastObjectElementsKind(copy->GetElementsKind())));
|
||||
if (value->IsJSObject()) {
|
||||
JSObject* js_object = JSObject::cast(value);
|
||||
{ MaybeObject* maybe_result = js_object->DeepCopy(isolate);
|
||||
if (!maybe_result->ToObject(&result)) return maybe_result;
|
||||
}
|
||||
elements->set(i, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DICTIONARY_ELEMENTS: {
|
||||
SeededNumberDictionary* element_dictionary = copy->element_dictionary();
|
||||
int capacity = element_dictionary->Capacity();
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
Object* k = element_dictionary->KeyAt(i);
|
||||
if (element_dictionary->IsKey(k)) {
|
||||
Object* value = element_dictionary->ValueAt(i);
|
||||
if (value->IsJSObject()) {
|
||||
JSObject* js_object = JSObject::cast(value);
|
||||
{ MaybeObject* maybe_result = js_object->DeepCopy(isolate);
|
||||
if (!maybe_result->ToObject(&result)) return maybe_result;
|
||||
}
|
||||
element_dictionary->ValueAtPut(i, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NON_STRICT_ARGUMENTS_ELEMENTS:
|
||||
UNIMPLEMENTED();
|
||||
break;
|
||||
case EXTERNAL_PIXEL_ELEMENTS:
|
||||
case EXTERNAL_BYTE_ELEMENTS:
|
||||
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
||||
case EXTERNAL_SHORT_ELEMENTS:
|
||||
case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
||||
case EXTERNAL_INT_ELEMENTS:
|
||||
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
||||
case EXTERNAL_FLOAT_ELEMENTS:
|
||||
case EXTERNAL_DOUBLE_ELEMENTS:
|
||||
case FAST_DOUBLE_ELEMENTS:
|
||||
case FAST_HOLEY_DOUBLE_ELEMENTS:
|
||||
// No contained objects, nothing to do.
|
||||
break;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
|
||||
// Tests for the fast common case for property enumeration:
|
||||
// - This object and all prototypes has an enum cache (which means that
|
||||
// it is no proxy, has no interceptors and needs no access checks).
|
||||
|
@ -2218,6 +2218,8 @@ class JSObject: public JSReceiver {
|
||||
static Handle<Object> PreventExtensions(Handle<JSObject> object);
|
||||
MUST_USE_RESULT MaybeObject* PreventExtensions();
|
||||
|
||||
// Copy object
|
||||
MUST_USE_RESULT MaybeObject* DeepCopy(Isolate* isolate);
|
||||
|
||||
// Dispatched behavior.
|
||||
void JSObjectShortPrint(StringStream* accumulator);
|
||||
|
146
src/runtime.cc
146
src/runtime.cc
@ -139,148 +139,6 @@ namespace internal {
|
||||
static_cast<LanguageMode>(args.smi_at(index));
|
||||
|
||||
|
||||
MUST_USE_RESULT static MaybeObject* DeepCopyBoilerplate(Isolate* isolate,
|
||||
JSObject* boilerplate) {
|
||||
StackLimitCheck check(isolate);
|
||||
if (check.HasOverflowed()) return isolate->StackOverflow();
|
||||
|
||||
Heap* heap = isolate->heap();
|
||||
Object* result;
|
||||
{ MaybeObject* maybe_result = heap->CopyJSObject(boilerplate);
|
||||
if (!maybe_result->ToObject(&result)) return maybe_result;
|
||||
}
|
||||
JSObject* copy = JSObject::cast(result);
|
||||
|
||||
// Deep copy local properties.
|
||||
if (copy->HasFastProperties()) {
|
||||
FixedArray* properties = copy->properties();
|
||||
for (int i = 0; i < properties->length(); i++) {
|
||||
Object* value = properties->get(i);
|
||||
if (value->IsJSObject()) {
|
||||
JSObject* js_object = JSObject::cast(value);
|
||||
{ MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, js_object);
|
||||
if (!maybe_result->ToObject(&result)) return maybe_result;
|
||||
}
|
||||
properties->set(i, result);
|
||||
}
|
||||
}
|
||||
int nof = copy->map()->inobject_properties();
|
||||
for (int i = 0; i < nof; i++) {
|
||||
Object* value = copy->InObjectPropertyAt(i);
|
||||
if (value->IsJSObject()) {
|
||||
JSObject* js_object = JSObject::cast(value);
|
||||
{ MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, js_object);
|
||||
if (!maybe_result->ToObject(&result)) return maybe_result;
|
||||
}
|
||||
copy->InObjectPropertyAtPut(i, result);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
{ MaybeObject* maybe_result =
|
||||
heap->AllocateFixedArray(copy->NumberOfLocalProperties());
|
||||
if (!maybe_result->ToObject(&result)) return maybe_result;
|
||||
}
|
||||
FixedArray* names = FixedArray::cast(result);
|
||||
copy->GetLocalPropertyNames(names, 0);
|
||||
for (int i = 0; i < names->length(); i++) {
|
||||
ASSERT(names->get(i)->IsString());
|
||||
String* key_string = String::cast(names->get(i));
|
||||
PropertyAttributes attributes =
|
||||
copy->GetLocalPropertyAttribute(key_string);
|
||||
// Only deep copy fields from the object literal expression.
|
||||
// In particular, don't try to copy the length attribute of
|
||||
// an array.
|
||||
if (attributes != NONE) continue;
|
||||
Object* value =
|
||||
copy->GetProperty(key_string, &attributes)->ToObjectUnchecked();
|
||||
if (value->IsJSObject()) {
|
||||
JSObject* js_object = JSObject::cast(value);
|
||||
{ MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, js_object);
|
||||
if (!maybe_result->ToObject(&result)) return maybe_result;
|
||||
}
|
||||
{ MaybeObject* maybe_result =
|
||||
// Creating object copy for literals. No strict mode needed.
|
||||
copy->SetProperty(key_string, result, NONE, kNonStrictMode);
|
||||
if (!maybe_result->ToObject(&result)) return maybe_result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Deep copy local elements.
|
||||
// Pixel elements cannot be created using an object literal.
|
||||
ASSERT(!copy->HasExternalArrayElements());
|
||||
switch (copy->GetElementsKind()) {
|
||||
case FAST_SMI_ELEMENTS:
|
||||
case FAST_ELEMENTS:
|
||||
case FAST_HOLEY_SMI_ELEMENTS:
|
||||
case FAST_HOLEY_ELEMENTS: {
|
||||
FixedArray* elements = FixedArray::cast(copy->elements());
|
||||
if (elements->map() == heap->fixed_cow_array_map()) {
|
||||
isolate->counters()->cow_arrays_created_runtime()->Increment();
|
||||
#ifdef DEBUG
|
||||
for (int i = 0; i < elements->length(); i++) {
|
||||
ASSERT(!elements->get(i)->IsJSObject());
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
for (int i = 0; i < elements->length(); i++) {
|
||||
Object* value = elements->get(i);
|
||||
ASSERT(value->IsSmi() ||
|
||||
value->IsTheHole() ||
|
||||
(IsFastObjectElementsKind(copy->GetElementsKind())));
|
||||
if (value->IsJSObject()) {
|
||||
JSObject* js_object = JSObject::cast(value);
|
||||
{ MaybeObject* maybe_result = DeepCopyBoilerplate(isolate,
|
||||
js_object);
|
||||
if (!maybe_result->ToObject(&result)) return maybe_result;
|
||||
}
|
||||
elements->set(i, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DICTIONARY_ELEMENTS: {
|
||||
SeededNumberDictionary* element_dictionary = copy->element_dictionary();
|
||||
int capacity = element_dictionary->Capacity();
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
Object* k = element_dictionary->KeyAt(i);
|
||||
if (element_dictionary->IsKey(k)) {
|
||||
Object* value = element_dictionary->ValueAt(i);
|
||||
if (value->IsJSObject()) {
|
||||
JSObject* js_object = JSObject::cast(value);
|
||||
{ MaybeObject* maybe_result = DeepCopyBoilerplate(isolate,
|
||||
js_object);
|
||||
if (!maybe_result->ToObject(&result)) return maybe_result;
|
||||
}
|
||||
element_dictionary->ValueAtPut(i, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NON_STRICT_ARGUMENTS_ELEMENTS:
|
||||
UNIMPLEMENTED();
|
||||
break;
|
||||
case EXTERNAL_PIXEL_ELEMENTS:
|
||||
case EXTERNAL_BYTE_ELEMENTS:
|
||||
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
||||
case EXTERNAL_SHORT_ELEMENTS:
|
||||
case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
||||
case EXTERNAL_INT_ELEMENTS:
|
||||
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
||||
case EXTERNAL_FLOAT_ELEMENTS:
|
||||
case EXTERNAL_DOUBLE_ELEMENTS:
|
||||
case FAST_DOUBLE_ELEMENTS:
|
||||
case FAST_HOLEY_DOUBLE_ELEMENTS:
|
||||
// No contained objects, nothing to do.
|
||||
break;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
|
||||
static Handle<Map> ComputeObjectLiteralMap(
|
||||
Handle<Context> context,
|
||||
Handle<FixedArray> constant_properties,
|
||||
@ -599,7 +457,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectLiteral) {
|
||||
// Update the functions literal and return the boilerplate.
|
||||
literals->set(literals_index, *boilerplate);
|
||||
}
|
||||
return DeepCopyBoilerplate(isolate, JSObject::cast(*boilerplate));
|
||||
return JSObject::cast(*boilerplate)->DeepCopy(isolate);
|
||||
}
|
||||
|
||||
|
||||
@ -646,7 +504,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteral) {
|
||||
// Update the functions literal and return the boilerplate.
|
||||
literals->set(literals_index, *boilerplate);
|
||||
}
|
||||
return DeepCopyBoilerplate(isolate, JSObject::cast(*boilerplate));
|
||||
return JSObject::cast(*boilerplate)->DeepCopy(isolate);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user