[wasm] Add untagged context properties to WasmInstanceObject
This CL is preparation for moving the contents of the WasmContext directly into the WasmInstanceObject. The moved fields are all untagged pointers to C++ memory or untagged sizes which will be used in generated machine code for WASM. They are not currently used, but they are all set to kHeapObjectTag to make sure they are not interpreted as tagged by the GC, using a custom object descriptor. R=mstarzinger@chromium.org CC=clemensh@chromium.org Bug: v8:7424 Change-Id: Ie5d5161df32564dcac74c6ff659f1a38ddca3cb0 Reviewed-on: https://chromium-review.googlesource.com/961065 Commit-Queue: Ben Titzer <titzer@chromium.org> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> Cr-Commit-Position: refs/heads/master@{#51932}
This commit is contained in:
parent
507fe1d105
commit
39bc48e283
@ -55,6 +55,7 @@ class JSWeakCollection;
|
||||
V(Symbol) \
|
||||
V(ThinString) \
|
||||
V(TransitionArray) \
|
||||
V(WasmInstanceObject) \
|
||||
V(WeakCell) \
|
||||
V(WeakFixedArray)
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "src/objects-body-descriptors.h"
|
||||
#include "src/objects/hash-table.h"
|
||||
#include "src/transitions.h"
|
||||
#include "src/wasm/wasm-objects-inl.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -463,6 +464,26 @@ class SeqTwoByteString::BodyDescriptor final : public BodyDescriptorBase {
|
||||
}
|
||||
};
|
||||
|
||||
class WasmInstanceObject::BodyDescriptor final : public BodyDescriptorBase {
|
||||
public:
|
||||
static bool IsValidSlot(HeapObject* obj, int offset) {
|
||||
if (offset < kMemoryStartOffset) return true;
|
||||
if (offset < kCompiledModuleOffset) return false;
|
||||
return IsValidSlotImpl(obj, offset);
|
||||
}
|
||||
|
||||
template <typename ObjectVisitor>
|
||||
static inline void IterateBody(HeapObject* obj, int object_size,
|
||||
ObjectVisitor* v) {
|
||||
IteratePointers(obj, kPropertiesOrHashOffset, kFirstUntaggedOffset, v);
|
||||
IterateBodyImpl(obj, kSize, object_size, v);
|
||||
}
|
||||
|
||||
static inline int SizeOf(Map* map, HeapObject* object) {
|
||||
return map->instance_size();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Op, typename ReturnType, typename T1, typename T2,
|
||||
typename T3>
|
||||
ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3) {
|
||||
@ -540,11 +561,12 @@ ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3) {
|
||||
case JS_SPECIAL_API_OBJECT_TYPE:
|
||||
case JS_MESSAGE_OBJECT_TYPE:
|
||||
case JS_BOUND_FUNCTION_TYPE:
|
||||
case WASM_INSTANCE_TYPE:
|
||||
case WASM_MEMORY_TYPE:
|
||||
case WASM_MODULE_TYPE:
|
||||
case WASM_TABLE_TYPE:
|
||||
return Op::template apply<JSObject::BodyDescriptor>(p1, p2, p3);
|
||||
case WASM_INSTANCE_TYPE:
|
||||
return Op::template apply<WasmInstanceObject::BodyDescriptor>(p1, p2, p3);
|
||||
case JS_WEAK_MAP_TYPE:
|
||||
case JS_WEAK_SET_TYPE:
|
||||
return Op::template apply<JSWeakCollection::BodyDescriptor>(p1, p2, p3);
|
||||
|
@ -3047,6 +3047,9 @@ VisitorId Map::GetVisitorId(Map* map) {
|
||||
case CODE_DATA_CONTAINER_TYPE:
|
||||
return kVisitCodeDataContainer;
|
||||
|
||||
case WASM_INSTANCE_TYPE:
|
||||
return kVisitWasmInstanceObject;
|
||||
|
||||
case JS_OBJECT_TYPE:
|
||||
case JS_ERROR_TYPE:
|
||||
case JS_ARGUMENTS_TYPE:
|
||||
@ -3073,7 +3076,6 @@ VisitorId Map::GetVisitorId(Map* map) {
|
||||
case JS_MAP_VALUE_ITERATOR_TYPE:
|
||||
case JS_STRING_ITERATOR_TYPE:
|
||||
case JS_PROMISE_TYPE:
|
||||
case WASM_INSTANCE_TYPE:
|
||||
case WASM_MEMORY_TYPE:
|
||||
case WASM_MODULE_TYPE:
|
||||
case WASM_TABLE_TYPE:
|
||||
|
@ -56,6 +56,7 @@ namespace internal {
|
||||
V(Symbol) \
|
||||
V(ThinString) \
|
||||
V(TransitionArray) \
|
||||
V(WasmInstanceObject) \
|
||||
V(WeakCell) \
|
||||
V(WeakFixedArray)
|
||||
|
||||
|
@ -28,6 +28,20 @@ CAST_ACCESSOR(WasmTableObject)
|
||||
} \
|
||||
ACCESSORS(holder, name, type, offset)
|
||||
|
||||
#define READ_PRIMITIVE_FIELD(p, type, offset) \
|
||||
(*reinterpret_cast<type const*>(FIELD_ADDR_CONST(p, offset)))
|
||||
|
||||
#define WRITE_PRIMITIVE_FIELD(p, type, offset, value) \
|
||||
(*reinterpret_cast<type*>(FIELD_ADDR(p, offset)) = value)
|
||||
|
||||
#define PRIMITIVE_ACCESSORS(holder, name, type, offset) \
|
||||
type holder::name() const { \
|
||||
return READ_PRIMITIVE_FIELD(this, type, offset); \
|
||||
} \
|
||||
void holder::set_##name(type value) { \
|
||||
WRITE_PRIMITIVE_FIELD(this, type, offset, value); \
|
||||
}
|
||||
|
||||
// WasmModuleObject
|
||||
ACCESSORS(WasmModuleObject, compiled_module, WasmCompiledModule,
|
||||
kCompiledModuleOffset)
|
||||
@ -46,6 +60,18 @@ OPTIONAL_ACCESSORS(WasmMemoryObject, instances, FixedArrayOfWeakCells,
|
||||
// WasmInstanceObject
|
||||
ACCESSORS(WasmInstanceObject, wasm_context, Managed<WasmContext>,
|
||||
kWasmContextOffset)
|
||||
PRIMITIVE_ACCESSORS(WasmInstanceObject, memory_start, byte*, kMemoryStartOffset)
|
||||
PRIMITIVE_ACCESSORS(WasmInstanceObject, memory_size, uintptr_t,
|
||||
kMemorySizeOffset)
|
||||
PRIMITIVE_ACCESSORS(WasmInstanceObject, memory_mask, uintptr_t,
|
||||
kMemoryMaskOffset)
|
||||
PRIMITIVE_ACCESSORS(WasmInstanceObject, globals_start, byte*,
|
||||
kGlobalsStartOffset)
|
||||
PRIMITIVE_ACCESSORS(WasmInstanceObject, indirect_function_table,
|
||||
IndirectFunctionTableEntry*, kIndirectFunctionTableOffset)
|
||||
PRIMITIVE_ACCESSORS(WasmInstanceObject, indirect_function_table_size, uintptr_t,
|
||||
kIndirectFunctionTableSizeOffset)
|
||||
|
||||
ACCESSORS(WasmInstanceObject, compiled_module, WasmCompiledModule,
|
||||
kCompiledModuleOffset)
|
||||
ACCESSORS(WasmInstanceObject, exports_object, JSObject, kExportsObjectOffset)
|
||||
@ -145,6 +171,9 @@ ACCESSORS(WasmCompiledModule, raw_prev_instance, Object, kPrevInstanceOffset);
|
||||
#undef WCM_OBJECT
|
||||
#undef WCM_SMALL_CONST_NUMBER
|
||||
#undef WCM_WEAK_LINK
|
||||
#undef READ_PRIMITIVE_FIELD
|
||||
#undef WRITE_PRIMITIVE_FIELD
|
||||
#undef PRIMITIVE_ACCESSORS
|
||||
|
||||
uint32_t WasmTableObject::current_length() { return functions()->length(); }
|
||||
|
||||
|
@ -535,6 +535,53 @@ int32_t WasmMemoryObject::Grow(Isolate* isolate,
|
||||
return old_size / wasm::kWasmPageSize;
|
||||
}
|
||||
|
||||
bool WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize(
|
||||
size_t minimum_size) {
|
||||
constexpr int kInvalidSigIndex = -1;
|
||||
uintptr_t old_size = indirect_function_table_size();
|
||||
if (old_size >= minimum_size) return false; // Nothing to do.
|
||||
|
||||
size_t new_size = minimum_size;
|
||||
IndirectFunctionTableEntry* new_storage;
|
||||
if (indirect_function_table()) {
|
||||
// Reallocate the old storage.
|
||||
new_storage = reinterpret_cast<IndirectFunctionTableEntry*>(
|
||||
realloc(indirect_function_table(),
|
||||
new_size * sizeof(IndirectFunctionTableEntry)));
|
||||
} else {
|
||||
// Allocate new storage.
|
||||
new_storage = reinterpret_cast<IndirectFunctionTableEntry*>(
|
||||
calloc(new_size, sizeof(IndirectFunctionTableEntry)));
|
||||
}
|
||||
// Initialize new entries.
|
||||
for (size_t j = old_size; j < new_size; j++) {
|
||||
auto entry = indirect_function_table_entry_at(static_cast<int>(j));
|
||||
entry->sig_id = kInvalidSigIndex;
|
||||
entry->context = nullptr;
|
||||
entry->target = nullptr;
|
||||
}
|
||||
set_indirect_function_table_size(new_size);
|
||||
set_indirect_function_table(new_storage);
|
||||
return true;
|
||||
}
|
||||
|
||||
IndirectFunctionTableEntry*
|
||||
WasmInstanceObject::indirect_function_table_entry_at(int i) {
|
||||
DCHECK_GE(i, 0);
|
||||
DCHECK_LT(i, indirect_function_table_size());
|
||||
return &indirect_function_table()[i];
|
||||
}
|
||||
|
||||
void WasmInstanceObject::SetRawMemory(byte* mem_start, size_t mem_size) {
|
||||
DCHECK_LE(mem_size, wasm::kV8MaxWasmMemoryPages * wasm::kWasmPageSize);
|
||||
uint64_t mem_size64 = mem_size;
|
||||
uint64_t mem_mask64 = base::bits::RoundUpToPowerOfTwo64(mem_size) - 1;
|
||||
DCHECK_LE(mem_size, mem_mask64 + 1);
|
||||
set_memory_start(mem_start);
|
||||
set_memory_size(static_cast<uintptr_t>(mem_size64));
|
||||
set_memory_mask(static_cast<uintptr_t>(mem_mask64));
|
||||
}
|
||||
|
||||
WasmModuleObject* WasmInstanceObject::module_object() {
|
||||
return compiled_module()->wasm_module();
|
||||
}
|
||||
@ -567,6 +614,18 @@ Handle<WasmInstanceObject> WasmInstanceObject::New(
|
||||
instance->set_wasm_context(*wasm_context);
|
||||
|
||||
instance->set_compiled_module(*compiled_module);
|
||||
|
||||
// TODO(titzer): ensure that untagged fields are not visited by the GC.
|
||||
// (if they are, the GC will crash).
|
||||
uintptr_t invalid = static_cast<uintptr_t>(kHeapObjectTag);
|
||||
instance->set_memory_start(reinterpret_cast<byte*>(invalid));
|
||||
instance->set_memory_size(invalid);
|
||||
instance->set_memory_mask(invalid);
|
||||
instance->set_globals_start(reinterpret_cast<byte*>(invalid));
|
||||
instance->set_indirect_function_table(
|
||||
reinterpret_cast<IndirectFunctionTableEntry*>(invalid));
|
||||
instance->set_indirect_function_table_size(invalid);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
@ -674,6 +733,15 @@ void InstanceFinalizer(const v8::WeakCallbackInfo<void>& data) {
|
||||
}
|
||||
}
|
||||
|
||||
void* invalid =
|
||||
reinterpret_cast<void*>(static_cast<uintptr_t>(kHeapObjectTag));
|
||||
if (owner->indirect_function_table() &&
|
||||
owner->indirect_function_table() != invalid) {
|
||||
// The indirect function table is C++ memory and needs to be explicitly
|
||||
// freed.
|
||||
free(owner->indirect_function_table());
|
||||
}
|
||||
|
||||
compiled_module->RemoveFromChain();
|
||||
|
||||
compiled_module->reset_weak_owning_instance();
|
||||
|
@ -203,23 +203,36 @@ class WasmInstanceObject : public JSObject {
|
||||
DECL_OPTIONAL_ACCESSORS(debug_info, WasmDebugInfo)
|
||||
DECL_OPTIONAL_ACCESSORS(table_object, WasmTableObject)
|
||||
DECL_OPTIONAL_ACCESSORS(function_tables, FixedArray)
|
||||
DECL_PRIMITIVE_ACCESSORS(memory_start, byte*)
|
||||
DECL_PRIMITIVE_ACCESSORS(memory_size, uintptr_t)
|
||||
DECL_PRIMITIVE_ACCESSORS(memory_mask, uintptr_t)
|
||||
DECL_PRIMITIVE_ACCESSORS(globals_start, byte*)
|
||||
DECL_PRIMITIVE_ACCESSORS(indirect_function_table, IndirectFunctionTableEntry*)
|
||||
DECL_PRIMITIVE_ACCESSORS(indirect_function_table_size, uintptr_t)
|
||||
|
||||
// FixedArray of all instances whose code was imported
|
||||
DECL_ACCESSORS(directly_called_instances, FixedArray)
|
||||
DECL_ACCESSORS(js_imports_table, FixedArray)
|
||||
|
||||
// Layout description.
|
||||
#define WASM_INSTANCE_OBJECT_FIELDS(V) \
|
||||
V(kWasmContextOffset, kPointerSize) \
|
||||
V(kCompiledModuleOffset, kPointerSize) \
|
||||
V(kExportsObjectOffset, kPointerSize) \
|
||||
V(kMemoryObjectOffset, kPointerSize) \
|
||||
V(kGlobalsBufferOffset, kPointerSize) \
|
||||
V(kDebugInfoOffset, kPointerSize) \
|
||||
V(kTableObjectOffset, kPointerSize) \
|
||||
V(kFunctionTablesOffset, kPointerSize) \
|
||||
V(kDirectlyCalledInstancesOffset, kPointerSize) \
|
||||
V(kJsImportsTableOffset, kPointerSize) \
|
||||
#define WASM_INSTANCE_OBJECT_FIELDS(V) \
|
||||
V(kWasmContextOffset, kPointerSize) \
|
||||
V(kCompiledModuleOffset, kPointerSize) \
|
||||
V(kExportsObjectOffset, kPointerSize) \
|
||||
V(kMemoryObjectOffset, kPointerSize) \
|
||||
V(kGlobalsBufferOffset, kPointerSize) \
|
||||
V(kDebugInfoOffset, kPointerSize) \
|
||||
V(kTableObjectOffset, kPointerSize) \
|
||||
V(kFunctionTablesOffset, kPointerSize) \
|
||||
V(kDirectlyCalledInstancesOffset, kPointerSize) \
|
||||
V(kJsImportsTableOffset, kPointerSize) \
|
||||
V(kFirstUntaggedOffset, 0) /* marker */ \
|
||||
V(kMemoryStartOffset, kPointerSize) /* untagged */ \
|
||||
V(kMemorySizeOffset, kPointerSize) /* untagged */ \
|
||||
V(kMemoryMaskOffset, kPointerSize) /* untagged */ \
|
||||
V(kGlobalsStartOffset, kPointerSize) /* untagged */ \
|
||||
V(kIndirectFunctionTableOffset, kPointerSize) /* untagged */ \
|
||||
V(kIndirectFunctionTableSizeOffset, kPointerSize) /* untagged */ \
|
||||
V(kSize, 0)
|
||||
|
||||
DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize,
|
||||
@ -229,6 +242,12 @@ class WasmInstanceObject : public JSObject {
|
||||
WasmModuleObject* module_object();
|
||||
V8_EXPORT_PRIVATE wasm::WasmModule* module();
|
||||
|
||||
bool EnsureIndirectFunctionTableWithMinimumSize(size_t minimum_size);
|
||||
|
||||
IndirectFunctionTableEntry* indirect_function_table_entry_at(int index);
|
||||
|
||||
void SetRawMemory(byte* mem_start, size_t mem_size);
|
||||
|
||||
// Get the debug info associated with the given wasm object.
|
||||
// If no debug info exists yet, it is created automatically.
|
||||
static Handle<WasmDebugInfo> GetOrCreateDebugInfo(Handle<WasmInstanceObject>);
|
||||
@ -252,6 +271,11 @@ class WasmInstanceObject : public JSObject {
|
||||
|
||||
static void InstallFinalizer(Isolate* isolate,
|
||||
Handle<WasmInstanceObject> instance);
|
||||
|
||||
// Iterates all fields in the object except the untagged fields.
|
||||
class BodyDescriptor;
|
||||
// No weak fields.
|
||||
typedef BodyDescriptor BodyDescriptorWeak;
|
||||
};
|
||||
|
||||
// A WASM function that is wrapped and exported to JavaScript.
|
||||
|
Loading…
Reference in New Issue
Block a user