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