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

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

Issue 2414053002: [wasm] Implement Table#set and Table#grow (Closed)
Patch Set: Avoid lossy int conversion Created 4 years, 2 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
« no previous file with comments | « no previous file | test/mjsunit/wasm/table.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/wasm/wasm-js.cc
diff --git a/src/wasm/wasm-js.cc b/src/wasm/wasm-js.cc
index ae4f972a984e75c3f76324ecc6664491295f410a..bb3920f7d0e2c35f7beff3e6e9785eee2e293fd7 100644
--- a/src/wasm/wasm-js.cc
+++ b/src/wasm/wasm-js.cc
@@ -366,6 +366,8 @@ bool GetIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower,
return false;
}
+const int max_table_size = 1 << 26;
+
void WebAssemblyTable(const v8::FunctionCallbackInfo<v8::Value>& args) {
v8::Isolate* isolate = args.GetIsolate();
HandleScope scope(isolate);
@@ -392,7 +394,6 @@ void WebAssemblyTable(const v8::FunctionCallbackInfo<v8::Value>& args) {
return;
}
}
- const int max_table_size = 1 << 26;
// The descriptor's 'initial'.
int initial;
if (!GetIntegerProperty(isolate, &thrower, context, descriptor,
@@ -511,10 +512,44 @@ void WebAssemblyTableGrow(const v8::FunctionCallbackInfo<v8::Value>& args) {
"Receiver is not a WebAssembly.Table")) {
return;
}
- // TODO(rossberg): grow table and update relevant instances.
- v8::Local<v8::Value> e =
- v8::Exception::TypeError(v8_str(isolate, "Table#grow unimplemented"));
- isolate->ThrowException(e);
+
+ 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);
+ int old_size = old_array->length();
+ int64_t new_size64 = 0;
+ if (args.Length() > 0 && !args[0]->IntegerValue(context).To(&new_size64)) {
+ return;
+ }
+ 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) {
+ v8::Local<v8::Value> e = v8::Exception::RangeError(
+ v8_str(isolate, new_size64 < old_size ? "trying to shrink table"
+ : "maximum table size exceeded"));
+ isolate->ThrowException(e);
+ return;
+ }
+ int new_size = static_cast<int>(new_size64);
+
+ if (new_size != old_size) {
+ i::Handle<i::FixedArray> new_array =
+ i_isolate->factory()->NewFixedArray(new_size);
+ 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);
+ }
+
+ // TODO(titzer): update relevant instances.
}
void WebAssemblyTableGet(const v8::FunctionCallbackInfo<v8::Value>& args) {
@@ -535,15 +570,21 @@ void WebAssemblyTableGet(const v8::FunctionCallbackInfo<v8::Value>& args) {
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()) {
- i::Handle<i::Object> value(i::Handle<i::FixedArray>::cast(array)->get(i),
- i_isolate);
- return_value.Set(Utils::ToLocal(value));
+ if (i < 0 || i >= i::Handle<i::FixedArray>::cast(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);
+ return_value.Set(Utils::ToLocal(value));
}
void WebAssemblyTableSet(const v8::FunctionCallbackInfo<v8::Value>& args) {
v8::Isolate* isolate = args.GetIsolate();
+ i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
Local<Context> context = isolate->GetCurrentContext();
i::Handle<i::Context> i_context = Utils::OpenHandle(*context);
if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()),
@@ -551,19 +592,39 @@ void WebAssemblyTableSet(const v8::FunctionCallbackInfo<v8::Value>& args) {
"Receiver is not a WebAssembly.Table")) {
return;
}
- if (args.Length() < 2 ||
- !(args[1]->IsNull() ||
- (args[1]->IsObject() && v8::Object::Cast(*args[1])->IsCallable()))) {
+ if (args.Length() < 2) {
v8::Local<v8::Value> e = v8::Exception::TypeError(
v8_str(isolate, "Argument 1 must be null or a function"));
isolate->ThrowException(e);
return;
}
+ i::Handle<i::Object> value = Utils::OpenHandle(*args[1]);
+ if (!value->IsNull(i_isolate) &&
+ (!value->IsJSFunction() ||
+ i::Handle<i::JSFunction>::cast(value)->code()->kind() !=
+ i::Code::JS_TO_WASM_FUNCTION)) {
+ v8::Local<v8::Value> e = v8::Exception::TypeError(
+ v8_str(isolate, "Argument 1 must be null or a WebAssembly function"));
+ isolate->ThrowException(e);
+ return;
+ }
- // TODO(rossberg): set table element and update relevent instances.
- v8::Local<v8::Value> e =
- v8::Exception::TypeError(v8_str(isolate, "Table#set unimplemented"));
- isolate->ThrowException(e);
+ 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 i;
+ if (!args[0]->Int32Value(context).To(&i)) return;
+ if (i < 0 || i >= i::Handle<i::FixedArray>::cast(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>::cast(array)->set(i, *value);
+
+ // TODO(titzer): update relevant instances.
}
void WebAssemblyMemoryGrow(const v8::FunctionCallbackInfo<v8::Value>& args) {
« no previous file with comments | « no previous file | test/mjsunit/wasm/table.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698