[runtime] Add a mode to lookup iterator that doesn't allocate
This CL adds a mode to the JSReceiver::GetDataProperty that does not box unboxed double fields. This method can be used to fix a critical bug in the heap snapshot generator that currently causes a GC in a place where no GC should be caused. Change-Id: If195f6811090281d364e3c8fa221a1d6b96bcd80 Bug: v8:9993 Fixed: chromium:1038490 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1993286 Commit-Queue: Sigurd Schneider <sigurds@chromium.org> Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Reviewed-by: Toon Verwaest <verwaest@chromium.org> Cr-Commit-Position: refs/heads/master@{#65694}
This commit is contained in:
parent
328c166ef4
commit
b44f8abb2a
@ -130,7 +130,8 @@ Maybe<bool> JSReceiver::HasOwnProperty(Handle<JSReceiver> object,
|
||||
return Just(attributes.FromJust() != ABSENT);
|
||||
}
|
||||
|
||||
Handle<Object> JSReceiver::GetDataProperty(LookupIterator* it) {
|
||||
Handle<Object> JSReceiver::GetDataProperty(LookupIterator* it,
|
||||
AllocationPolicy allocation_policy) {
|
||||
for (; it->IsFound(); it->Next()) {
|
||||
switch (it->state()) {
|
||||
case LookupIterator::INTERCEPTOR:
|
||||
@ -153,7 +154,7 @@ Handle<Object> JSReceiver::GetDataProperty(LookupIterator* it) {
|
||||
case LookupIterator::INTEGER_INDEXED_EXOTIC:
|
||||
return it->isolate()->factory()->undefined_value();
|
||||
case LookupIterator::DATA:
|
||||
return it->GetDataValue();
|
||||
return it->GetDataValue(allocation_policy);
|
||||
}
|
||||
}
|
||||
return it->isolate()->factory()->undefined_value();
|
||||
@ -446,11 +447,15 @@ std::pair<MaybeHandle<JSFunction>, Handle<String>> GetConstructorHelper(
|
||||
}
|
||||
}
|
||||
|
||||
LookupIterator it_tag(isolate, receiver,
|
||||
isolate->factory()->to_string_tag_symbol(), receiver,
|
||||
LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
|
||||
Handle<Object> maybe_tag = JSReceiver::GetDataProperty(
|
||||
receiver, isolate->factory()->to_string_tag_symbol());
|
||||
if (maybe_tag->IsString())
|
||||
&it_tag, AllocationPolicy::kAllocationDisallowed);
|
||||
if (maybe_tag->IsString()) {
|
||||
return std::make_pair(MaybeHandle<JSFunction>(),
|
||||
Handle<String>::cast(maybe_tag));
|
||||
}
|
||||
|
||||
PrototypeIterator iter(isolate, receiver);
|
||||
if (iter.IsAtEnd()) {
|
||||
@ -461,7 +466,8 @@ std::pair<MaybeHandle<JSFunction>, Handle<String>> GetConstructorHelper(
|
||||
Handle<JSReceiver> start = PrototypeIterator::GetCurrent<JSReceiver>(iter);
|
||||
LookupIterator it(isolate, receiver, isolate->factory()->constructor_string(),
|
||||
start, LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
|
||||
Handle<Object> maybe_constructor = JSReceiver::GetDataProperty(&it);
|
||||
Handle<Object> maybe_constructor =
|
||||
JSReceiver::GetDataProperty(&it, AllocationPolicy::kAllocationDisallowed);
|
||||
if (maybe_constructor->IsJSFunction()) {
|
||||
JSFunction constructor = JSFunction::cast(*maybe_constructor);
|
||||
String name = constructor.shared().DebugName();
|
||||
|
@ -19,6 +19,10 @@
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
// Enum for functions that offer a second mode that does not cause allocations.
|
||||
// Used in conjunction with LookupIterator and unboxed double fields.
|
||||
enum class AllocationPolicy { kAllocationAllowed, kAllocationDisallowed };
|
||||
|
||||
enum InstanceType : uint16_t;
|
||||
class JSGlobalObject;
|
||||
class JSGlobalProxy;
|
||||
@ -237,7 +241,9 @@ class JSReceiver : public HeapObject {
|
||||
|
||||
inline static Handle<Object> GetDataProperty(Handle<JSReceiver> object,
|
||||
Handle<Name> name);
|
||||
V8_EXPORT_PRIVATE static Handle<Object> GetDataProperty(LookupIterator* it);
|
||||
V8_EXPORT_PRIVATE static Handle<Object> GetDataProperty(
|
||||
LookupIterator* it, AllocationPolicy allocation_policy =
|
||||
AllocationPolicy::kAllocationAllowed);
|
||||
|
||||
// Retrieves a permanent object identity hash code. The undefined value might
|
||||
// be returned in case no hash was created yet.
|
||||
|
@ -840,7 +840,8 @@ bool LookupIterator::HolderIsReceiverOrHiddenPrototype() const {
|
||||
isolate_) == *holder_;
|
||||
}
|
||||
|
||||
Handle<Object> LookupIterator::FetchValue() const {
|
||||
Handle<Object> LookupIterator::FetchValue(
|
||||
AllocationPolicy allocation_policy) const {
|
||||
Object result;
|
||||
if (IsElement(*holder_)) {
|
||||
Handle<JSObject> holder = GetHolder<JSObject>();
|
||||
@ -858,6 +859,10 @@ Handle<Object> LookupIterator::FetchValue() const {
|
||||
Handle<JSObject> holder = GetHolder<JSObject>();
|
||||
FieldIndex field_index =
|
||||
FieldIndex::ForDescriptor(holder->map(isolate_), descriptor_number());
|
||||
if (allocation_policy == AllocationPolicy::kAllocationDisallowed &&
|
||||
field_index.is_inobject() && field_index.is_double()) {
|
||||
return isolate_->factory()->undefined_value();
|
||||
}
|
||||
return JSObject::FastPropertyAt(holder, property_details_.representation(),
|
||||
field_index);
|
||||
} else {
|
||||
@ -975,9 +980,10 @@ Handle<Object> LookupIterator::GetAccessors() const {
|
||||
return FetchValue();
|
||||
}
|
||||
|
||||
Handle<Object> LookupIterator::GetDataValue() const {
|
||||
Handle<Object> LookupIterator::GetDataValue(
|
||||
AllocationPolicy allocation_policy) const {
|
||||
DCHECK_EQ(DATA, state_);
|
||||
Handle<Object> value = FetchValue();
|
||||
Handle<Object> value = FetchValue(allocation_policy);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -179,7 +179,8 @@ class V8_EXPORT_PRIVATE LookupIterator final {
|
||||
Handle<Object> GetAccessors() const;
|
||||
inline Handle<InterceptorInfo> GetInterceptor() const;
|
||||
Handle<InterceptorInfo> GetInterceptorForFailedAccessCheck() const;
|
||||
Handle<Object> GetDataValue() const;
|
||||
Handle<Object> GetDataValue(AllocationPolicy allocation_policy =
|
||||
AllocationPolicy::kAllocationAllowed) const;
|
||||
void WriteDataValue(Handle<Object> value, bool initializing_store);
|
||||
inline void UpdateProtector();
|
||||
static inline void UpdateProtector(Isolate* isolate, Handle<Object> receiver,
|
||||
@ -238,7 +239,8 @@ class V8_EXPORT_PRIVATE LookupIterator final {
|
||||
}
|
||||
template <bool is_element>
|
||||
void RestartInternal(InterceptorState interceptor_state);
|
||||
Handle<Object> FetchValue() const;
|
||||
Handle<Object> FetchValue(AllocationPolicy allocation_policy =
|
||||
AllocationPolicy::kAllocationAllowed) const;
|
||||
bool IsConstFieldValueEqualTo(Object value) const;
|
||||
template <bool is_element>
|
||||
void ReloadPropertyInformation();
|
||||
|
Loading…
Reference in New Issue
Block a user