Commit 698bbe41 authored by ahaas's avatar ahaas Committed by Commit bot

[wasm] Set up Table and Memory constructors

Set up Wasm Table and Memory constructors

This only provides skeletons so far: the constructors work, but the
types are not wired up with the import/export mechanism yet; methods are
still nops.

Also, fix errors generated from Wasm to be proper Error/TypeError
instances instead of just strings.

I took over this CL from rossberg@chromium.org. The original CL is
https://codereview.chromium.org/2342623002

R=titzer@chromium.org, rossberg@chromium.org

Review-Url: https://codereview.chromium.org/2350643003
Cr-Commit-Position: refs/heads/master@{#39588}
parent 51b6a3d1
......@@ -138,6 +138,8 @@ class Utils {
v8::internal::Handle<v8::internal::JSReceiver> obj);
static inline Local<Object> ToLocal(
v8::internal::Handle<v8::internal::JSObject> obj);
static inline Local<Function> ToLocal(
v8::internal::Handle<v8::internal::JSFunction> obj);
static inline Local<Array> ToLocal(
v8::internal::Handle<v8::internal::JSArray> obj);
static inline Local<Map> ToLocal(
......@@ -293,6 +295,7 @@ MAKE_TO_LOCAL(ToLocal, Symbol, Symbol)
MAKE_TO_LOCAL(ToLocal, JSRegExp, RegExp)
MAKE_TO_LOCAL(ToLocal, JSReceiver, Object)
MAKE_TO_LOCAL(ToLocal, JSObject, Object)
MAKE_TO_LOCAL(ToLocal, JSFunction, Function)
MAKE_TO_LOCAL(ToLocal, JSArray, Array)
MAKE_TO_LOCAL(ToLocal, JSMap, Map)
MAKE_TO_LOCAL(ToLocal, JSSet, Set)
......
......@@ -207,7 +207,11 @@ enum ContextLookupFlags {
V(WASM_FUNCTION_MAP_INDEX, Map, wasm_function_map) \
V(WASM_MODULE_CONSTRUCTOR_INDEX, JSFunction, wasm_module_constructor) \
V(WASM_INSTANCE_CONSTRUCTOR_INDEX, JSFunction, wasm_instance_constructor) \
V(WASM_TABLE_CONSTRUCTOR_INDEX, JSFunction, wasm_table_constructor) \
V(WASM_MEMORY_CONSTRUCTOR_INDEX, JSFunction, wasm_memory_constructor) \
V(WASM_MODULE_SYM_INDEX, Symbol, wasm_module_sym) \
V(WASM_TABLE_SYM_INDEX, Symbol, wasm_table_sym) \
V(WASM_MEMORY_SYM_INDEX, Symbol, wasm_memory_sym) \
V(WASM_INSTANCE_SYM_INDEX, Symbol, wasm_instance_sym) \
V(SLOPPY_ASYNC_FUNCTION_MAP_INDEX, Map, sloppy_async_function_map) \
V(SLOPPY_GENERATOR_FUNCTION_MAP_INDEX, Map, sloppy_generator_function_map) \
......
This diff is collapsed.
......@@ -14,11 +14,16 @@ namespace internal {
class WasmJs {
public:
static void Install(Isolate* isolate, Handle<JSGlobalObject> global_object);
static void InstallWasmFunctionMapIfNeeded(Isolate* isolate,
Handle<Context> context);
static void InstallWasmModuleSymbolIfNeeded(Isolate* isolate,
Handle<JSGlobalObject> global,
Handle<Context> context);
static void InstallWasmMapsIfNeeded(Isolate* isolate,
Handle<Context> context);
static void InstallWasmConstructors(Isolate* isolate,
Handle<JSGlobalObject> global,
Handle<Context> context);
};
} // namespace internal
......
......@@ -27,15 +27,13 @@ std::ostream& operator<<(std::ostream& os, const ErrorCode& error_code) {
return os;
}
void ErrorThrower::Error(const char* format, ...) {
void ErrorThrower::Format(i::Handle<i::JSFunction> constructor,
const char* format, va_list args) {
// Only report the first error.
if (error()) return;
char buffer[256];
va_list arguments;
va_start(arguments, format);
base::OS::VSNPrintF(buffer, 255, format, arguments);
va_end(arguments);
base::OS::VSNPrintF(buffer, 255, format, args);
std::ostringstream str;
if (context_ != nullptr) {
......@@ -43,12 +41,39 @@ void ErrorThrower::Error(const char* format, ...) {
}
str << buffer;
message_ = isolate_->factory()->NewStringFromAsciiChecked(str.str().c_str());
i::Handle<i::String> message =
isolate_->factory()->NewStringFromAsciiChecked(str.str().c_str());
exception_ = isolate_->factory()->NewError(constructor, message);
}
void ErrorThrower::Error(const char* format, ...) {
if (error()) return;
va_list arguments;
va_start(arguments, format);
Format(isolate_->error_function(), format, arguments);
va_end(arguments);
}
void ErrorThrower::TypeError(const char* format, ...) {
if (error()) return;
va_list arguments;
va_start(arguments, format);
Format(isolate_->type_error_function(), format, arguments);
va_end(arguments);
}
void ErrorThrower::RangeError(const char* format, ...) {
if (error()) return;
va_list arguments;
va_start(arguments, format);
CHECK(*isolate_->range_error_function() != *isolate_->type_error_function());
Format(isolate_->range_error_function(), format, arguments);
va_end(arguments);
}
ErrorThrower::~ErrorThrower() {
if (error() && !isolate_->has_pending_exception()) {
isolate_->ScheduleThrow(*message_);
isolate_->ScheduleThrow(*exception_);
}
}
} // namespace wasm
......
......@@ -99,31 +99,35 @@ std::ostream& operator<<(std::ostream& os, const ErrorCode& error_code);
// A helper for generating error messages that bubble up to JS exceptions.
class ErrorThrower {
public:
ErrorThrower(Isolate* isolate, const char* context)
ErrorThrower(i::Isolate* isolate, const char* context)
: isolate_(isolate), context_(context) {}
~ErrorThrower();
PRINTF_FORMAT(2, 3) void Error(const char* fmt, ...);
PRINTF_FORMAT(2, 3) void TypeError(const char* fmt, ...);
PRINTF_FORMAT(2, 3) void RangeError(const char* fmt, ...);
template <typename T>
void Failed(const char* error, Result<T>& result) {
std::ostringstream str;
str << error << result;
return Error("%s", str.str().c_str());
Error("%s", str.str().c_str());
}
i::Handle<i::String> Reify() {
auto result = message_;
message_ = i::Handle<i::String>();
i::Handle<i::Object> Reify() {
i::Handle<i::Object> result = exception_;
exception_ = i::Handle<i::Object>::null();
return result;
}
bool error() const { return !message_.is_null(); }
bool error() const { return !exception_.is_null(); }
private:
Isolate* isolate_;
void Format(i::Handle<i::JSFunction> constructor, const char* fmt, va_list);
i::Isolate* isolate_;
const char* context_;
i::Handle<i::String> message_;
i::Handle<i::Object> exception_;
};
} // namespace wasm
} // namespace internal
......
......@@ -79,7 +79,7 @@ bytecodes: [
/* 15 S> */ B(LdrUndefined), R(0),
B(CreateArrayLiteral), U8(0), U8(0), U8(9),
B(Star), R(1),
B(CallJSRuntime), U8(135), R(0), U8(2),
B(CallJSRuntime), U8(139), R(0), U8(2),
/* 44 S> */ B(Return),
]
constant pool: [
......
......@@ -208,8 +208,7 @@ class TestingModule : public ModuleEnv {
Handle<String> name = isolate_->factory()->NewStringFromStaticChars("main");
Handle<JSObject> module_object = Handle<JSObject>(0, isolate_);
Handle<Code> code = instance->function_code[index];
WasmJs::InstallWasmFunctionMapIfNeeded(isolate_,
isolate_->native_context());
WasmJs::InstallWasmMapsIfNeeded(isolate_, isolate_->native_context());
Handle<Code> ret_code =
compiler::CompileJSToWasmWrapper(isolate_, this, code, index);
FunctionSig* funcSig = this->module->functions[index].sig;
......
......@@ -201,7 +201,7 @@ int32_t CallWasmFunctionForTesting(Isolate* isolate, Handle<JSObject> instance,
}
void SetupIsolateForWasmModule(Isolate* isolate) {
WasmJs::InstallWasmFunctionMapIfNeeded(isolate, isolate->native_context());
WasmJs::InstallWasmMapsIfNeeded(isolate, isolate->native_context());
WasmJs::InstallWasmModuleSymbolIfNeeded(isolate, isolate->global_object(),
isolate->native_context());
}
......
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --expose-wasm
// Basic tests.
var outOfUint32RangeValue = 1e12;
(function TestConstructor() {
assertTrue(WebAssembly.Memory instanceof Function);
assertSame(WebAssembly.Memory, WebAssembly.Memory.prototype.constructor);
assertTrue(WebAssembly.Memory.prototype.grow instanceof Function);
let desc = Object.getOwnPropertyDescriptor(WebAssembly.Memory.prototype, 'buffer');
assertTrue(desc.get instanceof Function);
assertSame(undefined, desc.set);
assertThrows(() => new WebAssembly.Memory(), TypeError);
assertThrows(() => new WebAssembly.Memory(1), TypeError);
assertThrows(() => new WebAssembly.Memory(""), TypeError);
assertThrows(() => new WebAssembly.Memory({initial: -1}), RangeError);
assertThrows(() => new WebAssembly.Memory({initial: outOfUint32RangeValue}), RangeError);
assertThrows(() => new WebAssembly.Memory({initial: 10, maximum: -1}), RangeError);
assertThrows(() => new WebAssembly.Memory({initial: 10, maximum: outOfUint32RangeValue}), RangeError);
assertThrows(() => new WebAssembly.Memory({initial: 10, maximum: 9}), RangeError);
let memory = new WebAssembly.Memory({initial: 1});
assertSame(WebAssembly.Memory.prototype, memory.__proto__);
assertSame(WebAssembly.Memory, memory.constructor);
assertTrue(memory instanceof Object);
assertTrue(memory instanceof WebAssembly.Memory);
})();
(function TestConstructorWithMaximum() {
let memory = new WebAssembly.Memory({initial: 1, maximum: 10});
assertSame(WebAssembly.Memory.prototype, memory.__proto__);
assertSame(WebAssembly.Memory, memory.constructor);
assertTrue(memory instanceof Object);
assertTrue(memory instanceof WebAssembly.Memory);
})();
(function TestBuffer() {
let memory = new WebAssembly.Memory({initial: 1});
assertTrue(memory.buffer instanceof Object);
assertTrue(memory.buffer instanceof ArrayBuffer);
assertThrows(() => {'use strict'; memory.buffer = memory.buffer}, TypeError)
assertThrows(() => ({__proto__: memory}).buffer, TypeError)
})();
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --expose-wasm
// Basic tests.
var outOfUint32RangeValue = 1e12;
(function TestConstructor() {
assertTrue(WebAssembly.Table instanceof Function);
assertSame(WebAssembly.Table, WebAssembly.Table.prototype.constructor);
assertTrue(WebAssembly.Table.prototype.grow instanceof Function);
assertTrue(WebAssembly.Table.prototype.get instanceof Function);
assertTrue(WebAssembly.Table.prototype.set instanceof Function);
let desc = Object.getOwnPropertyDescriptor(WebAssembly.Table.prototype, 'length');
assertTrue(desc.get instanceof Function);
assertSame(undefined, desc.set);
assertThrows(() => new WebAssembly.Table(), TypeError);
assertThrows(() => new WebAssembly.Table(1), TypeError);
assertThrows(() => new WebAssembly.Table(""), TypeError);
assertThrows(() => new WebAssembly.Table({}), TypeError);
assertThrows(() => new WebAssembly.Table({initial: 10}), TypeError);
assertThrows(() => new WebAssembly.Table({element: 0, initial: 10}), TypeError);
assertThrows(() => new WebAssembly.Table({element: "any", initial: 10}), TypeError);
assertThrows(() => new WebAssembly.Table({element: "anyfunc", initial: -1}), RangeError);
assertThrows(() => new WebAssembly.Table({element: "anyfunc", initial: outOfUint32RangeValue}), RangeError);
assertThrows(() => new WebAssembly.Table({element: "anyfunc", initial: 10, maximum: -1}), RangeError);
assertThrows(() => new WebAssembly.Table({element: "anyfunc", initial: 10, maximum: outOfUint32RangeValue}), RangeError);
assertThrows(() => new WebAssembly.Table({element: "anyfunc", initial: 10, maximum: 9}), RangeError);
let table = new WebAssembly.Table({element: "anyfunc", initial: 1});
assertSame(WebAssembly.Table.prototype, table.__proto__);
assertSame(WebAssembly.Table, table.constructor);
assertTrue(table instanceof Object);
assertTrue(table instanceof WebAssembly.Table);
})();
(function TestConstructorWithMaximum() {
let table = new WebAssembly.Table({element: "anyfunc", initial: 1, maximum: 10});
assertSame(WebAssembly.Table.prototype, table.__proto__);
assertSame(WebAssembly.Table, table.constructor);
assertTrue(table instanceof Object);
assertTrue(table instanceof WebAssembly.Table);
})();
......@@ -79,6 +79,7 @@ function checkImportsAndExports(imported_module_name, imported_function_name,
} catch (err) {
if (!shouldThrow) print(err);
assertTrue(shouldThrow, "Should not throw error on valid names");
assertTrue(err instanceof Error, "exception should be an Error");
assertContains("UTF-8", err.toString());
}
assertEquals(shouldThrow, hasThrown,
......
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