Skip to content

Commit 12c7cca

Browse files
committed
wasm-interp: Handle Refs
1 parent 7d229cf commit 12c7cca

File tree

5 files changed

+73
-7
lines changed

5 files changed

+73
-7
lines changed

include/wabt/interp/interp.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@ struct LocalDesc {
295295
struct CatchDesc {
296296
Index tag_index;
297297
u32 offset;
298+
bool ref = false;
298299
};
299300

300301
// Handlers for a catch-less `try` or `try-catch` block are included in the
@@ -313,6 +314,7 @@ struct HandlerDesc {
313314
// Local stack heights at the handler site that need to be restored.
314315
u32 values;
315316
u32 exceptions;
317+
bool catch_all_ref = false;
316318
};
317319

318320
struct FuncDesc {
@@ -1132,6 +1134,8 @@ class Thread {
11321134
void Push(Value);
11331135
void Push(Ref);
11341136

1137+
void SetRef(Index);
1138+
11351139
template <typename R, typename T>
11361140
using UnopFunc = R WABT_VECTORCALL(T);
11371141
template <typename R, typename T>

include/wabt/opcode.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,10 @@ WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xe3, InterpData, "data", "")
233233
WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xe4, InterpDropKeep, "drop_keep", "")
234234
WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xe5, InterpCatchDrop, "catch_drop", "")
235235
WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xe6, InterpAdjustFrameForReturnCall, "adjust_frame_for_return_call", "")
236+
WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xe7, InterpGlobalGetRef, "global.get.ref", "")
237+
WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xe9, InterpLocalGetRef, "local.get.ref", "")
238+
WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xea, InterpLocalSetRef, "local.set.ref", "")
239+
WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xeb, InterpLocalTeeRef, "local.tee.ref", "")
236240

237241
/* Saturating float-to-int opcodes (--enable-saturating-float-to-int) */
238242
WABT_OPCODE(I32, F32, ___, ___, 0, 0xfc, 0x00, I32TruncSatF32S, "i32.trunc_sat_f32_s", "")

src/interp/binary-reader-interp.cc

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1254,7 +1254,13 @@ Result BinaryReaderInterp::OnV128ConstExpr(v128 value_bits) {
12541254
Result BinaryReaderInterp::OnGlobalGetExpr(Index global_index) {
12551255
CHECK_RESULT(
12561256
validator_.OnGlobalGet(GetLocation(), Var(global_index, GetLocation())));
1257-
istream_.Emit(Opcode::GlobalGet, global_index);
1257+
1258+
Type type = global_types_.at(global_index).type;
1259+
if (type.IsRef()) {
1260+
istream_.Emit(Opcode::InterpGlobalGetRef, global_index);
1261+
} else {
1262+
istream_.Emit(Opcode::GlobalGet, global_index);
1263+
}
12581264
return Result::Ok;
12591265
}
12601266

@@ -1277,7 +1283,13 @@ Result BinaryReaderInterp::OnLocalGetExpr(Index local_index) {
12771283
Index translated_local_index = TranslateLocalIndex(local_index);
12781284
CHECK_RESULT(
12791285
validator_.OnLocalGet(GetLocation(), Var(local_index, GetLocation())));
1280-
istream_.Emit(Opcode::LocalGet, translated_local_index);
1286+
1287+
Type type = func_->GetLocalType(local_index);
1288+
if (type.IsRef()) {
1289+
istream_.Emit(Opcode::InterpLocalGetRef, translated_local_index);
1290+
} else {
1291+
istream_.Emit(Opcode::LocalGet, translated_local_index);
1292+
}
12811293
return Result::Ok;
12821294
}
12831295

@@ -1286,14 +1298,26 @@ Result BinaryReaderInterp::OnLocalSetExpr(Index local_index) {
12861298
Index translated_local_index = TranslateLocalIndex(local_index);
12871299
CHECK_RESULT(
12881300
validator_.OnLocalSet(GetLocation(), Var(local_index, GetLocation())));
1289-
istream_.Emit(Opcode::LocalSet, translated_local_index);
1301+
1302+
Type type = func_->GetLocalType(local_index);
1303+
if (type.IsRef()) {
1304+
istream_.Emit(Opcode::InterpLocalSetRef, translated_local_index);
1305+
} else {
1306+
istream_.Emit(Opcode::LocalSet, translated_local_index);
1307+
}
12901308
return Result::Ok;
12911309
}
12921310

12931311
Result BinaryReaderInterp::OnLocalTeeExpr(Index local_index) {
12941312
CHECK_RESULT(
12951313
validator_.OnLocalTee(GetLocation(), Var(local_index, GetLocation())));
1296-
istream_.Emit(Opcode::LocalTee, TranslateLocalIndex(local_index));
1314+
1315+
Type type = func_->GetLocalType(local_index);
1316+
if (type.IsRef()) {
1317+
istream_.Emit(Opcode::InterpLocalTeeRef, TranslateLocalIndex(local_index));
1318+
} else {
1319+
istream_.Emit(Opcode::LocalTee, TranslateLocalIndex(local_index));
1320+
}
12971321
return Result::Ok;
12981322
}
12991323

src/interp/interp.cc

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1166,6 +1166,16 @@ void Thread::Push(Ref ref) {
11661166
values_.push_back(Value::Make(ref));
11671167
}
11681168

1169+
void Thread::SetRef(Index index) {
1170+
assert(index > 0 && index <= values_.size());
1171+
Index slot = values_.size() - index;
1172+
// keep refs_ ordered!
1173+
auto it = std::find_if(refs_.rbegin(), refs_.rend(), [slot](u32 x) { return x <= slot; });
1174+
if (it == refs_.rend() || *it != slot) {
1175+
refs_.insert(it.base(), slot);
1176+
}
1177+
}
1178+
11691179
RunResult Thread::StepInternal(Trap::Ptr* out_trap) {
11701180
using O = Opcode;
11711181

@@ -1238,31 +1248,51 @@ RunResult Thread::StepInternal(Trap::Ptr* out_trap) {
12381248
break;
12391249

12401250
case O::Select: {
1241-
// TODO: need to mark whether this is a ref.
12421251
auto cond = Pop<u32>();
1252+
auto ref = false;
1253+
// check if either is a ref
1254+
ref |= !refs_.empty() && refs_.back() == values_.size();
12431255
Value false_ = Pop();
1256+
ref |= !refs_.empty() && refs_.back() == values_.size();
12441257
Value true_ = Pop();
1258+
if (ref) {
1259+
refs_.push_back(values_.size());
1260+
}
12451261
Push(cond ? true_ : false_);
12461262
break;
12471263
}
12481264

1265+
case O::InterpLocalGetRef:
1266+
refs_.push_back(values_.size());
1267+
[[fallthrough]];
12491268
case O::LocalGet:
1250-
// TODO: need to mark whether this is a ref.
12511269
Push(Pick(instr.imm_u32));
12521270
break;
12531271

1272+
case O::InterpLocalSetRef:
1273+
if (Pick(instr.imm_u32).Get<Ref>() == Ref::Null) {
1274+
SetRef(instr.imm_u32);
1275+
}
1276+
[[fallthrough]];
12541277
case O::LocalSet: {
12551278
Pick(instr.imm_u32) = Pick(1);
12561279
Pop();
12571280
break;
12581281
}
12591282

1283+
case O::InterpLocalTeeRef:
1284+
if (Pick(instr.imm_u32).Get<Ref>() == Ref::Null) {
1285+
SetRef(instr.imm_u32);
1286+
}
1287+
[[fallthrough]];
12601288
case O::LocalTee:
12611289
Pick(instr.imm_u32) = Pick(1);
12621290
break;
12631291

1292+
case O::InterpGlobalGetRef:
1293+
refs_.push_back(values_.size());
1294+
[[fallthrough]];
12641295
case O::GlobalGet: {
1265-
// TODO: need to mark whether this is a ref.
12661296
Global::Ptr global{store_, inst_->globals()[instr.imm_u32]};
12671297
Push(global->Get());
12681298
break;

src/interp/istream.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,8 @@ Instr Istream::Read(Offset* offset) const {
514514

515515
case Opcode::GlobalGet:
516516
case Opcode::LocalGet:
517+
case Opcode::InterpLocalGetRef:
518+
case Opcode::InterpGlobalGetRef:
517519
case Opcode::MemorySize:
518520
case Opcode::TableSize:
519521
case Opcode::DataDrop:
@@ -529,6 +531,8 @@ Instr Istream::Read(Offset* offset) const {
529531
case Opcode::GlobalSet:
530532
case Opcode::LocalSet:
531533
case Opcode::LocalTee:
534+
case Opcode::InterpLocalSetRef:
535+
case Opcode::InterpLocalTeeRef:
532536
case Opcode::MemoryGrow:
533537
case Opcode::TableGet:
534538
// Index immediate, 1 operand.

0 commit comments

Comments
 (0)