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

Side by Side Diff: src/x64/codegen-x64.cc

Issue 2087009: Custom call IC-s for String.prototype.{charAt,charCodeAt}. (Closed)
Patch Set: ARM port. Created 10 years, 7 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
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 25 matching lines...) Expand all
36 #include "ic-inl.h" 36 #include "ic-inl.h"
37 #include "parser.h" 37 #include "parser.h"
38 #include "regexp-macro-assembler.h" 38 #include "regexp-macro-assembler.h"
39 #include "register-allocator-inl.h" 39 #include "register-allocator-inl.h"
40 #include "scopes.h" 40 #include "scopes.h"
41 #include "virtual-frame-inl.h" 41 #include "virtual-frame-inl.h"
42 42
43 namespace v8 { 43 namespace v8 {
44 namespace internal { 44 namespace internal {
45 45
46 #define __ ACCESS_MASM(masm_) 46 #define __ ACCESS_MASM(masm)
47 47
48 // ------------------------------------------------------------------------- 48 // -------------------------------------------------------------------------
49 // Platform-specific DeferredCode functions. 49 // Platform-specific FrameRegisterState functions.
50 50
51 void DeferredCode::SaveRegisters() { 51 void FrameRegisterState::Save(MacroAssembler* masm) const {
52 for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) { 52 for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
53 int action = registers_[i]; 53 int action = registers_[i];
54 if (action == kPush) { 54 if (action == kPush) {
55 __ push(RegisterAllocator::ToRegister(i)); 55 __ push(RegisterAllocator::ToRegister(i));
56 } else if (action != kIgnore && (action & kSyncedFlag) == 0) { 56 } else if (action != kIgnore && (action & kSyncedFlag) == 0) {
57 __ movq(Operand(rbp, action), RegisterAllocator::ToRegister(i)); 57 __ movq(Operand(rbp, action), RegisterAllocator::ToRegister(i));
58 } 58 }
59 } 59 }
60 } 60 }
61 61
62 62
63 void DeferredCode::RestoreRegisters() { 63 void FrameRegisterState::Restore(MacroAssembler* masm) const {
64 // Restore registers in reverse order due to the stack. 64 // Restore registers in reverse order due to the stack.
65 for (int i = RegisterAllocator::kNumRegisters - 1; i >= 0; i--) { 65 for (int i = RegisterAllocator::kNumRegisters - 1; i >= 0; i--) {
66 int action = registers_[i]; 66 int action = registers_[i];
67 if (action == kPush) { 67 if (action == kPush) {
68 __ pop(RegisterAllocator::ToRegister(i)); 68 __ pop(RegisterAllocator::ToRegister(i));
69 } else if (action != kIgnore) { 69 } else if (action != kIgnore) {
70 action &= ~kSyncedFlag; 70 action &= ~kSyncedFlag;
71 __ movq(RegisterAllocator::ToRegister(i), Operand(rbp, action)); 71 __ movq(RegisterAllocator::ToRegister(i), Operand(rbp, action));
72 } 72 }
73 } 73 }
74 } 74 }
75 75
76 76
77 #undef __
78 #define __ ACCESS_MASM(masm_)
79
80 // -------------------------------------------------------------------------
81 // Platform-specific DeferredCode functions.
82
83 void DeferredCode::SaveRegisters() {
84 frame_state_.Save(masm_);
85 }
86
87
88 void DeferredCode::RestoreRegisters() {
89 frame_state_.Restore(masm_);
90 }
91
92
93 // -------------------------------------------------------------------------
94 // Platform-specific RuntimeCallHelper functions.
95
96 void VirtualFrameRuntimeCallHelper::BeforeCall(MacroAssembler* masm) const {
97 frame_state_->Save(masm);
98 }
99
100
101 void VirtualFrameRuntimeCallHelper::AfterCall(MacroAssembler* masm) const {
102 frame_state_->Restore(masm);
103 }
104
105
106 void ICRuntimeCallHelper::BeforeCall(MacroAssembler* masm) const {
107 masm->EnterInternalFrame();
108 }
109
110
111 void ICRuntimeCallHelper::AfterCall(MacroAssembler* masm) const {
112 masm->LeaveInternalFrame();
113 }
114
115
77 // ------------------------------------------------------------------------- 116 // -------------------------------------------------------------------------
78 // CodeGenState implementation. 117 // CodeGenState implementation.
79 118
80 CodeGenState::CodeGenState(CodeGenerator* owner) 119 CodeGenState::CodeGenState(CodeGenerator* owner)
81 : owner_(owner), 120 : owner_(owner),
82 destination_(NULL), 121 destination_(NULL),
83 previous_(NULL) { 122 previous_(NULL) {
84 owner_->set_state(this); 123 owner_->set_state(this);
85 } 124 }
86 125
(...skipping 3879 matching lines...) Expand 10 before | Expand all | Expand 10 after
3966 4005
3967 __ bind(&exit); 4006 __ bind(&exit);
3968 result.set_type_info(TypeInfo::Smi()); 4007 result.set_type_info(TypeInfo::Smi());
3969 if (FLAG_debug_code) { 4008 if (FLAG_debug_code) {
3970 __ AbortIfNotSmi(result.reg()); 4009 __ AbortIfNotSmi(result.reg());
3971 } 4010 }
3972 frame_->Push(&result); 4011 frame_->Push(&result);
3973 } 4012 }
3974 4013
3975 4014
3976 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) { 4015 class DeferredStringCharCodeAt : public DeferredCode {
3977 Comment(masm_, "[ GenerateFastCharCodeAt"); 4016 public:
4017 DeferredStringCharCodeAt(Register object,
4018 Register index,
4019 Register scratch,
4020 Register result)
4021 : result_(result),
4022 char_code_at_generator_(object,
4023 index,
4024 scratch,
4025 result,
4026 &need_conversion_,
4027 &need_conversion_,
4028 &index_out_of_range_,
4029 STRING_ANY_NUMBER_INDEX) {}
4030
4031 StringCharCodeAtGenerator* fast_case_generator() {
4032 return &char_code_at_generator_;
4033 }
4034
4035 virtual void Generate() {
4036 VirtualFrameRuntimeCallHelper call_helper(frame_state());
4037 char_code_at_generator_.GenerateSlow(masm(), call_helper);
4038
4039 __ bind(&need_conversion_);
4040 // Move the undefined value into the result register, which will
4041 // trigger conversion.
4042 __ LoadRoot(result_, Heap::kUndefinedValueRootIndex);
4043 __ jmp(exit_label());
4044
4045 __ bind(&index_out_of_range_);
4046 // When the index is out of range, the spec requires us to return
4047 // NaN.
4048 __ LoadRoot(result_, Heap::kNanValueRootIndex);
4049 __ jmp(exit_label());
4050 }
4051
4052 private:
4053 Register result_;
4054
4055 Label need_conversion_;
4056 Label index_out_of_range_;
4057
4058 StringCharCodeAtGenerator char_code_at_generator_;
4059 };
4060
4061
4062 // This generates code that performs a String.prototype.charCodeAt() call
4063 // or returns a smi in order to trigger conversion.
4064 void CodeGenerator::GenerateStringCharCodeAt(ZoneList<Expression*>* args) {
4065 Comment(masm_, "[ GenerateStringCharCodeAt");
3978 ASSERT(args->length() == 2); 4066 ASSERT(args->length() == 2);
3979 4067
3980 Load(args->at(0)); 4068 Load(args->at(0));
3981 Load(args->at(1)); 4069 Load(args->at(1));
3982 Result index = frame_->Pop(); 4070 Result index = frame_->Pop();
3983 Result object = frame_->Pop(); 4071 Result object = frame_->Pop();
3984
3985 // We will mutate the index register and possibly the object register.
3986 // The case where they are somehow the same register is handled
3987 // because we only mutate them in the case where the receiver is a
3988 // heap object and the index is not.
3989 object.ToRegister(); 4072 object.ToRegister();
3990 index.ToRegister(); 4073 index.ToRegister();
4074 // We might mutate the object register.
3991 frame_->Spill(object.reg()); 4075 frame_->Spill(object.reg());
3992 frame_->Spill(index.reg());
3993 4076
3994 // We need two extra registers. 4077 // We need two extra registers.
3995 Result result = allocator()->Allocate(); 4078 Result result = allocator()->Allocate();
3996 ASSERT(result.is_valid()); 4079 ASSERT(result.is_valid());
3997 Result scratch = allocator()->Allocate(); 4080 Result scratch = allocator()->Allocate();
3998 ASSERT(scratch.is_valid()); 4081 ASSERT(scratch.is_valid());
3999 4082
4000 // There is no virtual frame effect from here up to the final result 4083 DeferredStringCharCodeAt* deferred =
4001 // push. 4084 new DeferredStringCharCodeAt(object.reg(),
4002 Label slow_case; 4085 index.reg(),
4003 Label exit; 4086 scratch.reg(),
4004 StringHelper::GenerateFastCharCodeAt(masm_, 4087 result.reg());
4005 object.reg(), 4088 deferred->fast_case_generator()->GenerateFast(masm_);
4006 index.reg(), 4089 deferred->BindExit();
4007 scratch.reg(),
4008 result.reg(),
4009 &slow_case,
4010 &slow_case,
4011 &slow_case,
4012 &slow_case);
4013 __ jmp(&exit);
4014
4015 __ bind(&slow_case);
4016 // Move the undefined value into the result register, which will
4017 // trigger the slow case.
4018 __ LoadRoot(result.reg(), Heap::kUndefinedValueRootIndex);
4019
4020 __ bind(&exit);
4021 frame_->Push(&result); 4090 frame_->Push(&result);
4022 } 4091 }
4023 4092
4024 4093
4025 void CodeGenerator::GenerateCharFromCode(ZoneList<Expression*>* args) { 4094 class DeferredStringCharFromCode : public DeferredCode {
4026 Comment(masm_, "[ GenerateCharFromCode"); 4095 public:
4096 DeferredStringCharFromCode(Register code,
4097 Register result)
4098 : char_from_code_generator_(code, result) {}
4099
4100 StringCharFromCodeGenerator* fast_case_generator() {
4101 return &char_from_code_generator_;
4102 }
4103
4104 virtual void Generate() {
4105 VirtualFrameRuntimeCallHelper call_helper(frame_state());
4106 char_from_code_generator_.GenerateSlow(masm(), call_helper);
4107 }
4108
4109 private:
4110 StringCharFromCodeGenerator char_from_code_generator_;
4111 };
4112
4113
4114 // Generates code for creating a one-char string from a char code.
4115 void CodeGenerator::GenerateStringCharFromCode(ZoneList<Expression*>* args) {
4116 Comment(masm_, "[ GenerateStringCharFromCode");
4027 ASSERT(args->length() == 1); 4117 ASSERT(args->length() == 1);
4028 4118
4029 Load(args->at(0)); 4119 Load(args->at(0));
4030 4120
4031 Result code = frame_->Pop(); 4121 Result code = frame_->Pop();
4032 code.ToRegister(); 4122 code.ToRegister();
4033 ASSERT(code.is_valid()); 4123 ASSERT(code.is_valid());
4034 4124
4035 // StringHelper::GenerateCharFromCode may do a runtime call.
4036 frame_->SpillAll();
4037
4038 Result result = allocator()->Allocate(); 4125 Result result = allocator()->Allocate();
4039 ASSERT(result.is_valid()); 4126 ASSERT(result.is_valid());
4040 Result scratch = allocator()->Allocate();
4041 ASSERT(scratch.is_valid());
4042 4127
4043 StringHelper::GenerateCharFromCode(masm_, 4128 DeferredStringCharFromCode* deferred = new DeferredStringCharFromCode(
4044 code.reg(), 4129 code.reg(), result.reg());
4045 result.reg(), 4130 deferred->fast_case_generator()->GenerateFast(masm_);
4046 scratch.reg(), 4131 deferred->BindExit();
4047 CALL_FUNCTION);
4048 frame_->Push(&result); 4132 frame_->Push(&result);
4049 } 4133 }
4050 4134
4135
4136 class DeferredStringCharAt : public DeferredCode {
4137 public:
4138 DeferredStringCharAt(Register object,
4139 Register index,
4140 Register scratch1,
4141 Register scratch2,
4142 Register result)
4143 : result_(result),
4144 char_at_generator_(object,
4145 index,
4146 scratch1,
4147 scratch2,
4148 result,
4149 &need_conversion_,
4150 &need_conversion_,
4151 &index_out_of_range_,
4152 STRING_ANY_NUMBER_INDEX) {}
4153
4154 StringCharAtGenerator* fast_case_generator() {
4155 return &char_at_generator_;
4156 }
4157
4158 virtual void Generate() {
4159 VirtualFrameRuntimeCallHelper call_helper(frame_state());
4160 char_at_generator_.GenerateSlow(masm(), call_helper);
4161
4162 __ bind(&need_conversion_);
4163 // Move smi zero into the result register, which will trigger
4164 // conversion.
4165 __ Move(result_, Smi::FromInt(0));
4166 __ jmp(exit_label());
4167
4168 __ bind(&index_out_of_range_);
4169 // When the index is out of range, the spec requires us to return
4170 // the empty string.
4171 __ LoadRoot(result_, Heap::kEmptyStringRootIndex);
4172 __ jmp(exit_label());
4173 }
4174
4175 private:
4176 Register result_;
4177
4178 Label need_conversion_;
4179 Label index_out_of_range_;
4180
4181 StringCharAtGenerator char_at_generator_;
4182 };
4183
4184
4185 // This generates code that performs a String.prototype.charAt() call
4186 // or returns a smi in order to trigger conversion.
4187 void CodeGenerator::GenerateStringCharAt(ZoneList<Expression*>* args) {
4188 Comment(masm_, "[ GenerateStringCharAt");
4189 ASSERT(args->length() == 2);
4190
4191 Load(args->at(0));
4192 Load(args->at(1));
4193 Result index = frame_->Pop();
4194 Result object = frame_->Pop();
4195 object.ToRegister();
4196 index.ToRegister();
4197 // We might mutate the object register.
4198 frame_->Spill(object.reg());
4199
4200 // We need three extra registers.
4201 Result result = allocator()->Allocate();
4202 ASSERT(result.is_valid());
4203 Result scratch1 = allocator()->Allocate();
4204 ASSERT(scratch1.is_valid());
4205 Result scratch2 = allocator()->Allocate();
4206 ASSERT(scratch2.is_valid());
4207
4208 DeferredStringCharAt* deferred =
4209 new DeferredStringCharAt(object.reg(),
4210 index.reg(),
4211 scratch1.reg(),
4212 scratch2.reg(),
4213 result.reg());
4214 deferred->fast_case_generator()->GenerateFast(masm_);
4215 deferred->BindExit();
4216 frame_->Push(&result);
4217 }
4218
4051 4219
4052 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { 4220 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
4053 ASSERT(args->length() == 1); 4221 ASSERT(args->length() == 1);
4054 Load(args->at(0)); 4222 Load(args->at(0));
4055 Result value = frame_->Pop(); 4223 Result value = frame_->Pop();
4056 value.ToRegister(); 4224 value.ToRegister();
4057 ASSERT(value.is_valid()); 4225 ASSERT(value.is_valid());
4058 Condition positive_smi = masm_->CheckPositiveSmi(value.reg()); 4226 Condition positive_smi = masm_->CheckPositiveSmi(value.reg());
4059 value.Unuse(); 4227 value.Unuse();
4060 destination()->Split(positive_smi); 4228 destination()->Split(positive_smi);
(...skipping 6594 matching lines...) Expand 10 before | Expand all | Expand 10 after
10655 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), 10823 OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
10656 "CompareStub_%s%s%s%s", 10824 "CompareStub_%s%s%s%s",
10657 cc_name, 10825 cc_name,
10658 strict_name, 10826 strict_name,
10659 never_nan_nan_name, 10827 never_nan_nan_name,
10660 include_number_compare_name); 10828 include_number_compare_name);
10661 return name_; 10829 return name_;
10662 } 10830 }
10663 10831
10664 10832
10665 void StringHelper::GenerateFastCharCodeAt(MacroAssembler* masm, 10833 // -------------------------------------------------------------------------
10666 Register object, 10834 // StringCharCodeAtGenerator
10667 Register index, 10835
10668 Register scratch, 10836 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
10669 Register result, 10837 Label flat_string;
10670 Label* receiver_not_string,
10671 Label* index_not_smi,
10672 Label* index_out_of_range,
10673 Label* slow_case) {
10674 Label not_a_flat_string;
10675 Label try_again_with_new_string;
10676 Label ascii_string; 10838 Label ascii_string;
10677 Label got_char_code; 10839 Label got_char_code;
10678 10840
10679 // If the receiver is a smi trigger the non-string case. 10841 // If the receiver is a smi trigger the non-string case.
10680 __ JumpIfSmi(object, receiver_not_string); 10842 __ JumpIfSmi(object_, receiver_not_string_);
10681 10843
10682 // Fetch the instance type of the receiver into result register. 10844 // Fetch the instance type of the receiver into result register.
10683 __ movq(result, FieldOperand(object, HeapObject::kMapOffset)); 10845 __ movq(result_, FieldOperand(object_, HeapObject::kMapOffset));
10684 __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset)); 10846 __ movzxbl(result_, FieldOperand(result_, Map::kInstanceTypeOffset));
10685 // If the receiver is not a string trigger the non-string case. 10847 // If the receiver is not a string trigger the non-string case.
10686 __ testb(result, Immediate(kIsNotStringMask)); 10848 __ testb(result_, Immediate(kIsNotStringMask));
10687 __ j(not_zero, receiver_not_string); 10849 __ j(not_zero, receiver_not_string_);
10688 10850
10689 // If the index is non-smi trigger the non-smi case. 10851 // If the index is non-smi trigger the non-smi case.
10690 __ JumpIfNotSmi(index, index_not_smi); 10852 __ JumpIfNotSmi(index_, &index_not_smi_);
10853
10854 // Put smi-tagged index into scratch register.
10855 __ movq(scratch_, index_);
10856 __ bind(&got_smi_index_);
10691 10857
10692 // Check for index out of range. 10858 // Check for index out of range.
10693 __ SmiCompare(index, FieldOperand(object, String::kLengthOffset)); 10859 __ SmiCompare(scratch_, FieldOperand(object_, String::kLengthOffset));
10694 __ j(above_equal, index_out_of_range); 10860 __ j(above_equal, index_out_of_range_);
10695
10696 __ bind(&try_again_with_new_string);
10697 // ----------- S t a t e -------------
10698 // -- object : string to access
10699 // -- result : instance type of the string
10700 // -- scratch : non-negative index < length
10701 // -----------------------------------
10702 10861
10703 // We need special handling for non-flat strings. 10862 // We need special handling for non-flat strings.
10704 ASSERT_EQ(0, kSeqStringTag); 10863 ASSERT(kSeqStringTag == 0);
10705 __ testb(result, Immediate(kStringRepresentationMask)); 10864 __ testb(result_, Immediate(kStringRepresentationMask));
10706 __ j(not_zero, &not_a_flat_string); 10865 __ j(zero, &flat_string);
10707 10866
10708 // Put untagged index into scratch register. 10867 // Handle non-flat strings.
10709 __ SmiToInteger32(scratch, index); 10868 __ testb(result_, Immediate(kIsConsStringMask));
10869 __ j(zero, &call_runtime_);
10870
10871 // ConsString.
10872 // Check whether the right hand side is the empty string (i.e. if
10873 // this is really a flat string in a cons string). If that is not
10874 // the case we would rather go to the runtime system now to flatten
10875 // the string.
10876 __ CompareRoot(FieldOperand(object_, ConsString::kSecondOffset),
10877 Heap::kEmptyStringRootIndex);
10878 __ j(not_equal, &call_runtime_);
10879 // Get the first of the two strings and load its instance type.
10880 __ movq(object_, FieldOperand(object_, ConsString::kFirstOffset));
10881 __ movq(result_, FieldOperand(object_, HeapObject::kMapOffset));
10882 __ movzxbl(result_, FieldOperand(result_, Map::kInstanceTypeOffset));
10883 // If the first cons component is also non-flat, then go to runtime.
10884 ASSERT(kSeqStringTag == 0);
10885 __ testb(result_, Immediate(kStringRepresentationMask));
10886 __ j(not_zero, &call_runtime_);
10710 10887
10711 // Check for 1-byte or 2-byte string. 10888 // Check for 1-byte or 2-byte string.
10712 ASSERT_EQ(0, kTwoByteStringTag); 10889 __ bind(&flat_string);
10713 __ testb(result, Immediate(kStringEncodingMask)); 10890 ASSERT(kAsciiStringTag != 0);
10891 __ testb(result_, Immediate(kStringEncodingMask));
10714 __ j(not_zero, &ascii_string); 10892 __ j(not_zero, &ascii_string);
10715 10893
10716 // 2-byte string. 10894 // 2-byte string.
10717 // Load the 2-byte character code into the result register. 10895 // Load the 2-byte character code into the result register.
10718 __ movzxwl(result, FieldOperand(object, 10896 __ SmiToInteger32(scratch_, scratch_);
10719 scratch, 10897 __ movzxwl(result_, FieldOperand(object_,
10720 times_2, 10898 scratch_, times_2,
10721 SeqTwoByteString::kHeaderSize)); 10899 SeqTwoByteString::kHeaderSize));
10722 __ jmp(&got_char_code); 10900 __ jmp(&got_char_code);
10723 10901
10724 // Handle non-flat strings.
10725 __ bind(&not_a_flat_string);
10726 __ and_(result, Immediate(kStringRepresentationMask));
10727 __ cmpb(result, Immediate(kConsStringTag));
10728 __ j(not_equal, slow_case);
10729
10730 // ConsString.
10731 // Check that the right hand side is the empty string (ie if this is really a
10732 // flat string in a cons string). If that is not the case we would rather go
10733 // to the runtime system now, to flatten the string.
10734 __ movq(result, FieldOperand(object, ConsString::kSecondOffset));
10735 __ CompareRoot(result, Heap::kEmptyStringRootIndex);
10736 __ j(not_equal, slow_case);
10737 // Get the first of the two strings and load its instance type.
10738 __ movq(object, FieldOperand(object, ConsString::kFirstOffset));
10739 __ movq(result, FieldOperand(object, HeapObject::kMapOffset));
10740 __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset));
10741 __ jmp(&try_again_with_new_string);
10742
10743 // ASCII string. 10902 // ASCII string.
10903 // Load the byte into the result register.
10744 __ bind(&ascii_string); 10904 __ bind(&ascii_string);
10745 // Load the byte into the result register. 10905 __ SmiToInteger32(scratch_, scratch_);
10746 __ movzxbl(result, FieldOperand(object, 10906 __ movzxbl(result_, FieldOperand(object_,
10747 scratch, 10907 scratch_, times_1,
10748 times_1, 10908 SeqAsciiString::kHeaderSize));
10749 SeqAsciiString::kHeaderSize));
10750 __ bind(&got_char_code); 10909 __ bind(&got_char_code);
10751 __ Integer32ToSmi(result, result); 10910 __ Integer32ToSmi(result_, result_);
10911 __ bind(&exit_);
10752 } 10912 }
10753 10913
10754 10914
10755 void StringHelper::GenerateCharFromCode(MacroAssembler* masm, 10915 void StringCharCodeAtGenerator::GenerateSlow(
10756 Register code, 10916 MacroAssembler* masm, const RuntimeCallHelper& call_helper) {
10757 Register result, 10917 __ Abort("Unexpected fallthrough to CharCodeAt slow case");
10758 Register scratch,
10759 InvokeFlag flag) {
10760 ASSERT(!code.is(result));
10761 10918
10762 Label slow_case; 10919 // Index is not a smi.
10763 Label exit; 10920 __ bind(&index_not_smi_);
10921 // If index is a heap number, try converting it to an integer.
10922 __ CheckMap(index_, Factory::heap_number_map(), index_not_number_, true);
10923 call_helper.BeforeCall(masm);
10924 __ push(object_);
10925 __ push(index_);
10926 __ push(result_);
10927 __ push(index_); // Consumed by runtime conversion function.
10928 if (index_flags_ == STRING_ANY_NUMBER_INDEX) {
10929 // Strictly speaking, NumberToInteger should be called here, but
10930 // our string lengths don't exceed 32 bits and using ToUint32 maps
10931 // -0 to 0, which is what is required by the spec when accessing
10932 // strings.
10933 __ CallRuntime(Runtime::kNumberToJSUint32, 1);
10934 } else {
10935 ASSERT(index_flags_ == STRING_REQUIRE_ARRAY_INDEX);
10936 // NumberToSmi discards numbers that are not exact integers.
10937 __ CallRuntime(Runtime::kNumberToSmi, 1);
10938 }
10939 if (!scratch_.is(rax)) {
10940 // Save the conversion result before the pop instructions below
10941 // have a chance to overwrite it.
10942 __ movq(scratch_, rax);
10943 }
10944 __ pop(result_);
10945 __ pop(index_);
10946 __ pop(object_);
10947 call_helper.AfterCall(masm);
10948 // If index is still not a smi, it must be out of range.
10949 __ JumpIfNotSmi(scratch_, index_out_of_range_);
10950 // Otherwise, return to the fast path.
10951 __ jmp(&got_smi_index_);
10764 10952
10765 // Fast case of Heap::LookupSingleCharacterStringFromCode. 10953 // Call runtime. We get here when the receiver is a string and the
10766 __ JumpIfNotSmi(code, &slow_case); 10954 // index is a number, but the code of getting the actual character
10767 __ SmiToInteger32(scratch, code); 10955 // is too complex (e.g., when the string needs to be flattened).
10768 __ cmpl(scratch, Immediate(String::kMaxAsciiCharCode)); 10956 __ bind(&call_runtime_);
10769 __ j(above, &slow_case); 10957 call_helper.BeforeCall(masm);
10958 __ push(object_);
10959 __ push(index_);
10960 __ CallRuntime(Runtime::kStringCharCodeAt, 2);
10961 if (!result_.is(rax)) {
10962 __ movq(result_, rax);
10963 }
10964 call_helper.AfterCall(masm);
10965 __ jmp(&exit_);
10770 10966
10771 __ Move(result, Factory::single_character_string_cache()); 10967 __ Abort("Unexpected fallthrough from CharCodeAt slow case");
10772 __ movq(result, FieldOperand(result,
10773 scratch,
10774 times_pointer_size,
10775 FixedArray::kHeaderSize));
10776
10777 __ CompareRoot(result, Heap::kUndefinedValueRootIndex);
10778 __ j(equal, &slow_case);
10779 __ jmp(&exit);
10780
10781 __ bind(&slow_case);
10782 if (flag == CALL_FUNCTION) {
10783 __ push(code);
10784 __ CallRuntime(Runtime::kCharFromCode, 1);
10785 if (!result.is(rax)) {
10786 __ movq(result, rax);
10787 }
10788 } else {
10789 ASSERT(flag == JUMP_FUNCTION);
10790 ASSERT(result.is(rax));
10791 __ pop(rax); // Save return address.
10792 __ push(code);
10793 __ push(rax); // Restore return address.
10794 __ TailCallRuntime(Runtime::kCharFromCode, 1, 1);
10795 }
10796
10797 __ bind(&exit);
10798 if (flag == JUMP_FUNCTION) {
10799 ASSERT(result.is(rax));
10800 __ ret(0);
10801 }
10802 } 10968 }
10803 10969
10804 10970
10971 // -------------------------------------------------------------------------
10972 // StringCharFromCodeGenerator
10973
10974 void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
10975 // Fast case of Heap::LookupSingleCharacterStringFromCode.
10976 __ JumpIfNotSmi(code_, &slow_case_);
10977 __ SmiCompare(code_, Smi::FromInt(String::kMaxAsciiCharCode));
10978 __ j(above, &slow_case_);
10979
10980 __ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex);
10981 SmiIndex index = masm->SmiToIndex(kScratchRegister, code_, kPointerSizeLog2);
10982 __ movq(result_, FieldOperand(result_, index.reg, index.scale,
10983 FixedArray::kHeaderSize));
10984 __ CompareRoot(result_, Heap::kUndefinedValueRootIndex);
10985 __ j(equal, &slow_case_);
10986 __ bind(&exit_);
10987 }
10988
10989
10990 void StringCharFromCodeGenerator::GenerateSlow(
10991 MacroAssembler* masm, const RuntimeCallHelper& call_helper) {
10992 __ Abort("Unexpected fallthrough to CharFromCode slow case");
10993
10994 __ bind(&slow_case_);
10995 call_helper.BeforeCall(masm);
10996 __ push(code_);
10997 __ CallRuntime(Runtime::kCharFromCode, 1);
10998 if (!result_.is(rax)) {
10999 __ movq(result_, rax);
11000 }
11001 call_helper.AfterCall(masm);
11002 __ jmp(&exit_);
11003
11004 __ Abort("Unexpected fallthrough from CharFromCode slow case");
11005 }
11006
11007
11008 // -------------------------------------------------------------------------
11009 // StringCharAtGenerator
11010
11011 void StringCharAtGenerator::GenerateFast(MacroAssembler* masm) {
11012 char_code_at_generator_.GenerateFast(masm);
11013 char_from_code_generator_.GenerateFast(masm);
11014 }
11015
11016
11017 void StringCharAtGenerator::GenerateSlow(
11018 MacroAssembler* masm, const RuntimeCallHelper& call_helper) {
11019 char_code_at_generator_.GenerateSlow(masm, call_helper);
11020 char_from_code_generator_.GenerateSlow(masm, call_helper);
11021 }
11022
11023
10805 void StringAddStub::Generate(MacroAssembler* masm) { 11024 void StringAddStub::Generate(MacroAssembler* masm) {
10806 Label string_add_runtime; 11025 Label string_add_runtime;
10807 11026
10808 // Load the two arguments. 11027 // Load the two arguments.
10809 __ movq(rax, Operand(rsp, 2 * kPointerSize)); // First argument. 11028 __ movq(rax, Operand(rsp, 2 * kPointerSize)); // First argument.
10810 __ movq(rdx, Operand(rsp, 1 * kPointerSize)); // Second argument. 11029 __ movq(rdx, Operand(rsp, 1 * kPointerSize)); // Second argument.
10811 11030
10812 // Make sure that both arguments are strings if not known in advance. 11031 // Make sure that both arguments are strings if not known in advance.
10813 if (string_check_) { 11032 if (string_check_) {
10814 Condition is_smi; 11033 Condition is_smi;
(...skipping 835 matching lines...) Expand 10 before | Expand all | Expand 10 after
11650 } 11869 }
11651 11870
11652 #endif 11871 #endif
11653 11872
11654 11873
11655 #undef __ 11874 #undef __
11656 11875
11657 } } // namespace v8::internal 11876 } } // namespace v8::internal
11658 11877
11659 #endif // V8_TARGET_ARCH_X64 11878 #endif // V8_TARGET_ARCH_X64
OLDNEW
« src/codegen.h ('K') | « src/x64/codegen-x64.h ('k') | src/x64/full-codegen-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698