Commit 759baaff authored by clemensh's avatar clemensh Committed by Commit bot

[wasm] Refactor function name table and lookup

The function name table will now always be set; a CHECK will fail if
the length would exceed the integer range.
Also, the resolution of undefined function names to "<WASM UNNAMED>" is
moved over to the wasm side.

R=titzer@chromium.org

Committed: https://crrev.com/3400ee9f4f21a455b7850ec42a4182a3c0eba310
Review-Url: https://codereview.chromium.org/2057523002
Cr-Original-Commit-Position: refs/heads/master@{#36918}
Cr-Commit-Position: refs/heads/master@{#36952}
parent 56a9df6b
...@@ -605,16 +605,9 @@ class CaptureStackTraceHelper { ...@@ -605,16 +605,9 @@ class CaptureStackTraceHelper {
factory()->NewJSObject(isolate_->object_function()); factory()->NewJSObject(isolate_->object_function());
if (!function_key_.is_null()) { if (!function_key_.is_null()) {
Object* wasm_object = frame->wasm_obj(); Handle<String> name = wasm::GetWasmFunctionName(
Handle<String> name; isolate_, handle(frame->wasm_obj(), isolate_),
if (!wasm_object->IsUndefined(isolate_)) { frame->function_index());
Handle<JSObject> wasm = handle(JSObject::cast(wasm_object));
wasm::GetWasmFunctionName(wasm, frame->function_index())
.ToHandle(&name);
}
if (name.is_null()) {
name = isolate_->factory()->NewStringFromStaticChars("<WASM UNNAMED>");
}
JSObject::AddProperty(stack_frame, function_key_, name, NONE); JSObject::AddProperty(stack_frame, function_key_, name, NONE);
} }
// Encode the function index as line number. // Encode the function index as line number.
......
...@@ -205,10 +205,8 @@ Handle<Object> CallSite::GetFileName() { ...@@ -205,10 +205,8 @@ Handle<Object> CallSite::GetFileName() {
Handle<Object> CallSite::GetFunctionName() { Handle<Object> CallSite::GetFunctionName() {
if (IsWasm()) { if (IsWasm()) {
MaybeHandle<String> name = return wasm::GetWasmFunctionNameOrNull(isolate_, wasm_obj_,
wasm::GetWasmFunctionName(wasm_obj_, wasm_func_index_); wasm_func_index_);
if (name.is_null()) return isolate_->factory()->null_value();
return name.ToHandleChecked();
} }
Handle<String> result = JSFunction::GetName(fun_); Handle<String> result = JSFunction::GetName(fun_);
if (result->length() != 0) return result; if (result->length() != 0) return result;
......
...@@ -18,23 +18,19 @@ namespace wasm { ...@@ -18,23 +18,19 @@ namespace wasm {
// integer entry is the negative offset of the next function name. // integer entry is the negative offset of the next function name.
// After these N+1 integer entries, the second part begins, which holds a // After these N+1 integer entries, the second part begins, which holds a
// concatenation of all function names. // concatenation of all function names.
// Handle<ByteArray> BuildFunctionNamesTable(Isolate* isolate,
// Returns undefined if the array length would not fit in an integer value. const WasmModule* module) {
Handle<Object> BuildFunctionNamesTable(Isolate* isolate,
const WasmModule* module) {
uint64_t func_names_length = 0; uint64_t func_names_length = 0;
for (auto& func : module->functions) func_names_length += func.name_length; for (auto& func : module->functions) func_names_length += func.name_length;
int num_funcs_int = static_cast<int>(module->functions.size()); int num_funcs_int = static_cast<int>(module->functions.size());
int current_offset = (num_funcs_int + 1) * kIntSize; int current_offset = (num_funcs_int + 1) * kIntSize;
uint64_t total_array_length = current_offset + func_names_length; uint64_t total_array_length = current_offset + func_names_length;
int total_array_length_int = static_cast<int>(total_array_length); int total_array_length_int = static_cast<int>(total_array_length);
// Check for overflow. Just skip function names if it happens. // Check for overflow.
if (total_array_length_int != total_array_length || num_funcs_int < 0 || CHECK(total_array_length_int == total_array_length && num_funcs_int >= 0 &&
num_funcs_int != module->functions.size()) num_funcs_int == module->functions.size());
return isolate->factory()->undefined_value();
Handle<ByteArray> func_names_array = Handle<ByteArray> func_names_array =
isolate->factory()->NewByteArray(total_array_length_int, TENURED); isolate->factory()->NewByteArray(total_array_length_int, TENURED);
if (func_names_array.is_null()) return isolate->factory()->undefined_value();
func_names_array->set_int(0, num_funcs_int); func_names_array->set_int(0, num_funcs_int);
int func_index = 0; int func_index = 0;
for (const WasmFunction& fun : module->functions) { for (const WasmFunction& fun : module->functions) {
......
...@@ -16,9 +16,8 @@ namespace wasm { ...@@ -16,9 +16,8 @@ namespace wasm {
struct WasmModule; struct WasmModule;
// Encode all function names of the WasmModule into one ByteArray. // Encode all function names of the WasmModule into one ByteArray.
// Returns undefined if the array length would not fit in an integer value. Handle<ByteArray> BuildFunctionNamesTable(Isolate* isolate,
Handle<Object> BuildFunctionNamesTable(Isolate* isolate, const WasmModule* module);
const WasmModule* module);
// Extract the function name for the given func_index from the function name // Extract the function name for the given func_index from the function name
// table. // table.
......
...@@ -834,13 +834,12 @@ MaybeHandle<JSObject> WasmModule::Instantiate( ...@@ -834,13 +834,12 @@ MaybeHandle<JSObject> WasmModule::Instantiate(
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// Attach an array with function names and an array with offsets into that // Attach the function name table.
// first array.
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
{ Handle<ByteArray> function_name_table =
Handle<Object> arr = BuildFunctionNamesTable(isolate, module_env.module); BuildFunctionNamesTable(isolate, module_env.module);
instance.js_object->SetInternalField(kWasmFunctionNamesArray, *arr); instance.js_object->SetInternalField(kWasmFunctionNamesArray,
} *function_name_table);
code_stats.Report(); code_stats.Report();
...@@ -983,14 +982,30 @@ int32_t CompileAndRunWasmModule(Isolate* isolate, const WasmModule* module) { ...@@ -983,14 +982,30 @@ int32_t CompileAndRunWasmModule(Isolate* isolate, const WasmModule* module) {
return -1; return -1;
} }
MaybeHandle<String> GetWasmFunctionName(Handle<JSObject> wasm, Handle<Object> GetWasmFunctionNameOrNull(Isolate* isolate, Handle<Object> wasm,
uint32_t func_index) { uint32_t func_index) {
DCHECK(IsWasmObject(wasm)); if (!wasm->IsUndefined()) {
Object* func_names_arr_obj = wasm->GetInternalField(kWasmFunctionNamesArray); Handle<ByteArray> func_names_arr_obj(
Isolate* isolate = wasm->GetIsolate(); ByteArray::cast(Handle<JSObject>::cast(wasm)->GetInternalField(
if (func_names_arr_obj->IsUndefined(isolate)) return Handle<String>::null(); kWasmFunctionNamesArray)),
return GetWasmFunctionNameFromTable( isolate);
handle(ByteArray::cast(func_names_arr_obj), isolate), func_index); // TODO(clemens): Extract this from the module bytes; skip whole function
// name table.
Handle<Object> name;
if (GetWasmFunctionNameFromTable(func_names_arr_obj, func_index)
.ToHandle(&name)) {
return name;
}
}
return isolate->factory()->null_value();
}
Handle<String> GetWasmFunctionName(Isolate* isolate, Handle<Object> wasm,
uint32_t func_index) {
Handle<Object> name_or_null =
GetWasmFunctionNameOrNull(isolate, wasm, func_index);
if (!name_or_null->IsNull()) return Handle<String>::cast(name_or_null);
return isolate->factory()->NewStringFromStaticChars("<WASM UNNAMED>");
} }
bool IsWasmObject(Handle<JSObject> object) { bool IsWasmObject(Handle<JSObject> object) {
...@@ -998,9 +1013,7 @@ bool IsWasmObject(Handle<JSObject> object) { ...@@ -998,9 +1013,7 @@ bool IsWasmObject(Handle<JSObject> object) {
return object->GetInternalFieldCount() == kWasmModuleInternalFieldCount && return object->GetInternalFieldCount() == kWasmModuleInternalFieldCount &&
object->GetInternalField(kWasmModuleCodeTable)->IsFixedArray() && object->GetInternalField(kWasmModuleCodeTable)->IsFixedArray() &&
object->GetInternalField(kWasmMemArrayBuffer)->IsJSArrayBuffer() && object->GetInternalField(kWasmMemArrayBuffer)->IsJSArrayBuffer() &&
(object->GetInternalField(kWasmFunctionNamesArray)->IsByteArray() || object->GetInternalField(kWasmFunctionNamesArray)->IsByteArray();
object->GetInternalField(kWasmFunctionNamesArray)
->IsUndefined(object->GetIsolate()));
} }
} // namespace wasm } // namespace wasm
......
...@@ -5,11 +5,10 @@ ...@@ -5,11 +5,10 @@
#ifndef V8_WASM_MODULE_H_ #ifndef V8_WASM_MODULE_H_
#define V8_WASM_MODULE_H_ #define V8_WASM_MODULE_H_
#include "src/wasm/wasm-opcodes.h"
#include "src/wasm/wasm-result.h"
#include "src/api.h" #include "src/api.h"
#include "src/handles.h" #include "src/handles.h"
#include "src/wasm/wasm-opcodes.h"
#include "src/wasm/wasm-result.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -318,11 +317,17 @@ int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start, ...@@ -318,11 +317,17 @@ int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start,
// given decoded module. // given decoded module.
int32_t CompileAndRunWasmModule(Isolate* isolate, const WasmModule* module); int32_t CompileAndRunWasmModule(Isolate* isolate, const WasmModule* module);
// 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.
Handle<String> GetWasmFunctionName(Isolate* isolate, Handle<Object> wasm,
uint32_t func_index);
// Extract a function name from the given wasm object. // Extract a function name from the given wasm object.
// Returns a null handle if the function is unnamed or the name is not a valid // Returns a null handle if the function is unnamed or the name is not a valid
// UTF-8 string. // UTF-8 string.
MaybeHandle<String> GetWasmFunctionName(Handle<JSObject> wasm, Handle<Object> GetWasmFunctionNameOrNull(Isolate* isolate, Handle<Object> wasm,
uint32_t func_index); uint32_t func_index);
// Check whether the given object is a wasm object. // Check whether the given object is a wasm object.
// This checks the number and type of internal fields, so it's not 100 percent // This checks the number and type of internal fields, so it's not 100 percent
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment