Commit ee159a4b authored by Jakob Kummerow's avatar Jakob Kummerow Committed by Commit Bot

[wasm-gc] Implement array.len

Bug: v8:7748
Change-Id: I736aaebb08be1d43662058f0ffde8b877b025017
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2193852Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67745}
parent fff219bf
......@@ -5185,11 +5185,15 @@ Node* ArrayElementOffset(GraphAssembler* gasm, Node* index,
gasm->Int32Constant(element_type.element_size_bytes())));
}
Node* ArrayLength(GraphAssembler* gasm, Node* array) {
return gasm->Load(
MachineType::Uint32(), array,
gasm->Int32Constant(WasmArray::kLengthOffset - kHeapObjectTag));
}
void WasmGraphBuilder::BoundsCheck(Node* array, Node* index,
wasm::WasmCodePosition position) {
Node* length = gasm_->Load(
MachineType::Uint32(), array,
gasm_->Int32Constant(WasmArray::kLengthOffset - kHeapObjectTag));
Node* length = ArrayLength(gasm_.get(), array);
TrapIfFalse(wasm::kTrapArrayOutOfBounds, gasm_->Uint32LessThan(index, length),
position);
}
......@@ -5221,6 +5225,13 @@ Node* WasmGraphBuilder::ArraySet(Node* array_object,
return gasm_->Store(rep, array_object, offset, value);
}
Node* WasmGraphBuilder::ArrayLen(Node* array_object,
wasm::WasmCodePosition position) {
TrapIfTrue(wasm::kTrapNullDereference,
gasm_->WordEqual(array_object, RefNull()), position);
return ArrayLength(gasm_.get(), array_object);
}
class WasmDecorator final : public GraphDecorator {
public:
explicit WasmDecorator(NodeOriginTable* origins, wasm::Decoder* decoder)
......
......@@ -390,6 +390,7 @@ class WasmGraphBuilder {
wasm::WasmCodePosition position);
Node* ArraySet(Node* array_object, const wasm::ArrayType* type, Node* index,
Node* value, wasm::WasmCodePosition position);
Node* ArrayLen(Node* array_object, wasm::WasmCodePosition position);
bool has_simd() const { return has_simd_; }
......
......@@ -3384,6 +3384,10 @@ class LiftoffCompiler {
// TODO(7748): Implement.
unsupported(decoder, kGC, "array.set");
}
void ArrayLen(FullDecoder* decoder, const Value& array_obj, Value* result) {
// TODO(7748): Implement.
unsupported(decoder, kGC, "array.len");
}
void PassThrough(FullDecoder* decoder, const Value& from, Value* to) {
// TODO(7748): Implement.
......
......@@ -925,6 +925,7 @@ enum class LoadTransformationKind : uint8_t {
F(ArraySet, const Value& array_obj, \
const ArrayIndexImmediate<validate>& imm, const Value& index, \
const Value& value) \
F(ArrayLen, const Value& array_obj, Value* result) \
F(PassThrough, const Value& from, Value* to)
// Generic Wasm bytecode decoder with utilities for decoding immediates,
......@@ -3100,11 +3101,15 @@ class WasmFullDecoder : public WasmDecoder<validate> {
CALL_INTERFACE_IF_REACHABLE(ArraySet, array_obj, imm, index, value);
break;
}
UNIMPLEMENTED(); // TODO(7748): Implement.
break;
case kExprArrayLen:
UNIMPLEMENTED(); // TODO(7748): Implement.
case kExprArrayLen: {
ArrayIndexImmediate<validate> imm(this, this->pc_ + len);
len += imm.length;
if (!this->Validate(this->pc_ + len, imm)) break;
auto array_obj = Pop(0, ValueType(ValueType::kOptRef, imm.index));
auto* value = Push(kWasmI32);
CALL_INTERFACE_IF_REACHABLE(ArrayLen, array_obj, value);
break;
}
default:
this->error("invalid gc opcode");
return 0;
......
......@@ -672,6 +672,10 @@ class WasmGraphBuildingInterface {
decoder->position());
}
void ArrayLen(FullDecoder* decoder, const Value& array_obj, Value* result) {
result->node = BUILD(ArrayLen, array_obj.node, decoder->position());
}
void PassThrough(FullDecoder* decoder, const Value& from, Value* to) {
to->node = from.node;
}
......
......@@ -201,6 +201,15 @@ WASM_EXEC_TEST(BasicArray) {
kExprEnd};
f->EmitCode(f_code, sizeof(f_code));
// Reads and returns an array's length.
WasmFunctionBuilder* g = builder->AddFunction(sigs.i_v());
f->builder()->AddExport(CStrVector("g"), g);
byte g_code[] = {
WASM_ARRAY_LEN(type_index,
WASM_ARRAY_NEW(type_index, WASM_I32V(0), WASM_I32V(42))),
kExprEnd};
g->EmitCode(g_code, sizeof(g_code));
WasmFunctionBuilder* h = builder->AddFunction(&sig_q_v);
h->builder()->AddExport(CStrVector("h"), h);
// Create an array of length 2, initialized to [42, 42].
......@@ -247,6 +256,9 @@ WASM_EXEC_TEST(BasicArray) {
isolate->clear_pending_exception();
}
CHECK_EQ(42, testing::CallWasmFunctionForTesting(isolate, instance, &thrower,
"g", 0, nullptr));
// TODO(7748): This uses the JavaScript interface to retrieve the plain
// WasmArray. Once the JS interaction story is settled, this may well
// need to be changed.
......
......@@ -443,6 +443,8 @@ inline WasmOpcode LoadStoreOpcodeOf(MachineType type, bool store) {
array, index, WASM_GC_OP(kExprArrayGet), static_cast<byte>(typeidx)
#define WASM_ARRAY_SET(typeidx, array, index, value) \
array, index, value, WASM_GC_OP(kExprArraySet), static_cast<byte>(typeidx)
#define WASM_ARRAY_LEN(typeidx, array) \
array, WASM_GC_OP(kExprArrayLen), static_cast<byte>(typeidx)
#define WASM_BR_ON_NULL(depth, ref_object) \
ref_object, kExprBrOnNull, static_cast<byte>(depth)
......
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