[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

Review-Url: https://codereview.chromium.org/2057523002
Cr-Commit-Position: refs/heads/master@{#36918}
This commit is contained in:
clemensh 2016-06-13 02:31:51 -07:00 committed by Commit bot
parent e95cfafb67
commit 3400ee9f4f
6 changed files with 50 additions and 46 deletions

View File

@ -605,16 +605,9 @@ class CaptureStackTraceHelper {
factory()->NewJSObject(isolate_->object_function());
if (!function_key_.is_null()) {
Object* wasm_object = frame->wasm_obj();
Handle<String> name;
if (!wasm_object->IsUndefined(isolate_)) {
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>");
}
Handle<String> name = wasm::GetWasmFunctionName(
isolate_, handle(frame->wasm_obj(), isolate_),
frame->function_index());
JSObject::AddProperty(stack_frame, function_key_, name, NONE);
}
// Encode the function index as line number.

View File

@ -205,10 +205,8 @@ Handle<Object> CallSite::GetFileName() {
Handle<Object> CallSite::GetFunctionName() {
if (IsWasm()) {
MaybeHandle<String> name =
wasm::GetWasmFunctionName(wasm_obj_, wasm_func_index_);
if (name.is_null()) return isolate_->factory()->null_value();
return name.ToHandleChecked();
return wasm::GetWasmFunctionNameOrNull(isolate_, wasm_obj_,
wasm_func_index_);
}
Handle<String> result = JSFunction::GetName(fun_);
if (result->length() != 0) return result;

View File

@ -18,23 +18,19 @@ namespace wasm {
// integer entry is the negative offset of the next function name.
// After these N+1 integer entries, the second part begins, which holds a
// concatenation of all function names.
//
// Returns undefined if the array length would not fit in an integer value.
Handle<Object> BuildFunctionNamesTable(Isolate* isolate,
const WasmModule* module) {
Handle<ByteArray> BuildFunctionNamesTable(Isolate* isolate,
const WasmModule* module) {
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();
// Check for overflow.
CHECK(total_array_length_int == total_array_length && num_funcs_int >= 0 &&
num_funcs_int == module->functions.size());
Handle<ByteArray> func_names_array =
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);
int func_index = 0;
for (const WasmFunction& fun : module->functions) {

View File

@ -16,9 +16,8 @@ namespace wasm {
struct WasmModule;
// Encode all function names of the WasmModule into one ByteArray.
// Returns undefined if the array length would not fit in an integer value.
Handle<Object> BuildFunctionNamesTable(Isolate* isolate,
const WasmModule* module);
Handle<ByteArray> BuildFunctionNamesTable(Isolate* isolate,
const WasmModule* module);
// Extract the function name for the given func_index from the function name
// table.

View File

@ -837,10 +837,9 @@ MaybeHandle<JSObject> WasmModule::Instantiate(
// Attach an array with function names and an array with offsets into that
// first array.
//-------------------------------------------------------------------------
{
Handle<Object> arr = BuildFunctionNamesTable(isolate, module_env.module);
instance.js_object->SetInternalField(kWasmFunctionNamesArray, *arr);
}
instance.js_object->SetInternalField(
kWasmFunctionNamesArray,
*BuildFunctionNamesTable(isolate, module_env.module));
code_stats.Report();
@ -983,14 +982,30 @@ int32_t CompileAndRunWasmModule(Isolate* isolate, const WasmModule* module) {
return -1;
}
MaybeHandle<String> GetWasmFunctionName(Handle<JSObject> wasm,
uint32_t func_index) {
DCHECK(IsWasmObject(wasm));
Object* func_names_arr_obj = wasm->GetInternalField(kWasmFunctionNamesArray);
Isolate* isolate = wasm->GetIsolate();
if (func_names_arr_obj->IsUndefined(isolate)) return Handle<String>::null();
return GetWasmFunctionNameFromTable(
handle(ByteArray::cast(func_names_arr_obj), isolate), func_index);
Handle<Object> GetWasmFunctionNameOrNull(Isolate* isolate, Handle<Object> wasm,
uint32_t func_index) {
if (!wasm->IsUndefined()) {
Handle<ByteArray> func_names_arr_obj(
ByteArray::cast(Handle<JSObject>::cast(wasm)->GetInternalField(
kWasmFunctionNamesArray)),
isolate);
// 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) {
@ -998,9 +1013,7 @@ bool IsWasmObject(Handle<JSObject> object) {
return object->GetInternalFieldCount() == kWasmModuleInternalFieldCount &&
object->GetInternalField(kWasmModuleCodeTable)->IsFixedArray() &&
object->GetInternalField(kWasmMemArrayBuffer)->IsJSArrayBuffer() &&
(object->GetInternalField(kWasmFunctionNamesArray)->IsByteArray() ||
object->GetInternalField(kWasmFunctionNamesArray)
->IsUndefined(object->GetIsolate()));
object->GetInternalField(kWasmFunctionNamesArray)->IsByteArray();
}
} // namespace wasm

View File

@ -5,11 +5,10 @@
#ifndef 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/handles.h"
#include "src/wasm/wasm-opcodes.h"
#include "src/wasm/wasm-result.h"
namespace v8 {
namespace internal {
@ -318,11 +317,17 @@ int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start,
// given decoded 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.
// Returns a null handle if the function is unnamed or the name is not a valid
// UTF-8 string.
MaybeHandle<String> GetWasmFunctionName(Handle<JSObject> wasm,
uint32_t func_index);
Handle<Object> GetWasmFunctionNameOrNull(Isolate* isolate, Handle<Object> wasm,
uint32_t func_index);
// Check whether the given object is a wasm object.
// This checks the number and type of internal fields, so it's not 100 percent