[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:
parent
b853d7fbb3
commit
fa2ed010e6
@ -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_;
|
||||||
|
137
src/objects.cc
137
src/objects.cc
@ -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));
|
||||||
|
Loading…
Reference in New Issue
Block a user