[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:
Gus Caplan 2020-07-07 19:20:48 -05:00 committed by Commit Bot
parent e33e84815d
commit f14960b02a
9 changed files with 126 additions and 107 deletions

View File

@ -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",

View File

@ -329,6 +329,7 @@ extern enum MessageTemplate {
kWasmTrapNullDereference,
kWasmTrapIllegalCast,
kWasmTrapArrayOutOfBounds,
kWeakRefsWeakRefConstructorTargetMustBeObject,
...
}

View File

@ -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) \

View File

@ -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

View File

@ -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
View 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

View File

@ -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

View File

@ -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) \

View File

@ -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.