| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 18 matching lines...) Expand all Loading... |
| 29 | 29 |
| 30 #include "mips/lithium-codegen-mips.h" | 30 #include "mips/lithium-codegen-mips.h" |
| 31 #include "mips/lithium-gap-resolver-mips.h" | 31 #include "mips/lithium-gap-resolver-mips.h" |
| 32 #include "code-stubs.h" | 32 #include "code-stubs.h" |
| 33 #include "stub-cache.h" | 33 #include "stub-cache.h" |
| 34 | 34 |
| 35 namespace v8 { | 35 namespace v8 { |
| 36 namespace internal { | 36 namespace internal { |
| 37 | 37 |
| 38 | 38 |
| 39 class SafepointGenerator : public CallWrapper { | 39 class SafepointGenerator V8_FINAL : public CallWrapper { |
| 40 public: | 40 public: |
| 41 SafepointGenerator(LCodeGen* codegen, | 41 SafepointGenerator(LCodeGen* codegen, |
| 42 LPointerMap* pointers, | 42 LPointerMap* pointers, |
| 43 Safepoint::DeoptMode mode) | 43 Safepoint::DeoptMode mode) |
| 44 : codegen_(codegen), | 44 : codegen_(codegen), |
| 45 pointers_(pointers), | 45 pointers_(pointers), |
| 46 deopt_mode_(mode) { } | 46 deopt_mode_(mode) { } |
| 47 virtual ~SafepointGenerator() { } | 47 virtual ~SafepointGenerator() {} |
| 48 | 48 |
| 49 virtual void BeforeCall(int call_size) const { } | 49 virtual void BeforeCall(int call_size) const V8_OVERRIDE {} |
| 50 | 50 |
| 51 virtual void AfterCall() const { | 51 virtual void AfterCall() const V8_OVERRIDE { |
| 52 codegen_->RecordSafepoint(pointers_, deopt_mode_); | 52 codegen_->RecordSafepoint(pointers_, deopt_mode_); |
| 53 } | 53 } |
| 54 | 54 |
| 55 private: | 55 private: |
| 56 LCodeGen* codegen_; | 56 LCodeGen* codegen_; |
| 57 LPointerMap* pointers_; | 57 LPointerMap* pointers_; |
| 58 Safepoint::DeoptMode deopt_mode_; | 58 Safepoint::DeoptMode deopt_mode_; |
| 59 }; | 59 }; |
| 60 | 60 |
| 61 | 61 |
| (...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 316 } | 316 } |
| 317 } | 317 } |
| 318 // Deferred code is the last part of the instruction sequence. Mark | 318 // Deferred code is the last part of the instruction sequence. Mark |
| 319 // the generated code as done unless we bailed out. | 319 // the generated code as done unless we bailed out. |
| 320 if (!is_aborted()) status_ = DONE; | 320 if (!is_aborted()) status_ = DONE; |
| 321 return !is_aborted(); | 321 return !is_aborted(); |
| 322 } | 322 } |
| 323 | 323 |
| 324 | 324 |
| 325 bool LCodeGen::GenerateDeoptJumpTable() { | 325 bool LCodeGen::GenerateDeoptJumpTable() { |
| 326 // Check that the jump table is accessible from everywhere in the function | |
| 327 // code, i.e. that offsets to the table can be encoded in the 16bit signed | |
| 328 // immediate of a branch instruction. | |
| 329 // To simplify we consider the code size from the first instruction to the | |
| 330 // end of the jump table. | |
| 331 if (!is_int16((masm()->pc_offset() / Assembler::kInstrSize) + | |
| 332 deopt_jump_table_.length() * 12)) { | |
| 333 Abort(kGeneratedCodeIsTooLarge); | |
| 334 } | |
| 335 | |
| 336 if (deopt_jump_table_.length() > 0) { | 326 if (deopt_jump_table_.length() > 0) { |
| 337 Comment(";;; -------------------- Jump table --------------------"); | 327 Comment(";;; -------------------- Jump table --------------------"); |
| 338 } | 328 } |
| 339 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); | 329 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); |
| 340 Label table_start; | 330 Label table_start; |
| 341 __ bind(&table_start); | 331 __ bind(&table_start); |
| 342 Label needs_frame; | 332 Label needs_frame; |
| 343 for (int i = 0; i < deopt_jump_table_.length(); i++) { | 333 for (int i = 0; i < deopt_jump_table_.length(); i++) { |
| 344 __ bind(&deopt_jump_table_[i].label); | 334 __ bind(&deopt_jump_table_[i].label); |
| 345 Address entry = deopt_jump_table_[i].address; | 335 Address entry = deopt_jump_table_[i].address; |
| (...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 755 int deoptimization_index = deoptimizations_.length(); | 745 int deoptimization_index = deoptimizations_.length(); |
| 756 int pc_offset = masm()->pc_offset(); | 746 int pc_offset = masm()->pc_offset(); |
| 757 environment->Register(deoptimization_index, | 747 environment->Register(deoptimization_index, |
| 758 translation.index(), | 748 translation.index(), |
| 759 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); | 749 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); |
| 760 deoptimizations_.Add(environment, zone()); | 750 deoptimizations_.Add(environment, zone()); |
| 761 } | 751 } |
| 762 } | 752 } |
| 763 | 753 |
| 764 | 754 |
| 765 void LCodeGen::DeoptimizeIf(Condition cc, | 755 void LCodeGen::DeoptimizeIf(Condition condition, |
| 766 LEnvironment* environment, | 756 LEnvironment* environment, |
| 767 Deoptimizer::BailoutType bailout_type, | 757 Deoptimizer::BailoutType bailout_type, |
| 768 Register src1, | 758 Register src1, |
| 769 const Operand& src2) { | 759 const Operand& src2) { |
| 770 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); | 760 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); |
| 771 ASSERT(environment->HasBeenRegistered()); | 761 ASSERT(environment->HasBeenRegistered()); |
| 772 int id = environment->deoptimization_index(); | 762 int id = environment->deoptimization_index(); |
| 773 ASSERT(info()->IsOptimizing() || info()->IsStub()); | 763 ASSERT(info()->IsOptimizing() || info()->IsStub()); |
| 774 Address entry = | 764 Address entry = |
| 775 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); | 765 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); |
| 776 if (entry == NULL) { | 766 if (entry == NULL) { |
| 777 Abort(kBailoutWasNotPrepared); | 767 Abort(kBailoutWasNotPrepared); |
| 778 return; | 768 return; |
| 779 } | 769 } |
| 780 | 770 |
| 781 ASSERT(FLAG_deopt_every_n_times < 2); // Other values not supported on MIPS. | 771 ASSERT(FLAG_deopt_every_n_times < 2); // Other values not supported on MIPS. |
| 782 if (FLAG_deopt_every_n_times == 1 && | 772 if (FLAG_deopt_every_n_times == 1 && |
| 783 !info()->IsStub() && | 773 !info()->IsStub() && |
| 784 info()->opt_count() == id) { | 774 info()->opt_count() == id) { |
| 785 ASSERT(frame_is_built_); | 775 ASSERT(frame_is_built_); |
| 786 __ Call(entry, RelocInfo::RUNTIME_ENTRY); | 776 __ Call(entry, RelocInfo::RUNTIME_ENTRY); |
| 787 return; | 777 return; |
| 788 } | 778 } |
| 789 | 779 |
| 790 if (info()->ShouldTrapOnDeopt()) { | 780 if (info()->ShouldTrapOnDeopt()) { |
| 791 Label skip; | 781 Label skip; |
| 792 if (cc != al) { | 782 if (condition != al) { |
| 793 __ Branch(&skip, NegateCondition(cc), src1, src2); | 783 __ Branch(&skip, NegateCondition(condition), src1, src2); |
| 794 } | 784 } |
| 795 __ stop("trap_on_deopt"); | 785 __ stop("trap_on_deopt"); |
| 796 __ bind(&skip); | 786 __ bind(&skip); |
| 797 } | 787 } |
| 798 | 788 |
| 799 ASSERT(info()->IsStub() || frame_is_built_); | 789 ASSERT(info()->IsStub() || frame_is_built_); |
| 800 if (cc == al && frame_is_built_) { | 790 if (condition == al && frame_is_built_) { |
| 801 __ Call(entry, RelocInfo::RUNTIME_ENTRY, cc, src1, src2); | 791 __ Call(entry, RelocInfo::RUNTIME_ENTRY, condition, src1, src2); |
| 802 } else { | 792 } else { |
| 803 // We often have several deopts to the same entry, reuse the last | 793 // We often have several deopts to the same entry, reuse the last |
| 804 // jump entry if this is the case. | 794 // jump entry if this is the case. |
| 805 if (deopt_jump_table_.is_empty() || | 795 if (deopt_jump_table_.is_empty() || |
| 806 (deopt_jump_table_.last().address != entry) || | 796 (deopt_jump_table_.last().address != entry) || |
| 807 (deopt_jump_table_.last().bailout_type != bailout_type) || | 797 (deopt_jump_table_.last().bailout_type != bailout_type) || |
| 808 (deopt_jump_table_.last().needs_frame != !frame_is_built_)) { | 798 (deopt_jump_table_.last().needs_frame != !frame_is_built_)) { |
| 809 Deoptimizer::JumpTableEntry table_entry(entry, | 799 Deoptimizer::JumpTableEntry table_entry(entry, |
| 810 bailout_type, | 800 bailout_type, |
| 811 !frame_is_built_); | 801 !frame_is_built_); |
| 812 deopt_jump_table_.Add(table_entry, zone()); | 802 deopt_jump_table_.Add(table_entry, zone()); |
| 813 } | 803 } |
| 814 __ Branch(&deopt_jump_table_.last().label, cc, src1, src2); | 804 __ Branch(&deopt_jump_table_.last().label, condition, src1, src2); |
| 815 } | 805 } |
| 816 } | 806 } |
| 817 | 807 |
| 818 | 808 |
| 819 void LCodeGen::DeoptimizeIf(Condition cc, | 809 void LCodeGen::DeoptimizeIf(Condition condition, |
| 820 LEnvironment* environment, | 810 LEnvironment* environment, |
| 821 Register src1, | 811 Register src1, |
| 822 const Operand& src2) { | 812 const Operand& src2) { |
| 823 Deoptimizer::BailoutType bailout_type = info()->IsStub() | 813 Deoptimizer::BailoutType bailout_type = info()->IsStub() |
| 824 ? Deoptimizer::LAZY | 814 ? Deoptimizer::LAZY |
| 825 : Deoptimizer::EAGER; | 815 : Deoptimizer::EAGER; |
| 826 DeoptimizeIf(cc, environment, bailout_type, src1, src2); | 816 DeoptimizeIf(condition, environment, bailout_type, src1, src2); |
| 827 } | 817 } |
| 828 | 818 |
| 829 | 819 |
| 830 void LCodeGen::RegisterDependentCodeForEmbeddedMaps(Handle<Code> code) { | 820 void LCodeGen::RegisterDependentCodeForEmbeddedMaps(Handle<Code> code) { |
| 831 ZoneList<Handle<Map> > maps(1, zone()); | 821 ZoneList<Handle<Map> > maps(1, zone()); |
| 832 int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); | 822 int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); |
| 833 for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) { | 823 for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) { |
| 834 RelocInfo::Mode mode = it.rinfo()->rmode(); | 824 RelocInfo::Mode mode = it.rinfo()->rmode(); |
| 835 if (mode == RelocInfo::EMBEDDED_OBJECT && | 825 if (mode == RelocInfo::EMBEDDED_OBJECT && |
| 836 it.rinfo()->target_object()->IsMap()) { | 826 it.rinfo()->target_object()->IsMap()) { |
| (...skipping 1149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1986 | 1976 |
| 1987 int LCodeGen::GetNextEmittedBlock() const { | 1977 int LCodeGen::GetNextEmittedBlock() const { |
| 1988 for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) { | 1978 for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) { |
| 1989 if (!chunk_->GetLabel(i)->HasReplacement()) return i; | 1979 if (!chunk_->GetLabel(i)->HasReplacement()) return i; |
| 1990 } | 1980 } |
| 1991 return -1; | 1981 return -1; |
| 1992 } | 1982 } |
| 1993 | 1983 |
| 1994 template<class InstrType> | 1984 template<class InstrType> |
| 1995 void LCodeGen::EmitBranch(InstrType instr, | 1985 void LCodeGen::EmitBranch(InstrType instr, |
| 1996 Condition cc, Register src1, const Operand& src2) { | 1986 Condition condition, |
| 1987 Register src1, |
| 1988 const Operand& src2) { |
| 1997 int left_block = instr->TrueDestination(chunk_); | 1989 int left_block = instr->TrueDestination(chunk_); |
| 1998 int right_block = instr->FalseDestination(chunk_); | 1990 int right_block = instr->FalseDestination(chunk_); |
| 1999 | 1991 |
| 2000 int next_block = GetNextEmittedBlock(); | 1992 int next_block = GetNextEmittedBlock(); |
| 2001 if (right_block == left_block || cc == al) { | 1993 if (right_block == left_block || condition == al) { |
| 2002 EmitGoto(left_block); | 1994 EmitGoto(left_block); |
| 2003 } else if (left_block == next_block) { | 1995 } else if (left_block == next_block) { |
| 2004 __ Branch(chunk_->GetAssemblyLabel(right_block), | 1996 __ Branch(chunk_->GetAssemblyLabel(right_block), |
| 2005 NegateCondition(cc), src1, src2); | 1997 NegateCondition(condition), src1, src2); |
| 2006 } else if (right_block == next_block) { | 1998 } else if (right_block == next_block) { |
| 2007 __ Branch(chunk_->GetAssemblyLabel(left_block), cc, src1, src2); | 1999 __ Branch(chunk_->GetAssemblyLabel(left_block), condition, src1, src2); |
| 2008 } else { | 2000 } else { |
| 2009 __ Branch(chunk_->GetAssemblyLabel(left_block), cc, src1, src2); | 2001 __ Branch(chunk_->GetAssemblyLabel(left_block), condition, src1, src2); |
| 2010 __ Branch(chunk_->GetAssemblyLabel(right_block)); | 2002 __ Branch(chunk_->GetAssemblyLabel(right_block)); |
| 2011 } | 2003 } |
| 2012 } | 2004 } |
| 2013 | 2005 |
| 2014 | 2006 |
| 2015 template<class InstrType> | 2007 template<class InstrType> |
| 2016 void LCodeGen::EmitBranchF(InstrType instr, | 2008 void LCodeGen::EmitBranchF(InstrType instr, |
| 2017 Condition cc, FPURegister src1, FPURegister src2) { | 2009 Condition condition, |
| 2010 FPURegister src1, |
| 2011 FPURegister src2) { |
| 2018 int right_block = instr->FalseDestination(chunk_); | 2012 int right_block = instr->FalseDestination(chunk_); |
| 2019 int left_block = instr->TrueDestination(chunk_); | 2013 int left_block = instr->TrueDestination(chunk_); |
| 2020 | 2014 |
| 2021 int next_block = GetNextEmittedBlock(); | 2015 int next_block = GetNextEmittedBlock(); |
| 2022 if (right_block == left_block) { | 2016 if (right_block == left_block) { |
| 2023 EmitGoto(left_block); | 2017 EmitGoto(left_block); |
| 2024 } else if (left_block == next_block) { | 2018 } else if (left_block == next_block) { |
| 2025 __ BranchF(chunk_->GetAssemblyLabel(right_block), NULL, | 2019 __ BranchF(chunk_->GetAssemblyLabel(right_block), NULL, |
| 2026 NegateCondition(cc), src1, src2); | 2020 NegateCondition(condition), src1, src2); |
| 2027 } else if (right_block == next_block) { | 2021 } else if (right_block == next_block) { |
| 2028 __ BranchF(chunk_->GetAssemblyLabel(left_block), NULL, cc, src1, src2); | 2022 __ BranchF(chunk_->GetAssemblyLabel(left_block), NULL, |
| 2023 condition, src1, src2); |
| 2029 } else { | 2024 } else { |
| 2030 __ BranchF(chunk_->GetAssemblyLabel(left_block), NULL, cc, src1, src2); | 2025 __ BranchF(chunk_->GetAssemblyLabel(left_block), NULL, |
| 2026 condition, src1, src2); |
| 2031 __ Branch(chunk_->GetAssemblyLabel(right_block)); | 2027 __ Branch(chunk_->GetAssemblyLabel(right_block)); |
| 2032 } | 2028 } |
| 2033 } | 2029 } |
| 2034 | 2030 |
| 2035 | 2031 |
| 2032 template<class InstrType> |
| 2033 void LCodeGen::EmitFalseBranchF(InstrType instr, |
| 2034 Condition condition, |
| 2035 FPURegister src1, |
| 2036 FPURegister src2) { |
| 2037 int false_block = instr->FalseDestination(chunk_); |
| 2038 __ BranchF(chunk_->GetAssemblyLabel(false_block), NULL, |
| 2039 condition, src1, src2); |
| 2040 } |
| 2041 |
| 2042 |
| 2036 void LCodeGen::DoDebugBreak(LDebugBreak* instr) { | 2043 void LCodeGen::DoDebugBreak(LDebugBreak* instr) { |
| 2037 __ stop("LDebugBreak"); | 2044 __ stop("LDebugBreak"); |
| 2038 } | 2045 } |
| 2039 | 2046 |
| 2040 | 2047 |
| 2041 void LCodeGen::DoIsNumberAndBranch(LIsNumberAndBranch* instr) { | 2048 void LCodeGen::DoIsNumberAndBranch(LIsNumberAndBranch* instr) { |
| 2042 Representation r = instr->hydrogen()->value()->representation(); | 2049 Representation r = instr->hydrogen()->value()->representation(); |
| 2043 if (r.IsSmiOrInteger32() || r.IsDouble()) { | 2050 if (r.IsSmiOrInteger32() || r.IsDouble()) { |
| 2044 EmitBranch(instr, al, zero_reg, Operand(zero_reg)); | 2051 EmitBranch(instr, al, zero_reg, Operand(zero_reg)); |
| 2045 } else { | 2052 } else { |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2286 | 2293 |
| 2287 | 2294 |
| 2288 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { | 2295 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { |
| 2289 Register left = ToRegister(instr->left()); | 2296 Register left = ToRegister(instr->left()); |
| 2290 Register right = ToRegister(instr->right()); | 2297 Register right = ToRegister(instr->right()); |
| 2291 | 2298 |
| 2292 EmitBranch(instr, eq, left, Operand(right)); | 2299 EmitBranch(instr, eq, left, Operand(right)); |
| 2293 } | 2300 } |
| 2294 | 2301 |
| 2295 | 2302 |
| 2303 void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) { |
| 2304 if (instr->hydrogen()->representation().IsTagged()) { |
| 2305 Register input_reg = ToRegister(instr->object()); |
| 2306 __ li(at, Operand(factory()->the_hole_value())); |
| 2307 EmitBranch(instr, eq, input_reg, Operand(at)); |
| 2308 return; |
| 2309 } |
| 2310 |
| 2311 DoubleRegister input_reg = ToDoubleRegister(instr->object()); |
| 2312 EmitFalseBranchF(instr, eq, input_reg, input_reg); |
| 2313 |
| 2314 Register scratch = scratch0(); |
| 2315 __ FmoveHigh(scratch, input_reg); |
| 2316 EmitBranch(instr, eq, scratch, Operand(kHoleNanUpper32)); |
| 2317 } |
| 2318 |
| 2319 |
| 2296 Condition LCodeGen::EmitIsObject(Register input, | 2320 Condition LCodeGen::EmitIsObject(Register input, |
| 2297 Register temp1, | 2321 Register temp1, |
| 2298 Register temp2, | 2322 Register temp2, |
| 2299 Label* is_not_object, | 2323 Label* is_not_object, |
| 2300 Label* is_object) { | 2324 Label* is_object) { |
| 2301 __ JumpIfSmi(input, is_not_object); | 2325 __ JumpIfSmi(input, is_not_object); |
| 2302 | 2326 |
| 2303 __ LoadRoot(temp2, Heap::kNullValueRootIndex); | 2327 __ LoadRoot(temp2, Heap::kNullValueRootIndex); |
| 2304 __ Branch(is_object, eq, input, Operand(temp2)); | 2328 __ Branch(is_object, eq, input, Operand(temp2)); |
| 2305 | 2329 |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2574 __ Branch(&true_label, eq, result, Operand(zero_reg)); | 2598 __ Branch(&true_label, eq, result, Operand(zero_reg)); |
| 2575 __ li(result, Operand(factory()->false_value())); | 2599 __ li(result, Operand(factory()->false_value())); |
| 2576 __ Branch(&done); | 2600 __ Branch(&done); |
| 2577 __ bind(&true_label); | 2601 __ bind(&true_label); |
| 2578 __ li(result, Operand(factory()->true_value())); | 2602 __ li(result, Operand(factory()->true_value())); |
| 2579 __ bind(&done); | 2603 __ bind(&done); |
| 2580 } | 2604 } |
| 2581 | 2605 |
| 2582 | 2606 |
| 2583 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { | 2607 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { |
| 2584 class DeferredInstanceOfKnownGlobal: public LDeferredCode { | 2608 class DeferredInstanceOfKnownGlobal V8_FINAL : public LDeferredCode { |
| 2585 public: | 2609 public: |
| 2586 DeferredInstanceOfKnownGlobal(LCodeGen* codegen, | 2610 DeferredInstanceOfKnownGlobal(LCodeGen* codegen, |
| 2587 LInstanceOfKnownGlobal* instr) | 2611 LInstanceOfKnownGlobal* instr) |
| 2588 : LDeferredCode(codegen), instr_(instr) { } | 2612 : LDeferredCode(codegen), instr_(instr) { } |
| 2589 virtual void Generate() { | 2613 virtual void Generate() V8_OVERRIDE { |
| 2590 codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_); | 2614 codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_); |
| 2591 } | 2615 } |
| 2592 virtual LInstruction* instr() { return instr_; } | 2616 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 2593 Label* map_check() { return &map_check_; } | 2617 Label* map_check() { return &map_check_; } |
| 2594 | 2618 |
| 2595 private: | 2619 private: |
| 2596 LInstanceOfKnownGlobal* instr_; | 2620 LInstanceOfKnownGlobal* instr_; |
| 2597 Label map_check_; | 2621 Label map_check_; |
| 2598 }; | 2622 }; |
| 2599 | 2623 |
| 2600 DeferredInstanceOfKnownGlobal* deferred; | 2624 DeferredInstanceOfKnownGlobal* deferred; |
| 2601 deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr); | 2625 deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr); |
| 2602 | 2626 |
| (...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2914 Register result = ToRegister(instr->result()); | 2938 Register result = ToRegister(instr->result()); |
| 2915 if (access.IsInobject()) { | 2939 if (access.IsInobject()) { |
| 2916 __ lw(result, FieldMemOperand(object, offset)); | 2940 __ lw(result, FieldMemOperand(object, offset)); |
| 2917 } else { | 2941 } else { |
| 2918 __ lw(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 2942 __ lw(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
| 2919 __ lw(result, FieldMemOperand(result, offset)); | 2943 __ lw(result, FieldMemOperand(result, offset)); |
| 2920 } | 2944 } |
| 2921 } | 2945 } |
| 2922 | 2946 |
| 2923 | 2947 |
| 2924 void LCodeGen::EmitLoadFieldOrConstantFunction(Register result, | |
| 2925 Register object, | |
| 2926 Handle<Map> type, | |
| 2927 Handle<String> name, | |
| 2928 LEnvironment* env) { | |
| 2929 LookupResult lookup(isolate()); | |
| 2930 type->LookupDescriptor(NULL, *name, &lookup); | |
| 2931 ASSERT(lookup.IsFound() || lookup.IsCacheable()); | |
| 2932 if (lookup.IsField()) { | |
| 2933 int index = lookup.GetLocalFieldIndexFromMap(*type); | |
| 2934 int offset = index * kPointerSize; | |
| 2935 if (index < 0) { | |
| 2936 // Negative property indices are in-object properties, indexed | |
| 2937 // from the end of the fixed part of the object. | |
| 2938 __ lw(result, FieldMemOperand(object, offset + type->instance_size())); | |
| 2939 } else { | |
| 2940 // Non-negative property indices are in the properties array. | |
| 2941 __ lw(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); | |
| 2942 __ lw(result, FieldMemOperand(result, offset + FixedArray::kHeaderSize)); | |
| 2943 } | |
| 2944 } else if (lookup.IsConstant()) { | |
| 2945 Handle<Object> constant(lookup.GetConstantFromMap(*type), isolate()); | |
| 2946 __ LoadObject(result, constant); | |
| 2947 } else { | |
| 2948 // Negative lookup. | |
| 2949 // Check prototypes. | |
| 2950 Handle<HeapObject> current(HeapObject::cast((*type)->prototype())); | |
| 2951 Heap* heap = type->GetHeap(); | |
| 2952 while (*current != heap->null_value()) { | |
| 2953 __ LoadHeapObject(result, current); | |
| 2954 __ lw(result, FieldMemOperand(result, HeapObject::kMapOffset)); | |
| 2955 DeoptimizeIf(ne, env, result, Operand(Handle<Map>(current->map()))); | |
| 2956 current = | |
| 2957 Handle<HeapObject>(HeapObject::cast(current->map()->prototype())); | |
| 2958 } | |
| 2959 __ LoadRoot(result, Heap::kUndefinedValueRootIndex); | |
| 2960 } | |
| 2961 } | |
| 2962 | |
| 2963 | |
| 2964 void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) { | |
| 2965 Register object = ToRegister(instr->object()); | |
| 2966 Register result = ToRegister(instr->result()); | |
| 2967 Register object_map = scratch0(); | |
| 2968 | |
| 2969 int map_count = instr->hydrogen()->types()->length(); | |
| 2970 bool need_generic = instr->hydrogen()->need_generic(); | |
| 2971 | |
| 2972 if (map_count == 0 && !need_generic) { | |
| 2973 DeoptimizeIf(al, instr->environment()); | |
| 2974 return; | |
| 2975 } | |
| 2976 Handle<String> name = instr->hydrogen()->name(); | |
| 2977 Label done; | |
| 2978 __ lw(object_map, FieldMemOperand(object, HeapObject::kMapOffset)); | |
| 2979 for (int i = 0; i < map_count; ++i) { | |
| 2980 bool last = (i == map_count - 1); | |
| 2981 Handle<Map> map = instr->hydrogen()->types()->at(i); | |
| 2982 Label check_passed; | |
| 2983 __ CompareMapAndBranch(object_map, map, &check_passed, eq, &check_passed); | |
| 2984 if (last && !need_generic) { | |
| 2985 DeoptimizeIf(al, instr->environment()); | |
| 2986 __ bind(&check_passed); | |
| 2987 EmitLoadFieldOrConstantFunction( | |
| 2988 result, object, map, name, instr->environment()); | |
| 2989 } else { | |
| 2990 Label next; | |
| 2991 __ Branch(&next); | |
| 2992 __ bind(&check_passed); | |
| 2993 EmitLoadFieldOrConstantFunction( | |
| 2994 result, object, map, name, instr->environment()); | |
| 2995 __ Branch(&done); | |
| 2996 __ bind(&next); | |
| 2997 } | |
| 2998 } | |
| 2999 if (need_generic) { | |
| 3000 __ li(a2, Operand(name)); | |
| 3001 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | |
| 3002 CallCode(ic, RelocInfo::CODE_TARGET, instr); | |
| 3003 } | |
| 3004 __ bind(&done); | |
| 3005 } | |
| 3006 | |
| 3007 | |
| 3008 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { | 2948 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { |
| 3009 ASSERT(ToRegister(instr->object()).is(a0)); | 2949 ASSERT(ToRegister(instr->object()).is(a0)); |
| 3010 ASSERT(ToRegister(instr->result()).is(v0)); | 2950 ASSERT(ToRegister(instr->result()).is(v0)); |
| 3011 | 2951 |
| 3012 // Name is always in a2. | 2952 // Name is always in a2. |
| 3013 __ li(a2, Operand(instr->name())); | 2953 __ li(a2, Operand(instr->name())); |
| 3014 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2954 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
| 3015 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2955 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 3016 } | 2956 } |
| 3017 | 2957 |
| (...skipping 634 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3652 __ mov(result, input); | 3592 __ mov(result, input); |
| 3653 __ subu(result, zero_reg, input); | 3593 __ subu(result, zero_reg, input); |
| 3654 // Overflow if result is still negative, i.e. 0x80000000. | 3594 // Overflow if result is still negative, i.e. 0x80000000. |
| 3655 DeoptimizeIf(lt, instr->environment(), result, Operand(zero_reg)); | 3595 DeoptimizeIf(lt, instr->environment(), result, Operand(zero_reg)); |
| 3656 __ bind(&done); | 3596 __ bind(&done); |
| 3657 } | 3597 } |
| 3658 | 3598 |
| 3659 | 3599 |
| 3660 void LCodeGen::DoMathAbs(LMathAbs* instr) { | 3600 void LCodeGen::DoMathAbs(LMathAbs* instr) { |
| 3661 // Class for deferred case. | 3601 // Class for deferred case. |
| 3662 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { | 3602 class DeferredMathAbsTaggedHeapNumber V8_FINAL : public LDeferredCode { |
| 3663 public: | 3603 public: |
| 3664 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr) | 3604 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr) |
| 3665 : LDeferredCode(codegen), instr_(instr) { } | 3605 : LDeferredCode(codegen), instr_(instr) { } |
| 3666 virtual void Generate() { | 3606 virtual void Generate() V8_OVERRIDE { |
| 3667 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); | 3607 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); |
| 3668 } | 3608 } |
| 3669 virtual LInstruction* instr() { return instr_; } | 3609 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 3670 private: | 3610 private: |
| 3671 LMathAbs* instr_; | 3611 LMathAbs* instr_; |
| 3672 }; | 3612 }; |
| 3673 | 3613 |
| 3674 Representation r = instr->hydrogen()->value()->representation(); | 3614 Representation r = instr->hydrogen()->value()->representation(); |
| 3675 if (r.IsDouble()) { | 3615 if (r.IsDouble()) { |
| 3676 FPURegister input = ToDoubleRegister(instr->value()); | 3616 FPURegister input = ToDoubleRegister(instr->value()); |
| 3677 FPURegister result = ToDoubleRegister(instr->result()); | 3617 FPURegister result = ToDoubleRegister(instr->result()); |
| 3678 __ abs_d(result, input); | 3618 __ abs_d(result, input); |
| 3679 } else if (r.IsSmiOrInteger32()) { | 3619 } else if (r.IsSmiOrInteger32()) { |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3854 __ CallStub(&stub); | 3794 __ CallStub(&stub); |
| 3855 } else { | 3795 } else { |
| 3856 ASSERT(exponent_type.IsDouble()); | 3796 ASSERT(exponent_type.IsDouble()); |
| 3857 MathPowStub stub(MathPowStub::DOUBLE); | 3797 MathPowStub stub(MathPowStub::DOUBLE); |
| 3858 __ CallStub(&stub); | 3798 __ CallStub(&stub); |
| 3859 } | 3799 } |
| 3860 } | 3800 } |
| 3861 | 3801 |
| 3862 | 3802 |
| 3863 void LCodeGen::DoRandom(LRandom* instr) { | 3803 void LCodeGen::DoRandom(LRandom* instr) { |
| 3864 class DeferredDoRandom: public LDeferredCode { | 3804 class DeferredDoRandom V8_FINAL : public LDeferredCode { |
| 3865 public: | 3805 public: |
| 3866 DeferredDoRandom(LCodeGen* codegen, LRandom* instr) | 3806 DeferredDoRandom(LCodeGen* codegen, LRandom* instr) |
| 3867 : LDeferredCode(codegen), instr_(instr) { } | 3807 : LDeferredCode(codegen), instr_(instr) { } |
| 3868 virtual void Generate() { codegen()->DoDeferredRandom(instr_); } | 3808 virtual void Generate() V8_OVERRIDE { codegen()->DoDeferredRandom(instr_); } |
| 3869 virtual LInstruction* instr() { return instr_; } | 3809 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 3870 private: | 3810 private: |
| 3871 LRandom* instr_; | 3811 LRandom* instr_; |
| 3872 }; | 3812 }; |
| 3873 | 3813 |
| 3874 DeferredDoRandom* deferred = new(zone()) DeferredDoRandom(this, instr); | 3814 DeferredDoRandom* deferred = new(zone()) DeferredDoRandom(this, instr); |
| 3875 // Having marked this instruction as a call we can use any | 3815 // Having marked this instruction as a call we can use any |
| 3876 // registers. | 3816 // registers. |
| 3877 ASSERT(ToDoubleRegister(instr->result()).is(f0)); | 3817 ASSERT(ToDoubleRegister(instr->result()).is(f0)); |
| 3878 ASSERT(ToRegister(instr->global_object()).is(a0)); | 3818 ASSERT(ToRegister(instr->global_object()).is(a0)); |
| 3879 | 3819 |
| (...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4226 | 4166 |
| 4227 // Name is always in a2. | 4167 // Name is always in a2. |
| 4228 __ li(a2, Operand(instr->name())); | 4168 __ li(a2, Operand(instr->name())); |
| 4229 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) | 4169 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) |
| 4230 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 4170 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
| 4231 : isolate()->builtins()->StoreIC_Initialize(); | 4171 : isolate()->builtins()->StoreIC_Initialize(); |
| 4232 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 4172 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 4233 } | 4173 } |
| 4234 | 4174 |
| 4235 | 4175 |
| 4236 void LCodeGen::ApplyCheckIf(Condition cc, | 4176 void LCodeGen::ApplyCheckIf(Condition condition, |
| 4237 LBoundsCheck* check, | 4177 LBoundsCheck* check, |
| 4238 Register src1, | 4178 Register src1, |
| 4239 const Operand& src2) { | 4179 const Operand& src2) { |
| 4240 if (FLAG_debug_code && check->hydrogen()->skip_check()) { | 4180 if (FLAG_debug_code && check->hydrogen()->skip_check()) { |
| 4241 Label done; | 4181 Label done; |
| 4242 __ Branch(&done, NegateCondition(cc), src1, src2); | 4182 __ Branch(&done, NegateCondition(condition), src1, src2); |
| 4243 __ stop("eliminated bounds check failed"); | 4183 __ stop("eliminated bounds check failed"); |
| 4244 __ bind(&done); | 4184 __ bind(&done); |
| 4245 } else { | 4185 } else { |
| 4246 DeoptimizeIf(cc, check->environment(), src1, src2); | 4186 DeoptimizeIf(condition, check->environment(), src1, src2); |
| 4247 } | 4187 } |
| 4248 } | 4188 } |
| 4249 | 4189 |
| 4250 | 4190 |
| 4251 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { | 4191 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { |
| 4252 if (instr->hydrogen()->skip_check()) return; | 4192 if (instr->hydrogen()->skip_check()) return; |
| 4253 | 4193 |
| 4254 Condition condition = instr->hydrogen()->allow_equality() ? hi : hs; | 4194 Condition condition = instr->hydrogen()->allow_equality() ? hi : hs; |
| 4255 if (instr->index()->IsConstantOperand()) { | 4195 if (instr->index()->IsConstantOperand()) { |
| 4256 int constant_index = | 4196 int constant_index = |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4482 __ Branch(¬_applicable, ne, scratch, Operand(from_map)); | 4422 __ Branch(¬_applicable, ne, scratch, Operand(from_map)); |
| 4483 | 4423 |
| 4484 if (IsSimpleMapChangeTransition(from_kind, to_kind)) { | 4424 if (IsSimpleMapChangeTransition(from_kind, to_kind)) { |
| 4485 Register new_map_reg = ToRegister(instr->new_map_temp()); | 4425 Register new_map_reg = ToRegister(instr->new_map_temp()); |
| 4486 __ li(new_map_reg, Operand(to_map)); | 4426 __ li(new_map_reg, Operand(to_map)); |
| 4487 __ sw(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset)); | 4427 __ sw(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset)); |
| 4488 // Write barrier. | 4428 // Write barrier. |
| 4489 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, | 4429 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, |
| 4490 scratch, GetRAState(), kDontSaveFPRegs); | 4430 scratch, GetRAState(), kDontSaveFPRegs); |
| 4491 } else { | 4431 } else { |
| 4492 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 4432 PushSafepointRegistersScope scope( |
| 4433 this, Safepoint::kWithRegistersAndDoubles); |
| 4493 __ mov(a0, object_reg); | 4434 __ mov(a0, object_reg); |
| 4494 __ li(a1, Operand(to_map)); | 4435 __ li(a1, Operand(to_map)); |
| 4495 TransitionElementsKindStub stub(from_kind, to_kind); | 4436 TransitionElementsKindStub stub(from_kind, to_kind); |
| 4496 __ CallStub(&stub); | 4437 __ CallStub(&stub); |
| 4497 RecordSafepointWithRegisters( | 4438 RecordSafepointWithRegistersAndDoubles( |
| 4498 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); | 4439 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); |
| 4499 } | 4440 } |
| 4500 __ bind(¬_applicable); | 4441 __ bind(¬_applicable); |
| 4501 } | 4442 } |
| 4502 | 4443 |
| 4503 | 4444 |
| 4504 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { | 4445 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { |
| 4505 Register object = ToRegister(instr->object()); | 4446 Register object = ToRegister(instr->object()); |
| 4506 Register temp = ToRegister(instr->temp()); | 4447 Register temp = ToRegister(instr->temp()); |
| 4507 Label fail; | 4448 Label fail; |
| 4508 __ TestJSArrayForAllocationMemento(object, temp, ne, &fail); | 4449 __ TestJSArrayForAllocationMemento(object, temp, ne, &fail); |
| 4509 DeoptimizeIf(al, instr->environment()); | 4450 DeoptimizeIf(al, instr->environment()); |
| 4510 __ bind(&fail); | 4451 __ bind(&fail); |
| 4511 } | 4452 } |
| 4512 | 4453 |
| 4513 | 4454 |
| 4514 void LCodeGen::DoStringAdd(LStringAdd* instr) { | 4455 void LCodeGen::DoStringAdd(LStringAdd* instr) { |
| 4515 __ push(ToRegister(instr->left())); | 4456 __ push(ToRegister(instr->left())); |
| 4516 __ push(ToRegister(instr->right())); | 4457 __ push(ToRegister(instr->right())); |
| 4517 StringAddStub stub(instr->hydrogen()->flags()); | 4458 StringAddStub stub(instr->hydrogen()->flags()); |
| 4518 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 4459 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 4519 } | 4460 } |
| 4520 | 4461 |
| 4521 | 4462 |
| 4522 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { | 4463 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { |
| 4523 class DeferredStringCharCodeAt: public LDeferredCode { | 4464 class DeferredStringCharCodeAt V8_FINAL : public LDeferredCode { |
| 4524 public: | 4465 public: |
| 4525 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) | 4466 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) |
| 4526 : LDeferredCode(codegen), instr_(instr) { } | 4467 : LDeferredCode(codegen), instr_(instr) { } |
| 4527 virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); } | 4468 virtual void Generate() V8_OVERRIDE { |
| 4528 virtual LInstruction* instr() { return instr_; } | 4469 codegen()->DoDeferredStringCharCodeAt(instr_); |
| 4470 } |
| 4471 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 4529 private: | 4472 private: |
| 4530 LStringCharCodeAt* instr_; | 4473 LStringCharCodeAt* instr_; |
| 4531 }; | 4474 }; |
| 4532 | 4475 |
| 4533 DeferredStringCharCodeAt* deferred = | 4476 DeferredStringCharCodeAt* deferred = |
| 4534 new(zone()) DeferredStringCharCodeAt(this, instr); | 4477 new(zone()) DeferredStringCharCodeAt(this, instr); |
| 4535 StringCharLoadGenerator::Generate(masm(), | 4478 StringCharLoadGenerator::Generate(masm(), |
| 4536 ToRegister(instr->string()), | 4479 ToRegister(instr->string()), |
| 4537 ToRegister(instr->index()), | 4480 ToRegister(instr->index()), |
| 4538 ToRegister(instr->result()), | 4481 ToRegister(instr->result()), |
| (...skipping 26 matching lines...) Expand all Loading... |
| 4565 __ push(index); | 4508 __ push(index); |
| 4566 } | 4509 } |
| 4567 CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, instr); | 4510 CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, instr); |
| 4568 __ AssertSmi(v0); | 4511 __ AssertSmi(v0); |
| 4569 __ SmiUntag(v0); | 4512 __ SmiUntag(v0); |
| 4570 __ StoreToSafepointRegisterSlot(v0, result); | 4513 __ StoreToSafepointRegisterSlot(v0, result); |
| 4571 } | 4514 } |
| 4572 | 4515 |
| 4573 | 4516 |
| 4574 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { | 4517 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { |
| 4575 class DeferredStringCharFromCode: public LDeferredCode { | 4518 class DeferredStringCharFromCode V8_FINAL : public LDeferredCode { |
| 4576 public: | 4519 public: |
| 4577 DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr) | 4520 DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr) |
| 4578 : LDeferredCode(codegen), instr_(instr) { } | 4521 : LDeferredCode(codegen), instr_(instr) { } |
| 4579 virtual void Generate() { codegen()->DoDeferredStringCharFromCode(instr_); } | 4522 virtual void Generate() V8_OVERRIDE { |
| 4580 virtual LInstruction* instr() { return instr_; } | 4523 codegen()->DoDeferredStringCharFromCode(instr_); |
| 4524 } |
| 4525 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 4581 private: | 4526 private: |
| 4582 LStringCharFromCode* instr_; | 4527 LStringCharFromCode* instr_; |
| 4583 }; | 4528 }; |
| 4584 | 4529 |
| 4585 DeferredStringCharFromCode* deferred = | 4530 DeferredStringCharFromCode* deferred = |
| 4586 new(zone()) DeferredStringCharFromCode(this, instr); | 4531 new(zone()) DeferredStringCharFromCode(this, instr); |
| 4587 | 4532 |
| 4588 ASSERT(instr->hydrogen()->value()->representation().IsInteger32()); | 4533 ASSERT(instr->hydrogen()->value()->representation().IsInteger32()); |
| 4589 Register char_code = ToRegister(instr->char_code()); | 4534 Register char_code = ToRegister(instr->char_code()); |
| 4590 Register result = ToRegister(instr->result()); | 4535 Register result = ToRegister(instr->result()); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4656 LOperand* input = instr->value(); | 4601 LOperand* input = instr->value(); |
| 4657 LOperand* output = instr->result(); | 4602 LOperand* output = instr->result(); |
| 4658 | 4603 |
| 4659 FPURegister dbl_scratch = double_scratch0(); | 4604 FPURegister dbl_scratch = double_scratch0(); |
| 4660 __ mtc1(ToRegister(input), dbl_scratch); | 4605 __ mtc1(ToRegister(input), dbl_scratch); |
| 4661 __ Cvt_d_uw(ToDoubleRegister(output), dbl_scratch, f22); | 4606 __ Cvt_d_uw(ToDoubleRegister(output), dbl_scratch, f22); |
| 4662 } | 4607 } |
| 4663 | 4608 |
| 4664 | 4609 |
| 4665 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { | 4610 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { |
| 4666 class DeferredNumberTagI: public LDeferredCode { | 4611 class DeferredNumberTagI V8_FINAL : public LDeferredCode { |
| 4667 public: | 4612 public: |
| 4668 DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) | 4613 DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) |
| 4669 : LDeferredCode(codegen), instr_(instr) { } | 4614 : LDeferredCode(codegen), instr_(instr) { } |
| 4670 virtual void Generate() { | 4615 virtual void Generate() V8_OVERRIDE { |
| 4671 codegen()->DoDeferredNumberTagI(instr_, | 4616 codegen()->DoDeferredNumberTagI(instr_, |
| 4672 instr_->value(), | 4617 instr_->value(), |
| 4673 SIGNED_INT32); | 4618 SIGNED_INT32); |
| 4674 } | 4619 } |
| 4675 virtual LInstruction* instr() { return instr_; } | 4620 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 4676 private: | 4621 private: |
| 4677 LNumberTagI* instr_; | 4622 LNumberTagI* instr_; |
| 4678 }; | 4623 }; |
| 4679 | 4624 |
| 4680 Register src = ToRegister(instr->value()); | 4625 Register src = ToRegister(instr->value()); |
| 4681 Register dst = ToRegister(instr->result()); | 4626 Register dst = ToRegister(instr->result()); |
| 4682 Register overflow = scratch0(); | 4627 Register overflow = scratch0(); |
| 4683 | 4628 |
| 4684 DeferredNumberTagI* deferred = new(zone()) DeferredNumberTagI(this, instr); | 4629 DeferredNumberTagI* deferred = new(zone()) DeferredNumberTagI(this, instr); |
| 4685 __ SmiTagCheckOverflow(dst, src, overflow); | 4630 __ SmiTagCheckOverflow(dst, src, overflow); |
| 4686 __ BranchOnOverflow(deferred->entry(), overflow); | 4631 __ BranchOnOverflow(deferred->entry(), overflow); |
| 4687 __ bind(deferred->exit()); | 4632 __ bind(deferred->exit()); |
| 4688 } | 4633 } |
| 4689 | 4634 |
| 4690 | 4635 |
| 4691 void LCodeGen::DoNumberTagU(LNumberTagU* instr) { | 4636 void LCodeGen::DoNumberTagU(LNumberTagU* instr) { |
| 4692 class DeferredNumberTagU: public LDeferredCode { | 4637 class DeferredNumberTagU V8_FINAL : public LDeferredCode { |
| 4693 public: | 4638 public: |
| 4694 DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr) | 4639 DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr) |
| 4695 : LDeferredCode(codegen), instr_(instr) { } | 4640 : LDeferredCode(codegen), instr_(instr) { } |
| 4696 virtual void Generate() { | 4641 virtual void Generate() V8_OVERRIDE { |
| 4697 codegen()->DoDeferredNumberTagI(instr_, | 4642 codegen()->DoDeferredNumberTagI(instr_, |
| 4698 instr_->value(), | 4643 instr_->value(), |
| 4699 UNSIGNED_INT32); | 4644 UNSIGNED_INT32); |
| 4700 } | 4645 } |
| 4701 virtual LInstruction* instr() { return instr_; } | 4646 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 4702 private: | 4647 private: |
| 4703 LNumberTagU* instr_; | 4648 LNumberTagU* instr_; |
| 4704 }; | 4649 }; |
| 4705 | 4650 |
| 4706 LOperand* input = instr->value(); | 4651 LOperand* input = instr->value(); |
| 4707 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 4652 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
| 4708 Register reg = ToRegister(input); | 4653 Register reg = ToRegister(input); |
| 4709 | 4654 |
| 4710 DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr); | 4655 DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr); |
| 4711 __ Branch(deferred->entry(), hi, reg, Operand(Smi::kMaxValue)); | 4656 __ Branch(deferred->entry(), hi, reg, Operand(Smi::kMaxValue)); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4762 // Done. Put the value in dbl_scratch into the value of the allocated heap | 4707 // Done. Put the value in dbl_scratch into the value of the allocated heap |
| 4763 // number. | 4708 // number. |
| 4764 __ bind(&done); | 4709 __ bind(&done); |
| 4765 __ sdc1(dbl_scratch, MemOperand(dst, HeapNumber::kValueOffset)); | 4710 __ sdc1(dbl_scratch, MemOperand(dst, HeapNumber::kValueOffset)); |
| 4766 __ Addu(dst, dst, kHeapObjectTag); | 4711 __ Addu(dst, dst, kHeapObjectTag); |
| 4767 __ StoreToSafepointRegisterSlot(dst, dst); | 4712 __ StoreToSafepointRegisterSlot(dst, dst); |
| 4768 } | 4713 } |
| 4769 | 4714 |
| 4770 | 4715 |
| 4771 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { | 4716 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { |
| 4772 class DeferredNumberTagD: public LDeferredCode { | 4717 class DeferredNumberTagD V8_FINAL : public LDeferredCode { |
| 4773 public: | 4718 public: |
| 4774 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) | 4719 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) |
| 4775 : LDeferredCode(codegen), instr_(instr) { } | 4720 : LDeferredCode(codegen), instr_(instr) { } |
| 4776 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } | 4721 virtual void Generate() V8_OVERRIDE { |
| 4777 virtual LInstruction* instr() { return instr_; } | 4722 codegen()->DoDeferredNumberTagD(instr_); |
| 4723 } |
| 4724 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 4778 private: | 4725 private: |
| 4779 LNumberTagD* instr_; | 4726 LNumberTagD* instr_; |
| 4780 }; | 4727 }; |
| 4781 | 4728 |
| 4782 DoubleRegister input_reg = ToDoubleRegister(instr->value()); | 4729 DoubleRegister input_reg = ToDoubleRegister(instr->value()); |
| 4783 Register scratch = scratch0(); | 4730 Register scratch = scratch0(); |
| 4784 Register reg = ToRegister(instr->result()); | 4731 Register reg = ToRegister(instr->result()); |
| 4785 Register temp1 = ToRegister(instr->temp()); | 4732 Register temp1 = ToRegister(instr->temp()); |
| 4786 Register temp2 = ToRegister(instr->temp2()); | 4733 Register temp2 = ToRegister(instr->temp2()); |
| 4787 | 4734 |
| 4788 bool convert_hole = false; | |
| 4789 HValue* change_input = instr->hydrogen()->value(); | |
| 4790 if (change_input->IsLoadKeyed()) { | |
| 4791 HLoadKeyed* load = HLoadKeyed::cast(change_input); | |
| 4792 convert_hole = load->UsesMustHandleHole(); | |
| 4793 } | |
| 4794 | |
| 4795 Label no_special_nan_handling; | |
| 4796 Label done; | |
| 4797 if (convert_hole) { | |
| 4798 DoubleRegister input_reg = ToDoubleRegister(instr->value()); | |
| 4799 __ BranchF(&no_special_nan_handling, NULL, eq, input_reg, input_reg); | |
| 4800 __ Move(reg, scratch0(), input_reg); | |
| 4801 Label canonicalize; | |
| 4802 __ Branch(&canonicalize, ne, scratch0(), Operand(kHoleNanUpper32)); | |
| 4803 __ li(reg, factory()->the_hole_value()); | |
| 4804 __ Branch(&done); | |
| 4805 __ bind(&canonicalize); | |
| 4806 __ Move(input_reg, | |
| 4807 FixedDoubleArray::canonical_not_the_hole_nan_as_double()); | |
| 4808 } | |
| 4809 | |
| 4810 __ bind(&no_special_nan_handling); | |
| 4811 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); | 4735 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); |
| 4812 if (FLAG_inline_new) { | 4736 if (FLAG_inline_new) { |
| 4813 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); | 4737 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); |
| 4814 // We want the untagged address first for performance | 4738 // We want the untagged address first for performance |
| 4815 __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry(), | 4739 __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry(), |
| 4816 DONT_TAG_RESULT); | 4740 DONT_TAG_RESULT); |
| 4817 } else { | 4741 } else { |
| 4818 __ Branch(deferred->entry()); | 4742 __ Branch(deferred->entry()); |
| 4819 } | 4743 } |
| 4820 __ bind(deferred->exit()); | 4744 __ bind(deferred->exit()); |
| 4821 __ sdc1(input_reg, MemOperand(reg, HeapNumber::kValueOffset)); | 4745 __ sdc1(input_reg, MemOperand(reg, HeapNumber::kValueOffset)); |
| 4822 // Now that we have finished with the object's real address tag it | 4746 // Now that we have finished with the object's real address tag it |
| 4823 __ Addu(reg, reg, kHeapObjectTag); | 4747 __ Addu(reg, reg, kHeapObjectTag); |
| 4824 __ bind(&done); | |
| 4825 } | 4748 } |
| 4826 | 4749 |
| 4827 | 4750 |
| 4828 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { | 4751 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
| 4829 // TODO(3095996): Get rid of this. For now, we need to make the | 4752 // TODO(3095996): Get rid of this. For now, we need to make the |
| 4830 // result register contain a valid pointer because it is already | 4753 // result register contain a valid pointer because it is already |
| 4831 // contained in the register pointer map. | 4754 // contained in the register pointer map. |
| 4832 Register reg = ToRegister(instr->result()); | 4755 Register reg = ToRegister(instr->result()); |
| 4833 __ mov(reg, zero_reg); | 4756 __ mov(reg, zero_reg); |
| 4834 | 4757 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 4856 __ SmiUntag(result, input); | 4779 __ SmiUntag(result, input); |
| 4857 DeoptimizeIf(ne, instr->environment(), scratch, Operand(zero_reg)); | 4780 DeoptimizeIf(ne, instr->environment(), scratch, Operand(zero_reg)); |
| 4858 } else { | 4781 } else { |
| 4859 __ SmiUntag(result, input); | 4782 __ SmiUntag(result, input); |
| 4860 } | 4783 } |
| 4861 } | 4784 } |
| 4862 | 4785 |
| 4863 | 4786 |
| 4864 void LCodeGen::EmitNumberUntagD(Register input_reg, | 4787 void LCodeGen::EmitNumberUntagD(Register input_reg, |
| 4865 DoubleRegister result_reg, | 4788 DoubleRegister result_reg, |
| 4866 bool allow_undefined_as_nan, | 4789 bool can_convert_undefined_to_nan, |
| 4867 bool deoptimize_on_minus_zero, | 4790 bool deoptimize_on_minus_zero, |
| 4868 LEnvironment* env, | 4791 LEnvironment* env, |
| 4869 NumberUntagDMode mode) { | 4792 NumberUntagDMode mode) { |
| 4870 Register scratch = scratch0(); | 4793 Register scratch = scratch0(); |
| 4871 | 4794 |
| 4872 Label load_smi, heap_number, done; | 4795 Label load_smi, heap_number, done; |
| 4873 | 4796 |
| 4874 STATIC_ASSERT(NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE > | 4797 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { |
| 4875 NUMBER_CANDIDATE_IS_ANY_TAGGED); | |
| 4876 if (mode >= NUMBER_CANDIDATE_IS_ANY_TAGGED) { | |
| 4877 // Smi check. | 4798 // Smi check. |
| 4878 __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi); | 4799 __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi); |
| 4879 | 4800 |
| 4880 // Heap number map check. | 4801 // Heap number map check. |
| 4881 __ lw(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 4802 __ lw(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
| 4882 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); | 4803 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); |
| 4883 if (!allow_undefined_as_nan) { | 4804 if (!can_convert_undefined_to_nan) { |
| 4884 DeoptimizeIf(ne, env, scratch, Operand(at)); | 4805 DeoptimizeIf(ne, env, scratch, Operand(at)); |
| 4885 } else { | 4806 } else { |
| 4886 Label heap_number, convert; | 4807 Label heap_number, convert; |
| 4887 __ Branch(&heap_number, eq, scratch, Operand(at)); | 4808 __ Branch(&heap_number, eq, scratch, Operand(at)); |
| 4888 | 4809 |
| 4889 // Convert undefined (and hole) to NaN. | 4810 // Convert undefined (and hole) to NaN. |
| 4890 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | 4811 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
| 4891 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE) { | |
| 4892 __ Branch(&convert, eq, input_reg, Operand(at)); | |
| 4893 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | |
| 4894 } | |
| 4895 DeoptimizeIf(ne, env, input_reg, Operand(at)); | 4812 DeoptimizeIf(ne, env, input_reg, Operand(at)); |
| 4896 | 4813 |
| 4897 __ bind(&convert); | 4814 __ bind(&convert); |
| 4898 __ LoadRoot(at, Heap::kNanValueRootIndex); | 4815 __ LoadRoot(at, Heap::kNanValueRootIndex); |
| 4899 __ ldc1(result_reg, FieldMemOperand(at, HeapNumber::kValueOffset)); | 4816 __ ldc1(result_reg, FieldMemOperand(at, HeapNumber::kValueOffset)); |
| 4900 __ Branch(&done); | 4817 __ Branch(&done); |
| 4901 | 4818 |
| 4902 __ bind(&heap_number); | 4819 __ bind(&heap_number); |
| 4903 } | 4820 } |
| 4904 // Heap number to double register conversion. | 4821 // Heap number to double register conversion. |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4996 __ mfc1(scratch1, double_scratch.high()); | 4913 __ mfc1(scratch1, double_scratch.high()); |
| 4997 __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask)); | 4914 __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask)); |
| 4998 DeoptimizeIf(ne, instr->environment(), scratch1, Operand(zero_reg)); | 4915 DeoptimizeIf(ne, instr->environment(), scratch1, Operand(zero_reg)); |
| 4999 } | 4916 } |
| 5000 } | 4917 } |
| 5001 __ bind(&done); | 4918 __ bind(&done); |
| 5002 } | 4919 } |
| 5003 | 4920 |
| 5004 | 4921 |
| 5005 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { | 4922 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { |
| 5006 class DeferredTaggedToI: public LDeferredCode { | 4923 class DeferredTaggedToI V8_FINAL : public LDeferredCode { |
| 5007 public: | 4924 public: |
| 5008 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) | 4925 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) |
| 5009 : LDeferredCode(codegen), instr_(instr) { } | 4926 : LDeferredCode(codegen), instr_(instr) { } |
| 5010 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } | 4927 virtual void Generate() V8_OVERRIDE { |
| 5011 virtual LInstruction* instr() { return instr_; } | 4928 codegen()->DoDeferredTaggedToI(instr_); |
| 4929 } |
| 4930 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 5012 private: | 4931 private: |
| 5013 LTaggedToI* instr_; | 4932 LTaggedToI* instr_; |
| 5014 }; | 4933 }; |
| 5015 | 4934 |
| 5016 LOperand* input = instr->value(); | 4935 LOperand* input = instr->value(); |
| 5017 ASSERT(input->IsRegister()); | 4936 ASSERT(input->IsRegister()); |
| 5018 ASSERT(input->Equals(instr->result())); | 4937 ASSERT(input->Equals(instr->result())); |
| 5019 | 4938 |
| 5020 Register input_reg = ToRegister(input); | 4939 Register input_reg = ToRegister(input); |
| 5021 | 4940 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 5032 | 4951 |
| 5033 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { | 4952 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { |
| 5034 LOperand* input = instr->value(); | 4953 LOperand* input = instr->value(); |
| 5035 ASSERT(input->IsRegister()); | 4954 ASSERT(input->IsRegister()); |
| 5036 LOperand* result = instr->result(); | 4955 LOperand* result = instr->result(); |
| 5037 ASSERT(result->IsDoubleRegister()); | 4956 ASSERT(result->IsDoubleRegister()); |
| 5038 | 4957 |
| 5039 Register input_reg = ToRegister(input); | 4958 Register input_reg = ToRegister(input); |
| 5040 DoubleRegister result_reg = ToDoubleRegister(result); | 4959 DoubleRegister result_reg = ToDoubleRegister(result); |
| 5041 | 4960 |
| 5042 NumberUntagDMode mode = NUMBER_CANDIDATE_IS_ANY_TAGGED; | |
| 5043 HValue* value = instr->hydrogen()->value(); | 4961 HValue* value = instr->hydrogen()->value(); |
| 5044 if (value->type().IsSmi()) { | 4962 NumberUntagDMode mode = value->representation().IsSmi() |
| 5045 mode = NUMBER_CANDIDATE_IS_SMI; | 4963 ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED; |
| 5046 } else if (value->IsLoadKeyed()) { | |
| 5047 HLoadKeyed* load = HLoadKeyed::cast(value); | |
| 5048 if (load->UsesMustHandleHole()) { | |
| 5049 if (load->hole_mode() == ALLOW_RETURN_HOLE) { | |
| 5050 mode = NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE; | |
| 5051 } | |
| 5052 } | |
| 5053 } | |
| 5054 | 4964 |
| 5055 EmitNumberUntagD(input_reg, result_reg, | 4965 EmitNumberUntagD(input_reg, result_reg, |
| 5056 instr->hydrogen()->allow_undefined_as_nan(), | 4966 instr->hydrogen()->can_convert_undefined_to_nan(), |
| 5057 instr->hydrogen()->deoptimize_on_minus_zero(), | 4967 instr->hydrogen()->deoptimize_on_minus_zero(), |
| 5058 instr->environment(), | 4968 instr->environment(), |
| 5059 mode); | 4969 mode); |
| 5060 } | 4970 } |
| 5061 | 4971 |
| 5062 | 4972 |
| 5063 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { | 4973 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { |
| 5064 Register result_reg = ToRegister(instr->result()); | 4974 Register result_reg = ToRegister(instr->result()); |
| 5065 Register scratch1 = scratch0(); | 4975 Register scratch1 = scratch0(); |
| 5066 Register scratch2 = ToRegister(instr->temp()); | 4976 Register scratch2 = ToRegister(instr->temp()); |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5198 } | 5108 } |
| 5199 } | 5109 } |
| 5200 | 5110 |
| 5201 | 5111 |
| 5202 void LCodeGen::DoCheckFunction(LCheckFunction* instr) { | 5112 void LCodeGen::DoCheckFunction(LCheckFunction* instr) { |
| 5203 Register reg = ToRegister(instr->value()); | 5113 Register reg = ToRegister(instr->value()); |
| 5204 Handle<JSFunction> target = instr->hydrogen()->target(); | 5114 Handle<JSFunction> target = instr->hydrogen()->target(); |
| 5205 AllowDeferredHandleDereference smi_check; | 5115 AllowDeferredHandleDereference smi_check; |
| 5206 if (isolate()->heap()->InNewSpace(*target)) { | 5116 if (isolate()->heap()->InNewSpace(*target)) { |
| 5207 Register reg = ToRegister(instr->value()); | 5117 Register reg = ToRegister(instr->value()); |
| 5208 Handle<Cell> cell = isolate()->factory()->NewPropertyCell(target); | 5118 Handle<Cell> cell = isolate()->factory()->NewCell(target); |
| 5209 __ li(at, Operand(Handle<Object>(cell))); | 5119 __ li(at, Operand(Handle<Object>(cell))); |
| 5210 __ lw(at, FieldMemOperand(at, Cell::kValueOffset)); | 5120 __ lw(at, FieldMemOperand(at, Cell::kValueOffset)); |
| 5211 DeoptimizeIf(ne, instr->environment(), reg, | 5121 DeoptimizeIf(ne, instr->environment(), reg, |
| 5212 Operand(at)); | 5122 Operand(at)); |
| 5213 } else { | 5123 } else { |
| 5214 DeoptimizeIf(ne, instr->environment(), reg, | 5124 DeoptimizeIf(ne, instr->environment(), reg, |
| 5215 Operand(target)); | 5125 Operand(target)); |
| 5216 } | 5126 } |
| 5217 } | 5127 } |
| 5218 | 5128 |
| 5219 | 5129 |
| 5220 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { | 5130 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { |
| 5221 { | 5131 { |
| 5222 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 5132 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
| 5223 __ push(object); | 5133 __ push(object); |
| 5224 CallRuntimeFromDeferred(Runtime::kMigrateInstance, 1, instr); | 5134 CallRuntimeFromDeferred(Runtime::kMigrateInstance, 1, instr); |
| 5225 __ StoreToSafepointRegisterSlot(v0, scratch0()); | 5135 __ StoreToSafepointRegisterSlot(v0, scratch0()); |
| 5226 } | 5136 } |
| 5227 __ And(at, scratch0(), Operand(kSmiTagMask)); | 5137 __ And(at, scratch0(), Operand(kSmiTagMask)); |
| 5228 DeoptimizeIf(eq, instr->environment(), at, Operand(zero_reg)); | 5138 DeoptimizeIf(eq, instr->environment(), at, Operand(zero_reg)); |
| 5229 } | 5139 } |
| 5230 | 5140 |
| 5231 | 5141 |
| 5232 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { | 5142 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { |
| 5233 class DeferredCheckMaps: public LDeferredCode { | 5143 class DeferredCheckMaps V8_FINAL : public LDeferredCode { |
| 5234 public: | 5144 public: |
| 5235 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object) | 5145 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object) |
| 5236 : LDeferredCode(codegen), instr_(instr), object_(object) { | 5146 : LDeferredCode(codegen), instr_(instr), object_(object) { |
| 5237 SetExit(check_maps()); | 5147 SetExit(check_maps()); |
| 5238 } | 5148 } |
| 5239 virtual void Generate() { | 5149 virtual void Generate() V8_OVERRIDE { |
| 5240 codegen()->DoDeferredInstanceMigration(instr_, object_); | 5150 codegen()->DoDeferredInstanceMigration(instr_, object_); |
| 5241 } | 5151 } |
| 5242 Label* check_maps() { return &check_maps_; } | 5152 Label* check_maps() { return &check_maps_; } |
| 5243 virtual LInstruction* instr() { return instr_; } | 5153 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 5244 private: | 5154 private: |
| 5245 LCheckMaps* instr_; | 5155 LCheckMaps* instr_; |
| 5246 Label check_maps_; | 5156 Label check_maps_; |
| 5247 Register object_; | 5157 Register object_; |
| 5248 }; | 5158 }; |
| 5249 | 5159 |
| 5250 if (instr->hydrogen()->CanOmitMapChecks()) return; | 5160 if (instr->hydrogen()->CanOmitMapChecks()) return; |
| 5251 Register map_reg = scratch0(); | 5161 Register map_reg = scratch0(); |
| 5252 LOperand* input = instr->value(); | 5162 LOperand* input = instr->value(); |
| 5253 ASSERT(input->IsRegister()); | 5163 ASSERT(input->IsRegister()); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5322 __ jmp(&done); | 5232 __ jmp(&done); |
| 5323 | 5233 |
| 5324 __ bind(&is_smi); | 5234 __ bind(&is_smi); |
| 5325 __ ClampUint8(result_reg, scratch); | 5235 __ ClampUint8(result_reg, scratch); |
| 5326 | 5236 |
| 5327 __ bind(&done); | 5237 __ bind(&done); |
| 5328 } | 5238 } |
| 5329 | 5239 |
| 5330 | 5240 |
| 5331 void LCodeGen::DoAllocate(LAllocate* instr) { | 5241 void LCodeGen::DoAllocate(LAllocate* instr) { |
| 5332 class DeferredAllocate: public LDeferredCode { | 5242 class DeferredAllocate V8_FINAL : public LDeferredCode { |
| 5333 public: | 5243 public: |
| 5334 DeferredAllocate(LCodeGen* codegen, LAllocate* instr) | 5244 DeferredAllocate(LCodeGen* codegen, LAllocate* instr) |
| 5335 : LDeferredCode(codegen), instr_(instr) { } | 5245 : LDeferredCode(codegen), instr_(instr) { } |
| 5336 virtual void Generate() { codegen()->DoDeferredAllocate(instr_); } | 5246 virtual void Generate() V8_OVERRIDE { |
| 5337 virtual LInstruction* instr() { return instr_; } | 5247 codegen()->DoDeferredAllocate(instr_); |
| 5248 } |
| 5249 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 5338 private: | 5250 private: |
| 5339 LAllocate* instr_; | 5251 LAllocate* instr_; |
| 5340 }; | 5252 }; |
| 5341 | 5253 |
| 5342 DeferredAllocate* deferred = | 5254 DeferredAllocate* deferred = |
| 5343 new(zone()) DeferredAllocate(this, instr); | 5255 new(zone()) DeferredAllocate(this, instr); |
| 5344 | 5256 |
| 5345 Register result = ToRegister(instr->result()); | 5257 Register result = ToRegister(instr->result()); |
| 5346 Register scratch = ToRegister(instr->temp1()); | 5258 Register scratch = ToRegister(instr->temp1()); |
| 5347 Register scratch2 = ToRegister(instr->temp2()); | 5259 Register scratch2 = ToRegister(instr->temp2()); |
| (...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5701 | 5613 |
| 5702 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { | 5614 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { |
| 5703 Deoptimizer::BailoutType type = instr->hydrogen()->type(); | 5615 Deoptimizer::BailoutType type = instr->hydrogen()->type(); |
| 5704 // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the | 5616 // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the |
| 5705 // needed return address), even though the implementation of LAZY and EAGER is | 5617 // needed return address), even though the implementation of LAZY and EAGER is |
| 5706 // now identical. When LAZY is eventually completely folded into EAGER, remove | 5618 // now identical. When LAZY is eventually completely folded into EAGER, remove |
| 5707 // the special case below. | 5619 // the special case below. |
| 5708 if (info()->IsStub() && type == Deoptimizer::EAGER) { | 5620 if (info()->IsStub() && type == Deoptimizer::EAGER) { |
| 5709 type = Deoptimizer::LAZY; | 5621 type = Deoptimizer::LAZY; |
| 5710 } | 5622 } |
| 5623 |
| 5624 Comment(";;; deoptimize: %s", instr->hydrogen()->reason()); |
| 5711 DeoptimizeIf(al, instr->environment(), type, zero_reg, Operand(zero_reg)); | 5625 DeoptimizeIf(al, instr->environment(), type, zero_reg, Operand(zero_reg)); |
| 5712 } | 5626 } |
| 5713 | 5627 |
| 5714 | 5628 |
| 5715 void LCodeGen::DoDummyUse(LDummyUse* instr) { | 5629 void LCodeGen::DoDummyUse(LDummyUse* instr) { |
| 5716 // Nothing to see here, move on! | 5630 // Nothing to see here, move on! |
| 5717 } | 5631 } |
| 5718 | 5632 |
| 5719 | 5633 |
| 5720 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { | 5634 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { |
| 5721 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 5635 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
| 5722 __ CallRuntimeSaveDoubles(Runtime::kStackGuard); | 5636 __ CallRuntimeSaveDoubles(Runtime::kStackGuard); |
| 5723 RecordSafepointWithLazyDeopt( | 5637 RecordSafepointWithLazyDeopt( |
| 5724 instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); | 5638 instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); |
| 5725 ASSERT(instr->HasEnvironment()); | 5639 ASSERT(instr->HasEnvironment()); |
| 5726 LEnvironment* env = instr->environment(); | 5640 LEnvironment* env = instr->environment(); |
| 5727 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 5641 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
| 5728 } | 5642 } |
| 5729 | 5643 |
| 5730 | 5644 |
| 5731 void LCodeGen::DoStackCheck(LStackCheck* instr) { | 5645 void LCodeGen::DoStackCheck(LStackCheck* instr) { |
| 5732 class DeferredStackCheck: public LDeferredCode { | 5646 class DeferredStackCheck V8_FINAL : public LDeferredCode { |
| 5733 public: | 5647 public: |
| 5734 DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr) | 5648 DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr) |
| 5735 : LDeferredCode(codegen), instr_(instr) { } | 5649 : LDeferredCode(codegen), instr_(instr) { } |
| 5736 virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); } | 5650 virtual void Generate() V8_OVERRIDE { |
| 5737 virtual LInstruction* instr() { return instr_; } | 5651 codegen()->DoDeferredStackCheck(instr_); |
| 5652 } |
| 5653 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 5738 private: | 5654 private: |
| 5739 LStackCheck* instr_; | 5655 LStackCheck* instr_; |
| 5740 }; | 5656 }; |
| 5741 | 5657 |
| 5742 ASSERT(instr->HasEnvironment()); | 5658 ASSERT(instr->HasEnvironment()); |
| 5743 LEnvironment* env = instr->environment(); | 5659 LEnvironment* env = instr->environment(); |
| 5744 // There is no LLazyBailout instruction for stack-checks. We have to | 5660 // There is no LLazyBailout instruction for stack-checks. We have to |
| 5745 // prepare for lazy deoptimization explicitly here. | 5661 // prepare for lazy deoptimization explicitly here. |
| 5746 if (instr->hydrogen()->is_function_entry()) { | 5662 if (instr->hydrogen()->is_function_entry()) { |
| 5747 // Perform stack overflow check. | 5663 // Perform stack overflow check. |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5879 __ Subu(scratch, result, scratch); | 5795 __ Subu(scratch, result, scratch); |
| 5880 __ lw(result, FieldMemOperand(scratch, | 5796 __ lw(result, FieldMemOperand(scratch, |
| 5881 FixedArray::kHeaderSize - kPointerSize)); | 5797 FixedArray::kHeaderSize - kPointerSize)); |
| 5882 __ bind(&done); | 5798 __ bind(&done); |
| 5883 } | 5799 } |
| 5884 | 5800 |
| 5885 | 5801 |
| 5886 #undef __ | 5802 #undef __ |
| 5887 | 5803 |
| 5888 } } // namespace v8::internal | 5804 } } // namespace v8::internal |
| OLD | NEW |