[wasm] Improve {WasmExceptionPackage} type safety.

This uses Handle<WasmExceptionPackage> where applicable to increase type
safety. Note that {WasmExceptionPackage} is not a full-fledged instance
type though. The {HeapObject::IsWasmExceptionPackage} predicate is an
approximation because a precise version could only be implemented using
handlified code performing a property lookup.

R=clemensb@chromium.org

Change-Id: I061e3eea201a0e9909ba67ae33db81d14aaefe4b
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1477673
Commit-Queue: Michael Starzinger <mstarzinger@chromium.org>
Reviewed-by: Clemens Backes [né Hammacher] <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#63987}
This commit is contained in:
Michael Starzinger 2019-09-26 11:20:27 +02:00 committed by Commit Bot
parent 14d1e5320c
commit cae9aaeb32
9 changed files with 59 additions and 39 deletions

View File

@ -131,6 +131,7 @@ class Undetectable;
class UniqueName;
class WasmCapiFunctionData;
class WasmExceptionObject;
class WasmExceptionPackage;
class WasmExceptionTag;
class WasmExportedFunctionData;
class WasmGlobalObject;

View File

@ -226,6 +226,7 @@ class ZoneForwardList;
V(Undetectable) \
V(UniqueName) \
V(WasmExceptionObject) \
V(WasmExceptionPackage) \
V(WasmGlobalObject) \
V(WasmInstanceObject) \
V(WasmMemoryObject) \

View File

@ -411,6 +411,12 @@ DEF_GETTER(HeapObject, IsSmallOrderedHashTable, bool) {
IsSmallOrderedNameDictionary(isolate);
}
DEF_GETTER(HeapObject, IsWasmExceptionPackage, bool) {
// It is not possible to check for the existence of certain properties on the
// underlying {JSReceiver} here because that requires calling handlified code.
return IsJSReceiver(isolate);
}
bool Object::IsPrimitive() const {
if (IsSmi()) return true;
HeapObject this_heap_object = HeapObject::cast(*this);

View File

@ -1049,7 +1049,7 @@ RUNTIME_FUNCTION(Runtime_GetWasmRecoveredTrapCount) {
RUNTIME_FUNCTION(Runtime_GetWasmExceptionId) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, exception, 0);
CONVERT_ARG_HANDLE_CHECKED(WasmExceptionPackage, exception, 0);
CONVERT_ARG_HANDLE_CHECKED(WasmInstanceObject, instance, 1);
Handle<Object> tag =
WasmExceptionPackage::GetExceptionTag(isolate, exception);
@ -1065,7 +1065,7 @@ RUNTIME_FUNCTION(Runtime_GetWasmExceptionId) {
RUNTIME_FUNCTION(Runtime_GetWasmExceptionValues) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, exception, 0);
CONVERT_ARG_HANDLE_CHECKED(WasmExceptionPackage, exception, 0);
Handle<Object> values_obj =
WasmExceptionPackage::GetExceptionValues(isolate, exception);
CHECK(values_obj->IsFixedArray()); // Only called with correct input.

View File

@ -150,7 +150,12 @@ RUNTIME_FUNCTION(Runtime_WasmExceptionGetTag) {
CONVERT_ARG_CHECKED(Object, except_obj_raw, 0);
// TODO(mstarzinger): Manually box because parameters are not visited yet.
Handle<Object> except_obj(except_obj_raw, isolate);
return *WasmExceptionPackage::GetExceptionTag(isolate, except_obj);
if (!except_obj->IsWasmExceptionPackage(isolate)) {
return ReadOnlyRoots(isolate).undefined_value();
}
Handle<WasmExceptionPackage> exception =
Handle<WasmExceptionPackage>::cast(except_obj);
return *WasmExceptionPackage::GetExceptionTag(isolate, exception);
}
RUNTIME_FUNCTION(Runtime_WasmExceptionGetValues) {
@ -162,7 +167,12 @@ RUNTIME_FUNCTION(Runtime_WasmExceptionGetValues) {
CONVERT_ARG_CHECKED(Object, except_obj_raw, 0);
// TODO(mstarzinger): Manually box because parameters are not visited yet.
Handle<Object> except_obj(except_obj_raw, isolate);
return *WasmExceptionPackage::GetExceptionValues(isolate, except_obj);
if (!except_obj->IsWasmExceptionPackage(isolate)) {
return ReadOnlyRoots(isolate).undefined_value();
}
Handle<WasmExceptionPackage> exception =
Handle<WasmExceptionPackage>::cast(except_obj);
return *WasmExceptionPackage::GetExceptionValues(isolate, exception);
}
RUNTIME_FUNCTION(Runtime_WasmRunInterpreter) {

View File

@ -2727,7 +2727,7 @@ class ThreadImpl {
WasmExceptionTag::cast(instance_object_->exceptions_table().get(index)),
isolate_);
uint32_t encoded_size = WasmExceptionPackage::GetEncodedSize(exception);
Handle<Object> exception_object =
Handle<WasmExceptionPackage> exception_object =
WasmExceptionPackage::New(isolate_, exception_tag, encoded_size);
Handle<FixedArray> encoded_values = Handle<FixedArray>::cast(
WasmExceptionPackage::GetExceptionValues(isolate_, exception_object));
@ -2796,8 +2796,9 @@ class ThreadImpl {
// Determines whether the given exception has a tag matching the expected tag
// for the given index within the exception table of the current instance.
bool MatchingExceptionTag(Handle<Object> exception_object, uint32_t index) {
Handle<Object> caught_tag =
WasmExceptionPackage::GetExceptionTag(isolate_, exception_object);
if (!exception_object->IsWasmExceptionPackage(isolate_)) return false;
Handle<Object> caught_tag = WasmExceptionPackage::GetExceptionTag(
isolate_, Handle<WasmExceptionPackage>::cast(exception_object));
Handle<Object> expected_tag =
handle(instance_object_->exceptions_table().get(index), isolate_);
DCHECK(expected_tag->IsWasmExceptionTag());
@ -2824,8 +2825,9 @@ class ThreadImpl {
// the encoded values match the expected signature of the exception.
void DoUnpackException(const WasmException* exception,
Handle<Object> exception_object) {
Handle<FixedArray> encoded_values = Handle<FixedArray>::cast(
WasmExceptionPackage::GetExceptionValues(isolate_, exception_object));
Handle<FixedArray> encoded_values =
Handle<FixedArray>::cast(WasmExceptionPackage::GetExceptionValues(
isolate_, Handle<WasmExceptionPackage>::cast(exception_object)));
// Decode the exception values from the given exception package and push
// them onto the operand stack. This encoding has to be in sync with other
// backends so that exceptions can be passed between them.

View File

@ -309,6 +309,10 @@ ACCESSORS(WasmExceptionObject, serialized_signature, PodArray<wasm::ValueType>,
kSerializedSignatureOffset)
ACCESSORS(WasmExceptionObject, exception_tag, HeapObject, kExceptionTagOffset)
// WasmExceptionPackage
OBJECT_CONSTRUCTORS_IMPL(WasmExceptionPackage, JSReceiver)
CAST_ACCESSOR(WasmExceptionPackage)
// WasmExportedFunction
WasmExportedFunction::WasmExportedFunction(Address ptr) : JSFunction(ptr) {
SLOW_DCHECK(IsWasmExportedFunction(*this));

View File

@ -1930,7 +1930,7 @@ bool WasmCapiFunction::IsSignatureEqual(const wasm::FunctionSig* sig) const {
}
// static
Handle<JSReceiver> WasmExceptionPackage::New(
Handle<WasmExceptionPackage> WasmExceptionPackage::New(
Isolate* isolate, Handle<WasmExceptionTag> exception_tag, int size) {
Handle<Object> exception = isolate->factory()->NewWasmRuntimeError(
MessageTemplate::kWasmExceptionError);
@ -1945,37 +1945,31 @@ Handle<JSReceiver> WasmExceptionPackage::New(
values, StoreOrigin::kMaybeKeyed,
Just(ShouldThrow::kThrowOnError))
.is_null());
return Handle<JSReceiver>::cast(exception);
return Handle<WasmExceptionPackage>::cast(exception);
}
// static
Handle<Object> WasmExceptionPackage::GetExceptionTag(
Isolate* isolate, Handle<Object> exception_object) {
if (exception_object->IsJSReceiver()) {
Handle<JSReceiver> exception = Handle<JSReceiver>::cast(exception_object);
Handle<Object> tag;
if (JSReceiver::GetProperty(isolate, exception,
isolate->factory()->wasm_exception_tag_symbol())
.ToHandle(&tag)) {
return tag;
}
Isolate* isolate, Handle<WasmExceptionPackage> exception_package) {
Handle<Object> tag;
if (JSReceiver::GetProperty(isolate, exception_package,
isolate->factory()->wasm_exception_tag_symbol())
.ToHandle(&tag)) {
return tag;
}
return ReadOnlyRoots(isolate).undefined_value_handle();
}
// static
Handle<Object> WasmExceptionPackage::GetExceptionValues(
Isolate* isolate, Handle<Object> exception_object) {
if (exception_object->IsJSReceiver()) {
Handle<JSReceiver> exception = Handle<JSReceiver>::cast(exception_object);
Handle<Object> values;
if (JSReceiver::GetProperty(
isolate, exception,
isolate->factory()->wasm_exception_values_symbol())
.ToHandle(&values)) {
DCHECK(values->IsFixedArray());
return values;
}
Isolate* isolate, Handle<WasmExceptionPackage> exception_package) {
Handle<Object> values;
if (JSReceiver::GetProperty(
isolate, exception_package,
isolate->factory()->wasm_exception_values_symbol())
.ToHandle(&values)) {
DCHECK(values->IsFixedArray());
return values;
}
return ReadOnlyRoots(isolate).undefined_value_handle();
}

View File

@ -626,20 +626,22 @@ class WasmExceptionObject : public JSObject {
// A Wasm exception that has been thrown out of Wasm code.
class WasmExceptionPackage : public JSReceiver {
public:
// TODO(mstarzinger): Ideally this interface would use {WasmExceptionPackage}
// instead of {JSReceiver} throughout. For now a type-check implies doing a
// property lookup however, which would result in casts being handlified.
static Handle<JSReceiver> New(Isolate* isolate,
Handle<WasmExceptionTag> exception_tag,
int encoded_size);
static Handle<WasmExceptionPackage> New(
Isolate* isolate, Handle<WasmExceptionTag> exception_tag,
int encoded_size);
// The below getters return {undefined} in case the given exception package
// does not carry the requested values (i.e. is of a different type).
static Handle<Object> GetExceptionTag(Isolate*, Handle<Object> exception);
static Handle<Object> GetExceptionValues(Isolate*, Handle<Object> exception);
static Handle<Object> GetExceptionTag(
Isolate* isolate, Handle<WasmExceptionPackage> exception_package);
static Handle<Object> GetExceptionValues(
Isolate* isolate, Handle<WasmExceptionPackage> exception_package);
// Determines the size of the array holding all encoded exception values.
static uint32_t GetEncodedSize(const wasm::WasmException* exception);
DECL_CAST(WasmExceptionPackage)
OBJECT_CONSTRUCTORS(WasmExceptionPackage, JSReceiver);
};
// A Wasm function that is wrapped and exported to JavaScript.