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

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

Issue 1633024: Revert r4444 "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
« no previous file with comments | « src/ia32/codegen-ia32.h ('k') | src/ia32/ic-ia32.cc » ('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 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 | kSmiSignMask)); 2351 __ test(operand->reg(), Immediate(kSmiTagMask | 0x80000000));
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 | kSmiSignMask)); 5904 __ test(value.reg(), Immediate(kSmiTagMask | 0x80000000));
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
5920 Load(args->at(0)); 5927 Load(args->at(0));
5921 Load(args->at(1)); 5928 Load(args->at(1));
5922 Result index = frame_->Pop(); 5929 Result index = frame_->Pop();
5923 Result object = frame_->Pop(); 5930 Result object = frame_->Pop();
5924 5931
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
5925 // We will mutate the index register and possibly the object register. 5957 // We will mutate the index register and possibly the object register.
5926 // The case where they are somehow the same register is handled 5958 // The case where they are somehow the same register is handled
5927 // because we only mutate them in the case where the receiver is a 5959 // because we only mutate them in the case where the receiver is a
5928 // heap object and the index is not. 5960 // heap object and the index is not.
5929 object.ToRegister(); 5961 object.ToRegister();
5930 index.ToRegister(); 5962 index.ToRegister();
5931 frame_->Spill(object.reg()); 5963 frame_->Spill(object.reg());
5932 frame_->Spill(index.reg()); 5964 frame_->Spill(index.reg());
5933 5965
5934 // We need two extra registers. 5966 // We need a single extra temporary register.
5935 Result result = allocator()->Allocate(); 5967 Result temp = allocator()->Allocate();
5936 ASSERT(result.is_valid()); 5968 ASSERT(temp.is_valid());
5937 Result scratch = allocator()->Allocate();
5938 ASSERT(scratch.is_valid());
5939 5969
5940 // There is no virtual frame effect from here up to the final result 5970 // There is no virtual frame effect from here up to the final result
5941 // push. 5971 // push.
5942 Label slow_case; 5972
5943 Label exit; 5973 // If the receiver is a smi trigger the slow case.
5944 StringHelper::GenerateFastCharCodeAt(masm_, 5974 ASSERT(kSmiTag == 0);
5945 object.reg(), 5975 __ test(object.reg(), Immediate(kSmiTagMask));
5946 index.reg(), 5976 __ j(zero, &slow_case);
5947 scratch.reg(), 5977
5948 result.reg(), 5978 // If the index is negative or non-smi trigger the slow case.
5949 &slow_case, 5979 ASSERT(kSmiTag == 0);
5950 &slow_case, 5980 __ test(index.reg(), Immediate(kSmiTagMask | 0x80000000));
5951 &slow_case); 5981 __ j(not_zero, &slow_case);
5952 __ jmp(&exit); 5982 // Untag the index.
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);
5953 6045
5954 __ bind(&slow_case); 6046 __ bind(&slow_case);
5955 // Move the undefined value into the result register, which will 6047 // Move the undefined value into the result register, which will
5956 // trigger the slow case. 6048 // trigger the slow case.
5957 __ Set(result.reg(), Immediate(Factory::undefined_value())); 6049 __ Set(temp.reg(), Immediate(Factory::undefined_value()));
5958 6050
5959 __ bind(&exit); 6051 __ bind(&end);
5960 frame_->Push(&result); 6052 frame_->Push(&temp);
5961 } 6053 }
5962 6054
5963 6055
5964 void CodeGenerator::GenerateCharFromCode(ZoneList<Expression*>* args) { 6056 void CodeGenerator::GenerateCharFromCode(ZoneList<Expression*>* args) {
5965 Comment(masm_, "[ GenerateCharFromCode"); 6057 Comment(masm_, "[ GenerateCharFromCode");
5966 ASSERT(args->length() == 1); 6058 ASSERT(args->length() == 1);
5967 6059
5968 Load(args->at(0)); 6060 Load(args->at(0));
5969
5970 Result code = frame_->Pop(); 6061 Result code = frame_->Pop();
5971 code.ToRegister(); 6062 code.ToRegister();
5972 ASSERT(code.is_valid()); 6063 ASSERT(code.is_valid());
5973 6064
5974 // StringHelper::GenerateCharFromCode may do a runtime call. 6065 Result temp = allocator()->Allocate();
5975 frame_->SpillAll(); 6066 ASSERT(temp.is_valid());
5976 6067
5977 Result result = allocator()->Allocate(); 6068 JumpTarget slow_case;
5978 ASSERT(result.is_valid()); 6069 JumpTarget exit;
5979 6070
5980 StringHelper::GenerateCharFromCode(masm_, 6071 // Fast case of Heap::LookupSingleCharacterStringFromCode.
5981 code.reg(), 6072 ASSERT(kSmiTag == 0);
5982 result.reg(), 6073 ASSERT(kSmiShiftSize == 0);
5983 CALL_FUNCTION); 6074 ASSERT(IsPowerOf2(String::kMaxAsciiCharCode + 1));
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);
5984 frame_->Push(&result); 6098 frame_->Push(&result);
6099
6100 exit.Bind();
5985 } 6101 }
5986 6102
5987 6103
5988 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) { 6104 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) {
5989 ASSERT(args->length() == 1); 6105 ASSERT(args->length() == 1);
5990 Load(args->at(0)); 6106 Load(args->at(0));
5991 Result value = frame_->Pop(); 6107 Result value = frame_->Pop();
5992 value.ToRegister(); 6108 value.ToRegister();
5993 ASSERT(value.is_valid()); 6109 ASSERT(value.is_valid());
5994 __ test(value.reg(), Immediate(kSmiTagMask)); 6110 __ test(value.reg(), Immediate(kSmiTagMask));
(...skipping 2404 matching lines...) Expand 10 before | Expand all | Expand 10 after
8399 tmp.reg()); 8515 tmp.reg());
8400 8516
8401 // Check that the value is a smi if it is not a constant. We can skip 8517 // Check that the value is a smi if it is not a constant. We can skip
8402 // the write barrier for smis and constants. 8518 // the write barrier for smis and constants.
8403 if (!value_is_constant) { 8519 if (!value_is_constant) {
8404 __ test(result.reg(), Immediate(kSmiTagMask)); 8520 __ test(result.reg(), Immediate(kSmiTagMask));
8405 deferred->Branch(not_zero); 8521 deferred->Branch(not_zero);
8406 } 8522 }
8407 8523
8408 // Check that the key is a non-negative smi. 8524 // Check that the key is a non-negative smi.
8409 __ test(key.reg(), Immediate(kSmiTagMask | kSmiSignMask)); 8525 __ test(key.reg(), Immediate(kSmiTagMask | 0x80000000));
8410 deferred->Branch(not_zero); 8526 deferred->Branch(not_zero);
8411 8527
8412 // Check that the receiver is not a smi. 8528 // Check that the receiver is not a smi.
8413 __ test(receiver.reg(), Immediate(kSmiTagMask)); 8529 __ test(receiver.reg(), Immediate(kSmiTagMask));
8414 deferred->Branch(zero); 8530 deferred->Branch(zero);
8415 8531
8416 // Check that the receiver is a JSArray. 8532 // Check that the receiver is a JSArray.
8417 __ mov(tmp.reg(), 8533 __ mov(tmp.reg(),
8418 FieldOperand(receiver.reg(), HeapObject::kMapOffset)); 8534 FieldOperand(receiver.reg(), HeapObject::kMapOffset));
8419 __ movzx_b(tmp.reg(), 8535 __ movzx_b(tmp.reg(),
(...skipping 3611 matching lines...) Expand 10 before | Expand all | Expand 10 after
12031 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), 12147 OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
12032 "CompareStub_%s%s%s%s", 12148 "CompareStub_%s%s%s%s",
12033 cc_name, 12149 cc_name,
12034 strict_name, 12150 strict_name,
12035 never_nan_nan_name, 12151 never_nan_nan_name,
12036 include_number_compare_name); 12152 include_number_compare_name);
12037 return name_; 12153 return name_;
12038 } 12154 }
12039 12155
12040 12156
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
12189 void StringAddStub::Generate(MacroAssembler* masm) { 12157 void StringAddStub::Generate(MacroAssembler* masm) {
12190 Label string_add_runtime; 12158 Label string_add_runtime;
12191 12159
12192 // Load the two arguments. 12160 // Load the two arguments.
12193 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument. 12161 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument.
12194 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument. 12162 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument.
12195 12163
12196 // Make sure that both arguments are strings if not known in advance. 12164 // Make sure that both arguments are strings if not known in advance.
12197 if (string_check_) { 12165 if (string_check_) {
12198 __ test(eax, Immediate(kSmiTagMask)); 12166 __ test(eax, Immediate(kSmiTagMask));
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
12245 __ JumpIfNotBothSequentialAsciiStrings(eax, edx, ebx, ecx, 12213 __ JumpIfNotBothSequentialAsciiStrings(eax, edx, ebx, ecx,
12246 &string_add_runtime); 12214 &string_add_runtime);
12247 12215
12248 // Get the two characters forming the sub string. 12216 // Get the two characters forming the sub string.
12249 __ movzx_b(ebx, FieldOperand(eax, SeqAsciiString::kHeaderSize)); 12217 __ movzx_b(ebx, FieldOperand(eax, SeqAsciiString::kHeaderSize));
12250 __ movzx_b(ecx, FieldOperand(edx, SeqAsciiString::kHeaderSize)); 12218 __ movzx_b(ecx, FieldOperand(edx, SeqAsciiString::kHeaderSize));
12251 12219
12252 // Try to lookup two character string in symbol table. If it is not found 12220 // Try to lookup two character string in symbol table. If it is not found
12253 // just allocate a new one. 12221 // just allocate a new one.
12254 Label make_two_character_string, make_flat_ascii_string; 12222 Label make_two_character_string, make_flat_ascii_string;
12255 StringHelper::GenerateTwoCharacterSymbolTableProbe( 12223 GenerateTwoCharacterSymbolTableProbe(masm, ebx, ecx, eax, edx, edi,
12256 masm, ebx, ecx, eax, edx, edi, &make_two_character_string); 12224 &make_two_character_string);
12257 __ IncrementCounter(&Counters::string_add_native, 1); 12225 __ IncrementCounter(&Counters::string_add_native, 1);
12258 __ ret(2 * kPointerSize); 12226 __ ret(2 * kPointerSize);
12259 12227
12260 __ bind(&make_two_character_string); 12228 __ bind(&make_two_character_string);
12261 __ Set(ebx, Immediate(2)); 12229 __ Set(ebx, Immediate(2));
12262 __ jmp(&make_flat_ascii_string); 12230 __ jmp(&make_flat_ascii_string);
12263 12231
12264 __ bind(&longer_than_two); 12232 __ bind(&longer_than_two);
12265 // Check if resulting string will be flat. 12233 // Check if resulting string will be flat.
12266 __ cmp(ebx, String::kMinNonFlatLength); 12234 __ cmp(ebx, String::kMinNonFlatLength);
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
12338 // Locate first character of result. 12306 // Locate first character of result.
12339 __ add(Operand(ecx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 12307 __ add(Operand(ecx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
12340 // Load first argument and locate first character. 12308 // Load first argument and locate first character.
12341 __ mov(edx, Operand(esp, 2 * kPointerSize)); 12309 __ mov(edx, Operand(esp, 2 * kPointerSize));
12342 __ mov(edi, FieldOperand(edx, String::kLengthOffset)); 12310 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
12343 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 12311 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
12344 // eax: result string 12312 // eax: result string
12345 // ecx: first character of result 12313 // ecx: first character of result
12346 // edx: first char of first argument 12314 // edx: first char of first argument
12347 // edi: length of first argument 12315 // edi: length of first argument
12348 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true); 12316 GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true);
12349 // Load second argument and locate first character. 12317 // Load second argument and locate first character.
12350 __ mov(edx, Operand(esp, 1 * kPointerSize)); 12318 __ mov(edx, Operand(esp, 1 * kPointerSize));
12351 __ mov(edi, FieldOperand(edx, String::kLengthOffset)); 12319 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
12352 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 12320 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
12353 // eax: result string 12321 // eax: result string
12354 // ecx: next character of result 12322 // ecx: next character of result
12355 // edx: first char of second argument 12323 // edx: first char of second argument
12356 // edi: length of second argument 12324 // edi: length of second argument
12357 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true); 12325 GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true);
12358 __ IncrementCounter(&Counters::string_add_native, 1); 12326 __ IncrementCounter(&Counters::string_add_native, 1);
12359 __ ret(2 * kPointerSize); 12327 __ ret(2 * kPointerSize);
12360 12328
12361 // Handle creating a flat two byte result. 12329 // Handle creating a flat two byte result.
12362 // eax: first string - known to be two byte 12330 // eax: first string - known to be two byte
12363 // ebx: length of resulting flat string 12331 // ebx: length of resulting flat string
12364 // edx: second string 12332 // edx: second string
12365 __ bind(&non_ascii_string_add_flat_result); 12333 __ bind(&non_ascii_string_add_flat_result);
12366 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 12334 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
12367 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 12335 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
12368 __ and_(ecx, kAsciiStringTag); 12336 __ and_(ecx, kAsciiStringTag);
12369 __ j(not_zero, &string_add_runtime); 12337 __ j(not_zero, &string_add_runtime);
12370 // Both strings are two byte strings. As they are short they are both 12338 // Both strings are two byte strings. As they are short they are both
12371 // flat. 12339 // flat.
12372 __ AllocateTwoByteString(eax, ebx, ecx, edx, edi, &string_add_runtime); 12340 __ AllocateTwoByteString(eax, ebx, ecx, edx, edi, &string_add_runtime);
12373 // eax: result string 12341 // eax: result string
12374 __ mov(ecx, eax); 12342 __ mov(ecx, eax);
12375 // Locate first character of result. 12343 // Locate first character of result.
12376 __ add(Operand(ecx), 12344 __ add(Operand(ecx),
12377 Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 12345 Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
12378 // Load first argument and locate first character. 12346 // Load first argument and locate first character.
12379 __ mov(edx, Operand(esp, 2 * kPointerSize)); 12347 __ mov(edx, Operand(esp, 2 * kPointerSize));
12380 __ mov(edi, FieldOperand(edx, String::kLengthOffset)); 12348 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
12381 __ add(Operand(edx), 12349 __ add(Operand(edx),
12382 Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 12350 Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
12383 // eax: result string 12351 // eax: result string
12384 // ecx: first character of result 12352 // ecx: first character of result
12385 // edx: first char of first argument 12353 // edx: first char of first argument
12386 // edi: length of first argument 12354 // edi: length of first argument
12387 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false); 12355 GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false);
12388 // Load second argument and locate first character. 12356 // Load second argument and locate first character.
12389 __ mov(edx, Operand(esp, 1 * kPointerSize)); 12357 __ mov(edx, Operand(esp, 1 * kPointerSize));
12390 __ mov(edi, FieldOperand(edx, String::kLengthOffset)); 12358 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
12391 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 12359 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
12392 // eax: result string 12360 // eax: result string
12393 // ecx: next character of result 12361 // ecx: next character of result
12394 // edx: first char of second argument 12362 // edx: first char of second argument
12395 // edi: length of second argument 12363 // edi: length of second argument
12396 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false); 12364 GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false);
12397 __ IncrementCounter(&Counters::string_add_native, 1); 12365 __ IncrementCounter(&Counters::string_add_native, 1);
12398 __ ret(2 * kPointerSize); 12366 __ ret(2 * kPointerSize);
12399 12367
12400 // Just jump to runtime to add the two strings. 12368 // Just jump to runtime to add the two strings.
12401 __ bind(&string_add_runtime); 12369 __ bind(&string_add_runtime);
12402 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); 12370 __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
12403 } 12371 }
12404 12372
12405 12373
12406 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm, 12374 void StringStubBase::GenerateCopyCharacters(MacroAssembler* masm,
12407 Register dest, 12375 Register dest,
12408 Register src, 12376 Register src,
12409 Register count, 12377 Register count,
12410 Register scratch, 12378 Register scratch,
12411 bool ascii) { 12379 bool ascii) {
12412 Label loop; 12380 Label loop;
12413 __ bind(&loop); 12381 __ bind(&loop);
12414 // This loop just copies one character at a time, as it is only used for very 12382 // This loop just copies one character at a time, as it is only used for very
12415 // short strings. 12383 // short strings.
12416 if (ascii) { 12384 if (ascii) {
12417 __ mov_b(scratch, Operand(src, 0)); 12385 __ mov_b(scratch, Operand(src, 0));
12418 __ mov_b(Operand(dest, 0), scratch); 12386 __ mov_b(Operand(dest, 0), scratch);
12419 __ add(Operand(src), Immediate(1)); 12387 __ add(Operand(src), Immediate(1));
12420 __ add(Operand(dest), Immediate(1)); 12388 __ add(Operand(dest), Immediate(1));
12421 } else { 12389 } else {
12422 __ mov_w(scratch, Operand(src, 0)); 12390 __ mov_w(scratch, Operand(src, 0));
12423 __ mov_w(Operand(dest, 0), scratch); 12391 __ mov_w(Operand(dest, 0), scratch);
12424 __ add(Operand(src), Immediate(2)); 12392 __ add(Operand(src), Immediate(2));
12425 __ add(Operand(dest), Immediate(2)); 12393 __ add(Operand(dest), Immediate(2));
12426 } 12394 }
12427 __ sub(Operand(count), Immediate(1)); 12395 __ sub(Operand(count), Immediate(1));
12428 __ j(not_zero, &loop); 12396 __ j(not_zero, &loop);
12429 } 12397 }
12430 12398
12431 12399
12432 void StringHelper::GenerateCopyCharactersREP(MacroAssembler* masm, 12400 void StringStubBase::GenerateCopyCharactersREP(MacroAssembler* masm,
12433 Register dest, 12401 Register dest,
12434 Register src, 12402 Register src,
12435 Register count, 12403 Register count,
12436 Register scratch, 12404 Register scratch,
12437 bool ascii) { 12405 bool ascii) {
12438 // Copy characters using rep movs of doublewords. Align destination on 4 byte 12406 // Copy characters using rep movs of doublewords. Align destination on 4 byte
12439 // boundary before starting rep movs. Copy remaining characters after running 12407 // boundary before starting rep movs. Copy remaining characters after running
12440 // rep movs. 12408 // rep movs.
12441 ASSERT(dest.is(edi)); // rep movs destination 12409 ASSERT(dest.is(edi)); // rep movs destination
12442 ASSERT(src.is(esi)); // rep movs source 12410 ASSERT(src.is(esi)); // rep movs source
12443 ASSERT(count.is(ecx)); // rep movs count 12411 ASSERT(count.is(ecx)); // rep movs count
12444 ASSERT(!scratch.is(dest)); 12412 ASSERT(!scratch.is(dest));
12445 ASSERT(!scratch.is(src)); 12413 ASSERT(!scratch.is(src));
12446 ASSERT(!scratch.is(count)); 12414 ASSERT(!scratch.is(count));
12447 12415
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
12482 __ mov_b(Operand(dest, 0), scratch); 12450 __ mov_b(Operand(dest, 0), scratch);
12483 __ add(Operand(src), Immediate(1)); 12451 __ add(Operand(src), Immediate(1));
12484 __ add(Operand(dest), Immediate(1)); 12452 __ add(Operand(dest), Immediate(1));
12485 __ sub(Operand(count), Immediate(1)); 12453 __ sub(Operand(count), Immediate(1));
12486 __ j(not_zero, &loop); 12454 __ j(not_zero, &loop);
12487 12455
12488 __ bind(&done); 12456 __ bind(&done);
12489 } 12457 }
12490 12458
12491 12459
12492 void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm, 12460 void StringStubBase::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
12493 Register c1, 12461 Register c1,
12494 Register c2, 12462 Register c2,
12495 Register scratch1, 12463 Register scratch1,
12496 Register scratch2, 12464 Register scratch2,
12497 Register scratch3, 12465 Register scratch3,
12498 Label* not_found) { 12466 Label* not_found) {
12499 // Register scratch3 is the general scratch register in this function. 12467 // Register scratch3 is the general scratch register in this function.
12500 Register scratch = scratch3; 12468 Register scratch = scratch3;
12501 12469
12502 // Make sure that both characters are not digits as such strings has a 12470 // Make sure that both characters are not digits as such strings has a
12503 // different hash algorithm. Don't try to look for these in the symbol table. 12471 // different hash algorithm. Don't try to look for these in the symbol table.
12504 Label not_array_index; 12472 Label not_array_index;
12505 __ mov(scratch, c1); 12473 __ mov(scratch, c1);
12506 __ sub(Operand(scratch), Immediate(static_cast<int>('0'))); 12474 __ sub(Operand(scratch), Immediate(static_cast<int>('0')));
12507 __ cmp(Operand(scratch), Immediate(static_cast<int>('9' - '0'))); 12475 __ cmp(Operand(scratch), Immediate(static_cast<int>('9' - '0')));
12508 __ j(above, &not_array_index); 12476 __ j(above, &not_array_index);
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
12602 // Scratch register contains result when we fall through to here. 12570 // Scratch register contains result when we fall through to here.
12603 Register result = scratch; 12571 Register result = scratch;
12604 __ bind(&found_in_symbol_table); 12572 __ bind(&found_in_symbol_table);
12605 __ pop(mask); // Pop temporally saved mask from the stack. 12573 __ pop(mask); // Pop temporally saved mask from the stack.
12606 if (!result.is(eax)) { 12574 if (!result.is(eax)) {
12607 __ mov(eax, result); 12575 __ mov(eax, result);
12608 } 12576 }
12609 } 12577 }
12610 12578
12611 12579
12612 void StringHelper::GenerateHashInit(MacroAssembler* masm, 12580 void StringStubBase::GenerateHashInit(MacroAssembler* masm,
12613 Register hash, 12581 Register hash,
12614 Register character, 12582 Register character,
12615 Register scratch) { 12583 Register scratch) {
12616 // hash = character + (character << 10); 12584 // hash = character + (character << 10);
12617 __ mov(hash, character); 12585 __ mov(hash, character);
12618 __ shl(hash, 10); 12586 __ shl(hash, 10);
12619 __ add(hash, Operand(character)); 12587 __ add(hash, Operand(character));
12620 // hash ^= hash >> 6; 12588 // hash ^= hash >> 6;
12621 __ mov(scratch, hash); 12589 __ mov(scratch, hash);
12622 __ sar(scratch, 6); 12590 __ sar(scratch, 6);
12623 __ xor_(hash, Operand(scratch)); 12591 __ xor_(hash, Operand(scratch));
12624 } 12592 }
12625 12593
12626 12594
12627 void StringHelper::GenerateHashAddCharacter(MacroAssembler* masm, 12595 void StringStubBase::GenerateHashAddCharacter(MacroAssembler* masm,
12628 Register hash, 12596 Register hash,
12629 Register character, 12597 Register character,
12630 Register scratch) { 12598 Register scratch) {
12631 // hash += character; 12599 // hash += character;
12632 __ add(hash, Operand(character)); 12600 __ add(hash, Operand(character));
12633 // hash += hash << 10; 12601 // hash += hash << 10;
12634 __ mov(scratch, hash); 12602 __ mov(scratch, hash);
12635 __ shl(scratch, 10); 12603 __ shl(scratch, 10);
12636 __ add(hash, Operand(scratch)); 12604 __ add(hash, Operand(scratch));
12637 // hash ^= hash >> 6; 12605 // hash ^= hash >> 6;
12638 __ mov(scratch, hash); 12606 __ mov(scratch, hash);
12639 __ sar(scratch, 6); 12607 __ sar(scratch, 6);
12640 __ xor_(hash, Operand(scratch)); 12608 __ xor_(hash, Operand(scratch));
12641 } 12609 }
12642 12610
12643 12611
12644 void StringHelper::GenerateHashGetHash(MacroAssembler* masm, 12612 void StringStubBase::GenerateHashGetHash(MacroAssembler* masm,
12645 Register hash, 12613 Register hash,
12646 Register scratch) { 12614 Register scratch) {
12647 // hash += hash << 3; 12615 // hash += hash << 3;
12648 __ mov(scratch, hash); 12616 __ mov(scratch, hash);
12649 __ shl(scratch, 3); 12617 __ shl(scratch, 3);
12650 __ add(hash, Operand(scratch)); 12618 __ add(hash, Operand(scratch));
12651 // hash ^= hash >> 11; 12619 // hash ^= hash >> 11;
12652 __ mov(scratch, hash); 12620 __ mov(scratch, hash);
12653 __ sar(scratch, 11); 12621 __ sar(scratch, 11);
12654 __ xor_(hash, Operand(scratch)); 12622 __ xor_(hash, Operand(scratch));
12655 // hash += hash << 15; 12623 // hash += hash << 15;
12656 __ mov(scratch, hash); 12624 __ mov(scratch, hash);
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
12710 __ JumpIfInstanceTypeIsNotSequentialAscii(ebx, ebx, &runtime); 12678 __ JumpIfInstanceTypeIsNotSequentialAscii(ebx, ebx, &runtime);
12711 12679
12712 // Get the two characters forming the sub string. 12680 // Get the two characters forming the sub string.
12713 __ SmiUntag(edx); // From index is no longer smi. 12681 __ SmiUntag(edx); // From index is no longer smi.
12714 __ movzx_b(ebx, FieldOperand(eax, edx, times_1, SeqAsciiString::kHeaderSize)); 12682 __ movzx_b(ebx, FieldOperand(eax, edx, times_1, SeqAsciiString::kHeaderSize));
12715 __ movzx_b(ecx, 12683 __ movzx_b(ecx,
12716 FieldOperand(eax, edx, times_1, SeqAsciiString::kHeaderSize + 1)); 12684 FieldOperand(eax, edx, times_1, SeqAsciiString::kHeaderSize + 1));
12717 12685
12718 // Try to lookup two character string in symbol table. 12686 // Try to lookup two character string in symbol table.
12719 Label make_two_character_string; 12687 Label make_two_character_string;
12720 StringHelper::GenerateTwoCharacterSymbolTableProbe( 12688 GenerateTwoCharacterSymbolTableProbe(masm, ebx, ecx, eax, edx, edi,
12721 masm, ebx, ecx, eax, edx, edi, &make_two_character_string); 12689 &make_two_character_string);
12722 __ ret(3 * kPointerSize); 12690 __ ret(3 * kPointerSize);
12723 12691
12724 __ bind(&make_two_character_string); 12692 __ bind(&make_two_character_string);
12725 // Setup registers for allocating the two character string. 12693 // Setup registers for allocating the two character string.
12726 __ mov(eax, Operand(esp, 3 * kPointerSize)); 12694 __ mov(eax, Operand(esp, 3 * kPointerSize));
12727 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 12695 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
12728 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); 12696 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
12729 __ Set(ecx, Immediate(2)); 12697 __ Set(ecx, Immediate(2));
12730 12698
12731 __ bind(&result_longer_than_two); 12699 __ bind(&result_longer_than_two);
(...skipping 18 matching lines...) Expand all
12750 __ add(Operand(esi), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 12718 __ add(Operand(esi), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
12751 __ mov(ebx, Operand(esp, 2 * kPointerSize)); // from 12719 __ mov(ebx, Operand(esp, 2 * kPointerSize)); // from
12752 __ SmiUntag(ebx); 12720 __ SmiUntag(ebx);
12753 __ add(esi, Operand(ebx)); 12721 __ add(esi, Operand(ebx));
12754 12722
12755 // eax: result string 12723 // eax: result string
12756 // ecx: result length 12724 // ecx: result length
12757 // edx: original value of esi 12725 // edx: original value of esi
12758 // edi: first character of result 12726 // edi: first character of result
12759 // esi: character of sub string start 12727 // esi: character of sub string start
12760 StringHelper::GenerateCopyCharactersREP(masm, edi, esi, ecx, ebx, true); 12728 GenerateCopyCharactersREP(masm, edi, esi, ecx, ebx, true);
12761 __ mov(esi, edx); // Restore esi. 12729 __ mov(esi, edx); // Restore esi.
12762 __ IncrementCounter(&Counters::sub_string_native, 1); 12730 __ IncrementCounter(&Counters::sub_string_native, 1);
12763 __ ret(3 * kPointerSize); 12731 __ ret(3 * kPointerSize);
12764 12732
12765 __ bind(&non_ascii_flat); 12733 __ bind(&non_ascii_flat);
12766 // eax: string 12734 // eax: string
12767 // ebx: instance type & kStringRepresentationMask | kStringEncodingMask 12735 // ebx: instance type & kStringRepresentationMask | kStringEncodingMask
12768 // ecx: result string length 12736 // ecx: result string length
12769 // Check for flat two byte string 12737 // Check for flat two byte string
12770 __ cmp(ebx, kSeqStringTag | kTwoByteStringTag); 12738 __ cmp(ebx, kSeqStringTag | kTwoByteStringTag);
(...skipping 18 matching lines...) Expand all
12789 // byte character. 12757 // byte character.
12790 ASSERT_EQ(0, kSmiTag); 12758 ASSERT_EQ(0, kSmiTag);
12791 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); 12759 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize);
12792 __ add(esi, Operand(ebx)); 12760 __ add(esi, Operand(ebx));
12793 12761
12794 // eax: result string 12762 // eax: result string
12795 // ecx: result length 12763 // ecx: result length
12796 // edx: original value of esi 12764 // edx: original value of esi
12797 // edi: first character of result 12765 // edi: first character of result
12798 // esi: character of sub string start 12766 // esi: character of sub string start
12799 StringHelper::GenerateCopyCharactersREP(masm, edi, esi, ecx, ebx, false); 12767 GenerateCopyCharactersREP(masm, edi, esi, ecx, ebx, false);
12800 __ mov(esi, edx); // Restore esi. 12768 __ mov(esi, edx); // Restore esi.
12801 __ IncrementCounter(&Counters::sub_string_native, 1); 12769 __ IncrementCounter(&Counters::sub_string_native, 1);
12802 __ ret(3 * kPointerSize); 12770 __ ret(3 * kPointerSize);
12803 12771
12804 // Just jump to runtime to create the sub string. 12772 // Just jump to runtime to create the sub string.
12805 __ bind(&runtime); 12773 __ bind(&runtime);
12806 __ TailCallRuntime(Runtime::kSubString, 3, 1); 12774 __ TailCallRuntime(Runtime::kSubString, 3, 1);
12807 } 12775 }
12808 12776
12809 12777
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
12920 12888
12921 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) 12889 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
12922 // tagged as a small integer. 12890 // tagged as a small integer.
12923 __ bind(&runtime); 12891 __ bind(&runtime);
12924 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 12892 __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
12925 } 12893 }
12926 12894
12927 #undef __ 12895 #undef __
12928 12896
12929 } } // namespace v8::internal 12897 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/codegen-ia32.h ('k') | src/ia32/ic-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698