Commit 567a9bdf authored by Manos Koukoutos's avatar Manos Koukoutos Committed by Commit Bot

[wasm] Avoid runtime calls for exception handling

Motivation:
Improve code efficiency by replacing runtime calls with manually written
turbofan code where possible.

Changes:
- Remove the runtime functions `Runtime_WasmExceptionGetTag` and
  `Runtime_WasmExceptionGetValues` and replace them with turbofan code.
- Introduce the builtin function `GetOwnProperty`.
- Change `wasm-compiler.h` and `wasm-compiler.cc` to accomodate the new
  changes.
  - Introduce three new macros in `wasm-compiler.cc`.
  - Use those macros in two additional places to remove code
    duplication.

Change-Id: I4a32f9e5f7ee55dc50cd03378a68897888ece5c8
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2162905Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67530}
parent 0bd5bc2b
......@@ -846,6 +846,7 @@ namespace internal {
TFC(WasmTaggedToFloat64, WasmTaggedToFloat64) \
TFS(WasmAllocateJSArray, kArraySize) \
TFC(WasmAtomicNotify, WasmAtomicNotify) \
TFS(WasmGetOwnProperty, kObject, kUniqueName) \
TFC(WasmI32AtomicWait32, WasmI32AtomicWait32) \
TFC(WasmI32AtomicWait64, WasmI32AtomicWait64) \
TFC(WasmI64AtomicWait32, WasmI64AtomicWait32) \
......
......@@ -116,6 +116,37 @@ TF_BUILTIN(WasmAllocateJSArray, WasmBuiltinsAssembler) {
array_size, array_size));
}
TF_BUILTIN(WasmGetOwnProperty, CodeStubAssembler) {
TNode<Object> object = CAST(Parameter(Descriptor::kObject));
TNode<Name> unique_name = CAST(Parameter(Descriptor::kUniqueName));
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
TVariable<Object> var_value(this);
Label if_found(this), if_not_found(this), if_bailout(this);
GotoIf(TaggedIsSmi(object), &if_not_found);
GotoIf(IsUndefined(object), &if_not_found);
TNode<Map> map = LoadMap(CAST(object));
TNode<Uint16T> instance_type = LoadMapInstanceType(map);
GotoIfNot(IsJSReceiverInstanceType(instance_type), &if_not_found);
TryGetOwnProperty(context, CAST(object), CAST(object), map, instance_type,
unique_name, &if_found, &var_value, &if_not_found,
&if_bailout);
BIND(&if_found);
Return(var_value.value());
BIND(&if_not_found);
Return(UndefinedConstant());
BIND(&if_bailout); // This shouldn't happen when called from wasm compiler
Unreachable();
}
TF_BUILTIN(WasmAtomicNotify, WasmBuiltinsAssembler) {
TNode<Uint32T> address =
UncheckedCast<Uint32T>(Parameter(Descriptor::kAddress));
......
......@@ -11,7 +11,6 @@
#include "src/base/platform/platform.h"
#include "src/base/small-vector.h"
#include "src/base/v8-fallthrough.h"
#include "src/builtins/builtins.h"
#include "src/codegen/assembler-inl.h"
#include "src/codegen/assembler.h"
#include "src/codegen/code-factory.h"
......@@ -40,6 +39,7 @@
#include "src/logging/counters.h"
#include "src/logging/log.h"
#include "src/objects/heap-number.h"
#include "src/roots/roots.h"
#include "src/tracing/trace-event.h"
#include "src/trap-handler/trap-handler.h"
#include "src/utils/vector.h"
......@@ -78,6 +78,17 @@ MachineType assert_size(int expected_size, MachineType type) {
#define WASM_INSTANCE_OBJECT_OFFSET(name) \
wasm::ObjectAccess::ToTagged(WasmInstanceObject::k##name##Offset)
// We would like to use gasm_->Call() to implement this macro,
// but this doesn't work currently when we try to call it from functions
// which set IfSuccess/IfFailure control paths (e.g. within Throw()).
// TODO(manoskouk): Maybe clean this up at some point?
#define CALL_BUILTIN(name, ...) \
SetEffect(graph()->NewNode( \
mcgraph()->common()->Call(GetBuiltinCallDescriptor<name##Descriptor>( \
this, StubCallMode::kCallBuiltinPointer)), \
GetBuiltinPointerTarget(Builtins::k##name), ##__VA_ARGS__, effect(), \
control()))
#define LOAD_INSTANCE_FIELD(name, type) \
gasm_->Load(assert_size(WASM_INSTANCE_OBJECT_SIZE(name), type), \
instance_node_.get(), WASM_INSTANCE_OBJECT_OFFSET(name))
......@@ -269,9 +280,9 @@ Node* WasmGraphBuilder::EffectPhi(unsigned count, Node** effects_and_control) {
}
Node* WasmGraphBuilder::RefNull() {
Node* isolate_root = BuildLoadIsolateRoot();
return LOAD_FULL_POINTER(
isolate_root, IsolateData::root_slot_offset(RootIndex::kNullValue));
BuildLoadIsolateRoot(),
IsolateData::root_slot_offset(RootIndex::kNullValue));
}
Node* WasmGraphBuilder::RefFunc(uint32_t function_index) {
......@@ -2047,8 +2058,12 @@ Node* WasmGraphBuilder::Throw(uint32_t exception_index,
BuildCallToRuntime(Runtime::kWasmThrowCreate, create_parameters,
arraysize(create_parameters));
SetSourcePosition(except_obj, position);
Node* values_array =
BuildCallToRuntime(Runtime::kWasmExceptionGetValues, &except_obj, 1);
Node* values_array = CALL_BUILTIN(
WasmGetOwnProperty, except_obj,
LOAD_FULL_POINTER(BuildLoadIsolateRoot(),
IsolateData::root_slot_offset(
RootIndex::kwasm_exception_values_symbol)),
LOAD_INSTANCE_FIELD(NativeContext, MachineType::TaggedPointer()));
uint32_t index = 0;
const wasm::WasmExceptionSig* sig = exception->sig;
MachineOperatorBuilder* m = mcgraph()->machine();
......@@ -2187,14 +2202,23 @@ Node* WasmGraphBuilder::GetExceptionTag(Node* except_obj,
wasm::WasmCodePosition position) {
TrapIfTrue(wasm::kTrapBrOnExnNullRef, gasm_->WordEqual(RefNull(), except_obj),
position);
return BuildCallToRuntime(Runtime::kWasmExceptionGetTag, &except_obj, 1);
return CALL_BUILTIN(
WasmGetOwnProperty, except_obj,
LOAD_FULL_POINTER(
BuildLoadIsolateRoot(),
IsolateData::root_slot_offset(RootIndex::kwasm_exception_tag_symbol)),
LOAD_INSTANCE_FIELD(NativeContext, MachineType::TaggedPointer()));
}
Node* WasmGraphBuilder::GetExceptionValues(Node* except_obj,
const wasm::WasmException* exception,
Vector<Node*> values) {
Node* values_array =
BuildCallToRuntime(Runtime::kWasmExceptionGetValues, &except_obj, 1);
Node* values_array = CALL_BUILTIN(
WasmGetOwnProperty, except_obj,
LOAD_FULL_POINTER(BuildLoadIsolateRoot(),
IsolateData::root_slot_offset(
RootIndex::kwasm_exception_values_symbol)),
LOAD_INSTANCE_FIELD(NativeContext, MachineType::TaggedPointer()));
uint32_t index = 0;
const wasm::WasmExceptionSig* sig = exception->sig;
DCHECK_EQ(sig->parameter_count(), values.size());
......@@ -2540,6 +2564,11 @@ Node* WasmGraphBuilder::BuildI64RemU(Node* left, Node* right,
ZeroCheck64(wasm::kTrapRemByZero, right, position));
}
Node* WasmGraphBuilder::GetBuiltinPointerTarget(int builtin_id) {
static_assert(std::is_same<Smi, BuiltinPtr>(), "BuiltinPtr must be Smi");
return graph()->NewNode(mcgraph()->common()->NumberConstant(builtin_id));
}
Node* WasmGraphBuilder::BuildDiv64Call(Node* left, Node* right,
ExternalReference ref,
MachineType result_type,
......@@ -5095,11 +5124,6 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
return bigint_to_i64_descriptor_;
}
Node* GetBuiltinPointerTarget(Builtins::Name builtin_id) {
static_assert(std::is_same<Smi, BuiltinPtr>(), "BuiltinPtr must be Smi");
return graph()->NewNode(mcgraph()->common()->NumberConstant(builtin_id));
}
Node* GetTargetForBuiltinCall(wasm::WasmCode::RuntimeStubId wasm_stub,
Builtins::Name builtin_id) {
return (stub_mode_ == StubCallMode::kCallWasmRuntimeStub)
......@@ -5467,18 +5491,9 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
Node* BuildMultiReturnFixedArrayFromIterable(const wasm::FunctionSig* sig,
Node* iterable, Node* context) {
Node* iterable_to_fixed_array =
GetBuiltinPointerTarget(Builtins::kIterableToFixedArrayForWasm);
IterableToFixedArrayForWasmDescriptor interface_descriptor;
Node* length = BuildChangeUint31ToSmi(
Uint32Constant(static_cast<uint32_t>(sig->return_count())));
auto call_descriptor = Linkage::GetStubCallDescriptor(
mcgraph()->zone(), interface_descriptor,
interface_descriptor.GetStackParameterCount(), CallDescriptor::kNoFlags,
Operator::kNoProperties, StubCallMode::kCallBuiltinPointer);
return SetEffect(graph()->NewNode(
mcgraph()->common()->Call(call_descriptor), iterable_to_fixed_array,
iterable, length, context, effect(), control()));
return CALL_BUILTIN(IterableToFixedArrayForWasm, iterable, length, context);
}
// Extract the FixedArray implementing
......@@ -5494,11 +5509,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
// we make sure this is true based on statically known limits.
STATIC_ASSERT(wasm::kV8MaxWasmFunctionMultiReturns <=
JSArray::kInitialMaxFastElementArray);
auto call_descriptor =
GetBuiltinCallDescriptor<WasmAllocateJSArrayDescriptor>(
this, StubCallMode::kCallBuiltinPointer);
Node* call_target = GetBuiltinPointerTarget(Builtins::kWasmAllocateJSArray);
return gasm_->Call(call_descriptor, call_target, array_length, context);
return SetControl(CALL_BUILTIN(WasmAllocateJSArray, array_length, context));
}
void BuildJSToWasmWrapper(bool is_import) {
......@@ -7047,6 +7058,7 @@ AssemblerOptions WasmStubAssemblerOptions() {
}
#undef FATAL_UNSUPPORTED_OPCODE
#undef CALL_BUILTIN
#undef WASM_INSTANCE_OBJECT_SIZE
#undef WASM_INSTANCE_OBJECT_OFFSET
#undef LOAD_INSTANCE_FIELD
......
......@@ -457,6 +457,7 @@ class WasmGraphBuilder {
Node* BuildImportCall(const wasm::FunctionSig* sig, Vector<Node*> args,
Vector<Node*> rets, wasm::WasmCodePosition position,
Node* func_index, IsReturnCall continuation);
Node* GetBuiltinPointerTarget(int builtin_id);
Node* BuildF32CopySign(Node* left, Node* right);
Node* BuildF64CopySign(Node* left, Node* right);
......
......@@ -170,42 +170,6 @@ RUNTIME_FUNCTION(Runtime_WasmThrowCreate) {
return *exception;
}
RUNTIME_FUNCTION(Runtime_WasmExceptionGetTag) {
ClearThreadInWasmScope clear_wasm_flag;
// TODO(kschimpf): Can this be replaced with equivalent TurboFan code/calls.
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
DCHECK(isolate->context().is_null());
isolate->set_context(GetNativeContextFromWasmInstanceOnStackTop(isolate));
CONVERT_ARG_CHECKED(Object, except_obj_raw, 0);
// TODO(wasm): Manually box because parameters are not visited yet.
Handle<Object> except_obj(except_obj_raw, isolate);
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) {
ClearThreadInWasmScope clear_wasm_flag;
// TODO(kschimpf): Can this be replaced with equivalent TurboFan code/calls.
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
DCHECK(isolate->context().is_null());
isolate->set_context(GetNativeContextFromWasmInstanceOnStackTop(isolate));
CONVERT_ARG_CHECKED(Object, except_obj_raw, 0);
// TODO(wasm): Manually box because parameters are not visited yet.
Handle<Object> except_obj(except_obj_raw, isolate);
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) {
ClearThreadInWasmScope wasm_flag;
HandleScope scope(isolate);
......
......@@ -558,8 +558,6 @@ namespace internal {
F(WasmI32AtomicWait, 4, 1) \
F(WasmI64AtomicWait, 5, 1) \
F(WasmAtomicNotify, 3, 1) \
F(WasmExceptionGetValues, 1, 1) \
F(WasmExceptionGetTag, 1, 1) \
F(WasmMemoryGrow, 2, 1) \
F(WasmRunInterpreter, 2, 1) \
F(WasmStackGuard, 0, 1) \
......
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