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

Side by Side Diff: src/ia32/stub-cache-ia32.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/ia32/macro-assembler-ia32.cc ('k') | src/ic.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 387 matching lines...) Expand 10 before | Expand all | Expand 10 after
398 __ push(receiver); 398 __ push(receiver);
399 __ push(holder); 399 __ push(holder);
400 } 400 }
401 401
402 402
403 static void CompileCallLoadPropertyWithInterceptor( 403 static void CompileCallLoadPropertyWithInterceptor(
404 MacroAssembler* masm, 404 MacroAssembler* masm,
405 Register receiver, 405 Register receiver,
406 Register holder, 406 Register holder,
407 Register name, 407 Register name,
408 Handle<JSObject> holder_obj) { 408 Handle<JSObject> holder_obj,
409 IC::UtilityId id) {
409 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); 410 PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
410 __ CallExternalReference( 411 __ CallExternalReference(
411 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly), 412 ExternalReference(IC_Utility(id), masm->isolate()),
412 masm->isolate()),
413 StubCache::kInterceptorArgsLength); 413 StubCache::kInterceptorArgsLength);
414 } 414 }
415 415
416 416
417 // Number of pointers to be reserved on stack for fast API call. 417 // Number of pointers to be reserved on stack for fast API call.
418 static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength; 418 static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength;
419 419
420 420
421 // Reserves space for the extra arguments to API function in the 421 // Reserves space for the extra arguments to API function in the
422 // caller's frame. 422 // caller's frame.
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after
638 ApiParameterOperand(1), 638 ApiParameterOperand(1),
639 argc + kFastApiCallArguments + 1, 639 argc + kFastApiCallArguments + 1,
640 return_value_operand, 640 return_value_operand,
641 restore_context ? 641 restore_context ?
642 &context_restore_operand : NULL); 642 &context_restore_operand : NULL);
643 } 643 }
644 644
645 645
646 class CallInterceptorCompiler BASE_EMBEDDED { 646 class CallInterceptorCompiler BASE_EMBEDDED {
647 public: 647 public:
648 CallInterceptorCompiler(StubCompiler* stub_compiler, 648 CallInterceptorCompiler(CallStubCompiler* stub_compiler,
649 const ParameterCount& arguments, 649 const ParameterCount& arguments,
650 Register name, 650 Register name)
651 Code::ExtraICState extra_state)
652 : stub_compiler_(stub_compiler), 651 : stub_compiler_(stub_compiler),
653 arguments_(arguments), 652 arguments_(arguments),
654 name_(name), 653 name_(name) {}
655 extra_state_(extra_state) {}
656 654
657 void Compile(MacroAssembler* masm, 655 void Compile(MacroAssembler* masm,
658 Handle<JSObject> object, 656 Handle<JSObject> object,
659 Handle<JSObject> holder, 657 Handle<JSObject> holder,
660 Handle<Name> name, 658 Handle<Name> name,
661 LookupResult* lookup, 659 LookupResult* lookup,
662 Register receiver, 660 Register receiver,
663 Register scratch1, 661 Register scratch1,
664 Register scratch2, 662 Register scratch2,
665 Register scratch3, 663 Register scratch3,
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
716 if (can_do_fast_api_call) { 714 if (can_do_fast_api_call) {
717 __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1); 715 __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1);
718 ReserveSpaceForFastApiCall(masm, scratch1); 716 ReserveSpaceForFastApiCall(masm, scratch1);
719 } 717 }
720 718
721 // Check that the maps from receiver to interceptor's holder 719 // Check that the maps from receiver to interceptor's holder
722 // haven't changed and thus we can invoke interceptor. 720 // haven't changed and thus we can invoke interceptor.
723 Label miss_cleanup; 721 Label miss_cleanup;
724 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; 722 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label;
725 Register holder = 723 Register holder =
726 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, 724 stub_compiler_->CheckPrototypes(
727 scratch1, scratch2, scratch3, 725 IC::CurrentTypeOf(object, masm->isolate()), receiver,
728 name, depth1, miss); 726 interceptor_holder, scratch1, scratch2, scratch3,
727 name, depth1, miss);
729 728
730 // Invoke an interceptor and if it provides a value, 729 // Invoke an interceptor and if it provides a value,
731 // branch to |regular_invoke|. 730 // branch to |regular_invoke|.
732 Label regular_invoke; 731 Label regular_invoke;
733 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, 732 LoadWithInterceptor(masm, receiver, holder, interceptor_holder,
734 &regular_invoke); 733 &regular_invoke);
735 734
736 // Interceptor returned nothing for this property. Try to use cached 735 // Interceptor returned nothing for this property. Try to use cached
737 // constant function. 736 // constant function.
738 737
739 // Check that the maps from interceptor's holder to constant function's 738 // Check that the maps from interceptor's holder to constant function's
740 // holder haven't changed and thus we can use cached constant function. 739 // holder haven't changed and thus we can use cached constant function.
741 if (*interceptor_holder != lookup->holder()) { 740 if (*interceptor_holder != lookup->holder()) {
742 stub_compiler_->CheckPrototypes(interceptor_holder, receiver, 741 stub_compiler_->CheckPrototypes(
743 Handle<JSObject>(lookup->holder()), 742 IC::CurrentTypeOf(interceptor_holder, masm->isolate()), holder,
744 scratch1, scratch2, scratch3, 743 handle(lookup->holder()), scratch1, scratch2, scratch3,
745 name, depth2, miss); 744 name, depth2, miss);
746 } else { 745 } else {
747 // CheckPrototypes has a side effect of fetching a 'holder' 746 // CheckPrototypes has a side effect of fetching a 'holder'
748 // for API (object which is instanceof for the signature). It's 747 // for API (object which is instanceof for the signature). It's
749 // safe to omit it here, as if present, it should be fetched 748 // safe to omit it here, as if present, it should be fetched
750 // by the previous CheckPrototypes. 749 // by the previous CheckPrototypes.
751 ASSERT(depth2 == kInvalidProtoDepth); 750 ASSERT(depth2 == kInvalidProtoDepth);
752 } 751 }
753 752
754 // Invoke function. 753 // Invoke function.
755 if (can_do_fast_api_call) { 754 if (can_do_fast_api_call) {
756 GenerateFastApiCall(masm, optimization, arguments_.immediate()); 755 GenerateFastApiCall(masm, optimization, arguments_.immediate());
757 } else { 756 } else {
758 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 757 Handle<JSFunction> fun = optimization.constant_function();
759 ? CALL_AS_FUNCTION 758 stub_compiler_->GenerateJumpFunction(object, fun);
760 : CALL_AS_METHOD;
761 Handle<JSFunction> function = optimization.constant_function();
762 ParameterCount expected(function);
763 __ InvokeFunction(function, expected, arguments_,
764 JUMP_FUNCTION, NullCallWrapper(), call_kind);
765 } 759 }
766 760
767 // Deferred code for fast API call case---clean preallocated space. 761 // Deferred code for fast API call case---clean preallocated space.
768 if (can_do_fast_api_call) { 762 if (can_do_fast_api_call) {
769 __ bind(&miss_cleanup); 763 __ bind(&miss_cleanup);
770 FreeSpaceForFastApiCall(masm, scratch1); 764 FreeSpaceForFastApiCall(masm, scratch1);
771 __ jmp(miss_label); 765 __ jmp(miss_label);
772 } 766 }
773 767
774 // Invoke a regular function. 768 // Invoke a regular function.
775 __ bind(&regular_invoke); 769 __ bind(&regular_invoke);
776 if (can_do_fast_api_call) { 770 if (can_do_fast_api_call) {
777 FreeSpaceForFastApiCall(masm, scratch1); 771 FreeSpaceForFastApiCall(masm, scratch1);
778 } 772 }
779 } 773 }
780 774
781 void CompileRegular(MacroAssembler* masm, 775 void CompileRegular(MacroAssembler* masm,
782 Handle<JSObject> object, 776 Handle<JSObject> object,
783 Register receiver, 777 Register receiver,
784 Register scratch1, 778 Register scratch1,
785 Register scratch2, 779 Register scratch2,
786 Register scratch3, 780 Register scratch3,
787 Handle<Name> name, 781 Handle<Name> name,
788 Handle<JSObject> interceptor_holder, 782 Handle<JSObject> interceptor_holder,
789 Label* miss_label) { 783 Label* miss_label) {
790 Register holder = 784 Register holder =
791 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, 785 stub_compiler_->CheckPrototypes(
792 scratch1, scratch2, scratch3, 786 IC::CurrentTypeOf(object, masm->isolate()), receiver,
793 name, miss_label); 787 interceptor_holder, scratch1, scratch2, scratch3, name, miss_label);
794 788
795 FrameScope scope(masm, StackFrame::INTERNAL); 789 FrameScope scope(masm, StackFrame::INTERNAL);
796 // Save the name_ register across the call. 790 // Save the name_ register across the call.
797 __ push(name_); 791 __ push(name_);
798 792
799 PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder); 793 CompileCallLoadPropertyWithInterceptor(
800 794 masm, receiver, holder, name_, interceptor_holder,
801 __ CallExternalReference( 795 IC::kLoadPropertyWithInterceptorForCall);
802 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall),
803 masm->isolate()),
804 StubCache::kInterceptorArgsLength);
805 796
806 // Restore the name_ register. 797 // Restore the name_ register.
807 __ pop(name_); 798 __ pop(name_);
808 799
809 // Leave the internal frame. 800 // Leave the internal frame.
810 } 801 }
811 802
812 void LoadWithInterceptor(MacroAssembler* masm, 803 void LoadWithInterceptor(MacroAssembler* masm,
813 Register receiver, 804 Register receiver,
814 Register holder, 805 Register holder,
815 Handle<JSObject> holder_obj, 806 Handle<JSObject> holder_obj,
816 Label* interceptor_succeeded) { 807 Label* interceptor_succeeded) {
817 { 808 {
818 FrameScope scope(masm, StackFrame::INTERNAL); 809 FrameScope scope(masm, StackFrame::INTERNAL);
819 __ push(holder); // Save the holder. 810 __ push(receiver);
820 __ push(name_); // Save the name. 811 __ push(holder);
812 __ push(name_);
821 813
822 CompileCallLoadPropertyWithInterceptor(masm, 814 CompileCallLoadPropertyWithInterceptor(
823 receiver, 815 masm, receiver, holder, name_, holder_obj,
824 holder, 816 IC::kLoadPropertyWithInterceptorOnly);
825 name_,
826 holder_obj);
827 817
828 __ pop(name_); // Restore the name. 818 __ pop(name_);
829 __ pop(receiver); // Restore the holder. 819 __ pop(holder);
820 __ pop(receiver);
830 // Leave the internal frame. 821 // Leave the internal frame.
831 } 822 }
832 823
833 __ cmp(eax, masm->isolate()->factory()->no_interceptor_result_sentinel()); 824 __ cmp(eax, masm->isolate()->factory()->no_interceptor_result_sentinel());
834 __ j(not_equal, interceptor_succeeded); 825 __ j(not_equal, interceptor_succeeded);
835 } 826 }
836 827
837 StubCompiler* stub_compiler_; 828 CallStubCompiler* stub_compiler_;
838 const ParameterCount& arguments_; 829 const ParameterCount& arguments_;
839 Register name_; 830 Register name_;
840 Code::ExtraICState extra_state_;
841 }; 831 };
842 832
843 833
844 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, 834 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm,
845 Label* label, 835 Label* label,
846 Handle<Name> name) { 836 Handle<Name> name) {
847 if (!label->is_unused()) { 837 if (!label->is_unused()) {
848 __ bind(label); 838 __ bind(label);
849 __ mov(this->name(), Immediate(name)); 839 __ mov(this->name(), Immediate(name));
850 } 840 }
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after
1177 smi_check); 1167 smi_check);
1178 } 1168 }
1179 } 1169 }
1180 1170
1181 // Return the value (register eax). 1171 // Return the value (register eax).
1182 ASSERT(value_reg.is(eax)); 1172 ASSERT(value_reg.is(eax));
1183 __ ret(0); 1173 __ ret(0);
1184 } 1174 }
1185 1175
1186 1176
1187 void StubCompiler::GenerateCheckPropertyCells(MacroAssembler* masm,
1188 Handle<JSObject> object,
1189 Handle<JSObject> holder,
1190 Handle<Name> name,
1191 Register scratch,
1192 Label* miss) {
1193 Handle<JSObject> current = object;
1194 while (!current.is_identical_to(holder)) {
1195 if (current->IsJSGlobalObject()) {
1196 GenerateCheckPropertyCell(masm,
1197 Handle<JSGlobalObject>::cast(current),
1198 name,
1199 scratch,
1200 miss);
1201 }
1202 current = Handle<JSObject>(JSObject::cast(current->GetPrototype()));
1203 }
1204 }
1205
1206
1207 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { 1177 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) {
1208 __ jmp(code, RelocInfo::CODE_TARGET); 1178 __ jmp(code, RelocInfo::CODE_TARGET);
1209 } 1179 }
1210 1180
1211 1181
1212 #undef __ 1182 #undef __
1213 #define __ ACCESS_MASM(masm()) 1183 #define __ ACCESS_MASM(masm())
1214 1184
1215 1185
1216 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, 1186 Register StubCompiler::CheckPrototypes(Handle<Type> type,
1217 Register object_reg, 1187 Register object_reg,
1218 Handle<JSObject> holder, 1188 Handle<JSObject> holder,
1219 Register holder_reg, 1189 Register holder_reg,
1220 Register scratch1, 1190 Register scratch1,
1221 Register scratch2, 1191 Register scratch2,
1222 Handle<Name> name, 1192 Handle<Name> name,
1223 int save_at_depth, 1193 int save_at_depth,
1224 Label* miss, 1194 Label* miss,
1225 PrototypeCheckType check) { 1195 PrototypeCheckType check) {
1226 const int kHolderIndex = FunctionCallbackArguments::kHolderIndex + 1; 1196 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate()));
1227 // Make sure that the type feedback oracle harvests the receiver map. 1197 // Make sure that the type feedback oracle harvests the receiver map.
1228 // TODO(svenpanne) Remove this hack when all ICs are reworked. 1198 // TODO(svenpanne) Remove this hack when all ICs are reworked.
1229 __ mov(scratch1, Handle<Map>(object->map())); 1199 __ mov(scratch1, receiver_map);
1230 1200
1231 Handle<JSObject> first = object;
1232 // Make sure there's no overlap between holder and object registers. 1201 // Make sure there's no overlap between holder and object registers.
1233 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); 1202 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
1234 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) 1203 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg)
1235 && !scratch2.is(scratch1)); 1204 && !scratch2.is(scratch1));
1236 1205
1237 // Keep track of the current object in register reg. 1206 // Keep track of the current object in register reg.
1238 Register reg = object_reg; 1207 Register reg = object_reg;
1239 Handle<JSObject> current = object;
1240 int depth = 0; 1208 int depth = 0;
1241 1209
1210 const int kHolderIndex = FunctionCallbackArguments::kHolderIndex + 1;
1242 if (save_at_depth == depth) { 1211 if (save_at_depth == depth) {
1243 __ mov(Operand(esp, kHolderIndex * kPointerSize), reg); 1212 __ mov(Operand(esp, kHolderIndex * kPointerSize), reg);
1244 } 1213 }
1245 1214
1215 Handle<JSObject> current = Handle<JSObject>::null();
1216 if (type->IsConstant()) current = Handle<JSObject>::cast(type->AsConstant());
1217 Handle<JSObject> prototype = Handle<JSObject>::null();
1218 Handle<Map> current_map = receiver_map;
1219 Handle<Map> holder_map(holder->map());
1246 // Traverse the prototype chain and check the maps in the prototype chain for 1220 // Traverse the prototype chain and check the maps in the prototype chain for
1247 // fast and global objects or do negative lookup for normal objects. 1221 // fast and global objects or do negative lookup for normal objects.
1248 while (!current.is_identical_to(holder)) { 1222 while (!current_map.is_identical_to(holder_map)) {
1249 ++depth; 1223 ++depth;
1250 1224
1251 // Only global objects and objects that do not require access 1225 // Only global objects and objects that do not require access
1252 // checks are allowed in stubs. 1226 // checks are allowed in stubs.
1253 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); 1227 ASSERT(current_map->IsJSGlobalProxyMap() ||
1228 !current_map->is_access_check_needed());
1254 1229
1255 Handle<JSObject> prototype(JSObject::cast(current->GetPrototype())); 1230 prototype = handle(JSObject::cast(current_map->prototype()));
1256 if (!current->HasFastProperties() && 1231 if (current_map->is_dictionary_map() &&
1257 !current->IsJSGlobalObject() && 1232 !current_map->IsJSGlobalObjectMap() &&
1258 !current->IsJSGlobalProxy()) { 1233 !current_map->IsJSGlobalProxyMap()) {
1259 if (!name->IsUniqueName()) { 1234 if (!name->IsUniqueName()) {
1260 ASSERT(name->IsString()); 1235 ASSERT(name->IsString());
1261 name = factory()->InternalizeString(Handle<String>::cast(name)); 1236 name = factory()->InternalizeString(Handle<String>::cast(name));
1262 } 1237 }
1263 ASSERT(current->property_dictionary()->FindEntry(*name) == 1238 ASSERT(current.is_null() ||
1239 current->property_dictionary()->FindEntry(*name) ==
1264 NameDictionary::kNotFound); 1240 NameDictionary::kNotFound);
1265 1241
1266 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, 1242 GenerateDictionaryNegativeLookup(masm(), miss, reg, name,
1267 scratch1, scratch2); 1243 scratch1, scratch2);
1268 1244
1269 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); 1245 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
1270 reg = holder_reg; // From now on the object will be in holder_reg. 1246 reg = holder_reg; // From now on the object will be in holder_reg.
1271 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); 1247 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
1272 } else { 1248 } else {
1273 bool in_new_space = heap()->InNewSpace(*prototype); 1249 bool in_new_space = heap()->InNewSpace(*prototype);
1274 Handle<Map> current_map(current->map()); 1250 if (depth != 1 || check == CHECK_ALL_MAPS) {
1275 if (!current.is_identical_to(first) || check == CHECK_ALL_MAPS) {
1276 __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK); 1251 __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK);
1277 } 1252 }
1278 1253
1279 // Check access rights to the global object. This has to happen after 1254 // Check access rights to the global object. This has to happen after
1280 // the map check so that we know that the object is actually a global 1255 // the map check so that we know that the object is actually a global
1281 // object. 1256 // object.
1282 if (current->IsJSGlobalProxy()) { 1257 if (current_map->IsJSGlobalProxyMap()) {
1283 __ CheckAccessGlobalProxy(reg, scratch1, scratch2, miss); 1258 __ CheckAccessGlobalProxy(reg, scratch1, scratch2, miss);
1259 } else if (current_map->IsJSGlobalObjectMap()) {
1260 GenerateCheckPropertyCell(
1261 masm(), Handle<JSGlobalObject>::cast(current), name,
1262 scratch2, miss);
1284 } 1263 }
1285 1264
1286 if (in_new_space) { 1265 if (in_new_space) {
1287 // Save the map in scratch1 for later. 1266 // Save the map in scratch1 for later.
1288 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); 1267 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
1289 } 1268 }
1290 1269
1291 reg = holder_reg; // From now on the object will be in holder_reg. 1270 reg = holder_reg; // From now on the object will be in holder_reg.
1292 1271
1293 if (in_new_space) { 1272 if (in_new_space) {
1294 // The prototype is in new space; we cannot store a reference to it 1273 // The prototype is in new space; we cannot store a reference to it
1295 // in the code. Load it from the map. 1274 // in the code. Load it from the map.
1296 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); 1275 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
1297 } else { 1276 } else {
1298 // The prototype is in old space; load it directly. 1277 // The prototype is in old space; load it directly.
1299 __ mov(reg, prototype); 1278 __ mov(reg, prototype);
1300 } 1279 }
1301 } 1280 }
1302 1281
1303 if (save_at_depth == depth) { 1282 if (save_at_depth == depth) {
1304 __ mov(Operand(esp, kHolderIndex * kPointerSize), reg); 1283 __ mov(Operand(esp, kHolderIndex * kPointerSize), reg);
1305 } 1284 }
1306 1285
1307 // Go to the next object in the prototype chain. 1286 // Go to the next object in the prototype chain.
1308 current = prototype; 1287 current = prototype;
1288 current_map = handle(current->map());
1309 } 1289 }
1310 ASSERT(current.is_identical_to(holder));
1311 1290
1312 // Log the check depth. 1291 // Log the check depth.
1313 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); 1292 LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
1314 1293
1315 if (!holder.is_identical_to(first) || check == CHECK_ALL_MAPS) { 1294 if (depth != 0 || check == CHECK_ALL_MAPS) {
1316 // Check the holder map. 1295 // Check the holder map.
1317 __ CheckMap(reg, Handle<Map>(holder->map()), miss, DONT_DO_SMI_CHECK); 1296 __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK);
1318 } 1297 }
1319 1298
1320 // Perform security check for access to the global object. 1299 // Perform security check for access to the global object.
1321 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); 1300 ASSERT(current_map->IsJSGlobalProxyMap() ||
1322 if (holder->IsJSGlobalProxy()) { 1301 !current_map->is_access_check_needed());
1302 if (current_map->IsJSGlobalProxyMap()) {
1323 __ CheckAccessGlobalProxy(reg, scratch1, scratch2, miss); 1303 __ CheckAccessGlobalProxy(reg, scratch1, scratch2, miss);
1324 } 1304 }
1325 1305
1326 // If we've skipped any global objects, it's not enough to verify that
1327 // their maps haven't changed. We also need to check that the property
1328 // cell for the property is still empty.
1329 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss);
1330
1331 // Return the register containing the holder. 1306 // Return the register containing the holder.
1332 return reg; 1307 return reg;
1333 } 1308 }
1334 1309
1335 1310
1336 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { 1311 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) {
1337 if (!miss->is_unused()) { 1312 if (!miss->is_unused()) {
1338 Label success; 1313 Label success;
1339 __ jmp(&success); 1314 __ jmp(&success);
1340 __ bind(miss); 1315 __ bind(miss);
1341 TailCallBuiltin(masm(), MissBuiltin(kind())); 1316 TailCallBuiltin(masm(), MissBuiltin(kind()));
1342 __ bind(&success); 1317 __ bind(&success);
1343 } 1318 }
1344 } 1319 }
1345 1320
1346 1321
1347 void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { 1322 void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) {
1348 if (!miss->is_unused()) { 1323 if (!miss->is_unused()) {
1349 Label success; 1324 Label success;
1350 __ jmp(&success); 1325 __ jmp(&success);
1351 GenerateRestoreName(masm(), miss, name); 1326 GenerateRestoreName(masm(), miss, name);
1352 TailCallBuiltin(masm(), MissBuiltin(kind())); 1327 TailCallBuiltin(masm(), MissBuiltin(kind()));
1353 __ bind(&success); 1328 __ bind(&success);
1354 } 1329 }
1355 } 1330 }
1356 1331
1357 1332
1358 Register LoadStubCompiler::CallbackHandlerFrontend( 1333 Register LoadStubCompiler::CallbackHandlerFrontend(
1359 Handle<Object> object, 1334 Handle<Type> type,
1360 Register object_reg, 1335 Register object_reg,
1361 Handle<JSObject> holder, 1336 Handle<JSObject> holder,
1362 Handle<Name> name, 1337 Handle<Name> name,
1363 Handle<Object> callback) { 1338 Handle<Object> callback) {
1364 Label miss; 1339 Label miss;
1365 1340
1366 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); 1341 Register reg = HandlerFrontendHeader(type, object_reg, holder, name, &miss);
1367 1342
1368 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { 1343 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) {
1369 ASSERT(!reg.is(scratch2())); 1344 ASSERT(!reg.is(scratch2()));
1370 ASSERT(!reg.is(scratch3())); 1345 ASSERT(!reg.is(scratch3()));
1371 Register dictionary = scratch1(); 1346 Register dictionary = scratch1();
1372 bool must_preserve_dictionary_reg = reg.is(dictionary); 1347 bool must_preserve_dictionary_reg = reg.is(dictionary);
1373 1348
1374 // Load the properties dictionary. 1349 // Load the properties dictionary.
1375 if (must_preserve_dictionary_reg) { 1350 if (must_preserve_dictionary_reg) {
1376 __ push(dictionary); 1351 __ push(dictionary);
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
1560 1535
1561 if (must_preserve_receiver_reg) { 1536 if (must_preserve_receiver_reg) {
1562 __ push(receiver()); 1537 __ push(receiver());
1563 } 1538 }
1564 __ push(holder_reg); 1539 __ push(holder_reg);
1565 __ push(this->name()); 1540 __ push(this->name());
1566 1541
1567 // Invoke an interceptor. Note: map checks from receiver to 1542 // Invoke an interceptor. Note: map checks from receiver to
1568 // interceptor's holder has been compiled before (see a caller 1543 // interceptor's holder has been compiled before (see a caller
1569 // of this method.) 1544 // of this method.)
1570 CompileCallLoadPropertyWithInterceptor(masm(), 1545 CompileCallLoadPropertyWithInterceptor(
1571 receiver(), 1546 masm(), receiver(), holder_reg, this->name(), interceptor_holder,
1572 holder_reg, 1547 IC::kLoadPropertyWithInterceptorOnly);
1573 this->name(),
1574 interceptor_holder);
1575 1548
1576 // Check if interceptor provided a value for property. If it's 1549 // Check if interceptor provided a value for property. If it's
1577 // the case, return immediately. 1550 // the case, return immediately.
1578 Label interceptor_failed; 1551 Label interceptor_failed;
1579 __ cmp(eax, factory()->no_interceptor_result_sentinel()); 1552 __ cmp(eax, factory()->no_interceptor_result_sentinel());
1580 __ j(equal, &interceptor_failed); 1553 __ j(equal, &interceptor_failed);
1581 frame_scope.GenerateLeaveFrame(); 1554 frame_scope.GenerateLeaveFrame();
1582 __ ret(0); 1555 __ ret(0);
1583 1556
1584 // Clobber registers when generating debug-code to provoke errors. 1557 // Clobber registers when generating debug-code to provoke errors.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1616 1589
1617 1590
1618 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { 1591 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) {
1619 if (kind_ == Code::KEYED_CALL_IC) { 1592 if (kind_ == Code::KEYED_CALL_IC) {
1620 __ cmp(ecx, Immediate(name)); 1593 __ cmp(ecx, Immediate(name));
1621 __ j(not_equal, miss); 1594 __ j(not_equal, miss);
1622 } 1595 }
1623 } 1596 }
1624 1597
1625 1598
1626 void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object, 1599 void CallStubCompiler::GenerateFunctionCheck(Register function,
1627 Handle<JSObject> holder, 1600 Register scratch,
1628 Handle<Name> name, 1601 Label* miss) {
1629 Label* miss) { 1602 __ JumpIfSmi(function, miss);
1630 ASSERT(holder->IsGlobalObject()); 1603 __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch);
1631 1604 __ j(not_equal, miss);
1632 // Get the number of arguments.
1633 const int argc = arguments().immediate();
1634
1635 // Get the receiver from the stack.
1636 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1637
1638
1639 // Check that the maps haven't changed.
1640 __ JumpIfSmi(edx, miss);
1641 CheckPrototypes(object, edx, holder, ebx, eax, edi, name, miss);
1642 } 1605 }
1643 1606
1644 1607
1645 void CallStubCompiler::GenerateLoadFunctionFromCell( 1608 void CallStubCompiler::GenerateLoadFunctionFromCell(
1646 Handle<Cell> cell, 1609 Handle<Cell> cell,
1647 Handle<JSFunction> function, 1610 Handle<JSFunction> function,
1648 Label* miss) { 1611 Label* miss) {
1649 // Get the value from the cell. 1612 // Get the value from the cell.
1650 if (Serializer::enabled()) { 1613 if (Serializer::enabled()) {
1651 __ mov(edi, Immediate(cell)); 1614 __ mov(edi, Immediate(cell));
1652 __ mov(edi, FieldOperand(edi, Cell::kValueOffset)); 1615 __ mov(edi, FieldOperand(edi, Cell::kValueOffset));
1653 } else { 1616 } else {
1654 __ mov(edi, Operand::ForCell(cell)); 1617 __ mov(edi, Operand::ForCell(cell));
1655 } 1618 }
1656 1619
1657 // Check that the cell contains the same function. 1620 // Check that the cell contains the same function.
1658 if (isolate()->heap()->InNewSpace(*function)) { 1621 if (isolate()->heap()->InNewSpace(*function)) {
1659 // We can't embed a pointer to a function in new space so we have 1622 // We can't embed a pointer to a function in new space so we have
1660 // to verify that the shared function info is unchanged. This has 1623 // to verify that the shared function info is unchanged. This has
1661 // the nice side effect that multiple closures based on the same 1624 // the nice side effect that multiple closures based on the same
1662 // function can all use this call IC. Before we load through the 1625 // function can all use this call IC. Before we load through the
1663 // function, we have to verify that it still is a function. 1626 // function, we have to verify that it still is a function.
1664 __ JumpIfSmi(edi, miss); 1627 GenerateFunctionCheck(edi, ebx, miss);
1665 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx);
1666 __ j(not_equal, miss);
1667 1628
1668 // Check the shared function info. Make sure it hasn't changed. 1629 // Check the shared function info. Make sure it hasn't changed.
1669 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), 1630 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset),
1670 Immediate(Handle<SharedFunctionInfo>(function->shared()))); 1631 Immediate(Handle<SharedFunctionInfo>(function->shared())));
1671 } else { 1632 } else {
1672 __ cmp(edi, Immediate(function)); 1633 __ cmp(edi, Immediate(function));
1673 } 1634 }
1674 __ j(not_equal, miss); 1635 __ j(not_equal, miss);
1675 } 1636 }
1676 1637
1677 1638
1678 void CallStubCompiler::GenerateMissBranch() { 1639 void CallStubCompiler::GenerateMissBranch() {
1679 Handle<Code> code = 1640 Handle<Code> code =
1680 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), 1641 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(),
1681 kind_, 1642 kind_,
1682 extra_state_); 1643 extra_state());
1683 __ jmp(code, RelocInfo::CODE_TARGET); 1644 __ jmp(code, RelocInfo::CODE_TARGET);
1684 } 1645 }
1685 1646
1686 1647
1687 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, 1648 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
1688 Handle<JSObject> holder, 1649 Handle<JSObject> holder,
1689 PropertyIndex index, 1650 PropertyIndex index,
1690 Handle<Name> name) { 1651 Handle<Name> name) {
1691 // ----------- S t a t e -------------
1692 // -- ecx : name
1693 // -- esp[0] : return address
1694 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
1695 // -- ...
1696 // -- esp[(argc + 1) * 4] : receiver
1697 // -----------------------------------
1698 Label miss; 1652 Label miss;
1699 1653
1700 GenerateNameCheck(name, &miss); 1654 Register reg = HandlerFrontendHeader(
1701 1655 object, holder, name, RECEIVER_MAP_CHECK, &miss);
1702 // Get the receiver from the stack.
1703 const int argc = arguments().immediate();
1704 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1705
1706 // Check that the receiver isn't a smi.
1707 __ JumpIfSmi(edx, &miss);
1708
1709 // Do the right check and compute the holder register.
1710 Register reg = CheckPrototypes(object, edx, holder, ebx, eax, edi,
1711 name, &miss);
1712 1656
1713 GenerateFastPropertyLoad( 1657 GenerateFastPropertyLoad(
1714 masm(), edi, reg, index.is_inobject(holder), 1658 masm(), edi, reg, index.is_inobject(holder),
1715 index.translate(holder), Representation::Tagged()); 1659 index.translate(holder), Representation::Tagged());
1660 GenerateJumpFunction(object, edi, &miss);
1716 1661
1717 // Check that the function really is a function. 1662 HandlerFrontendFooter(&miss);
1718 __ JumpIfSmi(edi, &miss);
1719 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx);
1720 __ j(not_equal, &miss);
1721
1722 // Patch the receiver on the stack with the global proxy if
1723 // necessary.
1724 if (object->IsGlobalObject()) {
1725 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
1726 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
1727 }
1728
1729 // Invoke the function.
1730 CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
1731 ? CALL_AS_FUNCTION
1732 : CALL_AS_METHOD;
1733 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION,
1734 NullCallWrapper(), call_kind);
1735
1736 // Handle call cache miss.
1737 __ bind(&miss);
1738 GenerateMissBranch();
1739 1663
1740 // Return the generated code. 1664 // Return the generated code.
1741 return GetCode(Code::FAST, name); 1665 return GetCode(Code::FAST, name);
1742 } 1666 }
1743 1667
1744 1668
1745 Handle<Code> CallStubCompiler::CompileArrayCodeCall( 1669 Handle<Code> CallStubCompiler::CompileArrayCodeCall(
1746 Handle<Object> object, 1670 Handle<Object> object,
1747 Handle<JSObject> holder, 1671 Handle<JSObject> holder,
1748 Handle<Cell> cell, 1672 Handle<Cell> cell,
1749 Handle<JSFunction> function, 1673 Handle<JSFunction> function,
1750 Handle<String> name, 1674 Handle<String> name,
1751 Code::StubType type) { 1675 Code::StubType type) {
1752 Label miss; 1676 Label miss;
1753 1677
1754 // Check that function is still array 1678 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
1755 const int argc = arguments().immediate(); 1679 if (!cell.is_null()) {
1756 GenerateNameCheck(name, &miss);
1757
1758 if (cell.is_null()) {
1759 // Get the receiver from the stack.
1760 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1761
1762 // Check that the receiver isn't a smi.
1763 __ JumpIfSmi(edx, &miss);
1764 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi,
1765 name, &miss);
1766 } else {
1767 ASSERT(cell->value() == *function); 1680 ASSERT(cell->value() == *function);
1768 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
1769 &miss);
1770 GenerateLoadFunctionFromCell(cell, function, &miss); 1681 GenerateLoadFunctionFromCell(cell, function, &miss);
1771 } 1682 }
1772 1683
1773 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite(); 1684 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite();
1774 site->SetElementsKind(GetInitialFastElementsKind()); 1685 site->SetElementsKind(GetInitialFastElementsKind());
1775 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site); 1686 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site);
1687 const int argc = arguments().immediate();
1776 __ mov(eax, Immediate(argc)); 1688 __ mov(eax, Immediate(argc));
1777 __ mov(ebx, site_feedback_cell); 1689 __ mov(ebx, site_feedback_cell);
1778 __ mov(edi, function); 1690 __ mov(edi, function);
1779 1691
1780 ArrayConstructorStub stub(isolate()); 1692 ArrayConstructorStub stub(isolate());
1781 __ TailCallStub(&stub); 1693 __ TailCallStub(&stub);
1782 1694
1783 __ bind(&miss); 1695 HandlerFrontendFooter(&miss);
1784 GenerateMissBranch();
1785 1696
1786 // Return the generated code. 1697 // Return the generated code.
1787 return GetCode(type, name); 1698 return GetCode(type, name);
1788 } 1699 }
1789 1700
1790 1701
1791 Handle<Code> CallStubCompiler::CompileArrayPushCall( 1702 Handle<Code> CallStubCompiler::CompileArrayPushCall(
1792 Handle<Object> object, 1703 Handle<Object> object,
1793 Handle<JSObject> holder, 1704 Handle<JSObject> holder,
1794 Handle<Cell> cell, 1705 Handle<Cell> cell,
1795 Handle<JSFunction> function, 1706 Handle<JSFunction> function,
1796 Handle<String> name, 1707 Handle<String> name,
1797 Code::StubType type) { 1708 Code::StubType type) {
1798 // ----------- S t a t e ------------- 1709 // If object is not an array or is observed or sealed, bail out to regular
1799 // -- ecx : name 1710 // call.
1800 // -- esp[0] : return address
1801 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
1802 // -- ...
1803 // -- esp[(argc + 1) * 4] : receiver
1804 // -----------------------------------
1805
1806 // If object is not an array or is observed, bail out to regular call.
1807 if (!object->IsJSArray() || 1711 if (!object->IsJSArray() ||
1808 !cell.is_null() || 1712 !cell.is_null() ||
1809 Handle<JSArray>::cast(object)->map()->is_observed()) { 1713 Handle<JSArray>::cast(object)->map()->is_observed() ||
1714 !Handle<JSArray>::cast(object)->map()->is_extensible()) {
1810 return Handle<Code>::null(); 1715 return Handle<Code>::null();
1811 } 1716 }
1812 1717
1813 Label miss; 1718 Label miss;
1814 1719
1815 GenerateNameCheck(name, &miss); 1720 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
1816 1721
1817 // Get the receiver from the stack.
1818 const int argc = arguments().immediate(); 1722 const int argc = arguments().immediate();
1819 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1820
1821 // Check that the receiver isn't a smi.
1822 __ JumpIfSmi(edx, &miss);
1823
1824 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi,
1825 name, &miss);
1826
1827 if (argc == 0) { 1723 if (argc == 0) {
1828 // Noop, return the length. 1724 // Noop, return the length.
1829 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); 1725 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset));
1830 __ ret((argc + 1) * kPointerSize); 1726 __ ret((argc + 1) * kPointerSize);
1831 } else { 1727 } else {
1832 Label call_builtin; 1728 Label call_builtin;
1833 1729
1834 if (argc == 1) { // Otherwise fall through to call builtin. 1730 if (argc == 1) { // Otherwise fall through to call builtin.
1835 Label attempt_to_grow_elements, with_write_barrier, check_double; 1731 Label attempt_to_grow_elements, with_write_barrier, check_double;
1836 1732
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
2034 __ ret((argc + 1) * kPointerSize); 1930 __ ret((argc + 1) * kPointerSize);
2035 } 1931 }
2036 1932
2037 __ bind(&call_builtin); 1933 __ bind(&call_builtin);
2038 __ TailCallExternalReference( 1934 __ TailCallExternalReference(
2039 ExternalReference(Builtins::c_ArrayPush, isolate()), 1935 ExternalReference(Builtins::c_ArrayPush, isolate()),
2040 argc + 1, 1936 argc + 1,
2041 1); 1937 1);
2042 } 1938 }
2043 1939
2044 __ bind(&miss); 1940 HandlerFrontendFooter(&miss);
2045 GenerateMissBranch();
2046 1941
2047 // Return the generated code. 1942 // Return the generated code.
2048 return GetCode(type, name); 1943 return GetCode(type, name);
2049 } 1944 }
2050 1945
2051 1946
2052 Handle<Code> CallStubCompiler::CompileArrayPopCall( 1947 Handle<Code> CallStubCompiler::CompileArrayPopCall(
2053 Handle<Object> object, 1948 Handle<Object> object,
2054 Handle<JSObject> holder, 1949 Handle<JSObject> holder,
2055 Handle<Cell> cell, 1950 Handle<Cell> cell,
2056 Handle<JSFunction> function, 1951 Handle<JSFunction> function,
2057 Handle<String> name, 1952 Handle<String> name,
2058 Code::StubType type) { 1953 Code::StubType type) {
2059 // ----------- S t a t e ------------- 1954 // If object is not an array or is observed or sealed, bail out to regular
2060 // -- ecx : name 1955 // call.
2061 // -- esp[0] : return address
2062 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
2063 // -- ...
2064 // -- esp[(argc + 1) * 4] : receiver
2065 // -----------------------------------
2066
2067 // If object is not an array or is observed, bail out to regular call.
2068 if (!object->IsJSArray() || 1956 if (!object->IsJSArray() ||
2069 !cell.is_null() || 1957 !cell.is_null() ||
2070 Handle<JSArray>::cast(object)->map()->is_observed()) { 1958 Handle<JSArray>::cast(object)->map()->is_observed() ||
1959 !Handle<JSArray>::cast(object)->map()->is_extensible()) {
2071 return Handle<Code>::null(); 1960 return Handle<Code>::null();
2072 } 1961 }
2073 1962
2074 Label miss, return_undefined, call_builtin; 1963 Label miss, return_undefined, call_builtin;
2075 1964
2076 GenerateNameCheck(name, &miss); 1965 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
2077
2078 // Get the receiver from the stack.
2079 const int argc = arguments().immediate();
2080 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
2081
2082 // Check that the receiver isn't a smi.
2083 __ JumpIfSmi(edx, &miss);
2084 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi,
2085 name, &miss);
2086 1966
2087 // Get the elements array of the object. 1967 // Get the elements array of the object.
2088 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); 1968 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset));
2089 1969
2090 // Check that the elements are in fast mode and writable. 1970 // Check that the elements are in fast mode and writable.
2091 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), 1971 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
2092 Immediate(factory()->fixed_array_map())); 1972 Immediate(factory()->fixed_array_map()));
2093 __ j(not_equal, &call_builtin); 1973 __ j(not_equal, &call_builtin);
2094 1974
2095 // Get the array's length into ecx and calculate new length. 1975 // Get the array's length into ecx and calculate new length.
(...skipping 11 matching lines...) Expand all
2107 __ j(equal, &call_builtin); 1987 __ j(equal, &call_builtin);
2108 1988
2109 // Set the array's length. 1989 // Set the array's length.
2110 __ mov(FieldOperand(edx, JSArray::kLengthOffset), ecx); 1990 __ mov(FieldOperand(edx, JSArray::kLengthOffset), ecx);
2111 1991
2112 // Fill with the hole. 1992 // Fill with the hole.
2113 __ mov(FieldOperand(ebx, 1993 __ mov(FieldOperand(ebx,
2114 ecx, times_half_pointer_size, 1994 ecx, times_half_pointer_size,
2115 FixedArray::kHeaderSize), 1995 FixedArray::kHeaderSize),
2116 Immediate(factory()->the_hole_value())); 1996 Immediate(factory()->the_hole_value()));
1997 const int argc = arguments().immediate();
2117 __ ret((argc + 1) * kPointerSize); 1998 __ ret((argc + 1) * kPointerSize);
2118 1999
2119 __ bind(&return_undefined); 2000 __ bind(&return_undefined);
2120 __ mov(eax, Immediate(factory()->undefined_value())); 2001 __ mov(eax, Immediate(factory()->undefined_value()));
2121 __ ret((argc + 1) * kPointerSize); 2002 __ ret((argc + 1) * kPointerSize);
2122 2003
2123 __ bind(&call_builtin); 2004 __ bind(&call_builtin);
2124 __ TailCallExternalReference( 2005 __ TailCallExternalReference(
2125 ExternalReference(Builtins::c_ArrayPop, isolate()), 2006 ExternalReference(Builtins::c_ArrayPop, isolate()),
2126 argc + 1, 2007 argc + 1,
2127 1); 2008 1);
2128 2009
2129 __ bind(&miss); 2010 HandlerFrontendFooter(&miss);
2130 GenerateMissBranch();
2131 2011
2132 // Return the generated code. 2012 // Return the generated code.
2133 return GetCode(type, name); 2013 return GetCode(type, name);
2134 } 2014 }
2135 2015
2136 2016
2137 Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall( 2017 Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
2138 Handle<Object> object, 2018 Handle<Object> object,
2139 Handle<JSObject> holder, 2019 Handle<JSObject> holder,
2140 Handle<Cell> cell, 2020 Handle<Cell> cell,
2141 Handle<JSFunction> function, 2021 Handle<JSFunction> function,
2142 Handle<String> name, 2022 Handle<String> name,
2143 Code::StubType type) { 2023 Code::StubType type) {
2144 // ----------- S t a t e -------------
2145 // -- ecx : function name
2146 // -- esp[0] : return address
2147 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
2148 // -- ...
2149 // -- esp[(argc + 1) * 4] : receiver
2150 // -----------------------------------
2151
2152 // If object is not a string, bail out to regular call. 2024 // If object is not a string, bail out to regular call.
2153 if (!object->IsString() || !cell.is_null()) { 2025 if (!object->IsString() || !cell.is_null()) {
2154 return Handle<Code>::null(); 2026 return Handle<Code>::null();
2155 } 2027 }
2156 2028
2157 const int argc = arguments().immediate(); 2029 const int argc = arguments().immediate();
2158 2030
2159 Label miss; 2031 Label miss;
2160 Label name_miss; 2032 Label name_miss;
2161 Label index_out_of_range; 2033 Label index_out_of_range;
2162 Label* index_out_of_range_label = &index_out_of_range; 2034 Label* index_out_of_range_label = &index_out_of_range;
2163 2035
2164 if (kind_ == Code::CALL_IC && 2036 if (kind_ == Code::CALL_IC &&
2165 (CallICBase::StringStubState::decode(extra_state_) == 2037 (CallICBase::StringStubState::decode(extra_state()) ==
2166 DEFAULT_STRING_STUB)) { 2038 DEFAULT_STRING_STUB)) {
2167 index_out_of_range_label = &miss; 2039 index_out_of_range_label = &miss;
2168 } 2040 }
2169 2041
2170 GenerateNameCheck(name, &name_miss); 2042 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
2171
2172 // Check that the maps starting from the prototype haven't changed.
2173 GenerateDirectLoadGlobalFunctionPrototype(masm(),
2174 Context::STRING_FUNCTION_INDEX,
2175 eax,
2176 &miss);
2177 ASSERT(!object.is_identical_to(holder));
2178 CheckPrototypes(
2179 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))),
2180 eax, holder, ebx, edx, edi, name, &miss);
2181 2043
2182 Register receiver = ebx; 2044 Register receiver = ebx;
2183 Register index = edi; 2045 Register index = edi;
2184 Register result = eax; 2046 Register result = eax;
2185 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); 2047 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize));
2186 if (argc > 0) { 2048 if (argc > 0) {
2187 __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); 2049 __ mov(index, Operand(esp, (argc - 0) * kPointerSize));
2188 } else { 2050 } else {
2189 __ Set(index, Immediate(factory()->undefined_value())); 2051 __ Set(index, Immediate(factory()->undefined_value()));
2190 } 2052 }
(...skipping 13 matching lines...) Expand all
2204 2066
2205 if (index_out_of_range.is_linked()) { 2067 if (index_out_of_range.is_linked()) {
2206 __ bind(&index_out_of_range); 2068 __ bind(&index_out_of_range);
2207 __ Set(eax, Immediate(factory()->nan_value())); 2069 __ Set(eax, Immediate(factory()->nan_value()));
2208 __ ret((argc + 1) * kPointerSize); 2070 __ ret((argc + 1) * kPointerSize);
2209 } 2071 }
2210 2072
2211 __ bind(&miss); 2073 __ bind(&miss);
2212 // Restore function name in ecx. 2074 // Restore function name in ecx.
2213 __ Set(ecx, Immediate(name)); 2075 __ Set(ecx, Immediate(name));
2214 __ bind(&name_miss); 2076 HandlerFrontendFooter(&name_miss);
2215 GenerateMissBranch();
2216 2077
2217 // Return the generated code. 2078 // Return the generated code.
2218 return GetCode(type, name); 2079 return GetCode(type, name);
2219 } 2080 }
2220 2081
2221 2082
2222 Handle<Code> CallStubCompiler::CompileStringCharAtCall( 2083 Handle<Code> CallStubCompiler::CompileStringCharAtCall(
2223 Handle<Object> object, 2084 Handle<Object> object,
2224 Handle<JSObject> holder, 2085 Handle<JSObject> holder,
2225 Handle<Cell> cell, 2086 Handle<Cell> cell,
2226 Handle<JSFunction> function, 2087 Handle<JSFunction> function,
2227 Handle<String> name, 2088 Handle<String> name,
2228 Code::StubType type) { 2089 Code::StubType type) {
2229 // ----------- S t a t e -------------
2230 // -- ecx : function name
2231 // -- esp[0] : return address
2232 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
2233 // -- ...
2234 // -- esp[(argc + 1) * 4] : receiver
2235 // -----------------------------------
2236
2237 // If object is not a string, bail out to regular call. 2090 // If object is not a string, bail out to regular call.
2238 if (!object->IsString() || !cell.is_null()) { 2091 if (!object->IsString() || !cell.is_null()) {
2239 return Handle<Code>::null(); 2092 return Handle<Code>::null();
2240 } 2093 }
2241 2094
2242 const int argc = arguments().immediate(); 2095 const int argc = arguments().immediate();
2243 2096
2244 Label miss; 2097 Label miss;
2245 Label name_miss; 2098 Label name_miss;
2246 Label index_out_of_range; 2099 Label index_out_of_range;
2247 Label* index_out_of_range_label = &index_out_of_range; 2100 Label* index_out_of_range_label = &index_out_of_range;
2248 2101
2249 if (kind_ == Code::CALL_IC && 2102 if (kind_ == Code::CALL_IC &&
2250 (CallICBase::StringStubState::decode(extra_state_) == 2103 (CallICBase::StringStubState::decode(extra_state()) ==
2251 DEFAULT_STRING_STUB)) { 2104 DEFAULT_STRING_STUB)) {
2252 index_out_of_range_label = &miss; 2105 index_out_of_range_label = &miss;
2253 } 2106 }
2254 2107
2255 GenerateNameCheck(name, &name_miss); 2108 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
2256
2257 // Check that the maps starting from the prototype haven't changed.
2258 GenerateDirectLoadGlobalFunctionPrototype(masm(),
2259 Context::STRING_FUNCTION_INDEX,
2260 eax,
2261 &miss);
2262 ASSERT(!object.is_identical_to(holder));
2263 CheckPrototypes(
2264 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))),
2265 eax, holder, ebx, edx, edi, name, &miss);
2266 2109
2267 Register receiver = eax; 2110 Register receiver = eax;
2268 Register index = edi; 2111 Register index = edi;
2269 Register scratch = edx; 2112 Register scratch = edx;
2270 Register result = eax; 2113 Register result = eax;
2271 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); 2114 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize));
2272 if (argc > 0) { 2115 if (argc > 0) {
2273 __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); 2116 __ mov(index, Operand(esp, (argc - 0) * kPointerSize));
2274 } else { 2117 } else {
2275 __ Set(index, Immediate(factory()->undefined_value())); 2118 __ Set(index, Immediate(factory()->undefined_value()));
(...skipping 15 matching lines...) Expand all
2291 2134
2292 if (index_out_of_range.is_linked()) { 2135 if (index_out_of_range.is_linked()) {
2293 __ bind(&index_out_of_range); 2136 __ bind(&index_out_of_range);
2294 __ Set(eax, Immediate(factory()->empty_string())); 2137 __ Set(eax, Immediate(factory()->empty_string()));
2295 __ ret((argc + 1) * kPointerSize); 2138 __ ret((argc + 1) * kPointerSize);
2296 } 2139 }
2297 2140
2298 __ bind(&miss); 2141 __ bind(&miss);
2299 // Restore function name in ecx. 2142 // Restore function name in ecx.
2300 __ Set(ecx, Immediate(name)); 2143 __ Set(ecx, Immediate(name));
2301 __ bind(&name_miss); 2144 HandlerFrontendFooter(&name_miss);
2302 GenerateMissBranch();
2303 2145
2304 // Return the generated code. 2146 // Return the generated code.
2305 return GetCode(type, name); 2147 return GetCode(type, name);
2306 } 2148 }
2307 2149
2308 2150
2309 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( 2151 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
2310 Handle<Object> object, 2152 Handle<Object> object,
2311 Handle<JSObject> holder, 2153 Handle<JSObject> holder,
2312 Handle<Cell> cell, 2154 Handle<Cell> cell,
2313 Handle<JSFunction> function, 2155 Handle<JSFunction> function,
2314 Handle<String> name, 2156 Handle<String> name,
2315 Code::StubType type) { 2157 Code::StubType type) {
2316 // ----------- S t a t e -------------
2317 // -- ecx : function name
2318 // -- esp[0] : return address
2319 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
2320 // -- ...
2321 // -- esp[(argc + 1) * 4] : receiver
2322 // -----------------------------------
2323
2324 const int argc = arguments().immediate(); 2158 const int argc = arguments().immediate();
2325 2159
2326 // If the object is not a JSObject or we got an unexpected number of 2160 // If the object is not a JSObject or we got an unexpected number of
2327 // arguments, bail out to the regular call. 2161 // arguments, bail out to the regular call.
2328 if (!object->IsJSObject() || argc != 1) { 2162 if (!object->IsJSObject() || argc != 1) {
2329 return Handle<Code>::null(); 2163 return Handle<Code>::null();
2330 } 2164 }
2331 2165
2332 Label miss; 2166 Label miss;
2333 GenerateNameCheck(name, &miss);
2334 2167
2335 if (cell.is_null()) { 2168 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
2336 __ mov(edx, Operand(esp, 2 * kPointerSize)); 2169 if (!cell.is_null()) {
2337 STATIC_ASSERT(kSmiTag == 0);
2338 __ JumpIfSmi(edx, &miss);
2339 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi,
2340 name, &miss);
2341 } else {
2342 ASSERT(cell->value() == *function); 2170 ASSERT(cell->value() == *function);
2343 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
2344 &miss);
2345 GenerateLoadFunctionFromCell(cell, function, &miss); 2171 GenerateLoadFunctionFromCell(cell, function, &miss);
2346 } 2172 }
2347 2173
2348 // Load the char code argument. 2174 // Load the char code argument.
2349 Register code = ebx; 2175 Register code = ebx;
2350 __ mov(code, Operand(esp, 1 * kPointerSize)); 2176 __ mov(code, Operand(esp, 1 * kPointerSize));
2351 2177
2352 // Check the code is a smi. 2178 // Check the code is a smi.
2353 Label slow; 2179 Label slow;
2354 STATIC_ASSERT(kSmiTag == 0); 2180 STATIC_ASSERT(kSmiTag == 0);
2355 __ JumpIfNotSmi(code, &slow); 2181 __ JumpIfNotSmi(code, &slow);
2356 2182
2357 // Convert the smi code to uint16. 2183 // Convert the smi code to uint16.
2358 __ and_(code, Immediate(Smi::FromInt(0xffff))); 2184 __ and_(code, Immediate(Smi::FromInt(0xffff)));
2359 2185
2360 StringCharFromCodeGenerator generator(code, eax); 2186 StringCharFromCodeGenerator generator(code, eax);
2361 generator.GenerateFast(masm()); 2187 generator.GenerateFast(masm());
2362 __ ret(2 * kPointerSize); 2188 __ ret(2 * kPointerSize);
2363 2189
2364 StubRuntimeCallHelper call_helper; 2190 StubRuntimeCallHelper call_helper;
2365 generator.GenerateSlow(masm(), call_helper); 2191 generator.GenerateSlow(masm(), call_helper);
2366 2192
2367 // Tail call the full function. We do not have to patch the receiver
2368 // because the function makes no use of it.
2369 __ bind(&slow); 2193 __ bind(&slow);
2370 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 2194 // We do not have to patch the receiver because the function makes no use of
2371 ? CALL_AS_FUNCTION 2195 // it.
2372 : CALL_AS_METHOD; 2196 GenerateJumpFunctionIgnoreReceiver(function);
2373 ParameterCount expected(function);
2374 __ InvokeFunction(function, expected, arguments(),
2375 JUMP_FUNCTION, NullCallWrapper(), call_kind);
2376 2197
2377 __ bind(&miss); 2198 HandlerFrontendFooter(&miss);
2378 // ecx: function name.
2379 GenerateMissBranch();
2380 2199
2381 // Return the generated code. 2200 // Return the generated code.
2382 return GetCode(type, name); 2201 return GetCode(type, name);
2383 } 2202 }
2384 2203
2385 2204
2386 Handle<Code> CallStubCompiler::CompileMathFloorCall( 2205 Handle<Code> CallStubCompiler::CompileMathFloorCall(
2387 Handle<Object> object, 2206 Handle<Object> object,
2388 Handle<JSObject> holder, 2207 Handle<JSObject> holder,
2389 Handle<Cell> cell, 2208 Handle<Cell> cell,
2390 Handle<JSFunction> function, 2209 Handle<JSFunction> function,
2391 Handle<String> name, 2210 Handle<String> name,
2392 Code::StubType type) { 2211 Code::StubType type) {
2393 // ----------- S t a t e -------------
2394 // -- ecx : name
2395 // -- esp[0] : return address
2396 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
2397 // -- ...
2398 // -- esp[(argc + 1) * 4] : receiver
2399 // -----------------------------------
2400
2401 if (!CpuFeatures::IsSupported(SSE2)) { 2212 if (!CpuFeatures::IsSupported(SSE2)) {
2402 return Handle<Code>::null(); 2213 return Handle<Code>::null();
2403 } 2214 }
2404 2215
2405 CpuFeatureScope use_sse2(masm(), SSE2); 2216 CpuFeatureScope use_sse2(masm(), SSE2);
2406 2217
2407 const int argc = arguments().immediate(); 2218 const int argc = arguments().immediate();
2408 2219
2409 // If the object is not a JSObject or we got an unexpected number of 2220 // If the object is not a JSObject or we got an unexpected number of
2410 // arguments, bail out to the regular call. 2221 // arguments, bail out to the regular call.
2411 if (!object->IsJSObject() || argc != 1) { 2222 if (!object->IsJSObject() || argc != 1) {
2412 return Handle<Code>::null(); 2223 return Handle<Code>::null();
2413 } 2224 }
2414 2225
2415 Label miss; 2226 Label miss;
2416 GenerateNameCheck(name, &miss);
2417 2227
2418 if (cell.is_null()) { 2228 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
2419 __ mov(edx, Operand(esp, 2 * kPointerSize)); 2229 if (!cell.is_null()) {
2420
2421 STATIC_ASSERT(kSmiTag == 0);
2422 __ JumpIfSmi(edx, &miss);
2423
2424 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi,
2425 name, &miss);
2426 } else {
2427 ASSERT(cell->value() == *function); 2230 ASSERT(cell->value() == *function);
2428 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
2429 &miss);
2430 GenerateLoadFunctionFromCell(cell, function, &miss); 2231 GenerateLoadFunctionFromCell(cell, function, &miss);
2431 } 2232 }
2432 2233
2433 // Load the (only) argument into eax. 2234 // Load the (only) argument into eax.
2434 __ mov(eax, Operand(esp, 1 * kPointerSize)); 2235 __ mov(eax, Operand(esp, 1 * kPointerSize));
2435 2236
2436 // Check if the argument is a smi. 2237 // Check if the argument is a smi.
2437 Label smi; 2238 Label smi;
2438 STATIC_ASSERT(kSmiTag == 0); 2239 STATIC_ASSERT(kSmiTag == 0);
2439 __ JumpIfSmi(eax, &smi); 2240 __ JumpIfSmi(eax, &smi);
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
2492 // Return a new heap number. 2293 // Return a new heap number.
2493 __ AllocateHeapNumber(eax, ebx, edx, &slow); 2294 __ AllocateHeapNumber(eax, ebx, edx, &slow);
2494 __ movsd(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); 2295 __ movsd(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
2495 __ ret(2 * kPointerSize); 2296 __ ret(2 * kPointerSize);
2496 2297
2497 // Return the argument (when it's an already round heap number). 2298 // Return the argument (when it's an already round heap number).
2498 __ bind(&already_round); 2299 __ bind(&already_round);
2499 __ mov(eax, Operand(esp, 1 * kPointerSize)); 2300 __ mov(eax, Operand(esp, 1 * kPointerSize));
2500 __ ret(2 * kPointerSize); 2301 __ ret(2 * kPointerSize);
2501 2302
2502 // Tail call the full function. We do not have to patch the receiver
2503 // because the function makes no use of it.
2504 __ bind(&slow); 2303 __ bind(&slow);
2505 ParameterCount expected(function); 2304 // We do not have to patch the receiver because the function makes no use of
2506 __ InvokeFunction(function, expected, arguments(), 2305 // it.
2507 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); 2306 GenerateJumpFunctionIgnoreReceiver(function);
2508 2307
2509 __ bind(&miss); 2308 HandlerFrontendFooter(&miss);
2510 // ecx: function name.
2511 GenerateMissBranch();
2512 2309
2513 // Return the generated code. 2310 // Return the generated code.
2514 return GetCode(type, name); 2311 return GetCode(type, name);
2515 } 2312 }
2516 2313
2517 2314
2518 Handle<Code> CallStubCompiler::CompileMathAbsCall( 2315 Handle<Code> CallStubCompiler::CompileMathAbsCall(
2519 Handle<Object> object, 2316 Handle<Object> object,
2520 Handle<JSObject> holder, 2317 Handle<JSObject> holder,
2521 Handle<Cell> cell, 2318 Handle<Cell> cell,
2522 Handle<JSFunction> function, 2319 Handle<JSFunction> function,
2523 Handle<String> name, 2320 Handle<String> name,
2524 Code::StubType type) { 2321 Code::StubType type) {
2525 // ----------- S t a t e -------------
2526 // -- ecx : name
2527 // -- esp[0] : return address
2528 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
2529 // -- ...
2530 // -- esp[(argc + 1) * 4] : receiver
2531 // -----------------------------------
2532
2533 const int argc = arguments().immediate(); 2322 const int argc = arguments().immediate();
2534 2323
2535 // If the object is not a JSObject or we got an unexpected number of 2324 // If the object is not a JSObject or we got an unexpected number of
2536 // arguments, bail out to the regular call. 2325 // arguments, bail out to the regular call.
2537 if (!object->IsJSObject() || argc != 1) { 2326 if (!object->IsJSObject() || argc != 1) {
2538 return Handle<Code>::null(); 2327 return Handle<Code>::null();
2539 } 2328 }
2540 2329
2541 Label miss; 2330 Label miss;
2542 GenerateNameCheck(name, &miss);
2543 2331
2544 if (cell.is_null()) { 2332 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
2545 __ mov(edx, Operand(esp, 2 * kPointerSize)); 2333 if (!cell.is_null()) {
2546
2547 STATIC_ASSERT(kSmiTag == 0);
2548 __ JumpIfSmi(edx, &miss);
2549
2550 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi,
2551 name, &miss);
2552 } else {
2553 ASSERT(cell->value() == *function); 2334 ASSERT(cell->value() == *function);
2554 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
2555 &miss);
2556 GenerateLoadFunctionFromCell(cell, function, &miss); 2335 GenerateLoadFunctionFromCell(cell, function, &miss);
2557 } 2336 }
2558 2337
2559 // Load the (only) argument into eax. 2338 // Load the (only) argument into eax.
2560 __ mov(eax, Operand(esp, 1 * kPointerSize)); 2339 __ mov(eax, Operand(esp, 1 * kPointerSize));
2561 2340
2562 // Check if the argument is a smi. 2341 // Check if the argument is a smi.
2563 Label not_smi; 2342 Label not_smi;
2564 STATIC_ASSERT(kSmiTag == 0); 2343 STATIC_ASSERT(kSmiTag == 0);
2565 __ JumpIfNotSmi(eax, &not_smi); 2344 __ JumpIfNotSmi(eax, &not_smi);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
2601 // If the argument is negative, clear the sign, and return a new 2380 // If the argument is negative, clear the sign, and return a new
2602 // number. 2381 // number.
2603 __ bind(&negative_sign); 2382 __ bind(&negative_sign);
2604 __ and_(ebx, ~HeapNumber::kSignMask); 2383 __ and_(ebx, ~HeapNumber::kSignMask);
2605 __ mov(ecx, FieldOperand(eax, HeapNumber::kMantissaOffset)); 2384 __ mov(ecx, FieldOperand(eax, HeapNumber::kMantissaOffset));
2606 __ AllocateHeapNumber(eax, edi, edx, &slow); 2385 __ AllocateHeapNumber(eax, edi, edx, &slow);
2607 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ebx); 2386 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ebx);
2608 __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx); 2387 __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx);
2609 __ ret(2 * kPointerSize); 2388 __ ret(2 * kPointerSize);
2610 2389
2611 // Tail call the full function. We do not have to patch the receiver
2612 // because the function makes no use of it.
2613 __ bind(&slow); 2390 __ bind(&slow);
2614 ParameterCount expected(function); 2391 // We do not have to patch the receiver because the function makes no use of
2615 __ InvokeFunction(function, expected, arguments(), 2392 // it.
2616 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); 2393 GenerateJumpFunctionIgnoreReceiver(function);
2617 2394
2618 __ bind(&miss); 2395 HandlerFrontendFooter(&miss);
2619 // ecx: function name.
2620 GenerateMissBranch();
2621 2396
2622 // Return the generated code. 2397 // Return the generated code.
2623 return GetCode(type, name); 2398 return GetCode(type, name);
2624 } 2399 }
2625 2400
2626 2401
2627 Handle<Code> CallStubCompiler::CompileFastApiCall( 2402 Handle<Code> CallStubCompiler::CompileFastApiCall(
2628 const CallOptimization& optimization, 2403 const CallOptimization& optimization,
2629 Handle<Object> object, 2404 Handle<Object> object,
2630 Handle<JSObject> holder, 2405 Handle<JSObject> holder,
(...skipping 23 matching lines...) Expand all
2654 2429
2655 Counters* counters = isolate()->counters(); 2430 Counters* counters = isolate()->counters();
2656 __ IncrementCounter(counters->call_const(), 1); 2431 __ IncrementCounter(counters->call_const(), 1);
2657 __ IncrementCounter(counters->call_const_fast_api(), 1); 2432 __ IncrementCounter(counters->call_const_fast_api(), 1);
2658 2433
2659 // Allocate space for v8::Arguments implicit values. Must be initialized 2434 // Allocate space for v8::Arguments implicit values. Must be initialized
2660 // before calling any runtime function. 2435 // before calling any runtime function.
2661 __ sub(esp, Immediate(kFastApiCallArguments * kPointerSize)); 2436 __ sub(esp, Immediate(kFastApiCallArguments * kPointerSize));
2662 2437
2663 // Check that the maps haven't changed and find a Holder as a side effect. 2438 // Check that the maps haven't changed and find a Holder as a side effect.
2664 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, 2439 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder,
2665 name, depth, &miss); 2440 ebx, eax, edi, name, depth, &miss);
2666 2441
2667 // Move the return address on top of the stack. 2442 // Move the return address on top of the stack.
2668 __ mov(eax, Operand(esp, kFastApiCallArguments * kPointerSize)); 2443 __ mov(eax, Operand(esp, kFastApiCallArguments * kPointerSize));
2669 __ mov(Operand(esp, 0 * kPointerSize), eax); 2444 __ mov(Operand(esp, 0 * kPointerSize), eax);
2670 2445
2671 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains 2446 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains
2672 // duplicate of return address and will be overwritten. 2447 // duplicate of return address and will be overwritten.
2673 GenerateFastApiCall(masm(), optimization, argc); 2448 GenerateFastApiCall(masm(), optimization, argc);
2674 2449
2675 __ bind(&miss); 2450 __ bind(&miss);
2676 __ add(esp, Immediate(kFastApiCallArguments * kPointerSize)); 2451 __ add(esp, Immediate(kFastApiCallArguments * kPointerSize));
2677 2452
2678 __ bind(&miss_before_stack_reserved); 2453 HandlerFrontendFooter(&miss_before_stack_reserved);
2679 GenerateMissBranch();
2680 2454
2681 // Return the generated code. 2455 // Return the generated code.
2682 return GetCode(function); 2456 return GetCode(function);
2683 } 2457 }
2684 2458
2685 2459
2686 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { 2460 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
2687 Label success; 2461 Label success;
2688 // Check that the object is a boolean. 2462 // Check that the object is a boolean.
2689 __ cmp(object, factory()->true_value()); 2463 __ cmp(object, factory()->true_value());
2690 __ j(equal, &success); 2464 __ j(equal, &success);
2691 __ cmp(object, factory()->false_value()); 2465 __ cmp(object, factory()->false_value());
2692 __ j(not_equal, miss); 2466 __ j(not_equal, miss);
2693 __ bind(&success); 2467 __ bind(&success);
2694 } 2468 }
2695 2469
2696 2470
2697 void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object, 2471 void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) {
2698 Handle<JSObject> holder, 2472 if (object->IsGlobalObject()) {
2699 Handle<Name> name, 2473 const int argc = arguments().immediate();
2700 CheckType check) { 2474 const int receiver_offset = (argc + 1) * kPointerSize;
2701 // ----------- S t a t e ------------- 2475 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
2702 // -- ecx : name 2476 __ mov(Operand(esp, receiver_offset), edx);
2703 // -- esp[0] : return address 2477 }
2704 // -- esp[(argc - n) * 4] : arg[n] (zero-based) 2478 }
2705 // -- ...
2706 // -- esp[(argc + 1) * 4] : receiver
2707 // -----------------------------------
2708 Label miss;
2709 GenerateNameCheck(name, &miss);
2710 2479
2711 // Get the receiver from the stack. 2480
2481 Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object,
2482 Handle<JSObject> holder,
2483 Handle<Name> name,
2484 CheckType check,
2485 Label* miss) {
2486 GenerateNameCheck(name, miss);
2487
2488 Register reg = edx;
2489
2712 const int argc = arguments().immediate(); 2490 const int argc = arguments().immediate();
2713 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 2491 const int receiver_offset = (argc + 1) * kPointerSize;
2492 __ mov(reg, Operand(esp, receiver_offset));
2714 2493
2715 // Check that the receiver isn't a smi. 2494 // Check that the receiver isn't a smi.
2716 if (check != NUMBER_CHECK) { 2495 if (check != NUMBER_CHECK) {
2717 __ JumpIfSmi(edx, &miss); 2496 __ JumpIfSmi(reg, miss);
2718 } 2497 }
2719 2498
2720 // Make sure that it's okay not to patch the on stack receiver 2499 // Make sure that it's okay not to patch the on stack receiver
2721 // unless we're doing a receiver map check. 2500 // unless we're doing a receiver map check.
2722 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); 2501 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
2723 switch (check) { 2502 switch (check) {
2724 case RECEIVER_MAP_CHECK: 2503 case RECEIVER_MAP_CHECK:
2725 __ IncrementCounter(isolate()->counters()->call_const(), 1); 2504 __ IncrementCounter(isolate()->counters()->call_const(), 1);
2726 2505
2727 // Check that the maps haven't changed. 2506 // Check that the maps haven't changed.
2728 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, 2507 reg = CheckPrototypes(IC::CurrentTypeOf(object, isolate()), reg, holder,
2729 edi, name, &miss); 2508 ebx, eax, edi, name, miss);
2730 2509
2731 // Patch the receiver on the stack with the global proxy if
2732 // necessary.
2733 if (object->IsGlobalObject()) {
2734 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
2735 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
2736 }
2737 break; 2510 break;
2738 2511
2739 case STRING_CHECK: 2512 case STRING_CHECK: {
2740 // Check that the object is a string. 2513 // Check that the object is a string.
2741 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, eax); 2514 __ CmpObjectType(reg, FIRST_NONSTRING_TYPE, eax);
2742 __ j(above_equal, &miss); 2515 __ j(above_equal, miss);
2743 // Check that the maps starting from the prototype haven't changed. 2516 // Check that the maps starting from the prototype haven't changed.
2744 GenerateDirectLoadGlobalFunctionPrototype( 2517 GenerateDirectLoadGlobalFunctionPrototype(
2745 masm(), Context::STRING_FUNCTION_INDEX, eax, &miss); 2518 masm(), Context::STRING_FUNCTION_INDEX, eax, miss);
2746 CheckPrototypes(
2747 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))),
2748 eax, holder, ebx, edx, edi, name, &miss);
2749 break; 2519 break;
2750 2520 }
2751 case SYMBOL_CHECK: 2521 case SYMBOL_CHECK: {
2752 // Check that the object is a symbol. 2522 // Check that the object is a symbol.
2753 __ CmpObjectType(edx, SYMBOL_TYPE, eax); 2523 __ CmpObjectType(reg, SYMBOL_TYPE, eax);
2754 __ j(not_equal, &miss); 2524 __ j(not_equal, miss);
2755 // Check that the maps starting from the prototype haven't changed. 2525 // Check that the maps starting from the prototype haven't changed.
2756 GenerateDirectLoadGlobalFunctionPrototype( 2526 GenerateDirectLoadGlobalFunctionPrototype(
2757 masm(), Context::SYMBOL_FUNCTION_INDEX, eax, &miss); 2527 masm(), Context::SYMBOL_FUNCTION_INDEX, eax, miss);
2758 CheckPrototypes(
2759 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))),
2760 eax, holder, ebx, edx, edi, name, &miss);
2761 break; 2528 break;
2762 2529 }
2763 case NUMBER_CHECK: { 2530 case NUMBER_CHECK: {
2764 Label fast; 2531 Label fast;
2765 // Check that the object is a smi or a heap number. 2532 // Check that the object is a smi or a heap number.
2766 __ JumpIfSmi(edx, &fast); 2533 __ JumpIfSmi(reg, &fast);
2767 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax); 2534 __ CmpObjectType(reg, HEAP_NUMBER_TYPE, eax);
2768 __ j(not_equal, &miss); 2535 __ j(not_equal, miss);
2769 __ bind(&fast); 2536 __ bind(&fast);
2770 // Check that the maps starting from the prototype haven't changed. 2537 // Check that the maps starting from the prototype haven't changed.
2771 GenerateDirectLoadGlobalFunctionPrototype( 2538 GenerateDirectLoadGlobalFunctionPrototype(
2772 masm(), Context::NUMBER_FUNCTION_INDEX, eax, &miss); 2539 masm(), Context::NUMBER_FUNCTION_INDEX, eax, miss);
2773 CheckPrototypes(
2774 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))),
2775 eax, holder, ebx, edx, edi, name, &miss);
2776 break; 2540 break;
2777 } 2541 }
2778 case BOOLEAN_CHECK: { 2542 case BOOLEAN_CHECK: {
2779 GenerateBooleanCheck(edx, &miss); 2543 GenerateBooleanCheck(reg, miss);
2780 // Check that the maps starting from the prototype haven't changed. 2544 // Check that the maps starting from the prototype haven't changed.
2781 GenerateDirectLoadGlobalFunctionPrototype( 2545 GenerateDirectLoadGlobalFunctionPrototype(
2782 masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss); 2546 masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, miss);
2783 CheckPrototypes(
2784 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))),
2785 eax, holder, ebx, edx, edi, name, &miss);
2786 break; 2547 break;
2787 } 2548 }
2788 } 2549 }
2789 2550
2790 Label success; 2551 if (check != RECEIVER_MAP_CHECK) {
2791 __ jmp(&success); 2552 Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
2553 reg = CheckPrototypes(
2554 IC::CurrentTypeOf(prototype, isolate()),
2555 eax, holder, ebx, edx, edi, name, miss);
2556 }
2792 2557
2793 // Handle call cache miss. 2558 return reg;
2794 __ bind(&miss);
2795 GenerateMissBranch();
2796
2797 __ bind(&success);
2798 } 2559 }
2799 2560
2800 2561
2801 void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) { 2562 void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
2802 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 2563 Register function,
2803 ? CALL_AS_FUNCTION 2564 Label* miss) {
2804 : CALL_AS_METHOD; 2565 // Check that the function really is a function.
2805 ParameterCount expected(function); 2566 GenerateFunctionCheck(function, ebx, miss);
2806 __ InvokeFunction(function, expected, arguments(),
2807 JUMP_FUNCTION, NullCallWrapper(), call_kind);
2808 }
2809 2567
2568 if (!function.is(edi)) __ mov(edi, function);
2569 PatchGlobalProxy(object);
2810 2570
2811 Handle<Code> CallStubCompiler::CompileCallConstant( 2571 // Invoke the function.
2812 Handle<Object> object, 2572 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION,
2813 Handle<JSObject> holder, 2573 NullCallWrapper(), call_kind());
2814 Handle<Name> name,
2815 CheckType check,
2816 Handle<JSFunction> function) {
2817
2818 if (HasCustomCallGenerator(function)) {
2819 Handle<Code> code = CompileCustomCall(object, holder,
2820 Handle<Cell>::null(),
2821 function, Handle<String>::cast(name),
2822 Code::FAST);
2823 // A null handle means bail out to the regular compiler code below.
2824 if (!code.is_null()) return code;
2825 }
2826
2827 CompileHandlerFrontend(object, holder, name, check);
2828 CompileHandlerBackend(function);
2829
2830 // Return the generated code.
2831 return GetCode(function);
2832 } 2574 }
2833 2575
2834 2576
2835 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, 2577 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
2836 Handle<JSObject> holder, 2578 Handle<JSObject> holder,
2837 Handle<Name> name) { 2579 Handle<Name> name) {
2838 // ----------- S t a t e -------------
2839 // -- ecx : name
2840 // -- esp[0] : return address
2841 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
2842 // -- ...
2843 // -- esp[(argc + 1) * 4] : receiver
2844 // -----------------------------------
2845 Label miss; 2580 Label miss;
2846 2581
2847 GenerateNameCheck(name, &miss); 2582 GenerateNameCheck(name, &miss);
2848 2583
2849 // Get the number of arguments. 2584 // Get the number of arguments.
2850 const int argc = arguments().immediate(); 2585 const int argc = arguments().immediate();
2851 2586
2852 LookupResult lookup(isolate()); 2587 LookupResult lookup(isolate());
2853 LookupPostInterceptor(holder, name, &lookup); 2588 LookupPostInterceptor(holder, name, &lookup);
2854 2589
2855 // Get the receiver from the stack. 2590 // Get the receiver from the stack.
2856 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 2591 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
2857 2592
2858 CallInterceptorCompiler compiler(this, arguments(), ecx, extra_state_); 2593 CallInterceptorCompiler compiler(this, arguments(), ecx);
2859 compiler.Compile(masm(), object, holder, name, &lookup, edx, ebx, edi, eax, 2594 compiler.Compile(masm(), object, holder, name, &lookup, edx, ebx, edi, eax,
2860 &miss); 2595 &miss);
2861 2596
2862 // Restore receiver. 2597 // Restore receiver.
2863 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 2598 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
2864 2599
2865 // Check that the function really is a function. 2600 GenerateJumpFunction(object, eax, &miss);
2866 __ JumpIfSmi(eax, &miss);
2867 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
2868 __ j(not_equal, &miss);
2869 2601
2870 // Patch the receiver on the stack with the global proxy if 2602 HandlerFrontendFooter(&miss);
2871 // necessary.
2872 if (object->IsGlobalObject()) {
2873 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
2874 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
2875 }
2876
2877 // Invoke the function.
2878 __ mov(edi, eax);
2879 CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
2880 ? CALL_AS_FUNCTION
2881 : CALL_AS_METHOD;
2882 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION,
2883 NullCallWrapper(), call_kind);
2884
2885 // Handle load cache miss.
2886 __ bind(&miss);
2887 GenerateMissBranch();
2888 2603
2889 // Return the generated code. 2604 // Return the generated code.
2890 return GetCode(Code::FAST, name); 2605 return GetCode(Code::FAST, name);
2891 } 2606 }
2892 2607
2893 2608
2894 Handle<Code> CallStubCompiler::CompileCallGlobal( 2609 Handle<Code> CallStubCompiler::CompileCallGlobal(
2895 Handle<JSObject> object, 2610 Handle<JSObject> object,
2896 Handle<GlobalObject> holder, 2611 Handle<GlobalObject> holder,
2897 Handle<PropertyCell> cell, 2612 Handle<PropertyCell> cell,
2898 Handle<JSFunction> function, 2613 Handle<JSFunction> function,
2899 Handle<Name> name) { 2614 Handle<Name> name) {
2900 // ----------- S t a t e -------------
2901 // -- ecx : name
2902 // -- esp[0] : return address
2903 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
2904 // -- ...
2905 // -- esp[(argc + 1) * 4] : receiver
2906 // -----------------------------------
2907
2908 if (HasCustomCallGenerator(function)) { 2615 if (HasCustomCallGenerator(function)) {
2909 Handle<Code> code = CompileCustomCall( 2616 Handle<Code> code = CompileCustomCall(
2910 object, holder, cell, function, Handle<String>::cast(name), 2617 object, holder, cell, function, Handle<String>::cast(name),
2911 Code::NORMAL); 2618 Code::NORMAL);
2912 // A null handle means bail out to the regular compiler code below. 2619 // A null handle means bail out to the regular compiler code below.
2913 if (!code.is_null()) return code; 2620 if (!code.is_null()) return code;
2914 } 2621 }
2915 2622
2916 Label miss; 2623 Label miss;
2917 GenerateNameCheck(name, &miss); 2624 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
2625 // Potentially loads a closure that matches the shared function info of the
2626 // function, rather than function.
2627 GenerateLoadFunctionFromCell(cell, function, &miss);
2628 GenerateJumpFunction(object, edi, function);
2918 2629
2919 // Get the number of arguments. 2630 HandlerFrontendFooter(&miss);
2920 const int argc = arguments().immediate();
2921 GenerateGlobalReceiverCheck(object, holder, name, &miss);
2922 GenerateLoadFunctionFromCell(cell, function, &miss);
2923
2924 // Patch the receiver on the stack with the global proxy.
2925 if (object->IsGlobalObject()) {
2926 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
2927 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
2928 }
2929
2930 // Set up the context (function already in edi).
2931 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
2932
2933 // Jump to the cached code (tail call).
2934 Counters* counters = isolate()->counters();
2935 __ IncrementCounter(counters->call_global_inline(), 1);
2936 ParameterCount expected(function->shared()->formal_parameter_count());
2937 CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
2938 ? CALL_AS_FUNCTION
2939 : CALL_AS_METHOD;
2940 // We call indirectly through the code field in the function to
2941 // allow recompilation to take effect without changing any of the
2942 // call sites.
2943 __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset),
2944 expected, arguments(), JUMP_FUNCTION,
2945 NullCallWrapper(), call_kind);
2946
2947 // Handle call cache miss.
2948 __ bind(&miss);
2949 __ IncrementCounter(counters->call_global_inline_miss(), 1);
2950 GenerateMissBranch();
2951 2631
2952 // Return the generated code. 2632 // Return the generated code.
2953 return GetCode(Code::NORMAL, name); 2633 return GetCode(Code::NORMAL, name);
2954 } 2634 }
2955 2635
2956 2636
2957 Handle<Code> StoreStubCompiler::CompileStoreCallback( 2637 Handle<Code> StoreStubCompiler::CompileStoreCallback(
2958 Handle<JSObject> object, 2638 Handle<JSObject> object,
2959 Handle<JSObject> holder, 2639 Handle<JSObject> holder,
2960 Handle<Name> name, 2640 Handle<Name> name,
2961 Handle<ExecutableAccessorInfo> callback) { 2641 Handle<ExecutableAccessorInfo> callback) {
2962 HandlerFrontend(object, receiver(), holder, name); 2642 HandlerFrontend(IC::CurrentTypeOf(object, isolate()),
2643 receiver(), holder, name);
2963 2644
2964 __ pop(scratch1()); // remove the return address 2645 __ pop(scratch1()); // remove the return address
2965 __ push(receiver()); 2646 __ push(receiver());
2966 __ Push(callback); 2647 __ Push(callback);
2967 __ Push(name); 2648 __ Push(name);
2968 __ push(value()); 2649 __ push(value());
2969 __ push(scratch1()); // restore return address 2650 __ push(scratch1()); // restore return address
2970 2651
2971 // Do tail-call to the runtime system. 2652 // Do tail-call to the runtime system.
2972 ExternalReference store_callback_property = 2653 ExternalReference store_callback_property =
2973 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); 2654 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate());
2974 __ TailCallExternalReference(store_callback_property, 4, 1); 2655 __ TailCallExternalReference(store_callback_property, 4, 1);
2975 2656
2976 // Return the generated code. 2657 // Return the generated code.
2977 return GetCode(kind(), Code::FAST, name); 2658 return GetCode(kind(), Code::FAST, name);
2978 } 2659 }
2979 2660
2980 2661
2981 Handle<Code> StoreStubCompiler::CompileStoreCallback( 2662 Handle<Code> StoreStubCompiler::CompileStoreCallback(
2982 Handle<JSObject> object, 2663 Handle<JSObject> object,
2983 Handle<JSObject> holder, 2664 Handle<JSObject> holder,
2984 Handle<Name> name, 2665 Handle<Name> name,
2985 const CallOptimization& call_optimization) { 2666 const CallOptimization& call_optimization) {
2986 HandlerFrontend(object, receiver(), holder, name); 2667 HandlerFrontend(IC::CurrentTypeOf(object, isolate()),
2668 receiver(), holder, name);
2987 2669
2988 Register values[] = { value() }; 2670 Register values[] = { value() };
2989 GenerateFastApiCall( 2671 GenerateFastApiCall(
2990 masm(), call_optimization, receiver(), scratch1(), 2672 masm(), call_optimization, receiver(), scratch1(),
2991 scratch2(), this->name(), 1, values); 2673 scratch2(), this->name(), 1, values);
2992 2674
2993 // Return the generated code. 2675 // Return the generated code.
2994 return GetCode(kind(), Code::FAST, name); 2676 return GetCode(kind(), Code::FAST, name);
2995 } 2677 }
2996 2678
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
3042 #define __ ACCESS_MASM(masm()) 2724 #define __ ACCESS_MASM(masm())
3043 2725
3044 2726
3045 Handle<Code> StoreStubCompiler::CompileStoreInterceptor( 2727 Handle<Code> StoreStubCompiler::CompileStoreInterceptor(
3046 Handle<JSObject> object, 2728 Handle<JSObject> object,
3047 Handle<Name> name) { 2729 Handle<Name> name) {
3048 __ pop(scratch1()); // remove the return address 2730 __ pop(scratch1()); // remove the return address
3049 __ push(receiver()); 2731 __ push(receiver());
3050 __ push(this->name()); 2732 __ push(this->name());
3051 __ push(value()); 2733 __ push(value());
3052 __ push(Immediate(Smi::FromInt(strict_mode())));
3053 __ push(scratch1()); // restore return address 2734 __ push(scratch1()); // restore return address
3054 2735
3055 // Do tail-call to the runtime system. 2736 // Do tail-call to the runtime system.
3056 ExternalReference store_ic_property = 2737 ExternalReference store_ic_property =
3057 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); 2738 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate());
3058 __ TailCallExternalReference(store_ic_property, 4, 1); 2739 __ TailCallExternalReference(store_ic_property, 3, 1);
3059 2740
3060 // Return the generated code. 2741 // Return the generated code.
3061 return GetCode(kind(), Code::FAST, name); 2742 return GetCode(kind(), Code::FAST, name);
3062 } 2743 }
3063 2744
3064 2745
3065 Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( 2746 Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
3066 MapHandleList* receiver_maps, 2747 MapHandleList* receiver_maps,
3067 CodeHandleList* handler_stubs, 2748 CodeHandleList* handler_stubs,
3068 MapHandleList* transitioned_maps) { 2749 MapHandleList* transitioned_maps) {
(...skipping 14 matching lines...) Expand all
3083 } 2764 }
3084 __ bind(&miss); 2765 __ bind(&miss);
3085 TailCallBuiltin(masm(), MissBuiltin(kind())); 2766 TailCallBuiltin(masm(), MissBuiltin(kind()));
3086 2767
3087 // Return the generated code. 2768 // Return the generated code.
3088 return GetICCode( 2769 return GetICCode(
3089 kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); 2770 kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC);
3090 } 2771 }
3091 2772
3092 2773
3093 Handle<Code> LoadStubCompiler::CompileLoadNonexistent( 2774 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<Type> type,
3094 Handle<Object> object, 2775 Handle<JSObject> last,
3095 Handle<JSObject> last, 2776 Handle<Name> name) {
3096 Handle<Name> name, 2777 NonexistentHandlerFrontend(type, last, name);
3097 Handle<JSGlobalObject> global) {
3098 NonexistentHandlerFrontend(object, last, name, global);
3099 2778
3100 // Return undefined if maps of the full prototype chain are still the 2779 // Return undefined if maps of the full prototype chain are still the
3101 // same and no global property with this name contains a value. 2780 // same and no global property with this name contains a value.
3102 __ mov(eax, isolate()->factory()->undefined_value()); 2781 __ mov(eax, isolate()->factory()->undefined_value());
3103 __ ret(0); 2782 __ ret(0);
3104 2783
3105 // Return the generated code. 2784 // Return the generated code.
3106 return GetCode(kind(), Code::FAST, name); 2785 return GetCode(kind(), Code::FAST, name);
3107 } 2786 }
3108 2787
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
3179 } 2858 }
3180 __ ret(0); 2859 __ ret(0);
3181 } 2860 }
3182 2861
3183 2862
3184 #undef __ 2863 #undef __
3185 #define __ ACCESS_MASM(masm()) 2864 #define __ ACCESS_MASM(masm())
3186 2865
3187 2866
3188 Handle<Code> LoadStubCompiler::CompileLoadGlobal( 2867 Handle<Code> LoadStubCompiler::CompileLoadGlobal(
3189 Handle<Object> object, 2868 Handle<Type> type,
3190 Handle<GlobalObject> global, 2869 Handle<GlobalObject> global,
3191 Handle<PropertyCell> cell, 2870 Handle<PropertyCell> cell,
3192 Handle<Name> name, 2871 Handle<Name> name,
3193 bool is_dont_delete) { 2872 bool is_dont_delete) {
3194 Label miss; 2873 Label miss;
3195 2874
3196 HandlerFrontendHeader(object, receiver(), global, name, &miss); 2875 HandlerFrontendHeader(type, receiver(), global, name, &miss);
3197 // Get the value from the cell. 2876 // Get the value from the cell.
3198 if (Serializer::enabled()) { 2877 if (Serializer::enabled()) {
3199 __ mov(eax, Immediate(cell)); 2878 __ mov(eax, Immediate(cell));
3200 __ mov(eax, FieldOperand(eax, PropertyCell::kValueOffset)); 2879 __ mov(eax, FieldOperand(eax, PropertyCell::kValueOffset));
3201 } else { 2880 } else {
3202 __ mov(eax, Operand::ForCell(cell)); 2881 __ mov(eax, Operand::ForCell(cell));
3203 } 2882 }
3204 2883
3205 // Check for deleted property if property can actually be deleted. 2884 // Check for deleted property if property can actually be deleted.
3206 if (!is_dont_delete) { 2885 if (!is_dont_delete) {
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
3314 // ----------------------------------- 2993 // -----------------------------------
3315 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); 2994 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss);
3316 } 2995 }
3317 2996
3318 2997
3319 #undef __ 2998 #undef __
3320 2999
3321 } } // namespace v8::internal 3000 } } // namespace v8::internal
3322 3001
3323 #endif // V8_TARGET_ARCH_IA32 3002 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/macro-assembler-ia32.cc ('k') | src/ic.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698