| OLD | NEW |
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 // Helper function used to check that the dictionary doesn't contain | 104 // Helper function used to check that the dictionary doesn't contain |
| 105 // the property. This function may return false negatives, so miss_label | 105 // the property. This function may return false negatives, so miss_label |
| 106 // must always call a backup property check that is complete. | 106 // must always call a backup property check that is complete. |
| 107 // This function is safe to call if the receiver has fast properties. | 107 // This function is safe to call if the receiver has fast properties. |
| 108 // Name must be a symbol and receiver must be a heap object. | 108 // Name must be a symbol and receiver must be a heap object. |
| 109 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm, | 109 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm, |
| 110 Label* miss_label, | 110 Label* miss_label, |
| 111 Register receiver, | 111 Register receiver, |
| 112 String* name, | 112 String* name, |
| 113 Register r0, | 113 Register r0, |
| 114 Register extra) { | 114 Register r1) { |
| 115 ASSERT(name->IsSymbol()); | 115 ASSERT(name->IsSymbol()); |
| 116 __ IncrementCounter(&Counters::negative_lookups, 1); | 116 __ IncrementCounter(&Counters::negative_lookups, 1); |
| 117 __ IncrementCounter(&Counters::negative_lookups_miss, 1); | 117 __ IncrementCounter(&Counters::negative_lookups_miss, 1); |
| 118 | 118 |
| 119 Label done; | 119 Label done; |
| 120 __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset)); | 120 __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 121 | 121 |
| 122 const int kInterceptorOrAccessCheckNeededMask = | 122 const int kInterceptorOrAccessCheckNeededMask = |
| 123 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); | 123 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); |
| 124 | 124 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 153 StringDictionary::kElementsStartIndex * kPointerSize; | 153 StringDictionary::kElementsStartIndex * kPointerSize; |
| 154 | 154 |
| 155 // If names of slots in range from 1 to kProbes - 1 for the hash value are | 155 // If names of slots in range from 1 to kProbes - 1 for the hash value are |
| 156 // not equal to the name and kProbes-th slot is not used (its name is the | 156 // not equal to the name and kProbes-th slot is not used (its name is the |
| 157 // undefined value), it guarantees the hash table doesn't contain the | 157 // undefined value), it guarantees the hash table doesn't contain the |
| 158 // property. It's true even if some slots represent deleted properties | 158 // property. It's true even if some slots represent deleted properties |
| 159 // (their names are the null value). | 159 // (their names are the null value). |
| 160 for (int i = 0; i < kProbes; i++) { | 160 for (int i = 0; i < kProbes; i++) { |
| 161 // r0 points to properties hash. | 161 // r0 points to properties hash. |
| 162 // Compute the masked index: (hash + i + i * i) & mask. | 162 // Compute the masked index: (hash + i + i * i) & mask. |
| 163 if (extra.is(no_reg)) { | 163 Register index = r1; |
| 164 __ push(receiver); | |
| 165 } | |
| 166 Register index = extra.is(no_reg) ? receiver : extra; | |
| 167 // Capacity is smi 2^n. | 164 // Capacity is smi 2^n. |
| 168 __ mov(index, FieldOperand(properties, kCapacityOffset)); | 165 __ mov(index, FieldOperand(properties, kCapacityOffset)); |
| 169 __ dec(index); | 166 __ dec(index); |
| 170 __ and_(Operand(index), | 167 __ and_(Operand(index), |
| 171 Immediate(Smi::FromInt(name->Hash() + | 168 Immediate(Smi::FromInt(name->Hash() + |
| 172 StringDictionary::GetProbeOffset(i)))); | 169 StringDictionary::GetProbeOffset(i)))); |
| 173 | 170 |
| 174 // Scale the index by multiplying by the entry size. | 171 // Scale the index by multiplying by the entry size. |
| 175 ASSERT(StringDictionary::kEntrySize == 3); | 172 ASSERT(StringDictionary::kEntrySize == 3); |
| 176 __ lea(index, Operand(index, index, times_2, 0)); // index *= 3. | 173 __ lea(index, Operand(index, index, times_2, 0)); // index *= 3. |
| 177 | 174 |
| 178 Register entity_name = extra.is(no_reg) ? properties : extra; | 175 Register entity_name = r1; |
| 179 // Having undefined at this place means the name is not contained. | 176 // Having undefined at this place means the name is not contained. |
| 180 ASSERT_EQ(kSmiTagSize, 1); | 177 ASSERT_EQ(kSmiTagSize, 1); |
| 181 __ mov(entity_name, Operand(properties, index, times_half_pointer_size, | 178 __ mov(entity_name, Operand(properties, index, times_half_pointer_size, |
| 182 kElementsStartOffset - kHeapObjectTag)); | 179 kElementsStartOffset - kHeapObjectTag)); |
| 183 __ cmp(entity_name, Factory::undefined_value()); | 180 __ cmp(entity_name, Factory::undefined_value()); |
| 184 if (extra.is(no_reg)) { | |
| 185 // 'receiver' shares a register with 'entity_name'. | |
| 186 __ pop(receiver); | |
| 187 } | |
| 188 if (i != kProbes - 1) { | 181 if (i != kProbes - 1) { |
| 189 __ j(equal, &done, taken); | 182 __ j(equal, &done, taken); |
| 190 | 183 |
| 191 // Stop if found the property. | 184 // Stop if found the property. |
| 192 __ cmp(entity_name, Handle<String>(name)); | 185 __ cmp(entity_name, Handle<String>(name)); |
| 193 __ j(equal, miss_label, not_taken); | 186 __ j(equal, miss_label, not_taken); |
| 194 | |
| 195 if (extra.is(no_reg)) { | |
| 196 // Restore the properties if their register was occupied by the name. | |
| 197 __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); | |
| 198 } | |
| 199 } else { | 187 } else { |
| 200 // Give up probing if still not found the undefined value. | 188 // Give up probing if still not found the undefined value. |
| 201 __ j(not_equal, miss_label, not_taken); | 189 __ j(not_equal, miss_label, not_taken); |
| 202 } | 190 } |
| 203 } | 191 } |
| 204 | 192 |
| 205 __ bind(&done); | 193 __ bind(&done); |
| 206 __ DecrementCounter(&Counters::negative_lookups_miss, 1); | 194 __ DecrementCounter(&Counters::negative_lookups_miss, 1); |
| 207 } | 195 } |
| 208 | 196 |
| (...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 520 name_(name) {} | 508 name_(name) {} |
| 521 | 509 |
| 522 void Compile(MacroAssembler* masm, | 510 void Compile(MacroAssembler* masm, |
| 523 JSObject* object, | 511 JSObject* object, |
| 524 JSObject* holder, | 512 JSObject* holder, |
| 525 String* name, | 513 String* name, |
| 526 LookupResult* lookup, | 514 LookupResult* lookup, |
| 527 Register receiver, | 515 Register receiver, |
| 528 Register scratch1, | 516 Register scratch1, |
| 529 Register scratch2, | 517 Register scratch2, |
| 518 Register scratch3, |
| 530 Label* miss) { | 519 Label* miss) { |
| 531 ASSERT(holder->HasNamedInterceptor()); | 520 ASSERT(holder->HasNamedInterceptor()); |
| 532 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); | 521 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); |
| 533 | 522 |
| 534 // Check that the receiver isn't a smi. | 523 // Check that the receiver isn't a smi. |
| 535 __ test(receiver, Immediate(kSmiTagMask)); | 524 __ test(receiver, Immediate(kSmiTagMask)); |
| 536 __ j(zero, miss, not_taken); | 525 __ j(zero, miss, not_taken); |
| 537 | 526 |
| 538 CallOptimization optimization(lookup); | 527 CallOptimization optimization(lookup); |
| 539 | 528 |
| 540 if (optimization.is_constant_call()) { | 529 if (optimization.is_constant_call()) { |
| 541 CompileCacheable(masm, | 530 CompileCacheable(masm, |
| 542 object, | 531 object, |
| 543 receiver, | 532 receiver, |
| 544 scratch1, | 533 scratch1, |
| 545 scratch2, | 534 scratch2, |
| 535 scratch3, |
| 546 holder, | 536 holder, |
| 547 lookup, | 537 lookup, |
| 548 name, | 538 name, |
| 549 optimization, | 539 optimization, |
| 550 miss); | 540 miss); |
| 551 } else { | 541 } else { |
| 552 CompileRegular(masm, | 542 CompileRegular(masm, |
| 553 object, | 543 object, |
| 554 receiver, | 544 receiver, |
| 555 scratch1, | 545 scratch1, |
| 556 scratch2, | 546 scratch2, |
| 547 scratch3, |
| 557 name, | 548 name, |
| 558 holder, | 549 holder, |
| 559 miss); | 550 miss); |
| 560 } | 551 } |
| 561 } | 552 } |
| 562 | 553 |
| 563 private: | 554 private: |
| 564 void CompileCacheable(MacroAssembler* masm, | 555 void CompileCacheable(MacroAssembler* masm, |
| 565 JSObject* object, | 556 JSObject* object, |
| 566 Register receiver, | 557 Register receiver, |
| 567 Register scratch1, | 558 Register scratch1, |
| 568 Register scratch2, | 559 Register scratch2, |
| 560 Register scratch3, |
| 569 JSObject* interceptor_holder, | 561 JSObject* interceptor_holder, |
| 570 LookupResult* lookup, | 562 LookupResult* lookup, |
| 571 String* name, | 563 String* name, |
| 572 const CallOptimization& optimization, | 564 const CallOptimization& optimization, |
| 573 Label* miss_label) { | 565 Label* miss_label) { |
| 574 ASSERT(optimization.is_constant_call()); | 566 ASSERT(optimization.is_constant_call()); |
| 575 ASSERT(!lookup->holder()->IsGlobalObject()); | 567 ASSERT(!lookup->holder()->IsGlobalObject()); |
| 576 | 568 |
| 577 int depth1 = kInvalidProtoDepth; | 569 int depth1 = kInvalidProtoDepth; |
| 578 int depth2 = kInvalidProtoDepth; | 570 int depth2 = kInvalidProtoDepth; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 598 ReserveSpaceForFastApiCall(masm, scratch1); | 590 ReserveSpaceForFastApiCall(masm, scratch1); |
| 599 } | 591 } |
| 600 | 592 |
| 601 // Check that the maps from receiver to interceptor's holder | 593 // Check that the maps from receiver to interceptor's holder |
| 602 // haven't changed and thus we can invoke interceptor. | 594 // haven't changed and thus we can invoke interceptor. |
| 603 Label miss_cleanup; | 595 Label miss_cleanup; |
| 604 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; | 596 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; |
| 605 Register holder = | 597 Register holder = |
| 606 stub_compiler_->CheckPrototypes(object, receiver, | 598 stub_compiler_->CheckPrototypes(object, receiver, |
| 607 interceptor_holder, scratch1, | 599 interceptor_holder, scratch1, |
| 608 scratch2, name, depth1, miss); | 600 scratch2, scratch3, name, depth1, miss); |
| 609 | 601 |
| 610 // Invoke an interceptor and if it provides a value, | 602 // Invoke an interceptor and if it provides a value, |
| 611 // branch to |regular_invoke|. | 603 // branch to |regular_invoke|. |
| 612 Label regular_invoke; | 604 Label regular_invoke; |
| 613 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, | 605 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, |
| 614 ®ular_invoke); | 606 ®ular_invoke); |
| 615 | 607 |
| 616 // Interceptor returned nothing for this property. Try to use cached | 608 // Interceptor returned nothing for this property. Try to use cached |
| 617 // constant function. | 609 // constant function. |
| 618 | 610 |
| 619 // Check that the maps from interceptor's holder to constant function's | 611 // Check that the maps from interceptor's holder to constant function's |
| 620 // holder haven't changed and thus we can use cached constant function. | 612 // holder haven't changed and thus we can use cached constant function. |
| 621 if (interceptor_holder != lookup->holder()) { | 613 if (interceptor_holder != lookup->holder()) { |
| 622 stub_compiler_->CheckPrototypes(interceptor_holder, receiver, | 614 stub_compiler_->CheckPrototypes(interceptor_holder, receiver, |
| 623 lookup->holder(), scratch1, | 615 lookup->holder(), scratch1, |
| 624 scratch2, name, depth2, miss); | 616 scratch2, scratch3, name, depth2, miss); |
| 625 } else { | 617 } else { |
| 626 // CheckPrototypes has a side effect of fetching a 'holder' | 618 // CheckPrototypes has a side effect of fetching a 'holder' |
| 627 // for API (object which is instanceof for the signature). It's | 619 // for API (object which is instanceof for the signature). It's |
| 628 // safe to omit it here, as if present, it should be fetched | 620 // safe to omit it here, as if present, it should be fetched |
| 629 // by the previous CheckPrototypes. | 621 // by the previous CheckPrototypes. |
| 630 ASSERT(depth2 == kInvalidProtoDepth); | 622 ASSERT(depth2 == kInvalidProtoDepth); |
| 631 } | 623 } |
| 632 | 624 |
| 633 // Invoke function. | 625 // Invoke function. |
| 634 if (can_do_fast_api_call) { | 626 if (can_do_fast_api_call) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 650 if (can_do_fast_api_call) { | 642 if (can_do_fast_api_call) { |
| 651 FreeSpaceForFastApiCall(masm, scratch1); | 643 FreeSpaceForFastApiCall(masm, scratch1); |
| 652 } | 644 } |
| 653 } | 645 } |
| 654 | 646 |
| 655 void CompileRegular(MacroAssembler* masm, | 647 void CompileRegular(MacroAssembler* masm, |
| 656 JSObject* object, | 648 JSObject* object, |
| 657 Register receiver, | 649 Register receiver, |
| 658 Register scratch1, | 650 Register scratch1, |
| 659 Register scratch2, | 651 Register scratch2, |
| 652 Register scratch3, |
| 660 String* name, | 653 String* name, |
| 661 JSObject* interceptor_holder, | 654 JSObject* interceptor_holder, |
| 662 Label* miss_label) { | 655 Label* miss_label) { |
| 663 Register holder = | 656 Register holder = |
| 664 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, | 657 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, |
| 665 scratch1, scratch2, name, | 658 scratch1, scratch2, scratch3, name, |
| 666 miss_label); | 659 miss_label); |
| 667 | 660 |
| 668 __ EnterInternalFrame(); | 661 __ EnterInternalFrame(); |
| 669 // Save the name_ register across the call. | 662 // Save the name_ register across the call. |
| 670 __ push(name_); | 663 __ push(name_); |
| 671 | 664 |
| 672 PushInterceptorArguments(masm, | 665 PushInterceptorArguments(masm, |
| 673 receiver, | 666 receiver, |
| 674 holder, | 667 holder, |
| 675 name_, | 668 name_, |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 857 | 850 |
| 858 | 851 |
| 859 #undef __ | 852 #undef __ |
| 860 #define __ ACCESS_MASM(masm()) | 853 #define __ ACCESS_MASM(masm()) |
| 861 | 854 |
| 862 | 855 |
| 863 Register StubCompiler::CheckPrototypes(JSObject* object, | 856 Register StubCompiler::CheckPrototypes(JSObject* object, |
| 864 Register object_reg, | 857 Register object_reg, |
| 865 JSObject* holder, | 858 JSObject* holder, |
| 866 Register holder_reg, | 859 Register holder_reg, |
| 867 Register scratch, | 860 Register scratch1, |
| 861 Register scratch2, |
| 868 String* name, | 862 String* name, |
| 869 int save_at_depth, | 863 int save_at_depth, |
| 870 Label* miss, | 864 Label* miss) { |
| 871 Register extra) { | |
| 872 // Make sure there's no overlap between holder and object registers. | 865 // Make sure there's no overlap between holder and object registers. |
| 873 ASSERT(!scratch.is(object_reg) && !scratch.is(holder_reg)); | 866 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
| 874 ASSERT(!extra.is(object_reg) && !extra.is(holder_reg) && !extra.is(scratch)); | 867 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
| 868 && !scratch2.is(scratch1)); |
| 875 // Keep track of the current object in register reg. | 869 // Keep track of the current object in register reg. |
| 876 Register reg = object_reg; | 870 Register reg = object_reg; |
| 877 JSObject* current = object; | 871 JSObject* current = object; |
| 878 int depth = 0; | 872 int depth = 0; |
| 879 | 873 |
| 880 if (save_at_depth == depth) { | 874 if (save_at_depth == depth) { |
| 881 __ mov(Operand(esp, kPointerSize), reg); | 875 __ mov(Operand(esp, kPointerSize), reg); |
| 882 } | 876 } |
| 883 | 877 |
| 884 // Traverse the prototype chain and check the maps in the prototype chain for | 878 // Traverse the prototype chain and check the maps in the prototype chain for |
| (...skipping 19 matching lines...) Expand all Loading... |
| 904 name = String::cast(lookup_result); | 898 name = String::cast(lookup_result); |
| 905 } | 899 } |
| 906 } | 900 } |
| 907 ASSERT(current->property_dictionary()->FindEntry(name) == | 901 ASSERT(current->property_dictionary()->FindEntry(name) == |
| 908 StringDictionary::kNotFound); | 902 StringDictionary::kNotFound); |
| 909 | 903 |
| 910 GenerateDictionaryNegativeLookup(masm(), | 904 GenerateDictionaryNegativeLookup(masm(), |
| 911 miss, | 905 miss, |
| 912 reg, | 906 reg, |
| 913 name, | 907 name, |
| 914 scratch, | 908 scratch1, |
| 915 extra); | 909 scratch2); |
| 916 __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); | 910 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 917 reg = holder_reg; // from now the object is in holder_reg | 911 reg = holder_reg; // from now the object is in holder_reg |
| 918 __ mov(reg, FieldOperand(scratch, Map::kPrototypeOffset)); | 912 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
| 919 } else if (Heap::InNewSpace(prototype)) { | 913 } else if (Heap::InNewSpace(prototype)) { |
| 920 // Get the map of the current object. | 914 // Get the map of the current object. |
| 921 __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); | 915 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 922 __ cmp(Operand(scratch), Immediate(Handle<Map>(current->map()))); | 916 __ cmp(Operand(scratch1), Immediate(Handle<Map>(current->map()))); |
| 923 // Branch on the result of the map check. | 917 // Branch on the result of the map check. |
| 924 __ j(not_equal, miss, not_taken); | 918 __ j(not_equal, miss, not_taken); |
| 925 // Check access rights to the global object. This has to happen | 919 // Check access rights to the global object. This has to happen |
| 926 // after the map check so that we know that the object is | 920 // after the map check so that we know that the object is |
| 927 // actually a global object. | 921 // actually a global object. |
| 928 if (current->IsJSGlobalProxy()) { | 922 if (current->IsJSGlobalProxy()) { |
| 929 __ CheckAccessGlobalProxy(reg, scratch, miss); | 923 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
| 930 | 924 |
| 931 // Restore scratch register to be the map of the object. | 925 // Restore scratch register to be the map of the object. |
| 932 // We load the prototype from the map in the scratch register. | 926 // We load the prototype from the map in the scratch register. |
| 933 __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); | 927 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 934 } | 928 } |
| 935 // The prototype is in new space; we cannot store a reference | 929 // The prototype is in new space; we cannot store a reference |
| 936 // to it in the code. Load it from the map. | 930 // to it in the code. Load it from the map. |
| 937 reg = holder_reg; // from now the object is in holder_reg | 931 reg = holder_reg; // from now the object is in holder_reg |
| 938 __ mov(reg, FieldOperand(scratch, Map::kPrototypeOffset)); | 932 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
| 939 } else { | 933 } else { |
| 940 // Check the map of the current object. | 934 // Check the map of the current object. |
| 941 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 935 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 942 Immediate(Handle<Map>(current->map()))); | 936 Immediate(Handle<Map>(current->map()))); |
| 943 // Branch on the result of the map check. | 937 // Branch on the result of the map check. |
| 944 __ j(not_equal, miss, not_taken); | 938 __ j(not_equal, miss, not_taken); |
| 945 // Check access rights to the global object. This has to happen | 939 // Check access rights to the global object. This has to happen |
| 946 // after the map check so that we know that the object is | 940 // after the map check so that we know that the object is |
| 947 // actually a global object. | 941 // actually a global object. |
| 948 if (current->IsJSGlobalProxy()) { | 942 if (current->IsJSGlobalProxy()) { |
| 949 __ CheckAccessGlobalProxy(reg, scratch, miss); | 943 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
| 950 } | 944 } |
| 951 // The prototype is in old space; load it directly. | 945 // The prototype is in old space; load it directly. |
| 952 reg = holder_reg; // from now the object is in holder_reg | 946 reg = holder_reg; // from now the object is in holder_reg |
| 953 __ mov(reg, Handle<JSObject>(prototype)); | 947 __ mov(reg, Handle<JSObject>(prototype)); |
| 954 } | 948 } |
| 955 | 949 |
| 956 if (save_at_depth == depth) { | 950 if (save_at_depth == depth) { |
| 957 __ mov(Operand(esp, kPointerSize), reg); | 951 __ mov(Operand(esp, kPointerSize), reg); |
| 958 } | 952 } |
| 959 | 953 |
| 960 // Go to the next object in the prototype chain. | 954 // Go to the next object in the prototype chain. |
| 961 current = prototype; | 955 current = prototype; |
| 962 } | 956 } |
| 963 ASSERT(current == holder); | 957 ASSERT(current == holder); |
| 964 | 958 |
| 965 // Log the check depth. | 959 // Log the check depth. |
| 966 LOG(IntEvent("check-maps-depth", depth + 1)); | 960 LOG(IntEvent("check-maps-depth", depth + 1)); |
| 967 | 961 |
| 968 // Check the holder map. | 962 // Check the holder map. |
| 969 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 963 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 970 Immediate(Handle<Map>(holder->map()))); | 964 Immediate(Handle<Map>(holder->map()))); |
| 971 __ j(not_equal, miss, not_taken); | 965 __ j(not_equal, miss, not_taken); |
| 972 | 966 |
| 973 // Perform security check for access to the global object. | 967 // Perform security check for access to the global object. |
| 974 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | 968 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
| 975 if (holder->IsJSGlobalProxy()) { | 969 if (holder->IsJSGlobalProxy()) { |
| 976 __ CheckAccessGlobalProxy(reg, scratch, miss); | 970 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
| 977 }; | 971 }; |
| 978 | 972 |
| 979 // If we've skipped any global objects, it's not enough to verify | 973 // If we've skipped any global objects, it's not enough to verify |
| 980 // that their maps haven't changed. We also need to check that the | 974 // that their maps haven't changed. We also need to check that the |
| 981 // property cell for the property is still empty. | 975 // property cell for the property is still empty. |
| 982 Object* result = GenerateCheckPropertyCells(masm(), | 976 Object* result = GenerateCheckPropertyCells(masm(), |
| 983 object, | 977 object, |
| 984 holder, | 978 holder, |
| 985 name, | 979 name, |
| 986 scratch, | 980 scratch1, |
| 987 miss); | 981 miss); |
| 988 if (result->IsFailure()) set_failure(Failure::cast(result)); | 982 if (result->IsFailure()) set_failure(Failure::cast(result)); |
| 989 | 983 |
| 990 // Return the register containing the holder. | 984 // Return the register containing the holder. |
| 991 return reg; | 985 return reg; |
| 992 } | 986 } |
| 993 | 987 |
| 994 | 988 |
| 995 void StubCompiler::GenerateLoadField(JSObject* object, | 989 void StubCompiler::GenerateLoadField(JSObject* object, |
| 996 JSObject* holder, | 990 JSObject* holder, |
| 997 Register receiver, | 991 Register receiver, |
| 998 Register scratch1, | 992 Register scratch1, |
| 999 Register scratch2, | 993 Register scratch2, |
| 994 Register scratch3, |
| 1000 int index, | 995 int index, |
| 1001 String* name, | 996 String* name, |
| 1002 Label* miss) { | 997 Label* miss) { |
| 1003 // Check that the receiver isn't a smi. | 998 // Check that the receiver isn't a smi. |
| 1004 __ test(receiver, Immediate(kSmiTagMask)); | 999 __ test(receiver, Immediate(kSmiTagMask)); |
| 1005 __ j(zero, miss, not_taken); | 1000 __ j(zero, miss, not_taken); |
| 1006 | 1001 |
| 1007 // Check the prototype chain. | 1002 // Check the prototype chain. |
| 1008 Register reg = | 1003 Register reg = |
| 1009 CheckPrototypes(object, receiver, holder, | 1004 CheckPrototypes(object, receiver, holder, |
| 1010 scratch1, scratch2, name, miss); | 1005 scratch1, scratch2, scratch3, name, miss); |
| 1011 | 1006 |
| 1012 // Get the value from the properties. | 1007 // Get the value from the properties. |
| 1013 GenerateFastPropertyLoad(masm(), eax, reg, holder, index); | 1008 GenerateFastPropertyLoad(masm(), eax, reg, holder, index); |
| 1014 __ ret(0); | 1009 __ ret(0); |
| 1015 } | 1010 } |
| 1016 | 1011 |
| 1017 | 1012 |
| 1018 bool StubCompiler::GenerateLoadCallback(JSObject* object, | 1013 bool StubCompiler::GenerateLoadCallback(JSObject* object, |
| 1019 JSObject* holder, | 1014 JSObject* holder, |
| 1020 Register receiver, | 1015 Register receiver, |
| 1021 Register name_reg, | 1016 Register name_reg, |
| 1022 Register scratch1, | 1017 Register scratch1, |
| 1023 Register scratch2, | 1018 Register scratch2, |
| 1019 Register scratch3, |
| 1024 AccessorInfo* callback, | 1020 AccessorInfo* callback, |
| 1025 String* name, | 1021 String* name, |
| 1026 Label* miss, | 1022 Label* miss, |
| 1027 Failure** failure) { | 1023 Failure** failure) { |
| 1028 // Check that the receiver isn't a smi. | 1024 // Check that the receiver isn't a smi. |
| 1029 __ test(receiver, Immediate(kSmiTagMask)); | 1025 __ test(receiver, Immediate(kSmiTagMask)); |
| 1030 __ j(zero, miss, not_taken); | 1026 __ j(zero, miss, not_taken); |
| 1031 | 1027 |
| 1032 // Check that the maps haven't changed. | 1028 // Check that the maps haven't changed. |
| 1033 Register reg = | 1029 Register reg = |
| 1034 CheckPrototypes(object, receiver, holder, | 1030 CheckPrototypes(object, receiver, holder, |
| 1035 scratch1, scratch2, name, miss); | 1031 scratch1, scratch2, scratch3, name, miss); |
| 1036 | 1032 |
| 1037 Handle<AccessorInfo> callback_handle(callback); | 1033 Handle<AccessorInfo> callback_handle(callback); |
| 1038 | 1034 |
| 1039 Register other = reg.is(scratch1) ? scratch2 : scratch1; | 1035 Register other = reg.is(scratch1) ? scratch2 : scratch1; |
| 1040 __ EnterInternalFrame(); | 1036 __ EnterInternalFrame(); |
| 1041 __ PushHandleScope(other); | 1037 __ PushHandleScope(other); |
| 1042 // Push the stack address where the list of arguments ends | 1038 // Push the stack address where the list of arguments ends |
| 1043 __ mov(other, esp); | 1039 __ mov(other, esp); |
| 1044 __ sub(Operand(other), Immediate(2 * kPointerSize)); | 1040 __ sub(Operand(other), Immediate(2 * kPointerSize)); |
| 1045 __ push(other); | 1041 __ push(other); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1089 __ ret(0); | 1085 __ ret(0); |
| 1090 return true; | 1086 return true; |
| 1091 } | 1087 } |
| 1092 | 1088 |
| 1093 | 1089 |
| 1094 void StubCompiler::GenerateLoadConstant(JSObject* object, | 1090 void StubCompiler::GenerateLoadConstant(JSObject* object, |
| 1095 JSObject* holder, | 1091 JSObject* holder, |
| 1096 Register receiver, | 1092 Register receiver, |
| 1097 Register scratch1, | 1093 Register scratch1, |
| 1098 Register scratch2, | 1094 Register scratch2, |
| 1095 Register scratch3, |
| 1099 Object* value, | 1096 Object* value, |
| 1100 String* name, | 1097 String* name, |
| 1101 Label* miss) { | 1098 Label* miss) { |
| 1102 // Check that the receiver isn't a smi. | 1099 // Check that the receiver isn't a smi. |
| 1103 __ test(receiver, Immediate(kSmiTagMask)); | 1100 __ test(receiver, Immediate(kSmiTagMask)); |
| 1104 __ j(zero, miss, not_taken); | 1101 __ j(zero, miss, not_taken); |
| 1105 | 1102 |
| 1106 // Check that the maps haven't changed. | 1103 // Check that the maps haven't changed. |
| 1107 Register reg = | 1104 Register reg = |
| 1108 CheckPrototypes(object, receiver, holder, | 1105 CheckPrototypes(object, receiver, holder, |
| 1109 scratch1, scratch2, name, miss); | 1106 scratch1, scratch2, scratch3, name, miss); |
| 1110 | 1107 |
| 1111 // Return the constant value. | 1108 // Return the constant value. |
| 1112 __ mov(eax, Handle<Object>(value)); | 1109 __ mov(eax, Handle<Object>(value)); |
| 1113 __ ret(0); | 1110 __ ret(0); |
| 1114 } | 1111 } |
| 1115 | 1112 |
| 1116 | 1113 |
| 1117 void StubCompiler::GenerateLoadInterceptor(JSObject* object, | 1114 void StubCompiler::GenerateLoadInterceptor(JSObject* object, |
| 1118 JSObject* interceptor_holder, | 1115 JSObject* interceptor_holder, |
| 1119 LookupResult* lookup, | 1116 LookupResult* lookup, |
| 1120 Register receiver, | 1117 Register receiver, |
| 1121 Register name_reg, | 1118 Register name_reg, |
| 1122 Register scratch1, | 1119 Register scratch1, |
| 1123 Register scratch2, | 1120 Register scratch2, |
| 1121 Register scratch3, |
| 1124 String* name, | 1122 String* name, |
| 1125 Label* miss) { | 1123 Label* miss) { |
| 1126 ASSERT(interceptor_holder->HasNamedInterceptor()); | 1124 ASSERT(interceptor_holder->HasNamedInterceptor()); |
| 1127 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 1125 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); |
| 1128 | 1126 |
| 1129 // Check that the receiver isn't a smi. | 1127 // Check that the receiver isn't a smi. |
| 1130 __ test(receiver, Immediate(kSmiTagMask)); | 1128 __ test(receiver, Immediate(kSmiTagMask)); |
| 1131 __ j(zero, miss, not_taken); | 1129 __ j(zero, miss, not_taken); |
| 1132 | 1130 |
| 1133 // So far the most popular follow ups for interceptor loads are FIELD | 1131 // So far the most popular follow ups for interceptor loads are FIELD |
| 1134 // and CALLBACKS, so inline only them, other cases may be added | 1132 // and CALLBACKS, so inline only them, other cases may be added |
| 1135 // later. | 1133 // later. |
| 1136 bool compile_followup_inline = false; | 1134 bool compile_followup_inline = false; |
| 1137 if (lookup->IsProperty() && lookup->IsCacheable()) { | 1135 if (lookup->IsProperty() && lookup->IsCacheable()) { |
| 1138 if (lookup->type() == FIELD) { | 1136 if (lookup->type() == FIELD) { |
| 1139 compile_followup_inline = true; | 1137 compile_followup_inline = true; |
| 1140 } else if (lookup->type() == CALLBACKS && | 1138 } else if (lookup->type() == CALLBACKS && |
| 1141 lookup->GetCallbackObject()->IsAccessorInfo() && | 1139 lookup->GetCallbackObject()->IsAccessorInfo() && |
| 1142 AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL) { | 1140 AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL) { |
| 1143 compile_followup_inline = true; | 1141 compile_followup_inline = true; |
| 1144 } | 1142 } |
| 1145 } | 1143 } |
| 1146 | 1144 |
| 1147 if (compile_followup_inline) { | 1145 if (compile_followup_inline) { |
| 1148 // Compile the interceptor call, followed by inline code to load the | 1146 // Compile the interceptor call, followed by inline code to load the |
| 1149 // property from further up the prototype chain if the call fails. | 1147 // property from further up the prototype chain if the call fails. |
| 1150 // Check that the maps haven't changed. | 1148 // Check that the maps haven't changed. |
| 1151 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, | 1149 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, |
| 1152 scratch1, scratch2, name, miss); | 1150 scratch1, scratch2, scratch3, |
| 1151 name, miss); |
| 1153 ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1)); | 1152 ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1)); |
| 1154 | 1153 |
| 1155 // Save necessary data before invoking an interceptor. | 1154 // Save necessary data before invoking an interceptor. |
| 1156 // Requires a frame to make GC aware of pushed pointers. | 1155 // Requires a frame to make GC aware of pushed pointers. |
| 1157 __ EnterInternalFrame(); | 1156 __ EnterInternalFrame(); |
| 1158 | 1157 |
| 1159 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { | 1158 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { |
| 1160 // CALLBACKS case needs a receiver to be passed into C++ callback. | 1159 // CALLBACKS case needs a receiver to be passed into C++ callback. |
| 1161 __ push(receiver); | 1160 __ push(receiver); |
| 1162 } | 1161 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1190 __ LeaveInternalFrame(); | 1189 __ LeaveInternalFrame(); |
| 1191 | 1190 |
| 1192 // Check that the maps from interceptor's holder to lookup's holder | 1191 // Check that the maps from interceptor's holder to lookup's holder |
| 1193 // haven't changed. And load lookup's holder into holder_reg. | 1192 // haven't changed. And load lookup's holder into holder_reg. |
| 1194 if (interceptor_holder != lookup->holder()) { | 1193 if (interceptor_holder != lookup->holder()) { |
| 1195 holder_reg = CheckPrototypes(interceptor_holder, | 1194 holder_reg = CheckPrototypes(interceptor_holder, |
| 1196 holder_reg, | 1195 holder_reg, |
| 1197 lookup->holder(), | 1196 lookup->holder(), |
| 1198 scratch1, | 1197 scratch1, |
| 1199 scratch2, | 1198 scratch2, |
| 1199 scratch3, |
| 1200 name, | 1200 name, |
| 1201 miss); | 1201 miss); |
| 1202 } | 1202 } |
| 1203 | 1203 |
| 1204 if (lookup->type() == FIELD) { | 1204 if (lookup->type() == FIELD) { |
| 1205 // We found FIELD property in prototype chain of interceptor's holder. | 1205 // We found FIELD property in prototype chain of interceptor's holder. |
| 1206 // Retrieve a field from field's holder. | 1206 // Retrieve a field from field's holder. |
| 1207 GenerateFastPropertyLoad(masm(), eax, holder_reg, | 1207 GenerateFastPropertyLoad(masm(), eax, holder_reg, |
| 1208 lookup->holder(), lookup->GetFieldIndex()); | 1208 lookup->holder(), lookup->GetFieldIndex()); |
| 1209 __ ret(0); | 1209 __ ret(0); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1230 | 1230 |
| 1231 ExternalReference ref = | 1231 ExternalReference ref = |
| 1232 ExternalReference(IC_Utility(IC::kLoadCallbackProperty)); | 1232 ExternalReference(IC_Utility(IC::kLoadCallbackProperty)); |
| 1233 __ TailCallExternalReference(ref, 5, 1); | 1233 __ TailCallExternalReference(ref, 5, 1); |
| 1234 } | 1234 } |
| 1235 } else { // !compile_followup_inline | 1235 } else { // !compile_followup_inline |
| 1236 // Call the runtime system to load the interceptor. | 1236 // Call the runtime system to load the interceptor. |
| 1237 // Check that the maps haven't changed. | 1237 // Check that the maps haven't changed. |
| 1238 Register holder_reg = | 1238 Register holder_reg = |
| 1239 CheckPrototypes(object, receiver, interceptor_holder, | 1239 CheckPrototypes(object, receiver, interceptor_holder, |
| 1240 scratch1, scratch2, name, miss); | 1240 scratch1, scratch2, scratch3, name, miss); |
| 1241 __ pop(scratch2); // save old return address | 1241 __ pop(scratch2); // save old return address |
| 1242 PushInterceptorArguments(masm(), receiver, holder_reg, | 1242 PushInterceptorArguments(masm(), receiver, holder_reg, |
| 1243 name_reg, interceptor_holder); | 1243 name_reg, interceptor_holder); |
| 1244 __ push(scratch2); // restore old return address | 1244 __ push(scratch2); // restore old return address |
| 1245 | 1245 |
| 1246 ExternalReference ref = ExternalReference( | 1246 ExternalReference ref = ExternalReference( |
| 1247 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad)); | 1247 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad)); |
| 1248 __ TailCallExternalReference(ref, 5, 1); | 1248 __ TailCallExternalReference(ref, 5, 1); |
| 1249 } | 1249 } |
| 1250 } | 1250 } |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1305 | 1305 |
| 1306 // Get the receiver from the stack. | 1306 // Get the receiver from the stack. |
| 1307 const int argc = arguments().immediate(); | 1307 const int argc = arguments().immediate(); |
| 1308 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1308 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 1309 | 1309 |
| 1310 // Check that the receiver isn't a smi. | 1310 // Check that the receiver isn't a smi. |
| 1311 __ test(edx, Immediate(kSmiTagMask)); | 1311 __ test(edx, Immediate(kSmiTagMask)); |
| 1312 __ j(zero, &miss, not_taken); | 1312 __ j(zero, &miss, not_taken); |
| 1313 | 1313 |
| 1314 // Do the right check and compute the holder register. | 1314 // Do the right check and compute the holder register. |
| 1315 Register reg = CheckPrototypes(object, edx, holder, ebx, eax, | 1315 Register reg = CheckPrototypes(object, edx, holder, ebx, eax, edi, |
| 1316 name, &miss, edi); | 1316 name, &miss); |
| 1317 | 1317 |
| 1318 GenerateFastPropertyLoad(masm(), edi, reg, holder, index); | 1318 GenerateFastPropertyLoad(masm(), edi, reg, holder, index); |
| 1319 | 1319 |
| 1320 // Check that the function really is a function. | 1320 // Check that the function really is a function. |
| 1321 __ test(edi, Immediate(kSmiTagMask)); | 1321 __ test(edi, Immediate(kSmiTagMask)); |
| 1322 __ j(zero, &miss, not_taken); | 1322 __ j(zero, &miss, not_taken); |
| 1323 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); | 1323 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); |
| 1324 __ j(not_equal, &miss, not_taken); | 1324 __ j(not_equal, &miss, not_taken); |
| 1325 | 1325 |
| 1326 // Patch the receiver on the stack with the global proxy if | 1326 // Patch the receiver on the stack with the global proxy if |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1368 // Get the receiver from the stack. | 1368 // Get the receiver from the stack. |
| 1369 const int argc = arguments().immediate(); | 1369 const int argc = arguments().immediate(); |
| 1370 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1370 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 1371 | 1371 |
| 1372 // Check that the receiver isn't a smi. | 1372 // Check that the receiver isn't a smi. |
| 1373 __ test(edx, Immediate(kSmiTagMask)); | 1373 __ test(edx, Immediate(kSmiTagMask)); |
| 1374 __ j(zero, &miss); | 1374 __ j(zero, &miss); |
| 1375 | 1375 |
| 1376 CheckPrototypes(JSObject::cast(object), edx, | 1376 CheckPrototypes(JSObject::cast(object), edx, |
| 1377 holder, ebx, | 1377 holder, ebx, |
| 1378 eax, name, &miss, edi); | 1378 eax, edi, name, &miss); |
| 1379 | 1379 |
| 1380 if (argc == 0) { | 1380 if (argc == 0) { |
| 1381 // Noop, return the length. | 1381 // Noop, return the length. |
| 1382 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); | 1382 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); |
| 1383 __ ret((argc + 1) * kPointerSize); | 1383 __ ret((argc + 1) * kPointerSize); |
| 1384 } else { | 1384 } else { |
| 1385 // Get the elements array of the object. | 1385 // Get the elements array of the object. |
| 1386 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); | 1386 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); |
| 1387 | 1387 |
| 1388 // Check that the elements are in fast mode (not dictionary). | 1388 // Check that the elements are in fast mode (not dictionary). |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1514 | 1514 |
| 1515 // Get the receiver from the stack. | 1515 // Get the receiver from the stack. |
| 1516 const int argc = arguments().immediate(); | 1516 const int argc = arguments().immediate(); |
| 1517 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1517 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 1518 | 1518 |
| 1519 // Check that the receiver isn't a smi. | 1519 // Check that the receiver isn't a smi. |
| 1520 __ test(edx, Immediate(kSmiTagMask)); | 1520 __ test(edx, Immediate(kSmiTagMask)); |
| 1521 __ j(zero, &miss); | 1521 __ j(zero, &miss); |
| 1522 CheckPrototypes(JSObject::cast(object), edx, | 1522 CheckPrototypes(JSObject::cast(object), edx, |
| 1523 holder, ebx, | 1523 holder, ebx, |
| 1524 eax, name, &miss, edi); | 1524 eax, edi, name, &miss); |
| 1525 | 1525 |
| 1526 // Get the elements array of the object. | 1526 // Get the elements array of the object. |
| 1527 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); | 1527 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); |
| 1528 | 1528 |
| 1529 // Check that the elements are in fast mode (not dictionary). | 1529 // Check that the elements are in fast mode (not dictionary). |
| 1530 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), | 1530 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), |
| 1531 Immediate(Factory::fixed_array_map())); | 1531 Immediate(Factory::fixed_array_map())); |
| 1532 __ j(not_equal, &miss); | 1532 __ j(not_equal, &miss); |
| 1533 | 1533 |
| 1534 // Get the array's length into ecx and calculate new length. | 1534 // Get the array's length into ecx and calculate new length. |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1589 | 1589 |
| 1590 Label miss; | 1590 Label miss; |
| 1591 Label index_out_of_range; | 1591 Label index_out_of_range; |
| 1592 GenerateNameCheck(name, &miss); | 1592 GenerateNameCheck(name, &miss); |
| 1593 | 1593 |
| 1594 // Check that the maps starting from the prototype haven't changed. | 1594 // Check that the maps starting from the prototype haven't changed. |
| 1595 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 1595 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
| 1596 Context::STRING_FUNCTION_INDEX, | 1596 Context::STRING_FUNCTION_INDEX, |
| 1597 eax); | 1597 eax); |
| 1598 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 1598 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
| 1599 ebx, edx, name, &miss, edi); | 1599 ebx, edx, edi, name, &miss); |
| 1600 | 1600 |
| 1601 Register receiver = ebx; | 1601 Register receiver = ebx; |
| 1602 Register index = edi; | 1602 Register index = edi; |
| 1603 Register scratch = edx; | 1603 Register scratch = edx; |
| 1604 Register result = eax; | 1604 Register result = eax; |
| 1605 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); | 1605 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); |
| 1606 if (argc > 0) { | 1606 if (argc > 0) { |
| 1607 __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); | 1607 __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); |
| 1608 } else { | 1608 } else { |
| 1609 __ Set(index, Immediate(Factory::undefined_value())); | 1609 __ Set(index, Immediate(Factory::undefined_value())); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1654 Label miss; | 1654 Label miss; |
| 1655 Label index_out_of_range; | 1655 Label index_out_of_range; |
| 1656 | 1656 |
| 1657 GenerateNameCheck(name, &miss); | 1657 GenerateNameCheck(name, &miss); |
| 1658 | 1658 |
| 1659 // Check that the maps starting from the prototype haven't changed. | 1659 // Check that the maps starting from the prototype haven't changed. |
| 1660 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 1660 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
| 1661 Context::STRING_FUNCTION_INDEX, | 1661 Context::STRING_FUNCTION_INDEX, |
| 1662 eax); | 1662 eax); |
| 1663 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 1663 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
| 1664 ebx, edx, name, &miss, edi); | 1664 ebx, edx, edi, name, &miss); |
| 1665 | 1665 |
| 1666 Register receiver = eax; | 1666 Register receiver = eax; |
| 1667 Register index = edi; | 1667 Register index = edi; |
| 1668 Register scratch1 = ebx; | 1668 Register scratch1 = ebx; |
| 1669 Register scratch2 = edx; | 1669 Register scratch2 = edx; |
| 1670 Register result = eax; | 1670 Register result = eax; |
| 1671 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); | 1671 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); |
| 1672 if (argc > 0) { | 1672 if (argc > 0) { |
| 1673 __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); | 1673 __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); |
| 1674 } else { | 1674 } else { |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1759 JSObject::cast(object), holder); | 1759 JSObject::cast(object), holder); |
| 1760 } | 1760 } |
| 1761 | 1761 |
| 1762 if (depth != kInvalidProtoDepth) { | 1762 if (depth != kInvalidProtoDepth) { |
| 1763 __ IncrementCounter(&Counters::call_const_fast_api, 1); | 1763 __ IncrementCounter(&Counters::call_const_fast_api, 1); |
| 1764 ReserveSpaceForFastApiCall(masm(), eax); | 1764 ReserveSpaceForFastApiCall(masm(), eax); |
| 1765 } | 1765 } |
| 1766 | 1766 |
| 1767 // Check that the maps haven't changed. | 1767 // Check that the maps haven't changed. |
| 1768 CheckPrototypes(JSObject::cast(object), edx, holder, | 1768 CheckPrototypes(JSObject::cast(object), edx, holder, |
| 1769 ebx, eax, name, depth, &miss, edi); | 1769 ebx, eax, edi, name, depth, &miss); |
| 1770 | 1770 |
| 1771 // Patch the receiver on the stack with the global proxy if | 1771 // Patch the receiver on the stack with the global proxy if |
| 1772 // necessary. | 1772 // necessary. |
| 1773 if (object->IsGlobalObject()) { | 1773 if (object->IsGlobalObject()) { |
| 1774 ASSERT(depth == kInvalidProtoDepth); | 1774 ASSERT(depth == kInvalidProtoDepth); |
| 1775 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 1775 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
| 1776 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 1776 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
| 1777 } | 1777 } |
| 1778 break; | 1778 break; |
| 1779 | 1779 |
| 1780 case STRING_CHECK: | 1780 case STRING_CHECK: |
| 1781 if (!function->IsBuiltin()) { | 1781 if (!function->IsBuiltin()) { |
| 1782 // Calling non-builtins with a value as receiver requires boxing. | 1782 // Calling non-builtins with a value as receiver requires boxing. |
| 1783 __ jmp(&miss); | 1783 __ jmp(&miss); |
| 1784 } else { | 1784 } else { |
| 1785 // Check that the object is a string or a symbol. | 1785 // Check that the object is a string or a symbol. |
| 1786 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, eax); | 1786 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, eax); |
| 1787 __ j(above_equal, &miss, not_taken); | 1787 __ j(above_equal, &miss, not_taken); |
| 1788 // Check that the maps starting from the prototype haven't changed. | 1788 // Check that the maps starting from the prototype haven't changed. |
| 1789 GenerateDirectLoadGlobalFunctionPrototype( | 1789 GenerateDirectLoadGlobalFunctionPrototype( |
| 1790 masm(), Context::STRING_FUNCTION_INDEX, eax); | 1790 masm(), Context::STRING_FUNCTION_INDEX, eax); |
| 1791 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 1791 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
| 1792 ebx, edx, name, &miss, edi); | 1792 ebx, edx, edi, name, &miss); |
| 1793 } | 1793 } |
| 1794 break; | 1794 break; |
| 1795 | 1795 |
| 1796 case NUMBER_CHECK: { | 1796 case NUMBER_CHECK: { |
| 1797 if (!function->IsBuiltin()) { | 1797 if (!function->IsBuiltin()) { |
| 1798 // Calling non-builtins with a value as receiver requires boxing. | 1798 // Calling non-builtins with a value as receiver requires boxing. |
| 1799 __ jmp(&miss); | 1799 __ jmp(&miss); |
| 1800 } else { | 1800 } else { |
| 1801 Label fast; | 1801 Label fast; |
| 1802 // Check that the object is a smi or a heap number. | 1802 // Check that the object is a smi or a heap number. |
| 1803 __ test(edx, Immediate(kSmiTagMask)); | 1803 __ test(edx, Immediate(kSmiTagMask)); |
| 1804 __ j(zero, &fast, taken); | 1804 __ j(zero, &fast, taken); |
| 1805 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax); | 1805 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax); |
| 1806 __ j(not_equal, &miss, not_taken); | 1806 __ j(not_equal, &miss, not_taken); |
| 1807 __ bind(&fast); | 1807 __ bind(&fast); |
| 1808 // Check that the maps starting from the prototype haven't changed. | 1808 // Check that the maps starting from the prototype haven't changed. |
| 1809 GenerateDirectLoadGlobalFunctionPrototype( | 1809 GenerateDirectLoadGlobalFunctionPrototype( |
| 1810 masm(), Context::NUMBER_FUNCTION_INDEX, eax); | 1810 masm(), Context::NUMBER_FUNCTION_INDEX, eax); |
| 1811 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 1811 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
| 1812 ebx, edx, name, &miss, edi); | 1812 ebx, edx, edi, name, &miss); |
| 1813 } | 1813 } |
| 1814 break; | 1814 break; |
| 1815 } | 1815 } |
| 1816 | 1816 |
| 1817 case BOOLEAN_CHECK: { | 1817 case BOOLEAN_CHECK: { |
| 1818 if (!function->IsBuiltin()) { | 1818 if (!function->IsBuiltin()) { |
| 1819 // Calling non-builtins with a value as receiver requires boxing. | 1819 // Calling non-builtins with a value as receiver requires boxing. |
| 1820 __ jmp(&miss); | 1820 __ jmp(&miss); |
| 1821 } else { | 1821 } else { |
| 1822 Label fast; | 1822 Label fast; |
| 1823 // Check that the object is a boolean. | 1823 // Check that the object is a boolean. |
| 1824 __ cmp(edx, Factory::true_value()); | 1824 __ cmp(edx, Factory::true_value()); |
| 1825 __ j(equal, &fast, taken); | 1825 __ j(equal, &fast, taken); |
| 1826 __ cmp(edx, Factory::false_value()); | 1826 __ cmp(edx, Factory::false_value()); |
| 1827 __ j(not_equal, &miss, not_taken); | 1827 __ j(not_equal, &miss, not_taken); |
| 1828 __ bind(&fast); | 1828 __ bind(&fast); |
| 1829 // Check that the maps starting from the prototype haven't changed. | 1829 // Check that the maps starting from the prototype haven't changed. |
| 1830 GenerateDirectLoadGlobalFunctionPrototype( | 1830 GenerateDirectLoadGlobalFunctionPrototype( |
| 1831 masm(), Context::BOOLEAN_FUNCTION_INDEX, eax); | 1831 masm(), Context::BOOLEAN_FUNCTION_INDEX, eax); |
| 1832 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 1832 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
| 1833 ebx, edx, name, &miss, edi); | 1833 ebx, edx, edi, name, &miss); |
| 1834 } | 1834 } |
| 1835 break; | 1835 break; |
| 1836 } | 1836 } |
| 1837 | 1837 |
| 1838 default: | 1838 default: |
| 1839 UNREACHABLE(); | 1839 UNREACHABLE(); |
| 1840 } | 1840 } |
| 1841 | 1841 |
| 1842 if (depth != kInvalidProtoDepth) { | 1842 if (depth != kInvalidProtoDepth) { |
| 1843 GenerateFastApiCall(masm(), optimization, argc); | 1843 GenerateFastApiCall(masm(), optimization, argc); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1883 | 1883 |
| 1884 CallInterceptorCompiler compiler(this, arguments(), ecx); | 1884 CallInterceptorCompiler compiler(this, arguments(), ecx); |
| 1885 compiler.Compile(masm(), | 1885 compiler.Compile(masm(), |
| 1886 object, | 1886 object, |
| 1887 holder, | 1887 holder, |
| 1888 name, | 1888 name, |
| 1889 &lookup, | 1889 &lookup, |
| 1890 edx, | 1890 edx, |
| 1891 ebx, | 1891 ebx, |
| 1892 edi, | 1892 edi, |
| 1893 eax, |
| 1893 &miss); | 1894 &miss); |
| 1894 | 1895 |
| 1895 // Restore receiver. | 1896 // Restore receiver. |
| 1896 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1897 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 1897 | 1898 |
| 1898 // Check that the function really is a function. | 1899 // Check that the function really is a function. |
| 1899 __ test(eax, Immediate(kSmiTagMask)); | 1900 __ test(eax, Immediate(kSmiTagMask)); |
| 1900 __ j(zero, &miss, not_taken); | 1901 __ j(zero, &miss, not_taken); |
| 1901 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); | 1902 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); |
| 1902 __ j(not_equal, &miss, not_taken); | 1903 __ j(not_equal, &miss, not_taken); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1945 | 1946 |
| 1946 // If the object is the holder then we know that it's a global | 1947 // If the object is the holder then we know that it's a global |
| 1947 // object which can only happen for contextual calls. In this case, | 1948 // object which can only happen for contextual calls. In this case, |
| 1948 // the receiver cannot be a smi. | 1949 // the receiver cannot be a smi. |
| 1949 if (object != holder) { | 1950 if (object != holder) { |
| 1950 __ test(edx, Immediate(kSmiTagMask)); | 1951 __ test(edx, Immediate(kSmiTagMask)); |
| 1951 __ j(zero, &miss, not_taken); | 1952 __ j(zero, &miss, not_taken); |
| 1952 } | 1953 } |
| 1953 | 1954 |
| 1954 // Check that the maps haven't changed. | 1955 // Check that the maps haven't changed. |
| 1955 CheckPrototypes(object, edx, holder, ebx, eax, name, &miss, edi); | 1956 CheckPrototypes(object, edx, holder, ebx, eax, edi, name, &miss); |
| 1956 | 1957 |
| 1957 // Get the value from the cell. | 1958 // Get the value from the cell. |
| 1958 __ mov(edi, Immediate(Handle<JSGlobalPropertyCell>(cell))); | 1959 __ mov(edi, Immediate(Handle<JSGlobalPropertyCell>(cell))); |
| 1959 __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset)); | 1960 __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset)); |
| 1960 | 1961 |
| 1961 // Check that the cell contains the same function. | 1962 // Check that the cell contains the same function. |
| 1962 if (Heap::InNewSpace(function)) { | 1963 if (Heap::InNewSpace(function)) { |
| 1963 // We can't embed a pointer to a function in new space so we have | 1964 // We can't embed a pointer to a function in new space so we have |
| 1964 // to verify that the shared function info is unchanged. This has | 1965 // to verify that the shared function info is unchanged. This has |
| 1965 // the nice side effect that multiple closures based on the same | 1966 // the nice side effect that multiple closures based on the same |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2221 | 2222 |
| 2222 // Check that the receiver isn't a smi. | 2223 // Check that the receiver isn't a smi. |
| 2223 __ test(eax, Immediate(kSmiTagMask)); | 2224 __ test(eax, Immediate(kSmiTagMask)); |
| 2224 __ j(zero, &miss, not_taken); | 2225 __ j(zero, &miss, not_taken); |
| 2225 | 2226 |
| 2226 ASSERT(last->IsGlobalObject() || last->HasFastProperties()); | 2227 ASSERT(last->IsGlobalObject() || last->HasFastProperties()); |
| 2227 | 2228 |
| 2228 // Check the maps of the full prototype chain. Also check that | 2229 // Check the maps of the full prototype chain. Also check that |
| 2229 // global property cells up to (but not including) the last object | 2230 // global property cells up to (but not including) the last object |
| 2230 // in the prototype chain are empty. | 2231 // in the prototype chain are empty. |
| 2231 CheckPrototypes(object, eax, last, ebx, edx, name, &miss); | 2232 CheckPrototypes(object, eax, last, ebx, edx, edi, name, &miss); |
| 2232 | 2233 |
| 2233 // If the last object in the prototype chain is a global object, | 2234 // If the last object in the prototype chain is a global object, |
| 2234 // check that the global property cell is empty. | 2235 // check that the global property cell is empty. |
| 2235 if (last->IsGlobalObject()) { | 2236 if (last->IsGlobalObject()) { |
| 2236 Object* cell = GenerateCheckPropertyCell(masm(), | 2237 Object* cell = GenerateCheckPropertyCell(masm(), |
| 2237 GlobalObject::cast(last), | 2238 GlobalObject::cast(last), |
| 2238 name, | 2239 name, |
| 2239 edx, | 2240 edx, |
| 2240 &miss); | 2241 &miss); |
| 2241 if (cell->IsFailure()) return cell; | 2242 if (cell->IsFailure()) return cell; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2258 JSObject* holder, | 2259 JSObject* holder, |
| 2259 int index, | 2260 int index, |
| 2260 String* name) { | 2261 String* name) { |
| 2261 // ----------- S t a t e ------------- | 2262 // ----------- S t a t e ------------- |
| 2262 // -- eax : receiver | 2263 // -- eax : receiver |
| 2263 // -- ecx : name | 2264 // -- ecx : name |
| 2264 // -- esp[0] : return address | 2265 // -- esp[0] : return address |
| 2265 // ----------------------------------- | 2266 // ----------------------------------- |
| 2266 Label miss; | 2267 Label miss; |
| 2267 | 2268 |
| 2268 GenerateLoadField(object, holder, eax, ebx, edx, index, name, &miss); | 2269 GenerateLoadField(object, holder, eax, ebx, edx, edi, index, name, &miss); |
| 2269 __ bind(&miss); | 2270 __ bind(&miss); |
| 2270 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2271 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 2271 | 2272 |
| 2272 // Return the generated code. | 2273 // Return the generated code. |
| 2273 return GetCode(FIELD, name); | 2274 return GetCode(FIELD, name); |
| 2274 } | 2275 } |
| 2275 | 2276 |
| 2276 | 2277 |
| 2277 Object* LoadStubCompiler::CompileLoadCallback(String* name, | 2278 Object* LoadStubCompiler::CompileLoadCallback(String* name, |
| 2278 JSObject* object, | 2279 JSObject* object, |
| 2279 JSObject* holder, | 2280 JSObject* holder, |
| 2280 AccessorInfo* callback) { | 2281 AccessorInfo* callback) { |
| 2281 // ----------- S t a t e ------------- | 2282 // ----------- S t a t e ------------- |
| 2282 // -- eax : receiver | 2283 // -- eax : receiver |
| 2283 // -- ecx : name | 2284 // -- ecx : name |
| 2284 // -- esp[0] : return address | 2285 // -- esp[0] : return address |
| 2285 // ----------------------------------- | 2286 // ----------------------------------- |
| 2286 Label miss; | 2287 Label miss; |
| 2287 | 2288 |
| 2288 Failure* failure = Failure::InternalError(); | 2289 Failure* failure = Failure::InternalError(); |
| 2289 bool success = GenerateLoadCallback(object, holder, eax, ecx, ebx, edx, | 2290 bool success = GenerateLoadCallback(object, holder, eax, ecx, ebx, edx, edi, |
| 2290 callback, name, &miss, &failure); | 2291 callback, name, &miss, &failure); |
| 2291 if (!success) return failure; | 2292 if (!success) return failure; |
| 2292 | 2293 |
| 2293 __ bind(&miss); | 2294 __ bind(&miss); |
| 2294 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2295 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 2295 | 2296 |
| 2296 // Return the generated code. | 2297 // Return the generated code. |
| 2297 return GetCode(CALLBACKS, name); | 2298 return GetCode(CALLBACKS, name); |
| 2298 } | 2299 } |
| 2299 | 2300 |
| 2300 | 2301 |
| 2301 Object* LoadStubCompiler::CompileLoadConstant(JSObject* object, | 2302 Object* LoadStubCompiler::CompileLoadConstant(JSObject* object, |
| 2302 JSObject* holder, | 2303 JSObject* holder, |
| 2303 Object* value, | 2304 Object* value, |
| 2304 String* name) { | 2305 String* name) { |
| 2305 // ----------- S t a t e ------------- | 2306 // ----------- S t a t e ------------- |
| 2306 // -- eax : receiver | 2307 // -- eax : receiver |
| 2307 // -- ecx : name | 2308 // -- ecx : name |
| 2308 // -- esp[0] : return address | 2309 // -- esp[0] : return address |
| 2309 // ----------------------------------- | 2310 // ----------------------------------- |
| 2310 Label miss; | 2311 Label miss; |
| 2311 | 2312 |
| 2312 GenerateLoadConstant(object, holder, eax, ebx, edx, value, name, &miss); | 2313 GenerateLoadConstant(object, holder, eax, ebx, edx, edi, value, name, &miss); |
| 2313 __ bind(&miss); | 2314 __ bind(&miss); |
| 2314 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2315 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 2315 | 2316 |
| 2316 // Return the generated code. | 2317 // Return the generated code. |
| 2317 return GetCode(CONSTANT_FUNCTION, name); | 2318 return GetCode(CONSTANT_FUNCTION, name); |
| 2318 } | 2319 } |
| 2319 | 2320 |
| 2320 | 2321 |
| 2321 Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, | 2322 Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, |
| 2322 JSObject* holder, | 2323 JSObject* holder, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2333 | 2334 |
| 2334 // TODO(368): Compile in the whole chain: all the interceptors in | 2335 // TODO(368): Compile in the whole chain: all the interceptors in |
| 2335 // prototypes and ultimate answer. | 2336 // prototypes and ultimate answer. |
| 2336 GenerateLoadInterceptor(receiver, | 2337 GenerateLoadInterceptor(receiver, |
| 2337 holder, | 2338 holder, |
| 2338 &lookup, | 2339 &lookup, |
| 2339 eax, | 2340 eax, |
| 2340 ecx, | 2341 ecx, |
| 2341 edx, | 2342 edx, |
| 2342 ebx, | 2343 ebx, |
| 2344 edi, |
| 2343 name, | 2345 name, |
| 2344 &miss); | 2346 &miss); |
| 2345 | 2347 |
| 2346 __ bind(&miss); | 2348 __ bind(&miss); |
| 2347 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2349 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 2348 | 2350 |
| 2349 // Return the generated code. | 2351 // Return the generated code. |
| 2350 return GetCode(INTERCEPTOR, name); | 2352 return GetCode(INTERCEPTOR, name); |
| 2351 } | 2353 } |
| 2352 | 2354 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2365 | 2367 |
| 2366 // If the object is the holder then we know that it's a global | 2368 // If the object is the holder then we know that it's a global |
| 2367 // object which can only happen for contextual loads. In this case, | 2369 // object which can only happen for contextual loads. In this case, |
| 2368 // the receiver cannot be a smi. | 2370 // the receiver cannot be a smi. |
| 2369 if (object != holder) { | 2371 if (object != holder) { |
| 2370 __ test(eax, Immediate(kSmiTagMask)); | 2372 __ test(eax, Immediate(kSmiTagMask)); |
| 2371 __ j(zero, &miss, not_taken); | 2373 __ j(zero, &miss, not_taken); |
| 2372 } | 2374 } |
| 2373 | 2375 |
| 2374 // Check that the maps haven't changed. | 2376 // Check that the maps haven't changed. |
| 2375 CheckPrototypes(object, eax, holder, ebx, edx, name, &miss, edi); | 2377 CheckPrototypes(object, eax, holder, ebx, edx, edi, name, &miss); |
| 2376 | 2378 |
| 2377 // Get the value from the cell. | 2379 // Get the value from the cell. |
| 2378 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); | 2380 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); |
| 2379 __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset)); | 2381 __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset)); |
| 2380 | 2382 |
| 2381 // Check for deleted property if property can actually be deleted. | 2383 // Check for deleted property if property can actually be deleted. |
| 2382 if (!is_dont_delete) { | 2384 if (!is_dont_delete) { |
| 2383 __ cmp(ebx, Factory::the_hole_value()); | 2385 __ cmp(ebx, Factory::the_hole_value()); |
| 2384 __ j(equal, &miss, not_taken); | 2386 __ j(equal, &miss, not_taken); |
| 2385 } else if (FLAG_debug_code) { | 2387 } else if (FLAG_debug_code) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 2410 // -- esp[0] : return address | 2412 // -- esp[0] : return address |
| 2411 // ----------------------------------- | 2413 // ----------------------------------- |
| 2412 Label miss; | 2414 Label miss; |
| 2413 | 2415 |
| 2414 __ IncrementCounter(&Counters::keyed_load_field, 1); | 2416 __ IncrementCounter(&Counters::keyed_load_field, 1); |
| 2415 | 2417 |
| 2416 // Check that the name has not changed. | 2418 // Check that the name has not changed. |
| 2417 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 2419 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
| 2418 __ j(not_equal, &miss, not_taken); | 2420 __ j(not_equal, &miss, not_taken); |
| 2419 | 2421 |
| 2420 GenerateLoadField(receiver, holder, edx, ebx, ecx, index, name, &miss); | 2422 GenerateLoadField(receiver, holder, edx, ebx, ecx, edi, index, name, &miss); |
| 2421 | 2423 |
| 2422 __ bind(&miss); | 2424 __ bind(&miss); |
| 2423 __ DecrementCounter(&Counters::keyed_load_field, 1); | 2425 __ DecrementCounter(&Counters::keyed_load_field, 1); |
| 2424 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2426 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 2425 | 2427 |
| 2426 // Return the generated code. | 2428 // Return the generated code. |
| 2427 return GetCode(FIELD, name); | 2429 return GetCode(FIELD, name); |
| 2428 } | 2430 } |
| 2429 | 2431 |
| 2430 | 2432 |
| 2431 Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name, | 2433 Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name, |
| 2432 JSObject* receiver, | 2434 JSObject* receiver, |
| 2433 JSObject* holder, | 2435 JSObject* holder, |
| 2434 AccessorInfo* callback) { | 2436 AccessorInfo* callback) { |
| 2435 // ----------- S t a t e ------------- | 2437 // ----------- S t a t e ------------- |
| 2436 // -- eax : key | 2438 // -- eax : key |
| 2437 // -- edx : receiver | 2439 // -- edx : receiver |
| 2438 // -- esp[0] : return address | 2440 // -- esp[0] : return address |
| 2439 // ----------------------------------- | 2441 // ----------------------------------- |
| 2440 Label miss; | 2442 Label miss; |
| 2441 | 2443 |
| 2442 __ IncrementCounter(&Counters::keyed_load_callback, 1); | 2444 __ IncrementCounter(&Counters::keyed_load_callback, 1); |
| 2443 | 2445 |
| 2444 // Check that the name has not changed. | 2446 // Check that the name has not changed. |
| 2445 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 2447 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
| 2446 __ j(not_equal, &miss, not_taken); | 2448 __ j(not_equal, &miss, not_taken); |
| 2447 | 2449 |
| 2448 Failure* failure = Failure::InternalError(); | 2450 Failure* failure = Failure::InternalError(); |
| 2449 bool success = GenerateLoadCallback(receiver, holder, edx, eax, ebx, ecx, | 2451 bool success = GenerateLoadCallback(receiver, holder, edx, eax, ebx, ecx, edi, |
| 2450 callback, name, &miss, &failure); | 2452 callback, name, &miss, &failure); |
| 2451 if (!success) return failure; | 2453 if (!success) return failure; |
| 2452 | 2454 |
| 2453 __ bind(&miss); | 2455 __ bind(&miss); |
| 2454 __ DecrementCounter(&Counters::keyed_load_callback, 1); | 2456 __ DecrementCounter(&Counters::keyed_load_callback, 1); |
| 2455 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2457 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 2456 | 2458 |
| 2457 // Return the generated code. | 2459 // Return the generated code. |
| 2458 return GetCode(CALLBACKS, name); | 2460 return GetCode(CALLBACKS, name); |
| 2459 } | 2461 } |
| 2460 | 2462 |
| 2461 | 2463 |
| 2462 Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name, | 2464 Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name, |
| 2463 JSObject* receiver, | 2465 JSObject* receiver, |
| 2464 JSObject* holder, | 2466 JSObject* holder, |
| 2465 Object* value) { | 2467 Object* value) { |
| 2466 // ----------- S t a t e ------------- | 2468 // ----------- S t a t e ------------- |
| 2467 // -- eax : key | 2469 // -- eax : key |
| 2468 // -- edx : receiver | 2470 // -- edx : receiver |
| 2469 // -- esp[0] : return address | 2471 // -- esp[0] : return address |
| 2470 // ----------------------------------- | 2472 // ----------------------------------- |
| 2471 Label miss; | 2473 Label miss; |
| 2472 | 2474 |
| 2473 __ IncrementCounter(&Counters::keyed_load_constant_function, 1); | 2475 __ IncrementCounter(&Counters::keyed_load_constant_function, 1); |
| 2474 | 2476 |
| 2475 // Check that the name has not changed. | 2477 // Check that the name has not changed. |
| 2476 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 2478 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
| 2477 __ j(not_equal, &miss, not_taken); | 2479 __ j(not_equal, &miss, not_taken); |
| 2478 | 2480 |
| 2479 GenerateLoadConstant(receiver, holder, edx, ebx, ecx, | 2481 GenerateLoadConstant(receiver, holder, edx, ebx, ecx, edi, |
| 2480 value, name, &miss); | 2482 value, name, &miss); |
| 2481 __ bind(&miss); | 2483 __ bind(&miss); |
| 2482 __ DecrementCounter(&Counters::keyed_load_constant_function, 1); | 2484 __ DecrementCounter(&Counters::keyed_load_constant_function, 1); |
| 2483 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2485 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 2484 | 2486 |
| 2485 // Return the generated code. | 2487 // Return the generated code. |
| 2486 return GetCode(CONSTANT_FUNCTION, name); | 2488 return GetCode(CONSTANT_FUNCTION, name); |
| 2487 } | 2489 } |
| 2488 | 2490 |
| 2489 | 2491 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2505 | 2507 |
| 2506 LookupResult lookup; | 2508 LookupResult lookup; |
| 2507 LookupPostInterceptor(holder, name, &lookup); | 2509 LookupPostInterceptor(holder, name, &lookup); |
| 2508 GenerateLoadInterceptor(receiver, | 2510 GenerateLoadInterceptor(receiver, |
| 2509 holder, | 2511 holder, |
| 2510 &lookup, | 2512 &lookup, |
| 2511 edx, | 2513 edx, |
| 2512 eax, | 2514 eax, |
| 2513 ecx, | 2515 ecx, |
| 2514 ebx, | 2516 ebx, |
| 2517 edi, |
| 2515 name, | 2518 name, |
| 2516 &miss); | 2519 &miss); |
| 2517 __ bind(&miss); | 2520 __ bind(&miss); |
| 2518 __ DecrementCounter(&Counters::keyed_load_interceptor, 1); | 2521 __ DecrementCounter(&Counters::keyed_load_interceptor, 1); |
| 2519 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2522 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 2520 | 2523 |
| 2521 // Return the generated code. | 2524 // Return the generated code. |
| 2522 return GetCode(INTERCEPTOR, name); | 2525 return GetCode(INTERCEPTOR, name); |
| 2523 } | 2526 } |
| 2524 | 2527 |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2732 // Return the generated code. | 2735 // Return the generated code. |
| 2733 return GetCode(); | 2736 return GetCode(); |
| 2734 } | 2737 } |
| 2735 | 2738 |
| 2736 | 2739 |
| 2737 #undef __ | 2740 #undef __ |
| 2738 | 2741 |
| 2739 } } // namespace v8::internal | 2742 } } // namespace v8::internal |
| 2740 | 2743 |
| 2741 #endif // V8_TARGET_ARCH_IA32 | 2744 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |