| 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 "arm/lithium-codegen-arm.h" | 30 #include "arm/lithium-codegen-arm.h" |
| 31 #include "arm/lithium-gap-resolver-arm.h" | 31 #include "arm/lithium-gap-resolver-arm.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 719 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 781 int deoptimization_index = deoptimizations_.length(); | 781 int deoptimization_index = deoptimizations_.length(); |
| 782 int pc_offset = masm()->pc_offset(); | 782 int pc_offset = masm()->pc_offset(); |
| 783 environment->Register(deoptimization_index, | 783 environment->Register(deoptimization_index, |
| 784 translation.index(), | 784 translation.index(), |
| 785 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); | 785 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); |
| 786 deoptimizations_.Add(environment, zone()); | 786 deoptimizations_.Add(environment, zone()); |
| 787 } | 787 } |
| 788 } | 788 } |
| 789 | 789 |
| 790 | 790 |
| 791 void LCodeGen::DeoptimizeIf(Condition cc, | 791 void LCodeGen::DeoptimizeIf(Condition condition, |
| 792 LEnvironment* environment, | 792 LEnvironment* environment, |
| 793 Deoptimizer::BailoutType bailout_type) { | 793 Deoptimizer::BailoutType bailout_type) { |
| 794 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); | 794 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); |
| 795 ASSERT(environment->HasBeenRegistered()); | 795 ASSERT(environment->HasBeenRegistered()); |
| 796 int id = environment->deoptimization_index(); | 796 int id = environment->deoptimization_index(); |
| 797 ASSERT(info()->IsOptimizing() || info()->IsStub()); | 797 ASSERT(info()->IsOptimizing() || info()->IsStub()); |
| 798 Address entry = | 798 Address entry = |
| 799 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); | 799 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); |
| 800 if (entry == NULL) { | 800 if (entry == NULL) { |
| 801 Abort(kBailoutWasNotPrepared); | 801 Abort(kBailoutWasNotPrepared); |
| 802 return; | 802 return; |
| 803 } | 803 } |
| 804 | 804 |
| 805 ASSERT(FLAG_deopt_every_n_times < 2); // Other values not supported on ARM. | 805 ASSERT(FLAG_deopt_every_n_times < 2); // Other values not supported on ARM. |
| 806 if (FLAG_deopt_every_n_times == 1 && | 806 if (FLAG_deopt_every_n_times == 1 && |
| 807 !info()->IsStub() && | 807 !info()->IsStub() && |
| 808 info()->opt_count() == id) { | 808 info()->opt_count() == id) { |
| 809 ASSERT(frame_is_built_); | 809 ASSERT(frame_is_built_); |
| 810 __ Call(entry, RelocInfo::RUNTIME_ENTRY); | 810 __ Call(entry, RelocInfo::RUNTIME_ENTRY); |
| 811 return; | 811 return; |
| 812 } | 812 } |
| 813 | 813 |
| 814 if (info()->ShouldTrapOnDeopt()) { | 814 if (info()->ShouldTrapOnDeopt()) { |
| 815 __ stop("trap_on_deopt", cc); | 815 __ stop("trap_on_deopt", condition); |
| 816 } | 816 } |
| 817 | 817 |
| 818 ASSERT(info()->IsStub() || frame_is_built_); | 818 ASSERT(info()->IsStub() || frame_is_built_); |
| 819 if (cc == al && frame_is_built_) { | 819 if (condition == al && frame_is_built_) { |
| 820 __ Call(entry, RelocInfo::RUNTIME_ENTRY); | 820 __ Call(entry, RelocInfo::RUNTIME_ENTRY); |
| 821 } else { | 821 } else { |
| 822 // We often have several deopts to the same entry, reuse the last | 822 // We often have several deopts to the same entry, reuse the last |
| 823 // jump entry if this is the case. | 823 // jump entry if this is the case. |
| 824 if (deopt_jump_table_.is_empty() || | 824 if (deopt_jump_table_.is_empty() || |
| 825 (deopt_jump_table_.last().address != entry) || | 825 (deopt_jump_table_.last().address != entry) || |
| 826 (deopt_jump_table_.last().bailout_type != bailout_type) || | 826 (deopt_jump_table_.last().bailout_type != bailout_type) || |
| 827 (deopt_jump_table_.last().needs_frame != !frame_is_built_)) { | 827 (deopt_jump_table_.last().needs_frame != !frame_is_built_)) { |
| 828 Deoptimizer::JumpTableEntry table_entry(entry, | 828 Deoptimizer::JumpTableEntry table_entry(entry, |
| 829 bailout_type, | 829 bailout_type, |
| 830 !frame_is_built_); | 830 !frame_is_built_); |
| 831 deopt_jump_table_.Add(table_entry, zone()); | 831 deopt_jump_table_.Add(table_entry, zone()); |
| 832 } | 832 } |
| 833 __ b(cc, &deopt_jump_table_.last().label); | 833 __ b(condition, &deopt_jump_table_.last().label); |
| 834 } | 834 } |
| 835 } | 835 } |
| 836 | 836 |
| 837 | 837 |
| 838 void LCodeGen::DeoptimizeIf(Condition cc, | 838 void LCodeGen::DeoptimizeIf(Condition condition, |
| 839 LEnvironment* environment) { | 839 LEnvironment* environment) { |
| 840 Deoptimizer::BailoutType bailout_type = info()->IsStub() | 840 Deoptimizer::BailoutType bailout_type = info()->IsStub() |
| 841 ? Deoptimizer::LAZY | 841 ? Deoptimizer::LAZY |
| 842 : Deoptimizer::EAGER; | 842 : Deoptimizer::EAGER; |
| 843 DeoptimizeIf(cc, environment, bailout_type); | 843 DeoptimizeIf(condition, environment, bailout_type); |
| 844 } | 844 } |
| 845 | 845 |
| 846 | 846 |
| 847 void LCodeGen::RegisterDependentCodeForEmbeddedMaps(Handle<Code> code) { | 847 void LCodeGen::RegisterDependentCodeForEmbeddedMaps(Handle<Code> code) { |
| 848 ZoneList<Handle<Map> > maps(1, zone()); | 848 ZoneList<Handle<Map> > maps(1, zone()); |
| 849 int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); | 849 int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); |
| 850 for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) { | 850 for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) { |
| 851 RelocInfo::Mode mode = it.rinfo()->rmode(); | 851 RelocInfo::Mode mode = it.rinfo()->rmode(); |
| 852 if (mode == RelocInfo::EMBEDDED_OBJECT && | 852 if (mode == RelocInfo::EMBEDDED_OBJECT && |
| 853 it.rinfo()->target_object()->IsMap()) { | 853 it.rinfo()->target_object()->IsMap()) { |
| (...skipping 537 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1391 power = WhichPowerOf2(-divisor); | 1391 power = WhichPowerOf2(-divisor); |
| 1392 } | 1392 } |
| 1393 | 1393 |
| 1394 if (test_value != 0) { | 1394 if (test_value != 0) { |
| 1395 if (instr->hydrogen()->CheckFlag( | 1395 if (instr->hydrogen()->CheckFlag( |
| 1396 HInstruction::kAllUsesTruncatingToInt32)) { | 1396 HInstruction::kAllUsesTruncatingToInt32)) { |
| 1397 __ cmp(dividend, Operand(0)); | 1397 __ cmp(dividend, Operand(0)); |
| 1398 __ rsb(dividend, dividend, Operand(0), LeaveCC, lt); | 1398 __ rsb(dividend, dividend, Operand(0), LeaveCC, lt); |
| 1399 __ mov(dividend, Operand(dividend, ASR, power)); | 1399 __ mov(dividend, Operand(dividend, ASR, power)); |
| 1400 if (divisor > 0) __ rsb(dividend, dividend, Operand(0), LeaveCC, lt); | 1400 if (divisor > 0) __ rsb(dividend, dividend, Operand(0), LeaveCC, lt); |
| 1401 if (divisor < 0) __ rsb(dividend, dividend, Operand(0), LeaveCC, gt); |
| 1401 return; // Don't fall through to "__ rsb" below. | 1402 return; // Don't fall through to "__ rsb" below. |
| 1402 } else { | 1403 } else { |
| 1403 // Deoptimize if remainder is not 0. | 1404 // Deoptimize if remainder is not 0. |
| 1404 __ tst(dividend, Operand(test_value)); | 1405 __ tst(dividend, Operand(test_value)); |
| 1405 DeoptimizeIf(ne, instr->environment()); | 1406 DeoptimizeIf(ne, instr->environment()); |
| 1406 __ mov(dividend, Operand(dividend, ASR, power)); | 1407 __ mov(dividend, Operand(dividend, ASR, power)); |
| 1407 } | 1408 } |
| 1408 } | 1409 } |
| 1409 if (divisor < 0) __ rsb(dividend, dividend, Operand(0)); | 1410 if (divisor < 0) __ rsb(dividend, dividend, Operand(0)); |
| 1410 | 1411 |
| (...skipping 734 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2145 | 2146 |
| 2146 | 2147 |
| 2147 int LCodeGen::GetNextEmittedBlock() const { | 2148 int LCodeGen::GetNextEmittedBlock() const { |
| 2148 for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) { | 2149 for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) { |
| 2149 if (!chunk_->GetLabel(i)->HasReplacement()) return i; | 2150 if (!chunk_->GetLabel(i)->HasReplacement()) return i; |
| 2150 } | 2151 } |
| 2151 return -1; | 2152 return -1; |
| 2152 } | 2153 } |
| 2153 | 2154 |
| 2154 template<class InstrType> | 2155 template<class InstrType> |
| 2155 void LCodeGen::EmitBranch(InstrType instr, Condition cc) { | 2156 void LCodeGen::EmitBranch(InstrType instr, Condition condition) { |
| 2156 int left_block = instr->TrueDestination(chunk_); | 2157 int left_block = instr->TrueDestination(chunk_); |
| 2157 int right_block = instr->FalseDestination(chunk_); | 2158 int right_block = instr->FalseDestination(chunk_); |
| 2158 | 2159 |
| 2159 int next_block = GetNextEmittedBlock(); | 2160 int next_block = GetNextEmittedBlock(); |
| 2160 | 2161 |
| 2161 if (right_block == left_block || cc == al) { | 2162 if (right_block == left_block || condition == al) { |
| 2162 EmitGoto(left_block); | 2163 EmitGoto(left_block); |
| 2163 } else if (left_block == next_block) { | 2164 } else if (left_block == next_block) { |
| 2164 __ b(NegateCondition(cc), chunk_->GetAssemblyLabel(right_block)); | 2165 __ b(NegateCondition(condition), chunk_->GetAssemblyLabel(right_block)); |
| 2165 } else if (right_block == next_block) { | 2166 } else if (right_block == next_block) { |
| 2166 __ b(cc, chunk_->GetAssemblyLabel(left_block)); | 2167 __ b(condition, chunk_->GetAssemblyLabel(left_block)); |
| 2167 } else { | 2168 } else { |
| 2168 __ b(cc, chunk_->GetAssemblyLabel(left_block)); | 2169 __ b(condition, chunk_->GetAssemblyLabel(left_block)); |
| 2169 __ b(chunk_->GetAssemblyLabel(right_block)); | 2170 __ b(chunk_->GetAssemblyLabel(right_block)); |
| 2170 } | 2171 } |
| 2171 } | 2172 } |
| 2172 | 2173 |
| 2173 | 2174 |
| 2175 template<class InstrType> |
| 2176 void LCodeGen::EmitFalseBranch(InstrType instr, Condition condition) { |
| 2177 int false_block = instr->FalseDestination(chunk_); |
| 2178 __ b(condition, chunk_->GetAssemblyLabel(false_block)); |
| 2179 } |
| 2180 |
| 2181 |
| 2174 void LCodeGen::DoDebugBreak(LDebugBreak* instr) { | 2182 void LCodeGen::DoDebugBreak(LDebugBreak* instr) { |
| 2175 __ stop("LBreak"); | 2183 __ stop("LBreak"); |
| 2176 } | 2184 } |
| 2177 | 2185 |
| 2178 | 2186 |
| 2179 void LCodeGen::DoIsNumberAndBranch(LIsNumberAndBranch* instr) { | 2187 void LCodeGen::DoIsNumberAndBranch(LIsNumberAndBranch* instr) { |
| 2180 Representation r = instr->hydrogen()->value()->representation(); | 2188 Representation r = instr->hydrogen()->value()->representation(); |
| 2181 if (r.IsSmiOrInteger32() || r.IsDouble()) { | 2189 if (r.IsSmiOrInteger32() || r.IsDouble()) { |
| 2182 EmitBranch(instr, al); | 2190 EmitBranch(instr, al); |
| 2183 } else { | 2191 } else { |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2419 | 2427 |
| 2420 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { | 2428 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { |
| 2421 Register left = ToRegister(instr->left()); | 2429 Register left = ToRegister(instr->left()); |
| 2422 Register right = ToRegister(instr->right()); | 2430 Register right = ToRegister(instr->right()); |
| 2423 | 2431 |
| 2424 __ cmp(left, Operand(right)); | 2432 __ cmp(left, Operand(right)); |
| 2425 EmitBranch(instr, eq); | 2433 EmitBranch(instr, eq); |
| 2426 } | 2434 } |
| 2427 | 2435 |
| 2428 | 2436 |
| 2437 void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) { |
| 2438 if (instr->hydrogen()->representation().IsTagged()) { |
| 2439 Register input_reg = ToRegister(instr->object()); |
| 2440 __ mov(ip, Operand(factory()->the_hole_value())); |
| 2441 __ cmp(input_reg, ip); |
| 2442 EmitBranch(instr, eq); |
| 2443 return; |
| 2444 } |
| 2445 |
| 2446 DwVfpRegister input_reg = ToDoubleRegister(instr->object()); |
| 2447 __ VFPCompareAndSetFlags(input_reg, input_reg); |
| 2448 EmitFalseBranch(instr, vc); |
| 2449 |
| 2450 Register scratch = scratch0(); |
| 2451 __ VmovHigh(scratch, input_reg); |
| 2452 __ cmp(scratch, Operand(kHoleNanUpper32)); |
| 2453 EmitBranch(instr, eq); |
| 2454 } |
| 2455 |
| 2456 |
| 2429 Condition LCodeGen::EmitIsObject(Register input, | 2457 Condition LCodeGen::EmitIsObject(Register input, |
| 2430 Register temp1, | 2458 Register temp1, |
| 2431 Label* is_not_object, | 2459 Label* is_not_object, |
| 2432 Label* is_object) { | 2460 Label* is_object) { |
| 2433 Register temp2 = scratch0(); | 2461 Register temp2 = scratch0(); |
| 2434 __ JumpIfSmi(input, is_not_object); | 2462 __ JumpIfSmi(input, is_not_object); |
| 2435 | 2463 |
| 2436 __ LoadRoot(temp2, Heap::kNullValueRootIndex); | 2464 __ LoadRoot(temp2, Heap::kNullValueRootIndex); |
| 2437 __ cmp(input, temp2); | 2465 __ cmp(input, temp2); |
| 2438 __ b(eq, is_object); | 2466 __ b(eq, is_object); |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2700 InstanceofStub stub(InstanceofStub::kArgsInRegisters); | 2728 InstanceofStub stub(InstanceofStub::kArgsInRegisters); |
| 2701 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 2729 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 2702 | 2730 |
| 2703 __ cmp(r0, Operand::Zero()); | 2731 __ cmp(r0, Operand::Zero()); |
| 2704 __ mov(r0, Operand(factory()->false_value()), LeaveCC, ne); | 2732 __ mov(r0, Operand(factory()->false_value()), LeaveCC, ne); |
| 2705 __ mov(r0, Operand(factory()->true_value()), LeaveCC, eq); | 2733 __ mov(r0, Operand(factory()->true_value()), LeaveCC, eq); |
| 2706 } | 2734 } |
| 2707 | 2735 |
| 2708 | 2736 |
| 2709 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { | 2737 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { |
| 2710 class DeferredInstanceOfKnownGlobal: public LDeferredCode { | 2738 class DeferredInstanceOfKnownGlobal V8_FINAL : public LDeferredCode { |
| 2711 public: | 2739 public: |
| 2712 DeferredInstanceOfKnownGlobal(LCodeGen* codegen, | 2740 DeferredInstanceOfKnownGlobal(LCodeGen* codegen, |
| 2713 LInstanceOfKnownGlobal* instr) | 2741 LInstanceOfKnownGlobal* instr) |
| 2714 : LDeferredCode(codegen), instr_(instr) { } | 2742 : LDeferredCode(codegen), instr_(instr) { } |
| 2715 virtual void Generate() { | 2743 virtual void Generate() V8_OVERRIDE { |
| 2716 codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_); | 2744 codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_); |
| 2717 } | 2745 } |
| 2718 virtual LInstruction* instr() { return instr_; } | 2746 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 2719 Label* map_check() { return &map_check_; } | 2747 Label* map_check() { return &map_check_; } |
| 2720 private: | 2748 private: |
| 2721 LInstanceOfKnownGlobal* instr_; | 2749 LInstanceOfKnownGlobal* instr_; |
| 2722 Label map_check_; | 2750 Label map_check_; |
| 2723 }; | 2751 }; |
| 2724 | 2752 |
| 2725 DeferredInstanceOfKnownGlobal* deferred; | 2753 DeferredInstanceOfKnownGlobal* deferred; |
| 2726 deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr); | 2754 deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr); |
| 2727 | 2755 |
| 2728 Label done, false_result; | 2756 Label done, false_result; |
| (...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3045 Register result = ToRegister(instr->result()); | 3073 Register result = ToRegister(instr->result()); |
| 3046 if (access.IsInobject()) { | 3074 if (access.IsInobject()) { |
| 3047 __ ldr(result, FieldMemOperand(object, offset)); | 3075 __ ldr(result, FieldMemOperand(object, offset)); |
| 3048 } else { | 3076 } else { |
| 3049 __ ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 3077 __ ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
| 3050 __ ldr(result, FieldMemOperand(result, offset)); | 3078 __ ldr(result, FieldMemOperand(result, offset)); |
| 3051 } | 3079 } |
| 3052 } | 3080 } |
| 3053 | 3081 |
| 3054 | 3082 |
| 3055 void LCodeGen::EmitLoadFieldOrConstantFunction(Register result, | |
| 3056 Register object, | |
| 3057 Handle<Map> type, | |
| 3058 Handle<String> name, | |
| 3059 LEnvironment* env) { | |
| 3060 LookupResult lookup(isolate()); | |
| 3061 type->LookupDescriptor(NULL, *name, &lookup); | |
| 3062 ASSERT(lookup.IsFound() || lookup.IsCacheable()); | |
| 3063 if (lookup.IsField()) { | |
| 3064 int index = lookup.GetLocalFieldIndexFromMap(*type); | |
| 3065 int offset = index * kPointerSize; | |
| 3066 if (index < 0) { | |
| 3067 // Negative property indices are in-object properties, indexed | |
| 3068 // from the end of the fixed part of the object. | |
| 3069 __ ldr(result, FieldMemOperand(object, offset + type->instance_size())); | |
| 3070 } else { | |
| 3071 // Non-negative property indices are in the properties array. | |
| 3072 __ ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); | |
| 3073 __ ldr(result, FieldMemOperand(result, offset + FixedArray::kHeaderSize)); | |
| 3074 } | |
| 3075 } else if (lookup.IsConstant()) { | |
| 3076 Handle<Object> constant(lookup.GetConstantFromMap(*type), isolate()); | |
| 3077 __ LoadObject(result, constant); | |
| 3078 } else { | |
| 3079 // Negative lookup. | |
| 3080 // Check prototypes. | |
| 3081 Handle<HeapObject> current(HeapObject::cast((*type)->prototype())); | |
| 3082 Heap* heap = type->GetHeap(); | |
| 3083 while (*current != heap->null_value()) { | |
| 3084 __ LoadHeapObject(result, current); | |
| 3085 __ ldr(result, FieldMemOperand(result, HeapObject::kMapOffset)); | |
| 3086 __ cmp(result, Operand(Handle<Map>(current->map()))); | |
| 3087 DeoptimizeIf(ne, env); | |
| 3088 current = | |
| 3089 Handle<HeapObject>(HeapObject::cast(current->map()->prototype())); | |
| 3090 } | |
| 3091 __ LoadRoot(result, Heap::kUndefinedValueRootIndex); | |
| 3092 } | |
| 3093 } | |
| 3094 | |
| 3095 | |
| 3096 void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) { | |
| 3097 Register object = ToRegister(instr->object()); | |
| 3098 Register result = ToRegister(instr->result()); | |
| 3099 Register object_map = scratch0(); | |
| 3100 | |
| 3101 int map_count = instr->hydrogen()->types()->length(); | |
| 3102 bool need_generic = instr->hydrogen()->need_generic(); | |
| 3103 | |
| 3104 if (map_count == 0 && !need_generic) { | |
| 3105 DeoptimizeIf(al, instr->environment()); | |
| 3106 return; | |
| 3107 } | |
| 3108 Handle<String> name = instr->hydrogen()->name(); | |
| 3109 Label done; | |
| 3110 __ ldr(object_map, FieldMemOperand(object, HeapObject::kMapOffset)); | |
| 3111 for (int i = 0; i < map_count; ++i) { | |
| 3112 bool last = (i == map_count - 1); | |
| 3113 Handle<Map> map = instr->hydrogen()->types()->at(i); | |
| 3114 Label check_passed; | |
| 3115 __ CompareMap(object_map, map, &check_passed); | |
| 3116 if (last && !need_generic) { | |
| 3117 DeoptimizeIf(ne, instr->environment()); | |
| 3118 __ bind(&check_passed); | |
| 3119 EmitLoadFieldOrConstantFunction( | |
| 3120 result, object, map, name, instr->environment()); | |
| 3121 } else { | |
| 3122 Label next; | |
| 3123 __ b(ne, &next); | |
| 3124 __ bind(&check_passed); | |
| 3125 EmitLoadFieldOrConstantFunction( | |
| 3126 result, object, map, name, instr->environment()); | |
| 3127 __ b(&done); | |
| 3128 __ bind(&next); | |
| 3129 } | |
| 3130 } | |
| 3131 if (need_generic) { | |
| 3132 __ mov(r2, Operand(name)); | |
| 3133 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | |
| 3134 CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); | |
| 3135 } | |
| 3136 __ bind(&done); | |
| 3137 } | |
| 3138 | |
| 3139 | |
| 3140 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { | 3083 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { |
| 3141 ASSERT(ToRegister(instr->object()).is(r0)); | 3084 ASSERT(ToRegister(instr->object()).is(r0)); |
| 3142 ASSERT(ToRegister(instr->result()).is(r0)); | 3085 ASSERT(ToRegister(instr->result()).is(r0)); |
| 3143 | 3086 |
| 3144 // Name is always in r2. | 3087 // Name is always in r2. |
| 3145 __ mov(r2, Operand(instr->name())); | 3088 __ mov(r2, Operand(instr->name())); |
| 3146 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 3089 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
| 3147 CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); | 3090 CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); |
| 3148 } | 3091 } |
| 3149 | 3092 |
| (...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3772 // will clear the V (overflow) flag and rsb won't set this flag | 3715 // will clear the V (overflow) flag and rsb won't set this flag |
| 3773 // if input is positive. | 3716 // if input is positive. |
| 3774 __ rsb(result, input, Operand::Zero(), SetCC, mi); | 3717 __ rsb(result, input, Operand::Zero(), SetCC, mi); |
| 3775 // Deoptimize on overflow. | 3718 // Deoptimize on overflow. |
| 3776 DeoptimizeIf(vs, instr->environment()); | 3719 DeoptimizeIf(vs, instr->environment()); |
| 3777 } | 3720 } |
| 3778 | 3721 |
| 3779 | 3722 |
| 3780 void LCodeGen::DoMathAbs(LMathAbs* instr) { | 3723 void LCodeGen::DoMathAbs(LMathAbs* instr) { |
| 3781 // Class for deferred case. | 3724 // Class for deferred case. |
| 3782 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { | 3725 class DeferredMathAbsTaggedHeapNumber V8_FINAL : public LDeferredCode { |
| 3783 public: | 3726 public: |
| 3784 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr) | 3727 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr) |
| 3785 : LDeferredCode(codegen), instr_(instr) { } | 3728 : LDeferredCode(codegen), instr_(instr) { } |
| 3786 virtual void Generate() { | 3729 virtual void Generate() V8_OVERRIDE { |
| 3787 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); | 3730 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); |
| 3788 } | 3731 } |
| 3789 virtual LInstruction* instr() { return instr_; } | 3732 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 3790 private: | 3733 private: |
| 3791 LMathAbs* instr_; | 3734 LMathAbs* instr_; |
| 3792 }; | 3735 }; |
| 3793 | 3736 |
| 3794 Representation r = instr->hydrogen()->value()->representation(); | 3737 Representation r = instr->hydrogen()->value()->representation(); |
| 3795 if (r.IsDouble()) { | 3738 if (r.IsDouble()) { |
| 3796 DwVfpRegister input = ToDoubleRegister(instr->value()); | 3739 DwVfpRegister input = ToDoubleRegister(instr->value()); |
| 3797 DwVfpRegister result = ToDoubleRegister(instr->result()); | 3740 DwVfpRegister result = ToDoubleRegister(instr->result()); |
| 3798 __ vabs(result, input); | 3741 __ vabs(result, input); |
| 3799 } else if (r.IsSmiOrInteger32()) { | 3742 } else if (r.IsSmiOrInteger32()) { |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3928 __ CallStub(&stub); | 3871 __ CallStub(&stub); |
| 3929 } else { | 3872 } else { |
| 3930 ASSERT(exponent_type.IsDouble()); | 3873 ASSERT(exponent_type.IsDouble()); |
| 3931 MathPowStub stub(MathPowStub::DOUBLE); | 3874 MathPowStub stub(MathPowStub::DOUBLE); |
| 3932 __ CallStub(&stub); | 3875 __ CallStub(&stub); |
| 3933 } | 3876 } |
| 3934 } | 3877 } |
| 3935 | 3878 |
| 3936 | 3879 |
| 3937 void LCodeGen::DoRandom(LRandom* instr) { | 3880 void LCodeGen::DoRandom(LRandom* instr) { |
| 3938 class DeferredDoRandom: public LDeferredCode { | 3881 class DeferredDoRandom V8_FINAL : public LDeferredCode { |
| 3939 public: | 3882 public: |
| 3940 DeferredDoRandom(LCodeGen* codegen, LRandom* instr) | 3883 DeferredDoRandom(LCodeGen* codegen, LRandom* instr) |
| 3941 : LDeferredCode(codegen), instr_(instr) { } | 3884 : LDeferredCode(codegen), instr_(instr) { } |
| 3942 virtual void Generate() { codegen()->DoDeferredRandom(instr_); } | 3885 virtual void Generate() V8_OVERRIDE { codegen()->DoDeferredRandom(instr_); } |
| 3943 virtual LInstruction* instr() { return instr_; } | 3886 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 3944 private: | 3887 private: |
| 3945 LRandom* instr_; | 3888 LRandom* instr_; |
| 3946 }; | 3889 }; |
| 3947 | 3890 |
| 3948 DeferredDoRandom* deferred = new(zone()) DeferredDoRandom(this, instr); | 3891 DeferredDoRandom* deferred = new(zone()) DeferredDoRandom(this, instr); |
| 3949 | 3892 |
| 3950 // Having marked this instruction as a call we can use any | 3893 // Having marked this instruction as a call we can use any |
| 3951 // registers. | 3894 // registers. |
| 3952 ASSERT(ToDoubleRegister(instr->result()).is(d7)); | 3895 ASSERT(ToDoubleRegister(instr->result()).is(d7)); |
| 3953 ASSERT(ToRegister(instr->global_object()).is(r0)); | 3896 ASSERT(ToRegister(instr->global_object()).is(r0)); |
| (...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4302 | 4245 |
| 4303 // Name is always in r2. | 4246 // Name is always in r2. |
| 4304 __ mov(r2, Operand(instr->name())); | 4247 __ mov(r2, Operand(instr->name())); |
| 4305 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) | 4248 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) |
| 4306 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 4249 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
| 4307 : isolate()->builtins()->StoreIC_Initialize(); | 4250 : isolate()->builtins()->StoreIC_Initialize(); |
| 4308 CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); | 4251 CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); |
| 4309 } | 4252 } |
| 4310 | 4253 |
| 4311 | 4254 |
| 4312 void LCodeGen::ApplyCheckIf(Condition cc, LBoundsCheck* check) { | 4255 void LCodeGen::ApplyCheckIf(Condition condition, LBoundsCheck* check) { |
| 4313 if (FLAG_debug_code && check->hydrogen()->skip_check()) { | 4256 if (FLAG_debug_code && check->hydrogen()->skip_check()) { |
| 4314 Label done; | 4257 Label done; |
| 4315 __ b(NegateCondition(cc), &done); | 4258 __ b(NegateCondition(condition), &done); |
| 4316 __ stop("eliminated bounds check failed"); | 4259 __ stop("eliminated bounds check failed"); |
| 4317 __ bind(&done); | 4260 __ bind(&done); |
| 4318 } else { | 4261 } else { |
| 4319 DeoptimizeIf(cc, check->environment()); | 4262 DeoptimizeIf(condition, check->environment()); |
| 4320 } | 4263 } |
| 4321 } | 4264 } |
| 4322 | 4265 |
| 4323 | 4266 |
| 4324 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { | 4267 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { |
| 4325 if (instr->hydrogen()->skip_check()) return; | 4268 if (instr->hydrogen()->skip_check()) return; |
| 4326 | 4269 |
| 4327 if (instr->index()->IsConstantOperand()) { | 4270 if (instr->index()->IsConstantOperand()) { |
| 4328 int constant_index = | 4271 int constant_index = |
| 4329 ToInteger32(LConstantOperand::cast(instr->index())); | 4272 ToInteger32(LConstantOperand::cast(instr->index())); |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4540 __ b(ne, ¬_applicable); | 4483 __ b(ne, ¬_applicable); |
| 4541 | 4484 |
| 4542 if (IsSimpleMapChangeTransition(from_kind, to_kind)) { | 4485 if (IsSimpleMapChangeTransition(from_kind, to_kind)) { |
| 4543 Register new_map_reg = ToRegister(instr->new_map_temp()); | 4486 Register new_map_reg = ToRegister(instr->new_map_temp()); |
| 4544 __ mov(new_map_reg, Operand(to_map)); | 4487 __ mov(new_map_reg, Operand(to_map)); |
| 4545 __ str(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset)); | 4488 __ str(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset)); |
| 4546 // Write barrier. | 4489 // Write barrier. |
| 4547 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, | 4490 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, |
| 4548 scratch, GetLinkRegisterState(), kDontSaveFPRegs); | 4491 scratch, GetLinkRegisterState(), kDontSaveFPRegs); |
| 4549 } else { | 4492 } else { |
| 4550 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 4493 PushSafepointRegistersScope scope( |
| 4494 this, Safepoint::kWithRegistersAndDoubles); |
| 4551 __ Move(r0, object_reg); | 4495 __ Move(r0, object_reg); |
| 4552 __ Move(r1, to_map); | 4496 __ Move(r1, to_map); |
| 4553 TransitionElementsKindStub stub(from_kind, to_kind); | 4497 TransitionElementsKindStub stub(from_kind, to_kind); |
| 4554 __ CallStub(&stub); | 4498 __ CallStub(&stub); |
| 4555 RecordSafepointWithRegisters( | 4499 RecordSafepointWithRegistersAndDoubles( |
| 4556 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); | 4500 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); |
| 4557 } | 4501 } |
| 4558 __ bind(¬_applicable); | 4502 __ bind(¬_applicable); |
| 4559 } | 4503 } |
| 4560 | 4504 |
| 4561 | 4505 |
| 4562 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { | 4506 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { |
| 4563 Register object = ToRegister(instr->object()); | 4507 Register object = ToRegister(instr->object()); |
| 4564 Register temp = ToRegister(instr->temp()); | 4508 Register temp = ToRegister(instr->temp()); |
| 4565 __ TestJSArrayForAllocationMemento(object, temp); | 4509 __ TestJSArrayForAllocationMemento(object, temp); |
| 4566 DeoptimizeIf(eq, instr->environment()); | 4510 DeoptimizeIf(eq, instr->environment()); |
| 4567 } | 4511 } |
| 4568 | 4512 |
| 4569 | 4513 |
| 4570 void LCodeGen::DoStringAdd(LStringAdd* instr) { | 4514 void LCodeGen::DoStringAdd(LStringAdd* instr) { |
| 4571 __ push(ToRegister(instr->left())); | 4515 __ push(ToRegister(instr->left())); |
| 4572 __ push(ToRegister(instr->right())); | 4516 __ push(ToRegister(instr->right())); |
| 4573 StringAddStub stub(instr->hydrogen()->flags()); | 4517 StringAddStub stub(instr->hydrogen()->flags()); |
| 4574 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 4518 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 4575 } | 4519 } |
| 4576 | 4520 |
| 4577 | 4521 |
| 4578 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { | 4522 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { |
| 4579 class DeferredStringCharCodeAt: public LDeferredCode { | 4523 class DeferredStringCharCodeAt V8_FINAL : public LDeferredCode { |
| 4580 public: | 4524 public: |
| 4581 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) | 4525 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) |
| 4582 : LDeferredCode(codegen), instr_(instr) { } | 4526 : LDeferredCode(codegen), instr_(instr) { } |
| 4583 virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); } | 4527 virtual void Generate() V8_OVERRIDE { |
| 4584 virtual LInstruction* instr() { return instr_; } | 4528 codegen()->DoDeferredStringCharCodeAt(instr_); |
| 4529 } |
| 4530 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 4585 private: | 4531 private: |
| 4586 LStringCharCodeAt* instr_; | 4532 LStringCharCodeAt* instr_; |
| 4587 }; | 4533 }; |
| 4588 | 4534 |
| 4589 DeferredStringCharCodeAt* deferred = | 4535 DeferredStringCharCodeAt* deferred = |
| 4590 new(zone()) DeferredStringCharCodeAt(this, instr); | 4536 new(zone()) DeferredStringCharCodeAt(this, instr); |
| 4591 | 4537 |
| 4592 StringCharLoadGenerator::Generate(masm(), | 4538 StringCharLoadGenerator::Generate(masm(), |
| 4593 ToRegister(instr->string()), | 4539 ToRegister(instr->string()), |
| 4594 ToRegister(instr->index()), | 4540 ToRegister(instr->index()), |
| (...skipping 27 matching lines...) Expand all Loading... |
| 4622 __ push(index); | 4568 __ push(index); |
| 4623 } | 4569 } |
| 4624 CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, instr); | 4570 CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, instr); |
| 4625 __ AssertSmi(r0); | 4571 __ AssertSmi(r0); |
| 4626 __ SmiUntag(r0); | 4572 __ SmiUntag(r0); |
| 4627 __ StoreToSafepointRegisterSlot(r0, result); | 4573 __ StoreToSafepointRegisterSlot(r0, result); |
| 4628 } | 4574 } |
| 4629 | 4575 |
| 4630 | 4576 |
| 4631 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { | 4577 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { |
| 4632 class DeferredStringCharFromCode: public LDeferredCode { | 4578 class DeferredStringCharFromCode V8_FINAL : public LDeferredCode { |
| 4633 public: | 4579 public: |
| 4634 DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr) | 4580 DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr) |
| 4635 : LDeferredCode(codegen), instr_(instr) { } | 4581 : LDeferredCode(codegen), instr_(instr) { } |
| 4636 virtual void Generate() { codegen()->DoDeferredStringCharFromCode(instr_); } | 4582 virtual void Generate() V8_OVERRIDE { |
| 4637 virtual LInstruction* instr() { return instr_; } | 4583 codegen()->DoDeferredStringCharFromCode(instr_); |
| 4584 } |
| 4585 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 4638 private: | 4586 private: |
| 4639 LStringCharFromCode* instr_; | 4587 LStringCharFromCode* instr_; |
| 4640 }; | 4588 }; |
| 4641 | 4589 |
| 4642 DeferredStringCharFromCode* deferred = | 4590 DeferredStringCharFromCode* deferred = |
| 4643 new(zone()) DeferredStringCharFromCode(this, instr); | 4591 new(zone()) DeferredStringCharFromCode(this, instr); |
| 4644 | 4592 |
| 4645 ASSERT(instr->hydrogen()->value()->representation().IsInteger32()); | 4593 ASSERT(instr->hydrogen()->value()->representation().IsInteger32()); |
| 4646 Register char_code = ToRegister(instr->char_code()); | 4594 Register char_code = ToRegister(instr->char_code()); |
| 4647 Register result = ToRegister(instr->result()); | 4595 Register result = ToRegister(instr->result()); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4710 LOperand* input = instr->value(); | 4658 LOperand* input = instr->value(); |
| 4711 LOperand* output = instr->result(); | 4659 LOperand* output = instr->result(); |
| 4712 | 4660 |
| 4713 SwVfpRegister flt_scratch = double_scratch0().low(); | 4661 SwVfpRegister flt_scratch = double_scratch0().low(); |
| 4714 __ vmov(flt_scratch, ToRegister(input)); | 4662 __ vmov(flt_scratch, ToRegister(input)); |
| 4715 __ vcvt_f64_u32(ToDoubleRegister(output), flt_scratch); | 4663 __ vcvt_f64_u32(ToDoubleRegister(output), flt_scratch); |
| 4716 } | 4664 } |
| 4717 | 4665 |
| 4718 | 4666 |
| 4719 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { | 4667 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { |
| 4720 class DeferredNumberTagI: public LDeferredCode { | 4668 class DeferredNumberTagI V8_FINAL : public LDeferredCode { |
| 4721 public: | 4669 public: |
| 4722 DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) | 4670 DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) |
| 4723 : LDeferredCode(codegen), instr_(instr) { } | 4671 : LDeferredCode(codegen), instr_(instr) { } |
| 4724 virtual void Generate() { | 4672 virtual void Generate() V8_OVERRIDE { |
| 4725 codegen()->DoDeferredNumberTagI(instr_, | 4673 codegen()->DoDeferredNumberTagI(instr_, |
| 4726 instr_->value(), | 4674 instr_->value(), |
| 4727 SIGNED_INT32); | 4675 SIGNED_INT32); |
| 4728 } | 4676 } |
| 4729 virtual LInstruction* instr() { return instr_; } | 4677 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 4730 private: | 4678 private: |
| 4731 LNumberTagI* instr_; | 4679 LNumberTagI* instr_; |
| 4732 }; | 4680 }; |
| 4733 | 4681 |
| 4734 Register src = ToRegister(instr->value()); | 4682 Register src = ToRegister(instr->value()); |
| 4735 Register dst = ToRegister(instr->result()); | 4683 Register dst = ToRegister(instr->result()); |
| 4736 | 4684 |
| 4737 DeferredNumberTagI* deferred = new(zone()) DeferredNumberTagI(this, instr); | 4685 DeferredNumberTagI* deferred = new(zone()) DeferredNumberTagI(this, instr); |
| 4738 __ SmiTag(dst, src, SetCC); | 4686 __ SmiTag(dst, src, SetCC); |
| 4739 __ b(vs, deferred->entry()); | 4687 __ b(vs, deferred->entry()); |
| 4740 __ bind(deferred->exit()); | 4688 __ bind(deferred->exit()); |
| 4741 } | 4689 } |
| 4742 | 4690 |
| 4743 | 4691 |
| 4744 void LCodeGen::DoNumberTagU(LNumberTagU* instr) { | 4692 void LCodeGen::DoNumberTagU(LNumberTagU* instr) { |
| 4745 class DeferredNumberTagU: public LDeferredCode { | 4693 class DeferredNumberTagU V8_FINAL : public LDeferredCode { |
| 4746 public: | 4694 public: |
| 4747 DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr) | 4695 DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr) |
| 4748 : LDeferredCode(codegen), instr_(instr) { } | 4696 : LDeferredCode(codegen), instr_(instr) { } |
| 4749 virtual void Generate() { | 4697 virtual void Generate() V8_OVERRIDE { |
| 4750 codegen()->DoDeferredNumberTagI(instr_, | 4698 codegen()->DoDeferredNumberTagI(instr_, |
| 4751 instr_->value(), | 4699 instr_->value(), |
| 4752 UNSIGNED_INT32); | 4700 UNSIGNED_INT32); |
| 4753 } | 4701 } |
| 4754 virtual LInstruction* instr() { return instr_; } | 4702 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 4755 private: | 4703 private: |
| 4756 LNumberTagU* instr_; | 4704 LNumberTagU* instr_; |
| 4757 }; | 4705 }; |
| 4758 | 4706 |
| 4759 LOperand* input = instr->value(); | 4707 LOperand* input = instr->value(); |
| 4760 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 4708 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
| 4761 Register reg = ToRegister(input); | 4709 Register reg = ToRegister(input); |
| 4762 | 4710 |
| 4763 DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr); | 4711 DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr); |
| 4764 __ cmp(reg, Operand(Smi::kMaxValue)); | 4712 __ cmp(reg, Operand(Smi::kMaxValue)); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4817 // Done. Put the value in dbl_scratch into the value of the allocated heap | 4765 // Done. Put the value in dbl_scratch into the value of the allocated heap |
| 4818 // number. | 4766 // number. |
| 4819 __ bind(&done); | 4767 __ bind(&done); |
| 4820 __ vstr(dbl_scratch, dst, HeapNumber::kValueOffset); | 4768 __ vstr(dbl_scratch, dst, HeapNumber::kValueOffset); |
| 4821 __ add(dst, dst, Operand(kHeapObjectTag)); | 4769 __ add(dst, dst, Operand(kHeapObjectTag)); |
| 4822 __ StoreToSafepointRegisterSlot(dst, dst); | 4770 __ StoreToSafepointRegisterSlot(dst, dst); |
| 4823 } | 4771 } |
| 4824 | 4772 |
| 4825 | 4773 |
| 4826 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { | 4774 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { |
| 4827 class DeferredNumberTagD: public LDeferredCode { | 4775 class DeferredNumberTagD V8_FINAL : public LDeferredCode { |
| 4828 public: | 4776 public: |
| 4829 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) | 4777 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) |
| 4830 : LDeferredCode(codegen), instr_(instr) { } | 4778 : LDeferredCode(codegen), instr_(instr) { } |
| 4831 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } | 4779 virtual void Generate() V8_OVERRIDE { |
| 4832 virtual LInstruction* instr() { return instr_; } | 4780 codegen()->DoDeferredNumberTagD(instr_); |
| 4781 } |
| 4782 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 4833 private: | 4783 private: |
| 4834 LNumberTagD* instr_; | 4784 LNumberTagD* instr_; |
| 4835 }; | 4785 }; |
| 4836 | 4786 |
| 4837 DwVfpRegister input_reg = ToDoubleRegister(instr->value()); | 4787 DwVfpRegister input_reg = ToDoubleRegister(instr->value()); |
| 4838 Register scratch = scratch0(); | 4788 Register scratch = scratch0(); |
| 4839 Register reg = ToRegister(instr->result()); | 4789 Register reg = ToRegister(instr->result()); |
| 4840 Register temp1 = ToRegister(instr->temp()); | 4790 Register temp1 = ToRegister(instr->temp()); |
| 4841 Register temp2 = ToRegister(instr->temp2()); | 4791 Register temp2 = ToRegister(instr->temp2()); |
| 4842 | 4792 |
| 4843 bool convert_hole = false; | |
| 4844 HValue* change_input = instr->hydrogen()->value(); | |
| 4845 if (change_input->IsLoadKeyed()) { | |
| 4846 HLoadKeyed* load = HLoadKeyed::cast(change_input); | |
| 4847 convert_hole = load->UsesMustHandleHole(); | |
| 4848 } | |
| 4849 | |
| 4850 Label no_special_nan_handling; | |
| 4851 Label done; | |
| 4852 if (convert_hole) { | |
| 4853 DwVfpRegister input_reg = ToDoubleRegister(instr->value()); | |
| 4854 __ VFPCompareAndSetFlags(input_reg, input_reg); | |
| 4855 __ b(vc, &no_special_nan_handling); | |
| 4856 __ VmovHigh(scratch, input_reg); | |
| 4857 __ cmp(scratch, Operand(kHoleNanUpper32)); | |
| 4858 // If not the hole NaN, force the NaN to be canonical. | |
| 4859 __ VFPCanonicalizeNaN(input_reg, ne); | |
| 4860 __ b(ne, &no_special_nan_handling); | |
| 4861 __ Move(reg, factory()->the_hole_value()); | |
| 4862 __ b(&done); | |
| 4863 } | |
| 4864 | |
| 4865 __ bind(&no_special_nan_handling); | |
| 4866 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); | 4793 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); |
| 4867 if (FLAG_inline_new) { | 4794 if (FLAG_inline_new) { |
| 4868 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); | 4795 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); |
| 4869 // We want the untagged address first for performance | 4796 // We want the untagged address first for performance |
| 4870 __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry(), | 4797 __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry(), |
| 4871 DONT_TAG_RESULT); | 4798 DONT_TAG_RESULT); |
| 4872 } else { | 4799 } else { |
| 4873 __ jmp(deferred->entry()); | 4800 __ jmp(deferred->entry()); |
| 4874 } | 4801 } |
| 4875 __ bind(deferred->exit()); | 4802 __ bind(deferred->exit()); |
| 4876 __ vstr(input_reg, reg, HeapNumber::kValueOffset); | 4803 __ vstr(input_reg, reg, HeapNumber::kValueOffset); |
| 4877 // Now that we have finished with the object's real address tag it | 4804 // Now that we have finished with the object's real address tag it |
| 4878 __ add(reg, reg, Operand(kHeapObjectTag)); | 4805 __ add(reg, reg, Operand(kHeapObjectTag)); |
| 4879 __ bind(&done); | |
| 4880 } | 4806 } |
| 4881 | 4807 |
| 4882 | 4808 |
| 4883 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { | 4809 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
| 4884 // TODO(3095996): Get rid of this. For now, we need to make the | 4810 // TODO(3095996): Get rid of this. For now, we need to make the |
| 4885 // result register contain a valid pointer because it is already | 4811 // result register contain a valid pointer because it is already |
| 4886 // contained in the register pointer map. | 4812 // contained in the register pointer map. |
| 4887 Register reg = ToRegister(instr->result()); | 4813 Register reg = ToRegister(instr->result()); |
| 4888 __ mov(reg, Operand::Zero()); | 4814 __ mov(reg, Operand::Zero()); |
| 4889 | 4815 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 4909 __ SmiUntag(result, input, SetCC); | 4835 __ SmiUntag(result, input, SetCC); |
| 4910 DeoptimizeIf(cs, instr->environment()); | 4836 DeoptimizeIf(cs, instr->environment()); |
| 4911 } else { | 4837 } else { |
| 4912 __ SmiUntag(result, input); | 4838 __ SmiUntag(result, input); |
| 4913 } | 4839 } |
| 4914 } | 4840 } |
| 4915 | 4841 |
| 4916 | 4842 |
| 4917 void LCodeGen::EmitNumberUntagD(Register input_reg, | 4843 void LCodeGen::EmitNumberUntagD(Register input_reg, |
| 4918 DwVfpRegister result_reg, | 4844 DwVfpRegister result_reg, |
| 4919 bool allow_undefined_as_nan, | 4845 bool can_convert_undefined_to_nan, |
| 4920 bool deoptimize_on_minus_zero, | 4846 bool deoptimize_on_minus_zero, |
| 4921 LEnvironment* env, | 4847 LEnvironment* env, |
| 4922 NumberUntagDMode mode) { | 4848 NumberUntagDMode mode) { |
| 4923 Register scratch = scratch0(); | 4849 Register scratch = scratch0(); |
| 4924 SwVfpRegister flt_scratch = double_scratch0().low(); | 4850 SwVfpRegister flt_scratch = double_scratch0().low(); |
| 4925 ASSERT(!result_reg.is(double_scratch0())); | 4851 ASSERT(!result_reg.is(double_scratch0())); |
| 4926 | 4852 |
| 4927 Label load_smi, heap_number, done; | 4853 Label load_smi, heap_number, done; |
| 4928 | 4854 |
| 4929 STATIC_ASSERT(NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE > | 4855 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { |
| 4930 NUMBER_CANDIDATE_IS_ANY_TAGGED); | |
| 4931 if (mode >= NUMBER_CANDIDATE_IS_ANY_TAGGED) { | |
| 4932 // Smi check. | 4856 // Smi check. |
| 4933 __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi); | 4857 __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi); |
| 4934 | 4858 |
| 4935 // Heap number map check. | 4859 // Heap number map check. |
| 4936 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 4860 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
| 4937 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 4861 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
| 4938 __ cmp(scratch, Operand(ip)); | 4862 __ cmp(scratch, Operand(ip)); |
| 4939 if (!allow_undefined_as_nan) { | 4863 if (!can_convert_undefined_to_nan) { |
| 4940 DeoptimizeIf(ne, env); | 4864 DeoptimizeIf(ne, env); |
| 4941 } else { | 4865 } else { |
| 4942 Label heap_number, convert; | 4866 Label heap_number, convert; |
| 4943 __ b(eq, &heap_number); | 4867 __ b(eq, &heap_number); |
| 4944 | 4868 |
| 4945 // Convert undefined (and hole) to NaN. | 4869 // Convert undefined (and hole) to NaN. |
| 4946 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 4870 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
| 4947 __ cmp(input_reg, Operand(ip)); | 4871 __ cmp(input_reg, Operand(ip)); |
| 4948 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE) { | |
| 4949 __ b(eq, &convert); | |
| 4950 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | |
| 4951 __ cmp(input_reg, Operand(ip)); | |
| 4952 } | |
| 4953 DeoptimizeIf(ne, env); | 4872 DeoptimizeIf(ne, env); |
| 4954 | 4873 |
| 4955 __ bind(&convert); | 4874 __ bind(&convert); |
| 4956 __ LoadRoot(scratch, Heap::kNanValueRootIndex); | 4875 __ LoadRoot(scratch, Heap::kNanValueRootIndex); |
| 4957 __ vldr(result_reg, scratch, HeapNumber::kValueOffset - kHeapObjectTag); | 4876 __ vldr(result_reg, scratch, HeapNumber::kValueOffset - kHeapObjectTag); |
| 4958 __ jmp(&done); | 4877 __ jmp(&done); |
| 4959 | 4878 |
| 4960 __ bind(&heap_number); | 4879 __ bind(&heap_number); |
| 4961 } | 4880 } |
| 4962 // Heap number to double register conversion. | 4881 // Heap number to double register conversion. |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5046 __ VmovHigh(scratch1, double_scratch2); | 4965 __ VmovHigh(scratch1, double_scratch2); |
| 5047 __ tst(scratch1, Operand(HeapNumber::kSignMask)); | 4966 __ tst(scratch1, Operand(HeapNumber::kSignMask)); |
| 5048 DeoptimizeIf(ne, instr->environment()); | 4967 DeoptimizeIf(ne, instr->environment()); |
| 5049 } | 4968 } |
| 5050 } | 4969 } |
| 5051 __ bind(&done); | 4970 __ bind(&done); |
| 5052 } | 4971 } |
| 5053 | 4972 |
| 5054 | 4973 |
| 5055 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { | 4974 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { |
| 5056 class DeferredTaggedToI: public LDeferredCode { | 4975 class DeferredTaggedToI V8_FINAL : public LDeferredCode { |
| 5057 public: | 4976 public: |
| 5058 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) | 4977 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) |
| 5059 : LDeferredCode(codegen), instr_(instr) { } | 4978 : LDeferredCode(codegen), instr_(instr) { } |
| 5060 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } | 4979 virtual void Generate() V8_OVERRIDE { |
| 5061 virtual LInstruction* instr() { return instr_; } | 4980 codegen()->DoDeferredTaggedToI(instr_); |
| 4981 } |
| 4982 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 5062 private: | 4983 private: |
| 5063 LTaggedToI* instr_; | 4984 LTaggedToI* instr_; |
| 5064 }; | 4985 }; |
| 5065 | 4986 |
| 5066 LOperand* input = instr->value(); | 4987 LOperand* input = instr->value(); |
| 5067 ASSERT(input->IsRegister()); | 4988 ASSERT(input->IsRegister()); |
| 5068 ASSERT(input->Equals(instr->result())); | 4989 ASSERT(input->Equals(instr->result())); |
| 5069 | 4990 |
| 5070 Register input_reg = ToRegister(input); | 4991 Register input_reg = ToRegister(input); |
| 5071 | 4992 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 5083 | 5004 |
| 5084 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { | 5005 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { |
| 5085 LOperand* input = instr->value(); | 5006 LOperand* input = instr->value(); |
| 5086 ASSERT(input->IsRegister()); | 5007 ASSERT(input->IsRegister()); |
| 5087 LOperand* result = instr->result(); | 5008 LOperand* result = instr->result(); |
| 5088 ASSERT(result->IsDoubleRegister()); | 5009 ASSERT(result->IsDoubleRegister()); |
| 5089 | 5010 |
| 5090 Register input_reg = ToRegister(input); | 5011 Register input_reg = ToRegister(input); |
| 5091 DwVfpRegister result_reg = ToDoubleRegister(result); | 5012 DwVfpRegister result_reg = ToDoubleRegister(result); |
| 5092 | 5013 |
| 5093 NumberUntagDMode mode = NUMBER_CANDIDATE_IS_ANY_TAGGED; | |
| 5094 HValue* value = instr->hydrogen()->value(); | 5014 HValue* value = instr->hydrogen()->value(); |
| 5095 if (value->type().IsSmi()) { | 5015 NumberUntagDMode mode = value->representation().IsSmi() |
| 5096 mode = NUMBER_CANDIDATE_IS_SMI; | 5016 ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED; |
| 5097 } else if (value->IsLoadKeyed()) { | |
| 5098 HLoadKeyed* load = HLoadKeyed::cast(value); | |
| 5099 if (load->UsesMustHandleHole()) { | |
| 5100 if (load->hole_mode() == ALLOW_RETURN_HOLE) { | |
| 5101 mode = NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE; | |
| 5102 } | |
| 5103 } | |
| 5104 } | |
| 5105 | 5017 |
| 5106 EmitNumberUntagD(input_reg, result_reg, | 5018 EmitNumberUntagD(input_reg, result_reg, |
| 5107 instr->hydrogen()->allow_undefined_as_nan(), | 5019 instr->hydrogen()->can_convert_undefined_to_nan(), |
| 5108 instr->hydrogen()->deoptimize_on_minus_zero(), | 5020 instr->hydrogen()->deoptimize_on_minus_zero(), |
| 5109 instr->environment(), | 5021 instr->environment(), |
| 5110 mode); | 5022 mode); |
| 5111 } | 5023 } |
| 5112 | 5024 |
| 5113 | 5025 |
| 5114 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { | 5026 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { |
| 5115 Register result_reg = ToRegister(instr->result()); | 5027 Register result_reg = ToRegister(instr->result()); |
| 5116 Register scratch1 = scratch0(); | 5028 Register scratch1 = scratch0(); |
| 5117 Register scratch2 = ToRegister(instr->temp()); | 5029 Register scratch2 = ToRegister(instr->temp()); |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5227 } | 5139 } |
| 5228 } | 5140 } |
| 5229 | 5141 |
| 5230 | 5142 |
| 5231 void LCodeGen::DoCheckFunction(LCheckFunction* instr) { | 5143 void LCodeGen::DoCheckFunction(LCheckFunction* instr) { |
| 5232 Register reg = ToRegister(instr->value()); | 5144 Register reg = ToRegister(instr->value()); |
| 5233 Handle<JSFunction> target = instr->hydrogen()->target(); | 5145 Handle<JSFunction> target = instr->hydrogen()->target(); |
| 5234 AllowDeferredHandleDereference smi_check; | 5146 AllowDeferredHandleDereference smi_check; |
| 5235 if (isolate()->heap()->InNewSpace(*target)) { | 5147 if (isolate()->heap()->InNewSpace(*target)) { |
| 5236 Register reg = ToRegister(instr->value()); | 5148 Register reg = ToRegister(instr->value()); |
| 5237 Handle<Cell> cell = isolate()->factory()->NewPropertyCell(target); | 5149 Handle<Cell> cell = isolate()->factory()->NewCell(target); |
| 5238 __ mov(ip, Operand(Handle<Object>(cell))); | 5150 __ mov(ip, Operand(Handle<Object>(cell))); |
| 5239 __ ldr(ip, FieldMemOperand(ip, Cell::kValueOffset)); | 5151 __ ldr(ip, FieldMemOperand(ip, Cell::kValueOffset)); |
| 5240 __ cmp(reg, ip); | 5152 __ cmp(reg, ip); |
| 5241 } else { | 5153 } else { |
| 5242 __ cmp(reg, Operand(target)); | 5154 __ cmp(reg, Operand(target)); |
| 5243 } | 5155 } |
| 5244 DeoptimizeIf(ne, instr->environment()); | 5156 DeoptimizeIf(ne, instr->environment()); |
| 5245 } | 5157 } |
| 5246 | 5158 |
| 5247 | 5159 |
| 5248 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { | 5160 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { |
| 5249 { | 5161 { |
| 5250 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 5162 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
| 5251 __ push(object); | 5163 __ push(object); |
| 5252 CallRuntimeFromDeferred(Runtime::kMigrateInstance, 1, instr); | 5164 CallRuntimeFromDeferred(Runtime::kMigrateInstance, 1, instr); |
| 5253 __ StoreToSafepointRegisterSlot(r0, scratch0()); | 5165 __ StoreToSafepointRegisterSlot(r0, scratch0()); |
| 5254 } | 5166 } |
| 5255 __ tst(scratch0(), Operand(kSmiTagMask)); | 5167 __ tst(scratch0(), Operand(kSmiTagMask)); |
| 5256 DeoptimizeIf(eq, instr->environment()); | 5168 DeoptimizeIf(eq, instr->environment()); |
| 5257 } | 5169 } |
| 5258 | 5170 |
| 5259 | 5171 |
| 5260 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { | 5172 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { |
| 5261 class DeferredCheckMaps: public LDeferredCode { | 5173 class DeferredCheckMaps V8_FINAL : public LDeferredCode { |
| 5262 public: | 5174 public: |
| 5263 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object) | 5175 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object) |
| 5264 : LDeferredCode(codegen), instr_(instr), object_(object) { | 5176 : LDeferredCode(codegen), instr_(instr), object_(object) { |
| 5265 SetExit(check_maps()); | 5177 SetExit(check_maps()); |
| 5266 } | 5178 } |
| 5267 virtual void Generate() { | 5179 virtual void Generate() V8_OVERRIDE { |
| 5268 codegen()->DoDeferredInstanceMigration(instr_, object_); | 5180 codegen()->DoDeferredInstanceMigration(instr_, object_); |
| 5269 } | 5181 } |
| 5270 Label* check_maps() { return &check_maps_; } | 5182 Label* check_maps() { return &check_maps_; } |
| 5271 virtual LInstruction* instr() { return instr_; } | 5183 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 5272 private: | 5184 private: |
| 5273 LCheckMaps* instr_; | 5185 LCheckMaps* instr_; |
| 5274 Label check_maps_; | 5186 Label check_maps_; |
| 5275 Register object_; | 5187 Register object_; |
| 5276 }; | 5188 }; |
| 5277 | 5189 |
| 5278 if (instr->hydrogen()->CanOmitMapChecks()) return; | 5190 if (instr->hydrogen()->CanOmitMapChecks()) return; |
| 5279 Register map_reg = scratch0(); | 5191 Register map_reg = scratch0(); |
| 5280 | 5192 |
| 5281 LOperand* input = instr->value(); | 5193 LOperand* input = instr->value(); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5354 | 5266 |
| 5355 // smi | 5267 // smi |
| 5356 __ bind(&is_smi); | 5268 __ bind(&is_smi); |
| 5357 __ ClampUint8(result_reg, result_reg); | 5269 __ ClampUint8(result_reg, result_reg); |
| 5358 | 5270 |
| 5359 __ bind(&done); | 5271 __ bind(&done); |
| 5360 } | 5272 } |
| 5361 | 5273 |
| 5362 | 5274 |
| 5363 void LCodeGen::DoAllocate(LAllocate* instr) { | 5275 void LCodeGen::DoAllocate(LAllocate* instr) { |
| 5364 class DeferredAllocate: public LDeferredCode { | 5276 class DeferredAllocate V8_FINAL : public LDeferredCode { |
| 5365 public: | 5277 public: |
| 5366 DeferredAllocate(LCodeGen* codegen, LAllocate* instr) | 5278 DeferredAllocate(LCodeGen* codegen, LAllocate* instr) |
| 5367 : LDeferredCode(codegen), instr_(instr) { } | 5279 : LDeferredCode(codegen), instr_(instr) { } |
| 5368 virtual void Generate() { codegen()->DoDeferredAllocate(instr_); } | 5280 virtual void Generate() V8_OVERRIDE { |
| 5369 virtual LInstruction* instr() { return instr_; } | 5281 codegen()->DoDeferredAllocate(instr_); |
| 5282 } |
| 5283 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 5370 private: | 5284 private: |
| 5371 LAllocate* instr_; | 5285 LAllocate* instr_; |
| 5372 }; | 5286 }; |
| 5373 | 5287 |
| 5374 DeferredAllocate* deferred = | 5288 DeferredAllocate* deferred = |
| 5375 new(zone()) DeferredAllocate(this, instr); | 5289 new(zone()) DeferredAllocate(this, instr); |
| 5376 | 5290 |
| 5377 Register result = ToRegister(instr->result()); | 5291 Register result = ToRegister(instr->result()); |
| 5378 Register scratch = ToRegister(instr->temp1()); | 5292 Register scratch = ToRegister(instr->temp1()); |
| 5379 Register scratch2 = ToRegister(instr->temp2()); | 5293 Register scratch2 = ToRegister(instr->temp2()); |
| (...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5687 | 5601 |
| 5688 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { | 5602 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { |
| 5689 Deoptimizer::BailoutType type = instr->hydrogen()->type(); | 5603 Deoptimizer::BailoutType type = instr->hydrogen()->type(); |
| 5690 // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the | 5604 // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the |
| 5691 // needed return address), even though the implementation of LAZY and EAGER is | 5605 // needed return address), even though the implementation of LAZY and EAGER is |
| 5692 // now identical. When LAZY is eventually completely folded into EAGER, remove | 5606 // now identical. When LAZY is eventually completely folded into EAGER, remove |
| 5693 // the special case below. | 5607 // the special case below. |
| 5694 if (info()->IsStub() && type == Deoptimizer::EAGER) { | 5608 if (info()->IsStub() && type == Deoptimizer::EAGER) { |
| 5695 type = Deoptimizer::LAZY; | 5609 type = Deoptimizer::LAZY; |
| 5696 } | 5610 } |
| 5611 |
| 5612 Comment(";;; deoptimize: %s", instr->hydrogen()->reason()); |
| 5697 DeoptimizeIf(al, instr->environment(), type); | 5613 DeoptimizeIf(al, instr->environment(), type); |
| 5698 } | 5614 } |
| 5699 | 5615 |
| 5700 | 5616 |
| 5701 void LCodeGen::DoDummyUse(LDummyUse* instr) { | 5617 void LCodeGen::DoDummyUse(LDummyUse* instr) { |
| 5702 // Nothing to see here, move on! | 5618 // Nothing to see here, move on! |
| 5703 } | 5619 } |
| 5704 | 5620 |
| 5705 | 5621 |
| 5706 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { | 5622 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { |
| 5707 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 5623 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
| 5708 __ CallRuntimeSaveDoubles(Runtime::kStackGuard); | 5624 __ CallRuntimeSaveDoubles(Runtime::kStackGuard); |
| 5709 RecordSafepointWithLazyDeopt( | 5625 RecordSafepointWithLazyDeopt( |
| 5710 instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); | 5626 instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); |
| 5711 ASSERT(instr->HasEnvironment()); | 5627 ASSERT(instr->HasEnvironment()); |
| 5712 LEnvironment* env = instr->environment(); | 5628 LEnvironment* env = instr->environment(); |
| 5713 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 5629 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
| 5714 } | 5630 } |
| 5715 | 5631 |
| 5716 | 5632 |
| 5717 void LCodeGen::DoStackCheck(LStackCheck* instr) { | 5633 void LCodeGen::DoStackCheck(LStackCheck* instr) { |
| 5718 class DeferredStackCheck: public LDeferredCode { | 5634 class DeferredStackCheck V8_FINAL : public LDeferredCode { |
| 5719 public: | 5635 public: |
| 5720 DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr) | 5636 DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr) |
| 5721 : LDeferredCode(codegen), instr_(instr) { } | 5637 : LDeferredCode(codegen), instr_(instr) { } |
| 5722 virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); } | 5638 virtual void Generate() V8_OVERRIDE { |
| 5723 virtual LInstruction* instr() { return instr_; } | 5639 codegen()->DoDeferredStackCheck(instr_); |
| 5640 } |
| 5641 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 5724 private: | 5642 private: |
| 5725 LStackCheck* instr_; | 5643 LStackCheck* instr_; |
| 5726 }; | 5644 }; |
| 5727 | 5645 |
| 5728 ASSERT(instr->HasEnvironment()); | 5646 ASSERT(instr->HasEnvironment()); |
| 5729 LEnvironment* env = instr->environment(); | 5647 LEnvironment* env = instr->environment(); |
| 5730 // There is no LLazyBailout instruction for stack-checks. We have to | 5648 // There is no LLazyBailout instruction for stack-checks. We have to |
| 5731 // prepare for lazy deoptimization explicitly here. | 5649 // prepare for lazy deoptimization explicitly here. |
| 5732 if (instr->hydrogen()->is_function_entry()) { | 5650 if (instr->hydrogen()->is_function_entry()) { |
| 5733 // Perform stack overflow check. | 5651 // Perform stack overflow check. |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5870 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); | 5788 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); |
| 5871 __ ldr(result, FieldMemOperand(scratch, | 5789 __ ldr(result, FieldMemOperand(scratch, |
| 5872 FixedArray::kHeaderSize - kPointerSize)); | 5790 FixedArray::kHeaderSize - kPointerSize)); |
| 5873 __ bind(&done); | 5791 __ bind(&done); |
| 5874 } | 5792 } |
| 5875 | 5793 |
| 5876 | 5794 |
| 5877 #undef __ | 5795 #undef __ |
| 5878 | 5796 |
| 5879 } } // namespace v8::internal | 5797 } } // namespace v8::internal |
| OLD | NEW |