[wasm] Perform exception value encoding/decoding in code.

This removes some unnecessary runtime calls when encoding/decoding
values stored in exception objects. It reduces code size of the
generated code.

R=clemensh@chromium.org
BUG=v8:8341

Change-Id: I2394994be01d3071e58bfa2bfbba8bf72a6a04a5
Reviewed-on: https://chromium-review.googlesource.com/c/1293373
Commit-Queue: Michael Starzinger <mstarzinger@chromium.org>
Reviewed-by: Clemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#56860}
This commit is contained in:
Michael Starzinger 2018-10-22 16:20:10 +02:00 committed by Commit Bot
parent 15f0263f12
commit 99dcc4cd94
4 changed files with 35 additions and 63 deletions

View File

@ -98,6 +98,17 @@ MachineType assert_size(int expected_size, MachineType type) {
LOAD_TAGGED_POINTER( \
array_node, wasm::ObjectAccess::ElementOffsetInTaggedFixedArray(index))
// TODO(mstarzinger): This macro only works for Smi values and needs to be
// extended appropriately before it can be used for tagged pointers.
#define STORE_FIXED_ARRAY_SLOT(array_node, index, value) \
SetEffect(graph()->NewNode( \
mcgraph()->machine()->Store(StoreRepresentation( \
MachineRepresentation::kTaggedSigned, kNoWriteBarrier)), \
array_node, \
mcgraph()->Int32Constant( \
wasm::ObjectAccess::ElementOffsetInTaggedFixedArray(index)), \
value, Effect(), Control()))
constexpr uint32_t kBytesPerExceptionValuesArrayElement = 2;
void MergeControlToEnd(MachineGraph* mcgraph, Node* node) {
@ -2055,6 +2066,8 @@ Node* WasmGraphBuilder::Throw(uint32_t exception_index,
Node* except_obj =
BuildCallToRuntime(Runtime::kWasmThrowCreate, create_parameters,
arraysize(create_parameters));
Node* values_array =
BuildCallToRuntime(Runtime::kWasmExceptionGetValues, &except_obj, 1);
uint32_t index = 0;
const wasm::WasmExceptionSig* sig = exception->sig;
MachineOperatorBuilder* m = mcgraph()->machine();
@ -2065,7 +2078,7 @@ Node* WasmGraphBuilder::Throw(uint32_t exception_index,
value = graph()->NewNode(m->BitcastFloat32ToInt32(), value);
V8_FALLTHROUGH;
case wasm::kWasmI32:
BuildEncodeException32BitValue(except_obj, &index, value);
BuildEncodeException32BitValue(values_array, &index, value);
break;
case wasm::kWasmF64:
value = graph()->NewNode(m->BitcastFloat64ToInt64(), value);
@ -2074,9 +2087,9 @@ Node* WasmGraphBuilder::Throw(uint32_t exception_index,
Node* upper32 = graph()->NewNode(
m->TruncateInt64ToInt32(),
Binop(wasm::kExprI64ShrU, value, Int64Constant(32)));
BuildEncodeException32BitValue(except_obj, &index, upper32);
BuildEncodeException32BitValue(values_array, &index, upper32);
Node* lower32 = graph()->NewNode(m->TruncateInt64ToInt32(), value);
BuildEncodeException32BitValue(except_obj, &index, lower32);
BuildEncodeException32BitValue(values_array, &index, lower32);
break;
}
default:
@ -2096,25 +2109,17 @@ Node* WasmGraphBuilder::Throw(uint32_t exception_index,
except_obj, Effect(), Control())));
}
void WasmGraphBuilder::BuildEncodeException32BitValue(Node* except_obj,
void WasmGraphBuilder::BuildEncodeException32BitValue(Node* values_array,
uint32_t* index,
Node* value) {
MachineOperatorBuilder* machine = mcgraph()->machine();
Node* upper_parameters[] = {
except_obj, BuildChangeUint31ToSmi(Int32Constant(*index)),
BuildChangeUint31ToSmi(
graph()->NewNode(machine->Word32Shr(), value, Int32Constant(16))),
};
BuildCallToRuntime(Runtime::kWasmExceptionSetElement, upper_parameters,
arraysize(upper_parameters));
Node* upper_halfword_as_smi = BuildChangeUint31ToSmi(
graph()->NewNode(machine->Word32Shr(), value, Int32Constant(16)));
STORE_FIXED_ARRAY_SLOT(values_array, *index, upper_halfword_as_smi);
++(*index);
Node* lower_parameters[] = {
except_obj, BuildChangeUint31ToSmi(Int32Constant(*index)),
BuildChangeUint31ToSmi(graph()->NewNode(machine->Word32And(), value,
Int32Constant(0xFFFFu))),
};
BuildCallToRuntime(Runtime::kWasmExceptionSetElement, lower_parameters,
arraysize(lower_parameters));
Node* lower_halfword_as_smi = BuildChangeUint31ToSmi(
graph()->NewNode(machine->Word32And(), value, Int32Constant(0xFFFFu)));
STORE_FIXED_ARRAY_SLOT(values_array, *index, lower_halfword_as_smi);
++(*index);
}
@ -2169,13 +2174,12 @@ Node** WasmGraphBuilder::GetExceptionValues(
// call causes an exception.
// Start by getting the encoded values from the exception.
Node* values_array =
BuildCallToRuntime(Runtime::kWasmExceptionGetValues, &except_obj, 1);
uint32_t encoded_size = GetExceptionEncodedSize(except_decl);
Node** values = Buffer(encoded_size);
for (uint32_t i = 0; i < encoded_size; ++i) {
Node* parameters[] = {except_obj,
BuildChangeUint31ToSmi(Uint32Constant(i))};
values[i] = BuildCallToRuntime(Runtime::kWasmExceptionGetElement,
parameters, arraysize(parameters));
values[i] = LOAD_FIXED_ARRAY_SLOT(values_array, i);
}
// Now convert the leading entries to the corresponding parameter values.
@ -5482,6 +5486,7 @@ AssemblerOptions WasmAssemblerOptions() {
#undef LOAD_INSTANCE_FIELD
#undef LOAD_TAGGED_POINTER
#undef LOAD_FIXED_ARRAY_SLOT
#undef STORE_FIXED_ARRAY_SLOT
} // namespace compiler
} // namespace internal

View File

@ -463,7 +463,7 @@ class WasmGraphBuilder {
Node* BuildAsmjsStoreMem(MachineType type, Node* index, Node* val);
uint32_t GetExceptionEncodedSize(const wasm::WasmException* exception) const;
void BuildEncodeException32BitValue(Node* except_obj, uint32_t* index,
void BuildEncodeException32BitValue(Node* values_array, uint32_t* index,
Node* value);
Node* BuildDecodeException32BitValue(Node* const* values, uint32_t* index);

View File

@ -142,10 +142,10 @@ RUNTIME_FUNCTION(Runtime_WasmExceptionGetTag) {
return ReadOnlyRoots(isolate).undefined_value();
}
RUNTIME_FUNCTION(Runtime_WasmExceptionGetElement) {
RUNTIME_FUNCTION(Runtime_WasmExceptionGetValues) {
// TODO(kschimpf): Can this be replaced with equivalent TurboFan code/calls.
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
DCHECK_EQ(1, args.length());
DCHECK_NULL(isolate->context());
isolate->set_context(GetNativeContextFromWasmInstanceOnStackTop(isolate));
CONVERT_ARG_CHECKED(Object, except_obj_raw, 0);
@ -153,45 +153,13 @@ RUNTIME_FUNCTION(Runtime_WasmExceptionGetElement) {
Handle<Object> except_obj(except_obj_raw, isolate);
if (!except_obj.is_null() && except_obj->IsJSReceiver()) {
Handle<JSReceiver> exception(JSReceiver::cast(*except_obj), isolate);
Handle<Object> values_obj;
Handle<Object> values;
if (JSReceiver::GetProperty(
isolate, exception,
isolate->factory()->wasm_exception_values_symbol())
.ToHandle(&values_obj)) {
if (values_obj->IsFixedArray()) {
Handle<FixedArray> values = Handle<FixedArray>::cast(values_obj);
CONVERT_SMI_ARG_CHECKED(index, 1);
CHECK_LT(index, values->length());
return values->get(index);
}
}
}
return Smi::FromInt(0);
}
RUNTIME_FUNCTION(Runtime_WasmExceptionSetElement) {
// TODO(kschimpf): Can this be replaced with equivalent TurboFan code/calls.
HandleScope scope(isolate);
DCHECK_EQ(3, args.length());
DCHECK_NULL(isolate->context());
isolate->set_context(GetNativeContextFromWasmInstanceOnStackTop(isolate));
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);
if (!except_obj.is_null() && except_obj->IsJSReceiver()) {
Handle<JSReceiver> exception(JSReceiver::cast(*except_obj), isolate);
Handle<Object> values_obj;
if (JSReceiver::GetProperty(
isolate, exception,
isolate->factory()->wasm_exception_values_symbol())
.ToHandle(&values_obj)) {
if (values_obj->IsFixedArray()) {
Handle<FixedArray> values = Handle<FixedArray>::cast(values_obj);
CONVERT_SMI_ARG_CHECKED(index, 1);
CHECK_LT(index, values->length());
CONVERT_ARG_CHECKED(Object, value, 2);
values->set(index, value);
}
.ToHandle(&values)) {
DCHECK(values->IsFixedArray());
return *values;
}
}
return ReadOnlyRoots(isolate).undefined_value();

View File

@ -536,8 +536,7 @@ namespace internal {
#define FOR_EACH_INTRINSIC_WASM(F, I) \
F(ThrowWasmError, 1, 1) \
F(ThrowWasmStackOverflow, 0, 1) \
F(WasmExceptionGetElement, 2, 1) \
F(WasmExceptionSetElement, 3, 1) \
F(WasmExceptionGetValues, 1, 1) \
F(WasmExceptionGetTag, 1, 1) \
F(WasmGrowMemory, 2, 1) \
F(WasmRunInterpreter, 2, 1) \