Skip to content

Commit

Permalink
Revert D19318598: Refactor creation of JS objects
Browse files Browse the repository at this point in the history
Differential Revision:
D19318598

Original commit changeset: 5989ebf4ef2d

fbshipit-source-id: ce023f6fb658eac50d5f1bfa75da1b7bbeaaaaf2
  • Loading branch information
Greg Nelson authored and facebook-github-bot committed Jan 14, 2020
1 parent c4d8d8f commit cc56574
Show file tree
Hide file tree
Showing 19 changed files with 251 additions and 275 deletions.
73 changes: 4 additions & 69 deletions include/hermes/VM/JSObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ class JSObject : public GCCell {
parent_(runtime, parent, &runtime->getHeap(), needsBarriers),
clazz_(runtime, clazz, &runtime->getHeap(), needsBarriers),
propStorage_(runtime, nullptr, &runtime->getHeap(), needsBarriers) {
// Direct property slots are initialized by initDirectPropStorage.
// Direct property slots are initialized by allocateSmallPropStorage.
}

/// Until we apply the NeedsBarriers pattern to all subtypes of JSObject, we
Expand All @@ -339,7 +339,7 @@ class JSObject : public GCCell {
JSObject *parent,
HiddenClass *clazz)
: JSObject(runtime, vtp, parent, clazz, GCPointerBase::NoBarriers()) {
// Direct property slots are initialized by initDirectPropStorage.
// Direct property slots are initialized by allocateSmallPropStorage.
}

public:
Expand Down Expand Up @@ -422,7 +422,7 @@ class JSObject : public GCCell {
/// direct property slots.
/// \return a copy of self for convenience.
template <typename T>
static inline T *initDirectPropStorage(T *self);
static inline T *allocateSmallPropStorage(T *self);

/// ES9 9.1 O.[[Extensible]] internal slot
bool isExtensible() const {
Expand Down Expand Up @@ -1464,71 +1464,6 @@ class PropertyAccessor final : public GCCell {
create(Runtime *runtime, Handle<Callable> getter, Handle<Callable> setter);
};

/// Allocation utility for JSObject and its subclasses. Ensures direct property
/// slots are initialized and that no allocation happens during construction.
/// Should be used in a placement new expression, whose result is passed through
/// one of the init* methods:
///
/// JSObjectAlloc<MyObjectType, HasFinalizer::Yes> mem{runtime};
/// return mem.initToHandle(new (mem) MyObjectType(foo(), bar(), baz()));
///
template <typename JSObjectType, HasFinalizer hasFinalizer = HasFinalizer::No>
class JSObjectAlloc {
public:
/// Allocate memory that can hold an instance of JSObjectType.
JSObjectAlloc(Runtime *runtime)
: runtime_(runtime),
mem_(runtime->alloc</*fixedSize*/ true, hasFinalizer>(
cellSize<JSObjectType>())),
noAlloc_(runtime) {}

/// Provides access to the allocated memory for a "placement new" expression.
operator void *() {
return mem_;
}

/// Initialize direct properties of obj and return it in a handle.
Handle<JSObjectType> initToHandle(JSObjectType *obj) {
noAlloc_.release();
return runtime_->makeHandle(init(obj));
}

/// Initialize direct properties of obj and return it in a pseudo-handle.
PseudoHandle<JSObjectType> initToPseudoHandle(JSObjectType *obj) {
noAlloc_.release();
return createPseudoHandle(init(obj));
}

/// Initialize direct properties of obj and return it as a raw HermesValue.
HermesValue initToHermesValue(JSObjectType *obj) {
return HermesValue::encodeObjectValue(init(obj));
}

~JSObjectAlloc() {
assert(!mem_ && "Must call init* at least once");
}

private:
JSObjectType *init(JSObjectType *obj) {
assert(obj == mem_ && "Must call init* no more than once");

// Check that the object looks well-formed.
assert(JSObjectType::classof(obj) && "Mismatched CellKind");

mem_ = nullptr;
return JSObjectType::initDirectPropStorage(obj);
}

/// Runtime used for heap and handle allocation.
Runtime *runtime_;

/// Allocated memory for the object.
void *mem_;

/// Asserts no additional allocation happens until the object is constructed.
NoAllocScope noAlloc_;
};

//===----------------------------------------------------------------------===//
// Object inline methods.

Expand Down Expand Up @@ -1590,7 +1525,7 @@ inline CallResult<PseudoHandle<JSObject>> JSObject::allocatePropStorage(
}

template <typename T>
inline T *JSObject::initDirectPropStorage(T *self) {
inline T *JSObject::allocateSmallPropStorage(T *self) {
constexpr auto count = numOverlapSlots<T>() + T::ANONYMOUS_PROPERTY_SLOTS +
T::NAMED_PROPERTY_SLOTS;
static_assert(
Expand Down
13 changes: 7 additions & 6 deletions include/hermes/VM/SingleObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,14 @@ class SingleObject final : public JSObject {
static CallResult<HermesValue> create(
Runtime *runtime,
Handle<JSObject> parentHandle) {
JSObjectAlloc<SingleObject> mem{runtime};
return mem.initToHermesValue(new (mem) SingleObject(
runtime,
*parentHandle,
runtime->getHiddenClassForPrototypeRaw(
void *mem = runtime->alloc(cellSize<SingleObject>());
return HermesValue::encodeObjectValue(
JSObject::allocateSmallPropStorage(new (mem) SingleObject(
runtime,
*parentHandle,
numOverlapSlots<SingleObject>() + ANONYMOUS_PROPERTY_SLOTS)));
runtime->getHiddenClassForPrototypeRaw(
*parentHandle,
numOverlapSlots<SingleObject>() + ANONYMOUS_PROPERTY_SLOTS))));
}

protected:
Expand Down
97 changes: 52 additions & 45 deletions lib/VM/Callable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -560,15 +560,16 @@ CallResult<HermesValue> BoundFunction::create(
}
auto argStorageHandle = runtime->makeHandle<ArrayStorage>(*arrRes);

JSObjectAlloc<BoundFunction> mem{runtime};
auto selfHandle = mem.initToHandle(new (mem) BoundFunction(
runtime,
runtime->functionPrototypeRawPtr,
runtime->getHiddenClassForPrototypeRaw(
void *mem = runtime->alloc(cellSize<BoundFunction>());
auto selfHandle =
runtime->makeHandle(allocateSmallPropStorage(new (mem) BoundFunction(
runtime,
runtime->functionPrototypeRawPtr,
numOverlapSlots<BoundFunction>() + ANONYMOUS_PROPERTY_SLOTS),
target,
argStorageHandle));
runtime->getHiddenClassForPrototypeRaw(
runtime->functionPrototypeRawPtr,
numOverlapSlots<BoundFunction>() + ANONYMOUS_PROPERTY_SLOTS),
target,
argStorageHandle)));

// Copy the arguments. If we don't have any, we must at least initialize
// 'this' to 'undefined'.
Expand Down Expand Up @@ -981,17 +982,18 @@ Handle<NativeFunction> NativeFunction::create(
unsigned paramCount,
Handle<JSObject> prototypeObjectHandle,
unsigned additionalSlotCount) {
JSObjectAlloc<NativeFunction> mem{runtime};
auto selfHandle = mem.initToHandle(new (mem) NativeFunction(
runtime,
&vt.base.base,
*parentHandle,
runtime->getHiddenClassForPrototypeRaw(
void *mem = runtime->alloc(cellSize<NativeFunction>());
auto selfHandle =
runtime->makeHandle(allocateSmallPropStorage(new (mem) NativeFunction(
runtime,
&vt.base.base,
*parentHandle,
numOverlapSlots<NativeFunction>() + ANONYMOUS_PROPERTY_SLOTS +
additionalSlotCount),
context,
functionPtr));
runtime->getHiddenClassForPrototypeRaw(
*parentHandle,
numOverlapSlots<NativeFunction>() + ANONYMOUS_PROPERTY_SLOTS +
additionalSlotCount),
context,
functionPtr)));

auto st = defineNameLengthAndPrototype(
selfHandle,
Expand All @@ -1018,18 +1020,19 @@ Handle<NativeFunction> NativeFunction::create(
unsigned paramCount,
Handle<JSObject> prototypeObjectHandle,
unsigned additionalSlotCount) {
JSObjectAlloc<NativeFunction> mem{runtime};
auto selfHandle = mem.initToHandle(new (mem) NativeFunction(
runtime,
&vt.base.base,
*parentHandle,
runtime->getHiddenClassForPrototypeRaw(
void *mem = runtime->alloc(cellSize<NativeFunction>());
auto selfHandle =
runtime->makeHandle(allocateSmallPropStorage(new (mem) NativeFunction(
runtime,
&vt.base.base,
*parentHandle,
numOverlapSlots<NativeFunction>() + ANONYMOUS_PROPERTY_SLOTS +
additionalSlotCount),
parentEnvHandle,
context,
functionPtr));
runtime->getHiddenClassForPrototypeRaw(
*parentHandle,
numOverlapSlots<NativeFunction>() + ANONYMOUS_PROPERTY_SLOTS +
additionalSlotCount),
parentEnvHandle,
context,
functionPtr)));

auto st = defineNameLengthAndPrototype(
selfHandle,
Expand Down Expand Up @@ -1248,8 +1251,9 @@ CallResult<HermesValue> JSFunction::create(
Handle<JSObject> parentHandle,
Handle<Environment> envHandle,
CodeBlock *codeBlock) {
JSObjectAlloc<JSFunction, kHasFinalizer> mem{runtime};
auto self = mem.initToPseudoHandle(new (mem) JSFunction(
void *mem =
runtime->alloc</*fixedSize*/ true, kHasFinalizer>(cellSize<JSFunction>());
auto *self = allocateSmallPropStorage(new (mem) JSFunction(
runtime,
*domain,
*parentHandle,
Expand All @@ -1259,7 +1263,7 @@ CallResult<HermesValue> JSFunction::create(
envHandle,
codeBlock));
self->flags_.lazyObject = 1;
return self.getHermesValue();
return HermesValue::encodeObjectValue(self);
}

void JSFunction::addLocationToSnapshot(
Expand Down Expand Up @@ -1363,8 +1367,9 @@ CallResult<HermesValue> JSGeneratorFunction::create(
Handle<JSObject> parentHandle,
Handle<Environment> envHandle,
CodeBlock *codeBlock) {
JSObjectAlloc<JSGeneratorFunction, kHasFinalizer> mem{runtime};
auto self = mem.initToPseudoHandle(new (mem) JSGeneratorFunction(
void *mem = runtime->alloc</*fixedSize*/ true, kHasFinalizer>(
cellSize<JSGeneratorFunction>());
auto *self = allocateSmallPropStorage(new (mem) JSGeneratorFunction(
runtime,
*domain,
*parentHandle,
Expand All @@ -1374,7 +1379,7 @@ CallResult<HermesValue> JSGeneratorFunction::create(
envHandle,
codeBlock));
self->flags_.lazyObject = 1;
return self.getHermesValue();
return HermesValue::encodeObjectValue(self);
}

//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -1470,17 +1475,19 @@ CallResult<Handle<GeneratorInnerFunction>> GeneratorInnerFunction::create(
Handle<Environment> envHandle,
CodeBlock *codeBlock,
NativeArgs args) {
JSObjectAlloc<GeneratorInnerFunction> mem{runtime};
auto self = mem.initToHandle(new (mem) GeneratorInnerFunction(
runtime,
*domain,
*parentHandle,
runtime->getHiddenClassForPrototypeRaw(
void *mem = runtime->alloc(cellSize<GeneratorInnerFunction>());
auto self = runtime->makeHandle(
allocateSmallPropStorage(new (mem) GeneratorInnerFunction(
runtime,
*domain,
*parentHandle,
numOverlapSlots<GeneratorInnerFunction>() + ANONYMOUS_PROPERTY_SLOTS),
envHandle,
codeBlock,
args.getArgCount()));
runtime->getHiddenClassForPrototypeRaw(
*parentHandle,
numOverlapSlots<GeneratorInnerFunction>() +
ANONYMOUS_PROPERTY_SLOTS),
envHandle,
codeBlock,
args.getArgCount())));

// We must store the entire frame, including the extra registers the callee
// had to allocate at the start.
Expand Down
14 changes: 8 additions & 6 deletions lib/VM/Domain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -337,13 +337,15 @@ Handle<RequireContext> RequireContext::create(
Runtime *runtime,
Handle<Domain> domain,
Handle<StringPrimitive> dirname) {
JSObjectAlloc<RequireContext> mem{runtime};
auto self = mem.initToHandle(new (mem) RequireContext(
runtime,
vmcast<JSObject>(runtime->objectPrototype),
runtime->getHiddenClassForPrototypeRaw(
void *mem = runtime->alloc</*fixedSize*/ true, HasFinalizer::No>(
cellSize<RequireContext>());
auto self = runtime->makeHandle(
JSObject::allocateSmallPropStorage(new (mem) RequireContext(
runtime,
vmcast<JSObject>(runtime->objectPrototype),
ANONYMOUS_PROPERTY_SLOTS)));
runtime->getHiddenClassForPrototypeRaw(
vmcast<JSObject>(runtime->objectPrototype),
ANONYMOUS_PROPERTY_SLOTS))));

JSObject::setInternalProperty(
*self, runtime, domainPropIndex(), domain.getHermesValue());
Expand Down
33 changes: 18 additions & 15 deletions lib/VM/HostModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,17 +64,19 @@ CallResult<HermesValue> FinalizableNativeFunction::createWithoutPrototype(
unsigned paramCount) {
auto parentHandle = Handle<JSObject>::vmcast(&runtime->functionPrototype);

JSObjectAlloc<FinalizableNativeFunction, HasFinalizer::Yes> mem{runtime};
auto selfHandle = mem.initToHandle(new (mem) FinalizableNativeFunction(
runtime,
parentHandle,
createPseudoHandle(runtime->getHiddenClassForPrototypeRaw(
*parentHandle,
numOverlapSlots<FinalizableNativeFunction>() +
ANONYMOUS_PROPERTY_SLOTS)),
context,
functionPtr,
finalizePtr));
void *mem = runtime->alloc</*fixedSize*/ true, HasFinalizer::Yes>(
cellSize<FinalizableNativeFunction>());
auto selfHandle = runtime->makeHandle(
allocateSmallPropStorage(new (mem) FinalizableNativeFunction(
runtime,
parentHandle,
createPseudoHandle(runtime->getHiddenClassForPrototypeRaw(
*parentHandle,
numOverlapSlots<FinalizableNativeFunction>() +
ANONYMOUS_PROPERTY_SLOTS)),
context,
functionPtr,
finalizePtr)));

auto prototypeObjectHandle = Handle<JSObject>(runtime);

Expand Down Expand Up @@ -131,18 +133,19 @@ CallResult<HermesValue> HostObject::createWithoutPrototype(
std::shared_ptr<HostObjectProxy> proxy) {
auto parentHandle = Handle<JSObject>::vmcast(&runtime->objectPrototype);

JSObjectAlloc<HostObject, HasFinalizer::Yes> mem{runtime};
HostObject *hostObj = new (mem) HostObject(
void *mem = runtime->alloc</*fixedSize*/ true, HasFinalizer::Yes>(
cellSize<HostObject>());
HostObject *hostObj = JSObject::allocateSmallPropStorage(new (mem) HostObject(
runtime,
*parentHandle,
runtime->getHiddenClassForPrototypeRaw(
*parentHandle,
numOverlapSlots<HostObject>() + ANONYMOUS_PROPERTY_SLOTS),
proxy);
proxy));

hostObj->flags_.hostObject = true;

return mem.initToHermesValue(hostObj);
return HermesValue::encodeObjectValue(hostObj);
}

void HostObject::_finalizeImpl(GCCell *cell, GC *) {
Expand Down
Loading

0 comments on commit cc56574

Please sign in to comment.