[shared-struct] Fix shared barrier for always shared objects

Currently the shared value barrier manually fast paths instance types
for objects that are always in the shared heap. This CL makes a common
superclass, AlwaysSharedSpaceJSObject, and uses that for the fast path.

Bug: chromium:1402920, v8:12547
Fixed: chromium:1402920
Change-Id: I84421802791a4dc72925341eeb0cfc5949b8938a
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4134475
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Commit-Queue: Shu-yu Guo <syg@chromium.org>
Cr-Commit-Position: refs/heads/main@{#85192}
This commit is contained in:
Shu-yu Guo 2023-01-09 11:44:44 -08:00 committed by V8 LUCI CQ
parent 59657281c2
commit b0be4f8ddb
17 changed files with 122 additions and 76 deletions

View File

@ -435,8 +435,8 @@ void BaseCollectionsAssembler::GotoIfCannotBeHeldWeakly(
// TODO(v8:12547) Shared structs and arrays should only be able to point
// to shared values in weak collections. For now, disallow them as weak
// collection keys.
GotoIf(IsJSSharedStructInstanceType(instance_type), if_cannot_be_held_weakly);
GotoIf(IsJSSharedArrayInstanceType(instance_type), if_cannot_be_held_weakly);
GotoIf(IsAlwaysSharedSpaceJSObjectInstanceType(instance_type),
if_cannot_be_held_weakly);
Goto(&end);
Bind(&check_symbol_key);
GotoIfNot(HasHarmonySymbolAsWeakmapKeyFlag(), if_cannot_be_held_weakly);

View File

@ -6817,6 +6817,12 @@ TNode<BoolT> CodeStubAssembler::IsJSArrayIterator(TNode<HeapObject> object) {
return HasInstanceType(object, JS_ARRAY_ITERATOR_TYPE);
}
TNode<BoolT> CodeStubAssembler::IsAlwaysSharedSpaceJSObjectInstanceType(
TNode<Int32T> instance_type) {
return IsInRange(instance_type, FIRST_ALWAYS_SHARED_SPACE_JS_OBJECT_TYPE,
LAST_ALWAYS_SHARED_SPACE_JS_OBJECT_TYPE);
}
TNode<BoolT> CodeStubAssembler::IsJSSharedArrayInstanceType(
TNode<Int32T> instance_type) {
return InstanceTypeEqual(instance_type, JS_SHARED_ARRAY_TYPE);
@ -16828,9 +16834,9 @@ void CodeStubAssembler::SharedValueBarrier(
TNode<Uint16T> value_instance_type =
LoadMapInstanceType(LoadMap(CAST(value)));
GotoIf(IsSharedStringInstanceType(value_instance_type), &skip_barrier);
GotoIf(IsJSSharedStructInstanceType(value_instance_type), &skip_barrier);
GotoIf(IsAlwaysSharedSpaceJSObjectInstanceType(value_instance_type),
&skip_barrier);
GotoIf(IsHeapNumberInstanceType(value_instance_type), &check_in_shared_heap);
GotoIf(IsJSSharedArrayInstanceType(value_instance_type), &skip_barrier);
Goto(&slow);
BIND(&check_in_shared_heap);

View File

@ -2590,6 +2590,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
TNode<BoolT> InstanceTypeEqual(TNode<Int32T> instance_type, int type);
TNode<BoolT> IsNoElementsProtectorCellInvalid();
TNode<BoolT> IsMegaDOMProtectorCellInvalid();
TNode<BoolT> IsAlwaysSharedSpaceJSObjectInstanceType(
TNode<Int32T> instance_type);
TNode<BoolT> IsArrayIteratorProtectorCellInvalid();
TNode<BoolT> IsBigIntInstanceType(TNode<Int32T> instance_type);
TNode<BoolT> IsBigInt(TNode<HeapObject> object);

View File

@ -9,6 +9,7 @@
#include "src/common/globals.h"
#include "src/heap/heap-write-barrier-inl.h"
#include "src/objects/js-atomics-synchronization.h"
#include "src/objects/js-struct-inl.h"
#include "src/objects/objects-inl.h"
// Has to be the last include (doesn't have include guards):

View File

@ -10,6 +10,7 @@
#include "src/base/platform/time.h"
#include "src/execution/thread-id.h"
#include "src/objects/js-objects.h"
#include "src/objects/js-struct.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
@ -26,7 +27,7 @@ class WaiterQueueNode;
// Base class for JSAtomicsMutex and JSAtomicsCondition
class JSSynchronizationPrimitive
: public TorqueGeneratedJSSynchronizationPrimitive<
JSSynchronizationPrimitive, JSObject> {
JSSynchronizationPrimitive, AlwaysSharedSpaceJSObject> {
public:
// Synchronization only store raw data as state.
static constexpr int kEndOfTaggedFieldsOffset = JSObject::kHeaderSize;
@ -44,10 +45,10 @@ class JSSynchronizationPrimitive
inline std::atomic<StateT>* AtomicStatePtr();
using TorqueGeneratedJSSynchronizationPrimitive<JSSynchronizationPrimitive,
JSObject>::state;
using TorqueGeneratedJSSynchronizationPrimitive<JSSynchronizationPrimitive,
JSObject>::set_state;
using TorqueGeneratedJSSynchronizationPrimitive<
JSSynchronizationPrimitive, AlwaysSharedSpaceJSObject>::state;
using TorqueGeneratedJSSynchronizationPrimitive<
JSSynchronizationPrimitive, AlwaysSharedSpaceJSObject>::set_state;
};
// A non-recursive mutex that is exposed to JS.

View File

@ -3,7 +3,7 @@
// found in the LICENSE file.
@abstract
extern class JSSynchronizationPrimitive extends JSObject {
extern class JSSynchronizationPrimitive extends AlwaysSharedSpaceJSObject {
@if(TAGGED_SIZE_8_BYTES) state: uintptr;
@ifnot(TAGGED_SIZE_8_BYTES) state: uint32;
}

View File

@ -8,6 +8,7 @@
#include "src/api/api-inl.h"
#include "src/heap/heap-write-barrier-inl.h"
#include "src/objects/js-shared-array.h"
#include "src/objects/js-struct-inl.h"
#include "src/objects/smi-inl.h"
// Has to be the last include (doesn't have include guards):

View File

@ -6,6 +6,7 @@
#define V8_OBJECTS_JS_SHARED_ARRAY_H_
#include "src/objects/js-objects.h"
#include "src/objects/js-struct.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
@ -16,7 +17,8 @@ namespace internal {
#include "torque-generated/src/objects/js-shared-array-tq.inc"
class JSSharedArray
: public TorqueGeneratedJSSharedArray<JSSharedArray, JSObject> {
: public TorqueGeneratedJSSharedArray<JSSharedArray,
AlwaysSharedSpaceJSObject> {
public:
DECL_CAST(JSSharedArray)
DECL_PRINTER(JSSharedArray)

View File

@ -2,4 +2,4 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
extern class JSSharedArray extends JSObject {}
extern class JSSharedArray extends AlwaysSharedSpaceJSObject {}

View File

@ -18,6 +18,8 @@ namespace internal {
#include "torque-generated/src/objects/js-struct-tq-inl.inc"
TQ_OBJECT_CONSTRUCTORS_IMPL(AlwaysSharedSpaceJSObject)
TQ_OBJECT_CONSTRUCTORS_IMPL(JSSharedStruct)
CAST_ACCESSOR(JSSharedStruct)

View File

@ -15,8 +15,17 @@ namespace internal {
#include "torque-generated/src/objects/js-struct-tq.inc"
class AlwaysSharedSpaceJSObject
: public TorqueGeneratedAlwaysSharedSpaceJSObject<AlwaysSharedSpaceJSObject,
JSObject> {
public:
static_assert(kHeaderSize == JSObject::kHeaderSize);
TQ_OBJECT_CONSTRUCTORS(AlwaysSharedSpaceJSObject)
};
class JSSharedStruct
: public TorqueGeneratedJSSharedStruct<JSSharedStruct, JSObject> {
: public TorqueGeneratedJSSharedStruct<JSSharedStruct,
AlwaysSharedSpaceJSObject> {
public:
DECL_CAST(JSSharedStruct)
DECL_PRINTER(JSSharedStruct)

View File

@ -2,6 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
extern class JSSharedStruct extends JSObject {
// escaped_local_thread: Smi;
// AlwaysSharedSpaceJSObject are JSObjects that must always be allocated in the
// shared space. Its instance type range is used to fast path the shared value
// barrier.
@abstract
@highestInstanceTypeWithinParentClassRange
extern class AlwaysSharedSpaceJSObject extends JSObject {
}
extern class JSSharedStruct extends AlwaysSharedSpaceJSObject {}

View File

@ -78,6 +78,7 @@ class ZoneForwardList;
V(AccessCheckNeeded) \
V(AccessorInfo) \
V(AllocationSite) \
V(AlwaysSharedSpaceJSObject) \
V(ArrayList) \
V(BigInt) \
V(BigIntBase) \

View File

@ -1233,13 +1233,14 @@ bool Object::IsShared() const {
}
// Check if this object is already shared.
switch (object.map().instance_type()) {
InstanceType instance_type = object.map().instance_type();
if (InstanceTypeChecker::IsAlwaysSharedSpaceJSObject(instance_type)) {
DCHECK(object.InSharedHeap());
return true;
}
switch (instance_type) {
case SHARED_STRING_TYPE:
case SHARED_ONE_BYTE_STRING_TYPE:
case JS_SHARED_ARRAY_TYPE:
case JS_SHARED_STRUCT_TYPE:
case JS_ATOMICS_MUTEX_TYPE:
case JS_ATOMICS_CONDITION_TYPE:
DCHECK(object.InSharedHeap());
return true;
case INTERNALIZED_STRING_TYPE:

View File

@ -34,3 +34,10 @@ let cv = new Atomics.Condition;
assertEquals(false, Atomics.Condition.wait(cv, mutex, 100));
});
})();
// Mutexes can be assigned to shared objects.
(function TestConditionCanBeAssignedToSharedObjects() {
const Box = new SharedStructType(["payload"]);
const box = new Box;
box.payload = cv;
})();

View File

@ -44,3 +44,10 @@ assertThrowsEquals(() => {
}, 42);
Atomics.Mutex.tryLock(mutex, () => { locked_count++; });
assertEquals(locked_count, 6);
// Mutexes can be assigned to shared objects.
(function TestMutexCanBeAssignedToSharedObjects() {
const Box = new SharedStructType(["payload"]);
const box = new Box;
box.payload = mutex;
})();

View File

@ -236,60 +236,60 @@ INSTANCE_TYPES = {
2098: "JS_ASYNC_GENERATOR_OBJECT_TYPE",
2099: "JS_MAP_TYPE",
2100: "JS_SET_TYPE",
2101: "JS_ATOMICS_CONDITION_TYPE",
2102: "JS_ATOMICS_MUTEX_TYPE",
2103: "JS_WEAK_MAP_TYPE",
2104: "JS_WEAK_SET_TYPE",
2105: "JS_ARGUMENTS_OBJECT_TYPE",
2106: "JS_ARRAY_TYPE",
2107: "JS_ARRAY_ITERATOR_TYPE",
2108: "JS_ASYNC_FROM_SYNC_ITERATOR_TYPE",
2109: "JS_COLLATOR_TYPE",
2110: "JS_CONTEXT_EXTENSION_OBJECT_TYPE",
2111: "JS_DATE_TYPE",
2112: "JS_DATE_TIME_FORMAT_TYPE",
2113: "JS_DISPLAY_NAMES_TYPE",
2114: "JS_DURATION_FORMAT_TYPE",
2115: "JS_ERROR_TYPE",
2116: "JS_EXTERNAL_OBJECT_TYPE",
2117: "JS_FINALIZATION_REGISTRY_TYPE",
2118: "JS_LIST_FORMAT_TYPE",
2119: "JS_LOCALE_TYPE",
2120: "JS_MESSAGE_OBJECT_TYPE",
2121: "JS_NUMBER_FORMAT_TYPE",
2122: "JS_PLURAL_RULES_TYPE",
2123: "JS_RAW_JSON_TYPE",
2124: "JS_REG_EXP_TYPE",
2125: "JS_REG_EXP_STRING_ITERATOR_TYPE",
2126: "JS_RELATIVE_TIME_FORMAT_TYPE",
2127: "JS_SEGMENT_ITERATOR_TYPE",
2128: "JS_SEGMENTER_TYPE",
2129: "JS_SEGMENTS_TYPE",
2130: "JS_SHADOW_REALM_TYPE",
2131: "JS_SHARED_ARRAY_TYPE",
2132: "JS_SHARED_STRUCT_TYPE",
2133: "JS_STRING_ITERATOR_TYPE",
2134: "JS_TEMPORAL_CALENDAR_TYPE",
2135: "JS_TEMPORAL_DURATION_TYPE",
2136: "JS_TEMPORAL_INSTANT_TYPE",
2137: "JS_TEMPORAL_PLAIN_DATE_TYPE",
2138: "JS_TEMPORAL_PLAIN_DATE_TIME_TYPE",
2139: "JS_TEMPORAL_PLAIN_MONTH_DAY_TYPE",
2140: "JS_TEMPORAL_PLAIN_TIME_TYPE",
2141: "JS_TEMPORAL_PLAIN_YEAR_MONTH_TYPE",
2142: "JS_TEMPORAL_TIME_ZONE_TYPE",
2143: "JS_TEMPORAL_ZONED_DATE_TIME_TYPE",
2144: "JS_V8_BREAK_ITERATOR_TYPE",
2145: "JS_WEAK_REF_TYPE",
2146: "WASM_EXCEPTION_PACKAGE_TYPE",
2147: "WASM_GLOBAL_OBJECT_TYPE",
2148: "WASM_INSTANCE_OBJECT_TYPE",
2149: "WASM_MEMORY_OBJECT_TYPE",
2150: "WASM_MODULE_OBJECT_TYPE",
2151: "WASM_SUSPENDER_OBJECT_TYPE",
2152: "WASM_TABLE_OBJECT_TYPE",
2153: "WASM_TAG_OBJECT_TYPE",
2154: "WASM_VALUE_OBJECT_TYPE",
2101: "JS_WEAK_MAP_TYPE",
2102: "JS_WEAK_SET_TYPE",
2103: "JS_ARGUMENTS_OBJECT_TYPE",
2104: "JS_ARRAY_TYPE",
2105: "JS_ARRAY_ITERATOR_TYPE",
2106: "JS_ASYNC_FROM_SYNC_ITERATOR_TYPE",
2107: "JS_COLLATOR_TYPE",
2108: "JS_CONTEXT_EXTENSION_OBJECT_TYPE",
2109: "JS_DATE_TYPE",
2110: "JS_DATE_TIME_FORMAT_TYPE",
2111: "JS_DISPLAY_NAMES_TYPE",
2112: "JS_DURATION_FORMAT_TYPE",
2113: "JS_ERROR_TYPE",
2114: "JS_EXTERNAL_OBJECT_TYPE",
2115: "JS_FINALIZATION_REGISTRY_TYPE",
2116: "JS_LIST_FORMAT_TYPE",
2117: "JS_LOCALE_TYPE",
2118: "JS_MESSAGE_OBJECT_TYPE",
2119: "JS_NUMBER_FORMAT_TYPE",
2120: "JS_PLURAL_RULES_TYPE",
2121: "JS_RAW_JSON_TYPE",
2122: "JS_REG_EXP_TYPE",
2123: "JS_REG_EXP_STRING_ITERATOR_TYPE",
2124: "JS_RELATIVE_TIME_FORMAT_TYPE",
2125: "JS_SEGMENT_ITERATOR_TYPE",
2126: "JS_SEGMENTER_TYPE",
2127: "JS_SEGMENTS_TYPE",
2128: "JS_SHADOW_REALM_TYPE",
2129: "JS_STRING_ITERATOR_TYPE",
2130: "JS_TEMPORAL_CALENDAR_TYPE",
2131: "JS_TEMPORAL_DURATION_TYPE",
2132: "JS_TEMPORAL_INSTANT_TYPE",
2133: "JS_TEMPORAL_PLAIN_DATE_TYPE",
2134: "JS_TEMPORAL_PLAIN_DATE_TIME_TYPE",
2135: "JS_TEMPORAL_PLAIN_MONTH_DAY_TYPE",
2136: "JS_TEMPORAL_PLAIN_TIME_TYPE",
2137: "JS_TEMPORAL_PLAIN_YEAR_MONTH_TYPE",
2138: "JS_TEMPORAL_TIME_ZONE_TYPE",
2139: "JS_TEMPORAL_ZONED_DATE_TIME_TYPE",
2140: "JS_V8_BREAK_ITERATOR_TYPE",
2141: "JS_WEAK_REF_TYPE",
2142: "WASM_EXCEPTION_PACKAGE_TYPE",
2143: "WASM_GLOBAL_OBJECT_TYPE",
2144: "WASM_INSTANCE_OBJECT_TYPE",
2145: "WASM_MEMORY_OBJECT_TYPE",
2146: "WASM_MODULE_OBJECT_TYPE",
2147: "WASM_SUSPENDER_OBJECT_TYPE",
2148: "WASM_TABLE_OBJECT_TYPE",
2149: "WASM_TAG_OBJECT_TYPE",
2150: "WASM_VALUE_OBJECT_TYPE",
2151: "JS_ATOMICS_CONDITION_TYPE",
2152: "JS_ATOMICS_MUTEX_TYPE",
2153: "JS_SHARED_ARRAY_TYPE",
2154: "JS_SHARED_STRUCT_TYPE",
}
# List of known V8 maps.
@ -481,8 +481,8 @@ KNOWN_MAPS = {
("read_only_space", 0x03e95): (272, "WasmTypeInfoMap"),
("read_only_space", 0x03ebd): (268, "WasmContinuationObjectMap"),
("read_only_space", 0x03ee5): (274, "WeakCellMap"),
("old_space", 0x0438d): (2116, "ExternalMap"),
("old_space", 0x043b5): (2120, "JSMessageObjectMap"),
("old_space", 0x0438d): (2114, "ExternalMap"),
("old_space", 0x043b5): (2118, "JSMessageObjectMap"),
}
# List of known V8 objects.