Commit dd3c4fca authored by Marja Hölttä's avatar Marja Hölttä Committed by Commit Bot

[objects.h splitting] Move Promise-related classes.

BUG=v8:5402,v8:7310

Change-Id: Ic3ee7d2dec0403e7831f51735365c26caadc6a7b
Reviewed-on: https://chromium-review.googlesource.com/934136
Commit-Queue: Marja Hölttä <marja@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51565}
parent d18125e7
......@@ -1861,6 +1861,8 @@ v8_source_set("v8_base") {
"src/objects/js-array.h",
"src/objects/js-collection-inl.h",
"src/objects/js-collection.h",
"src/objects/js-promise-inl.h",
"src/objects/js-promise.h",
"src/objects/js-regexp-inl.h",
"src/objects/js-regexp.h",
"src/objects/literal-objects-inl.h",
......@@ -1875,6 +1877,8 @@ v8_source_set("v8_base") {
"src/objects/name.h",
"src/objects/object-macros-undef.h",
"src/objects/object-macros.h",
"src/objects/promise-inl.h",
"src/objects/promise.h",
"src/objects/property-descriptor-object-inl.h",
"src/objects/property-descriptor-object.h",
"src/objects/regexp-match-info.h",
......
......@@ -7,6 +7,7 @@
#include "src/code-stub-assembler.h"
#include "src/contexts.h"
#include "src/objects/promise.h"
namespace v8 {
namespace internal {
......
......@@ -31,6 +31,11 @@ class JSCollection;
class JSWeakCollection;
class JSWeakMap;
class JSWeakSet;
class PromiseCapability;
class PromiseFulfillReactionJobTask;
class PromiseReaction;
class PromiseReactionJobTask;
class PromiseRejectReactionJobTask;
class Factory;
class Zone;
......
......@@ -18,6 +18,7 @@
#include "src/objects/debug-objects-inl.h"
#include "src/objects/frame-array-inl.h"
#include "src/objects/module.h"
#include "src/objects/promise-inl.h"
#include "src/objects/scope-info.h"
#include "src/unicode-cache.h"
#include "src/unicode-decoder.h"
......
......@@ -40,6 +40,7 @@ class JSWeakMap;
class NewFunctionArgs;
struct SourceRange;
class PreParsedScopeData;
class PromiseResolveThenableJobTask;
class TemplateObjectDescription;
enum FunctionMode {
......
......@@ -42,6 +42,7 @@
#include "src/log.h"
#include "src/messages.h"
#include "src/objects/frame-array-inl.h"
#include "src/objects/promise-inl.h"
#include "src/profiler/cpu-profiler.h"
#include "src/prototype.h"
#include "src/regexp/regexp-stack.h"
......
......@@ -18,6 +18,7 @@
#include "src/objects/debug-objects-inl.h"
#include "src/objects/literal-objects.h"
#include "src/objects/module.h"
#include "src/objects/promise-inl.h"
#include "src/ostreams.h"
#include "src/regexp/jsregexp.h"
#include "src/transitions.h"
......
......@@ -40,6 +40,7 @@
#include "src/objects/hash-table.h"
#include "src/objects/js-array-inl.h"
#include "src/objects/js-collection-inl.h"
#include "src/objects/js-promise-inl.h"
#include "src/objects/js-regexp-inl.h"
#include "src/objects/literal-objects.h"
#include "src/objects/module-inl.h"
......@@ -101,7 +102,6 @@ TYPE_CHECKER(JSError, JS_ERROR_TYPE)
TYPE_CHECKER(JSFunction, JS_FUNCTION_TYPE)
TYPE_CHECKER(JSGlobalObject, JS_GLOBAL_OBJECT_TYPE)
TYPE_CHECKER(JSMessageObject, JS_MESSAGE_OBJECT_TYPE)
TYPE_CHECKER(JSPromise, JS_PROMISE_TYPE)
TYPE_CHECKER(JSStringIterator, JS_STRING_ITERATOR_TYPE)
TYPE_CHECKER(JSValue, JS_VALUE_TYPE)
TYPE_CHECKER(MutableHeapNumber, MUTABLE_HEAP_NUMBER_TYPE)
......@@ -600,7 +600,6 @@ CAST_ACCESSOR(JSGlobalObject)
CAST_ACCESSOR(JSGlobalProxy)
CAST_ACCESSOR(JSMessageObject)
CAST_ACCESSOR(JSObject)
CAST_ACCESSOR(JSPromise)
CAST_ACCESSOR(JSProxy)
CAST_ACCESSOR(JSReceiver)
CAST_ACCESSOR(JSStringIterator)
......@@ -617,12 +616,6 @@ CAST_ACCESSOR(ObjectTemplateInfo)
CAST_ACCESSOR(Oddball)
CAST_ACCESSOR(OrderedHashMap)
CAST_ACCESSOR(OrderedHashSet)
CAST_ACCESSOR(PromiseCapability)
CAST_ACCESSOR(PromiseReaction)
CAST_ACCESSOR(PromiseReactionJobTask)
CAST_ACCESSOR(PromiseFulfillReactionJobTask)
CAST_ACCESSOR(PromiseRejectReactionJobTask)
CAST_ACCESSOR(PromiseResolveThenableJobTask)
CAST_ACCESSOR(PropertyArray)
CAST_ACCESSOR(PropertyCell)
CAST_ACCESSOR(PrototypeInfo)
......@@ -2301,11 +2294,6 @@ bool AccessorInfo::has_getter() {
return result;
}
ACCESSORS(PromiseReaction, next, Object, kNextOffset)
ACCESSORS(PromiseReaction, reject_handler, HeapObject, kRejectHandlerOffset)
ACCESSORS(PromiseReaction, fulfill_handler, HeapObject, kFulfillHandlerOffset)
ACCESSORS(PromiseReaction, payload, HeapObject, kPayloadOffset)
ACCESSORS(AsyncGeneratorRequest, next, Object, kNextOffset)
SMI_ACCESSORS(AsyncGeneratorRequest, resume_mode, kResumeModeOffset)
ACCESSORS(AsyncGeneratorRequest, value, Object, kValueOffset)
......@@ -2813,36 +2801,6 @@ ACCESSORS(CallableTask, context, Context, kContextOffset)
ACCESSORS(CallbackTask, callback, Foreign, kCallbackOffset)
ACCESSORS(CallbackTask, data, Foreign, kDataOffset)
ACCESSORS(PromiseResolveThenableJobTask, context, Context, kContextOffset)
ACCESSORS(PromiseResolveThenableJobTask, promise_to_resolve, JSPromise,
kPromiseToResolveOffset)
ACCESSORS(PromiseResolveThenableJobTask, then, JSReceiver, kThenOffset)
ACCESSORS(PromiseResolveThenableJobTask, thenable, JSReceiver, kThenableOffset)
ACCESSORS(PromiseReactionJobTask, context, Context, kContextOffset)
ACCESSORS(PromiseReactionJobTask, argument, Object, kArgumentOffset);
ACCESSORS(PromiseReactionJobTask, handler, HeapObject, kHandlerOffset);
ACCESSORS(PromiseReactionJobTask, payload, HeapObject, kPayloadOffset);
ACCESSORS(PromiseCapability, promise, HeapObject, kPromiseOffset)
ACCESSORS(PromiseCapability, resolve, Object, kResolveOffset)
ACCESSORS(PromiseCapability, reject, Object, kRejectOffset)
ACCESSORS(JSPromise, reactions_or_result, Object, kReactionsOrResultOffset)
SMI_ACCESSORS(JSPromise, flags, kFlagsOffset)
BOOL_ACCESSORS(JSPromise, flags, has_handler, kHasHandlerBit)
BOOL_ACCESSORS(JSPromise, flags, handled_hint, kHandledHintBit)
Object* JSPromise::result() const {
DCHECK_NE(Promise::kPending, status());
return reactions_or_result();
}
Object* JSPromise::reactions() const {
DCHECK_EQ(Promise::kPending, status());
return reactions_or_result();
}
ElementsKind JSObject::GetElementsKind() {
ElementsKind kind = map()->elements_kind();
#if VERIFY_HEAP && DEBUG
......
......@@ -13,6 +13,7 @@
#include "src/interpreter/bytecodes.h"
#include "src/objects-inl.h"
#include "src/objects/debug-objects-inl.h"
#include "src/objects/promise-inl.h"
#include "src/ostreams.h"
#include "src/regexp/jsregexp.h"
#include "src/transitions-inl.h"
......
......@@ -60,6 +60,7 @@
#include "src/objects/frame-array-inl.h"
#include "src/objects/hash-table.h"
#include "src/objects/map.h"
#include "src/objects/promise-inl.h"
#include "src/parsing/preparsed-scope-data.h"
#include "src/property-descriptor.h"
#include "src/prototype.h"
......
......@@ -2946,153 +2946,6 @@ class CallableTask : public Microtask {
DISALLOW_IMPLICIT_CONSTRUCTORS(CallableTask);
};
// Struct to hold state required for PromiseReactionJob. See the comment on the
// PromiseReaction below for details on how this is being managed to reduce the
// memory and allocation overhead. This is the base class for the concrete
//
// - PromiseFulfillReactionJobTask
// - PromiseRejectReactionJobTask
//
// classes, which are used to represent either reactions, and we distinguish
// them by their instance types.
class PromiseReactionJobTask : public Microtask {
public:
DECL_ACCESSORS(argument, Object)
DECL_ACCESSORS(context, Context)
// [handler]: This is either a Code object, a Callable or Undefined.
DECL_ACCESSORS(handler, HeapObject)
// [payload]: Usually a JSPromise or a PromiseCapability.
DECL_ACCESSORS(payload, HeapObject)
static const int kArgumentOffset = Microtask::kHeaderSize;
static const int kContextOffset = kArgumentOffset + kPointerSize;
static const int kHandlerOffset = kContextOffset + kPointerSize;
static const int kPayloadOffset = kHandlerOffset + kPointerSize;
static const int kSize = kPayloadOffset + kPointerSize;
// Dispatched behavior.
DECL_CAST(PromiseReactionJobTask)
DECL_VERIFIER(PromiseReactionJobTask)
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(PromiseReactionJobTask);
};
// Struct to hold state required for a PromiseReactionJob of type "Fulfill".
class PromiseFulfillReactionJobTask : public PromiseReactionJobTask {
public:
// Dispatched behavior.
DECL_CAST(PromiseFulfillReactionJobTask)
DECL_PRINTER(PromiseFulfillReactionJobTask)
DECL_VERIFIER(PromiseFulfillReactionJobTask)
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(PromiseFulfillReactionJobTask);
};
// Struct to hold state required for a PromiseReactionJob of type "Reject".
class PromiseRejectReactionJobTask : public PromiseReactionJobTask {
public:
// Dispatched behavior.
DECL_CAST(PromiseRejectReactionJobTask)
DECL_PRINTER(PromiseRejectReactionJobTask)
DECL_VERIFIER(PromiseRejectReactionJobTask)
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(PromiseRejectReactionJobTask);
};
// A container struct to hold state required for PromiseResolveThenableJob.
class PromiseResolveThenableJobTask : public Microtask {
public:
DECL_ACCESSORS(context, Context)
DECL_ACCESSORS(promise_to_resolve, JSPromise)
DECL_ACCESSORS(then, JSReceiver)
DECL_ACCESSORS(thenable, JSReceiver)
static const int kContextOffset = Microtask::kHeaderSize;
static const int kPromiseToResolveOffset = kContextOffset + kPointerSize;
static const int kThenOffset = kPromiseToResolveOffset + kPointerSize;
static const int kThenableOffset = kThenOffset + kPointerSize;
static const int kSize = kThenableOffset + kPointerSize;
// Dispatched behavior.
DECL_CAST(PromiseResolveThenableJobTask)
DECL_PRINTER(PromiseResolveThenableJobTask)
DECL_VERIFIER(PromiseResolveThenableJobTask)
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(PromiseResolveThenableJobTask);
};
// Struct to hold the state of a PromiseCapability.
class PromiseCapability : public Struct {
public:
DECL_ACCESSORS(promise, HeapObject)
DECL_ACCESSORS(resolve, Object)
DECL_ACCESSORS(reject, Object)
static const int kPromiseOffset = Struct::kHeaderSize;
static const int kResolveOffset = kPromiseOffset + kPointerSize;
static const int kRejectOffset = kResolveOffset + kPointerSize;
static const int kSize = kRejectOffset + kPointerSize;
// Dispatched behavior.
DECL_CAST(PromiseCapability)
DECL_PRINTER(PromiseCapability)
DECL_VERIFIER(PromiseCapability)
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(PromiseCapability);
};
// A representation of promise reaction. This differs from the specification
// in that the PromiseReaction here holds both handlers for the fulfill and
// the reject case. When a JSPromise is eventually resolved (either via
// fulfilling it or rejecting it), we morph this PromiseReaction object in
// memory into a proper PromiseReactionJobTask and schedule it on the queue
// of microtasks. So the size of PromiseReaction and the size of the
// PromiseReactionJobTask has to be same for this to work.
//
// The PromiseReaction::payload field usually holds a JSPromise
// instance (in the fast case of a native promise) or a PromiseCapability
// in case of a custom promise. For await we store the JSGeneratorObject
// here and use custom Code handlers.
//
// We need to keep the context in the PromiseReaction so that we can run
// the default handlers (in case they are undefined) in the proper context.
//
// The PromiseReaction objects form a singly-linked list, terminated by
// Smi 0. On the JSPromise instance they are linked in reverse order,
// and are turned into the proper order again when scheduling them on
// the microtask queue.
class PromiseReaction : public Struct {
public:
enum Type { kFulfill, kReject };
DECL_ACCESSORS(next, Object)
// [reject_handler]: This is either a Code object, a Callable or Undefined.
DECL_ACCESSORS(reject_handler, HeapObject)
// [fulfill_handler]: This is either a Code object, a Callable or Undefined.
DECL_ACCESSORS(fulfill_handler, HeapObject)
// [payload]: Usually a JSPromise or a PromiseCapability.
DECL_ACCESSORS(payload, HeapObject)
static const int kNextOffset = Struct::kHeaderSize;
static const int kRejectHandlerOffset = kNextOffset + kPointerSize;
static const int kFulfillHandlerOffset = kRejectHandlerOffset + kPointerSize;
static const int kPayloadOffset = kFulfillHandlerOffset + kPointerSize;
static const int kSize = kPayloadOffset + kPointerSize;
// Dispatched behavior.
DECL_CAST(PromiseReaction)
DECL_PRINTER(PromiseReaction)
DECL_VERIFIER(PromiseReaction)
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(PromiseReaction);
};
class AsyncGeneratorRequest : public Struct {
public:
// Holds an AsyncGeneratorRequest, or Undefined.
......@@ -3984,89 +3837,6 @@ class JSMessageObject: public JSObject {
typedef BodyDescriptor BodyDescriptorWeak;
};
// Representation of promise objects in the specification. Our layout of
// JSPromise differs a bit from the layout in the specification, for example
// there's only a single list of PromiseReaction objects, instead of separate
// lists for fulfill and reject reactions. The PromiseReaction carries both
// callbacks from the start, and is eventually morphed into the proper kind of
// PromiseReactionJobTask when the JSPromise is settled.
//
// We also overlay the result and reactions fields on the JSPromise, since
// the reactions are only necessary for pending promises, whereas the result
// is only meaningful for settled promises.
class JSPromise : public JSObject {
public:
// [reactions_or_result]: Smi 0 terminated list of PromiseReaction objects
// in case the JSPromise was not settled yet, otherwise the result.
DECL_ACCESSORS(reactions_or_result, Object)
// [result]: Checks that the promise is settled and returns the result.
inline Object* result() const;
// [reactions]: Checks that the promise is pending and returns the reactions.
inline Object* reactions() const;
DECL_INT_ACCESSORS(flags)
// [has_handler]: Whether this promise has a reject handler or not.
DECL_BOOLEAN_ACCESSORS(has_handler)
// [handled_hint]: Whether this promise will be handled by a catch
// block in an async function.
DECL_BOOLEAN_ACCESSORS(handled_hint)
static const char* Status(Promise::PromiseState status);
Promise::PromiseState status() const;
void set_status(Promise::PromiseState status);
// ES section #sec-fulfillpromise
static Handle<Object> Fulfill(Handle<JSPromise> promise,
Handle<Object> value);
// ES section #sec-rejectpromise
static Handle<Object> Reject(Handle<JSPromise> promise, Handle<Object> reason,
bool debug_event = true);
// ES section #sec-promise-resolve-functions
MUST_USE_RESULT static MaybeHandle<Object> Resolve(Handle<JSPromise> promise,
Handle<Object> resolution);
// This is a helper that extracts the JSPromise from the input
// {object}, which is used as a payload for PromiseReaction and
// PromiseReactionJobTask.
MUST_USE_RESULT static MaybeHandle<JSPromise> From(Handle<HeapObject> object);
DECL_CAST(JSPromise)
// Dispatched behavior.
DECL_PRINTER(JSPromise)
DECL_VERIFIER(JSPromise)
// Layout description.
static const int kReactionsOrResultOffset = JSObject::kHeaderSize;
static const int kFlagsOffset = kReactionsOrResultOffset + kPointerSize;
static const int kSize = kFlagsOffset + kPointerSize;
static const int kSizeWithEmbedderFields =
kSize + v8::Promise::kEmbedderFieldCount * kPointerSize;
// Flags layout.
// The first two bits store the v8::Promise::PromiseState.
static const int kStatusBits = 2;
static const int kHasHandlerBit = 2;
static const int kHandledHintBit = 3;
static const int kStatusShift = 0;
static const int kStatusMask = 0x3;
STATIC_ASSERT(v8::Promise::kPending == 0);
STATIC_ASSERT(v8::Promise::kFulfilled == 1);
STATIC_ASSERT(v8::Promise::kRejected == 2);
private:
// ES section #sec-triggerpromisereactions
static Handle<Object> TriggerPromiseReactions(Isolate* isolate,
Handle<Object> reactions,
Handle<Object> argument,
PromiseReaction::Type type);
};
class AllocationSite: public Struct {
public:
static const uint32_t kMaximumArrayBytesToPretransition = 8 * 1024;
......
// Copyright 2018 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_OBJECTS_JS_PROMISE_INL_H_
#define V8_OBJECTS_JS_PROMISE_INL_H_
#include "src/objects.h"
#include "src/objects/js-promise.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
namespace v8 {
namespace internal {
TYPE_CHECKER(JSPromise, JS_PROMISE_TYPE)
CAST_ACCESSOR(JSPromise)
ACCESSORS(JSPromise, reactions_or_result, Object, kReactionsOrResultOffset)
SMI_ACCESSORS(JSPromise, flags, kFlagsOffset)
BOOL_ACCESSORS(JSPromise, flags, has_handler, kHasHandlerBit)
BOOL_ACCESSORS(JSPromise, flags, handled_hint, kHandledHintBit)
Object* JSPromise::result() const {
DCHECK_NE(Promise::kPending, status());
return reactions_or_result();
}
Object* JSPromise::reactions() const {
DCHECK_EQ(Promise::kPending, status());
return reactions_or_result();
}
} // namespace internal
} // namespace v8
#include "src/objects/object-macros-undef.h"
#endif // V8_OBJECTS_JS_PROMISE_INL_H_
// Copyright 2018 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_OBJECTS_JS_PROMISE_H_
#define V8_OBJECTS_JS_PROMISE_H_
#include "src/objects.h"
#include "src/objects/promise.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
namespace v8 {
namespace internal {
// Representation of promise objects in the specification. Our layout of
// JSPromise differs a bit from the layout in the specification, for example
// there's only a single list of PromiseReaction objects, instead of separate
// lists for fulfill and reject reactions. The PromiseReaction carries both
// callbacks from the start, and is eventually morphed into the proper kind of
// PromiseReactionJobTask when the JSPromise is settled.
//
// We also overlay the result and reactions fields on the JSPromise, since
// the reactions are only necessary for pending promises, whereas the result
// is only meaningful for settled promises.
class JSPromise : public JSObject {
public:
// [reactions_or_result]: Smi 0 terminated list of PromiseReaction objects
// in case the JSPromise was not settled yet, otherwise the result.
DECL_ACCESSORS(reactions_or_result, Object)
// [result]: Checks that the promise is settled and returns the result.
inline Object* result() const;
// [reactions]: Checks that the promise is pending and returns the reactions.
inline Object* reactions() const;
DECL_INT_ACCESSORS(flags)
// [has_handler]: Whether this promise has a reject handler or not.
DECL_BOOLEAN_ACCESSORS(has_handler)
// [handled_hint]: Whether this promise will be handled by a catch
// block in an async function.
DECL_BOOLEAN_ACCESSORS(handled_hint)
static const char* Status(Promise::PromiseState status);
Promise::PromiseState status() const;
void set_status(Promise::PromiseState status);
// ES section #sec-fulfillpromise
static Handle<Object> Fulfill(Handle<JSPromise> promise,
Handle<Object> value);
// ES section #sec-rejectpromise
static Handle<Object> Reject(Handle<JSPromise> promise, Handle<Object> reason,
bool debug_event = true);
// ES section #sec-promise-resolve-functions
MUST_USE_RESULT static MaybeHandle<Object> Resolve(Handle<JSPromise> promise,
Handle<Object> resolution);
// This is a helper that extracts the JSPromise from the input
// {object}, which is used as a payload for PromiseReaction and
// PromiseReactionJobTask.
MUST_USE_RESULT static MaybeHandle<JSPromise> From(Handle<HeapObject> object);
DECL_CAST(JSPromise)
// Dispatched behavior.
DECL_PRINTER(JSPromise)
DECL_VERIFIER(JSPromise)
// Layout description.
static const int kReactionsOrResultOffset = JSObject::kHeaderSize;
static const int kFlagsOffset = kReactionsOrResultOffset + kPointerSize;
static const int kSize = kFlagsOffset + kPointerSize;
static const int kSizeWithEmbedderFields =
kSize + v8::Promise::kEmbedderFieldCount * kPointerSize;
// Flags layout.
// The first two bits store the v8::Promise::PromiseState.
static const int kStatusBits = 2;
static const int kHasHandlerBit = 2;
static const int kHandledHintBit = 3;
static const int kStatusShift = 0;
static const int kStatusMask = 0x3;
STATIC_ASSERT(v8::Promise::kPending == 0);
STATIC_ASSERT(v8::Promise::kFulfilled == 1);
STATIC_ASSERT(v8::Promise::kRejected == 2);
private:
// ES section #sec-triggerpromisereactions
static Handle<Object> TriggerPromiseReactions(Isolate* isolate,
Handle<Object> reactions,
Handle<Object> argument,
PromiseReaction::Type type);
};
} // namespace internal
} // namespace v8
#include "src/objects/object-macros-undef.h"
#endif // V8_OBJECTS_JS_PROMISE_H_
// Copyright 2018 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_OBJECTS_PROMISE_INL_H_
#define V8_OBJECTS_PROMISE_INL_H_
#include "src/objects/promise.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
namespace v8 {
namespace internal {
CAST_ACCESSOR(PromiseCapability)
CAST_ACCESSOR(PromiseReaction)
CAST_ACCESSOR(PromiseReactionJobTask)
CAST_ACCESSOR(PromiseFulfillReactionJobTask)
CAST_ACCESSOR(PromiseRejectReactionJobTask)
CAST_ACCESSOR(PromiseResolveThenableJobTask)
ACCESSORS(PromiseReaction, next, Object, kNextOffset)
ACCESSORS(PromiseReaction, reject_handler, HeapObject, kRejectHandlerOffset)
ACCESSORS(PromiseReaction, fulfill_handler, HeapObject, kFulfillHandlerOffset)
ACCESSORS(PromiseReaction, payload, HeapObject, kPayloadOffset)
ACCESSORS(PromiseResolveThenableJobTask, context, Context, kContextOffset)
ACCESSORS(PromiseResolveThenableJobTask, promise_to_resolve, JSPromise,
kPromiseToResolveOffset)
ACCESSORS(PromiseResolveThenableJobTask, then, JSReceiver, kThenOffset)
ACCESSORS(PromiseResolveThenableJobTask, thenable, JSReceiver, kThenableOffset)
ACCESSORS(PromiseReactionJobTask, context, Context, kContextOffset)
ACCESSORS(PromiseReactionJobTask, argument, Object, kArgumentOffset);
ACCESSORS(PromiseReactionJobTask, handler, HeapObject, kHandlerOffset);
ACCESSORS(PromiseReactionJobTask, payload, HeapObject, kPayloadOffset);
ACCESSORS(PromiseCapability, promise, HeapObject, kPromiseOffset)
ACCESSORS(PromiseCapability, resolve, Object, kResolveOffset)
ACCESSORS(PromiseCapability, reject, Object, kRejectOffset)
} // namespace internal
} // namespace v8
#include "src/objects/object-macros-undef.h"
#endif // V8_OBJECTS_PROMISE_INL_H_
// Copyright 2018 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_OBJECTS_PROMISE_H_
#define V8_OBJECTS_PROMISE_H_
#include "src/objects.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
namespace v8 {
namespace internal {
// Struct to hold state required for PromiseReactionJob. See the comment on the
// PromiseReaction below for details on how this is being managed to reduce the
// memory and allocation overhead. This is the base class for the concrete
//
// - PromiseFulfillReactionJobTask
// - PromiseRejectReactionJobTask
//
// classes, which are used to represent either reactions, and we distinguish
// them by their instance types.
class PromiseReactionJobTask : public Microtask {
public:
DECL_ACCESSORS(argument, Object)
DECL_ACCESSORS(context, Context)
// [handler]: This is either a Code object, a Callable or Undefined.
DECL_ACCESSORS(handler, HeapObject)
// [payload]: Usually a JSPromise or a PromiseCapability.
DECL_ACCESSORS(payload, HeapObject)
static const int kArgumentOffset = Microtask::kHeaderSize;
static const int kContextOffset = kArgumentOffset + kPointerSize;
static const int kHandlerOffset = kContextOffset + kPointerSize;
static const int kPayloadOffset = kHandlerOffset + kPointerSize;
static const int kSize = kPayloadOffset + kPointerSize;
// Dispatched behavior.
DECL_CAST(PromiseReactionJobTask)
DECL_VERIFIER(PromiseReactionJobTask)
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(PromiseReactionJobTask);
};
// Struct to hold state required for a PromiseReactionJob of type "Fulfill".
class PromiseFulfillReactionJobTask : public PromiseReactionJobTask {
public:
// Dispatched behavior.
DECL_CAST(PromiseFulfillReactionJobTask)
DECL_PRINTER(PromiseFulfillReactionJobTask)
DECL_VERIFIER(PromiseFulfillReactionJobTask)
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(PromiseFulfillReactionJobTask);
};
// Struct to hold state required for a PromiseReactionJob of type "Reject".
class PromiseRejectReactionJobTask : public PromiseReactionJobTask {
public:
// Dispatched behavior.
DECL_CAST(PromiseRejectReactionJobTask)
DECL_PRINTER(PromiseRejectReactionJobTask)
DECL_VERIFIER(PromiseRejectReactionJobTask)
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(PromiseRejectReactionJobTask);
};
// A container struct to hold state required for PromiseResolveThenableJob.
class PromiseResolveThenableJobTask : public Microtask {
public:
DECL_ACCESSORS(context, Context)
DECL_ACCESSORS(promise_to_resolve, JSPromise)
DECL_ACCESSORS(then, JSReceiver)
DECL_ACCESSORS(thenable, JSReceiver)
static const int kContextOffset = Microtask::kHeaderSize;
static const int kPromiseToResolveOffset = kContextOffset + kPointerSize;
static const int kThenOffset = kPromiseToResolveOffset + kPointerSize;
static const int kThenableOffset = kThenOffset + kPointerSize;
static const int kSize = kThenableOffset + kPointerSize;
// Dispatched behavior.
DECL_CAST(PromiseResolveThenableJobTask)
DECL_PRINTER(PromiseResolveThenableJobTask)
DECL_VERIFIER(PromiseResolveThenableJobTask)
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(PromiseResolveThenableJobTask);
};
// Struct to hold the state of a PromiseCapability.
class PromiseCapability : public Struct {
public:
DECL_ACCESSORS(promise, HeapObject)
DECL_ACCESSORS(resolve, Object)
DECL_ACCESSORS(reject, Object)
static const int kPromiseOffset = Struct::kHeaderSize;
static const int kResolveOffset = kPromiseOffset + kPointerSize;
static const int kRejectOffset = kResolveOffset + kPointerSize;
static const int kSize = kRejectOffset + kPointerSize;
// Dispatched behavior.
DECL_CAST(PromiseCapability)
DECL_PRINTER(PromiseCapability)
DECL_VERIFIER(PromiseCapability)
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(PromiseCapability);
};
// A representation of promise reaction. This differs from the specification
// in that the PromiseReaction here holds both handlers for the fulfill and
// the reject case. When a JSPromise is eventually resolved (either via
// fulfilling it or rejecting it), we morph this PromiseReaction object in
// memory into a proper PromiseReactionJobTask and schedule it on the queue
// of microtasks. So the size of PromiseReaction and the size of the
// PromiseReactionJobTask has to be same for this to work.
//
// The PromiseReaction::payload field usually holds a JSPromise
// instance (in the fast case of a native promise) or a PromiseCapability
// in case of a custom promise. For await we store the JSGeneratorObject
// here and use custom Code handlers.
//
// We need to keep the context in the PromiseReaction so that we can run
// the default handlers (in case they are undefined) in the proper context.
//
// The PromiseReaction objects form a singly-linked list, terminated by
// Smi 0. On the JSPromise instance they are linked in reverse order,
// and are turned into the proper order again when scheduling them on
// the microtask queue.
class PromiseReaction : public Struct {
public:
enum Type { kFulfill, kReject };
DECL_ACCESSORS(next, Object)
// [reject_handler]: This is either a Code object, a Callable or Undefined.
DECL_ACCESSORS(reject_handler, HeapObject)
// [fulfill_handler]: This is either a Code object, a Callable or Undefined.
DECL_ACCESSORS(fulfill_handler, HeapObject)
// [payload]: Usually a JSPromise or a PromiseCapability.
DECL_ACCESSORS(payload, HeapObject)
static const int kNextOffset = Struct::kHeaderSize;
static const int kRejectHandlerOffset = kNextOffset + kPointerSize;
static const int kFulfillHandlerOffset = kRejectHandlerOffset + kPointerSize;
static const int kPayloadOffset = kFulfillHandlerOffset + kPointerSize;
static const int kSize = kPayloadOffset + kPointerSize;
// Dispatched behavior.
DECL_CAST(PromiseReaction)
DECL_PRINTER(PromiseReaction)
DECL_VERIFIER(PromiseReaction)
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(PromiseReaction);
};
} // namespace internal
} // namespace v8
#include "src/objects/object-macros-undef.h"
#endif // V8_OBJECTS_PROMISE_H_
......@@ -15,6 +15,7 @@
#include "src/debug/debug.h"
#include "src/isolate.h"
#include "src/objects-inl.h"
#include "src/objects/promise-inl.h"
#include "test/cctest/compiler/code-assembler-tester.h"
#include "test/cctest/compiler/function-tester.h"
......
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