CallDescriptor* Linkage::GetStubCallDescriptor(
- CallInterfaceDescriptor descriptor, int stack_parameter_count,
+ const CallInterfaceDescriptor& descriptor, int stack_parameter_count,
CallDescriptor::Flags flags, Zone* zone) {
return LH::GetStubCallDescriptor(zone, descriptor, stack_parameter_count,
flags);
CallDescriptor* Linkage::GetStubCallDescriptor(
- CallInterfaceDescriptor descriptor, int stack_parameter_count,
+ const CallInterfaceDescriptor& descriptor, int stack_parameter_count,
CallDescriptor::Flags flags, Zone* zone) {
return LH::GetStubCallDescriptor(zone, descriptor, stack_parameter_count,
flags);
#ifndef V8_COMPILER_CODE_GENERATOR_IMPL_H_
#define V8_COMPILER_CODE_GENERATOR_IMPL_H_
+#include "src/code-stubs.h"
#include "src/compiler/code-generator.h"
#include "src/compiler/instruction.h"
#include "src/compiler/linkage.h"
#include "src/compiler/opcodes.h"
+#include "src/macro-assembler.h"
namespace v8 {
namespace internal {
namespace internal {
namespace compiler {
+class Linkage;
+
// Generates native code for a sequence of instructions.
class CodeGenerator FINAL : public GapResolver::Assembler {
public:
#include "src/assembler.h"
#include "src/base/lazy-instance.h"
#include "src/compiler/linkage.h"
+#include "src/compiler/opcodes.h"
+#include "src/compiler/operator.h"
#include "src/unique.h"
#include "src/zone.h"
#include <sstream>
#include <string>
+#include "src/code-stubs.h"
#include "src/compiler/generic-algorithm.h"
#include "src/compiler/generic-node.h"
#include "src/compiler/generic-node-inl.h"
Tag tag(this, "intervals");
PrintStringProperty("name", phase);
- const Vector<LiveRange*>* fixed_d = allocator->fixed_double_live_ranges();
- for (int i = 0; i < fixed_d->length(); ++i) {
- PrintLiveRange(fixed_d->at(i), "fixed");
+ for (auto range : allocator->fixed_double_live_ranges()) {
+ PrintLiveRange(range, "fixed");
}
- const Vector<LiveRange*>* fixed = allocator->fixed_live_ranges();
- for (int i = 0; i < fixed->length(); ++i) {
- PrintLiveRange(fixed->at(i), "fixed");
+ for (auto range : allocator->fixed_live_ranges()) {
+ PrintLiveRange(range, "fixed");
}
- const ZoneList<LiveRange*>* live_ranges = allocator->live_ranges();
- for (int i = 0; i < live_ranges->length(); ++i) {
- PrintLiveRange(live_ranges->at(i), "object");
+ for (auto range : allocator->live_ranges()) {
+ PrintLiveRange(range, "object");
}
}
CallDescriptor* Linkage::GetStubCallDescriptor(
- CallInterfaceDescriptor descriptor, int stack_parameter_count,
+ const CallInterfaceDescriptor& descriptor, int stack_parameter_count,
CallDescriptor::Flags flags, Zone* zone) {
return LH::GetStubCallDescriptor(zone, descriptor, stack_parameter_count,
flags);
#include "src/compiler/instruction.h"
#include "src/compiler/instruction-selector.h"
#include "src/compiler/linkage.h"
+#include "src/macro-assembler.h"
namespace v8 {
namespace internal {
// Forward declarations.
struct CallBuffer; // TODO(bmeurer): Remove this.
class FlagsContinuation;
+class Linkage;
class InstructionSelector FINAL {
public:
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/compiler/instruction.h"
-
#include "src/compiler/common-operator.h"
#include "src/compiler/generic-node-inl.h"
#include "src/compiler/graph.h"
+#include "src/compiler/instruction.h"
+#include "src/macro-assembler.h"
namespace v8 {
namespace internal {
namespace compiler {
+STATIC_ASSERT(kMaxGeneralRegisters >= Register::kNumRegisters);
+STATIC_ASSERT(kMaxDoubleRegisters >= DoubleRegister::kMaxNumRegisters);
+
+
std::ostream& operator<<(std::ostream& os, const InstructionOperand& op) {
switch (op.kind()) {
case InstructionOperand::INVALID:
#include "src/compiler/opcodes.h"
#include "src/compiler/schedule.h"
#include "src/compiler/source-position.h"
-// TODO(titzer): don't include the macro-assembler?
-#include "src/macro-assembler.h"
#include "src/zone-allocator.h"
namespace v8 {
namespace internal {
namespace compiler {
-// Forward declarations.
-class Linkage;
-
// A couple of reserved opcodes are used for internal use.
const InstructionCode kGapInstruction = -1;
const InstructionCode kBlockStartInstruction = -2;
const InstructionCode kSourcePositionInstruction = -3;
+// Platform independent maxes.
+static const int kMaxGeneralRegisters = 32;
+static const int kMaxDoubleRegisters = 32;
+
-#define INSTRUCTION_OPERAND_LIST(V) \
- V(Constant, CONSTANT, 0) \
- V(Immediate, IMMEDIATE, 0) \
- V(StackSlot, STACK_SLOT, 128) \
- V(DoubleStackSlot, DOUBLE_STACK_SLOT, 128) \
- V(Register, REGISTER, Register::kNumRegisters) \
- V(DoubleRegister, DOUBLE_REGISTER, DoubleRegister::kMaxNumRegisters)
+#define INSTRUCTION_OPERAND_LIST(V) \
+ V(Constant, CONSTANT, 0) \
+ V(Immediate, IMMEDIATE, 0) \
+ V(StackSlot, STACK_SLOT, 128) \
+ V(DoubleStackSlot, DOUBLE_STACK_SLOT, 128) \
+ V(Register, REGISTER, kMaxGeneralRegisters) \
+ V(DoubleRegister, DOUBLE_REGISTER, kMaxDoubleRegisters)
class InstructionOperand : public ZoneObject {
public:
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "src/code-stubs.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/node-properties-inl.h"
#include "src/compiler/typer.h"
#ifndef V8_COMPILER_LINKAGE_IMPL_H_
#define V8_COMPILER_LINKAGE_IMPL_H_
+#include "src/code-stubs.h"
+
namespace v8 {
namespace internal {
namespace compiler {
// TODO(turbofan): cache call descriptors for code stub calls.
static CallDescriptor* GetStubCallDescriptor(
- Zone* zone, CallInterfaceDescriptor descriptor, int stack_parameter_count,
- CallDescriptor::Flags flags) {
+ Zone* zone, const CallInterfaceDescriptor& descriptor,
+ int stack_parameter_count, CallDescriptor::Flags flags) {
const int register_parameter_count =
descriptor.GetEnvironmentParameterCount();
const int js_parameter_count =
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/compiler/linkage.h"
-
#include "src/code-stubs.h"
#include "src/compiler.h"
+#include "src/compiler/linkage.h"
#include "src/compiler/node.h"
#include "src/compiler/pipeline.h"
#include "src/scopes.h"
CallDescriptor* Linkage::GetStubCallDescriptor(
- CallInterfaceDescriptor descriptor, int stack_parameter_count,
+ const CallInterfaceDescriptor& descriptor, int stack_parameter_count,
CallDescriptor::Flags flags) const {
return GetStubCallDescriptor(descriptor, stack_parameter_count, flags, zone_);
}
CallDescriptor* Linkage::GetStubCallDescriptor(
- CallInterfaceDescriptor descriptor, int stack_parameter_count,
+ const CallInterfaceDescriptor& descriptor, int stack_parameter_count,
CallDescriptor::Flags flags, Zone* zone) {
UNIMPLEMENTED();
return NULL;
#define V8_COMPILER_LINKAGE_H_
#include "src/base/flags.h"
-#include "src/code-stubs.h"
#include "src/compiler/frame.h"
#include "src/compiler/machine-type.h"
-#include "src/compiler/node.h"
#include "src/compiler/operator.h"
#include "src/zone.h"
namespace v8 {
namespace internal {
+
+class CallInterfaceDescriptor;
+
namespace compiler {
// Describes the location for a parameter or a return value to a call.
Operator::Properties properties, Zone* zone);
CallDescriptor* GetStubCallDescriptor(
- CallInterfaceDescriptor descriptor, int stack_parameter_count = 0,
+ const CallInterfaceDescriptor& descriptor, int stack_parameter_count = 0,
CallDescriptor::Flags flags = CallDescriptor::kNoFlags) const;
static CallDescriptor* GetStubCallDescriptor(
- CallInterfaceDescriptor descriptor, int stack_parameter_count,
+ const CallInterfaceDescriptor& descriptor, int stack_parameter_count,
CallDescriptor::Flags flags, Zone* zone);
// Creates a call descriptor for simplified C calls that is appropriate
CallDescriptor* Linkage::GetStubCallDescriptor(
- CallInterfaceDescriptor descriptor, int stack_parameter_count,
+ const CallInterfaceDescriptor& descriptor, int stack_parameter_count,
CallDescriptor::Flags flags, Zone* zone) {
return LH::GetStubCallDescriptor(zone, descriptor, stack_parameter_count,
flags);
debug_name = GetDebugName(info());
#endif
- RegisterAllocator allocator(zone_scope.zone(), &frame, &sequence,
+
+ RegisterAllocator allocator(RegisterAllocator::PlatformConfig(),
+ zone_scope.zone(), &frame, &sequence,
debug_name.get());
if (!allocator.Allocate(data->pipeline_statistics())) {
info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc);
#include "src/compiler/linkage.h"
#include "src/compiler/pipeline-statistics.h"
#include "src/compiler/register-allocator.h"
+#include "src/macro-assembler.h" // TODO(dcarney): remove this.
#include "src/string-stream.h"
namespace v8 {
}
-RegisterAllocator::RegisterAllocator(Zone* local_zone, Frame* frame,
- InstructionSequence* code,
+RegisterAllocator::Config RegisterAllocator::PlatformConfig() {
+ DCHECK_EQ(Register::kMaxNumAllocatableRegisters,
+ Register::NumAllocatableRegisters());
+ Config config;
+ config.num_general_registers_ = Register::kMaxNumAllocatableRegisters;
+ config.num_double_registers_ = DoubleRegister::kMaxNumAllocatableRegisters;
+ config.num_aliased_double_registers_ =
+ DoubleRegister::NumAllocatableAliasedRegisters();
+ config.GeneralRegisterName = Register::AllocationIndexToString;
+ config.DoubleRegisterName = DoubleRegister::AllocationIndexToString;
+ return config;
+}
+
+
+RegisterAllocator::RegisterAllocator(const Config& config, Zone* local_zone,
+ Frame* frame, InstructionSequence* code,
const char* debug_name)
: zone_(local_zone),
frame_(frame),
code_(code),
debug_name_(debug_name),
+ config_(config),
live_in_sets_(code->InstructionBlockCount(), zone()),
live_ranges_(code->VirtualRegisterCount() * 2, zone()),
- fixed_live_ranges_(NULL),
- fixed_double_live_ranges_(NULL),
+ fixed_live_ranges_(this->config().num_general_registers_, NULL, zone()),
+ fixed_double_live_ranges_(this->config().num_double_registers_, NULL,
+ zone()),
unhandled_live_ranges_(code->VirtualRegisterCount() * 2, zone()),
active_live_ranges_(8, zone()),
inactive_live_ranges_(8, zone()),
reusable_slots_(8, zone()),
mode_(UNALLOCATED_REGISTERS),
num_registers_(-1),
- allocation_ok_(true) {}
+ allocation_ok_(true) {
+ DCHECK(this->config().num_general_registers_ <= kMaxGeneralRegisters);
+ DCHECK(this->config().num_double_registers_ <= kMaxDoubleRegisters);
+ // TryAllocateFreeReg and AllocateBlockedReg assume this
+ // when allocating local arrays.
+ DCHECK(this->config().num_double_registers_ >=
+ this->config().num_general_registers_);
+}
void RegisterAllocator::InitializeLivenessAnalysis() {
int RegisterAllocator::FixedDoubleLiveRangeID(int index) {
- return -index - 1 - Register::kMaxNumAllocatableRegisters;
+ return -index - 1 - config().num_general_registers_;
}
LiveRange* RegisterAllocator::FixedLiveRangeFor(int index) {
- DCHECK(index < Register::kMaxNumAllocatableRegisters);
+ DCHECK(index < config().num_general_registers_);
LiveRange* result = fixed_live_ranges_[index];
if (result == NULL) {
// TODO(titzer): add a utility method to allocate a new LiveRange:
LiveRange* RegisterAllocator::FixedDoubleLiveRangeFor(int index) {
- DCHECK(index < DoubleRegister::NumAllocatableAliasedRegisters());
+ DCHECK(index < config().num_aliased_double_registers_);
LiveRange* result = fixed_double_live_ranges_[index];
if (result == NULL) {
result = new (zone()) LiveRange(FixedDoubleLiveRangeID(index), code_zone());
}
if (instr->ClobbersRegisters()) {
- for (int i = 0; i < Register::kMaxNumAllocatableRegisters; ++i) {
+ for (int i = 0; i < config().num_general_registers_; ++i) {
if (!IsOutputRegisterOf(instr, i)) {
LiveRange* range = FixedLiveRangeFor(i);
range->AddUseInterval(curr_position, curr_position.InstructionEnd(),
}
if (instr->ClobbersDoubleRegisters()) {
- for (int i = 0; i < DoubleRegister::NumAllocatableAliasedRegisters();
- ++i) {
+ for (int i = 0; i < config().num_aliased_double_registers_; ++i) {
if (!IsOutputDoubleRegisterOf(instr, i)) {
LiveRange* range = FixedDoubleLiveRangeFor(i);
range->AddUseInterval(curr_position, curr_position.InstructionEnd(),
bool RegisterAllocator::Allocate(PipelineStatistics* stats) {
- assigned_registers_ = new (code_zone())
- BitVector(Register::NumAllocatableRegisters(), code_zone());
+ assigned_registers_ =
+ new (code_zone()) BitVector(config().num_general_registers_, code_zone());
assigned_double_registers_ = new (code_zone())
- BitVector(DoubleRegister::NumAllocatableAliasedRegisters(), code_zone());
+ BitVector(config().num_aliased_double_registers_, code_zone());
{
PhaseScope phase_scope(stats, "meet register constraints");
MeetRegisterConstraints();
void RegisterAllocator::ConnectRanges() {
- for (int i = 0; i < live_ranges()->length(); ++i) {
- LiveRange* first_range = live_ranges()->at(i);
+ for (int i = 0; i < live_ranges().length(); ++i) {
+ LiveRange* first_range = live_ranges().at(i);
if (first_range == NULL || first_range->parent() != NULL) continue;
LiveRange* second_range = first_range->next();
int last_range_start = 0;
const PointerMapDeque* pointer_maps = code()->pointer_maps();
PointerMapDeque::const_iterator first_it = pointer_maps->begin();
- for (int range_idx = 0; range_idx < live_ranges()->length(); ++range_idx) {
- LiveRange* range = live_ranges()->at(range_idx);
+ for (int range_idx = 0; range_idx < live_ranges().length(); ++range_idx) {
+ LiveRange* range = live_ranges().at(range_idx);
if (range == NULL) continue;
// Iterate over the first parts of multi-part live ranges.
if (range->parent() != NULL) continue;
void RegisterAllocator::AllocateGeneralRegisters() {
- num_registers_ = Register::NumAllocatableRegisters();
+ num_registers_ = config().num_general_registers_;
mode_ = GENERAL_REGISTERS;
AllocateRegisters();
}
void RegisterAllocator::AllocateDoubleRegisters() {
- num_registers_ = DoubleRegister::NumAllocatableAliasedRegisters();
+ num_registers_ = config().num_aliased_double_registers_;
mode_ = DOUBLE_REGISTERS;
AllocateRegisters();
}
DCHECK(inactive_live_ranges_.is_empty());
if (mode_ == DOUBLE_REGISTERS) {
- for (int i = 0; i < DoubleRegister::NumAllocatableAliasedRegisters(); ++i) {
+ for (int i = 0; i < config().num_aliased_double_registers_; ++i) {
LiveRange* current = fixed_double_live_ranges_.at(i);
if (current != NULL) {
AddToInactive(current);
}
} else {
DCHECK(mode_ == GENERAL_REGISTERS);
- for (int i = 0; i < fixed_live_ranges_.length(); ++i) {
- LiveRange* current = fixed_live_ranges_.at(i);
+ for (auto current : fixed_live_ranges()) {
if (current != NULL) {
AddToInactive(current);
}
const char* RegisterAllocator::RegisterName(int allocation_index) {
if (mode_ == GENERAL_REGISTERS) {
- return Register::AllocationIndexToString(allocation_index);
+ return config().GeneralRegisterName(allocation_index);
} else {
- return DoubleRegister::AllocationIndexToString(allocation_index);
+ return config().DoubleRegisterName(allocation_index);
}
}
}
-// TryAllocateFreeReg and AllocateBlockedReg assume this
-// when allocating local arrays.
-STATIC_ASSERT(DoubleRegister::kMaxNumAllocatableRegisters >=
- Register::kMaxNumAllocatableRegisters);
-
-
bool RegisterAllocator::TryAllocateFreeReg(LiveRange* current) {
- LifetimePosition free_until_pos[DoubleRegister::kMaxNumAllocatableRegisters];
+ LifetimePosition free_until_pos[kMaxDoubleRegisters];
for (int i = 0; i < num_registers_; i++) {
free_until_pos[i] = LifetimePosition::MaxPosition();
return;
}
-
- LifetimePosition use_pos[DoubleRegister::kMaxNumAllocatableRegisters];
- LifetimePosition block_pos[DoubleRegister::kMaxNumAllocatableRegisters];
+ LifetimePosition use_pos[kMaxGeneralRegisters];
+ LifetimePosition block_pos[kMaxDoubleRegisters];
for (int i = 0; i < num_registers_; i++) {
use_pos[i] = block_pos[i] = LifetimePosition::MaxPosition();
void RegisterAllocator::Verify() const {
- for (int i = 0; i < live_ranges()->length(); ++i) {
- LiveRange* current = live_ranges()->at(i);
+ for (auto current : live_ranges()) {
if (current != NULL) current->Verify();
}
}
#ifndef V8_REGISTER_ALLOCATOR_H_
#define V8_REGISTER_ALLOCATOR_H_
-#include "src/allocation.h"
#include "src/compiler/instruction.h"
-#include "src/macro-assembler.h"
-#include "src/zone.h"
+#include "src/zone-containers.h"
namespace v8 {
namespace internal {
class RegisterAllocator BASE_EMBEDDED {
public:
- explicit RegisterAllocator(Zone* local_zone, Frame* frame,
- InstructionSequence* code,
+ class Config {
+ public:
+ int num_general_registers_;
+ int num_double_registers_;
+ int num_aliased_double_registers_;
+ const char* (*GeneralRegisterName)(int allocation_index);
+ const char* (*DoubleRegisterName)(int allocation_index);
+ };
+
+ static Config PlatformConfig();
+
+ explicit RegisterAllocator(const Config& config, Zone* local_zone,
+ Frame* frame, InstructionSequence* code,
const char* debug_name = nullptr);
bool Allocate(PipelineStatistics* stats = NULL);
BitVector* assigned_registers() { return assigned_registers_; }
BitVector* assigned_double_registers() { return assigned_double_registers_; }
- const ZoneList<LiveRange*>* live_ranges() const { return &live_ranges_; }
- const Vector<LiveRange*>* fixed_live_ranges() const {
- return &fixed_live_ranges_;
+ const ZoneList<LiveRange*>& live_ranges() const { return live_ranges_; }
+ const ZoneVector<LiveRange*>& fixed_live_ranges() const {
+ return fixed_live_ranges_;
}
- const Vector<LiveRange*>* fixed_double_live_ranges() const {
- return &fixed_double_live_ranges_;
+ const ZoneVector<LiveRange*>& fixed_double_live_ranges() const {
+ return fixed_double_live_ranges_;
}
InstructionSequence* code() const { return code_; }
// Helper methods for the fixed registers.
int RegisterCount() const;
static int FixedLiveRangeID(int index) { return -index - 1; }
- static int FixedDoubleLiveRangeID(int index);
+ int FixedDoubleLiveRangeID(int index);
LiveRange* FixedLiveRangeFor(int index);
LiveRange* FixedDoubleLiveRangeFor(int index);
LiveRange* LiveRangeFor(int index);
Frame* frame() const { return frame_; }
const char* debug_name() const { return debug_name_; }
+ const Config& config() const { return config_; }
Zone* const zone_;
Frame* const frame_;
InstructionSequence* const code_;
const char* const debug_name_;
+ const Config config_;
+
// During liveness analysis keep a mapping from block id to live_in sets
// for blocks already analyzed.
ZoneList<BitVector*> live_in_sets_;
ZoneList<LiveRange*> live_ranges_;
// Lists of live ranges
- EmbeddedVector<LiveRange*, Register::kMaxNumAllocatableRegisters>
- fixed_live_ranges_;
- EmbeddedVector<LiveRange*, DoubleRegister::kMaxNumAllocatableRegisters>
- fixed_double_live_ranges_;
+ ZoneVector<LiveRange*> fixed_live_ranges_;
+ ZoneVector<LiveRange*> fixed_double_live_ranges_;
ZoneList<LiveRange*> unhandled_live_ranges_;
ZoneList<LiveRange*> active_live_ranges_;
ZoneList<LiveRange*> inactive_live_ranges_;
CallDescriptor* Linkage::GetStubCallDescriptor(
- CallInterfaceDescriptor descriptor, int stack_parameter_count,
+ const CallInterfaceDescriptor& descriptor, int stack_parameter_count,
CallDescriptor::Flags flags, Zone* zone) {
return LH::GetStubCallDescriptor(zone, descriptor, stack_parameter_count,
flags);
}
-const char* CallInterfaceDescriptor::DebugName(Isolate* isolate) {
+const char* CallInterfaceDescriptor::DebugName(Isolate* isolate) const {
CallInterfaceDescriptorData* start = isolate->call_descriptor_data(0);
size_t index = data_ - start;
DCHECK(index < CallDescriptors::NUMBER_OF_DESCRIPTORS);
static const Register ContextRegister();
- const char* DebugName(Isolate* isolate);
+ const char* DebugName(Isolate* isolate) const;
protected:
const CallInterfaceDescriptorData* data() const { return data_; }
}
Frame frame;
- RegisterAllocator allocator(scope_->main_zone(), &frame, code);
+ RegisterAllocator allocator(RegisterAllocator::PlatformConfig(),
+ scope_->main_zone(), &frame, code);
CHECK(allocator.Allocate());
if (FLAG_trace_turbo) {
#include <limits>
#include "src/base/bits.h"
+#include "src/codegen.h"
#include "src/compiler/generic-node-inl.h"
#include "test/cctest/cctest.h"
#include "test/cctest/compiler/codegen-tester.h"
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "src/code-stubs.h"
#include "src/compiler/change-lowering.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/node-properties-inl.h"
#include "src/base/utils/random-number-generator.h"
#include "src/compiler/instruction-selector.h"
#include "src/compiler/raw-machine-assembler.h"
+#include "src/macro-assembler.h"
#include "test/unittests/test-utils.h"
namespace v8 {