| Index: src/objects.cc
|
| diff --git a/src/objects.cc b/src/objects.cc
|
| index a3163eb619c6d76ff18ab33db93ded19414542c3..f3e7471c07b74a43421ae1c90f110d9374211ec5 100644
|
| --- a/src/objects.cc
|
| +++ b/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).
|
|
|