[wasm] Introduce instance types for WebAssembly.* objects.

This CL refactors the internal representation of JavaScript-exposed
WebAssembly objects to be more like other such objects in V8. By introducing
a new instance type for each of the JS-exposed types, we get more robust
typechecking without using embedder fields (which were previously used
when these objects where instance type JS_API_OBJECT).

In addition to the new instance types, the subclasses X of JSObject
(WasmInstanceObject, WasmMemoryObject, WasmModuleObject, WasmTableObject)
now have appropriate Is##X() methods on Object and are now robust.

BUG=v8:6547
CQ_INCLUDE_TRYBOTS=master.tryserver.chromium.linux:linux_chromium_rel_ng

Review-Url: https://codereview.chromium.org/2964943002
Cr-Commit-Position: refs/heads/master@{#46475}
This commit is contained in:
titzer 2017-07-07 05:27:56 -07:00 committed by Commit Bot
parent c16a39f23e
commit 17001a05c8
24 changed files with 537 additions and 548 deletions

View File

@ -7703,10 +7703,10 @@ MaybeLocal<Proxy> Proxy::New(Local<Context> context, Local<Object> local_target,
}
Local<String> WasmCompiledModule::GetWasmWireBytes() {
i::Handle<i::JSObject> obj =
i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
i::Handle<i::WasmModuleObject> obj =
i::Handle<i::WasmModuleObject>::cast(Utils::OpenHandle(this));
i::Handle<i::WasmCompiledModule> compiled_part =
i::handle(i::WasmCompiledModule::cast(obj->GetEmbedderField(0)));
i::handle(i::WasmCompiledModule::cast(obj->compiled_module()));
i::Handle<i::String> wire_bytes(compiled_part->module_bytes());
return Local<String>::Cast(Utils::ToLocal(wire_bytes));
}
@ -7742,10 +7742,10 @@ MaybeLocal<WasmCompiledModule> WasmCompiledModule::FromTransferrableModule(
}
WasmCompiledModule::SerializedModule WasmCompiledModule::Serialize() {
i::Handle<i::JSObject> obj =
i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
i::Handle<i::WasmModuleObject> obj =
i::Handle<i::WasmModuleObject>::cast(Utils::OpenHandle(this));
i::Handle<i::WasmCompiledModule> compiled_part =
i::handle(i::WasmCompiledModule::cast(obj->GetEmbedderField(0)));
i::handle(i::WasmCompiledModule::cast(obj->compiled_module()));
std::unique_ptr<i::ScriptData> script_data =
i::WasmCompiledModuleSerializer::SerializeWasmModule(obj->GetIsolate(),

View File

@ -267,6 +267,10 @@ Type::bitset BitsetType::Lub(i::Map* map) {
case JS_WEAK_SET_TYPE:
case JS_PROMISE_CAPABILITY_TYPE:
case JS_PROMISE_TYPE:
case WASM_MODULE_TYPE:
case WASM_INSTANCE_TYPE:
case WASM_MEMORY_TYPE:
case WASM_TABLE_TYPE:
DCHECK(!map->is_callable());
DCHECK(!map->is_undetectable());
return kOtherObject;

View File

@ -3983,6 +3983,10 @@ Handle<Object> TranslatedState::MaterializeCapturedObjectAt(
case PADDING_TYPE_1:
case PADDING_TYPE_2:
case PADDING_TYPE_3:
case WASM_MODULE_TYPE:
case WASM_INSTANCE_TYPE:
case WASM_MEMORY_TYPE:
case WASM_TABLE_TYPE:
OFStream os(stderr);
os << "[couldn't handle instance type " << map->instance_type() << "]"
<< std::endl;

View File

@ -3641,6 +3641,10 @@ AllocationResult Heap::CopyJSObject(JSObject* source, AllocationSite* site) {
map->instance_type() == JS_ERROR_TYPE ||
map->instance_type() == JS_ARRAY_TYPE ||
map->instance_type() == JS_API_OBJECT_TYPE ||
map->instance_type() == WASM_INSTANCE_TYPE ||
map->instance_type() == WASM_MEMORY_TYPE ||
map->instance_type() == WASM_MODULE_TYPE ||
map->instance_type() == WASM_TABLE_TYPE ||
map->instance_type() == JS_SPECIAL_API_OBJECT_TYPE);
int object_size = map->instance_size();

View File

@ -658,6 +658,10 @@ 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 JS_WEAK_MAP_TYPE:
case JS_WEAK_SET_TYPE:

View File

@ -110,6 +110,10 @@ void HeapObject::HeapObjectVerify() {
case JS_API_OBJECT_TYPE:
case JS_SPECIAL_API_OBJECT_TYPE:
case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
case WASM_INSTANCE_TYPE:
case WASM_MEMORY_TYPE:
case WASM_MODULE_TYPE:
case WASM_TABLE_TYPE:
JSObject::cast(this)->JSObjectVerify();
break;
case JS_ARGUMENTS_TYPE:

View File

@ -106,6 +106,10 @@ TYPE_CHECKER(JSTypedArray, JS_TYPED_ARRAY_TYPE)
TYPE_CHECKER(JSValue, JS_VALUE_TYPE)
TYPE_CHECKER(JSWeakMap, JS_WEAK_MAP_TYPE)
TYPE_CHECKER(JSWeakSet, JS_WEAK_SET_TYPE)
TYPE_CHECKER(WasmInstanceObject, WASM_INSTANCE_TYPE)
TYPE_CHECKER(WasmMemoryObject, WASM_MEMORY_TYPE)
TYPE_CHECKER(WasmModuleObject, WASM_MODULE_TYPE)
TYPE_CHECKER(WasmTableObject, WASM_TABLE_TYPE)
TYPE_CHECKER(Map, MAP_TYPE)
TYPE_CHECKER(MutableHeapNumber, MUTABLE_HEAP_NUMBER_TYPE)
TYPE_CHECKER(Oddball, ODDBALL_TYPE)
@ -1476,79 +1480,12 @@ void WeakCell::clear_next(Object* the_hole_value) {
bool WeakCell::next_cleared() { return next()->IsTheHole(GetIsolate()); }
int JSObject::GetHeaderSize() { return GetHeaderSize(map()->instance_type()); }
int JSObject::GetHeaderSize(InstanceType type) {
int JSObject::GetHeaderSize() {
// Check for the most common kind of JavaScript object before
// falling into the generic switch. This speeds up the internal
// field operations considerably on average.
if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
switch (type) {
case JS_API_OBJECT_TYPE:
case JS_SPECIAL_API_OBJECT_TYPE:
return JSObject::kHeaderSize;
case JS_GENERATOR_OBJECT_TYPE:
return JSGeneratorObject::kSize;
case JS_ASYNC_GENERATOR_OBJECT_TYPE:
return JSAsyncGeneratorObject::kSize;
case JS_GLOBAL_PROXY_TYPE:
return JSGlobalProxy::kSize;
case JS_GLOBAL_OBJECT_TYPE:
return JSGlobalObject::kSize;
case JS_BOUND_FUNCTION_TYPE:
return JSBoundFunction::kSize;
case JS_FUNCTION_TYPE:
return JSFunction::kSize;
case JS_VALUE_TYPE:
return JSValue::kSize;
case JS_DATE_TYPE:
return JSDate::kSize;
case JS_ARRAY_TYPE:
return JSArray::kSize;
case JS_ARRAY_BUFFER_TYPE:
return JSArrayBuffer::kSize;
case JS_TYPED_ARRAY_TYPE:
return JSTypedArray::kSize;
case JS_DATA_VIEW_TYPE:
return JSDataView::kSize;
case JS_SET_TYPE:
return JSSet::kSize;
case JS_MAP_TYPE:
return JSMap::kSize;
case JS_SET_ITERATOR_TYPE:
return JSSetIterator::kSize;
case JS_MAP_ITERATOR_TYPE:
return JSMapIterator::kSize;
case JS_WEAK_MAP_TYPE:
return JSWeakMap::kSize;
case JS_WEAK_SET_TYPE:
return JSWeakSet::kSize;
case JS_PROMISE_CAPABILITY_TYPE:
return JSPromiseCapability::kSize;
case JS_PROMISE_TYPE:
return JSPromise::kSize;
case JS_REGEXP_TYPE:
return JSRegExp::kSize;
case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
return JSObject::kHeaderSize;
case JS_MESSAGE_OBJECT_TYPE:
return JSMessageObject::kSize;
case JS_ARGUMENTS_TYPE:
return JSArgumentsObject::kHeaderSize;
case JS_ERROR_TYPE:
return JSObject::kHeaderSize;
case JS_STRING_ITERATOR_TYPE:
return JSStringIterator::kSize;
case JS_MODULE_NAMESPACE_TYPE:
return JSModuleNamespace::kHeaderSize;
default:
if (type >= FIRST_ARRAY_ITERATOR_TYPE &&
type <= LAST_ARRAY_ITERATOR_TYPE) {
return JSArrayIterator::kSize;
}
UNREACHABLE();
}
InstanceType type = map()->instance_type();
return type == JS_OBJECT_TYPE ? JSObject::kHeaderSize : GetHeaderSize(type);
}
inline bool IsSpecialReceiverInstanceType(InstanceType instance_type) {

View File

@ -153,6 +153,10 @@ void HeapObject::HeapObjectPrint(std::ostream& os) { // NOLINT
case JS_ARGUMENTS_TYPE:
case JS_ERROR_TYPE:
case JS_PROMISE_CAPABILITY_TYPE:
case WASM_INSTANCE_TYPE: // TODO(titzer): debug printing for wasm objects
case WASM_MEMORY_TYPE:
case WASM_MODULE_TYPE:
case WASM_TABLE_TYPE:
JSObject::cast(this)->JSObjectPrint(os);
break;
case JS_PROMISE_TYPE:

View File

@ -1290,6 +1290,82 @@ void JSObject::EnsureWritableFastElements(Handle<JSObject> object) {
isolate->counters()->cow_arrays_converted()->Increment();
}
int JSObject::GetHeaderSize(InstanceType type) {
switch (type) {
case JS_OBJECT_TYPE:
case JS_API_OBJECT_TYPE:
case JS_SPECIAL_API_OBJECT_TYPE:
return JSObject::kHeaderSize;
case JS_GENERATOR_OBJECT_TYPE:
return JSGeneratorObject::kSize;
case JS_ASYNC_GENERATOR_OBJECT_TYPE:
return JSAsyncGeneratorObject::kSize;
case JS_GLOBAL_PROXY_TYPE:
return JSGlobalProxy::kSize;
case JS_GLOBAL_OBJECT_TYPE:
return JSGlobalObject::kSize;
case JS_BOUND_FUNCTION_TYPE:
return JSBoundFunction::kSize;
case JS_FUNCTION_TYPE:
return JSFunction::kSize;
case JS_VALUE_TYPE:
return JSValue::kSize;
case JS_DATE_TYPE:
return JSDate::kSize;
case JS_ARRAY_TYPE:
return JSArray::kSize;
case JS_ARRAY_BUFFER_TYPE:
return JSArrayBuffer::kSize;
case JS_TYPED_ARRAY_TYPE:
return JSTypedArray::kSize;
case JS_DATA_VIEW_TYPE:
return JSDataView::kSize;
case JS_SET_TYPE:
return JSSet::kSize;
case JS_MAP_TYPE:
return JSMap::kSize;
case JS_SET_ITERATOR_TYPE:
return JSSetIterator::kSize;
case JS_MAP_ITERATOR_TYPE:
return JSMapIterator::kSize;
case JS_WEAK_MAP_TYPE:
return JSWeakMap::kSize;
case JS_WEAK_SET_TYPE:
return JSWeakSet::kSize;
case JS_PROMISE_CAPABILITY_TYPE:
return JSPromiseCapability::kSize;
case JS_PROMISE_TYPE:
return JSPromise::kSize;
case JS_REGEXP_TYPE:
return JSRegExp::kSize;
case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
return JSObject::kHeaderSize;
case JS_MESSAGE_OBJECT_TYPE:
return JSMessageObject::kSize;
case JS_ARGUMENTS_TYPE:
return JSArgumentsObject::kHeaderSize;
case JS_ERROR_TYPE:
return JSObject::kHeaderSize;
case JS_STRING_ITERATOR_TYPE:
return JSStringIterator::kSize;
case JS_MODULE_NAMESPACE_TYPE:
return JSModuleNamespace::kHeaderSize;
case WASM_INSTANCE_TYPE:
return WasmInstanceObject::kSize;
case WASM_MEMORY_TYPE:
return WasmMemoryObject::kSize;
case WASM_MODULE_TYPE:
return WasmModuleObject::kSize;
case WASM_TABLE_TYPE:
return WasmTableObject::kSize;
default:
if (type >= FIRST_ARRAY_ITERATOR_TYPE &&
type <= LAST_ARRAY_ITERATOR_TYPE) {
return JSArrayIterator::kSize;
}
UNREACHABLE();
}
}
// ES6 9.5.1
// static
@ -3011,6 +3087,10 @@ VisitorId Map::GetVisitorId(Map* map) {
case JS_PROMISE_CAPABILITY_TYPE:
case JS_PROMISE_TYPE:
case WASM_INSTANCE_TYPE:
case WASM_MEMORY_TYPE:
case WASM_MODULE_TYPE:
case WASM_TABLE_TYPE:
case JS_BOUND_FUNCTION_TYPE:
return has_unboxed_fields ? kVisitJSObject : kVisitJSObjectFast;
case JS_API_OBJECT_TYPE:

View File

@ -73,6 +73,10 @@
// - JSDate
// - JSMessageObject
// - JSModuleNamespace
// - WasmInstanceObject
// - WasmMemoryObject
// - WasmModuleObject
// - WasmTableObject
// - JSProxy
// - FixedArrayBase
// - ByteArray
@ -99,6 +103,8 @@
// - ModuleInfo
// - ScriptContextTable
// - WeakFixedArray
// - WasmSharedModuleData
// - WasmCompiledModule
// - FixedDoubleArray
// - Name
// - String
@ -445,6 +451,10 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1;
V(JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE) \
V(JS_GENERIC_ARRAY_VALUE_ITERATOR_TYPE) \
\
V(WASM_INSTANCE_TYPE) \
V(WASM_MEMORY_TYPE) \
V(WASM_MODULE_TYPE) \
V(WASM_TABLE_TYPE) \
V(JS_BOUND_FUNCTION_TYPE) \
V(JS_FUNCTION_TYPE)
@ -798,6 +808,10 @@ enum InstanceType {
JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE,
JS_GENERIC_ARRAY_VALUE_ITERATOR_TYPE,
WASM_INSTANCE_TYPE,
WASM_MEMORY_TYPE,
WASM_MODULE_TYPE,
WASM_TABLE_TYPE,
JS_BOUND_FUNCTION_TYPE,
JS_FUNCTION_TYPE, // LAST_JS_OBJECT_TYPE, LAST_JS_RECEIVER_TYPE
@ -1053,6 +1067,10 @@ template <class C> inline bool Is(Object* obj);
V(JSMapIterator) \
V(JSMessageObject) \
V(JSModuleNamespace) \
V(WasmInstanceObject) \
V(WasmMemoryObject) \
V(WasmModuleObject) \
V(WasmTableObject) \
V(JSObject) \
V(JSPromise) \
V(JSPromiseCapability) \
@ -2389,7 +2407,7 @@ class JSObject: public JSReceiver {
// Get the header size for a JSObject. Used to compute the index of
// embedder fields as well as the number of embedder fields.
static inline int GetHeaderSize(InstanceType instance_type);
static int GetHeaderSize(InstanceType instance_type);
inline int GetHeaderSize();
static inline int GetEmbedderFieldCount(const Map* map);

View File

@ -864,16 +864,12 @@ RUNTIME_FUNCTION(Runtime_SpeciesProtector) {
return isolate->heap()->ToBoolean(isolate->IsArraySpeciesLookupChainIntact());
}
#define CONVERT_ARG_HANDLE_CHECKED_2(Type, name, index) \
CHECK(Type::Is##Type(args[index])); \
Handle<Type> name = args.at<Type>(index);
// Take a compiled wasm module, serialize it and copy the buffer into an array
// buffer, which is then returned.
RUNTIME_FUNCTION(Runtime_SerializeWasmModule) {
HandleScope shs(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED_2(WasmModuleObject, module_obj, 0);
CONVERT_ARG_HANDLE_CHECKED(WasmModuleObject, module_obj, 0);
Handle<WasmCompiledModule> orig(module_obj->compiled_module());
std::unique_ptr<ScriptData> data =
@ -925,7 +921,7 @@ RUNTIME_FUNCTION(Runtime_DeserializeWasmModule) {
RUNTIME_FUNCTION(Runtime_ValidateWasmInstancesChain) {
HandleScope shs(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED_2(WasmModuleObject, module_obj, 0);
CONVERT_ARG_HANDLE_CHECKED(WasmModuleObject, module_obj, 0);
CONVERT_ARG_HANDLE_CHECKED(Smi, instance_count, 1);
wasm::testing::ValidateInstancesChain(isolate, module_obj,
instance_count->value());
@ -935,7 +931,7 @@ RUNTIME_FUNCTION(Runtime_ValidateWasmInstancesChain) {
RUNTIME_FUNCTION(Runtime_ValidateWasmModuleState) {
HandleScope shs(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED_2(WasmModuleObject, module_obj, 0);
CONVERT_ARG_HANDLE_CHECKED(WasmModuleObject, module_obj, 0);
wasm::testing::ValidateModuleState(isolate, module_obj);
return isolate->heap()->ToBoolean(true);
}
@ -943,7 +939,7 @@ RUNTIME_FUNCTION(Runtime_ValidateWasmModuleState) {
RUNTIME_FUNCTION(Runtime_ValidateWasmOrphanedInstance) {
HandleScope shs(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED_2(WasmInstanceObject, instance, 0);
CONVERT_ARG_HANDLE_CHECKED(WasmInstanceObject, instance, 0);
wasm::testing::ValidateOrphanedInstance(isolate, instance);
return isolate->heap()->ToBoolean(true);
}
@ -968,10 +964,7 @@ RUNTIME_FUNCTION(Runtime_HeapObjectVerify) {
RUNTIME_FUNCTION(Runtime_WasmNumInterpretedCalls) {
DCHECK_EQ(1, args.length());
HandleScope scope(isolate);
CONVERT_ARG_HANDLE_CHECKED(JSObject, instance_obj, 0);
CHECK(WasmInstanceObject::IsWasmInstanceObject(*instance_obj));
Handle<WasmInstanceObject> instance =
Handle<WasmInstanceObject>::cast(instance_obj);
CONVERT_ARG_HANDLE_CHECKED(WasmInstanceObject, instance, 0);
if (!instance->has_debug_info()) return 0;
uint64_t num = instance->debug_info()->NumInterpretedCalls();
return *isolate->factory()->NewNumberFromSize(static_cast<size_t>(num));
@ -980,11 +973,8 @@ RUNTIME_FUNCTION(Runtime_WasmNumInterpretedCalls) {
RUNTIME_FUNCTION(Runtime_RedirectToWasmInterpreter) {
DCHECK_EQ(2, args.length());
HandleScope scope(isolate);
CONVERT_ARG_HANDLE_CHECKED(JSObject, instance_obj, 0);
CONVERT_ARG_HANDLE_CHECKED(WasmInstanceObject, instance, 0);
CONVERT_SMI_ARG_CHECKED(function_index, 1);
CHECK(WasmInstanceObject::IsWasmInstanceObject(*instance_obj));
Handle<WasmInstanceObject> instance =
Handle<WasmInstanceObject>::cast(instance_obj);
Handle<WasmDebugInfo> debug_info =
WasmInstanceObject::GetOrCreateDebugInfo(instance);
WasmDebugInfo::RedirectToInterpreter(debug_info,

View File

@ -180,12 +180,9 @@ RUNTIME_FUNCTION(Runtime_ClearThreadInWasm) {
RUNTIME_FUNCTION(Runtime_WasmRunInterpreter) {
DCHECK_EQ(3, args.length());
HandleScope scope(isolate);
CONVERT_ARG_HANDLE_CHECKED(JSObject, instance_obj, 0);
CONVERT_ARG_HANDLE_CHECKED(WasmInstanceObject, instance, 0);
CONVERT_NUMBER_CHECKED(int32_t, func_index, Int32, args[1]);
CONVERT_ARG_HANDLE_CHECKED(Object, arg_buffer_obj, 2);
CHECK(WasmInstanceObject::IsWasmInstanceObject(*instance_obj));
Handle<WasmInstanceObject> instance =
Handle<WasmInstanceObject>::cast(instance_obj);
// The arg buffer is the raw pointer to the caller's stack. It looks like a
// Smi (lowest bit not set, as checked by IsSmi), but is no valid Smi. We just

View File

@ -449,12 +449,7 @@ Maybe<bool> ValueSerializer::WriteJSReceiver(Handle<JSReceiver> receiver) {
case JS_OBJECT_TYPE:
case JS_API_OBJECT_TYPE: {
Handle<JSObject> js_object = Handle<JSObject>::cast(receiver);
Map* map = js_object->map();
if (!FLAG_wasm_disable_structured_cloning &&
map->GetConstructor() ==
isolate_->native_context()->wasm_module_constructor()) {
return WriteWasmModule(js_object);
} else if (JSObject::GetEmbedderFieldCount(map)) {
if (JSObject::GetEmbedderFieldCount(js_object->map())) {
return WriteHostObject(js_object);
} else {
return WriteJSObject(js_object);
@ -479,6 +474,11 @@ Maybe<bool> ValueSerializer::WriteJSReceiver(Handle<JSReceiver> receiver) {
case JS_TYPED_ARRAY_TYPE:
case JS_DATA_VIEW_TYPE:
return WriteJSArrayBufferView(JSArrayBufferView::cast(*receiver));
case WASM_MODULE_TYPE:
if (!FLAG_wasm_disable_structured_cloning) {
// Only write WebAssembly modules if not disabled by a flag.
return WriteWasmModule(Handle<WasmModuleObject>::cast(receiver));
} // fall through to error case
default:
ThrowDataCloneError(MessageTemplate::kDataCloneError, receiver);
return Nothing<bool>();
@ -815,11 +815,13 @@ Maybe<bool> ValueSerializer::WriteJSArrayBufferView(JSArrayBufferView* view) {
return ThrowIfOutOfMemory();
}
Maybe<bool> ValueSerializer::WriteWasmModule(Handle<JSObject> object) {
Maybe<bool> ValueSerializer::WriteWasmModule(Handle<WasmModuleObject> object) {
if (delegate_ != nullptr) {
// TODO(titzer): introduce a Utils::ToLocal for WasmModuleObject.
Maybe<uint32_t> transfer_id = delegate_->GetWasmModuleTransferId(
reinterpret_cast<v8::Isolate*>(isolate_),
v8::Local<v8::WasmCompiledModule>::Cast(Utils::ToLocal(object)));
v8::Local<v8::WasmCompiledModule>::Cast(
Utils::ToLocal(Handle<JSObject>::cast(object))));
RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate_, Nothing<bool>());
uint32_t id = 0;
if (transfer_id.To(&id)) {
@ -829,8 +831,7 @@ Maybe<bool> ValueSerializer::WriteWasmModule(Handle<JSObject> object) {
}
}
Handle<WasmCompiledModule> compiled_part(
WasmCompiledModule::cast(object->GetEmbedderField(0)), isolate_);
Handle<WasmCompiledModule> compiled_part(object->compiled_module(), isolate_);
WasmEncodingTag encoding_tag = WasmEncodingTag::kRawBytes;
WriteTag(SerializationTag::kWasmModule);
WriteRawBytes(&encoding_tag, sizeof(encoding_tag));

View File

@ -125,7 +125,8 @@ class ValueSerializer {
Maybe<bool> WriteJSArrayBuffer(Handle<JSArrayBuffer> array_buffer)
WARN_UNUSED_RESULT;
Maybe<bool> WriteJSArrayBufferView(JSArrayBufferView* array_buffer);
Maybe<bool> WriteWasmModule(Handle<JSObject> object) WARN_UNUSED_RESULT;
Maybe<bool> WriteWasmModule(Handle<WasmModuleObject> object)
WARN_UNUSED_RESULT;
Maybe<bool> WriteHostObject(Handle<JSObject> object) WARN_UNUSED_RESULT;
/*

View File

@ -1022,7 +1022,7 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
//--------------------------------------------------------------------------
// Add instance to Memory object
//--------------------------------------------------------------------------
DCHECK(wasm::IsWasmInstance(*instance));
DCHECK(instance->IsWasmInstanceObject());
if (instance->has_memory_object()) {
instance->memory_object()->AddInstance(isolate_, instance);
}
@ -1074,7 +1074,7 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
compiled_module_->set_weak_wasm_module(
original.ToHandleChecked()->weak_wasm_module());
}
module_object_->SetEmbedderField(0, *compiled_module_);
module_object_->set_compiled_module(*compiled_module_);
compiled_module_->set_weak_owning_instance(link_to_owning_instance);
GlobalHandles::MakeWeak(
global_handle.location(), global_handle.location(),
@ -1398,7 +1398,7 @@ int InstanceBuilder::ProcessImports(Handle<FixedArray> code_table,
auto memory = Handle<WasmMemoryObject>::cast(value);
DCHECK(WasmJs::IsWasmMemoryObject(isolate_, memory));
instance->set_memory_object(*memory);
memory_ = Handle<JSArrayBuffer>(memory->buffer(), isolate_);
memory_ = Handle<JSArrayBuffer>(memory->array_buffer(), isolate_);
uint32_t imported_cur_pages = static_cast<uint32_t>(
memory_->byte_length()->Number() / WasmModule::kPageSize);
if (imported_cur_pages < module_->min_mem_pages) {
@ -1668,7 +1668,6 @@ void InstanceBuilder::ProcessExports(
} else {
memory_object =
Handle<WasmMemoryObject>(instance->memory_object(), isolate_);
DCHECK(WasmJs::IsWasmMemoryObject(isolate_, memory_object));
memory_object->ResetInstancesLink(isolate_);
}

View File

@ -539,25 +539,25 @@ class InterpreterHandle {
InterpreterHandle* GetOrCreateInterpreterHandle(
Isolate* isolate, Handle<WasmDebugInfo> debug_info) {
Handle<Object> handle(debug_info->get(WasmDebugInfo::kInterpreterHandle),
Handle<Object> handle(debug_info->get(WasmDebugInfo::kInterpreterHandleIndex),
isolate);
if (handle->IsUndefined(isolate)) {
InterpreterHandle* cpp_handle = new InterpreterHandle(isolate, *debug_info);
handle = Managed<InterpreterHandle>::New(isolate, cpp_handle);
debug_info->set(WasmDebugInfo::kInterpreterHandle, *handle);
debug_info->set(WasmDebugInfo::kInterpreterHandleIndex, *handle);
}
return Handle<Managed<InterpreterHandle>>::cast(handle)->get();
}
InterpreterHandle* GetInterpreterHandle(WasmDebugInfo* debug_info) {
Object* handle_obj = debug_info->get(WasmDebugInfo::kInterpreterHandle);
Object* handle_obj = debug_info->get(WasmDebugInfo::kInterpreterHandleIndex);
DCHECK(!handle_obj->IsUndefined(debug_info->GetIsolate()));
return Managed<InterpreterHandle>::cast(handle_obj)->get();
}
InterpreterHandle* GetInterpreterHandleOrNull(WasmDebugInfo* debug_info) {
Object* handle_obj = debug_info->get(WasmDebugInfo::kInterpreterHandle);
Object* handle_obj = debug_info->get(WasmDebugInfo::kInterpreterHandleIndex);
if (handle_obj->IsUndefined(debug_info->GetIsolate())) return nullptr;
return Managed<InterpreterHandle>::cast(handle_obj)->get();
}
@ -571,13 +571,13 @@ int GetNumFunctions(WasmInstanceObject* instance) {
Handle<FixedArray> GetOrCreateInterpretedFunctions(
Isolate* isolate, Handle<WasmDebugInfo> debug_info) {
Handle<Object> obj(debug_info->get(WasmDebugInfo::kInterpretedFunctions),
Handle<Object> obj(debug_info->get(WasmDebugInfo::kInterpretedFunctionsIndex),
isolate);
if (!obj->IsUndefined(isolate)) return Handle<FixedArray>::cast(obj);
Handle<FixedArray> new_arr = isolate->factory()->NewFixedArray(
GetNumFunctions(debug_info->wasm_instance()));
debug_info->set(WasmDebugInfo::kInterpretedFunctions, *new_arr);
debug_info->set(WasmDebugInfo::kInterpretedFunctionsIndex, *new_arr);
return new_arr;
}
@ -622,8 +622,7 @@ Handle<WasmDebugInfo> WasmDebugInfo::New(Handle<WasmInstanceObject> instance) {
DCHECK(!instance->has_debug_info());
Factory* factory = instance->GetIsolate()->factory();
Handle<FixedArray> arr = factory->NewFixedArray(kFieldCount, TENURED);
arr->set(kWrapperTracerHeader, Smi::kZero);
arr->set(kInstance, *instance);
arr->set(kInstanceIndex, *instance);
Handle<WasmDebugInfo> debug_info = Handle<WasmDebugInfo>::cast(arr);
instance->set_debug_info(*debug_info);
return debug_info;
@ -636,29 +635,29 @@ WasmInterpreter* WasmDebugInfo::SetupForTesting(
InterpreterHandle* cpp_handle =
new InterpreterHandle(isolate, *debug_info, instance);
Handle<Object> handle = Managed<InterpreterHandle>::New(isolate, cpp_handle);
debug_info->set(kInterpreterHandle, *handle);
debug_info->set(kInterpreterHandleIndex, *handle);
return cpp_handle->interpreter();
}
bool WasmDebugInfo::IsDebugInfo(Object* object) {
bool WasmDebugInfo::IsWasmDebugInfo(Object* object) {
if (!object->IsFixedArray()) return false;
FixedArray* arr = FixedArray::cast(object);
if (arr->length() != kFieldCount) return false;
if (!IsWasmInstance(arr->get(kInstance))) return false;
if (!arr->get(kInstanceIndex)->IsWasmInstanceObject()) return false;
Isolate* isolate = arr->GetIsolate();
if (!arr->get(kInterpreterHandle)->IsUndefined(isolate) &&
!arr->get(kInterpreterHandle)->IsForeign())
if (!arr->get(kInterpreterHandleIndex)->IsUndefined(isolate) &&
!arr->get(kInterpreterHandleIndex)->IsForeign())
return false;
return true;
}
WasmDebugInfo* WasmDebugInfo::cast(Object* object) {
DCHECK(IsDebugInfo(object));
DCHECK(IsWasmDebugInfo(object));
return reinterpret_cast<WasmDebugInfo*>(object);
}
WasmInstanceObject* WasmDebugInfo::wasm_instance() {
return WasmInstanceObject::cast(get(kInstance));
return WasmInstanceObject::cast(get(kInstanceIndex));
}
void WasmDebugInfo::SetBreakpoint(Handle<WasmDebugInfo> debug_info,

View File

@ -90,7 +90,7 @@ struct WasmVal {
}
};
#define DECLARE_CAST(field, localtype, ctype) \
#define DECLARE_CASTS(field, localtype, ctype) \
template <> \
inline ctype WasmVal::to_unchecked() const { \
return val.field; \
@ -100,7 +100,7 @@ struct WasmVal {
CHECK_EQ(localtype, type); \
return val.field; \
}
FOREACH_UNION_MEMBER(DECLARE_CAST)
FOREACH_UNION_MEMBER(DECLARE_CASTS)
#undef DECLARE_CAST
// Representation of frames within the interpreter.

View File

@ -69,7 +69,7 @@ class ScheduledErrorThrower : public ErrorThrower {
}
};
// TODO(wasm): move brand check to the respective types, and don't throw
// TODO(titzer): move brand check to the respective types, and don't throw
// in it, rather, use a provided ErrorThrower, or let caller handle it.
static bool HasBrand(i::Handle<i::Object> value, i::Handle<i::Symbol> sym) {
if (!value->IsJSObject()) return false;
@ -780,7 +780,7 @@ void WebAssemblyMemoryGrow(const v8::FunctionCallbackInfo<v8::Value>& args) {
max_size64 > static_cast<int64_t>(i::FLAG_wasm_max_mem_pages)) {
max_size64 = i::FLAG_wasm_max_mem_pages;
}
i::Handle<i::JSArrayBuffer> old_buffer(receiver->buffer());
i::Handle<i::JSArrayBuffer> old_buffer(receiver->array_buffer());
uint32_t old_size =
old_buffer->byte_length()->Number() / i::wasm::kSpecMaxWasmMemoryPages;
int64_t new_size64 = old_size + delta_size;
@ -817,7 +817,7 @@ void WebAssemblyMemoryGetBuffer(
}
i::Handle<i::WasmMemoryObject> receiver =
i::Handle<i::WasmMemoryObject>::cast(Utils::OpenHandle(*args.This()));
i::Handle<i::Object> buffer(receiver->buffer(), i_isolate);
i::Handle<i::Object> buffer(receiver->array_buffer(), i_isolate);
DCHECK(buffer->IsJSArrayBuffer());
v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
return_value.Set(Utils::ToLocal(buffer));
@ -879,12 +879,9 @@ void WasmJs::Install(Isolate* isolate) {
int pre_allocated =
prev_map->GetInObjectProperties() - prev_map->unused_property_fields();
int instance_size = 0;
int in_object_properties = 0;
int wasm_embedder_fields = embedder_fields + 1 // module instance object
+ 1 // function arity
+ 1; // function signature
JSFunction::CalculateInstanceSizeHelper(instance_type, wasm_embedder_fields,
0, &instance_size,
int in_object_properties = WasmExportedFunction::kFieldCount;
JSFunction::CalculateInstanceSizeHelper(instance_type, embedder_fields,
in_object_properties, &instance_size,
&in_object_properties);
int unused_property_fields = in_object_properties - pre_allocated;
@ -942,8 +939,8 @@ void WasmJs::Install(Isolate* isolate) {
Handle<JSObject> module_proto =
factory->NewJSObject(module_constructor, TENURED);
i::Handle<i::Map> module_map = isolate->factory()->NewMap(
i::JS_API_OBJECT_TYPE, i::JSObject::kHeaderSize +
WasmModuleObject::kFieldCount * i::kPointerSize);
i::WASM_MODULE_TYPE, i::JSObject::kHeaderSize +
WasmModuleObject::kFieldCount * i::kPointerSize);
JSFunction::SetInitialMap(module_constructor, module_map, module_proto);
InstallFunc(isolate, module_constructor, "imports", WebAssemblyModuleImports,
1);
@ -963,8 +960,7 @@ void WasmJs::Install(Isolate* isolate) {
Handle<JSObject> instance_proto =
factory->NewJSObject(instance_constructor, TENURED);
i::Handle<i::Map> instance_map = isolate->factory()->NewMap(
i::JS_API_OBJECT_TYPE, i::JSObject::kHeaderSize +
WasmInstanceObject::kFieldCount * i::kPointerSize);
i::WASM_INSTANCE_TYPE, WasmInstanceObject::kSize);
JSFunction::SetInitialMap(instance_constructor, instance_map, instance_proto);
JSObject::AddProperty(instance_proto,
isolate->factory()->constructor_string(),
@ -978,9 +974,8 @@ void WasmJs::Install(Isolate* isolate) {
context->set_wasm_table_constructor(*table_constructor);
Handle<JSObject> table_proto =
factory->NewJSObject(table_constructor, TENURED);
i::Handle<i::Map> table_map = isolate->factory()->NewMap(
i::JS_API_OBJECT_TYPE, i::JSObject::kHeaderSize +
WasmTableObject::kFieldCount * i::kPointerSize);
i::Handle<i::Map> table_map =
isolate->factory()->NewMap(i::WASM_TABLE_TYPE, WasmTableObject::kSize);
JSFunction::SetInitialMap(table_constructor, table_map, table_proto);
JSObject::AddProperty(table_proto, isolate->factory()->constructor_string(),
table_constructor, DONT_ENUM);
@ -997,9 +992,8 @@ void WasmJs::Install(Isolate* isolate) {
context->set_wasm_memory_constructor(*memory_constructor);
Handle<JSObject> memory_proto =
factory->NewJSObject(memory_constructor, TENURED);
i::Handle<i::Map> memory_map = isolate->factory()->NewMap(
i::JS_API_OBJECT_TYPE, i::JSObject::kHeaderSize +
WasmMemoryObject::kFieldCount * i::kPointerSize);
i::Handle<i::Map> memory_map =
isolate->factory()->NewMap(i::WASM_MEMORY_TYPE, WasmMemoryObject::kSize);
JSFunction::SetInitialMap(memory_constructor, memory_map, memory_proto);
JSObject::AddProperty(memory_proto, isolate->factory()->constructor_string(),
memory_constructor, DONT_ENUM);

View File

@ -159,9 +159,9 @@ static void InstanceFinalizer(const v8::WeakCallbackInfo<void>& data) {
// was GC-ed. In that case, there won't be any new instances created,
// and we don't need to maintain the links between instances.
if (!weak_wasm_module->cleared()) {
JSObject* wasm_module = JSObject::cast(weak_wasm_module->value());
WasmCompiledModule* current_template =
WasmCompiledModule::cast(wasm_module->GetEmbedderField(0));
WasmModuleObject* wasm_module =
WasmModuleObject::cast(weak_wasm_module->value());
WasmCompiledModule* current_template = wasm_module->compiled_module();
TRACE("chain before {\n");
TRACE_CHAIN(current_template);
@ -175,10 +175,12 @@ static void InstanceFinalizer(const v8::WeakCallbackInfo<void>& data) {
if (next == nullptr) {
WasmCompiledModule::Reset(isolate, compiled_module);
} else {
DCHECK(next->value()->IsFixedArray());
wasm_module->SetEmbedderField(0, next->value());
WasmCompiledModule* next_compiled_module =
WasmCompiledModule::cast(next->value());
WasmModuleObject::cast(wasm_module)
->set_compiled_module(next_compiled_module);
DCHECK_NULL(prev);
WasmCompiledModule::cast(next->value())->reset_weak_prev_instance();
next_compiled_module->reset_weak_prev_instance();
}
} else {
DCHECK(!(prev == nullptr && next == nullptr));
@ -205,7 +207,7 @@ static void InstanceFinalizer(const v8::WeakCallbackInfo<void>& data) {
}
}
TRACE("chain after {\n");
TRACE_CHAIN(WasmCompiledModule::cast(wasm_module->GetEmbedderField(0)));
TRACE_CHAIN(wasm_module->compiled_module());
TRACE("}\n");
}
compiled_module->reset_weak_owning_instance();
@ -452,10 +454,6 @@ void wasm::TableSet(ErrorThrower* thrower, Isolate* isolate,
array->set(index, *value);
}
bool wasm::IsWasmInstance(Object* object) {
return WasmInstanceObject::IsWasmInstanceObject(object);
}
Handle<Script> wasm::GetScript(Handle<JSObject> instance) {
WasmCompiledModule* compiled_module =
WasmInstanceObject::cast(*instance)->compiled_module();
@ -514,8 +512,9 @@ void testing::ValidateInstancesChain(Isolate* isolate,
CHECK((prev == nullptr && !current_instance->has_weak_prev_instance()) ||
current_instance->ptr_to_weak_prev_instance()->value() == prev);
CHECK_EQ(current_instance->ptr_to_weak_wasm_module()->value(), *module_obj);
CHECK(IsWasmInstance(
current_instance->ptr_to_weak_owning_instance()->value()));
CHECK(current_instance->ptr_to_weak_owning_instance()
->value()
->IsWasmInstanceObject());
prev = current_instance;
current_instance = WasmCompiledModule::cast(
current_instance->ptr_to_weak_next_instance()->value());

View File

@ -384,13 +384,6 @@ std::ostream& operator<<(std::ostream& os, const WasmFunctionName& name);
// If no debug info exists yet, it is created automatically.
Handle<WasmDebugInfo> GetDebugInfo(Handle<JSObject> wasm);
// Check whether the given object represents a WebAssembly.Instance instance.
// This checks the number and type of embedder fields, so it's not 100 percent
// secure. If it turns out that we need more complete checks, we could add a
// special marker as embedder field, which will definitely never occur anywhere
// else.
bool IsWasmInstance(Object* instance);
// Get the script of the wasm module. If the origin of the module is asm.js, the
// returned Script will be a JavaScript Script of Script::TYPE_NORMAL, otherwise
// it's of type TYPE_WASM.

View File

@ -29,46 +29,6 @@
using namespace v8::internal;
using namespace v8::internal::wasm;
#define DEFINE_GETTER0(getter, Container, name, field, type) \
type* Container::name() { return type::cast(getter(field)); }
#define DEFINE_ACCESSORS0(getter, setter, Container, name, field, type) \
DEFINE_GETTER0(getter, Container, name, field, type) \
void Container::set_##name(type* value) { return setter(field, value); }
#define DEFINE_OPTIONAL_ACCESSORS0(getter, setter, Container, name, field, \
type) \
DEFINE_ACCESSORS0(getter, setter, Container, name, field, type) \
bool Container::has_##name() { \
return !getter(field)->IsUndefined(GetIsolate()); \
}
#define DEFINE_OPTIONAL_GETTER0(getter, Container, name, field, type) \
DEFINE_GETTER0(getter, Container, name, field, type) \
bool Container::has_##name() { \
return !getter(field)->IsUndefined(GetIsolate()); \
}
#define DEFINE_GETTER0(getter, Container, name, field, type) \
type* Container::name() { return type::cast(getter(field)); }
#define DEFINE_OBJ_GETTER(Container, name, field, type) \
DEFINE_GETTER0(GetEmbedderField, Container, name, field, type)
#define DEFINE_OBJ_ACCESSORS(Container, name, field, type) \
DEFINE_ACCESSORS0(GetEmbedderField, SetEmbedderField, Container, name, \
field, type)
#define DEFINE_OPTIONAL_OBJ_ACCESSORS(Container, name, field, type) \
DEFINE_OPTIONAL_ACCESSORS0(GetEmbedderField, SetEmbedderField, Container, \
name, field, type)
#define DEFINE_ARR_GETTER(Container, name, field, type) \
DEFINE_GETTER0(get, Container, name, field, type)
#define DEFINE_ARR_ACCESSORS(Container, name, field, type) \
DEFINE_ACCESSORS0(get, set, Container, name, field, type)
#define DEFINE_OPTIONAL_ARR_ACCESSORS(Container, name, field, type) \
DEFINE_OPTIONAL_ACCESSORS0(get, set, Container, name, field, type)
#define DEFINE_OPTIONAL_ARR_GETTER(Container, name, field, type) \
DEFINE_OPTIONAL_GETTER0(get, Container, name, field, type)
namespace {
// An iterator that returns first the module itself, then all modules linked via
@ -198,63 +158,38 @@ bool IsBreakablePosition(Handle<WasmCompiledModule> compiled_module,
Handle<WasmModuleObject> WasmModuleObject::New(
Isolate* isolate, Handle<WasmCompiledModule> compiled_module) {
WasmModule* module = compiled_module->module();
Handle<JSObject> module_object;
if (module->is_wasm()) {
Handle<JSFunction> module_cons(
isolate->native_context()->wasm_module_constructor());
module_object = isolate->factory()->NewJSObject(module_cons);
Handle<Symbol> module_sym(isolate->native_context()->wasm_module_sym());
Object::SetProperty(module_object, module_sym, module_object, STRICT)
.Check();
} else {
DCHECK(module->is_asm_js());
Handle<Map> map = isolate->factory()->NewMap(
JS_OBJECT_TYPE,
JSObject::kHeaderSize + WasmModuleObject::kFieldCount * kPointerSize);
module_object = isolate->factory()->NewJSObjectFromMap(map, TENURED);
}
module_object->SetEmbedderField(WasmModuleObject::kCompiledModule,
*compiled_module);
Handle<JSFunction> module_cons(
isolate->native_context()->wasm_module_constructor());
auto module_object = Handle<WasmModuleObject>::cast(
isolate->factory()->NewJSObject(module_cons));
Handle<Symbol> module_sym(isolate->native_context()->wasm_module_sym());
Object::SetProperty(module_object, module_sym, module_object, STRICT).Check();
module_object->set_compiled_module(*compiled_module);
Handle<WeakCell> link_to_module =
isolate->factory()->NewWeakCell(module_object);
compiled_module->set_weak_wasm_module(link_to_module);
return Handle<WasmModuleObject>::cast(module_object);
return module_object;
}
WasmModuleObject* WasmModuleObject::cast(Object* object) {
DCHECK(object->IsJSObject());
// TODO(titzer): brand check for WasmModuleObject.
return reinterpret_cast<WasmModuleObject*>(object);
}
bool WasmModuleObject::IsWasmModuleObject(Object* object) {
return object->IsJSObject() &&
JSObject::cast(object)->GetEmbedderFieldCount() == kFieldCount;
}
DEFINE_OBJ_GETTER(WasmModuleObject, compiled_module, kCompiledModule,
WasmCompiledModule)
Handle<WasmTableObject> WasmTableObject::New(Isolate* isolate, uint32_t initial,
int64_t maximum,
Handle<FixedArray>* js_functions) {
Handle<JSFunction> table_ctor(
isolate->native_context()->wasm_table_constructor());
Handle<JSObject> table_obj = isolate->factory()->NewJSObject(table_ctor);
table_obj->SetEmbedderField(kWrapperTracerHeader, Smi::kZero);
auto table_obj = Handle<WasmTableObject>::cast(
isolate->factory()->NewJSObject(table_ctor));
*js_functions = isolate->factory()->NewFixedArray(initial);
Object* null = isolate->heap()->null_value();
for (int i = 0; i < static_cast<int>(initial); ++i) {
(*js_functions)->set(i, null);
}
table_obj->SetEmbedderField(kFunctions, *(*js_functions));
Handle<Object> max = isolate->factory()->NewNumber(maximum);
table_obj->SetEmbedderField(kMaximum, *max);
table_obj->set_functions(**js_functions);
DCHECK_EQ(maximum, static_cast<int>(maximum));
table_obj->set_maximum_length(static_cast<int>(maximum));
Handle<FixedArray> dispatch_tables = isolate->factory()->NewFixedArray(0);
table_obj->SetEmbedderField(kDispatchTables, *dispatch_tables);
table_obj->set_dispatch_tables(*dispatch_tables);
Handle<Symbol> table_sym(isolate->native_context()->wasm_table_sym());
Object::SetProperty(table_obj, table_sym, table_obj, STRICT).Check();
return Handle<WasmTableObject>::cast(table_obj);
@ -264,8 +199,7 @@ Handle<FixedArray> WasmTableObject::AddDispatchTable(
Isolate* isolate, Handle<WasmTableObject> table_obj,
Handle<WasmInstanceObject> instance, int table_index,
Handle<FixedArray> function_table, Handle<FixedArray> signature_table) {
Handle<FixedArray> dispatch_tables(
FixedArray::cast(table_obj->GetEmbedderField(kDispatchTables)), isolate);
Handle<FixedArray> dispatch_tables(table_obj->dispatch_tables());
DCHECK_EQ(0, dispatch_tables->length() % 4);
if (instance.is_null()) return dispatch_tables;
@ -281,35 +215,13 @@ Handle<FixedArray> WasmTableObject::AddDispatchTable(
new_dispatch_tables->set(dispatch_tables->length() + 2, *function_table);
new_dispatch_tables->set(dispatch_tables->length() + 3, *signature_table);
table_obj->SetEmbedderField(WasmTableObject::kDispatchTables,
*new_dispatch_tables);
table_obj->set_dispatch_tables(*new_dispatch_tables);
return new_dispatch_tables;
}
DEFINE_OBJ_ACCESSORS(WasmTableObject, functions, kFunctions, FixedArray)
DEFINE_OBJ_GETTER(WasmTableObject, dispatch_tables, kDispatchTables, FixedArray)
uint32_t WasmTableObject::current_length() { return functions()->length(); }
bool WasmTableObject::has_maximum_length() {
return GetEmbedderField(kMaximum)->Number() >= 0;
}
int64_t WasmTableObject::maximum_length() {
return static_cast<int64_t>(GetEmbedderField(kMaximum)->Number());
}
WasmTableObject* WasmTableObject::cast(Object* object) {
DCHECK(object && object->IsJSObject());
// TODO(titzer): brand check for WasmTableObject.
return reinterpret_cast<WasmTableObject*>(object);
}
void WasmTableObject::grow(Isolate* isolate, uint32_t count) {
Handle<FixedArray> dispatch_tables(
FixedArray::cast(GetEmbedderField(kDispatchTables)));
Handle<FixedArray> dispatch_tables(this->dispatch_tables());
DCHECK_EQ(0, dispatch_tables->length() % 4);
uint32_t old_size = functions()->length();
@ -406,46 +318,26 @@ Handle<WasmMemoryObject> WasmMemoryObject::New(Isolate* isolate,
int32_t maximum) {
Handle<JSFunction> memory_ctor(
isolate->native_context()->wasm_memory_constructor());
Handle<JSObject> memory_obj =
isolate->factory()->NewJSObject(memory_ctor, TENURED);
memory_obj->SetEmbedderField(kWrapperTracerHeader, Smi::kZero);
auto memory_obj = Handle<WasmMemoryObject>::cast(
isolate->factory()->NewJSObject(memory_ctor, TENURED));
if (buffer.is_null()) {
const bool enable_guard_regions = EnableGuardRegions();
buffer = SetupArrayBuffer(isolate, nullptr, 0, nullptr, 0, false,
enable_guard_regions);
}
memory_obj->SetEmbedderField(kArrayBuffer, *buffer);
Handle<Object> max = isolate->factory()->NewNumber(maximum);
memory_obj->SetEmbedderField(kMaximum, *max);
memory_obj->set_array_buffer(*buffer);
memory_obj->set_maximum_pages(maximum);
Handle<Symbol> memory_sym(isolate->native_context()->wasm_memory_sym());
Object::SetProperty(memory_obj, memory_sym, memory_obj, STRICT).Check();
return Handle<WasmMemoryObject>::cast(memory_obj);
}
DEFINE_OBJ_ACCESSORS(WasmMemoryObject, buffer, kArrayBuffer, JSArrayBuffer)
DEFINE_OPTIONAL_OBJ_ACCESSORS(WasmMemoryObject, instances_link, kInstancesLink,
WasmInstanceWrapper)
uint32_t WasmMemoryObject::current_pages() {
uint32_t byte_length;
CHECK(buffer()->byte_length()->ToUint32(&byte_length));
CHECK(array_buffer()->byte_length()->ToUint32(&byte_length));
return byte_length / wasm::WasmModule::kPageSize;
}
bool WasmMemoryObject::has_maximum_pages() {
return GetEmbedderField(kMaximum)->Number() >= 0;
}
int32_t WasmMemoryObject::maximum_pages() {
return static_cast<int32_t>(GetEmbedderField(kMaximum)->Number());
}
WasmMemoryObject* WasmMemoryObject::cast(Object* object) {
DCHECK(object && object->IsJSObject());
// TODO(titzer): brand check for WasmMemoryObject.
return reinterpret_cast<WasmMemoryObject*>(object);
}
void WasmMemoryObject::AddInstance(Isolate* isolate,
Handle<WasmInstanceObject> instance) {
Handle<WasmInstanceWrapper> instance_wrapper =
@ -460,16 +352,11 @@ void WasmMemoryObject::AddInstance(Isolate* isolate,
set_instances_link(*instance_wrapper);
}
void WasmMemoryObject::ResetInstancesLink(Isolate* isolate) {
Handle<Object> undefined = isolate->factory()->undefined_value();
SetEmbedderField(kInstancesLink, *undefined);
}
// static
int32_t WasmMemoryObject::Grow(Isolate* isolate,
Handle<WasmMemoryObject> memory_object,
uint32_t pages) {
Handle<JSArrayBuffer> old_buffer(memory_object->buffer());
Handle<JSArrayBuffer> old_buffer(memory_object->array_buffer());
uint32_t old_size = 0;
CHECK(old_buffer->byte_length()->ToUint32(&old_size));
Handle<JSArrayBuffer> new_buffer;
@ -482,7 +369,7 @@ int32_t WasmMemoryObject::Grow(Isolate* isolate,
isolate, old_buffer->allocation_base(),
old_buffer->allocation_length(), old_buffer->backing_store(),
old_size, old_buffer->is_external(), old_buffer->has_guard_region());
memory_object->set_buffer(*new_buffer);
memory_object->set_array_buffer(*new_buffer);
}
DCHECK_EQ(0, old_size % WasmModule::kPageSize);
return old_size / WasmModule::kPageSize;
@ -504,7 +391,7 @@ int32_t WasmMemoryObject::Grow(Isolate* isolate,
DCHECK(WasmInstanceWrapper::IsWasmInstanceWrapper(*instance_wrapper));
DCHECK(instance_wrapper->has_instance());
Handle<WasmInstanceObject> instance = instance_wrapper->instance_object();
DCHECK(IsWasmInstance(*instance));
DCHECK(instance->IsWasmInstanceObject());
uint32_t max_pages = instance->GetMaxMemoryPages();
// Grow memory object buffer and update instances associated with it.
@ -518,31 +405,16 @@ int32_t WasmMemoryObject::Grow(Isolate* isolate,
instance_wrapper = instance_wrapper->next_wrapper();
DCHECK(WasmInstanceWrapper::IsWasmInstanceWrapper(*instance_wrapper));
Handle<WasmInstanceObject> instance = instance_wrapper->instance_object();
DCHECK(IsWasmInstance(*instance));
DCHECK(instance->IsWasmInstanceObject());
SetInstanceMemory(isolate, instance, new_buffer);
UncheckedUpdateInstanceMemory(isolate, instance, old_mem_start, old_size);
}
}
memory_object->set_buffer(*new_buffer);
memory_object->set_array_buffer(*new_buffer);
DCHECK_EQ(0, old_size % WasmModule::kPageSize);
return old_size / WasmModule::kPageSize;
}
DEFINE_OBJ_ACCESSORS(WasmInstanceObject, compiled_module, kCompiledModule,
WasmCompiledModule)
DEFINE_OPTIONAL_OBJ_ACCESSORS(WasmInstanceObject, globals_buffer,
kGlobalsArrayBuffer, JSArrayBuffer)
DEFINE_OPTIONAL_OBJ_ACCESSORS(WasmInstanceObject, memory_buffer,
kMemoryArrayBuffer, JSArrayBuffer)
DEFINE_OPTIONAL_OBJ_ACCESSORS(WasmInstanceObject, memory_object, kMemoryObject,
WasmMemoryObject)
DEFINE_OPTIONAL_OBJ_ACCESSORS(WasmInstanceObject, debug_info, kDebugInfo,
WasmDebugInfo)
DEFINE_OPTIONAL_OBJ_ACCESSORS(WasmInstanceObject, instance_wrapper,
kWasmMemInstanceWrapper, WasmInstanceWrapper)
DEFINE_OPTIONAL_OBJ_ACCESSORS(WasmInstanceObject, directly_called_instances,
kDirectlyCalledInstances, FixedArray)
WasmModuleObject* WasmInstanceObject::module_object() {
return *compiled_module()->wasm_module();
}
@ -557,38 +429,12 @@ Handle<WasmDebugInfo> WasmInstanceObject::GetOrCreateDebugInfo(
return new_info;
}
WasmInstanceObject* WasmInstanceObject::cast(Object* object) {
DCHECK(IsWasmInstanceObject(object));
return reinterpret_cast<WasmInstanceObject*>(object);
}
bool WasmInstanceObject::IsWasmInstanceObject(Object* object) {
if (!object->IsJSObject()) return false;
JSObject* obj = JSObject::cast(object);
Isolate* isolate = obj->GetIsolate();
if (obj->GetEmbedderFieldCount() != kFieldCount) {
return false;
}
Object* mem = obj->GetEmbedderField(kMemoryArrayBuffer);
if (!(mem->IsUndefined(isolate) || mem->IsJSArrayBuffer()) ||
!WasmCompiledModule::IsWasmCompiledModule(
obj->GetEmbedderField(kCompiledModule))) {
return false;
}
// All checks passed.
return true;
}
Handle<WasmInstanceObject> WasmInstanceObject::New(
Isolate* isolate, Handle<WasmCompiledModule> compiled_module) {
Handle<JSFunction> instance_cons(
isolate->native_context()->wasm_instance_constructor());
Handle<JSObject> instance_object =
isolate->factory()->NewJSObject(instance_cons, TENURED);
instance_object->SetEmbedderField(kWrapperTracerHeader, Smi::kZero);
Handle<Symbol> instance_sym(isolate->native_context()->wasm_instance_sym());
Object::SetProperty(instance_object, instance_sym, instance_object, STRICT)
@ -596,11 +442,10 @@ Handle<WasmInstanceObject> WasmInstanceObject::New(
Handle<WasmInstanceObject> instance(
reinterpret_cast<WasmInstanceObject*>(*instance_object), isolate);
instance->SetEmbedderField(kCompiledModule, *compiled_module);
instance->SetEmbedderField(kMemoryObject, isolate->heap()->undefined_value());
instance->set_compiled_module(*compiled_module);
Handle<WasmInstanceWrapper> instance_wrapper =
WasmInstanceWrapper::New(isolate, instance);
instance->SetEmbedderField(kWasmMemInstanceWrapper, *instance_wrapper);
instance->set_instance_wrapper(*instance_wrapper);
return instance;
}
@ -656,16 +501,6 @@ uint32_t WasmInstanceObject::GetMaxMemoryPages() {
return FLAG_wasm_max_mem_pages;
}
WasmInstanceObject* WasmExportedFunction::instance() {
return WasmInstanceObject::cast(GetEmbedderField(kInstance));
}
int WasmExportedFunction::function_index() {
int32_t func_index;
CHECK(GetEmbedderField(kIndex)->ToInt32(&func_index));
return func_index;
}
WasmExportedFunction* WasmExportedFunction::cast(Object* object) {
DCHECK(object && object->IsJSFunction());
DCHECK_EQ(Code::JS_TO_WASM_FUNCTION,
@ -694,14 +529,16 @@ Handle<WasmExportedFunction> WasmExportedFunction::New(
isolate->factory()->NewSharedFunctionInfo(name, export_wrapper, false);
shared->set_length(arity);
shared->set_internal_formal_parameter_count(arity);
Handle<JSFunction> function = isolate->factory()->NewFunction(
Handle<JSFunction> js_function = isolate->factory()->NewFunction(
isolate->wasm_function_map(), name, export_wrapper);
function->SetEmbedderField(kWrapperTracerHeader, Smi::kZero);
Handle<WasmExportedFunction> function(
reinterpret_cast<WasmExportedFunction*>(*js_function), isolate);
function->set_shared(*shared);
function->set_instance(*instance);
function->set_function_index(func_index);
function->SetEmbedderField(kInstance, *instance);
function->SetEmbedderField(kIndex, Smi::FromInt(func_index));
return Handle<WasmExportedFunction>::cast(function);
}
@ -710,16 +547,16 @@ bool WasmSharedModuleData::IsWasmSharedModuleData(Object* object) {
FixedArray* arr = FixedArray::cast(object);
if (arr->length() != kFieldCount) return false;
Isolate* isolate = arr->GetIsolate();
if (!arr->get(kModuleWrapper)->IsForeign()) return false;
if (!arr->get(kModuleBytes)->IsUndefined(isolate) &&
!arr->get(kModuleBytes)->IsSeqOneByteString())
if (!arr->get(kModuleWrapperIndex)->IsForeign()) return false;
if (!arr->get(kModuleBytesIndex)->IsUndefined(isolate) &&
!arr->get(kModuleBytesIndex)->IsSeqOneByteString())
return false;
if (!arr->get(kScript)->IsScript()) return false;
if (!arr->get(kAsmJsOffsetTable)->IsUndefined(isolate) &&
!arr->get(kAsmJsOffsetTable)->IsByteArray())
if (!arr->get(kScriptIndex)->IsScript()) return false;
if (!arr->get(kAsmJsOffsetTableIndex)->IsUndefined(isolate) &&
!arr->get(kAsmJsOffsetTableIndex)->IsByteArray())
return false;
if (!arr->get(kBreakPointInfos)->IsUndefined(isolate) &&
!arr->get(kBreakPointInfos)->IsFixedArray())
if (!arr->get(kBreakPointInfosIndex)->IsUndefined(isolate) &&
!arr->get(kBreakPointInfosIndex)->IsFixedArray())
return false;
return true;
}
@ -736,41 +573,34 @@ wasm::WasmModule* WasmSharedModuleData::module() {
// a Managed<WasmModule> object, as well as cases when it's managed
// by the embedder. CcTests fall into the latter case.
return *(reinterpret_cast<wasm::WasmModule**>(
Foreign::cast(get(kModuleWrapper))->foreign_address()));
Foreign::cast(get(kModuleWrapperIndex))->foreign_address()));
}
DEFINE_OPTIONAL_ARR_ACCESSORS(WasmSharedModuleData, module_bytes, kModuleBytes,
SeqOneByteString);
DEFINE_ARR_GETTER(WasmSharedModuleData, script, kScript, Script);
DEFINE_OPTIONAL_ARR_ACCESSORS(WasmSharedModuleData, asm_js_offset_table,
kAsmJsOffsetTable, ByteArray);
DEFINE_OPTIONAL_ARR_GETTER(WasmSharedModuleData, breakpoint_infos,
kBreakPointInfos, FixedArray);
DEFINE_OPTIONAL_ARR_GETTER(WasmSharedModuleData, lazy_compilation_orchestrator,
kLazyCompilationOrchestrator, Foreign);
Handle<WasmSharedModuleData> WasmSharedModuleData::New(
Isolate* isolate, Handle<Foreign> module_wrapper,
Handle<SeqOneByteString> module_bytes, Handle<Script> script,
Handle<ByteArray> asm_js_offset_table) {
Handle<FixedArray> arr =
isolate->factory()->NewFixedArray(kFieldCount, TENURED);
arr->set(kWrapperTracerHeader, Smi::kZero);
arr->set(kModuleWrapper, *module_wrapper);
arr->set(kModuleWrapperIndex, *module_wrapper);
if (!module_bytes.is_null()) {
arr->set(kModuleBytes, *module_bytes);
arr->set(kModuleBytesIndex, *module_bytes);
}
if (!script.is_null()) {
arr->set(kScript, *script);
arr->set(kScriptIndex, *script);
}
if (!asm_js_offset_table.is_null()) {
arr->set(kAsmJsOffsetTable, *asm_js_offset_table);
arr->set(kAsmJsOffsetTableIndex, *asm_js_offset_table);
}
DCHECK(WasmSharedModuleData::IsWasmSharedModuleData(*arr));
return Handle<WasmSharedModuleData>::cast(arr);
}
Foreign* WasmSharedModuleData::lazy_compilation_orchestrator() {
return Foreign::cast(get(kLazyCompilationOrchestratorIndex));
}
bool WasmSharedModuleData::is_asm_js() {
bool asm_js = module()->is_asm_js();
DCHECK_EQ(asm_js, script()->IsUserJavaScript());
@ -780,7 +610,7 @@ bool WasmSharedModuleData::is_asm_js() {
void WasmSharedModuleData::ReinitializeAfterDeserialization(
Isolate* isolate, Handle<WasmSharedModuleData> shared) {
DCHECK(shared->get(kModuleWrapper)->IsUndefined(isolate));
DCHECK(shared->get(kModuleWrapperIndex)->IsUndefined(isolate));
#ifdef DEBUG
// No BreakpointInfo objects should survive deserialization.
if (shared->has_breakpoint_infos()) {
@ -790,7 +620,7 @@ void WasmSharedModuleData::ReinitializeAfterDeserialization(
}
#endif
shared->set(kBreakPointInfos, isolate->heap()->undefined_value());
shared->set(kBreakPointInfosIndex, isolate->heap()->undefined_value());
WasmModule* module = nullptr;
{
@ -815,7 +645,7 @@ void WasmSharedModuleData::ReinitializeAfterDeserialization(
Handle<WasmModuleWrapper> module_wrapper =
WasmModuleWrapper::New(isolate, module);
shared->set(kModuleWrapper, *module_wrapper);
shared->set(kModuleWrapperIndex, *module_wrapper);
DCHECK(WasmSharedModuleData::IsWasmSharedModuleData(*shared));
}
@ -860,7 +690,7 @@ void WasmSharedModuleData::AddBreakpoint(Handle<WasmSharedModuleData> shared,
breakpoint_infos = handle(shared->breakpoint_infos(), isolate);
} else {
breakpoint_infos = isolate->factory()->NewFixedArray(4, TENURED);
shared->set(kBreakPointInfos, *breakpoint_infos);
shared->set(kBreakPointInfosIndex, *breakpoint_infos);
}
int insert_pos =
@ -884,7 +714,7 @@ void WasmSharedModuleData::AddBreakpoint(Handle<WasmSharedModuleData> shared,
if (need_realloc) {
new_breakpoint_infos = isolate->factory()->NewFixedArray(
2 * breakpoint_infos->length(), TENURED);
shared->set(kBreakPointInfos, *new_breakpoint_infos);
shared->set(kBreakPointInfosIndex, *new_breakpoint_infos);
// Copy over the entries [0, insert_pos).
for (int i = 0; i < insert_pos; ++i)
new_breakpoint_infos->set(i, breakpoint_infos->get(i));
@ -946,7 +776,7 @@ void WasmSharedModuleData::PrepareForLazyCompilation(
LazyCompilationOrchestrator* orch = new LazyCompilationOrchestrator();
Handle<Managed<LazyCompilationOrchestrator>> orch_handle =
Managed<LazyCompilationOrchestrator>::New(isolate, orch);
shared->set(WasmSharedModuleData::kLazyCompilationOrchestrator, *orch_handle);
shared->set(kLazyCompilationOrchestratorIndex, *orch_handle);
}
Handle<WasmCompiledModule> WasmCompiledModule::New(
@ -1575,28 +1405,25 @@ Handle<Code> WasmCompiledModule::CompileLazy(
Handle<WasmInstanceWrapper> WasmInstanceWrapper::New(
Isolate* isolate, Handle<WasmInstanceObject> instance) {
Handle<FixedArray> array =
isolate->factory()->NewFixedArray(kWrapperPropertyCount, TENURED);
isolate->factory()->NewFixedArray(kFieldCount, TENURED);
Handle<WasmInstanceWrapper> instance_wrapper(
reinterpret_cast<WasmInstanceWrapper*>(*array), isolate);
Handle<WeakCell> cell = isolate->factory()->NewWeakCell(instance);
instance_wrapper->set(kWrapperInstanceObject, *cell);
instance_wrapper->set(kWrapperInstanceObjectIndex, *cell);
return instance_wrapper;
}
bool WasmInstanceWrapper::IsWasmInstanceWrapper(Object* obj) {
if (!obj->IsFixedArray()) return false;
Handle<FixedArray> array = handle(FixedArray::cast(obj));
if (array->length() != kWrapperPropertyCount) return false;
if (!array->get(kWrapperInstanceObject)->IsWeakCell()) return false;
if (array->length() != kFieldCount) return false;
if (!array->get(kWrapperInstanceObjectIndex)->IsWeakCell()) return false;
Isolate* isolate = array->GetIsolate();
if (!array->get(kNextInstanceWrapper)->IsUndefined(isolate) &&
!array->get(kNextInstanceWrapper)->IsFixedArray())
if (!array->get(kNextInstanceWrapperIndex)->IsUndefined(isolate) &&
!array->get(kNextInstanceWrapperIndex)->IsFixedArray())
return false;
if (!array->get(kPreviousInstanceWrapper)->IsUndefined(isolate) &&
!array->get(kPreviousInstanceWrapper)->IsFixedArray())
if (!array->get(kPreviousInstanceWrapperIndex)->IsUndefined(isolate) &&
!array->get(kPreviousInstanceWrapperIndex)->IsFixedArray())
return false;
return true;
}
DEFINE_OPTIONAL_ARR_ACCESSORS(WasmDebugInfo, locals_names, kLocalsNames,
FixedArray)

View File

@ -13,6 +13,12 @@
#include "src/wasm/wasm-limits.h"
#include "src/wasm/wasm-module.h"
#include "src/heap/heap-inl.h"
#include "src/heap/heap.h"
// Has to be the last include (doesn't have include guards)
#include "src/objects/object-macros.h"
namespace v8 {
namespace internal {
namespace wasm {
@ -25,34 +31,42 @@ class WasmDebugInfo;
class WasmInstanceObject;
class WasmInstanceWrapper;
#define DECLARE_CASTS(name) \
static bool Is##name(Object* object); \
static name* cast(Object* object)
#define DECL_OOL_QUERY(type) static bool Is##type(Object* object);
#define DECL_OOL_CAST(type) static type* cast(Object* object);
#define DECLARE_GETTER(name, type) type* name()
#define DECL_GETTER(name, type) type* name();
#define DECLARE_ACCESSORS(name, type) \
void set_##name(type* value); \
DECLARE_GETTER(name, type)
#define DECL_OPTIONAL_ACCESSORS(name, type) \
INLINE(bool has_##name()); \
DECL_ACCESSORS(name, type)
#define DECLARE_OPTIONAL_ACCESSORS(name, type) \
bool has_##name(); \
DECLARE_ACCESSORS(name, type)
#define DECL_OPTIONAL_GETTER(name, type) \
INLINE(bool has_##name()); \
DECL_GETTER(name, type)
#define DECLARE_OPTIONAL_GETTER(name, type) \
bool has_##name(); \
DECLARE_GETTER(name, type)
#define DEF_SIZE(parent) \
static const int kSize = parent::kHeaderSize + kFieldCount * kPointerSize; \
static const int kParentSize = parent::kHeaderSize; \
static const int kHeaderSize = kSize;
#define DEF_OFFSET(name) \
static const int k##name##Offset = \
kSize + (k##name##Index - kFieldCount) * kPointerSize;
// Representation of a WebAssembly.Module JavaScript-level object.
class WasmModuleObject : public JSObject {
public:
// If a second field is added, we need a kWrapperTracerHeader field as well.
// TODO(titzer): add the brand as an embedder field instead of a property.
enum Fields { kCompiledModule, kFieldCount };
DECL_CAST(WasmModuleObject)
DECLARE_CASTS(WasmModuleObject);
// Shared compiled code between multiple WebAssembly.Module objects.
DECL_ACCESSORS(compiled_module, WasmCompiledModule)
WasmCompiledModule* compiled_module();
enum { // --
kCompiledModuleIndex,
kFieldCount
};
DEF_SIZE(JSObject)
DEF_OFFSET(CompiledModule)
static Handle<WasmModuleObject> New(
Isolate* isolate, Handle<WasmCompiledModule> compiled_module);
@ -61,23 +75,26 @@ class WasmModuleObject : public JSObject {
// Representation of a WebAssembly.Table JavaScript-level object.
class WasmTableObject : public JSObject {
public:
// The 0-th field is used by the Blink Wrapper Tracer.
// TODO(titzer): add the brand as an embedder field instead of a property.
enum Fields {
kWrapperTracerHeader,
kFunctions,
kMaximum,
kDispatchTables,
DECL_CAST(WasmTableObject)
DECL_ACCESSORS(functions, FixedArray)
DECL_INT_ACCESSORS(maximum_length)
DECL_ACCESSORS(dispatch_tables, FixedArray)
enum { // --
kFunctionsIndex,
kMaximumLengthIndex,
kDispatchTablesIndex,
kFieldCount
};
DECLARE_CASTS(WasmTableObject);
DECLARE_ACCESSORS(functions, FixedArray);
DECLARE_GETTER(dispatch_tables, FixedArray);
DEF_SIZE(JSObject)
DEF_OFFSET(Functions)
DEF_OFFSET(MaximumLength)
DEF_OFFSET(DispatchTables)
uint32_t current_length();
bool has_maximum_length();
int64_t maximum_length(); // Returns < 0 if no maximum.
inline uint32_t current_length() { return functions()->length(); }
inline bool has_maximum_length() { return maximum_length() >= 0; }
void grow(Isolate* isolate, uint32_t count);
static Handle<WasmTableObject> New(Isolate* isolate, uint32_t initial,
@ -92,25 +109,28 @@ class WasmTableObject : public JSObject {
// Representation of a WebAssembly.Memory JavaScript-level object.
class WasmMemoryObject : public JSObject {
public:
// The 0-th field is used by the Blink Wrapper Tracer.
// TODO(titzer): add the brand as an embedder field instead of a property.
enum Fields : uint8_t {
kWrapperTracerHeader,
kArrayBuffer,
kMaximum,
kInstancesLink,
DECL_CAST(WasmMemoryObject)
DECL_ACCESSORS(array_buffer, JSArrayBuffer)
DECL_INT_ACCESSORS(maximum_pages)
DECL_OPTIONAL_ACCESSORS(instances_link, WasmInstanceWrapper)
enum { // --
kArrayBufferIndex,
kMaximumPagesIndex,
kInstancesLinkIndex,
kFieldCount
};
DECLARE_CASTS(WasmMemoryObject);
DECLARE_ACCESSORS(buffer, JSArrayBuffer);
DECLARE_OPTIONAL_ACCESSORS(instances_link, WasmInstanceWrapper);
DEF_SIZE(JSObject)
DEF_OFFSET(ArrayBuffer)
DEF_OFFSET(MaximumPages)
DEF_OFFSET(InstancesLink)
void AddInstance(Isolate* isolate, Handle<WasmInstanceObject> object);
void ResetInstancesLink(Isolate* isolate);
inline void ResetInstancesLink(Isolate* isolate);
uint32_t current_pages();
bool has_maximum_pages();
int32_t maximum_pages(); // Returns < 0 if there is no maximum.
inline bool has_maximum_pages() { return maximum_pages() >= 0; }
static Handle<WasmMemoryObject> New(Isolate* isolate,
Handle<JSArrayBuffer> buffer,
@ -119,33 +139,39 @@ class WasmMemoryObject : public JSObject {
static int32_t Grow(Isolate*, Handle<WasmMemoryObject>, uint32_t pages);
};
// Representation of a WebAssembly.Instance JavaScript-level object.
// A WebAssembly.Instance JavaScript-level object.
class WasmInstanceObject : public JSObject {
public:
// The 0-th field is used by the Blink Wrapper Tracer.
// TODO(titzer): add the brand as an embedder field instead of a property.
enum Fields {
kWrapperTracerHeader,
kCompiledModule,
kMemoryObject,
kMemoryArrayBuffer,
kGlobalsArrayBuffer,
kDebugInfo,
kWasmMemInstanceWrapper,
// FixedArray of wasm instances whose code we imported (to keep them alive).
kDirectlyCalledInstances,
DECL_CAST(WasmInstanceObject)
DECL_ACCESSORS(compiled_module, WasmCompiledModule)
DECL_OPTIONAL_ACCESSORS(memory_object, WasmMemoryObject)
DECL_OPTIONAL_ACCESSORS(memory_buffer, JSArrayBuffer)
DECL_OPTIONAL_ACCESSORS(globals_buffer, JSArrayBuffer)
DECL_OPTIONAL_ACCESSORS(debug_info, WasmDebugInfo)
DECL_OPTIONAL_ACCESSORS(instance_wrapper, WasmInstanceWrapper)
// FixedArray of all instances whose code was imported
DECL_OPTIONAL_ACCESSORS(directly_called_instances, FixedArray)
enum { // --
kCompiledModuleIndex,
kMemoryObjectIndex,
kMemoryBufferIndex,
kGlobalsBufferIndex,
kDebugInfoIndex,
kInstanceWrapperIndex,
kDirectlyCalledInstancesIndex,
kFieldCount
};
DECLARE_CASTS(WasmInstanceObject);
DECLARE_ACCESSORS(compiled_module, WasmCompiledModule);
DECLARE_OPTIONAL_ACCESSORS(globals_buffer, JSArrayBuffer);
DECLARE_OPTIONAL_ACCESSORS(memory_buffer, JSArrayBuffer);
DECLARE_OPTIONAL_ACCESSORS(memory_object, WasmMemoryObject);
DECLARE_OPTIONAL_ACCESSORS(debug_info, WasmDebugInfo);
DECLARE_OPTIONAL_ACCESSORS(instance_wrapper, WasmInstanceWrapper);
DECLARE_OPTIONAL_ACCESSORS(directly_called_instances, FixedArray);
DEF_SIZE(JSObject)
DEF_OFFSET(CompiledModule)
DEF_OFFSET(MemoryObject)
DEF_OFFSET(MemoryBuffer)
DEF_OFFSET(GlobalsBuffer)
DEF_OFFSET(DebugInfo)
DEF_OFFSET(InstanceWrapper)
DEF_OFFSET(DirectlyCalledInstances)
WasmModuleObject* module_object();
V8_EXPORT_PRIVATE wasm::WasmModule* module();
@ -164,16 +190,24 @@ class WasmInstanceObject : public JSObject {
uint32_t GetMaxMemoryPages();
};
// Representation of an exported wasm function.
// A WASM function that is wrapped and exported to JavaScript.
class WasmExportedFunction : public JSFunction {
public:
// The 0-th field is used by the Blink Wrapper Tracer.
enum Fields { kWrapperTracerHeader, kInstance, kIndex, kFieldCount };
DECL_OOL_QUERY(WasmExportedFunction)
DECL_OOL_CAST(WasmExportedFunction)
DECLARE_CASTS(WasmExportedFunction);
DECL_ACCESSORS(instance, WasmInstanceObject)
DECL_INT_ACCESSORS(function_index)
WasmInstanceObject* instance();
int function_index();
enum { // --
kInstanceIndex,
kFunctionIndexIndex,
kFieldCount
};
static const int kSize = JSFunction::kSize + kFieldCount * kPointerSize;
DEF_OFFSET(Instance)
DEF_OFFSET(FunctionIndex)
static Handle<WasmExportedFunction> New(Isolate* isolate,
Handle<WasmInstanceObject> instance,
@ -184,31 +218,33 @@ class WasmExportedFunction : public JSFunction {
// Information shared by all WasmCompiledModule objects for the same module.
class WasmSharedModuleData : public FixedArray {
// The 0-th field is used by the Blink Wrapper Tracer.
enum Fields {
kWrapperTracerHeader,
kModuleWrapper,
kModuleBytes,
kScript,
kAsmJsOffsetTable,
kBreakPointInfos,
kLazyCompilationOrchestrator,
public:
DECL_OOL_QUERY(WasmSharedModuleData)
DECL_OOL_CAST(WasmSharedModuleData)
DECL_GETTER(module, wasm::WasmModule)
DECL_OPTIONAL_ACCESSORS(module_bytes, SeqOneByteString)
DECL_ACCESSORS(script, Script)
DECL_OPTIONAL_ACCESSORS(asm_js_offset_table, ByteArray)
DECL_OPTIONAL_ACCESSORS(breakpoint_infos, FixedArray)
enum { // --
kModuleWrapperIndex,
kModuleBytesIndex,
kScriptIndex,
kAsmJsOffsetTableIndex,
kBreakPointInfosIndex,
kLazyCompilationOrchestratorIndex,
kFieldCount
};
public:
DECLARE_CASTS(WasmSharedModuleData);
DECLARE_GETTER(module, wasm::WasmModule);
DECLARE_OPTIONAL_ACCESSORS(module_bytes, SeqOneByteString);
DECLARE_GETTER(script, Script);
DECLARE_OPTIONAL_ACCESSORS(asm_js_offset_table, ByteArray);
DECLARE_OPTIONAL_GETTER(breakpoint_infos, FixedArray);
static Handle<WasmSharedModuleData> New(
Isolate* isolate, Handle<Foreign> module_wrapper,
Handle<SeqOneByteString> module_bytes, Handle<Script> script,
Handle<ByteArray> asm_js_offset_table);
DEF_SIZE(FixedArray)
DEF_OFFSET(ModuleWrapper)
DEF_OFFSET(ModuleBytes)
DEF_OFFSET(Script)
DEF_OFFSET(AsmJsOffsetTable)
DEF_OFFSET(BreakPointInfos)
DEF_OFFSET(LazyCompilationOrchestrator)
// Check whether this module was generated from asm.js source.
bool is_asm_js();
@ -224,8 +260,13 @@ class WasmSharedModuleData : public FixedArray {
static void PrepareForLazyCompilation(Handle<WasmSharedModuleData>);
static Handle<WasmSharedModuleData> New(
Isolate* isolate, Handle<Foreign> module_wrapper,
Handle<SeqOneByteString> module_bytes, Handle<Script> script,
Handle<ByteArray> asm_js_offset_table);
private:
DECLARE_OPTIONAL_GETTER(lazy_compilation_orchestrator, Foreign);
DECL_OPTIONAL_GETTER(lazy_compilation_orchestrator, Foreign)
friend class WasmCompiledModule;
};
@ -255,7 +296,9 @@ class WasmSharedModuleData : public FixedArray {
// we embed them as objects, and they may move.
class WasmCompiledModule : public FixedArray {
public:
enum Fields { kFieldCount };
enum { // --
kFieldCount
};
static WasmCompiledModule* cast(Object* fixed_array) {
SLOW_DCHECK(IsWasmCompiledModule(fixed_array));
@ -544,18 +587,25 @@ class WasmCompiledModule : public FixedArray {
class WasmDebugInfo : public FixedArray {
public:
// The 0-th field is used by the Blink Wrapper Tracer.
enum Fields {
kWrapperTracerHeader,
kInstance,
kInterpreterHandle,
kInterpretedFunctions,
// FixedArray of FixedArray of <undefined|String>.
kLocalsNames,
DECL_OOL_QUERY(WasmDebugInfo)
DECL_OOL_CAST(WasmDebugInfo)
DECL_GETTER(wasm_instance, WasmInstanceObject)
DECL_OPTIONAL_ACCESSORS(locals_names, FixedArray)
enum { // --
kInstanceIndex,
kInterpreterHandleIndex,
kInterpretedFunctionsIndex,
kLocalsNamesIndex,
kFieldCount
};
DECLARE_OPTIONAL_ACCESSORS(locals_names, FixedArray);
DEF_SIZE(FixedArray)
DEF_OFFSET(Instance)
DEF_OFFSET(InterpreterHandle)
DEF_OFFSET(InterpretedFunctions)
DEF_OFFSET(LocalsNames)
static Handle<WasmDebugInfo> New(Handle<WasmInstanceObject>);
@ -566,9 +616,6 @@ class WasmDebugInfo : public FixedArray {
V8_EXPORT_PRIVATE static wasm::WasmInterpreter* SetupForTesting(
Handle<WasmInstanceObject>, wasm::WasmInstance*);
static bool IsDebugInfo(Object*);
static WasmDebugInfo* cast(Object*);
// Set a breakpoint in the given function at the given byte offset within that
// function. This will redirect all future calls to this function to the
// interpreter and will always pause at the given offset.
@ -605,8 +652,6 @@ class WasmDebugInfo : public FixedArray {
// Returns the number of calls / function frames executed in the interpreter.
uint64_t NumInterpretedCalls();
DECLARE_GETTER(wasm_instance, WasmInstanceObject);
// Update the memory view of the interpreter after executing GrowMemory in
// compiled code.
void UpdateMemory(JSArrayBuffer* new_memory);
@ -625,63 +670,145 @@ class WasmDebugInfo : public FixedArray {
class WasmInstanceWrapper : public FixedArray {
public:
static Handle<WasmInstanceWrapper> New(Isolate* isolate,
Handle<WasmInstanceObject> instance);
enum { // --
kWrapperInstanceObjectIndex,
kNextInstanceWrapperIndex,
kPreviousInstanceWrapperIndex,
kFieldCount
};
static WasmInstanceWrapper* cast(Object* fixed_array) {
SLOW_DCHECK(IsWasmInstanceWrapper(fixed_array));
return reinterpret_cast<WasmInstanceWrapper*>(fixed_array);
}
static bool IsWasmInstanceWrapper(Object* obj);
bool has_instance() { return get(kWrapperInstanceObject)->IsWeakCell(); }
bool has_instance() { return get(kWrapperInstanceObjectIndex)->IsWeakCell(); }
Handle<WasmInstanceObject> instance_object() {
Object* obj = get(kWrapperInstanceObject);
Object* obj = get(kWrapperInstanceObjectIndex);
DCHECK(obj->IsWeakCell());
WeakCell* cell = WeakCell::cast(obj);
DCHECK(cell->value()->IsJSObject());
return handle(WasmInstanceObject::cast(cell->value()));
}
bool has_next() { return IsWasmInstanceWrapper(get(kNextInstanceWrapper)); }
bool has_next() {
return IsWasmInstanceWrapper(get(kNextInstanceWrapperIndex));
}
bool has_previous() {
return IsWasmInstanceWrapper(get(kPreviousInstanceWrapper));
return IsWasmInstanceWrapper(get(kPreviousInstanceWrapperIndex));
}
void set_next_wrapper(Object* obj) {
DCHECK(IsWasmInstanceWrapper(obj));
set(kNextInstanceWrapper, obj);
set(kNextInstanceWrapperIndex, obj);
}
void set_previous_wrapper(Object* obj) {
DCHECK(IsWasmInstanceWrapper(obj));
set(kPreviousInstanceWrapper, obj);
set(kPreviousInstanceWrapperIndex, obj);
}
Handle<WasmInstanceWrapper> next_wrapper() {
Object* obj = get(kNextInstanceWrapper);
Object* obj = get(kNextInstanceWrapperIndex);
DCHECK(IsWasmInstanceWrapper(obj));
return handle(WasmInstanceWrapper::cast(obj));
}
Handle<WasmInstanceWrapper> previous_wrapper() {
Object* obj = get(kPreviousInstanceWrapper);
Object* obj = get(kPreviousInstanceWrapperIndex);
DCHECK(IsWasmInstanceWrapper(obj));
return handle(WasmInstanceWrapper::cast(obj));
}
void reset_next_wrapper() { set_undefined(kNextInstanceWrapper); }
void reset_previous_wrapper() { set_undefined(kPreviousInstanceWrapper); }
void reset_next_wrapper() { set_undefined(kNextInstanceWrapperIndex); }
void reset_previous_wrapper() {
set_undefined(kPreviousInstanceWrapperIndex);
}
void reset() {
for (int kID = 0; kID < kWrapperPropertyCount; kID++) set_undefined(kID);
for (int kID = 0; kID < kFieldCount; kID++) set_undefined(kID);
}
private:
enum {
kWrapperInstanceObject,
kNextInstanceWrapper,
kPreviousInstanceWrapper,
kWrapperPropertyCount
};
static Handle<WasmInstanceWrapper> New(Isolate* isolate,
Handle<WasmInstanceObject> instance);
};
#undef DECLARE_CASTS
#undef DECLARE_GETTER
#undef DECLARE_ACCESSORS
#undef DECLARE_OPTIONAL_ACCESSORS
#undef DECLARE_OPTIONAL_GETTER
// TODO(titzer): these should be moved to wasm-objects-inl.h
CAST_ACCESSOR(WasmInstanceObject)
CAST_ACCESSOR(WasmMemoryObject)
CAST_ACCESSOR(WasmModuleObject)
CAST_ACCESSOR(WasmTableObject)
// WasmModuleObject
ACCESSORS(WasmModuleObject, compiled_module, WasmCompiledModule,
kCompiledModuleOffset)
// WasmTableObject
ACCESSORS(WasmTableObject, functions, FixedArray, kFunctionsOffset)
SMI_ACCESSORS(WasmTableObject, maximum_length, kMaximumLengthOffset)
ACCESSORS(WasmTableObject, dispatch_tables, FixedArray, kDispatchTablesOffset)
// WasmMemoryObject
ACCESSORS(WasmMemoryObject, array_buffer, JSArrayBuffer, kArrayBufferOffset)
SMI_ACCESSORS(WasmMemoryObject, maximum_pages, kMaximumPagesOffset)
ACCESSORS(WasmMemoryObject, instances_link, WasmInstanceWrapper,
kInstancesLinkOffset)
// WasmInstanceObject
ACCESSORS(WasmInstanceObject, compiled_module, WasmCompiledModule,
kCompiledModuleOffset)
ACCESSORS(WasmInstanceObject, memory_object, WasmMemoryObject,
kMemoryObjectOffset)
ACCESSORS(WasmInstanceObject, memory_buffer, JSArrayBuffer, kMemoryBufferOffset)
ACCESSORS(WasmInstanceObject, globals_buffer, JSArrayBuffer,
kGlobalsBufferOffset)
ACCESSORS(WasmInstanceObject, debug_info, WasmDebugInfo, kDebugInfoOffset)
ACCESSORS(WasmInstanceObject, instance_wrapper, WasmInstanceWrapper,
kInstanceWrapperOffset)
ACCESSORS(WasmInstanceObject, directly_called_instances, FixedArray,
kDirectlyCalledInstancesOffset)
// WasmExportedFunction
ACCESSORS(WasmExportedFunction, instance, WasmInstanceObject, kInstanceOffset)
SMI_ACCESSORS(WasmExportedFunction, function_index, kFunctionIndexOffset)
// WasmSharedModuleData
ACCESSORS(WasmSharedModuleData, module_bytes, SeqOneByteString,
kModuleBytesOffset)
ACCESSORS(WasmSharedModuleData, script, Script, kScriptOffset)
ACCESSORS(WasmSharedModuleData, asm_js_offset_table, ByteArray,
kAsmJsOffsetTableOffset)
ACCESSORS(WasmSharedModuleData, breakpoint_infos, FixedArray,
kBreakPointInfosOffset)
#define OPTIONAL_ACCESSOR(holder, name, offset) \
bool holder::has_##name() { \
return !READ_FIELD(this, offset)->IsUndefined(GetIsolate()); \
}
OPTIONAL_ACCESSOR(WasmInstanceObject, debug_info, kDebugInfoOffset)
OPTIONAL_ACCESSOR(WasmInstanceObject, memory_buffer, kMemoryBufferOffset)
OPTIONAL_ACCESSOR(WasmInstanceObject, memory_object, kMemoryObjectOffset)
OPTIONAL_ACCESSOR(WasmInstanceObject, instance_wrapper, kInstanceWrapperOffset)
OPTIONAL_ACCESSOR(WasmMemoryObject, instances_link, kInstancesLinkOffset)
OPTIONAL_ACCESSOR(WasmSharedModuleData, breakpoint_infos,
kBreakPointInfosOffset)
OPTIONAL_ACCESSOR(WasmSharedModuleData, asm_js_offset_table,
kAsmJsOffsetTableOffset)
OPTIONAL_ACCESSOR(WasmSharedModuleData, lazy_compilation_orchestrator,
kLazyCompilationOrchestratorOffset)
ACCESSORS(WasmDebugInfo, locals_names, FixedArray, kLocalsNamesOffset)
OPTIONAL_ACCESSOR(WasmDebugInfo, locals_names, kLocalsNamesOffset)
inline void WasmMemoryObject::ResetInstancesLink(Isolate* isolate) {
// This has to be a raw access to bypass typechecking.
WRITE_FIELD(this, kInstancesLinkOffset, isolate->heap()->undefined_value());
}
#undef DECL_OOL_QUERY
#undef DECL_OOL_CAST
#undef DECL_GETTER
#undef DECL_OPTIONAL_ACCESSORS
#undef DECL_OPTIONAL_GETTER
#include "src/objects/object-macros-undef.h"
} // namespace internal
} // namespace v8

View File

@ -272,9 +272,8 @@ class WasmSerializationTest {
v8::Utils::OpenHandle(*deserialized_module));
{
DisallowHeapAllocation assume_no_gc;
Handle<WasmCompiledModule> compiled_part(
WasmCompiledModule::cast(module_object->GetEmbedderField(0)),
current_isolate());
Handle<WasmCompiledModule> compiled_part(module_object->compiled_module(),
current_isolate());
CHECK_EQ(memcmp(compiled_part->module_bytes()->GetCharsAddress(),
wire_bytes().first, wire_bytes().second),
0);
@ -1109,7 +1108,7 @@ TEST(Run_WasmModule_Buffer_Externalized_GrowMem) {
const bool free_memory = true;
wasm::DetachWebAssemblyMemoryBuffer(isolate, memory, free_memory);
CHECK_EQ(16, result);
memory = handle(mem_obj->buffer());
memory = handle(mem_obj->array_buffer());
instance->set_memory_buffer(*memory);
// Externalize should make no difference without the JS API as in this case
// the buffer is not detached.

View File

@ -148,8 +148,12 @@ INSTANCE_TYPES = {
244: "JS_FAST_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE",
245: "JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE",
246: "JS_GENERIC_ARRAY_VALUE_ITERATOR_TYPE",
247: "JS_BOUND_FUNCTION_TYPE",
248: "JS_FUNCTION_TYPE",
247: "WASM_INSTANCE_TYPE",
248: "WASM_MEMORY_TYPE",
249: "WASM_MODULE_TYPE",
250: "WASM_TABLE_TYPE",
251: "JS_BOUND_FUNCTION_TYPE",
252: "JS_FUNCTION_TYPE",
}
# List of known V8 maps.