| 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 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 372 __ push(receiver); | 372 __ push(receiver); |
| 373 __ push(holder); | 373 __ push(holder); |
| 374 } | 374 } |
| 375 | 375 |
| 376 | 376 |
| 377 static void CompileCallLoadPropertyWithInterceptor( | 377 static void CompileCallLoadPropertyWithInterceptor( |
| 378 MacroAssembler* masm, | 378 MacroAssembler* masm, |
| 379 Register receiver, | 379 Register receiver, |
| 380 Register holder, | 380 Register holder, |
| 381 Register name, | 381 Register name, |
| 382 Handle<JSObject> holder_obj) { | 382 Handle<JSObject> holder_obj, |
| 383 IC::UtilityId id) { |
| 383 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | 384 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); |
| 384 | 385 __ CallExternalReference( |
| 385 ExternalReference ref = | 386 ExternalReference(IC_Utility(id), masm->isolate()), |
| 386 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly), | 387 StubCache::kInterceptorArgsLength); |
| 387 masm->isolate()); | |
| 388 __ Set(rax, StubCache::kInterceptorArgsLength); | |
| 389 __ LoadAddress(rbx, ref); | |
| 390 | |
| 391 CEntryStub stub(1); | |
| 392 __ CallStub(&stub); | |
| 393 } | 388 } |
| 394 | 389 |
| 395 | 390 |
| 396 // Number of pointers to be reserved on stack for fast API call. | 391 // Number of pointers to be reserved on stack for fast API call. |
| 397 static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength; | 392 static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength; |
| 398 | 393 |
| 399 | 394 |
| 400 // Reserves space for the extra arguments to API function in the | 395 // Reserves space for the extra arguments to API function in the |
| 401 // caller's frame. | 396 // caller's frame. |
| 402 // | 397 // |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 635 thunk_address, | 630 thunk_address, |
| 636 callback_arg, | 631 callback_arg, |
| 637 argc + kFastApiCallArguments + 1, | 632 argc + kFastApiCallArguments + 1, |
| 638 return_value_operand, | 633 return_value_operand, |
| 639 restore_context ? &context_restore_operand : NULL); | 634 restore_context ? &context_restore_operand : NULL); |
| 640 } | 635 } |
| 641 | 636 |
| 642 | 637 |
| 643 class CallInterceptorCompiler BASE_EMBEDDED { | 638 class CallInterceptorCompiler BASE_EMBEDDED { |
| 644 public: | 639 public: |
| 645 CallInterceptorCompiler(StubCompiler* stub_compiler, | 640 CallInterceptorCompiler(CallStubCompiler* stub_compiler, |
| 646 const ParameterCount& arguments, | 641 const ParameterCount& arguments, |
| 647 Register name, | 642 Register name) |
| 648 Code::ExtraICState extra_ic_state) | |
| 649 : stub_compiler_(stub_compiler), | 643 : stub_compiler_(stub_compiler), |
| 650 arguments_(arguments), | 644 arguments_(arguments), |
| 651 name_(name), | 645 name_(name) {} |
| 652 extra_ic_state_(extra_ic_state) {} | |
| 653 | 646 |
| 654 void Compile(MacroAssembler* masm, | 647 void Compile(MacroAssembler* masm, |
| 655 Handle<JSObject> object, | 648 Handle<JSObject> object, |
| 656 Handle<JSObject> holder, | 649 Handle<JSObject> holder, |
| 657 Handle<Name> name, | 650 Handle<Name> name, |
| 658 LookupResult* lookup, | 651 LookupResult* lookup, |
| 659 Register receiver, | 652 Register receiver, |
| 660 Register scratch1, | 653 Register scratch1, |
| 661 Register scratch2, | 654 Register scratch2, |
| 662 Register scratch3, | 655 Register scratch3, |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 713 if (can_do_fast_api_call) { | 706 if (can_do_fast_api_call) { |
| 714 __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1); | 707 __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1); |
| 715 ReserveSpaceForFastApiCall(masm, scratch1); | 708 ReserveSpaceForFastApiCall(masm, scratch1); |
| 716 } | 709 } |
| 717 | 710 |
| 718 // Check that the maps from receiver to interceptor's holder | 711 // Check that the maps from receiver to interceptor's holder |
| 719 // haven't changed and thus we can invoke interceptor. | 712 // haven't changed and thus we can invoke interceptor. |
| 720 Label miss_cleanup; | 713 Label miss_cleanup; |
| 721 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; | 714 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; |
| 722 Register holder = | 715 Register holder = |
| 723 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, | 716 stub_compiler_->CheckPrototypes( |
| 724 scratch1, scratch2, scratch3, | 717 IC::CurrentTypeOf(object, masm->isolate()), receiver, |
| 725 name, depth1, miss); | 718 interceptor_holder, scratch1, scratch2, scratch3, |
| 719 name, depth1, miss); |
| 726 | 720 |
| 727 // Invoke an interceptor and if it provides a value, | 721 // Invoke an interceptor and if it provides a value, |
| 728 // branch to |regular_invoke|. | 722 // branch to |regular_invoke|. |
| 729 Label regular_invoke; | 723 Label regular_invoke; |
| 730 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, | 724 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, |
| 731 ®ular_invoke); | 725 ®ular_invoke); |
| 732 | 726 |
| 733 // Interceptor returned nothing for this property. Try to use cached | 727 // Interceptor returned nothing for this property. Try to use cached |
| 734 // constant function. | 728 // constant function. |
| 735 | 729 |
| 736 // Check that the maps from interceptor's holder to constant function's | 730 // Check that the maps from interceptor's holder to constant function's |
| 737 // holder haven't changed and thus we can use cached constant function. | 731 // holder haven't changed and thus we can use cached constant function. |
| 738 if (*interceptor_holder != lookup->holder()) { | 732 if (*interceptor_holder != lookup->holder()) { |
| 739 stub_compiler_->CheckPrototypes(interceptor_holder, receiver, | 733 stub_compiler_->CheckPrototypes( |
| 740 Handle<JSObject>(lookup->holder()), | 734 IC::CurrentTypeOf(interceptor_holder, masm->isolate()), holder, |
| 741 scratch1, scratch2, scratch3, | 735 handle(lookup->holder()), scratch1, scratch2, scratch3, |
| 742 name, depth2, miss); | 736 name, depth2, miss); |
| 743 } else { | 737 } else { |
| 744 // CheckPrototypes has a side effect of fetching a 'holder' | 738 // CheckPrototypes has a side effect of fetching a 'holder' |
| 745 // for API (object which is instanceof for the signature). It's | 739 // for API (object which is instanceof for the signature). It's |
| 746 // safe to omit it here, as if present, it should be fetched | 740 // safe to omit it here, as if present, it should be fetched |
| 747 // by the previous CheckPrototypes. | 741 // by the previous CheckPrototypes. |
| 748 ASSERT(depth2 == kInvalidProtoDepth); | 742 ASSERT(depth2 == kInvalidProtoDepth); |
| 749 } | 743 } |
| 750 | 744 |
| 751 // Invoke function. | 745 // Invoke function. |
| 752 if (can_do_fast_api_call) { | 746 if (can_do_fast_api_call) { |
| 753 GenerateFastApiCall(masm, optimization, arguments_.immediate()); | 747 GenerateFastApiCall(masm, optimization, arguments_.immediate()); |
| 754 } else { | 748 } else { |
| 755 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | |
| 756 ? CALL_AS_FUNCTION | |
| 757 : CALL_AS_METHOD; | |
| 758 Handle<JSFunction> fun = optimization.constant_function(); | 749 Handle<JSFunction> fun = optimization.constant_function(); |
| 759 ParameterCount expected(fun); | 750 stub_compiler_->GenerateJumpFunction(object, fun); |
| 760 __ InvokeFunction(fun, expected, arguments_, | |
| 761 JUMP_FUNCTION, NullCallWrapper(), call_kind); | |
| 762 } | 751 } |
| 763 | 752 |
| 764 // Deferred code for fast API call case---clean preallocated space. | 753 // Deferred code for fast API call case---clean preallocated space. |
| 765 if (can_do_fast_api_call) { | 754 if (can_do_fast_api_call) { |
| 766 __ bind(&miss_cleanup); | 755 __ bind(&miss_cleanup); |
| 767 FreeSpaceForFastApiCall(masm, scratch1); | 756 FreeSpaceForFastApiCall(masm, scratch1); |
| 768 __ jmp(miss_label); | 757 __ jmp(miss_label); |
| 769 } | 758 } |
| 770 | 759 |
| 771 // Invoke a regular function. | 760 // Invoke a regular function. |
| 772 __ bind(®ular_invoke); | 761 __ bind(®ular_invoke); |
| 773 if (can_do_fast_api_call) { | 762 if (can_do_fast_api_call) { |
| 774 FreeSpaceForFastApiCall(masm, scratch1); | 763 FreeSpaceForFastApiCall(masm, scratch1); |
| 775 } | 764 } |
| 776 } | 765 } |
| 777 | 766 |
| 778 void CompileRegular(MacroAssembler* masm, | 767 void CompileRegular(MacroAssembler* masm, |
| 779 Handle<JSObject> object, | 768 Handle<JSObject> object, |
| 780 Register receiver, | 769 Register receiver, |
| 781 Register scratch1, | 770 Register scratch1, |
| 782 Register scratch2, | 771 Register scratch2, |
| 783 Register scratch3, | 772 Register scratch3, |
| 784 Handle<Name> name, | 773 Handle<Name> name, |
| 785 Handle<JSObject> interceptor_holder, | 774 Handle<JSObject> interceptor_holder, |
| 786 Label* miss_label) { | 775 Label* miss_label) { |
| 787 Register holder = | 776 Register holder = |
| 788 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, | 777 stub_compiler_->CheckPrototypes( |
| 789 scratch1, scratch2, scratch3, | 778 IC::CurrentTypeOf(object, masm->isolate()), receiver, |
| 790 name, miss_label); | 779 interceptor_holder, scratch1, scratch2, scratch3, name, miss_label); |
| 791 | 780 |
| 792 FrameScope scope(masm, StackFrame::INTERNAL); | 781 FrameScope scope(masm, StackFrame::INTERNAL); |
| 793 // Save the name_ register across the call. | 782 // Save the name_ register across the call. |
| 794 __ push(name_); | 783 __ push(name_); |
| 795 | 784 |
| 796 PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder); | 785 CompileCallLoadPropertyWithInterceptor( |
| 797 | 786 masm, receiver, holder, name_, interceptor_holder, |
| 798 __ CallExternalReference( | 787 IC::kLoadPropertyWithInterceptorForCall); |
| 799 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall), | |
| 800 masm->isolate()), | |
| 801 StubCache::kInterceptorArgsLength); | |
| 802 | 788 |
| 803 // Restore the name_ register. | 789 // Restore the name_ register. |
| 804 __ pop(name_); | 790 __ pop(name_); |
| 805 | 791 |
| 806 // Leave the internal frame. | 792 // Leave the internal frame. |
| 807 } | 793 } |
| 808 | 794 |
| 809 void LoadWithInterceptor(MacroAssembler* masm, | 795 void LoadWithInterceptor(MacroAssembler* masm, |
| 810 Register receiver, | 796 Register receiver, |
| 811 Register holder, | 797 Register holder, |
| 812 Handle<JSObject> holder_obj, | 798 Handle<JSObject> holder_obj, |
| 813 Label* interceptor_succeeded) { | 799 Label* interceptor_succeeded) { |
| 814 { | 800 { |
| 815 FrameScope scope(masm, StackFrame::INTERNAL); | 801 FrameScope scope(masm, StackFrame::INTERNAL); |
| 816 __ push(holder); // Save the holder. | 802 __ push(receiver); |
| 817 __ push(name_); // Save the name. | 803 __ push(holder); |
| 804 __ push(name_); |
| 818 | 805 |
| 819 CompileCallLoadPropertyWithInterceptor(masm, | 806 CompileCallLoadPropertyWithInterceptor( |
| 820 receiver, | 807 masm, receiver, holder, name_, holder_obj, |
| 821 holder, | 808 IC::kLoadPropertyWithInterceptorOnly); |
| 822 name_, | |
| 823 holder_obj); | |
| 824 | 809 |
| 825 __ pop(name_); // Restore the name. | 810 __ pop(name_); |
| 826 __ pop(receiver); // Restore the holder. | 811 __ pop(holder); |
| 812 __ pop(receiver); |
| 827 // Leave the internal frame. | 813 // Leave the internal frame. |
| 828 } | 814 } |
| 829 | 815 |
| 830 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex); | 816 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex); |
| 831 __ j(not_equal, interceptor_succeeded); | 817 __ j(not_equal, interceptor_succeeded); |
| 832 } | 818 } |
| 833 | 819 |
| 834 StubCompiler* stub_compiler_; | 820 CallStubCompiler* stub_compiler_; |
| 835 const ParameterCount& arguments_; | 821 const ParameterCount& arguments_; |
| 836 Register name_; | 822 Register name_; |
| 837 Code::ExtraICState extra_ic_state_; | |
| 838 }; | 823 }; |
| 839 | 824 |
| 840 | 825 |
| 841 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, | 826 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, |
| 842 Label* label, | 827 Label* label, |
| 843 Handle<Name> name) { | 828 Handle<Name> name) { |
| 844 if (!label->is_unused()) { | 829 if (!label->is_unused()) { |
| 845 __ bind(label); | 830 __ bind(label); |
| 846 __ Move(this->name(), name); | 831 __ Move(this->name(), name); |
| 847 } | 832 } |
| (...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1115 EMIT_REMEMBERED_SET, smi_check); | 1100 EMIT_REMEMBERED_SET, smi_check); |
| 1116 } | 1101 } |
| 1117 } | 1102 } |
| 1118 | 1103 |
| 1119 // Return the value (register rax). | 1104 // Return the value (register rax). |
| 1120 ASSERT(value_reg.is(rax)); | 1105 ASSERT(value_reg.is(rax)); |
| 1121 __ ret(0); | 1106 __ ret(0); |
| 1122 } | 1107 } |
| 1123 | 1108 |
| 1124 | 1109 |
| 1125 void StubCompiler::GenerateCheckPropertyCells(MacroAssembler* masm, | |
| 1126 Handle<JSObject> object, | |
| 1127 Handle<JSObject> holder, | |
| 1128 Handle<Name> name, | |
| 1129 Register scratch, | |
| 1130 Label* miss) { | |
| 1131 Handle<JSObject> current = object; | |
| 1132 while (!current.is_identical_to(holder)) { | |
| 1133 if (current->IsJSGlobalObject()) { | |
| 1134 GenerateCheckPropertyCell(masm, | |
| 1135 Handle<JSGlobalObject>::cast(current), | |
| 1136 name, | |
| 1137 scratch, | |
| 1138 miss); | |
| 1139 } | |
| 1140 current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); | |
| 1141 } | |
| 1142 } | |
| 1143 | |
| 1144 | |
| 1145 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { | 1110 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { |
| 1146 __ jmp(code, RelocInfo::CODE_TARGET); | 1111 __ jmp(code, RelocInfo::CODE_TARGET); |
| 1147 } | 1112 } |
| 1148 | 1113 |
| 1149 | 1114 |
| 1150 #undef __ | 1115 #undef __ |
| 1151 #define __ ACCESS_MASM((masm())) | 1116 #define __ ACCESS_MASM((masm())) |
| 1152 | 1117 |
| 1153 | 1118 |
| 1154 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, | 1119 Register StubCompiler::CheckPrototypes(Handle<Type> type, |
| 1155 Register object_reg, | 1120 Register object_reg, |
| 1156 Handle<JSObject> holder, | 1121 Handle<JSObject> holder, |
| 1157 Register holder_reg, | 1122 Register holder_reg, |
| 1158 Register scratch1, | 1123 Register scratch1, |
| 1159 Register scratch2, | 1124 Register scratch2, |
| 1160 Handle<Name> name, | 1125 Handle<Name> name, |
| 1161 int save_at_depth, | 1126 int save_at_depth, |
| 1162 Label* miss, | 1127 Label* miss, |
| 1163 PrototypeCheckType check) { | 1128 PrototypeCheckType check) { |
| 1129 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); |
| 1164 // Make sure that the type feedback oracle harvests the receiver map. | 1130 // Make sure that the type feedback oracle harvests the receiver map. |
| 1165 // TODO(svenpanne) Remove this hack when all ICs are reworked. | 1131 // TODO(svenpanne) Remove this hack when all ICs are reworked. |
| 1166 __ Move(scratch1, Handle<Map>(object->map())); | 1132 __ Move(scratch1, receiver_map); |
| 1167 | 1133 |
| 1168 Handle<JSObject> first = object; | |
| 1169 // Make sure there's no overlap between holder and object registers. | 1134 // Make sure there's no overlap between holder and object registers. |
| 1170 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 1135 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
| 1171 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 1136 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
| 1172 && !scratch2.is(scratch1)); | 1137 && !scratch2.is(scratch1)); |
| 1173 | 1138 |
| 1174 // Keep track of the current object in register reg. On the first | 1139 // Keep track of the current object in register reg. On the first |
| 1175 // iteration, reg is an alias for object_reg, on later iterations, | 1140 // iteration, reg is an alias for object_reg, on later iterations, |
| 1176 // it is an alias for holder_reg. | 1141 // it is an alias for holder_reg. |
| 1177 Register reg = object_reg; | 1142 Register reg = object_reg; |
| 1178 int depth = 0; | 1143 int depth = 0; |
| 1179 | 1144 |
| 1180 StackArgumentsAccessor args(rsp, kFastApiCallArguments, | 1145 StackArgumentsAccessor args(rsp, kFastApiCallArguments, |
| 1181 ARGUMENTS_DONT_CONTAIN_RECEIVER); | 1146 ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| 1182 const int kHolderIndex = kFastApiCallArguments - 1 - | 1147 const int kHolderIndex = kFastApiCallArguments - 1 - |
| 1183 FunctionCallbackArguments::kHolderIndex; | 1148 FunctionCallbackArguments::kHolderIndex; |
| 1184 | 1149 |
| 1185 if (save_at_depth == depth) { | 1150 if (save_at_depth == depth) { |
| 1186 __ movq(args.GetArgumentOperand(kHolderIndex), object_reg); | 1151 __ movq(args.GetArgumentOperand(kHolderIndex), object_reg); |
| 1187 } | 1152 } |
| 1188 | 1153 |
| 1189 // Check the maps in the prototype chain. | 1154 Handle<JSObject> current = Handle<JSObject>::null(); |
| 1190 // Traverse the prototype chain from the object and do map checks. | 1155 if (type->IsConstant()) current = Handle<JSObject>::cast(type->AsConstant()); |
| 1191 Handle<JSObject> current = object; | 1156 Handle<JSObject> prototype = Handle<JSObject>::null(); |
| 1192 while (!current.is_identical_to(holder)) { | 1157 Handle<Map> current_map = receiver_map; |
| 1158 Handle<Map> holder_map(holder->map()); |
| 1159 // Traverse the prototype chain and check the maps in the prototype chain for |
| 1160 // fast and global objects or do negative lookup for normal objects. |
| 1161 while (!current_map.is_identical_to(holder_map)) { |
| 1193 ++depth; | 1162 ++depth; |
| 1194 | 1163 |
| 1195 // Only global objects and objects that do not require access | 1164 // Only global objects and objects that do not require access |
| 1196 // checks are allowed in stubs. | 1165 // checks are allowed in stubs. |
| 1197 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); | 1166 ASSERT(current_map->IsJSGlobalProxyMap() || |
| 1167 !current_map->is_access_check_needed()); |
| 1198 | 1168 |
| 1199 Handle<JSObject> prototype(JSObject::cast(current->GetPrototype())); | 1169 prototype = handle(JSObject::cast(current_map->prototype())); |
| 1200 if (!current->HasFastProperties() && | 1170 if (current_map->is_dictionary_map() && |
| 1201 !current->IsJSGlobalObject() && | 1171 !current_map->IsJSGlobalObjectMap() && |
| 1202 !current->IsJSGlobalProxy()) { | 1172 !current_map->IsJSGlobalProxyMap()) { |
| 1203 if (!name->IsUniqueName()) { | 1173 if (!name->IsUniqueName()) { |
| 1204 ASSERT(name->IsString()); | 1174 ASSERT(name->IsString()); |
| 1205 name = factory()->InternalizeString(Handle<String>::cast(name)); | 1175 name = factory()->InternalizeString(Handle<String>::cast(name)); |
| 1206 } | 1176 } |
| 1207 ASSERT(current->property_dictionary()->FindEntry(*name) == | 1177 ASSERT(current.is_null() || |
| 1178 current->property_dictionary()->FindEntry(*name) == |
| 1208 NameDictionary::kNotFound); | 1179 NameDictionary::kNotFound); |
| 1209 | 1180 |
| 1210 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, | 1181 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, |
| 1211 scratch1, scratch2); | 1182 scratch1, scratch2); |
| 1212 | 1183 |
| 1213 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 1184 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 1214 reg = holder_reg; // From now on the object will be in holder_reg. | 1185 reg = holder_reg; // From now on the object will be in holder_reg. |
| 1215 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 1186 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
| 1216 } else { | 1187 } else { |
| 1217 bool in_new_space = heap()->InNewSpace(*prototype); | 1188 bool in_new_space = heap()->InNewSpace(*prototype); |
| 1218 Handle<Map> current_map(current->map()); | |
| 1219 if (in_new_space) { | 1189 if (in_new_space) { |
| 1220 // Save the map in scratch1 for later. | 1190 // Save the map in scratch1 for later. |
| 1221 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 1191 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 1222 } | 1192 } |
| 1223 if (!current.is_identical_to(first) || check == CHECK_ALL_MAPS) { | 1193 if (depth != 1 || check == CHECK_ALL_MAPS) { |
| 1224 __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK); | 1194 __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK); |
| 1225 } | 1195 } |
| 1226 | 1196 |
| 1227 // Check access rights to the global object. This has to happen after | 1197 // Check access rights to the global object. This has to happen after |
| 1228 // the map check so that we know that the object is actually a global | 1198 // the map check so that we know that the object is actually a global |
| 1229 // object. | 1199 // object. |
| 1230 if (current->IsJSGlobalProxy()) { | 1200 if (current_map->IsJSGlobalProxyMap()) { |
| 1231 __ CheckAccessGlobalProxy(reg, scratch2, miss); | 1201 __ CheckAccessGlobalProxy(reg, scratch2, miss); |
| 1202 } else if (current_map->IsJSGlobalObjectMap()) { |
| 1203 GenerateCheckPropertyCell( |
| 1204 masm(), Handle<JSGlobalObject>::cast(current), name, |
| 1205 scratch2, miss); |
| 1232 } | 1206 } |
| 1233 reg = holder_reg; // From now on the object will be in holder_reg. | 1207 reg = holder_reg; // From now on the object will be in holder_reg. |
| 1234 | 1208 |
| 1235 if (in_new_space) { | 1209 if (in_new_space) { |
| 1236 // The prototype is in new space; we cannot store a reference to it | 1210 // The prototype is in new space; we cannot store a reference to it |
| 1237 // in the code. Load it from the map. | 1211 // in the code. Load it from the map. |
| 1238 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 1212 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
| 1239 } else { | 1213 } else { |
| 1240 // The prototype is in old space; load it directly. | 1214 // The prototype is in old space; load it directly. |
| 1241 __ Move(reg, prototype); | 1215 __ Move(reg, prototype); |
| 1242 } | 1216 } |
| 1243 } | 1217 } |
| 1244 | 1218 |
| 1245 if (save_at_depth == depth) { | 1219 if (save_at_depth == depth) { |
| 1246 __ movq(args.GetArgumentOperand(kHolderIndex), reg); | 1220 __ movq(args.GetArgumentOperand(kHolderIndex), reg); |
| 1247 } | 1221 } |
| 1248 | 1222 |
| 1249 // Go to the next object in the prototype chain. | 1223 // Go to the next object in the prototype chain. |
| 1250 current = prototype; | 1224 current = prototype; |
| 1225 current_map = handle(current->map()); |
| 1251 } | 1226 } |
| 1252 ASSERT(current.is_identical_to(holder)); | |
| 1253 | 1227 |
| 1254 // Log the check depth. | 1228 // Log the check depth. |
| 1255 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 1229 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
| 1256 | 1230 |
| 1257 if (!holder.is_identical_to(first) || check == CHECK_ALL_MAPS) { | 1231 if (depth != 0 || check == CHECK_ALL_MAPS) { |
| 1258 // Check the holder map. | 1232 // Check the holder map. |
| 1259 __ CheckMap(reg, Handle<Map>(holder->map()), miss, DONT_DO_SMI_CHECK); | 1233 __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK); |
| 1260 } | 1234 } |
| 1261 | 1235 |
| 1262 // Perform security check for access to the global object. | 1236 // Perform security check for access to the global object. |
| 1263 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); | 1237 ASSERT(current_map->IsJSGlobalProxyMap() || |
| 1264 if (current->IsJSGlobalProxy()) { | 1238 !current_map->is_access_check_needed()); |
| 1239 if (current_map->IsJSGlobalProxyMap()) { |
| 1265 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 1240 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
| 1266 } | 1241 } |
| 1267 | 1242 |
| 1268 // If we've skipped any global objects, it's not enough to verify that | |
| 1269 // their maps haven't changed. We also need to check that the property | |
| 1270 // cell for the property is still empty. | |
| 1271 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); | |
| 1272 | |
| 1273 // Return the register containing the holder. | 1243 // Return the register containing the holder. |
| 1274 return reg; | 1244 return reg; |
| 1275 } | 1245 } |
| 1276 | 1246 |
| 1277 | 1247 |
| 1278 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { | 1248 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { |
| 1279 if (!miss->is_unused()) { | 1249 if (!miss->is_unused()) { |
| 1280 Label success; | 1250 Label success; |
| 1281 __ jmp(&success); | 1251 __ jmp(&success); |
| 1282 __ bind(miss); | 1252 __ bind(miss); |
| 1283 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1253 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1284 __ bind(&success); | 1254 __ bind(&success); |
| 1285 } | 1255 } |
| 1286 } | 1256 } |
| 1287 | 1257 |
| 1288 | 1258 |
| 1289 void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { | 1259 void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { |
| 1290 if (!miss->is_unused()) { | 1260 if (!miss->is_unused()) { |
| 1291 Label success; | 1261 Label success; |
| 1292 __ jmp(&success); | 1262 __ jmp(&success); |
| 1293 GenerateRestoreName(masm(), miss, name); | 1263 GenerateRestoreName(masm(), miss, name); |
| 1294 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1264 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1295 __ bind(&success); | 1265 __ bind(&success); |
| 1296 } | 1266 } |
| 1297 } | 1267 } |
| 1298 | 1268 |
| 1299 | 1269 |
| 1300 Register LoadStubCompiler::CallbackHandlerFrontend( | 1270 Register LoadStubCompiler::CallbackHandlerFrontend( |
| 1301 Handle<Object> object, | 1271 Handle<Type> type, |
| 1302 Register object_reg, | 1272 Register object_reg, |
| 1303 Handle<JSObject> holder, | 1273 Handle<JSObject> holder, |
| 1304 Handle<Name> name, | 1274 Handle<Name> name, |
| 1305 Handle<Object> callback) { | 1275 Handle<Object> callback) { |
| 1306 Label miss; | 1276 Label miss; |
| 1307 | 1277 |
| 1308 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); | 1278 Register reg = HandlerFrontendHeader(type, object_reg, holder, name, &miss); |
| 1309 | 1279 |
| 1310 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { | 1280 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { |
| 1311 ASSERT(!reg.is(scratch2())); | 1281 ASSERT(!reg.is(scratch2())); |
| 1312 ASSERT(!reg.is(scratch3())); | 1282 ASSERT(!reg.is(scratch3())); |
| 1313 ASSERT(!reg.is(scratch4())); | 1283 ASSERT(!reg.is(scratch4())); |
| 1314 | 1284 |
| 1315 // Load the properties dictionary. | 1285 // Load the properties dictionary. |
| 1316 Register dictionary = scratch4(); | 1286 Register dictionary = scratch4(); |
| 1317 __ movq(dictionary, FieldOperand(reg, JSObject::kPropertiesOffset)); | 1287 __ movq(dictionary, FieldOperand(reg, JSObject::kPropertiesOffset)); |
| 1318 | 1288 |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1508 | 1478 |
| 1509 if (must_preserve_receiver_reg) { | 1479 if (must_preserve_receiver_reg) { |
| 1510 __ push(receiver()); | 1480 __ push(receiver()); |
| 1511 } | 1481 } |
| 1512 __ push(holder_reg); | 1482 __ push(holder_reg); |
| 1513 __ push(this->name()); | 1483 __ push(this->name()); |
| 1514 | 1484 |
| 1515 // Invoke an interceptor. Note: map checks from receiver to | 1485 // Invoke an interceptor. Note: map checks from receiver to |
| 1516 // interceptor's holder has been compiled before (see a caller | 1486 // interceptor's holder has been compiled before (see a caller |
| 1517 // of this method.) | 1487 // of this method.) |
| 1518 CompileCallLoadPropertyWithInterceptor(masm(), | 1488 CompileCallLoadPropertyWithInterceptor( |
| 1519 receiver(), | 1489 masm(), receiver(), holder_reg, this->name(), interceptor_holder, |
| 1520 holder_reg, | 1490 IC::kLoadPropertyWithInterceptorOnly); |
| 1521 this->name(), | |
| 1522 interceptor_holder); | |
| 1523 | 1491 |
| 1524 // Check if interceptor provided a value for property. If it's | 1492 // Check if interceptor provided a value for property. If it's |
| 1525 // the case, return immediately. | 1493 // the case, return immediately. |
| 1526 Label interceptor_failed; | 1494 Label interceptor_failed; |
| 1527 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex); | 1495 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex); |
| 1528 __ j(equal, &interceptor_failed); | 1496 __ j(equal, &interceptor_failed); |
| 1529 frame_scope.GenerateLeaveFrame(); | 1497 frame_scope.GenerateLeaveFrame(); |
| 1530 __ ret(0); | 1498 __ ret(0); |
| 1531 | 1499 |
| 1532 __ bind(&interceptor_failed); | 1500 __ bind(&interceptor_failed); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1556 | 1524 |
| 1557 | 1525 |
| 1558 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { | 1526 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { |
| 1559 if (kind_ == Code::KEYED_CALL_IC) { | 1527 if (kind_ == Code::KEYED_CALL_IC) { |
| 1560 __ Cmp(rcx, name); | 1528 __ Cmp(rcx, name); |
| 1561 __ j(not_equal, miss); | 1529 __ j(not_equal, miss); |
| 1562 } | 1530 } |
| 1563 } | 1531 } |
| 1564 | 1532 |
| 1565 | 1533 |
| 1566 void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object, | 1534 void CallStubCompiler::GenerateFunctionCheck(Register function, |
| 1567 Handle<JSObject> holder, | 1535 Register scratch, |
| 1568 Handle<Name> name, | 1536 Label* miss) { |
| 1569 Label* miss) { | 1537 __ JumpIfSmi(function, miss); |
| 1570 ASSERT(holder->IsGlobalObject()); | 1538 __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch); |
| 1571 | 1539 __ j(not_equal, miss); |
| 1572 StackArgumentsAccessor args(rsp, arguments()); | |
| 1573 __ movq(rdx, args.GetReceiverOperand()); | |
| 1574 | |
| 1575 | |
| 1576 // Check that the maps haven't changed. | |
| 1577 __ JumpIfSmi(rdx, miss); | |
| 1578 CheckPrototypes(object, rdx, holder, rbx, rax, rdi, name, miss); | |
| 1579 } | 1540 } |
| 1580 | 1541 |
| 1581 | 1542 |
| 1582 void CallStubCompiler::GenerateLoadFunctionFromCell( | 1543 void CallStubCompiler::GenerateLoadFunctionFromCell( |
| 1583 Handle<Cell> cell, | 1544 Handle<Cell> cell, |
| 1584 Handle<JSFunction> function, | 1545 Handle<JSFunction> function, |
| 1585 Label* miss) { | 1546 Label* miss) { |
| 1586 // Get the value from the cell. | 1547 // Get the value from the cell. |
| 1587 __ Move(rdi, cell); | 1548 __ Move(rdi, cell); |
| 1588 __ movq(rdi, FieldOperand(rdi, Cell::kValueOffset)); | 1549 __ movq(rdi, FieldOperand(rdi, Cell::kValueOffset)); |
| 1589 | 1550 |
| 1590 // Check that the cell contains the same function. | 1551 // Check that the cell contains the same function. |
| 1591 if (heap()->InNewSpace(*function)) { | 1552 if (heap()->InNewSpace(*function)) { |
| 1592 // We can't embed a pointer to a function in new space so we have | 1553 // We can't embed a pointer to a function in new space so we have |
| 1593 // to verify that the shared function info is unchanged. This has | 1554 // to verify that the shared function info is unchanged. This has |
| 1594 // the nice side effect that multiple closures based on the same | 1555 // the nice side effect that multiple closures based on the same |
| 1595 // function can all use this call IC. Before we load through the | 1556 // function can all use this call IC. Before we load through the |
| 1596 // function, we have to verify that it still is a function. | 1557 // function, we have to verify that it still is a function. |
| 1597 __ JumpIfSmi(rdi, miss); | 1558 GenerateFunctionCheck(rdi, rax, miss); |
| 1598 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rax); | |
| 1599 __ j(not_equal, miss); | |
| 1600 | 1559 |
| 1601 // Check the shared function info. Make sure it hasn't changed. | 1560 // Check the shared function info. Make sure it hasn't changed. |
| 1602 __ Move(rax, Handle<SharedFunctionInfo>(function->shared())); | 1561 __ Move(rax, Handle<SharedFunctionInfo>(function->shared())); |
| 1603 __ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rax); | 1562 __ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rax); |
| 1604 } else { | 1563 } else { |
| 1605 __ Cmp(rdi, function); | 1564 __ Cmp(rdi, function); |
| 1606 } | 1565 } |
| 1607 __ j(not_equal, miss); | 1566 __ j(not_equal, miss); |
| 1608 } | 1567 } |
| 1609 | 1568 |
| 1610 | 1569 |
| 1611 void CallStubCompiler::GenerateMissBranch() { | 1570 void CallStubCompiler::GenerateMissBranch() { |
| 1612 Handle<Code> code = | 1571 Handle<Code> code = |
| 1613 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), | 1572 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), |
| 1614 kind_, | 1573 kind_, |
| 1615 extra_state_); | 1574 extra_state()); |
| 1616 __ Jump(code, RelocInfo::CODE_TARGET); | 1575 __ Jump(code, RelocInfo::CODE_TARGET); |
| 1617 } | 1576 } |
| 1618 | 1577 |
| 1619 | 1578 |
| 1620 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, | 1579 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, |
| 1621 Handle<JSObject> holder, | 1580 Handle<JSObject> holder, |
| 1622 PropertyIndex index, | 1581 PropertyIndex index, |
| 1623 Handle<Name> name) { | 1582 Handle<Name> name) { |
| 1624 // ----------- S t a t e ------------- | |
| 1625 // rcx : function name | |
| 1626 // rsp[0] : return address | |
| 1627 // rsp[8] : argument argc | |
| 1628 // rsp[16] : argument argc - 1 | |
| 1629 // ... | |
| 1630 // rsp[argc * 8] : argument 1 | |
| 1631 // rsp[(argc + 1) * 8] : argument 0 = receiver | |
| 1632 // ----------------------------------- | |
| 1633 Label miss; | 1583 Label miss; |
| 1634 | 1584 |
| 1635 GenerateNameCheck(name, &miss); | 1585 Register reg = HandlerFrontendHeader( |
| 1636 | 1586 object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 1637 StackArgumentsAccessor args(rsp, arguments()); | |
| 1638 __ movq(rdx, args.GetReceiverOperand()); | |
| 1639 | |
| 1640 // Check that the receiver isn't a smi. | |
| 1641 __ JumpIfSmi(rdx, &miss); | |
| 1642 | |
| 1643 // Do the right check and compute the holder register. | |
| 1644 Register reg = CheckPrototypes(object, rdx, holder, rbx, rax, rdi, | |
| 1645 name, &miss); | |
| 1646 | 1587 |
| 1647 GenerateFastPropertyLoad(masm(), rdi, reg, index.is_inobject(holder), | 1588 GenerateFastPropertyLoad(masm(), rdi, reg, index.is_inobject(holder), |
| 1648 index.translate(holder), Representation::Tagged()); | 1589 index.translate(holder), Representation::Tagged()); |
| 1590 GenerateJumpFunction(object, rdi, &miss); |
| 1649 | 1591 |
| 1650 // Check that the function really is a function. | 1592 HandlerFrontendFooter(&miss); |
| 1651 __ JumpIfSmi(rdi, &miss); | |
| 1652 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rbx); | |
| 1653 __ j(not_equal, &miss); | |
| 1654 | |
| 1655 // Patch the receiver on the stack with the global proxy if | |
| 1656 // necessary. | |
| 1657 if (object->IsGlobalObject()) { | |
| 1658 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | |
| 1659 __ movq(args.GetReceiverOperand(), rdx); | |
| 1660 } | |
| 1661 | |
| 1662 // Invoke the function. | |
| 1663 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | |
| 1664 ? CALL_AS_FUNCTION | |
| 1665 : CALL_AS_METHOD; | |
| 1666 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, | |
| 1667 NullCallWrapper(), call_kind); | |
| 1668 | |
| 1669 // Handle call cache miss. | |
| 1670 __ bind(&miss); | |
| 1671 GenerateMissBranch(); | |
| 1672 | 1593 |
| 1673 // Return the generated code. | 1594 // Return the generated code. |
| 1674 return GetCode(Code::FAST, name); | 1595 return GetCode(Code::FAST, name); |
| 1675 } | 1596 } |
| 1676 | 1597 |
| 1677 | 1598 |
| 1678 Handle<Code> CallStubCompiler::CompileArrayCodeCall( | 1599 Handle<Code> CallStubCompiler::CompileArrayCodeCall( |
| 1679 Handle<Object> object, | 1600 Handle<Object> object, |
| 1680 Handle<JSObject> holder, | 1601 Handle<JSObject> holder, |
| 1681 Handle<Cell> cell, | 1602 Handle<Cell> cell, |
| 1682 Handle<JSFunction> function, | 1603 Handle<JSFunction> function, |
| 1683 Handle<String> name, | 1604 Handle<String> name, |
| 1684 Code::StubType type) { | 1605 Code::StubType type) { |
| 1685 Label miss; | 1606 Label miss; |
| 1686 | 1607 |
| 1687 // Check that function is still array | 1608 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 1688 const int argc = arguments().immediate(); | 1609 if (!cell.is_null()) { |
| 1689 StackArgumentsAccessor args(rsp, argc); | |
| 1690 GenerateNameCheck(name, &miss); | |
| 1691 | |
| 1692 if (cell.is_null()) { | |
| 1693 __ movq(rdx, args.GetReceiverOperand()); | |
| 1694 | |
| 1695 // Check that the receiver isn't a smi. | |
| 1696 __ JumpIfSmi(rdx, &miss); | |
| 1697 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, | |
| 1698 name, &miss); | |
| 1699 } else { | |
| 1700 ASSERT(cell->value() == *function); | 1610 ASSERT(cell->value() == *function); |
| 1701 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | |
| 1702 &miss); | |
| 1703 GenerateLoadFunctionFromCell(cell, function, &miss); | 1611 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 1704 } | 1612 } |
| 1705 | 1613 |
| 1706 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite(); | 1614 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite(); |
| 1707 site->SetElementsKind(GetInitialFastElementsKind()); | 1615 site->SetElementsKind(GetInitialFastElementsKind()); |
| 1708 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site); | 1616 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site); |
| 1617 const int argc = arguments().immediate(); |
| 1709 __ movq(rax, Immediate(argc)); | 1618 __ movq(rax, Immediate(argc)); |
| 1710 __ Move(rbx, site_feedback_cell); | 1619 __ Move(rbx, site_feedback_cell); |
| 1711 __ Move(rdi, function); | 1620 __ Move(rdi, function); |
| 1712 | 1621 |
| 1713 ArrayConstructorStub stub(isolate()); | 1622 ArrayConstructorStub stub(isolate()); |
| 1714 __ TailCallStub(&stub); | 1623 __ TailCallStub(&stub); |
| 1715 | 1624 |
| 1716 __ bind(&miss); | 1625 HandlerFrontendFooter(&miss); |
| 1717 GenerateMissBranch(); | |
| 1718 | 1626 |
| 1719 // Return the generated code. | 1627 // Return the generated code. |
| 1720 return GetCode(type, name); | 1628 return GetCode(type, name); |
| 1721 } | 1629 } |
| 1722 | 1630 |
| 1723 | 1631 |
| 1724 Handle<Code> CallStubCompiler::CompileArrayPushCall( | 1632 Handle<Code> CallStubCompiler::CompileArrayPushCall( |
| 1725 Handle<Object> object, | 1633 Handle<Object> object, |
| 1726 Handle<JSObject> holder, | 1634 Handle<JSObject> holder, |
| 1727 Handle<Cell> cell, | 1635 Handle<Cell> cell, |
| 1728 Handle<JSFunction> function, | 1636 Handle<JSFunction> function, |
| 1729 Handle<String> name, | 1637 Handle<String> name, |
| 1730 Code::StubType type) { | 1638 Code::StubType type) { |
| 1731 // ----------- S t a t e ------------- | 1639 // If object is not an array or is observed or sealed, bail out to regular |
| 1732 // -- rcx : name | 1640 // call. |
| 1733 // -- rsp[0] : return address | |
| 1734 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | |
| 1735 // -- ... | |
| 1736 // -- rsp[(argc + 1) * 8] : receiver | |
| 1737 // ----------------------------------- | |
| 1738 | |
| 1739 // If object is not an array or is observed, bail out to regular call. | |
| 1740 if (!object->IsJSArray() || | 1641 if (!object->IsJSArray() || |
| 1741 !cell.is_null() || | 1642 !cell.is_null() || |
| 1742 Handle<JSArray>::cast(object)->map()->is_observed()) { | 1643 Handle<JSArray>::cast(object)->map()->is_observed() || |
| 1644 !Handle<JSArray>::cast(object)->map()->is_extensible()) { |
| 1743 return Handle<Code>::null(); | 1645 return Handle<Code>::null(); |
| 1744 } | 1646 } |
| 1745 | 1647 |
| 1746 Label miss; | 1648 Label miss; |
| 1747 GenerateNameCheck(name, &miss); | 1649 |
| 1650 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 1748 | 1651 |
| 1749 const int argc = arguments().immediate(); | 1652 const int argc = arguments().immediate(); |
| 1750 StackArgumentsAccessor args(rsp, argc); | 1653 StackArgumentsAccessor args(rsp, argc); |
| 1751 __ movq(rdx, args.GetReceiverOperand()); | |
| 1752 | |
| 1753 // Check that the receiver isn't a smi. | |
| 1754 __ JumpIfSmi(rdx, &miss); | |
| 1755 | |
| 1756 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, | |
| 1757 name, &miss); | |
| 1758 | |
| 1759 if (argc == 0) { | 1654 if (argc == 0) { |
| 1760 // Noop, return the length. | 1655 // Noop, return the length. |
| 1761 __ movq(rax, FieldOperand(rdx, JSArray::kLengthOffset)); | 1656 __ movq(rax, FieldOperand(rdx, JSArray::kLengthOffset)); |
| 1762 __ ret((argc + 1) * kPointerSize); | 1657 __ ret((argc + 1) * kPointerSize); |
| 1763 } else { | 1658 } else { |
| 1764 Label call_builtin; | 1659 Label call_builtin; |
| 1765 | 1660 |
| 1766 if (argc == 1) { // Otherwise fall through to call builtin. | 1661 if (argc == 1) { // Otherwise fall through to call builtin. |
| 1767 Label attempt_to_grow_elements, with_write_barrier, check_double; | 1662 Label attempt_to_grow_elements, with_write_barrier, check_double; |
| 1768 | 1663 |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1961 __ ret((argc + 1) * kPointerSize); | 1856 __ ret((argc + 1) * kPointerSize); |
| 1962 } | 1857 } |
| 1963 | 1858 |
| 1964 __ bind(&call_builtin); | 1859 __ bind(&call_builtin); |
| 1965 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush, | 1860 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush, |
| 1966 isolate()), | 1861 isolate()), |
| 1967 argc + 1, | 1862 argc + 1, |
| 1968 1); | 1863 1); |
| 1969 } | 1864 } |
| 1970 | 1865 |
| 1971 __ bind(&miss); | 1866 HandlerFrontendFooter(&miss); |
| 1972 GenerateMissBranch(); | |
| 1973 | 1867 |
| 1974 // Return the generated code. | 1868 // Return the generated code. |
| 1975 return GetCode(type, name); | 1869 return GetCode(type, name); |
| 1976 } | 1870 } |
| 1977 | 1871 |
| 1978 | 1872 |
| 1979 Handle<Code> CallStubCompiler::CompileArrayPopCall( | 1873 Handle<Code> CallStubCompiler::CompileArrayPopCall( |
| 1980 Handle<Object> object, | 1874 Handle<Object> object, |
| 1981 Handle<JSObject> holder, | 1875 Handle<JSObject> holder, |
| 1982 Handle<Cell> cell, | 1876 Handle<Cell> cell, |
| 1983 Handle<JSFunction> function, | 1877 Handle<JSFunction> function, |
| 1984 Handle<String> name, | 1878 Handle<String> name, |
| 1985 Code::StubType type) { | 1879 Code::StubType type) { |
| 1986 // ----------- S t a t e ------------- | 1880 // If object is not an array or is observed or sealed, bail out to regular |
| 1987 // -- rcx : name | 1881 // call. |
| 1988 // -- rsp[0] : return address | |
| 1989 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | |
| 1990 // -- ... | |
| 1991 // -- rsp[(argc + 1) * 8] : receiver | |
| 1992 // ----------------------------------- | |
| 1993 | |
| 1994 // If object is not an array or is observed, bail out to regular call. | |
| 1995 if (!object->IsJSArray() || | 1882 if (!object->IsJSArray() || |
| 1996 !cell.is_null() || | 1883 !cell.is_null() || |
| 1997 Handle<JSArray>::cast(object)->map()->is_observed()) { | 1884 Handle<JSArray>::cast(object)->map()->is_observed() || |
| 1885 !Handle<JSArray>::cast(object)->map()->is_extensible()) { |
| 1998 return Handle<Code>::null(); | 1886 return Handle<Code>::null(); |
| 1999 } | 1887 } |
| 2000 | 1888 |
| 2001 Label miss, return_undefined, call_builtin; | 1889 Label miss, return_undefined, call_builtin; |
| 2002 GenerateNameCheck(name, &miss); | |
| 2003 | 1890 |
| 2004 const int argc = arguments().immediate(); | 1891 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 2005 StackArgumentsAccessor args(rsp, argc); | |
| 2006 __ movq(rdx, args.GetReceiverOperand()); | |
| 2007 | |
| 2008 // Check that the receiver isn't a smi. | |
| 2009 __ JumpIfSmi(rdx, &miss); | |
| 2010 | |
| 2011 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, | |
| 2012 name, &miss); | |
| 2013 | 1892 |
| 2014 // Get the elements array of the object. | 1893 // Get the elements array of the object. |
| 2015 __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset)); | 1894 __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset)); |
| 2016 | 1895 |
| 2017 // Check that the elements are in fast mode and writable. | 1896 // Check that the elements are in fast mode and writable. |
| 2018 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), | 1897 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), |
| 2019 Heap::kFixedArrayMapRootIndex); | 1898 Heap::kFixedArrayMapRootIndex); |
| 2020 __ j(not_equal, &call_builtin); | 1899 __ j(not_equal, &call_builtin); |
| 2021 | 1900 |
| 2022 // Get the array's length into rcx and calculate new length. | 1901 // Get the array's length into rcx and calculate new length. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2035 __ j(equal, &call_builtin); | 1914 __ j(equal, &call_builtin); |
| 2036 | 1915 |
| 2037 // Set the array's length. | 1916 // Set the array's length. |
| 2038 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rcx); | 1917 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rcx); |
| 2039 | 1918 |
| 2040 // Fill with the hole and return original value. | 1919 // Fill with the hole and return original value. |
| 2041 __ movq(FieldOperand(rbx, | 1920 __ movq(FieldOperand(rbx, |
| 2042 rcx, times_pointer_size, | 1921 rcx, times_pointer_size, |
| 2043 FixedArray::kHeaderSize), | 1922 FixedArray::kHeaderSize), |
| 2044 r9); | 1923 r9); |
| 1924 const int argc = arguments().immediate(); |
| 2045 __ ret((argc + 1) * kPointerSize); | 1925 __ ret((argc + 1) * kPointerSize); |
| 2046 | 1926 |
| 2047 __ bind(&return_undefined); | 1927 __ bind(&return_undefined); |
| 2048 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 1928 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); |
| 2049 __ ret((argc + 1) * kPointerSize); | 1929 __ ret((argc + 1) * kPointerSize); |
| 2050 | 1930 |
| 2051 __ bind(&call_builtin); | 1931 __ bind(&call_builtin); |
| 2052 __ TailCallExternalReference( | 1932 __ TailCallExternalReference( |
| 2053 ExternalReference(Builtins::c_ArrayPop, isolate()), | 1933 ExternalReference(Builtins::c_ArrayPop, isolate()), |
| 2054 argc + 1, | 1934 argc + 1, |
| 2055 1); | 1935 1); |
| 2056 | 1936 |
| 2057 __ bind(&miss); | 1937 HandlerFrontendFooter(&miss); |
| 2058 GenerateMissBranch(); | |
| 2059 | 1938 |
| 2060 // Return the generated code. | 1939 // Return the generated code. |
| 2061 return GetCode(type, name); | 1940 return GetCode(type, name); |
| 2062 } | 1941 } |
| 2063 | 1942 |
| 2064 | 1943 |
| 2065 Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall( | 1944 Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall( |
| 2066 Handle<Object> object, | 1945 Handle<Object> object, |
| 2067 Handle<JSObject> holder, | 1946 Handle<JSObject> holder, |
| 2068 Handle<Cell> cell, | 1947 Handle<Cell> cell, |
| 2069 Handle<JSFunction> function, | 1948 Handle<JSFunction> function, |
| 2070 Handle<String> name, | 1949 Handle<String> name, |
| 2071 Code::StubType type) { | 1950 Code::StubType type) { |
| 2072 // ----------- S t a t e ------------- | |
| 2073 // -- rcx : function name | |
| 2074 // -- rsp[0] : return address | |
| 2075 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | |
| 2076 // -- ... | |
| 2077 // -- rsp[(argc + 1) * 8] : receiver | |
| 2078 // ----------------------------------- | |
| 2079 | |
| 2080 // If object is not a string, bail out to regular call. | 1951 // If object is not a string, bail out to regular call. |
| 2081 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); | 1952 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); |
| 2082 | 1953 |
| 2083 const int argc = arguments().immediate(); | |
| 2084 StackArgumentsAccessor args(rsp, argc); | |
| 2085 | |
| 2086 Label miss; | 1954 Label miss; |
| 2087 Label name_miss; | 1955 Label name_miss; |
| 2088 Label index_out_of_range; | 1956 Label index_out_of_range; |
| 2089 Label* index_out_of_range_label = &index_out_of_range; | 1957 Label* index_out_of_range_label = &index_out_of_range; |
| 2090 if (kind_ == Code::CALL_IC && | 1958 if (kind_ == Code::CALL_IC && |
| 2091 (CallICBase::StringStubState::decode(extra_state_) == | 1959 (CallICBase::StringStubState::decode(extra_state()) == |
| 2092 DEFAULT_STRING_STUB)) { | 1960 DEFAULT_STRING_STUB)) { |
| 2093 index_out_of_range_label = &miss; | 1961 index_out_of_range_label = &miss; |
| 2094 } | 1962 } |
| 2095 GenerateNameCheck(name, &name_miss); | |
| 2096 | 1963 |
| 2097 // Check that the maps starting from the prototype haven't changed. | 1964 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss); |
| 2098 GenerateDirectLoadGlobalFunctionPrototype(masm(), | |
| 2099 Context::STRING_FUNCTION_INDEX, | |
| 2100 rax, | |
| 2101 &miss); | |
| 2102 ASSERT(!object.is_identical_to(holder)); | |
| 2103 CheckPrototypes( | |
| 2104 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | |
| 2105 rax, holder, rbx, rdx, rdi, name, &miss); | |
| 2106 | 1965 |
| 2107 Register receiver = rbx; | 1966 Register receiver = rbx; |
| 2108 Register index = rdi; | 1967 Register index = rdi; |
| 2109 Register result = rax; | 1968 Register result = rax; |
| 1969 const int argc = arguments().immediate(); |
| 1970 StackArgumentsAccessor args(rsp, argc); |
| 1971 |
| 2110 __ movq(receiver, args.GetReceiverOperand()); | 1972 __ movq(receiver, args.GetReceiverOperand()); |
| 2111 if (argc > 0) { | 1973 if (argc > 0) { |
| 2112 __ movq(index, args.GetArgumentOperand(1)); | 1974 __ movq(index, args.GetArgumentOperand(1)); |
| 2113 } else { | 1975 } else { |
| 2114 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); | 1976 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); |
| 2115 } | 1977 } |
| 2116 | 1978 |
| 2117 StringCharCodeAtGenerator generator(receiver, | 1979 StringCharCodeAtGenerator generator(receiver, |
| 2118 index, | 1980 index, |
| 2119 result, | 1981 result, |
| 2120 &miss, // When not a string. | 1982 &miss, // When not a string. |
| 2121 &miss, // When not a number. | 1983 &miss, // When not a number. |
| 2122 index_out_of_range_label, | 1984 index_out_of_range_label, |
| 2123 STRING_INDEX_IS_NUMBER); | 1985 STRING_INDEX_IS_NUMBER); |
| 2124 generator.GenerateFast(masm()); | 1986 generator.GenerateFast(masm()); |
| 2125 __ ret((argc + 1) * kPointerSize); | 1987 __ ret((argc + 1) * kPointerSize); |
| 2126 | 1988 |
| 2127 StubRuntimeCallHelper call_helper; | 1989 StubRuntimeCallHelper call_helper; |
| 2128 generator.GenerateSlow(masm(), call_helper); | 1990 generator.GenerateSlow(masm(), call_helper); |
| 2129 | 1991 |
| 2130 if (index_out_of_range.is_linked()) { | 1992 if (index_out_of_range.is_linked()) { |
| 2131 __ bind(&index_out_of_range); | 1993 __ bind(&index_out_of_range); |
| 2132 __ LoadRoot(rax, Heap::kNanValueRootIndex); | 1994 __ LoadRoot(rax, Heap::kNanValueRootIndex); |
| 2133 __ ret((argc + 1) * kPointerSize); | 1995 __ ret((argc + 1) * kPointerSize); |
| 2134 } | 1996 } |
| 2135 | 1997 |
| 2136 __ bind(&miss); | 1998 __ bind(&miss); |
| 2137 // Restore function name in rcx. | 1999 // Restore function name in rcx. |
| 2138 __ Move(rcx, name); | 2000 __ Move(rcx, name); |
| 2139 __ bind(&name_miss); | 2001 HandlerFrontendFooter(&name_miss); |
| 2140 GenerateMissBranch(); | |
| 2141 | 2002 |
| 2142 // Return the generated code. | 2003 // Return the generated code. |
| 2143 return GetCode(type, name); | 2004 return GetCode(type, name); |
| 2144 } | 2005 } |
| 2145 | 2006 |
| 2146 | 2007 |
| 2147 Handle<Code> CallStubCompiler::CompileStringCharAtCall( | 2008 Handle<Code> CallStubCompiler::CompileStringCharAtCall( |
| 2148 Handle<Object> object, | 2009 Handle<Object> object, |
| 2149 Handle<JSObject> holder, | 2010 Handle<JSObject> holder, |
| 2150 Handle<Cell> cell, | 2011 Handle<Cell> cell, |
| 2151 Handle<JSFunction> function, | 2012 Handle<JSFunction> function, |
| 2152 Handle<String> name, | 2013 Handle<String> name, |
| 2153 Code::StubType type) { | 2014 Code::StubType type) { |
| 2154 // ----------- S t a t e ------------- | |
| 2155 // -- rcx : function name | |
| 2156 // -- rsp[0] : return address | |
| 2157 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | |
| 2158 // -- ... | |
| 2159 // -- rsp[(argc + 1) * 8] : receiver | |
| 2160 // ----------------------------------- | |
| 2161 | |
| 2162 // If object is not a string, bail out to regular call. | 2015 // If object is not a string, bail out to regular call. |
| 2163 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); | 2016 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); |
| 2164 | 2017 |
| 2165 const int argc = arguments().immediate(); | 2018 const int argc = arguments().immediate(); |
| 2166 StackArgumentsAccessor args(rsp, argc); | 2019 StackArgumentsAccessor args(rsp, argc); |
| 2167 | 2020 |
| 2168 Label miss; | 2021 Label miss; |
| 2169 Label name_miss; | 2022 Label name_miss; |
| 2170 Label index_out_of_range; | 2023 Label index_out_of_range; |
| 2171 Label* index_out_of_range_label = &index_out_of_range; | 2024 Label* index_out_of_range_label = &index_out_of_range; |
| 2172 if (kind_ == Code::CALL_IC && | 2025 if (kind_ == Code::CALL_IC && |
| 2173 (CallICBase::StringStubState::decode(extra_state_) == | 2026 (CallICBase::StringStubState::decode(extra_state()) == |
| 2174 DEFAULT_STRING_STUB)) { | 2027 DEFAULT_STRING_STUB)) { |
| 2175 index_out_of_range_label = &miss; | 2028 index_out_of_range_label = &miss; |
| 2176 } | 2029 } |
| 2177 GenerateNameCheck(name, &name_miss); | |
| 2178 | 2030 |
| 2179 // Check that the maps starting from the prototype haven't changed. | 2031 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss); |
| 2180 GenerateDirectLoadGlobalFunctionPrototype(masm(), | |
| 2181 Context::STRING_FUNCTION_INDEX, | |
| 2182 rax, | |
| 2183 &miss); | |
| 2184 ASSERT(!object.is_identical_to(holder)); | |
| 2185 CheckPrototypes( | |
| 2186 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | |
| 2187 rax, holder, rbx, rdx, rdi, name, &miss); | |
| 2188 | 2032 |
| 2189 Register receiver = rax; | 2033 Register receiver = rax; |
| 2190 Register index = rdi; | 2034 Register index = rdi; |
| 2191 Register scratch = rdx; | 2035 Register scratch = rdx; |
| 2192 Register result = rax; | 2036 Register result = rax; |
| 2193 __ movq(receiver, args.GetReceiverOperand()); | 2037 __ movq(receiver, args.GetReceiverOperand()); |
| 2194 if (argc > 0) { | 2038 if (argc > 0) { |
| 2195 __ movq(index, args.GetArgumentOperand(1)); | 2039 __ movq(index, args.GetArgumentOperand(1)); |
| 2196 } else { | 2040 } else { |
| 2197 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); | 2041 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2212 generator.GenerateSlow(masm(), call_helper); | 2056 generator.GenerateSlow(masm(), call_helper); |
| 2213 | 2057 |
| 2214 if (index_out_of_range.is_linked()) { | 2058 if (index_out_of_range.is_linked()) { |
| 2215 __ bind(&index_out_of_range); | 2059 __ bind(&index_out_of_range); |
| 2216 __ LoadRoot(rax, Heap::kempty_stringRootIndex); | 2060 __ LoadRoot(rax, Heap::kempty_stringRootIndex); |
| 2217 __ ret((argc + 1) * kPointerSize); | 2061 __ ret((argc + 1) * kPointerSize); |
| 2218 } | 2062 } |
| 2219 __ bind(&miss); | 2063 __ bind(&miss); |
| 2220 // Restore function name in rcx. | 2064 // Restore function name in rcx. |
| 2221 __ Move(rcx, name); | 2065 __ Move(rcx, name); |
| 2222 __ bind(&name_miss); | 2066 HandlerFrontendFooter(&name_miss); |
| 2223 GenerateMissBranch(); | |
| 2224 | 2067 |
| 2225 // Return the generated code. | 2068 // Return the generated code. |
| 2226 return GetCode(type, name); | 2069 return GetCode(type, name); |
| 2227 } | 2070 } |
| 2228 | 2071 |
| 2229 | 2072 |
| 2230 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( | 2073 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( |
| 2231 Handle<Object> object, | 2074 Handle<Object> object, |
| 2232 Handle<JSObject> holder, | 2075 Handle<JSObject> holder, |
| 2233 Handle<Cell> cell, | 2076 Handle<Cell> cell, |
| 2234 Handle<JSFunction> function, | 2077 Handle<JSFunction> function, |
| 2235 Handle<String> name, | 2078 Handle<String> name, |
| 2236 Code::StubType type) { | 2079 Code::StubType type) { |
| 2237 // ----------- S t a t e ------------- | |
| 2238 // -- rcx : function name | |
| 2239 // -- rsp[0] : return address | |
| 2240 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | |
| 2241 // -- ... | |
| 2242 // -- rsp[(argc + 1) * 8] : receiver | |
| 2243 // ----------------------------------- | |
| 2244 | |
| 2245 // If the object is not a JSObject or we got an unexpected number of | 2080 // If the object is not a JSObject or we got an unexpected number of |
| 2246 // arguments, bail out to the regular call. | 2081 // arguments, bail out to the regular call. |
| 2247 const int argc = arguments().immediate(); | 2082 const int argc = arguments().immediate(); |
| 2248 StackArgumentsAccessor args(rsp, argc); | 2083 StackArgumentsAccessor args(rsp, argc); |
| 2249 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); | 2084 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
| 2250 | 2085 |
| 2251 Label miss; | 2086 Label miss; |
| 2252 GenerateNameCheck(name, &miss); | |
| 2253 | 2087 |
| 2254 if (cell.is_null()) { | 2088 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 2255 __ movq(rdx, args.GetReceiverOperand()); | 2089 if (!cell.is_null()) { |
| 2256 __ JumpIfSmi(rdx, &miss); | |
| 2257 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, | |
| 2258 name, &miss); | |
| 2259 } else { | |
| 2260 ASSERT(cell->value() == *function); | 2090 ASSERT(cell->value() == *function); |
| 2261 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | |
| 2262 &miss); | |
| 2263 GenerateLoadFunctionFromCell(cell, function, &miss); | 2091 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2264 } | 2092 } |
| 2265 | 2093 |
| 2266 // Load the char code argument. | 2094 // Load the char code argument. |
| 2267 Register code = rbx; | 2095 Register code = rbx; |
| 2268 __ movq(code, args.GetArgumentOperand(1)); | 2096 __ movq(code, args.GetArgumentOperand(1)); |
| 2269 | 2097 |
| 2270 // Check the code is a smi. | 2098 // Check the code is a smi. |
| 2271 Label slow; | 2099 Label slow; |
| 2272 __ JumpIfNotSmi(code, &slow); | 2100 __ JumpIfNotSmi(code, &slow); |
| 2273 | 2101 |
| 2274 // Convert the smi code to uint16. | 2102 // Convert the smi code to uint16. |
| 2275 __ SmiAndConstant(code, code, Smi::FromInt(0xffff)); | 2103 __ SmiAndConstant(code, code, Smi::FromInt(0xffff)); |
| 2276 | 2104 |
| 2277 StringCharFromCodeGenerator generator(code, rax); | 2105 StringCharFromCodeGenerator generator(code, rax); |
| 2278 generator.GenerateFast(masm()); | 2106 generator.GenerateFast(masm()); |
| 2279 __ ret(2 * kPointerSize); | 2107 __ ret(2 * kPointerSize); |
| 2280 | 2108 |
| 2281 StubRuntimeCallHelper call_helper; | 2109 StubRuntimeCallHelper call_helper; |
| 2282 generator.GenerateSlow(masm(), call_helper); | 2110 generator.GenerateSlow(masm(), call_helper); |
| 2283 | 2111 |
| 2284 // Tail call the full function. We do not have to patch the receiver | |
| 2285 // because the function makes no use of it. | |
| 2286 __ bind(&slow); | 2112 __ bind(&slow); |
| 2287 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2113 // We do not have to patch the receiver because the function makes no use of |
| 2288 ? CALL_AS_FUNCTION | 2114 // it. |
| 2289 : CALL_AS_METHOD; | 2115 GenerateJumpFunctionIgnoreReceiver(function); |
| 2290 ParameterCount expected(function); | |
| 2291 __ InvokeFunction(function, expected, arguments(), | |
| 2292 JUMP_FUNCTION, NullCallWrapper(), call_kind); | |
| 2293 | 2116 |
| 2294 __ bind(&miss); | 2117 HandlerFrontendFooter(&miss); |
| 2295 // rcx: function name. | |
| 2296 GenerateMissBranch(); | |
| 2297 | 2118 |
| 2298 // Return the generated code. | 2119 // Return the generated code. |
| 2299 return GetCode(type, name); | 2120 return GetCode(type, name); |
| 2300 } | 2121 } |
| 2301 | 2122 |
| 2302 | 2123 |
| 2303 Handle<Code> CallStubCompiler::CompileMathFloorCall( | 2124 Handle<Code> CallStubCompiler::CompileMathFloorCall( |
| 2304 Handle<Object> object, | 2125 Handle<Object> object, |
| 2305 Handle<JSObject> holder, | 2126 Handle<JSObject> holder, |
| 2306 Handle<Cell> cell, | 2127 Handle<Cell> cell, |
| 2307 Handle<JSFunction> function, | 2128 Handle<JSFunction> function, |
| 2308 Handle<String> name, | 2129 Handle<String> name, |
| 2309 Code::StubType type) { | 2130 Code::StubType type) { |
| 2310 // ----------- S t a t e ------------- | |
| 2311 // -- rcx : name | |
| 2312 // -- rsp[0] : return address | |
| 2313 // -- rsp[(argc - n) * 4] : arg[n] (zero-based) | |
| 2314 // -- ... | |
| 2315 // -- rsp[(argc + 1) * 4] : receiver | |
| 2316 // ----------------------------------- | |
| 2317 const int argc = arguments().immediate(); | 2131 const int argc = arguments().immediate(); |
| 2318 StackArgumentsAccessor args(rsp, argc); | 2132 StackArgumentsAccessor args(rsp, argc); |
| 2319 | 2133 |
| 2320 // If the object is not a JSObject or we got an unexpected number of | 2134 // If the object is not a JSObject or we got an unexpected number of |
| 2321 // arguments, bail out to the regular call. | 2135 // arguments, bail out to the regular call. |
| 2322 if (!object->IsJSObject() || argc != 1) { | 2136 if (!object->IsJSObject() || argc != 1) { |
| 2323 return Handle<Code>::null(); | 2137 return Handle<Code>::null(); |
| 2324 } | 2138 } |
| 2325 | 2139 |
| 2326 Label miss; | 2140 Label miss, slow; |
| 2327 GenerateNameCheck(name, &miss); | |
| 2328 | 2141 |
| 2329 if (cell.is_null()) { | 2142 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 2330 __ movq(rdx, args.GetReceiverOperand()); | 2143 if (!cell.is_null()) { |
| 2331 | |
| 2332 STATIC_ASSERT(kSmiTag == 0); | |
| 2333 __ JumpIfSmi(rdx, &miss); | |
| 2334 | |
| 2335 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, | |
| 2336 name, &miss); | |
| 2337 } else { | |
| 2338 ASSERT(cell->value() == *function); | 2144 ASSERT(cell->value() == *function); |
| 2339 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | |
| 2340 &miss); | |
| 2341 GenerateLoadFunctionFromCell(cell, function, &miss); | 2145 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2342 } | 2146 } |
| 2343 | 2147 |
| 2344 // Load the (only) argument into rax. | 2148 // Load the (only) argument into rax. |
| 2345 __ movq(rax, args.GetArgumentOperand(1)); | 2149 __ movq(rax, args.GetArgumentOperand(1)); |
| 2346 | 2150 |
| 2347 // Check if the argument is a smi. | 2151 // Check if the argument is a smi. |
| 2348 Label smi; | 2152 Label smi; |
| 2349 STATIC_ASSERT(kSmiTag == 0); | 2153 STATIC_ASSERT(kSmiTag == 0); |
| 2350 __ JumpIfSmi(rax, &smi); | 2154 __ JumpIfSmi(rax, &smi); |
| 2351 | 2155 |
| 2352 // Check if the argument is a heap number and load its value into xmm0. | 2156 // Check if the argument is a heap number and load its value into xmm0. |
| 2353 Label slow; | |
| 2354 __ CheckMap(rax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK); | 2157 __ CheckMap(rax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK); |
| 2355 __ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset)); | 2158 __ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset)); |
| 2356 | 2159 |
| 2357 // Check if the argument is strictly positive. Note this also discards NaN. | 2160 // Check if the argument is strictly positive. Note this also discards NaN. |
| 2358 __ xorpd(xmm1, xmm1); | 2161 __ xorpd(xmm1, xmm1); |
| 2359 __ ucomisd(xmm0, xmm1); | 2162 __ ucomisd(xmm0, xmm1); |
| 2360 __ j(below_equal, &slow); | 2163 __ j(below_equal, &slow); |
| 2361 | 2164 |
| 2362 // Do a truncating conversion. | 2165 // Do a truncating conversion. |
| 2363 __ cvttsd2si(rax, xmm0); | 2166 __ cvttsd2si(rax, xmm0); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2405 // Return a new heap number. | 2208 // Return a new heap number. |
| 2406 __ AllocateHeapNumber(rax, rbx, &slow); | 2209 __ AllocateHeapNumber(rax, rbx, &slow); |
| 2407 __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm0); | 2210 __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm0); |
| 2408 __ ret(2 * kPointerSize); | 2211 __ ret(2 * kPointerSize); |
| 2409 | 2212 |
| 2410 // Return the argument (when it's an already round heap number). | 2213 // Return the argument (when it's an already round heap number). |
| 2411 __ bind(&already_round); | 2214 __ bind(&already_round); |
| 2412 __ movq(rax, args.GetArgumentOperand(1)); | 2215 __ movq(rax, args.GetArgumentOperand(1)); |
| 2413 __ ret(2 * kPointerSize); | 2216 __ ret(2 * kPointerSize); |
| 2414 | 2217 |
| 2415 // Tail call the full function. We do not have to patch the receiver | |
| 2416 // because the function makes no use of it. | |
| 2417 __ bind(&slow); | 2218 __ bind(&slow); |
| 2418 ParameterCount expected(function); | 2219 // We do not have to patch the receiver because the function makes no use of |
| 2419 __ InvokeFunction(function, expected, arguments(), | 2220 // it. |
| 2420 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 2221 GenerateJumpFunctionIgnoreReceiver(function); |
| 2421 | 2222 |
| 2422 __ bind(&miss); | 2223 HandlerFrontendFooter(&miss); |
| 2423 // rcx: function name. | |
| 2424 GenerateMissBranch(); | |
| 2425 | 2224 |
| 2426 // Return the generated code. | 2225 // Return the generated code. |
| 2427 return GetCode(type, name); | 2226 return GetCode(type, name); |
| 2428 } | 2227 } |
| 2429 | 2228 |
| 2430 | 2229 |
| 2431 Handle<Code> CallStubCompiler::CompileMathAbsCall( | 2230 Handle<Code> CallStubCompiler::CompileMathAbsCall( |
| 2432 Handle<Object> object, | 2231 Handle<Object> object, |
| 2433 Handle<JSObject> holder, | 2232 Handle<JSObject> holder, |
| 2434 Handle<Cell> cell, | 2233 Handle<Cell> cell, |
| 2435 Handle<JSFunction> function, | 2234 Handle<JSFunction> function, |
| 2436 Handle<String> name, | 2235 Handle<String> name, |
| 2437 Code::StubType type) { | 2236 Code::StubType type) { |
| 2438 // ----------- S t a t e ------------- | |
| 2439 // -- rcx : function name | |
| 2440 // -- rsp[0] : return address | |
| 2441 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | |
| 2442 // -- ... | |
| 2443 // -- rsp[(argc + 1) * 8] : receiver | |
| 2444 // ----------------------------------- | |
| 2445 | |
| 2446 // If the object is not a JSObject or we got an unexpected number of | 2237 // If the object is not a JSObject or we got an unexpected number of |
| 2447 // arguments, bail out to the regular call. | 2238 // arguments, bail out to the regular call. |
| 2448 const int argc = arguments().immediate(); | 2239 const int argc = arguments().immediate(); |
| 2449 StackArgumentsAccessor args(rsp, argc); | 2240 StackArgumentsAccessor args(rsp, argc); |
| 2450 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); | 2241 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
| 2451 | 2242 |
| 2452 Label miss; | 2243 Label miss; |
| 2453 GenerateNameCheck(name, &miss); | |
| 2454 | 2244 |
| 2455 if (cell.is_null()) { | 2245 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 2456 __ movq(rdx, args.GetReceiverOperand()); | 2246 if (!cell.is_null()) { |
| 2457 __ JumpIfSmi(rdx, &miss); | |
| 2458 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, | |
| 2459 name, &miss); | |
| 2460 } else { | |
| 2461 ASSERT(cell->value() == *function); | 2247 ASSERT(cell->value() == *function); |
| 2462 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | |
| 2463 &miss); | |
| 2464 GenerateLoadFunctionFromCell(cell, function, &miss); | 2248 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2465 } | 2249 } |
| 2250 |
| 2466 // Load the (only) argument into rax. | 2251 // Load the (only) argument into rax. |
| 2467 __ movq(rax, args.GetArgumentOperand(1)); | 2252 __ movq(rax, args.GetArgumentOperand(1)); |
| 2468 | 2253 |
| 2469 // Check if the argument is a smi. | 2254 // Check if the argument is a smi. |
| 2470 Label not_smi; | 2255 Label not_smi; |
| 2471 STATIC_ASSERT(kSmiTag == 0); | 2256 STATIC_ASSERT(kSmiTag == 0); |
| 2472 __ JumpIfNotSmi(rax, ¬_smi); | 2257 __ JumpIfNotSmi(rax, ¬_smi); |
| 2473 | 2258 |
| 2474 // Branchless abs implementation, refer to below: | 2259 // Branchless abs implementation, refer to below: |
| 2475 // http://graphics.stanford.edu/~seander/bithacks.html#IntegerAbs | 2260 // http://graphics.stanford.edu/~seander/bithacks.html#IntegerAbs |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2507 __ ret(2 * kPointerSize); | 2292 __ ret(2 * kPointerSize); |
| 2508 | 2293 |
| 2509 // If the argument is negative, clear the sign, and return a new | 2294 // If the argument is negative, clear the sign, and return a new |
| 2510 // number. We still have the sign mask in rdi. | 2295 // number. We still have the sign mask in rdi. |
| 2511 __ bind(&negative_sign); | 2296 __ bind(&negative_sign); |
| 2512 __ xor_(rbx, rdi); | 2297 __ xor_(rbx, rdi); |
| 2513 __ AllocateHeapNumber(rax, rdx, &slow); | 2298 __ AllocateHeapNumber(rax, rdx, &slow); |
| 2514 __ MoveDouble(FieldOperand(rax, HeapNumber::kValueOffset), rbx); | 2299 __ MoveDouble(FieldOperand(rax, HeapNumber::kValueOffset), rbx); |
| 2515 __ ret(2 * kPointerSize); | 2300 __ ret(2 * kPointerSize); |
| 2516 | 2301 |
| 2517 // Tail call the full function. We do not have to patch the receiver | |
| 2518 // because the function makes no use of it. | |
| 2519 __ bind(&slow); | 2302 __ bind(&slow); |
| 2520 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2303 // We do not have to patch the receiver because the function makes no use of |
| 2521 ? CALL_AS_FUNCTION | 2304 // it. |
| 2522 : CALL_AS_METHOD; | 2305 GenerateJumpFunctionIgnoreReceiver(function); |
| 2523 ParameterCount expected(function); | |
| 2524 __ InvokeFunction(function, expected, arguments(), | |
| 2525 JUMP_FUNCTION, NullCallWrapper(), call_kind); | |
| 2526 | 2306 |
| 2527 __ bind(&miss); | 2307 HandlerFrontendFooter(&miss); |
| 2528 // rcx: function name. | |
| 2529 GenerateMissBranch(); | |
| 2530 | 2308 |
| 2531 // Return the generated code. | 2309 // Return the generated code. |
| 2532 return GetCode(type, name); | 2310 return GetCode(type, name); |
| 2533 } | 2311 } |
| 2534 | 2312 |
| 2535 | 2313 |
| 2536 Handle<Code> CallStubCompiler::CompileFastApiCall( | 2314 Handle<Code> CallStubCompiler::CompileFastApiCall( |
| 2537 const CallOptimization& optimization, | 2315 const CallOptimization& optimization, |
| 2538 Handle<Object> object, | 2316 Handle<Object> object, |
| 2539 Handle<JSObject> holder, | 2317 Handle<JSObject> holder, |
| (...skipping 22 matching lines...) Expand all Loading... |
| 2562 | 2340 |
| 2563 Counters* counters = isolate()->counters(); | 2341 Counters* counters = isolate()->counters(); |
| 2564 __ IncrementCounter(counters->call_const(), 1); | 2342 __ IncrementCounter(counters->call_const(), 1); |
| 2565 __ IncrementCounter(counters->call_const_fast_api(), 1); | 2343 __ IncrementCounter(counters->call_const_fast_api(), 1); |
| 2566 | 2344 |
| 2567 // Allocate space for v8::Arguments implicit values. Must be initialized | 2345 // Allocate space for v8::Arguments implicit values. Must be initialized |
| 2568 // before calling any runtime function. | 2346 // before calling any runtime function. |
| 2569 __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); | 2347 __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); |
| 2570 | 2348 |
| 2571 // Check that the maps haven't changed and find a Holder as a side effect. | 2349 // Check that the maps haven't changed and find a Holder as a side effect. |
| 2572 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, | 2350 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder, |
| 2573 name, depth, &miss); | 2351 rbx, rax, rdi, name, depth, &miss); |
| 2574 | 2352 |
| 2575 // Move the return address on top of the stack. | 2353 // Move the return address on top of the stack. |
| 2576 __ movq(rax, | 2354 __ movq(rax, |
| 2577 StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize)); | 2355 StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize)); |
| 2578 __ movq(StackOperandForReturnAddress(0), rax); | 2356 __ movq(StackOperandForReturnAddress(0), rax); |
| 2579 | 2357 |
| 2580 GenerateFastApiCall(masm(), optimization, argc); | 2358 GenerateFastApiCall(masm(), optimization, argc); |
| 2581 | 2359 |
| 2582 __ bind(&miss); | 2360 __ bind(&miss); |
| 2583 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); | 2361 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); |
| 2584 | 2362 |
| 2585 __ bind(&miss_before_stack_reserved); | 2363 HandlerFrontendFooter(&miss_before_stack_reserved); |
| 2586 GenerateMissBranch(); | |
| 2587 | 2364 |
| 2588 // Return the generated code. | 2365 // Return the generated code. |
| 2589 return GetCode(function); | 2366 return GetCode(function); |
| 2590 } | 2367 } |
| 2591 | 2368 |
| 2592 | 2369 |
| 2593 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { | 2370 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { |
| 2594 Label success; | 2371 Label success; |
| 2595 // Check that the object is a boolean. | 2372 // Check that the object is a boolean. |
| 2596 __ CompareRoot(object, Heap::kTrueValueRootIndex); | 2373 __ CompareRoot(object, Heap::kTrueValueRootIndex); |
| 2597 __ j(equal, &success); | 2374 __ j(equal, &success); |
| 2598 __ CompareRoot(object, Heap::kFalseValueRootIndex); | 2375 __ CompareRoot(object, Heap::kFalseValueRootIndex); |
| 2599 __ j(not_equal, miss); | 2376 __ j(not_equal, miss); |
| 2600 __ bind(&success); | 2377 __ bind(&success); |
| 2601 } | 2378 } |
| 2602 | 2379 |
| 2603 | 2380 |
| 2604 void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object, | 2381 void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) { |
| 2605 Handle<JSObject> holder, | 2382 if (object->IsGlobalObject()) { |
| 2606 Handle<Name> name, | 2383 StackArgumentsAccessor args(rsp, arguments()); |
| 2607 CheckType check) { | 2384 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
| 2608 // ----------- S t a t e ------------- | 2385 __ movq(args.GetReceiverOperand(), rdx); |
| 2609 // rcx : function name | 2386 } |
| 2610 // rsp[0] : return address | 2387 } |
| 2611 // rsp[8] : argument argc | 2388 |
| 2612 // rsp[16] : argument argc - 1 | 2389 |
| 2613 // ... | 2390 Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object, |
| 2614 // rsp[argc * 8] : argument 1 | 2391 Handle<JSObject> holder, |
| 2615 // rsp[(argc + 1) * 8] : argument 0 = receiver | 2392 Handle<Name> name, |
| 2616 // ----------------------------------- | 2393 CheckType check, |
| 2617 Label miss; | 2394 Label* miss) { |
| 2618 GenerateNameCheck(name, &miss); | 2395 GenerateNameCheck(name, miss); |
| 2396 |
| 2397 Register reg = rdx; |
| 2619 | 2398 |
| 2620 StackArgumentsAccessor args(rsp, arguments()); | 2399 StackArgumentsAccessor args(rsp, arguments()); |
| 2621 __ movq(rdx, args.GetReceiverOperand()); | 2400 __ movq(reg, args.GetReceiverOperand()); |
| 2622 | 2401 |
| 2623 // Check that the receiver isn't a smi. | 2402 // Check that the receiver isn't a smi. |
| 2624 if (check != NUMBER_CHECK) { | 2403 if (check != NUMBER_CHECK) { |
| 2625 __ JumpIfSmi(rdx, &miss); | 2404 __ JumpIfSmi(reg, miss); |
| 2626 } | 2405 } |
| 2627 | 2406 |
| 2628 // Make sure that it's okay not to patch the on stack receiver | 2407 // Make sure that it's okay not to patch the on stack receiver |
| 2629 // unless we're doing a receiver map check. | 2408 // unless we're doing a receiver map check. |
| 2630 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 2409 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
| 2631 | 2410 |
| 2632 Counters* counters = isolate()->counters(); | 2411 Counters* counters = isolate()->counters(); |
| 2633 switch (check) { | 2412 switch (check) { |
| 2634 case RECEIVER_MAP_CHECK: | 2413 case RECEIVER_MAP_CHECK: |
| 2635 __ IncrementCounter(counters->call_const(), 1); | 2414 __ IncrementCounter(counters->call_const(), 1); |
| 2636 | 2415 |
| 2637 // Check that the maps haven't changed. | 2416 // Check that the maps haven't changed. |
| 2638 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, | 2417 reg = CheckPrototypes(IC::CurrentTypeOf(object, isolate()), reg, holder, |
| 2639 rdi, name, &miss); | 2418 rbx, rax, rdi, name, miss); |
| 2640 | |
| 2641 // Patch the receiver on the stack with the global proxy if | |
| 2642 // necessary. | |
| 2643 if (object->IsGlobalObject()) { | |
| 2644 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | |
| 2645 __ movq(args.GetReceiverOperand(), rdx); | |
| 2646 } | |
| 2647 break; | 2419 break; |
| 2648 | 2420 |
| 2649 case STRING_CHECK: | 2421 case STRING_CHECK: { |
| 2650 // Check that the object is a string. | 2422 // Check that the object is a string. |
| 2651 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rax); | 2423 __ CmpObjectType(reg, FIRST_NONSTRING_TYPE, rax); |
| 2652 __ j(above_equal, &miss); | 2424 __ j(above_equal, miss); |
| 2653 // Check that the maps starting from the prototype haven't changed. | 2425 // Check that the maps starting from the prototype haven't changed. |
| 2654 GenerateDirectLoadGlobalFunctionPrototype( | 2426 GenerateDirectLoadGlobalFunctionPrototype( |
| 2655 masm(), Context::STRING_FUNCTION_INDEX, rax, &miss); | 2427 masm(), Context::STRING_FUNCTION_INDEX, rax, miss); |
| 2656 CheckPrototypes( | |
| 2657 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | |
| 2658 rax, holder, rbx, rdx, rdi, name, &miss); | |
| 2659 break; | 2428 break; |
| 2660 | 2429 } |
| 2661 case SYMBOL_CHECK: | 2430 case SYMBOL_CHECK: { |
| 2662 // Check that the object is a symbol. | 2431 // Check that the object is a symbol. |
| 2663 __ CmpObjectType(rdx, SYMBOL_TYPE, rax); | 2432 __ CmpObjectType(reg, SYMBOL_TYPE, rax); |
| 2664 __ j(not_equal, &miss); | 2433 __ j(not_equal, miss); |
| 2665 // Check that the maps starting from the prototype haven't changed. | 2434 // Check that the maps starting from the prototype haven't changed. |
| 2666 GenerateDirectLoadGlobalFunctionPrototype( | 2435 GenerateDirectLoadGlobalFunctionPrototype( |
| 2667 masm(), Context::SYMBOL_FUNCTION_INDEX, rax, &miss); | 2436 masm(), Context::SYMBOL_FUNCTION_INDEX, rax, miss); |
| 2668 CheckPrototypes( | |
| 2669 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | |
| 2670 rax, holder, rbx, rdx, rdi, name, &miss); | |
| 2671 break; | 2437 break; |
| 2672 | 2438 } |
| 2673 case NUMBER_CHECK: { | 2439 case NUMBER_CHECK: { |
| 2674 Label fast; | 2440 Label fast; |
| 2675 // Check that the object is a smi or a heap number. | 2441 // Check that the object is a smi or a heap number. |
| 2676 __ JumpIfSmi(rdx, &fast); | 2442 __ JumpIfSmi(reg, &fast); |
| 2677 __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rax); | 2443 __ CmpObjectType(reg, HEAP_NUMBER_TYPE, rax); |
| 2678 __ j(not_equal, &miss); | 2444 __ j(not_equal, miss); |
| 2679 __ bind(&fast); | 2445 __ bind(&fast); |
| 2680 // Check that the maps starting from the prototype haven't changed. | 2446 // Check that the maps starting from the prototype haven't changed. |
| 2681 GenerateDirectLoadGlobalFunctionPrototype( | 2447 GenerateDirectLoadGlobalFunctionPrototype( |
| 2682 masm(), Context::NUMBER_FUNCTION_INDEX, rax, &miss); | 2448 masm(), Context::NUMBER_FUNCTION_INDEX, rax, miss); |
| 2683 CheckPrototypes( | |
| 2684 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | |
| 2685 rax, holder, rbx, rdx, rdi, name, &miss); | |
| 2686 break; | 2449 break; |
| 2687 } | 2450 } |
| 2688 case BOOLEAN_CHECK: { | 2451 case BOOLEAN_CHECK: { |
| 2689 GenerateBooleanCheck(rdx, &miss); | 2452 GenerateBooleanCheck(reg, miss); |
| 2690 // Check that the maps starting from the prototype haven't changed. | 2453 // Check that the maps starting from the prototype haven't changed. |
| 2691 GenerateDirectLoadGlobalFunctionPrototype( | 2454 GenerateDirectLoadGlobalFunctionPrototype( |
| 2692 masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, &miss); | 2455 masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, miss); |
| 2693 CheckPrototypes( | |
| 2694 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | |
| 2695 rax, holder, rbx, rdx, rdi, name, &miss); | |
| 2696 break; | 2456 break; |
| 2697 } | 2457 } |
| 2698 } | 2458 } |
| 2699 | 2459 |
| 2700 Label success; | 2460 if (check != RECEIVER_MAP_CHECK) { |
| 2701 __ jmp(&success); | 2461 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2462 reg = CheckPrototypes( |
| 2463 IC::CurrentTypeOf(prototype, isolate()), |
| 2464 rax, holder, rbx, rdx, rdi, name, miss); |
| 2465 } |
| 2702 | 2466 |
| 2703 // Handle call cache miss. | 2467 return reg; |
| 2704 __ bind(&miss); | |
| 2705 GenerateMissBranch(); | |
| 2706 | |
| 2707 __ bind(&success); | |
| 2708 } | 2468 } |
| 2709 | 2469 |
| 2710 | 2470 |
| 2711 void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) { | 2471 void CallStubCompiler::GenerateJumpFunction(Handle<Object> object, |
| 2712 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2472 Register function, |
| 2713 ? CALL_AS_FUNCTION | 2473 Label* miss) { |
| 2714 : CALL_AS_METHOD; | 2474 // Check that the function really is a function. |
| 2715 ParameterCount expected(function); | 2475 GenerateFunctionCheck(function, rbx, miss); |
| 2716 __ InvokeFunction(function, expected, arguments(), | |
| 2717 JUMP_FUNCTION, NullCallWrapper(), call_kind); | |
| 2718 } | |
| 2719 | 2476 |
| 2477 if (!function.is(rdi)) __ movq(rdi, function); |
| 2478 PatchGlobalProxy(object); |
| 2720 | 2479 |
| 2721 Handle<Code> CallStubCompiler::CompileCallConstant( | 2480 // Invoke the function. |
| 2722 Handle<Object> object, | 2481 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, |
| 2723 Handle<JSObject> holder, | 2482 NullCallWrapper(), call_kind()); |
| 2724 Handle<Name> name, | |
| 2725 CheckType check, | |
| 2726 Handle<JSFunction> function) { | |
| 2727 if (HasCustomCallGenerator(function)) { | |
| 2728 Handle<Code> code = CompileCustomCall(object, holder, | |
| 2729 Handle<PropertyCell>::null(), | |
| 2730 function, Handle<String>::cast(name), | |
| 2731 Code::FAST); | |
| 2732 // A null handle means bail out to the regular compiler code below. | |
| 2733 if (!code.is_null()) return code; | |
| 2734 } | |
| 2735 | |
| 2736 CompileHandlerFrontend(object, holder, name, check); | |
| 2737 CompileHandlerBackend(function); | |
| 2738 | |
| 2739 // Return the generated code. | |
| 2740 return GetCode(function); | |
| 2741 } | 2483 } |
| 2742 | 2484 |
| 2743 | 2485 |
| 2744 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, | 2486 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, |
| 2745 Handle<JSObject> holder, | 2487 Handle<JSObject> holder, |
| 2746 Handle<Name> name) { | 2488 Handle<Name> name) { |
| 2747 // ----------- S t a t e ------------- | |
| 2748 // rcx : function name | |
| 2749 // rsp[0] : return address | |
| 2750 // rsp[8] : argument argc | |
| 2751 // rsp[16] : argument argc - 1 | |
| 2752 // ... | |
| 2753 // rsp[argc * 8] : argument 1 | |
| 2754 // rsp[(argc + 1) * 8] : argument 0 = receiver | |
| 2755 // ----------------------------------- | |
| 2756 Label miss; | 2489 Label miss; |
| 2757 GenerateNameCheck(name, &miss); | 2490 GenerateNameCheck(name, &miss); |
| 2758 | 2491 |
| 2759 | |
| 2760 LookupResult lookup(isolate()); | 2492 LookupResult lookup(isolate()); |
| 2761 LookupPostInterceptor(holder, name, &lookup); | 2493 LookupPostInterceptor(holder, name, &lookup); |
| 2762 | 2494 |
| 2763 // Get the receiver from the stack. | 2495 // Get the receiver from the stack. |
| 2764 StackArgumentsAccessor args(rsp, arguments()); | 2496 StackArgumentsAccessor args(rsp, arguments()); |
| 2765 __ movq(rdx, args.GetReceiverOperand()); | 2497 __ movq(rdx, args.GetReceiverOperand()); |
| 2766 | 2498 |
| 2767 CallInterceptorCompiler compiler(this, arguments(), rcx, extra_state_); | 2499 CallInterceptorCompiler compiler(this, arguments(), rcx); |
| 2768 compiler.Compile(masm(), object, holder, name, &lookup, rdx, rbx, rdi, rax, | 2500 compiler.Compile(masm(), object, holder, name, &lookup, rdx, rbx, rdi, rax, |
| 2769 &miss); | 2501 &miss); |
| 2770 | 2502 |
| 2771 // Restore receiver. | 2503 // Restore receiver. |
| 2772 __ movq(rdx, args.GetReceiverOperand()); | 2504 __ movq(rdx, args.GetReceiverOperand()); |
| 2773 | 2505 |
| 2774 // Check that the function really is a function. | 2506 GenerateJumpFunction(object, rax, &miss); |
| 2775 __ JumpIfSmi(rax, &miss); | |
| 2776 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); | |
| 2777 __ j(not_equal, &miss); | |
| 2778 | 2507 |
| 2779 // Patch the receiver on the stack with the global proxy if | 2508 HandlerFrontendFooter(&miss); |
| 2780 // necessary. | |
| 2781 if (object->IsGlobalObject()) { | |
| 2782 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | |
| 2783 __ movq(args.GetReceiverOperand(), rdx); | |
| 2784 } | |
| 2785 | |
| 2786 // Invoke the function. | |
| 2787 __ movq(rdi, rax); | |
| 2788 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | |
| 2789 ? CALL_AS_FUNCTION | |
| 2790 : CALL_AS_METHOD; | |
| 2791 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, | |
| 2792 NullCallWrapper(), call_kind); | |
| 2793 | |
| 2794 // Handle load cache miss. | |
| 2795 __ bind(&miss); | |
| 2796 GenerateMissBranch(); | |
| 2797 | 2509 |
| 2798 // Return the generated code. | 2510 // Return the generated code. |
| 2799 return GetCode(Code::FAST, name); | 2511 return GetCode(Code::FAST, name); |
| 2800 } | 2512 } |
| 2801 | 2513 |
| 2802 | 2514 |
| 2803 Handle<Code> CallStubCompiler::CompileCallGlobal( | 2515 Handle<Code> CallStubCompiler::CompileCallGlobal( |
| 2804 Handle<JSObject> object, | 2516 Handle<JSObject> object, |
| 2805 Handle<GlobalObject> holder, | 2517 Handle<GlobalObject> holder, |
| 2806 Handle<PropertyCell> cell, | 2518 Handle<PropertyCell> cell, |
| 2807 Handle<JSFunction> function, | 2519 Handle<JSFunction> function, |
| 2808 Handle<Name> name) { | 2520 Handle<Name> name) { |
| 2809 // ----------- S t a t e ------------- | |
| 2810 // rcx : function name | |
| 2811 // rsp[0] : return address | |
| 2812 // rsp[8] : argument argc | |
| 2813 // rsp[16] : argument argc - 1 | |
| 2814 // ... | |
| 2815 // rsp[argc * 8] : argument 1 | |
| 2816 // rsp[(argc + 1) * 8] : argument 0 = receiver | |
| 2817 // ----------------------------------- | |
| 2818 | |
| 2819 if (HasCustomCallGenerator(function)) { | 2521 if (HasCustomCallGenerator(function)) { |
| 2820 Handle<Code> code = CompileCustomCall( | 2522 Handle<Code> code = CompileCustomCall( |
| 2821 object, holder, cell, function, Handle<String>::cast(name), | 2523 object, holder, cell, function, Handle<String>::cast(name), |
| 2822 Code::NORMAL); | 2524 Code::NORMAL); |
| 2823 // A null handle means bail out to the regular compiler code below. | 2525 // A null handle means bail out to the regular compiler code below. |
| 2824 if (!code.is_null()) return code; | 2526 if (!code.is_null()) return code; |
| 2825 } | 2527 } |
| 2826 | 2528 |
| 2827 Label miss; | 2529 Label miss; |
| 2828 GenerateNameCheck(name, &miss); | 2530 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 2829 | 2531 // Potentially loads a closure that matches the shared function info of the |
| 2830 StackArgumentsAccessor args(rsp, arguments()); | 2532 // function, rather than function. |
| 2831 GenerateGlobalReceiverCheck(object, holder, name, &miss); | |
| 2832 GenerateLoadFunctionFromCell(cell, function, &miss); | 2533 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2833 | |
| 2834 // Patch the receiver on the stack with the global proxy. | |
| 2835 if (object->IsGlobalObject()) { | |
| 2836 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | |
| 2837 __ movq(args.GetReceiverOperand(), rdx); | |
| 2838 } | |
| 2839 | |
| 2840 // Set up the context (function already in rdi). | |
| 2841 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); | |
| 2842 | |
| 2843 // Jump to the cached code (tail call). | |
| 2844 Counters* counters = isolate()->counters(); | 2534 Counters* counters = isolate()->counters(); |
| 2845 __ IncrementCounter(counters->call_global_inline(), 1); | 2535 __ IncrementCounter(counters->call_global_inline(), 1); |
| 2846 ParameterCount expected(function->shared()->formal_parameter_count()); | 2536 GenerateJumpFunction(object, rdi, function); |
| 2847 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2537 HandlerFrontendFooter(&miss); |
| 2848 ? CALL_AS_FUNCTION | |
| 2849 : CALL_AS_METHOD; | |
| 2850 // We call indirectly through the code field in the function to | |
| 2851 // allow recompilation to take effect without changing any of the | |
| 2852 // call sites. | |
| 2853 __ movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); | |
| 2854 __ InvokeCode(rdx, expected, arguments(), JUMP_FUNCTION, | |
| 2855 NullCallWrapper(), call_kind); | |
| 2856 | |
| 2857 // Handle call cache miss. | |
| 2858 __ bind(&miss); | |
| 2859 __ IncrementCounter(counters->call_global_inline_miss(), 1); | |
| 2860 GenerateMissBranch(); | |
| 2861 | 2538 |
| 2862 // Return the generated code. | 2539 // Return the generated code. |
| 2863 return GetCode(Code::NORMAL, name); | 2540 return GetCode(Code::NORMAL, name); |
| 2864 } | 2541 } |
| 2865 | 2542 |
| 2866 | 2543 |
| 2867 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2544 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
| 2868 Handle<JSObject> object, | 2545 Handle<JSObject> object, |
| 2869 Handle<JSObject> holder, | 2546 Handle<JSObject> holder, |
| 2870 Handle<Name> name, | 2547 Handle<Name> name, |
| 2871 Handle<ExecutableAccessorInfo> callback) { | 2548 Handle<ExecutableAccessorInfo> callback) { |
| 2872 HandlerFrontend(object, receiver(), holder, name); | 2549 HandlerFrontend(IC::CurrentTypeOf(object, isolate()), |
| 2550 receiver(), holder, name); |
| 2873 | 2551 |
| 2874 __ PopReturnAddressTo(scratch1()); | 2552 __ PopReturnAddressTo(scratch1()); |
| 2875 __ push(receiver()); | 2553 __ push(receiver()); |
| 2876 __ Push(callback); // callback info | 2554 __ Push(callback); // callback info |
| 2877 __ Push(name); | 2555 __ Push(name); |
| 2878 __ push(value()); | 2556 __ push(value()); |
| 2879 __ PushReturnAddressFrom(scratch1()); | 2557 __ PushReturnAddressFrom(scratch1()); |
| 2880 | 2558 |
| 2881 // Do tail-call to the runtime system. | 2559 // Do tail-call to the runtime system. |
| 2882 ExternalReference store_callback_property = | 2560 ExternalReference store_callback_property = |
| 2883 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); | 2561 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); |
| 2884 __ TailCallExternalReference(store_callback_property, 4, 1); | 2562 __ TailCallExternalReference(store_callback_property, 4, 1); |
| 2885 | 2563 |
| 2886 // Return the generated code. | 2564 // Return the generated code. |
| 2887 return GetCode(kind(), Code::FAST, name); | 2565 return GetCode(kind(), Code::FAST, name); |
| 2888 } | 2566 } |
| 2889 | 2567 |
| 2890 | 2568 |
| 2891 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2569 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
| 2892 Handle<JSObject> object, | 2570 Handle<JSObject> object, |
| 2893 Handle<JSObject> holder, | 2571 Handle<JSObject> holder, |
| 2894 Handle<Name> name, | 2572 Handle<Name> name, |
| 2895 const CallOptimization& call_optimization) { | 2573 const CallOptimization& call_optimization) { |
| 2896 HandlerFrontend(object, receiver(), holder, name); | 2574 HandlerFrontend(IC::CurrentTypeOf(object, isolate()), |
| 2575 receiver(), holder, name); |
| 2897 | 2576 |
| 2898 Register values[] = { value() }; | 2577 Register values[] = { value() }; |
| 2899 GenerateFastApiCall( | 2578 GenerateFastApiCall( |
| 2900 masm(), call_optimization, receiver(), scratch1(), | 2579 masm(), call_optimization, receiver(), scratch1(), |
| 2901 scratch2(), this->name(), 1, values); | 2580 scratch2(), this->name(), 1, values); |
| 2902 | 2581 |
| 2903 // Return the generated code. | 2582 // Return the generated code. |
| 2904 return GetCode(kind(), Code::FAST, name); | 2583 return GetCode(kind(), Code::FAST, name); |
| 2905 } | 2584 } |
| 2906 | 2585 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2952 #define __ ACCESS_MASM(masm()) | 2631 #define __ ACCESS_MASM(masm()) |
| 2953 | 2632 |
| 2954 | 2633 |
| 2955 Handle<Code> StoreStubCompiler::CompileStoreInterceptor( | 2634 Handle<Code> StoreStubCompiler::CompileStoreInterceptor( |
| 2956 Handle<JSObject> object, | 2635 Handle<JSObject> object, |
| 2957 Handle<Name> name) { | 2636 Handle<Name> name) { |
| 2958 __ PopReturnAddressTo(scratch1()); | 2637 __ PopReturnAddressTo(scratch1()); |
| 2959 __ push(receiver()); | 2638 __ push(receiver()); |
| 2960 __ push(this->name()); | 2639 __ push(this->name()); |
| 2961 __ push(value()); | 2640 __ push(value()); |
| 2962 __ Push(Smi::FromInt(strict_mode())); | |
| 2963 __ PushReturnAddressFrom(scratch1()); | 2641 __ PushReturnAddressFrom(scratch1()); |
| 2964 | 2642 |
| 2965 // Do tail-call to the runtime system. | 2643 // Do tail-call to the runtime system. |
| 2966 ExternalReference store_ic_property = | 2644 ExternalReference store_ic_property = |
| 2967 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); | 2645 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); |
| 2968 __ TailCallExternalReference(store_ic_property, 4, 1); | 2646 __ TailCallExternalReference(store_ic_property, 3, 1); |
| 2969 | 2647 |
| 2970 // Return the generated code. | 2648 // Return the generated code. |
| 2971 return GetCode(kind(), Code::FAST, name); | 2649 return GetCode(kind(), Code::FAST, name); |
| 2972 } | 2650 } |
| 2973 | 2651 |
| 2974 | 2652 |
| 2975 Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( | 2653 Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( |
| 2976 MapHandleList* receiver_maps, | 2654 MapHandleList* receiver_maps, |
| 2977 CodeHandleList* handler_stubs, | 2655 CodeHandleList* handler_stubs, |
| 2978 MapHandleList* transitioned_maps) { | 2656 MapHandleList* transitioned_maps) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 3000 __ bind(&miss); | 2678 __ bind(&miss); |
| 3001 | 2679 |
| 3002 TailCallBuiltin(masm(), MissBuiltin(kind())); | 2680 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 3003 | 2681 |
| 3004 // Return the generated code. | 2682 // Return the generated code. |
| 3005 return GetICCode( | 2683 return GetICCode( |
| 3006 kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); | 2684 kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); |
| 3007 } | 2685 } |
| 3008 | 2686 |
| 3009 | 2687 |
| 3010 Handle<Code> LoadStubCompiler::CompileLoadNonexistent( | 2688 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<Type> type, |
| 3011 Handle<Object> object, | 2689 Handle<JSObject> last, |
| 3012 Handle<JSObject> last, | 2690 Handle<Name> name) { |
| 3013 Handle<Name> name, | 2691 NonexistentHandlerFrontend(type, last, name); |
| 3014 Handle<JSGlobalObject> global) { | |
| 3015 NonexistentHandlerFrontend(object, last, name, global); | |
| 3016 | 2692 |
| 3017 // Return undefined if maps of the full prototype chain are still the | 2693 // Return undefined if maps of the full prototype chain are still the |
| 3018 // same and no global property with this name contains a value. | 2694 // same and no global property with this name contains a value. |
| 3019 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 2695 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); |
| 3020 __ ret(0); | 2696 __ ret(0); |
| 3021 | 2697 |
| 3022 // Return the generated code. | 2698 // Return the generated code. |
| 3023 return GetCode(kind(), Code::FAST, name); | 2699 return GetCode(kind(), Code::FAST, name); |
| 3024 } | 2700 } |
| 3025 | 2701 |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3101 } | 2777 } |
| 3102 __ ret(0); | 2778 __ ret(0); |
| 3103 } | 2779 } |
| 3104 | 2780 |
| 3105 | 2781 |
| 3106 #undef __ | 2782 #undef __ |
| 3107 #define __ ACCESS_MASM(masm()) | 2783 #define __ ACCESS_MASM(masm()) |
| 3108 | 2784 |
| 3109 | 2785 |
| 3110 Handle<Code> LoadStubCompiler::CompileLoadGlobal( | 2786 Handle<Code> LoadStubCompiler::CompileLoadGlobal( |
| 3111 Handle<Object> object, | 2787 Handle<Type> type, |
| 3112 Handle<GlobalObject> global, | 2788 Handle<GlobalObject> global, |
| 3113 Handle<PropertyCell> cell, | 2789 Handle<PropertyCell> cell, |
| 3114 Handle<Name> name, | 2790 Handle<Name> name, |
| 3115 bool is_dont_delete) { | 2791 bool is_dont_delete) { |
| 3116 Label miss; | 2792 Label miss; |
| 3117 // TODO(verwaest): Directly store to rax. Currently we cannot do this, since | 2793 // TODO(verwaest): Directly store to rax. Currently we cannot do this, since |
| 3118 // rax is used as receiver(), which we would otherwise clobber before a | 2794 // rax is used as receiver(), which we would otherwise clobber before a |
| 3119 // potential miss. | 2795 // potential miss. |
| 3120 HandlerFrontendHeader(object, receiver(), global, name, &miss); | 2796 HandlerFrontendHeader(type, receiver(), global, name, &miss); |
| 3121 | 2797 |
| 3122 // Get the value from the cell. | 2798 // Get the value from the cell. |
| 3123 __ Move(rbx, cell); | 2799 __ Move(rbx, cell); |
| 3124 __ movq(rbx, FieldOperand(rbx, PropertyCell::kValueOffset)); | 2800 __ movq(rbx, FieldOperand(rbx, PropertyCell::kValueOffset)); |
| 3125 | 2801 |
| 3126 // Check for deleted property if property can actually be deleted. | 2802 // Check for deleted property if property can actually be deleted. |
| 3127 if (!is_dont_delete) { | 2803 if (!is_dont_delete) { |
| 3128 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); | 2804 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); |
| 3129 __ j(equal, &miss); | 2805 __ j(equal, &miss); |
| 3130 } else if (FLAG_debug_code) { | 2806 } else if (FLAG_debug_code) { |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3234 // ----------------------------------- | 2910 // ----------------------------------- |
| 3235 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 2911 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
| 3236 } | 2912 } |
| 3237 | 2913 |
| 3238 | 2914 |
| 3239 #undef __ | 2915 #undef __ |
| 3240 | 2916 |
| 3241 } } // namespace v8::internal | 2917 } } // namespace v8::internal |
| 3242 | 2918 |
| 3243 #endif // V8_TARGET_ARCH_X64 | 2919 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |