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

Side by Side Diff: src/x64/stub-cache-x64.cc

Issue 112863002: Merge bleeding_edge 18021:18297 (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/x64/macro-assembler-x64.cc ('k') | test/cctest/cctest.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 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
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
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
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 &regular_invoke); 725 &regular_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(&regular_invoke); 761 __ bind(&regular_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
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
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
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
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
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
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
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, &not_smi); 2257 __ JumpIfNotSmi(rax, &not_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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/x64/macro-assembler-x64.cc ('k') | test/cctest/cctest.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698