| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 57 __ b(eq, global_object); | 57 __ b(eq, global_object); |
| 58 __ cmp(type, Operand(JS_BUILTINS_OBJECT_TYPE)); | 58 __ cmp(type, Operand(JS_BUILTINS_OBJECT_TYPE)); |
| 59 __ b(eq, global_object); | 59 __ b(eq, global_object); |
| 60 __ cmp(type, Operand(JS_GLOBAL_PROXY_TYPE)); | 60 __ cmp(type, Operand(JS_GLOBAL_PROXY_TYPE)); |
| 61 __ b(eq, global_object); | 61 __ b(eq, global_object); |
| 62 } | 62 } |
| 63 | 63 |
| 64 | 64 |
| 65 // Generated code falls through if the receiver is a regular non-global | 65 // Generated code falls through if the receiver is a regular non-global |
| 66 // JS object with slow properties and no interceptors. | 66 // JS object with slow properties and no interceptors. |
| 67 static void GenerateStringDictionaryReceiverCheck(MacroAssembler* masm, | 67 static void GenerateNameDictionaryReceiverCheck(MacroAssembler* masm, |
| 68 Register receiver, | 68 Register receiver, |
| 69 Register elements, | 69 Register elements, |
| 70 Register t0, | 70 Register t0, |
| 71 Register t1, | 71 Register t1, |
| 72 Label* miss) { | 72 Label* miss) { |
| 73 // Register usage: | 73 // Register usage: |
| 74 // receiver: holds the receiver on entry and is unchanged. | 74 // receiver: holds the receiver on entry and is unchanged. |
| 75 // elements: holds the property dictionary on fall through. | 75 // elements: holds the property dictionary on fall through. |
| 76 // Scratch registers: | 76 // Scratch registers: |
| 77 // t0: used to holds the receiver map. | 77 // t0: used to holds the receiver map. |
| 78 // t1: used to holds the receiver instance type, receiver bit mask and | 78 // t1: used to holds the receiver instance type, receiver bit mask and |
| 79 // elements map. | 79 // elements map. |
| 80 | 80 |
| 81 // Check that the receiver isn't a smi. | 81 // Check that the receiver isn't a smi. |
| 82 __ JumpIfSmi(receiver, miss); | 82 __ JumpIfSmi(receiver, miss); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 Register result, | 124 Register result, |
| 125 Register scratch1, | 125 Register scratch1, |
| 126 Register scratch2) { | 126 Register scratch2) { |
| 127 // Main use of the scratch registers. | 127 // Main use of the scratch registers. |
| 128 // scratch1: Used as temporary and to hold the capacity of the property | 128 // scratch1: Used as temporary and to hold the capacity of the property |
| 129 // dictionary. | 129 // dictionary. |
| 130 // scratch2: Used as temporary. | 130 // scratch2: Used as temporary. |
| 131 Label done; | 131 Label done; |
| 132 | 132 |
| 133 // Probe the dictionary. | 133 // Probe the dictionary. |
| 134 StringDictionaryLookupStub::GeneratePositiveLookup(masm, | 134 NameDictionaryLookupStub::GeneratePositiveLookup(masm, |
| 135 miss, | 135 miss, |
| 136 &done, | 136 &done, |
| 137 elements, | 137 elements, |
| 138 name, | 138 name, |
| 139 scratch1, | 139 scratch1, |
| 140 scratch2); | 140 scratch2); |
| 141 | 141 |
| 142 // If probing finds an entry check that the value is a normal | 142 // If probing finds an entry check that the value is a normal |
| 143 // property. | 143 // property. |
| 144 __ bind(&done); // scratch2 == elements + 4 * index | 144 __ bind(&done); // scratch2 == elements + 4 * index |
| 145 const int kElementsStartOffset = StringDictionary::kHeaderSize + | 145 const int kElementsStartOffset = NameDictionary::kHeaderSize + |
| 146 StringDictionary::kElementsStartIndex * kPointerSize; | 146 NameDictionary::kElementsStartIndex * kPointerSize; |
| 147 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; | 147 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; |
| 148 __ ldr(scratch1, FieldMemOperand(scratch2, kDetailsOffset)); | 148 __ ldr(scratch1, FieldMemOperand(scratch2, kDetailsOffset)); |
| 149 __ tst(scratch1, Operand(PropertyDetails::TypeField::kMask << kSmiTagSize)); | 149 __ tst(scratch1, Operand(PropertyDetails::TypeField::kMask << kSmiTagSize)); |
| 150 __ b(ne, miss); | 150 __ b(ne, miss); |
| 151 | 151 |
| 152 // Get the value at the masked, scaled index and return. | 152 // Get the value at the masked, scaled index and return. |
| 153 __ ldr(result, | 153 __ ldr(result, |
| 154 FieldMemOperand(scratch2, kElementsStartOffset + 1 * kPointerSize)); | 154 FieldMemOperand(scratch2, kElementsStartOffset + 1 * kPointerSize)); |
| 155 } | 155 } |
| 156 | 156 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 173 Register value, | 173 Register value, |
| 174 Register scratch1, | 174 Register scratch1, |
| 175 Register scratch2) { | 175 Register scratch2) { |
| 176 // Main use of the scratch registers. | 176 // Main use of the scratch registers. |
| 177 // scratch1: Used as temporary and to hold the capacity of the property | 177 // scratch1: Used as temporary and to hold the capacity of the property |
| 178 // dictionary. | 178 // dictionary. |
| 179 // scratch2: Used as temporary. | 179 // scratch2: Used as temporary. |
| 180 Label done; | 180 Label done; |
| 181 | 181 |
| 182 // Probe the dictionary. | 182 // Probe the dictionary. |
| 183 StringDictionaryLookupStub::GeneratePositiveLookup(masm, | 183 NameDictionaryLookupStub::GeneratePositiveLookup(masm, |
| 184 miss, | 184 miss, |
| 185 &done, | 185 &done, |
| 186 elements, | 186 elements, |
| 187 name, | 187 name, |
| 188 scratch1, | 188 scratch1, |
| 189 scratch2); | 189 scratch2); |
| 190 | 190 |
| 191 // If probing finds an entry in the dictionary check that the value | 191 // If probing finds an entry in the dictionary check that the value |
| 192 // is a normal property that is not read only. | 192 // is a normal property that is not read only. |
| 193 __ bind(&done); // scratch2 == elements + 4 * index | 193 __ bind(&done); // scratch2 == elements + 4 * index |
| 194 const int kElementsStartOffset = StringDictionary::kHeaderSize + | 194 const int kElementsStartOffset = NameDictionary::kHeaderSize + |
| 195 StringDictionary::kElementsStartIndex * kPointerSize; | 195 NameDictionary::kElementsStartIndex * kPointerSize; |
| 196 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; | 196 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; |
| 197 const int kTypeAndReadOnlyMask = | 197 const int kTypeAndReadOnlyMask = |
| 198 (PropertyDetails::TypeField::kMask | | 198 (PropertyDetails::TypeField::kMask | |
| 199 PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize; | 199 PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize; |
| 200 __ ldr(scratch1, FieldMemOperand(scratch2, kDetailsOffset)); | 200 __ ldr(scratch1, FieldMemOperand(scratch2, kDetailsOffset)); |
| 201 __ tst(scratch1, Operand(kTypeAndReadOnlyMask)); | 201 __ tst(scratch1, Operand(kTypeAndReadOnlyMask)); |
| 202 __ b(ne, miss); | 202 __ b(ne, miss); |
| 203 | 203 |
| 204 // Store the value at the masked, scaled index and return. | 204 // Store the value at the masked, scaled index and return. |
| 205 const int kValueOffset = kElementsStartOffset + kPointerSize; | 205 const int kValueOffset = kElementsStartOffset + kPointerSize; |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 296 MemOperand(scratch1, key, LSL, kPointerSizeLog2 - kSmiTagSize)); | 296 MemOperand(scratch1, key, LSL, kPointerSizeLog2 - kSmiTagSize)); |
| 297 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 297 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
| 298 __ cmp(scratch2, ip); | 298 __ cmp(scratch2, ip); |
| 299 // In case the loaded value is the_hole we have to consult GetProperty | 299 // In case the loaded value is the_hole we have to consult GetProperty |
| 300 // to ensure the prototype chain is searched. | 300 // to ensure the prototype chain is searched. |
| 301 __ b(eq, out_of_range); | 301 __ b(eq, out_of_range); |
| 302 __ mov(result, scratch2); | 302 __ mov(result, scratch2); |
| 303 } | 303 } |
| 304 | 304 |
| 305 | 305 |
| 306 // Checks whether a key is an array index string or an internalized string. | 306 // Checks whether a key is an array index string or a unique name. |
| 307 // Falls through if a key is an internalized string. | 307 // Falls through if a key is a unique name. |
| 308 static void GenerateKeyStringCheck(MacroAssembler* masm, | 308 static void GenerateKeyNameCheck(MacroAssembler* masm, |
| 309 Register key, | 309 Register key, |
| 310 Register map, | 310 Register map, |
| 311 Register hash, | 311 Register hash, |
| 312 Label* index_string, | 312 Label* index_string, |
| 313 Label* not_internalized) { | 313 Label* not_unique) { |
| 314 // The key is not a smi. | 314 // The key is not a smi. |
| 315 // Is it a string? | 315 Label unique; |
| 316 __ CompareObjectType(key, map, hash, FIRST_NONSTRING_TYPE); | 316 // Is it a name? |
| 317 __ b(ge, not_internalized); | 317 __ CompareObjectType(key, map, hash, LAST_UNIQUE_NAME_TYPE); |
| 318 __ b(hi, not_unique); |
| 319 STATIC_ASSERT(LAST_UNIQUE_NAME_TYPE == FIRST_NONSTRING_TYPE); |
| 320 __ b(eq, &unique); |
| 318 | 321 |
| 319 // Is the string an array index, with cached numeric value? | 322 // Is the string an array index, with cached numeric value? |
| 320 __ ldr(hash, FieldMemOperand(key, String::kHashFieldOffset)); | 323 __ ldr(hash, FieldMemOperand(key, Name::kHashFieldOffset)); |
| 321 __ tst(hash, Operand(String::kContainsCachedArrayIndexMask)); | 324 __ tst(hash, Operand(Name::kContainsCachedArrayIndexMask)); |
| 322 __ b(eq, index_string); | 325 __ b(eq, index_string); |
| 323 | 326 |
| 324 // Is the string internalized? | 327 // Is the string internalized? |
| 325 // map: key map | 328 // map: key map |
| 326 __ ldrb(hash, FieldMemOperand(map, Map::kInstanceTypeOffset)); | 329 __ ldrb(hash, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
| 327 STATIC_ASSERT(kInternalizedTag != 0); | 330 STATIC_ASSERT(kInternalizedTag != 0); |
| 328 __ tst(hash, Operand(kIsInternalizedMask)); | 331 __ tst(hash, Operand(kIsInternalizedMask)); |
| 329 __ b(eq, not_internalized); | 332 __ b(eq, not_unique); |
| 333 |
| 334 __ bind(&unique); |
| 330 } | 335 } |
| 331 | 336 |
| 332 | 337 |
| 333 // Defined in ic.cc. | 338 // Defined in ic.cc. |
| 334 Object* CallIC_Miss(Arguments args); | 339 Object* CallIC_Miss(Arguments args); |
| 335 | 340 |
| 336 // The generated code does not accept smi keys. | 341 // The generated code does not accept smi keys. |
| 337 // The generated code falls through if both probes miss. | 342 // The generated code falls through if both probes miss. |
| 338 void CallICBase::GenerateMonomorphicCacheProbe(MacroAssembler* masm, | 343 void CallICBase::GenerateMonomorphicCacheProbe(MacroAssembler* masm, |
| 339 int argc, | 344 int argc, |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 420 void CallICBase::GenerateNormal(MacroAssembler* masm, int argc) { | 425 void CallICBase::GenerateNormal(MacroAssembler* masm, int argc) { |
| 421 // ----------- S t a t e ------------- | 426 // ----------- S t a t e ------------- |
| 422 // -- r2 : name | 427 // -- r2 : name |
| 423 // -- lr : return address | 428 // -- lr : return address |
| 424 // ----------------------------------- | 429 // ----------------------------------- |
| 425 Label miss; | 430 Label miss; |
| 426 | 431 |
| 427 // Get the receiver of the function from the stack into r1. | 432 // Get the receiver of the function from the stack into r1. |
| 428 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | 433 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); |
| 429 | 434 |
| 430 GenerateStringDictionaryReceiverCheck(masm, r1, r0, r3, r4, &miss); | 435 GenerateNameDictionaryReceiverCheck(masm, r1, r0, r3, r4, &miss); |
| 431 | 436 |
| 432 // r0: elements | 437 // r0: elements |
| 433 // Search the dictionary - put result in register r1. | 438 // Search the dictionary - put result in register r1. |
| 434 GenerateDictionaryLoad(masm, &miss, r0, r2, r1, r3, r4); | 439 GenerateDictionaryLoad(masm, &miss, r0, r2, r1, r3, r4); |
| 435 | 440 |
| 436 GenerateFunctionTailCall(masm, argc, &miss, r4); | 441 GenerateFunctionTailCall(masm, argc, &miss, r4); |
| 437 | 442 |
| 438 __ bind(&miss); | 443 __ bind(&miss); |
| 439 } | 444 } |
| 440 | 445 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 524 void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { | 529 void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { |
| 525 // ----------- S t a t e ------------- | 530 // ----------- S t a t e ------------- |
| 526 // -- r2 : name | 531 // -- r2 : name |
| 527 // -- lr : return address | 532 // -- lr : return address |
| 528 // ----------------------------------- | 533 // ----------------------------------- |
| 529 | 534 |
| 530 // Get the receiver of the function from the stack into r1. | 535 // Get the receiver of the function from the stack into r1. |
| 531 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | 536 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); |
| 532 | 537 |
| 533 Label do_call, slow_call, slow_load, slow_reload_receiver; | 538 Label do_call, slow_call, slow_load, slow_reload_receiver; |
| 534 Label check_number_dictionary, check_string, lookup_monomorphic_cache; | 539 Label check_number_dictionary, check_name, lookup_monomorphic_cache; |
| 535 Label index_smi, index_string; | 540 Label index_smi, index_name; |
| 536 | 541 |
| 537 // Check that the key is a smi. | 542 // Check that the key is a smi. |
| 538 __ JumpIfNotSmi(r2, &check_string); | 543 __ JumpIfNotSmi(r2, &check_name); |
| 539 __ bind(&index_smi); | 544 __ bind(&index_smi); |
| 540 // Now the key is known to be a smi. This place is also jumped to from below | 545 // Now the key is known to be a smi. This place is also jumped to from below |
| 541 // where a numeric string is converted to a smi. | 546 // where a numeric string is converted to a smi. |
| 542 | 547 |
| 543 GenerateKeyedLoadReceiverCheck( | 548 GenerateKeyedLoadReceiverCheck( |
| 544 masm, r1, r0, r3, Map::kHasIndexedInterceptor, &slow_call); | 549 masm, r1, r0, r3, Map::kHasIndexedInterceptor, &slow_call); |
| 545 | 550 |
| 546 GenerateFastArrayLoad( | 551 GenerateFastArrayLoad( |
| 547 masm, r1, r2, r4, r3, r0, r1, &check_number_dictionary, &slow_load); | 552 masm, r1, r2, r4, r3, r0, r1, &check_number_dictionary, &slow_load); |
| 548 Counters* counters = masm->isolate()->counters(); | 553 Counters* counters = masm->isolate()->counters(); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 575 { | 580 { |
| 576 FrameScope scope(masm, StackFrame::INTERNAL); | 581 FrameScope scope(masm, StackFrame::INTERNAL); |
| 577 __ push(r2); // save the key | 582 __ push(r2); // save the key |
| 578 __ Push(r1, r2); // pass the receiver and the key | 583 __ Push(r1, r2); // pass the receiver and the key |
| 579 __ CallRuntime(Runtime::kKeyedGetProperty, 2); | 584 __ CallRuntime(Runtime::kKeyedGetProperty, 2); |
| 580 __ pop(r2); // restore the key | 585 __ pop(r2); // restore the key |
| 581 } | 586 } |
| 582 __ mov(r1, r0); | 587 __ mov(r1, r0); |
| 583 __ jmp(&do_call); | 588 __ jmp(&do_call); |
| 584 | 589 |
| 585 __ bind(&check_string); | 590 __ bind(&check_name); |
| 586 GenerateKeyStringCheck(masm, r2, r0, r3, &index_string, &slow_call); | 591 GenerateKeyNameCheck(masm, r2, r0, r3, &index_name, &slow_call); |
| 587 | 592 |
| 588 // The key is known to be internalized. | 593 // The key is known to be a uniquq name. |
| 589 // If the receiver is a regular JS object with slow properties then do | 594 // If the receiver is a regular JS object with slow properties then do |
| 590 // a quick inline probe of the receiver's dictionary. | 595 // a quick inline probe of the receiver's dictionary. |
| 591 // Otherwise do the monomorphic cache probe. | 596 // Otherwise do the monomorphic cache probe. |
| 592 GenerateKeyedLoadReceiverCheck( | 597 GenerateKeyedLoadReceiverCheck( |
| 593 masm, r1, r0, r3, Map::kHasNamedInterceptor, &lookup_monomorphic_cache); | 598 masm, r1, r0, r3, Map::kHasNamedInterceptor, &lookup_monomorphic_cache); |
| 594 | 599 |
| 595 __ ldr(r0, FieldMemOperand(r1, JSObject::kPropertiesOffset)); | 600 __ ldr(r0, FieldMemOperand(r1, JSObject::kPropertiesOffset)); |
| 596 __ ldr(r3, FieldMemOperand(r0, HeapObject::kMapOffset)); | 601 __ ldr(r3, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 597 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); | 602 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); |
| 598 __ cmp(r3, ip); | 603 __ cmp(r3, ip); |
| 599 __ b(ne, &lookup_monomorphic_cache); | 604 __ b(ne, &lookup_monomorphic_cache); |
| 600 | 605 |
| 601 GenerateDictionaryLoad(masm, &slow_load, r0, r2, r1, r3, r4); | 606 GenerateDictionaryLoad(masm, &slow_load, r0, r2, r1, r3, r4); |
| 602 __ IncrementCounter(counters->keyed_call_generic_lookup_dict(), 1, r0, r3); | 607 __ IncrementCounter(counters->keyed_call_generic_lookup_dict(), 1, r0, r3); |
| 603 __ jmp(&do_call); | 608 __ jmp(&do_call); |
| 604 | 609 |
| 605 __ bind(&lookup_monomorphic_cache); | 610 __ bind(&lookup_monomorphic_cache); |
| 606 __ IncrementCounter(counters->keyed_call_generic_lookup_cache(), 1, r0, r3); | 611 __ IncrementCounter(counters->keyed_call_generic_lookup_cache(), 1, r0, r3); |
| 607 GenerateMonomorphicCacheProbe(masm, | 612 GenerateMonomorphicCacheProbe(masm, |
| 608 argc, | 613 argc, |
| 609 Code::KEYED_CALL_IC, | 614 Code::KEYED_CALL_IC, |
| 610 Code::kNoExtraICState); | 615 Code::kNoExtraICState); |
| 611 // Fall through on miss. | 616 // Fall through on miss. |
| 612 | 617 |
| 613 __ bind(&slow_call); | 618 __ bind(&slow_call); |
| 614 // This branch is taken if: | 619 // This branch is taken if: |
| 615 // - the receiver requires boxing or access check, | 620 // - the receiver requires boxing or access check, |
| 616 // - the key is neither smi nor an internalized string, | 621 // - the key is neither smi nor a unique name, |
| 617 // - the value loaded is not a function, | 622 // - the value loaded is not a function, |
| 618 // - there is hope that the runtime will create a monomorphic call stub | 623 // - there is hope that the runtime will create a monomorphic call stub |
| 619 // that will get fetched next time. | 624 // that will get fetched next time. |
| 620 __ IncrementCounter(counters->keyed_call_generic_slow(), 1, r0, r3); | 625 __ IncrementCounter(counters->keyed_call_generic_slow(), 1, r0, r3); |
| 621 GenerateMiss(masm, argc); | 626 GenerateMiss(masm, argc); |
| 622 | 627 |
| 623 __ bind(&index_string); | 628 __ bind(&index_name); |
| 624 __ IndexFromHash(r3, r2); | 629 __ IndexFromHash(r3, r2); |
| 625 // Now jump to the place where smi keys are handled. | 630 // Now jump to the place where smi keys are handled. |
| 626 __ jmp(&index_smi); | 631 __ jmp(&index_smi); |
| 627 } | 632 } |
| 628 | 633 |
| 629 | 634 |
| 630 void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { | 635 void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { |
| 631 // ----------- S t a t e ------------- | 636 // ----------- S t a t e ------------- |
| 632 // -- r2 : name | 637 // -- r2 : name |
| 633 // -- lr : return address | 638 // -- lr : return address |
| 634 // ----------------------------------- | 639 // ----------------------------------- |
| 635 | 640 |
| 636 // Check if the name is a string. | 641 // Check if the name is really a name. |
| 637 Label miss; | 642 Label miss; |
| 638 __ JumpIfSmi(r2, &miss); | 643 __ JumpIfSmi(r2, &miss); |
| 639 __ IsObjectJSStringType(r2, r0, &miss); | 644 __ IsObjectNameType(r2, r0, &miss); |
| 640 | 645 |
| 641 CallICBase::GenerateNormal(masm, argc); | 646 CallICBase::GenerateNormal(masm, argc); |
| 642 __ bind(&miss); | 647 __ bind(&miss); |
| 643 GenerateMiss(masm, argc); | 648 GenerateMiss(masm, argc); |
| 644 } | 649 } |
| 645 | 650 |
| 646 | 651 |
| 647 // Defined in ic.cc. | 652 // Defined in ic.cc. |
| 648 Object* LoadIC_Miss(Arguments args); | 653 Object* LoadIC_Miss(Arguments args); |
| 649 | 654 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 668 | 673 |
| 669 void LoadIC::GenerateNormal(MacroAssembler* masm) { | 674 void LoadIC::GenerateNormal(MacroAssembler* masm) { |
| 670 // ----------- S t a t e ------------- | 675 // ----------- S t a t e ------------- |
| 671 // -- r2 : name | 676 // -- r2 : name |
| 672 // -- lr : return address | 677 // -- lr : return address |
| 673 // -- r0 : receiver | 678 // -- r0 : receiver |
| 674 // -- sp[0] : receiver | 679 // -- sp[0] : receiver |
| 675 // ----------------------------------- | 680 // ----------------------------------- |
| 676 Label miss; | 681 Label miss; |
| 677 | 682 |
| 678 GenerateStringDictionaryReceiverCheck(masm, r0, r1, r3, r4, &miss); | 683 GenerateNameDictionaryReceiverCheck(masm, r0, r1, r3, r4, &miss); |
| 679 | 684 |
| 680 // r1: elements | 685 // r1: elements |
| 681 GenerateDictionaryLoad(masm, &miss, r1, r2, r0, r3, r4); | 686 GenerateDictionaryLoad(masm, &miss, r1, r2, r0, r3, r4); |
| 682 __ Ret(); | 687 __ Ret(); |
| 683 | 688 |
| 684 // Cache miss: Jump to runtime. | 689 // Cache miss: Jump to runtime. |
| 685 __ bind(&miss); | 690 __ bind(&miss); |
| 686 GenerateMiss(masm); | 691 GenerateMiss(masm); |
| 687 } | 692 } |
| 688 | 693 |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 911 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); | 916 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); |
| 912 } | 917 } |
| 913 | 918 |
| 914 | 919 |
| 915 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { | 920 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { |
| 916 // ---------- S t a t e -------------- | 921 // ---------- S t a t e -------------- |
| 917 // -- lr : return address | 922 // -- lr : return address |
| 918 // -- r0 : key | 923 // -- r0 : key |
| 919 // -- r1 : receiver | 924 // -- r1 : receiver |
| 920 // ----------------------------------- | 925 // ----------------------------------- |
| 921 Label slow, check_string, index_smi, index_string, property_array_property; | 926 Label slow, check_name, index_smi, index_name, property_array_property; |
| 922 Label probe_dictionary, check_number_dictionary; | 927 Label probe_dictionary, check_number_dictionary; |
| 923 | 928 |
| 924 Register key = r0; | 929 Register key = r0; |
| 925 Register receiver = r1; | 930 Register receiver = r1; |
| 926 | 931 |
| 927 Isolate* isolate = masm->isolate(); | 932 Isolate* isolate = masm->isolate(); |
| 928 | 933 |
| 929 // Check that the key is a smi. | 934 // Check that the key is a smi. |
| 930 __ JumpIfNotSmi(key, &check_string); | 935 __ JumpIfNotSmi(key, &check_name); |
| 931 __ bind(&index_smi); | 936 __ bind(&index_smi); |
| 932 // Now the key is known to be a smi. This place is also jumped to from below | 937 // Now the key is known to be a smi. This place is also jumped to from below |
| 933 // where a numeric string is converted to a smi. | 938 // where a numeric string is converted to a smi. |
| 934 | 939 |
| 935 GenerateKeyedLoadReceiverCheck( | 940 GenerateKeyedLoadReceiverCheck( |
| 936 masm, receiver, r2, r3, Map::kHasIndexedInterceptor, &slow); | 941 masm, receiver, r2, r3, Map::kHasIndexedInterceptor, &slow); |
| 937 | 942 |
| 938 // Check the receiver's map to see if it has fast elements. | 943 // Check the receiver's map to see if it has fast elements. |
| 939 __ CheckFastElements(r2, r3, &check_number_dictionary); | 944 __ CheckFastElements(r2, r3, &check_number_dictionary); |
| 940 | 945 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 957 __ mov(r2, Operand(r0, ASR, kSmiTagSize)); | 962 __ mov(r2, Operand(r0, ASR, kSmiTagSize)); |
| 958 __ LoadFromNumberDictionary(&slow, r4, r0, r0, r2, r3, r5); | 963 __ LoadFromNumberDictionary(&slow, r4, r0, r0, r2, r3, r5); |
| 959 __ Ret(); | 964 __ Ret(); |
| 960 | 965 |
| 961 // Slow case, key and receiver still in r0 and r1. | 966 // Slow case, key and receiver still in r0 and r1. |
| 962 __ bind(&slow); | 967 __ bind(&slow); |
| 963 __ IncrementCounter(isolate->counters()->keyed_load_generic_slow(), | 968 __ IncrementCounter(isolate->counters()->keyed_load_generic_slow(), |
| 964 1, r2, r3); | 969 1, r2, r3); |
| 965 GenerateRuntimeGetProperty(masm); | 970 GenerateRuntimeGetProperty(masm); |
| 966 | 971 |
| 967 __ bind(&check_string); | 972 __ bind(&check_name); |
| 968 GenerateKeyStringCheck(masm, key, r2, r3, &index_string, &slow); | 973 GenerateKeyNameCheck(masm, key, r2, r3, &index_name, &slow); |
| 969 | 974 |
| 970 GenerateKeyedLoadReceiverCheck( | 975 GenerateKeyedLoadReceiverCheck( |
| 971 masm, receiver, r2, r3, Map::kHasNamedInterceptor, &slow); | 976 masm, receiver, r2, r3, Map::kHasNamedInterceptor, &slow); |
| 972 | 977 |
| 973 // If the receiver is a fast-case object, check the keyed lookup | 978 // If the receiver is a fast-case object, check the keyed lookup |
| 974 // cache. Otherwise probe the dictionary. | 979 // cache. Otherwise probe the dictionary. |
| 975 __ ldr(r3, FieldMemOperand(r1, JSObject::kPropertiesOffset)); | 980 __ ldr(r3, FieldMemOperand(r1, JSObject::kPropertiesOffset)); |
| 976 __ ldr(r4, FieldMemOperand(r3, HeapObject::kMapOffset)); | 981 __ ldr(r4, FieldMemOperand(r3, HeapObject::kMapOffset)); |
| 977 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); | 982 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); |
| 978 __ cmp(r4, ip); | 983 __ cmp(r4, ip); |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1069 // r3: elements | 1074 // r3: elements |
| 1070 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); | 1075 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); |
| 1071 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset)); | 1076 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset)); |
| 1072 GenerateGlobalInstanceTypeCheck(masm, r2, &slow); | 1077 GenerateGlobalInstanceTypeCheck(masm, r2, &slow); |
| 1073 // Load the property to r0. | 1078 // Load the property to r0. |
| 1074 GenerateDictionaryLoad(masm, &slow, r3, r0, r0, r2, r4); | 1079 GenerateDictionaryLoad(masm, &slow, r3, r0, r0, r2, r4); |
| 1075 __ IncrementCounter( | 1080 __ IncrementCounter( |
| 1076 isolate->counters()->keyed_load_generic_symbol(), 1, r2, r3); | 1081 isolate->counters()->keyed_load_generic_symbol(), 1, r2, r3); |
| 1077 __ Ret(); | 1082 __ Ret(); |
| 1078 | 1083 |
| 1079 __ bind(&index_string); | 1084 __ bind(&index_name); |
| 1080 __ IndexFromHash(r3, key); | 1085 __ IndexFromHash(r3, key); |
| 1081 // Now jump to the place where smi keys are handled. | 1086 // Now jump to the place where smi keys are handled. |
| 1082 __ jmp(&index_smi); | 1087 __ jmp(&index_smi); |
| 1083 } | 1088 } |
| 1084 | 1089 |
| 1085 | 1090 |
| 1086 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { | 1091 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { |
| 1087 // ---------- S t a t e -------------- | 1092 // ---------- S t a t e -------------- |
| 1088 // -- lr : return address | 1093 // -- lr : return address |
| 1089 // -- r0 : key (index) | 1094 // -- r0 : key (index) |
| (...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1540 | 1545 |
| 1541 void StoreIC::GenerateNormal(MacroAssembler* masm) { | 1546 void StoreIC::GenerateNormal(MacroAssembler* masm) { |
| 1542 // ----------- S t a t e ------------- | 1547 // ----------- S t a t e ------------- |
| 1543 // -- r0 : value | 1548 // -- r0 : value |
| 1544 // -- r1 : receiver | 1549 // -- r1 : receiver |
| 1545 // -- r2 : name | 1550 // -- r2 : name |
| 1546 // -- lr : return address | 1551 // -- lr : return address |
| 1547 // ----------------------------------- | 1552 // ----------------------------------- |
| 1548 Label miss; | 1553 Label miss; |
| 1549 | 1554 |
| 1550 GenerateStringDictionaryReceiverCheck(masm, r1, r3, r4, r5, &miss); | 1555 GenerateNameDictionaryReceiverCheck(masm, r1, r3, r4, r5, &miss); |
| 1551 | 1556 |
| 1552 GenerateDictionaryStore(masm, &miss, r3, r2, r0, r4, r5); | 1557 GenerateDictionaryStore(masm, &miss, r3, r2, r0, r4, r5); |
| 1553 Counters* counters = masm->isolate()->counters(); | 1558 Counters* counters = masm->isolate()->counters(); |
| 1554 __ IncrementCounter(counters->store_normal_hit(), | 1559 __ IncrementCounter(counters->store_normal_hit(), |
| 1555 1, r4, r5); | 1560 1, r4, r5); |
| 1556 __ Ret(); | 1561 __ Ret(); |
| 1557 | 1562 |
| 1558 __ bind(&miss); | 1563 __ bind(&miss); |
| 1559 __ IncrementCounter(counters->store_normal_miss(), 1, r4, r5); | 1564 __ IncrementCounter(counters->store_normal_miss(), 1, r4, r5); |
| 1560 GenerateMiss(masm); | 1565 GenerateMiss(masm); |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1676 } else { | 1681 } else { |
| 1677 ASSERT(Assembler::GetCondition(branch_instr) == ne); | 1682 ASSERT(Assembler::GetCondition(branch_instr) == ne); |
| 1678 patcher.EmitCondition(eq); | 1683 patcher.EmitCondition(eq); |
| 1679 } | 1684 } |
| 1680 } | 1685 } |
| 1681 | 1686 |
| 1682 | 1687 |
| 1683 } } // namespace v8::internal | 1688 } } // namespace v8::internal |
| 1684 | 1689 |
| 1685 #endif // V8_TARGET_ARCH_ARM | 1690 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |