Refactor ExternalObjects
Instead of implementing ExternalObjects as plain JSObjects with a single EmbedderDataSlot pointing to a Foreign containing the actual raw pointer, this CL now creates a new JSExternalObject type that directly contains the external pointer. As a side-effect of this refactoring, nullptr values are now no longer valid for ExternalObjects. Change-Id: Ic8ff334681c966e823ca70f34dd1efaaa21a0789 Cq-Include-Trybots: luci.v8.try:v8_linux64_heap_sandbox_dbg_ng,v8_linux_arm64_sim_heap_sandbox_dbg_ng Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3513234 Reviewed-by: Igor Sheludko <ishell@chromium.org> Reviewed-by: Toon Verwaest <verwaest@chromium.org> Reviewed-by: Michael Lippautz <mlippautz@chromium.org> Commit-Queue: Samuel Groß <saelo@chromium.org> Cr-Commit-Position: refs/heads/main@{#79459}
This commit is contained in:
parent
bed5bc495f
commit
5a968b08b3
@ -303,6 +303,7 @@ enum ExternalPointerTag : uint64_t {
|
||||
kNativeContextMicrotaskQueueTag = 0b1000000111011111ULL << 48,
|
||||
kEmbedderDataSlotPayloadTag = 0b1000000111101111ULL << 48,
|
||||
kCodeEntryPointTag = 0b1000000111110111ULL << 48,
|
||||
kExternalObjectValueTag = 0b1000000111111011ULL << 48,
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
@ -3633,15 +3633,7 @@ bool Value::IsBoolean() const { return Utils::OpenHandle(this)->IsBoolean(); }
|
||||
|
||||
bool Value::IsExternal() const {
|
||||
i::Object obj = *Utils::OpenHandle(this);
|
||||
if (!obj.IsHeapObject()) return false;
|
||||
i::HeapObject heap_obj = i::HeapObject::cast(obj);
|
||||
// Check the instance type is JS_OBJECT (instance type of Externals) before
|
||||
// attempting to get the Isolate since that guarantees the object is writable
|
||||
// and GetIsolate will work.
|
||||
if (heap_obj.map().instance_type() != i::JS_OBJECT_TYPE) return false;
|
||||
i::Isolate* isolate = i::JSObject::cast(heap_obj).GetIsolate();
|
||||
ASSERT_NO_SCRIPT_NO_EXCEPTION(isolate);
|
||||
return heap_obj.IsExternal(isolate);
|
||||
return obj.IsJSExternalObject();
|
||||
}
|
||||
|
||||
bool Value::IsInt32() const {
|
||||
@ -5996,15 +5988,6 @@ void v8::Object::SetAlignedPointerInInternalFields(int argc, int indices[],
|
||||
#endif // VERIFY_HEAP
|
||||
}
|
||||
|
||||
static void* ExternalValue(i::Object obj) {
|
||||
// Obscure semantics for undefined, but somehow checked in our unit tests...
|
||||
if (obj.IsUndefined()) {
|
||||
return nullptr;
|
||||
}
|
||||
i::Object foreign = i::JSObject::cast(obj).GetEmbedderField(0);
|
||||
return reinterpret_cast<void*>(i::Foreign::cast(foreign).foreign_address());
|
||||
}
|
||||
|
||||
// --- E n v i r o n m e n t ---
|
||||
|
||||
void v8::V8::InitializePlatform(Platform* platform) {
|
||||
@ -6732,6 +6715,11 @@ bool FunctionTemplate::IsLeafTemplateForApiObject(
|
||||
|
||||
Local<External> v8::External::New(Isolate* isolate, void* value) {
|
||||
STATIC_ASSERT(sizeof(value) == sizeof(i::Address));
|
||||
// Nullptr is not allowed here because serialization/deserialization of
|
||||
// nullptr external api references is not possible as nullptr is used as an
|
||||
// external_references table terminator, see v8::SnapshotCreator()
|
||||
// constructors.
|
||||
DCHECK_NOT_NULL(value);
|
||||
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
|
||||
LOG_API(i_isolate, External, New);
|
||||
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
|
||||
@ -6740,7 +6728,8 @@ Local<External> v8::External::New(Isolate* isolate, void* value) {
|
||||
}
|
||||
|
||||
void* External::Value() const {
|
||||
return ExternalValue(*Utils::OpenHandle(this));
|
||||
auto self = Utils::OpenHandle(this);
|
||||
return i::JSExternalObject::cast(*self).value();
|
||||
}
|
||||
|
||||
// anonymous namespace for string creation helper functions
|
||||
|
@ -196,6 +196,7 @@ Type::bitset BitsetType::Lub(const MapRefLike& map) {
|
||||
case JS_STRING_ITERATOR_PROTOTYPE_TYPE:
|
||||
case JS_ARGUMENTS_OBJECT_TYPE:
|
||||
case JS_ERROR_TYPE:
|
||||
case JS_EXTERNAL_OBJECT_TYPE:
|
||||
case JS_GLOBAL_OBJECT_TYPE:
|
||||
case JS_GLOBAL_PROXY_TYPE:
|
||||
case JS_API_OBJECT_TYPE:
|
||||
|
@ -116,6 +116,10 @@ class ConcurrentMarkingVisitor final
|
||||
return VisitJSObjectSubclassFast(map, object);
|
||||
}
|
||||
|
||||
int VisitJSExternalObject(Map map, JSExternalObject object) {
|
||||
return VisitJSObjectSubclass(map, object);
|
||||
}
|
||||
|
||||
#if V8_ENABLE_WEBASSEMBLY
|
||||
int VisitWasmInstanceObject(Map map, WasmInstanceObject object) {
|
||||
return VisitJSObjectSubclass(map, object);
|
||||
|
@ -2272,9 +2272,10 @@ Handle<JSObject> Factory::NewFunctionPrototype(Handle<JSFunction> function) {
|
||||
}
|
||||
|
||||
Handle<JSObject> Factory::NewExternal(void* value) {
|
||||
Handle<Foreign> foreign = NewForeign(reinterpret_cast<Address>(value));
|
||||
Handle<JSObject> external = NewJSObjectFromMap(external_map());
|
||||
external->SetEmbedderField(0, *foreign);
|
||||
auto external =
|
||||
Handle<JSExternalObject>::cast(NewJSObjectFromMap(external_map()));
|
||||
external->AllocateExternalPointerEntries(isolate());
|
||||
external->set_value(isolate(), value);
|
||||
return external;
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@ namespace internal {
|
||||
V(FixedDoubleArray) \
|
||||
V(JSArrayBuffer) \
|
||||
V(JSDataView) \
|
||||
V(JSExternalObject) \
|
||||
V(JSFinalizationRegistry) \
|
||||
V(JSFunction) \
|
||||
V(JSObject) \
|
||||
|
@ -527,7 +527,7 @@ bool Heap::CreateInitialMaps() {
|
||||
|
||||
ALLOCATE_MAP(JS_MESSAGE_OBJECT_TYPE, JSMessageObject::kHeaderSize,
|
||||
message_object)
|
||||
ALLOCATE_MAP(JS_OBJECT_TYPE, JSObject::kHeaderSize + kEmbedderDataSlotSize,
|
||||
ALLOCATE_MAP(JS_EXTERNAL_OBJECT_TYPE, JSExternalObject::kHeaderSize,
|
||||
external)
|
||||
external_map().set_is_extensible(false);
|
||||
#undef ALLOCATE_PRIMITIVE_MAP
|
||||
|
@ -96,8 +96,6 @@ class HeapObject : public Object {
|
||||
IS_TYPE_FUNCTION_DECL(CodeT)
|
||||
#undef IS_TYPE_FUNCTION_DECL
|
||||
|
||||
bool IsExternal(Isolate* isolate) const;
|
||||
|
||||
// Oddball checks are faster when they are raw pointer comparisons, so the
|
||||
// isolate/read-only roots overloads should be preferred where possible.
|
||||
#define IS_TYPE_FUNCTION_DECL(Type, Value) \
|
||||
|
@ -525,6 +525,35 @@ void JSObject::InitializeBody(Map map, int start_offset,
|
||||
}
|
||||
}
|
||||
|
||||
TQ_OBJECT_CONSTRUCTORS_IMPL(JSExternalObject)
|
||||
|
||||
DEF_GETTER(JSExternalObject, value, void*) {
|
||||
Isolate* isolate = GetIsolateForSandbox(*this);
|
||||
return reinterpret_cast<void*>(
|
||||
ReadExternalPointerField(kValueOffset, isolate, kExternalObjectValueTag));
|
||||
}
|
||||
|
||||
void JSExternalObject::AllocateExternalPointerEntries(Isolate* isolate) {
|
||||
InitExternalPointerField(kValueOffset, isolate, kExternalObjectValueTag);
|
||||
}
|
||||
|
||||
void JSExternalObject::set_value(Isolate* isolate, void* value) {
|
||||
WriteExternalPointerField(kValueOffset, isolate,
|
||||
reinterpret_cast<Address>(value),
|
||||
kExternalObjectValueTag);
|
||||
}
|
||||
|
||||
uint32_t JSExternalObject::GetValueRefForDeserialization() {
|
||||
ExternalPointer_t encoded_address =
|
||||
ReadField<ExternalPointer_t>(kValueOffset);
|
||||
return static_cast<uint32_t>(encoded_address);
|
||||
}
|
||||
|
||||
void JSExternalObject::SetValueRefForSerialization(uint32_t ref) {
|
||||
WriteField<ExternalPointer_t>(kValueOffset,
|
||||
static_cast<ExternalPointer_t>(ref));
|
||||
}
|
||||
|
||||
DEF_GETTER(JSGlobalObject, native_context_unchecked, Object) {
|
||||
return TaggedField<Object, kNativeContextOffset>::Relaxed_Load(cage_base,
|
||||
*this);
|
||||
|
@ -584,7 +584,7 @@ Handle<String> JSReceiver::GetConstructorName(Isolate* isolate,
|
||||
MaybeHandle<NativeContext> JSReceiver::GetCreationContext() {
|
||||
JSReceiver receiver = *this;
|
||||
// Externals are JSObjects with null as a constructor.
|
||||
DCHECK(!receiver.IsExternal(GetIsolate()));
|
||||
DCHECK(!receiver.IsJSExternalObject());
|
||||
Object constructor = receiver.map().GetConstructor();
|
||||
JSFunction function;
|
||||
if (constructor.IsJSFunction()) {
|
||||
@ -2344,6 +2344,8 @@ int JSObject::GetHeaderSize(InstanceType type,
|
||||
return JSObject::kHeaderSize;
|
||||
case JS_ERROR_TYPE:
|
||||
return JSObject::kHeaderSize;
|
||||
case JS_EXTERNAL_OBJECT_TYPE:
|
||||
return JSExternalObject::kHeaderSize;
|
||||
case JS_SHADOW_REALM_TYPE:
|
||||
return JSShadowRealm::kHeaderSize;
|
||||
case JS_STRING_ITERATOR_TYPE:
|
||||
|
@ -890,6 +890,30 @@ class JSObject : public TorqueGeneratedJSObject<JSObject, JSReceiver> {
|
||||
TQ_OBJECT_CONSTRUCTORS(JSObject)
|
||||
};
|
||||
|
||||
// A JSObject created through the public api which wraps an external pointer.
|
||||
// See v8::External.
|
||||
class JSExternalObject
|
||||
: public TorqueGeneratedJSExternalObject<JSExternalObject, JSObject> {
|
||||
public:
|
||||
inline void AllocateExternalPointerEntries(Isolate* isolate);
|
||||
|
||||
// [value]: field containing the pointer value.
|
||||
DECL_GETTER(value, void*)
|
||||
|
||||
inline void set_value(Isolate* isolate, void* value);
|
||||
|
||||
// Used in the serializer/deserializer.
|
||||
inline uint32_t GetValueRefForDeserialization();
|
||||
inline void SetValueRefForSerialization(uint32_t ref);
|
||||
|
||||
static constexpr int kEndOfTaggedFieldsOffset = JSObject::kHeaderSize;
|
||||
|
||||
class BodyDescriptor;
|
||||
|
||||
private:
|
||||
TQ_OBJECT_CONSTRUCTORS(JSExternalObject)
|
||||
};
|
||||
|
||||
// An abstract superclass for JSObjects that may have elements while having an
|
||||
// empty fixed array as elements backing store. It doesn't carry any
|
||||
// functionality but allows function classes to be identified in the type
|
||||
|
@ -40,6 +40,8 @@ macro NewJSObject(implicit context: Context)(): JSObject {
|
||||
return AllocateJSObjectFromMap(map);
|
||||
}
|
||||
|
||||
extern class JSExternalObject extends JSObject { value: ExternalPointer; }
|
||||
|
||||
@abstract
|
||||
@lowestInstanceTypeWithinParentClassRange
|
||||
extern class JSCustomElementsObject extends JSObject {
|
||||
|
@ -206,6 +206,9 @@ VisitorId Map::GetVisitorId(Map map) {
|
||||
case JS_DATA_VIEW_TYPE:
|
||||
return kVisitJSDataView;
|
||||
|
||||
case JS_EXTERNAL_OBJECT_TYPE:
|
||||
return kVisitJSExternalObject;
|
||||
|
||||
case JS_FUNCTION_TYPE:
|
||||
case JS_CLASS_CONSTRUCTOR_TYPE:
|
||||
case JS_PROMISE_CONSTRUCTOR_TYPE:
|
||||
|
@ -46,6 +46,7 @@ enum InstanceType : uint16_t;
|
||||
V(JSApiObject) \
|
||||
V(JSArrayBuffer) \
|
||||
V(JSDataView) \
|
||||
V(JSExternalObject) \
|
||||
V(JSFinalizationRegistry) \
|
||||
V(JSFunction) \
|
||||
V(JSObject) \
|
||||
|
@ -139,6 +139,7 @@ class ZoneForwardList;
|
||||
V(JSDataView) \
|
||||
V(JSDate) \
|
||||
V(JSError) \
|
||||
V(JSExternalObject) \
|
||||
V(JSFinalizationRegistry) \
|
||||
V(JSFunction) \
|
||||
V(JSFunctionOrBoundFunctionOrWrappedFunction) \
|
||||
|
@ -436,6 +436,22 @@ class JSDataView::BodyDescriptor final : public BodyDescriptorBase {
|
||||
}
|
||||
};
|
||||
|
||||
class JSExternalObject::BodyDescriptor final : public BodyDescriptorBase {
|
||||
public:
|
||||
static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; }
|
||||
|
||||
template <typename ObjectVisitor>
|
||||
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
||||
ObjectVisitor* v) {
|
||||
IteratePointers(obj, kPropertiesOrHashOffset, kEndOfTaggedFieldsOffset, v);
|
||||
v->VisitExternalPointer(obj, obj.RawExternalPointerField(kValueOffset));
|
||||
}
|
||||
|
||||
static inline int SizeOf(Map map, HeapObject object) {
|
||||
return map.instance_size();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Derived>
|
||||
class V8_EXPORT_PRIVATE SmallOrderedHashTable<Derived>::BodyDescriptor final
|
||||
: public BodyDescriptorBase {
|
||||
@ -1211,6 +1227,8 @@ auto BodyDescriptorApply(InstanceType type, Args&&... args) {
|
||||
return CALL_APPLY(JSDataView);
|
||||
case JS_TYPED_ARRAY_TYPE:
|
||||
return CALL_APPLY(JSTypedArray);
|
||||
case JS_EXTERNAL_OBJECT_TYPE:
|
||||
return CALL_APPLY(JSExternalObject);
|
||||
case WEAK_CELL_TYPE:
|
||||
return CALL_APPLY(WeakCell);
|
||||
case JS_WEAK_REF_TYPE:
|
||||
|
@ -2448,10 +2448,6 @@ void HeapObject::RehashBasedOnMap(IsolateT* isolate) {
|
||||
template void HeapObject::RehashBasedOnMap(Isolate* isolate);
|
||||
template void HeapObject::RehashBasedOnMap(LocalIsolate* isolate);
|
||||
|
||||
bool HeapObject::IsExternal(Isolate* isolate) const {
|
||||
return map(isolate).FindRootMap(isolate) == isolate->heap()->external_map();
|
||||
}
|
||||
|
||||
void DescriptorArray::GeneralizeAllFields() {
|
||||
int length = number_of_descriptors();
|
||||
for (InternalIndex i : InternalIndex::Range(length)) {
|
||||
|
@ -264,9 +264,12 @@ void HeapProfiler::QueryObjects(Handle<Context> context,
|
||||
heap()->CollectAllAvailableGarbage(GarbageCollectionReason::kHeapProfiler);
|
||||
CombinedHeapObjectIterator heap_iterator(
|
||||
heap(), HeapObjectIterator::kFilterUnreachable);
|
||||
PtrComprCageBase cage_base(isolate());
|
||||
for (HeapObject heap_obj = heap_iterator.Next(); !heap_obj.is_null();
|
||||
heap_obj = heap_iterator.Next()) {
|
||||
if (!heap_obj.IsJSObject() || heap_obj.IsExternal(isolate())) continue;
|
||||
if (!heap_obj.IsJSObject(cage_base) ||
|
||||
heap_obj.IsJSExternalObject(cage_base))
|
||||
continue;
|
||||
v8::Local<v8::Object> v8_obj(
|
||||
Utils::ToLocal(handle(JSObject::cast(heap_obj), isolate())));
|
||||
if (!predicate->Filter(v8_obj)) continue;
|
||||
|
@ -380,6 +380,14 @@ template bool StringTableInsertionKey::IsMatch(LocalIsolate* isolate,
|
||||
|
||||
namespace {
|
||||
|
||||
void NoExternalReferencesCallback() {
|
||||
// The following check will trigger if a function or object template
|
||||
// with references to native functions have been deserialized from
|
||||
// snapshot, but no actual external references were provided when the
|
||||
// isolate was created.
|
||||
FATAL("No external references provided via API");
|
||||
}
|
||||
|
||||
void PostProcessExternalString(ExternalString string, Isolate* isolate) {
|
||||
DisallowGarbageCollection no_gc;
|
||||
uint32_t index = string.GetResourceRefForDeserialization();
|
||||
@ -450,6 +458,24 @@ void Deserializer<IsolateT>::PostProcessNewJSReceiver(
|
||||
HeapObject::RequiredAlignment(map)));
|
||||
}
|
||||
|
||||
template <typename IsolateT>
|
||||
void Deserializer<IsolateT>::PostProcessJSExternalObject(
|
||||
JSExternalObject object, Isolate* isolate) {
|
||||
DisallowGarbageCollection no_gc;
|
||||
uint32_t index = object.GetValueRefForDeserialization();
|
||||
Address address;
|
||||
if (main_thread_isolate()->api_external_references()) {
|
||||
DCHECK_WITH_MSG(index < num_api_references_,
|
||||
"too few external references provided through the API");
|
||||
address = static_cast<Address>(
|
||||
main_thread_isolate()->api_external_references()[index]);
|
||||
} else {
|
||||
address = reinterpret_cast<Address>(NoExternalReferencesCallback);
|
||||
}
|
||||
object.AllocateExternalPointerEntries(isolate);
|
||||
object.set_value(isolate, reinterpret_cast<void*>(address));
|
||||
}
|
||||
|
||||
template <typename IsolateT>
|
||||
void Deserializer<IsolateT>::PostProcessNewObject(Handle<Map> map,
|
||||
Handle<HeapObject> obj,
|
||||
@ -545,6 +571,9 @@ void Deserializer<IsolateT>::PostProcessNewObject(Handle<Map> map,
|
||||
} else if (InstanceTypeChecker::IsExternalString(instance_type)) {
|
||||
PostProcessExternalString(ExternalString::cast(raw_obj),
|
||||
main_thread_isolate());
|
||||
} else if (InstanceTypeChecker::IsJSExternalObject(instance_type)) {
|
||||
PostProcessJSExternalObject(JSExternalObject::cast(raw_obj),
|
||||
main_thread_isolate());
|
||||
} else if (InstanceTypeChecker::IsJSReceiver(instance_type)) {
|
||||
return PostProcessNewJSReceiver(raw_map, Handle<JSReceiver>::cast(obj),
|
||||
JSReceiver::cast(raw_obj), instance_type,
|
||||
@ -859,14 +888,6 @@ int Deserializer<IsolateT>::ReadRepeatedObject(SlotAccessor slot_accessor,
|
||||
|
||||
namespace {
|
||||
|
||||
void NoExternalReferencesCallback() {
|
||||
// The following check will trigger if a function or object template
|
||||
// with references to native functions have been deserialized from
|
||||
// snapshot, but no actual external references were provided when the
|
||||
// isolate was created.
|
||||
FATAL("No external references provided via API");
|
||||
}
|
||||
|
||||
// Template used by the below CASE_RANGE macro to statically verify that the
|
||||
// given number of cases matches the number of expected cases for that bytecode.
|
||||
template <int byte_code_count, int expected>
|
||||
|
@ -198,6 +198,7 @@ class Deserializer : public SerializerDeserializer {
|
||||
void PostProcessNewJSReceiver(Map map, Handle<JSReceiver> obj,
|
||||
JSReceiver raw_obj, InstanceType instance_type,
|
||||
SnapshotSpace space);
|
||||
void PostProcessJSExternalObject(JSExternalObject object, Isolate* isolate);
|
||||
|
||||
HeapObject Allocate(AllocationType allocation, int size,
|
||||
AllocationAlignment alignment);
|
||||
|
@ -549,6 +549,26 @@ void Serializer::ObjectSerializer::SerializeJSArrayBuffer() {
|
||||
buffer->set_extension(extension);
|
||||
}
|
||||
|
||||
void Serializer::ObjectSerializer::SerializeJSExternalObject() {
|
||||
Handle<JSExternalObject> obj = Handle<JSExternalObject>::cast(object_);
|
||||
Address value = reinterpret_cast<Address>(obj->value());
|
||||
ExternalReferenceEncoder::Value reference =
|
||||
serializer_->EncodeExternalReference(value);
|
||||
DCHECK(reference.is_from_api());
|
||||
#ifdef V8_SANDBOXED_EXTERNAL_POINTERS
|
||||
// TODO(saelo) unify this code with the non-sandbox version maybe?
|
||||
STATIC_ASSERT(sizeof(ExternalPointer_t) == sizeof(uint32_t));
|
||||
uint32_t external_pointer_entry = obj->GetValueRefForDeserialization();
|
||||
#endif
|
||||
obj->SetValueRefForSerialization(reference.index());
|
||||
SerializeObject();
|
||||
#ifdef V8_SANDBOXED_EXTERNAL_POINTERS
|
||||
obj->SetValueRefForSerialization(external_pointer_entry);
|
||||
#else
|
||||
obj->set_value(isolate(), reinterpret_cast<void*>(value));
|
||||
#endif
|
||||
}
|
||||
|
||||
void Serializer::ObjectSerializer::SerializeExternalString() {
|
||||
// For external strings with known resources, we replace the resource field
|
||||
// with the encoded external reference, which we restore upon deserialize.
|
||||
@ -692,6 +712,9 @@ void Serializer::ObjectSerializer::Serialize() {
|
||||
if (object_->IsExternalString(cage_base)) {
|
||||
SerializeExternalString();
|
||||
return;
|
||||
} else if (object_->IsJSExternalObject(cage_base)) {
|
||||
SerializeJSExternalObject();
|
||||
return;
|
||||
} else if (!ReadOnlyHeap::Contains(*object_)) {
|
||||
// Only clear padding for strings outside the read-only heap. Read-only heap
|
||||
// should have been cleared elsewhere.
|
||||
|
@ -472,6 +472,7 @@ class Serializer::ObjectSerializer : public ObjectVisitor {
|
||||
uint32_t SerializeBackingStore(void* backing_store, int32_t byte_length);
|
||||
void SerializeJSTypedArray();
|
||||
void SerializeJSArrayBuffer();
|
||||
void SerializeJSExternalObject();
|
||||
void SerializeExternalString();
|
||||
void SerializeExternalStringAsSequentialString();
|
||||
|
||||
|
@ -3415,8 +3415,8 @@ UNINITIALIZED_TEST(SnapshotCreatorTemplates) {
|
||||
object_template->NewInstance(context).ToLocalChecked();
|
||||
v8::Local<v8::Object> c =
|
||||
object_template->NewInstance(context).ToLocalChecked();
|
||||
v8::Local<v8::External> null_external =
|
||||
v8::External::New(isolate, nullptr);
|
||||
v8::Local<v8::External> resource_external =
|
||||
v8::External::New(isolate, &serializable_one_byte_resource);
|
||||
v8::Local<v8::External> field_external =
|
||||
v8::External::New(isolate, &serialized_static_field);
|
||||
|
||||
@ -3427,7 +3427,7 @@ UNINITIALIZED_TEST(SnapshotCreatorTemplates) {
|
||||
b->SetAlignedPointerInInternalField(1, b1);
|
||||
c->SetAlignedPointerInInternalField(1, c1);
|
||||
|
||||
a->SetInternalField(2, null_external);
|
||||
a->SetInternalField(2, resource_external);
|
||||
b->SetInternalField(2, field_external);
|
||||
c->SetInternalField(2, v8_num(35));
|
||||
CHECK(context->Global()->Set(context, v8_str("a"), a).FromJust());
|
||||
@ -3525,7 +3525,8 @@ UNINITIALIZED_TEST(SnapshotCreatorTemplates) {
|
||||
CHECK_EQ(30u, c1->data);
|
||||
|
||||
CHECK(a2->IsExternal());
|
||||
CHECK_NULL(v8::Local<v8::External>::Cast(a2)->Value());
|
||||
CHECK_EQ(static_cast<void*>(&serializable_one_byte_resource),
|
||||
v8::Local<v8::External>::Cast(a2)->Value());
|
||||
CHECK(b2->IsExternal());
|
||||
CHECK_EQ(static_cast<void*>(&serialized_static_field),
|
||||
v8::Local<v8::External>::Cast(b2)->Value());
|
||||
|
@ -232,42 +232,43 @@ INSTANCE_TYPES = {
|
||||
2109: "JS_DATE_TIME_FORMAT_TYPE",
|
||||
2110: "JS_DISPLAY_NAMES_TYPE",
|
||||
2111: "JS_ERROR_TYPE",
|
||||
2112: "JS_FINALIZATION_REGISTRY_TYPE",
|
||||
2113: "JS_LIST_FORMAT_TYPE",
|
||||
2114: "JS_LOCALE_TYPE",
|
||||
2115: "JS_MESSAGE_OBJECT_TYPE",
|
||||
2116: "JS_NUMBER_FORMAT_TYPE",
|
||||
2117: "JS_PLURAL_RULES_TYPE",
|
||||
2118: "JS_PROMISE_TYPE",
|
||||
2119: "JS_REG_EXP_TYPE",
|
||||
2120: "JS_REG_EXP_STRING_ITERATOR_TYPE",
|
||||
2121: "JS_RELATIVE_TIME_FORMAT_TYPE",
|
||||
2122: "JS_SEGMENT_ITERATOR_TYPE",
|
||||
2123: "JS_SEGMENTER_TYPE",
|
||||
2124: "JS_SEGMENTS_TYPE",
|
||||
2125: "JS_SHADOW_REALM_TYPE",
|
||||
2126: "JS_SHARED_STRUCT_TYPE",
|
||||
2127: "JS_STRING_ITERATOR_TYPE",
|
||||
2128: "JS_TEMPORAL_CALENDAR_TYPE",
|
||||
2129: "JS_TEMPORAL_DURATION_TYPE",
|
||||
2130: "JS_TEMPORAL_INSTANT_TYPE",
|
||||
2131: "JS_TEMPORAL_PLAIN_DATE_TYPE",
|
||||
2132: "JS_TEMPORAL_PLAIN_DATE_TIME_TYPE",
|
||||
2133: "JS_TEMPORAL_PLAIN_MONTH_DAY_TYPE",
|
||||
2134: "JS_TEMPORAL_PLAIN_TIME_TYPE",
|
||||
2135: "JS_TEMPORAL_PLAIN_YEAR_MONTH_TYPE",
|
||||
2136: "JS_TEMPORAL_TIME_ZONE_TYPE",
|
||||
2137: "JS_TEMPORAL_ZONED_DATE_TIME_TYPE",
|
||||
2138: "JS_V8_BREAK_ITERATOR_TYPE",
|
||||
2139: "JS_WEAK_REF_TYPE",
|
||||
2140: "WASM_GLOBAL_OBJECT_TYPE",
|
||||
2141: "WASM_INSTANCE_OBJECT_TYPE",
|
||||
2142: "WASM_MEMORY_OBJECT_TYPE",
|
||||
2143: "WASM_MODULE_OBJECT_TYPE",
|
||||
2144: "WASM_SUSPENDER_OBJECT_TYPE",
|
||||
2145: "WASM_TABLE_OBJECT_TYPE",
|
||||
2146: "WASM_TAG_OBJECT_TYPE",
|
||||
2147: "WASM_VALUE_OBJECT_TYPE",
|
||||
2112: "JS_EXTERNAL_OBJECT_TYPE",
|
||||
2113: "JS_FINALIZATION_REGISTRY_TYPE",
|
||||
2114: "JS_LIST_FORMAT_TYPE",
|
||||
2115: "JS_LOCALE_TYPE",
|
||||
2116: "JS_MESSAGE_OBJECT_TYPE",
|
||||
2117: "JS_NUMBER_FORMAT_TYPE",
|
||||
2118: "JS_PLURAL_RULES_TYPE",
|
||||
2119: "JS_PROMISE_TYPE",
|
||||
2120: "JS_REG_EXP_TYPE",
|
||||
2121: "JS_REG_EXP_STRING_ITERATOR_TYPE",
|
||||
2122: "JS_RELATIVE_TIME_FORMAT_TYPE",
|
||||
2123: "JS_SEGMENT_ITERATOR_TYPE",
|
||||
2124: "JS_SEGMENTER_TYPE",
|
||||
2125: "JS_SEGMENTS_TYPE",
|
||||
2126: "JS_SHADOW_REALM_TYPE",
|
||||
2127: "JS_SHARED_STRUCT_TYPE",
|
||||
2128: "JS_STRING_ITERATOR_TYPE",
|
||||
2129: "JS_TEMPORAL_CALENDAR_TYPE",
|
||||
2130: "JS_TEMPORAL_DURATION_TYPE",
|
||||
2131: "JS_TEMPORAL_INSTANT_TYPE",
|
||||
2132: "JS_TEMPORAL_PLAIN_DATE_TYPE",
|
||||
2133: "JS_TEMPORAL_PLAIN_DATE_TIME_TYPE",
|
||||
2134: "JS_TEMPORAL_PLAIN_MONTH_DAY_TYPE",
|
||||
2135: "JS_TEMPORAL_PLAIN_TIME_TYPE",
|
||||
2136: "JS_TEMPORAL_PLAIN_YEAR_MONTH_TYPE",
|
||||
2137: "JS_TEMPORAL_TIME_ZONE_TYPE",
|
||||
2138: "JS_TEMPORAL_ZONED_DATE_TIME_TYPE",
|
||||
2139: "JS_V8_BREAK_ITERATOR_TYPE",
|
||||
2140: "JS_WEAK_REF_TYPE",
|
||||
2141: "WASM_GLOBAL_OBJECT_TYPE",
|
||||
2142: "WASM_INSTANCE_OBJECT_TYPE",
|
||||
2143: "WASM_MEMORY_OBJECT_TYPE",
|
||||
2144: "WASM_MODULE_OBJECT_TYPE",
|
||||
2145: "WASM_SUSPENDER_OBJECT_TYPE",
|
||||
2146: "WASM_TABLE_OBJECT_TYPE",
|
||||
2147: "WASM_TAG_OBJECT_TYPE",
|
||||
2148: "WASM_VALUE_OBJECT_TYPE",
|
||||
}
|
||||
|
||||
# List of known V8 maps.
|
||||
@ -447,8 +448,8 @@ KNOWN_MAPS = {
|
||||
("read_only_space", 0x06a95): (138, "StoreHandler1Map"),
|
||||
("read_only_space", 0x06abd): (138, "StoreHandler2Map"),
|
||||
("read_only_space", 0x06ae5): (138, "StoreHandler3Map"),
|
||||
("map_space", 0x02151): (1057, "ExternalMap"),
|
||||
("map_space", 0x02179): (2115, "JSMessageObjectMap"),
|
||||
("map_space", 0x02151): (2112, "ExternalMap"),
|
||||
("map_space", 0x02179): (2116, "JSMessageObjectMap"),
|
||||
}
|
||||
|
||||
# List of known V8 objects.
|
||||
|
Loading…
Reference in New Issue
Block a user