[Torque] Port WeakRef APIs to torque
Bug: v8:9891 Change-Id: I559ee50a09a2c8530c3d75a650b383b7d987f6f4 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2282713 Commit-Queue: Gus Caplan <me@gus.host> Reviewed-by: Shu-yu Guo <syg@chromium.org> Reviewed-by: Bill Budge <bbudge@chromium.org> Reviewed-by: Marja Hölttä <marja@chromium.org> Cr-Commit-Position: refs/heads/master@{#68727}
This commit is contained in:
parent
e33e84815d
commit
f14960b02a
1
BUILD.gn
1
BUILD.gn
@ -1168,6 +1168,7 @@ torque_files = [
|
||||
"src/builtins/typed-array-values.tq",
|
||||
"src/builtins/typed-array.tq",
|
||||
"src/builtins/wasm.tq",
|
||||
"src/builtins/weak-ref.tq",
|
||||
"src/ic/handler-configuration.tq",
|
||||
"src/objects/allocation-site.tq",
|
||||
"src/objects/api-callbacks.tq",
|
||||
|
@ -329,6 +329,7 @@ extern enum MessageTemplate {
|
||||
kWasmTrapNullDereference,
|
||||
kWasmTrapIllegalCast,
|
||||
kWasmTrapArrayOutOfBounds,
|
||||
kWeakRefsWeakRefConstructorTargetMustBeObject,
|
||||
...
|
||||
}
|
||||
|
||||
|
@ -918,11 +918,8 @@ namespace internal {
|
||||
CPP(Trace) \
|
||||
\
|
||||
/* Weak refs */ \
|
||||
CPP(FinalizationRegistryConstructor) \
|
||||
CPP(FinalizationRegistryRegister) \
|
||||
CPP(FinalizationRegistryUnregister) \
|
||||
CPP(WeakRefConstructor) \
|
||||
CPP(WeakRefDeref) \
|
||||
\
|
||||
/* Async modules */ \
|
||||
TFJ(AsyncModuleEvaluate, kDontAdaptArgumentsSentinel) \
|
||||
|
@ -9,41 +9,6 @@
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
BUILTIN(FinalizationRegistryConstructor) {
|
||||
HandleScope scope(isolate);
|
||||
Handle<JSFunction> target = args.target();
|
||||
if (args.new_target()->IsUndefined(isolate)) { // [[Call]]
|
||||
THROW_NEW_ERROR_RETURN_FAILURE(
|
||||
isolate, NewTypeError(MessageTemplate::kConstructorNotFunction,
|
||||
handle(target->shared().Name(), isolate)));
|
||||
}
|
||||
// [[Construct]]
|
||||
Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
|
||||
Handle<Object> cleanup = args.atOrUndefined(isolate, 1);
|
||||
|
||||
if (!cleanup->IsCallable()) {
|
||||
THROW_NEW_ERROR_RETURN_FAILURE(
|
||||
isolate, NewTypeError(MessageTemplate::kWeakRefsCleanupMustBeCallable));
|
||||
}
|
||||
|
||||
Handle<JSObject> result;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, result,
|
||||
JSObject::New(target, new_target, Handle<AllocationSite>::null()));
|
||||
|
||||
Handle<JSFinalizationRegistry> finalization_registry =
|
||||
Handle<JSFinalizationRegistry>::cast(result);
|
||||
finalization_registry->set_native_context(*isolate->native_context());
|
||||
finalization_registry->set_cleanup(*cleanup);
|
||||
finalization_registry->set_flags(
|
||||
JSFinalizationRegistry::ScheduledForCleanupBit::encode(false));
|
||||
|
||||
DCHECK(finalization_registry->active_cells().IsUndefined(isolate));
|
||||
DCHECK(finalization_registry->cleared_cells().IsUndefined(isolate));
|
||||
DCHECK(finalization_registry->key_map().IsUndefined(isolate));
|
||||
return *finalization_registry;
|
||||
}
|
||||
|
||||
BUILTIN(FinalizationRegistryRegister) {
|
||||
HandleScope scope(isolate);
|
||||
const char* method_name = "FinalizationRegistry.prototype.register";
|
||||
@ -122,53 +87,5 @@ BUILTIN(FinalizationRegistryUnregister) {
|
||||
return *isolate->factory()->ToBoolean(success);
|
||||
}
|
||||
|
||||
BUILTIN(WeakRefConstructor) {
|
||||
HandleScope scope(isolate);
|
||||
Handle<JSFunction> target = args.target();
|
||||
if (args.new_target()->IsUndefined(isolate)) { // [[Call]]
|
||||
THROW_NEW_ERROR_RETURN_FAILURE(
|
||||
isolate, NewTypeError(MessageTemplate::kConstructorNotFunction,
|
||||
handle(target->shared().Name(), isolate)));
|
||||
}
|
||||
// [[Construct]]
|
||||
Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
|
||||
Handle<Object> target_object = args.atOrUndefined(isolate, 1);
|
||||
if (!target_object->IsJSReceiver()) {
|
||||
THROW_NEW_ERROR_RETURN_FAILURE(
|
||||
isolate,
|
||||
NewTypeError(
|
||||
MessageTemplate::kWeakRefsWeakRefConstructorTargetMustBeObject));
|
||||
}
|
||||
Handle<JSReceiver> target_receiver =
|
||||
handle(JSReceiver::cast(*target_object), isolate);
|
||||
isolate->heap()->KeepDuringJob(target_receiver);
|
||||
|
||||
// TODO(marja): Realms.
|
||||
|
||||
Handle<JSObject> result;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, result,
|
||||
JSObject::New(target, new_target, Handle<AllocationSite>::null()));
|
||||
|
||||
Handle<JSWeakRef> weak_ref = Handle<JSWeakRef>::cast(result);
|
||||
weak_ref->set_target(*target_receiver);
|
||||
return *weak_ref;
|
||||
}
|
||||
|
||||
BUILTIN(WeakRefDeref) {
|
||||
HandleScope scope(isolate);
|
||||
CHECK_RECEIVER(JSWeakRef, weak_ref, "WeakRef.prototype.deref");
|
||||
if (weak_ref->target().IsJSReceiver()) {
|
||||
Handle<JSReceiver> target =
|
||||
handle(JSReceiver::cast(weak_ref->target()), isolate);
|
||||
// KeepDuringJob might allocate and cause a GC, but it won't clear
|
||||
// weak_ref since we hold a Handle to its target.
|
||||
isolate->heap()->KeepDuringJob(target);
|
||||
} else {
|
||||
DCHECK(weak_ref->target().IsUndefined(isolate));
|
||||
}
|
||||
return weak_ref->target();
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -77,6 +77,39 @@ FinalizationRegistryCleanupLoop(implicit context: Context)(
|
||||
context, finalizationRegistry);
|
||||
}
|
||||
|
||||
transitioning javascript builtin
|
||||
FinalizationRegistryConstructor(
|
||||
js-implicit context: NativeContext, receiver: JSAny, newTarget: JSAny,
|
||||
target: JSFunction)(cleanupCallback: JSAny): JSFinalizationRegistry {
|
||||
// 1. If NewTarget is undefined, throw a TypeError exception.
|
||||
if (newTarget == Undefined) {
|
||||
ThrowTypeError(
|
||||
MessageTemplate::kConstructorNotFunction, 'FinalizationRegistry');
|
||||
}
|
||||
// 2. If IsCallable(cleanupCallback) is false, throw a TypeError exception.
|
||||
const cleanupCallback = Cast<Callable>(cleanupCallback) otherwise
|
||||
ThrowTypeError(MessageTemplate::kWeakRefsCleanupMustBeCallable);
|
||||
// 3. Let finalizationRegistry be ? OrdinaryCreateFromConstructor(NewTarget,
|
||||
// "%FinalizationRegistryPrototype%", « [[Realm]], [[CleanupCallback]],
|
||||
// [[Cells]] »).
|
||||
const map = GetDerivedMap(target, UnsafeCast<JSReceiver>(newTarget));
|
||||
const finalizationRegistry = UnsafeCast<JSFinalizationRegistry>(
|
||||
AllocateFastOrSlowJSObjectFromMap(map));
|
||||
// 4. Let fn be the active function object.
|
||||
// 5. Set finalizationRegistry.[[Realm]] to fn.[[Realm]].
|
||||
finalizationRegistry.native_context = context;
|
||||
// 6. Set finalizationRegistry.[[CleanupCallback]] to cleanupCallback.
|
||||
finalizationRegistry.cleanup = cleanupCallback;
|
||||
finalizationRegistry.flags =
|
||||
SmiTag(FinalizationRegistryFlags{scheduled_for_cleanup: false});
|
||||
// 7. Set finalizationRegistry.[[Cells]] to be an empty List.
|
||||
assert(finalizationRegistry.active_cells == Undefined);
|
||||
assert(finalizationRegistry.cleared_cells == Undefined);
|
||||
assert(finalizationRegistry.key_map == Undefined);
|
||||
// 8. Return finalizationRegistry.
|
||||
return finalizationRegistry;
|
||||
}
|
||||
|
||||
transitioning javascript builtin
|
||||
FinalizationRegistryPrototypeCleanupSome(
|
||||
js-implicit context: NativeContext, receiver: JSAny)(...arguments): JSAny {
|
||||
|
59
src/builtins/weak-ref.tq
Normal file
59
src/builtins/weak-ref.tq
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright 2020 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
namespace runtime {
|
||||
|
||||
extern runtime JSWeakRefAddToKeptObjects(implicit context: Context)(JSReceiver);
|
||||
|
||||
} // namespace runtime
|
||||
|
||||
namespace weakref {
|
||||
|
||||
transitioning javascript builtin
|
||||
WeakRefConstructor(
|
||||
js-implicit context: NativeContext, receiver: JSAny, newTarget: JSAny,
|
||||
target: JSFunction)(weakTarget: JSAny): JSWeakRef {
|
||||
// 1. If NewTarget is undefined, throw a TypeError exception.
|
||||
if (newTarget == Undefined) {
|
||||
ThrowTypeError(MessageTemplate::kConstructorNotFunction, 'WeakRef');
|
||||
}
|
||||
// 2. If Type(target) is not Object, throw a TypeError exception.
|
||||
const weakTarget = Cast<JSReceiver>(weakTarget) otherwise
|
||||
ThrowTypeError(
|
||||
MessageTemplate::kWeakRefsWeakRefConstructorTargetMustBeObject);
|
||||
// 3. Let weakRef be ? OrdinaryCreateFromConstructor(NewTarget,
|
||||
// "%WeakRefPrototype%", « [[WeakRefTarget]] »).
|
||||
const map = GetDerivedMap(target, UnsafeCast<JSReceiver>(newTarget));
|
||||
const weakRef = UnsafeCast<JSWeakRef>(AllocateFastOrSlowJSObjectFromMap(map));
|
||||
// 4. Perfom ! AddToKeptObjects(target).
|
||||
runtime::JSWeakRefAddToKeptObjects(weakTarget);
|
||||
// 5. Set weakRef.[[WeakRefTarget]] to target.
|
||||
weakRef.target = weakTarget;
|
||||
// 6. Return weakRef.
|
||||
return weakRef;
|
||||
}
|
||||
|
||||
transitioning javascript builtin
|
||||
WeakRefDeref(js-implicit context: NativeContext, receiver: JSAny)(): JSAny {
|
||||
// 1. Let weakRef be the this value.
|
||||
// 2. Perform ? RequireInternalSlot(weakRef, [[WeakRefTarget]]).
|
||||
const weakRef = Cast<JSWeakRef>(receiver) otherwise
|
||||
ThrowTypeError(
|
||||
MessageTemplate::kIncompatibleMethodReceiver, 'WeakRef.prototype.deref',
|
||||
receiver);
|
||||
// 3. Let target be the value of weakRef.[[WeakRefTarget]].
|
||||
const target = weakRef.target;
|
||||
// 4. If target is not empty,
|
||||
// a. Perform ! AddToKeptObjects(target).
|
||||
// b. Return target.
|
||||
// 5. Return undefined.
|
||||
if (target != Undefined) {
|
||||
// JSWeakRefAddToKeptObjects might allocate and cause a GC, but it
|
||||
// won't clear `target` since we hold it here on the stack.
|
||||
runtime::JSWeakRefAddToKeptObjects(UnsafeCast<JSReceiver>(target));
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
} // namespace weakrefs
|
@ -26,5 +26,15 @@ RUNTIME_FUNCTION(Runtime_ShrinkFinalizationRegistryUnregisterTokenMap) {
|
||||
return ReadOnlyRoots(isolate).undefined_value();
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_JSWeakRefAddToKeptObjects) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(1, args.length());
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
|
||||
|
||||
isolate->heap()->KeepDuringJob(object);
|
||||
|
||||
return ReadOnlyRoots(isolate).undefined_value();
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -579,6 +579,7 @@ namespace internal {
|
||||
F(WasmAllocateRtt, 2, 1)
|
||||
|
||||
#define FOR_EACH_INTRINSIC_WEAKREF(F, I) \
|
||||
F(JSWeakRefAddToKeptObjects, 1, 1) \
|
||||
F(ShrinkFinalizationRegistryUnregisterTokenMap, 1, 1)
|
||||
|
||||
#define FOR_EACH_INTRINSIC_RETURN_PAIR_IMPL(F, I) \
|
||||
|
@ -441,27 +441,27 @@ KNOWN_OBJECTS = {
|
||||
("old_space", 0x009ed): "StringSplitCache",
|
||||
("old_space", 0x00df5): "RegExpMultipleCache",
|
||||
("old_space", 0x011fd): "BuiltinsConstantsTable",
|
||||
("old_space", 0x015a1): "AsyncFunctionAwaitRejectSharedFun",
|
||||
("old_space", 0x015c9): "AsyncFunctionAwaitResolveSharedFun",
|
||||
("old_space", 0x015f1): "AsyncGeneratorAwaitRejectSharedFun",
|
||||
("old_space", 0x01619): "AsyncGeneratorAwaitResolveSharedFun",
|
||||
("old_space", 0x01641): "AsyncGeneratorYieldResolveSharedFun",
|
||||
("old_space", 0x01669): "AsyncGeneratorReturnResolveSharedFun",
|
||||
("old_space", 0x01691): "AsyncGeneratorReturnClosedRejectSharedFun",
|
||||
("old_space", 0x016b9): "AsyncGeneratorReturnClosedResolveSharedFun",
|
||||
("old_space", 0x016e1): "AsyncIteratorValueUnwrapSharedFun",
|
||||
("old_space", 0x01709): "PromiseAllResolveElementSharedFun",
|
||||
("old_space", 0x01731): "PromiseAllSettledResolveElementSharedFun",
|
||||
("old_space", 0x01759): "PromiseAllSettledRejectElementSharedFun",
|
||||
("old_space", 0x01781): "PromiseAnyRejectElementSharedFun",
|
||||
("old_space", 0x017a9): "PromiseCapabilityDefaultRejectSharedFun",
|
||||
("old_space", 0x017d1): "PromiseCapabilityDefaultResolveSharedFun",
|
||||
("old_space", 0x017f9): "PromiseCatchFinallySharedFun",
|
||||
("old_space", 0x01821): "PromiseGetCapabilitiesExecutorSharedFun",
|
||||
("old_space", 0x01849): "PromiseThenFinallySharedFun",
|
||||
("old_space", 0x01871): "PromiseThrowerFinallySharedFun",
|
||||
("old_space", 0x01899): "PromiseValueThunkFinallySharedFun",
|
||||
("old_space", 0x018c1): "ProxyRevokeSharedFun",
|
||||
("old_space", 0x015a5): "AsyncFunctionAwaitRejectSharedFun",
|
||||
("old_space", 0x015cd): "AsyncFunctionAwaitResolveSharedFun",
|
||||
("old_space", 0x015f5): "AsyncGeneratorAwaitRejectSharedFun",
|
||||
("old_space", 0x0161d): "AsyncGeneratorAwaitResolveSharedFun",
|
||||
("old_space", 0x01645): "AsyncGeneratorYieldResolveSharedFun",
|
||||
("old_space", 0x0166d): "AsyncGeneratorReturnResolveSharedFun",
|
||||
("old_space", 0x01695): "AsyncGeneratorReturnClosedRejectSharedFun",
|
||||
("old_space", 0x016bd): "AsyncGeneratorReturnClosedResolveSharedFun",
|
||||
("old_space", 0x016e5): "AsyncIteratorValueUnwrapSharedFun",
|
||||
("old_space", 0x0170d): "PromiseAllResolveElementSharedFun",
|
||||
("old_space", 0x01735): "PromiseAllSettledResolveElementSharedFun",
|
||||
("old_space", 0x0175d): "PromiseAllSettledRejectElementSharedFun",
|
||||
("old_space", 0x01785): "PromiseAnyRejectElementSharedFun",
|
||||
("old_space", 0x017ad): "PromiseCapabilityDefaultRejectSharedFun",
|
||||
("old_space", 0x017d5): "PromiseCapabilityDefaultResolveSharedFun",
|
||||
("old_space", 0x017fd): "PromiseCatchFinallySharedFun",
|
||||
("old_space", 0x01825): "PromiseGetCapabilitiesExecutorSharedFun",
|
||||
("old_space", 0x0184d): "PromiseThenFinallySharedFun",
|
||||
("old_space", 0x01875): "PromiseThrowerFinallySharedFun",
|
||||
("old_space", 0x0189d): "PromiseValueThunkFinallySharedFun",
|
||||
("old_space", 0x018c5): "ProxyRevokeSharedFun",
|
||||
}
|
||||
|
||||
# Lower 32 bits of first page addresses for various heap spaces.
|
||||
|
Loading…
Reference in New Issue
Block a user