Reland "[torque] typed context slot access"
This is a reland of 408e7240d7
Change: Allow CSA load elimination accross code comments
Original change's description:
> [torque] typed context slot access
>
> This introduces a new type Slot<ContextType, SlotType> that is used
> for enum values used to access context slots.
> Together with new types for the various custom contexts used in
> Torque, this results in fairly type-safe access to context slots,
> including the NativeContext's slots.
>
> Drive-by changes:
> - Introduce a new header file to specify headers needed for
> generated CSA headers, to reduce the amount of includes specified
> in implementation-visitor.cc
> - Port AllocateSyntheticFunctionContext to Torque.
>
> Bug: v8:7793
> Change-Id: I509a128916ca408eeeb636a9bcc376b2cc868532
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2335064
> Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
> Reviewed-by: Seth Brenith <seth.brenith@microsoft.com>
> Cr-Commit-Position: refs/heads/master@{#69249}
Bug: v8:7793
Change-Id: I1fe100d8d62e8220524eddb8ecc4faa85219748d
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2339462
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#69264}
This commit is contained in:
parent
54fd06268a
commit
6647f2927c
1
BUILD.gn
1
BUILD.gn
@ -1767,6 +1767,7 @@ v8_source_set("v8_initializers") {
|
||||
"src/builtins/profile-data-reader.cc",
|
||||
"src/builtins/profile-data-reader.h",
|
||||
"src/builtins/setup-builtins-internal.cc",
|
||||
"src/builtins/torque-csa-header-includes.h",
|
||||
"src/codegen/code-stub-assembler.cc",
|
||||
"src/codegen/code-stub-assembler.h",
|
||||
"src/heap/setup-heap-internal.cc",
|
||||
|
@ -414,17 +414,18 @@ const kMinJoinStackSize:
|
||||
constexpr int31 generates 'JSArray::kMinJoinStackSize';
|
||||
macro LoadJoinStack(implicit context: Context)(): FixedArray
|
||||
labels IfUninitialized {
|
||||
const nativeContext: NativeContext = LoadNativeContext(context);
|
||||
const stack: HeapObject = UnsafeCast<HeapObject>(
|
||||
nativeContext.elements[NativeContextSlot::ARRAY_JOIN_STACK_INDEX]);
|
||||
if (stack == Undefined) goto IfUninitialized;
|
||||
assert(Is<FixedArray>(stack));
|
||||
return UnsafeCast<FixedArray>(stack);
|
||||
typeswitch (*NativeContextSlot(ContextSlot::ARRAY_JOIN_STACK_INDEX)) {
|
||||
case (Undefined): {
|
||||
goto IfUninitialized;
|
||||
}
|
||||
case (stack: FixedArray): {
|
||||
return stack;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro SetJoinStack(implicit context: Context)(stack: FixedArray): void {
|
||||
const nativeContext: NativeContext = LoadNativeContext(context);
|
||||
nativeContext.elements[NativeContextSlot::ARRAY_JOIN_STACK_INDEX] = stack;
|
||||
*NativeContextSlot(ContextSlot::ARRAY_JOIN_STACK_INDEX) = stack;
|
||||
}
|
||||
|
||||
// Adds a receiver to the stack. The FixedArray will automatically grow to
|
||||
|
@ -451,8 +451,6 @@ const UNSAFE_SKIP_WRITE_BARRIER:
|
||||
|
||||
extern transitioning macro AllocateJSIteratorResult(implicit context: Context)(
|
||||
JSAny, Boolean): JSObject;
|
||||
extern macro AllocateSyntheticFunctionContext(
|
||||
NativeContext, constexpr int32): Context;
|
||||
|
||||
extern class Filler extends HeapObject generates 'TNode<HeapObject>';
|
||||
|
||||
@ -1102,74 +1100,47 @@ macro AllowNonNumberElements(kind: ElementsKind): ElementsKind {
|
||||
}
|
||||
|
||||
macro GetObjectFunction(implicit context: Context)(): JSFunction {
|
||||
return UnsafeCast<JSFunction>(
|
||||
LoadNativeContext(context)
|
||||
.elements[NativeContextSlot::OBJECT_FUNCTION_INDEX]);
|
||||
return *NativeContextSlot(ContextSlot::OBJECT_FUNCTION_INDEX);
|
||||
}
|
||||
macro GetArrayFunction(implicit context: Context)(): JSFunction {
|
||||
return UnsafeCast<JSFunction>(
|
||||
LoadNativeContext(context)
|
||||
.elements[NativeContextSlot::ARRAY_FUNCTION_INDEX]);
|
||||
return *NativeContextSlot(ContextSlot::ARRAY_FUNCTION_INDEX);
|
||||
}
|
||||
macro GetArrayBufferFunction(implicit context: Context)(): Constructor {
|
||||
return UnsafeCast<Constructor>(
|
||||
LoadNativeContext(context)
|
||||
.elements[NativeContextSlot::ARRAY_BUFFER_FUN_INDEX]);
|
||||
return *NativeContextSlot(ContextSlot::ARRAY_BUFFER_FUN_INDEX);
|
||||
}
|
||||
macro GetArrayBufferNoInitFunction(implicit context: Context)(): JSFunction {
|
||||
return UnsafeCast<JSFunction>(
|
||||
LoadNativeContext(context)
|
||||
.elements[NativeContextSlot::ARRAY_BUFFER_NOINIT_FUN_INDEX]);
|
||||
return *NativeContextSlot(ContextSlot::ARRAY_BUFFER_NOINIT_FUN_INDEX);
|
||||
}
|
||||
macro GetFastPackedElementsJSArrayMap(implicit context: Context)(): Map {
|
||||
return UnsafeCast<Map>(
|
||||
LoadNativeContext(context)
|
||||
.elements[NativeContextSlot::JS_ARRAY_PACKED_ELEMENTS_MAP_INDEX]);
|
||||
return *NativeContextSlot(ContextSlot::JS_ARRAY_PACKED_ELEMENTS_MAP_INDEX);
|
||||
}
|
||||
macro GetFastPackedSmiElementsJSArrayMap(implicit context: Context)(): Map {
|
||||
return UnsafeCast<Map>(
|
||||
LoadNativeContext(context)
|
||||
.elements[NativeContextSlot::JS_ARRAY_PACKED_SMI_ELEMENTS_MAP_INDEX]);
|
||||
return *NativeContextSlot(
|
||||
ContextSlot::JS_ARRAY_PACKED_SMI_ELEMENTS_MAP_INDEX);
|
||||
}
|
||||
macro GetProxyRevocableResultMap(implicit context: Context)(): Map {
|
||||
return UnsafeCast<Map>(
|
||||
LoadNativeContext(context)
|
||||
.elements[NativeContextSlot::PROXY_REVOCABLE_RESULT_MAP_INDEX]);
|
||||
return *NativeContextSlot(ContextSlot::PROXY_REVOCABLE_RESULT_MAP_INDEX);
|
||||
}
|
||||
macro GetIteratorResultMap(implicit context: Context)(): Map {
|
||||
return UnsafeCast<Map>(
|
||||
LoadNativeContext(context)
|
||||
.elements[NativeContextSlot::ITERATOR_RESULT_MAP_INDEX]);
|
||||
return *NativeContextSlot(ContextSlot::ITERATOR_RESULT_MAP_INDEX);
|
||||
}
|
||||
macro GetInitialStringIteratorMap(implicit context: Context)(): Map {
|
||||
return UnsafeCast<Map>(
|
||||
LoadNativeContext(context)
|
||||
.elements[NativeContextSlot::INITIAL_STRING_ITERATOR_MAP_INDEX]);
|
||||
return *NativeContextSlot(ContextSlot::INITIAL_STRING_ITERATOR_MAP_INDEX);
|
||||
}
|
||||
macro GetReflectApply(implicit context: Context)(): Callable {
|
||||
return UnsafeCast<Callable>(
|
||||
LoadNativeContext(context)
|
||||
.elements[NativeContextSlot::REFLECT_APPLY_INDEX]);
|
||||
return *NativeContextSlot(ContextSlot::REFLECT_APPLY_INDEX);
|
||||
}
|
||||
macro GetRegExpLastMatchInfo(implicit context: Context)(): RegExpMatchInfo {
|
||||
return %RawDownCast<RegExpMatchInfo>(
|
||||
LoadNativeContext(context)
|
||||
.elements[NativeContextSlot::REGEXP_LAST_MATCH_INFO_INDEX]);
|
||||
return *NativeContextSlot(ContextSlot::REGEXP_LAST_MATCH_INFO_INDEX);
|
||||
}
|
||||
macro GetStrictArgumentsMap(implicit context: Context)(): Map {
|
||||
return UnsafeCast<Map>(
|
||||
LoadNativeContext(context)
|
||||
.elements[NativeContextSlot::STRICT_ARGUMENTS_MAP_INDEX]);
|
||||
return *NativeContextSlot(ContextSlot::STRICT_ARGUMENTS_MAP_INDEX);
|
||||
}
|
||||
macro GetSloppyArgumentsMap(implicit context: Context)(): Map {
|
||||
return UnsafeCast<Map>(
|
||||
LoadNativeContext(context)
|
||||
.elements[NativeContextSlot::SLOPPY_ARGUMENTS_MAP_INDEX]);
|
||||
return *NativeContextSlot(ContextSlot::SLOPPY_ARGUMENTS_MAP_INDEX);
|
||||
}
|
||||
macro GetFastAliasedArgumentsMap(implicit context: Context)(): Map {
|
||||
return UnsafeCast<Map>(
|
||||
LoadNativeContext(context)
|
||||
.elements[NativeContextSlot::FAST_ALIASED_ARGUMENTS_MAP_INDEX]);
|
||||
return *NativeContextSlot(ContextSlot::FAST_ALIASED_ARGUMENTS_MAP_INDEX);
|
||||
}
|
||||
macro GetWeakCellMap(implicit context: Context)(): Map {
|
||||
return %GetClassMapConstant<WeakCell>();
|
||||
|
@ -62,9 +62,10 @@ TNode<JSProxy> ProxiesCodeStubAssembler::AllocateProxy(
|
||||
|
||||
TNode<Context> ProxiesCodeStubAssembler::CreateProxyRevokeFunctionContext(
|
||||
TNode<JSProxy> proxy, TNode<NativeContext> native_context) {
|
||||
const TNode<Context> context =
|
||||
AllocateSyntheticFunctionContext(native_context, kProxyContextLength);
|
||||
StoreContextElementNoWriteBarrier(context, kProxySlot, proxy);
|
||||
const TNode<Context> context = AllocateSyntheticFunctionContext(
|
||||
native_context, ProxyRevokeFunctionContextSlot::kProxyContextLength);
|
||||
StoreContextElementNoWriteBarrier(
|
||||
context, ProxyRevokeFunctionContextSlot::kProxySlot, proxy);
|
||||
return context;
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,6 @@ class ProxiesCodeStubAssembler : public CodeStubAssembler {
|
||||
void CheckDeleteTrapResult(TNode<Context> context, TNode<JSReceiver> target,
|
||||
TNode<JSProxy> proxy, TNode<Name> name);
|
||||
|
||||
protected:
|
||||
enum ProxyRevokeFunctionContextSlot {
|
||||
kProxySlot = Context::MIN_CONTEXT_SLOTS,
|
||||
kProxyContextLength,
|
||||
|
@ -611,6 +611,35 @@ Cast<JSFunction|JSBoundFunction>(implicit context: Context)(o: Object):
|
||||
}
|
||||
}
|
||||
|
||||
Cast<FixedArray|Undefined>(o: HeapObject): FixedArray|
|
||||
Undefined labels CastError {
|
||||
typeswitch (o) {
|
||||
case (o: Undefined): {
|
||||
return o;
|
||||
}
|
||||
case (o: FixedArray): {
|
||||
return o;
|
||||
}
|
||||
case (Object): {
|
||||
goto CastError;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Cast<JSProxy|Null>(o: HeapObject): JSProxy|Null labels CastError {
|
||||
typeswitch (o) {
|
||||
case (o: Null): {
|
||||
return o;
|
||||
}
|
||||
case (o: JSProxy): {
|
||||
return o;
|
||||
}
|
||||
case (Object): {
|
||||
goto CastError;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro Is<A : type extends Object, B : type extends Object>(
|
||||
implicit context: Context)(o: B): bool {
|
||||
Cast<A>(o) otherwise return false;
|
||||
|
@ -112,7 +112,7 @@ transitioning builtin ToObject(implicit context: Context)(input: JSAny):
|
||||
try {
|
||||
typeswitch (input) {
|
||||
case (Smi): {
|
||||
goto WrapPrimitive(NativeContextSlot::NUMBER_FUNCTION_INDEX);
|
||||
goto WrapPrimitive(ContextSlot::NUMBER_FUNCTION_INDEX);
|
||||
}
|
||||
case (o: JSReceiver): {
|
||||
return o;
|
||||
@ -120,14 +120,14 @@ transitioning builtin ToObject(implicit context: Context)(input: JSAny):
|
||||
case (o: JSAnyNotSmi): {
|
||||
const index: intptr = Convert<intptr>(
|
||||
o.map.in_object_properties_start_or_constructor_function_index);
|
||||
if (index != kNoConstructorFunctionIndex) goto WrapPrimitive(index);
|
||||
if (index != kNoConstructorFunctionIndex)
|
||||
goto WrapPrimitive(
|
||||
%RawDownCast<Slot<NativeContext, JSFunction>>(index));
|
||||
ThrowTypeError(MessageTemplate::kUndefinedOrNullToObject, 'ToObject');
|
||||
}
|
||||
}
|
||||
} label WrapPrimitive(constructorIndex: intptr) {
|
||||
const nativeContext = LoadNativeContext(context);
|
||||
const constructor =
|
||||
UnsafeCast<JSFunction>(nativeContext.elements[constructorIndex]);
|
||||
} label WrapPrimitive(constructorIndex: Slot<NativeContext, JSFunction>) {
|
||||
const constructor = *NativeContextSlot(constructorIndex);
|
||||
const map: Map = UnsafeCast<Map>(constructor.prototype_or_initial_map);
|
||||
const wrapper =
|
||||
UnsafeCast<JSPrimitiveWrapper>(AllocateFastOrSlowJSObjectFromMap(map));
|
||||
|
@ -66,14 +66,12 @@ FastFunctionPrototypeBind(
|
||||
// Choose the right bound function map based on whether the target is
|
||||
// constructable.
|
||||
|
||||
const boundFunctionMap: Map = UnsafeCast<Map>(
|
||||
const boundFunctionMap: Map =
|
||||
IsConstructor(fn) ?
|
||||
context
|
||||
.elements[NativeContextSlot::
|
||||
BOUND_FUNCTION_WITH_CONSTRUCTOR_MAP_INDEX] :
|
||||
context.elements
|
||||
[NativeContextSlot::
|
||||
BOUND_FUNCTION_WITHOUT_CONSTRUCTOR_MAP_INDEX]);
|
||||
*NativeContextSlot(
|
||||
ContextSlot::BOUND_FUNCTION_WITH_CONSTRUCTOR_MAP_INDEX) :
|
||||
*NativeContextSlot(ContextSlot::
|
||||
BOUND_FUNCTION_WITHOUT_CONSTRUCTOR_MAP_INDEX);
|
||||
|
||||
// Verify that prototype matches that of the target bound function.
|
||||
|
||||
|
@ -437,19 +437,16 @@ extern macro RefillMathRandom(NativeContext): Smi;
|
||||
|
||||
transitioning javascript builtin
|
||||
MathRandom(js-implicit context: NativeContext, receiver: JSAny)(): Number {
|
||||
let smiIndex: Smi =
|
||||
Cast<Smi>(context.elements[NativeContextSlot::MATH_RANDOM_INDEX_INDEX])
|
||||
otherwise unreachable;
|
||||
let smiIndex: Smi = *NativeContextSlot(ContextSlot::MATH_RANDOM_INDEX_INDEX);
|
||||
if (smiIndex == 0) {
|
||||
// refill math random.
|
||||
smiIndex = RefillMathRandom(context);
|
||||
}
|
||||
const newSmiIndex: Smi = smiIndex - 1;
|
||||
context.elements[NativeContextSlot::MATH_RANDOM_INDEX_INDEX] = newSmiIndex;
|
||||
*NativeContextSlot(ContextSlot::MATH_RANDOM_INDEX_INDEX) = newSmiIndex;
|
||||
|
||||
const array: FixedDoubleArray = Cast<FixedDoubleArray>(
|
||||
context.elements[NativeContextSlot::MATH_RANDOM_CACHE_INDEX])
|
||||
otherwise unreachable;
|
||||
const array: FixedDoubleArray =
|
||||
*NativeContextSlot(ContextSlot::MATH_RANDOM_CACHE_INDEX);
|
||||
const random: float64 =
|
||||
array.floats[Convert<intptr>(newSmiIndex)].ValueUnsafeAssumeNotHole();
|
||||
return AllocateHeapNumberWithValue(random);
|
||||
|
@ -92,22 +92,19 @@ ObjectSetPrototypeOfDontThrow(implicit context: Context)(
|
||||
|
||||
transitioning builtin CreateObjectWithoutProperties(implicit context: Context)(
|
||||
prototype: JSAny): JSAny {
|
||||
const nativeContext = LoadNativeContext(context);
|
||||
|
||||
try {
|
||||
let map: Map;
|
||||
let properties: NameDictionary|EmptyFixedArray;
|
||||
typeswitch (prototype) {
|
||||
case (Null): {
|
||||
map = UnsafeCast<Map>(
|
||||
nativeContext.elements
|
||||
[NativeContextSlot::SLOW_OBJECT_WITH_NULL_PROTOTYPE_MAP]);
|
||||
map = *NativeContextSlot(
|
||||
ContextSlot::SLOW_OBJECT_WITH_NULL_PROTOTYPE_MAP);
|
||||
properties = AllocateNameDictionary(kNameDictionaryInitialCapacity);
|
||||
}
|
||||
case (prototype: JSReceiver): {
|
||||
properties = kEmptyFixedArray;
|
||||
const objectFunction = UnsafeCast<JSFunction>(
|
||||
nativeContext.elements[NativeContextSlot::OBJECT_FUNCTION_INDEX]);
|
||||
const objectFunction =
|
||||
*NativeContextSlot(ContextSlot::OBJECT_FUNCTION_INDEX);
|
||||
map = UnsafeCast<Map>(objectFunction.prototype_or_initial_map);
|
||||
if (prototype != map.prototype) {
|
||||
const prototypeInfo = prototype.map.PrototypeInfo() otherwise Runtime;
|
||||
|
@ -35,7 +35,7 @@ const kResolveString: String = ResolveStringConstant();
|
||||
extern macro IsPromiseResolveProtectorCellInvalid(): bool;
|
||||
|
||||
extern macro AllocateFunctionWithMapAndContext(
|
||||
Map, SharedFunctionInfo, Context): JSFunction;
|
||||
Map, SharedFunctionInfo, FunctionContext): JSFunction;
|
||||
|
||||
extern macro PromiseReactionMapConstant(): Map;
|
||||
extern macro PromiseFulfillReactionJobTaskMapConstant(): Map;
|
||||
@ -252,24 +252,33 @@ RejectPromise(implicit context: Context)(
|
||||
|
||||
const kPromiseCapabilitySize:
|
||||
constexpr int31 generates 'PromiseCapability::kSize';
|
||||
const kPromiseBuiltinsCapabilitiesContextLength: constexpr int31
|
||||
generates 'PromiseBuiltins::kCapabilitiesContextLength';
|
||||
const kPromiseBuiltinsCapabilitySlot: constexpr ContextSlot
|
||||
generates 'PromiseBuiltins::kCapabilitySlot';
|
||||
const kPromiseBuiltinsPromiseSlot: constexpr ContextSlot
|
||||
generates 'PromiseBuiltins::kPromiseSlot';
|
||||
const kPromiseBuiltinsAlreadyResolvedSlot: constexpr ContextSlot
|
||||
generates 'PromiseBuiltins::kAlreadyResolvedSlot';
|
||||
const kPromiseBuiltinsDebugEventSlot: constexpr ContextSlot
|
||||
generates 'PromiseBuiltins::kDebugEventSlot';
|
||||
|
||||
type PromiseResolvingFunctionContext extends FunctionContext;
|
||||
extern enum PromiseResolvingFunctionContextSlot extends intptr
|
||||
constexpr 'PromiseBuiltins::PromiseResolvingFunctionContextSlot' {
|
||||
kPromiseSlot: Slot<PromiseResolvingFunctionContext, JSPromise>,
|
||||
kAlreadyResolvedSlot: Slot<PromiseResolvingFunctionContext, Boolean>,
|
||||
kDebugEventSlot: Slot<PromiseResolvingFunctionContext, Boolean>,
|
||||
kPromiseContextLength
|
||||
}
|
||||
|
||||
type PromiseCapabilitiesExecutorContext extends FunctionContext;
|
||||
extern enum FunctionContextSlot extends intptr
|
||||
constexpr 'PromiseBuiltins::FunctionContextSlot' {
|
||||
kCapabilitySlot: Slot<PromiseCapabilitiesExecutorContext, PromiseCapability>,
|
||||
kCapabilitiesContextLength
|
||||
}
|
||||
|
||||
@export
|
||||
macro CreatePromiseCapabilitiesExecutorContext(
|
||||
nativeContext: NativeContext, capability: PromiseCapability): Context {
|
||||
const executorContext = AllocateSyntheticFunctionContext(
|
||||
nativeContext, kPromiseBuiltinsCapabilitiesContextLength);
|
||||
nativeContext: NativeContext, capability: PromiseCapability):
|
||||
PromiseCapabilitiesExecutorContext {
|
||||
const executorContext = %RawDownCast<PromiseCapabilitiesExecutorContext>(
|
||||
AllocateSyntheticFunctionContext(
|
||||
nativeContext, FunctionContextSlot::kCapabilitiesContextLength));
|
||||
|
||||
executorContext.elements[kPromiseBuiltinsCapabilitySlot] = capability;
|
||||
InitContextSlot(
|
||||
executorContext, FunctionContextSlot::kCapabilitySlot, capability);
|
||||
return executorContext;
|
||||
}
|
||||
|
||||
@ -293,13 +302,12 @@ struct PromiseResolvingFunctions {
|
||||
|
||||
@export
|
||||
macro CreatePromiseResolvingFunctions(implicit context: Context)(
|
||||
promise: JSPromise, debugEvent: Object, nativeContext: NativeContext):
|
||||
promise: JSPromise, debugEvent: Boolean, nativeContext: NativeContext):
|
||||
PromiseResolvingFunctions {
|
||||
const promiseContext = CreatePromiseResolvingFunctionsContext(
|
||||
promise, debugEvent, nativeContext);
|
||||
const map = UnsafeCast<Map>(
|
||||
nativeContext.elements
|
||||
[NativeContextSlot::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX]);
|
||||
const map = *NativeContextSlot(
|
||||
nativeContext, ContextSlot::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
|
||||
const resolveInfo = PromiseCapabilityDefaultResolveSharedFunConstant();
|
||||
|
||||
const resolve: JSFunction =
|
||||
@ -312,11 +320,10 @@ macro CreatePromiseResolvingFunctions(implicit context: Context)(
|
||||
|
||||
transitioning macro
|
||||
InnerNewPromiseCapability(implicit context: Context)(
|
||||
constructor: HeapObject, debugEvent: Object): PromiseCapability {
|
||||
constructor: HeapObject, debugEvent: Boolean): PromiseCapability {
|
||||
const nativeContext = LoadNativeContext(context);
|
||||
if (TaggedEqual(
|
||||
constructor,
|
||||
nativeContext.elements[NativeContextSlot::PROMISE_FUNCTION_INDEX])) {
|
||||
if (constructor ==
|
||||
*NativeContextSlot(nativeContext, ContextSlot::PROMISE_FUNCTION_INDEX)) {
|
||||
const promise = NewJSPromise();
|
||||
|
||||
const pair =
|
||||
@ -331,9 +338,10 @@ InnerNewPromiseCapability(implicit context: Context)(
|
||||
CreatePromiseCapabilitiesExecutorContext(nativeContext, capability);
|
||||
|
||||
const executorInfo = PromiseGetCapabilitiesExecutorSharedFunConstant();
|
||||
const functionMap = UnsafeCast<Map>(
|
||||
nativeContext.elements
|
||||
[NativeContextSlot::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX]);
|
||||
const functionMap =
|
||||
*NativeContextSlot(
|
||||
nativeContext,
|
||||
ContextSlot::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
|
||||
const executor = AllocateFunctionWithMapAndContext(
|
||||
functionMap, executorInfo, executorContext);
|
||||
|
||||
@ -351,7 +359,7 @@ InnerNewPromiseCapability(implicit context: Context)(
|
||||
// https://tc39.es/ecma262/#sec-newpromisecapability
|
||||
transitioning builtin
|
||||
NewPromiseCapability(implicit context: Context)(
|
||||
maybeConstructor: Object, debugEvent: Object): PromiseCapability {
|
||||
maybeConstructor: Object, debugEvent: Boolean): PromiseCapability {
|
||||
typeswitch (maybeConstructor) {
|
||||
case (Smi): {
|
||||
ThrowTypeError(MessageTemplate::kNotConstructor, maybeConstructor);
|
||||
@ -368,14 +376,15 @@ NewPromiseCapability(implicit context: Context)(
|
||||
// https://tc39.es/ecma262/#sec-promise-reject-functions
|
||||
transitioning javascript builtin
|
||||
PromiseCapabilityDefaultReject(
|
||||
js-implicit context: NativeContext, receiver: JSAny)(reason: JSAny): JSAny {
|
||||
js-implicit context: Context, receiver: JSAny)(reason: JSAny): JSAny {
|
||||
const context = %RawDownCast<PromiseResolvingFunctionContext>(context);
|
||||
// 2. Let promise be F.[[Promise]].
|
||||
const promise =
|
||||
UnsafeCast<JSPromise>(context.elements[kPromiseBuiltinsPromiseSlot]);
|
||||
*ContextSlot(context, PromiseResolvingFunctionContextSlot::kPromiseSlot);
|
||||
|
||||
// 3. Let alreadyResolved be F.[[AlreadyResolved]].
|
||||
const alreadyResolved = UnsafeCast<Boolean>(
|
||||
context.elements[kPromiseBuiltinsAlreadyResolvedSlot]);
|
||||
const alreadyResolved = *ContextSlot(
|
||||
context, PromiseResolvingFunctionContextSlot::kAlreadyResolvedSlot);
|
||||
|
||||
// 4. If alreadyResolved.[[Value]] is true, return undefined.
|
||||
if (alreadyResolved == True) {
|
||||
@ -383,26 +392,28 @@ PromiseCapabilityDefaultReject(
|
||||
}
|
||||
|
||||
// 5. Set alreadyResolved.[[Value]] to true.
|
||||
context.elements[kPromiseBuiltinsAlreadyResolvedSlot] = True;
|
||||
*ContextSlot(
|
||||
context, PromiseResolvingFunctionContextSlot::kAlreadyResolvedSlot) =
|
||||
True;
|
||||
|
||||
// 6. Return RejectPromise(promise, reason).
|
||||
const debugEvent =
|
||||
UnsafeCast<Boolean>(context.elements[kPromiseBuiltinsDebugEventSlot]);
|
||||
const debugEvent = *ContextSlot(
|
||||
context, PromiseResolvingFunctionContextSlot::kDebugEventSlot);
|
||||
return RejectPromise(promise, reason, debugEvent);
|
||||
}
|
||||
|
||||
// https://tc39.es/ecma262/#sec-promise-resolve-functions
|
||||
transitioning javascript builtin
|
||||
PromiseCapabilityDefaultResolve(
|
||||
js-implicit context: NativeContext,
|
||||
receiver: JSAny)(resolution: JSAny): JSAny {
|
||||
js-implicit context: Context, receiver: JSAny)(resolution: JSAny): JSAny {
|
||||
const context = %RawDownCast<PromiseResolvingFunctionContext>(context);
|
||||
// 2. Let promise be F.[[Promise]].
|
||||
const promise =
|
||||
UnsafeCast<JSPromise>(context.elements[kPromiseBuiltinsPromiseSlot]);
|
||||
const promise: JSPromise =
|
||||
*ContextSlot(context, PromiseResolvingFunctionContextSlot::kPromiseSlot);
|
||||
|
||||
// 3. Let alreadyResolved be F.[[AlreadyResolved]].
|
||||
const alreadyResolved = UnsafeCast<Boolean>(
|
||||
context.elements[kPromiseBuiltinsAlreadyResolvedSlot]);
|
||||
const alreadyResolved: Boolean = *ContextSlot(
|
||||
context, PromiseResolvingFunctionContextSlot::kAlreadyResolvedSlot);
|
||||
|
||||
// 4. If alreadyResolved.[[Value]] is true, return undefined.
|
||||
if (alreadyResolved == True) {
|
||||
@ -410,7 +421,9 @@ PromiseCapabilityDefaultResolve(
|
||||
}
|
||||
|
||||
// 5. Set alreadyResolved.[[Value]] to true.
|
||||
context.elements[kPromiseBuiltinsAlreadyResolvedSlot] = True;
|
||||
*ContextSlot(
|
||||
context, PromiseResolvingFunctionContextSlot::kAlreadyResolvedSlot) =
|
||||
True;
|
||||
|
||||
// The rest of the logic (and the catch prediction) is
|
||||
// encapsulated in the dedicated ResolvePromise builtin.
|
||||
@ -477,8 +490,7 @@ PromiseReject(
|
||||
const receiver = Cast<JSReceiver>(receiver) otherwise
|
||||
ThrowTypeError(MessageTemplate::kCalledOnNonObject, 'PromiseReject');
|
||||
|
||||
const promiseFun =
|
||||
context.elements[NativeContextSlot::PROMISE_FUNCTION_INDEX];
|
||||
const promiseFun = *NativeContextSlot(ContextSlot::PROMISE_FUNCTION_INDEX);
|
||||
if (promiseFun == receiver) {
|
||||
const promise = NewJSPromise(PromiseState::kRejected, reason);
|
||||
runtime::PromiseRejectEventFromStack(promise, reason);
|
||||
@ -501,11 +513,11 @@ const kPromiseExecutorAlreadyInvoked: constexpr MessageTemplate
|
||||
|
||||
// https://tc39.es/ecma262/#sec-getcapabilitiesexecutor-functions
|
||||
transitioning javascript builtin
|
||||
PromiseGetCapabilitiesExecutor(
|
||||
js-implicit context: NativeContext, receiver: JSAny)(
|
||||
PromiseGetCapabilitiesExecutor(js-implicit context: Context, receiver: JSAny)(
|
||||
resolve: JSAny, reject: JSAny): JSAny {
|
||||
const capability = UnsafeCast<PromiseCapability>(
|
||||
context.elements[kPromiseBuiltinsCapabilitySlot]);
|
||||
const context = %RawDownCast<PromiseCapabilitiesExecutorContext>(context);
|
||||
const capability: PromiseCapability =
|
||||
*ContextSlot(context, FunctionContextSlot::kCapabilitySlot);
|
||||
if (capability.resolve != Undefined || capability.reject != Undefined)
|
||||
deferred {
|
||||
ThrowTypeError(kPromiseExecutorAlreadyInvoked);
|
||||
@ -519,8 +531,8 @@ PromiseGetCapabilitiesExecutor(
|
||||
macro IsPromiseResolveLookupChainIntact(implicit context: Context)(
|
||||
nativeContext: NativeContext, constructor: JSReceiver): bool {
|
||||
if (IsForceSlowPath()) return false;
|
||||
const promiseFun = UnsafeCast<JSFunction>(
|
||||
nativeContext.elements[NativeContextSlot::PROMISE_FUNCTION_INDEX]);
|
||||
const promiseFun =
|
||||
*NativeContextSlot(nativeContext, ContextSlot::PROMISE_FUNCTION_INDEX);
|
||||
return promiseFun == constructor && !IsPromiseResolveProtectorCellInvalid();
|
||||
}
|
||||
|
||||
|
@ -21,8 +21,8 @@ struct PromiseAllSettledWrapResultAsFulfilledFunctor {
|
||||
// TODO(gsathya): Optimize the creation using a cached map to
|
||||
// prevent transitions here.
|
||||
// 9. Let obj be ! ObjectCreate(%ObjectPrototype%).
|
||||
const objectFunction = UnsafeCast<JSFunction>(
|
||||
nativeContext.elements[NativeContextSlot::OBJECT_FUNCTION_INDEX]);
|
||||
const objectFunction =
|
||||
*NativeContextSlot(nativeContext, ContextSlot::OBJECT_FUNCTION_INDEX);
|
||||
const objectFunctionMap =
|
||||
UnsafeCast<Map>(objectFunction.prototype_or_initial_map);
|
||||
const obj = AllocateJSObjectFromMap(objectFunctionMap);
|
||||
@ -44,8 +44,8 @@ struct PromiseAllSettledWrapResultAsRejectedFunctor {
|
||||
// TODO(gsathya): Optimize the creation using a cached map to
|
||||
// prevent transitions here.
|
||||
// 9. Let obj be ! ObjectCreate(%ObjectPrototype%).
|
||||
const objectFunction = UnsafeCast<JSFunction>(
|
||||
nativeContext.elements[NativeContextSlot::OBJECT_FUNCTION_INDEX]);
|
||||
const objectFunction =
|
||||
*NativeContextSlot(nativeContext, ContextSlot::OBJECT_FUNCTION_INDEX);
|
||||
const objectFunctionMap =
|
||||
UnsafeCast<Map>(objectFunction.prototype_or_initial_map);
|
||||
const obj = AllocateJSObjectFromMap(objectFunctionMap);
|
||||
@ -62,11 +62,15 @@ struct PromiseAllSettledWrapResultAsRejectedFunctor {
|
||||
|
||||
extern macro LoadJSReceiverIdentityHash(Object): intptr labels IfNoHash;
|
||||
|
||||
extern enum PromiseAllResolveElementContextSlots extends int31
|
||||
type PromiseAllResolveElementContext extends FunctionContext;
|
||||
extern enum PromiseAllResolveElementContextSlots extends intptr
|
||||
constexpr 'PromiseBuiltins::PromiseAllResolveElementContextSlots' {
|
||||
kPromiseAllResolveElementRemainingSlot,
|
||||
kPromiseAllResolveElementCapabilitySlot,
|
||||
kPromiseAllResolveElementValuesSlot,
|
||||
kPromiseAllResolveElementRemainingSlot:
|
||||
Slot<PromiseAllResolveElementContext, Smi>,
|
||||
kPromiseAllResolveElementCapabilitySlot:
|
||||
Slot<PromiseAllResolveElementContext, PromiseCapability>,
|
||||
kPromiseAllResolveElementValuesSlot:
|
||||
Slot<PromiseAllResolveElementContext, FixedArray>,
|
||||
kPromiseAllResolveElementLength
|
||||
}
|
||||
extern operator '[]=' macro StoreContextElement(
|
||||
@ -81,7 +85,7 @@ const kPropertyArrayHashFieldMax: constexpr int31
|
||||
generates 'PropertyArray::HashField::kMax';
|
||||
|
||||
transitioning macro PromiseAllResolveElementClosure<F: type>(
|
||||
implicit context: Context)(
|
||||
implicit context: PromiseAllResolveElementContext|NativeContext)(
|
||||
value: JSAny, function: JSFunction, wrapResultFunctor: F,
|
||||
hasResolveAndRejectClosures: constexpr bool): JSAny {
|
||||
// We use the {function}s context as the marker to remember whether this
|
||||
@ -89,14 +93,21 @@ transitioning macro PromiseAllResolveElementClosure<F: type>(
|
||||
// element context (which is a FunctionContext) until it was called the
|
||||
// first time, in which case we make it point to the native context here
|
||||
// to mark this resolve element closure as done.
|
||||
if (IsNativeContext(context)) deferred {
|
||||
let promiseContext: PromiseAllResolveElementContext;
|
||||
typeswitch (context) {
|
||||
case (NativeContext): deferred {
|
||||
return Undefined;
|
||||
}
|
||||
case (context: PromiseAllResolveElementContext): {
|
||||
promiseContext = context;
|
||||
}
|
||||
}
|
||||
|
||||
assert(
|
||||
context.length ==
|
||||
PromiseAllResolveElementContextSlots::kPromiseAllResolveElementLength);
|
||||
const nativeContext = LoadNativeContext(context);
|
||||
promiseContext.length ==
|
||||
SmiTag(PromiseAllResolveElementContextSlots::
|
||||
kPromiseAllResolveElementLength));
|
||||
const nativeContext = LoadNativeContext(promiseContext);
|
||||
function.context = nativeContext;
|
||||
|
||||
// Determine the index from the {function}.
|
||||
@ -106,19 +117,23 @@ transitioning macro PromiseAllResolveElementClosure<F: type>(
|
||||
assert(identityHash > 0);
|
||||
const index = identityHash - 1;
|
||||
|
||||
let remainingElementsCount = UnsafeCast<Smi>(
|
||||
context.elements[PromiseAllResolveElementContextSlots::
|
||||
kPromiseAllResolveElementRemainingSlot]);
|
||||
let remainingElementsCount = *ContextSlot(
|
||||
promiseContext,
|
||||
PromiseAllResolveElementContextSlots::
|
||||
kPromiseAllResolveElementRemainingSlot);
|
||||
|
||||
let values = UnsafeCast<FixedArray>(
|
||||
context.elements[PromiseAllResolveElementContextSlots::
|
||||
kPromiseAllResolveElementValuesSlot]);
|
||||
let values = *ContextSlot(
|
||||
promiseContext,
|
||||
PromiseAllResolveElementContextSlots::
|
||||
kPromiseAllResolveElementValuesSlot);
|
||||
const newCapacity = index + 1;
|
||||
if (newCapacity > values.length_intptr) deferred {
|
||||
// This happens only when the promises are resolved during iteration.
|
||||
values = ExtractFixedArray(values, 0, values.length_intptr, newCapacity);
|
||||
context.elements[PromiseAllResolveElementContextSlots::
|
||||
kPromiseAllResolveElementValuesSlot] = values;
|
||||
*ContextSlot(
|
||||
promiseContext,
|
||||
PromiseAllResolveElementContextSlots::
|
||||
kPromiseAllResolveElementValuesSlot) = values;
|
||||
}
|
||||
|
||||
// Promise.allSettled, for each input element, has both a resolve and a reject
|
||||
@ -144,19 +159,21 @@ transitioning macro PromiseAllResolveElementClosure<F: type>(
|
||||
values.objects[index] = updatedValue;
|
||||
|
||||
remainingElementsCount = remainingElementsCount - 1;
|
||||
context.elements[PromiseAllResolveElementContextSlots::
|
||||
kPromiseAllResolveElementRemainingSlot] =
|
||||
remainingElementsCount;
|
||||
*ContextSlot(
|
||||
promiseContext,
|
||||
PromiseAllResolveElementContextSlots::
|
||||
kPromiseAllResolveElementRemainingSlot) = remainingElementsCount;
|
||||
if (remainingElementsCount == 0) {
|
||||
const capability = UnsafeCast<PromiseCapability>(
|
||||
context.elements[PromiseAllResolveElementContextSlots::
|
||||
kPromiseAllResolveElementCapabilitySlot]);
|
||||
const capability = *ContextSlot(
|
||||
promiseContext,
|
||||
PromiseAllResolveElementContextSlots::
|
||||
kPromiseAllResolveElementCapabilitySlot);
|
||||
const resolve = UnsafeCast<JSAny>(capability.resolve);
|
||||
const arrayMap = UnsafeCast<Map>(
|
||||
nativeContext
|
||||
.elements[NativeContextSlot::JS_ARRAY_PACKED_ELEMENTS_MAP_INDEX]);
|
||||
const arrayMap =
|
||||
*NativeContextSlot(
|
||||
nativeContext, ContextSlot::JS_ARRAY_PACKED_ELEMENTS_MAP_INDEX);
|
||||
const valuesArray = NewJSArray(arrayMap, values);
|
||||
Call(context, resolve, Undefined, valuesArray);
|
||||
Call(promiseContext, resolve, Undefined, valuesArray);
|
||||
}
|
||||
return Undefined;
|
||||
}
|
||||
@ -165,6 +182,8 @@ transitioning javascript builtin
|
||||
PromiseAllResolveElementClosure(
|
||||
js-implicit context: Context, receiver: JSAny,
|
||||
target: JSFunction)(value: JSAny): JSAny {
|
||||
const context =
|
||||
%RawDownCast<PromiseAllResolveElementContext|NativeContext>(context);
|
||||
return PromiseAllResolveElementClosure(
|
||||
value, target, PromiseAllWrapResultAsFulfilledFunctor{}, false);
|
||||
}
|
||||
@ -173,6 +192,8 @@ transitioning javascript builtin
|
||||
PromiseAllSettledResolveElementClosure(
|
||||
js-implicit context: Context, receiver: JSAny,
|
||||
target: JSFunction)(value: JSAny): JSAny {
|
||||
const context =
|
||||
%RawDownCast<PromiseAllResolveElementContext|NativeContext>(context);
|
||||
return PromiseAllResolveElementClosure(
|
||||
value, target, PromiseAllSettledWrapResultAsFulfilledFunctor{}, true);
|
||||
}
|
||||
@ -181,6 +202,8 @@ transitioning javascript builtin
|
||||
PromiseAllSettledRejectElementClosure(
|
||||
js-implicit context: Context, receiver: JSAny,
|
||||
target: JSFunction)(value: JSAny): JSAny {
|
||||
const context =
|
||||
%RawDownCast<PromiseAllResolveElementContext|NativeContext>(context);
|
||||
return PromiseAllResolveElementClosure(
|
||||
value, target, PromiseAllSettledWrapResultAsRejectedFunctor{}, true);
|
||||
}
|
||||
|
@ -17,31 +17,38 @@ const kPromiseBuiltinsPromiseContextLength: constexpr int31
|
||||
// was called already (we slap the native context onto the closure in that
|
||||
// case to mark it's done).
|
||||
macro CreatePromiseAllResolveElementContext(implicit context: Context)(
|
||||
capability: PromiseCapability, nativeContext: NativeContext): Context {
|
||||
const resolveContext = AllocateSyntheticFunctionContext(
|
||||
capability: PromiseCapability,
|
||||
nativeContext: NativeContext): PromiseAllResolveElementContext {
|
||||
const resolveContext = %RawDownCast<
|
||||
PromiseAllResolveElementContext>(AllocateSyntheticFunctionContext(
|
||||
nativeContext,
|
||||
PromiseAllResolveElementContextSlots::kPromiseAllResolveElementLength);
|
||||
resolveContext.elements[PromiseAllResolveElementContextSlots::
|
||||
kPromiseAllResolveElementRemainingSlot] =
|
||||
SmiConstant(1);
|
||||
resolveContext.elements[PromiseAllResolveElementContextSlots::
|
||||
kPromiseAllResolveElementCapabilitySlot] =
|
||||
capability;
|
||||
resolveContext.elements[PromiseAllResolveElementContextSlots::
|
||||
kPromiseAllResolveElementValuesSlot] =
|
||||
kEmptyFixedArray;
|
||||
PromiseAllResolveElementContextSlots::kPromiseAllResolveElementLength));
|
||||
InitContextSlot(
|
||||
resolveContext,
|
||||
PromiseAllResolveElementContextSlots::
|
||||
kPromiseAllResolveElementRemainingSlot,
|
||||
1);
|
||||
InitContextSlot(
|
||||
resolveContext,
|
||||
PromiseAllResolveElementContextSlots::
|
||||
kPromiseAllResolveElementCapabilitySlot,
|
||||
capability);
|
||||
InitContextSlot(
|
||||
resolveContext,
|
||||
PromiseAllResolveElementContextSlots::kPromiseAllResolveElementValuesSlot,
|
||||
kEmptyFixedArray);
|
||||
return resolveContext;
|
||||
}
|
||||
|
||||
macro CreatePromiseAllResolveElementFunction(implicit context: Context)(
|
||||
resolveElementContext: Context, index: Smi, nativeContext: NativeContext,
|
||||
resolveElementContext: PromiseAllResolveElementContext, index: Smi,
|
||||
nativeContext: NativeContext,
|
||||
resolveFunction: SharedFunctionInfo): JSFunction {
|
||||
assert(index > 0);
|
||||
assert(index < kPropertyArrayHashFieldMax);
|
||||
|
||||
const map = UnsafeCast<Map>(
|
||||
nativeContext.elements
|
||||
[NativeContextSlot::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX]);
|
||||
const map = *ContextSlot(
|
||||
nativeContext, ContextSlot::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
|
||||
const resolve = AllocateFunctionWithMapAndContext(
|
||||
map, resolveFunction, resolveElementContext);
|
||||
|
||||
@ -52,13 +59,24 @@ macro CreatePromiseAllResolveElementFunction(implicit context: Context)(
|
||||
|
||||
@export
|
||||
macro CreatePromiseResolvingFunctionsContext(implicit context: Context)(
|
||||
promise: JSPromise, debugEvent: Object, nativeContext: NativeContext):
|
||||
Context {
|
||||
const resolveContext = AllocateSyntheticFunctionContext(
|
||||
nativeContext, kPromiseBuiltinsPromiseContextLength);
|
||||
resolveContext.elements[kPromiseBuiltinsPromiseSlot] = promise;
|
||||
resolveContext.elements[kPromiseBuiltinsAlreadyResolvedSlot] = False;
|
||||
resolveContext.elements[kPromiseBuiltinsDebugEventSlot] = debugEvent;
|
||||
promise: JSPromise, debugEvent: Boolean, nativeContext: NativeContext):
|
||||
PromiseResolvingFunctionContext {
|
||||
const resolveContext = %RawDownCast<PromiseResolvingFunctionContext>(
|
||||
AllocateSyntheticFunctionContext(
|
||||
nativeContext,
|
||||
PromiseResolvingFunctionContextSlot::kPromiseContextLength));
|
||||
InitContextSlot(
|
||||
resolveContext, PromiseResolvingFunctionContextSlot::kPromiseSlot,
|
||||
promise);
|
||||
InitContextSlot(
|
||||
resolveContext, PromiseResolvingFunctionContextSlot::kAlreadyResolvedSlot,
|
||||
False);
|
||||
InitContextSlot(
|
||||
resolveContext, PromiseResolvingFunctionContextSlot::kDebugEventSlot,
|
||||
debugEvent);
|
||||
static_assert(
|
||||
PromiseResolvingFunctionContextSlot::kPromiseContextLength ==
|
||||
ContextSlot::MIN_CONTEXT_SLOTS + 3);
|
||||
return resolveContext;
|
||||
}
|
||||
|
||||
@ -66,15 +84,17 @@ macro IsPromiseThenLookupChainIntact(implicit context: Context)(
|
||||
nativeContext: NativeContext, receiverMap: Map): bool {
|
||||
if (IsForceSlowPath()) return false;
|
||||
if (!IsJSPromiseMap(receiverMap)) return false;
|
||||
if (receiverMap.prototype !=
|
||||
nativeContext.elements[NativeContextSlot::PROMISE_PROTOTYPE_INDEX])
|
||||
if (receiverMap.prototype != *NativeContextSlot(
|
||||
nativeContext, ContextSlot::PROMISE_PROTOTYPE_INDEX)) {
|
||||
return false;
|
||||
}
|
||||
return !IsPromiseThenProtectorCellInvalid();
|
||||
}
|
||||
|
||||
struct PromiseAllResolveElementFunctor {
|
||||
macro Call(implicit context: Context)(
|
||||
resolveElementContext: Context, nativeContext: NativeContext, index: Smi,
|
||||
resolveElementContext: PromiseAllResolveElementContext,
|
||||
nativeContext: NativeContext, index: Smi,
|
||||
_capability: PromiseCapability): Callable {
|
||||
return CreatePromiseAllResolveElementFunction(
|
||||
resolveElementContext, index, nativeContext,
|
||||
@ -84,15 +104,17 @@ struct PromiseAllResolveElementFunctor {
|
||||
|
||||
struct PromiseAllRejectElementFunctor {
|
||||
macro Call(implicit context: Context)(
|
||||
_resolveElementContext: Context, _nativeContext: NativeContext,
|
||||
_index: Smi, capability: PromiseCapability): Callable {
|
||||
_resolveElementContext: PromiseAllResolveElementContext,
|
||||
_nativeContext: NativeContext, _index: Smi,
|
||||
capability: PromiseCapability): Callable {
|
||||
return UnsafeCast<Callable>(capability.reject);
|
||||
}
|
||||
}
|
||||
|
||||
struct PromiseAllSettledResolveElementFunctor {
|
||||
macro Call(implicit context: Context)(
|
||||
resolveElementContext: Context, nativeContext: NativeContext, index: Smi,
|
||||
resolveElementContext: PromiseAllResolveElementContext,
|
||||
nativeContext: NativeContext, index: Smi,
|
||||
_capability: PromiseCapability): Callable {
|
||||
return CreatePromiseAllResolveElementFunction(
|
||||
resolveElementContext, index, nativeContext,
|
||||
@ -102,7 +124,8 @@ struct PromiseAllSettledResolveElementFunctor {
|
||||
|
||||
struct PromiseAllSettledRejectElementFunctor {
|
||||
macro Call(implicit context: Context)(
|
||||
resolveElementContext: Context, nativeContext: NativeContext, index: Smi,
|
||||
resolveElementContext: PromiseAllResolveElementContext,
|
||||
nativeContext: NativeContext, index: Smi,
|
||||
_capability: PromiseCapability): Callable {
|
||||
return CreatePromiseAllResolveElementFunction(
|
||||
resolveElementContext, index, nativeContext,
|
||||
@ -133,8 +156,8 @@ Reject(Object) {
|
||||
let index: Smi = 1;
|
||||
|
||||
try {
|
||||
const fastIteratorResultMap = UnsafeCast<Map>(
|
||||
nativeContext.elements[NativeContextSlot::ITERATOR_RESULT_MAP_INDEX]);
|
||||
const fastIteratorResultMap = *NativeContextSlot(
|
||||
nativeContext, ContextSlot::ITERATOR_RESULT_MAP_INDEX);
|
||||
while (true) {
|
||||
let nextValue: JSAny;
|
||||
try {
|
||||
@ -169,14 +192,10 @@ Reject(Object) {
|
||||
|
||||
// Set remainingElementsCount.[[Value]] to
|
||||
// remainingElementsCount.[[Value]] + 1.
|
||||
const remainingElementsCount = UnsafeCast<Smi>(
|
||||
resolveElementContext
|
||||
.elements[PromiseAllResolveElementContextSlots::
|
||||
kPromiseAllResolveElementRemainingSlot]);
|
||||
resolveElementContext
|
||||
.elements[PromiseAllResolveElementContextSlots::
|
||||
kPromiseAllResolveElementRemainingSlot] =
|
||||
remainingElementsCount + 1;
|
||||
*ContextSlot(
|
||||
resolveElementContext,
|
||||
PromiseAllResolveElementContextSlots::
|
||||
kPromiseAllResolveElementRemainingSlot) += 1;
|
||||
|
||||
// Let resolveElement be CreateBuiltinFunction(steps,
|
||||
// « [[AlreadyCalled]],
|
||||
@ -252,32 +271,27 @@ Reject(Object) {
|
||||
// Set iteratorRecord.[[Done]] to true.
|
||||
// Set remainingElementsCount.[[Value]] to
|
||||
// remainingElementsCount.[[Value]] - 1.
|
||||
let remainingElementsCount = UnsafeCast<Smi>(
|
||||
resolveElementContext
|
||||
.elements[PromiseAllResolveElementContextSlots::
|
||||
kPromiseAllResolveElementRemainingSlot]);
|
||||
remainingElementsCount -= 1;
|
||||
resolveElementContext.elements[PromiseAllResolveElementContextSlots::
|
||||
kPromiseAllResolveElementRemainingSlot] =
|
||||
remainingElementsCount;
|
||||
const remainingElementsCount = -- *ContextSlot(
|
||||
resolveElementContext,
|
||||
PromiseAllResolveElementContextSlots::
|
||||
kPromiseAllResolveElementRemainingSlot);
|
||||
|
||||
if (remainingElementsCount > 0) {
|
||||
// Pre-allocate the backing store for the {values} to the desired
|
||||
// capacity. We may already have elements in "values" - this happens
|
||||
// when the Thenable calls the resolve callback immediately.
|
||||
let values = UnsafeCast<FixedArray>(
|
||||
resolveElementContext
|
||||
.elements[PromiseAllResolveElementContextSlots::
|
||||
kPromiseAllResolveElementValuesSlot]);
|
||||
const valuesRef:&FixedArray = ContextSlot(
|
||||
resolveElementContext,
|
||||
PromiseAllResolveElementContextSlots::
|
||||
kPromiseAllResolveElementValuesSlot);
|
||||
const values = *valuesRef;
|
||||
// 'index' is a 1-based index and incremented after every Promise. Later we
|
||||
// use 'values' as a 0-based array, so capacity 'index - 1' is enough.
|
||||
const newCapacity = SmiUntag(index) - 1;
|
||||
|
||||
const oldCapacity = values.length_intptr;
|
||||
if (oldCapacity < newCapacity) {
|
||||
values = ExtractFixedArray(values, 0, oldCapacity, newCapacity);
|
||||
resolveElementContext.elements[PromiseAllResolveElementContextSlots::
|
||||
kPromiseAllResolveElementValuesSlot] =
|
||||
values;
|
||||
*valuesRef = ExtractFixedArray(values, 0, oldCapacity, newCapacity);
|
||||
}
|
||||
} else
|
||||
deferred {
|
||||
@ -287,13 +301,13 @@ Reject(Object) {
|
||||
// Perform ? Call(resultCapability.[[Resolve]], undefined,
|
||||
// « valuesArray »).
|
||||
|
||||
const values = UnsafeCast<FixedArray>(
|
||||
resolveElementContext
|
||||
.elements[PromiseAllResolveElementContextSlots::
|
||||
kPromiseAllResolveElementValuesSlot]);
|
||||
const arrayMap = UnsafeCast<Map>(
|
||||
nativeContext
|
||||
.elements[NativeContextSlot::JS_ARRAY_PACKED_ELEMENTS_MAP_INDEX]);
|
||||
const values: FixedArray = *ContextSlot(
|
||||
resolveElementContext,
|
||||
PromiseAllResolveElementContextSlots::
|
||||
kPromiseAllResolveElementValuesSlot);
|
||||
const arrayMap =
|
||||
*NativeContextSlot(
|
||||
nativeContext, ContextSlot::JS_ARRAY_PACKED_ELEMENTS_MAP_INDEX);
|
||||
const valuesArray = NewJSArray(arrayMap, values);
|
||||
Call(nativeContext, UnsafeCast<JSAny>(resolve), Undefined, valuesArray);
|
||||
}
|
||||
|
@ -5,11 +5,15 @@
|
||||
#include 'src/builtins/builtins-promise-gen.h'
|
||||
|
||||
namespace promise {
|
||||
extern enum PromiseAnyRejectElementContextSlots extends int31
|
||||
type PromiseAnyRejectElementContext extends FunctionContext;
|
||||
extern enum PromiseAnyRejectElementContextSlots extends intptr
|
||||
constexpr 'PromiseBuiltins::PromiseAnyRejectElementContextSlots' {
|
||||
kPromiseAnyRejectElementRemainingSlot,
|
||||
kPromiseAnyRejectElementCapabilitySlot,
|
||||
kPromiseAnyRejectElementErrorsSlot,
|
||||
kPromiseAnyRejectElementRemainingSlot:
|
||||
Slot<PromiseAnyRejectElementContext, Smi>,
|
||||
kPromiseAnyRejectElementCapabilitySlot:
|
||||
Slot<PromiseAnyRejectElementContext, PromiseCapability>,
|
||||
kPromiseAnyRejectElementErrorsSlot:
|
||||
Slot<PromiseAnyRejectElementContext, FixedArray>,
|
||||
kPromiseAnyRejectElementLength
|
||||
}
|
||||
|
||||
@ -27,30 +31,36 @@ extern operator '[]' macro LoadContextElement(
|
||||
// case to mark it's done). See Promise.all which uses the same approach.
|
||||
transitioning macro CreatePromiseAnyRejectElementContext(
|
||||
implicit context: Context)(
|
||||
capability: PromiseCapability, nativeContext: NativeContext): Context {
|
||||
const rejectContext = AllocateSyntheticFunctionContext(
|
||||
nativeContext,
|
||||
PromiseAnyRejectElementContextSlots::kPromiseAnyRejectElementLength);
|
||||
rejectContext.elements[PromiseAnyRejectElementContextSlots::
|
||||
kPromiseAnyRejectElementRemainingSlot] =
|
||||
SmiConstant(1);
|
||||
rejectContext.elements[PromiseAnyRejectElementContextSlots::
|
||||
kPromiseAnyRejectElementCapabilitySlot] =
|
||||
capability;
|
||||
rejectContext.elements[PromiseAnyRejectElementContextSlots::
|
||||
kPromiseAnyRejectElementErrorsSlot] =
|
||||
kEmptyFixedArray;
|
||||
capability: PromiseCapability,
|
||||
nativeContext: NativeContext): PromiseAnyRejectElementContext {
|
||||
const rejectContext = %RawDownCast<PromiseAnyRejectElementContext>(
|
||||
AllocateSyntheticFunctionContext(
|
||||
nativeContext,
|
||||
PromiseAnyRejectElementContextSlots::kPromiseAnyRejectElementLength));
|
||||
InitContextSlot(
|
||||
rejectContext,
|
||||
PromiseAnyRejectElementContextSlots::
|
||||
kPromiseAnyRejectElementRemainingSlot,
|
||||
1);
|
||||
InitContextSlot(
|
||||
rejectContext,
|
||||
PromiseAnyRejectElementContextSlots::
|
||||
kPromiseAnyRejectElementCapabilitySlot,
|
||||
capability);
|
||||
InitContextSlot(
|
||||
rejectContext,
|
||||
PromiseAnyRejectElementContextSlots::kPromiseAnyRejectElementErrorsSlot,
|
||||
kEmptyFixedArray);
|
||||
return rejectContext;
|
||||
}
|
||||
|
||||
macro CreatePromiseAnyRejectElementFunction(implicit context: Context)(
|
||||
rejectElementContext: Context, index: Smi,
|
||||
rejectElementContext: PromiseAnyRejectElementContext, index: Smi,
|
||||
nativeContext: NativeContext): JSFunction {
|
||||
assert(index > 0);
|
||||
assert(index < kPropertyArrayHashFieldMax);
|
||||
const map = UnsafeCast<Map>(
|
||||
nativeContext.elements
|
||||
[NativeContextSlot::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX]);
|
||||
const map = *ContextSlot(
|
||||
nativeContext, ContextSlot::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
|
||||
const rejectInfo = PromiseAnyRejectElementSharedFunConstant();
|
||||
const reject =
|
||||
AllocateFunctionWithMapAndContext(map, rejectInfo, rejectElementContext);
|
||||
@ -81,7 +91,9 @@ PromiseAnyRejectElementClosure(
|
||||
|
||||
assert(
|
||||
context.length ==
|
||||
PromiseAnyRejectElementContextSlots::kPromiseAnyRejectElementLength);
|
||||
SmiTag(
|
||||
PromiseAnyRejectElementContextSlots::kPromiseAnyRejectElementLength));
|
||||
const context = %RawDownCast<PromiseAnyRejectElementContext>(context);
|
||||
|
||||
// 4. Set alreadyCalled.[[Value]] to true.
|
||||
const nativeContext = LoadNativeContext(context);
|
||||
@ -94,32 +106,36 @@ PromiseAnyRejectElementClosure(
|
||||
const index = identityHash - 1;
|
||||
|
||||
// 6. Let errors be F.[[Errors]].
|
||||
let errors = UnsafeCast<FixedArray>(
|
||||
context.elements[PromiseAnyRejectElementContextSlots::
|
||||
kPromiseAnyRejectElementErrorsSlot]);
|
||||
let errors = *ContextSlot(
|
||||
context,
|
||||
PromiseAnyRejectElementContextSlots::kPromiseAnyRejectElementErrorsSlot);
|
||||
|
||||
// 7. Let promiseCapability be F.[[Capability]].
|
||||
|
||||
// 8. Let remainingElementsCount be F.[[RemainingElements]].
|
||||
let remainingElementsCount = UnsafeCast<Smi>(
|
||||
context.elements[PromiseAnyRejectElementContextSlots::
|
||||
kPromiseAnyRejectElementRemainingSlot]);
|
||||
let remainingElementsCount = *ContextSlot(
|
||||
context,
|
||||
PromiseAnyRejectElementContextSlots::
|
||||
kPromiseAnyRejectElementRemainingSlot);
|
||||
|
||||
// 9. Set errors[index] to x.
|
||||
const newCapacity = IntPtrMax(SmiUntag(remainingElementsCount), index + 1);
|
||||
if (newCapacity > errors.length_intptr) deferred {
|
||||
errors = ExtractFixedArray(errors, 0, errors.length_intptr, newCapacity);
|
||||
context.elements[PromiseAnyRejectElementContextSlots::
|
||||
kPromiseAnyRejectElementErrorsSlot] = errors;
|
||||
*ContextSlot(
|
||||
context,
|
||||
PromiseAnyRejectElementContextSlots::
|
||||
kPromiseAnyRejectElementErrorsSlot) = errors;
|
||||
}
|
||||
errors.objects[index] = value;
|
||||
|
||||
// 10. Set remainingElementsCount.[[Value]] to
|
||||
// remainingElementsCount.[[Value]] - 1.
|
||||
remainingElementsCount = remainingElementsCount - 1;
|
||||
context.elements[PromiseAnyRejectElementContextSlots::
|
||||
kPromiseAnyRejectElementRemainingSlot] =
|
||||
remainingElementsCount;
|
||||
*ContextSlot(
|
||||
context,
|
||||
PromiseAnyRejectElementContextSlots::
|
||||
kPromiseAnyRejectElementRemainingSlot) = remainingElementsCount;
|
||||
|
||||
// 11. If remainingElementsCount.[[Value]] is 0, then
|
||||
if (remainingElementsCount == 0) {
|
||||
@ -128,9 +144,10 @@ PromiseAnyRejectElementClosure(
|
||||
// b. Set error.[[AggregateErrors]] to errors.
|
||||
const error = ConstructAggregateError(errors);
|
||||
// c. Return ? Call(promiseCapability.[[Reject]], undefined, « error »).
|
||||
const capability = UnsafeCast<PromiseCapability>(
|
||||
context.elements[PromiseAnyRejectElementContextSlots::
|
||||
kPromiseAnyRejectElementCapabilitySlot]);
|
||||
const capability = *ContextSlot(
|
||||
context,
|
||||
PromiseAnyRejectElementContextSlots::
|
||||
kPromiseAnyRejectElementCapabilitySlot);
|
||||
Call(context, UnsafeCast<Callable>(capability.reject), Undefined, error);
|
||||
}
|
||||
|
||||
@ -158,8 +175,8 @@ Reject(Object) {
|
||||
let index: Smi = 1;
|
||||
|
||||
try {
|
||||
const fastIteratorResultMap = UnsafeCast<Map>(
|
||||
nativeContext.elements[NativeContextSlot::ITERATOR_RESULT_MAP_INDEX]);
|
||||
const fastIteratorResultMap = *NativeContextSlot(
|
||||
nativeContext, ContextSlot::ITERATOR_RESULT_MAP_INDEX);
|
||||
// 8. Repeat,
|
||||
while (true) {
|
||||
let nextValue: JSAny;
|
||||
@ -231,12 +248,14 @@ Reject(Object) {
|
||||
rejectElementContext, index, nativeContext);
|
||||
// q. Set remainingElementsCount.[[Value]] to
|
||||
// remainingElementsCount.[[Value]] + 1.
|
||||
const remainingElementsCount = UnsafeCast<Smi>(
|
||||
rejectElementContext
|
||||
.elements[PromiseAnyRejectElementContextSlots::
|
||||
kPromiseAnyRejectElementRemainingSlot]);
|
||||
rejectElementContext.elements[PromiseAnyRejectElementContextSlots::
|
||||
kPromiseAnyRejectElementRemainingSlot] =
|
||||
const remainingElementsCount = *ContextSlot(
|
||||
rejectElementContext,
|
||||
PromiseAnyRejectElementContextSlots::
|
||||
kPromiseAnyRejectElementRemainingSlot);
|
||||
*ContextSlot(
|
||||
rejectElementContext,
|
||||
PromiseAnyRejectElementContextSlots::
|
||||
kPromiseAnyRejectElementRemainingSlot) =
|
||||
remainingElementsCount + 1;
|
||||
|
||||
// r. Perform ? Invoke(nextPromise, "then", «
|
||||
@ -270,13 +289,10 @@ Reject(Object) {
|
||||
// i. Set iteratorRecord.[[Done]] to true.
|
||||
// ii. Set remainingElementsCount.[[Value]] to
|
||||
// remainingElementsCount.[[Value]] - 1.
|
||||
let remainingElementsCount = UnsafeCast<Smi>(
|
||||
rejectElementContext.elements[PromiseAnyRejectElementContextSlots::
|
||||
kPromiseAnyRejectElementRemainingSlot]);
|
||||
remainingElementsCount -= 1;
|
||||
rejectElementContext.elements[PromiseAnyRejectElementContextSlots::
|
||||
kPromiseAnyRejectElementRemainingSlot] =
|
||||
remainingElementsCount;
|
||||
const remainingElementsCount = -- *ContextSlot(
|
||||
rejectElementContext,
|
||||
PromiseAnyRejectElementContextSlots::
|
||||
kPromiseAnyRejectElementRemainingSlot);
|
||||
|
||||
// iii. If remainingElementsCount.[[Value]] is 0, then
|
||||
if (remainingElementsCount == 0) deferred {
|
||||
@ -285,10 +301,10 @@ Reject(Object) {
|
||||
|
||||
// We may already have elements in "errors" - this happens when the
|
||||
// Thenable calls the reject callback immediately.
|
||||
const errors = UnsafeCast<FixedArray>(
|
||||
rejectElementContext
|
||||
.elements[PromiseAnyRejectElementContextSlots::
|
||||
kPromiseAnyRejectElementErrorsSlot]);
|
||||
const errors: FixedArray = *ContextSlot(
|
||||
rejectElementContext,
|
||||
PromiseAnyRejectElementContextSlots::
|
||||
kPromiseAnyRejectElementErrorsSlot);
|
||||
|
||||
const error = ConstructAggregateError(errors);
|
||||
// 3. Return ThrowCompletion(error).
|
||||
|
@ -57,8 +57,7 @@ PromiseConstructor(
|
||||
ThrowTypeError(MessageTemplate::kResolverNotAFunction, executor);
|
||||
}
|
||||
|
||||
const promiseFun = UnsafeCast<JSFunction>(
|
||||
context.elements[NativeContextSlot::PROMISE_FUNCTION_INDEX]);
|
||||
const promiseFun = *NativeContextSlot(ContextSlot::PROMISE_FUNCTION_INDEX);
|
||||
|
||||
// Silently fail if the stack looks fishy.
|
||||
if (HasAccessCheckFailed(context, promiseFun, executor)) {
|
||||
|
@ -7,41 +7,48 @@
|
||||
|
||||
namespace promise {
|
||||
|
||||
// TODO(joshualitt): The below ContextSlots are only available on synthetic
|
||||
// contexts created by the promise pipeline for use in the promise pipeline.
|
||||
// However, with Torque we should type the context and its slots to prevent
|
||||
// accidentially using these slots on contexts which don't support them.
|
||||
const kPromiseBuiltinsValueSlot: constexpr ContextSlot
|
||||
generates 'PromiseBuiltins::kValueSlot';
|
||||
const kPromiseBuiltinsOnFinallySlot: constexpr ContextSlot
|
||||
generates 'PromiseBuiltins::kOnFinallySlot';
|
||||
const kPromiseBuiltinsConstructorSlot: constexpr ContextSlot
|
||||
generates 'PromiseBuiltins::kConstructorSlot';
|
||||
const kPromiseBuiltinsPromiseValueThunkOrReasonContextLength: constexpr int31
|
||||
generates 'PromiseBuiltins::kPromiseValueThunkOrReasonContextLength';
|
||||
const kPromiseBuiltinsPromiseFinallyContextLength: constexpr int31
|
||||
generates 'PromiseBuiltins::kPromiseFinallyContextLength';
|
||||
type PromiseValueThunkOrReasonContext extends FunctionContext;
|
||||
extern enum PromiseValueThunkOrReasonContextSlot extends intptr
|
||||
constexpr 'PromiseBuiltins::PromiseValueThunkOrReasonContextSlot' {
|
||||
kValueSlot: Slot<PromiseValueThunkOrReasonContext, JSAny>,
|
||||
kPromiseValueThunkOrReasonContextLength
|
||||
}
|
||||
|
||||
type PromiseFinallyContext extends FunctionContext;
|
||||
extern enum PromiseFinallyContextSlot extends intptr
|
||||
constexpr 'PromiseBuiltins::PromiseFinallyContextSlot' {
|
||||
kOnFinallySlot: Slot<PromiseFinallyContext, Callable>,
|
||||
kConstructorSlot: Slot<PromiseFinallyContext, Constructor>,
|
||||
kPromiseFinallyContextLength
|
||||
}
|
||||
|
||||
transitioning javascript builtin
|
||||
PromiseValueThunkFinally(
|
||||
js-implicit context: Context, receiver: JSAny)(): JSAny {
|
||||
return UnsafeCast<JSAny>(context.elements[kPromiseBuiltinsValueSlot]);
|
||||
const context = %RawDownCast<PromiseValueThunkOrReasonContext>(context);
|
||||
return *ContextSlot(
|
||||
context, PromiseValueThunkOrReasonContextSlot::kValueSlot);
|
||||
}
|
||||
|
||||
transitioning javascript builtin
|
||||
PromiseThrowerFinally(js-implicit context: Context, receiver: JSAny)(): never {
|
||||
const reason = UnsafeCast<JSAny>(context.elements[kPromiseBuiltinsValueSlot]);
|
||||
const context = %RawDownCast<PromiseValueThunkOrReasonContext>(context);
|
||||
const reason =
|
||||
*ContextSlot(context, PromiseValueThunkOrReasonContextSlot::kValueSlot);
|
||||
Throw(reason);
|
||||
}
|
||||
|
||||
macro CreateThrowerFunction(implicit context: Context)(
|
||||
nativeContext: NativeContext, reason: JSAny): JSFunction {
|
||||
const throwerContext = AllocateSyntheticFunctionContext(
|
||||
nativeContext, kPromiseBuiltinsPromiseValueThunkOrReasonContextLength);
|
||||
throwerContext.elements[kPromiseBuiltinsValueSlot] = reason;
|
||||
const map = UnsafeCast<Map>(
|
||||
nativeContext.elements
|
||||
[NativeContextSlot::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX]);
|
||||
const throwerContext = %RawDownCast<PromiseValueThunkOrReasonContext>(
|
||||
AllocateSyntheticFunctionContext(
|
||||
nativeContext,
|
||||
PromiseValueThunkOrReasonContextSlot::
|
||||
kPromiseValueThunkOrReasonContextLength));
|
||||
InitContextSlot(
|
||||
throwerContext, PromiseValueThunkOrReasonContextSlot::kValueSlot, reason);
|
||||
const map = *ContextSlot(
|
||||
nativeContext, ContextSlot::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
|
||||
const throwerInfo = PromiseThrowerFinallySharedFunConstant();
|
||||
return AllocateFunctionWithMapAndContext(map, throwerInfo, throwerContext);
|
||||
}
|
||||
@ -49,17 +56,18 @@ macro CreateThrowerFunction(implicit context: Context)(
|
||||
transitioning javascript builtin
|
||||
PromiseCatchFinally(
|
||||
js-implicit context: Context, receiver: JSAny)(reason: JSAny): JSAny {
|
||||
const context = %RawDownCast<PromiseFinallyContext>(context);
|
||||
// 1. Let onFinally be F.[[OnFinally]].
|
||||
// 2. Assert: IsCallable(onFinally) is true.
|
||||
const onFinally =
|
||||
UnsafeCast<Callable>(context.elements[kPromiseBuiltinsOnFinallySlot]);
|
||||
const onFinally: Callable =
|
||||
*ContextSlot(context, PromiseFinallyContextSlot::kOnFinallySlot);
|
||||
|
||||
// 3. Let result be ? Call(onFinally).
|
||||
const result = Call(context, onFinally, Undefined);
|
||||
|
||||
// 4. Let C be F.[[Constructor]].
|
||||
const constructor =
|
||||
UnsafeCast<JSFunction>(context.elements[kPromiseBuiltinsConstructorSlot]);
|
||||
const constructor: Constructor =
|
||||
*ContextSlot(context, PromiseFinallyContextSlot::kConstructorSlot);
|
||||
|
||||
// 5. Assert: IsConstructor(C) is true.
|
||||
assert(IsConstructor(constructor));
|
||||
@ -77,12 +85,16 @@ PromiseCatchFinally(
|
||||
|
||||
macro CreateValueThunkFunction(implicit context: Context)(
|
||||
nativeContext: NativeContext, value: JSAny): JSFunction {
|
||||
const valueThunkContext = AllocateSyntheticFunctionContext(
|
||||
nativeContext, kPromiseBuiltinsPromiseValueThunkOrReasonContextLength);
|
||||
valueThunkContext.elements[kPromiseBuiltinsValueSlot] = value;
|
||||
const map = UnsafeCast<Map>(
|
||||
nativeContext.elements
|
||||
[NativeContextSlot::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX]);
|
||||
const valueThunkContext = %RawDownCast<PromiseValueThunkOrReasonContext>(
|
||||
AllocateSyntheticFunctionContext(
|
||||
nativeContext,
|
||||
PromiseValueThunkOrReasonContextSlot::
|
||||
kPromiseValueThunkOrReasonContextLength));
|
||||
InitContextSlot(
|
||||
valueThunkContext, PromiseValueThunkOrReasonContextSlot::kValueSlot,
|
||||
value);
|
||||
const map = *ContextSlot(
|
||||
nativeContext, ContextSlot::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
|
||||
const valueThunkInfo = PromiseValueThunkFinallySharedFunConstant();
|
||||
return AllocateFunctionWithMapAndContext(
|
||||
map, valueThunkInfo, valueThunkContext);
|
||||
@ -91,17 +103,18 @@ macro CreateValueThunkFunction(implicit context: Context)(
|
||||
transitioning javascript builtin
|
||||
PromiseThenFinally(
|
||||
js-implicit context: Context, receiver: JSAny)(value: JSAny): JSAny {
|
||||
const context = %RawDownCast<PromiseFinallyContext>(context);
|
||||
// 1. Let onFinally be F.[[OnFinally]].
|
||||
// 2. Assert: IsCallable(onFinally) is true.
|
||||
const onFinally =
|
||||
UnsafeCast<Callable>(context.elements[kPromiseBuiltinsOnFinallySlot]);
|
||||
*ContextSlot(context, PromiseFinallyContextSlot::kOnFinallySlot);
|
||||
|
||||
// 3. Let result be ? Call(onFinally).
|
||||
const result = Call(context, onFinally, Undefined);
|
||||
|
||||
// 4. Let C be F.[[Constructor]].
|
||||
const constructor =
|
||||
UnsafeCast<JSFunction>(context.elements[kPromiseBuiltinsConstructorSlot]);
|
||||
*ContextSlot(context, PromiseFinallyContextSlot::kConstructorSlot);
|
||||
|
||||
// 5. Assert: IsConstructor(C) is true.
|
||||
assert(IsConstructor(constructor));
|
||||
@ -124,14 +137,17 @@ struct PromiseFinallyFunctions {
|
||||
|
||||
macro CreatePromiseFinallyFunctions(implicit context: Context)(
|
||||
nativeContext: NativeContext, onFinally: Callable,
|
||||
constructor: JSReceiver): PromiseFinallyFunctions {
|
||||
const promiseContext = AllocateSyntheticFunctionContext(
|
||||
nativeContext, kPromiseBuiltinsPromiseFinallyContextLength);
|
||||
promiseContext.elements[kPromiseBuiltinsOnFinallySlot] = onFinally;
|
||||
promiseContext.elements[kPromiseBuiltinsConstructorSlot] = constructor;
|
||||
const map = UnsafeCast<Map>(
|
||||
nativeContext.elements
|
||||
[NativeContextSlot::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX]);
|
||||
constructor: Constructor): PromiseFinallyFunctions {
|
||||
const promiseContext =
|
||||
%RawDownCast<PromiseFinallyContext>(AllocateSyntheticFunctionContext(
|
||||
nativeContext,
|
||||
PromiseFinallyContextSlot::kPromiseFinallyContextLength));
|
||||
InitContextSlot(
|
||||
promiseContext, PromiseFinallyContextSlot::kOnFinallySlot, onFinally);
|
||||
InitContextSlot(
|
||||
promiseContext, PromiseFinallyContextSlot::kConstructorSlot, constructor);
|
||||
const map = *ContextSlot(
|
||||
nativeContext, ContextSlot::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
|
||||
const thenFinallyInfo = PromiseThenFinallySharedFunConstant();
|
||||
const thenFinally =
|
||||
AllocateFunctionWithMapAndContext(map, thenFinallyInfo, promiseContext);
|
||||
@ -154,15 +170,15 @@ PromisePrototypeFinally(
|
||||
|
||||
// 3. Let C be ? SpeciesConstructor(promise, %Promise%).
|
||||
const nativeContext = LoadNativeContext(context);
|
||||
const promiseFun = UnsafeCast<Callable>(
|
||||
nativeContext.elements[NativeContextSlot::PROMISE_FUNCTION_INDEX]);
|
||||
const promiseFun = *NativeContextSlot(ContextSlot::PROMISE_FUNCTION_INDEX);
|
||||
|
||||
let constructor: JSReceiver = promiseFun;
|
||||
let constructor: Constructor = UnsafeCast<Constructor>(promiseFun);
|
||||
const receiverMap = jsReceiver.map;
|
||||
if (!IsJSPromiseMap(receiverMap) ||
|
||||
!IsPromiseSpeciesLookupChainIntact(nativeContext, receiverMap))
|
||||
deferred {
|
||||
constructor = SpeciesConstructor(jsReceiver, promiseFun);
|
||||
constructor =
|
||||
UnsafeCast<Constructor>(SpeciesConstructor(jsReceiver, promiseFun));
|
||||
}
|
||||
|
||||
// 4. Assert: IsConstructor(C) is true.
|
||||
|
@ -22,8 +22,7 @@ PromiseResolveThenableJob(implicit context: Context)(
|
||||
// We take the generic (slow-)path if a PromiseHook is enabled or the
|
||||
// debugger is active, to make sure we expose spec compliant behavior.
|
||||
const nativeContext = LoadNativeContext(context);
|
||||
const promiseThen =
|
||||
nativeContext.elements[NativeContextSlot::PROMISE_THEN_INDEX];
|
||||
const promiseThen = *NativeContextSlot(ContextSlot::PROMISE_THEN_INDEX);
|
||||
const thenableMap = thenable.map;
|
||||
if (TaggedEqual(then, promiseThen) && IsJSPromiseMap(thenableMap) &&
|
||||
!IsPromiseHookEnabledOrDebugIsActiveOrHasAsyncEventDelegate() &&
|
||||
|
@ -38,9 +38,7 @@ macro PromiseInit(promise: JSPromise): void {
|
||||
}
|
||||
|
||||
macro InnerNewJSPromise(implicit context: Context)(): JSPromise {
|
||||
const nativeContext = LoadNativeContext(context);
|
||||
const promiseFun = UnsafeCast<JSFunction>(
|
||||
nativeContext.elements[NativeContextSlot::PROMISE_FUNCTION_INDEX]);
|
||||
const promiseFun = *NativeContextSlot(ContextSlot::PROMISE_FUNCTION_INDEX);
|
||||
assert(IsFunctionWithPrototypeSlotMap(promiseFun.map));
|
||||
const promiseMap = UnsafeCast<Map>(promiseFun.prototype_or_initial_map);
|
||||
const promiseHeapObject = promise_internal::AllocateJSPromise(context);
|
||||
@ -70,8 +68,8 @@ macro NewPromiseFulfillReactionJobTask(implicit context: Context)(
|
||||
handler,
|
||||
promise_or_capability: promiseOrCapability,
|
||||
continuation_preserved_embedder_data:
|
||||
nativeContext.elements
|
||||
[NativeContextSlot::CONTINUATION_PRESERVED_EMBEDDER_DATA_INDEX]
|
||||
*ContextSlot(
|
||||
nativeContext, ContextSlot::CONTINUATION_PRESERVED_EMBEDDER_DATA_INDEX)
|
||||
};
|
||||
}
|
||||
|
||||
@ -87,8 +85,8 @@ macro NewPromiseRejectReactionJobTask(implicit context: Context)(
|
||||
handler,
|
||||
promise_or_capability: promiseOrCapability,
|
||||
continuation_preserved_embedder_data:
|
||||
nativeContext.elements
|
||||
[NativeContextSlot::CONTINUATION_PRESERVED_EMBEDDER_DATA_INDEX]
|
||||
*ContextSlot(
|
||||
nativeContext, ContextSlot::CONTINUATION_PRESERVED_EMBEDDER_DATA_INDEX)
|
||||
};
|
||||
}
|
||||
|
||||
@ -146,8 +144,8 @@ macro NewPromiseReaction(implicit context: Context)(
|
||||
fulfill_handler: fulfillHandler,
|
||||
promise_or_capability: promiseOrCapability,
|
||||
continuation_preserved_embedder_data:
|
||||
nativeContext.elements
|
||||
[NativeContextSlot::CONTINUATION_PRESERVED_EMBEDDER_DATA_INDEX]
|
||||
*ContextSlot(
|
||||
nativeContext, ContextSlot::CONTINUATION_PRESERVED_EMBEDDER_DATA_INDEX)
|
||||
};
|
||||
}
|
||||
|
||||
@ -210,8 +208,8 @@ macro InvokeThen<F: type>(implicit context: Context)(
|
||||
if (!Is<Smi>(receiver) &&
|
||||
IsPromiseThenLookupChainIntact(
|
||||
nativeContext, UnsafeCast<HeapObject>(receiver).map)) {
|
||||
const then = UnsafeCast<JSAny>(
|
||||
nativeContext.elements[NativeContextSlot::PROMISE_THEN_INDEX]);
|
||||
const then =
|
||||
*NativeContextSlot(nativeContext, ContextSlot::PROMISE_THEN_INDEX);
|
||||
return callFunctor.Call(nativeContext, then, receiver, arg1, arg2);
|
||||
} else
|
||||
deferred {
|
||||
|
@ -50,8 +50,8 @@ PromiseRace(
|
||||
|
||||
// Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability).
|
||||
try {
|
||||
const fastIteratorResultMap = UnsafeCast<Map>(
|
||||
nativeContext.elements[NativeContextSlot::ITERATOR_RESULT_MAP_INDEX]);
|
||||
const fastIteratorResultMap = *NativeContextSlot(
|
||||
nativeContext, ContextSlot::ITERATOR_RESULT_MAP_INDEX);
|
||||
while (true) {
|
||||
let nextValue: JSAny;
|
||||
try {
|
||||
|
@ -30,8 +30,7 @@ transitioning builtin
|
||||
PromiseResolve(implicit context: Context)(
|
||||
constructor: JSReceiver, value: JSAny): JSAny {
|
||||
const nativeContext = LoadNativeContext(context);
|
||||
const promiseFun =
|
||||
nativeContext.elements[NativeContextSlot::PROMISE_FUNCTION_INDEX];
|
||||
const promiseFun = *NativeContextSlot(ContextSlot::PROMISE_FUNCTION_INDEX);
|
||||
try {
|
||||
// Check if {value} is a JSPromise.
|
||||
const value = Cast<JSPromise>(value) otherwise NeedToAllocate;
|
||||
@ -41,7 +40,9 @@ PromiseResolve(implicit context: Context)(
|
||||
// intact, as that guards the lookup path for "constructor" on
|
||||
// JSPromise instances which have the (initial) Promise.prototype.
|
||||
const promisePrototype =
|
||||
nativeContext.elements[NativeContextSlot::PROMISE_PROTOTYPE_INDEX];
|
||||
*NativeContextSlot(ContextSlot::PROMISE_PROTOTYPE_INDEX);
|
||||
// Check that Torque load elimination works.
|
||||
static_assert(nativeContext == LoadNativeContext(context));
|
||||
if (value.map.prototype != promisePrototype) {
|
||||
goto SlowConstructor;
|
||||
}
|
||||
@ -138,8 +139,7 @@ ResolvePromise(implicit context: Context)(
|
||||
assert(IsJSReceiverMap(resolutionMap));
|
||||
assert(!IsPromiseThenProtectorCellInvalid());
|
||||
if (resolutionMap ==
|
||||
nativeContext
|
||||
.elements[NativeContextSlot::ITERATOR_RESULT_MAP_INDEX]) {
|
||||
*NativeContextSlot(ContextSlot::ITERATOR_RESULT_MAP_INDEX)) {
|
||||
return FulfillPromise(promise, resolution);
|
||||
} else {
|
||||
goto Slow;
|
||||
@ -147,10 +147,12 @@ ResolvePromise(implicit context: Context)(
|
||||
}
|
||||
|
||||
const promisePrototype =
|
||||
nativeContext.elements[NativeContextSlot::PROMISE_PROTOTYPE_INDEX];
|
||||
*NativeContextSlot(ContextSlot::PROMISE_PROTOTYPE_INDEX);
|
||||
if (resolutionMap.prototype == promisePrototype) {
|
||||
// The {resolution} is a native Promise in this case.
|
||||
then = nativeContext.elements[NativeContextSlot::PROMISE_THEN_INDEX];
|
||||
then = *NativeContextSlot(ContextSlot::PROMISE_THEN_INDEX);
|
||||
// Check that Torque load elimination works.
|
||||
static_assert(nativeContext == LoadNativeContext(context));
|
||||
goto Enqueue;
|
||||
}
|
||||
goto Slow;
|
||||
|
@ -10,7 +10,7 @@ macro
|
||||
IsPromiseSpeciesLookupChainIntact(
|
||||
nativeContext: NativeContext, promiseMap: Map): bool {
|
||||
const promisePrototype =
|
||||
nativeContext.elements[NativeContextSlot::PROMISE_PROTOTYPE_INDEX];
|
||||
*NativeContextSlot(nativeContext, ContextSlot::PROMISE_PROTOTYPE_INDEX);
|
||||
if (IsForceSlowPath()) return false;
|
||||
if (promiseMap.prototype != promisePrototype) return false;
|
||||
return !IsPromiseSpeciesProtectorCellInvalid();
|
||||
@ -27,8 +27,7 @@ PromisePrototypeThen(js-implicit context: NativeContext, receiver: JSAny)(
|
||||
receiver);
|
||||
|
||||
// 3. Let C be ? SpeciesConstructor(promise, %Promise%).
|
||||
const promiseFun = UnsafeCast<JSFunction>(
|
||||
context.elements[NativeContextSlot::PROMISE_FUNCTION_INDEX]);
|
||||
const promiseFun = *NativeContextSlot(ContextSlot::PROMISE_FUNCTION_INDEX);
|
||||
|
||||
// 4. Let resultCapability be ? NewPromiseCapability(C).
|
||||
let resultPromiseOrCapability: JSPromise|PromiseCapability;
|
||||
|
@ -9,28 +9,34 @@ namespace proxy {
|
||||
// Proxy Revocation Functions
|
||||
// https://tc39.github.io/ecma262/#sec-proxy-revocation-functions
|
||||
transitioning javascript builtin
|
||||
ProxyRevoke(js-implicit context: NativeContext)(): Undefined {
|
||||
ProxyRevoke(js-implicit context: Context)(): Undefined {
|
||||
const context = %RawDownCast<ProxyRevokeFunctionContext>(context);
|
||||
|
||||
// 1. Let p be F.[[RevocableProxy]].
|
||||
const proxyObject: Object = context.elements[PROXY_SLOT];
|
||||
const proxySlot:&(JSProxy | Null) =
|
||||
ContextSlot(context, ProxyRevokeFunctionContextSlot::kProxySlot);
|
||||
|
||||
// 2. If p is null, return undefined
|
||||
if (proxyObject == Null) {
|
||||
return Undefined;
|
||||
typeswitch (*proxySlot) {
|
||||
case (Null): {
|
||||
// 2. If p is null, return undefined
|
||||
return Undefined;
|
||||
}
|
||||
case (proxy: JSProxy): {
|
||||
// 3. Set F.[[RevocableProxy]] to null.
|
||||
*proxySlot = Null;
|
||||
|
||||
// 4. Assert: p is a Proxy object.
|
||||
assert(Is<JSProxy>(proxy));
|
||||
|
||||
// 5. Set p.[[ProxyTarget]] to null.
|
||||
proxy.target = Null;
|
||||
|
||||
// 6. Set p.[[ProxyHandler]] to null.
|
||||
proxy.handler = Null;
|
||||
|
||||
// 7. Return undefined.
|
||||
return Undefined;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Set F.[[RevocableProxy]] to null.
|
||||
context.elements[PROXY_SLOT] = Null;
|
||||
|
||||
// 4. Assert: p is a Proxy object.
|
||||
const proxy: JSProxy = UnsafeCast<JSProxy>(proxyObject);
|
||||
|
||||
// 5. Set p.[[ProxyTarget]] to null.
|
||||
proxy.target = Null;
|
||||
|
||||
// 6. Set p.[[ProxyHandler]] to null.
|
||||
proxy.handler = Null;
|
||||
|
||||
// 7. Return undefined.
|
||||
return Undefined;
|
||||
}
|
||||
}
|
||||
|
@ -23,4 +23,11 @@ const kProxyGet: constexpr int31
|
||||
generates 'JSProxy::AccessKind::kGet';
|
||||
const kProxySet: constexpr int31
|
||||
generates 'JSProxy::AccessKind::kSet';
|
||||
|
||||
type ProxyRevokeFunctionContext extends FunctionContext;
|
||||
extern enum ProxyRevokeFunctionContextSlot extends intptr
|
||||
constexpr 'ProxiesCodeStubAssembler::ProxyRevokeFunctionContextSlot' {
|
||||
kProxySlot: Slot<ProxyRevokeFunctionContext, JSProxy|Null>,
|
||||
kProxyContextLength
|
||||
}
|
||||
}
|
||||
|
@ -155,10 +155,8 @@ transitioning macro RegExpPrototypeExecBody(implicit context: Context)(
|
||||
regexp, matchIndices, string, lastIndex);
|
||||
}
|
||||
|
||||
macro LoadRegExpFunction(implicit context: Context)(
|
||||
nativeContext: NativeContext): JSFunction {
|
||||
return UnsafeCast<JSFunction>(
|
||||
nativeContext.elements[NativeContextSlot::REGEXP_FUNCTION_INDEX]);
|
||||
macro LoadRegExpFunction(nativeContext: NativeContext): JSFunction {
|
||||
return *NativeContextSlot(nativeContext, ContextSlot::REGEXP_FUNCTION_INDEX);
|
||||
}
|
||||
|
||||
// Note this doesn't guarantee const-ness of object properties, just
|
||||
|
19
src/builtins/torque-csa-header-includes.h
Normal file
19
src/builtins/torque-csa-header-includes.h
Normal file
@ -0,0 +1,19 @@
|
||||
// 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.
|
||||
|
||||
#ifndef V8_BUILTINS_TORQUE_CSA_HEADER_INCLUDES_H_
|
||||
#define V8_BUILTINS_TORQUE_CSA_HEADER_INCLUDES_H_
|
||||
|
||||
// This file is included by Torque-generated CSA headers and contains
|
||||
// includes necessary for these headers.
|
||||
|
||||
#include "src/builtins/builtins-promise.h"
|
||||
#include "src/builtins/builtins-proxy-gen.h"
|
||||
#include "src/codegen/code-stub-assembler.h"
|
||||
#include "src/compiler/code-assembler.h"
|
||||
#include "src/utils/utils.h"
|
||||
#include "torque-generated/csa-types-tq.h"
|
||||
#include "torque-generated/field-offsets-tq.h"
|
||||
|
||||
#endif // V8_BUILTINS_TORQUE_CSA_HEADER_INCLUDES_H_
|
@ -25,6 +25,11 @@ macro NewReference<T: type>(object: HeapObject, offset: intptr):&T {
|
||||
return %RawDownCast<&T>(
|
||||
Reference<T>{object: object, offset: offset, unsafeMarker: Unsafe {}});
|
||||
}
|
||||
macro ReferenceCast<T: type, U: type>(ref:&U):&T {
|
||||
const ref = NewReference<T>(ref.object, ref.offset);
|
||||
UnsafeCast<T>(*ref);
|
||||
return ref;
|
||||
}
|
||||
} // namespace unsafe
|
||||
|
||||
struct Slice<T: type> {
|
||||
|
@ -13037,34 +13037,6 @@ void CodeStubAssembler::PerformStackCheck(TNode<Context> context) {
|
||||
BIND(&ok);
|
||||
}
|
||||
|
||||
TNode<Context> CodeStubAssembler::AllocateSyntheticFunctionContext(
|
||||
TNode<NativeContext> native_context, int slots) {
|
||||
DCHECK_GE(slots, Context::MIN_CONTEXT_SLOTS);
|
||||
TNode<HeapObject> context_heap_object =
|
||||
AllocateInNewSpace(FixedArray::SizeFor(slots));
|
||||
InitializeSyntheticFunctionContext(native_context, context_heap_object,
|
||||
slots);
|
||||
return CAST(context_heap_object);
|
||||
}
|
||||
|
||||
void CodeStubAssembler::InitializeSyntheticFunctionContext(
|
||||
TNode<NativeContext> native_context, TNode<HeapObject> context_heap_object,
|
||||
int slots) {
|
||||
DCHECK_GE(slots, Context::MIN_CONTEXT_SLOTS);
|
||||
TNode<Map> map = CAST(
|
||||
LoadContextElement(native_context, Context::FUNCTION_CONTEXT_MAP_INDEX));
|
||||
StoreMapNoWriteBarrier(context_heap_object, map);
|
||||
StoreObjectFieldNoWriteBarrier(context_heap_object, FixedArray::kLengthOffset,
|
||||
SmiConstant(slots));
|
||||
|
||||
TNode<Context> context = CAST(context_heap_object);
|
||||
const TNode<Object> empty_scope_info = LoadRoot(RootIndex::kEmptyScopeInfo);
|
||||
StoreContextElementNoWriteBarrier(context, Context::SCOPE_INFO_INDEX,
|
||||
empty_scope_info);
|
||||
StoreContextElementNoWriteBarrier(context, Context::PREVIOUS_INDEX,
|
||||
UndefinedConstant());
|
||||
}
|
||||
|
||||
TNode<Object> CodeStubAssembler::CallApiCallback(
|
||||
TNode<Object> context, TNode<RawPtrT> callback, TNode<IntPtrT> argc,
|
||||
TNode<Object> data, TNode<Object> holder, TNode<Object> receiver) {
|
||||
|
@ -128,6 +128,7 @@ enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
|
||||
V(default_string, default_string, DefaultString) \
|
||||
V(EmptyByteArray, empty_byte_array, EmptyByteArray) \
|
||||
V(EmptyFixedArray, empty_fixed_array, EmptyFixedArray) \
|
||||
V(EmptyScopeInfo, empty_scope_info, EmptyScopeInfo) \
|
||||
V(EmptyPropertyDictionary, empty_property_dictionary, \
|
||||
EmptyPropertyDictionary) \
|
||||
V(EmptySlowElementDictionary, empty_slow_element_dictionary, \
|
||||
@ -3708,12 +3709,6 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
|
||||
TNode<IntPtrT> TryToIntptr(SloppyTNode<Object> key, Label* if_not_intptr,
|
||||
TVariable<Int32T>* var_instance_type = nullptr);
|
||||
|
||||
TNode<Context> AllocateSyntheticFunctionContext(
|
||||
TNode<NativeContext> native_context, int slots);
|
||||
void InitializeSyntheticFunctionContext(TNode<NativeContext> native_context,
|
||||
TNode<HeapObject> context_heap_object,
|
||||
int slots);
|
||||
|
||||
TNode<JSArray> ArrayCreate(TNode<Context> context, TNode<Number> length);
|
||||
|
||||
// Allocate a clone of a mutable primitive, if {object} is a mutable
|
||||
|
@ -969,8 +969,8 @@ struct StackPointerGreaterThanOperator : public Operator1<StackCheckKind> {
|
||||
|
||||
struct CommentOperator : public Operator1<const char*> {
|
||||
explicit CommentOperator(const char* msg)
|
||||
: Operator1(IrOpcode::kComment, Operator::kNoThrow, "Comment", 0, 1, 1, 0,
|
||||
1, 0, msg) {}
|
||||
: Operator1(IrOpcode::kComment, Operator::kNoThrow | Operator::kNoWrite,
|
||||
"Comment", 0, 1, 1, 0, 1, 0, msg) {}
|
||||
};
|
||||
|
||||
MachineOperatorBuilder::MachineOperatorBuilder(
|
||||
|
@ -150,7 +150,7 @@ macro NewParameterMapIterator(
|
||||
context: Context, formalParameterCount: intptr,
|
||||
mappedCount: intptr): ParameterMapIterator {
|
||||
const flags = context.GetScopeInfo().flags;
|
||||
let contextHeaderSize: intptr = MIN_CONTEXT_SLOTS;
|
||||
let contextHeaderSize: intptr = ContextSlot::MIN_CONTEXT_SLOTS;
|
||||
if (flags.has_context_extension_slot) ++contextHeaderSize;
|
||||
// Copy the parameter slots and the holes in the arguments.
|
||||
// We need to fill in mapped_count slots. They index the context,
|
||||
|
@ -5,7 +5,7 @@
|
||||
@abstract
|
||||
extern class Context extends HeapObject {
|
||||
macro GetScopeInfo(): ScopeInfo {
|
||||
return UnsafeCast<ScopeInfo>(this.elements[0]);
|
||||
return *ContextSlot(this, ContextSlot::SCOPE_INFO_INDEX);
|
||||
}
|
||||
const length: Smi;
|
||||
elements[length]: Object;
|
||||
@ -17,56 +17,116 @@ extern class CatchContext extends Context generates 'TNode<Context>';
|
||||
extern class DebugEvaluateContext extends Context
|
||||
generates 'TNode<Context>';
|
||||
extern class EvalContext extends Context generates 'TNode<Context>';
|
||||
extern class FunctionContext extends Context generates 'TNode<Context>';
|
||||
extern class ModuleContext extends Context generates 'TNode<Context>';
|
||||
extern class NativeContext extends Context;
|
||||
extern class ScriptContext extends Context generates 'TNode<Context>';
|
||||
extern class WithContext extends Context generates 'TNode<Context>';
|
||||
|
||||
const MIN_CONTEXT_SLOTS: constexpr int31
|
||||
generates 'Context::MIN_CONTEXT_SLOTS';
|
||||
extern class FunctionContext extends Context generates 'TNode<Context>';
|
||||
|
||||
extern enum NativeContextSlot extends intptr constexpr 'Context::Field' {
|
||||
AGGREGATE_ERROR_FUNCTION_INDEX,
|
||||
ARRAY_BUFFER_FUN_INDEX,
|
||||
ARRAY_BUFFER_NOINIT_FUN_INDEX,
|
||||
ARRAY_BUFFER_MAP_INDEX,
|
||||
ARRAY_FUNCTION_INDEX,
|
||||
ARRAY_JOIN_STACK_INDEX,
|
||||
OBJECT_FUNCTION_INDEX,
|
||||
ITERATOR_RESULT_MAP_INDEX,
|
||||
JS_ARRAY_PACKED_ELEMENTS_MAP_INDEX,
|
||||
JS_ARRAY_PACKED_SMI_ELEMENTS_MAP_INDEX,
|
||||
MATH_RANDOM_CACHE_INDEX,
|
||||
MATH_RANDOM_INDEX_INDEX,
|
||||
NUMBER_FUNCTION_INDEX,
|
||||
PROXY_REVOCABLE_RESULT_MAP_INDEX,
|
||||
REFLECT_APPLY_INDEX,
|
||||
REGEXP_FUNCTION_INDEX,
|
||||
REGEXP_LAST_MATCH_INFO_INDEX,
|
||||
INITIAL_STRING_ITERATOR_MAP_INDEX,
|
||||
INITIAL_ARRAY_ITERATOR_MAP_INDEX,
|
||||
SLOW_OBJECT_WITH_NULL_PROTOTYPE_MAP,
|
||||
STRICT_ARGUMENTS_MAP_INDEX,
|
||||
SLOPPY_ARGUMENTS_MAP_INDEX,
|
||||
FAST_ALIASED_ARGUMENTS_MAP_INDEX,
|
||||
const kInitialContextSlotValue: Smi = 0;
|
||||
|
||||
PROMISE_FUNCTION_INDEX,
|
||||
PROMISE_THEN_INDEX,
|
||||
PROMISE_PROTOTYPE_INDEX,
|
||||
STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX,
|
||||
|
||||
CONTINUATION_PRESERVED_EMBEDDER_DATA_INDEX,
|
||||
|
||||
BOUND_FUNCTION_WITH_CONSTRUCTOR_MAP_INDEX,
|
||||
BOUND_FUNCTION_WITHOUT_CONSTRUCTOR_MAP_INDEX,
|
||||
...
|
||||
@export
|
||||
macro AllocateSyntheticFunctionContext(
|
||||
nativeContext: NativeContext, slots: constexpr int31): FunctionContext {
|
||||
return AllocateSyntheticFunctionContext(
|
||||
nativeContext, Convert<intptr>(slots));
|
||||
}
|
||||
|
||||
type ContextSlot extends intptr
|
||||
generates 'TNode<IntPtrT>' constexpr 'int32_t';
|
||||
const PROXY_SLOT: constexpr ContextSlot
|
||||
generates 'Context::MIN_CONTEXT_SLOTS';
|
||||
macro AllocateSyntheticFunctionContext(
|
||||
nativeContext: NativeContext, slots: intptr): FunctionContext {
|
||||
static_assert(slots >= ContextSlot::MIN_CONTEXT_SLOTS);
|
||||
const map =
|
||||
*ContextSlot(nativeContext, ContextSlot::FUNCTION_CONTEXT_MAP_INDEX);
|
||||
const result = new FunctionContext{
|
||||
map,
|
||||
length: Convert<Smi>(slots),
|
||||
elements: ...ConstantIterator<Smi>(kInitialContextSlotValue)
|
||||
};
|
||||
InitContextSlot(result, ContextSlot::SCOPE_INFO_INDEX, kEmptyScopeInfo);
|
||||
InitContextSlot(result, ContextSlot::PREVIOUS_INDEX, Undefined);
|
||||
return result;
|
||||
}
|
||||
|
||||
extern class NativeContext extends Context;
|
||||
|
||||
type Slot<Container : type extends Context, T : type extends Object> extends
|
||||
intptr;
|
||||
|
||||
// We cannot use ContextSlot() for initialization since that one asserts the
|
||||
// slot has the right type already.
|
||||
macro InitContextSlot<
|
||||
ArgumentContext: type, AnnotatedContext: type, T: type, U: type>(
|
||||
context: ArgumentContext, index: Slot<AnnotatedContext, T>, value: U) {
|
||||
// Make sure the arguments have the right type.
|
||||
const context: AnnotatedContext = context;
|
||||
const value: T = value;
|
||||
assert(TaggedEqual(context.elements[index], kInitialContextSlotValue));
|
||||
context.elements[index] = value;
|
||||
}
|
||||
|
||||
macro ContextSlot<ArgumentContext: type, AnnotatedContext: type, T: type>(
|
||||
context: ArgumentContext, index: Slot<AnnotatedContext, T>):&T {
|
||||
const context: AnnotatedContext = context;
|
||||
return torque_internal::unsafe::ReferenceCast<T>(&context.elements[index]);
|
||||
}
|
||||
|
||||
macro NativeContextSlot<T: type>(
|
||||
context: NativeContext, index: Slot<NativeContext, T>):&T {
|
||||
return ContextSlot(context, index);
|
||||
}
|
||||
macro NativeContextSlot<T: type>(
|
||||
context: Context, index: Slot<NativeContext, T>):&T {
|
||||
return ContextSlot(LoadNativeContext(context), index);
|
||||
}
|
||||
macro NativeContextSlot<C: type, T: type>(implicit context: C)(
|
||||
index: Slot<NativeContext, T>):&T {
|
||||
return NativeContextSlot(context, index);
|
||||
}
|
||||
|
||||
extern enum ContextSlot extends intptr constexpr 'Context::Field' {
|
||||
SCOPE_INFO_INDEX: Slot<Context, ScopeInfo>,
|
||||
// Zero is used for the NativeContext, Undefined is used for synthetic
|
||||
// function contexts.
|
||||
PREVIOUS_INDEX: Slot<Context, Context|Zero|Undefined>,
|
||||
|
||||
AGGREGATE_ERROR_FUNCTION_INDEX: Slot<NativeContext, JSFunction>,
|
||||
ARRAY_BUFFER_FUN_INDEX: Slot<NativeContext, Constructor>,
|
||||
ARRAY_BUFFER_NOINIT_FUN_INDEX: Slot<NativeContext, JSFunction>,
|
||||
ARRAY_BUFFER_MAP_INDEX: Slot<NativeContext, Map>,
|
||||
ARRAY_FUNCTION_INDEX: Slot<NativeContext, JSFunction>,
|
||||
ARRAY_JOIN_STACK_INDEX: Slot<NativeContext, Undefined|FixedArray>,
|
||||
OBJECT_FUNCTION_INDEX: Slot<NativeContext, JSFunction>,
|
||||
ITERATOR_RESULT_MAP_INDEX: Slot<NativeContext, Map>,
|
||||
JS_ARRAY_PACKED_ELEMENTS_MAP_INDEX: Slot<NativeContext, Map>,
|
||||
JS_ARRAY_PACKED_SMI_ELEMENTS_MAP_INDEX: Slot<NativeContext, Map>,
|
||||
MATH_RANDOM_CACHE_INDEX: Slot<NativeContext, FixedDoubleArray>,
|
||||
MATH_RANDOM_INDEX_INDEX: Slot<NativeContext, Smi>,
|
||||
NUMBER_FUNCTION_INDEX: Slot<NativeContext, JSFunction>,
|
||||
PROXY_REVOCABLE_RESULT_MAP_INDEX: Slot<NativeContext, Map>,
|
||||
REFLECT_APPLY_INDEX: Slot<NativeContext, Callable>,
|
||||
REGEXP_FUNCTION_INDEX: Slot<NativeContext, JSFunction>,
|
||||
REGEXP_LAST_MATCH_INFO_INDEX: Slot<NativeContext, RegExpMatchInfo>,
|
||||
INITIAL_STRING_ITERATOR_MAP_INDEX: Slot<NativeContext, Map>,
|
||||
INITIAL_ARRAY_ITERATOR_MAP_INDEX: Slot<NativeContext, Map>,
|
||||
SLOW_OBJECT_WITH_NULL_PROTOTYPE_MAP: Slot<NativeContext, Map>,
|
||||
STRICT_ARGUMENTS_MAP_INDEX: Slot<NativeContext, Map>,
|
||||
SLOPPY_ARGUMENTS_MAP_INDEX: Slot<NativeContext, Map>,
|
||||
FAST_ALIASED_ARGUMENTS_MAP_INDEX: Slot<NativeContext, Map>,
|
||||
FUNCTION_CONTEXT_MAP_INDEX: Slot<NativeContext, Map>,
|
||||
|
||||
PROMISE_FUNCTION_INDEX: Slot<NativeContext, JSFunction>,
|
||||
PROMISE_THEN_INDEX: Slot<NativeContext, JSFunction>,
|
||||
PROMISE_PROTOTYPE_INDEX: Slot<NativeContext, JSObject>,
|
||||
STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX: Slot<NativeContext, Map>,
|
||||
|
||||
CONTINUATION_PRESERVED_EMBEDDER_DATA_INDEX: Slot<NativeContext, HeapObject>,
|
||||
|
||||
BOUND_FUNCTION_WITH_CONSTRUCTOR_MAP_INDEX: Slot<NativeContext, Map>,
|
||||
BOUND_FUNCTION_WITHOUT_CONSTRUCTOR_MAP_INDEX: Slot<NativeContext, Map>,
|
||||
|
||||
MIN_CONTEXT_SLOTS,
|
||||
...
|
||||
}
|
||||
|
||||
@export
|
||||
macro LoadContextElement(c: Context, i: intptr): Object {
|
||||
|
@ -16,8 +16,7 @@ extern class JSArrayIterator extends JSObject {
|
||||
macro CreateArrayIterator(implicit context: NativeContext)(
|
||||
array: JSReceiver, kind: constexpr IterationKind): JSArrayIterator {
|
||||
return new JSArrayIterator{
|
||||
map: UnsafeCast<Map>(
|
||||
context.elements[NativeContextSlot::INITIAL_ARRAY_ITERATOR_MAP_INDEX]),
|
||||
map: *NativeContextSlot(ContextSlot::INITIAL_ARRAY_ITERATOR_MAP_INDEX),
|
||||
properties_or_hash: kEmptyFixedArray,
|
||||
elements: kEmptyFixedArray,
|
||||
iterated_object: array,
|
||||
|
@ -4,6 +4,9 @@
|
||||
|
||||
extern class ScopeInfo extends FixedArray;
|
||||
|
||||
extern macro EmptyScopeInfoConstant(): ScopeInfo;
|
||||
const kEmptyScopeInfo: ScopeInfo = EmptyScopeInfoConstant();
|
||||
|
||||
const kScopeInfoFlagsIndex:
|
||||
constexpr int32 generates 'ScopeInfo::Fields::kFlags';
|
||||
|
||||
|
@ -374,8 +374,10 @@ Callable* DeclarationVisitor::Specialize(
|
||||
}
|
||||
|
||||
void PredeclarationVisitor::ResolvePredeclarations() {
|
||||
for (auto& p : GlobalContext::AllDeclarables()) {
|
||||
if (const TypeAlias* alias = TypeAlias::DynamicCast(p.get())) {
|
||||
const auto& all_declarables = GlobalContext::AllDeclarables();
|
||||
for (size_t i = 0; i < all_declarables.size(); ++i) {
|
||||
Declarable* declarable = all_declarables[i].get();
|
||||
if (const TypeAlias* alias = TypeAlias::DynamicCast(declarable)) {
|
||||
CurrentScope::Scope scope_activator(alias->ParentScope());
|
||||
CurrentSourcePosition::Scope position_activator(alias->Position());
|
||||
alias->Resolve();
|
||||
|
@ -81,12 +81,7 @@ void ImplementationVisitor::BeginCSAFiles() {
|
||||
UnderlinifyPath(SourceFileMap::PathFromV8Root(file)) + "_H_";
|
||||
header << "#ifndef " << headerDefine << "\n";
|
||||
header << "#define " << headerDefine << "\n\n";
|
||||
header << "#include \"src/builtins/builtins-promise.h\"\n";
|
||||
header << "#include \"src/compiler/code-assembler.h\"\n";
|
||||
header << "#include \"src/codegen/code-stub-assembler.h\"\n";
|
||||
header << "#include \"src/utils/utils.h\"\n";
|
||||
header << "#include \"torque-generated/field-offsets-tq.h\"\n";
|
||||
header << "#include \"torque-generated/csa-types-tq.h\"\n";
|
||||
header << "#include \"src/builtins/torque-csa-header-includes.h\"\n";
|
||||
header << "\n";
|
||||
|
||||
header << "namespace v8 {\n"
|
||||
|
@ -1306,9 +1306,8 @@ macro TestGeneratedCastOperators(implicit context: Context)() {
|
||||
assert(!Is<ExportedSubClass>(cO));
|
||||
assert(Is<ExportedSubClass2>(cO));
|
||||
|
||||
const nativeContext = LoadNativeContext(context);
|
||||
const jsf: JSFunction = UnsafeCast<JSFunction>(
|
||||
nativeContext.elements[NativeContextSlot::REGEXP_FUNCTION_INDEX]);
|
||||
const jsf: JSFunction =
|
||||
*NativeContextSlot(ContextSlot::REGEXP_FUNCTION_INDEX);
|
||||
assert(!Is<JSSloppyArgumentsObject>(jsf));
|
||||
|
||||
const parameterValues = NewFixedArray(0, ConstantIterator(TheHole));
|
||||
|
Loading…
Reference in New Issue
Block a user