Skip to content

Commit d19a707

Browse files
sygV8 LUCI CQ
authored andcommitted
[compiler] Fix typing JSLoadNamed of private brands
Private method loads are compiled to a named load of a private brand, which always loads a BlockContext. This BlockContext holds the private methods common to all instances of a class. TurboFan currently considers JSLoadNamed to be of Type::NonInternal(). Private methods break this assumption, since BlockContext is of Type::OtherInternal(). This CL changes the typing of JSLoadNamed of private brands to be Type::OtherInternal(). Bug: v8:12500 Change-Id: I91f39747bf9422bd419d299f44152f567d8be8db Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3351167 Reviewed-by: Maya Lekova <[email protected]> Commit-Queue: Shu-yu Guo <[email protected]> Cr-Commit-Position: refs/heads/main@{#78431}
1 parent 6c30d63 commit d19a707

File tree

4 files changed

+46
-8
lines changed

4 files changed

+46
-8
lines changed

src/compiler/access-info.cc

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -431,8 +431,9 @@ bool AccessInfoFactory::ComputeElementAccessInfos(
431431
}
432432

433433
PropertyAccessInfo AccessInfoFactory::ComputeDataFieldAccessInfo(
434-
MapRef receiver_map, MapRef map, base::Optional<JSObjectRef> holder,
435-
InternalIndex descriptor, AccessMode access_mode) const {
434+
MapRef receiver_map, MapRef map, NameRef name,
435+
base::Optional<JSObjectRef> holder, InternalIndex descriptor,
436+
AccessMode access_mode) const {
436437
DCHECK(descriptor.is_found());
437438
// TODO(jgruber,v8:7790): Use DescriptorArrayRef instead.
438439
Handle<DescriptorArray> descriptors = map.instance_descriptors().object();
@@ -449,7 +450,10 @@ PropertyAccessInfo AccessInfoFactory::ComputeDataFieldAccessInfo(
449450
}
450451
FieldIndex field_index = FieldIndex::ForPropertyIndex(*map.object(), index,
451452
details_representation);
452-
Type field_type = Type::NonInternal();
453+
// Private brands are used when loading private methods, which are stored in a
454+
// BlockContext, an internal object.
455+
Type field_type = name.object()->IsPrivateBrand() ? Type::OtherInternal()
456+
: Type::NonInternal();
453457
base::Optional<MapRef> field_map;
454458

455459
ZoneVector<CompilationDependency const*> unrecorded_dependencies(zone());
@@ -842,8 +846,8 @@ PropertyAccessInfo AccessInfoFactory::ComputePropertyAccessInfo(
842846
}
843847
if (details.location() == PropertyLocation::kField) {
844848
if (details.kind() == PropertyKind::kData) {
845-
return ComputeDataFieldAccessInfo(receiver_map, map, holder, index,
846-
access_mode);
849+
return ComputeDataFieldAccessInfo(receiver_map, map, name, holder,
850+
index, access_mode);
847851
} else {
848852
DCHECK_EQ(PropertyKind::kAccessor, details.kind());
849853
// TODO(turbofan): Add support for general accessors?

src/compiler/access-info.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -289,8 +289,9 @@ class AccessInfoFactory final {
289289
base::Optional<JSObjectRef> holder,
290290
PropertyAttributes attrs) const;
291291
PropertyAccessInfo ComputeDataFieldAccessInfo(
292-
MapRef receiver_map, MapRef map, base::Optional<JSObjectRef> holder,
293-
InternalIndex descriptor, AccessMode access_mode) const;
292+
MapRef receiver_map, MapRef map, NameRef name,
293+
base::Optional<JSObjectRef> holder, InternalIndex descriptor,
294+
AccessMode access_mode) const;
294295
PropertyAccessInfo ComputeAccessorDescriptorAccessInfo(
295296
MapRef receiver_map, NameRef name, MapRef map,
296297
base::Optional<JSObjectRef> holder, InternalIndex descriptor,

src/compiler/typer.cc

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1323,7 +1323,18 @@ Type Typer::Visitor::TypeJSGetTemplateObject(Node* node) {
13231323

13241324
Type Typer::Visitor::TypeJSLoadProperty(Node* node) { return Type::Any(); }
13251325

1326-
Type Typer::Visitor::TypeJSLoadNamed(Node* node) { return Type::NonInternal(); }
1326+
Type Typer::Visitor::TypeJSLoadNamed(Node* node) {
1327+
#ifdef DEBUG
1328+
// Loading of private methods is compiled to a named load of a BlockContext
1329+
// via a private brand, which is an internal object. However, native context
1330+
// specialization should always apply for those cases, so assert that the name
1331+
// is not a private brand here. Otherwise Type::NonInternal() is wrong.
1332+
JSLoadNamedNode n(node);
1333+
NamedAccess const& p = n.Parameters();
1334+
DCHECK(!p.name(typer_->broker()).object()->IsPrivateBrand());
1335+
#endif
1336+
return Type::NonInternal();
1337+
}
13271338

13281339
Type Typer::Visitor::TypeJSLoadNamedFromSuper(Node* node) {
13291340
return Type::NonInternal();
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2021 the V8 project authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
// Flags: --allow-natives-syntax
6+
7+
class A {
8+
a() { this.#b() }
9+
#b() {}
10+
}
11+
12+
function InlinePrivateMethod() {
13+
for (let i = 0; i < 10; i++) {
14+
new A().a();
15+
}
16+
}
17+
18+
%PrepareFunctionForOptimization(A);
19+
%PrepareFunctionForOptimization(InlinePrivateMethod);
20+
InlinePrivateMethod();
21+
%OptimizeFunctionOnNextCall(InlinePrivateMethod);
22+
InlinePrivateMethod();

0 commit comments

Comments
 (0)