[wasm] Move all heap-allocated WASM structures into wasm-objects.h.

This CL moves all heap-allocated WASM data structures, both ones
that are bonafide JSObjects and ones that are FixedArrays only, into a
consistent place with consistent layout. Note that not all accessors are complete, and I haven't fully spread the new static typing goodness
to all places in the code.

R=ahaas@chromium.org,rossberg@chromium.org
CC=gdeepti@chromium.org,mtrofin@chromium.org,clemensh@chromium.org
BUG=

Review-Url: https://codereview.chromium.org/2490663002
Cr-Commit-Position: refs/heads/master@{#40913}
This commit is contained in:
titzer 2016-11-11 03:12:31 -08:00 committed by Commit bot
parent fc97c638fa
commit fa9c25cebf
21 changed files with 902 additions and 748 deletions

View File

@ -1723,7 +1723,6 @@ v8_source_set("v8_base") {
"src/wasm/signature-map.cc",
"src/wasm/signature-map.h",
"src/wasm/wasm-debug.cc",
"src/wasm/wasm-debug.h",
"src/wasm/wasm-external-refs.cc",
"src/wasm/wasm-external-refs.h",
"src/wasm/wasm-interpreter.cc",
@ -1735,6 +1734,8 @@ v8_source_set("v8_base") {
"src/wasm/wasm-module-builder.h",
"src/wasm/wasm-module.cc",
"src/wasm/wasm-module.h",
"src/wasm/wasm-objects.cc",
"src/wasm/wasm-objects.h",
"src/wasm/wasm-opcodes.cc",
"src/wasm/wasm-opcodes.h",
"src/wasm/wasm-result.cc",

View File

@ -73,6 +73,7 @@
#include "src/version.h"
#include "src/vm-state-inl.h"
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-objects.h"
#include "src/wasm/wasm-result.h"
namespace v8 {
@ -7237,8 +7238,8 @@ 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::wasm::WasmCompiledModule> compiled_part =
i::handle(i::wasm::WasmCompiledModule::cast(obj->GetInternalField(0)));
i::Handle<i::WasmCompiledModule> compiled_part =
i::handle(i::WasmCompiledModule::cast(obj->GetInternalField(0)));
i::Handle<i::String> wire_bytes = compiled_part->module_bytes();
return Local<String>::Cast(Utils::ToLocal(wire_bytes));
}
@ -7246,8 +7247,8 @@ Local<String> WasmCompiledModule::GetWasmWireBytes() {
WasmCompiledModule::SerializedModule WasmCompiledModule::Serialize() {
i::Handle<i::JSObject> obj =
i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
i::Handle<i::wasm::WasmCompiledModule> compiled_part =
i::handle(i::wasm::WasmCompiledModule::cast(obj->GetInternalField(0)));
i::Handle<i::WasmCompiledModule> compiled_part =
i::handle(i::WasmCompiledModule::cast(obj->GetInternalField(0)));
std::unique_ptr<i::ScriptData> script_data =
i::WasmCompiledModuleSerializer::SerializeWasmModule(obj->GetIsolate(),
@ -7273,11 +7274,11 @@ MaybeLocal<WasmCompiledModule> WasmCompiledModule::Deserialize(
if (!maybe_compiled_part.ToHandle(&compiled_part)) {
return MaybeLocal<WasmCompiledModule>();
}
i::Handle<i::wasm::WasmCompiledModule> compiled_module =
handle(i::wasm::WasmCompiledModule::cast(*compiled_part));
i::Handle<i::WasmCompiledModule> compiled_module =
handle(i::WasmCompiledModule::cast(*compiled_part));
return Local<WasmCompiledModule>::Cast(
Utils::ToLocal(i::wasm::CreateWasmModuleObject(
i_isolate, compiled_module, i::wasm::ModuleOrigin::kWasmOrigin)));
Utils::ToLocal(i::Handle<i::JSObject>::cast(
i::WasmModuleObject::New(i_isolate, compiled_module))));
}
MaybeLocal<WasmCompiledModule> WasmCompiledModule::DeserializeOrCompile(

View File

@ -20,6 +20,7 @@
#include "src/wasm/wasm-js.h"
#include "src/wasm/wasm-module-builder.h"
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-objects.h"
#include "src/wasm/wasm-result.h"
typedef uint8_t byte;

View File

@ -27,7 +27,6 @@
#include "src/log.h"
#include "src/messages.h"
#include "src/snapshot/natives.h"
#include "src/wasm/wasm-debug.h"
#include "src/wasm/wasm-module.h"
#include "include/v8-debug.h"

View File

@ -15,8 +15,8 @@
#include "src/safepoint-table.h"
#include "src/string-stream.h"
#include "src/vm-state-inl.h"
#include "src/wasm/wasm-debug.h"
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-objects.h"
namespace v8 {
namespace internal {
@ -1520,8 +1520,8 @@ Script* WasmFrame::script() const {
if (wasm::WasmIsAsmJs(*instance, isolate())) {
return *wasm::GetAsmWasmScript(instance);
}
Handle<wasm::WasmDebugInfo> debug_info = wasm::GetDebugInfo(instance);
return wasm::WasmDebugInfo::GetFunctionScript(debug_info, function_index());
Handle<WasmDebugInfo> debug_info = wasm::GetDebugInfo(instance);
return WasmDebugInfo::GetFunctionScript(debug_info, function_index());
}
int WasmFrame::position() const {

View File

@ -16,8 +16,8 @@
#include "src/interpreter/interpreter.h"
#include "src/isolate-inl.h"
#include "src/runtime/runtime.h"
#include "src/wasm/wasm-debug.h"
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-objects.h"
namespace v8 {
namespace internal {
@ -1906,9 +1906,9 @@ RUNTIME_FUNCTION(Runtime_GetWasmFunctionOffsetTable) {
CHECK(script_val->value()->IsScript());
Handle<Script> script = Handle<Script>(Script::cast(script_val->value()));
Handle<wasm::WasmDebugInfo> debug_info =
Handle<WasmDebugInfo> debug_info =
wasm::GetDebugInfo(handle(script->wasm_instance(), isolate));
Handle<FixedArray> elements = wasm::WasmDebugInfo::GetFunctionOffsetTable(
Handle<FixedArray> elements = WasmDebugInfo::GetFunctionOffsetTable(
debug_info, script->wasm_function_index());
return *isolate->factory()->NewJSArrayWithElements(elements);
}
@ -1922,10 +1922,10 @@ RUNTIME_FUNCTION(Runtime_DisassembleWasmFunction) {
CHECK(script_val->value()->IsScript());
Handle<Script> script = Handle<Script>(Script::cast(script_val->value()));
Handle<wasm::WasmDebugInfo> debug_info =
Handle<WasmDebugInfo> debug_info =
wasm::GetDebugInfo(handle(script->wasm_instance(), isolate));
return *wasm::WasmDebugInfo::DisassembleFunction(
debug_info, script->wasm_function_index());
return *WasmDebugInfo::DisassembleFunction(debug_info,
script->wasm_function_index());
}
} // namespace internal

View File

@ -17,6 +17,7 @@
#include "src/snapshot/code-serializer.h"
#include "src/snapshot/natives.h"
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-objects.h"
namespace v8 {
namespace internal {
@ -783,9 +784,8 @@ RUNTIME_FUNCTION(Runtime_DeserializeWasmModule) {
if (!maybe_compiled_module.ToHandle(&compiled_module)) {
return isolate->heap()->undefined_value();
}
return *wasm::CreateWasmModuleObject(
isolate, Handle<wasm::WasmCompiledModule>::cast(compiled_module),
wasm::kWasmOrigin);
return *WasmModuleObject::New(
isolate, Handle<WasmCompiledModule>::cast(compiled_module));
}
RUNTIME_FUNCTION(Runtime_ValidateWasmInstancesChain) {

View File

@ -13,6 +13,7 @@
#include "src/snapshot/snapshot.h"
#include "src/version.h"
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-objects.h"
namespace v8 {
namespace internal {
@ -219,8 +220,8 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize(
std::unique_ptr<ScriptData> WasmCompiledModuleSerializer::SerializeWasmModule(
Isolate* isolate, Handle<FixedArray> input) {
Handle<wasm::WasmCompiledModule> compiled_module =
Handle<wasm::WasmCompiledModule>::cast(input);
Handle<WasmCompiledModule> compiled_module =
Handle<WasmCompiledModule>::cast(input);
WasmCompiledModuleSerializer wasm_cs(isolate, 0);
wasm_cs.reference_map()->AddAttachedReference(*isolate->native_context());
wasm_cs.reference_map()->AddAttachedReference(
@ -261,10 +262,10 @@ MaybeHandle<FixedArray> WasmCompiledModuleSerializer::DeserializeWasmModule(
MaybeHandle<HeapObject> obj = deserializer.DeserializeObject(isolate);
if (obj.is_null() || !obj.ToHandleChecked()->IsFixedArray()) return nothing;
Handle<wasm::WasmCompiledModule> compiled_module =
Handle<wasm::WasmCompiledModule>::cast(obj.ToHandleChecked());
Handle<WasmCompiledModule> compiled_module =
Handle<WasmCompiledModule>::cast(obj.ToHandleChecked());
wasm::WasmCompiledModule::RecreateModuleWrapper(isolate, compiled_module);
WasmCompiledModule::RecreateModuleWrapper(isolate, compiled_module);
return compiled_module;
}

View File

@ -1263,7 +1263,6 @@
'wasm/signature-map.cc',
'wasm/signature-map.h',
'wasm/wasm-debug.cc',
'wasm/wasm-debug.h',
'wasm/wasm-external-refs.cc',
'wasm/wasm-external-refs.h',
'wasm/wasm-js.cc',
@ -1275,6 +1274,8 @@
'wasm/wasm-module-builder.h',
'wasm/wasm-interpreter.cc',
'wasm/wasm-interpreter.h',
'wasm/wasm-objects.cc',
'wasm/wasm-objects.h',
'wasm/wasm-opcodes.cc',
'wasm/wasm-opcodes.h',
'wasm/wasm-result.cc',

View File

@ -17,6 +17,7 @@
#include "src/snapshot/code-serializer.h"
#include "src/transitions.h"
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-objects.h"
#include "src/wasm/wasm-result.h"
namespace v8 {
@ -739,8 +740,8 @@ Maybe<bool> ValueSerializer::WriteJSArrayBufferView(JSArrayBufferView* view) {
}
Maybe<bool> ValueSerializer::WriteWasmModule(Handle<JSObject> object) {
Handle<wasm::WasmCompiledModule> compiled_part(
wasm::WasmCompiledModule::cast(object->GetInternalField(0)), isolate_);
Handle<WasmCompiledModule> compiled_part(
WasmCompiledModule::cast(object->GetInternalField(0)), isolate_);
WasmEncodingTag encoding_tag = WasmEncodingTag::kRawBytes;
WriteTag(SerializationTag::kWasmModule);
WriteRawBytes(&encoding_tag, sizeof(encoding_tag));
@ -1508,9 +1509,8 @@ MaybeHandle<JSObject> ValueDeserializer::ReadWasmModule() {
if (WasmCompiledModuleSerializer::DeserializeWasmModule(
isolate_, &script_data, wire_bytes)
.ToHandle(&compiled_part)) {
return wasm::CreateWasmModuleObject(
isolate_, Handle<wasm::WasmCompiledModule>::cast(compiled_part),
wasm::ModuleOrigin::kWasmOrigin);
return WasmModuleObject::New(
isolate_, Handle<WasmCompiledModule>::cast(compiled_part));
}
// If that fails, recompile.

View File

@ -2,14 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/wasm/wasm-debug.h"
#include "src/assert-scope.h"
#include "src/debug/debug.h"
#include "src/factory.h"
#include "src/isolate.h"
#include "src/wasm/module-decoder.h"
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-objects.h"
using namespace v8::internal;
using namespace v8::internal::wasm;

View File

@ -1,51 +0,0 @@
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_WASM_DEBUG_H_
#define V8_WASM_DEBUG_H_
#include "src/handles.h"
#include "src/objects.h"
namespace v8 {
namespace internal {
namespace wasm {
class WasmDebugInfo : public FixedArray {
public:
static Handle<WasmDebugInfo> New(Handle<JSObject> wasm);
static bool IsDebugInfo(Object* object);
static WasmDebugInfo* cast(Object* object);
JSObject* wasm_instance();
bool SetBreakPoint(int byte_offset);
// Get the Script for the specified function.
static Script* GetFunctionScript(Handle<WasmDebugInfo> debug_info,
int func_index);
// Disassemble the specified function from this module.
static Handle<String> DisassembleFunction(Handle<WasmDebugInfo> debug_info,
int func_index);
// Get the offset table for the specified function, mapping from byte offsets
// to position in the disassembly.
// Returns an array with three entries per instruction: byte offset, line and
// column.
static Handle<FixedArray> GetFunctionOffsetTable(
Handle<WasmDebugInfo> debug_info, int func_index);
// Get the asm.js source position from a byte offset.
// Must only be called if the associated wasm object was created from asm.js.
static int GetAsmJsSourcePosition(Handle<WasmDebugInfo> debug_info,
int func_index, int byte_offset);
};
} // namespace wasm
} // namespace internal
} // namespace v8
#endif // V8_WASM_DEBUG_H_

View File

@ -19,6 +19,7 @@
#include "src/wasm/module-decoder.h"
#include "src/wasm/wasm-js.h"
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-objects.h"
#include "src/wasm/wasm-result.h"
typedef uint8_t byte;
@ -27,21 +28,12 @@ using v8::internal::wasm::ErrorThrower;
namespace v8 {
static const int kWasmTableArrayFieldIndex = 0;
static const int kWasmTableMaximumFieldIndex = 1;
static const int kWasmTableDispatchTablesFieldIndex = 2;
enum WasmMemoryObjectData {
kWasmMemoryBuffer,
kWasmMemoryMaximum,
kWasmMemoryInstanceObject
};
enum WasmInternalFieldCountData {
kWasmTableInternalFieldCount = 3,
kWasmMemoryInternalFieldCount = 3
};
namespace {
i::Handle<i::String> v8_str(i::Isolate* isolate, const char* str) {
return isolate->factory()->NewStringFromAsciiChecked(str);
@ -93,14 +85,14 @@ RawBuffer GetRawBufferSource(
return {start, end};
}
static i::MaybeHandle<i::JSObject> CreateModuleObject(
static i::MaybeHandle<i::WasmModuleObject> CreateModuleObject(
v8::Isolate* isolate, const v8::Local<v8::Value> source,
ErrorThrower* thrower) {
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
i::MaybeHandle<i::JSObject> nothing;
RawBuffer buffer = GetRawBufferSource(source, thrower);
if (buffer.start == nullptr) return i::MaybeHandle<i::JSObject>();
if (buffer.start == nullptr) return i::MaybeHandle<i::WasmModuleObject>();
DCHECK(source->IsArrayBuffer() || source->IsTypedArray());
return i::wasm::CreateModuleObjectFromBytes(
@ -123,7 +115,7 @@ static bool ValidateModule(v8::Isolate* isolate,
i::wasm::ModuleOrigin::kWasmOrigin);
}
bool BrandCheck(Isolate* isolate, i::Handle<i::Object> value,
static bool BrandCheck(Isolate* isolate, i::Handle<i::Object> value,
i::Handle<i::Symbol> sym, const char* msg) {
if (value->IsJSObject()) {
i::Handle<i::JSObject> object = i::Handle<i::JSObject>::cast(value);
@ -233,7 +225,9 @@ void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) {
Local<Object> obj = Local<Object>::Cast(args[2]);
i::Handle<i::Object> mem_obj = v8::Utils::OpenHandle(*obj);
if (i::WasmJs::IsWasmMemoryObject(i_isolate, mem_obj)) {
memory = i::WasmJs::GetWasmMemoryArrayBuffer(i_isolate, mem_obj);
memory = i::Handle<i::JSArrayBuffer>(
i::Handle<i::WasmMemoryObject>::cast(mem_obj)->get_buffer(),
i_isolate);
} else {
thrower.TypeError("Argument 2 must be a WebAssembly.Memory");
}
@ -325,12 +319,14 @@ void WebAssemblyTable(const v8::FunctionCallbackInfo<v8::Value>& args) {
&maximum, initial, max_table_size)) {
return;
}
} else {
maximum = static_cast<int>(i::wasm::WasmModule::kV8MaxTableSize);
}
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
i::Handle<i::FixedArray> fixed_array;
i::Handle<i::JSObject> table_obj = i::WasmJs::CreateWasmTableObject(
i_isolate, initial, has_maximum.FromJust(), maximum, &fixed_array);
i::Handle<i::JSObject> table_obj =
i::WasmTableObject::New(i_isolate, initial, maximum, &fixed_array);
v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
return_value.Set(Utils::ToLocal(table_obj));
}
@ -374,10 +370,9 @@ void WebAssemblyMemory(const v8::FunctionCallbackInfo<v8::Value>& args) {
static_cast<size_t>(initial);
i::JSArrayBuffer::SetupAllocatingData(buffer, i_isolate, size);
i::Handle<i::JSObject> memory_obj = i::WasmJs::CreateWasmMemoryObject(
i_isolate, buffer, has_maximum.FromJust(), maximum);
v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
return_value.Set(Utils::ToLocal(memory_obj));
i::Handle<i::JSObject> memory_obj = i::WasmMemoryObject::New(
i_isolate, buffer, has_maximum.FromJust() ? maximum : -1);
args.GetReturnValue().Set(Utils::ToLocal(memory_obj));
}
void WebAssemblyTableGetLength(
@ -390,14 +385,10 @@ void WebAssemblyTableGetLength(
"Receiver is not a WebAssembly.Table")) {
return;
}
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
i::Handle<i::JSObject> receiver =
i::Handle<i::JSObject>::cast(Utils::OpenHandle(*args.This()));
i::Handle<i::Object> array(
receiver->GetInternalField(kWasmTableArrayFieldIndex), i_isolate);
int length = i::Handle<i::FixedArray>::cast(array)->length();
v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
return_value.Set(v8::Number::New(isolate, length));
auto receiver =
i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This()));
args.GetReturnValue().Set(
v8::Number::New(isolate, receiver->current_length()));
}
void WebAssemblyTableGrow(const v8::FunctionCallbackInfo<v8::Value>& args) {
@ -411,12 +402,9 @@ void WebAssemblyTableGrow(const v8::FunctionCallbackInfo<v8::Value>& args) {
}
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
i::Handle<i::JSObject> receiver =
i::Handle<i::JSObject>::cast(Utils::OpenHandle(*args.This()));
i::Handle<i::FixedArray> old_array(
i::FixedArray::cast(
receiver->GetInternalField(kWasmTableArrayFieldIndex)),
i_isolate);
auto receiver =
i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This()));
i::Handle<i::FixedArray> old_array(receiver->get_functions(), i_isolate);
int old_size = old_array->length();
int64_t new_size64 = 0;
if (args.Length() > 0 && !args[0]->IntegerValue(context).To(&new_size64)) {
@ -424,11 +412,7 @@ void WebAssemblyTableGrow(const v8::FunctionCallbackInfo<v8::Value>& args) {
}
new_size64 += old_size;
i::Handle<i::Object> max_val(
receiver->GetInternalField(kWasmTableMaximumFieldIndex), i_isolate);
int max_size =
max_val->IsSmi() ? i::Smi::cast(*max_val)->value() : max_table_size;
if (new_size64 < old_size || new_size64 > max_size) {
if (new_size64 < old_size || new_size64 > receiver->maximum_length()) {
v8::Local<v8::Value> e = v8::Exception::RangeError(
v8_str(isolate, new_size64 < old_size ? "trying to shrink table"
: "maximum table size exceeded"));
@ -443,7 +427,7 @@ void WebAssemblyTableGrow(const v8::FunctionCallbackInfo<v8::Value>& args) {
for (int i = 0; i < old_size; ++i) new_array->set(i, old_array->get(i));
i::Object* null = i_isolate->heap()->null_value();
for (int i = old_size; i < new_size; ++i) new_array->set(i, null);
receiver->SetInternalField(kWasmTableArrayFieldIndex, *new_array);
receiver->set_functions(*new_array);
}
// TODO(titzer): update relevant instances.
@ -460,22 +444,20 @@ void WebAssemblyTableGet(const v8::FunctionCallbackInfo<v8::Value>& args) {
}
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
i::Handle<i::JSObject> receiver =
i::Handle<i::JSObject>::cast(Utils::OpenHandle(*args.This()));
i::Handle<i::Object> array(
receiver->GetInternalField(kWasmTableArrayFieldIndex), i_isolate);
auto receiver =
i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This()));
i::Handle<i::FixedArray> array(receiver->get_functions(), i_isolate);
int i = 0;
if (args.Length() > 0 && !args[0]->Int32Value(context).To(&i)) return;
v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
if (i < 0 || i >= i::Handle<i::FixedArray>::cast(array)->length()) {
if (i < 0 || i >= array->length()) {
v8::Local<v8::Value> e =
v8::Exception::RangeError(v8_str(isolate, "index out of bounds"));
isolate->ThrowException(e);
return;
}
i::Handle<i::Object> value(i::Handle<i::FixedArray>::cast(array)->get(i),
i_isolate);
i::Handle<i::Object> value(array->get(i), i_isolate);
return_value.Set(Utils::ToLocal(value));
}
@ -506,22 +488,19 @@ void WebAssemblyTableSet(const v8::FunctionCallbackInfo<v8::Value>& args) {
return;
}
i::Handle<i::JSObject> receiver =
i::Handle<i::JSObject>::cast(Utils::OpenHandle(*args.This()));
i::Handle<i::Object> array(
receiver->GetInternalField(kWasmTableArrayFieldIndex), i_isolate);
auto receiver =
i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This()));
i::Handle<i::FixedArray> array(receiver->get_functions(), i_isolate);
int i;
if (!args[0]->Int32Value(context).To(&i)) return;
if (i < 0 || i >= i::Handle<i::FixedArray>::cast(array)->length()) {
if (i < 0 || i >= array->length()) {
v8::Local<v8::Value> e =
v8::Exception::RangeError(v8_str(isolate, "index out of bounds"));
isolate->ThrowException(e);
return;
}
i::Handle<i::FixedArray> dispatch_tables(
i::FixedArray::cast(
receiver->GetInternalField(kWasmTableDispatchTablesFieldIndex)),
i::Handle<i::FixedArray> dispatch_tables(receiver->get_dispatch_tables(),
i_isolate);
if (value->IsNull(i_isolate)) {
i::wasm::UpdateDispatchTables(i_isolate, dispatch_tables, i,
@ -602,81 +581,6 @@ void WebAssemblyMemoryGetBuffer(
}
} // namespace
i::Handle<i::JSObject> i::WasmJs::CreateWasmMemoryObject(
i::Isolate* i_isolate, i::Handle<i::JSArrayBuffer> buffer, bool has_maximum,
int maximum) {
i::Handle<i::JSFunction> memory_ctor(
i_isolate->native_context()->wasm_memory_constructor());
i::Handle<i::JSObject> memory_obj =
i_isolate->factory()->NewJSObject(memory_ctor);
memory_obj->SetInternalField(kWasmMemoryBuffer, *buffer);
memory_obj->SetInternalField(
kWasmMemoryMaximum,
has_maximum
? static_cast<i::Object*>(i::Smi::FromInt(maximum))
: static_cast<i::Object*>(i_isolate->heap()->undefined_value()));
i::Handle<i::Symbol> memory_sym(
i_isolate->native_context()->wasm_memory_sym());
i::Object::SetProperty(memory_obj, memory_sym, memory_obj, i::STRICT).Check();
return memory_obj;
}
i::Handle<i::JSObject> i::WasmJs::CreateWasmTableObject(
i::Isolate* i_isolate, uint32_t initial, bool has_maximum, uint32_t maximum,
i::Handle<i::FixedArray>* js_functions) {
i::Handle<i::JSFunction> table_ctor(
i_isolate->native_context()->wasm_table_constructor());
i::Handle<i::JSObject> table_obj =
i_isolate->factory()->NewJSObject(table_ctor);
*js_functions = i_isolate->factory()->NewFixedArray(initial);
i::Object* null = i_isolate->heap()->null_value();
// TODO(titzer): consider moving FixedArray to size_t.
for (int i = 0; i < static_cast<int>(initial); ++i) {
(*js_functions)->set(i, null);
}
table_obj->SetInternalField(kWasmTableArrayFieldIndex, *(*js_functions));
table_obj->SetInternalField(
kWasmTableMaximumFieldIndex,
has_maximum
? static_cast<i::Object*>(i::Smi::FromInt(maximum))
: static_cast<i::Object*>(i_isolate->heap()->undefined_value()));
Handle<FixedArray> dispatch_tables = i_isolate->factory()->NewFixedArray(0);
table_obj->SetInternalField(kWasmTableDispatchTablesFieldIndex,
*dispatch_tables);
i::Handle<i::Symbol> table_sym(i_isolate->native_context()->wasm_table_sym());
i::Object::SetProperty(table_obj, table_sym, table_obj, i::STRICT).Check();
return table_obj;
}
i::Handle<i::FixedArray> i::WasmJs::AddWasmTableDispatchTable(
i::Isolate* i_isolate, i::Handle<i::JSObject> table_obj,
i::Handle<i::JSObject> instance, int table_index,
i::Handle<i::FixedArray> dispatch_table) {
DCHECK(IsWasmTableObject(i_isolate, table_obj));
i::Handle<i::FixedArray> dispatch_tables(
i::FixedArray::cast(
table_obj->GetInternalField(kWasmTableDispatchTablesFieldIndex)),
i_isolate);
DCHECK_EQ(0, dispatch_tables->length() % 3);
if (instance.is_null()) return dispatch_tables;
// TODO(titzer): use weak cells here to avoid leaking instances.
// Grow the dispatch table and add a new pair at the end.
i::Handle<i::FixedArray> new_dispatch_tables =
i_isolate->factory()->CopyFixedArrayAndGrow(dispatch_tables, 3);
new_dispatch_tables->set(dispatch_tables->length() + 0, *instance);
new_dispatch_tables->set(dispatch_tables->length() + 1,
Smi::FromInt(table_index));
new_dispatch_tables->set(dispatch_tables->length() + 2, *dispatch_table);
table_obj->SetInternalField(kWasmTableDispatchTablesFieldIndex,
*new_dispatch_tables);
return new_dispatch_tables;
}
// TODO(titzer): we use the API to create the function template because the
// internal guts are too ugly to replicate here.
static i::Handle<i::FunctionTemplateInfo> NewTemplate(i::Isolate* i_isolate,
@ -765,7 +669,8 @@ void WasmJs::InstallWasmConstructors(Isolate* isolate,
Handle<JSObject> module_proto =
factory->NewJSObject(module_constructor, TENURED);
i::Handle<i::Map> map = isolate->factory()->NewMap(
i::JS_OBJECT_TYPE, i::JSObject::kHeaderSize + i::kPointerSize);
i::JS_OBJECT_TYPE, i::JSObject::kHeaderSize +
WasmModuleObject::kFieldCount * i::kPointerSize);
JSFunction::SetInitialMap(module_constructor, map, module_proto);
JSObject::AddProperty(module_proto, isolate->factory()->constructor_string(),
module_constructor, DONT_ENUM);
@ -783,7 +688,7 @@ void WasmJs::InstallWasmConstructors(Isolate* isolate,
factory->NewJSObject(table_constructor, TENURED);
map = isolate->factory()->NewMap(
i::JS_OBJECT_TYPE, i::JSObject::kHeaderSize +
kWasmTableInternalFieldCount * i::kPointerSize);
WasmTableObject::kFieldCount * i::kPointerSize);
JSFunction::SetInitialMap(table_constructor, map, table_proto);
JSObject::AddProperty(table_proto, isolate->factory()->constructor_string(),
table_constructor, DONT_ENUM);
@ -800,7 +705,7 @@ void WasmJs::InstallWasmConstructors(Isolate* isolate,
factory->NewJSObject(memory_constructor, TENURED);
map = isolate->factory()->NewMap(
i::JS_OBJECT_TYPE, i::JSObject::kHeaderSize +
kWasmMemoryInternalFieldCount * i::kPointerSize);
WasmMemoryObject::kFieldCount * i::kPointerSize);
JSFunction::SetInitialMap(memory_constructor, map, memory_proto);
JSObject::AddProperty(memory_proto, isolate->factory()->constructor_string(),
memory_constructor, DONT_ENUM);
@ -881,50 +786,5 @@ bool WasmJs::IsWasmTableObject(Isolate* isolate, Handle<Object> value) {
i::Handle<i::Symbol> symbol(isolate->context()->wasm_table_sym(), isolate);
return HasBrand(value, symbol);
}
Handle<FixedArray> WasmJs::GetWasmTableFunctions(Isolate* isolate,
Handle<JSObject> value) {
DCHECK(IsWasmTableObject(isolate, value));
Handle<Object> arr(
JSObject::cast(*value)->GetInternalField(kWasmTableArrayFieldIndex),
isolate);
return Handle<FixedArray>::cast(arr);
}
Handle<JSArrayBuffer> WasmJs::GetWasmMemoryArrayBuffer(Isolate* isolate,
Handle<Object> value) {
DCHECK(IsWasmMemoryObject(isolate, value));
Handle<Object> buf(
JSObject::cast(*value)->GetInternalField(kWasmMemoryBuffer), isolate);
return Handle<JSArrayBuffer>::cast(buf);
}
void WasmJs::SetWasmMemoryArrayBuffer(Isolate* isolate, Handle<Object> value,
Handle<JSArrayBuffer> buffer) {
DCHECK(IsWasmMemoryObject(isolate, value));
JSObject::cast(*value)->SetInternalField(kWasmMemoryBuffer, *buffer);
}
uint32_t WasmJs::GetWasmMemoryMaximumSize(Isolate* isolate,
Handle<Object> value) {
DCHECK(IsWasmMemoryObject(isolate, value));
Object* max_mem =
JSObject::cast(*value)->GetInternalField(kWasmMemoryMaximum);
if (max_mem->IsUndefined(isolate)) return 0;
uint32_t max_pages = Smi::cast(max_mem)->value();
return max_pages;
}
void WasmJs::SetWasmMemoryInstance(Isolate* isolate,
Handle<Object> memory_object,
Handle<JSObject> instance) {
if (!memory_object->IsUndefined(isolate)) {
DCHECK(IsWasmMemoryObject(isolate, memory_object));
// TODO(gdeepti): This should be a weak list of instance objects
// for instances that share memory.
JSObject::cast(*memory_object)
->SetInternalField(kWasmMemoryInstanceObject, *instance);
}
}
} // namespace internal
} // namespace v8

View File

@ -25,37 +25,10 @@ class WasmJs {
Handle<Context> context);
// WebAssembly.Table.
static Handle<JSObject> CreateWasmTableObject(
Isolate* isolate, uint32_t initial, bool has_maximum, uint32_t maximum,
Handle<FixedArray>* js_functions);
static bool IsWasmTableObject(Isolate* isolate, Handle<Object> value);
static Handle<FixedArray> GetWasmTableFunctions(Isolate* isolate,
Handle<JSObject> object);
static Handle<FixedArray> AddWasmTableDispatchTable(
Isolate* isolate, Handle<JSObject> table_obj, Handle<JSObject> instance,
int table_index, Handle<FixedArray> dispatch_table);
// WebAssembly.Memory
static Handle<JSObject> CreateWasmMemoryObject(Isolate* isolate,
Handle<JSArrayBuffer> buffer,
bool has_maximum, int maximum);
static bool IsWasmMemoryObject(Isolate* isolate, Handle<Object> value);
static Handle<JSArrayBuffer> GetWasmMemoryArrayBuffer(Isolate* isolate,
Handle<Object> value);
static void SetWasmMemoryArrayBuffer(Isolate* isolate, Handle<Object> value,
Handle<JSArrayBuffer> buffer);
static uint32_t GetWasmMemoryMaximumSize(Isolate* isolate,
Handle<Object> value);
static void SetWasmMemoryInstance(Isolate* isolate, Handle<Object> value,
Handle<JSObject> instance);
};
} // namespace internal

View File

@ -16,9 +16,9 @@
#include "src/wasm/ast-decoder.h"
#include "src/wasm/module-decoder.h"
#include "src/wasm/wasm-debug.h"
#include "src/wasm/wasm-js.h"
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-objects.h"
#include "src/wasm/wasm-result.h"
#include "src/compiler/wasm-compiler.h"
@ -37,61 +37,15 @@ namespace base = v8::base;
instance->PrintInstancesChain(); \
} while (false)
static const int kInvalidSigIndex = -1;
// Collects all the data values to which a given WASM code object may be
// specialized.
struct Specialization {
// The native context, which is used in JS->WASM and WASM->JS wrappers
// and calls to the runtime.
Handle<Context> context;
// Specialization to the memory.
byte* memory_base;
uint32_t memory_size;
// Specialization to the globals.
byte* globals_base;
// Specialization to the function table.
uint32_t function_table_size;
Handle<FixedArray> function_table_sigs;
Handle<FixedArray> function_table_code;
Specialization()
: memory_base(nullptr),
memory_size(0),
globals_base(nullptr),
function_table_size(0) {}
};
namespace {
static const int kInvalidSigIndex = -1;
static const int kPlaceholderMarker = 1000000000;
enum JSFunctionExportInternalField {
kInternalModuleInstance,
kInternalFunctionIndex
};
// Internal constants for the layout of the module object.
enum WasmInstanceObjectFields {
kWasmCompiledModule = 0,
kWasmMemObject,
kWasmMemArrayBuffer,
kWasmGlobalsArrayBuffer,
kWasmDebugInfo,
kWasmInstanceInternalFieldCount
};
byte* raw_buffer_ptr(MaybeHandle<JSArrayBuffer> buffer, int offset) {
return static_cast<byte*>(buffer.ToHandleChecked()->backing_store()) + offset;
}
uint32_t GetMinModuleMemSize(const WasmModule* module) {
return WasmModule::kPageSize * module->min_mem_pages;
}
MaybeHandle<String> ExtractStringFromModuleBytes(
Isolate* isolate, Handle<WasmCompiledModule> compiled_module,
uint32_t offset, uint32_t size) {
@ -171,8 +125,8 @@ Handle<Code> CreatePlaceholder(Factory* factory, uint32_t index,
Code::Kind kind) {
// Create a placeholder code object and encode the corresponding index in
// the {constant_pool_offset} field of the code object.
// TODO(titzer): placeholder code objects are somewhat dangerous.
static byte buffer[] = {0, 0, 0, 0, 0, 0, 0, 0}; // fake instructions.
// TODO(titzer): instead of placeholders, use a reloc_info mode.
static byte buffer[] = {0, 0, 0, 0}; // fake instructions.
static CodeDesc desc = {
buffer, arraysize(buffer), arraysize(buffer), 0, 0, nullptr, 0, nullptr};
Handle<Code> code = factory->NewCode(desc, Code::KindField::encode(kind),
@ -296,12 +250,12 @@ static void RecordStats(Isolate* isolate, Handle<FixedArray> functions) {
}
Address GetGlobalStartAddressFromCodeTemplate(Object* undefined,
JSObject* owner) {
JSObject* object) {
auto instance = WasmInstanceObject::cast(object);
Address old_address = nullptr;
Object* stored_value = owner->GetInternalField(kWasmGlobalsArrayBuffer);
if (stored_value != undefined) {
old_address = static_cast<Address>(
JSArrayBuffer::cast(stored_value)->backing_store());
if (instance->has_globals_buffer()) {
old_address =
static_cast<Address>(instance->get_globals_buffer()->backing_store());
}
return old_address;
}
@ -494,7 +448,7 @@ void PatchDirectCalls(Handle<FixedArray> old_functions,
}
}
static void ResetCompiledModule(Isolate* isolate, JSObject* owner,
static void ResetCompiledModule(Isolate* isolate, WasmInstanceObject* owner,
WasmCompiledModule* compiled_module) {
TRACE("Resetting %d\n", compiled_module->instance_id());
Object* undefined = *isolate->factory()->undefined_value();
@ -564,8 +518,8 @@ static void ResetCompiledModule(Isolate* isolate, JSObject* owner,
static void InstanceFinalizer(const v8::WeakCallbackInfo<void>& data) {
JSObject** p = reinterpret_cast<JSObject**>(data.GetParameter());
JSObject* owner = *p;
WasmCompiledModule* compiled_module = GetCompiledModule(owner);
WasmInstanceObject* owner = reinterpret_cast<WasmInstanceObject*>(*p);
WasmCompiledModule* compiled_module = owner->get_compiled_module();
TRACE("Finalizing %d {\n", compiled_module->instance_id());
Isolate* isolate = reinterpret_cast<Isolate*>(data.GetIsolate());
DCHECK(compiled_module->has_weak_wasm_module());
@ -698,23 +652,6 @@ std::ostream& wasm::operator<<(std::ostream& os, const WasmFunctionName& pair) {
return os;
}
Handle<JSFunction> wasm::WrapExportCodeAsJSFunction(
Isolate* isolate, Handle<Code> export_code, Handle<String> name,
FunctionSig* sig, int func_index, Handle<JSObject> instance) {
Handle<SharedFunctionInfo> shared =
isolate->factory()->NewSharedFunctionInfo(name, export_code, false);
int arity = static_cast<int>(sig->parameter_count());
shared->set_length(arity);
shared->set_internal_formal_parameter_count(arity);
Handle<JSFunction> function = isolate->factory()->NewFunction(
isolate->wasm_function_map(), name, export_code);
function->set_shared(*shared);
function->SetInternalField(kInternalModuleInstance, *instance);
function->SetInternalField(kInternalFunctionIndex, Smi::FromInt(func_index));
return function;
}
Object* wasm::GetOwningWasmInstance(Code* code) {
DCHECK(code->kind() == Code::WASM_FUNCTION);
DisallowHeapAllocation no_gc;
@ -727,15 +664,10 @@ Object* wasm::GetOwningWasmInstance(Code* code) {
return cell->value();
}
WasmModule* GetCppModule(Handle<JSObject> instance) {
DCHECK(IsWasmInstance(*instance));
return reinterpret_cast<WasmModuleWrapper*>(
*GetCompiledModule(*instance)->module_wrapper())
->get();
}
int wasm::GetNumImportedFunctions(Handle<JSObject> instance) {
return static_cast<int>(GetCppModule(instance)->num_imported_functions);
int wasm::GetNumImportedFunctions(Handle<JSObject> object) {
return static_cast<int>(Handle<WasmInstanceObject>::cast(object)
->module()
->num_imported_functions);
}
WasmModule::WasmModule(Zone* owned, const byte* module_start)
@ -752,7 +684,7 @@ MaybeHandle<WasmCompiledModule> WasmModule::CompileFunctions(
WasmInstance temp_instance(this);
temp_instance.context = isolate->native_context();
temp_instance.mem_size = GetMinModuleMemSize(this);
temp_instance.mem_size = WasmModule::kPageSize * this->min_mem_pages;
temp_instance.mem_start = nullptr;
temp_instance.globals_start = nullptr;
@ -876,14 +808,11 @@ static WasmFunction* GetWasmFunctionForImportWrapper(Isolate* isolate,
Handle<Object> target) {
if (target->IsJSFunction()) {
Handle<JSFunction> func = Handle<JSFunction>::cast(target);
Handle<Code> export_wrapper_code = handle(func->code());
if (export_wrapper_code->kind() == Code::JS_TO_WASM_FUNCTION) {
Handle<JSObject> other_instance(
JSObject::cast(func->GetInternalField(kInternalModuleInstance)),
isolate);
int func_index =
Smi::cast(func->GetInternalField(kInternalFunctionIndex))->value();
return &GetCppModule(other_instance)->functions[func_index];
if (func->code()->kind() == Code::JS_TO_WASM_FUNCTION) {
auto exported = Handle<WasmExportedFunction>::cast(func);
Handle<WasmInstanceObject> other_instance(exported->instance(), isolate);
int func_index = exported->function_index();
return &other_instance->module()->functions[func_index];
}
}
return nullptr;
@ -937,16 +866,17 @@ static void UpdateDispatchTablesInternal(Isolate* isolate,
Handle<Code> code) {
DCHECK_EQ(0, dispatch_tables->length() % 3);
for (int i = 0; i < dispatch_tables->length(); i += 3) {
Handle<Object> instance(dispatch_tables->get(i), isolate);
WasmModule* module = GetCppModule(Handle<JSObject>::cast(instance));
int table_index = Smi::cast(dispatch_tables->get(i + 1))->value();
Handle<FixedArray> dispatch_table(
FixedArray::cast(dispatch_tables->get(i + 2)), isolate);
if (function) {
// TODO(titzer): the signature might need to be copied to avoid
// a dangling pointer in the signature map.
Handle<WasmInstanceObject> instance(
WasmInstanceObject::cast(dispatch_tables->get(i)), isolate);
int sig_index = static_cast<int>(
module->function_tables[table_index].map.FindOrInsert(function->sig));
instance->module()->function_tables[table_index].map.FindOrInsert(
function->sig));
dispatch_table->set(index, Smi::FromInt(sig_index));
dispatch_table->set(index + (dispatch_table->length() / 2), *code);
} else {
@ -997,7 +927,7 @@ class WasmInstanceBuilder {
//--------------------------------------------------------------------------
Handle<FixedArray> code_table;
Handle<FixedArray> old_code_table;
MaybeHandle<JSObject> owner;
MaybeHandle<WasmInstanceObject> owner;
TRACE("Starting new module instantiation\n");
{
@ -1013,8 +943,8 @@ class WasmInstanceBuilder {
original = handle(
WasmCompiledModule::cast(module_object_->GetInternalField(0)));
if (original->has_weak_owning_instance()) {
owner =
handle(JSObject::cast(original->weak_owning_instance()->value()));
owner = handle(WasmInstanceObject::cast(
original->weak_owning_instance()->value()));
}
}
DCHECK(!original.is_null());
@ -1068,12 +998,8 @@ class WasmInstanceBuilder {
//--------------------------------------------------------------------------
// Allocate the instance object.
//--------------------------------------------------------------------------
Handle<Map> map = factory->NewMap(
JS_OBJECT_TYPE,
JSObject::kHeaderSize + kWasmInstanceInternalFieldCount * kPointerSize);
Handle<JSObject> instance = factory->NewJSObjectFromMap(map, TENURED);
instance->SetInternalField(kWasmMemObject,
isolate_->heap()->undefined_value());
Handle<WasmInstanceObject> instance =
WasmInstanceObject::New(isolate_, compiled_module_);
//--------------------------------------------------------------------------
// Set up the globals for the new instance.
@ -1088,14 +1014,13 @@ class WasmInstanceBuilder {
thrower_->RangeError("Out of memory: wasm globals");
return nothing;
}
Address old_address = owner.is_null()
? nullptr
: GetGlobalStartAddressFromCodeTemplate(
Address old_address =
owner.is_null() ? nullptr : GetGlobalStartAddressFromCodeTemplate(
isolate_->heap()->undefined_value(),
JSObject::cast(*owner.ToHandleChecked()));
*owner.ToHandleChecked());
RelocateGlobals(code_table, old_address,
static_cast<Address>(global_buffer->backing_store()));
instance->SetInternalField(kWasmGlobalsArrayBuffer, *global_buffer);
instance->set_globals_buffer(*global_buffer);
}
//--------------------------------------------------------------------------
@ -1105,7 +1030,7 @@ class WasmInstanceBuilder {
static_cast<int>(module_->function_tables.size());
table_instances_.reserve(module_->function_tables.size());
for (int index = 0; index < function_table_count; ++index) {
table_instances_.push_back({Handle<JSObject>::null(),
table_instances_.push_back({Handle<WasmTableObject>::null(),
Handle<FixedArray>::null(),
Handle<FixedArray>::null()});
}
@ -1138,7 +1063,7 @@ class WasmInstanceBuilder {
}
if (!memory_.is_null()) {
instance->SetInternalField(kWasmMemArrayBuffer, *memory_);
instance->set_memory_buffer(*memory_);
Address mem_start = static_cast<Address>(memory_->backing_store());
uint32_t mem_size =
static_cast<uint32_t>(memory_->byte_length()->Number());
@ -1205,7 +1130,7 @@ class WasmInstanceBuilder {
// we want all the publishing to happen free from GC interruptions, and
// so we do it in
// one GC-free scope afterwards.
original = handle(GetCompiledModule(*owner.ToHandleChecked()));
original = handle(owner.ToHandleChecked()->get_compiled_module());
link_to_original = factory->NewWeakCell(original.ToHandleChecked());
}
// Publish the new instance to the instances chain.
@ -1219,7 +1144,6 @@ class WasmInstanceBuilder {
original.ToHandleChecked()->weak_wasm_module());
}
module_object_->SetInternalField(0, *compiled_module_);
instance->SetInternalField(kWasmCompiledModule, *compiled_module_);
compiled_module_->set_weak_owning_instance(link_to_owning_instance);
GlobalHandles::MakeWeak(global_handle.location(),
global_handle.location(), &InstanceFinalizer,
@ -1228,9 +1152,9 @@ class WasmInstanceBuilder {
}
DCHECK(wasm::IsWasmInstance(*instance));
Handle<Object> memory_object(instance->GetInternalField(kWasmMemObject),
isolate_);
WasmJs::SetWasmMemoryInstance(isolate_, memory_object, instance);
if (instance->has_memory_object()) {
instance->get_memory_object()->AddInstance(*instance);
}
//--------------------------------------------------------------------------
// Run the start function if one was specified.
@ -1247,9 +1171,9 @@ class WasmInstanceBuilder {
FunctionSig* sig = module_->functions[start_index].sig;
Handle<Code> wrapper_code = compiler::CompileJSToWasmWrapper(
isolate_, &module_env, startup_code, start_index);
Handle<JSFunction> startup_fct = WrapExportCodeAsJSFunction(
isolate_, wrapper_code, factory->InternalizeUtf8String("start"), sig,
start_index, instance);
Handle<WasmExportedFunction> startup_fct = WasmExportedFunction::New(
isolate_, instance, factory->InternalizeUtf8String("start"),
wrapper_code, static_cast<int>(sig->parameter_count()), start_index);
RecordStats(isolate_, *startup_code);
// Call the JS function.
Handle<Object> undefined = factory->undefined_value();
@ -1276,7 +1200,7 @@ class WasmInstanceBuilder {
private:
// Represents the initialized state of a table.
struct TableInstance {
Handle<JSObject> table_object; // WebAssembly.Table instance
Handle<WasmTableObject> table_object; // WebAssembly.Table instance
Handle<FixedArray> js_wrappers; // JSFunctions exported
Handle<FixedArray> dispatch_table; // internal (code, sig) pairs
};
@ -1417,7 +1341,8 @@ class WasmInstanceBuilder {
// Process the imports, including functions, tables, globals, and memory, in
// order, loading them from the {ffi_} object. Returns the number of imported
// functions.
int ProcessImports(Handle<FixedArray> code_table, Handle<JSObject> instance) {
int ProcessImports(Handle<FixedArray> code_table,
Handle<WasmInstanceObject> instance) {
int num_imported_functions = 0;
int num_imported_tables = 0;
for (int index = 0; index < static_cast<int>(module_->import_table.size());
@ -1473,9 +1398,9 @@ class WasmInstanceBuilder {
WasmIndirectFunctionTable& table =
module_->function_tables[num_imported_tables];
TableInstance& table_instance = table_instances_[num_imported_tables];
table_instance.table_object = Handle<JSObject>::cast(value);
table_instance.js_wrappers = WasmJs::GetWasmTableFunctions(
isolate_, table_instance.table_object);
table_instance.table_object = Handle<WasmTableObject>::cast(value);
table_instance.js_wrappers = Handle<FixedArray>(
table_instance.table_object->get_functions(), isolate_);
// TODO(titzer): import table size must match exactly for now.
int table_size = table_instance.js_wrappers->length();
@ -1521,8 +1446,9 @@ class WasmInstanceBuilder {
index, module_name, function_name);
return -1;
}
instance->SetInternalField(kWasmMemObject, *object);
memory_ = WasmJs::GetWasmMemoryArrayBuffer(isolate_, object);
auto memory = Handle<WasmMemoryObject>::cast(object);
instance->set_memory_object(*memory);
memory_ = Handle<JSArrayBuffer>(memory->get_buffer(), isolate_);
break;
}
case kExternalGlobal: {
@ -1610,7 +1536,7 @@ class WasmInstanceBuilder {
// Process the exports, creating wrappers for functions, tables, memories,
// and globals.
void ProcessExports(Handle<FixedArray> code_table,
Handle<JSObject> instance) {
Handle<WasmInstanceObject> instance) {
bool needs_wrappers = module_->num_exported_functions > 0;
for (auto table_instance : table_instances_) {
if (!table_instance.js_wrappers.is_null()) {
@ -1663,9 +1589,10 @@ class WasmInstanceBuilder {
// Wrap the exported code as a JSFunction.
Handle<Code> export_code =
code_table->GetValueChecked<Code>(isolate_, func_index);
js_function = WrapExportCodeAsJSFunction(
isolate_, export_code, name, function.sig, function.func_index,
instance);
js_function = WasmExportedFunction::New(
isolate_, instance, name, export_code,
static_cast<int>(function.sig->parameter_count()),
function.func_index);
js_wrappers_[exp.index] = js_function;
}
desc.set_value(js_function);
@ -1678,27 +1605,28 @@ class WasmInstanceBuilder {
WasmIndirectFunctionTable& table =
module_->function_tables[exp.index];
if (table_instance.table_object.is_null()) {
table_instance.table_object = WasmJs::CreateWasmTableObject(
isolate_, table.min_size, table.has_max, table.max_size,
&table_instance.js_wrappers);
uint32_t maximum =
table.has_max ? table.max_size : WasmModule::kV8MaxTableSize;
table_instance.table_object = WasmTableObject::New(
isolate_, table.min_size, maximum, &table_instance.js_wrappers);
}
desc.set_value(table_instance.table_object);
break;
}
case kExternalMemory: {
// Export the memory as a WebAssembly.Memory object.
Handle<Object> memory_object(
instance->GetInternalField(kWasmMemObject), isolate_);
if (memory_object->IsUndefined(isolate_)) {
Handle<WasmMemoryObject> memory_object;
if (!instance->has_memory_object()) {
// If there was no imported WebAssembly.Memory object, create one.
Handle<JSArrayBuffer> buffer(
JSArrayBuffer::cast(
instance->GetInternalField(kWasmMemArrayBuffer)),
Handle<JSArrayBuffer> buffer(instance->get_memory_buffer(),
isolate_);
memory_object = WasmJs::CreateWasmMemoryObject(
isolate_, buffer, (module_->max_mem_pages != 0),
module_->max_mem_pages);
instance->SetInternalField(kWasmMemObject, *memory_object);
memory_object = WasmMemoryObject::New(
isolate_, buffer,
(module_->max_mem_pages != 0) ? module_->max_mem_pages : -1);
instance->set_memory_object(*memory_object);
} else {
memory_object = Handle<WasmMemoryObject>(
instance->get_memory_object(), isolate_);
}
desc.set_value(memory_object);
@ -1740,7 +1668,7 @@ class WasmInstanceBuilder {
}
void InitializeTables(Handle<FixedArray> code_table,
Handle<JSObject> instance) {
Handle<WasmInstanceObject> instance) {
Handle<FixedArray> old_function_tables =
compiled_module_->function_tables();
int function_table_count =
@ -1769,9 +1697,10 @@ class WasmInstanceBuilder {
Handle<FixedArray> all_dispatch_tables;
if (!table_instance.table_object.is_null()) {
// Get the existing dispatch table(s) with the WebAssembly.Table object.
all_dispatch_tables = WasmJs::AddWasmTableDispatchTable(
isolate_, table_instance.table_object, Handle<JSObject>::null(),
index, Handle<FixedArray>::null());
all_dispatch_tables = WasmTableObject::AddDispatchTable(
isolate_, table_instance.table_object,
Handle<WasmInstanceObject>::null(), index,
Handle<FixedArray>::null());
}
// TODO(titzer): this does redundant work if there are multiple tables,
@ -1816,9 +1745,12 @@ class WasmInstanceBuilder {
Handle<Code> wrapper_code = compiler::CompileJSToWasmWrapper(
isolate_, &module_env, wasm_code, func_index);
Handle<JSFunction> js_function = WrapExportCodeAsJSFunction(
isolate_, wrapper_code, isolate_->factory()->empty_string(),
function->sig, func_index, instance);
Handle<WasmExportedFunction> js_function =
WasmExportedFunction::New(
isolate_, instance, isolate_->factory()->empty_string(),
wrapper_code,
static_cast<int>(function->sig->parameter_count()),
func_index);
js_wrappers_[func_index] = js_function;
}
table_instance.js_wrappers->set(table_index,
@ -1835,7 +1767,7 @@ class WasmInstanceBuilder {
// initialized.
if (!table_instance.table_object.is_null()) {
// Add the new dispatch table to the WebAssembly.Table object.
all_dispatch_tables = WasmJs::AddWasmTableDispatchTable(
all_dispatch_tables = WasmTableObject::AddDispatchTable(
isolate_, table_instance.table_object, instance, index,
table_instance.dispatch_table);
}
@ -1865,69 +1797,14 @@ MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate,
return builder.Build();
}
Handle<WasmCompiledModule> WasmCompiledModule::New(
Isolate* isolate, Handle<WasmModuleWrapper> module_wrapper) {
Handle<FixedArray> ret =
isolate->factory()->NewFixedArray(PropertyIndices::Count, TENURED);
// WasmCompiledModule::cast would fail since module bytes are not set yet.
Handle<WasmCompiledModule> compiled_module(
reinterpret_cast<WasmCompiledModule*>(*ret), isolate);
compiled_module->InitId();
compiled_module->set_module_wrapper(module_wrapper);
return compiled_module;
}
void WasmCompiledModule::InitId() {
#if DEBUG
static uint32_t instance_id_counter = 0;
set(kID_instance_id, Smi::FromInt(instance_id_counter++));
TRACE("New compiled module id: %d\n", instance_id());
#endif
}
bool WasmCompiledModule::IsWasmCompiledModule(Object* obj) {
if (!obj->IsFixedArray()) return false;
FixedArray* arr = FixedArray::cast(obj);
if (arr->length() != PropertyIndices::Count) return false;
Isolate* isolate = arr->GetIsolate();
#define WCM_CHECK_SMALL_NUMBER(TYPE, NAME) \
if (!arr->get(kID_##NAME)->IsSmi()) return false;
#define WCM_CHECK_OBJECT_OR_WEAK(TYPE, NAME) \
if (!arr->get(kID_##NAME)->IsUndefined(isolate) && \
!arr->get(kID_##NAME)->Is##TYPE()) \
return false;
#define WCM_CHECK_OBJECT(TYPE, NAME) WCM_CHECK_OBJECT_OR_WEAK(TYPE, NAME)
#define WCM_CHECK_WEAK_LINK(TYPE, NAME) WCM_CHECK_OBJECT_OR_WEAK(WeakCell, NAME)
#define WCM_CHECK(KIND, TYPE, NAME) WCM_CHECK_##KIND(TYPE, NAME)
WCM_PROPERTY_TABLE(WCM_CHECK)
#undef WCM_CHECK
// All checks passed.
return true;
}
void WasmCompiledModule::PrintInstancesChain() {
#if DEBUG
if (!FLAG_trace_wasm_instances) return;
for (WasmCompiledModule* current = this; current != nullptr;) {
PrintF("->%d", current->instance_id());
if (current->ptr_to_weak_next_instance() == nullptr) break;
CHECK(!current->ptr_to_weak_next_instance()->cleared());
current =
WasmCompiledModule::cast(current->ptr_to_weak_next_instance()->value());
}
PrintF("\n");
#endif
}
Handle<Object> wasm::GetWasmFunctionNameOrNull(Isolate* isolate,
Handle<Object> instance,
Handle<Object> object,
uint32_t func_index) {
if (!instance->IsUndefined(isolate)) {
DCHECK(IsWasmInstance(*instance));
WasmModule* module = GetCppModule(Handle<JSObject>::cast(instance));
if (!object->IsUndefined(isolate)) {
auto instance = Handle<WasmInstanceObject>::cast(object);
WasmModule* module = instance->module();
WasmFunction& function = module->functions[func_index];
Handle<WasmCompiledModule> compiled_module(GetCompiledModule(*instance),
Handle<WasmCompiledModule> compiled_module(instance->get_compiled_module(),
isolate);
MaybeHandle<String> string = ExtractStringFromModuleBytes(
isolate, compiled_module, function.name_offset, function.name_length);
@ -1948,40 +1825,24 @@ Handle<String> wasm::GetWasmFunctionName(Isolate* isolate,
}
bool wasm::IsWasmInstance(Object* object) {
if (!object->IsJSObject()) return false;
JSObject* obj = JSObject::cast(object);
Isolate* isolate = obj->GetIsolate();
if (obj->GetInternalFieldCount() != kWasmInstanceInternalFieldCount) {
return false;
return WasmInstanceObject::IsWasmInstanceObject(object);
}
Object* mem = obj->GetInternalField(kWasmMemArrayBuffer);
if (!(mem->IsUndefined(isolate) || mem->IsJSArrayBuffer()) ||
!WasmCompiledModule::IsWasmCompiledModule(
obj->GetInternalField(kWasmCompiledModule))) {
return false;
WasmCompiledModule* wasm::GetCompiledModule(Object* object) {
return WasmInstanceObject::cast(object)->get_compiled_module();
}
// All checks passed.
return true;
bool wasm::WasmIsAsmJs(Object* object, Isolate* isolate) {
return IsWasmInstance(object) &&
WasmInstanceObject::cast(object)
->get_compiled_module()
->has_asm_js_script();
}
WasmCompiledModule* wasm::GetCompiledModule(Object* instance) {
DCHECK(IsWasmInstance(instance));
return WasmCompiledModule::cast(
JSObject::cast(instance)->GetInternalField(kWasmCompiledModule));
}
bool wasm::WasmIsAsmJs(Object* instance, Isolate* isolate) {
return IsWasmInstance(instance) &&
GetCompiledModule(JSObject::cast(instance))->has_asm_js_script();
}
Handle<Script> wasm::GetAsmWasmScript(Handle<JSObject> instance) {
DCHECK(IsWasmInstance(*instance));
WasmCompiledModule* compiled_module = GetCompiledModule(*instance);
return compiled_module->asm_js_script();
Handle<Script> wasm::GetAsmWasmScript(Handle<JSObject> object) {
return Handle<WasmInstanceObject>::cast(object)
->get_compiled_module()
->asm_js_script();
}
int wasm::GetAsmWasmSourcePosition(Handle<JSObject> instance, int func_index,
@ -1990,58 +1851,36 @@ int wasm::GetAsmWasmSourcePosition(Handle<JSObject> instance, int func_index,
func_index, byte_offset);
}
Handle<SeqOneByteString> wasm::GetWasmBytes(Handle<JSObject> instance) {
DCHECK(IsWasmInstance(*instance));
WasmCompiledModule* compiled_module = GetCompiledModule(*instance);
return compiled_module->module_bytes();
Handle<SeqOneByteString> wasm::GetWasmBytes(Handle<JSObject> object) {
return Handle<WasmInstanceObject>::cast(object)
->get_compiled_module()
->module_bytes();
}
Handle<WasmDebugInfo> wasm::GetDebugInfo(Handle<JSObject> instance) {
Handle<Object> info(instance->GetInternalField(kWasmDebugInfo),
Handle<WasmDebugInfo> wasm::GetDebugInfo(Handle<JSObject> object) {
auto instance = Handle<WasmInstanceObject>::cast(object);
if (instance->has_debug_info()) {
Handle<WasmDebugInfo> info(instance->get_debug_info(),
instance->GetIsolate());
if (!info->IsUndefined(instance->GetIsolate()))
return Handle<WasmDebugInfo>::cast(info);
return info;
}
Handle<WasmDebugInfo> new_info = WasmDebugInfo::New(instance);
instance->SetInternalField(kWasmDebugInfo, *new_info);
instance->set_debug_info(*new_info);
return new_info;
}
int wasm::GetNumberOfFunctions(Handle<JSObject> instance) {
return static_cast<int>(GetCppModule(instance)->functions.size());
}
Handle<JSObject> wasm::CreateWasmModuleObject(
Isolate* isolate, Handle<WasmCompiledModule> compiled_module,
ModuleOrigin origin) {
Handle<JSObject> wasm_module;
if (origin == ModuleOrigin::kWasmOrigin) {
Handle<JSFunction> module_cons(
isolate->native_context()->wasm_module_constructor());
wasm_module = isolate->factory()->NewJSObject(module_cons);
} else {
DCHECK(origin == ModuleOrigin::kAsmJsOrigin);
Handle<Map> map = isolate->factory()->NewMap(
JS_OBJECT_TYPE, JSObject::kHeaderSize + kPointerSize);
wasm_module = isolate->factory()->NewJSObjectFromMap(map, TENURED);
}
wasm_module->SetInternalField(0, *compiled_module);
if (origin == ModuleOrigin::kWasmOrigin) {
Handle<Symbol> module_sym(isolate->native_context()->wasm_module_sym());
Object::SetProperty(wasm_module, module_sym, wasm_module, STRICT).Check();
}
Handle<WeakCell> link_to_module =
isolate->factory()->NewWeakCell(wasm_module);
compiled_module->set_weak_wasm_module(link_to_module);
return wasm_module;
int wasm::GetNumberOfFunctions(Handle<JSObject> object) {
return static_cast<int>(
Handle<WasmInstanceObject>::cast(object)->module()->functions.size());
}
// TODO(clemensh): origin can be inferred from asm_js_script; remove it.
MaybeHandle<JSObject> wasm::CreateModuleObjectFromBytes(
MaybeHandle<WasmModuleObject> wasm::CreateModuleObjectFromBytes(
Isolate* isolate, const byte* start, const byte* end, ErrorThrower* thrower,
ModuleOrigin origin, Handle<Script> asm_js_script,
const byte* asm_js_offset_tables_start,
const byte* asm_js_offset_tables_end) {
MaybeHandle<JSObject> nothing;
MaybeHandle<WasmModuleObject> nothing;
ModuleResult result = DecodeWasmModule(isolate, start, end, false, origin);
if (result.failed()) {
if (result.val) delete result.val;
@ -2077,7 +1916,7 @@ MaybeHandle<JSObject> wasm::CreateModuleObjectFromBytes(
compiled_module->set_asm_js_offset_tables(offset_tables);
}
return CreateWasmModuleObject(isolate, compiled_module, origin);
return WasmModuleObject::New(isolate, compiled_module);
}
bool wasm::ValidateModuleBytes(Isolate* isolate, const byte* start,
@ -2093,19 +1932,19 @@ bool wasm::ValidateModuleBytes(Isolate* isolate, const byte* start,
}
MaybeHandle<JSArrayBuffer> wasm::GetInstanceMemory(Isolate* isolate,
Handle<JSObject> instance) {
Object* mem = instance->GetInternalField(kWasmMemArrayBuffer);
DCHECK(IsWasmInstance(*instance));
if (mem->IsUndefined(isolate)) return MaybeHandle<JSArrayBuffer>();
return Handle<JSArrayBuffer>(JSArrayBuffer::cast(mem));
Handle<JSObject> object) {
auto instance = Handle<WasmInstanceObject>::cast(object);
if (instance->has_memory_buffer()) {
return Handle<JSArrayBuffer>(instance->get_memory_buffer(), isolate);
}
return MaybeHandle<JSArrayBuffer>();
}
void SetInstanceMemory(Handle<JSObject> instance, JSArrayBuffer* buffer) {
void SetInstanceMemory(Handle<JSObject> object, JSArrayBuffer* buffer) {
DisallowHeapAllocation no_gc;
DCHECK(IsWasmInstance(*instance));
instance->SetInternalField(kWasmMemArrayBuffer, buffer);
WasmCompiledModule* compiled_module = GetCompiledModule(*instance);
compiled_module->set_ptr_to_memory(buffer);
auto instance = Handle<WasmInstanceObject>::cast(object);
instance->set_memory_buffer(buffer);
instance->get_compiled_module()->set_ptr_to_memory(buffer);
}
int32_t wasm::GetInstanceMemorySize(Isolate* isolate,
@ -2120,24 +1959,27 @@ int32_t wasm::GetInstanceMemorySize(Isolate* isolate,
}
}
uint32_t GetMaxInstanceMemorySize(Isolate* isolate, Handle<JSObject> instance) {
Handle<Object> memory_object(instance->GetInternalField(kWasmMemObject),
uint32_t GetMaxInstanceMemorySize(Isolate* isolate,
Handle<WasmInstanceObject> instance) {
if (instance->has_memory_object()) {
Handle<WasmMemoryObject> memory_object(instance->get_memory_object(),
isolate);
if (!memory_object->IsUndefined(isolate)) {
uint32_t mem_obj_max =
WasmJs::GetWasmMemoryMaximumSize(isolate, memory_object);
if (mem_obj_max != 0) return mem_obj_max;
int maximum = memory_object->maximum_pages();
if (maximum > 0) return static_cast<uint32_t>(maximum);
}
uint32_t compiled_max_pages = GetCompiledModule(*instance)->max_mem_pages();
uint32_t compiled_max_pages =
instance->get_compiled_module()->max_mem_pages();
isolate->counters()->wasm_max_mem_pages_count()->AddSample(
compiled_max_pages);
if (compiled_max_pages != 0) return compiled_max_pages;
return WasmModule::kV8MaxPages;
}
int32_t wasm::GrowInstanceMemory(Isolate* isolate, Handle<JSObject> instance,
int32_t wasm::GrowInstanceMemory(Isolate* isolate, Handle<JSObject> object,
uint32_t pages) {
if (!IsWasmInstance(*instance)) return -1;
if (!IsWasmInstance(*object)) return -1;
auto instance = Handle<WasmInstanceObject>::cast(object);
if (pages == 0) return GetInstanceMemorySize(isolate, instance);
uint32_t max_pages = GetMaxInstanceMemorySize(isolate, instance);
@ -2175,13 +2017,11 @@ int32_t wasm::GrowInstanceMemory(Isolate* isolate, Handle<JSObject> instance,
memcpy(new_mem_start, old_mem_start, old_size);
}
SetInstanceMemory(instance, *buffer);
Handle<FixedArray> code_table = GetCompiledModule(*instance)->code_table();
Handle<FixedArray> code_table = instance->get_compiled_module()->code_table();
RelocateMemoryReferencesInCode(code_table, old_mem_start, new_mem_start,
old_size, new_size);
Handle<Object> memory_object(instance->GetInternalField(kWasmMemObject),
isolate);
if (!memory_object->IsUndefined(isolate)) {
WasmJs::SetWasmMemoryArrayBuffer(isolate, memory_object, buffer);
if (instance->has_memory_object()) {
instance->get_memory_object()->set_buffer(*buffer);
}
DCHECK(old_size % WasmModule::kPageSize == 0);
@ -2229,10 +2069,10 @@ void testing::ValidateModuleState(Isolate* isolate,
}
void testing::ValidateOrphanedInstance(Isolate* isolate,
Handle<JSObject> wasm_module) {
Handle<JSObject> object) {
DisallowHeapAllocation no_gc;
CHECK(IsWasmInstance(*wasm_module));
WasmCompiledModule* compiled_module = GetCompiledModule(*wasm_module);
WasmInstanceObject* instance = WasmInstanceObject::cast(*object);
WasmCompiledModule* compiled_module = instance->get_compiled_module();
CHECK(compiled_module->has_weak_wasm_module());
CHECK(compiled_module->ptr_to_weak_wasm_module()->cleared());
}

View File

@ -19,6 +19,10 @@
namespace v8 {
namespace internal {
class WasmCompiledModule;
class WasmDebugInfo;
class WasmModuleObject;
namespace compiler {
class CallDescriptor;
class WasmCompilationUnit;
@ -58,8 +62,6 @@ inline bool IsValidSectionCode(uint8_t byte) {
const char* SectionName(WasmSectionCode code);
class WasmDebugInfo;
// Constants for fixed-size elements within a module.
static const uint32_t kMaxReturnCount = 1;
static const uint8_t kResizableMaximumFlag = 1;
@ -170,8 +172,6 @@ struct WasmExport {
enum ModuleOrigin { kWasmOrigin, kAsmJsOrigin };
class WasmCompiledModule;
// Static representation of a module.
struct V8_EXPORT_PRIVATE WasmModule {
static const uint32_t kPageSize = 0x10000; // Page size, 64kb.
@ -353,125 +353,6 @@ std::ostream& operator<<(std::ostream& os, const WasmModule& module);
std::ostream& operator<<(std::ostream& os, const WasmFunction& function);
std::ostream& operator<<(std::ostream& os, const WasmFunctionName& name);
class WasmCompiledModule : public FixedArray {
public:
static WasmCompiledModule* cast(Object* fixed_array) {
SLOW_DCHECK(IsWasmCompiledModule(fixed_array));
return reinterpret_cast<WasmCompiledModule*>(fixed_array);
}
#define WCM_OBJECT_OR_WEAK(TYPE, NAME, ID) \
Handle<TYPE> NAME() const { return handle(ptr_to_##NAME()); } \
\
MaybeHandle<TYPE> maybe_##NAME() const { \
if (has_##NAME()) return NAME(); \
return MaybeHandle<TYPE>(); \
} \
\
TYPE* ptr_to_##NAME() const { \
Object* obj = get(ID); \
if (!obj->Is##TYPE()) return nullptr; \
return TYPE::cast(obj); \
} \
\
void set_##NAME(Handle<TYPE> value) { set_ptr_to_##NAME(*value); } \
\
void set_ptr_to_##NAME(TYPE* value) { set(ID, value); } \
\
bool has_##NAME() const { return get(ID)->Is##TYPE(); } \
\
void reset_##NAME() { set_undefined(ID); }
#define WCM_OBJECT(TYPE, NAME) WCM_OBJECT_OR_WEAK(TYPE, NAME, kID_##NAME)
#define WCM_SMALL_NUMBER(TYPE, NAME) \
TYPE NAME() const { \
return static_cast<TYPE>(Smi::cast(get(kID_##NAME))->value()); \
} \
void set_##NAME(TYPE value) { set(kID_##NAME, Smi::FromInt(value)); }
#define WCM_WEAK_LINK(TYPE, NAME) \
WCM_OBJECT_OR_WEAK(WeakCell, weak_##NAME, kID_##NAME); \
\
Handle<TYPE> NAME() const { \
return handle(TYPE::cast(weak_##NAME()->value())); \
}
#define CORE_WCM_PROPERTY_TABLE(MACRO) \
MACRO(OBJECT, FixedArray, code_table) \
MACRO(OBJECT, Foreign, module_wrapper) \
MACRO(OBJECT, SeqOneByteString, module_bytes) \
MACRO(OBJECT, Script, asm_js_script) \
MACRO(OBJECT, FixedArray, function_tables) \
MACRO(OBJECT, FixedArray, empty_function_tables) \
MACRO(OBJECT, ByteArray, asm_js_offset_tables) \
MACRO(OBJECT, JSArrayBuffer, memory) \
MACRO(SMALL_NUMBER, uint32_t, min_mem_pages) \
MACRO(SMALL_NUMBER, uint32_t, max_mem_pages) \
MACRO(WEAK_LINK, WasmCompiledModule, next_instance) \
MACRO(WEAK_LINK, WasmCompiledModule, prev_instance) \
MACRO(WEAK_LINK, JSObject, owning_instance) \
MACRO(WEAK_LINK, JSObject, wasm_module)
#if DEBUG
#define DEBUG_ONLY_TABLE(MACRO) MACRO(SMALL_NUMBER, uint32_t, instance_id)
#else
#define DEBUG_ONLY_TABLE(IGNORE)
uint32_t instance_id() const { return -1; }
#endif
#define WCM_PROPERTY_TABLE(MACRO) \
CORE_WCM_PROPERTY_TABLE(MACRO) \
DEBUG_ONLY_TABLE(MACRO)
private:
enum PropertyIndices {
#define INDICES(IGNORE1, IGNORE2, NAME) kID_##NAME,
WCM_PROPERTY_TABLE(INDICES) Count
#undef INDICES
};
public:
static Handle<WasmCompiledModule> New(
Isolate* isolate, Handle<Managed<WasmModule>> module_wrapper);
static Handle<WasmCompiledModule> Clone(Isolate* isolate,
Handle<WasmCompiledModule> module) {
Handle<WasmCompiledModule> ret = Handle<WasmCompiledModule>::cast(
isolate->factory()->CopyFixedArray(module));
ret->InitId();
ret->reset_weak_owning_instance();
ret->reset_weak_next_instance();
ret->reset_weak_prev_instance();
return ret;
}
uint32_t mem_size() const {
return has_memory() ? memory()->byte_length()->Number()
: default_mem_size();
}
uint32_t default_mem_size() const {
return min_mem_pages() * WasmModule::kPageSize;
}
#define DECLARATION(KIND, TYPE, NAME) WCM_##KIND(TYPE, NAME)
WCM_PROPERTY_TABLE(DECLARATION)
#undef DECLARATION
static bool IsWasmCompiledModule(Object* obj);
void PrintInstancesChain();
static void RecreateModuleWrapper(Isolate* isolate,
Handle<FixedArray> compiled_module);
private:
void InitId();
DISALLOW_IMPLICIT_CONSTRUCTORS(WasmCompiledModule);
};
// Extract a function name from the given wasm object.
// Returns "<WASM UNNAMED>" if the function is unnamed or the name is not a
// valid UTF-8 string.
@ -522,21 +403,7 @@ Handle<Script> GetAsmWasmScript(Handle<JSObject> instance);
int GetAsmWasmSourcePosition(Handle<JSObject> instance, int func_index,
int byte_offset);
// Constructs a single function table as a FixedArray of double size,
// populating it with function signature indices and function indices.
Handle<FixedArray> BuildFunctionTable(Isolate* isolate, uint32_t index,
const WasmModule* module);
// Populates a function table by replacing function indices with handles to
// the compiled code.
void PopulateFunctionTable(Handle<FixedArray> table, uint32_t table_size,
const std::vector<Handle<Code>>* code_table);
Handle<JSObject> CreateWasmModuleObject(
Isolate* isolate, Handle<WasmCompiledModule> compiled_module,
ModuleOrigin origin);
V8_EXPORT_PRIVATE MaybeHandle<JSObject> CreateModuleObjectFromBytes(
V8_EXPORT_PRIVATE MaybeHandle<WasmModuleObject> CreateModuleObjectFromBytes(
Isolate* isolate, const byte* start, const byte* end, ErrorThrower* thrower,
ModuleOrigin origin, Handle<Script> asm_js_script,
const byte* asm_offset_tables_start, const byte* asm_offset_tables_end);

359
src/wasm/wasm-objects.cc Normal file
View File

@ -0,0 +1,359 @@
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/wasm/wasm-objects.h"
#include "src/wasm/wasm-module.h"
#define TRACE(...) \
do { \
if (FLAG_trace_wasm_instances) PrintF(__VA_ARGS__); \
} while (false)
#define TRACE_CHAIN(instance) \
do { \
instance->PrintInstancesChain(); \
} while (false)
using namespace v8::internal;
using namespace v8::internal::wasm;
#define DEFINE_ACCESSORS(Container, name, field, type) \
type* Container::get_##name() { \
return type::cast(GetInternalField(field)); \
} \
void Container::set_##name(type* value) { \
return SetInternalField(field, value); \
}
#define DEFINE_OPTIONAL_ACCESSORS(Container, name, field, type) \
bool Container::has_##name() { \
return !GetInternalField(field)->IsUndefined(GetIsolate()); \
} \
type* Container::get_##name() { \
return type::cast(GetInternalField(field)); \
} \
void Container::set_##name(type* value) { \
return SetInternalField(field, value); \
}
#define DEFINE_GETTER(Container, name, field, type) \
type* Container::get_##name() { return type::cast(GetInternalField(field)); }
static uint32_t SafeUint32(Object* value) {
if (value->IsSmi()) {
int32_t val = Smi::cast(value)->value();
CHECK_GE(val, 0);
return static_cast<uint32_t>(val);
}
DCHECK(value->IsHeapNumber());
HeapNumber* num = HeapNumber::cast(value);
CHECK_GE(num->value(), 0.0);
CHECK_LE(num->value(), static_cast<double>(kMaxUInt32));
return static_cast<uint32_t>(num->value());
}
static int32_t SafeInt32(Object* value) {
if (value->IsSmi()) {
return Smi::cast(value)->value();
}
DCHECK(value->IsHeapNumber());
HeapNumber* num = HeapNumber::cast(value);
CHECK_GE(num->value(), static_cast<double>(Smi::kMinValue));
CHECK_LE(num->value(), static_cast<double>(Smi::kMaxValue));
return static_cast<int32_t>(num->value());
}
Handle<WasmModuleObject> WasmModuleObject::New(
Isolate* isolate, Handle<WasmCompiledModule> compiled_module) {
ModuleOrigin origin = compiled_module->module()->origin;
Handle<JSObject> module_object;
if (origin == ModuleOrigin::kWasmOrigin) {
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(origin == ModuleOrigin::kAsmJsOrigin);
Handle<Map> map = isolate->factory()->NewMap(
JS_OBJECT_TYPE,
JSObject::kHeaderSize + WasmModuleObject::kFieldCount * kPointerSize);
module_object = isolate->factory()->NewJSObjectFromMap(map, TENURED);
}
module_object->SetInternalField(WasmModuleObject::kCompiledModule,
*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);
}
WasmModuleObject* WasmModuleObject::cast(Object* object) {
DCHECK(object->IsJSObject());
// TODO(titzer): brand check for WasmModuleObject.
return reinterpret_cast<WasmModuleObject*>(object);
}
Handle<WasmTableObject> WasmTableObject::New(Isolate* isolate, uint32_t initial,
uint32_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);
*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->SetInternalField(kFunctions, *(*js_functions));
table_obj->SetInternalField(kMaximum,
static_cast<Object*>(Smi::FromInt(maximum)));
Handle<FixedArray> dispatch_tables = isolate->factory()->NewFixedArray(0);
table_obj->SetInternalField(kDispatchTables, *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);
}
DEFINE_GETTER(WasmTableObject, dispatch_tables, kDispatchTables, FixedArray)
Handle<FixedArray> WasmTableObject::AddDispatchTable(
Isolate* isolate, Handle<WasmTableObject> table_obj,
Handle<WasmInstanceObject> instance, int table_index,
Handle<FixedArray> dispatch_table) {
Handle<FixedArray> dispatch_tables(
FixedArray::cast(table_obj->GetInternalField(kDispatchTables)), isolate);
DCHECK_EQ(0, dispatch_tables->length() % 3);
if (instance.is_null()) return dispatch_tables;
// TODO(titzer): use weak cells here to avoid leaking instances.
// Grow the dispatch table and add a new triple at the end.
Handle<FixedArray> new_dispatch_tables =
isolate->factory()->CopyFixedArrayAndGrow(dispatch_tables, 3);
new_dispatch_tables->set(dispatch_tables->length() + 0, *instance);
new_dispatch_tables->set(dispatch_tables->length() + 1,
Smi::FromInt(table_index));
new_dispatch_tables->set(dispatch_tables->length() + 2, *dispatch_table);
table_obj->SetInternalField(WasmTableObject::kDispatchTables,
*new_dispatch_tables);
return new_dispatch_tables;
}
DEFINE_ACCESSORS(WasmTableObject, functions, kFunctions, FixedArray)
uint32_t WasmTableObject::current_length() { return get_functions()->length(); }
uint32_t WasmTableObject::maximum_length() {
return SafeUint32(GetInternalField(kMaximum));
}
WasmTableObject* WasmTableObject::cast(Object* object) {
DCHECK(object && object->IsJSObject());
// TODO(titzer): brand check for WasmTableObject.
return reinterpret_cast<WasmTableObject*>(object);
}
Handle<WasmMemoryObject> WasmMemoryObject::New(Isolate* isolate,
Handle<JSArrayBuffer> buffer,
int maximum) {
Handle<JSFunction> memory_ctor(
isolate->native_context()->wasm_memory_constructor());
Handle<JSObject> memory_obj = isolate->factory()->NewJSObject(memory_ctor);
memory_obj->SetInternalField(kArrayBuffer, *buffer);
memory_obj->SetInternalField(kMaximum,
static_cast<Object*>(Smi::FromInt(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_ACCESSORS(WasmMemoryObject, buffer, kArrayBuffer, JSArrayBuffer)
uint32_t WasmMemoryObject::current_pages() {
return SafeUint32(get_buffer()->byte_length()) / wasm::WasmModule::kPageSize;
}
int32_t WasmMemoryObject::maximum_pages() {
return SafeInt32(GetInternalField(kMaximum));
}
WasmMemoryObject* WasmMemoryObject::cast(Object* object) {
DCHECK(object && object->IsJSObject());
// TODO(titzer): brand check for WasmMemoryObject.
return reinterpret_cast<WasmMemoryObject*>(object);
}
void WasmMemoryObject::AddInstance(WasmInstanceObject* instance) {
// TODO(gdeepti): This should be a weak list of instance objects
// for instances that share memory.
SetInternalField(kInstance, instance);
}
DEFINE_ACCESSORS(WasmInstanceObject, compiled_module, kCompiledModule,
WasmCompiledModule)
DEFINE_OPTIONAL_ACCESSORS(WasmInstanceObject, globals_buffer,
kGlobalsArrayBuffer, JSArrayBuffer)
DEFINE_OPTIONAL_ACCESSORS(WasmInstanceObject, memory_buffer, kMemoryArrayBuffer,
JSArrayBuffer)
DEFINE_OPTIONAL_ACCESSORS(WasmInstanceObject, memory_object, kMemoryObject,
WasmMemoryObject)
DEFINE_OPTIONAL_ACCESSORS(WasmInstanceObject, debug_info, kDebugInfo,
WasmDebugInfo)
WasmModuleObject* WasmInstanceObject::module_object() {
return WasmModuleObject::cast(*get_compiled_module()->wasm_module());
}
WasmModule* WasmInstanceObject::module() {
return reinterpret_cast<WasmModuleWrapper*>(
*get_compiled_module()->module_wrapper())
->get();
}
WasmInstanceObject* WasmInstanceObject::cast(Object* object) {
DCHECK(IsWasmInstanceObject(object));
return reinterpret_cast<WasmInstanceObject*>(object);
}
bool WasmInstanceObject::IsWasmInstanceObject(Object* object) {
if (!object->IsObject()) return false;
if (!object->IsJSObject()) return false;
JSObject* obj = JSObject::cast(object);
Isolate* isolate = obj->GetIsolate();
if (obj->GetInternalFieldCount() != kFieldCount) {
return false;
}
Object* mem = obj->GetInternalField(kMemoryArrayBuffer);
if (!(mem->IsUndefined(isolate) || mem->IsJSArrayBuffer()) ||
!WasmCompiledModule::IsWasmCompiledModule(
obj->GetInternalField(kCompiledModule))) {
return false;
}
// All checks passed.
return true;
}
Handle<WasmInstanceObject> WasmInstanceObject::New(
Isolate* isolate, Handle<WasmCompiledModule> compiled_module) {
Handle<Map> map = isolate->factory()->NewMap(
JS_OBJECT_TYPE, JSObject::kHeaderSize + kFieldCount * kPointerSize);
Handle<WasmInstanceObject> instance(
reinterpret_cast<WasmInstanceObject*>(
*isolate->factory()->NewJSObjectFromMap(map, TENURED)),
isolate);
instance->SetInternalField(kCompiledModule, *compiled_module);
instance->SetInternalField(kMemoryObject, isolate->heap()->undefined_value());
return instance;
}
WasmInstanceObject* WasmExportedFunction::instance() {
return WasmInstanceObject::cast(GetInternalField(kInstance));
}
int WasmExportedFunction::function_index() {
return SafeInt32(GetInternalField(kIndex));
}
WasmExportedFunction* WasmExportedFunction::cast(Object* object) {
DCHECK(object && object->IsJSFunction());
DCHECK_EQ(Code::JS_TO_WASM_FUNCTION,
JSFunction::cast(object)->code()->kind());
// TODO(titzer): brand check for WasmExportedFunction.
return reinterpret_cast<WasmExportedFunction*>(object);
}
Handle<WasmExportedFunction> WasmExportedFunction::New(
Isolate* isolate, Handle<WasmInstanceObject> instance, Handle<String> name,
Handle<Code> export_wrapper, int arity, int func_index) {
DCHECK_EQ(Code::JS_TO_WASM_FUNCTION, export_wrapper->kind());
Handle<SharedFunctionInfo> shared =
isolate->factory()->NewSharedFunctionInfo(name, export_wrapper, false);
shared->set_length(arity);
shared->set_internal_formal_parameter_count(arity);
Handle<JSFunction> function = isolate->factory()->NewFunction(
isolate->wasm_function_map(), name, export_wrapper);
function->set_shared(*shared);
function->SetInternalField(kInstance, *instance);
function->SetInternalField(kIndex, Smi::FromInt(func_index));
return Handle<WasmExportedFunction>::cast(function);
}
Handle<WasmCompiledModule> WasmCompiledModule::New(
Isolate* isolate, Handle<WasmModuleWrapper> module_wrapper) {
Handle<FixedArray> ret =
isolate->factory()->NewFixedArray(PropertyIndices::Count, TENURED);
// WasmCompiledModule::cast would fail since module bytes are not set yet.
Handle<WasmCompiledModule> compiled_module(
reinterpret_cast<WasmCompiledModule*>(*ret), isolate);
compiled_module->InitId();
compiled_module->set_module_wrapper(module_wrapper);
return compiled_module;
}
wasm::WasmModule* WasmCompiledModule::module() const {
return reinterpret_cast<WasmModuleWrapper*>(*module_wrapper())->get();
}
void WasmCompiledModule::InitId() {
#if DEBUG
static uint32_t instance_id_counter = 0;
set(kID_instance_id, Smi::FromInt(instance_id_counter++));
TRACE("New compiled module id: %d\n", instance_id());
#endif
}
bool WasmCompiledModule::IsWasmCompiledModule(Object* obj) {
if (!obj->IsFixedArray()) return false;
FixedArray* arr = FixedArray::cast(obj);
if (arr->length() != PropertyIndices::Count) return false;
Isolate* isolate = arr->GetIsolate();
#define WCM_CHECK_SMALL_NUMBER(TYPE, NAME) \
if (!arr->get(kID_##NAME)->IsSmi()) return false;
#define WCM_CHECK_OBJECT_OR_WEAK(TYPE, NAME) \
if (!arr->get(kID_##NAME)->IsUndefined(isolate) && \
!arr->get(kID_##NAME)->Is##TYPE()) \
return false;
#define WCM_CHECK_OBJECT(TYPE, NAME) WCM_CHECK_OBJECT_OR_WEAK(TYPE, NAME)
#define WCM_CHECK_WEAK_LINK(TYPE, NAME) WCM_CHECK_OBJECT_OR_WEAK(WeakCell, NAME)
#define WCM_CHECK(KIND, TYPE, NAME) WCM_CHECK_##KIND(TYPE, NAME)
WCM_PROPERTY_TABLE(WCM_CHECK)
#undef WCM_CHECK
// All checks passed.
return true;
}
void WasmCompiledModule::PrintInstancesChain() {
#if DEBUG
if (!FLAG_trace_wasm_instances) return;
for (WasmCompiledModule* current = this; current != nullptr;) {
PrintF("->%d", current->instance_id());
if (current->ptr_to_weak_next_instance() == nullptr) break;
CHECK(!current->ptr_to_weak_next_instance()->cleared());
current =
WasmCompiledModule::cast(current->ptr_to_weak_next_instance()->value());
}
PrintF("\n");
#endif
}
uint32_t WasmCompiledModule::mem_size() const {
return has_memory() ? memory()->byte_length()->Number() : default_mem_size();
}
uint32_t WasmCompiledModule::default_mem_size() const {
return min_mem_pages() * WasmModule::kPageSize;
}

300
src/wasm/wasm-objects.h Normal file
View File

@ -0,0 +1,300 @@
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_WASM_OBJECTS_H_
#define V8_WASM_OBJECTS_H_
#include "src/objects-inl.h"
#include "src/wasm/managed.h"
namespace v8 {
namespace internal {
namespace wasm {
struct WasmModule;
}
class WasmCompiledModule;
class WasmDebugInfo;
class WasmInstanceObject;
#define DECLARE_CASTS(name) \
static bool Is##name(Object* object); \
static name* cast(Object* object)
#define DECLARE_ACCESSORS(name, type) \
type* get_##name(); \
void set_##name(type* value)
#define DECLARE_OPTIONAL_ACCESSORS(name, type) \
bool has_##name(); \
type* get_##name(); \
void set_##name(type* value)
// Representation of a WebAssembly.Module JavaScript-level object.
class WasmModuleObject : public JSObject {
public:
// TODO(titzer): add the brand as an internal field instead of a property.
enum Fields { kCompiledModule, kFieldCount };
DECLARE_CASTS(WasmModuleObject);
WasmCompiledModule* compiled_module();
wasm::WasmModule* module();
int num_functions();
bool is_asm_js();
int GetAsmWasmSourcePosition(int func_index, int byte_offset);
WasmDebugInfo* debug_info();
void set_debug_info(WasmDebugInfo* debug_info);
MaybeHandle<String> GetFunctionName(Isolate* isolate, int func_index);
static Handle<WasmModuleObject> New(
Isolate* isolate, Handle<WasmCompiledModule> compiled_module);
};
// Representation of a WebAssembly.Table JavaScript-level object.
class WasmTableObject : public JSObject {
public:
// TODO(titzer): add the brand as an internal field instead of a property.
enum Fields { kFunctions, kMaximum, kDispatchTables, kFieldCount };
DECLARE_CASTS(WasmTableObject);
DECLARE_ACCESSORS(functions, FixedArray);
FixedArray* get_dispatch_tables();
uint32_t current_length();
uint32_t maximum_length();
static Handle<WasmTableObject> New(Isolate* isolate, uint32_t initial,
uint32_t maximum,
Handle<FixedArray>* js_functions);
static bool Grow(Handle<WasmTableObject> table, uint32_t count);
static Handle<FixedArray> AddDispatchTable(
Isolate* isolate, Handle<WasmTableObject> table,
Handle<WasmInstanceObject> instance, int table_index,
Handle<FixedArray> dispatch_table);
};
// Representation of a WebAssembly.Memory JavaScript-level object.
class WasmMemoryObject : public JSObject {
public:
// TODO(titzer): add the brand as an internal field instead of a property.
enum Fields : uint8_t { kArrayBuffer, kMaximum, kInstance, kFieldCount };
DECLARE_CASTS(WasmMemoryObject);
DECLARE_ACCESSORS(buffer, JSArrayBuffer);
void AddInstance(WasmInstanceObject* object);
uint32_t current_pages();
int32_t maximum_pages(); // returns < 0 if there is no maximum
static Handle<WasmMemoryObject> New(Isolate* isolate,
Handle<JSArrayBuffer> buffer,
int maximum);
static bool Grow(Handle<WasmMemoryObject> memory, uint32_t count);
};
// Representation of a WebAssembly.Instance JavaScript-level object.
class WasmInstanceObject : public JSObject {
public:
// TODO(titzer): add the brand as an internal field instead of a property.
enum Fields {
kCompiledModule,
kMemoryObject,
kMemoryArrayBuffer,
kGlobalsArrayBuffer,
kDebugInfo,
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);
WasmModuleObject* module_object();
wasm::WasmModule* module();
static Handle<WasmInstanceObject> New(
Isolate* isolate, Handle<WasmCompiledModule> compiled_module);
};
// Representation of an exported WASM function.
class WasmExportedFunction : public JSFunction {
public:
enum Fields { kInstance, kIndex, kFieldCount };
DECLARE_CASTS(WasmExportedFunction);
WasmInstanceObject* instance();
int function_index();
static Handle<WasmExportedFunction> New(Isolate* isolate,
Handle<WasmInstanceObject> instance,
Handle<String> name,
Handle<Code> export_wrapper,
int arity, int func_index);
};
class WasmCompiledModule : public FixedArray {
public:
enum Fields { kFieldCount };
static WasmCompiledModule* cast(Object* fixed_array) {
SLOW_DCHECK(IsWasmCompiledModule(fixed_array));
return reinterpret_cast<WasmCompiledModule*>(fixed_array);
}
#define WCM_OBJECT_OR_WEAK(TYPE, NAME, ID) \
Handle<TYPE> NAME() const { return handle(ptr_to_##NAME()); } \
\
MaybeHandle<TYPE> maybe_##NAME() const { \
if (has_##NAME()) return NAME(); \
return MaybeHandle<TYPE>(); \
} \
\
TYPE* ptr_to_##NAME() const { \
Object* obj = get(ID); \
if (!obj->Is##TYPE()) return nullptr; \
return TYPE::cast(obj); \
} \
\
void set_##NAME(Handle<TYPE> value) { set_ptr_to_##NAME(*value); } \
\
void set_ptr_to_##NAME(TYPE* value) { set(ID, value); } \
\
bool has_##NAME() const { return get(ID)->Is##TYPE(); } \
\
void reset_##NAME() { set_undefined(ID); }
#define WCM_OBJECT(TYPE, NAME) WCM_OBJECT_OR_WEAK(TYPE, NAME, kID_##NAME)
#define WCM_SMALL_NUMBER(TYPE, NAME) \
TYPE NAME() const { \
return static_cast<TYPE>(Smi::cast(get(kID_##NAME))->value()); \
} \
void set_##NAME(TYPE value) { set(kID_##NAME, Smi::FromInt(value)); }
#define WCM_WEAK_LINK(TYPE, NAME) \
WCM_OBJECT_OR_WEAK(WeakCell, weak_##NAME, kID_##NAME); \
\
Handle<TYPE> NAME() const { \
return handle(TYPE::cast(weak_##NAME()->value())); \
}
#define CORE_WCM_PROPERTY_TABLE(MACRO) \
MACRO(OBJECT, FixedArray, code_table) \
MACRO(OBJECT, Foreign, module_wrapper) \
MACRO(OBJECT, SeqOneByteString, module_bytes) \
MACRO(OBJECT, Script, asm_js_script) \
MACRO(OBJECT, FixedArray, function_tables) \
MACRO(OBJECT, FixedArray, empty_function_tables) \
MACRO(OBJECT, ByteArray, asm_js_offset_tables) \
MACRO(OBJECT, JSArrayBuffer, memory) \
MACRO(SMALL_NUMBER, uint32_t, min_mem_pages) \
MACRO(SMALL_NUMBER, uint32_t, max_mem_pages) \
MACRO(WEAK_LINK, WasmCompiledModule, next_instance) \
MACRO(WEAK_LINK, WasmCompiledModule, prev_instance) \
MACRO(WEAK_LINK, JSObject, owning_instance) \
MACRO(WEAK_LINK, JSObject, wasm_module)
#if DEBUG
#define DEBUG_ONLY_TABLE(MACRO) MACRO(SMALL_NUMBER, uint32_t, instance_id)
#else
#define DEBUG_ONLY_TABLE(IGNORE)
uint32_t instance_id() const { return -1; }
#endif
#define WCM_PROPERTY_TABLE(MACRO) \
CORE_WCM_PROPERTY_TABLE(MACRO) \
DEBUG_ONLY_TABLE(MACRO)
private:
enum PropertyIndices {
#define INDICES(IGNORE1, IGNORE2, NAME) kID_##NAME,
WCM_PROPERTY_TABLE(INDICES) Count
#undef INDICES
};
public:
static Handle<WasmCompiledModule> New(
Isolate* isolate, Handle<Managed<wasm::WasmModule>> module_wrapper);
static Handle<WasmCompiledModule> Clone(Isolate* isolate,
Handle<WasmCompiledModule> module) {
Handle<WasmCompiledModule> ret = Handle<WasmCompiledModule>::cast(
isolate->factory()->CopyFixedArray(module));
ret->InitId();
ret->reset_weak_owning_instance();
ret->reset_weak_next_instance();
ret->reset_weak_prev_instance();
return ret;
}
uint32_t mem_size() const;
uint32_t default_mem_size() const;
wasm::WasmModule* module() const;
#define DECLARATION(KIND, TYPE, NAME) WCM_##KIND(TYPE, NAME)
WCM_PROPERTY_TABLE(DECLARATION)
#undef DECLARATION
static bool IsWasmCompiledModule(Object* obj);
void PrintInstancesChain();
static void RecreateModuleWrapper(Isolate* isolate,
Handle<FixedArray> compiled_module);
private:
void InitId();
DISALLOW_IMPLICIT_CONSTRUCTORS(WasmCompiledModule);
};
class WasmDebugInfo : public FixedArray {
public:
enum class Fields { kFieldCount };
static Handle<WasmDebugInfo> New(Handle<JSObject> wasm);
static bool IsDebugInfo(Object* object);
static WasmDebugInfo* cast(Object* object);
JSObject* wasm_instance();
bool SetBreakPoint(int byte_offset);
// Get the Script for the specified function.
static Script* GetFunctionScript(Handle<WasmDebugInfo> debug_info,
int func_index);
// Disassemble the specified function from this module.
static Handle<String> DisassembleFunction(Handle<WasmDebugInfo> debug_info,
int func_index);
// Get the offset table for the specified function, mapping from byte offsets
// to position in the disassembly.
// Returns an array with three entries per instruction: byte offset, line and
// column.
static Handle<FixedArray> GetFunctionOffsetTable(
Handle<WasmDebugInfo> debug_info, int func_index);
// Get the asm.js source position from a byte offset.
// Must only be called if the associated wasm object was created from asm.js.
static int GetAsmJsSourcePosition(Handle<WasmDebugInfo> debug_info,
int func_index, int byte_offset);
};
#undef DECLARE_ACCESSORS
#undef DECLARE_OPTIONAL_ACCESSORS
} // namespace internal
} // namespace v8
#endif // V8_WASM_OBJECTS_H_

View File

@ -11,6 +11,7 @@
#include "src/wasm/wasm-macro-gen.h"
#include "src/wasm/wasm-module-builder.h"
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-objects.h"
#include "src/wasm/wasm-opcodes.h"
#include "test/cctest/cctest.h"
@ -317,9 +318,8 @@ class WasmSerializationTest {
decoding_result.val->CompileFunctions(serialization_isolate,
module_wrapper, &thrower);
CHECK(!compiled_module.is_null());
Handle<JSObject> module_obj = CreateWasmModuleObject(
serialization_isolate, compiled_module.ToHandleChecked(),
ModuleOrigin::kWasmOrigin);
Handle<JSObject> module_obj = WasmModuleObject::New(
serialization_isolate, compiled_module.ToHandleChecked());
v8::Local<v8::Object> v8_module_obj = v8::Utils::ToLocal(module_obj);
CHECK(v8_module_obj->IsWebAssemblyCompiledModule());

View File

@ -25,6 +25,7 @@
#include "src/wasm/wasm-js.h"
#include "src/wasm/wasm-macro-gen.h"
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-objects.h"
#include "src/wasm/wasm-opcodes.h"
#include "src/zone/zone.h"
@ -206,14 +207,15 @@ class TestingModule : public ModuleEnv {
Handle<JSFunction> WrapCode(uint32_t index) {
// Wrap the code so it can be called as a JS function.
Handle<String> name = isolate_->factory()->NewStringFromStaticChars("main");
Handle<JSObject> module_object = Handle<JSObject>(0, isolate_);
Handle<WasmInstanceObject> instance_obj(0, isolate_);
Handle<Code> code = instance->function_code[index];
WasmJs::InstallWasmMapsIfNeeded(isolate_, isolate_->native_context());
Handle<Code> ret_code =
compiler::CompileJSToWasmWrapper(isolate_, this, code, index);
Handle<JSFunction> ret = WrapExportCodeAsJSFunction(
isolate_, ret_code, name, this->module->functions[index].sig,
static_cast<int>(index), module_object);
Handle<JSFunction> ret = WasmExportedFunction::New(
isolate_, instance_obj, name, ret_code,
static_cast<int>(this->module->functions[index].sig->parameter_count()),
static_cast<int>(index));
return ret;
}

View File

@ -12,6 +12,7 @@
#include "src/wasm/wasm-interpreter.h"
#include "src/wasm/wasm-js.h"
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-objects.h"
#include "src/wasm/wasm-result.h"
namespace v8 {
@ -60,7 +61,7 @@ const Handle<JSObject> InstantiateModuleForTesting(Isolate* isolate,
// Although we decoded the module for some pre-validation, run the bytes
// again through the normal pipeline.
// TODO(wasm): Use {module} instead of decoding the module bytes again.
MaybeHandle<JSObject> module_object = CreateModuleObjectFromBytes(
MaybeHandle<WasmModuleObject> module_object = CreateModuleObjectFromBytes(
isolate, module->module_start, module->module_end, thrower,
ModuleOrigin::kWasmOrigin, Handle<Script>::null(), nullptr, nullptr);
if (module_object.is_null()) {