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:
Tobias Tebbi 2020-08-06 12:06:53 +02:00 committed by Commit Bot
parent 54fd06268a
commit 6647f2927c
36 changed files with 603 additions and 471 deletions

View File

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

View File

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

View File

@ -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>();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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);
}

View File

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

View File

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

View File

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

View File

@ -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() &&

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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();

View File

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

View File

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