OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
288 __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); | 288 __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); |
289 } | 289 } |
290 | 290 |
291 | 291 |
292 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( | 292 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( |
293 MacroAssembler* masm, | 293 MacroAssembler* masm, |
294 int index, | 294 int index, |
295 Register prototype, | 295 Register prototype, |
296 Label* miss) { | 296 Label* miss) { |
297 Isolate* isolate = masm->isolate(); | 297 Isolate* isolate = masm->isolate(); |
298 // Check we're still in the same context. | |
299 __ ldr(prototype, | |
300 MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | |
301 __ Move(ip, isolate->global_object()); | |
302 __ cmp(prototype, ip); | |
303 __ b(ne, miss); | |
304 // Get the global function with the given index. | 298 // Get the global function with the given index. |
305 Handle<JSFunction> function( | 299 Handle<JSFunction> function( |
306 JSFunction::cast(isolate->native_context()->get(index))); | 300 JSFunction::cast(isolate->native_context()->get(index))); |
| 301 |
| 302 // Check we're still in the same context. |
| 303 Register scratch = prototype; |
| 304 const int offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX); |
| 305 __ ldr(scratch, MemOperand(cp, offset)); |
| 306 __ ldr(scratch, FieldMemOperand(scratch, GlobalObject::kNativeContextOffset)); |
| 307 __ ldr(scratch, MemOperand(scratch, Context::SlotOffset(index))); |
| 308 __ Move(ip, function); |
| 309 __ cmp(ip, scratch); |
| 310 __ b(ne, miss); |
| 311 |
307 // Load its initial map. The global functions all have initial maps. | 312 // Load its initial map. The global functions all have initial maps. |
308 __ Move(prototype, Handle<Map>(function->initial_map())); | 313 __ Move(prototype, Handle<Map>(function->initial_map())); |
309 // Load the prototype from the initial map. | 314 // Load the prototype from the initial map. |
310 __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); | 315 __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); |
311 } | 316 } |
312 | 317 |
313 | 318 |
314 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, | 319 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, |
315 Register dst, | 320 Register dst, |
316 Register src, | 321 Register src, |
(...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
781 const CallOptimization& optimization, | 786 const CallOptimization& optimization, |
782 int argc, | 787 int argc, |
783 Register holder_in, | 788 Register holder_in, |
784 bool restore_context) { | 789 bool restore_context) { |
785 ASSERT(optimization.is_simple_api_call()); | 790 ASSERT(optimization.is_simple_api_call()); |
786 | 791 |
787 // Abi for CallApiFunctionStub. | 792 // Abi for CallApiFunctionStub. |
788 Register callee = r0; | 793 Register callee = r0; |
789 Register call_data = r4; | 794 Register call_data = r4; |
790 Register holder = r2; | 795 Register holder = r2; |
791 Register api_function_address = r3; | 796 Register api_function_address = r1; |
792 Register thunk_arg = r1; | |
793 | 797 |
794 // Put holder in place. | 798 // Put holder in place. |
795 __ Move(holder, holder_in); | 799 __ Move(holder, holder_in); |
796 | 800 |
797 Isolate* isolate = masm->isolate(); | 801 Isolate* isolate = masm->isolate(); |
798 Handle<JSFunction> function = optimization.constant_function(); | 802 Handle<JSFunction> function = optimization.constant_function(); |
799 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); | 803 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); |
800 Handle<Object> call_data_obj(api_call_info->data(), isolate); | 804 Handle<Object> call_data_obj(api_call_info->data(), isolate); |
801 | 805 |
802 // Put callee in place. | 806 // Put callee in place. |
(...skipping 12 matching lines...) Expand all Loading... |
815 } | 819 } |
816 | 820 |
817 // Put api_function_address in place. | 821 // Put api_function_address in place. |
818 Address function_address = v8::ToCData<Address>(api_call_info->callback()); | 822 Address function_address = v8::ToCData<Address>(api_call_info->callback()); |
819 ApiFunction fun(function_address); | 823 ApiFunction fun(function_address); |
820 ExternalReference::Type type = ExternalReference::DIRECT_API_CALL; | 824 ExternalReference::Type type = ExternalReference::DIRECT_API_CALL; |
821 ExternalReference ref = ExternalReference(&fun, | 825 ExternalReference ref = ExternalReference(&fun, |
822 type, | 826 type, |
823 masm->isolate()); | 827 masm->isolate()); |
824 __ mov(api_function_address, Operand(ref)); | 828 __ mov(api_function_address, Operand(ref)); |
825 __ mov(thunk_arg, Operand(reinterpret_cast<int32_t>(function_address))); | |
826 | 829 |
827 // Jump to stub. | 830 // Jump to stub. |
828 CallApiFunctionStub stub(restore_context, call_data_undefined, argc); | 831 CallApiFunctionStub stub(restore_context, call_data_undefined, argc); |
829 __ TailCallStub(&stub); | 832 __ TailCallStub(&stub); |
830 } | 833 } |
831 | 834 |
832 | 835 |
833 // Generates call to API function. | |
834 static void GenerateFastApiCall(MacroAssembler* masm, | |
835 const CallOptimization& optimization, | |
836 int argc, | |
837 Handle<Map> map_to_holder, | |
838 CallOptimization::HolderLookup holder_lookup) { | |
839 Counters* counters = masm->isolate()->counters(); | |
840 __ IncrementCounter(counters->call_const_fast_api(), 1, r0, r1); | |
841 | |
842 // Move holder to a register | |
843 Register holder_reg = r2; | |
844 switch (holder_lookup) { | |
845 case CallOptimization::kHolderIsReceiver: | |
846 { | |
847 ASSERT(map_to_holder.is_null()); | |
848 __ ldr(holder_reg, MemOperand(sp, argc * kPointerSize)); | |
849 } | |
850 break; | |
851 case CallOptimization::kHolderIsPrototypeOfMap: | |
852 { | |
853 Handle<JSObject> holder(JSObject::cast(map_to_holder->prototype())); | |
854 if (!masm->isolate()->heap()->InNewSpace(*holder)) { | |
855 __ Move(holder_reg, holder); | |
856 } else { | |
857 __ Move(holder_reg, map_to_holder); | |
858 __ ldr(holder_reg, | |
859 FieldMemOperand(holder_reg, Map::kPrototypeOffset)); | |
860 } | |
861 } | |
862 break; | |
863 case CallOptimization::kHolderNotFound: | |
864 UNREACHABLE(); | |
865 } | |
866 GenerateFastApiCallBody(masm, | |
867 optimization, | |
868 argc, | |
869 holder_reg, | |
870 false); | |
871 } | |
872 | |
873 | |
874 // Generate call to api function. | 836 // Generate call to api function. |
875 static void GenerateFastApiCall(MacroAssembler* masm, | 837 static void GenerateFastApiCall(MacroAssembler* masm, |
876 const CallOptimization& optimization, | 838 const CallOptimization& optimization, |
877 Register receiver, | 839 Register receiver, |
878 Register scratch, | 840 Register scratch, |
879 int argc, | 841 int argc, |
880 Register* values) { | 842 Register* values) { |
881 ASSERT(!receiver.is(scratch)); | 843 ASSERT(!receiver.is(scratch)); |
882 __ push(receiver); | 844 __ push(receiver); |
883 // Write the arguments to stack frame. | 845 // Write the arguments to stack frame. |
884 for (int i = 0; i < argc; i++) { | 846 for (int i = 0; i < argc; i++) { |
885 Register arg = values[argc-1-i]; | 847 Register arg = values[argc-1-i]; |
886 ASSERT(!receiver.is(arg)); | 848 ASSERT(!receiver.is(arg)); |
887 ASSERT(!scratch.is(arg)); | 849 ASSERT(!scratch.is(arg)); |
888 __ push(arg); | 850 __ push(arg); |
889 } | 851 } |
890 // Stack now matches JSFunction abi. | 852 // Stack now matches JSFunction abi. |
891 GenerateFastApiCallBody(masm, | 853 GenerateFastApiCallBody(masm, |
892 optimization, | 854 optimization, |
893 argc, | 855 argc, |
894 receiver, | 856 receiver, |
895 true); | 857 true); |
896 } | 858 } |
897 | 859 |
898 | 860 |
899 class CallInterceptorCompiler BASE_EMBEDDED { | |
900 public: | |
901 CallInterceptorCompiler(CallStubCompiler* stub_compiler, | |
902 const ParameterCount& arguments, | |
903 Register name) | |
904 : stub_compiler_(stub_compiler), | |
905 arguments_(arguments), | |
906 name_(name) {} | |
907 | |
908 void Compile(MacroAssembler* masm, | |
909 Handle<JSObject> object, | |
910 Handle<JSObject> holder, | |
911 Handle<Name> name, | |
912 LookupResult* lookup, | |
913 Register receiver, | |
914 Register scratch1, | |
915 Register scratch2, | |
916 Register scratch3, | |
917 Label* miss) { | |
918 ASSERT(holder->HasNamedInterceptor()); | |
919 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); | |
920 | |
921 // Check that the receiver isn't a smi. | |
922 __ JumpIfSmi(receiver, miss); | |
923 CallOptimization optimization(lookup); | |
924 if (optimization.is_constant_call()) { | |
925 CompileCacheable(masm, object, receiver, scratch1, scratch2, scratch3, | |
926 holder, lookup, name, optimization, miss); | |
927 } else { | |
928 CompileRegular(masm, object, receiver, scratch1, scratch2, scratch3, | |
929 name, holder, miss); | |
930 } | |
931 } | |
932 | |
933 private: | |
934 void CompileCacheable(MacroAssembler* masm, | |
935 Handle<JSObject> object, | |
936 Register receiver, | |
937 Register scratch1, | |
938 Register scratch2, | |
939 Register scratch3, | |
940 Handle<JSObject> interceptor_holder, | |
941 LookupResult* lookup, | |
942 Handle<Name> name, | |
943 const CallOptimization& optimization, | |
944 Label* miss_label) { | |
945 ASSERT(optimization.is_constant_call()); | |
946 ASSERT(!lookup->holder()->IsGlobalObject()); | |
947 Counters* counters = masm->isolate()->counters(); | |
948 __ IncrementCounter(counters->call_const_interceptor(), 1, | |
949 scratch1, scratch2); | |
950 | |
951 // Check that the maps from receiver to interceptor's holder | |
952 // haven't changed and thus we can invoke interceptor. | |
953 Label miss_cleanup; | |
954 Register holder = | |
955 stub_compiler_->CheckPrototypes( | |
956 IC::CurrentTypeOf(object, masm->isolate()), receiver, | |
957 interceptor_holder, scratch1, scratch2, scratch3, | |
958 name, miss_label); | |
959 | |
960 // Invoke an interceptor and if it provides a value, | |
961 // branch to |regular_invoke|. | |
962 Label regular_invoke; | |
963 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, scratch2, | |
964 ®ular_invoke); | |
965 | |
966 // Interceptor returned nothing for this property. Try to use cached | |
967 // constant function. | |
968 | |
969 // Check that the maps from interceptor's holder to constant function's | |
970 // holder haven't changed and thus we can use cached constant function. | |
971 if (*interceptor_holder != lookup->holder()) { | |
972 stub_compiler_->CheckPrototypes( | |
973 IC::CurrentTypeOf(interceptor_holder, masm->isolate()), holder, | |
974 handle(lookup->holder()), scratch1, scratch2, scratch3, | |
975 name, miss_label); | |
976 } | |
977 | |
978 Handle<Map> lookup_map; | |
979 CallOptimization::HolderLookup holder_lookup = | |
980 CallOptimization::kHolderNotFound; | |
981 if (optimization.is_simple_api_call() && | |
982 !lookup->holder()->IsGlobalObject()) { | |
983 lookup_map = optimization.LookupHolderOfExpectedType( | |
984 object, object, interceptor_holder, &holder_lookup); | |
985 if (holder_lookup == CallOptimization::kHolderNotFound) { | |
986 lookup_map = | |
987 optimization.LookupHolderOfExpectedType( | |
988 object, | |
989 interceptor_holder, | |
990 Handle<JSObject>(lookup->holder()), | |
991 &holder_lookup); | |
992 } | |
993 } | |
994 | |
995 // Invoke function. | |
996 if (holder_lookup != CallOptimization::kHolderNotFound) { | |
997 int argc = arguments_.immediate(); | |
998 GenerateFastApiCall(masm, | |
999 optimization, | |
1000 argc, | |
1001 lookup_map, | |
1002 holder_lookup); | |
1003 } else { | |
1004 Handle<JSFunction> function = optimization.constant_function(); | |
1005 __ Move(r0, receiver); | |
1006 stub_compiler_->GenerateJumpFunction(object, function); | |
1007 } | |
1008 | |
1009 // Invoke a regular function. | |
1010 __ bind(®ular_invoke); | |
1011 } | |
1012 | |
1013 void CompileRegular(MacroAssembler* masm, | |
1014 Handle<JSObject> object, | |
1015 Register receiver, | |
1016 Register scratch1, | |
1017 Register scratch2, | |
1018 Register scratch3, | |
1019 Handle<Name> name, | |
1020 Handle<JSObject> interceptor_holder, | |
1021 Label* miss_label) { | |
1022 Register holder = | |
1023 stub_compiler_->CheckPrototypes( | |
1024 IC::CurrentTypeOf(object, masm->isolate()), receiver, | |
1025 interceptor_holder, scratch1, scratch2, scratch3, name, miss_label); | |
1026 | |
1027 // Call a runtime function to load the interceptor property. | |
1028 FrameScope scope(masm, StackFrame::INTERNAL); | |
1029 // Save the name_ register across the call. | |
1030 __ push(name_); | |
1031 | |
1032 CompileCallLoadPropertyWithInterceptor( | |
1033 masm, receiver, holder, name_, interceptor_holder, | |
1034 IC::kLoadPropertyWithInterceptorForCall); | |
1035 | |
1036 // Restore the name_ register. | |
1037 __ pop(name_); | |
1038 // Leave the internal frame. | |
1039 } | |
1040 | |
1041 void LoadWithInterceptor(MacroAssembler* masm, | |
1042 Register receiver, | |
1043 Register holder, | |
1044 Handle<JSObject> holder_obj, | |
1045 Register scratch, | |
1046 Label* interceptor_succeeded) { | |
1047 { | |
1048 FrameScope scope(masm, StackFrame::INTERNAL); | |
1049 __ Push(receiver); | |
1050 __ Push(holder, name_); | |
1051 CompileCallLoadPropertyWithInterceptor( | |
1052 masm, receiver, holder, name_, holder_obj, | |
1053 IC::kLoadPropertyWithInterceptorOnly); | |
1054 __ pop(name_); | |
1055 __ pop(holder); | |
1056 __ pop(receiver); | |
1057 } | |
1058 // If interceptor returns no-result sentinel, call the constant function. | |
1059 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex); | |
1060 __ cmp(r0, scratch); | |
1061 __ b(ne, interceptor_succeeded); | |
1062 } | |
1063 | |
1064 CallStubCompiler* stub_compiler_; | |
1065 const ParameterCount& arguments_; | |
1066 Register name_; | |
1067 }; | |
1068 | |
1069 | |
1070 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { | 861 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { |
1071 __ Jump(code, RelocInfo::CODE_TARGET); | 862 __ Jump(code, RelocInfo::CODE_TARGET); |
1072 } | 863 } |
1073 | 864 |
1074 | 865 |
1075 #undef __ | 866 #undef __ |
1076 #define __ ACCESS_MASM(masm()) | 867 #define __ ACCESS_MASM(masm()) |
1077 | 868 |
1078 | 869 |
1079 Register StubCompiler::CheckPrototypes(Handle<HeapType> type, | 870 Register StubCompiler::CheckPrototypes(Handle<HeapType> type, |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1315 } | 1106 } |
1316 __ push(scratch3()); | 1107 __ push(scratch3()); |
1317 __ LoadRoot(scratch3(), Heap::kUndefinedValueRootIndex); | 1108 __ LoadRoot(scratch3(), Heap::kUndefinedValueRootIndex); |
1318 __ mov(scratch4(), scratch3()); | 1109 __ mov(scratch4(), scratch3()); |
1319 __ Push(scratch3(), scratch4()); | 1110 __ Push(scratch3(), scratch4()); |
1320 __ mov(scratch4(), | 1111 __ mov(scratch4(), |
1321 Operand(ExternalReference::isolate_address(isolate()))); | 1112 Operand(ExternalReference::isolate_address(isolate()))); |
1322 __ Push(scratch4(), reg); | 1113 __ Push(scratch4(), reg); |
1323 __ mov(scratch2(), sp); // scratch2 = PropertyAccessorInfo::args_ | 1114 __ mov(scratch2(), sp); // scratch2 = PropertyAccessorInfo::args_ |
1324 __ push(name()); | 1115 __ push(name()); |
1325 __ mov(r0, sp); // r0 = Handle<Name> | |
1326 | 1116 |
1327 const int kApiStackSpace = 1; | 1117 // Abi for CallApiGetter |
1328 FrameScope frame_scope(masm(), StackFrame::MANUAL); | 1118 Register getter_address_reg = r2; |
1329 __ EnterExitFrame(false, kApiStackSpace); | |
1330 | 1119 |
1331 // Create PropertyAccessorInfo instance on the stack above the exit frame with | |
1332 // scratch2 (internal::Object** args_) as the data. | |
1333 __ str(scratch2(), MemOperand(sp, 1 * kPointerSize)); | |
1334 __ add(r1, sp, Operand(1 * kPointerSize)); // r1 = AccessorInfo& | |
1335 | |
1336 const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1; | |
1337 Address getter_address = v8::ToCData<Address>(callback->getter()); | 1120 Address getter_address = v8::ToCData<Address>(callback->getter()); |
1338 | |
1339 ApiFunction fun(getter_address); | 1121 ApiFunction fun(getter_address); |
1340 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; | 1122 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; |
1341 ExternalReference ref = ExternalReference(&fun, type, isolate()); | 1123 ExternalReference ref = ExternalReference(&fun, type, isolate()); |
1342 Register getter_address_reg = r3; | |
1343 Register thunk_last_arg = r2; | |
1344 __ mov(getter_address_reg, Operand(ref)); | 1124 __ mov(getter_address_reg, Operand(ref)); |
1345 __ mov(thunk_last_arg, Operand(reinterpret_cast<int32_t>(getter_address))); | |
1346 | 1125 |
1347 Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback); | 1126 CallApiGetterStub stub; |
1348 ExternalReference::Type thunk_type = | 1127 __ TailCallStub(&stub); |
1349 ExternalReference::PROFILING_GETTER_CALL; | |
1350 ApiFunction thunk_fun(thunk_address); | |
1351 ExternalReference thunk_ref = ExternalReference(&thunk_fun, thunk_type, | |
1352 isolate()); | |
1353 __ CallApiFunctionAndReturn(getter_address_reg, | |
1354 thunk_ref, | |
1355 thunk_last_arg, | |
1356 kStackUnwindSpace, | |
1357 MemOperand(fp, 6 * kPointerSize), | |
1358 NULL); | |
1359 } | 1128 } |
1360 | 1129 |
1361 | 1130 |
1362 void LoadStubCompiler::GenerateLoadInterceptor( | 1131 void LoadStubCompiler::GenerateLoadInterceptor( |
1363 Register holder_reg, | 1132 Register holder_reg, |
1364 Handle<Object> object, | 1133 Handle<Object> object, |
1365 Handle<JSObject> interceptor_holder, | 1134 Handle<JSObject> interceptor_holder, |
1366 LookupResult* lookup, | 1135 LookupResult* lookup, |
1367 Handle<Name> name) { | 1136 Handle<Name> name) { |
1368 ASSERT(interceptor_holder->HasNamedInterceptor()); | 1137 ASSERT(interceptor_holder->HasNamedInterceptor()); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1440 this->name(), interceptor_holder); | 1209 this->name(), interceptor_holder); |
1441 | 1210 |
1442 ExternalReference ref = | 1211 ExternalReference ref = |
1443 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), | 1212 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), |
1444 isolate()); | 1213 isolate()); |
1445 __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1); | 1214 __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1); |
1446 } | 1215 } |
1447 } | 1216 } |
1448 | 1217 |
1449 | 1218 |
1450 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { | |
1451 if (kind_ == Code::KEYED_CALL_IC) { | |
1452 __ cmp(r2, Operand(name)); | |
1453 __ b(ne, miss); | |
1454 } | |
1455 } | |
1456 | |
1457 | |
1458 void CallStubCompiler::GenerateFunctionCheck(Register function, | |
1459 Register scratch, | |
1460 Label* miss) { | |
1461 __ JumpIfSmi(function, miss); | |
1462 __ CompareObjectType(function, scratch, scratch, JS_FUNCTION_TYPE); | |
1463 __ b(ne, miss); | |
1464 } | |
1465 | |
1466 | |
1467 void CallStubCompiler::GenerateLoadFunctionFromCell( | |
1468 Handle<Cell> cell, | |
1469 Handle<JSFunction> function, | |
1470 Label* miss) { | |
1471 // Get the value from the cell. | |
1472 __ mov(r3, Operand(cell)); | |
1473 __ ldr(r1, FieldMemOperand(r3, Cell::kValueOffset)); | |
1474 | |
1475 // Check that the cell contains the same function. | |
1476 if (heap()->InNewSpace(*function)) { | |
1477 // We can't embed a pointer to a function in new space so we have | |
1478 // to verify that the shared function info is unchanged. This has | |
1479 // the nice side effect that multiple closures based on the same | |
1480 // function can all use this call IC. Before we load through the | |
1481 // function, we have to verify that it still is a function. | |
1482 GenerateFunctionCheck(r1, r3, miss); | |
1483 | |
1484 // Check the shared function info. Make sure it hasn't changed. | |
1485 __ Move(r3, Handle<SharedFunctionInfo>(function->shared())); | |
1486 __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | |
1487 __ cmp(r4, r3); | |
1488 } else { | |
1489 __ cmp(r1, Operand(function)); | |
1490 } | |
1491 __ b(ne, miss); | |
1492 } | |
1493 | |
1494 | |
1495 void CallStubCompiler::GenerateMissBranch() { | |
1496 Handle<Code> code = | |
1497 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), | |
1498 kind_, | |
1499 extra_state()); | |
1500 __ Jump(code, RelocInfo::CODE_TARGET); | |
1501 } | |
1502 | |
1503 | |
1504 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, | |
1505 Handle<JSObject> holder, | |
1506 PropertyIndex index, | |
1507 Handle<Name> name) { | |
1508 Label miss; | |
1509 | |
1510 Register reg = HandlerFrontendHeader( | |
1511 object, holder, name, RECEIVER_MAP_CHECK, &miss); | |
1512 GenerateFastPropertyLoad(masm(), r1, reg, index.is_inobject(holder), | |
1513 index.translate(holder), Representation::Tagged()); | |
1514 GenerateJumpFunction(object, r1, &miss); | |
1515 | |
1516 HandlerFrontendFooter(&miss); | |
1517 | |
1518 // Return the generated code. | |
1519 return GetCode(Code::FAST, name); | |
1520 } | |
1521 | |
1522 | |
1523 Handle<Code> CallStubCompiler::CompileFastApiCall( | |
1524 const CallOptimization& optimization, | |
1525 Handle<Object> object, | |
1526 Handle<JSObject> holder, | |
1527 Handle<Cell> cell, | |
1528 Handle<JSFunction> function, | |
1529 Handle<String> name) { | |
1530 Counters* counters = isolate()->counters(); | |
1531 | |
1532 ASSERT(optimization.is_simple_api_call()); | |
1533 // Bail out if object is a global object as we don't want to | |
1534 // repatch it to global receiver. | |
1535 if (object->IsGlobalObject()) return Handle<Code>::null(); | |
1536 if (!cell.is_null()) return Handle<Code>::null(); | |
1537 if (!object->IsJSObject()) return Handle<Code>::null(); | |
1538 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | |
1539 CallOptimization::HolderLookup holder_lookup = | |
1540 CallOptimization::kHolderNotFound; | |
1541 Handle<Map> lookup_map = optimization.LookupHolderOfExpectedType( | |
1542 receiver, receiver, holder, &holder_lookup); | |
1543 if (holder_lookup == CallOptimization::kHolderNotFound) { | |
1544 return Handle<Code>::null(); | |
1545 } | |
1546 | |
1547 Label miss; | |
1548 GenerateNameCheck(name, &miss); | |
1549 | |
1550 // Get the receiver from the stack. | |
1551 const int argc = arguments().immediate(); | |
1552 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | |
1553 | |
1554 // Check that the receiver isn't a smi. | |
1555 __ JumpIfSmi(r1, &miss); | |
1556 | |
1557 __ IncrementCounter(counters->call_const(), 1, r0, r3); | |
1558 | |
1559 // Check that the maps haven't changed and find a Holder as a side effect. | |
1560 CheckPrototypes( | |
1561 IC::CurrentTypeOf(object, isolate()), | |
1562 r1, holder, r0, r3, r4, name, &miss); | |
1563 | |
1564 GenerateFastApiCall( | |
1565 masm(), optimization, argc, lookup_map, holder_lookup); | |
1566 | |
1567 HandlerFrontendFooter(&miss); | |
1568 | |
1569 // Return the generated code. | |
1570 return GetCode(function); | |
1571 } | |
1572 | |
1573 | |
1574 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { | 1219 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { |
1575 Label success; | 1220 Label success; |
1576 // Check that the object is a boolean. | 1221 // Check that the object is a boolean. |
1577 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 1222 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
1578 __ cmp(object, ip); | 1223 __ cmp(object, ip); |
1579 __ b(eq, &success); | 1224 __ b(eq, &success); |
1580 __ LoadRoot(ip, Heap::kFalseValueRootIndex); | 1225 __ LoadRoot(ip, Heap::kFalseValueRootIndex); |
1581 __ cmp(object, ip); | 1226 __ cmp(object, ip); |
1582 __ b(ne, miss); | 1227 __ b(ne, miss); |
1583 __ bind(&success); | 1228 __ bind(&success); |
1584 } | 1229 } |
1585 | 1230 |
1586 | 1231 |
1587 void CallStubCompiler::PatchImplicitReceiver(Handle<Object> object) { | |
1588 if (object->IsGlobalObject()) { | |
1589 const int argc = arguments().immediate(); | |
1590 const int receiver_offset = argc * kPointerSize; | |
1591 __ LoadRoot(r3, Heap::kUndefinedValueRootIndex); | |
1592 __ str(r3, MemOperand(sp, receiver_offset)); | |
1593 } | |
1594 } | |
1595 | |
1596 | |
1597 Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object, | |
1598 Handle<JSObject> holder, | |
1599 Handle<Name> name, | |
1600 CheckType check, | |
1601 Label* miss) { | |
1602 // ----------- S t a t e ------------- | |
1603 // -- r2 : name | |
1604 // -- lr : return address | |
1605 // ----------------------------------- | |
1606 GenerateNameCheck(name, miss); | |
1607 | |
1608 Register reg = r0; | |
1609 | |
1610 // Get the receiver from the stack | |
1611 const int argc = arguments().immediate(); | |
1612 const int receiver_offset = argc * kPointerSize; | |
1613 __ ldr(r0, MemOperand(sp, receiver_offset)); | |
1614 | |
1615 // Check that the receiver isn't a smi. | |
1616 if (check != NUMBER_CHECK) { | |
1617 __ JumpIfSmi(r0, miss); | |
1618 } | |
1619 | |
1620 // Make sure that it's okay not to patch the on stack receiver | |
1621 // unless we're doing a receiver map check. | |
1622 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | |
1623 switch (check) { | |
1624 case RECEIVER_MAP_CHECK: | |
1625 __ IncrementCounter(isolate()->counters()->call_const(), 1, r1, r3); | |
1626 | |
1627 // Check that the maps haven't changed. | |
1628 reg = CheckPrototypes( | |
1629 IC::CurrentTypeOf(object, isolate()), | |
1630 reg, holder, r1, r3, r4, name, miss); | |
1631 break; | |
1632 | |
1633 case STRING_CHECK: { | |
1634 // Check that the object is a string. | |
1635 __ CompareObjectType(reg, r3, r3, FIRST_NONSTRING_TYPE); | |
1636 __ b(ge, miss); | |
1637 // Check that the maps starting from the prototype haven't changed. | |
1638 GenerateDirectLoadGlobalFunctionPrototype( | |
1639 masm(), Context::STRING_FUNCTION_INDEX, r1, miss); | |
1640 break; | |
1641 } | |
1642 case SYMBOL_CHECK: { | |
1643 // Check that the object is a symbol. | |
1644 __ CompareObjectType(reg, r3, r3, SYMBOL_TYPE); | |
1645 __ b(ne, miss); | |
1646 // Check that the maps starting from the prototype haven't changed. | |
1647 GenerateDirectLoadGlobalFunctionPrototype( | |
1648 masm(), Context::SYMBOL_FUNCTION_INDEX, r1, miss); | |
1649 break; | |
1650 } | |
1651 case NUMBER_CHECK: { | |
1652 Label fast; | |
1653 // Check that the object is a smi or a heap number. | |
1654 __ JumpIfSmi(reg, &fast); | |
1655 __ CompareObjectType(reg, r3, r3, HEAP_NUMBER_TYPE); | |
1656 __ b(ne, miss); | |
1657 __ bind(&fast); | |
1658 // Check that the maps starting from the prototype haven't changed. | |
1659 GenerateDirectLoadGlobalFunctionPrototype( | |
1660 masm(), Context::NUMBER_FUNCTION_INDEX, r1, miss); | |
1661 break; | |
1662 } | |
1663 case BOOLEAN_CHECK: { | |
1664 GenerateBooleanCheck(reg, miss); | |
1665 | |
1666 // Check that the maps starting from the prototype haven't changed. | |
1667 GenerateDirectLoadGlobalFunctionPrototype( | |
1668 masm(), Context::BOOLEAN_FUNCTION_INDEX, r1, miss); | |
1669 break; | |
1670 } | |
1671 } | |
1672 | |
1673 if (check != RECEIVER_MAP_CHECK) { | |
1674 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | |
1675 reg = CheckPrototypes( | |
1676 IC::CurrentTypeOf(prototype, isolate()), | |
1677 r1, holder, r1, r3, r4, name, miss); | |
1678 } | |
1679 | |
1680 return reg; | |
1681 } | |
1682 | |
1683 | |
1684 void CallStubCompiler::GenerateJumpFunction(Handle<Object> object, | |
1685 Register function, | |
1686 Label* miss) { | |
1687 ASSERT(function.is(r1)); | |
1688 // Check that the function really is a function. | |
1689 GenerateFunctionCheck(function, r3, miss); | |
1690 PatchImplicitReceiver(object); | |
1691 | |
1692 // Invoke the function. | |
1693 __ InvokeFunction(r1, arguments(), JUMP_FUNCTION, NullCallWrapper()); | |
1694 } | |
1695 | |
1696 | |
1697 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, | |
1698 Handle<JSObject> holder, | |
1699 Handle<Name> name) { | |
1700 Label miss; | |
1701 GenerateNameCheck(name, &miss); | |
1702 | |
1703 // Get the number of arguments. | |
1704 const int argc = arguments().immediate(); | |
1705 LookupResult lookup(isolate()); | |
1706 LookupPostInterceptor(holder, name, &lookup); | |
1707 | |
1708 // Get the receiver from the stack. | |
1709 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | |
1710 | |
1711 CallInterceptorCompiler compiler(this, arguments(), r2); | |
1712 compiler.Compile(masm(), object, holder, name, &lookup, r1, r3, r4, r0, | |
1713 &miss); | |
1714 | |
1715 // Move returned value, the function to call, to r1. | |
1716 __ mov(r1, r0); | |
1717 // Restore receiver. | |
1718 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); | |
1719 | |
1720 GenerateJumpFunction(object, r1, &miss); | |
1721 | |
1722 HandlerFrontendFooter(&miss); | |
1723 | |
1724 // Return the generated code. | |
1725 return GetCode(Code::FAST, name); | |
1726 } | |
1727 | |
1728 | |
1729 Handle<Code> CallStubCompiler::CompileCallGlobal( | |
1730 Handle<JSObject> object, | |
1731 Handle<GlobalObject> holder, | |
1732 Handle<PropertyCell> cell, | |
1733 Handle<JSFunction> function, | |
1734 Handle<Name> name) { | |
1735 if (HasCustomCallGenerator(function)) { | |
1736 Handle<Code> code = CompileCustomCall( | |
1737 object, holder, cell, function, Handle<String>::cast(name), | |
1738 Code::NORMAL); | |
1739 // A null handle means bail out to the regular compiler code below. | |
1740 if (!code.is_null()) return code; | |
1741 } | |
1742 | |
1743 Label miss; | |
1744 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); | |
1745 // Potentially loads a closure that matches the shared function info of the | |
1746 // function, rather than function. | |
1747 GenerateLoadFunctionFromCell(cell, function, &miss); | |
1748 | |
1749 Counters* counters = isolate()->counters(); | |
1750 __ IncrementCounter(counters->call_global_inline(), 1, r3, r4); | |
1751 GenerateJumpFunction(object, r1, function); | |
1752 HandlerFrontendFooter(&miss); | |
1753 | |
1754 // Return the generated code. | |
1755 return GetCode(Code::NORMAL, name); | |
1756 } | |
1757 | |
1758 | |
1759 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 1232 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
1760 Handle<JSObject> object, | 1233 Handle<JSObject> object, |
1761 Handle<JSObject> holder, | 1234 Handle<JSObject> holder, |
1762 Handle<Name> name, | 1235 Handle<Name> name, |
1763 Handle<ExecutableAccessorInfo> callback) { | 1236 Handle<ExecutableAccessorInfo> callback) { |
1764 Register holder_reg = HandlerFrontend( | 1237 Register holder_reg = HandlerFrontend( |
1765 IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); | 1238 IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); |
1766 | 1239 |
1767 // Stub never generated for non-global objects that require access checks. | 1240 // Stub never generated for non-global objects that require access checks. |
1768 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | 1241 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1963 #define __ ACCESS_MASM(masm()) | 1436 #define __ ACCESS_MASM(masm()) |
1964 | 1437 |
1965 | 1438 |
1966 Handle<Code> LoadStubCompiler::CompileLoadGlobal( | 1439 Handle<Code> LoadStubCompiler::CompileLoadGlobal( |
1967 Handle<HeapType> type, | 1440 Handle<HeapType> type, |
1968 Handle<GlobalObject> global, | 1441 Handle<GlobalObject> global, |
1969 Handle<PropertyCell> cell, | 1442 Handle<PropertyCell> cell, |
1970 Handle<Name> name, | 1443 Handle<Name> name, |
1971 bool is_dont_delete) { | 1444 bool is_dont_delete) { |
1972 Label miss; | 1445 Label miss; |
1973 | |
1974 HandlerFrontendHeader(type, receiver(), global, name, &miss); | 1446 HandlerFrontendHeader(type, receiver(), global, name, &miss); |
1975 | 1447 |
1976 // Get the value from the cell. | 1448 // Get the value from the cell. |
1977 __ mov(r3, Operand(cell)); | 1449 __ mov(r3, Operand(cell)); |
1978 __ ldr(r4, FieldMemOperand(r3, Cell::kValueOffset)); | 1450 __ ldr(r4, FieldMemOperand(r3, Cell::kValueOffset)); |
1979 | 1451 |
1980 // Check for deleted property if property can actually be deleted. | 1452 // Check for deleted property if property can actually be deleted. |
1981 if (!is_dont_delete) { | 1453 if (!is_dont_delete) { |
1982 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 1454 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
1983 __ cmp(r4, ip); | 1455 __ cmp(r4, ip); |
1984 __ b(eq, &miss); | 1456 __ b(eq, &miss); |
1985 } | 1457 } |
1986 | 1458 |
1987 HandlerFrontendFooter(name, &miss); | |
1988 | |
1989 Counters* counters = isolate()->counters(); | 1459 Counters* counters = isolate()->counters(); |
1990 __ IncrementCounter(counters->named_load_global_stub(), 1, r1, r3); | 1460 __ IncrementCounter(counters->named_load_global_stub(), 1, r1, r3); |
1991 __ mov(r0, r4); | 1461 __ mov(r0, r4); |
1992 __ Ret(); | 1462 __ Ret(); |
1993 | 1463 |
| 1464 HandlerFrontendFooter(name, &miss); |
| 1465 |
1994 // Return the generated code. | 1466 // Return the generated code. |
1995 return GetCode(kind(), Code::NORMAL, name); | 1467 return GetCode(kind(), Code::NORMAL, name); |
1996 } | 1468 } |
1997 | 1469 |
1998 | 1470 |
1999 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC( | 1471 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC( |
2000 TypeHandleList* types, | 1472 TypeHandleList* types, |
2001 CodeHandleList* handlers, | 1473 CodeHandleList* handlers, |
2002 Handle<Name> name, | 1474 Handle<Name> name, |
2003 Code::StubType type, | 1475 Code::StubType type, |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2120 // ----------------------------------- | 1592 // ----------------------------------- |
2121 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 1593 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
2122 } | 1594 } |
2123 | 1595 |
2124 | 1596 |
2125 #undef __ | 1597 #undef __ |
2126 | 1598 |
2127 } } // namespace v8::internal | 1599 } } // namespace v8::internal |
2128 | 1600 |
2129 #endif // V8_TARGET_ARCH_ARM | 1601 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |