Commit 9f3c996d authored by Andreas Haas's avatar Andreas Haas Committed by Commit Bot

[wasm] Group anyref parameter

To allow any-ref parameters, we have to make sure that any-ref stack
parameters get seen by the GC. This CL is a first step into that
direction. The goal of this CL is to group any-ref parameters at the
stack side of the parameters. This means that in the stack frame
iterator we do not need information about where anyref parameters are
in the stack frame. We only need information about how many anyref
parameters there are at the bottom of the stack frame.


R=mstarzinger@chromium.org

Also-By: mstarzinger@chromium.org
Bug: v8:7581
Change-Id: I3ff7cc38fabed5f8e51b5b990190e35f3ea29803
Reviewed-on: https://chromium-review.googlesource.com/c/1371827
Commit-Queue: Andreas Haas <ahaas@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58184}
parent 8badfe6e
......@@ -5794,13 +5794,27 @@ CallDescriptor* GetWasmCallDescriptor(
// The instance object.
locations.AddParam(params.Next(MachineRepresentation::kTaggedPointer));
const size_t param_offset = 1; // Actual params start here.
const int parameter_count = static_cast<int>(fsig->parameter_count());
for (int i = 0; i < parameter_count; i++) {
// Parameters are separated into two groups (first all untagged, then all
// tagged parameters). This allows for easy iteration of tagged parameters
// during frame iteration.
const size_t parameter_count = fsig->parameter_count();
for (size_t i = 0; i < parameter_count; i++) {
MachineRepresentation param =
wasm::ValueTypes::MachineRepresentationFor(fsig->GetParam(i));
// Skip tagged parameters (e.g. any-ref).
if (IsAnyTagged(param)) continue;
auto l = params.Next(param);
locations.AddParamAt(i + param_offset, l);
}
for (size_t i = 0; i < parameter_count; i++) {
MachineRepresentation param =
wasm::ValueTypes::MachineRepresentationFor(fsig->GetParam(i));
// Skip untagged parameters.
if (!IsAnyTagged(param)) continue;
auto l = params.Next(param);
locations.AddParam(l);
locations.AddParamAt(i + param_offset, l);
}
// Import call wrappers have an additional (implicit) parameter, the callable.
......
......@@ -74,10 +74,18 @@ class Signature : public ZoneObject {
DCHECK_LT(rcursor_, return_count_);
buffer_[rcursor_++] = val;
}
void AddParam(T val) {
DCHECK_LT(pcursor_, parameter_count_);
buffer_[return_count_ + pcursor_++] = val;
}
void AddParamAt(size_t index, T val) {
DCHECK_LT(index, parameter_count_);
buffer_[return_count_ + index] = val;
pcursor_ = std::max(pcursor_, index + 1);
}
Signature<T>* Build() {
DCHECK_EQ(rcursor_, return_count_);
DCHECK_EQ(pcursor_, parameter_count_);
......
......@@ -208,6 +208,7 @@ v8_source_set("unittests_sources") {
"wasm/module-decoder-unittest.cc",
"wasm/streaming-decoder-unittest.cc",
"wasm/wasm-code-manager-unittest.cc",
"wasm/wasm-compiler-unittest.cc",
"wasm/wasm-macro-gen-unittest.cc",
"wasm/wasm-module-builder-unittest.cc",
"wasm/wasm-opcodes-unittest.cc",
......
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "test/unittests/test-utils.h"
#include "src/compiler/linkage.h"
#include "src/compiler/wasm-compiler.h"
#include "src/machine-type.h"
#include "src/signature.h"
#include "src/wasm/value-type.h"
namespace v8 {
namespace internal {
namespace wasm {
class WasmCallDescriptorTest : public TestWithZone {};
TEST_F(WasmCallDescriptorTest, TestAnyRefIsGrouped) {
constexpr size_t kMaxCount = 30;
ValueType params[kMaxCount];
for (size_t i = 0; i < kMaxCount; i += 2) {
params[i] = ValueType::kWasmAnyRef;
CHECK_LT(i + 1, kMaxCount);
params[i + 1] = ValueType::kWasmI32;
}
for (size_t count = 1; count <= kMaxCount; ++count) {
FunctionSig sig(/*return_count=*/0, count, params);
compiler::CallDescriptor* desc =
compiler::GetWasmCallDescriptor(zone(), &sig);
// The WasmInstance is the implicit first parameter.
CHECK_EQ(count + 1, desc->ParameterCount());
bool has_untagged_stack_param = false;
bool has_tagged_register_param = false;
int max_tagged_stack_location = std::numeric_limits<int>::min();
int min_untagged_stack_location = std::numeric_limits<int>::max();
for (size_t i = 1; i < desc->ParameterCount(); ++i) {
// InputLocation i + 1, because target is the first input.
compiler::LinkageLocation location = desc->GetInputLocation(i + 1);
if (desc->GetParameterType(i).IsTagged()) {
if (location.IsRegister()) {
has_tagged_register_param = true;
} else {
CHECK(location.IsCallerFrameSlot());
max_tagged_stack_location =
std::max(max_tagged_stack_location, location.AsCallerFrameSlot());
}
} else { // !isTagged()
if (location.IsCallerFrameSlot()) {
has_untagged_stack_param = true;
min_untagged_stack_location = std::min(min_untagged_stack_location,
location.AsCallerFrameSlot());
} else {
CHECK(location.IsRegister());
}
}
}
// There should never be a tagged parameter in a register and an untagged
// parameter on the stack at the same time.
CHECK_EQ(false, has_tagged_register_param && has_untagged_stack_param);
CHECK_LT(max_tagged_stack_location, min_untagged_stack_location);
}
}
} // namespace wasm
} // namespace internal
} // namespace v8
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