Commit eb573e11 authored by palfia@homejinni.com's avatar palfia@homejinni.com

MIPS: Generate the TransitionElementsStub using Crankshaft

Port r13585 (4174b9d2)

Original commit message:
This includes:
* Adding support for saving callee-clobbered double registers in Crankshaft code.
* Adding a new "HTrapAllocationMemento" hydrogen instruction to handle AllocationSiteInfo data in crankshafted stubs.
* Adding a new "HAllocate" hydrogen instruction that can allocate raw memory from the GC in crankshafted code.
* Support for manipulation of the hole in HChange instructions for Crankshafted stubs.
* Utility routines to manually build loops and if statements containing hydrogen code.

BUG=
TEST=

Review URL: https://chromiumcodereview.appspot.com/12212080

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13655 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 1d33c772
......@@ -91,7 +91,7 @@ int Register::NumAllocatableRegisters() {
int DoubleRegister::NumRegisters() {
if (CpuFeatures::IsSupported(FPU)) {
return FPURegister::kNumRegisters;
return FPURegister::kMaxNumRegisters;
} else {
return 1;
}
......
......@@ -189,7 +189,7 @@ Register ToRegister(int num);
// Coprocessor register.
struct FPURegister {
static const int kNumRegisters = v8::internal::kNumFPURegisters;
static const int kMaxNumRegisters = v8::internal::kNumFPURegisters;
// TODO(plind): Warning, inconsistent numbering here. kNumFPURegisters refers
// to number of 32-bit FPU regs, but kNumAllocatableRegisters refers to
......@@ -200,7 +200,7 @@ struct FPURegister {
// f28: 0.0
// f30: scratch register.
static const int kNumReservedRegisters = 2;
static const int kMaxNumAllocatableRegisters = kNumRegisters / 2 -
static const int kMaxNumAllocatableRegisters = kMaxNumRegisters / 2 -
kNumReservedRegisters;
inline static int NumRegisters();
......@@ -218,7 +218,7 @@ struct FPURegister {
return r;
}
bool is_valid() const { return 0 <= code_ && code_ < kNumFPURegisters ; }
bool is_valid() const { return 0 <= code_ && code_ < kMaxNumRegisters ; }
bool is(FPURegister creg) const { return code_ == creg.code_; }
FPURegister low() const {
// Find low reg of a Double-reg pair, which is the reg itself.
......
......@@ -50,6 +50,18 @@ void KeyedLoadFastElementStub::InitializeInterfaceDescriptor(
}
void TransitionElementsKindStub::InitializeInterfaceDescriptor(
Isolate* isolate,
CodeStubInterfaceDescriptor* descriptor) {
static Register registers[] = { a0, a1 };
descriptor->register_param_count_ = 2;
descriptor->register_params_ = registers;
Address entry =
Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry;
descriptor->deoptimization_handler_ = FUNCTION_ADDR(entry);
}
#define __ ACCESS_MASM(masm)
static void EmitIdenticalObjectComparison(MacroAssembler* masm,
......
......@@ -155,7 +155,7 @@ void ElementsTransitionGenerator::GenerateMapChangeElementsTransition(
// -----------------------------------
if (mode == TRACK_ALLOCATION_SITE) {
ASSERT(allocation_site_info_found != NULL);
masm->TestJSArrayForAllocationSiteInfo(a2, t0,
masm->TestJSArrayForAllocationSiteInfo(a2, t0, eq,
allocation_site_info_found);
}
......@@ -188,7 +188,7 @@ void ElementsTransitionGenerator::GenerateSmiToDouble(
Register scratch = t6;
if (mode == TRACK_ALLOCATION_SITE) {
masm->TestJSArrayForAllocationSiteInfo(a2, t0, fail);
masm->TestJSArrayForAllocationSiteInfo(a2, t0, eq, fail);
}
// Check for empty arrays, which only require a map transition and no changes
......@@ -332,7 +332,7 @@ void ElementsTransitionGenerator::GenerateDoubleToObject(
Label entry, loop, convert_hole, gc_required, only_change_map;
if (mode == TRACK_ALLOCATION_SITE) {
masm->TestJSArrayForAllocationSiteInfo(a2, t0, fail);
masm->TestJSArrayForAllocationSiteInfo(a2, t0, eq, fail);
}
// Check for empty arrays, which only require a map transition and no changes
......
......@@ -526,6 +526,11 @@ void Deoptimizer::DoCompiledStubFrame(TranslationIterator* iterator,
DoTranslateCommand(iterator, 0, output_frame_offset);
}
for (int i = 0; i < DoubleRegister::kMaxNumRegisters; ++i) {
double double_value = input_->GetDoubleRegister(i);
output_frame->SetDoubleRegister(i, double_value);
}
value = input_->GetRegister(fp.code());
output_frame->SetRegister(fp.code(), value);
output_frame->SetFp(value);
......@@ -1076,11 +1081,11 @@ void Deoptimizer::EntryGenerator::Generate() {
}
}
int double_regs_offset = FrameDescription::double_registers_offset();
if (CpuFeatures::IsSupported(FPU)) {
CpuFeatures::Scope scope(FPU);
// Copy FPU registers to
// double_registers_[DoubleRegister::kNumAllocatableRegisters]
int double_regs_offset = FrameDescription::double_registers_offset();
for (int i = 0; i < FPURegister::NumAllocatableRegisters(); ++i) {
int dst_offset = i * kDoubleSize + double_regs_offset;
int src_offset = i * kDoubleSize + kNumberOfRegisters * kPointerSize;
......@@ -1131,16 +1136,16 @@ void Deoptimizer::EntryGenerator::Generate() {
// Replace the current (input) frame with the output frames.
Label outer_push_loop, inner_push_loop,
outer_loop_header, inner_loop_header;
// Outer loop state: a0 = current "FrameDescription** output_",
// Outer loop state: t0 = current "FrameDescription** output_",
// a1 = one past the last FrameDescription**.
__ lw(a1, MemOperand(a0, Deoptimizer::output_count_offset()));
__ lw(a0, MemOperand(a0, Deoptimizer::output_offset())); // a0 is output_.
__ lw(t0, MemOperand(a0, Deoptimizer::output_offset())); // t0 is output_.
__ sll(a1, a1, kPointerSizeLog2); // Count to offset.
__ addu(a1, a0, a1); // a1 = one past the last FrameDescription**.
__ addu(a1, t0, a1); // a1 = one past the last FrameDescription**.
__ jmp(&outer_loop_header);
__ bind(&outer_push_loop);
// Inner loop state: a2 = current FrameDescription*, a3 = loop index.
__ lw(a2, MemOperand(a0, 0)); // output_[ix]
__ lw(a2, MemOperand(t0, 0)); // output_[ix]
__ lw(a3, MemOperand(a2, FrameDescription::frame_size_offset()));
__ jmp(&inner_loop_header);
__ bind(&inner_push_loop);
......@@ -1151,10 +1156,20 @@ void Deoptimizer::EntryGenerator::Generate() {
__ bind(&inner_loop_header);
__ Branch(&inner_push_loop, ne, a3, Operand(zero_reg));
__ Addu(a0, a0, Operand(kPointerSize));
__ Addu(t0, t0, Operand(kPointerSize));
__ bind(&outer_loop_header);
__ Branch(&outer_push_loop, lt, a0, Operand(a1));
__ Branch(&outer_push_loop, lt, t0, Operand(a1));
if (CpuFeatures::IsSupported(FPU)) {
CpuFeatures::Scope scope(FPU);
__ lw(a1, MemOperand(a0, Deoptimizer::input_offset()));
for (int i = 0; i < FPURegister::kMaxNumAllocatableRegisters; ++i) {
const FPURegister fpu_reg = FPURegister::FromAllocationIndex(i);
int src_offset = i * kDoubleSize + double_regs_offset;
__ ldc1(fpu_reg, MemOperand(a1, src_offset));
}
}
// Push state, pc, and continuation from the last output frame.
if (type() != OSR) {
......
This diff is collapsed.
......@@ -133,6 +133,7 @@ class LCodeGen BASE_EMBEDDED {
void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr);
void DoDeferredStringCharFromCode(LStringCharFromCode* instr);
void DoDeferredAllocateObject(LAllocateObject* instr);
void DoDeferredAllocate(LAllocate* instr);
void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
Label* map_check);
......@@ -326,7 +327,8 @@ class LCodeGen BASE_EMBEDDED {
DoubleRegister result,
bool deoptimize_on_undefined,
bool deoptimize_on_minus_zero,
LEnvironment* env);
LEnvironment* env,
NumberUntagDMode mode);
// Emits optimized code for typeof x == "y". Modifies input register.
// Returns the condition on which a final split to
......
......@@ -2011,12 +2011,16 @@ LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
LInstruction* LChunkBuilder::DoTransitionElementsKind(
HTransitionElementsKind* instr) {
LOperand* object = UseRegister(instr->object());
if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) {
LOperand* object = UseRegister(instr->object());
LOperand* new_map_reg = TempRegister();
LTransitionElementsKind* result =
new(zone()) LTransitionElementsKind(object, new_map_reg, NULL);
return DefineSameAsFirst(result);
} else if (FLAG_compiled_transitions) {
LTransitionElementsKind* result =
new(zone()) LTransitionElementsKind(object, NULL, NULL);
return AssignPointerMap(result);
} else {
LOperand* object = UseFixed(instr->object(), a0);
LOperand* fixed_object_reg = FixedTemp(a2);
......@@ -2025,11 +2029,21 @@ LInstruction* LChunkBuilder::DoTransitionElementsKind(
new(zone()) LTransitionElementsKind(object,
new_map_reg,
fixed_object_reg);
return MarkAsCall(DefineFixed(result, v0), instr);
return MarkAsCall(result, instr);
}
}
LInstruction* LChunkBuilder::DoTrapAllocationMemento(
HTrapAllocationMemento* instr) {
LOperand* object = UseRegister(instr->object());
LOperand* temp = TempRegister();
LTrapAllocationMemento* result =
new(zone()) LTrapAllocationMemento(object, temp);
return AssignEnvironment(result);
}
LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
bool needs_write_barrier = instr->NeedsWriteBarrier();
bool needs_write_barrier_for_map = !instr->transition().is_null() &&
......@@ -2096,12 +2110,23 @@ LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
LInstruction* LChunkBuilder::DoAllocateObject(HAllocateObject* instr) {
info()->MarkAsDeferredCalling();
LAllocateObject* result =
new(zone()) LAllocateObject(TempRegister(), TempRegister());
return AssignPointerMap(DefineAsRegister(result));
}
LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
info()->MarkAsDeferredCalling();
LOperand* size = UseTempRegister(instr->size());
LOperand* temp1 = TempRegister();
LOperand* temp2 = TempRegister();
LAllocate* result = new(zone()) LAllocate(size, temp1, temp2);
return AssignPointerMap(DefineAsRegister(result));
}
LInstruction* LChunkBuilder::DoFastLiteral(HFastLiteral* instr) {
return MarkAsCall(DefineFixed(new(zone()) LFastLiteral, v0), instr);
}
......
......@@ -50,6 +50,7 @@ class LCodeGen;
V(AccessArgumentsAt) \
V(AddI) \
V(AllocateObject) \
V(Allocate) \
V(ApplyArguments) \
V(ArgumentsElements) \
V(ArgumentsLength) \
......@@ -173,6 +174,7 @@ class LCodeGen;
V(Throw) \
V(ToFastProperties) \
V(TransitionElementsKind) \
V(TrapAllocationMemento) \
V(Typeof) \
V(TypeofIsAndBranch) \
V(UnaryMathOperation) \
......@@ -1583,6 +1585,7 @@ class LThisFunction: public LTemplateInstruction<1, 0, 0> {
class LContext: public LTemplateInstruction<1, 0, 0> {
public:
DECLARE_CONCRETE_INSTRUCTION(Context, "context")
DECLARE_HYDROGEN_ACCESSOR(Context)
};
......@@ -1816,6 +1819,7 @@ class LNumberTagD: public LTemplateInstruction<1, 1, 2> {
LOperand* temp2() { return temps_[1]; }
DECLARE_CONCRETE_INSTRUCTION(NumberTagD, "number-tag-d")
DECLARE_HYDROGEN_ACCESSOR(Change)
};
......@@ -2000,10 +2004,10 @@ class LTransitionElementsKind: public LTemplateInstruction<1, 1, 2> {
public:
LTransitionElementsKind(LOperand* object,
LOperand* new_map_temp,
LOperand* temp) {
LOperand* fixed_object_temp) {
inputs_[0] = object;
temps_[0] = new_map_temp;
temps_[1] = temp;
temps_[1] = fixed_object_temp;
}
LOperand* object() { return inputs_[0]; }
......@@ -2023,6 +2027,22 @@ class LTransitionElementsKind: public LTemplateInstruction<1, 1, 2> {
};
class LTrapAllocationMemento : public LTemplateInstruction<0, 1, 1> {
public:
LTrapAllocationMemento(LOperand* object,
LOperand* temp) {
inputs_[0] = object;
temps_[0] = temp;
}
LOperand* object() { return inputs_[0]; }
LOperand* temp() { return temps_[0]; }
DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento,
"trap-allocation-memento")
};
class LStringAdd: public LTemplateInstruction<1, 2, 0> {
public:
LStringAdd(LOperand* left, LOperand* right) {
......@@ -2203,7 +2223,7 @@ class LClampTToUint8: public LTemplateInstruction<1, 1, 1> {
};
class LAllocateObject: public LTemplateInstruction<1, 0, 2> {
class LAllocateObject: public LTemplateInstruction<1, 1, 2> {
public:
LAllocateObject(LOperand* temp, LOperand* temp2) {
temps_[0] = temp;
......@@ -2218,6 +2238,23 @@ class LAllocateObject: public LTemplateInstruction<1, 0, 2> {
};
class LAllocate: public LTemplateInstruction<1, 2, 2> {
public:
LAllocate(LOperand* size, LOperand* temp1, LOperand* temp2) {
inputs_[1] = size;
temps_[0] = temp1;
temps_[1] = temp2;
}
LOperand* size() { return inputs_[1]; }
LOperand* temp1() { return temps_[0]; }
LOperand* temp2() { return temps_[1]; }
DECLARE_CONCRETE_INSTRUCTION(Allocate, "allocate")
DECLARE_HYDROGEN_ACCESSOR(Allocate)
};
class LFastLiteral: public LTemplateInstruction<1, 0, 0> {
public:
DECLARE_CONCRETE_INSTRUCTION(FastLiteral, "fast-literal")
......
......@@ -4632,16 +4632,17 @@ void MacroAssembler::EnterExitFrame(bool save_doubles,
const int frame_alignment = MacroAssembler::ActivationFrameAlignment();
if (save_doubles) {
CpuFeatures::Scope scope(FPU);
// The stack must be allign to 0 modulo 8 for stores with sdc1.
ASSERT(kDoubleSize == frame_alignment);
if (frame_alignment > 0) {
ASSERT(IsPowerOf2(frame_alignment));
And(sp, sp, Operand(-frame_alignment)); // Align stack.
}
int space = FPURegister::kNumRegisters * kDoubleSize;
int space = FPURegister::kMaxNumRegisters * kDoubleSize;
Subu(sp, sp, Operand(space));
// Remember: we only need to save every 2nd double FPU value.
for (int i = 0; i < FPURegister::kNumRegisters; i+=2) {
for (int i = 0; i < FPURegister::kMaxNumRegisters; i+=2) {
FPURegister reg = FPURegister::from_code(i);
sdc1(reg, MemOperand(sp, i * kDoubleSize));
}
......@@ -4669,9 +4670,10 @@ void MacroAssembler::LeaveExitFrame(bool save_doubles,
bool do_return) {
// Optionally restore all double registers.
if (save_doubles) {
CpuFeatures::Scope scope(FPU);
// Remember: we only need to restore every 2nd double FPU value.
lw(t8, MemOperand(fp, ExitFrameConstants::kSPOffset));
for (int i = 0; i < FPURegister::kNumRegisters; i+=2) {
for (int i = 0; i < FPURegister::kMaxNumRegisters; i+=2) {
FPURegister reg = FPURegister::from_code(i);
ldc1(reg, MemOperand(t8, i * kDoubleSize + kPointerSize));
}
......@@ -5448,6 +5450,7 @@ void MacroAssembler::ClampDoubleToUint8(Register result_reg,
void MacroAssembler::TestJSArrayForAllocationSiteInfo(
Register receiver_reg,
Register scratch_reg,
Condition cond,
Label* allocation_info_present) {
Label no_info_available;
ExternalReference new_space_start =
......@@ -5461,7 +5464,7 @@ void MacroAssembler::TestJSArrayForAllocationSiteInfo(
lw(at, MemOperand(at));
Branch(&no_info_available, gt, scratch_reg, Operand(at));
lw(scratch_reg, MemOperand(scratch_reg, -AllocationSiteInfo::kSize));
Branch(allocation_info_present, eq, scratch_reg,
Branch(allocation_info_present, cond, scratch_reg,
Operand(Handle<Map>(isolate()->heap()->allocation_site_info_map())));
bind(&no_info_available);
}
......
......@@ -1448,6 +1448,7 @@ class MacroAssembler: public Assembler {
// If allocation info is present, jump to allocation_info_present
void TestJSArrayForAllocationSiteInfo(Register receiver_reg,
Register scratch_reg,
Condition cond,
Label* allocation_info_present);
private:
......
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