Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(283)

Unified Diff: src/wasm/wasm-module.cc

Issue 1912103002: [wasm] Store function names in the wasm object (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@wasm-offset-table-2
Patch Set: fix gcmole and signed/unsigned comparison issue Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« src/objects-inl.h ('K') | « src/wasm/wasm-module.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/wasm/wasm-module.cc
diff --git a/src/wasm/wasm-module.cc b/src/wasm/wasm-module.cc
index e15b8d1f55318c7dcc8a51ad1746c06b4b8c3fc6..a2df5ee3df3f88d573bfd3554292e86e985bf7cc 100644
--- a/src/wasm/wasm-module.cc
+++ b/src/wasm/wasm-module.cc
@@ -200,11 +200,12 @@ class WasmLinker {
namespace {
// Internal constants for the layout of the module object.
-const int kWasmModuleInternalFieldCount = 4;
+const int kWasmModuleInternalFieldCount = 5;
const int kWasmModuleFunctionTable = 0;
const int kWasmModuleCodeTable = 1;
const int kWasmMemArrayBuffer = 2;
const int kWasmGlobalsArrayBuffer = 3;
+const int kWasmFunctionNamesArray = 4;
size_t AllocateGlobalsOffsets(std::vector<WasmGlobal>& globals) {
uint32_t offset = 0;
@@ -246,6 +247,57 @@ Handle<FixedArray> BuildFunctionTable(Isolate* isolate, WasmModule* module) {
return fixed;
}
+// Build an array with all function names. If there are N functions in the
+// module, then the first (kIntSize * (N+1)) bytes are integer entries.
+// The first integer entry encodes the number of functions in the module.
+// The entries 1 to N contain offsets into the seconds part of this array.
titzer 2016/04/22 13:21:08 s/seconds/second/
+// After these N+1 integer entries, the second part begins, which holds a
+// concatenation of all function names. If a function is unnamed (not to be
+// confused with an empty name), then the corresponding integer entry contains
+// the negative distance to the next entry with a name. It points behind the
+// last integer entry if there are no more entries with names.
+// This allows to easily determine for each function the start of the next
+// function name, and hence the length of the function name.
+Handle<Object> BuildFunctionNamesArray(Isolate* isolate, WasmModule* module) {
titzer 2016/04/22 13:21:08 Can we factor out the encoding and decoding logic
Clemens Hammacher 2016/04/22 14:38:40 OK, will work on that on Monday and then update th
+ uint64_t func_names_length = 0;
+ for (auto& func : module->functions) func_names_length += func.name_length;
+ int num_funcs_int = static_cast<int>(module->functions.size());
+ int current_offset = (num_funcs_int + 1) * kIntSize;
+ uint64_t total_array_length = current_offset + func_names_length;
+ int total_array_length_int = static_cast<int>(total_array_length);
+ // Check for overflow. Just skip function names if it happens.
+ if (total_array_length_int != total_array_length || num_funcs_int < 0 ||
+ num_funcs_int != module->functions.size())
+ return isolate->factory()->undefined_value();
+ Handle<ByteArray> func_names_arr =
+ isolate->factory()->NewByteArray(total_array_length_int, TENURED);
+ func_names_arr->set_int(0, num_funcs_int);
+ for (int func_index = 0; func_index != num_funcs_int; ++func_index) {
titzer 2016/04/22 13:21:08 Would prefer a C++ foreach-loop with a separate in
Clemens Hammacher 2016/04/22 14:38:40 C++ foreach does not work, since we increase func_
+ WasmName name = module->GetNameOrNull(&module->functions[func_index]);
+ if (name.name == nullptr) {
+ // Find next function with a name, and store the negative distance to that
+ // function. On the way, we also set all the entries inbetween.
+ int next_func_with_name = func_index + 1;
+ while (
+ next_func_with_name != num_funcs_int &&
+ module->GetNameOrNull(&module->functions[next_func_with_name]).name ==
+ nullptr)
+ ++next_func_with_name;
+ for (; func_index < next_func_with_name; ++func_index)
+ func_names_arr->set_int(func_index + 1,
+ func_index - next_func_with_name);
+ --func_index;
+ } else {
+ func_names_arr->set(current_offset,
+ reinterpret_cast<const byte*>(name.name),
+ name.length);
+ func_names_arr->set_int(func_index + 1, current_offset);
+ current_offset += name.length;
+ }
+ }
+ return func_names_arr;
+}
+
Handle<JSArrayBuffer> NewArrayBuffer(Isolate* isolate, size_t size,
byte** backing_store) {
if (size > (WasmModule::kMaxMemPages * WasmModule::kPageSize)) {
@@ -415,7 +467,7 @@ MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate,
// Allocate the instance and its JS counterpart.
//-------------------------------------------------------------------------
Handle<Map> map = factory->NewMap(
- JS_OBJECT_TYPE,
+ JS_WASM_TYPE,
JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize);
WasmModuleInstance instance(this);
instance.context = isolate->native_context();
@@ -582,6 +634,15 @@ MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate,
}
}
+ //-------------------------------------------------------------------------
+ // Attach an array with function names and an array with offsets into that
+ // first array.
+ //-------------------------------------------------------------------------
+ {
+ Handle<Object> arr = BuildFunctionNamesArray(isolate, module_env.module);
+ instance.js_object->SetInternalField(kWasmFunctionNamesArray, *arr);
+ }
+
// Run the start function if one was specified.
if (this->start_function_index >= 0) {
HandleScope scope(isolate);
@@ -732,6 +793,42 @@ int32_t CompileAndRunWasmModule(Isolate* isolate, WasmModule* module) {
thrower.Error("WASM.compileRun() failed: Return value should be number");
return -1;
}
+
+Handle<Object> GetWasmFunctionName(Handle<JSObject> wasm, uint32_t func_index) {
+ DCHECK(wasm->map()->instance_type() == JS_WASM_TYPE);
+ Handle<Object> func_names_arr_obj = handle(
+ wasm->GetInternalField(kWasmFunctionNamesArray), wasm->GetIsolate());
+ if (func_names_arr_obj->IsUndefined())
+ return func_names_arr_obj; // Return undefined.
+ Handle<ByteArray> func_names_arr =
+ Handle<ByteArray>::cast(func_names_arr_obj);
+ uint32_t num_funcs = static_cast<uint32_t>(func_names_arr->get_int(0));
+ DCHECK(static_cast<int>(num_funcs) >= 0);
+ if (func_index >= num_funcs)
+ return wasm->GetIsolate()->factory()->undefined_value();
+ int offset = func_names_arr->get_int(func_index + 1);
+ if (offset < 0) return wasm->GetIsolate()->factory()->undefined_value();
+ int next_offset = func_index == num_funcs - 1
+ ? func_names_arr->length()
+ : func_names_arr->get_int(func_index + 2);
+ if (next_offset < 0) {
+ uint32_t next_func_index = func_index + 1 - next_offset;
+ next_offset = next_func_index == num_funcs
+ ? func_names_arr->length()
+ : func_names_arr->get_int(next_func_index + 1);
+ }
+ DCHECK(next_offset >= 0 && next_offset <= func_names_arr->length());
+ DCHECK(next_offset >= offset);
+ ScopedVector<byte> buffer(next_offset - offset);
+ func_names_arr->get(offset, buffer.start(), next_offset - offset);
+ MaybeHandle<Object> maybe_name =
+ wasm->GetIsolate()->factory()->NewStringFromUtf8(
+ Vector<const char>::cast(buffer));
+ if (maybe_name.is_null())
+ return wasm->GetIsolate()->factory()->undefined_value();
+ return maybe_name.ToHandleChecked();
+}
+
} // namespace wasm
} // namespace internal
} // namespace v8
« src/objects-inl.h ('K') | « src/wasm/wasm-module.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698