[turbofan]: Add better encapsulation to LinkageLocation

Add factory methods for different types of LinkageLocations, and ensure that
accesses to the underlying data in the location are classified by type and
funneled through explicit accessors.

Also change the representation of LinkageLocation to use a BitField rather
than using a reserved section of the integer range.

Review URL: https://codereview.chromium.org/1262343002

Cr-Commit-Position: refs/heads/master@{#29938}
This commit is contained in:
danno 2015-07-30 07:52:13 -07:00 committed by Commit bot
parent 8ae236c0c4
commit 3c9f69d399
7 changed files with 121 additions and 73 deletions

View File

@ -16,13 +16,13 @@ namespace compiler {
namespace {
// Platform-specific configuration for C calling convention.
LinkageLocation regloc(Register reg) {
return LinkageLocation(Register::ToAllocationIndex(reg));
return LinkageLocation::ForRegister(Register::ToAllocationIndex(reg));
}
LinkageLocation stackloc(int i) {
DCHECK_LT(i, 0);
return LinkageLocation(i);
return LinkageLocation::ForCallerFrameSlot(i);
}
@ -226,7 +226,7 @@ CallDescriptor* Linkage::GetSimplifiedCDescriptor(
// The target for C calls is always an address (i.e. machine pointer).
MachineType target_type = kMachPtr;
LinkageLocation target_loc = LinkageLocation::AnyRegister();
LinkageLocation target_loc = LinkageLocation::ForAnyRegister();
return new (zone) CallDescriptor( // --
CallDescriptor::kCallAddress, // kind
target_type, // target MachineType

View File

@ -208,30 +208,28 @@ class OperandGenerator {
UnallocatedOperand ToUnallocatedOperand(LinkageLocation location,
MachineType type,
int virtual_register) {
if (location.location_ == LinkageLocation::ANY_REGISTER) {
if (location.IsAnyRegister()) {
// any machine register.
return UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER,
virtual_register);
}
if (location.location_ < 0) {
if (location.IsCallerFrameSlot()) {
// a location on the caller frame.
return UnallocatedOperand(UnallocatedOperand::FIXED_SLOT,
location.location_, virtual_register);
location.AsCallerFrameSlot(), virtual_register);
}
if (location.location_ > LinkageLocation::ANY_REGISTER) {
if (location.IsCalleeFrameSlot()) {
// a spill location on this (callee) frame.
return UnallocatedOperand(
UnallocatedOperand::FIXED_SLOT,
location.location_ - LinkageLocation::ANY_REGISTER - 1,
virtual_register);
return UnallocatedOperand(UnallocatedOperand::FIXED_SLOT,
location.AsCalleeFrameSlot(), virtual_register);
}
// a fixed register.
if (RepresentationOf(type) == kRepFloat64) {
return UnallocatedOperand(UnallocatedOperand::FIXED_DOUBLE_REGISTER,
location.location_, virtual_register);
location.AsRegister(), virtual_register);
}
return UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER,
location.location_, virtual_register);
location.AsRegister(), virtual_register);
}
InstructionSelector* selector_;

View File

@ -122,7 +122,7 @@ class LinkageHelper {
// The target for runtime calls is a code object.
MachineType target_type = kMachAnyTagged;
LinkageLocation target_loc = LinkageLocation::AnyRegister();
LinkageLocation target_loc = LinkageLocation::ForAnyRegister();
return new (zone) CallDescriptor( // --
CallDescriptor::kCallCodeObject, // kind
target_type, // target MachineType
@ -182,7 +182,7 @@ class LinkageHelper {
// The target for stub calls is a code object.
MachineType target_type = kMachAnyTagged;
LinkageLocation target_loc = LinkageLocation::AnyRegister();
LinkageLocation target_loc = LinkageLocation::ForAnyRegister();
return new (zone) CallDescriptor( // --
CallDescriptor::kCallCodeObject, // kind
target_type, // target MachineType
@ -214,7 +214,7 @@ class LinkageHelper {
types.AddParam(kMachPtr);
locations.AddParam(regloc(LinkageTraits::InterpreterDispatchTableReg()));
LinkageLocation target_loc = LinkageLocation::AnyRegister();
LinkageLocation target_loc = LinkageLocation::ForAnyRegister();
return new (zone) CallDescriptor( // --
CallDescriptor::kInterpreterDispatch, // kind
kMachNone, // target MachineType
@ -230,12 +230,11 @@ class LinkageHelper {
}
static LinkageLocation regloc(Register reg) {
return LinkageLocation(Register::ToAllocationIndex(reg));
return LinkageLocation::ForRegister(Register::ToAllocationIndex(reg));
}
static LinkageLocation stackloc(int i) {
DCHECK_LT(i, 0);
return LinkageLocation(i);
return LinkageLocation::ForCallerFrameSlot(i);
}
static MachineType reptyp(Representation representation) {
@ -280,11 +279,8 @@ LinkageLocation Linkage::GetOsrValueLocation(int index) const {
return incoming_->GetInputLocation(context_index);
} else if (index >= first_stack_slot) {
// Local variable stored in this (callee) stack.
int spill_index =
LinkageLocation::ANY_REGISTER + 1 + index - first_stack_slot;
// TODO(titzer): bailout instead of crashing here.
CHECK(spill_index <= LinkageLocation::MAX_STACK_SLOT);
return LinkageLocation(spill_index);
int spill_index = index - first_stack_slot;
return LinkageLocation::ForCalleeFrameSlot(spill_index);
} else {
// Parameter. Use the assigned location from the incoming call descriptor.
int parameter_index = 1 + index; // skip index 0, which is the target.

View File

@ -56,17 +56,17 @@ bool CallDescriptor::CanTailCall(const Node* node) const {
// Determine the number of stack parameters passed in
size_t stack_params = 0;
for (size_t i = 0; i < InputCount(); ++i) {
if (!GetInputLocation(i).is_register()) {
if (!GetInputLocation(i).IsRegister()) {
++stack_params;
}
}
// Ensure the input linkage contains the stack parameters in the right order
size_t current_stack_param = 0;
for (size_t i = 0; i < InputCount(); ++i) {
if (!GetInputLocation(i).is_register()) {
if (GetInputLocation(i) !=
LinkageLocation(static_cast<int>(current_stack_param) -
static_cast<int>(stack_params))) {
if (!GetInputLocation(i).IsRegister()) {
if (GetInputLocation(i) != LinkageLocation::ForCallerFrameSlot(
static_cast<int>(current_stack_param) -
static_cast<int>(stack_params))) {
return false;
}
++current_stack_param;
@ -82,7 +82,7 @@ bool CallDescriptor::CanTailCall(const Node* node) const {
while (true) {
if (other_input >= other->InputCount()) {
while (current_input < InputCount()) {
if (!GetInputLocation(current_input).is_register()) {
if (!GetInputLocation(current_input).IsRegister()) {
return false;
}
++current_input;
@ -91,18 +91,18 @@ bool CallDescriptor::CanTailCall(const Node* node) const {
}
if (current_input >= InputCount()) {
while (other_input < other->InputCount()) {
if (!other->GetInputLocation(other_input).is_register()) {
if (!other->GetInputLocation(other_input).IsRegister()) {
return false;
}
++other_input;
}
return true;
}
if (GetInputLocation(current_input).is_register()) {
if (GetInputLocation(current_input).IsRegister()) {
++current_input;
continue;
}
if (other->GetInputLocation(other_input).is_register()) {
if (other->GetInputLocation(other_input).IsRegister()) {
++other_input;
continue;
}
@ -238,10 +238,10 @@ int Linkage::FrameStateInputCount(Runtime::FunctionId function) {
bool CallDescriptor::UsesOnlyRegisters() const {
for (size_t i = 0; i < InputCount(); ++i) {
if (!GetInputLocation(i).is_register()) return false;
if (!GetInputLocation(i).IsRegister()) return false;
}
for (size_t i = 0; i < ReturnCount(); ++i) {
if (!GetReturnLocation(i).is_register()) return false;
if (!GetReturnLocation(i).IsRegister()) return false;
}
return true;
}

View File

@ -26,33 +26,77 @@ class OsrHelper;
// Describes the location for a parameter or a return value to a call.
class LinkageLocation {
public:
explicit LinkageLocation(int location) : location_(location) {}
bool is_register() const {
return 0 <= location_ && location_ <= ANY_REGISTER;
}
static const int16_t ANY_REGISTER = 1023;
static const int16_t MAX_STACK_SLOT = 32767;
static LinkageLocation AnyRegister() { return LinkageLocation(ANY_REGISTER); }
bool operator==(const LinkageLocation& other) const {
return location_ == other.location_;
return bit_field_ == other.bit_field_;
}
bool operator!=(const LinkageLocation& other) const {
return !(*this == other);
}
static LinkageLocation ForAnyRegister() {
return LinkageLocation(REGISTER, ANY_REGISTER);
}
static LinkageLocation ForRegister(int32_t reg) {
DCHECK(reg >= 0);
return LinkageLocation(REGISTER, reg);
}
static LinkageLocation ForCallerFrameSlot(int32_t slot) {
DCHECK(slot < 0);
return LinkageLocation(STACK_SLOT, slot);
}
static LinkageLocation ForCalleeFrameSlot(int32_t slot) {
// TODO(titzer): bailout instead of crashing here.
DCHECK(slot >= 0 && slot < LinkageLocation::MAX_STACK_SLOT);
return LinkageLocation(STACK_SLOT, slot);
}
private:
friend class CallDescriptor;
friend class OperandGenerator;
// location < 0 -> a stack slot on the caller frame
// 0 <= location < 1023 -> a specific machine register
// 1023 <= location < 1024 -> any machine register
// 1024 <= location -> a stack slot in the callee frame
int16_t location_;
enum LocationType { REGISTER, STACK_SLOT };
class TypeField : public BitField<LocationType, 0, 1> {};
class LocationField : public BitField<int32_t, TypeField::kNext, 31> {};
static const int32_t ANY_REGISTER = -1;
static const int32_t MAX_STACK_SLOT = 32767;
LinkageLocation(LocationType type, int32_t location) {
bit_field_ = TypeField::encode(type) |
((location << LocationField::kShift) & LocationField::kMask);
}
int32_t GetLocation() const {
return static_cast<int32_t>(bit_field_ & LocationField::kMask) >>
LocationField::kShift;
}
bool IsRegister() const { return TypeField::decode(bit_field_) == REGISTER; }
bool IsAnyRegister() const {
return IsRegister() && GetLocation() == ANY_REGISTER;
}
bool IsCallerFrameSlot() const { return !IsRegister() && GetLocation() < 0; }
bool IsCalleeFrameSlot() const { return !IsRegister() && GetLocation() >= 0; }
int32_t AsRegister() const {
DCHECK(IsRegister());
return GetLocation();
}
int32_t AsCallerFrameSlot() const {
DCHECK(IsCallerFrameSlot());
return GetLocation();
}
int32_t AsCalleeFrameSlot() const {
DCHECK(IsCalleeFrameSlot());
return GetLocation();
}
int32_t bit_field_;
};
typedef Signature<LinkageLocation> LocationSignature;

View File

@ -28,7 +28,7 @@ class LinkageTailCall : public TestWithZone {
locations->return_count(), locations->parameter_count(), kMachineTypes);
return new (zone())
CallDescriptor(CallDescriptor::kCallCodeObject, kMachAnyTagged,
LinkageLocation::AnyRegister(),
LinkageLocation::ForAnyRegister(),
types, // machine_sig
locations, // location_sig
0, // js_parameter_count
@ -39,9 +39,13 @@ class LinkageTailCall : public TestWithZone {
"");
}
LinkageLocation StackLocation(int loc) { return LinkageLocation(-loc); }
LinkageLocation StackLocation(int loc) {
return LinkageLocation::ForCallerFrameSlot(-loc);
}
LinkageLocation RegisterLocation(int loc) { return LinkageLocation(loc); }
LinkageLocation RegisterLocation(int loc) {
return LinkageLocation::ForRegister(loc);
}
};

View File

@ -27,10 +27,11 @@ class TailCallOptimizationTest : public GraphTest {
TEST_F(TailCallOptimizationTest, CallCodeObject0) {
MachineType kMachineSignature[] = {kMachAnyTagged, kMachAnyTagged};
LinkageLocation kLocationSignature[] = {LinkageLocation(0),
LinkageLocation(1)};
LinkageLocation kLocationSignature[] = {LinkageLocation::ForRegister(0),
LinkageLocation::ForRegister(1)};
const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor(
CallDescriptor::kCallCodeObject, kMachAnyTagged, LinkageLocation(0),
CallDescriptor::kCallCodeObject, kMachAnyTagged,
LinkageLocation::ForRegister(0),
new (zone()) MachineSignature(1, 1, kMachineSignature),
new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
Operator::kNoProperties, 0, 0, CallDescriptor::kNoFlags);
@ -47,10 +48,11 @@ TEST_F(TailCallOptimizationTest, CallCodeObject0) {
TEST_F(TailCallOptimizationTest, CallCodeObject1) {
MachineType kMachineSignature[] = {kMachAnyTagged, kMachAnyTagged};
LinkageLocation kLocationSignature[] = {LinkageLocation(0),
LinkageLocation(1)};
LinkageLocation kLocationSignature[] = {LinkageLocation::ForRegister(0),
LinkageLocation::ForRegister(1)};
const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor(
CallDescriptor::kCallCodeObject, kMachAnyTagged, LinkageLocation(0),
CallDescriptor::kCallCodeObject, kMachAnyTagged,
LinkageLocation::ForRegister(0),
new (zone()) MachineSignature(1, 1, kMachineSignature),
new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls);
@ -71,10 +73,11 @@ TEST_F(TailCallOptimizationTest, CallCodeObject1) {
TEST_F(TailCallOptimizationTest, CallCodeObject2) {
MachineType kMachineSignature[] = {kMachAnyTagged, kMachAnyTagged};
LinkageLocation kLocationSignature[] = {LinkageLocation(0),
LinkageLocation(1)};
LinkageLocation kLocationSignature[] = {LinkageLocation::ForRegister(0),
LinkageLocation::ForRegister(1)};
const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor(
CallDescriptor::kCallCodeObject, kMachAnyTagged, LinkageLocation(0),
CallDescriptor::kCallCodeObject, kMachAnyTagged,
LinkageLocation::ForRegister(0),
new (zone()) MachineSignature(1, 1, kMachineSignature),
new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls);
@ -93,10 +96,11 @@ TEST_F(TailCallOptimizationTest, CallCodeObject2) {
TEST_F(TailCallOptimizationTest, CallJSFunction0) {
MachineType kMachineSignature[] = {kMachAnyTagged, kMachAnyTagged};
LinkageLocation kLocationSignature[] = {LinkageLocation(0),
LinkageLocation(1)};
LinkageLocation kLocationSignature[] = {LinkageLocation::ForRegister(0),
LinkageLocation::ForRegister(1)};
const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor(
CallDescriptor::kCallJSFunction, kMachAnyTagged, LinkageLocation(0),
CallDescriptor::kCallJSFunction, kMachAnyTagged,
LinkageLocation::ForRegister(0),
new (zone()) MachineSignature(1, 1, kMachineSignature),
new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
Operator::kNoProperties, 0, 0, CallDescriptor::kNoFlags);
@ -113,10 +117,11 @@ TEST_F(TailCallOptimizationTest, CallJSFunction0) {
TEST_F(TailCallOptimizationTest, CallJSFunction1) {
MachineType kMachineSignature[] = {kMachAnyTagged, kMachAnyTagged};
LinkageLocation kLocationSignature[] = {LinkageLocation(0),
LinkageLocation(1)};
LinkageLocation kLocationSignature[] = {LinkageLocation::ForRegister(0),
LinkageLocation::ForRegister(1)};
const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor(
CallDescriptor::kCallJSFunction, kMachAnyTagged, LinkageLocation(0),
CallDescriptor::kCallJSFunction, kMachAnyTagged,
LinkageLocation::ForRegister(0),
new (zone()) MachineSignature(1, 1, kMachineSignature),
new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls);
@ -137,10 +142,11 @@ TEST_F(TailCallOptimizationTest, CallJSFunction1) {
TEST_F(TailCallOptimizationTest, CallJSFunction2) {
MachineType kMachineSignature[] = {kMachAnyTagged, kMachAnyTagged};
LinkageLocation kLocationSignature[] = {LinkageLocation(0),
LinkageLocation(1)};
LinkageLocation kLocationSignature[] = {LinkageLocation::ForRegister(0),
LinkageLocation::ForRegister(1)};
const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor(
CallDescriptor::kCallJSFunction, kMachAnyTagged, LinkageLocation(0),
CallDescriptor::kCallJSFunction, kMachAnyTagged,
LinkageLocation::ForRegister(0),
new (zone()) MachineSignature(1, 1, kMachineSignature),
new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls);