Commit 6f94a8f1 authored by gsathya's avatar gsathya Committed by Commit bot

[promises] Move PromiseReactionJob to c++

This patch results in a 11% improvement over 5 runs in the
bluebird benchmark.

BUG=v8:5343,v8:5046
TBR=bmeurer@chromium.org

Review-Url: https://codereview.chromium.org/2406343002
Cr-Commit-Position: refs/heads/master@{#40239}
parent 38ac7fe6
...@@ -8308,8 +8308,8 @@ class Internals { ...@@ -8308,8 +8308,8 @@ class Internals {
static const int kNodeIsPartiallyDependentShift = 4; static const int kNodeIsPartiallyDependentShift = 4;
static const int kNodeIsActiveShift = 4; static const int kNodeIsActiveShift = 4;
static const int kJSObjectType = 0xb9; static const int kJSObjectType = 0xba;
static const int kJSApiObjectType = 0xb8; static const int kJSApiObjectType = 0xb9;
static const int kFirstNonstringType = 0x80; static const int kFirstNonstringType = 0x80;
static const int kOddballType = 0x83; static const int kOddballType = 0x83;
static const int kForeignType = 0x87; static const int kForeignType = 0x87;
......
...@@ -262,6 +262,7 @@ AstType::bitset AstBitsetType::Lub(i::Map* map) { ...@@ -262,6 +262,7 @@ AstType::bitset AstBitsetType::Lub(i::Map* map) {
case INTERCEPTOR_INFO_TYPE: case INTERCEPTOR_INFO_TYPE:
case CALL_HANDLER_INFO_TYPE: case CALL_HANDLER_INFO_TYPE:
case PROMISE_CONTAINER_TYPE: case PROMISE_CONTAINER_TYPE:
case PROMISE_REACTION_JOB_INFO_TYPE:
case FUNCTION_TEMPLATE_INFO_TYPE: case FUNCTION_TEMPLATE_INFO_TYPE:
case OBJECT_TEMPLATE_INFO_TYPE: case OBJECT_TEMPLATE_INFO_TYPE:
case SIGNATURE_INFO_TYPE: case SIGNATURE_INFO_TYPE:
......
...@@ -265,6 +265,7 @@ Type::bitset BitsetType::Lub(i::Map* map) { ...@@ -265,6 +265,7 @@ Type::bitset BitsetType::Lub(i::Map* map) {
case ALIASED_ARGUMENTS_ENTRY_TYPE: case ALIASED_ARGUMENTS_ENTRY_TYPE:
case BOX_TYPE: case BOX_TYPE:
case PROMISE_CONTAINER_TYPE: case PROMISE_CONTAINER_TYPE:
case PROMISE_REACTION_JOB_INFO_TYPE:
case DEBUG_INFO_TYPE: case DEBUG_INFO_TYPE:
case BREAK_POINT_INFO_TYPE: case BREAK_POINT_INFO_TYPE:
case CELL_TYPE: case CELL_TYPE:
......
...@@ -91,6 +91,7 @@ enum ContextLookupFlags { ...@@ -91,6 +91,7 @@ enum ContextLookupFlags {
V(PROMISE_CATCH_INDEX, JSFunction, promise_catch) \ V(PROMISE_CATCH_INDEX, JSFunction, promise_catch) \
V(PROMISE_CREATE_INDEX, JSFunction, promise_create) \ V(PROMISE_CREATE_INDEX, JSFunction, promise_create) \
V(PROMISE_FUNCTION_INDEX, JSFunction, promise_function) \ V(PROMISE_FUNCTION_INDEX, JSFunction, promise_function) \
V(PROMISE_HANDLE_INDEX, JSFunction, promise_handle) \
V(PROMISE_HAS_USER_DEFINED_REJECT_HANDLER_INDEX, JSFunction, \ V(PROMISE_HAS_USER_DEFINED_REJECT_HANDLER_INDEX, JSFunction, \
promise_has_user_defined_reject_handler) \ promise_has_user_defined_reject_handler) \
V(PROMISE_REJECT_INDEX, JSFunction, promise_reject) \ V(PROMISE_REJECT_INDEX, JSFunction, promise_reject) \
......
...@@ -938,6 +938,21 @@ Handle<PromiseContainer> Factory::NewPromiseContainer( ...@@ -938,6 +938,21 @@ Handle<PromiseContainer> Factory::NewPromiseContainer(
return result; return result;
} }
Handle<PromiseReactionJobInfo> Factory::NewPromiseReactionJobInfo(
Handle<Object> value, Handle<Object> tasks, Handle<Object> deferred,
Handle<Object> before_debug_event, Handle<Object> after_debug_event,
Handle<Context> context) {
Handle<PromiseReactionJobInfo> result = Handle<PromiseReactionJobInfo>::cast(
NewStruct(PROMISE_REACTION_JOB_INFO_TYPE));
result->set_value(*value);
result->set_tasks(*tasks);
result->set_deferred(*deferred);
result->set_before_debug_event(*before_debug_event);
result->set_after_debug_event(*after_debug_event);
result->set_context(*context);
return result;
}
Handle<AliasedArgumentsEntry> Factory::NewAliasedArgumentsEntry( Handle<AliasedArgumentsEntry> Factory::NewAliasedArgumentsEntry(
int aliased_context_slot) { int aliased_context_slot) {
Handle<AliasedArgumentsEntry> entry = Handle<AliasedArgumentsEntry>::cast( Handle<AliasedArgumentsEntry> entry = Handle<AliasedArgumentsEntry>::cast(
......
...@@ -60,6 +60,12 @@ class Factory final { ...@@ -60,6 +60,12 @@ class Factory final {
// Create a new boxed value. // Create a new boxed value.
Handle<Box> NewBox(Handle<Object> value); Handle<Box> NewBox(Handle<Object> value);
// Create a new PromiseReactionJobInfo struct.
Handle<PromiseReactionJobInfo> NewPromiseReactionJobInfo(
Handle<Object> value, Handle<Object> tasks, Handle<Object> deferred,
Handle<Object> before_debug, Handle<Object> after_debug_event,
Handle<Context> context);
// Create a new PromiseContainer struct. // Create a new PromiseContainer struct.
Handle<PromiseContainer> NewPromiseContainer( Handle<PromiseContainer> NewPromiseContainer(
Handle<JSReceiver> thenable, Handle<JSReceiver> then, Handle<JSReceiver> thenable, Handle<JSReceiver> then,
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "src/crankshaft/hydrogen.h" #include "src/crankshaft/hydrogen.h"
#include "src/debug/debug.h" #include "src/debug/debug.h"
#include "src/deoptimizer.h" #include "src/deoptimizer.h"
#include "src/elements.h"
#include "src/external-reference-table.h" #include "src/external-reference-table.h"
#include "src/frames-inl.h" #include "src/frames-inl.h"
#include "src/ic/access-compiler-data.h" #include "src/ic/access-compiler-data.h"
...@@ -3066,15 +3067,80 @@ void Isolate::ReportPromiseReject(Handle<JSObject> promise, ...@@ -3066,15 +3067,80 @@ void Isolate::ReportPromiseReject(Handle<JSObject> promise,
v8::Utils::StackTraceToLocal(stack_trace))); v8::Utils::StackTraceToLocal(stack_trace)));
} }
namespace {
class PromiseDebugEventScope {
public:
PromiseDebugEventScope(Isolate* isolate, Object* before, Object* after)
: isolate_(isolate),
after_(after, isolate_),
is_debug_active_(isolate_->debug()->is_active() &&
before->IsJSObject() && after->IsJSObject()) {
if (is_debug_active_) {
isolate_->debug()->OnAsyncTaskEvent(
handle(JSObject::cast(before), isolate_));
}
}
~PromiseDebugEventScope() {
if (is_debug_active_) {
isolate_->debug()->OnAsyncTaskEvent(Handle<JSObject>::cast(after_));
}
}
private:
Isolate* isolate_;
Handle<Object> after_;
bool is_debug_active_;
};
} // namespace
void Isolate::PromiseReactionJob(Handle<PromiseReactionJobInfo> info,
MaybeHandle<Object>* result,
MaybeHandle<Object>* maybe_exception) {
PromiseDebugEventScope helper(this, info->before_debug_event(),
info->after_debug_event());
Handle<Object> value(info->value(), this);
Handle<Object> tasks(info->tasks(), this);
Handle<JSFunction> promise_handle_fn = promise_handle();
Handle<Object> undefined = factory()->undefined_value();
// If tasks is an array we have multiple onFulfilled/onRejected callbacks
// associated with the promise. The deferred object for each callback
// is attached to this array as well.
// Otherwise, there is a single callback and the deferred object is attached
// directly to PromiseReactionJobInfo.
if (tasks->IsJSArray()) {
Handle<JSArray> array = Handle<JSArray>::cast(tasks);
DCHECK(array->length()->IsSmi());
int length = Smi::cast(array->length())->value();
ElementsAccessor* accessor = array->GetElementsAccessor();
DCHECK(length % 2 == 0);
for (int i = 0; i < length; i += 2) {
DCHECK(accessor->HasElement(array, i));
DCHECK(accessor->HasElement(array, i + 1));
Handle<Object> argv[] = {value, accessor->Get(array, i),
accessor->Get(array, i + 1)};
*result = Execution::TryCall(this, promise_handle_fn, undefined,
arraysize(argv), argv, maybe_exception);
// If execution is terminating, just bail out.
if (result->is_null() && maybe_exception->is_null()) {
return;
}
}
} else {
Handle<Object> deferred(info->deferred(), this);
Handle<Object> argv[] = {value, tasks, deferred};
*result = Execution::TryCall(this, promise_handle_fn, undefined,
arraysize(argv), argv, maybe_exception);
}
}
void Isolate::PromiseResolveThenableJob(Handle<PromiseContainer> container, void Isolate::PromiseResolveThenableJob(Handle<PromiseContainer> container,
MaybeHandle<Object>* result, MaybeHandle<Object>* result,
MaybeHandle<Object>* maybe_exception) { MaybeHandle<Object>* maybe_exception) {
if (debug()->is_active()) { PromiseDebugEventScope helper(this, container->before_debug_event(),
Handle<Object> before_debug_event(container->before_debug_event(), this); container->after_debug_event());
if (before_debug_event->IsJSObject()) {
debug()->OnAsyncTaskEvent(Handle<JSObject>::cast(before_debug_event));
}
}
Handle<JSReceiver> thenable(container->thenable(), this); Handle<JSReceiver> thenable(container->thenable(), this);
Handle<JSFunction> resolve(container->resolve(), this); Handle<JSFunction> resolve(container->resolve(), this);
...@@ -3092,18 +3158,12 @@ void Isolate::PromiseResolveThenableJob(Handle<PromiseContainer> container, ...@@ -3092,18 +3158,12 @@ void Isolate::PromiseResolveThenableJob(Handle<PromiseContainer> container,
Execution::TryCall(this, reject, factory()->undefined_value(), Execution::TryCall(this, reject, factory()->undefined_value(),
arraysize(reason_arg), reason_arg, maybe_exception); arraysize(reason_arg), reason_arg, maybe_exception);
} }
if (debug()->is_active()) {
Handle<Object> after_debug_event(container->after_debug_event(), this);
if (after_debug_event->IsJSObject()) {
debug()->OnAsyncTaskEvent(Handle<JSObject>::cast(after_debug_event));
}
}
} }
void Isolate::EnqueueMicrotask(Handle<Object> microtask) { void Isolate::EnqueueMicrotask(Handle<Object> microtask) {
DCHECK(microtask->IsJSFunction() || microtask->IsCallHandlerInfo() || DCHECK(microtask->IsJSFunction() || microtask->IsCallHandlerInfo() ||
microtask->IsPromiseContainer()); microtask->IsPromiseContainer() ||
microtask->IsPromiseReactionJobInfo());
Handle<FixedArray> queue(heap()->microtask_queue(), this); Handle<FixedArray> queue(heap()->microtask_queue(), this);
int num_tasks = pending_microtask_count(); int num_tasks = pending_microtask_count();
DCHECK(num_tasks <= queue->length()); DCHECK(num_tasks <= queue->length());
...@@ -3155,11 +3215,16 @@ void Isolate::RunMicrotasksInternal() { ...@@ -3155,11 +3215,16 @@ void Isolate::RunMicrotasksInternal() {
callback(data); callback(data);
} else { } else {
SaveContext save(this); SaveContext save(this);
Context* context = microtask->IsJSFunction() Context* context;
? Handle<JSFunction>::cast(microtask)->context() if (microtask->IsJSFunction()) {
: Handle<PromiseContainer>::cast(microtask) context = Handle<JSFunction>::cast(microtask)->context();
->resolve() } else if (microtask->IsPromiseContainer()) {
->context(); context =
Handle<PromiseContainer>::cast(microtask)->resolve()->context();
} else {
context = Handle<PromiseReactionJobInfo>::cast(microtask)->context();
}
set_context(context->native_context()); set_context(context->native_context());
handle_scope_implementer_->EnterMicrotaskContext( handle_scope_implementer_->EnterMicrotaskContext(
Handle<Context>(context, this)); Handle<Context>(context, this));
...@@ -3173,9 +3238,12 @@ void Isolate::RunMicrotasksInternal() { ...@@ -3173,9 +3238,12 @@ void Isolate::RunMicrotasksInternal() {
result = Execution::TryCall(this, microtask_function, result = Execution::TryCall(this, microtask_function,
factory()->undefined_value(), 0, NULL, factory()->undefined_value(), 0, NULL,
&maybe_exception); &maybe_exception);
} else { } else if (microtask->IsPromiseContainer()) {
PromiseResolveThenableJob(Handle<PromiseContainer>::cast(microtask), PromiseResolveThenableJob(Handle<PromiseContainer>::cast(microtask),
&result, &maybe_exception); &result, &maybe_exception);
} else {
PromiseReactionJob(Handle<PromiseReactionJobInfo>::cast(microtask),
&result, &maybe_exception);
} }
handle_scope_implementer_->LeaveMicrotaskContext(); handle_scope_implementer_->LeaveMicrotaskContext();
......
...@@ -1109,6 +1109,9 @@ class Isolate { ...@@ -1109,6 +1109,9 @@ class Isolate {
void ReportPromiseReject(Handle<JSObject> promise, Handle<Object> value, void ReportPromiseReject(Handle<JSObject> promise, Handle<Object> value,
v8::PromiseRejectEvent event); v8::PromiseRejectEvent event);
void PromiseReactionJob(Handle<PromiseReactionJobInfo> info,
MaybeHandle<Object>* result,
MaybeHandle<Object>* maybe_exception);
void PromiseResolveThenableJob(Handle<PromiseContainer> container, void PromiseResolveThenableJob(Handle<PromiseContainer> container,
MaybeHandle<Object>* result, MaybeHandle<Object>* result,
MaybeHandle<Object>* maybe_exception); MaybeHandle<Object>* maybe_exception);
......
...@@ -185,22 +185,8 @@ function PromiseHandle(value, handler, deferred) { ...@@ -185,22 +185,8 @@ function PromiseHandle(value, handler, deferred) {
} }
function PromiseEnqueue(value, tasks, deferreds, status) { function PromiseEnqueue(value, tasks, deferreds, status) {
var id, name, instrumenting = DEBUG_IS_ACTIVE; var id, name, beforeDebug, afterDebug, instrumenting = DEBUG_IS_ACTIVE;
%EnqueueMicrotask(function() {
if (instrumenting) {
%DebugAsyncTaskEvent({ type: "willHandle", id: id, name: name });
}
if (IS_ARRAY(tasks)) {
for (var i = 0; i < tasks.length; i += 2) {
PromiseHandle(value, tasks[i], tasks[i + 1]);
}
} else {
PromiseHandle(value, tasks, deferreds);
}
if (instrumenting) {
%DebugAsyncTaskEvent({ type: "didHandle", id: id, name: name });
}
});
if (instrumenting) { if (instrumenting) {
// In an async function, reuse the existing stack related to the outer // In an async function, reuse the existing stack related to the outer
// Promise. Otherwise, e.g. in a direct call to then, save a new stack. // Promise. Otherwise, e.g. in a direct call to then, save a new stack.
...@@ -220,7 +206,12 @@ function PromiseEnqueue(value, tasks, deferreds, status) { ...@@ -220,7 +206,12 @@ function PromiseEnqueue(value, tasks, deferreds, status) {
name = status === kFulfilled ? "Promise.resolve" : "Promise.reject"; name = status === kFulfilled ? "Promise.resolve" : "Promise.reject";
%DebugAsyncTaskEvent({ type: "enqueue", id: id, name: name }); %DebugAsyncTaskEvent({ type: "enqueue", id: id, name: name });
} }
beforeDebug = { type: "willHandle", id: id, name: name };
afterDebug = { type: "didHandle", id: id, name: name };
} }
%EnqueuePromiseReactionJob(value, tasks, deferreds, beforeDebug, afterDebug);
} }
function PromiseAttachCallbacks(promise, deferred, onResolve, onReject) { function PromiseAttachCallbacks(promise, deferred, onResolve, onReject) {
...@@ -698,7 +689,8 @@ utils.InstallFunctions(GlobalPromise.prototype, DONT_ENUM, [ ...@@ -698,7 +689,8 @@ utils.InstallFunctions(GlobalPromise.prototype, DONT_ENUM, [
"promise_has_user_defined_reject_handler", PromiseHasUserDefinedRejectHandler, "promise_has_user_defined_reject_handler", PromiseHasUserDefinedRejectHandler,
"promise_reject", DoRejectPromise, "promise_reject", DoRejectPromise,
"promise_resolve", ResolvePromise, "promise_resolve", ResolvePromise,
"promise_then", PromiseThen "promise_then", PromiseThen,
"promise_handle", PromiseHandle
]); ]);
// This allows extras to create promises quickly without building extra // This allows extras to create promises quickly without building extra
......
...@@ -922,6 +922,19 @@ void PromiseContainer::PromiseContainerVerify() { ...@@ -922,6 +922,19 @@ void PromiseContainer::PromiseContainerVerify() {
after_debug_event()->ObjectVerify(); after_debug_event()->ObjectVerify();
} }
void PromiseReactionJobInfo::PromiseReactionJobInfoVerify() {
Isolate* isolate = GetIsolate();
CHECK(IsPromiseReactionJobInfo());
CHECK(value()->IsObject());
CHECK(tasks()->IsJSArray() || tasks()->IsCallable());
CHECK(deferred()->IsJSObject() || deferred()->IsUndefined(isolate));
CHECK(before_debug_event()->IsJSObject() ||
before_debug_event()->IsUndefined(isolate));
CHECK(after_debug_event()->IsJSObject() ||
after_debug_event()->IsUndefined(isolate));
CHECK(context()->IsContext());
}
void JSModuleNamespace::JSModuleNamespaceVerify() { void JSModuleNamespace::JSModuleNamespaceVerify() {
CHECK(IsJSModuleNamespace()); CHECK(IsJSModuleNamespace());
module()->ObjectVerify(); module()->ObjectVerify();
......
...@@ -5661,6 +5661,15 @@ ACCESSORS(PromiseContainer, reject, JSFunction, kRejectOffset) ...@@ -5661,6 +5661,15 @@ ACCESSORS(PromiseContainer, reject, JSFunction, kRejectOffset)
ACCESSORS(PromiseContainer, before_debug_event, Object, kBeforeDebugEventOffset) ACCESSORS(PromiseContainer, before_debug_event, Object, kBeforeDebugEventOffset)
ACCESSORS(PromiseContainer, after_debug_event, Object, kAfterDebugEventOffset) ACCESSORS(PromiseContainer, after_debug_event, Object, kAfterDebugEventOffset)
ACCESSORS(PromiseReactionJobInfo, value, Object, kValueOffset);
ACCESSORS(PromiseReactionJobInfo, tasks, Object, kTasksOffset);
ACCESSORS(PromiseReactionJobInfo, deferred, Object, kDeferredOffset);
ACCESSORS(PromiseReactionJobInfo, before_debug_event, Object,
kBeforeDebugEventOffset);
ACCESSORS(PromiseReactionJobInfo, after_debug_event, Object,
kAfterDebugEventOffset);
ACCESSORS(PromiseReactionJobInfo, context, Context, kContextOffset);
Map* PrototypeInfo::ObjectCreateMap() { Map* PrototypeInfo::ObjectCreateMap() {
return Map::cast(WeakCell::cast(object_create_map())->value()); return Map::cast(WeakCell::cast(object_create_map())->value());
} }
......
...@@ -1161,6 +1161,18 @@ void PromiseContainer::PromiseContainerPrint(std::ostream& os) { // NOLINT ...@@ -1161,6 +1161,18 @@ void PromiseContainer::PromiseContainerPrint(std::ostream& os) { // NOLINT
os << "\n"; os << "\n";
} }
void PromiseReactionJobInfo::PromiseReactionJobInfoPrint(
std::ostream& os) { // NOLINT
HeapObject::PrintHeader(os, "PromiseReactionJobInfo");
os << "\n - value: " << Brief(value());
os << "\n - tasks: " << Brief(tasks());
os << "\n - deferred: " << Brief(deferred());
os << "\n - before debug event: " << Brief(before_debug_event());
os << "\n - after debug event: " << Brief(after_debug_event());
os << "\n - reaction context: " << Brief(context());
os << "\n";
}
void Module::ModulePrint(std::ostream& os) { // NOLINT void Module::ModulePrint(std::ostream& os) { // NOLINT
HeapObject::PrintHeader(os, "Module"); HeapObject::PrintHeader(os, "Module");
os << "\n - code: " << Brief(code()); os << "\n - code: " << Brief(code());
......
...@@ -143,6 +143,8 @@ ...@@ -143,6 +143,8 @@
// - Struct // - Struct
// - Box // - Box
// - AccessorInfo // - AccessorInfo
// - PromiseContainer
// - PromiseReactionJobInfo
// - AccessorPair // - AccessorPair
// - AccessCheckInfo // - AccessCheckInfo
// - InterceptorInfo // - InterceptorInfo
...@@ -399,6 +401,7 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1; ...@@ -399,6 +401,7 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1;
V(ALIASED_ARGUMENTS_ENTRY_TYPE) \ V(ALIASED_ARGUMENTS_ENTRY_TYPE) \
V(BOX_TYPE) \ V(BOX_TYPE) \
V(PROMISE_CONTAINER_TYPE) \ V(PROMISE_CONTAINER_TYPE) \
V(PROMISE_REACTION_JOB_INFO_TYPE) \
V(PROTOTYPE_INFO_TYPE) \ V(PROTOTYPE_INFO_TYPE) \
V(CONTEXT_EXTENSION_TYPE) \ V(CONTEXT_EXTENSION_TYPE) \
V(MODULE_TYPE) \ V(MODULE_TYPE) \
...@@ -506,6 +509,8 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1; ...@@ -506,6 +509,8 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1;
#define STRUCT_LIST(V) \ #define STRUCT_LIST(V) \
V(BOX, Box, box) \ V(BOX, Box, box) \
V(PROMISE_CONTAINER, PromiseContainer, promise_container) \ V(PROMISE_CONTAINER, PromiseContainer, promise_container) \
V(PROMISE_REACTION_JOB_INFO, PromiseReactionJobInfo, \
promise_reaction_job_info) \
V(ACCESSOR_INFO, AccessorInfo, accessor_info) \ V(ACCESSOR_INFO, AccessorInfo, accessor_info) \
V(ACCESSOR_PAIR, AccessorPair, accessor_pair) \ V(ACCESSOR_PAIR, AccessorPair, accessor_pair) \
V(ACCESS_CHECK_INFO, AccessCheckInfo, access_check_info) \ V(ACCESS_CHECK_INFO, AccessCheckInfo, access_check_info) \
...@@ -688,6 +693,7 @@ enum InstanceType { ...@@ -688,6 +693,7 @@ enum InstanceType {
ALIASED_ARGUMENTS_ENTRY_TYPE, ALIASED_ARGUMENTS_ENTRY_TYPE,
BOX_TYPE, BOX_TYPE,
PROMISE_CONTAINER_TYPE, PROMISE_CONTAINER_TYPE,
PROMISE_REACTION_JOB_INFO_TYPE,
DEBUG_INFO_TYPE, DEBUG_INFO_TYPE,
BREAK_POINT_INFO_TYPE, BREAK_POINT_INFO_TYPE,
FIXED_ARRAY_TYPE, FIXED_ARRAY_TYPE,
...@@ -6675,9 +6681,8 @@ class Struct: public HeapObject { ...@@ -6675,9 +6681,8 @@ class Struct: public HeapObject {
DECLARE_CAST(Struct) DECLARE_CAST(Struct)
}; };
// A container struct to hold state required for // A container struct to hold state required for PromiseResolveThenableJob.
// PromiseResolveThenableJob. {before, after}_debug_event could // TODO(gsathya): Rename this to be less generic.
// potentially be undefined if the debugger is turned off.
class PromiseContainer : public Struct { class PromiseContainer : public Struct {
public: public:
DECL_ACCESSORS(thenable, JSReceiver) DECL_ACCESSORS(thenable, JSReceiver)
...@@ -6704,6 +6709,33 @@ class PromiseContainer : public Struct { ...@@ -6704,6 +6709,33 @@ class PromiseContainer : public Struct {
DISALLOW_IMPLICIT_CONSTRUCTORS(PromiseContainer); DISALLOW_IMPLICIT_CONSTRUCTORS(PromiseContainer);
}; };
// Struct to hold state required for PromiseReactionJob.
class PromiseReactionJobInfo : public Struct {
public:
DECL_ACCESSORS(value, Object)
DECL_ACCESSORS(tasks, Object)
DECL_ACCESSORS(deferred, Object)
DECL_ACCESSORS(before_debug_event, Object)
DECL_ACCESSORS(after_debug_event, Object)
DECL_ACCESSORS(context, Context)
static const int kValueOffset = Struct::kHeaderSize;
static const int kTasksOffset = kValueOffset + kPointerSize;
static const int kDeferredOffset = kTasksOffset + kPointerSize;
static const int kBeforeDebugEventOffset = kDeferredOffset + kPointerSize;
static const int kAfterDebugEventOffset =
kBeforeDebugEventOffset + kPointerSize;
static const int kContextOffset = kAfterDebugEventOffset + kPointerSize;
static const int kSize = kContextOffset + kPointerSize;
DECLARE_CAST(PromiseReactionJobInfo)
DECLARE_PRINTER(PromiseReactionJobInfo)
DECLARE_VERIFIER(PromiseReactionJobInfo)
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(PromiseReactionJobInfo);
};
// A simple one-element struct, useful where smis need to be boxed. // A simple one-element struct, useful where smis need to be boxed.
class Box : public Struct { class Box : public Struct {
public: public:
......
...@@ -571,6 +571,22 @@ RUNTIME_FUNCTION(Runtime_GetAndResetRuntimeCallStats) { ...@@ -571,6 +571,22 @@ RUNTIME_FUNCTION(Runtime_GetAndResetRuntimeCallStats) {
} }
} }
RUNTIME_FUNCTION(Runtime_EnqueuePromiseReactionJob) {
HandleScope scope(isolate);
DCHECK(args.length() == 5);
CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, tasks, 1);
CONVERT_ARG_HANDLE_CHECKED(Object, deferred, 2);
CONVERT_ARG_HANDLE_CHECKED(Object, before_debug_event, 3);
CONVERT_ARG_HANDLE_CHECKED(Object, after_debug_event, 4);
Handle<PromiseReactionJobInfo> info =
isolate->factory()->NewPromiseReactionJobInfo(
value, tasks, deferred, before_debug_event, after_debug_event,
isolate->native_context());
isolate->EnqueueMicrotask(info);
return isolate->heap()->undefined_value();
}
RUNTIME_FUNCTION(Runtime_EnqueuePromiseResolveThenableJob) { RUNTIME_FUNCTION(Runtime_EnqueuePromiseResolveThenableJob) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK(args.length() == 6); DCHECK(args.length() == 6);
......
...@@ -290,6 +290,7 @@ namespace internal { ...@@ -290,6 +290,7 @@ namespace internal {
F(CheckIsBootstrapping, 0, 1) \ F(CheckIsBootstrapping, 0, 1) \
F(CreateListFromArrayLike, 1, 1) \ F(CreateListFromArrayLike, 1, 1) \
F(EnqueueMicrotask, 1, 1) \ F(EnqueueMicrotask, 1, 1) \
F(EnqueuePromiseReactionJob, 5, 1) \
F(EnqueuePromiseResolveThenableJob, 6, 1) \ F(EnqueuePromiseResolveThenableJob, 6, 1) \
F(GetAndResetRuntimeCallStats, -1 /* <= 2 */, 1) \ F(GetAndResetRuntimeCallStats, -1 /* <= 2 */, 1) \
F(ExportExperimentalFromRuntime, 1, 1) \ F(ExportExperimentalFromRuntime, 1, 1) \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment