Implement GC (Garbage Collection) feature for interpreter, AOT and LLVM-JIT (#3125)

Implement the GC (Garbage Collection) feature for interpreter mode,
AOT mode and LLVM-JIT mode, and support most features of the latest
spec proposal, and also enable the stringref feature.

Use `cmake -DWAMR_BUILD_GC=1/0` to enable/disable the feature,
and `wamrc --enable-gc` to generate the AOT file with GC supported.

And update the AOT file version from 2 to 3 since there are many AOT
ABI breaks, including the changes of AOT file format, the changes of
AOT module/memory instance layouts, the AOT runtime APIs for the
AOT code to invoke and so on.
This commit is contained in:
Wenyong Huang
2024-02-06 20:47:11 +08:00
committed by GitHub
parent 5931aaacbe
commit 16a4d71b34
98 changed files with 33469 additions and 3159 deletions

View File

@ -626,7 +626,7 @@ def vector_value_comparison(out, expected):
int(expected_val[1]) if not "0x" in expected_val[1] else int(expected_val[1], 16))
if lane_type in ["i8x16", "i16x8", "i32x4", "i64x2"]:
return out_packed == expected_packed;
return out_packed == expected_packed
else:
assert(lane_type in ["f32x4", "f64x2"]), "unexpected lane_type"
@ -817,7 +817,7 @@ def test_assert_return(r, opts, form):
n = re.search('^\(assert_return\s+\(invoke\s+\$((?:[^\s])*)\s+"([^"]*)"*()()\)\s*\)\s*$', form, re.S)
if not m and not n:
if re.search('^\(assert_return\s+\(get.*\).*\)$', form, re.S):
log("ignoring assert_return get");
log("ignoring assert_return get")
return
else:
raise Exception("unparsed assert_return: '%s'" % form)
@ -898,6 +898,7 @@ def test_assert_return(r, opts, form):
except:
_, exc, _ = sys.exc_info()
log("Run wamrc failed:\n got: '%s'" % r.buf)
ret_code = 1
sys.exit(1)
r = run_wasm_with_repl(module+".wasm", module+".aot" if test_aot else module, opts, r)
# Wait for the initial prompt
@ -963,6 +964,7 @@ def test_assert_trap(r, opts, form):
except:
_, exc, _ = sys.exc_info()
log("Run wamrc failed:\n got: '%s'" % r.buf)
ret_code = 1
sys.exit(1)
r = run_wasm_with_repl(module+".wasm", module+".aot" if test_aot else module, opts, r)
# Wait for the initial prompt
@ -1091,7 +1093,7 @@ def compile_wast_to_wasm(form, wast_tempfile, wasm_tempfile, opts):
return True
def compile_wasm_to_aot(wasm_tempfile, aot_tempfile, runner, opts, r, output = 'default'):
log("Compiling AOT to '%s'" % aot_tempfile)
log("Compiling '%s' to '%s'" % (wasm_tempfile, aot_tempfile))
cmd = [opts.aot_compiler]
if test_target in aot_target_options_map:
@ -1110,6 +1112,10 @@ def compile_wasm_to_aot(wasm_tempfile, aot_tempfile, runner, opts, r, output = '
if opts.multi_thread:
cmd.append("--enable-multi-thread")
if opts.gc:
cmd.append("--enable-gc")
cmd.append("--enable-tail-call")
if output == 'object':
cmd.append("--format=object")
elif output == 'ir':
@ -1223,6 +1229,7 @@ def test_assert_with_exception(form, wast_tempfile, wasm_tempfile, aot_tempfile,
else:
log("Run wamrc failed:\n expected: '%s'\n got: '%s'" % \
(expected, r.buf))
ret_code = 1
sys.exit(1)
r = run_wasm_with_repl(wasm_tempfile, aot_tempfile if test_aot else None, opts, r)
@ -1319,26 +1326,47 @@ if __name__ == "__main__":
log("Out exception includes expected one, pass:")
log(" Expected: %s" % error_msg)
log(" Got: %s" % r.buf)
continue
# one case in binary.wast
elif (error_msg == "unexpected end of section or function"
and r.buf.find("unexpected end")):
continue
# one case in binary.wast
elif (error_msg == "invalid value type"
and r.buf.find("unexpected end")):
continue
# one case in binary.wast
elif (error_msg == "integer too large"
and r.buf.find("tables cannot be shared")):
continue
# one case in binary.wast
elif (error_msg == "zero byte expected"
and r.buf.find("unknown table")):
continue
# one case in binary.wast
elif (error_msg == "invalid section id"
and r.buf.find("unexpected end of section or function")):
continue
# one case in binary.wast
elif (error_msg == "illegal opcode"
and r.buf.find("unexpected end of section or function")):
continue
# one case in custom.wast
elif (error_msg == "length out of bounds"
and r.buf.find("unexpected end")):
continue
# several cases in binary-leb128.wast
elif (error_msg == "integer representation too long"
and r.buf.find("invalid section id")):
continue
else:
log("Run wamrc failed:\n expected: '%s'\n got: '%s'" % \
(error_msg, r.buf))
continue
ret_code = 1
sys.exit(1)
r = run_wasm_with_repl(wasm_tempfile, aot_tempfile if test_aot else None, opts, r)
if (error_msg == "unexpected end of section or function"):
# one case in binary.wast
assert_prompt(r, ["unexpected end", error_msg], opts.start_timeout, True)
elif (error_msg == "invalid value type"):
# one case in binary.wast
assert_prompt(r, ["unexpected end", error_msg], opts.start_timeout, True)
elif (error_msg == "length out of bounds"):
# one case in custom.wast
assert_prompt(r, ["unexpected end", error_msg], opts.start_timeout, True)
elif (error_msg == "integer representation too long"):
# several cases in binary-leb128.wast
assert_prompt(r, ["invalid section id", error_msg], opts.start_timeout, True)
elif re.match("^\(assert_malformed\s*\(module quote", form):
log("ignoring assert_malformed module quote")
else:
@ -1371,6 +1399,7 @@ if __name__ == "__main__":
except:
_, exc, _ = sys.exc_info()
log("Run wamrc failed:\n got: '%s'" % r.buf)
ret_code = 1
sys.exit(1)
temp_module_table[module_name] = temp_files[1]
r = run_wasm_with_repl(temp_files[1], temp_files[2] if test_aot else None, opts, r)
@ -1385,6 +1414,7 @@ if __name__ == "__main__":
except:
_, exc, _ = sys.exc_info()
log("Run wamrc failed:\n got: '%s'" % r.buf)
ret_code = 1
sys.exit(1)
r = run_wasm_with_repl(wasm_tempfile, aot_tempfile if test_aot else None, opts, r)
@ -1468,4 +1498,3 @@ if __name__ == "__main__":
log("Leaving tempfiles: %s" % ([wast_tempfile, wasm_tempfile]))
sys.exit(ret_code)