Commit ae2a8ac4 authored by Bill Budge's avatar Bill Budge Committed by Commit Bot

[wasm] Torqueify WasmTableGet, WasmTableSet, and WasmRefFunc

- Port WasmTableGet, WasmTableSet, and WasmRefFunc to Torque.
- Breaks WasmBuiltinsAssembler into .cc and .h files.

Change-Id: I0f62715ce10beedabf7b4f9502c9476de9efdd5a
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2175090
Commit-Queue: Bill Budge <bbudge@chromium.org>
Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67575}
parent 4ca768db
......@@ -1654,6 +1654,7 @@ v8_source_set("v8_initializers") {
"src/builtins/builtins-typed-array-gen.h",
"src/builtins/builtins-utils-gen.h",
"src/builtins/builtins-wasm-gen.cc",
"src/builtins/builtins-wasm-gen.h",
"src/builtins/growable-fixed-array-gen.cc",
"src/builtins/growable-fixed-array-gen.h",
"src/builtins/setup-builtins-internal.cc",
......
......@@ -307,6 +307,7 @@ extern enum MessageTemplate {
kProxySetPrototypeOfNonExtensible,
kProxyDeletePropertyNonExtensible,
kWeakRefsCleanupMustBeCallable,
kWasmTrapTableOutOfBounds,
...
}
......@@ -646,6 +647,7 @@ extern macro IsFastAliasedArgumentsMap(implicit context: Context)(Map): bool;
extern macro IsSlowAliasedArgumentsMap(implicit context: Context)(Map): bool;
extern macro IsSloppyArgumentsMap(implicit context: Context)(Map): bool;
extern macro IsStrictArgumentsMap(implicit context: Context)(Map): bool;
extern macro IsTuple2Map(Map): bool;
extern macro SmiAbove(Smi, Smi): bool;
......@@ -884,6 +886,7 @@ extern macro TruncateIntPtrToInt32(intptr): int32;
extern macro SmiTag(intptr): Smi;
extern macro SmiFromInt32(int32): Smi;
extern macro SmiFromUint32(uint32): Smi;
extern macro SmiFromIntPtr(intptr): Smi;
extern macro SmiUntag(Smi): intptr;
macro SmiUntag<T: type>(value: SmiTagged<T>): T {
return %RawDownCast<T>(Unsigned(SmiToInt32(Convert<Smi>(value))));
......
......@@ -849,11 +849,8 @@ namespace internal {
TFC(WasmI64AtomicWait32, WasmI64AtomicWait32) \
TFC(WasmI64AtomicWait64, WasmI64AtomicWait64) \
TFC(WasmMemoryGrow, WasmMemoryGrow) \
TFC(WasmRefFunc, WasmRefFunc) \
TFC(WasmTableInit, WasmTableInit) \
TFC(WasmTableCopy, WasmTableCopy) \
TFC(WasmTableGet, WasmTableGet) \
TFC(WasmTableSet, WasmTableSet) \
TFC(WasmStackGuard, NoContext) \
TFC(WasmStackOverflow, NoContext) \
TFC(WasmThrow, WasmThrow) \
......
......@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/builtins/builtins-wasm-gen.h"
#include "src/builtins/builtins-utils-gen.h"
#include "src/codegen/code-stub-assembler.h"
#include "src/codegen/interface-descriptors.h"
......@@ -12,30 +14,37 @@
namespace v8 {
namespace internal {
class WasmBuiltinsAssembler : public CodeStubAssembler {
public:
explicit WasmBuiltinsAssembler(compiler::CodeAssemblerState* state)
: CodeStubAssembler(state) {}
TNode<WasmInstanceObject> WasmBuiltinsAssembler::LoadInstanceFromFrame() {
return CAST(
LoadFromParentFrame(WasmCompiledFrameConstants::kWasmInstanceOffset));
}
protected:
TNode<WasmInstanceObject> LoadInstanceFromFrame() {
return CAST(
LoadFromParentFrame(WasmCompiledFrameConstants::kWasmInstanceOffset));
}
TNode<Context> WasmBuiltinsAssembler::LoadContextFromInstance(
TNode<WasmInstanceObject> instance) {
return CAST(Load(MachineType::AnyTagged(), instance,
IntPtrConstant(WasmInstanceObject::kNativeContextOffset -
kHeapObjectTag)));
}
TNode<Context> LoadContextFromInstance(TNode<WasmInstanceObject> instance) {
return CAST(Load(MachineType::AnyTagged(), instance,
IntPtrConstant(WasmInstanceObject::kNativeContextOffset -
kHeapObjectTag)));
}
TNode<FixedArray> WasmBuiltinsAssembler::LoadTablesFromInstance(
TNode<WasmInstanceObject> instance) {
return LoadObjectField<FixedArray>(instance,
WasmInstanceObject::kTablesOffset);
}
TNode<Smi> SmiFromUint32WithSaturation(TNode<Uint32T> value, uint32_t max) {
DCHECK_LE(max, static_cast<uint32_t>(Smi::kMaxValue));
TNode<Uint32T> capped_value = SelectConstant(
Uint32LessThan(value, Uint32Constant(max)), value, Uint32Constant(max));
return SmiFromUint32(capped_value);
}
};
TNode<FixedArray> WasmBuiltinsAssembler::LoadExternalFunctionsFromInstance(
TNode<WasmInstanceObject> instance) {
return LoadObjectField<FixedArray>(
instance, WasmInstanceObject::kWasmExternalFunctionsOffset);
}
TNode<Smi> WasmBuiltinsAssembler::SmiFromUint32WithSaturation(
TNode<Uint32T> value, uint32_t max) {
DCHECK_LE(max, static_cast<uint32_t>(Smi::kMaxValue));
TNode<Uint32T> capped_value = SelectConstant(
Uint32LessThan(value, Uint32Constant(max)), value, Uint32Constant(max));
return SmiFromUint32(capped_value);
}
TF_BUILTIN(WasmFloat32ToNumber, WasmBuiltinsAssembler) {
TNode<Float32T> val = UncheckedCast<Float32T>(Parameter(Descriptor::kValue));
......@@ -282,32 +291,6 @@ TF_BUILTIN(WasmMemoryGrow, WasmBuiltinsAssembler) {
Return(Int32Constant(-1));
}
TF_BUILTIN(WasmRefFunc, WasmBuiltinsAssembler) {
TNode<WasmInstanceObject> instance = LoadInstanceFromFrame();
Label call_runtime(this, Label::kDeferred);
TNode<Uint32T> raw_index =
UncheckedCast<Uint32T>(Parameter(Descriptor::kFunctionIndex));
TNode<FixedArray> table = LoadObjectField<FixedArray>(
instance, WasmInstanceObject::kWasmExternalFunctionsOffset);
GotoIf(IsUndefined(table), &call_runtime);
TNode<IntPtrT> function_index =
UncheckedCast<IntPtrT>(ChangeUint32ToWord(raw_index));
// Function index should be in range.
TNode<Object> result = LoadFixedArrayElement(table, function_index);
GotoIf(IsUndefined(result), &call_runtime);
Return(result);
BIND(&call_runtime);
// Fall back to the runtime call for more complex cases.
// function_index is known to be in Smi range.
TailCallRuntime(Runtime::kWasmRefFunc, LoadContextFromInstance(instance),
instance, SmiFromUint32(raw_index));
}
TF_BUILTIN(WasmTableInit, WasmBuiltinsAssembler) {
TNode<Uint32T> dst_raw =
UncheckedCast<Uint32T>(Parameter(Descriptor::kDestination));
......@@ -368,103 +351,6 @@ TF_BUILTIN(WasmTableCopy, WasmBuiltinsAssembler) {
src_table, dst, src, size);
}
TF_BUILTIN(WasmTableGet, WasmBuiltinsAssembler) {
TNode<WasmInstanceObject> instance = LoadInstanceFromFrame();
Label call_runtime(this, Label::kDeferred),
index_out_of_range(this, Label::kDeferred);
TNode<IntPtrT> table_index =
UncheckedCast<IntPtrT>(Parameter(Descriptor::kTableIndex));
GotoIfNot(IsValidPositiveSmi(table_index), &index_out_of_range);
TNode<IntPtrT> entry_index = ChangeInt32ToIntPtr(
UncheckedCast<Int32T>(Parameter(Descriptor::kEntryIndex)));
GotoIfNot(IsValidPositiveSmi(entry_index), &index_out_of_range);
TNode<FixedArray> tables_array =
LoadObjectField<FixedArray>(instance, WasmInstanceObject::kTablesOffset);
TNode<WasmTableObject> table =
CAST(LoadFixedArrayElement(tables_array, table_index));
TNode<IntPtrT> entries_length =
LoadAndUntagObjectField(table, WasmTableObject::kCurrentLengthOffset);
GotoIfNot(IntPtrLessThan(entry_index, entries_length), &index_out_of_range);
TNode<FixedArray> entries_array =
LoadObjectField<FixedArray>(table, WasmTableObject::kEntriesOffset);
TNode<Object> entry = LoadFixedArrayElement(entries_array, entry_index);
// If the entry is our placeholder for lazy function initialization, then we
// fall back to the runtime call.
TNode<Map> map = LoadReceiverMap(entry);
GotoIf(IsTuple2Map(map), &call_runtime);
Return(entry);
BIND(&call_runtime);
// Fall back to the runtime call for more complex cases.
// table_index and entry_index must be in Smi range, due to checks above.
TailCallRuntime(Runtime::kWasmFunctionTableGet,
LoadContextFromInstance(instance), instance,
SmiFromIntPtr(table_index), SmiFromIntPtr(entry_index));
BIND(&index_out_of_range);
MessageTemplate message_id =
wasm::WasmOpcodes::TrapReasonToMessageId(wasm::kTrapTableOutOfBounds);
TailCallRuntime(Runtime::kThrowWasmError, LoadContextFromInstance(instance),
SmiConstant(static_cast<int>(message_id)));
}
TF_BUILTIN(WasmTableSet, WasmBuiltinsAssembler) {
TNode<WasmInstanceObject> instance = LoadInstanceFromFrame();
Label call_runtime(this, Label::kDeferred),
index_out_of_range(this, Label::kDeferred);
TNode<IntPtrT> table_index =
UncheckedCast<IntPtrT>(Parameter(Descriptor::kTableIndex));
GotoIfNot(IsValidPositiveSmi(table_index), &index_out_of_range);
TNode<IntPtrT> entry_index = ChangeInt32ToIntPtr(
UncheckedCast<Int32T>(Parameter(Descriptor::kEntryIndex)));
GotoIfNot(IsValidPositiveSmi(entry_index), &index_out_of_range);
TNode<Object> value = CAST(Parameter(Descriptor::kValue));
TNode<FixedArray> tables_array =
LoadObjectField<FixedArray>(instance, WasmInstanceObject::kTablesOffset);
TNode<WasmTableObject> table =
CAST(LoadFixedArrayElement(tables_array, table_index));
// Fall back to the runtime to set funcrefs, since we have to update function
// dispatch tables.
TNode<Smi> table_type =
LoadObjectField<Smi>(table, WasmTableObject::kRawTypeOffset);
GotoIf(SmiEqual(table_type, SmiConstant(wasm::ValueType::Kind::kFuncRef)),
&call_runtime);
TNode<IntPtrT> entries_length =
LoadAndUntagObjectField(table, WasmTableObject::kCurrentLengthOffset);
GotoIfNot(IntPtrLessThan(entry_index, entries_length), &index_out_of_range);
TNode<FixedArray> entries_array =
LoadObjectField<FixedArray>(table, WasmTableObject::kEntriesOffset);
StoreFixedArrayElement(entries_array, entry_index, value);
Return(UndefinedConstant());
BIND(&call_runtime);
// Fall back to the runtime call for more complex cases.
// table_index and entry_index must be in Smi range, due to checks above.
TailCallRuntime(
Runtime::kWasmFunctionTableSet, LoadContextFromInstance(instance),
instance, SmiFromIntPtr(table_index), SmiFromIntPtr(entry_index), value);
BIND(&index_out_of_range);
MessageTemplate message_id =
wasm::WasmOpcodes::TrapReasonToMessageId(wasm::kTrapTableOutOfBounds);
TailCallRuntime(Runtime::kThrowWasmError, LoadContextFromInstance(instance),
SmiConstant(static_cast<int>(message_id)));
}
#define DECLARE_THROW_RUNTIME_FN(name) \
TF_BUILTIN(ThrowWasm##name, WasmBuiltinsAssembler) { \
TNode<WasmInstanceObject> instance = LoadInstanceFromFrame(); \
......
// Copyright 2020 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.
#ifndef V8_BUILTINS_BUILTINS_WASM_GEN_H_
#define V8_BUILTINS_BUILTINS_WASM_GEN_H_
#include "src/codegen/code-stub-assembler.h"
namespace v8 {
namespace internal {
class WasmBuiltinsAssembler : public CodeStubAssembler {
public:
explicit WasmBuiltinsAssembler(compiler::CodeAssemblerState* state)
: CodeStubAssembler(state) {}
TNode<WasmInstanceObject> LoadInstanceFromFrame();
TNode<Context> LoadContextFromInstance(TNode<WasmInstanceObject> instance);
TNode<FixedArray> LoadTablesFromInstance(TNode<WasmInstanceObject> instance);
TNode<FixedArray> LoadExternalFunctionsFromInstance(
TNode<WasmInstanceObject> instance);
protected:
TNode<Smi> SmiFromUint32WithSaturation(TNode<Uint32T> value, uint32_t max);
};
} // namespace internal
} // namespace v8
#endif // V8_BUILTINS_BUILTINS_WASM_GEN_H_
......@@ -30,6 +30,7 @@ extern macro IsNumberNormalized(Number): bool;
extern macro IsSafeInteger(Object): bool;
extern macro IsOddball(HeapObject): bool;
extern macro IsSymbol(HeapObject): bool;
extern macro IsTuple2(HeapObject): bool;
extern macro IsJSArrayMap(Map): bool;
extern macro IsExtensibleMap(Map): bool;
extern macro IsJSPrimitiveWrapper(HeapObject): bool;
......
......@@ -2,7 +2,33 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include 'src/builtins/builtins-wasm-gen.h'
namespace runtime {
extern runtime WasmRefFunc(Context, WasmInstanceObject, Smi): JSAny;
extern runtime WasmFunctionTableGet(Context, WasmInstanceObject, Smi, Smi):
JSAny;
extern runtime WasmFunctionTableSet(
Context, WasmInstanceObject, Smi, Smi, Object): JSAny;
extern runtime ThrowWasmError(Context, Smi): JSAny;
}
namespace wasm {
const kFuncTableType: constexpr int31
generates 'wasm::ValueType::Kind::kFuncRef';
extern macro WasmBuiltinsAssembler::LoadInstanceFromFrame():
WasmInstanceObject;
// WasmInstanceObject has a field layout that Torque can't handle yet.
// TODO(bbudge) Eliminate these functions when Torque is ready.
extern macro WasmBuiltinsAssembler::LoadContextFromInstance(
WasmInstanceObject): Context;
extern macro WasmBuiltinsAssembler::LoadTablesFromInstance(
WasmInstanceObject): FixedArray;
extern macro WasmBuiltinsAssembler::LoadExternalFunctionsFromInstance(
WasmInstanceObject): FixedArray;
builtin WasmInt32ToHeapNumber(val: int32): HeapNumber {
return AllocateHeapNumberWithValue(Convert<float64>(val));
}
......@@ -15,4 +41,94 @@ namespace wasm {
builtin WasmTaggedToFloat64(implicit context: Context)(val: JSAny): float64 {
return ChangeTaggedToFloat64(val);
}
builtin WasmTableGet(tableIndex: intptr, index: int32): Object {
const instance: WasmInstanceObject = LoadInstanceFromFrame();
const entryIndex: intptr = ChangeInt32ToIntPtr(index);
try {
assert(IsValidPositiveSmi(tableIndex));
if (!IsValidPositiveSmi(entryIndex)) goto IndexOutOfRange;
const tables: FixedArray = LoadTablesFromInstance(instance);
const table: WasmTableObject = %RawDownCast<WasmTableObject>(
LoadFixedArrayElement(tables, tableIndex));
const entriesCount: intptr = Convert<intptr, Smi>(table.current_length);
if (entryIndex >= entriesCount) goto IndexOutOfRange;
const entries: FixedArray = table.entries;
const entry: Object = LoadFixedArrayElement(entries, entryIndex);
try {
const entryObject: HeapObject =
TaggedToHeapObject<HeapObject>(entry) otherwise ReturnEntry;
if (IsTuple2Map(entryObject.map)) goto CallRuntime;
goto ReturnEntry;
}
label ReturnEntry {
return entry;
}
}
label CallRuntime deferred {
tail runtime::WasmFunctionTableGet(
LoadContextFromInstance(instance), instance,
SmiFromIntPtr(tableIndex), SmiFromIntPtr(entryIndex));
}
label IndexOutOfRange deferred {
tail runtime::ThrowWasmError(
LoadContextFromInstance(instance),
SmiConstant(MessageTemplate::kWasmTrapTableOutOfBounds));
}
}
builtin WasmTableSet(tableIndex: intptr, index: int32, value: Object):
Object {
const instance: WasmInstanceObject = LoadInstanceFromFrame();
const entryIndex: intptr = ChangeInt32ToIntPtr(index);
try {
assert(IsValidPositiveSmi(tableIndex));
if (!IsValidPositiveSmi(entryIndex)) goto IndexOutOfRange;
const tables: FixedArray = LoadTablesFromInstance(instance);
const table: WasmTableObject = %RawDownCast<WasmTableObject>(
LoadFixedArrayElement(tables, tableIndex));
// Fall back to the runtime to set funcrefs, since we have to update
// function dispatch tables.
const tableType: Smi = table.raw_type;
if (tableType == SmiConstant(kFuncTableType)) goto CallRuntime;
const entriesCount: intptr = Convert<intptr, Smi>(table.current_length);
if (entryIndex >= entriesCount) goto IndexOutOfRange;
const entries: FixedArray = table.entries;
StoreFixedArrayElement(entries, entryIndex, value);
return Undefined;
}
label CallRuntime deferred {
tail runtime::WasmFunctionTableSet(
LoadContextFromInstance(instance), instance,
SmiFromIntPtr(tableIndex), SmiFromIntPtr(entryIndex), value);
}
label IndexOutOfRange deferred {
tail runtime::ThrowWasmError(
LoadContextFromInstance(instance),
SmiConstant(MessageTemplate::kWasmTrapTableOutOfBounds));
}
}
builtin WasmRefFunc(index: uint32): Object {
const instance: WasmInstanceObject = LoadInstanceFromFrame();
try {
const table: FixedArray = LoadExternalFunctionsFromInstance(instance);
if (table == Undefined) goto CallRuntime;
const functionIndex: intptr = Signed(ChangeUint32ToWord(index));
const result: Object = LoadFixedArrayElement(table, functionIndex);
if (result == Undefined) goto CallRuntime;
return result;
}
label CallRuntime deferred {
tail runtime::WasmRefFunc(
LoadContextFromInstance(instance), instance, SmiFromUint32(index));
}
}
}
......@@ -396,11 +396,6 @@ void WasmMemoryGrowDescriptor::InitializePlatformSpecific(
DefaultInitializePlatformSpecific(data, kParameterCount);
}
void WasmRefFuncDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, kParameterCount);
}
void WasmTableInitDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data,
......@@ -413,16 +408,6 @@ void WasmTableCopyDescriptor::InitializePlatformSpecific(
kParameterCount - kStackArgumentsCount);
}
void WasmTableGetDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, kParameterCount);
}
void WasmTableSetDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, kParameterCount);
}
void WasmThrowDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, kParameterCount);
......
......@@ -98,11 +98,8 @@ namespace internal {
V(WasmI64AtomicWait32) \
V(WasmI64AtomicWait64) \
V(WasmMemoryGrow) \
V(WasmRefFunc) \
V(WasmTableInit) \
V(WasmTableCopy) \
V(WasmTableGet) \
V(WasmTableSet) \
V(WasmThrow) \
BUILTIN_LIST_TFS(V) \
TORQUE_BUILTIN_LIST_TFC(V)
......@@ -1339,14 +1336,6 @@ class WasmMemoryGrowDescriptor final : public CallInterfaceDescriptor {
DECLARE_DESCRIPTOR(WasmMemoryGrowDescriptor, CallInterfaceDescriptor)
};
class WasmRefFuncDescriptor final : public CallInterfaceDescriptor {
public:
DEFINE_PARAMETERS_NO_CONTEXT(kFunctionIndex)
DEFINE_RESULT_AND_PARAMETER_TYPES(MachineType::AnyTagged(), // result
MachineType::Uint32()) // kFunctionIndex
DECLARE_DESCRIPTOR(WasmRefFuncDescriptor, CallInterfaceDescriptor)
};
class WasmTableInitDescriptor final : public CallInterfaceDescriptor {
public:
DEFINE_PARAMETERS_NO_CONTEXT(kDestination, kSource, kSize, kTableIndex,
......@@ -1393,24 +1382,6 @@ class WasmTableCopyDescriptor final : public CallInterfaceDescriptor {
DECLARE_DESCRIPTOR(WasmTableCopyDescriptor, CallInterfaceDescriptor)
};
class WasmTableGetDescriptor final : public CallInterfaceDescriptor {
public:
DEFINE_PARAMETERS_NO_CONTEXT(kTableIndex, kEntryIndex)
DEFINE_RESULT_AND_PARAMETER_TYPES(MachineType::AnyTagged(), // result
MachineType::IntPtr(), // kTableIndex
MachineType::Int32()) // kEntryIndex
DECLARE_DESCRIPTOR(WasmTableGetDescriptor, CallInterfaceDescriptor)
};
class WasmTableSetDescriptor final : public CallInterfaceDescriptor {
public:
DEFINE_PARAMETERS_NO_CONTEXT(kTableIndex, kEntryIndex, kValue)
DEFINE_PARAMETER_TYPES(MachineType::IntPtr(), // kTableIndex
MachineType::Int32(), // kEntryIndex
MachineType::AnyTagged()) // kValue
DECLARE_DESCRIPTOR(WasmTableSetDescriptor, CallInterfaceDescriptor)
};
class WasmThrowDescriptor final : public CallInterfaceDescriptor {
public:
DEFINE_PARAMETERS_NO_CONTEXT(kException)
......
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