[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:
parent
15f0263f12
commit
99dcc4cd94
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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) \
|
||||
|
Loading…
Reference in New Issue
Block a user