[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:
parent
fc97c638fa
commit
fa9c25cebf
3
BUILD.gn
3
BUILD.gn
@ -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",
|
||||
|
17
src/api.cc
17
src/api.cc
@ -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(
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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',
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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_
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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
359
src/wasm/wasm-objects.cc
Normal 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
300
src/wasm/wasm-objects.h
Normal 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_
|
@ -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());
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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()) {
|
||||
|
Loading…
Reference in New Issue
Block a user