[promises] Port remaining promise code to Torque.
Bug: v8:9838 Change-Id: Idc6bda122354a54dd24e39b0356f35b0f54ef089 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2012596 Commit-Queue: Joshua Litt <joshualitt@chromium.org> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Cr-Commit-Position: refs/heads/master@{#66031}
This commit is contained in:
parent
01646bc89c
commit
f22c213304
1
BUILD.gn
1
BUILD.gn
@ -987,6 +987,7 @@ torque_files = [
|
||||
"src/builtins/promise-all-element-closure.tq",
|
||||
"src/builtins/promise-constructor.tq",
|
||||
"src/builtins/promise-finally.tq",
|
||||
"src/builtins/promise-misc.tq",
|
||||
"src/builtins/promise-race.tq",
|
||||
"src/builtins/promise-reaction-job.tq",
|
||||
"src/builtins/promise-resolve.tq",
|
||||
|
@ -148,7 +148,7 @@ void AsyncGeneratorBuiltinsAssembler::AsyncGeneratorEnqueue(
|
||||
// presently executing, then this method will loop through, processing each
|
||||
// request from front to back.
|
||||
// This loop resides in AsyncGeneratorResumeNext.
|
||||
TNode<JSPromise> promise = AllocateAndInitJSPromise(context);
|
||||
TNode<JSPromise> promise = NewJSPromise(context);
|
||||
|
||||
Label if_receiverisincompatible(this, Label::kDeferred);
|
||||
GotoIf(TaggedIsSmi(receiver), &if_receiverisincompatible);
|
||||
|
@ -105,7 +105,7 @@ void AsyncFromSyncBuiltinsAssembler::Generate_AsyncFromSyncIteratorMethod(
|
||||
const char* operation_name, Label::Type reject_label_type,
|
||||
base::Optional<TNode<Object>> initial_exception_value) {
|
||||
const TNode<NativeContext> native_context = LoadNativeContext(context);
|
||||
const TNode<JSPromise> promise = AllocateAndInitJSPromise(context);
|
||||
const TNode<JSPromise> promise = NewJSPromise(context);
|
||||
|
||||
TVARIABLE(
|
||||
Object, var_exception,
|
||||
|
@ -20,234 +20,22 @@
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
using Node = compiler::Node;
|
||||
using IteratorRecord = TorqueStructIteratorRecord;
|
||||
using PromiseResolvingFunctions = TorqueStructPromiseResolvingFunctions;
|
||||
|
||||
TNode<JSPromise> PromiseBuiltinsAssembler::AllocateJSPromise(
|
||||
TNode<Context> context) {
|
||||
const TNode<NativeContext> native_context = LoadNativeContext(context);
|
||||
const TNode<JSFunction> promise_fun =
|
||||
CAST(LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX));
|
||||
CSA_ASSERT(this, IsFunctionWithPrototypeSlotMap(LoadMap(promise_fun)));
|
||||
const TNode<Map> promise_map = LoadObjectField<Map>(
|
||||
promise_fun, JSFunction::kPrototypeOrInitialMapOffset);
|
||||
const TNode<HeapObject> promise =
|
||||
Allocate(JSPromise::kSizeWithEmbedderFields);
|
||||
StoreMapNoWriteBarrier(promise, promise_map);
|
||||
StoreObjectFieldRoot(promise, JSPromise::kPropertiesOrHashOffset,
|
||||
RootIndex::kEmptyFixedArray);
|
||||
StoreObjectFieldRoot(promise, JSPromise::kElementsOffset,
|
||||
RootIndex::kEmptyFixedArray);
|
||||
return CAST(promise);
|
||||
}
|
||||
|
||||
void PromiseBuiltinsAssembler::PromiseInit(TNode<JSPromise> promise) {
|
||||
STATIC_ASSERT(v8::Promise::kPending == 0);
|
||||
StoreObjectFieldNoWriteBarrier(promise, JSPromise::kReactionsOrResultOffset,
|
||||
SmiConstant(Smi::zero()));
|
||||
StoreObjectFieldNoWriteBarrier(promise, JSPromise::kFlagsOffset,
|
||||
SmiConstant(Smi::zero()));
|
||||
void PromiseBuiltinsAssembler::ZeroOutEmbedderOffsets(
|
||||
TNode<JSPromise> promise) {
|
||||
for (int offset = JSPromise::kHeaderSize;
|
||||
offset < JSPromise::kSizeWithEmbedderFields; offset += kTaggedSize) {
|
||||
StoreObjectFieldNoWriteBarrier(promise, offset, SmiConstant(Smi::zero()));
|
||||
}
|
||||
}
|
||||
|
||||
TNode<JSPromise> PromiseBuiltinsAssembler::AllocateAndInitJSPromise(
|
||||
TNode<HeapObject> PromiseBuiltinsAssembler::AllocatePromiseReactionJobTask(
|
||||
TNode<Context> context) {
|
||||
return AllocateAndInitJSPromise(context, UndefinedConstant());
|
||||
return Allocate(PromiseReactionJobTask::kSizeOfAllPromiseReactionJobTasks);
|
||||
}
|
||||
|
||||
TNode<JSPromise> PromiseBuiltinsAssembler::AllocateAndInitJSPromise(
|
||||
TNode<Context> context, TNode<Object> parent) {
|
||||
const TNode<JSPromise> instance = AllocateJSPromise(context);
|
||||
PromiseInit(instance);
|
||||
|
||||
Label out(this);
|
||||
GotoIfNot(IsPromiseHookEnabledOrHasAsyncEventDelegate(), &out);
|
||||
CallRuntime(Runtime::kPromiseHookInit, context, instance, parent);
|
||||
Goto(&out);
|
||||
|
||||
BIND(&out);
|
||||
return instance;
|
||||
}
|
||||
|
||||
TNode<JSPromise> PromiseBuiltinsAssembler::AllocateAndSetJSPromise(
|
||||
TNode<Context> context, v8::Promise::PromiseState status,
|
||||
TNode<Object> result) {
|
||||
DCHECK_NE(Promise::kPending, status);
|
||||
|
||||
const TNode<JSPromise> instance = AllocateJSPromise(context);
|
||||
StoreObjectFieldNoWriteBarrier(instance, JSPromise::kReactionsOrResultOffset,
|
||||
result);
|
||||
STATIC_ASSERT(JSPromise::kStatusShift == 0);
|
||||
StoreObjectFieldNoWriteBarrier(instance, JSPromise::kFlagsOffset,
|
||||
SmiConstant(status));
|
||||
for (int offset = JSPromise::kHeaderSize;
|
||||
offset < JSPromise::kSizeWithEmbedderFields; offset += kTaggedSize) {
|
||||
StoreObjectFieldNoWriteBarrier(instance, offset, SmiConstant(0));
|
||||
}
|
||||
|
||||
Label out(this);
|
||||
GotoIfNot(IsPromiseHookEnabledOrHasAsyncEventDelegate(), &out);
|
||||
CallRuntime(Runtime::kPromiseHookInit, context, instance,
|
||||
UndefinedConstant());
|
||||
Goto(&out);
|
||||
|
||||
BIND(&out);
|
||||
return instance;
|
||||
}
|
||||
|
||||
TNode<BoolT> PromiseBuiltinsAssembler::PromiseHasHandler(
|
||||
TNode<JSPromise> promise) {
|
||||
const TNode<Smi> flags =
|
||||
LoadObjectField<Smi>(promise, JSPromise::kFlagsOffset);
|
||||
return IsSetWord(SmiUntag(flags), 1 << JSPromise::kHasHandlerBit);
|
||||
}
|
||||
|
||||
TNode<PromiseReaction> PromiseBuiltinsAssembler::AllocatePromiseReaction(
|
||||
TNode<Object> next, TNode<HeapObject> promise_or_capability,
|
||||
TNode<HeapObject> fulfill_handler, TNode<HeapObject> reject_handler) {
|
||||
const TNode<HeapObject> reaction = Allocate(PromiseReaction::kSize);
|
||||
StoreMapNoWriteBarrier(reaction, RootIndex::kPromiseReactionMap);
|
||||
StoreObjectFieldNoWriteBarrier(reaction, PromiseReaction::kNextOffset, next);
|
||||
StoreObjectFieldNoWriteBarrier(reaction,
|
||||
PromiseReaction::kPromiseOrCapabilityOffset,
|
||||
promise_or_capability);
|
||||
StoreObjectFieldNoWriteBarrier(
|
||||
reaction, PromiseReaction::kFulfillHandlerOffset, fulfill_handler);
|
||||
StoreObjectFieldNoWriteBarrier(
|
||||
reaction, PromiseReaction::kRejectHandlerOffset, reject_handler);
|
||||
return CAST(reaction);
|
||||
}
|
||||
|
||||
TNode<PromiseReactionJobTask>
|
||||
PromiseBuiltinsAssembler::AllocatePromiseReactionJobTask(
|
||||
TNode<Map> map, TNode<Context> context, TNode<Object> argument,
|
||||
TNode<HeapObject> handler, TNode<HeapObject> promise_or_capability) {
|
||||
const TNode<HeapObject> microtask =
|
||||
Allocate(PromiseReactionJobTask::kSizeOfAllPromiseReactionJobTasks);
|
||||
StoreMapNoWriteBarrier(microtask, map);
|
||||
StoreObjectFieldNoWriteBarrier(
|
||||
microtask, PromiseReactionJobTask::kArgumentOffset, argument);
|
||||
StoreObjectFieldNoWriteBarrier(
|
||||
microtask, PromiseReactionJobTask::kContextOffset, context);
|
||||
StoreObjectFieldNoWriteBarrier(
|
||||
microtask, PromiseReactionJobTask::kHandlerOffset, handler);
|
||||
StoreObjectFieldNoWriteBarrier(
|
||||
microtask, PromiseReactionJobTask::kPromiseOrCapabilityOffset,
|
||||
promise_or_capability);
|
||||
return CAST(microtask);
|
||||
}
|
||||
|
||||
TNode<PromiseResolveThenableJobTask>
|
||||
PromiseBuiltinsAssembler::AllocatePromiseResolveThenableJobTask(
|
||||
TNode<JSPromise> promise_to_resolve, TNode<JSReceiver> then,
|
||||
TNode<JSReceiver> thenable, TNode<Context> context) {
|
||||
const TNode<HeapObject> microtask =
|
||||
Allocate(PromiseResolveThenableJobTask::kSize);
|
||||
StoreMapNoWriteBarrier(microtask,
|
||||
RootIndex::kPromiseResolveThenableJobTaskMap);
|
||||
StoreObjectFieldNoWriteBarrier(
|
||||
microtask, PromiseResolveThenableJobTask::kContextOffset, context);
|
||||
StoreObjectFieldNoWriteBarrier(
|
||||
microtask, PromiseResolveThenableJobTask::kPromiseToResolveOffset,
|
||||
promise_to_resolve);
|
||||
StoreObjectFieldNoWriteBarrier(
|
||||
microtask, PromiseResolveThenableJobTask::kThenOffset, then);
|
||||
StoreObjectFieldNoWriteBarrier(
|
||||
microtask, PromiseResolveThenableJobTask::kThenableOffset, thenable);
|
||||
return CAST(microtask);
|
||||
}
|
||||
|
||||
void PromiseBuiltinsAssembler::BranchIfPromiseResolveLookupChainIntact(
|
||||
TNode<NativeContext> native_context, TNode<Object> constructor,
|
||||
Label* if_fast, Label* if_slow) {
|
||||
GotoIfForceSlowPath(if_slow);
|
||||
TNode<Object> promise_fun =
|
||||
LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
|
||||
GotoIfNot(TaggedEqual(promise_fun, constructor), if_slow);
|
||||
Branch(IsPromiseResolveProtectorCellInvalid(), if_slow, if_fast);
|
||||
}
|
||||
|
||||
void PromiseBuiltinsAssembler::GotoIfNotPromiseResolveLookupChainIntact(
|
||||
TNode<NativeContext> native_context, TNode<Object> constructor,
|
||||
Label* if_slow) {
|
||||
Label if_fast(this);
|
||||
BranchIfPromiseResolveLookupChainIntact(native_context, constructor, &if_fast,
|
||||
if_slow);
|
||||
BIND(&if_fast);
|
||||
}
|
||||
|
||||
void PromiseBuiltinsAssembler::BranchIfPromiseSpeciesLookupChainIntact(
|
||||
TNode<NativeContext> native_context, TNode<Map> promise_map, Label* if_fast,
|
||||
Label* if_slow) {
|
||||
TNode<Object> promise_prototype =
|
||||
LoadContextElement(native_context, Context::PROMISE_PROTOTYPE_INDEX);
|
||||
GotoIfForceSlowPath(if_slow);
|
||||
GotoIfNot(TaggedEqual(LoadMapPrototype(promise_map), promise_prototype),
|
||||
if_slow);
|
||||
Branch(IsPromiseSpeciesProtectorCellInvalid(), if_slow, if_fast);
|
||||
}
|
||||
|
||||
void PromiseBuiltinsAssembler::BranchIfPromiseThenLookupChainIntact(
|
||||
TNode<NativeContext> native_context, TNode<Map> receiver_map,
|
||||
Label* if_fast, Label* if_slow) {
|
||||
GotoIfForceSlowPath(if_slow);
|
||||
GotoIfNot(IsJSPromiseMap(receiver_map), if_slow);
|
||||
const TNode<Object> promise_prototype =
|
||||
LoadContextElement(native_context, Context::PROMISE_PROTOTYPE_INDEX);
|
||||
GotoIfNot(TaggedEqual(LoadMapPrototype(receiver_map), promise_prototype),
|
||||
if_slow);
|
||||
Branch(IsPromiseThenProtectorCellInvalid(), if_slow, if_fast);
|
||||
}
|
||||
|
||||
void PromiseBuiltinsAssembler::BranchIfAccessCheckFailed(
|
||||
TNode<Context> context, TNode<Context> native_context,
|
||||
TNode<Object> promise_constructor, TNode<Object> executor,
|
||||
Label* if_noaccess) {
|
||||
TVARIABLE(HeapObject, var_executor);
|
||||
var_executor = CAST(executor);
|
||||
Label has_access(this), call_runtime(this, Label::kDeferred);
|
||||
|
||||
// If executor is a bound function, load the bound function until we've
|
||||
// reached an actual function.
|
||||
Label found_function(this), loop_over_bound_function(this, &var_executor);
|
||||
Goto(&loop_over_bound_function);
|
||||
BIND(&loop_over_bound_function);
|
||||
{
|
||||
TNode<Uint16T> executor_type = LoadInstanceType(var_executor.value());
|
||||
GotoIf(InstanceTypeEqual(executor_type, JS_FUNCTION_TYPE), &found_function);
|
||||
GotoIfNot(InstanceTypeEqual(executor_type, JS_BOUND_FUNCTION_TYPE),
|
||||
&call_runtime);
|
||||
var_executor = LoadObjectField<HeapObject>(
|
||||
var_executor.value(), JSBoundFunction::kBoundTargetFunctionOffset);
|
||||
Goto(&loop_over_bound_function);
|
||||
}
|
||||
|
||||
// Load the context from the function and compare it to the Promise
|
||||
// constructor's context. If they match, everything is fine, otherwise, bail
|
||||
// out to the runtime.
|
||||
BIND(&found_function);
|
||||
{
|
||||
TNode<Context> function_context = LoadObjectField<Context>(
|
||||
var_executor.value(), JSFunction::kContextOffset);
|
||||
TNode<NativeContext> native_function_context =
|
||||
LoadNativeContext(function_context);
|
||||
Branch(TaggedEqual(native_context, native_function_context), &has_access,
|
||||
&call_runtime);
|
||||
}
|
||||
|
||||
BIND(&call_runtime);
|
||||
{
|
||||
Branch(TaggedEqual(CallRuntime(Runtime::kAllowDynamicFunction, context,
|
||||
promise_constructor),
|
||||
TrueConstant()),
|
||||
&has_access, if_noaccess);
|
||||
}
|
||||
|
||||
BIND(&has_access);
|
||||
TNode<HeapObject> PromiseBuiltinsAssembler::AllocateJSPromise(
|
||||
TNode<Context> context) {
|
||||
return Allocate(JSPromise::kSizeWithEmbedderFields);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
@ -17,112 +17,11 @@ class V8_EXPORT_PRIVATE PromiseBuiltinsAssembler : public CodeStubAssembler {
|
||||
public:
|
||||
explicit PromiseBuiltinsAssembler(compiler::CodeAssemblerState* state)
|
||||
: CodeStubAssembler(state) {}
|
||||
// These allocate and initialize a promise with pending state and
|
||||
// undefined fields.
|
||||
//
|
||||
// This uses undefined as the parent promise for the promise init
|
||||
// hook.
|
||||
TNode<JSPromise> AllocateAndInitJSPromise(TNode<Context> context);
|
||||
// This uses the given parent as the parent promise for the promise
|
||||
// init hook.
|
||||
TNode<JSPromise> AllocateAndInitJSPromise(TNode<Context> context,
|
||||
TNode<Object> parent);
|
||||
void ZeroOutEmbedderOffsets(TNode<JSPromise> promise);
|
||||
|
||||
// This allocates and initializes a promise with the given state and
|
||||
// fields.
|
||||
TNode<JSPromise> AllocateAndSetJSPromise(TNode<Context> context,
|
||||
v8::Promise::PromiseState status,
|
||||
TNode<Object> result);
|
||||
TNode<HeapObject> AllocateJSPromise(TNode<Context> context);
|
||||
|
||||
TNode<PromiseReaction> AllocatePromiseReaction(
|
||||
TNode<Object> next, TNode<HeapObject> promise_or_capability,
|
||||
TNode<HeapObject> fulfill_handler, TNode<HeapObject> reject_handler);
|
||||
|
||||
TNode<PromiseReactionJobTask> AllocatePromiseReactionJobTask(
|
||||
TNode<Map> map, TNode<Context> context, TNode<Object> argument,
|
||||
TNode<HeapObject> handler, TNode<HeapObject> promise_or_capability);
|
||||
|
||||
TNode<PromiseResolveThenableJobTask> AllocatePromiseResolveThenableJobTask(
|
||||
TNode<JSPromise> promise_to_resolve, TNode<JSReceiver> then,
|
||||
TNode<JSReceiver> thenable, TNode<Context> context);
|
||||
TNode<BoolT> PromiseHasHandler(TNode<JSPromise> promise);
|
||||
|
||||
void BranchIfAccessCheckFailed(TNode<Context> context,
|
||||
TNode<Context> native_context,
|
||||
TNode<Object> promise_constructor,
|
||||
TNode<Object> executor, Label* if_noaccess);
|
||||
void PromiseInit(TNode<JSPromise> promise);
|
||||
|
||||
// We can shortcut the SpeciesConstructor on {promise_map} if it's
|
||||
// [[Prototype]] is the (initial) Promise.prototype and the @@species
|
||||
// protector is intact, as that guards the lookup path for the "constructor"
|
||||
// property on JSPromise instances which have the %PromisePrototype%.
|
||||
void BranchIfPromiseSpeciesLookupChainIntact(
|
||||
TNode<NativeContext> native_context, TNode<Map> promise_map,
|
||||
Label* if_fast, Label* if_slow);
|
||||
|
||||
template <typename... TArgs>
|
||||
TNode<Object> InvokeThen(TNode<NativeContext> native_context,
|
||||
TNode<Object> receiver, TArgs... args) {
|
||||
TVARIABLE(Object, var_result);
|
||||
Label if_fast(this), if_slow(this, Label::kDeferred),
|
||||
done(this, &var_result);
|
||||
GotoIf(TaggedIsSmi(receiver), &if_slow);
|
||||
const TNode<Map> receiver_map = LoadMap(CAST(receiver));
|
||||
// We can skip the "then" lookup on {receiver} if it's [[Prototype]]
|
||||
// is the (initial) Promise.prototype and the Promise#then protector
|
||||
// is intact, as that guards the lookup path for the "then" property
|
||||
// on JSPromise instances which have the (initial) %PromisePrototype%.
|
||||
BranchIfPromiseThenLookupChainIntact(native_context, receiver_map, &if_fast,
|
||||
&if_slow);
|
||||
|
||||
BIND(&if_fast);
|
||||
{
|
||||
const TNode<Object> then =
|
||||
LoadContextElement(native_context, Context::PROMISE_THEN_INDEX);
|
||||
var_result =
|
||||
CallJS(CodeFactory::CallFunction(
|
||||
isolate(), ConvertReceiverMode::kNotNullOrUndefined),
|
||||
native_context, then, receiver, args...);
|
||||
Goto(&done);
|
||||
}
|
||||
|
||||
BIND(&if_slow);
|
||||
{
|
||||
const TNode<Object> then = GetProperty(
|
||||
native_context, receiver, isolate()->factory()->then_string());
|
||||
var_result =
|
||||
CallJS(CodeFactory::Call(isolate(),
|
||||
ConvertReceiverMode::kNotNullOrUndefined),
|
||||
native_context, then, receiver, args...);
|
||||
Goto(&done);
|
||||
}
|
||||
|
||||
BIND(&done);
|
||||
return var_result.value();
|
||||
}
|
||||
|
||||
protected:
|
||||
// We can skip the "resolve" lookup on {constructor} if it's the (initial)
|
||||
// Promise constructor and the Promise.resolve() protector is intact, as
|
||||
// that guards the lookup path for the "resolve" property on the %Promise%
|
||||
// intrinsic object.
|
||||
void BranchIfPromiseResolveLookupChainIntact(
|
||||
TNode<NativeContext> native_context, TNode<Object> constructor,
|
||||
Label* if_fast, Label* if_slow);
|
||||
void GotoIfNotPromiseResolveLookupChainIntact(
|
||||
TNode<NativeContext> native_context, TNode<Object> constructor,
|
||||
Label* if_slow);
|
||||
|
||||
// We can skip the "then" lookup on {receiver_map} if it's [[Prototype]]
|
||||
// is the (initial) Promise.prototype and the Promise#then() protector
|
||||
// is intact, as that guards the lookup path for the "then" property
|
||||
// on JSPromise instances which have the (initial) %PromisePrototype%.
|
||||
void BranchIfPromiseThenLookupChainIntact(TNode<NativeContext> native_context,
|
||||
TNode<Map> receiver_map,
|
||||
Label* if_fast, Label* if_slow);
|
||||
|
||||
TNode<JSPromise> AllocateJSPromise(TNode<Context> context);
|
||||
TNode<HeapObject> AllocatePromiseReactionJobTask(TNode<Context> context);
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
@ -36,6 +36,7 @@ extern macro IsExtensibleMap(Map): bool;
|
||||
extern macro IsJSPrimitiveWrapper(HeapObject): bool;
|
||||
extern macro IsPromiseCapability(HeapObject): bool;
|
||||
extern macro IsPromiseReaction(HeapObject): bool;
|
||||
extern macro IsPromiseReactionJobTask(HeapObject): bool;
|
||||
extern macro IsPromiseRejectReactionJobTask(HeapObject): bool;
|
||||
extern macro IsPromiseFulfillReactionJobTask(HeapObject): bool;
|
||||
extern macro IsSharedFunctionInfo(HeapObject): bool;
|
||||
@ -643,6 +644,14 @@ Cast<JSReceiver|Null>(o: HeapObject): JSReceiver|Null
|
||||
}
|
||||
}
|
||||
|
||||
Cast<PromiseReactionJobTask>(o: HeapObject):
|
||||
PromiseReactionJobTask labels CastError {
|
||||
if (IsPromiseReactionJobTask(o)) {
|
||||
return %RawDownCast<PromiseReactionJobTask>(o);
|
||||
}
|
||||
goto CastError;
|
||||
}
|
||||
|
||||
Cast<PromiseFulfillReactionJobTask>(o: HeapObject):
|
||||
PromiseFulfillReactionJobTask labels CastError {
|
||||
if (IsPromiseFulfillReactionJobTask(o)) {
|
||||
|
@ -246,9 +246,6 @@ namespace promise {
|
||||
const kPromiseBuiltinsDebugEventSlot: constexpr ContextSlot
|
||||
generates 'PromiseBuiltins::kDebugEventSlot';
|
||||
|
||||
extern macro
|
||||
PromiseBuiltinsAssembler::AllocateAndInitJSPromise(Context): JSPromise;
|
||||
|
||||
@export
|
||||
macro CreatePromiseCapabilitiesExecutorContext(
|
||||
nativeContext: NativeContext, capability: PromiseCapability): Context {
|
||||
@ -306,7 +303,7 @@ namespace promise {
|
||||
if (TaggedEqual(
|
||||
constructor,
|
||||
nativeContext[NativeContextSlot::PROMISE_FUNCTION_INDEX])) {
|
||||
const promise = AllocateAndInitJSPromise(nativeContext);
|
||||
const promise = NewJSPromise();
|
||||
|
||||
const pair =
|
||||
CreatePromiseResolvingFunctions(promise, debugEvent, nativeContext);
|
||||
@ -409,14 +406,6 @@ namespace promise {
|
||||
return ResolvePromise(context, promise, resolution);
|
||||
}
|
||||
|
||||
extern macro
|
||||
PromiseBuiltinsAssembler::AllocatePromiseReaction(
|
||||
Object, HeapObject, HeapObject, HeapObject): PromiseReaction;
|
||||
|
||||
extern macro
|
||||
PromiseBuiltinsAssembler::AllocatePromiseReactionJobTask(
|
||||
Map, Context, Object, HeapObject, HeapObject): PromiseReactionJobTask;
|
||||
|
||||
@export
|
||||
transitioning macro PerformPromiseThenImpl(implicit context: Context)(
|
||||
promise: JSPromise, onFulfilled: Callable|Undefined,
|
||||
@ -427,13 +416,14 @@ namespace promise {
|
||||
// PromiseReaction holding both the onFulfilled and onRejected callbacks.
|
||||
// Once the {promise} is resolved we decide on the concrete handler to
|
||||
// push onto the microtask queue.
|
||||
const promiseReactions = promise.reactions_or_result;
|
||||
const reaction = AllocatePromiseReaction(
|
||||
const promiseReactions =
|
||||
UnsafeCast<(Zero | PromiseReaction)>(promise.reactions_or_result);
|
||||
const reaction = NewPromiseReaction(
|
||||
promiseReactions, resultPromiseOrCapability, onFulfilled, onRejected);
|
||||
promise.reactions_or_result = reaction;
|
||||
} else {
|
||||
let map: Map;
|
||||
let handler: HeapObject;
|
||||
let handler: Callable|Undefined = Undefined;
|
||||
let handlerContext: Context;
|
||||
if (promise.Status() == PromiseState::kFulfilled) {
|
||||
map = PromiseFulfillReactionJobTaskMapConstant();
|
||||
@ -451,7 +441,7 @@ namespace promise {
|
||||
}
|
||||
|
||||
const reactionsOrResult = promise.reactions_or_result;
|
||||
const microtask = AllocatePromiseReactionJobTask(
|
||||
const microtask = NewPromiseReactionJobTask(
|
||||
map, handlerContext, reactionsOrResult, handler,
|
||||
resultPromiseOrCapability);
|
||||
EnqueueMicrotask(handlerContext, microtask);
|
||||
@ -469,10 +459,6 @@ namespace promise {
|
||||
return resultPromise;
|
||||
}
|
||||
|
||||
extern macro
|
||||
PromiseBuiltinsAssembler::AllocateAndSetJSPromise(
|
||||
Context, constexpr PromiseState, JSAny): JSPromise;
|
||||
|
||||
// https://tc39.es/ecma262/#sec-promise-reject-functions
|
||||
transitioning javascript builtin
|
||||
PromiseReject(js-implicit context: NativeContext, receiver: JSAny)(
|
||||
@ -484,8 +470,7 @@ namespace promise {
|
||||
|
||||
const promiseFun = context[NativeContextSlot::PROMISE_FUNCTION_INDEX];
|
||||
if (promiseFun == receiver) {
|
||||
const promise =
|
||||
AllocateAndSetJSPromise(context, PromiseState::kRejected, reason);
|
||||
const promise = NewJSPromise(PromiseState::kRejected, reason);
|
||||
runtime::PromiseRejectEventFromStack(promise, reason);
|
||||
return promise;
|
||||
} else {
|
||||
|
@ -25,18 +25,13 @@ namespace promise {
|
||||
const kPromiseConstructorReturnedUndefined: constexpr UseCounterFeature
|
||||
generates 'v8::Isolate::kPromiseConstructorReturnedUndefined';
|
||||
|
||||
extern macro
|
||||
PromiseBuiltinsAssembler::BranchIfAccessCheckFailed(
|
||||
Context, Context, Object, Object): void labels NoAccess;
|
||||
|
||||
extern macro
|
||||
IsDebugActive(): bool;
|
||||
|
||||
transitioning macro
|
||||
HasAccessCheckFailed(
|
||||
context: Context, nativeContext: Context, promiseFun: Object,
|
||||
executor: Object): bool {
|
||||
BranchIfAccessCheckFailed(context, nativeContext, promiseFun, executor)
|
||||
HasAccessCheckFailed(implicit context: Context)(
|
||||
nativeContext: NativeContext, promiseFun: JSAny, executor: JSAny): bool {
|
||||
BranchIfAccessCheckFailed(nativeContext, promiseFun, executor)
|
||||
otherwise return true;
|
||||
return false;
|
||||
}
|
||||
@ -44,8 +39,6 @@ namespace promise {
|
||||
extern macro ConstructorBuiltinsAssembler::EmitFastNewObject(
|
||||
Context, JSFunction, JSReceiver): JSObject;
|
||||
|
||||
extern macro PromiseBuiltinsAssembler::PromiseInit(JSPromise): void;
|
||||
|
||||
extern macro
|
||||
PromiseBuiltinsAssembler::IsPromiseHookEnabledOrHasAsyncEventDelegate(): bool;
|
||||
|
||||
@ -68,7 +61,7 @@ namespace promise {
|
||||
context[NativeContextSlot::PROMISE_FUNCTION_INDEX]);
|
||||
|
||||
// Silently fail if the stack looks fishy.
|
||||
if (HasAccessCheckFailed(context, context, promiseFun, executor)) {
|
||||
if (HasAccessCheckFailed(context, promiseFun, executor)) {
|
||||
IncrementUseCounter(
|
||||
context, SmiConstant(kPromiseConstructorReturnedUndefined));
|
||||
return Undefined;
|
||||
@ -76,7 +69,7 @@ namespace promise {
|
||||
|
||||
let result: JSPromise;
|
||||
if (promiseFun == newTarget) {
|
||||
result = AllocateAndInitJSPromise(context);
|
||||
result = NewJSPromise();
|
||||
} else {
|
||||
result = UnsafeCast<JSPromise>(EmitFastNewObject(
|
||||
context, promiseFun, UnsafeCast<JSReceiver>(newTarget)));
|
||||
|
@ -48,11 +48,6 @@ namespace promise {
|
||||
return AllocateFunctionWithMapAndContext(map, throwerInfo, throwerContext);
|
||||
}
|
||||
|
||||
extern transitioning macro
|
||||
PromiseBuiltinsAssembler::InvokeThen(NativeContext, JSAny, JSAny): JSAny;
|
||||
extern transitioning macro PromiseBuiltinsAssembler::InvokeThen(
|
||||
NativeContext, JSAny, JSAny, JSAny): JSAny;
|
||||
|
||||
transitioning javascript builtin
|
||||
PromiseCatchFinally(js-implicit context: Context, receiver: JSAny)(
|
||||
reason: JSAny): JSAny {
|
||||
|
236
src/builtins/promise-misc.tq
Normal file
236
src/builtins/promise-misc.tq
Normal file
@ -0,0 +1,236 @@
|
||||
// Copyright 2019 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.
|
||||
|
||||
#include 'src/builtins/builtins-promise.h'
|
||||
#include 'src/builtins/builtins-promise-gen.h'
|
||||
|
||||
namespace runtime {
|
||||
extern transitioning runtime
|
||||
AllowDynamicFunction(implicit context: Context)(JSAny): JSAny;
|
||||
}
|
||||
|
||||
// Unsafe functions that should be used very carefully.
|
||||
namespace promise_internal {
|
||||
extern macro PromiseBuiltinsAssembler::ZeroOutEmbedderOffsets(JSPromise):
|
||||
void;
|
||||
|
||||
extern macro PromiseBuiltinsAssembler::AllocateJSPromise(Context): HeapObject;
|
||||
|
||||
extern macro PromiseBuiltinsAssembler::AllocatePromiseReactionJobTask(
|
||||
Context): HeapObject;
|
||||
|
||||
}
|
||||
|
||||
namespace promise {
|
||||
extern macro IsFunctionWithPrototypeSlotMap(Map): bool;
|
||||
|
||||
@export
|
||||
macro PromiseHasHandler(promise: JSPromise): bool {
|
||||
return promise.HasHandler();
|
||||
}
|
||||
|
||||
@export
|
||||
macro PromiseInit(promise: JSPromise): void {
|
||||
assert(PromiseState::kPending == 0);
|
||||
promise.reactions_or_result = kZero;
|
||||
promise.flags = 0;
|
||||
promise_internal::ZeroOutEmbedderOffsets(promise);
|
||||
}
|
||||
|
||||
macro InnerNewJSPromise(implicit context: Context)(): JSPromise {
|
||||
const nativeContext = LoadNativeContext(context);
|
||||
const promiseFun = UnsafeCast<JSFunction>(
|
||||
nativeContext[NativeContextSlot::PROMISE_FUNCTION_INDEX]);
|
||||
assert(IsFunctionWithPrototypeSlotMap(promiseFun.map));
|
||||
const promiseMap = UnsafeCast<Map>(promiseFun.prototype_or_initial_map);
|
||||
const promiseHeapObject = promise_internal::AllocateJSPromise(context);
|
||||
promiseHeapObject.map = promiseMap;
|
||||
const promise = UnsafeCast<JSPromise>(promiseHeapObject);
|
||||
promise.properties_or_hash = kEmptyFixedArray;
|
||||
promise.elements = kEmptyFixedArray;
|
||||
promise.reactions_or_result = kZero;
|
||||
promise.flags = 0;
|
||||
return promise;
|
||||
}
|
||||
|
||||
macro NewPromiseReactionJobTask(implicit context: Context)(
|
||||
map: Map, handlerContext: Context, argument: Object,
|
||||
handler: Callable|Undefined,
|
||||
promiseOrCapability: JSPromise|PromiseCapability|
|
||||
Undefined): PromiseReactionJobTask {
|
||||
const taskHeapObject =
|
||||
promise_internal::AllocatePromiseReactionJobTask(context);
|
||||
taskHeapObject.map = map;
|
||||
const jobTask = UnsafeCast<PromiseReactionJobTask>(taskHeapObject);
|
||||
jobTask.argument = argument;
|
||||
jobTask.context = handlerContext;
|
||||
jobTask.handler = handler;
|
||||
jobTask.promise_or_capability = promiseOrCapability;
|
||||
return jobTask;
|
||||
}
|
||||
|
||||
// These allocate and initialize a promise with pending state and
|
||||
// undefined fields.
|
||||
//
|
||||
// This uses the given parent as the parent promise for the promise
|
||||
// init hook.
|
||||
@export
|
||||
transitioning macro NewJSPromise(implicit context: Context)(parent: Object):
|
||||
JSPromise {
|
||||
const instance = InnerNewJSPromise();
|
||||
PromiseInit(instance);
|
||||
if (IsPromiseHookEnabledOrHasAsyncEventDelegate()) {
|
||||
runtime::PromiseHookInit(instance, parent);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
// This uses undefined as the parent promise for the promise init
|
||||
// hook.
|
||||
@export
|
||||
transitioning macro NewJSPromise(implicit context: Context)(): JSPromise {
|
||||
return NewJSPromise(Undefined);
|
||||
}
|
||||
|
||||
// This allocates and initializes a promise with the given state and
|
||||
// fields.
|
||||
@export
|
||||
transitioning macro NewJSPromise(implicit context: Context)(
|
||||
status: constexpr PromiseState, result: JSAny): JSPromise {
|
||||
assert(status != PromiseState::kPending);
|
||||
assert(kJSPromiseStatusShift == 0);
|
||||
|
||||
const instance = InnerNewJSPromise();
|
||||
instance.reactions_or_result = result;
|
||||
instance.SetStatus(status);
|
||||
promise_internal::ZeroOutEmbedderOffsets(instance);
|
||||
|
||||
if (IsPromiseHookEnabledOrHasAsyncEventDelegate()) {
|
||||
runtime::PromiseHookInit(instance, Undefined);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
macro NewPromiseReaction(implicit context: Context)(
|
||||
next: Zero|PromiseReaction,
|
||||
promiseOrCapability: JSPromise|PromiseCapability|Undefined,
|
||||
fulfillHandler: Callable|Undefined,
|
||||
rejectHandler: Callable|Undefined): PromiseReaction {
|
||||
return new PromiseReaction{
|
||||
map: PromiseReactionMapConstant(),
|
||||
next: next,
|
||||
reject_handler: rejectHandler,
|
||||
fulfill_handler: fulfillHandler,
|
||||
promise_or_capability: promiseOrCapability
|
||||
};
|
||||
}
|
||||
|
||||
extern macro PromiseResolveThenableJobTaskMapConstant(): Map;
|
||||
|
||||
macro NewPromiseResolveThenableJobTask(implicit context: Context)(
|
||||
promiseToResolve: JSPromise, then: JSReceiver, thenable: JSReceiver,
|
||||
thenableContext: Context): PromiseResolveThenableJobTask {
|
||||
return new PromiseResolveThenableJobTask{
|
||||
map: PromiseResolveThenableJobTaskMapConstant(),
|
||||
context: thenableContext,
|
||||
promise_to_resolve: promiseToResolve,
|
||||
then: then,
|
||||
thenable: thenable
|
||||
};
|
||||
}
|
||||
|
||||
struct InvokeThenOneArgFunctor {
|
||||
transitioning
|
||||
macro Call(
|
||||
nativeContext: NativeContext, then: JSAny, receiver: JSAny, arg1: JSAny,
|
||||
_arg2: JSAny): JSAny {
|
||||
return Call(nativeContext, then, receiver, arg1);
|
||||
}
|
||||
}
|
||||
|
||||
struct InvokeThenTwoArgFunctor {
|
||||
transitioning
|
||||
macro Call(
|
||||
nativeContext: NativeContext, then: JSAny, receiver: JSAny, arg1: JSAny,
|
||||
arg2: JSAny): JSAny {
|
||||
return Call(nativeContext, then, receiver, arg1, arg2);
|
||||
}
|
||||
}
|
||||
|
||||
transitioning
|
||||
macro InvokeThen<F: type>(implicit context: Context)(
|
||||
nativeContext: NativeContext, receiver: JSAny, arg1: JSAny, arg2: JSAny,
|
||||
callFunctor: F): JSAny {
|
||||
// We can skip the "then" lookup on {receiver} if it's [[Prototype]]
|
||||
// is the (initial) Promise.prototype and the Promise#then protector
|
||||
// is intact, as that guards the lookup path for the "then" property
|
||||
// on JSPromise instances which have the (initial) %PromisePrototype%.
|
||||
if (!Is<Smi>(receiver) &&
|
||||
IsPromiseThenLookupChainIntact(
|
||||
nativeContext, UnsafeCast<HeapObject>(receiver).map)) {
|
||||
const then = UnsafeCast<JSAny>(
|
||||
nativeContext[NativeContextSlot::PROMISE_THEN_INDEX]);
|
||||
return callFunctor.Call(nativeContext, then, receiver, arg1, arg2);
|
||||
} else
|
||||
deferred {
|
||||
const then = UnsafeCast<JSAny>(GetProperty(receiver, kThenString));
|
||||
return callFunctor.Call(nativeContext, then, receiver, arg1, arg2);
|
||||
}
|
||||
}
|
||||
|
||||
transitioning
|
||||
macro InvokeThen(implicit context: Context)(
|
||||
nativeContext: NativeContext, receiver: JSAny, arg: JSAny): JSAny {
|
||||
return InvokeThen(
|
||||
nativeContext, receiver, arg, Undefined, InvokeThenOneArgFunctor{});
|
||||
}
|
||||
|
||||
transitioning
|
||||
macro InvokeThen(implicit context: Context)(
|
||||
nativeContext: NativeContext, receiver: JSAny, arg1: JSAny,
|
||||
arg2: JSAny): JSAny {
|
||||
return InvokeThen(
|
||||
nativeContext, receiver, arg1, arg2, InvokeThenTwoArgFunctor{});
|
||||
}
|
||||
|
||||
transitioning
|
||||
macro BranchIfAccessCheckFailed(implicit context: Context)(
|
||||
nativeContext: NativeContext, promiseConstructor: JSAny,
|
||||
executor: JSAny): void labels IfNoAccess {
|
||||
try {
|
||||
// If executor is a bound function, load the bound function until we've
|
||||
// reached an actual function.
|
||||
let foundExecutor = executor;
|
||||
while (true) {
|
||||
typeswitch (foundExecutor) {
|
||||
case (f: JSFunction): {
|
||||
// Load the context from the function and compare it to the Promise
|
||||
// constructor's context. If they match, everything is fine,
|
||||
// otherwise, bail out to the runtime.
|
||||
const functionContext = f.context;
|
||||
const nativeFunctionContext = LoadNativeContext(functionContext);
|
||||
if (TaggedEqual(nativeContext, nativeFunctionContext)) {
|
||||
goto HasAccess;
|
||||
} else {
|
||||
goto CallRuntime;
|
||||
}
|
||||
}
|
||||
case (b: JSBoundFunction): {
|
||||
foundExecutor = b.bound_target_function;
|
||||
}
|
||||
case (Object): {
|
||||
goto CallRuntime;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
label CallRuntime deferred {
|
||||
const result = runtime::AllowDynamicFunction(promiseConstructor);
|
||||
if (result != True) {
|
||||
goto IfNoAccess;
|
||||
}
|
||||
}
|
||||
label HasAccess {}
|
||||
}
|
||||
}
|
@ -64,7 +64,7 @@ namespace promise {
|
||||
if (promiseFun == constructor) {
|
||||
// This adds a fast path for native promises that don't need to
|
||||
// create NewPromiseCapability.
|
||||
const result = AllocateAndInitJSPromise(context);
|
||||
const result = NewJSPromise();
|
||||
ResolvePromise(context, result, value);
|
||||
return result;
|
||||
} else
|
||||
@ -85,10 +85,6 @@ namespace promise {
|
||||
|
||||
const kThenString: String = ThenStringConstant();
|
||||
|
||||
extern macro PromiseBuiltinsAssembler::AllocatePromiseResolveThenableJobTask(
|
||||
JSPromise, JSReceiver, JSReceiver,
|
||||
Context): PromiseResolveThenableJobTask;
|
||||
|
||||
transitioning builtin
|
||||
ResolvePromise(implicit context:
|
||||
Context)(promise: JSPromise, resolution: JSAny): JSAny {
|
||||
@ -182,7 +178,7 @@ namespace promise {
|
||||
// 12. Perform EnqueueJob("PromiseJobs", PromiseResolveThenableJob,
|
||||
// «promise, resolution, thenAction»).
|
||||
const nativeContext = LoadNativeContext(context);
|
||||
const task = AllocatePromiseResolveThenableJobTask(
|
||||
const task = NewPromiseResolveThenableJobTask(
|
||||
promise, UnsafeCast<JSReceiver>(then),
|
||||
UnsafeCast<JSReceiver>(resolution), nativeContext);
|
||||
return EnqueueMicrotask(nativeContext, task);
|
||||
|
@ -6,22 +6,16 @@
|
||||
|
||||
namespace promise {
|
||||
|
||||
extern macro
|
||||
PromiseBuiltinsAssembler::BranchIfPromiseSpeciesLookupChainIntact(
|
||||
NativeContext, Map): never labels IsIntact,
|
||||
IsNotIntact;
|
||||
|
||||
macro
|
||||
IsPromiseSpeciesLookupChainIntact(
|
||||
nativeContext: NativeContext, promiseMap: Map): bool {
|
||||
BranchIfPromiseSpeciesLookupChainIntact(nativeContext, promiseMap)
|
||||
otherwise return true, return false;
|
||||
const promisePrototype =
|
||||
nativeContext[NativeContextSlot::PROMISE_PROTOTYPE_INDEX];
|
||||
if (IsForceSlowPath()) return false;
|
||||
if (promiseMap.prototype != promisePrototype) return false;
|
||||
return !IsPromiseSpeciesProtectorCellInvalid();
|
||||
}
|
||||
|
||||
extern macro
|
||||
PromiseBuiltinsAssembler::AllocateAndInitJSPromise(Context, Object):
|
||||
JSPromise;
|
||||
|
||||
// https://tc39.es/ecma262/#sec-promise.prototype.then
|
||||
transitioning javascript builtin
|
||||
PromisePrototypeThen(js-implicit context: NativeContext, receiver: JSAny)(
|
||||
@ -54,7 +48,7 @@ namespace promise {
|
||||
}
|
||||
}
|
||||
label AllocateAndInit {
|
||||
const resultJSPromise = AllocateAndInitJSPromise(context, promise);
|
||||
const resultJSPromise = NewJSPromise(promise);
|
||||
resultPromiseOrCapability = resultJSPromise;
|
||||
resultPromise = resultJSPromise;
|
||||
}
|
||||
|
@ -6010,6 +6010,13 @@ TNode<BoolT> CodeStubAssembler::IsPromiseReaction(
|
||||
return HasInstanceType(object, PROMISE_REACTION_TYPE);
|
||||
}
|
||||
|
||||
TNode<BoolT> CodeStubAssembler::IsPromiseReactionJobTask(
|
||||
TNode<HeapObject> object) {
|
||||
TNode<Uint16T> instance_type = LoadInstanceType(object);
|
||||
return IsInRange(instance_type, FIRST_PROMISE_REACTION_JOB_TASK_TYPE,
|
||||
LAST_PROMISE_REACTION_JOB_TASK_TYPE);
|
||||
}
|
||||
|
||||
TNode<BoolT> CodeStubAssembler::IsPromiseRejectReactionJobTask(
|
||||
SloppyTNode<HeapObject> object) {
|
||||
return HasInstanceType(object, PROMISE_REJECT_REACTION_JOB_TASK_TYPE);
|
||||
|
@ -129,6 +129,8 @@ enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
|
||||
V(PromiseReactionMap, promise_reaction_map, PromiseReactionMap) \
|
||||
V(PromiseRejectReactionJobTaskMap, promise_reject_reaction_job_task_map, \
|
||||
PromiseRejectReactionJobTaskMap) \
|
||||
V(PromiseResolveThenableJobTaskMap, promise_resolve_thenable_job_task_map, \
|
||||
PromiseResolveThenableJobTaskMap) \
|
||||
V(prototype_string, prototype_string, PrototypeString) \
|
||||
V(PrototypeInfoMap, prototype_info_map, PrototypeInfoMap) \
|
||||
V(replace_symbol, replace_symbol, ReplaceSymbol) \
|
||||
@ -2548,6 +2550,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
|
||||
TNode<BoolT> IsPropertyArray(SloppyTNode<HeapObject> object);
|
||||
TNode<BoolT> IsPropertyCell(SloppyTNode<HeapObject> object);
|
||||
TNode<BoolT> IsPromiseReaction(SloppyTNode<HeapObject> object);
|
||||
TNode<BoolT> IsPromiseReactionJobTask(TNode<HeapObject> object);
|
||||
TNode<BoolT> IsPromiseRejectReactionJobTask(SloppyTNode<HeapObject> object);
|
||||
TNode<BoolT> IsPromiseFulfillReactionJobTask(SloppyTNode<HeapObject> object);
|
||||
TNode<BoolT> IsPrototypeInitialArrayPrototype(SloppyTNode<Context> context,
|
||||
|
@ -2449,7 +2449,7 @@ TEST(IsPromiseHookEnabled) {
|
||||
CHECK_EQ(ReadOnlyRoots(isolate).false_value(), *result);
|
||||
}
|
||||
|
||||
TEST(AllocateAndInitJSPromise) {
|
||||
TEST(NewJSPromise) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
|
||||
const int kNumParams = 1;
|
||||
@ -2457,7 +2457,7 @@ TEST(AllocateAndInitJSPromise) {
|
||||
PromiseBuiltinsAssembler m(asm_tester.state());
|
||||
|
||||
Node* const context = m.Parameter(kNumParams + 2);
|
||||
const TNode<JSPromise> promise = m.AllocateAndInitJSPromise(m.CAST(context));
|
||||
const TNode<JSPromise> promise = m.NewJSPromise(m.CAST(context));
|
||||
m.Return(promise);
|
||||
|
||||
FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
|
||||
@ -2466,7 +2466,7 @@ TEST(AllocateAndInitJSPromise) {
|
||||
CHECK(result->IsJSPromise());
|
||||
}
|
||||
|
||||
TEST(AllocateAndSetJSPromise) {
|
||||
TEST(NewJSPromise2) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
|
||||
const int kNumParams = 1;
|
||||
@ -2474,8 +2474,8 @@ TEST(AllocateAndSetJSPromise) {
|
||||
PromiseBuiltinsAssembler m(asm_tester.state());
|
||||
|
||||
Node* const context = m.Parameter(kNumParams + 2);
|
||||
const TNode<JSPromise> promise = m.AllocateAndSetJSPromise(
|
||||
m.CAST(context), v8::Promise::kRejected, m.SmiConstant(1));
|
||||
const TNode<JSPromise> promise =
|
||||
m.NewJSPromise(m.CAST(context), v8::Promise::kRejected, m.SmiConstant(1));
|
||||
m.Return(promise);
|
||||
|
||||
FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
|
||||
@ -2538,7 +2538,7 @@ TEST(PromiseHasHandler) {
|
||||
|
||||
Node* const context = m.Parameter(kNumParams + 2);
|
||||
const TNode<JSPromise> promise =
|
||||
m.AllocateAndInitJSPromise(m.CAST(context), m.UndefinedConstant());
|
||||
m.NewJSPromise(m.CAST(context), m.UndefinedConstant());
|
||||
m.Return(m.SelectBooleanConstant(m.PromiseHasHandler(promise)));
|
||||
|
||||
FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
|
||||
@ -2557,7 +2557,7 @@ TEST(CreatePromiseResolvingFunctionsContext) {
|
||||
const TNode<Context> context = m.CAST(m.Parameter(kNumParams + 2));
|
||||
const TNode<NativeContext> native_context = m.LoadNativeContext(context);
|
||||
const TNode<JSPromise> promise =
|
||||
m.AllocateAndInitJSPromise(context, m.UndefinedConstant());
|
||||
m.NewJSPromise(context, m.UndefinedConstant());
|
||||
const TNode<Context> promise_context =
|
||||
m.CreatePromiseResolvingFunctionsContext(
|
||||
context, promise, m.BooleanConstant(false), native_context);
|
||||
@ -2585,7 +2585,7 @@ TEST(CreatePromiseResolvingFunctions) {
|
||||
Node* const context = m.Parameter(kNumParams + 2);
|
||||
const TNode<NativeContext> native_context = m.LoadNativeContext(context);
|
||||
const TNode<JSPromise> promise =
|
||||
m.AllocateAndInitJSPromise(m.CAST(context), m.UndefinedConstant());
|
||||
m.NewJSPromise(m.CAST(context), m.UndefinedConstant());
|
||||
PromiseResolvingFunctions funcs = m.CreatePromiseResolvingFunctions(
|
||||
m.CAST(context), promise, m.BooleanConstant(false), native_context);
|
||||
Node *resolve = funcs.resolve, *reject = funcs.reject;
|
||||
@ -2675,7 +2675,7 @@ TEST(AllocateFunctionWithMapAndContext) {
|
||||
const TNode<Context> context = m.CAST(m.Parameter(kNumParams + 2));
|
||||
const TNode<NativeContext> native_context = m.LoadNativeContext(context);
|
||||
const TNode<JSPromise> promise =
|
||||
m.AllocateAndInitJSPromise(context, m.UndefinedConstant());
|
||||
m.NewJSPromise(context, m.UndefinedConstant());
|
||||
TNode<Context> promise_context = m.CreatePromiseResolvingFunctionsContext(
|
||||
context, promise, m.BooleanConstant(false), native_context);
|
||||
TNode<Object> resolve_info = m.LoadContextElement(
|
||||
|
Loading…
Reference in New Issue
Block a user