Commit 0c22df65 authored by titzer's avatar titzer Committed by Commit Bot

[wasm] Allow full u32 range for table maximum in WebAssembly.Table constructor.

R=clemensh@chromium.org
BUG=chromium:740199

Review-Url: https://codereview.chromium.org/2977543002
Cr-Commit-Position: refs/heads/master@{#46508}
parent b14de85d
...@@ -1340,7 +1340,7 @@ int InstanceBuilder::ProcessImports(Handle<FixedArray> code_table, ...@@ -1340,7 +1340,7 @@ int InstanceBuilder::ProcessImports(Handle<FixedArray> code_table,
if (table.has_max) { if (table.has_max) {
int64_t imported_max_size = int64_t imported_max_size =
table_instance.table_object->maximum_length(); table_instance.table_object->maximum_length()->Number();
if (imported_max_size < 0) { if (imported_max_size < 0) {
thrower_->LinkError( thrower_->LinkError(
"table import %d has no maximum length, expected %d", index, "table import %d has no maximum length, expected %d", index,
......
...@@ -472,7 +472,7 @@ void WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) { ...@@ -472,7 +472,7 @@ void WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) {
bool GetIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower, bool GetIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower,
Local<Context> context, Local<v8::Object> object, Local<Context> context, Local<v8::Object> object,
Local<String> property, int* result, Local<String> property, int64_t* result,
int64_t lower_bound, uint64_t upper_bound) { int64_t lower_bound, uint64_t upper_bound) {
v8::MaybeLocal<v8::Value> maybe = object->Get(context, property); v8::MaybeLocal<v8::Value> maybe = object->Get(context, property);
v8::Local<v8::Value> value; v8::Local<v8::Value> value;
...@@ -525,14 +525,14 @@ void WebAssemblyTable(const v8::FunctionCallbackInfo<v8::Value>& args) { ...@@ -525,14 +525,14 @@ void WebAssemblyTable(const v8::FunctionCallbackInfo<v8::Value>& args) {
} }
} }
// The descriptor's 'initial'. // The descriptor's 'initial'.
int initial = 0; int64_t initial = 0;
if (!GetIntegerProperty(isolate, &thrower, context, descriptor, if (!GetIntegerProperty(isolate, &thrower, context, descriptor,
v8_str(isolate, "initial"), &initial, 0, v8_str(isolate, "initial"), &initial, 0,
i::FLAG_wasm_max_table_size)) { i::FLAG_wasm_max_table_size)) {
return; return;
} }
// The descriptor's 'maximum'. // The descriptor's 'maximum'.
int maximum = -1; int64_t maximum = -1;
Local<String> maximum_key = v8_str(isolate, "maximum"); Local<String> maximum_key = v8_str(isolate, "maximum");
Maybe<bool> has_maximum = descriptor->Has(context, maximum_key); Maybe<bool> has_maximum = descriptor->Has(context, maximum_key);
...@@ -545,8 +545,8 @@ void WebAssemblyTable(const v8::FunctionCallbackInfo<v8::Value>& args) { ...@@ -545,8 +545,8 @@ void WebAssemblyTable(const v8::FunctionCallbackInfo<v8::Value>& args) {
} }
i::Handle<i::FixedArray> fixed_array; i::Handle<i::FixedArray> fixed_array;
i::Handle<i::JSObject> table_obj = i::Handle<i::JSObject> table_obj = i::WasmTableObject::New(
i::WasmTableObject::New(i_isolate, initial, maximum, &fixed_array); i_isolate, static_cast<uint32_t>(initial), maximum, &fixed_array);
v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
return_value.Set(Utils::ToLocal(table_obj)); return_value.Set(Utils::ToLocal(table_obj));
} }
...@@ -563,14 +563,14 @@ void WebAssemblyMemory(const v8::FunctionCallbackInfo<v8::Value>& args) { ...@@ -563,14 +563,14 @@ void WebAssemblyMemory(const v8::FunctionCallbackInfo<v8::Value>& args) {
Local<Context> context = isolate->GetCurrentContext(); Local<Context> context = isolate->GetCurrentContext();
Local<v8::Object> descriptor = args[0]->ToObject(context).ToLocalChecked(); Local<v8::Object> descriptor = args[0]->ToObject(context).ToLocalChecked();
// The descriptor's 'initial'. // The descriptor's 'initial'.
int initial = 0; int64_t initial = 0;
if (!GetIntegerProperty(isolate, &thrower, context, descriptor, if (!GetIntegerProperty(isolate, &thrower, context, descriptor,
v8_str(isolate, "initial"), &initial, 0, v8_str(isolate, "initial"), &initial, 0,
i::FLAG_wasm_max_mem_pages)) { i::FLAG_wasm_max_mem_pages)) {
return; return;
} }
// The descriptor's 'maximum'. // The descriptor's 'maximum'.
int maximum = -1; int64_t maximum = -1;
Local<String> maximum_key = v8_str(isolate, "maximum"); Local<String> maximum_key = v8_str(isolate, "maximum");
Maybe<bool> has_maximum = descriptor->Has(context, maximum_key); Maybe<bool> has_maximum = descriptor->Has(context, maximum_key);
...@@ -589,8 +589,8 @@ void WebAssemblyMemory(const v8::FunctionCallbackInfo<v8::Value>& args) { ...@@ -589,8 +589,8 @@ void WebAssemblyMemory(const v8::FunctionCallbackInfo<v8::Value>& args) {
thrower.RangeError("could not allocate memory"); thrower.RangeError("could not allocate memory");
return; return;
} }
i::Handle<i::JSObject> memory_obj = i::Handle<i::JSObject> memory_obj = i::WasmMemoryObject::New(
i::WasmMemoryObject::New(i_isolate, buffer, maximum); i_isolate, buffer, static_cast<int32_t>(maximum));
args.GetReturnValue().Set(Utils::ToLocal(memory_obj)); args.GetReturnValue().Set(Utils::ToLocal(memory_obj));
} }
...@@ -638,9 +638,8 @@ void WebAssemblyTableGrow(const v8::FunctionCallbackInfo<v8::Value>& args) { ...@@ -638,9 +638,8 @@ void WebAssemblyTableGrow(const v8::FunctionCallbackInfo<v8::Value>& args) {
} }
new_size64 += old_size; new_size64 += old_size;
int64_t max_size64 = receiver->maximum_length(); int64_t max_size64 = receiver->maximum_length()->Number();
if (max_size64 < 0 || if (max_size64 < 0 || max_size64 > i::FLAG_wasm_max_table_size) {
max_size64 > static_cast<int64_t>(i::FLAG_wasm_max_table_size)) {
max_size64 = i::FLAG_wasm_max_table_size; max_size64 = i::FLAG_wasm_max_table_size;
} }
......
...@@ -184,7 +184,8 @@ Handle<WasmTableObject> WasmTableObject::New(Isolate* isolate, uint32_t initial, ...@@ -184,7 +184,8 @@ Handle<WasmTableObject> WasmTableObject::New(Isolate* isolate, uint32_t initial,
} }
table_obj->set_functions(**js_functions); table_obj->set_functions(**js_functions);
DCHECK_EQ(maximum, static_cast<int>(maximum)); DCHECK_EQ(maximum, static_cast<int>(maximum));
table_obj->set_maximum_length(static_cast<int>(maximum)); Handle<Object> max = isolate->factory()->NewNumber(maximum);
table_obj->set_maximum_length(*max);
Handle<FixedArray> dispatch_tables = isolate->factory()->NewFixedArray(0); Handle<FixedArray> dispatch_tables = isolate->factory()->NewFixedArray(0);
table_obj->set_dispatch_tables(*dispatch_tables); table_obj->set_dispatch_tables(*dispatch_tables);
......
...@@ -77,7 +77,8 @@ class WasmTableObject : public JSObject { ...@@ -77,7 +77,8 @@ class WasmTableObject : public JSObject {
DECL_CAST(WasmTableObject) DECL_CAST(WasmTableObject)
DECL_ACCESSORS(functions, FixedArray) DECL_ACCESSORS(functions, FixedArray)
DECL_INT_ACCESSORS(maximum_length) // TODO(titzer): introduce DECL_I64_ACCESSORS macro
DECL_ACCESSORS(maximum_length, Object)
DECL_ACCESSORS(dispatch_tables, FixedArray) DECL_ACCESSORS(dispatch_tables, FixedArray)
enum { // -- enum { // --
...@@ -93,7 +94,7 @@ class WasmTableObject : public JSObject { ...@@ -93,7 +94,7 @@ class WasmTableObject : public JSObject {
DEF_OFFSET(DispatchTables) DEF_OFFSET(DispatchTables)
inline uint32_t current_length() { return functions()->length(); } inline uint32_t current_length() { return functions()->length(); }
inline bool has_maximum_length() { return maximum_length() >= 0; } inline bool has_maximum_length() { return maximum_length()->Number() >= 0; }
void grow(Isolate* isolate, uint32_t count); void grow(Isolate* isolate, uint32_t count);
static Handle<WasmTableObject> New(Isolate* isolate, uint32_t initial, static Handle<WasmTableObject> New(Isolate* isolate, uint32_t initial,
...@@ -680,7 +681,7 @@ ACCESSORS(WasmModuleObject, compiled_module, WasmCompiledModule, ...@@ -680,7 +681,7 @@ ACCESSORS(WasmModuleObject, compiled_module, WasmCompiledModule,
// WasmTableObject // WasmTableObject
ACCESSORS(WasmTableObject, functions, FixedArray, kFunctionsOffset) ACCESSORS(WasmTableObject, functions, FixedArray, kFunctionsOffset)
SMI_ACCESSORS(WasmTableObject, maximum_length, kMaximumLengthOffset) ACCESSORS(WasmTableObject, maximum_length, Object, kMaximumLengthOffset)
ACCESSORS(WasmTableObject, dispatch_tables, FixedArray, kDispatchTablesOffset) ACCESSORS(WasmTableObject, dispatch_tables, FixedArray, kDispatchTablesOffset)
// WasmMemoryObject // WasmMemoryObject
......
...@@ -14,13 +14,15 @@ load("test/mjsunit/wasm/wasm-module-builder.js"); ...@@ -14,13 +14,15 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
var outOfUint32RangeValue = 1e12; var outOfUint32RangeValue = 1e12;
var int32ButOob = 1073741824; var int32ButOob = 1073741824;
var kMaxUint32 = (4 * 1024 * 1024 * 1024) - 1; var kMaxUint32 = (4 * 1024 * 1024 * 1024) - 1;
var kMaxUint31 = (2 * 1024 * 1024 * 1024) - 1;
var kV8MaxWasmTableSize = 10000000; var kV8MaxWasmTableSize = 10000000;
function assertTableIsValid(table) { function assertTableIsValid(table, length) {
assertSame(WebAssembly.Table.prototype, table.__proto__); assertSame(WebAssembly.Table.prototype, table.__proto__);
assertSame(WebAssembly.Table, table.constructor); assertSame(WebAssembly.Table, table.constructor);
assertTrue(table instanceof Object); assertTrue(table instanceof Object);
assertTrue(table instanceof WebAssembly.Table); assertTrue(table instanceof WebAssembly.Table);
assertEquals(length, table.length);
} }
(function TestConstructor() { (function TestConstructor() {
...@@ -57,56 +59,48 @@ function assertTableIsValid(table) { ...@@ -57,56 +59,48 @@ function assertTableIsValid(table) {
let table; let table;
table = new WebAssembly.Table({element: "anyfunc", initial: 1}); table = new WebAssembly.Table({element: "anyfunc", initial: 1});
assertTableIsValid(table); assertTableIsValid(table, 1);
assertEquals(1, table.length);
assertEquals(null, table.get(0)); assertEquals(null, table.get(0));
assertEquals(undefined, table[0]); assertEquals(undefined, table[0]);
table = new WebAssembly.Table({element: "anyfunc", initial: "2"}); table = new WebAssembly.Table({element: "anyfunc", initial: "2"});
assertTableIsValid(table); assertTableIsValid(table, 2);
assertEquals(2, table.length);
assertEquals(null, table.get(0)); assertEquals(null, table.get(0));
assertEquals(null, table.get(1)); assertEquals(null, table.get(1));
assertEquals(undefined, table[0]); assertEquals(undefined, table[0]);
assertEquals(undefined, table[1]); assertEquals(undefined, table[1]);
table = new WebAssembly.Table({element: "anyfunc", initial: {valueOf() { return "1" }}}); table = new WebAssembly.Table({element: "anyfunc", initial: {valueOf() { return "1" }}});
assertTableIsValid(table); assertTableIsValid(table, 1);
assertEquals(1, table.length);
assertEquals(null, table.get(0)); assertEquals(null, table.get(0));
assertEquals(undefined, table[0]); assertEquals(undefined, table[0]);
table = new WebAssembly.Table({element: "anyfunc", initial: undefined}); table = new WebAssembly.Table({element: "anyfunc", initial: undefined});
assertTableIsValid(table); assertTableIsValid(table, 0);
assertEquals(0, table.length);
table = new WebAssembly.Table({element: "anyfunc"}); table = new WebAssembly.Table({element: "anyfunc"});
assertTableIsValid(table); assertTableIsValid(table, 0);
assertEquals(0, table.length);
table = new WebAssembly.Table({element: "anyfunc", maximum: 10}); table = new WebAssembly.Table({element: "anyfunc", maximum: 10});
assertTableIsValid(table); assertTableIsValid(table, 0);
assertEquals(0, table.length);
table = new WebAssembly.Table({element: "anyfunc", maximum: "10"}); table = new WebAssembly.Table({element: "anyfunc", maximum: "10"});
assertTableIsValid(table); assertTableIsValid(table, 0);
assertEquals(0, table.length);
table = new WebAssembly.Table({element: "anyfunc", maximum: {valueOf() { return "10" }}}); table = new WebAssembly.Table({element: "anyfunc", maximum: {valueOf() { return "10" }}});
assertTableIsValid(table); assertTableIsValid(table, 0);
assertEquals(0, table.length);
table = new WebAssembly.Table({element: "anyfunc", initial: 0, maximum: undefined}); table = new WebAssembly.Table({element: "anyfunc", initial: 0, maximum: undefined});
assertTableIsValid(table); assertTableIsValid(table, 0);
assertEquals(0, table.length);
table = new WebAssembly.Table({element: "anyfunc", maximum: kMaxUint31});
assertTableIsValid(table, 0);
table = new WebAssembly.Table({element: "anyfunc", maximum: kMaxUint32}); table = new WebAssembly.Table({element: "anyfunc", maximum: kMaxUint32});
assertTableIsValid(table); assertTableIsValid(table, 0);
assertEquals(0, table.length);
table = new WebAssembly.Table({element: "anyfunc", maximum: kV8MaxWasmTableSize + 1}); table = new WebAssembly.Table({element: "anyfunc", maximum: kV8MaxWasmTableSize + 1});
assertTableIsValid(table); assertTableIsValid(table, 0);
assertEquals(0, table.length);
})(); })();
(function TestMaximumIsReadOnce() { (function TestMaximumIsReadOnce() {
...@@ -123,7 +117,7 @@ function assertTableIsValid(table) { ...@@ -123,7 +117,7 @@ function assertTableIsValid(table) {
} }
}}); }});
let table = new WebAssembly.Table(desc); let table = new WebAssembly.Table(desc);
assertTableIsValid(table); assertTableIsValid(table, 10);
})(); })();
(function TestMaximumDoesHasProperty() { (function TestMaximumDoesHasProperty() {
...@@ -134,7 +128,7 @@ function assertTableIsValid(table) { ...@@ -134,7 +128,7 @@ function assertTableIsValid(table) {
}); });
Object.setPrototypeOf(desc, proxy); Object.setPrototypeOf(desc, proxy);
let table = new WebAssembly.Table(desc); let table = new WebAssembly.Table(desc);
assertTableIsValid(table); assertTableIsValid(table, 10);
})(); })();
(function TestLength() { (function TestLength() {
......
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