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

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

Issue 1582041: Reapply: Inline fast cases in string keyed load IC. (Closed)
Patch Set: . Created 10 years, 8 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 2330 matching lines...) Expand 10 before | Expand all | Expand 10 after
2341 operand->ToRegister(); 2341 operand->ToRegister();
2342 frame_->Spill(operand->reg()); 2342 frame_->Spill(operand->reg());
2343 DeferredCode* deferred = 2343 DeferredCode* deferred =
2344 new DeferredInlineSmiOperation(op, 2344 new DeferredInlineSmiOperation(op,
2345 operand->reg(), 2345 operand->reg(),
2346 operand->reg(), 2346 operand->reg(),
2347 operand->type_info(), 2347 operand->type_info(),
2348 smi_value, 2348 smi_value,
2349 overwrite_mode); 2349 overwrite_mode);
2350 // Check for negative or non-Smi left hand side. 2350 // Check for negative or non-Smi left hand side.
2351 __ test(operand->reg(), Immediate(kSmiTagMask | 0x80000000)); 2351 __ test(operand->reg(), Immediate(kSmiTagMask | kSmiSignMask));
2352 deferred->Branch(not_zero); 2352 deferred->Branch(not_zero);
2353 if (int_value < 0) int_value = -int_value; 2353 if (int_value < 0) int_value = -int_value;
2354 if (int_value == 1) { 2354 if (int_value == 1) {
2355 __ mov(operand->reg(), Immediate(Smi::FromInt(0))); 2355 __ mov(operand->reg(), Immediate(Smi::FromInt(0)));
2356 } else { 2356 } else {
2357 __ and_(operand->reg(), (int_value << kSmiTagSize) - 1); 2357 __ and_(operand->reg(), (int_value << kSmiTagSize) - 1);
2358 } 2358 }
2359 deferred->BindExit(); 2359 deferred->BindExit();
2360 answer = *operand; 2360 answer = *operand;
2361 break; 2361 break;
(...skipping 3532 matching lines...) Expand 10 before | Expand all | Expand 10 after
5894 frame_->Push(Factory::undefined_value()); 5894 frame_->Push(Factory::undefined_value());
5895 } 5895 }
5896 5896
5897 5897
5898 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { 5898 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
5899 ASSERT(args->length() == 1); 5899 ASSERT(args->length() == 1);
5900 Load(args->at(0)); 5900 Load(args->at(0));
5901 Result value = frame_->Pop(); 5901 Result value = frame_->Pop();
5902 value.ToRegister(); 5902 value.ToRegister();
5903 ASSERT(value.is_valid()); 5903 ASSERT(value.is_valid());
5904 __ test(value.reg(), Immediate(kSmiTagMask | 0x80000000)); 5904 __ test(value.reg(), Immediate(kSmiTagMask | kSmiSignMask));
5905 value.Unuse(); 5905 value.Unuse();
5906 destination()->Split(zero); 5906 destination()->Split(zero);
5907 } 5907 }
5908 5908
5909 5909
5910 // This generates code that performs a charCodeAt() call or returns 5910 // This generates code that performs a charCodeAt() call or returns
5911 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt. 5911 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt.
5912 // It can handle flat, 8 and 16 bit characters and cons strings where the 5912 // It can handle flat, 8 and 16 bit characters and cons strings where the
5913 // answer is found in the left hand branch of the cons. The slow case will 5913 // answer is found in the left hand branch of the cons. The slow case will
5914 // flatten the string, which will ensure that the answer is in the left hand 5914 // flatten the string, which will ensure that the answer is in the left hand
5915 // side the next time around. 5915 // side the next time around.
5916 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) { 5916 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) {
5917 Comment(masm_, "[ GenerateFastCharCodeAt"); 5917 Comment(masm_, "[ GenerateFastCharCodeAt");
5918 ASSERT(args->length() == 2); 5918 ASSERT(args->length() == 2);
5919 5919
5920 Label slow_case;
5921 Label end;
5922 Label not_a_flat_string;
5923 Label try_again_with_new_string;
5924 Label ascii_string;
5925 Label got_char_code;
5926
5927 Load(args->at(0)); 5920 Load(args->at(0));
5928 Load(args->at(1)); 5921 Load(args->at(1));
5929 Result index = frame_->Pop(); 5922 Result index = frame_->Pop();
5930 Result object = frame_->Pop(); 5923 Result object = frame_->Pop();
5931 5924
5932 // Get register ecx to use as shift amount later.
5933 Result shift_amount;
5934 if (object.is_register() && object.reg().is(ecx)) {
5935 Result fresh = allocator_->Allocate();
5936 shift_amount = object;
5937 object = fresh;
5938 __ mov(object.reg(), ecx);
5939 }
5940 if (index.is_register() && index.reg().is(ecx)) {
5941 Result fresh = allocator_->Allocate();
5942 shift_amount = index;
5943 index = fresh;
5944 __ mov(index.reg(), ecx);
5945 }
5946 // There could be references to ecx in the frame. Allocating will
5947 // spill them, otherwise spill explicitly.
5948 if (shift_amount.is_valid()) {
5949 frame_->Spill(ecx);
5950 } else {
5951 shift_amount = allocator()->Allocate(ecx);
5952 }
5953 ASSERT(shift_amount.is_register());
5954 ASSERT(shift_amount.reg().is(ecx));
5955 ASSERT(allocator_->count(ecx) == 1);
5956
5957 // We will mutate the index register and possibly the object register. 5925 // We will mutate the index register and possibly the object register.
5958 // The case where they are somehow the same register is handled 5926 // The case where they are somehow the same register is handled
5959 // because we only mutate them in the case where the receiver is a 5927 // because we only mutate them in the case where the receiver is a
5960 // heap object and the index is not. 5928 // heap object and the index is not.
5961 object.ToRegister(); 5929 object.ToRegister();
5962 index.ToRegister(); 5930 index.ToRegister();
5963 frame_->Spill(object.reg()); 5931 frame_->Spill(object.reg());
5964 frame_->Spill(index.reg()); 5932 frame_->Spill(index.reg());
5965 5933
5966 // We need a single extra temporary register. 5934 // We need two extra registers.
5967 Result temp = allocator()->Allocate(); 5935 Result result = allocator()->Allocate();
5968 ASSERT(temp.is_valid()); 5936 ASSERT(result.is_valid());
5937 Result scratch = allocator()->Allocate();
5938 ASSERT(scratch.is_valid());
5969 5939
5970 // There is no virtual frame effect from here up to the final result 5940 // There is no virtual frame effect from here up to the final result
5971 // push. 5941 // push.
5972 5942 Label slow_case;
5973 // If the receiver is a smi trigger the slow case. 5943 Label exit;
5974 ASSERT(kSmiTag == 0); 5944 StringHelper::GenerateFastCharCodeAt(masm_,
5975 __ test(object.reg(), Immediate(kSmiTagMask)); 5945 object.reg(),
5976 __ j(zero, &slow_case); 5946 index.reg(),
5977 5947 scratch.reg(),
5978 // If the index is negative or non-smi trigger the slow case. 5948 result.reg(),
5979 ASSERT(kSmiTag == 0); 5949 &slow_case,
5980 __ test(index.reg(), Immediate(kSmiTagMask | 0x80000000)); 5950 &slow_case,
5981 __ j(not_zero, &slow_case); 5951 &slow_case);
5982 // Untag the index. 5952 __ jmp(&exit);
5983 __ SmiUntag(index.reg());
5984
5985 __ bind(&try_again_with_new_string);
5986 // Fetch the instance type of the receiver into ecx.
5987 __ mov(ecx, FieldOperand(object.reg(), HeapObject::kMapOffset));
5988 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
5989 // If the receiver is not a string trigger the slow case.
5990 __ test(ecx, Immediate(kIsNotStringMask));
5991 __ j(not_zero, &slow_case);
5992
5993 // Fetch the length field into the temporary register.
5994 __ mov(temp.reg(), FieldOperand(object.reg(), String::kLengthOffset));
5995 // Check for index out of range.
5996 __ cmp(index.reg(), Operand(temp.reg()));
5997 __ j(greater_equal, &slow_case);
5998 // Reload the instance type (into the temp register this time)..
5999 __ mov(temp.reg(), FieldOperand(object.reg(), HeapObject::kMapOffset));
6000 __ movzx_b(temp.reg(), FieldOperand(temp.reg(), Map::kInstanceTypeOffset));
6001
6002 // We need special handling for non-flat strings.
6003 ASSERT(kSeqStringTag == 0);
6004 __ test(temp.reg(), Immediate(kStringRepresentationMask));
6005 __ j(not_zero, &not_a_flat_string);
6006 // Check for 1-byte or 2-byte string.
6007 __ test(temp.reg(), Immediate(kStringEncodingMask));
6008 __ j(not_zero, &ascii_string);
6009
6010 // 2-byte string.
6011 // Load the 2-byte character code into the temp register.
6012 __ movzx_w(temp.reg(), FieldOperand(object.reg(),
6013 index.reg(),
6014 times_2,
6015 SeqTwoByteString::kHeaderSize));
6016 __ jmp(&got_char_code);
6017
6018 // ASCII string.
6019 __ bind(&ascii_string);
6020 // Load the byte into the temp register.
6021 __ movzx_b(temp.reg(), FieldOperand(object.reg(),
6022 index.reg(),
6023 times_1,
6024 SeqAsciiString::kHeaderSize));
6025 __ bind(&got_char_code);
6026 __ SmiTag(temp.reg());
6027 __ jmp(&end);
6028
6029 // Handle non-flat strings.
6030 __ bind(&not_a_flat_string);
6031 __ and_(temp.reg(), kStringRepresentationMask);
6032 __ cmp(temp.reg(), kConsStringTag);
6033 __ j(not_equal, &slow_case);
6034
6035 // ConsString.
6036 // Check that the right hand side is the empty string (ie if this is really a
6037 // flat string in a cons string). If that is not the case we would rather go
6038 // to the runtime system now, to flatten the string.
6039 __ mov(temp.reg(), FieldOperand(object.reg(), ConsString::kSecondOffset));
6040 __ cmp(Operand(temp.reg()), Factory::empty_string());
6041 __ j(not_equal, &slow_case);
6042 // Get the first of the two strings.
6043 __ mov(object.reg(), FieldOperand(object.reg(), ConsString::kFirstOffset));
6044 __ jmp(&try_again_with_new_string);
6045 5953
6046 __ bind(&slow_case); 5954 __ bind(&slow_case);
6047 // Move the undefined value into the result register, which will 5955 // Move the undefined value into the result register, which will
6048 // trigger the slow case. 5956 // trigger the slow case.
6049 __ Set(temp.reg(), Immediate(Factory::undefined_value())); 5957 __ Set(result.reg(), Immediate(Factory::undefined_value()));
6050 5958
6051 __ bind(&end); 5959 __ bind(&exit);
6052 frame_->Push(&temp); 5960 frame_->Push(&result);
6053 } 5961 }
6054 5962
6055 5963
6056 void CodeGenerator::GenerateCharFromCode(ZoneList<Expression*>* args) { 5964 void CodeGenerator::GenerateCharFromCode(ZoneList<Expression*>* args) {
6057 Comment(masm_, "[ GenerateCharFromCode"); 5965 Comment(masm_, "[ GenerateCharFromCode");
6058 ASSERT(args->length() == 1); 5966 ASSERT(args->length() == 1);
6059 5967
6060 Load(args->at(0)); 5968 Load(args->at(0));
5969
6061 Result code = frame_->Pop(); 5970 Result code = frame_->Pop();
6062 code.ToRegister(); 5971 code.ToRegister();
6063 ASSERT(code.is_valid()); 5972 ASSERT(code.is_valid());
6064 5973
6065 Result temp = allocator()->Allocate(); 5974 // StringHelper::GenerateCharFromCode may do a runtime call.
6066 ASSERT(temp.is_valid()); 5975 frame_->SpillAll();
6067 5976
6068 JumpTarget slow_case; 5977 Result result = allocator()->Allocate();
6069 JumpTarget exit; 5978 ASSERT(result.is_valid());
6070 5979
6071 // Fast case of Heap::LookupSingleCharacterStringFromCode. 5980 StringHelper::GenerateCharFromCode(masm_,
6072 ASSERT(kSmiTag == 0); 5981 code.reg(),
6073 ASSERT(kSmiShiftSize == 0); 5982 result.reg(),
6074 ASSERT(IsPowerOf2(String::kMaxAsciiCharCode + 1)); 5983 CALL_FUNCTION);
6075 __ test(code.reg(),
6076 Immediate(kSmiTagMask |
6077 ((~String::kMaxAsciiCharCode) << kSmiTagSize)));
6078 slow_case.Branch(not_zero, &code, not_taken);
6079
6080 __ Set(temp.reg(), Immediate(Factory::single_character_string_cache()));
6081 ASSERT(kSmiTag == 0);
6082 ASSERT(kSmiTagSize == 1);
6083 ASSERT(kSmiShiftSize == 0);
6084 // At this point code register contains smi tagged ascii char code.
6085 __ mov(temp.reg(), FieldOperand(temp.reg(),
6086 code.reg(), times_half_pointer_size,
6087 FixedArray::kHeaderSize));
6088 __ cmp(temp.reg(), Factory::undefined_value());
6089 slow_case.Branch(equal, &code, not_taken);
6090 code.Unuse();
6091
6092 frame_->Push(&temp);
6093 exit.Jump();
6094
6095 slow_case.Bind(&code);
6096 frame_->Push(&code);
6097 Result result = frame_->CallRuntime(Runtime::kCharFromCode, 1);
6098 frame_->Push(&result); 5984 frame_->Push(&result);
6099
6100 exit.Bind();
6101 } 5985 }
6102 5986
6103 5987
6104 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) { 5988 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) {
6105 ASSERT(args->length() == 1); 5989 ASSERT(args->length() == 1);
6106 Load(args->at(0)); 5990 Load(args->at(0));
6107 Result value = frame_->Pop(); 5991 Result value = frame_->Pop();
6108 value.ToRegister(); 5992 value.ToRegister();
6109 ASSERT(value.is_valid()); 5993 ASSERT(value.is_valid());
6110 __ test(value.reg(), Immediate(kSmiTagMask)); 5994 __ test(value.reg(), Immediate(kSmiTagMask));
(...skipping 2404 matching lines...) Expand 10 before | Expand all | Expand 10 after
8515 tmp.reg()); 8399 tmp.reg());
8516 8400
8517 // Check that the value is a smi if it is not a constant. We can skip 8401 // Check that the value is a smi if it is not a constant. We can skip
8518 // the write barrier for smis and constants. 8402 // the write barrier for smis and constants.
8519 if (!value_is_constant) { 8403 if (!value_is_constant) {
8520 __ test(result.reg(), Immediate(kSmiTagMask)); 8404 __ test(result.reg(), Immediate(kSmiTagMask));
8521 deferred->Branch(not_zero); 8405 deferred->Branch(not_zero);
8522 } 8406 }
8523 8407
8524 // Check that the key is a non-negative smi. 8408 // Check that the key is a non-negative smi.
8525 __ test(key.reg(), Immediate(kSmiTagMask | 0x80000000)); 8409 __ test(key.reg(), Immediate(kSmiTagMask | kSmiSignMask));
8526 deferred->Branch(not_zero); 8410 deferred->Branch(not_zero);
8527 8411
8528 // Check that the receiver is not a smi. 8412 // Check that the receiver is not a smi.
8529 __ test(receiver.reg(), Immediate(kSmiTagMask)); 8413 __ test(receiver.reg(), Immediate(kSmiTagMask));
8530 deferred->Branch(zero); 8414 deferred->Branch(zero);
8531 8415
8532 // Check that the receiver is a JSArray. 8416 // Check that the receiver is a JSArray.
8533 __ mov(tmp.reg(), 8417 __ mov(tmp.reg(),
8534 FieldOperand(receiver.reg(), HeapObject::kMapOffset)); 8418 FieldOperand(receiver.reg(), HeapObject::kMapOffset));
8535 __ movzx_b(tmp.reg(), 8419 __ movzx_b(tmp.reg(),
(...skipping 3611 matching lines...) Expand 10 before | Expand all | Expand 10 after
12147 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), 12031 OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
12148 "CompareStub_%s%s%s%s", 12032 "CompareStub_%s%s%s%s",
12149 cc_name, 12033 cc_name,
12150 strict_name, 12034 strict_name,
12151 never_nan_nan_name, 12035 never_nan_nan_name,
12152 include_number_compare_name); 12036 include_number_compare_name);
12153 return name_; 12037 return name_;
12154 } 12038 }
12155 12039
12156 12040
12041 void StringHelper::GenerateFastCharCodeAt(MacroAssembler* masm,
12042 Register object,
12043 Register index,
12044 Register scratch,
12045 Register result,
12046 Label* receiver_not_string,
12047 Label* index_not_positive_smi,
12048 Label* slow_case) {
12049 Label not_a_flat_string;
12050 Label try_again_with_new_string;
12051 Label ascii_string;
12052 Label got_char_code;
12053
12054 // If the receiver is a smi trigger the non-string case.
12055 ASSERT(kSmiTag == 0);
12056 __ test(object, Immediate(kSmiTagMask));
12057 __ j(zero, receiver_not_string);
12058
12059 // Fetch the instance type of the receiver into result register.
12060 __ mov(result, FieldOperand(object, HeapObject::kMapOffset));
12061 __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset));
12062 // If the receiver is not a string trigger the non-string case.
12063 __ test(result, Immediate(kIsNotStringMask));
12064 __ j(not_zero, receiver_not_string);
12065
12066 // If the index is negative or non-smi trigger the non-positive-smi
12067 // case.
12068 ASSERT(kSmiTag == 0);
12069 __ test(index, Immediate(kSmiTagMask | kSmiSignMask));
12070 __ j(not_zero, index_not_positive_smi);
12071
12072 // Put untagged index into scratch register.
12073 __ mov(scratch, index);
12074 __ SmiUntag(scratch);
12075
12076 // Check for index out of range.
12077 __ cmp(scratch, FieldOperand(object, String::kLengthOffset));
12078 __ j(greater_equal, slow_case);
12079
12080 __ bind(&try_again_with_new_string);
12081 // ----------- S t a t e -------------
12082 // -- object : string to access
12083 // -- result : instance type of the string
12084 // -- scratch : positive smi index < length
12085 // -----------------------------------
12086
12087 // We need special handling for non-flat strings.
12088 ASSERT(kSeqStringTag == 0);
12089 __ test(result, Immediate(kStringRepresentationMask));
12090 __ j(not_zero, &not_a_flat_string);
12091
12092 // Check for 1-byte or 2-byte string.
12093 ASSERT(kAsciiStringTag != 0);
12094 __ test(result, Immediate(kStringEncodingMask));
12095 __ j(not_zero, &ascii_string);
12096
12097 // 2-byte string.
12098 // Load the 2-byte character code into the temp register.
12099 __ movzx_w(result, FieldOperand(object,
12100 scratch, times_2,
12101 SeqTwoByteString::kHeaderSize));
12102 __ jmp(&got_char_code);
12103
12104 // Handle non-flat strings.
12105 __ bind(&not_a_flat_string);
12106 __ and_(result, kStringRepresentationMask);
12107 __ cmp(result, kConsStringTag);
12108 __ j(not_equal, slow_case);
12109
12110 // ConsString.
12111 // Check whether the right hand side is the empty string (i.e. if
12112 // this is really a flat string in a cons string). If that is not
12113 // the case we would rather go to the runtime system now to flatten
12114 // the string.
12115 __ mov(result, FieldOperand(object, ConsString::kSecondOffset));
12116 __ cmp(Operand(result), Factory::empty_string());
12117 __ j(not_equal, slow_case);
12118 // Get the first of the two strings and load its instance type.
12119 __ mov(object, FieldOperand(object, ConsString::kFirstOffset));
12120 __ mov(result, FieldOperand(object, HeapObject::kMapOffset));
12121 __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset));
12122 __ jmp(&try_again_with_new_string);
12123
12124 // ASCII string.
12125 __ bind(&ascii_string);
12126 // Load the byte into the temp register.
12127 __ movzx_b(result, FieldOperand(object,
12128 scratch, times_1,
12129 SeqAsciiString::kHeaderSize));
12130 __ bind(&got_char_code);
12131 __ SmiTag(result);
12132 }
12133
12134
12135 void StringHelper::GenerateCharFromCode(MacroAssembler* masm,
12136 Register code,
12137 Register result,
12138 InvokeFlag flag) {
12139 ASSERT(!code.is(result));
12140
12141 Label slow_case;
12142 Label exit;
12143
12144 // Fast case of Heap::LookupSingleCharacterStringFromCode.
12145 ASSERT(kSmiTag == 0);
12146 ASSERT(kSmiShiftSize == 0);
12147 ASSERT(IsPowerOf2(String::kMaxAsciiCharCode + 1));
12148 __ test(code,
12149 Immediate(kSmiTagMask |
12150 ((~String::kMaxAsciiCharCode) << kSmiTagSize)));
12151 __ j(not_zero, &slow_case, not_taken);
12152
12153 __ Set(result, Immediate(Factory::single_character_string_cache()));
12154 ASSERT(kSmiTag == 0);
12155 ASSERT(kSmiTagSize == 1);
12156 ASSERT(kSmiShiftSize == 0);
12157 // At this point code register contains smi tagged ascii char code.
12158 __ mov(result, FieldOperand(result,
12159 code, times_half_pointer_size,
12160 FixedArray::kHeaderSize));
12161 __ cmp(result, Factory::undefined_value());
12162 __ j(equal, &slow_case, not_taken);
12163 __ jmp(&exit);
12164
12165 __ bind(&slow_case);
12166 if (flag == CALL_FUNCTION) {
12167 __ push(code);
12168 __ CallRuntime(Runtime::kCharFromCode, 1);
12169 if (!result.is(eax)) {
12170 __ mov(result, eax);
12171 }
12172 } else {
12173 ASSERT(flag == JUMP_FUNCTION);
12174 ASSERT(result.is(eax));
12175 __ pop(eax); // Save return address.
12176 __ push(code);
12177 __ push(eax); // Restore return address.
12178 __ TailCallRuntime(Runtime::kCharFromCode, 1, 1);
12179 }
12180
12181 __ bind(&exit);
12182 if (flag == JUMP_FUNCTION) {
12183 ASSERT(result.is(eax));
12184 __ ret(0);
12185 }
12186 }
12187
12188
12157 void StringAddStub::Generate(MacroAssembler* masm) { 12189 void StringAddStub::Generate(MacroAssembler* masm) {
12158 Label string_add_runtime; 12190 Label string_add_runtime;
12159 12191
12160 // Load the two arguments. 12192 // Load the two arguments.
12161 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument. 12193 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument.
12162 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument. 12194 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument.
12163 12195
12164 // Make sure that both arguments are strings if not known in advance. 12196 // Make sure that both arguments are strings if not known in advance.
12165 if (string_check_) { 12197 if (string_check_) {
12166 __ test(eax, Immediate(kSmiTagMask)); 12198 __ test(eax, Immediate(kSmiTagMask));
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
12213 __ JumpIfNotBothSequentialAsciiStrings(eax, edx, ebx, ecx, 12245 __ JumpIfNotBothSequentialAsciiStrings(eax, edx, ebx, ecx,
12214 &string_add_runtime); 12246 &string_add_runtime);
12215 12247
12216 // Get the two characters forming the sub string. 12248 // Get the two characters forming the sub string.
12217 __ movzx_b(ebx, FieldOperand(eax, SeqAsciiString::kHeaderSize)); 12249 __ movzx_b(ebx, FieldOperand(eax, SeqAsciiString::kHeaderSize));
12218 __ movzx_b(ecx, FieldOperand(edx, SeqAsciiString::kHeaderSize)); 12250 __ movzx_b(ecx, FieldOperand(edx, SeqAsciiString::kHeaderSize));
12219 12251
12220 // Try to lookup two character string in symbol table. If it is not found 12252 // Try to lookup two character string in symbol table. If it is not found
12221 // just allocate a new one. 12253 // just allocate a new one.
12222 Label make_two_character_string, make_flat_ascii_string; 12254 Label make_two_character_string, make_flat_ascii_string;
12223 GenerateTwoCharacterSymbolTableProbe(masm, ebx, ecx, eax, edx, edi, 12255 StringHelper::GenerateTwoCharacterSymbolTableProbe(
12224 &make_two_character_string); 12256 masm, ebx, ecx, eax, edx, edi, &make_two_character_string);
12225 __ IncrementCounter(&Counters::string_add_native, 1); 12257 __ IncrementCounter(&Counters::string_add_native, 1);
12226 __ ret(2 * kPointerSize); 12258 __ ret(2 * kPointerSize);
12227 12259
12228 __ bind(&make_two_character_string); 12260 __ bind(&make_two_character_string);
12229 __ Set(ebx, Immediate(2)); 12261 __ Set(ebx, Immediate(2));
12230 __ jmp(&make_flat_ascii_string); 12262 __ jmp(&make_flat_ascii_string);
12231 12263
12232 __ bind(&longer_than_two); 12264 __ bind(&longer_than_two);
12233 // Check if resulting string will be flat. 12265 // Check if resulting string will be flat.
12234 __ cmp(ebx, String::kMinNonFlatLength); 12266 __ cmp(ebx, String::kMinNonFlatLength);
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
12306 // Locate first character of result. 12338 // Locate first character of result.
12307 __ add(Operand(ecx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 12339 __ add(Operand(ecx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
12308 // Load first argument and locate first character. 12340 // Load first argument and locate first character.
12309 __ mov(edx, Operand(esp, 2 * kPointerSize)); 12341 __ mov(edx, Operand(esp, 2 * kPointerSize));
12310 __ mov(edi, FieldOperand(edx, String::kLengthOffset)); 12342 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
12311 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 12343 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
12312 // eax: result string 12344 // eax: result string
12313 // ecx: first character of result 12345 // ecx: first character of result
12314 // edx: first char of first argument 12346 // edx: first char of first argument
12315 // edi: length of first argument 12347 // edi: length of first argument
12316 GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true); 12348 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true);
12317 // Load second argument and locate first character. 12349 // Load second argument and locate first character.
12318 __ mov(edx, Operand(esp, 1 * kPointerSize)); 12350 __ mov(edx, Operand(esp, 1 * kPointerSize));
12319 __ mov(edi, FieldOperand(edx, String::kLengthOffset)); 12351 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
12320 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 12352 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
12321 // eax: result string 12353 // eax: result string
12322 // ecx: next character of result 12354 // ecx: next character of result
12323 // edx: first char of second argument 12355 // edx: first char of second argument
12324 // edi: length of second argument 12356 // edi: length of second argument
12325 GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true); 12357 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true);
12326 __ IncrementCounter(&Counters::string_add_native, 1); 12358 __ IncrementCounter(&Counters::string_add_native, 1);
12327 __ ret(2 * kPointerSize); 12359 __ ret(2 * kPointerSize);
12328 12360
12329 // Handle creating a flat two byte result. 12361 // Handle creating a flat two byte result.
12330 // eax: first string - known to be two byte 12362 // eax: first string - known to be two byte
12331 // ebx: length of resulting flat string 12363 // ebx: length of resulting flat string
12332 // edx: second string 12364 // edx: second string
12333 __ bind(&non_ascii_string_add_flat_result); 12365 __ bind(&non_ascii_string_add_flat_result);
12334 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 12366 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
12335 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 12367 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
12336 __ and_(ecx, kAsciiStringTag); 12368 __ and_(ecx, kAsciiStringTag);
12337 __ j(not_zero, &string_add_runtime); 12369 __ j(not_zero, &string_add_runtime);
12338 // Both strings are two byte strings. As they are short they are both 12370 // Both strings are two byte strings. As they are short they are both
12339 // flat. 12371 // flat.
12340 __ AllocateTwoByteString(eax, ebx, ecx, edx, edi, &string_add_runtime); 12372 __ AllocateTwoByteString(eax, ebx, ecx, edx, edi, &string_add_runtime);
12341 // eax: result string 12373 // eax: result string
12342 __ mov(ecx, eax); 12374 __ mov(ecx, eax);
12343 // Locate first character of result. 12375 // Locate first character of result.
12344 __ add(Operand(ecx), 12376 __ add(Operand(ecx),
12345 Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 12377 Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
12346 // Load first argument and locate first character. 12378 // Load first argument and locate first character.
12347 __ mov(edx, Operand(esp, 2 * kPointerSize)); 12379 __ mov(edx, Operand(esp, 2 * kPointerSize));
12348 __ mov(edi, FieldOperand(edx, String::kLengthOffset)); 12380 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
12349 __ add(Operand(edx), 12381 __ add(Operand(edx),
12350 Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 12382 Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
12351 // eax: result string 12383 // eax: result string
12352 // ecx: first character of result 12384 // ecx: first character of result
12353 // edx: first char of first argument 12385 // edx: first char of first argument
12354 // edi: length of first argument 12386 // edi: length of first argument
12355 GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false); 12387 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false);
12356 // Load second argument and locate first character. 12388 // Load second argument and locate first character.
12357 __ mov(edx, Operand(esp, 1 * kPointerSize)); 12389 __ mov(edx, Operand(esp, 1 * kPointerSize));
12358 __ mov(edi, FieldOperand(edx, String::kLengthOffset)); 12390 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
12359 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 12391 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
12360 // eax: result string 12392 // eax: result string
12361 // ecx: next character of result 12393 // ecx: next character of result
12362 // edx: first char of second argument 12394 // edx: first char of second argument
12363 // edi: length of second argument 12395 // edi: length of second argument
12364 GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false); 12396 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false);
12365 __ IncrementCounter(&Counters::string_add_native, 1); 12397 __ IncrementCounter(&Counters::string_add_native, 1);
12366 __ ret(2 * kPointerSize); 12398 __ ret(2 * kPointerSize);
12367 12399
12368 // Just jump to runtime to add the two strings. 12400 // Just jump to runtime to add the two strings.
12369 __ bind(&string_add_runtime); 12401 __ bind(&string_add_runtime);
12370 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); 12402 __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
12371 } 12403 }
12372 12404
12373 12405
12374 void StringStubBase::GenerateCopyCharacters(MacroAssembler* masm, 12406 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm,
12375 Register dest, 12407 Register dest,
12376 Register src, 12408 Register src,
12377 Register count, 12409 Register count,
12378 Register scratch, 12410 Register scratch,
12379 bool ascii) { 12411 bool ascii) {
12380 Label loop; 12412 Label loop;
12381 __ bind(&loop); 12413 __ bind(&loop);
12382 // This loop just copies one character at a time, as it is only used for very 12414 // This loop just copies one character at a time, as it is only used for very
12383 // short strings. 12415 // short strings.
12384 if (ascii) { 12416 if (ascii) {
12385 __ mov_b(scratch, Operand(src, 0)); 12417 __ mov_b(scratch, Operand(src, 0));
12386 __ mov_b(Operand(dest, 0), scratch); 12418 __ mov_b(Operand(dest, 0), scratch);
12387 __ add(Operand(src), Immediate(1)); 12419 __ add(Operand(src), Immediate(1));
12388 __ add(Operand(dest), Immediate(1)); 12420 __ add(Operand(dest), Immediate(1));
12389 } else { 12421 } else {
12390 __ mov_w(scratch, Operand(src, 0)); 12422 __ mov_w(scratch, Operand(src, 0));
12391 __ mov_w(Operand(dest, 0), scratch); 12423 __ mov_w(Operand(dest, 0), scratch);
12392 __ add(Operand(src), Immediate(2)); 12424 __ add(Operand(src), Immediate(2));
12393 __ add(Operand(dest), Immediate(2)); 12425 __ add(Operand(dest), Immediate(2));
12394 } 12426 }
12395 __ sub(Operand(count), Immediate(1)); 12427 __ sub(Operand(count), Immediate(1));
12396 __ j(not_zero, &loop); 12428 __ j(not_zero, &loop);
12397 } 12429 }
12398 12430
12399 12431
12400 void StringStubBase::GenerateCopyCharactersREP(MacroAssembler* masm, 12432 void StringHelper::GenerateCopyCharactersREP(MacroAssembler* masm,
12401 Register dest, 12433 Register dest,
12402 Register src, 12434 Register src,
12403 Register count, 12435 Register count,
12404 Register scratch, 12436 Register scratch,
12405 bool ascii) { 12437 bool ascii) {
12406 // Copy characters using rep movs of doublewords. Align destination on 4 byte 12438 // Copy characters using rep movs of doublewords. Align destination on 4 byte
12407 // boundary before starting rep movs. Copy remaining characters after running 12439 // boundary before starting rep movs. Copy remaining characters after running
12408 // rep movs. 12440 // rep movs.
12409 ASSERT(dest.is(edi)); // rep movs destination 12441 ASSERT(dest.is(edi)); // rep movs destination
12410 ASSERT(src.is(esi)); // rep movs source 12442 ASSERT(src.is(esi)); // rep movs source
12411 ASSERT(count.is(ecx)); // rep movs count 12443 ASSERT(count.is(ecx)); // rep movs count
12412 ASSERT(!scratch.is(dest)); 12444 ASSERT(!scratch.is(dest));
12413 ASSERT(!scratch.is(src)); 12445 ASSERT(!scratch.is(src));
12414 ASSERT(!scratch.is(count)); 12446 ASSERT(!scratch.is(count));
12415 12447
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
12450 __ mov_b(Operand(dest, 0), scratch); 12482 __ mov_b(Operand(dest, 0), scratch);
12451 __ add(Operand(src), Immediate(1)); 12483 __ add(Operand(src), Immediate(1));
12452 __ add(Operand(dest), Immediate(1)); 12484 __ add(Operand(dest), Immediate(1));
12453 __ sub(Operand(count), Immediate(1)); 12485 __ sub(Operand(count), Immediate(1));
12454 __ j(not_zero, &loop); 12486 __ j(not_zero, &loop);
12455 12487
12456 __ bind(&done); 12488 __ bind(&done);
12457 } 12489 }
12458 12490
12459 12491
12460 void StringStubBase::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm, 12492 void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
12461 Register c1, 12493 Register c1,
12462 Register c2, 12494 Register c2,
12463 Register scratch1, 12495 Register scratch1,
12464 Register scratch2, 12496 Register scratch2,
12465 Register scratch3, 12497 Register scratch3,
12466 Label* not_found) { 12498 Label* not_found) {
12467 // Register scratch3 is the general scratch register in this function. 12499 // Register scratch3 is the general scratch register in this function.
12468 Register scratch = scratch3; 12500 Register scratch = scratch3;
12469 12501
12470 // Make sure that both characters are not digits as such strings has a 12502 // Make sure that both characters are not digits as such strings has a
12471 // different hash algorithm. Don't try to look for these in the symbol table. 12503 // different hash algorithm. Don't try to look for these in the symbol table.
12472 Label not_array_index; 12504 Label not_array_index;
12473 __ mov(scratch, c1); 12505 __ mov(scratch, c1);
12474 __ sub(Operand(scratch), Immediate(static_cast<int>('0'))); 12506 __ sub(Operand(scratch), Immediate(static_cast<int>('0')));
12475 __ cmp(Operand(scratch), Immediate(static_cast<int>('9' - '0'))); 12507 __ cmp(Operand(scratch), Immediate(static_cast<int>('9' - '0')));
12476 __ j(above, &not_array_index); 12508 __ j(above, &not_array_index);
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
12570 // Scratch register contains result when we fall through to here. 12602 // Scratch register contains result when we fall through to here.
12571 Register result = scratch; 12603 Register result = scratch;
12572 __ bind(&found_in_symbol_table); 12604 __ bind(&found_in_symbol_table);
12573 __ pop(mask); // Pop temporally saved mask from the stack. 12605 __ pop(mask); // Pop temporally saved mask from the stack.
12574 if (!result.is(eax)) { 12606 if (!result.is(eax)) {
12575 __ mov(eax, result); 12607 __ mov(eax, result);
12576 } 12608 }
12577 } 12609 }
12578 12610
12579 12611
12580 void StringStubBase::GenerateHashInit(MacroAssembler* masm, 12612 void StringHelper::GenerateHashInit(MacroAssembler* masm,
12581 Register hash, 12613 Register hash,
12582 Register character, 12614 Register character,
12583 Register scratch) { 12615 Register scratch) {
12584 // hash = character + (character << 10); 12616 // hash = character + (character << 10);
12585 __ mov(hash, character); 12617 __ mov(hash, character);
12586 __ shl(hash, 10); 12618 __ shl(hash, 10);
12587 __ add(hash, Operand(character)); 12619 __ add(hash, Operand(character));
12588 // hash ^= hash >> 6; 12620 // hash ^= hash >> 6;
12589 __ mov(scratch, hash); 12621 __ mov(scratch, hash);
12590 __ sar(scratch, 6); 12622 __ sar(scratch, 6);
12591 __ xor_(hash, Operand(scratch)); 12623 __ xor_(hash, Operand(scratch));
12592 } 12624 }
12593 12625
12594 12626
12595 void StringStubBase::GenerateHashAddCharacter(MacroAssembler* masm, 12627 void StringHelper::GenerateHashAddCharacter(MacroAssembler* masm,
12596 Register hash, 12628 Register hash,
12597 Register character, 12629 Register character,
12598 Register scratch) { 12630 Register scratch) {
12599 // hash += character; 12631 // hash += character;
12600 __ add(hash, Operand(character)); 12632 __ add(hash, Operand(character));
12601 // hash += hash << 10; 12633 // hash += hash << 10;
12602 __ mov(scratch, hash); 12634 __ mov(scratch, hash);
12603 __ shl(scratch, 10); 12635 __ shl(scratch, 10);
12604 __ add(hash, Operand(scratch)); 12636 __ add(hash, Operand(scratch));
12605 // hash ^= hash >> 6; 12637 // hash ^= hash >> 6;
12606 __ mov(scratch, hash); 12638 __ mov(scratch, hash);
12607 __ sar(scratch, 6); 12639 __ sar(scratch, 6);
12608 __ xor_(hash, Operand(scratch)); 12640 __ xor_(hash, Operand(scratch));
12609 } 12641 }
12610 12642
12611 12643
12612 void StringStubBase::GenerateHashGetHash(MacroAssembler* masm, 12644 void StringHelper::GenerateHashGetHash(MacroAssembler* masm,
12613 Register hash, 12645 Register hash,
12614 Register scratch) { 12646 Register scratch) {
12615 // hash += hash << 3; 12647 // hash += hash << 3;
12616 __ mov(scratch, hash); 12648 __ mov(scratch, hash);
12617 __ shl(scratch, 3); 12649 __ shl(scratch, 3);
12618 __ add(hash, Operand(scratch)); 12650 __ add(hash, Operand(scratch));
12619 // hash ^= hash >> 11; 12651 // hash ^= hash >> 11;
12620 __ mov(scratch, hash); 12652 __ mov(scratch, hash);
12621 __ sar(scratch, 11); 12653 __ sar(scratch, 11);
12622 __ xor_(hash, Operand(scratch)); 12654 __ xor_(hash, Operand(scratch));
12623 // hash += hash << 15; 12655 // hash += hash << 15;
12624 __ mov(scratch, hash); 12656 __ mov(scratch, hash);
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
12678 __ JumpIfInstanceTypeIsNotSequentialAscii(ebx, ebx, &runtime); 12710 __ JumpIfInstanceTypeIsNotSequentialAscii(ebx, ebx, &runtime);
12679 12711
12680 // Get the two characters forming the sub string. 12712 // Get the two characters forming the sub string.
12681 __ SmiUntag(edx); // From index is no longer smi. 12713 __ SmiUntag(edx); // From index is no longer smi.
12682 __ movzx_b(ebx, FieldOperand(eax, edx, times_1, SeqAsciiString::kHeaderSize)); 12714 __ movzx_b(ebx, FieldOperand(eax, edx, times_1, SeqAsciiString::kHeaderSize));
12683 __ movzx_b(ecx, 12715 __ movzx_b(ecx,
12684 FieldOperand(eax, edx, times_1, SeqAsciiString::kHeaderSize + 1)); 12716 FieldOperand(eax, edx, times_1, SeqAsciiString::kHeaderSize + 1));
12685 12717
12686 // Try to lookup two character string in symbol table. 12718 // Try to lookup two character string in symbol table.
12687 Label make_two_character_string; 12719 Label make_two_character_string;
12688 GenerateTwoCharacterSymbolTableProbe(masm, ebx, ecx, eax, edx, edi, 12720 StringHelper::GenerateTwoCharacterSymbolTableProbe(
12689 &make_two_character_string); 12721 masm, ebx, ecx, eax, edx, edi, &make_two_character_string);
12690 __ ret(3 * kPointerSize); 12722 __ ret(3 * kPointerSize);
12691 12723
12692 __ bind(&make_two_character_string); 12724 __ bind(&make_two_character_string);
12693 // Setup registers for allocating the two character string. 12725 // Setup registers for allocating the two character string.
12694 __ mov(eax, Operand(esp, 3 * kPointerSize)); 12726 __ mov(eax, Operand(esp, 3 * kPointerSize));
12695 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 12727 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
12696 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); 12728 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
12697 __ Set(ecx, Immediate(2)); 12729 __ Set(ecx, Immediate(2));
12698 12730
12699 __ bind(&result_longer_than_two); 12731 __ bind(&result_longer_than_two);
(...skipping 18 matching lines...) Expand all
12718 __ add(Operand(esi), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 12750 __ add(Operand(esi), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
12719 __ mov(ebx, Operand(esp, 2 * kPointerSize)); // from 12751 __ mov(ebx, Operand(esp, 2 * kPointerSize)); // from
12720 __ SmiUntag(ebx); 12752 __ SmiUntag(ebx);
12721 __ add(esi, Operand(ebx)); 12753 __ add(esi, Operand(ebx));
12722 12754
12723 // eax: result string 12755 // eax: result string
12724 // ecx: result length 12756 // ecx: result length
12725 // edx: original value of esi 12757 // edx: original value of esi
12726 // edi: first character of result 12758 // edi: first character of result
12727 // esi: character of sub string start 12759 // esi: character of sub string start
12728 GenerateCopyCharactersREP(masm, edi, esi, ecx, ebx, true); 12760 StringHelper::GenerateCopyCharactersREP(masm, edi, esi, ecx, ebx, true);
12729 __ mov(esi, edx); // Restore esi. 12761 __ mov(esi, edx); // Restore esi.
12730 __ IncrementCounter(&Counters::sub_string_native, 1); 12762 __ IncrementCounter(&Counters::sub_string_native, 1);
12731 __ ret(3 * kPointerSize); 12763 __ ret(3 * kPointerSize);
12732 12764
12733 __ bind(&non_ascii_flat); 12765 __ bind(&non_ascii_flat);
12734 // eax: string 12766 // eax: string
12735 // ebx: instance type & kStringRepresentationMask | kStringEncodingMask 12767 // ebx: instance type & kStringRepresentationMask | kStringEncodingMask
12736 // ecx: result string length 12768 // ecx: result string length
12737 // Check for flat two byte string 12769 // Check for flat two byte string
12738 __ cmp(ebx, kSeqStringTag | kTwoByteStringTag); 12770 __ cmp(ebx, kSeqStringTag | kTwoByteStringTag);
(...skipping 18 matching lines...) Expand all
12757 // byte character. 12789 // byte character.
12758 ASSERT_EQ(0, kSmiTag); 12790 ASSERT_EQ(0, kSmiTag);
12759 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); 12791 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize);
12760 __ add(esi, Operand(ebx)); 12792 __ add(esi, Operand(ebx));
12761 12793
12762 // eax: result string 12794 // eax: result string
12763 // ecx: result length 12795 // ecx: result length
12764 // edx: original value of esi 12796 // edx: original value of esi
12765 // edi: first character of result 12797 // edi: first character of result
12766 // esi: character of sub string start 12798 // esi: character of sub string start
12767 GenerateCopyCharactersREP(masm, edi, esi, ecx, ebx, false); 12799 StringHelper::GenerateCopyCharactersREP(masm, edi, esi, ecx, ebx, false);
12768 __ mov(esi, edx); // Restore esi. 12800 __ mov(esi, edx); // Restore esi.
12769 __ IncrementCounter(&Counters::sub_string_native, 1); 12801 __ IncrementCounter(&Counters::sub_string_native, 1);
12770 __ ret(3 * kPointerSize); 12802 __ ret(3 * kPointerSize);
12771 12803
12772 // Just jump to runtime to create the sub string. 12804 // Just jump to runtime to create the sub string.
12773 __ bind(&runtime); 12805 __ bind(&runtime);
12774 __ TailCallRuntime(Runtime::kSubString, 3, 1); 12806 __ TailCallRuntime(Runtime::kSubString, 3, 1);
12775 } 12807 }
12776 12808
12777 12809
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
12888 12920
12889 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) 12921 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
12890 // tagged as a small integer. 12922 // tagged as a small integer.
12891 __ bind(&runtime); 12923 __ bind(&runtime);
12892 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 12924 __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
12893 } 12925 }
12894 12926
12895 #undef __ 12927 #undef __
12896 12928
12897 } } // namespace v8::internal 12929 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/codegen-ia32.h ('k') | src/ia32/ic-ia32.cc » ('j') | src/ia32/ic-ia32.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698