OLD | NEW |
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 Loading... |
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 Loading... |
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, ¬_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(¬_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 Loading... |
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 Loading... |
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, ¬_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(¬_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 Loading... |
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 Loading... |
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 Loading... |
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, ¬_array_index); | 12508 __ j(above, ¬_array_index); |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |