| 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 749 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 760     IC::UtilityId id) { | 760     IC::UtilityId id) { | 
| 761   PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | 761   PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | 
| 762   __ CallExternalReference( | 762   __ CallExternalReference( | 
| 763       ExternalReference(IC_Utility(id), masm->isolate()), | 763       ExternalReference(IC_Utility(id), masm->isolate()), | 
| 764       StubCache::kInterceptorArgsLength); | 764       StubCache::kInterceptorArgsLength); | 
| 765 } | 765 } | 
| 766 | 766 | 
| 767 | 767 | 
| 768 static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength; | 768 static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength; | 
| 769 | 769 | 
| 770 // Reserves space for the extra arguments to API function in the |  | 
| 771 // caller's frame. |  | 
| 772 // |  | 
| 773 // These arguments are set by CheckPrototypes and GenerateFastApiDirectCall. |  | 
| 774 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, |  | 
| 775                                        Register scratch) { |  | 
| 776   ASSERT(Smi::FromInt(0) == 0); |  | 
| 777   for (int i = 0; i < kFastApiCallArguments; i++) { |  | 
| 778     __ push(zero_reg); |  | 
| 779   } |  | 
| 780 } |  | 
| 781 | 770 | 
|  | 771 static void GenerateFastApiCallBody(MacroAssembler* masm, | 
|  | 772                                     const CallOptimization& optimization, | 
|  | 773                                     int argc, | 
|  | 774                                     Register holder, | 
|  | 775                                     Register scratch1, | 
|  | 776                                     Register scratch2, | 
|  | 777                                     Register scratch3, | 
|  | 778                                     bool restore_context) { | 
|  | 779   // ----------- S t a t e ------------- | 
|  | 780   //  -- sp[0]              : last JS argument | 
|  | 781   //  -- ... | 
|  | 782   //  -- sp[(argc - 1) * 4] : first JS argument | 
|  | 783   //  -- sp[argc * 4]       : receiver | 
|  | 784   // ----------------------------------- | 
|  | 785   ASSERT(optimization.is_simple_api_call()); | 
| 782 | 786 | 
| 783 // Undoes the effects of ReserveSpaceForFastApiCall. | 787   typedef FunctionCallbackArguments FCA; | 
| 784 static void FreeSpaceForFastApiCall(MacroAssembler* masm) { |  | 
| 785   __ Drop(kFastApiCallArguments); |  | 
| 786 } |  | 
| 787 | 788 | 
|  | 789   STATIC_ASSERT(FCA::kHolderIndex == 0); | 
|  | 790   STATIC_ASSERT(FCA::kIsolateIndex == 1); | 
|  | 791   STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); | 
|  | 792   STATIC_ASSERT(FCA::kReturnValueOffset == 3); | 
|  | 793   STATIC_ASSERT(FCA::kDataIndex == 4); | 
|  | 794   STATIC_ASSERT(FCA::kCalleeIndex == 5); | 
|  | 795   STATIC_ASSERT(FCA::kContextSaveIndex == 6); | 
|  | 796   STATIC_ASSERT(FCA::kArgsLength == 7); | 
| 788 | 797 | 
| 789 static void GenerateFastApiDirectCall(MacroAssembler* masm, | 798   ASSERT(!holder.is(cp)); | 
| 790                                       const CallOptimization& optimization, | 799 | 
| 791                                       int argc, |  | 
| 792                                       bool restore_context) { |  | 
| 793   // ----------- S t a t e ------------- |  | 
| 794   //  -- sp[0] - sp[24]     : FunctionCallbackInfo, incl. |  | 
| 795   //                        :  holder (set by CheckPrototypes) |  | 
| 796   //  -- sp[28]             : last JS argument |  | 
| 797   //  -- ... |  | 
| 798   //  -- sp[(argc + 6) * 4] : first JS argument |  | 
| 799   //  -- sp[(argc + 7) * 4] : receiver |  | 
| 800   // ----------------------------------- |  | 
| 801   typedef FunctionCallbackArguments FCA; |  | 
| 802   // Save calling context. | 800   // Save calling context. | 
| 803   __ sw(cp, MemOperand(sp, FCA::kContextSaveIndex * kPointerSize)); | 801   __ push(cp); | 
| 804   // Get the function and setup the context. | 802   // Get the function and setup the context. | 
| 805   Handle<JSFunction> function = optimization.constant_function(); | 803   Handle<JSFunction> function = optimization.constant_function(); | 
| 806   __ li(t1, function); | 804   __ li(scratch1, function); | 
| 807   __ lw(cp, FieldMemOperand(t1, JSFunction::kContextOffset)); | 805   __ lw(cp, FieldMemOperand(scratch1, JSFunction::kContextOffset)); | 
| 808   __ sw(t1, MemOperand(sp, FCA::kCalleeIndex * kPointerSize)); | 806   __ push(scratch1); | 
| 809 | 807 | 
| 810   // Construct the FunctionCallbackInfo. | 808   // Construct the FunctionCallbackInfo. | 
| 811   Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); | 809   Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); | 
| 812   Handle<Object> call_data(api_call_info->data(), masm->isolate()); | 810   Handle<Object> call_data(api_call_info->data(), masm->isolate()); | 
|  | 811   bool call_data_undefined = false; | 
| 813   if (masm->isolate()->heap()->InNewSpace(*call_data)) { | 812   if (masm->isolate()->heap()->InNewSpace(*call_data)) { | 
| 814     __ li(a0, api_call_info); | 813     __ li(scratch1, api_call_info); | 
| 815     __ lw(t2, FieldMemOperand(a0, CallHandlerInfo::kDataOffset)); | 814     __ lw(scratch1, FieldMemOperand(scratch1, CallHandlerInfo::kDataOffset)); | 
|  | 815   }  else if (call_data->IsUndefined()) { | 
|  | 816     call_data_undefined = true; | 
|  | 817     __ LoadRoot(scratch3, Heap::kUndefinedValueRootIndex); | 
| 816   } else { | 818   } else { | 
| 817     __ li(t2, call_data); | 819     __ li(scratch1, call_data); | 
| 818   } | 820   } | 
| 819   // Store call data. | 821   // Store call data. | 
| 820   __ sw(t2, MemOperand(sp, FCA::kDataIndex * kPointerSize)); | 822   __ push(scratch1); | 
|  | 823   if (!call_data_undefined) { | 
|  | 824     __ LoadRoot(scratch1, Heap::kUndefinedValueRootIndex); | 
|  | 825   } | 
|  | 826   // Store ReturnValue default and ReturnValue. | 
|  | 827   __ LoadRoot(scratch1, Heap::kUndefinedValueRootIndex); | 
|  | 828   __ Push(scratch1, scratch1); | 
| 821   // Store isolate. | 829   // Store isolate. | 
| 822   __ li(t3, Operand(ExternalReference::isolate_address(masm->isolate()))); | 830   __ li(scratch1, Operand(ExternalReference::isolate_address(masm->isolate()))); | 
| 823   __ sw(t3, MemOperand(sp, FCA::kIsolateIndex * kPointerSize)); | 831   __ push(scratch1); | 
| 824   // Store ReturnValue default and ReturnValue. | 832   // Store holder. | 
| 825   __ LoadRoot(t1, Heap::kUndefinedValueRootIndex); | 833   __ push(holder); | 
| 826   __ sw(t1, MemOperand(sp, FCA::kReturnValueOffset * kPointerSize)); |  | 
| 827   __ sw(t1, MemOperand(sp, FCA::kReturnValueDefaultValueIndex * kPointerSize)); |  | 
| 828 | 834 | 
| 829   // Prepare arguments. | 835   // Prepare arguments. | 
| 830   __ Move(a2, sp); | 836   __ Move(a2, sp); | 
| 831 | 837 | 
| 832   // Allocate the v8::Arguments structure in the arguments' space since | 838   // Allocate the v8::Arguments structure in the arguments' space since | 
| 833   // it's not controlled by GC. | 839   // it's not controlled by GC. | 
| 834   const int kApiStackSpace = 4; | 840   const int kApiStackSpace = 4; | 
| 835 | 841 | 
| 836   FrameScope frame_scope(masm, StackFrame::MANUAL); | 842   FrameScope frame_scope(masm, StackFrame::MANUAL); | 
| 837   __ EnterExitFrame(false, kApiStackSpace); | 843   __ EnterExitFrame(false, kApiStackSpace); | 
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 874                               function_address, | 880                               function_address, | 
| 875                               thunk_ref, | 881                               thunk_ref, | 
| 876                               a1, | 882                               a1, | 
| 877                               kStackUnwindSpace, | 883                               kStackUnwindSpace, | 
| 878                               return_value_operand, | 884                               return_value_operand, | 
| 879                               restore_context ? | 885                               restore_context ? | 
| 880                                   &context_restore_operand : NULL); | 886                                   &context_restore_operand : NULL); | 
| 881 } | 887 } | 
| 882 | 888 | 
| 883 | 889 | 
|  | 890 // Generates call to API function. | 
|  | 891 static void GenerateFastApiCall(MacroAssembler* masm, | 
|  | 892                                 const CallOptimization& optimization, | 
|  | 893                                 int argc, | 
|  | 894                                 Handle<Map> map_to_holder, | 
|  | 895                                 CallOptimization::HolderLookup holder_lookup) { | 
|  | 896   Counters* counters = masm->isolate()->counters(); | 
|  | 897   __ IncrementCounter(counters->call_const_fast_api(), 1, a0, a1); | 
|  | 898 | 
|  | 899   // Move holder to a register. | 
|  | 900   Register holder_reg = a0; | 
|  | 901   switch (holder_lookup) { | 
|  | 902     case CallOptimization::kHolderIsReceiver: | 
|  | 903       { | 
|  | 904         ASSERT(map_to_holder.is_null()); | 
|  | 905         __ lw(holder_reg, MemOperand(sp, argc * kPointerSize)); | 
|  | 906       } | 
|  | 907       break; | 
|  | 908     case CallOptimization::kHolderIsPrototypeOfMap: | 
|  | 909       { | 
|  | 910         Handle<JSObject> holder(JSObject::cast(map_to_holder->prototype())); | 
|  | 911         if (!masm->isolate()->heap()->InNewSpace(*holder)) { | 
|  | 912           __ li(holder_reg, holder); | 
|  | 913         } else { | 
|  | 914           __ li(holder_reg, map_to_holder); | 
|  | 915           __ lw(holder_reg, | 
|  | 916                 FieldMemOperand(holder_reg, Map::kPrototypeOffset)); | 
|  | 917         } | 
|  | 918       } | 
|  | 919      break; | 
|  | 920     case CallOptimization::kHolderNotFound: | 
|  | 921       UNREACHABLE(); | 
|  | 922   } | 
|  | 923   GenerateFastApiCallBody(masm, | 
|  | 924                           optimization, | 
|  | 925                           argc, | 
|  | 926                           holder_reg, | 
|  | 927                           a1, | 
|  | 928                           a2, | 
|  | 929                           a3, | 
|  | 930                           false); | 
|  | 931 } | 
|  | 932 | 
|  | 933 | 
| 884 // Generate call to api function. | 934 // Generate call to api function. | 
| 885 static void GenerateFastApiCall(MacroAssembler* masm, | 935 static void GenerateFastApiCall(MacroAssembler* masm, | 
| 886                                 const CallOptimization& optimization, | 936                                 const CallOptimization& optimization, | 
| 887                                 Register receiver, | 937                                 Register receiver, | 
| 888                                 Register scratch, | 938                                 Register scratch, | 
| 889                                 int argc, | 939                                 int argc, | 
| 890                                 Register* values) { | 940                                 Register* values) { | 
| 891   ASSERT(optimization.is_simple_api_call()); |  | 
| 892   ASSERT(!receiver.is(scratch)); | 941   ASSERT(!receiver.is(scratch)); | 
| 893 | 942   __ push(receiver); | 
| 894   typedef FunctionCallbackArguments FCA; |  | 
| 895   const int stack_space = kFastApiCallArguments + argc + 1; |  | 
| 896   // Assign stack space for the call arguments. |  | 
| 897   __ Subu(sp, sp, Operand(stack_space * kPointerSize)); |  | 
| 898   // Write holder to stack frame. |  | 
| 899   __ sw(receiver, MemOperand(sp, FCA::kHolderIndex * kPointerSize)); |  | 
| 900   // Write receiver to stack frame. |  | 
| 901   int index = stack_space - 1; |  | 
| 902   __ sw(receiver, MemOperand(sp, index-- * kPointerSize)); |  | 
| 903   // Write the arguments to stack frame. | 943   // Write the arguments to stack frame. | 
| 904   for (int i = 0; i < argc; i++) { | 944   for (int i = 0; i < argc; i++) { | 
| 905     ASSERT(!receiver.is(values[i])); | 945     Register arg = values[argc-1-i]; | 
| 906     ASSERT(!scratch.is(values[i])); | 946     ASSERT(!receiver.is(arg)); | 
| 907     __ sw(values[i], MemOperand(sp, index-- * kPointerSize)); | 947     ASSERT(!scratch.is(arg)); | 
|  | 948     __ push(arg); | 
| 908   } | 949   } | 
| 909 | 950 | 
| 910   GenerateFastApiDirectCall(masm, optimization, argc, true); | 951   Register scratch1 = a0; | 
|  | 952   Register scratch2 = a1; | 
|  | 953   Register scratch3 = a2; | 
|  | 954   if (!a3.is(receiver)) { | 
|  | 955     __ mov(a3, receiver); | 
|  | 956     receiver = a3; | 
|  | 957   } | 
|  | 958   // Stack now matches JSFunction abi. | 
|  | 959   GenerateFastApiCallBody(masm, | 
|  | 960                           optimization, | 
|  | 961                           argc, | 
|  | 962                           receiver, | 
|  | 963                           scratch1, | 
|  | 964                           scratch2, | 
|  | 965                           scratch3, | 
|  | 966                           true); | 
| 911 } | 967 } | 
| 912 | 968 | 
| 913 | 969 | 
| 914 class CallInterceptorCompiler BASE_EMBEDDED { | 970 class CallInterceptorCompiler BASE_EMBEDDED { | 
| 915  public: | 971  public: | 
| 916   CallInterceptorCompiler(CallStubCompiler* stub_compiler, | 972   CallInterceptorCompiler(CallStubCompiler* stub_compiler, | 
| 917                           const ParameterCount& arguments, | 973                           const ParameterCount& arguments, | 
| 918                           Register name) | 974                           Register name) | 
| 919       : stub_compiler_(stub_compiler), | 975       : stub_compiler_(stub_compiler), | 
| 920         arguments_(arguments), | 976         arguments_(arguments), | 
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 953                         Register scratch2, | 1009                         Register scratch2, | 
| 954                         Register scratch3, | 1010                         Register scratch3, | 
| 955                         Handle<JSObject> interceptor_holder, | 1011                         Handle<JSObject> interceptor_holder, | 
| 956                         LookupResult* lookup, | 1012                         LookupResult* lookup, | 
| 957                         Handle<Name> name, | 1013                         Handle<Name> name, | 
| 958                         const CallOptimization& optimization, | 1014                         const CallOptimization& optimization, | 
| 959                         Label* miss_label) { | 1015                         Label* miss_label) { | 
| 960     ASSERT(optimization.is_constant_call()); | 1016     ASSERT(optimization.is_constant_call()); | 
| 961     ASSERT(!lookup->holder()->IsGlobalObject()); | 1017     ASSERT(!lookup->holder()->IsGlobalObject()); | 
| 962     Counters* counters = masm->isolate()->counters(); | 1018     Counters* counters = masm->isolate()->counters(); | 
| 963     int depth1 = kInvalidProtoDepth; |  | 
| 964     int depth2 = kInvalidProtoDepth; |  | 
| 965     bool can_do_fast_api_call = false; |  | 
| 966     if (optimization.is_simple_api_call() && |  | 
| 967           !lookup->holder()->IsGlobalObject()) { |  | 
| 968       depth1 = optimization.GetPrototypeDepthOfExpectedType( |  | 
| 969           object, interceptor_holder); |  | 
| 970       if (depth1 == kInvalidProtoDepth) { |  | 
| 971         depth2 = optimization.GetPrototypeDepthOfExpectedType( |  | 
| 972             interceptor_holder, Handle<JSObject>(lookup->holder())); |  | 
| 973       } |  | 
| 974       can_do_fast_api_call = |  | 
| 975           depth1 != kInvalidProtoDepth || depth2 != kInvalidProtoDepth; |  | 
| 976     } |  | 
| 977 |  | 
| 978     __ IncrementCounter(counters->call_const_interceptor(), 1, | 1019     __ IncrementCounter(counters->call_const_interceptor(), 1, | 
| 979                         scratch1, scratch2); | 1020                         scratch1, scratch2); | 
| 980 | 1021 | 
| 981     if (can_do_fast_api_call) { |  | 
| 982       __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1, |  | 
| 983                           scratch1, scratch2); |  | 
| 984       ReserveSpaceForFastApiCall(masm, scratch1); |  | 
| 985     } |  | 
| 986 |  | 
| 987     // Check that the maps from receiver to interceptor's holder | 1022     // Check that the maps from receiver to interceptor's holder | 
| 988     // haven't changed and thus we can invoke interceptor. | 1023     // haven't changed and thus we can invoke interceptor. | 
| 989     Label miss_cleanup; | 1024     Label miss_cleanup; | 
| 990     Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; |  | 
| 991     Register holder = | 1025     Register holder = | 
| 992         stub_compiler_->CheckPrototypes( | 1026         stub_compiler_->CheckPrototypes( | 
| 993             IC::CurrentTypeOf(object, masm->isolate()), receiver, | 1027             IC::CurrentTypeOf(object, masm->isolate()), receiver, | 
| 994             interceptor_holder, scratch1, scratch2, scratch3, | 1028             interceptor_holder, scratch1, scratch2, scratch3, | 
| 995             name, depth1, miss); | 1029             name, miss_label); | 
| 996 | 1030 | 
| 997     // Invoke an interceptor and if it provides a value, | 1031     // Invoke an interceptor and if it provides a value, | 
| 998     // branch to |regular_invoke|. | 1032     // branch to |regular_invoke|. | 
| 999     Label regular_invoke; | 1033     Label regular_invoke; | 
| 1000     LoadWithInterceptor(masm, receiver, holder, interceptor_holder, scratch2, | 1034     LoadWithInterceptor(masm, receiver, holder, interceptor_holder, scratch2, | 
| 1001                         ®ular_invoke); | 1035                         ®ular_invoke); | 
| 1002 | 1036 | 
| 1003     // Interceptor returned nothing for this property.  Try to use cached | 1037     // Interceptor returned nothing for this property.  Try to use cached | 
| 1004     // constant function. | 1038     // constant function. | 
| 1005 | 1039 | 
| 1006     // Check that the maps from interceptor's holder to constant function's | 1040     // Check that the maps from interceptor's holder to constant function's | 
| 1007     // holder haven't changed and thus we can use cached constant function. | 1041     // holder haven't changed and thus we can use cached constant function. | 
| 1008     if (*interceptor_holder != lookup->holder()) { | 1042     if (*interceptor_holder != lookup->holder()) { | 
| 1009       stub_compiler_->CheckPrototypes( | 1043       stub_compiler_->CheckPrototypes( | 
| 1010           IC::CurrentTypeOf(interceptor_holder, masm->isolate()), holder, | 1044           IC::CurrentTypeOf(interceptor_holder, masm->isolate()), holder, | 
| 1011           handle(lookup->holder()), scratch1, scratch2, scratch3, | 1045           handle(lookup->holder()), scratch1, scratch2, scratch3, | 
| 1012           name, depth2, miss); | 1046           name, miss_label); | 
| 1013     } else { | 1047     } | 
| 1014       // CheckPrototypes has a side effect of fetching a 'holder' | 1048 | 
| 1015       // for API (object which is instanceof for the signature).  It's | 1049     Handle<Map> lookup_map; | 
| 1016       // safe to omit it here, as if present, it should be fetched | 1050     CallOptimization::HolderLookup holder_lookup = | 
| 1017       // by the previous CheckPrototypes. | 1051         CallOptimization::kHolderNotFound; | 
| 1018       ASSERT(depth2 == kInvalidProtoDepth); | 1052     if (optimization.is_simple_api_call() && | 
|  | 1053         !lookup->holder()->IsGlobalObject()) { | 
|  | 1054       lookup_map = optimization.LookupHolderOfExpectedType( | 
|  | 1055           object, object, interceptor_holder, &holder_lookup); | 
|  | 1056       if (holder_lookup == CallOptimization::kHolderNotFound) { | 
|  | 1057         lookup_map = | 
|  | 1058             optimization.LookupHolderOfExpectedType( | 
|  | 1059                 object, | 
|  | 1060                 interceptor_holder, | 
|  | 1061                 Handle<JSObject>(lookup->holder()), | 
|  | 1062                 &holder_lookup); | 
|  | 1063       } | 
| 1019     } | 1064     } | 
| 1020 | 1065 | 
| 1021     // Invoke function. | 1066     // Invoke function. | 
| 1022     if (can_do_fast_api_call) { | 1067     if (holder_lookup != CallOptimization::kHolderNotFound) { | 
| 1023       GenerateFastApiDirectCall( | 1068       int argc = arguments_.immediate(); | 
| 1024           masm, optimization, arguments_.immediate(), false); | 1069       GenerateFastApiCall(masm, | 
|  | 1070                           optimization, | 
|  | 1071                           argc, | 
|  | 1072                           lookup_map, | 
|  | 1073                           holder_lookup); | 
| 1025     } else { | 1074     } else { | 
| 1026       Handle<JSFunction> function = optimization.constant_function(); | 1075       Handle<JSFunction> function = optimization.constant_function(); | 
| 1027       __ Move(a0, receiver); | 1076       __ Move(a0, receiver); | 
| 1028       stub_compiler_->GenerateJumpFunction(object, function); | 1077       stub_compiler_->GenerateJumpFunction(object, function); | 
| 1029     } | 1078     } | 
| 1030 | 1079 | 
| 1031     // Deferred code for fast API call case---clean preallocated space. |  | 
| 1032     if (can_do_fast_api_call) { |  | 
| 1033       __ bind(&miss_cleanup); |  | 
| 1034       FreeSpaceForFastApiCall(masm); |  | 
| 1035       __ Branch(miss_label); |  | 
| 1036     } |  | 
| 1037 |  | 
| 1038     // Invoke a regular function. | 1080     // Invoke a regular function. | 
| 1039     __ bind(®ular_invoke); | 1081     __ bind(®ular_invoke); | 
| 1040     if (can_do_fast_api_call) { |  | 
| 1041       FreeSpaceForFastApiCall(masm); |  | 
| 1042     } |  | 
| 1043   } | 1082   } | 
| 1044 | 1083 | 
| 1045   void CompileRegular(MacroAssembler* masm, | 1084   void CompileRegular(MacroAssembler* masm, | 
| 1046                       Handle<JSObject> object, | 1085                       Handle<JSObject> object, | 
| 1047                       Register receiver, | 1086                       Register receiver, | 
| 1048                       Register scratch1, | 1087                       Register scratch1, | 
| 1049                       Register scratch2, | 1088                       Register scratch2, | 
| 1050                       Register scratch3, | 1089                       Register scratch3, | 
| 1051                       Handle<Name> name, | 1090                       Handle<Name> name, | 
| 1052                       Handle<JSObject> interceptor_holder, | 1091                       Handle<JSObject> interceptor_holder, | 
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1107 #define __ ACCESS_MASM(masm()) | 1146 #define __ ACCESS_MASM(masm()) | 
| 1108 | 1147 | 
| 1109 | 1148 | 
| 1110 Register StubCompiler::CheckPrototypes(Handle<HeapType> type, | 1149 Register StubCompiler::CheckPrototypes(Handle<HeapType> type, | 
| 1111                                        Register object_reg, | 1150                                        Register object_reg, | 
| 1112                                        Handle<JSObject> holder, | 1151                                        Handle<JSObject> holder, | 
| 1113                                        Register holder_reg, | 1152                                        Register holder_reg, | 
| 1114                                        Register scratch1, | 1153                                        Register scratch1, | 
| 1115                                        Register scratch2, | 1154                                        Register scratch2, | 
| 1116                                        Handle<Name> name, | 1155                                        Handle<Name> name, | 
| 1117                                        int save_at_depth, |  | 
| 1118                                        Label* miss, | 1156                                        Label* miss, | 
| 1119                                        PrototypeCheckType check) { | 1157                                        PrototypeCheckType check) { | 
| 1120   Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); | 1158   Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); | 
| 1121   // Make sure that the type feedback oracle harvests the receiver map. | 1159   // Make sure that the type feedback oracle harvests the receiver map. | 
| 1122   // TODO(svenpanne) Remove this hack when all ICs are reworked. | 1160   // TODO(svenpanne) Remove this hack when all ICs are reworked. | 
| 1123   __ li(scratch1, Operand(receiver_map)); | 1161   __ li(scratch1, Operand(receiver_map)); | 
| 1124 | 1162 | 
| 1125   // Make sure there's no overlap between holder and object registers. | 1163   // Make sure there's no overlap between holder and object registers. | 
| 1126   ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 1164   ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 
| 1127   ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 1165   ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 
| 1128          && !scratch2.is(scratch1)); | 1166          && !scratch2.is(scratch1)); | 
| 1129 | 1167 | 
| 1130   // Keep track of the current object in register reg. | 1168   // Keep track of the current object in register reg. | 
| 1131   Register reg = object_reg; | 1169   Register reg = object_reg; | 
| 1132   int depth = 0; | 1170   int depth = 0; | 
| 1133 | 1171 | 
| 1134   typedef FunctionCallbackArguments FCA; |  | 
| 1135   if (save_at_depth == depth) { |  | 
| 1136     __ sw(reg, MemOperand(sp, FCA::kHolderIndex * kPointerSize)); |  | 
| 1137   } |  | 
| 1138 |  | 
| 1139   Handle<JSObject> current = Handle<JSObject>::null(); | 1172   Handle<JSObject> current = Handle<JSObject>::null(); | 
| 1140   if (type->IsConstant()) current = Handle<JSObject>::cast(type->AsConstant()); | 1173   if (type->IsConstant()) current = Handle<JSObject>::cast(type->AsConstant()); | 
| 1141   Handle<JSObject> prototype = Handle<JSObject>::null(); | 1174   Handle<JSObject> prototype = Handle<JSObject>::null(); | 
| 1142   Handle<Map> current_map = receiver_map; | 1175   Handle<Map> current_map = receiver_map; | 
| 1143   Handle<Map> holder_map(holder->map()); | 1176   Handle<Map> holder_map(holder->map()); | 
| 1144   // Traverse the prototype chain and check the maps in the prototype chain for | 1177   // Traverse the prototype chain and check the maps in the prototype chain for | 
| 1145   // fast and global objects or do negative lookup for normal objects. | 1178   // fast and global objects or do negative lookup for normal objects. | 
| 1146   while (!current_map.is_identical_to(holder_map)) { | 1179   while (!current_map.is_identical_to(holder_map)) { | 
| 1147     ++depth; | 1180     ++depth; | 
| 1148 | 1181 | 
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1194       if (heap()->InNewSpace(*prototype)) { | 1227       if (heap()->InNewSpace(*prototype)) { | 
| 1195         // The prototype is in new space; we cannot store a reference to it | 1228         // The prototype is in new space; we cannot store a reference to it | 
| 1196         // in the code.  Load it from the map. | 1229         // in the code.  Load it from the map. | 
| 1197         __ lw(reg, FieldMemOperand(map_reg, Map::kPrototypeOffset)); | 1230         __ lw(reg, FieldMemOperand(map_reg, Map::kPrototypeOffset)); | 
| 1198       } else { | 1231       } else { | 
| 1199         // The prototype is in old space; load it directly. | 1232         // The prototype is in old space; load it directly. | 
| 1200         __ li(reg, Operand(prototype)); | 1233         __ li(reg, Operand(prototype)); | 
| 1201       } | 1234       } | 
| 1202     } | 1235     } | 
| 1203 | 1236 | 
| 1204     if (save_at_depth == depth) { |  | 
| 1205       __ sw(reg, MemOperand(sp, FCA::kHolderIndex * kPointerSize)); |  | 
| 1206     } |  | 
| 1207 |  | 
| 1208     // Go to the next object in the prototype chain. | 1237     // Go to the next object in the prototype chain. | 
| 1209     current = prototype; | 1238     current = prototype; | 
| 1210     current_map = handle(current->map()); | 1239     current_map = handle(current->map()); | 
| 1211   } | 1240   } | 
| 1212 | 1241 | 
| 1213   // Log the check depth. | 1242   // Log the check depth. | 
| 1214   LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 1243   LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 
| 1215 | 1244 | 
| 1216   if (depth != 0 || check == CHECK_ALL_MAPS) { | 1245   if (depth != 0 || check == CHECK_ALL_MAPS) { | 
| 1217     // Check the holder map. | 1246     // Check the holder map. | 
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1565     Handle<String> name) { | 1594     Handle<String> name) { | 
| 1566 | 1595 | 
| 1567   Counters* counters = isolate()->counters(); | 1596   Counters* counters = isolate()->counters(); | 
| 1568 | 1597 | 
| 1569   ASSERT(optimization.is_simple_api_call()); | 1598   ASSERT(optimization.is_simple_api_call()); | 
| 1570   // Bail out if object is a global object as we don't want to | 1599   // Bail out if object is a global object as we don't want to | 
| 1571   // repatch it to global receiver. | 1600   // repatch it to global receiver. | 
| 1572   if (object->IsGlobalObject()) return Handle<Code>::null(); | 1601   if (object->IsGlobalObject()) return Handle<Code>::null(); | 
| 1573   if (!cell.is_null()) return Handle<Code>::null(); | 1602   if (!cell.is_null()) return Handle<Code>::null(); | 
| 1574   if (!object->IsJSObject()) return Handle<Code>::null(); | 1603   if (!object->IsJSObject()) return Handle<Code>::null(); | 
| 1575   int depth = optimization.GetPrototypeDepthOfExpectedType( | 1604   Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 
| 1576       Handle<JSObject>::cast(object), holder); | 1605   CallOptimization::HolderLookup holder_lookup = | 
| 1577   if (depth == kInvalidProtoDepth) return Handle<Code>::null(); | 1606       CallOptimization::kHolderNotFound; | 
|  | 1607   Handle<Map> lookup_map = optimization.LookupHolderOfExpectedType( | 
|  | 1608       receiver, receiver, holder, &holder_lookup); | 
|  | 1609   if (holder_lookup == CallOptimization::kHolderNotFound) { | 
|  | 1610     return Handle<Code>::null(); | 
|  | 1611   } | 
| 1578 | 1612 | 
| 1579   Label miss, miss_before_stack_reserved; | 1613   Label miss; | 
| 1580 | 1614   GenerateNameCheck(name, &miss); | 
| 1581   GenerateNameCheck(name, &miss_before_stack_reserved); |  | 
| 1582 | 1615 | 
| 1583   // Get the receiver from the stack. | 1616   // Get the receiver from the stack. | 
| 1584   const int argc = arguments().immediate(); | 1617   const int argc = arguments().immediate(); | 
| 1585   __ lw(a1, MemOperand(sp, argc * kPointerSize)); | 1618   __ lw(a1, MemOperand(sp, argc * kPointerSize)); | 
| 1586 | 1619 | 
| 1587   // Check that the receiver isn't a smi. | 1620   // Check that the receiver isn't a smi. | 
| 1588   __ JumpIfSmi(a1, &miss_before_stack_reserved); | 1621   __ JumpIfSmi(a1, &miss); | 
| 1589 | 1622 | 
| 1590   __ IncrementCounter(counters->call_const(), 1, a0, a3); | 1623   __ IncrementCounter(counters->call_const(), 1, a0, a3); | 
| 1591   __ IncrementCounter(counters->call_const_fast_api(), 1, a0, a3); |  | 
| 1592 |  | 
| 1593   ReserveSpaceForFastApiCall(masm(), a0); |  | 
| 1594 | 1624 | 
| 1595   // Check that the maps haven't changed and find a Holder as a side effect. | 1625   // Check that the maps haven't changed and find a Holder as a side effect. | 
| 1596   CheckPrototypes( | 1626   CheckPrototypes( | 
| 1597       IC::CurrentTypeOf(object, isolate()), | 1627       IC::CurrentTypeOf(object, isolate()), | 
| 1598       a1, holder, a0, a3, t0, name, depth, &miss); | 1628       a1, holder, a0, a3, t0, name, &miss); | 
| 1599 | 1629 | 
| 1600   GenerateFastApiDirectCall(masm(), optimization, argc, false); | 1630   GenerateFastApiCall( | 
|  | 1631       masm(), optimization, argc, lookup_map, holder_lookup); | 
| 1601 | 1632 | 
| 1602   __ bind(&miss); | 1633   HandlerFrontendFooter(&miss); | 
| 1603   FreeSpaceForFastApiCall(masm()); |  | 
| 1604 |  | 
| 1605   HandlerFrontendFooter(&miss_before_stack_reserved); |  | 
| 1606 | 1634 | 
| 1607   // Return the generated code. | 1635   // Return the generated code. | 
| 1608   return GetCode(function); | 1636   return GetCode(function); | 
| 1609 } | 1637 } | 
| 1610 | 1638 | 
| 1611 | 1639 | 
| 1612 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { | 1640 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { | 
| 1613   Label success; | 1641   Label success; | 
| 1614   // Check that the object is a boolean. | 1642   // Check that the object is a boolean. | 
| 1615   __ LoadRoot(at, Heap::kTrueValueRootIndex); | 1643   __ LoadRoot(at, Heap::kTrueValueRootIndex); | 
| (...skipping 539 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2155   // ----------------------------------- | 2183   // ----------------------------------- | 
| 2156   TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 2184   TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 
| 2157 } | 2185 } | 
| 2158 | 2186 | 
| 2159 | 2187 | 
| 2160 #undef __ | 2188 #undef __ | 
| 2161 | 2189 | 
| 2162 } }  // namespace v8::internal | 2190 } }  // namespace v8::internal | 
| 2163 | 2191 | 
| 2164 #endif  // V8_TARGET_ARCH_MIPS | 2192 #endif  // V8_TARGET_ARCH_MIPS | 
| OLD | NEW | 
|---|