From 40172e6a7b8851649bf55901eea32d6be27db234 Mon Sep 17 00:00:00 2001 From: "sgjesse@chromium.org" Date: Mon, 9 May 2011 14:28:09 +0000 Subject: [PATCH] Update mips infrastructure files. - Merge to current tip of tree, fix build problems. - Remove deprecated source files. - Add cctest test-disasm-mips - Consistently use single-reg push()/pop() (remove uppercase variants) - Add assembler field accessors. - More style fixes. BUG= TEST= Review URL: http://codereview.chromium.org//6965006 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7825 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/mips/assembler-mips-inl.h | 22 +- src/mips/assembler-mips.cc | 299 +++++--- src/mips/assembler-mips.h | 165 +++-- src/mips/builtins-mips.cc | 4 +- src/mips/code-stubs-mips.cc | 263 ++++--- src/mips/code-stubs-mips.h | 465 +++++++----- src/mips/codegen-mips-inl.h | 64 -- src/mips/codegen-mips.cc | 1165 +------------------------------ src/mips/codegen-mips.h | 531 +------------- src/mips/constants-mips.cc | 14 +- src/mips/constants-mips.h | 35 +- src/mips/cpu-mips.cc | 20 +- src/mips/debug-mips.cc | 2 +- src/mips/disasm-mips.cc | 251 ++++--- src/mips/frames-mips.cc | 8 +- src/mips/frames-mips.h | 5 +- src/mips/full-codegen-mips.cc | 13 +- src/mips/ic-mips.cc | 37 +- src/mips/jump-target-mips.cc | 80 --- src/mips/lithium-codegen-mips.h | 2 +- src/mips/lithium-mips.h | 13 +- src/mips/macro-assembler-mips.cc | 508 ++++++++++---- src/mips/macro-assembler-mips.h | 210 ++++-- src/mips/regexp-macro-assembler-mips.cc | 2 +- src/mips/register-allocator-mips-inl.h | 134 ---- src/mips/register-allocator-mips.cc | 63 -- src/mips/register-allocator-mips.h | 47 -- src/mips/simulator-mips.cc | 305 ++++---- src/mips/simulator-mips.h | 35 +- src/mips/stub-cache-mips.cc | 2 +- src/mips/virtual-frame-mips-inl.h | 58 -- src/mips/virtual-frame-mips.cc | 307 -------- src/mips/virtual-frame-mips.h | 530 -------------- test/cctest/SConscript | 3 +- test/cctest/cctest.gyp | 7 +- test/cctest/cctest.status | 1 + test/cctest/test-assembler-mips.cc | 120 ++-- 37 files changed, 1812 insertions(+), 3978 deletions(-) delete mode 100644 src/mips/codegen-mips-inl.h delete mode 100644 src/mips/jump-target-mips.cc delete mode 100644 src/mips/register-allocator-mips-inl.h delete mode 100644 src/mips/register-allocator-mips.cc delete mode 100644 src/mips/register-allocator-mips.h delete mode 100644 src/mips/virtual-frame-mips-inl.h delete mode 100644 src/mips/virtual-frame-mips.cc delete mode 100644 src/mips/virtual-frame-mips.h diff --git a/src/mips/assembler-mips-inl.h b/src/mips/assembler-mips-inl.h index f7453d1..6f7d385 100644 --- a/src/mips/assembler-mips-inl.h +++ b/src/mips/assembler-mips-inl.h @@ -30,7 +30,7 @@ // The original source code covered by the above license above has been // modified significantly by Google Inc. -// Copyright 2010 the V8 project authors. All rights reserved. +// Copyright 2011 the V8 project authors. All rights reserved. #ifndef V8_MIPS_ASSEMBLER_MIPS_INL_H_ @@ -45,7 +45,7 @@ namespace v8 { namespace internal { // ----------------------------------------------------------------------------- -// Operand and MemOperand +// Operand and MemOperand. Operand::Operand(int32_t immediate, RelocInfo::Mode rmode) { rm_ = no_reg; @@ -80,7 +80,7 @@ bool Operand::is_reg() const { // ----------------------------------------------------------------------------- -// RelocInfo +// RelocInfo. void RelocInfo::apply(intptr_t delta) { // On MIPS we do not use pc relative addressing, so we don't need to patch the @@ -254,23 +254,25 @@ void RelocInfo::Visit(ObjectVisitor* visitor) { // RelocInfo is needed when pointer must be updated/serialized, such as // UpdatingVisitor in mark-compact.cc or Serializer in serialize.cc. // It is ignored by visitors that do not need it. - // Commenting out, to simplify arch-independednt changes. + // TODO(mips): Commenting out, to simplify arch-independent changes. // GC won't work like this, but this commit is for asm/disasm/sim. // visitor->VisitPointer(target_object_address(), this); } else if (RelocInfo::IsCodeTarget(mode)) { visitor->VisitCodeTarget(this); + } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) { + visitor->VisitGlobalPropertyCell(this); } else if (mode == RelocInfo::EXTERNAL_REFERENCE) { // RelocInfo is needed when external-references must be serialized by // Serializer Visitor in serialize.cc. It is ignored by visitors that // do not need it. - // Commenting out, to simplify arch-independednt changes. + // TODO(mips): Commenting out, to simplify arch-independent changes. // Serializer won't work like this, but this commit is for asm/disasm/sim. // visitor->VisitExternalReference(target_reference_address(), this); #ifdef ENABLE_DEBUGGER_SUPPORT // TODO(isolates): Get a cached isolate below. } else if (((RelocInfo::IsJSReturn(mode) && IsPatchedReturnSequence()) || - (RelocInfo::IsDebugBreakSlot(mode) && + (RelocInfo::IsDebugBreakSlot(mode) && IsPatchedDebugBreakSlotSequence())) && Isolate::Current()->debug()->has_break_points()) { visitor->VisitDebugTarget(this); @@ -287,7 +289,9 @@ void RelocInfo::Visit(Heap* heap) { if (mode == RelocInfo::EMBEDDED_OBJECT) { StaticVisitor::VisitPointer(heap, target_object_address()); } else if (RelocInfo::IsCodeTarget(mode)) { - StaticVisitor::VisitCodeTarget(this); + StaticVisitor::VisitCodeTarget(heap, this); + } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) { + StaticVisitor::VisitGlobalPropertyCell(heap, this); } else if (mode == RelocInfo::EXTERNAL_REFERENCE) { StaticVisitor::VisitExternalReference(target_reference_address()); #ifdef ENABLE_DEBUGGER_SUPPORT @@ -296,7 +300,7 @@ void RelocInfo::Visit(Heap* heap) { IsPatchedReturnSequence()) || (RelocInfo::IsDebugBreakSlot(mode) && IsPatchedDebugBreakSlotSequence()))) { - StaticVisitor::VisitDebugTarget(this); + StaticVisitor::VisitDebugTarget(heap, this); #endif } else if (mode == RelocInfo::RUNTIME_ENTRY) { StaticVisitor::VisitRuntimeEntry(this); @@ -305,7 +309,7 @@ void RelocInfo::Visit(Heap* heap) { // ----------------------------------------------------------------------------- -// Assembler +// Assembler. void Assembler::CheckBuffer() { diff --git a/src/mips/assembler-mips.cc b/src/mips/assembler-mips.cc index 7d00da1..8a4e11b 100644 --- a/src/mips/assembler-mips.cc +++ b/src/mips/assembler-mips.cc @@ -30,7 +30,7 @@ // The original source code covered by the above license above has been // modified significantly by Google Inc. -// Copyright 2010 the V8 project authors. All rights reserved. +// Copyright 2011 the V8 project authors. All rights reserved. #include "v8.h" @@ -43,13 +43,17 @@ namespace v8 { namespace internal { -CpuFeatures::CpuFeatures() - : supported_(0), - enabled_(0), - found_by_runtime_probing_(0) { -} +#ifdef DEBUG +bool CpuFeatures::initialized_ = false; +#endif +unsigned CpuFeatures::supported_ = 0; +unsigned CpuFeatures::found_by_runtime_probing_ = 0; -void CpuFeatures::Probe(bool portable) { +void CpuFeatures::Probe() { + ASSERT(!initialized_); +#ifdef DEBUG + initialized_ = true; +#endif // If the compiler is allowed to use fpu then we can use fpu too in our // code generation. #if !defined(__mips__) @@ -58,7 +62,7 @@ void CpuFeatures::Probe(bool portable) { supported_ |= 1u << FPU; } #else - if (portable && Serializer::enabled()) { + if (Serializer::enabled()) { supported_ |= OS::CpuFeaturesImpliedByPlatform(); return; // No features if we might serialize. } @@ -69,8 +73,6 @@ void CpuFeatures::Probe(bool portable) { supported_ |= 1u << FPU; found_by_runtime_probing_ |= 1u << FPU; } - - if (!portable) found_by_runtime_probing_ = 0; #endif } @@ -235,11 +237,11 @@ const Instr kLwSwOffsetMask = kImm16Mask; static const int kMinimalBufferSize = 4 * KB; -Assembler::Assembler(void* buffer, int buffer_size) - : AssemblerBase(Isolate::Current()), +Assembler::Assembler(Isolate* arg_isolate, void* buffer, int buffer_size) + : AssemblerBase(arg_isolate), positions_recorder_(this), - allow_peephole_optimization_(false) { - // BUG(3245989): disable peephole optimization if crankshaft is enabled. + allow_peephole_optimization_(false), + emit_debug_code_(FLAG_debug_code) { allow_peephole_optimization_ = FLAG_peephole_optimization; if (buffer == NULL) { // Do our own buffer management. @@ -276,13 +278,16 @@ Assembler::Assembler(void* buffer, int buffer_size) no_trampoline_pool_before_ = 0; trampoline_pool_blocked_nesting_ = 0; next_buffer_check_ = kMaxBranchOffset - kTrampolineSize; + internal_trampoline_exception_ = false; + + ast_id_for_reloc_info_ = kNoASTId; } Assembler::~Assembler() { if (own_buffer_) { if (isolate()->assembler_spare_buffer() == NULL && - buffer_size_ == kMinimalBufferSize) { + buffer_size_ == kMinimalBufferSize) { isolate()->set_assembler_spare_buffer(buffer_); } else { DeleteArray(buffer_); @@ -316,13 +321,82 @@ void Assembler::CodeTargetAlign() { } -Register Assembler::GetRt(Instr instr) { +Register Assembler::GetRtReg(Instr instr) { Register rt; - rt.code_ = (instr & kRtMask) >> kRtShift; + rt.code_ = (instr & kRtFieldMask) >> kRtShift; return rt; } +Register Assembler::GetRsReg(Instr instr) { + Register rs; + rs.code_ = (instr & kRsFieldMask) >> kRsShift; + return rs; +} + + +Register Assembler::GetRdReg(Instr instr) { + Register rd; + rd.code_ = (instr & kRdFieldMask) >> kRdShift; + return rd; +} + + +uint32_t Assembler::GetRt(Instr instr) { + return (instr & kRtFieldMask) >> kRtShift; +} + + +uint32_t Assembler::GetRtField(Instr instr) { + return instr & kRtFieldMask; +} + + +uint32_t Assembler::GetRs(Instr instr) { + return (instr & kRsFieldMask) >> kRsShift; +} + + +uint32_t Assembler::GetRsField(Instr instr) { + return instr & kRsFieldMask; +} + + +uint32_t Assembler::GetRd(Instr instr) { + return (instr & kRdFieldMask) >> kRdShift; +} + + +uint32_t Assembler::GetRdField(Instr instr) { + return instr & kRdFieldMask; +} + + +uint32_t Assembler::GetSa(Instr instr) { + return (instr & kSaFieldMask) >> kSaShift; +} + + +uint32_t Assembler::GetSaField(Instr instr) { + return instr & kSaFieldMask; +} + + +uint32_t Assembler::GetOpcodeField(Instr instr) { + return instr & kOpcodeMask; +} + + +uint32_t Assembler::GetImmediate16(Instr instr) { + return instr & kImm16Mask; +} + + +uint32_t Assembler::GetLabelConst(Instr instr) { + return instr & ~kImm16Mask; +} + + bool Assembler::IsPop(Instr instr) { return (instr & ~kRtMask) == kPopRegPattern; } @@ -374,10 +448,10 @@ const int kEndOfChain = -4; bool Assembler::IsBranch(Instr instr) { - uint32_t opcode = ((instr & kOpcodeMask)); - uint32_t rt_field = ((instr & kRtFieldMask)); - uint32_t rs_field = ((instr & kRsFieldMask)); - uint32_t label_constant = (instr & ~kImm16Mask); + uint32_t opcode = GetOpcodeField(instr); + uint32_t rt_field = GetRtField(instr); + uint32_t rs_field = GetRsField(instr); + uint32_t label_constant = GetLabelConst(instr); // Checks if the instruction is a branch. return opcode == BEQ || opcode == BNE || @@ -386,7 +460,7 @@ bool Assembler::IsBranch(Instr instr) { opcode == BEQL || opcode == BNEL || opcode == BLEZL || - opcode == BGTZL|| + opcode == BGTZL || (opcode == REGIMM && (rt_field == BLTZ || rt_field == BGEZ || rt_field == BLTZAL || rt_field == BGEZAL)) || (opcode == COP1 && rs_field == BC1) || // Coprocessor branch. @@ -394,13 +468,23 @@ bool Assembler::IsBranch(Instr instr) { } +bool Assembler::IsBeq(Instr instr) { + return GetOpcodeField(instr) == BEQ; +} + + +bool Assembler::IsBne(Instr instr) { + return GetOpcodeField(instr) == BNE; +} + + bool Assembler::IsNop(Instr instr, unsigned int type) { // See Assembler::nop(type). ASSERT(type < 32); - uint32_t opcode = ((instr & kOpcodeMask)); - uint32_t rt = ((instr & kRtFieldMask) >> kRtShift); - uint32_t rs = ((instr & kRsFieldMask) >> kRsShift); - uint32_t sa = ((instr & kSaFieldMask) >> kSaShift); + uint32_t opcode = GetOpcodeField(instr); + uint32_t rt = GetRt(instr); + uint32_t rs = GetRs(instr); + uint32_t sa = GetSa(instr); // nop(type) == sll(zero_reg, zero_reg, type); // Technically all these values will be 0 but @@ -465,6 +549,11 @@ Instr Assembler::SetAddImmediateOffset(Instr instr, int16_t offset) { } +bool Assembler::IsAndImmediate(Instr instr) { + return GetOpcodeField(instr) == ANDI; +} + + int Assembler::target_at(int32_t pos) { Instr instr = instr_at(pos); if ((instr & ~kImm16Mask) == 0) { @@ -546,6 +635,10 @@ void Assembler::bind_to(Label* L, int pos) { if (dist > kMaxBranchOffset) { do { int32_t trampoline_pos = get_trampoline_entry(fixup_pos); + if (kInvalidSlotPos == trampoline_pos) { + // Internal error. + return; + } ASSERT((trampoline_pos - fixup_pos) <= kMaxBranchOffset); target_at_put(fixup_pos, trampoline_pos); fixup_pos = trampoline_pos; @@ -554,6 +647,10 @@ void Assembler::bind_to(Label* L, int pos) { } else if (dist < -kMaxBranchOffset) { do { int32_t trampoline_pos = get_trampoline_entry(fixup_pos, false); + if (kInvalidSlotPos == trampoline_pos) { + // Internal error. + return; + } ASSERT((trampoline_pos - fixup_pos) >= -kMaxBranchOffset); target_at_put(fixup_pos, trampoline_pos); fixup_pos = trampoline_pos; @@ -652,7 +749,7 @@ void Assembler::GenInstrRegister(Opcode opcode, FPURegister fd, SecondaryField func) { ASSERT(fd.is_valid() && fs.is_valid() && ft.is_valid()); - ASSERT(isolate()->cpu_features()->IsEnabled(FPU)); + ASSERT(CpuFeatures::IsEnabled(FPU)); Instr instr = opcode | fmt | (ft.code() << kFtShift) | (fs.code() << kFsShift) | (fd.code() << kFdShift) | func; emit(instr); @@ -666,7 +763,7 @@ void Assembler::GenInstrRegister(Opcode opcode, FPURegister fd, SecondaryField func) { ASSERT(fd.is_valid() && fs.is_valid() && rt.is_valid()); - ASSERT(isolate()->cpu_features()->IsEnabled(FPU)); + ASSERT(CpuFeatures::IsEnabled(FPU)); Instr instr = opcode | fmt | (rt.code() << kRtShift) | (fs.code() << kFsShift) | (fd.code() << kFdShift) | func; emit(instr); @@ -679,7 +776,7 @@ void Assembler::GenInstrRegister(Opcode opcode, FPUControlRegister fs, SecondaryField func) { ASSERT(fs.is_valid() && rt.is_valid()); - ASSERT(isolate()->cpu_features()->IsEnabled(FPU)); + ASSERT(CpuFeatures::IsEnabled(FPU)); Instr instr = opcode | fmt | (rt.code() << kRtShift) | (fs.code() << kFsShift) | func; emit(instr); @@ -714,7 +811,7 @@ void Assembler::GenInstrImmediate(Opcode opcode, FPURegister ft, int32_t j) { ASSERT(rs.is_valid() && ft.is_valid() && (is_int16(j) || is_uint16(j))); - ASSERT(isolate()->cpu_features()->IsEnabled(FPU)); + ASSERT(CpuFeatures::IsEnabled(FPU)); Instr instr = opcode | (rs.code() << kRsShift) | (ft.code() << kFtShift) | (j & kImm16Mask); emit(instr); @@ -760,23 +857,28 @@ int32_t Assembler::get_label_entry(int32_t pos, bool next_pool) { // Returns the next free trampoline entry from the next trampoline pool. int32_t Assembler::get_trampoline_entry(int32_t pos, bool next_pool) { int trampoline_count = trampolines_.length(); - int32_t trampoline_entry = 0; + int32_t trampoline_entry = kInvalidSlotPos; ASSERT(trampoline_count > 0); - if (next_pool) { - for (int i = 0; i < trampoline_count; i++) { - if (trampolines_[i].start() > pos) { - trampoline_entry = trampolines_[i].take_slot(); - break; + if (!internal_trampoline_exception_) { + if (next_pool) { + for (int i = 0; i < trampoline_count; i++) { + if (trampolines_[i].start() > pos) { + trampoline_entry = trampolines_[i].take_slot(); + break; + } } - } - } else { // Caller needs a trampoline entry from the previous pool. - for (int i = trampoline_count-1; i >= 0; i--) { - if (trampolines_[i].end() < pos) { - trampoline_entry = trampolines_[i].take_slot(); - break; + } else { // Caller needs a trampoline entry from the previous pool. + for (int i = trampoline_count-1; i >= 0; i--) { + if (trampolines_[i].end() < pos) { + trampoline_entry = trampolines_[i].take_slot(); + break; + } } } + if (kInvalidSlotPos == trampoline_entry) { + internal_trampoline_exception_ = true; + } } return trampoline_entry; } @@ -792,6 +894,10 @@ int32_t Assembler::branch_offset(Label* L, bool jump_elimination_allowed) { if (dist > kMaxBranchOffset) { do { int32_t trampoline_pos = get_trampoline_entry(target_pos); + if (kInvalidSlotPos == trampoline_pos) { + // Internal error. + return 0; + } ASSERT((trampoline_pos - target_pos) > 0); ASSERT((trampoline_pos - target_pos) <= kMaxBranchOffset); target_at_put(trampoline_pos, target_pos); @@ -801,6 +907,10 @@ int32_t Assembler::branch_offset(Label* L, bool jump_elimination_allowed) { } else if (dist < -kMaxBranchOffset) { do { int32_t trampoline_pos = get_trampoline_entry(target_pos, false); + if (kInvalidSlotPos == trampoline_pos) { + // Internal error. + return 0; + } ASSERT((target_pos - trampoline_pos) > 0); ASSERT((target_pos - trampoline_pos) <= kMaxBranchOffset); target_at_put(trampoline_pos, target_pos); @@ -1018,8 +1128,8 @@ void Assembler::addiu(Register rd, Register rs, int32_t j) { // we delete both the push & pop and insert a register move. // push ry, pop rx --> mov rx, ry. Register reg_pushed, reg_popped; - reg_pushed = GetRt(push_instr); - reg_popped = GetRt(pop_instr); + reg_pushed = GetRtReg(push_instr); + reg_popped = GetRtReg(pop_instr); pc_ -= 4 * kInstrSize; // Insert a mov instruction, which is better than a pair of push & pop. or_(reg_popped, reg_pushed, zero_reg); @@ -1054,7 +1164,7 @@ void Assembler::addiu(Register rd, Register rs, int32_t j) { if ((mem_write_instr & kRtMask) == (mem_read_instr & kRtMask)) { // Pattern: push & pop from/to same register, - // with a fp+offset lw in between. + // with a fp + offset lw in between. // // The following: // addiu sp, sp, -4 @@ -1077,7 +1187,8 @@ void Assembler::addiu(Register rd, Register rs, int32_t j) { emit(lw_instr); } if (FLAG_print_peephole_optimization) { - PrintF("%x push/pop -dead ldr fp+offset in middle\n", pc_offset()); + PrintF("%x push/pop -dead ldr fp + offset in middle\n", + pc_offset()); } } else { // Pattern: push & pop from/to different registers @@ -1102,14 +1213,14 @@ void Assembler::addiu(Register rd, Register rs, int32_t j) { Register reg_pushed, reg_popped; if ((mem_read_instr & kRtMask) == (lw_instr & kRtMask)) { - reg_pushed = GetRt(mem_write_instr); - reg_popped = GetRt(mem_read_instr); + reg_pushed = GetRtReg(mem_write_instr); + reg_popped = GetRtReg(mem_read_instr); pc_ -= 5 * kInstrSize; or_(reg_popped, reg_pushed, zero_reg); // Move instruction. } else if ((mem_write_instr & kRtMask) != (lw_instr & kRtMask)) { - reg_pushed = GetRt(mem_write_instr); - reg_popped = GetRt(mem_read_instr); + reg_pushed = GetRtReg(mem_write_instr); + reg_popped = GetRtReg(mem_read_instr); pc_ -= 5 * kInstrSize; emit(lw_instr); or_(reg_popped, reg_pushed, zero_reg); // Move instruction. @@ -1117,8 +1228,8 @@ void Assembler::addiu(Register rd, Register rs, int32_t j) { != (lw_instr & kRtMask)) || ((mem_write_instr & kRtMask) == (lw_instr & kRtMask)) ) { - reg_pushed = GetRt(mem_write_instr); - reg_popped = GetRt(mem_read_instr); + reg_pushed = GetRtReg(mem_write_instr); + reg_popped = GetRtReg(mem_read_instr); pc_ -= 5 * kInstrSize; or_(reg_popped, reg_pushed, zero_reg); // Move instruction. emit(lw_instr); @@ -1354,8 +1465,8 @@ void Assembler::lw(Register rd, const MemOperand& rs) { // mov ry, rx Register reg_stored, reg_loaded; - reg_stored = GetRt(sw_instr); - reg_loaded = GetRt(lw_instr); + reg_stored = GetRtReg(sw_instr); + reg_loaded = GetRtReg(lw_instr); pc_ -= 1 * kInstrSize; // Insert a mov instruction, which is better than lw. or_(reg_loaded, reg_stored, zero_reg); // Move instruction. @@ -1545,14 +1656,14 @@ void Assembler::movn(Register rd, Register rs, Register rt) { void Assembler::movt(Register rd, Register rs, uint16_t cc) { Register rt; - rt.code_ = (cc & 0x0003) << 2 | 1; + rt.code_ = (cc & 0x0007) << 2 | 1; GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI); } void Assembler::movf(Register rd, Register rs, uint16_t cc) { Register rt; - rt.code_ = (cc & 0x0003) << 2 | 0; + rt.code_ = (cc & 0x0007) << 2 | 0; GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI); } @@ -1816,7 +1927,7 @@ void Assembler::cvt_d_s(FPURegister fd, FPURegister fs) { // Conditions. void Assembler::c(FPUCondition cond, SecondaryField fmt, FPURegister fs, FPURegister ft, uint16_t cc) { - ASSERT(isolate()->cpu_features()->IsEnabled(FPU)); + ASSERT(CpuFeatures::IsEnabled(FPU)); ASSERT(is_uint3(cc)); ASSERT((fmt & ~(31 << kRsShift)) == 0); Instr instr = COP1 | fmt | ft.code() << 16 | fs.code() << kFsShift @@ -1827,7 +1938,7 @@ void Assembler::c(FPUCondition cond, SecondaryField fmt, void Assembler::fcmp(FPURegister src1, const double src2, FPUCondition cond) { - ASSERT(isolate()->cpu_features()->IsSupported(FPU)); + ASSERT(CpuFeatures::IsEnabled(FPU)); ASSERT(src2 == 0.0); mtc1(zero_reg, f14); cvt_d_w(f14, f14); @@ -1836,7 +1947,7 @@ void Assembler::fcmp(FPURegister src1, const double src2, void Assembler::bc1f(int16_t offset, uint16_t cc) { - ASSERT(isolate()->cpu_features()->IsEnabled(FPU)); + ASSERT(CpuFeatures::IsEnabled(FPU)); ASSERT(is_uint3(cc)); Instr instr = COP1 | BC1 | cc << 18 | 0 << 16 | (offset & kImm16Mask); emit(instr); @@ -1844,7 +1955,7 @@ void Assembler::bc1f(int16_t offset, uint16_t cc) { void Assembler::bc1t(int16_t offset, uint16_t cc) { - ASSERT(isolate()->cpu_features()->IsEnabled(FPU)); + ASSERT(CpuFeatures::IsEnabled(FPU)); ASSERT(is_uint3(cc)); Instr instr = COP1 | BC1 | cc << 18 | 1 << 16 | (offset & kImm16Mask); emit(instr); @@ -1949,7 +2060,14 @@ void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { return; } ASSERT(buffer_space() >= kMaxRelocSize); // Too late to grow buffer here. - reloc_info_writer.Write(&rinfo); + if (rmode == RelocInfo::CODE_TARGET_WITH_ID) { + ASSERT(ast_id_for_reloc_info_ != kNoASTId); + RelocInfo reloc_info_with_ast_id(pc_, rmode, ast_id_for_reloc_info_); + ast_id_for_reloc_info_ = kNoASTId; + reloc_info_writer.Write(&reloc_info_with_ast_id); + } else { + reloc_info_writer.Write(&rinfo); + } } } @@ -2017,72 +2135,39 @@ void Assembler::CheckTrampolinePool(bool force_emit) { Address Assembler::target_address_at(Address pc) { Instr instr1 = instr_at(pc); Instr instr2 = instr_at(pc + kInstrSize); - // Check we have 2 instructions generated by li. - ASSERT(((instr1 & kOpcodeMask) == LUI && (instr2 & kOpcodeMask) == ORI) || - ((instr1 == nopInstr) && ((instr2 & kOpcodeMask) == ADDI || - (instr2 & kOpcodeMask) == ORI || - (instr2 & kOpcodeMask) == LUI))); - // Interpret these 2 instructions. - if (instr1 == nopInstr) { - if ((instr2 & kOpcodeMask) == ADDI) { - return reinterpret_cast
(((instr2 & kImm16Mask) << 16) >> 16); - } else if ((instr2 & kOpcodeMask) == ORI) { - return reinterpret_cast
(instr2 & kImm16Mask); - } else if ((instr2 & kOpcodeMask) == LUI) { - return reinterpret_cast
((instr2 & kImm16Mask) << 16); - } - } else if ((instr1 & kOpcodeMask) == LUI && (instr2 & kOpcodeMask) == ORI) { - // 32 bit value. + // Interpret 2 instructions generated by li: lui/ori + if ((GetOpcodeField(instr1) == LUI) && (GetOpcodeField(instr2) == ORI)) { + // Assemble the 32 bit value. return reinterpret_cast
( - (instr1 & kImm16Mask) << 16 | (instr2 & kImm16Mask)); + (GetImmediate16(instr1) << 16) | GetImmediate16(instr2)); } - // We should never get here. + // We should never get here, force a bad address if we do. UNREACHABLE(); return (Address)0x0; } void Assembler::set_target_address_at(Address pc, Address target) { - // On MIPS we need to patch the code to generate. + // On MIPS we patch the address into lui/ori instruction pair. - // First check we have a li. + // First check we have an li (lui/ori pair). Instr instr2 = instr_at(pc + kInstrSize); #ifdef DEBUG Instr instr1 = instr_at(pc); // Check we have indeed the result from a li with MustUseReg true. - CHECK(((instr1 & kOpcodeMask) == LUI && (instr2 & kOpcodeMask) == ORI) || - ((instr1 == 0) && ((instr2 & kOpcodeMask)== ADDIU || - (instr2 & kOpcodeMask)== ORI || - (instr2 & kOpcodeMask)== LUI))); + CHECK((GetOpcodeField(instr1) == LUI && GetOpcodeField(instr2) == ORI)); #endif - uint32_t rt_code = (instr2 & kRtFieldMask); + uint32_t rt_code = GetRtField(instr2); uint32_t* p = reinterpret_cast(pc); uint32_t itarget = reinterpret_cast(target); - if (is_int16(itarget)) { - // nop. - // addiu rt zero_reg j. - *p = nopInstr; - *(p+1) = ADDIU | rt_code | (itarget & kImm16Mask); - } else if (!(itarget & kHiMask)) { - // nop. - // ori rt zero_reg j. - *p = nopInstr; - *(p+1) = ORI | rt_code | (itarget & kImm16Mask); - } else if (!(itarget & kImm16Mask)) { - // nop. - // lui rt (kHiMask & itarget) >> kLuiShift. - *p = nopInstr; - *(p+1) = LUI | rt_code | ((itarget & kHiMask) >> kLuiShift); - } else { - // lui rt (kHiMask & itarget) >> kLuiShift. - // ori rt rt, (kImm16Mask & itarget). - *p = LUI | rt_code | ((itarget & kHiMask) >> kLuiShift); - *(p+1) = ORI | rt_code | (rt_code << 5) | (itarget & kImm16Mask); - } + // lui rt, high-16. + // ori rt rt, low-16. + *p = LUI | rt_code | ((itarget & kHiMask) >> kLuiShift); + *(p+1) = ORI | rt_code | (rt_code << 5) | (itarget & kImm16Mask); CPU::FlushICache(pc, 2 * sizeof(int32_t)); } diff --git a/src/mips/assembler-mips.h b/src/mips/assembler-mips.h index 5a6e271..1a49148 100644 --- a/src/mips/assembler-mips.h +++ b/src/mips/assembler-mips.h @@ -30,7 +30,7 @@ // The original source code covered by the above license above has been // modified significantly by Google Inc. -// Copyright 2010 the V8 project authors. All rights reserved. +// Copyright 2011 the V8 project authors. All rights reserved. #ifndef V8_MIPS_ASSEMBLER_MIPS_H_ @@ -67,12 +67,13 @@ namespace internal { // ----------------------------------------------------------------------------- -// Implementation of Register and FPURegister +// Implementation of Register and FPURegister. // Core register. struct Register { static const int kNumRegisters = v8::internal::kNumRegisters; - static const int kNumAllocatableRegisters = 14; // v0 through t7 + static const int kNumAllocatableRegisters = 14; // v0 through t7. + static const int kSizeInBytes = 4; static int ToAllocationIndex(Register reg) { return reg.code() - 2; // zero_reg and 'at' are skipped. @@ -267,9 +268,6 @@ const FPURegister f31 = { 31 }; // FPU (coprocessor 1) control registers. // Currently only FCSR (#31) is implemented. struct FPUControlRegister { - static const int kFCSRRegister = 31; - static const int kInvalidFPUControlRegister = -1; - bool is_valid() const { return code_ == kFCSRRegister; } bool is(FPUControlRegister creg) const { return code_ == creg.code_; } int code() const { @@ -288,7 +286,7 @@ struct FPUControlRegister { int code_; }; -const FPUControlRegister no_fpucreg = { -1 }; +const FPUControlRegister no_fpucreg = { kInvalidFPUControlRegister }; const FPUControlRegister FCSR = { kFCSRRegister }; @@ -318,7 +316,7 @@ class Operand BASE_EMBEDDED { private: Register rm_; - int32_t imm32_; // Valid if rm_ == no_reg + int32_t imm32_; // Valid if rm_ == no_reg. RelocInfo::Mode rmode_; friend class Assembler; @@ -342,58 +340,98 @@ class MemOperand : public Operand { // CpuFeatures keeps track of which features are supported by the target CPU. // Supported features must be enabled by a Scope before use. -class CpuFeatures { +class CpuFeatures : public AllStatic { public: // Detect features of the target CPU. Set safe defaults if the serializer // is enabled (snapshots must be portable). - void Probe(bool portable); + static void Probe(); // Check whether a feature is supported by the target CPU. - bool IsSupported(CpuFeature f) const { + static bool IsSupported(CpuFeature f) { + ASSERT(initialized_); if (f == FPU && !FLAG_enable_fpu) return false; return (supported_ & (1u << f)) != 0; } + +#ifdef DEBUG // Check whether a feature is currently enabled. - bool IsEnabled(CpuFeature f) const { - return (enabled_ & (1u << f)) != 0; + static bool IsEnabled(CpuFeature f) { + ASSERT(initialized_); + Isolate* isolate = Isolate::UncheckedCurrent(); + if (isolate == NULL) { + // When no isolate is available, work as if we're running in + // release mode. + return IsSupported(f); + } + unsigned enabled = static_cast(isolate->enabled_cpu_features()); + return (enabled & (1u << f)) != 0; } +#endif // Enable a specified feature within a scope. class Scope BASE_EMBEDDED { #ifdef DEBUG public: - explicit Scope(CpuFeature f) - : cpu_features_(Isolate::Current()->cpu_features()), - isolate_(Isolate::Current()) { - ASSERT(cpu_features_->IsSupported(f)); + explicit Scope(CpuFeature f) { + unsigned mask = 1u << f; + ASSERT(CpuFeatures::IsSupported(f)); ASSERT(!Serializer::enabled() || - (cpu_features_->found_by_runtime_probing_ & (1u << f)) == 0); - old_enabled_ = cpu_features_->enabled_; - cpu_features_->enabled_ |= 1u << f; + (CpuFeatures::found_by_runtime_probing_ & mask) == 0); + isolate_ = Isolate::UncheckedCurrent(); + old_enabled_ = 0; + if (isolate_ != NULL) { + old_enabled_ = static_cast(isolate_->enabled_cpu_features()); + isolate_->set_enabled_cpu_features(old_enabled_ | mask); + } } ~Scope() { - ASSERT_EQ(Isolate::Current(), isolate_); - cpu_features_->enabled_ = old_enabled_; - } + ASSERT_EQ(Isolate::UncheckedCurrent(), isolate_); + if (isolate_ != NULL) { + isolate_->set_enabled_cpu_features(old_enabled_); + } + } private: - unsigned old_enabled_; - CpuFeatures* cpu_features_; Isolate* isolate_; + unsigned old_enabled_; #else public: explicit Scope(CpuFeature f) {} #endif }; - private: - CpuFeatures(); + class TryForceFeatureScope BASE_EMBEDDED { + public: + explicit TryForceFeatureScope(CpuFeature f) + : old_supported_(CpuFeatures::supported_) { + if (CanForce()) { + CpuFeatures::supported_ |= (1u << f); + } + } - unsigned supported_; - unsigned enabled_; - unsigned found_by_runtime_probing_; + ~TryForceFeatureScope() { + if (CanForce()) { + CpuFeatures::supported_ = old_supported_; + } + } - friend class Isolate; + private: + static bool CanForce() { + // It's only safe to temporarily force support of CPU features + // when there's only a single isolate, which is guaranteed when + // the serializer is enabled. + return Serializer::enabled(); + } + + const unsigned old_supported_; + }; + + private: +#ifdef DEBUG + static bool initialized_; +#endif + static unsigned supported_; + static unsigned found_by_runtime_probing_; DISALLOW_COPY_AND_ASSIGN(CpuFeatures); }; @@ -414,7 +452,7 @@ class Assembler : public AssemblerBase { // for code generation and assumes its size to be buffer_size. If the buffer // is too small, a fatal error occurs. No deallocation of the buffer is done // upon destruction of the assembler. - Assembler(void* buffer, int buffer_size); + Assembler(Isolate* isolate, void* buffer, int buffer_size); ~Assembler(); // Overrides the default provided by FLAG_debug_code. @@ -439,10 +477,10 @@ class Assembler : public AssemblerBase { // // Note: The same Label can be used for forward and backward branches // but it may be bound only once. - void bind(Label* L); // binds an unbound label L to the current code position + void bind(Label* L); // Binds an unbound label L to current code position. - // Returns the branch offset to the given label from the current code position - // Links the label to the current position if it is still unbound + // Returns the branch offset to the given label from the current code + // position. Links the label to the current position if it is still unbound. // Manages the jump elimination optimization if the second parameter is true. int32_t branch_offset(Label* L, bool jump_elimination_allowed); int32_t shifted_branch_offset(Label* L, bool jump_elimination_allowed) { @@ -541,14 +579,14 @@ class Assembler : public AssemblerBase { FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED }; - // type == 0 is the default non-marking type. + // Type == 0 is the default non-marking type. void nop(unsigned int type = 0) { ASSERT(type < 32); sll(zero_reg, zero_reg, type, true); } - //------- Branch and jump instructions -------- + // --------Branch-and-jump-instructions---------- // We don't use likely variant of instructions. void b(int16_t offset); void b(Label* L) { b(branch_offset(L, false)>>2); } @@ -571,7 +609,7 @@ class Assembler : public AssemblerBase { } // Never use the int16_t b(l)cond version with a branch offset - // instead of using the Label* version. See Twiki for infos. + // instead of using the Label* version. // Jump targets must be in the current 256 MB-aligned region. ie 28 bits. void j(int32_t target); @@ -761,6 +799,10 @@ class Assembler : public AssemblerBase { // Mark address of a debug break slot. void RecordDebugBreakSlot(); + // Record the AST id of the CallIC being compiled, so that it can be placed + // in the relocation information. + void RecordAstId(unsigned ast_id) { ast_id_for_reloc_info_ = ast_id; } + // Record a comment relocation entry that can be used by a disassembler. // Use --code-comments to enable. void RecordComment(const char* msg); @@ -804,6 +846,8 @@ class Assembler : public AssemblerBase { // Check if an instruction is a branch of some kind. static bool IsBranch(Instr instr); + static bool IsBeq(Instr instr); + static bool IsBne(Instr instr); static bool IsNop(Instr instr, unsigned int type); static bool IsPop(Instr instr); @@ -813,7 +857,21 @@ class Assembler : public AssemblerBase { static bool IsLwRegFpNegOffset(Instr instr); static bool IsSwRegFpNegOffset(Instr instr); - static Register GetRt(Instr instr); + static Register GetRtReg(Instr instr); + static Register GetRsReg(Instr instr); + static Register GetRdReg(Instr instr); + + static uint32_t GetRt(Instr instr); + static uint32_t GetRtField(Instr instr); + static uint32_t GetRs(Instr instr); + static uint32_t GetRsField(Instr instr); + static uint32_t GetRd(Instr instr); + static uint32_t GetRdField(Instr instr); + static uint32_t GetSa(Instr instr); + static uint32_t GetSaField(Instr instr); + static uint32_t GetOpcodeField(Instr instr); + static uint32_t GetImmediate16(Instr instr); + static uint32_t GetLabelConst(Instr instr); static int32_t GetBranchOffset(Instr instr); static bool IsLw(Instr instr); @@ -825,9 +883,16 @@ class Assembler : public AssemblerBase { static bool IsAddImmediate(Instr instr); static Instr SetAddImmediateOffset(Instr instr, int16_t offset); + static bool IsAndImmediate(Instr instr); + void CheckTrampolinePool(bool force_emit = false); protected: + // Relocation for a type-recording IC has the AST id added to it. This + // member variable is a way to pass the information from the call site to + // the relocation info. + unsigned ast_id_for_reloc_info_; + bool emit_debug_code() const { return emit_debug_code_; } int32_t buffer_space() const { return reloc_info_writer.pos() - pc_; } @@ -861,6 +926,10 @@ class Assembler : public AssemblerBase { return trampoline_pool_blocked_nesting_ > 0; } + bool has_exception() const { + return internal_trampoline_exception_; + } + private: // Code buffer: // The buffer into which code and relocation info are generated. @@ -1005,10 +1074,18 @@ class Assembler : public AssemblerBase { return end_; } int take_slot() { - int trampoline_slot = next_slot_; - ASSERT(free_slot_count_ > 0); - free_slot_count_--; - next_slot_ += 2 * kInstrSize; + int trampoline_slot = kInvalidSlotPos; + if (free_slot_count_ <= 0) { + // We have run out of space on trampolines. + // Make sure we fail in debug mode, so we become aware of each case + // when this happens. + ASSERT(0); + // Internal exception will be caught. + } else { + trampoline_slot = next_slot_; + free_slot_count_--; + next_slot_ += 2*kInstrSize; + } return trampoline_slot; } int take_label() { @@ -1038,8 +1115,10 @@ class Assembler : public AssemblerBase { static const int kMaxBranchOffset = (1 << (18 - 1)) - 1; static const int kMaxDistBetweenPools = kMaxBranchOffset - 2 * kTrampolineSize; + static const int kInvalidSlotPos = -1; List trampolines_; + bool internal_trampoline_exception_; friend class RegExpMacroAssemblerMIPS; friend class RelocInfo; diff --git a/src/mips/builtins-mips.cc b/src/mips/builtins-mips.cc index b4bab8e..5cbeda8 100644 --- a/src/mips/builtins-mips.cc +++ b/src/mips/builtins-mips.cc @@ -1,4 +1,4 @@ -// Copyright 2010 the V8 project authors. All rights reserved. +// Copyright 2011 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -31,7 +31,7 @@ #if defined(V8_TARGET_ARCH_MIPS) -#include "codegen-inl.h" +#include "codegen.h" #include "debug.h" #include "deoptimizer.h" #include "full-codegen.h" diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc index cf6c652..e0028f8 100644 --- a/src/mips/code-stubs-mips.cc +++ b/src/mips/code-stubs-mips.cc @@ -31,7 +31,7 @@ #include "bootstrapper.h" #include "code-stubs.h" -#include "codegen-inl.h" +#include "codegen.h" #include "regexp-macro-assembler.h" namespace v8 { @@ -111,63 +111,6 @@ void ConvertToDoubleStub::Generate(MacroAssembler* masm) { } -class FloatingPointHelper : public AllStatic { - public: - - enum Destination { - kFPURegisters, - kCoreRegisters - }; - - - // Loads smis from a0 and a1 (right and left in binary operations) into - // floating point registers. Depending on the destination the values ends up - // either f14 and f12 or in a2/a3 and a0/a1 respectively. If the destination - // is floating point registers FPU must be supported. If core registers are - // requested when FPU is supported f12 and f14 will be scratched. - static void LoadSmis(MacroAssembler* masm, - Destination destination, - Register scratch1, - Register scratch2); - - // Loads objects from a0 and a1 (right and left in binary operations) into - // floating point registers. Depending on the destination the values ends up - // either f14 and f12 or in a2/a3 and a0/a1 respectively. If the destination - // is floating point registers FPU must be supported. If core registers are - // requested when FPU is supported f12 and f14 will still be scratched. If - // either a0 or a1 is not a number (not smi and not heap number object) the - // not_number label is jumped to with a0 and a1 intact. - static void LoadOperands(MacroAssembler* masm, - FloatingPointHelper::Destination destination, - Register heap_number_map, - Register scratch1, - Register scratch2, - Label* not_number); - // Loads the number from object into dst as a 32-bit integer if possible. If - // the object is not a 32-bit integer control continues at the label - // not_int32. If FPU is supported double_scratch is used but not scratch2. - static void LoadNumberAsInteger(MacroAssembler* masm, - Register object, - Register dst, - Register heap_number_map, - Register scratch1, - Register scratch2, - FPURegister double_scratch, - Label* not_int32); - private: - static void LoadNumber(MacroAssembler* masm, - FloatingPointHelper::Destination destination, - Register object, - FPURegister dst, - Register dst1, - Register dst2, - Register heap_number_map, - Register scratch1, - Register scratch2, - Label* not_number); -}; - - void FloatingPointHelper::LoadSmis(MacroAssembler* masm, FloatingPointHelper::Destination destination, Register scratch1, @@ -201,14 +144,74 @@ void FloatingPointHelper::LoadNumber(MacroAssembler* masm, } -void FloatingPointHelper::LoadNumberAsInteger(MacroAssembler* masm, - Register object, - Register dst, - Register heap_number_map, - Register scratch1, - Register scratch2, - FPURegister double_scratch, - Label* not_int32) { +void FloatingPointHelper::ConvertNumberToInt32(MacroAssembler* masm, + Register object, + Register dst, + Register heap_number_map, + Register scratch1, + Register scratch2, + Register scratch3, + FPURegister double_scratch, + Label* not_number) { + UNIMPLEMENTED_MIPS(); +} + + +void FloatingPointHelper::ConvertIntToDouble(MacroAssembler* masm, + Register int_scratch, + Destination destination, + FPURegister double_dst, + Register dst1, + Register dst2, + Register scratch2, + FPURegister single_scratch) { + UNIMPLEMENTED_MIPS(); +} + + +void FloatingPointHelper::LoadNumberAsInt32Double(MacroAssembler* masm, + Register object, + Destination destination, + FPURegister double_dst, + Register dst1, + Register dst2, + Register heap_number_map, + Register scratch1, + Register scratch2, + FPURegister single_scratch, + Label* not_int32) { + UNIMPLEMENTED_MIPS(); +} + + +void FloatingPointHelper::LoadNumberAsInt32(MacroAssembler* masm, + Register object, + Register dst, + Register heap_number_map, + Register scratch1, + Register scratch2, + Register scratch3, + FPURegister double_scratch, + Label* not_int32) { + UNIMPLEMENTED_MIPS(); +} + + +void FloatingPointHelper::DoubleIs32BitInteger(MacroAssembler* masm, + Register src1, + Register src2, + Register dst, + Register scratch, + Label* not_int32) { + UNIMPLEMENTED_MIPS(); +} + + +void FloatingPointHelper::CallCCodeForDoubleOperation( + MacroAssembler* masm, + Token::Value op, + Register heap_number_result, + Register scratch) { UNIMPLEMENTED_MIPS(); } @@ -256,49 +259,107 @@ void ToBooleanStub::Generate(MacroAssembler* masm) { } -// We fall into this code if the operands were Smis, but the result was -// not (eg. overflow). We branch into this code (to the not_smi label) if -// the operands were not both Smi. The operands are in lhs and rhs. -// To call the C-implemented binary fp operation routines we need to end up -// with the double precision floating point operands in a0 and a1 (for the -// value in a1) and a2 and a3 (for the value in a0). -void GenericBinaryOpStub::HandleBinaryOpSlowCases(MacroAssembler* masm, - Label* not_smi, - Register lhs, - Register rhs, - const Builtins::JavaScript& builtin) { +Handle GetTypeRecordingUnaryOpStub(int key, + TRUnaryOpIC::TypeInfo type_info) { + TypeRecordingUnaryOpStub stub(key, type_info); + return stub.GetCode(); +} + + +const char* TypeRecordingUnaryOpStub::GetName() { UNIMPLEMENTED_MIPS(); + return NULL; } -// For bitwise ops where the inputs are not both Smis we here try to determine -// whether both inputs are either Smis or at least heap numbers that can be -// represented by a 32 bit signed value. We truncate towards zero as required -// by the ES spec. If this is the case we do the bitwise op and see if the -// result is a Smi. If so, great, otherwise we try to find a heap number to -// write the answer into (either by allocating or by overwriting). -// On entry the operands are in lhs (x) and rhs (y). (Result = x op y). -// On exit the result is in v0. -void GenericBinaryOpStub::HandleNonSmiBitwiseOp(MacroAssembler* masm, - Register lhs, - Register rhs) { +// TODO(svenpanne): Use virtual functions instead of switch. +void TypeRecordingUnaryOpStub::Generate(MacroAssembler* masm) { UNIMPLEMENTED_MIPS(); } -void GenericBinaryOpStub::Generate(MacroAssembler* masm) { +void TypeRecordingUnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { UNIMPLEMENTED_MIPS(); } -void GenericBinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { +// TODO(svenpanne): Use virtual functions instead of switch. +void TypeRecordingUnaryOpStub::GenerateSmiStub(MacroAssembler* masm) { UNIMPLEMENTED_MIPS(); } -Handle GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info) { - GenericBinaryOpStub stub(key, type_info); - return stub.GetCode(); +void TypeRecordingUnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) { + UNIMPLEMENTED_MIPS(); +} + + +void TypeRecordingUnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) { + UNIMPLEMENTED_MIPS(); +} + + +void TypeRecordingUnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm, + Label* non_smi, + Label* slow) { + UNIMPLEMENTED_MIPS(); +} + + +void TypeRecordingUnaryOpStub::GenerateSmiCodeBitNot(MacroAssembler* masm, + Label* non_smi) { + UNIMPLEMENTED_MIPS(); +} + + +// TODO(svenpanne): Use virtual functions instead of switch. +void TypeRecordingUnaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) { + UNIMPLEMENTED_MIPS(); +} + + +void TypeRecordingUnaryOpStub::GenerateHeapNumberStubSub(MacroAssembler* masm) { + UNIMPLEMENTED_MIPS(); +} + + +void TypeRecordingUnaryOpStub::GenerateHeapNumberStubBitNot( + MacroAssembler* masm) { + UNIMPLEMENTED_MIPS(); +} + + +void TypeRecordingUnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm, + Label* slow) { + UNIMPLEMENTED_MIPS(); +} + + +void TypeRecordingUnaryOpStub::GenerateHeapNumberCodeBitNot( + MacroAssembler* masm, Label* slow) { + UNIMPLEMENTED_MIPS(); +} + + +// TODO(svenpanne): Use virtual functions instead of switch. +void TypeRecordingUnaryOpStub::GenerateGenericStub(MacroAssembler* masm) { + UNIMPLEMENTED_MIPS(); +} + + +void TypeRecordingUnaryOpStub::GenerateGenericStubSub(MacroAssembler* masm) { + UNIMPLEMENTED_MIPS(); +} + + +void TypeRecordingUnaryOpStub::GenerateGenericStubBitNot(MacroAssembler* masm) { + UNIMPLEMENTED_MIPS(); +} + + +void TypeRecordingUnaryOpStub::GenerateGenericCodeFallback( + MacroAssembler* masm) { + UNIMPLEMENTED_MIPS(); } @@ -352,6 +413,7 @@ void TypeRecordingBinaryOpStub::GenerateFPOperation(MacroAssembler* masm, // requested the code falls through. If number allocation is requested but a // heap number cannot be allocated the code jumps to the lable gc_required. void TypeRecordingBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, + Label* use_runtime, Label* gc_required, SmiCodeGenerateHeapNumberResults allow_heapnumber_results) { UNIMPLEMENTED_MIPS(); @@ -426,6 +488,11 @@ void StackCheckStub::Generate(MacroAssembler* masm) { } +void MathPowStub::Generate(MacroAssembler* masm) { + UNIMPLEMENTED_MIPS(); +} + + bool CEntryStub::NeedsImmovableCode() { return true; } @@ -510,8 +577,7 @@ int CompareStub::MinorKey() { } -// StringCharCodeAtGenerator - +// StringCharCodeAtGenerator. void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { UNIMPLEMENTED_MIPS(); } @@ -684,8 +750,8 @@ void SubStringStub::Generate(MacroAssembler* masm) { void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, - Register right, Register left, + Register right, Register scratch1, Register scratch2, Register scratch3, @@ -714,6 +780,11 @@ void ICCompareStub::GenerateHeapNumbers(MacroAssembler* masm) { } +void ICCompareStub::GenerateStrings(MacroAssembler* masm) { + UNIMPLEMENTED_MIPS(); +} + + void ICCompareStub::GenerateObjects(MacroAssembler* masm) { UNIMPLEMENTED_MIPS(); } diff --git a/src/mips/code-stubs-mips.h b/src/mips/code-stubs-mips.h index 675730a..d1307b5 100644 --- a/src/mips/code-stubs-mips.h +++ b/src/mips/code-stubs-mips.h @@ -1,4 +1,4 @@ -// Copyright 2010 the V8 project authors. All rights reserved. +// Copyright 2011 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -39,13 +39,22 @@ namespace internal { // TranscendentalCache runtime function. class TranscendentalCacheStub: public CodeStub { public: - explicit TranscendentalCacheStub(TranscendentalCache::Type type) - : type_(type) {} + enum ArgumentType { + TAGGED = 0 << TranscendentalCache::kTranscendentalTypeBits, + UNTAGGED = 1 << TranscendentalCache::kTranscendentalTypeBits + }; + + TranscendentalCacheStub(TranscendentalCache::Type type, + ArgumentType argument_type) + : type_(type), argument_type_(argument_type) { } void Generate(MacroAssembler* masm); private: TranscendentalCache::Type type_; + ArgumentType argument_type_; + void GenerateCallCFunction(MacroAssembler* masm, Register scratch); + Major MajorKey() { return TranscendentalCache; } - int MinorKey() { return type_; } + int MinorKey() { return type_ | argument_type_; } Runtime::FunctionId RuntimeFunction(); }; @@ -63,161 +72,92 @@ class ToBooleanStub: public CodeStub { }; -class GenericBinaryOpStub : public CodeStub { +class TypeRecordingUnaryOpStub: public CodeStub { public: - static const int kUnknownIntValue = -1; - - GenericBinaryOpStub(Token::Value op, - OverwriteMode mode, - Register lhs, - Register rhs, - int constant_rhs = kUnknownIntValue) + TypeRecordingUnaryOpStub(Token::Value op, UnaryOverwriteMode mode) : op_(op), mode_(mode), - lhs_(lhs), - rhs_(rhs), - constant_rhs_(constant_rhs), - specialized_on_rhs_(RhsIsOneWeWantToOptimizeFor(op, constant_rhs)), - runtime_operands_type_(BinaryOpIC::UNINIT_OR_SMI), - name_(NULL) { } + operand_type_(TRUnaryOpIC::UNINITIALIZED), + name_(NULL) { + } - GenericBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info) + TypeRecordingUnaryOpStub( + int key, + TRUnaryOpIC::TypeInfo operand_type) : op_(OpBits::decode(key)), mode_(ModeBits::decode(key)), - lhs_(LhsRegister(RegisterBits::decode(key))), - rhs_(RhsRegister(RegisterBits::decode(key))), - constant_rhs_(KnownBitsForMinorKey(KnownIntBits::decode(key))), - specialized_on_rhs_(RhsIsOneWeWantToOptimizeFor(op_, constant_rhs_)), - runtime_operands_type_(type_info), - name_(NULL) { } + operand_type_(operand_type), + name_(NULL) { + } private: Token::Value op_; - OverwriteMode mode_; - Register lhs_; - Register rhs_; - int constant_rhs_; - bool specialized_on_rhs_; - BinaryOpIC::TypeInfo runtime_operands_type_; - char* name_; - - static const int kMaxKnownRhs = 0x40000000; - static const int kKnownRhsKeyBits = 6; + UnaryOverwriteMode mode_; - // Minor key encoding in 16 bits. - class ModeBits: public BitField {}; - class OpBits: public BitField {}; - class TypeInfoBits: public BitField {}; - class RegisterBits: public BitField {}; - class KnownIntBits: public BitField {}; + // Operand type information determined at runtime. + TRUnaryOpIC::TypeInfo operand_type_; - Major MajorKey() { return GenericBinaryOp; } - int MinorKey() { - ASSERT((lhs_.is(a0) && rhs_.is(a1)) || - (lhs_.is(a1) && rhs_.is(a0))); - // Encode the parameters in a unique 16 bit value. - return OpBits::encode(op_) - | ModeBits::encode(mode_) - | KnownIntBits::encode(MinorKeyForKnownInt()) - | TypeInfoBits::encode(runtime_operands_type_) - | RegisterBits::encode(lhs_.is(a0)); - } + char* name_; - void Generate(MacroAssembler* masm); - void HandleNonSmiBitwiseOp(MacroAssembler* masm, - Register lhs, - Register rhs); - void HandleBinaryOpSlowCases(MacroAssembler* masm, - Label* not_smi, - Register lhs, - Register rhs, - const Builtins::JavaScript& builtin); - void GenerateTypeTransition(MacroAssembler* masm); + const char* GetName(); - static bool RhsIsOneWeWantToOptimizeFor(Token::Value op, int constant_rhs) { - if (constant_rhs == kUnknownIntValue) return false; - if (op == Token::DIV) return constant_rhs >= 2 && constant_rhs <= 3; - if (op == Token::MOD) { - if (constant_rhs <= 1) return false; - if (constant_rhs <= 10) return true; - if (constant_rhs <= kMaxKnownRhs && IsPowerOf2(constant_rhs)) return true; - return false; - } - return false; +#ifdef DEBUG + void Print() { + PrintF("TypeRecordingUnaryOpStub %d (op %s), " + "(mode %d, runtime_type_info %s)\n", + MinorKey(), + Token::String(op_), + static_cast(mode_), + TRUnaryOpIC::GetName(operand_type_)); } +#endif - int MinorKeyForKnownInt() { - if (!specialized_on_rhs_) return 0; - if (constant_rhs_ <= 10) return constant_rhs_ + 1; - ASSERT(IsPowerOf2(constant_rhs_)); - int key = 12; - int d = constant_rhs_; - while ((d & 1) == 0) { - key++; - d >>= 1; - } - ASSERT(key >= 0 && key < (1 << kKnownRhsKeyBits)); - return key; - } + class ModeBits: public BitField {}; + class OpBits: public BitField {}; + class OperandTypeInfoBits: public BitField {}; - int KnownBitsForMinorKey(int key) { - if (!key) return 0; - if (key <= 11) return key - 1; - int d = 1; - while (key != 12) { - key--; - d <<= 1; - } - return d; + Major MajorKey() { return TypeRecordingUnaryOp; } + int MinorKey() { + return ModeBits::encode(mode_) + | OpBits::encode(op_) + | OperandTypeInfoBits::encode(operand_type_); } - Register LhsRegister(bool lhs_is_a0) { - return lhs_is_a0 ? a0 : a1; - } + // Note: A lot of the helper functions below will vanish when we use virtual + // function instead of switch more often. + void Generate(MacroAssembler* masm); - Register RhsRegister(bool lhs_is_a0) { - return lhs_is_a0 ? a1 : a0; - } + void GenerateTypeTransition(MacroAssembler* masm); - bool HasSmiSmiFastPath() { - return op_ != Token::DIV; - } + void GenerateSmiStub(MacroAssembler* masm); + void GenerateSmiStubSub(MacroAssembler* masm); + void GenerateSmiStubBitNot(MacroAssembler* masm); + void GenerateSmiCodeSub(MacroAssembler* masm, Label* non_smi, Label* slow); + void GenerateSmiCodeBitNot(MacroAssembler* masm, Label* slow); - bool ShouldGenerateSmiCode() { - return ((op_ != Token::DIV && op_ != Token::MOD) || specialized_on_rhs_) && - runtime_operands_type_ != BinaryOpIC::HEAP_NUMBERS && - runtime_operands_type_ != BinaryOpIC::STRINGS; - } + void GenerateHeapNumberStub(MacroAssembler* masm); + void GenerateHeapNumberStubSub(MacroAssembler* masm); + void GenerateHeapNumberStubBitNot(MacroAssembler* masm); + void GenerateHeapNumberCodeSub(MacroAssembler* masm, Label* slow); + void GenerateHeapNumberCodeBitNot(MacroAssembler* masm, Label* slow); - bool ShouldGenerateFPCode() { - return runtime_operands_type_ != BinaryOpIC::STRINGS; - } + void GenerateGenericStub(MacroAssembler* masm); + void GenerateGenericStubSub(MacroAssembler* masm); + void GenerateGenericStubBitNot(MacroAssembler* masm); + void GenerateGenericCodeFallback(MacroAssembler* masm); - virtual int GetCodeKind() { return Code::BINARY_OP_IC; } + virtual int GetCodeKind() { return Code::TYPE_RECORDING_UNARY_OP_IC; } virtual InlineCacheState GetICState() { - return BinaryOpIC::ToState(runtime_operands_type_); + return TRUnaryOpIC::ToState(operand_type_); } - const char* GetName(); - virtual void FinishCode(Code* code) { - code->set_binary_op_type(runtime_operands_type_); - } - -#ifdef DEBUG - void Print() { - if (!specialized_on_rhs_) { - PrintF("GenericBinaryOpStub (%s)\n", Token::String(op_)); - } else { - PrintF("GenericBinaryOpStub (%s by %d)\n", - Token::String(op_), - constant_rhs_); - } + code->set_type_recording_unary_op_type(operand_type_); } -#endif }; + class TypeRecordingBinaryOpStub: public CodeStub { public: TypeRecordingBinaryOpStub(Token::Value op, OverwriteMode mode) @@ -226,7 +166,8 @@ class TypeRecordingBinaryOpStub: public CodeStub { operands_type_(TRBinaryOpIC::UNINITIALIZED), result_type_(TRBinaryOpIC::UNINITIALIZED), name_(NULL) { - UNIMPLEMENTED_MIPS(); + use_fpu_ = CpuFeatures::IsSupported(FPU); + ASSERT(OpBits::is_valid(Token::NUM_TOKENS)); } TypeRecordingBinaryOpStub( @@ -293,6 +234,7 @@ class TypeRecordingBinaryOpStub: public CodeStub { Label* not_numbers, Label* gc_required); void GenerateSmiCode(MacroAssembler* masm, + Label* use_runtime, Label* gc_required, SmiCodeGenerateHeapNumberResults heapnumber_results); void GenerateLoadArguments(MacroAssembler* masm); @@ -301,7 +243,9 @@ class TypeRecordingBinaryOpStub: public CodeStub { void GenerateSmiStub(MacroAssembler* masm); void GenerateInt32Stub(MacroAssembler* masm); void GenerateHeapNumberStub(MacroAssembler* masm); + void GenerateOddballStub(MacroAssembler* masm); void GenerateStringStub(MacroAssembler* masm); + void GenerateBothStringStub(MacroAssembler* masm); void GenerateGenericStub(MacroAssembler* masm); void GenerateAddStrings(MacroAssembler* masm); void GenerateCallRuntime(MacroAssembler* masm); @@ -334,24 +278,36 @@ class TypeRecordingBinaryOpStub: public CodeStub { // Flag that indicates how to generate code for the stub StringAddStub. enum StringAddFlags { NO_STRING_ADD_FLAGS = 0, - NO_STRING_CHECK_IN_STUB = 1 << 0 // Omit string check in stub. + // Omit left string check in stub (left is definitely a string). + NO_STRING_CHECK_LEFT_IN_STUB = 1 << 0, + // Omit right string check in stub (right is definitely a string). + NO_STRING_CHECK_RIGHT_IN_STUB = 1 << 1, + // Omit both string checks in stub. + NO_STRING_CHECK_IN_STUB = + NO_STRING_CHECK_LEFT_IN_STUB | NO_STRING_CHECK_RIGHT_IN_STUB }; class StringAddStub: public CodeStub { public: - explicit StringAddStub(StringAddFlags flags) { - string_check_ = ((flags & NO_STRING_CHECK_IN_STUB) == 0); - } + explicit StringAddStub(StringAddFlags flags) : flags_(flags) {} private: Major MajorKey() { return StringAdd; } - int MinorKey() { return string_check_ ? 0 : 1; } + int MinorKey() { return flags_; } void Generate(MacroAssembler* masm); - // Should the stub check whether arguments are strings? - bool string_check_; + void GenerateConvertArgument(MacroAssembler* masm, + int stack_offset, + Register arg, + Register scratch1, + Register scratch2, + Register scratch3, + Register scratch4, + Label* slow); + + const StringAddFlags flags_; }; @@ -372,7 +328,6 @@ class StringCompareStub: public CodeStub { StringCompareStub() { } // Compare two flat ASCII strings and returns result in v0. - // Does not use the stack. static void GenerateCompareFlatAsciiStrings(MacroAssembler* masm, Register left, Register right, @@ -381,11 +336,28 @@ class StringCompareStub: public CodeStub { Register scratch3, Register scratch4); - private: - Major MajorKey() { return StringCompare; } - int MinorKey() { return 0; } + // Compares two flat ASCII strings for equality and returns result + // in v0. + static void GenerateFlatAsciiStringEquals(MacroAssembler* masm, + Register left, + Register right, + Register scratch1, + Register scratch2, + Register scratch3); - void Generate(MacroAssembler* masm); + private: + virtual Major MajorKey() { return StringCompare; } + virtual int MinorKey() { return 0; } + virtual void Generate(MacroAssembler* masm); + + static void GenerateAsciiCharsCompareLoop(MacroAssembler* masm, + Register left, + Register right, + Register length, + Register scratch1, + Register scratch2, + Register scratch3, + Label* chars_not_equal); }; @@ -485,25 +457,202 @@ class RegExpCEntryStub: public CodeStub { }; -// Generate code the to load an element from a pixel array. The receiver is -// assumed to not be a smi and to have elements, the caller must guarantee this -// precondition. If the receiver does not have elements that are pixel arrays, -// the generated code jumps to not_pixel_array. If key is not a smi, then the -// generated code branches to key_not_smi. Callers can specify NULL for -// key_not_smi to signal that a smi check has already been performed on key so -// that the smi check is not generated . If key is not a valid index within the -// bounds of the pixel array, the generated code jumps to out_of_range. -void GenerateFastPixelArrayLoad(MacroAssembler* masm, - Register receiver, - Register key, - Register elements_map, - Register elements, +class FloatingPointHelper : public AllStatic { + public: + + enum Destination { + kFPURegisters, + kCoreRegisters + }; + + + // Loads smis from a0 and a1 (right and left in binary operations) into + // floating point registers. Depending on the destination the values ends up + // either f14 and f12 or in a2/a3 and a0/a1 respectively. If the destination + // is floating point registers FPU must be supported. If core registers are + // requested when FPU is supported f12 and f14 will be scratched. + static void LoadSmis(MacroAssembler* masm, + Destination destination, + Register scratch1, + Register scratch2); + + // Loads objects from a0 and a1 (right and left in binary operations) into + // floating point registers. Depending on the destination the values ends up + // either f14 and f12 or in a2/a3 and a0/a1 respectively. If the destination + // is floating point registers FPU must be supported. If core registers are + // requested when FPU is supported f12 and f14 will still be scratched. If + // either a0 or a1 is not a number (not smi and not heap number object) the + // not_number label is jumped to with a0 and a1 intact. + static void LoadOperands(MacroAssembler* masm, + FloatingPointHelper::Destination destination, + Register heap_number_map, + Register scratch1, + Register scratch2, + Label* not_number); + + // Convert the smi or heap number in object to an int32 using the rules + // for ToInt32 as described in ECMAScript 9.5.: the value is truncated + // and brought into the range -2^31 .. +2^31 - 1. + static void ConvertNumberToInt32(MacroAssembler* masm, + Register object, + Register dst, + Register heap_number_map, + Register scratch1, + Register scratch2, + Register scratch3, + FPURegister double_scratch, + Label* not_int32); + + // Converts the integer (untagged smi) in |int_scratch| to a double, storing + // the result either in |double_dst| or |dst2:dst1|, depending on + // |destination|. + // Warning: The value in |int_scratch| will be changed in the process! + static void ConvertIntToDouble(MacroAssembler* masm, + Register int_scratch, + Destination destination, + FPURegister double_dst, + Register dst1, + Register dst2, + Register scratch2, + FPURegister single_scratch); + + // Load the number from object into double_dst in the double format. + // Control will jump to not_int32 if the value cannot be exactly represented + // by a 32-bit integer. + // Floating point value in the 32-bit integer range that are not exact integer + // won't be loaded. + static void LoadNumberAsInt32Double(MacroAssembler* masm, + Register object, + Destination destination, + FPURegister double_dst, + Register dst1, + Register dst2, + Register heap_number_map, + Register scratch1, + Register scratch2, + FPURegister single_scratch, + Label* not_int32); + + // Loads the number from object into dst as a 32-bit integer. + // Control will jump to not_int32 if the object cannot be exactly represented + // by a 32-bit integer. + // Floating point value in the 32-bit integer range that are not exact integer + // won't be converted. + // scratch3 is not used when FPU is supported. + static void LoadNumberAsInt32(MacroAssembler* masm, + Register object, + Register dst, + Register heap_number_map, Register scratch1, Register scratch2, - Register result, - Label* not_pixel_array, - Label* key_not_smi, - Label* out_of_range); + Register scratch3, + FPURegister double_scratch, + Label* not_int32); + + // Generate non FPU code to check if a double can be exactly represented by a + // 32-bit integer. This does not check for 0 or -0, which need + // to be checked for separately. + // Control jumps to not_int32 if the value is not a 32-bit integer, and falls + // through otherwise. + // src1 and src2 will be cloberred. + // + // Expected input: + // - src1: higher (exponent) part of the double value. + // - src2: lower (mantissa) part of the double value. + // Output status: + // - dst: 32 higher bits of the mantissa. (mantissa[51:20]) + // - src2: contains 1. + // - other registers are clobbered. + static void DoubleIs32BitInteger(MacroAssembler* masm, + Register src1, + Register src2, + Register dst, + Register scratch, + Label* not_int32); + + // Generates code to call a C function to do a double operation using core + // registers. (Used when FPU is not supported.) + // This code never falls through, but returns with a heap number containing + // the result in v0. + // Register heapnumber_result must be a heap number in which the + // result of the operation will be stored. + // Requires the following layout on entry: + // a0: Left value (least significant part of mantissa). + // a1: Left value (sign, exponent, top of mantissa). + // a2: Right value (least significant part of mantissa). + // a3: Right value (sign, exponent, top of mantissa). + static void CallCCodeForDoubleOperation(MacroAssembler* masm, + Token::Value op, + Register heap_number_result, + Register scratch); + + private: + static void LoadNumber(MacroAssembler* masm, + FloatingPointHelper::Destination destination, + Register object, + FPURegister dst, + Register dst1, + Register dst2, + Register heap_number_map, + Register scratch1, + Register scratch2, + Label* not_number); +}; + + +class StringDictionaryLookupStub: public CodeStub { + public: + enum LookupMode { POSITIVE_LOOKUP, NEGATIVE_LOOKUP }; + + explicit StringDictionaryLookupStub(LookupMode mode) : mode_(mode) { } + + void Generate(MacroAssembler* masm); + + static void GenerateNegativeLookup(MacroAssembler* masm, + Label* miss, + Label* done, + Register receiver, + Register properties, + String* name, + Register scratch0) ; + + static void GeneratePositiveLookup(MacroAssembler* masm, + Label* miss, + Label* done, + Register elements, + Register name, + Register r0, + Register r1); + + private: + static const int kInlinedProbes = 4; + static const int kTotalProbes = 20; + + static const int kCapacityOffset = + StringDictionary::kHeaderSize + + StringDictionary::kCapacityIndex * kPointerSize; + + static const int kElementsStartOffset = + StringDictionary::kHeaderSize + + StringDictionary::kElementsStartIndex * kPointerSize; + + +#ifdef DEBUG + void Print() { + PrintF("StringDictionaryLookupStub\n"); + } +#endif + + Major MajorKey() { return StringDictionaryNegativeLookup; } + + int MinorKey() { + return LookupModeBits::encode(mode_); + } + + class LookupModeBits: public BitField {}; + + LookupMode mode_; +}; } } // namespace v8::internal diff --git a/src/mips/codegen-mips-inl.h b/src/mips/codegen-mips-inl.h deleted file mode 100644 index be9ae9e..0000000 --- a/src/mips/codegen-mips-inl.h +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2010 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -#ifndef V8_MIPS_CODEGEN_MIPS_INL_H_ -#define V8_MIPS_CODEGEN_MIPS_INL_H_ - -#include "virtual-frame-mips.h" - -namespace v8 { -namespace internal { - -#define __ ACCESS_MASM(masm_) - -// Platform-specific inline functions. - -void DeferredCode::Jump() { - __ b(&entry_label_); - __ nop(); -} - - -// Note: this has been hacked for submisson. Mips branches require two -// additional operands: Register src1, const Operand& src2. -void DeferredCode::Branch(Condition cond) { - __ Branch(&entry_label_, cond, zero_reg, Operand(0)); -} - - -void Reference::GetValueAndSpill() { - GetValue(); -} - - -#undef __ - -} } // namespace v8::internal - -#endif // V8_MIPS_CODEGEN_MIPS_INL_H_ - diff --git a/src/mips/codegen-mips.cc b/src/mips/codegen-mips.cc index c1149df..4400b64 100644 --- a/src/mips/codegen-mips.cc +++ b/src/mips/codegen-mips.cc @@ -1,4 +1,4 @@ -// Copyright 2010 the V8 project authors. All rights reserved. +// Copyright 2011 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -25,61 +25,18 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - #include "v8.h" #if defined(V8_TARGET_ARCH_MIPS) -#include "bootstrapper.h" -#include "code-stubs.h" -#include "codegen-inl.h" -#include "compiler.h" -#include "debug.h" -#include "ic-inl.h" -#include "jsregexp.h" -#include "jump-target-inl.h" -#include "parser.h" -#include "regexp-macro-assembler.h" -#include "regexp-stack.h" -#include "register-allocator-inl.h" -#include "runtime.h" -#include "scopes.h" -#include "stub-cache.h" -#include "virtual-frame-inl.h" -#include "virtual-frame-mips-inl.h" +#include "codegen.h" namespace v8 { namespace internal { - -#define __ ACCESS_MASM(masm_) - -// ------------------------------------------------------------------------- -// Platform-specific DeferredCode functions. - -void DeferredCode::SaveRegisters() { - // On MIPS you either have a completely spilled frame or you - // handle it yourself, but at the moment there's no automation - // of registers and deferred code. -} - - -void DeferredCode::RestoreRegisters() { -} - - // ------------------------------------------------------------------------- // Platform-specific RuntimeCallHelper functions. -void VirtualFrameRuntimeCallHelper::BeforeCall(MacroAssembler* masm) const { - frame_state_->frame()->AssertIsSpilled(); -} - - -void VirtualFrameRuntimeCallHelper::AfterCall(MacroAssembler* masm) const { -} - - void StubRuntimeCallHelper::BeforeCall(MacroAssembler* masm) const { masm->EnterInternalFrame(); } @@ -90,1124 +47,6 @@ void StubRuntimeCallHelper::AfterCall(MacroAssembler* masm) const { } -// ----------------------------------------------------------------------------- -// CodeGenState implementation. - -CodeGenState::CodeGenState(CodeGenerator* owner) - : owner_(owner), - previous_(owner->state()) { - owner->set_state(this); -} - - -ConditionCodeGenState::ConditionCodeGenState(CodeGenerator* owner, - JumpTarget* true_target, - JumpTarget* false_target) - : CodeGenState(owner), - true_target_(true_target), - false_target_(false_target) { - owner->set_state(this); -} - - -TypeInfoCodeGenState::TypeInfoCodeGenState(CodeGenerator* owner, - Slot* slot, - TypeInfo type_info) - : CodeGenState(owner), - slot_(slot) { - owner->set_state(this); - old_type_info_ = owner->set_type_info(slot, type_info); -} - - -CodeGenState::~CodeGenState() { - ASSERT(owner_->state() == this); - owner_->set_state(previous_); -} - - -TypeInfoCodeGenState::~TypeInfoCodeGenState() { - owner()->set_type_info(slot_, old_type_info_); -} - - -// ----------------------------------------------------------------------------- -// CodeGenerator implementation. - -CodeGenerator::CodeGenerator(MacroAssembler* masm) - : deferred_(8), - masm_(masm), - info_(NULL), - frame_(NULL), - allocator_(NULL), - cc_reg_(cc_always), - state_(NULL), - loop_nesting_(0), - type_info_(NULL), - function_return_(JumpTarget::BIDIRECTIONAL), - function_return_is_shadowed_(false) { -} - - -// Calling conventions: -// fp: caller's frame pointer -// sp: stack pointer -// a1: called JS function -// cp: callee's context - -void CodeGenerator::Generate(CompilationInfo* info) { - UNIMPLEMENTED_MIPS(); -} - - -int CodeGenerator::NumberOfSlot(Slot* slot) { - UNIMPLEMENTED_MIPS(); - return 0; -} - - -MemOperand CodeGenerator::SlotOperand(Slot* slot, Register tmp) { - UNIMPLEMENTED_MIPS(); - return MemOperand(zero_reg, 0); -} - - -MemOperand CodeGenerator::ContextSlotOperandCheckExtensions( - Slot* slot, - Register tmp, - Register tmp2, - JumpTarget* slow) { - UNIMPLEMENTED_MIPS(); - return MemOperand(zero_reg, 0); -} - - -void CodeGenerator::LoadCondition(Expression* x, - JumpTarget* true_target, - JumpTarget* false_target, - bool force_cc) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::Load(Expression* x) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::LoadGlobal() { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::LoadGlobalReceiver(Register scratch) { - UNIMPLEMENTED_MIPS(); -} - - -ArgumentsAllocationMode CodeGenerator::ArgumentsMode() { - UNIMPLEMENTED_MIPS(); - return EAGER_ARGUMENTS_ALLOCATION; -} - - -void CodeGenerator::StoreArgumentsObject(bool initial) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::LoadTypeofExpression(Expression* x) { - UNIMPLEMENTED_MIPS(); -} - - -Reference::Reference(CodeGenerator* cgen, - Expression* expression, - bool persist_after_get) - : cgen_(cgen), - expression_(expression), - type_(ILLEGAL), - persist_after_get_(persist_after_get) { - UNIMPLEMENTED_MIPS(); -} - - -Reference::~Reference() { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::LoadReference(Reference* ref) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::UnloadReference(Reference* ref) { - UNIMPLEMENTED_MIPS(); -} - - -// ECMA-262, section 9.2, page 30: ToBoolean(). Convert the given -// register to a boolean in the condition code register. The code -// may jump to 'false_target' in case the register converts to 'false'. -void CodeGenerator::ToBoolean(JumpTarget* true_target, - JumpTarget* false_target) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenericBinaryOperation(Token::Value op, - OverwriteMode overwrite_mode, - GenerateInlineSmi inline_smi, - int constant_rhs) { - UNIMPLEMENTED_MIPS(); -} - - -class DeferredInlineSmiOperation: public DeferredCode { - public: - DeferredInlineSmiOperation(Token::Value op, - int value, - bool reversed, - OverwriteMode overwrite_mode, - Register tos) - : op_(op), - value_(value), - reversed_(reversed), - overwrite_mode_(overwrite_mode), - tos_register_(tos) { - set_comment("[ DeferredInlinedSmiOperation"); - } - - virtual void Generate(); - // This stub makes explicit calls to SaveRegisters(), RestoreRegisters() and - // Exit(). Currently on MIPS SaveRegisters() and RestoreRegisters() are empty - // methods, it is the responsibility of the deferred code to save and restore - // registers. - virtual bool AutoSaveAndRestore() { return false; } - - void JumpToNonSmiInput(Condition cond, Register cmp1, const Operand& cmp2); - void JumpToAnswerOutOfRange(Condition cond, - Register cmp1, - const Operand& cmp2); - - private: - void GenerateNonSmiInput(); - void GenerateAnswerOutOfRange(); - void WriteNonSmiAnswer(Register answer, - Register heap_number, - Register scratch); - - Token::Value op_; - int value_; - bool reversed_; - OverwriteMode overwrite_mode_; - Register tos_register_; - Label non_smi_input_; - Label answer_out_of_range_; -}; - - -// For bit operations we try harder and handle the case where the input is not -// a Smi but a 32bits integer without calling the generic stub. -void DeferredInlineSmiOperation::JumpToNonSmiInput(Condition cond, - Register cmp1, - const Operand& cmp2) { - UNIMPLEMENTED_MIPS(); -} - - -// For bit operations the result is always 32bits so we handle the case where -// the result does not fit in a Smi without calling the generic stub. -void DeferredInlineSmiOperation::JumpToAnswerOutOfRange(Condition cond, - Register cmp1, - const Operand& cmp2) { - UNIMPLEMENTED_MIPS(); -} - - -// On entry the non-constant side of the binary operation is in tos_register_ -// and the constant smi side is nowhere. The tos_register_ is not used by the -// virtual frame. On exit the answer is in the tos_register_ and the virtual -// frame is unchanged. -void DeferredInlineSmiOperation::Generate() { - UNIMPLEMENTED_MIPS(); -} - - -// Convert and write the integer answer into heap_number. -void DeferredInlineSmiOperation::WriteNonSmiAnswer(Register answer, - Register heap_number, - Register scratch) { - UNIMPLEMENTED_MIPS(); -} - - -void DeferredInlineSmiOperation::GenerateNonSmiInput() { - UNIMPLEMENTED_MIPS(); -} - - -void DeferredInlineSmiOperation::GenerateAnswerOutOfRange() { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::SmiOperation(Token::Value op, - Handle value, - bool reversed, - OverwriteMode mode) { - UNIMPLEMENTED_MIPS(); -} - - -// On MIPS we load registers condReg1 and condReg2 with the values which should -// be compared. With the CodeGenerator::cc_reg_ condition, functions will be -// able to evaluate correctly the condition. (eg CodeGenerator::Branch) -void CodeGenerator::Comparison(Condition cc, - Expression* left, - Expression* right, - bool strict) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::CallWithArguments(ZoneList* args, - CallFunctionFlags flags, - int position) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::CallApplyLazy(Expression* applicand, - Expression* receiver, - VariableProxy* arguments, - int position) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::Branch(bool if_true, JumpTarget* target) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::CheckStack() { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitStatements(ZoneList* statements) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitBlock(Block* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::DeclareGlobals(Handle pairs) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitDeclaration(Declaration* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitIfStatement(IfStatement* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitContinueStatement(ContinueStatement* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitBreakStatement(BreakStatement* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitReturnStatement(ReturnStatement* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateReturnSequence() { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitDoWhileStatement(DoWhileStatement* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitWhileStatement(WhileStatement* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitForStatement(ForStatement* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitForInStatement(ForInStatement* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitTryCatchStatement(TryCatchStatement* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::InstantiateFunction( - Handle function_info, - bool pretenure) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitSharedFunctionInfoLiteral( - SharedFunctionInfoLiteral* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitConditional(Conditional* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::LoadFromSlotCheckForArguments(Slot* slot, - TypeofState state) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::LoadFromGlobalSlotCheckExtensions(Slot* slot, - TypeofState typeof_state, - JumpTarget* slow) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::EmitDynamicLoadFromSlotFastCase(Slot* slot, - TypeofState typeof_state, - JumpTarget* slow, - JumpTarget* done) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitSlot(Slot* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitVariableProxy(VariableProxy* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitLiteral(Literal* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::EmitSlotAssignment(Assignment* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::EmitKeyedPropertyAssignment(Assignment* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitAssignment(Assignment* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitThrow(Throw* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitProperty(Property* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitCall(Call* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitCallNew(CallNew* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateClassOf(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateValueOf(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateSetValueOf(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateIsSmi(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateLog(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateMathPow(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateMathSqrt(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -class DeferredStringCharCodeAt : public DeferredCode { - public: - DeferredStringCharCodeAt(Register object, - Register index, - Register scratch, - Register result) - : result_(result), - char_code_at_generator_(object, - index, - scratch, - result, - &need_conversion_, - &need_conversion_, - &index_out_of_range_, - STRING_INDEX_IS_NUMBER) {} - - StringCharCodeAtGenerator* fast_case_generator() { - return &char_code_at_generator_; - } - - virtual void Generate() { - UNIMPLEMENTED_MIPS(); - } - - private: - Register result_; - - Label need_conversion_; - Label index_out_of_range_; - - StringCharCodeAtGenerator char_code_at_generator_; -}; - - -void CodeGenerator::GenerateStringCharCodeAt(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -class DeferredStringCharFromCode : public DeferredCode { - public: - DeferredStringCharFromCode(Register code, - Register result) - : char_from_code_generator_(code, result) {} - - StringCharFromCodeGenerator* fast_case_generator() { - return &char_from_code_generator_; - } - - virtual void Generate() { - VirtualFrameRuntimeCallHelper call_helper(frame_state()); - char_from_code_generator_.GenerateSlow(masm(), call_helper); - } - - private: - StringCharFromCodeGenerator char_from_code_generator_; -}; - - -void CodeGenerator::GenerateStringCharFromCode(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -class DeferredStringCharAt : public DeferredCode { - public: - DeferredStringCharAt(Register object, - Register index, - Register scratch1, - Register scratch2, - Register result) - : result_(result), - char_at_generator_(object, - index, - scratch1, - scratch2, - result, - &need_conversion_, - &need_conversion_, - &index_out_of_range_, - STRING_INDEX_IS_NUMBER) {} - - StringCharAtGenerator* fast_case_generator() { - return &char_at_generator_; - } - - virtual void Generate() { - UNIMPLEMENTED_MIPS(); -} - - private: - Register result_; - - Label need_conversion_; - Label index_out_of_range_; - - StringCharAtGenerator char_at_generator_; -}; - - -void CodeGenerator::GenerateStringCharAt(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateIsArray(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateIsRegExp(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateIsObject(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateIsSpecObject(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -class DeferredIsStringWrapperSafeForDefaultValueOf : public DeferredCode { - public: - DeferredIsStringWrapperSafeForDefaultValueOf(Register object, - Register map_result, - Register scratch1, - Register scratch2) - : object_(object), - map_result_(map_result), - scratch1_(scratch1), - scratch2_(scratch2) { } - - virtual void Generate() { - UNIMPLEMENTED_MIPS(); - } - - private: - Register object_; - Register map_result_; - Register scratch1_; - Register scratch2_; -}; - - -void CodeGenerator::GenerateIsStringWrapperSafeForDefaultValueOf( - ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateIsFunction(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateIsUndetectableObject(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateIsConstructCall(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateArgumentsLength(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateArguments(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateRandomHeapNumber( - ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateStringAdd(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateSubString(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateStringCompare(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateRegExpExec(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateRegExpConstructResult(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -class DeferredSearchCache: public DeferredCode { - public: - DeferredSearchCache(Register dst, Register cache, Register key) - : dst_(dst), cache_(cache), key_(key) { - set_comment("[ DeferredSearchCache"); - } - - virtual void Generate(); - - private: - Register dst_, cache_, key_; -}; - - -void DeferredSearchCache::Generate() { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateGetFromCache(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateNumberToString(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -class DeferredSwapElements: public DeferredCode { - public: - DeferredSwapElements(Register object, Register index1, Register index2) - : object_(object), index1_(index1), index2_(index2) { - set_comment("[ DeferredSwapElements"); - } - - virtual void Generate(); - - private: - Register object_, index1_, index2_; -}; - - -void DeferredSwapElements::Generate() { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateSwapElements(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateCallFunction(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateMathSin(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateMathCos(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateMathLog(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateObjectEquals(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateIsRegExpEquivalent(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateHasCachedArrayIndex(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateGetCachedArrayIndex(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateFastAsciiArrayJoin(ZoneList* args) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitCallRuntime(CallRuntime* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { - UNIMPLEMENTED_MIPS(); -} - - -class DeferredCountOperation: public DeferredCode { - public: - DeferredCountOperation(Register value, - bool is_increment, - bool is_postfix, - int target_size) - : value_(value), - is_increment_(is_increment), - is_postfix_(is_postfix), - target_size_(target_size) {} - - virtual void Generate() { - UNIMPLEMENTED_MIPS(); - } - - private: - Register value_; - bool is_increment_; - bool is_postfix_; - int target_size_; -}; - - -void CodeGenerator::VisitCountOperation(CountOperation* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::GenerateLogicalBooleanOperation(BinaryOperation* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitThisFunction(ThisFunction* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitCompareOperation(CompareOperation* node) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::VisitCompareToNull(CompareToNull* node) { - UNIMPLEMENTED_MIPS(); -} - - -class DeferredReferenceGetNamedValue: public DeferredCode { - public: - explicit DeferredReferenceGetNamedValue(Register receiver, - Handle name, - bool is_contextual) - : receiver_(receiver), - name_(name), - is_contextual_(is_contextual), - is_dont_delete_(false) { - set_comment(is_contextual - ? "[ DeferredReferenceGetNamedValue (contextual)" - : "[ DeferredReferenceGetNamedValue"); - } - - virtual void Generate(); - - void set_is_dont_delete(bool value) { - ASSERT(is_contextual_); - is_dont_delete_ = value; - } - - private: - Register receiver_; - Handle name_; - bool is_contextual_; - bool is_dont_delete_; -}; - - - -void DeferredReferenceGetNamedValue::Generate() { - UNIMPLEMENTED_MIPS(); -} - - -class DeferredReferenceGetKeyedValue: public DeferredCode { - public: - DeferredReferenceGetKeyedValue(Register key, Register receiver) - : key_(key), receiver_(receiver) { - set_comment("[ DeferredReferenceGetKeyedValue"); - } - - virtual void Generate(); - - private: - Register key_; - Register receiver_; -}; - - -void DeferredReferenceGetKeyedValue::Generate() { - UNIMPLEMENTED_MIPS(); -} - - -class DeferredReferenceSetKeyedValue: public DeferredCode { - public: - DeferredReferenceSetKeyedValue(Register value, - Register key, - Register receiver) - : value_(value), key_(key), receiver_(receiver) { - set_comment("[ DeferredReferenceSetKeyedValue"); - } - - virtual void Generate(); - - private: - Register value_; - Register key_; - Register receiver_; -}; - - -void DeferredReferenceSetKeyedValue::Generate() { - UNIMPLEMENTED_MIPS(); -} - - -class DeferredReferenceSetNamedValue: public DeferredCode { - public: - DeferredReferenceSetNamedValue(Register value, - Register receiver, - Handle name) - : value_(value), receiver_(receiver), name_(name) { - set_comment("[ DeferredReferenceSetNamedValue"); - } - - virtual void Generate(); - - private: - Register value_; - Register receiver_; - Handle name_; -}; - - -void DeferredReferenceSetNamedValue::Generate() { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::EmitNamedLoad(Handle name, bool is_contextual) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::EmitNamedStore(Handle name, bool is_contextual) { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::EmitKeyedLoad() { - UNIMPLEMENTED_MIPS(); -} - - -void CodeGenerator::EmitKeyedStore(StaticType* key_type, - WriteBarrierCharacter wb_info) { - UNIMPLEMENTED_MIPS(); -} - - -#ifdef DEBUG -bool CodeGenerator::HasValidEntryRegisters() { - UNIMPLEMENTED_MIPS(); - return false; -} -#endif - - -#undef __ -#define __ ACCESS_MASM(masm) - -// ----------------------------------------------------------------------------- -// Reference support. - - -Handle Reference::GetName() { - UNIMPLEMENTED_MIPS(); - return Handle(); -} - - -void Reference::DupIfPersist() { - UNIMPLEMENTED_MIPS(); -} - - -void Reference::GetValue() { - UNIMPLEMENTED_MIPS(); -} - - -void Reference::SetValue(InitState init_state, WriteBarrierCharacter wb_info) { - UNIMPLEMENTED_MIPS(); -} - - -const char* GenericBinaryOpStub::GetName() { - UNIMPLEMENTED_MIPS(); - return name_; -} - - -#undef __ - } } // namespace v8::internal #endif // V8_TARGET_ARCH_MIPS diff --git a/src/mips/codegen-mips.h b/src/mips/codegen-mips.h index 0a2cd45..f847b51 100644 --- a/src/mips/codegen-mips.h +++ b/src/mips/codegen-mips.h @@ -1,4 +1,4 @@ -// Copyright 2010 the V8 project authors. All rights reserved. +// Copyright 2011 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -51,190 +51,14 @@ static const bool IsMipsSoftFloatABI = true; // Forward declarations class CompilationInfo; -class DeferredCode; -class JumpTarget; -class RegisterAllocator; -class RegisterFile; -enum InitState { CONST_INIT, NOT_CONST_INIT }; enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF }; -enum GenerateInlineSmi { DONT_GENERATE_INLINE_SMI, GENERATE_INLINE_SMI }; -enum WriteBarrierCharacter { UNLIKELY_SMI, LIKELY_SMI, NEVER_NEWSPACE }; - - -// ----------------------------------------------------------------------------- -// Reference support - -// A reference is a C++ stack-allocated object that keeps an ECMA -// reference on the execution stack while in scope. For variables -// the reference is empty, indicating that it isn't necessary to -// store state on the stack for keeping track of references to those. -// For properties, we keep either one (named) or two (indexed) values -// on the execution stack to represent the reference. -class Reference BASE_EMBEDDED { - public: - // The values of the types is important, see size(). - enum Type { UNLOADED = -2, ILLEGAL = -1, SLOT = 0, NAMED = 1, KEYED = 2 }; - Reference(CodeGenerator* cgen, - Expression* expression, - bool persist_after_get = false); - ~Reference(); - - Expression* expression() const { return expression_; } - Type type() const { return type_; } - void set_type(Type value) { - ASSERT_EQ(ILLEGAL, type_); - type_ = value; - } - - void set_unloaded() { - ASSERT_NE(ILLEGAL, type_); - ASSERT_NE(UNLOADED, type_); - type_ = UNLOADED; - } - // The size the reference takes up on the stack. - int size() const { - return (type_ < SLOT) ? 0 : type_; - } - - bool is_illegal() const { return type_ == ILLEGAL; } - bool is_slot() const { return type_ == SLOT; } - bool is_property() const { return type_ == NAMED || type_ == KEYED; } - bool is_unloaded() const { return type_ == UNLOADED; } - - // Return the name. Only valid for named property references. - Handle GetName(); - - // Generate code to push the value of the reference on top of the - // expression stack. The reference is expected to be already on top of - // the expression stack, and it is consumed by the call unless the - // reference is for a compound assignment. - // If the reference is not consumed, it is left in place under its value. - void GetValue(); - - // Generate code to pop a reference, push the value of the reference, - // and then spill the stack frame. - inline void GetValueAndSpill(); - - // Generate code to store the value on top of the expression stack in the - // reference. The reference is expected to be immediately below the value - // on the expression stack. The value is stored in the location specified - // by the reference, and is left on top of the stack, after the reference - // is popped from beneath it (unloaded). - void SetValue(InitState init_state, WriteBarrierCharacter wb); - - // This is in preparation for something that uses the reference on the stack. - // If we need this reference afterwards get then dup it now. Otherwise mark - // it as used. - inline void DupIfPersist(); - - private: - CodeGenerator* cgen_; - Expression* expression_; - Type type_; - // Keep the reference on the stack after get, so it can be used by set later. - bool persist_after_get_; -}; - - -// ----------------------------------------------------------------------------- -// Code generation state - -// The state is passed down the AST by the code generator (and back up, in -// the form of the state of the label pair). It is threaded through the -// call stack. Constructing a state implicitly pushes it on the owning code -// generator's stack of states, and destroying one implicitly pops it. - -class CodeGenState BASE_EMBEDDED { - public: - // Create an initial code generator state. Destroying the initial state - // leaves the code generator with a NULL state. - explicit CodeGenState(CodeGenerator* owner); - - - - // Destroy a code generator state and restore the owning code generator's - // previous state. - virtual ~CodeGenState(); - - virtual JumpTarget* true_target() const { return NULL; } - virtual JumpTarget* false_target() const { return NULL; } - - protected: - inline CodeGenerator* owner() { return owner_; } - inline CodeGenState* previous() const { return previous_; } - - private: - // The owning code generator. - CodeGenerator* owner_; - - - - // The previous state of the owning code generator, restored when - // this state is destroyed. - CodeGenState* previous_; -}; - - -class ConditionCodeGenState : public CodeGenState { - public: - // Create a code generator state based on a code generator's current - // state. The new state has its own pair of branch labels. - ConditionCodeGenState(CodeGenerator* owner, - JumpTarget* true_target, - JumpTarget* false_target); - - virtual JumpTarget* true_target() const { return true_target_; } - virtual JumpTarget* false_target() const { return false_target_; } - - private: - JumpTarget* true_target_; - JumpTarget* false_target_; -}; - - -class TypeInfoCodeGenState : public CodeGenState { - public: - TypeInfoCodeGenState(CodeGenerator* owner, - Slot* slot_number, - TypeInfo info); - virtual ~TypeInfoCodeGenState(); - - virtual JumpTarget* true_target() const { return previous()->true_target(); } - virtual JumpTarget* false_target() const { - return previous()->false_target(); - } - - private: - Slot* slot_; - TypeInfo old_type_info_; -}; - // ------------------------------------------------------------------------- -// Arguments allocation mode - -enum ArgumentsAllocationMode { - NO_ARGUMENTS_ALLOCATION, - EAGER_ARGUMENTS_ALLOCATION, - LAZY_ARGUMENTS_ALLOCATION -}; - - -// ----------------------------------------------------------------------------- // CodeGenerator class CodeGenerator: public AstVisitor { public: - // Compilation mode. Either the compiler is used as the primary - // compiler and needs to setup everything or the compiler is used as - // the secondary compiler for split compilation and has to handle - // bailouts. - enum Mode { - PRIMARY, - SECONDARY - }; - static bool MakeCode(CompilationInfo* info); // Printing of AST, etc. as requested by flags. @@ -261,50 +85,14 @@ class CodeGenerator: public AstVisitor { int pos, bool right_here = false); - // Accessors - MacroAssembler* masm() { return masm_; } - VirtualFrame* frame() const { return frame_; } - inline Handle