[wasm-gc] Implement array.len
Bug: v8:7748 Change-Id: I736aaebb08be1d43662058f0ffde8b877b025017 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2193852 Reviewed-by: Andreas Haas <ahaas@chromium.org> Commit-Queue: Jakob Kummerow <jkummerow@chromium.org> Cr-Commit-Position: refs/heads/master@{#67745}
This commit is contained in:
parent
fff219bff7
commit
ee159a4bac
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user