Commit 39bc48e2 authored by Ben L. Titzer's avatar Ben L. Titzer Committed by Commit Bot

[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: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51932}
parent 507fe1d1
......@@ -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.
......
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