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, ...@@ -5185,11 +5185,15 @@ Node* ArrayElementOffset(GraphAssembler* gasm, Node* index,
gasm->Int32Constant(element_type.element_size_bytes()))); 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, void WasmGraphBuilder::BoundsCheck(Node* array, Node* index,
wasm::WasmCodePosition position) { wasm::WasmCodePosition position) {
Node* length = gasm_->Load( Node* length = ArrayLength(gasm_.get(), array);
MachineType::Uint32(), array,
gasm_->Int32Constant(WasmArray::kLengthOffset - kHeapObjectTag));
TrapIfFalse(wasm::kTrapArrayOutOfBounds, gasm_->Uint32LessThan(index, length), TrapIfFalse(wasm::kTrapArrayOutOfBounds, gasm_->Uint32LessThan(index, length),
position); position);
} }
...@@ -5221,6 +5225,13 @@ Node* WasmGraphBuilder::ArraySet(Node* array_object, ...@@ -5221,6 +5225,13 @@ Node* WasmGraphBuilder::ArraySet(Node* array_object,
return gasm_->Store(rep, array_object, offset, value); 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 { class WasmDecorator final : public GraphDecorator {
public: public:
explicit WasmDecorator(NodeOriginTable* origins, wasm::Decoder* decoder) explicit WasmDecorator(NodeOriginTable* origins, wasm::Decoder* decoder)
......
...@@ -390,6 +390,7 @@ class WasmGraphBuilder { ...@@ -390,6 +390,7 @@ class WasmGraphBuilder {
wasm::WasmCodePosition position); wasm::WasmCodePosition position);
Node* ArraySet(Node* array_object, const wasm::ArrayType* type, Node* index, Node* ArraySet(Node* array_object, const wasm::ArrayType* type, Node* index,
Node* value, wasm::WasmCodePosition position); Node* value, wasm::WasmCodePosition position);
Node* ArrayLen(Node* array_object, wasm::WasmCodePosition position);
bool has_simd() const { return has_simd_; } bool has_simd() const { return has_simd_; }
......
...@@ -3384,6 +3384,10 @@ class LiftoffCompiler { ...@@ -3384,6 +3384,10 @@ class LiftoffCompiler {
// TODO(7748): Implement. // TODO(7748): Implement.
unsupported(decoder, kGC, "array.set"); 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) { void PassThrough(FullDecoder* decoder, const Value& from, Value* to) {
// TODO(7748): Implement. // TODO(7748): Implement.
......
...@@ -925,6 +925,7 @@ enum class LoadTransformationKind : uint8_t { ...@@ -925,6 +925,7 @@ enum class LoadTransformationKind : uint8_t {
F(ArraySet, const Value& array_obj, \ F(ArraySet, const Value& array_obj, \
const ArrayIndexImmediate<validate>& imm, const Value& index, \ const ArrayIndexImmediate<validate>& imm, const Value& index, \
const Value& value) \ const Value& value) \
F(ArrayLen, const Value& array_obj, Value* result) \
F(PassThrough, const Value& from, Value* to) F(PassThrough, const Value& from, Value* to)
// Generic Wasm bytecode decoder with utilities for decoding immediates, // Generic Wasm bytecode decoder with utilities for decoding immediates,
...@@ -3100,11 +3101,15 @@ class WasmFullDecoder : public WasmDecoder<validate> { ...@@ -3100,11 +3101,15 @@ class WasmFullDecoder : public WasmDecoder<validate> {
CALL_INTERFACE_IF_REACHABLE(ArraySet, array_obj, imm, index, value); CALL_INTERFACE_IF_REACHABLE(ArraySet, array_obj, imm, index, value);
break; break;
} }
UNIMPLEMENTED(); // TODO(7748): Implement. case kExprArrayLen: {
break; ArrayIndexImmediate<validate> imm(this, this->pc_ + len);
case kExprArrayLen: len += imm.length;
UNIMPLEMENTED(); // TODO(7748): Implement. 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; break;
}
default: default:
this->error("invalid gc opcode"); this->error("invalid gc opcode");
return 0; return 0;
......
...@@ -672,6 +672,10 @@ class WasmGraphBuildingInterface { ...@@ -672,6 +672,10 @@ class WasmGraphBuildingInterface {
decoder->position()); 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) { void PassThrough(FullDecoder* decoder, const Value& from, Value* to) {
to->node = from.node; to->node = from.node;
} }
......
...@@ -201,6 +201,15 @@ WASM_EXEC_TEST(BasicArray) { ...@@ -201,6 +201,15 @@ WASM_EXEC_TEST(BasicArray) {
kExprEnd}; kExprEnd};
f->EmitCode(f_code, sizeof(f_code)); 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); WasmFunctionBuilder* h = builder->AddFunction(&sig_q_v);
h->builder()->AddExport(CStrVector("h"), h); h->builder()->AddExport(CStrVector("h"), h);
// Create an array of length 2, initialized to [42, 42]. // Create an array of length 2, initialized to [42, 42].
...@@ -247,6 +256,9 @@ WASM_EXEC_TEST(BasicArray) { ...@@ -247,6 +256,9 @@ WASM_EXEC_TEST(BasicArray) {
isolate->clear_pending_exception(); 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 // TODO(7748): This uses the JavaScript interface to retrieve the plain
// WasmArray. Once the JS interaction story is settled, this may well // WasmArray. Once the JS interaction story is settled, this may well
// need to be changed. // need to be changed.
......
...@@ -443,6 +443,8 @@ inline WasmOpcode LoadStoreOpcodeOf(MachineType type, bool store) { ...@@ -443,6 +443,8 @@ inline WasmOpcode LoadStoreOpcodeOf(MachineType type, bool store) {
array, index, WASM_GC_OP(kExprArrayGet), static_cast<byte>(typeidx) array, index, WASM_GC_OP(kExprArrayGet), static_cast<byte>(typeidx)
#define WASM_ARRAY_SET(typeidx, array, index, value) \ #define WASM_ARRAY_SET(typeidx, array, index, value) \
array, index, value, WASM_GC_OP(kExprArraySet), static_cast<byte>(typeidx) 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) \ #define WASM_BR_ON_NULL(depth, ref_object) \
ref_object, kExprBrOnNull, static_cast<byte>(depth) 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