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

Side by Side Diff: src/arm/code-stubs-arm.cc

Issue 6960009: Version 3.3.5 (Closed) Base URL: https://v8.googlecode.com/svn/trunk
Patch Set: Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/arm/code-stubs-arm.h ('k') | src/arm/ic-arm.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 1550 matching lines...) Expand 10 before | Expand all | Expand 10 after
1561 EmitCheckForSymbolsOrObjects(masm, lhs_, rhs_, &flat_string_check, &slow); 1561 EmitCheckForSymbolsOrObjects(masm, lhs_, rhs_, &flat_string_check, &slow);
1562 } 1562 }
1563 1563
1564 // Check for both being sequential ASCII strings, and inline if that is the 1564 // Check for both being sequential ASCII strings, and inline if that is the
1565 // case. 1565 // case.
1566 __ bind(&flat_string_check); 1566 __ bind(&flat_string_check);
1567 1567
1568 __ JumpIfNonSmisNotBothSequentialAsciiStrings(lhs_, rhs_, r2, r3, &slow); 1568 __ JumpIfNonSmisNotBothSequentialAsciiStrings(lhs_, rhs_, r2, r3, &slow);
1569 1569
1570 __ IncrementCounter(isolate->counters()->string_compare_native(), 1, r2, r3); 1570 __ IncrementCounter(isolate->counters()->string_compare_native(), 1, r2, r3);
1571 StringCompareStub::GenerateCompareFlatAsciiStrings(masm, 1571 if (cc_ == eq) {
1572 StringCompareStub::GenerateFlatAsciiStringEquals(masm,
1572 lhs_, 1573 lhs_,
1573 rhs_, 1574 rhs_,
1574 r2, 1575 r2,
1575 r3, 1576 r3,
1576 r4, 1577 r4);
1577 r5); 1578 } else {
1579 StringCompareStub::GenerateCompareFlatAsciiStrings(masm,
1580 lhs_,
1581 rhs_,
1582 r2,
1583 r3,
1584 r4,
1585 r5);
1586 }
1578 // Never falls through to here. 1587 // Never falls through to here.
1579 1588
1580 __ bind(&slow); 1589 __ bind(&slow);
1581 1590
1582 __ Push(lhs_, rhs_); 1591 __ Push(lhs_, rhs_);
1583 // Figure out which native to call and setup the arguments. 1592 // Figure out which native to call and setup the arguments.
1584 Builtins::JavaScript native; 1593 Builtins::JavaScript native;
1585 if (cc_ == eq) { 1594 if (cc_ == eq) {
1586 native = strict_ ? Builtins::STRICT_EQUALS : Builtins::EQUALS; 1595 native = strict_ ? Builtins::STRICT_EQUALS : Builtins::EQUALS;
1587 } else { 1596 } else {
(...skipping 3797 matching lines...) Expand 10 before | Expand all | Expand 10 after
5385 __ IncrementCounter(counters->sub_string_native(), 1, r3, r4); 5394 __ IncrementCounter(counters->sub_string_native(), 1, r3, r4);
5386 __ add(sp, sp, Operand(3 * kPointerSize)); 5395 __ add(sp, sp, Operand(3 * kPointerSize));
5387 __ Ret(); 5396 __ Ret();
5388 5397
5389 // Just jump to runtime to create the sub string. 5398 // Just jump to runtime to create the sub string.
5390 __ bind(&runtime); 5399 __ bind(&runtime);
5391 __ TailCallRuntime(Runtime::kSubString, 3, 1); 5400 __ TailCallRuntime(Runtime::kSubString, 3, 1);
5392 } 5401 }
5393 5402
5394 5403
5404 void StringCompareStub::GenerateFlatAsciiStringEquals(MacroAssembler* masm,
5405 Register left,
5406 Register right,
5407 Register scratch1,
5408 Register scratch2,
5409 Register scratch3) {
5410 Register length = scratch1;
5411
5412 // Compare lengths.
5413 Label strings_not_equal, check_zero_length;
5414 __ ldr(length, FieldMemOperand(left, String::kLengthOffset));
5415 __ ldr(scratch2, FieldMemOperand(right, String::kLengthOffset));
5416 __ cmp(length, scratch2);
5417 __ b(eq, &check_zero_length);
5418 __ bind(&strings_not_equal);
5419 __ mov(r0, Operand(Smi::FromInt(NOT_EQUAL)));
5420 __ Ret();
5421
5422 // Check if the length is zero.
5423 Label compare_chars;
5424 __ bind(&check_zero_length);
5425 STATIC_ASSERT(kSmiTag == 0);
5426 __ tst(length, Operand(length));
5427 __ b(ne, &compare_chars);
5428 __ mov(r0, Operand(Smi::FromInt(EQUAL)));
5429 __ Ret();
5430
5431 // Compare characters.
5432 __ bind(&compare_chars);
5433 GenerateAsciiCharsCompareLoop(masm,
5434 left, right, length, scratch2, scratch3,
5435 &strings_not_equal);
5436
5437 // Characters are equal.
5438 __ mov(r0, Operand(Smi::FromInt(EQUAL)));
5439 __ Ret();
5440 }
5441
5442
5395 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, 5443 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
5396 Register left, 5444 Register left,
5397 Register right, 5445 Register right,
5398 Register scratch1, 5446 Register scratch1,
5399 Register scratch2, 5447 Register scratch2,
5400 Register scratch3, 5448 Register scratch3,
5401 Register scratch4) { 5449 Register scratch4) {
5402 Label compare_lengths; 5450 Label result_not_equal, compare_lengths;
5403 // Find minimum length and length difference. 5451 // Find minimum length and length difference.
5404 __ ldr(scratch1, FieldMemOperand(left, String::kLengthOffset)); 5452 __ ldr(scratch1, FieldMemOperand(left, String::kLengthOffset));
5405 __ ldr(scratch2, FieldMemOperand(right, String::kLengthOffset)); 5453 __ ldr(scratch2, FieldMemOperand(right, String::kLengthOffset));
5406 __ sub(scratch3, scratch1, Operand(scratch2), SetCC); 5454 __ sub(scratch3, scratch1, Operand(scratch2), SetCC);
5407 Register length_delta = scratch3; 5455 Register length_delta = scratch3;
5408 __ mov(scratch1, scratch2, LeaveCC, gt); 5456 __ mov(scratch1, scratch2, LeaveCC, gt);
5409 Register min_length = scratch1; 5457 Register min_length = scratch1;
5410 STATIC_ASSERT(kSmiTag == 0); 5458 STATIC_ASSERT(kSmiTag == 0);
5411 __ tst(min_length, Operand(min_length)); 5459 __ tst(min_length, Operand(min_length));
5412 __ b(eq, &compare_lengths); 5460 __ b(eq, &compare_lengths);
5413 5461
5414 // Untag smi. 5462 // Compare loop.
5415 __ mov(min_length, Operand(min_length, ASR, kSmiTagSize)); 5463 GenerateAsciiCharsCompareLoop(masm,
5464 left, right, min_length, scratch2, scratch4,
5465 &result_not_equal);
5416 5466
5417 // Setup registers so that we only need to increment one register 5467 // Compare lengths - strings up to min-length are equal.
5418 // in the loop.
5419 __ add(scratch2, min_length,
5420 Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
5421 __ add(left, left, Operand(scratch2));
5422 __ add(right, right, Operand(scratch2));
5423 // Registers left and right points to the min_length character of strings.
5424 __ rsb(min_length, min_length, Operand(-1));
5425 Register index = min_length;
5426 // Index starts at -min_length.
5427
5428 {
5429 // Compare loop.
5430 Label loop;
5431 __ bind(&loop);
5432 // Compare characters.
5433 __ add(index, index, Operand(1), SetCC);
5434 __ ldrb(scratch2, MemOperand(left, index), ne);
5435 __ ldrb(scratch4, MemOperand(right, index), ne);
5436 // Skip to compare lengths with eq condition true.
5437 __ b(eq, &compare_lengths);
5438 __ cmp(scratch2, scratch4);
5439 __ b(eq, &loop);
5440 // Fallthrough with eq condition false.
5441 }
5442 // Compare lengths - strings up to min-length are equal.
5443 __ bind(&compare_lengths); 5468 __ bind(&compare_lengths);
5444 ASSERT(Smi::FromInt(EQUAL) == static_cast<Smi*>(0)); 5469 ASSERT(Smi::FromInt(EQUAL) == static_cast<Smi*>(0));
5445 // Use zero length_delta as result. 5470 // Use length_delta as result if it's zero.
5446 __ mov(r0, Operand(length_delta), SetCC, eq); 5471 __ mov(r0, Operand(length_delta), SetCC);
5447 // Fall through to here if characters compare not-equal. 5472 __ bind(&result_not_equal);
5473 // Conditionally update the result based either on length_delta or
5474 // the last comparion performed in the loop above.
5448 __ mov(r0, Operand(Smi::FromInt(GREATER)), LeaveCC, gt); 5475 __ mov(r0, Operand(Smi::FromInt(GREATER)), LeaveCC, gt);
5449 __ mov(r0, Operand(Smi::FromInt(LESS)), LeaveCC, lt); 5476 __ mov(r0, Operand(Smi::FromInt(LESS)), LeaveCC, lt);
5450 __ Ret(); 5477 __ Ret();
5451 } 5478 }
5452 5479
5453 5480
5481 void StringCompareStub::GenerateAsciiCharsCompareLoop(
5482 MacroAssembler* masm,
5483 Register left,
5484 Register right,
5485 Register length,
5486 Register scratch1,
5487 Register scratch2,
5488 Label* chars_not_equal) {
5489 // Change index to run from -length to -1 by adding length to string
5490 // start. This means that loop ends when index reaches zero, which
5491 // doesn't need an additional compare.
5492 __ SmiUntag(length);
5493 __ add(scratch1, length,
5494 Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
5495 __ add(left, left, Operand(scratch1));
5496 __ add(right, right, Operand(scratch1));
5497 __ rsb(length, length, Operand(0));
5498 Register index = length; // index = -length;
5499
5500 // Compare loop.
5501 Label loop;
5502 __ bind(&loop);
5503 __ ldrb(scratch1, MemOperand(left, index));
5504 __ ldrb(scratch2, MemOperand(right, index));
5505 __ cmp(scratch1, scratch2);
5506 __ b(ne, chars_not_equal);
5507 __ add(index, index, Operand(1), SetCC);
5508 __ b(ne, &loop);
5509 }
5510
5511
5454 void StringCompareStub::Generate(MacroAssembler* masm) { 5512 void StringCompareStub::Generate(MacroAssembler* masm) {
5455 Label runtime; 5513 Label runtime;
5456 5514
5457 Counters* counters = masm->isolate()->counters(); 5515 Counters* counters = masm->isolate()->counters();
5458 5516
5459 // Stack frame on entry. 5517 // Stack frame on entry.
5460 // sp[0]: right string 5518 // sp[0]: right string
5461 // sp[4]: left string 5519 // sp[4]: left string
5462 __ Ldrd(r0 , r1, MemOperand(sp)); // Load right in r0, left in r1. 5520 __ Ldrd(r0 , r1, MemOperand(sp)); // Load right in r0, left in r1.
5463 5521
(...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after
5896 5954
5897 CompareStub stub(GetCondition(), strict(), NO_COMPARE_FLAGS, r1, r0); 5955 CompareStub stub(GetCondition(), strict(), NO_COMPARE_FLAGS, r1, r0);
5898 __ bind(&generic_stub); 5956 __ bind(&generic_stub);
5899 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); 5957 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
5900 5958
5901 __ bind(&miss); 5959 __ bind(&miss);
5902 GenerateMiss(masm); 5960 GenerateMiss(masm);
5903 } 5961 }
5904 5962
5905 5963
5964 void ICCompareStub::GenerateStrings(MacroAssembler* masm) {
5965 ASSERT(state_ == CompareIC::STRINGS);
5966 Label miss;
5967
5968 // Registers containing left and right operands respectively.
5969 Register left = r1;
5970 Register right = r0;
5971 Register tmp1 = r2;
5972 Register tmp2 = r3;
5973 Register tmp3 = r4;
5974 Register tmp4 = r5;
5975
5976 // Check that both operands are heap objects.
5977 __ JumpIfEitherSmi(left, right, &miss);
5978
5979 // Check that both operands are strings. This leaves the instance
5980 // types loaded in tmp1 and tmp2.
5981 __ ldr(tmp1, FieldMemOperand(left, HeapObject::kMapOffset));
5982 __ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
5983 __ ldrb(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset));
5984 __ ldrb(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset));
5985 STATIC_ASSERT(kNotStringTag != 0);
5986 __ orr(tmp3, tmp1, tmp2);
5987 __ tst(tmp3, Operand(kIsNotStringMask));
5988 __ b(ne, &miss);
5989
5990 // Fast check for identical strings.
5991 __ cmp(left, right);
5992 STATIC_ASSERT(EQUAL == 0);
5993 STATIC_ASSERT(kSmiTag == 0);
5994 __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq);
5995 __ Ret(eq);
5996
5997 // Handle not identical strings.
5998
5999 // Check that both strings are symbols. If they are, we're done
6000 // because we already know they are not identical.
6001 ASSERT(GetCondition() == eq);
6002 STATIC_ASSERT(kSymbolTag != 0);
6003 __ and_(tmp3, tmp1, Operand(tmp2));
6004 __ tst(tmp3, Operand(kIsSymbolMask));
6005 // Make sure r0 is non-zero. At this point input operands are
6006 // guaranteed to be non-zero.
6007 ASSERT(right.is(r0));
6008 __ Ret(ne);
6009
6010 // Check that both strings are sequential ASCII.
6011 Label runtime;
6012 __ JumpIfBothInstanceTypesAreNotSequentialAscii(tmp1, tmp2, tmp3, tmp4,
6013 &runtime);
6014
6015 // Compare flat ASCII strings. Returns when done.
6016 StringCompareStub::GenerateFlatAsciiStringEquals(
6017 masm, left, right, tmp1, tmp2, tmp3);
6018
6019 // Handle more complex cases in runtime.
6020 __ bind(&runtime);
6021 __ Push(left, right);
6022 __ TailCallRuntime(Runtime::kStringEquals, 2, 1);
6023
6024 __ bind(&miss);
6025 GenerateMiss(masm);
6026 }
6027
6028
5906 void ICCompareStub::GenerateObjects(MacroAssembler* masm) { 6029 void ICCompareStub::GenerateObjects(MacroAssembler* masm) {
5907 ASSERT(state_ == CompareIC::OBJECTS); 6030 ASSERT(state_ == CompareIC::OBJECTS);
5908 Label miss; 6031 Label miss;
5909 __ and_(r2, r1, Operand(r0)); 6032 __ and_(r2, r1, Operand(r0));
5910 __ tst(r2, Operand(kSmiTagMask)); 6033 __ tst(r2, Operand(kSmiTagMask));
5911 __ b(eq, &miss); 6034 __ b(eq, &miss);
5912 6035
5913 __ CompareObjectType(r0, r2, r2, JS_OBJECT_TYPE); 6036 __ CompareObjectType(r0, r2, r2, JS_OBJECT_TYPE);
5914 __ b(ne, &miss); 6037 __ b(ne, &miss);
5915 __ CompareObjectType(r1, r2, r2, JS_OBJECT_TYPE); 6038 __ CompareObjectType(r1, r2, r2, JS_OBJECT_TYPE);
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
5966 void DirectCEntryStub::GenerateCall(MacroAssembler* masm, 6089 void DirectCEntryStub::GenerateCall(MacroAssembler* masm,
5967 Register target) { 6090 Register target) {
5968 __ mov(lr, Operand(reinterpret_cast<intptr_t>(GetCode().location()), 6091 __ mov(lr, Operand(reinterpret_cast<intptr_t>(GetCode().location()),
5969 RelocInfo::CODE_TARGET)); 6092 RelocInfo::CODE_TARGET));
5970 // Push return address (accessible to GC through exit frame pc). 6093 // Push return address (accessible to GC through exit frame pc).
5971 __ str(pc, MemOperand(sp, 0)); 6094 __ str(pc, MemOperand(sp, 0));
5972 __ Jump(target); // Call the C++ function. 6095 __ Jump(target); // Call the C++ function.
5973 } 6096 }
5974 6097
5975 6098
6099 void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm,
6100 Label* miss,
6101 Label* done,
6102 Register receiver,
6103 Register properties,
6104 String* name,
6105 Register scratch0) {
6106 // If names of slots in range from 1 to kProbes - 1 for the hash value are
6107 // not equal to the name and kProbes-th slot is not used (its name is the
6108 // undefined value), it guarantees the hash table doesn't contain the
6109 // property. It's true even if some slots represent deleted properties
6110 // (their names are the null value).
6111 for (int i = 0; i < kInlinedProbes; i++) {
6112 // scratch0 points to properties hash.
6113 // Compute the masked index: (hash + i + i * i) & mask.
6114 Register index = scratch0;
6115 // Capacity is smi 2^n.
6116 __ ldr(index, FieldMemOperand(properties, kCapacityOffset));
6117 __ sub(index, index, Operand(1));
6118 __ and_(index, index, Operand(
6119 Smi::FromInt(name->Hash() + StringDictionary::GetProbeOffset(i))));
6120
6121 // Scale the index by multiplying by the entry size.
6122 ASSERT(StringDictionary::kEntrySize == 3);
6123 __ add(index, index, Operand(index, LSL, 1)); // index *= 3.
6124
6125 Register entity_name = scratch0;
6126 // Having undefined at this place means the name is not contained.
6127 ASSERT_EQ(kSmiTagSize, 1);
6128 Register tmp = properties;
6129 __ add(tmp, properties, Operand(index, LSL, 1));
6130 __ ldr(entity_name, FieldMemOperand(tmp, kElementsStartOffset));
6131
6132 ASSERT(!tmp.is(entity_name));
6133 __ LoadRoot(tmp, Heap::kUndefinedValueRootIndex);
6134 __ cmp(entity_name, tmp);
6135 __ b(eq, done);
6136
6137 if (i != kInlinedProbes - 1) {
6138 // Stop if found the property.
6139 __ cmp(entity_name, Operand(Handle<String>(name)));
6140 __ b(eq, miss);
6141
6142 // Check if the entry name is not a symbol.
6143 __ ldr(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset));
6144 __ ldrb(entity_name,
6145 FieldMemOperand(entity_name, Map::kInstanceTypeOffset));
6146 __ tst(entity_name, Operand(kIsSymbolMask));
6147 __ b(eq, miss);
6148
6149 // Restore the properties.
6150 __ ldr(properties,
6151 FieldMemOperand(receiver, JSObject::kPropertiesOffset));
6152 }
6153 }
6154
6155 const int spill_mask =
6156 (lr.bit() | r6.bit() | r5.bit() | r4.bit() | r3.bit() |
6157 r2.bit() | r1.bit() | r0.bit());
6158
6159 __ stm(db_w, sp, spill_mask);
6160 __ ldr(r0, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
6161 __ mov(r1, Operand(Handle<String>(name)));
6162 StringDictionaryLookupStub stub(NEGATIVE_LOOKUP);
6163 __ CallStub(&stub);
6164 __ tst(r0, Operand(r0));
6165 __ ldm(ia_w, sp, spill_mask);
6166
6167 __ b(eq, done);
6168 __ b(ne, miss);
6169 }
6170
6171
6172 // Probe the string dictionary in the |elements| register. Jump to the
6173 // |done| label if a property with the given name is found. Jump to
6174 // the |miss| label otherwise.
6175 // If lookup was successful |scratch2| will be equal to elements + 4 * index.
6176 void StringDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm,
6177 Label* miss,
6178 Label* done,
6179 Register elements,
6180 Register name,
6181 Register scratch1,
6182 Register scratch2) {
6183 // Assert that name contains a string.
6184 if (FLAG_debug_code) __ AbortIfNotString(name);
6185
6186 // Compute the capacity mask.
6187 __ ldr(scratch1, FieldMemOperand(elements, kCapacityOffset));
6188 __ mov(scratch1, Operand(scratch1, ASR, kSmiTagSize)); // convert smi to int
6189 __ sub(scratch1, scratch1, Operand(1));
6190
6191 // Generate an unrolled loop that performs a few probes before
6192 // giving up. Measurements done on Gmail indicate that 2 probes
6193 // cover ~93% of loads from dictionaries.
6194 for (int i = 0; i < kInlinedProbes; i++) {
6195 // Compute the masked index: (hash + i + i * i) & mask.
6196 __ ldr(scratch2, FieldMemOperand(name, String::kHashFieldOffset));
6197 if (i > 0) {
6198 // Add the probe offset (i + i * i) left shifted to avoid right shifting
6199 // the hash in a separate instruction. The value hash + i + i * i is right
6200 // shifted in the following and instruction.
6201 ASSERT(StringDictionary::GetProbeOffset(i) <
6202 1 << (32 - String::kHashFieldOffset));
6203 __ add(scratch2, scratch2, Operand(
6204 StringDictionary::GetProbeOffset(i) << String::kHashShift));
6205 }
6206 __ and_(scratch2, scratch1, Operand(scratch2, LSR, String::kHashShift));
6207
6208 // Scale the index by multiplying by the element size.
6209 ASSERT(StringDictionary::kEntrySize == 3);
6210 // scratch2 = scratch2 * 3.
6211 __ add(scratch2, scratch2, Operand(scratch2, LSL, 1));
6212
6213 // Check if the key is identical to the name.
6214 __ add(scratch2, elements, Operand(scratch2, LSL, 2));
6215 __ ldr(ip, FieldMemOperand(scratch2, kElementsStartOffset));
6216 __ cmp(name, Operand(ip));
6217 __ b(eq, done);
6218 }
6219
6220 const int spill_mask =
6221 (lr.bit() | r6.bit() | r5.bit() | r4.bit() |
6222 r3.bit() | r2.bit() | r1.bit() | r0.bit()) &
6223 ~(scratch1.bit() | scratch2.bit());
6224
6225 __ stm(db_w, sp, spill_mask);
6226 __ Move(r0, elements);
6227 __ Move(r1, name);
6228 StringDictionaryLookupStub stub(POSITIVE_LOOKUP);
6229 __ CallStub(&stub);
6230 __ tst(r0, Operand(r0));
6231 __ mov(scratch2, Operand(r2));
6232 __ ldm(ia_w, sp, spill_mask);
6233
6234 __ b(ne, done);
6235 __ b(eq, miss);
6236 }
6237
6238
6239 void StringDictionaryLookupStub::Generate(MacroAssembler* masm) {
6240 // Registers:
6241 // result: StringDictionary to probe
6242 // r1: key
6243 // : StringDictionary to probe.
6244 // index_: will hold an index of entry if lookup is successful.
6245 // might alias with result_.
6246 // Returns:
6247 // result_ is zero if lookup failed, non zero otherwise.
6248
6249 Register result = r0;
6250 Register dictionary = r0;
6251 Register key = r1;
6252 Register index = r2;
6253 Register mask = r3;
6254 Register hash = r4;
6255 Register undefined = r5;
6256 Register entry_key = r6;
6257
6258 Label in_dictionary, maybe_in_dictionary, not_in_dictionary;
6259
6260 __ ldr(mask, FieldMemOperand(dictionary, kCapacityOffset));
6261 __ mov(mask, Operand(mask, ASR, kSmiTagSize));
6262 __ sub(mask, mask, Operand(1));
6263
6264 __ ldr(hash, FieldMemOperand(key, String::kHashFieldOffset));
6265
6266 __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex);
6267
6268 for (int i = kInlinedProbes; i < kTotalProbes; i++) {
6269 // Compute the masked index: (hash + i + i * i) & mask.
6270 // Capacity is smi 2^n.
6271 if (i > 0) {
6272 // Add the probe offset (i + i * i) left shifted to avoid right shifting
6273 // the hash in a separate instruction. The value hash + i + i * i is right
6274 // shifted in the following and instruction.
6275 ASSERT(StringDictionary::GetProbeOffset(i) <
6276 1 << (32 - String::kHashFieldOffset));
6277 __ add(index, hash, Operand(
6278 StringDictionary::GetProbeOffset(i) << String::kHashShift));
6279 } else {
6280 __ mov(index, Operand(hash));
6281 }
6282 __ and_(index, mask, Operand(index, LSR, String::kHashShift));
6283
6284 // Scale the index by multiplying by the entry size.
6285 ASSERT(StringDictionary::kEntrySize == 3);
6286 __ add(index, index, Operand(index, LSL, 1)); // index *= 3.
6287
6288 ASSERT_EQ(kSmiTagSize, 1);
6289 __ add(index, dictionary, Operand(index, LSL, 2));
6290 __ ldr(entry_key, FieldMemOperand(index, kElementsStartOffset));
6291
6292 // Having undefined at this place means the name is not contained.
6293 __ cmp(entry_key, Operand(undefined));
6294 __ b(eq, &not_in_dictionary);
6295
6296 // Stop if found the property.
6297 __ cmp(entry_key, Operand(key));
6298 __ b(eq, &in_dictionary);
6299
6300 if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) {
6301 // Check if the entry name is not a symbol.
6302 __ ldr(entry_key, FieldMemOperand(entry_key, HeapObject::kMapOffset));
6303 __ ldrb(entry_key,
6304 FieldMemOperand(entry_key, Map::kInstanceTypeOffset));
6305 __ tst(entry_key, Operand(kIsSymbolMask));
6306 __ b(eq, &maybe_in_dictionary);
6307 }
6308 }
6309
6310 __ bind(&maybe_in_dictionary);
6311 // If we are doing negative lookup then probing failure should be
6312 // treated as a lookup success. For positive lookup probing failure
6313 // should be treated as lookup failure.
6314 if (mode_ == POSITIVE_LOOKUP) {
6315 __ mov(result, Operand(0));
6316 __ Ret();
6317 }
6318
6319 __ bind(&in_dictionary);
6320 __ mov(result, Operand(1));
6321 __ Ret();
6322
6323 __ bind(&not_in_dictionary);
6324 __ mov(result, Operand(0));
6325 __ Ret();
6326 }
6327
6328
5976 #undef __ 6329 #undef __
5977 6330
5978 } } // namespace v8::internal 6331 } } // namespace v8::internal
5979 6332
5980 #endif // V8_TARGET_ARCH_ARM 6333 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/code-stubs-arm.h ('k') | src/arm/ic-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698