Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(97)

Side by Side Diff: src/arm/lithium-codegen-arm.cc

Issue 148573005: A64: Synchronize with r16249. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/arm/lithium-codegen-arm.h ('k') | src/arm/lithium-gap-resolver-arm.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
4540 __ b(ne, &not_applicable); 4483 __ b(ne, &not_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(&not_applicable); 4502 __ bind(&not_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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/arm/lithium-codegen-arm.h ('k') | src/arm/lithium-gap-resolver-arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698