[runtime] Move 'copying' flag to ContextObject, don't copy named properties for array boilerplates

Bug: 
Change-Id: Ie754efaec80eb175ac18c328c750524009ca8e60
Reviewed-on: https://chromium-review.googlesource.com/517104
Reviewed-by: Igor Sheludko <ishell@chromium.org>
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#45572}
This commit is contained in:
Toon Verwaest 2017-05-26 15:08:16 +02:00 committed by Commit Bot
parent b853d7fbb3
commit fa2ed010e6
2 changed files with 68 additions and 71 deletions

View File

@ -53,6 +53,7 @@ class AllocationSiteCreationContext : public AllocationSiteContext {
Handle<AllocationSite> EnterNewScope(); Handle<AllocationSite> EnterNewScope();
void ExitScope(Handle<AllocationSite> site, Handle<JSObject> object); void ExitScope(Handle<AllocationSite> site, Handle<JSObject> object);
static const bool kCopying = false;
}; };
@ -86,6 +87,7 @@ class AllocationSiteUsageContext : public AllocationSiteContext {
} }
bool ShouldCreateMemento(Handle<JSObject> object); bool ShouldCreateMemento(Handle<JSObject> object);
static const bool kCopying = true;
private: private:
Handle<AllocationSite> top_site_; Handle<AllocationSite> top_site_;

View File

@ -7886,11 +7886,9 @@ Handle<Object> JSObject::FastPropertyAt(Handle<JSObject> object,
template <class ContextObject> template <class ContextObject>
class JSObjectWalkVisitor { class JSObjectWalkVisitor {
public: public:
JSObjectWalkVisitor(ContextObject* site_context, bool copying, JSObjectWalkVisitor(ContextObject* site_context,
JSObject::DeepCopyHints hints) JSObject::DeepCopyHints hints)
: site_context_(site_context), : site_context_(site_context), hints_(hints) {}
copying_(copying),
hints_(hints) {}
MUST_USE_RESULT MaybeHandle<JSObject> StructureWalk(Handle<JSObject> object); MUST_USE_RESULT MaybeHandle<JSObject> StructureWalk(Handle<JSObject> object);
@ -7907,11 +7905,8 @@ class JSObjectWalkVisitor {
inline ContextObject* site_context() { return site_context_; } inline ContextObject* site_context() { return site_context_; }
inline Isolate* isolate() { return site_context()->isolate(); } inline Isolate* isolate() { return site_context()->isolate(); }
inline bool copying() const { return copying_; }
private: private:
ContextObject* site_context_; ContextObject* site_context_;
const bool copying_;
const JSObject::DeepCopyHints hints_; const JSObject::DeepCopyHints hints_;
}; };
@ -7919,7 +7914,7 @@ template <class ContextObject>
MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk( MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
Handle<JSObject> object) { Handle<JSObject> object) {
Isolate* isolate = this->isolate(); Isolate* isolate = this->isolate();
bool copying = this->copying(); bool copying = ContextObject::kCopying;
bool shallow = hints_ == JSObject::kObjectIsShallow; bool shallow = hints_ == JSObject::kObjectIsShallow;
if (!shallow) { if (!shallow) {
@ -7958,33 +7953,32 @@ MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
isolate->counters()->cow_arrays_created_runtime()->Increment(); isolate->counters()->cow_arrays_created_runtime()->Increment();
} }
if (!shallow) { if (shallow) return copy;
HandleScope scope(isolate);
// Deep copy own properties. HandleScope scope(isolate);
// Deep copy own properties. Arrays only have 1 property "length".
if (!copy->IsJSArray()) {
if (copy->HasFastProperties()) { if (copy->HasFastProperties()) {
Handle<DescriptorArray> descriptors(copy->map()->instance_descriptors()); Handle<DescriptorArray> descriptors(copy->map()->instance_descriptors());
// Skip the length field of JSArrays.
int i = copy->IsJSArray() ? 1 : 0;
int limit = copy->map()->NumberOfOwnDescriptors(); int limit = copy->map()->NumberOfOwnDescriptors();
for (; i < limit; i++) { for (int i = 0; i < limit; i++) {
DCHECK_EQ(kField, descriptors->GetDetails(i).location()); DCHECK_EQ(kField, descriptors->GetDetails(i).location());
DCHECK_EQ(kData, descriptors->GetDetails(i).kind()); DCHECK_EQ(kData, descriptors->GetDetails(i).kind());
FieldIndex index = FieldIndex::ForDescriptor(copy->map(), i); FieldIndex index = FieldIndex::ForDescriptor(copy->map(), i);
if (copy->IsUnboxedDoubleField(index)) continue; if (copy->IsUnboxedDoubleField(index)) continue;
Object* raw = copy->RawFastPropertyAt(index); Object* raw = copy->RawFastPropertyAt(index);
if (raw->IsMutableHeapNumber()) { if (raw->IsJSObject()) {
if (!copying) continue; Handle<JSObject> value(JSObject::cast(raw), isolate);
ASSIGN_RETURN_ON_EXCEPTION(
isolate, value, VisitElementOrProperty(copy, value), JSObject);
if (copying) copy->FastPropertyAtPut(index, *value);
} else if (copying && raw->IsMutableHeapNumber()) {
DCHECK(descriptors->GetDetails(i).representation().IsDouble()); DCHECK(descriptors->GetDetails(i).representation().IsDouble());
uint64_t double_value = HeapNumber::cast(raw)->value_as_bits(); uint64_t double_value = HeapNumber::cast(raw)->value_as_bits();
Handle<HeapNumber> value = isolate->factory()->NewHeapNumber(MUTABLE); Handle<HeapNumber> value = isolate->factory()->NewHeapNumber(MUTABLE);
value->set_value_as_bits(double_value); value->set_value_as_bits(double_value);
copy->FastPropertyAtPut(index, *value); copy->FastPropertyAtPut(index, *value);
} else if (raw->IsJSObject()) {
Handle<JSObject> value(JSObject::cast(raw), isolate);
ASSIGN_RETURN_ON_EXCEPTION(
isolate, value, VisitElementOrProperty(copy, value), JSObject);
if (copying) copy->FastPropertyAtPut(index, *value);
} }
} }
} else { } else {
@ -8000,54 +7994,57 @@ MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
} }
} }
// Deep copy own elements. // Assume non-arrays don't end up having elements.
switch (kind) { if (copy->elements()->length() == 0) return copy;
case FAST_ELEMENTS: }
case FAST_HOLEY_ELEMENTS: {
Handle<FixedArray> elements(FixedArray::cast(copy->elements())); // Deep copy own elements.
if (elements->map() == isolate->heap()->fixed_cow_array_map()) { switch (kind) {
case FAST_ELEMENTS:
case FAST_HOLEY_ELEMENTS: {
Handle<FixedArray> elements(FixedArray::cast(copy->elements()));
if (elements->map() == isolate->heap()->fixed_cow_array_map()) {
#ifdef DEBUG #ifdef DEBUG
for (int i = 0; i < elements->length(); i++) { for (int i = 0; i < elements->length(); i++) {
DCHECK(!elements->get(i)->IsJSObject()); DCHECK(!elements->get(i)->IsJSObject());
}
#endif
} else {
for (int i = 0; i < elements->length(); i++) {
Object* raw = elements->get(i);
if (!raw->IsJSObject()) continue;
Handle<JSObject> value(JSObject::cast(raw), isolate);
ASSIGN_RETURN_ON_EXCEPTION(
isolate, value, VisitElementOrProperty(copy, value), JSObject);
if (copying) elements->set(i, *value);
}
} }
break; #endif
} } else {
case DICTIONARY_ELEMENTS: { for (int i = 0; i < elements->length(); i++) {
Handle<SeededNumberDictionary> element_dictionary( Object* raw = elements->get(i);
copy->element_dictionary());
int capacity = element_dictionary->Capacity();
for (int i = 0; i < capacity; i++) {
Object* raw = element_dictionary->ValueAt(i);
if (!raw->IsJSObject()) continue; if (!raw->IsJSObject()) continue;
Handle<JSObject> value(JSObject::cast(raw), isolate); Handle<JSObject> value(JSObject::cast(raw), isolate);
ASSIGN_RETURN_ON_EXCEPTION( ASSIGN_RETURN_ON_EXCEPTION(
isolate, value, VisitElementOrProperty(copy, value), JSObject); isolate, value, VisitElementOrProperty(copy, value), JSObject);
if (copying) element_dictionary->ValueAtPut(i, *value); if (copying) elements->set(i, *value);
} }
break;
} }
case FAST_SLOPPY_ARGUMENTS_ELEMENTS: break;
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: }
UNIMPLEMENTED(); case DICTIONARY_ELEMENTS: {
break; Handle<SeededNumberDictionary> element_dictionary(
case FAST_STRING_WRAPPER_ELEMENTS: copy->element_dictionary());
case SLOW_STRING_WRAPPER_ELEMENTS: int capacity = element_dictionary->Capacity();
UNREACHABLE(); for (int i = 0; i < capacity; i++) {
break; Object* raw = element_dictionary->ValueAt(i);
if (!raw->IsJSObject()) continue;
Handle<JSObject> value(JSObject::cast(raw), isolate);
ASSIGN_RETURN_ON_EXCEPTION(
isolate, value, VisitElementOrProperty(copy, value), JSObject);
if (copying) element_dictionary->ValueAtPut(i, *value);
}
break;
}
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
UNIMPLEMENTED();
break;
case FAST_STRING_WRAPPER_ELEMENTS:
case SLOW_STRING_WRAPPER_ELEMENTS:
UNREACHABLE();
break;
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) case TYPE##_ELEMENTS:
case TYPE##_ELEMENTS: \
TYPED_ARRAYS(TYPED_ARRAY_CASE) TYPED_ARRAYS(TYPED_ARRAY_CASE)
#undef TYPED_ARRAY_CASE #undef TYPED_ARRAY_CASE
@ -8055,14 +8052,13 @@ MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
UNREACHABLE(); UNREACHABLE();
break; break;
case FAST_SMI_ELEMENTS: case FAST_SMI_ELEMENTS:
case FAST_HOLEY_SMI_ELEMENTS: case FAST_HOLEY_SMI_ELEMENTS:
case FAST_DOUBLE_ELEMENTS: case FAST_DOUBLE_ELEMENTS:
case FAST_HOLEY_DOUBLE_ELEMENTS: case FAST_HOLEY_DOUBLE_ELEMENTS:
case NO_ELEMENTS: case NO_ELEMENTS:
// No contained objects, nothing to do. // No contained objects, nothing to do.
break; break;
}
} }
return copy; return copy;
@ -8072,8 +8068,7 @@ MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
MaybeHandle<JSObject> JSObject::DeepWalk( MaybeHandle<JSObject> JSObject::DeepWalk(
Handle<JSObject> object, Handle<JSObject> object,
AllocationSiteCreationContext* site_context) { AllocationSiteCreationContext* site_context) {
JSObjectWalkVisitor<AllocationSiteCreationContext> v(site_context, false, JSObjectWalkVisitor<AllocationSiteCreationContext> v(site_context, kNoHints);
kNoHints);
MaybeHandle<JSObject> result = v.StructureWalk(object); MaybeHandle<JSObject> result = v.StructureWalk(object);
Handle<JSObject> for_assert; Handle<JSObject> for_assert;
DCHECK(!result.ToHandle(&for_assert) || for_assert.is_identical_to(object)); DCHECK(!result.ToHandle(&for_assert) || for_assert.is_identical_to(object));
@ -8085,7 +8080,7 @@ MaybeHandle<JSObject> JSObject::DeepCopy(
Handle<JSObject> object, Handle<JSObject> object,
AllocationSiteUsageContext* site_context, AllocationSiteUsageContext* site_context,
DeepCopyHints hints) { DeepCopyHints hints) {
JSObjectWalkVisitor<AllocationSiteUsageContext> v(site_context, true, hints); JSObjectWalkVisitor<AllocationSiteUsageContext> v(site_context, hints);
MaybeHandle<JSObject> copy = v.StructureWalk(object); MaybeHandle<JSObject> copy = v.StructureWalk(object);
Handle<JSObject> for_assert; Handle<JSObject> for_assert;
DCHECK(!copy.ToHandle(&for_assert) || !for_assert.is_identical_to(object)); DCHECK(!copy.ToHandle(&for_assert) || !for_assert.is_identical_to(object));