| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 419 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); | 419 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); |
| 420 __ mov(v0, scratch1); | 420 __ mov(v0, scratch1); |
| 421 __ Ret(); | 421 __ Ret(); |
| 422 } | 422 } |
| 423 | 423 |
| 424 | 424 |
| 425 // Generate StoreField code, value is passed in a0 register. | 425 // Generate StoreField code, value is passed in a0 register. |
| 426 // After executing generated code, the receiver_reg and name_reg | 426 // After executing generated code, the receiver_reg and name_reg |
| 427 // may be clobbered. | 427 // may be clobbered. |
| 428 void StubCompiler::GenerateStoreField(MacroAssembler* masm, | 428 void StubCompiler::GenerateStoreField(MacroAssembler* masm, |
| 429 JSObject* object, | 429 Handle<JSObject> object, |
| 430 int index, | 430 int index, |
| 431 Map* transition, | 431 Handle<Map> transition, |
| 432 Register receiver_reg, | 432 Register receiver_reg, |
| 433 Register name_reg, | 433 Register name_reg, |
| 434 Register scratch, | 434 Register scratch, |
| 435 Label* miss_label) { | 435 Label* miss_label) { |
| 436 // a0 : value. | 436 // a0 : value. |
| 437 Label exit; | 437 Label exit; |
| 438 | 438 |
| 439 // Check that the receiver isn't a smi. | 439 // Check that the receiver isn't a smi. |
| 440 __ JumpIfSmi(receiver_reg, miss_label, scratch); | 440 __ JumpIfSmi(receiver_reg, miss_label, scratch); |
| 441 | 441 |
| 442 // Check that the map of the receiver hasn't changed. | 442 // Check that the map of the receiver hasn't changed. |
| 443 __ lw(scratch, FieldMemOperand(receiver_reg, HeapObject::kMapOffset)); | 443 __ lw(scratch, FieldMemOperand(receiver_reg, HeapObject::kMapOffset)); |
| 444 __ Branch(miss_label, ne, scratch, Operand(Handle<Map>(object->map()))); | 444 __ Branch(miss_label, ne, scratch, Operand(Handle<Map>(object->map()))); |
| 445 | 445 |
| 446 // Perform global security token check if needed. | 446 // Perform global security token check if needed. |
| 447 if (object->IsJSGlobalProxy()) { | 447 if (object->IsJSGlobalProxy()) { |
| 448 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); | 448 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); |
| 449 } | 449 } |
| 450 | 450 |
| 451 // Stub never generated for non-global objects that require access | 451 // Stub never generated for non-global objects that require access |
| 452 // checks. | 452 // checks. |
| 453 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 453 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
| 454 | 454 |
| 455 // Perform map transition for the receiver if necessary. | 455 // Perform map transition for the receiver if necessary. |
| 456 if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) { | 456 if (!transition.is_null() && (object->map()->unused_property_fields() == 0)) { |
| 457 // The properties must be extended before we can store the value. | 457 // The properties must be extended before we can store the value. |
| 458 // We jump to a runtime call that extends the properties array. | 458 // We jump to a runtime call that extends the properties array. |
| 459 __ push(receiver_reg); | 459 __ push(receiver_reg); |
| 460 __ li(a2, Operand(Handle<Map>(transition))); | 460 __ li(a2, Operand(transition)); |
| 461 __ Push(a2, a0); | 461 __ Push(a2, a0); |
| 462 __ TailCallExternalReference( | 462 __ TailCallExternalReference( |
| 463 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), | 463 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), |
| 464 masm->isolate()), | 464 masm->isolate()), |
| 465 3, 1); | 465 3, 1); |
| 466 return; | 466 return; |
| 467 } | 467 } |
| 468 | 468 |
| 469 if (transition != NULL) { | 469 if (!transition.is_null()) { |
| 470 // Update the map of the object; no write barrier updating is | 470 // Update the map of the object; no write barrier updating is |
| 471 // needed because the map is never in new space. | 471 // needed because the map is never in new space. |
| 472 __ li(t0, Operand(Handle<Map>(transition))); | 472 __ li(t0, Operand(transition)); |
| 473 __ sw(t0, FieldMemOperand(receiver_reg, HeapObject::kMapOffset)); | 473 __ sw(t0, FieldMemOperand(receiver_reg, HeapObject::kMapOffset)); |
| 474 } | 474 } |
| 475 | 475 |
| 476 // Adjust for the number of properties stored in the object. Even in the | 476 // Adjust for the number of properties stored in the object. Even in the |
| 477 // face of a transition we can use the old map here because the size of the | 477 // face of a transition we can use the old map here because the size of the |
| 478 // object and the number of in-object properties is not going to change. | 478 // object and the number of in-object properties is not going to change. |
| 479 index -= object->map()->inobject_properties(); | 479 index -= object->map()->inobject_properties(); |
| 480 | 480 |
| 481 if (index < 0) { | 481 if (index < 0) { |
| 482 // Set the property straight into the object. | 482 // Set the property straight into the object. |
| (...skipping 2334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2817 __ bind(&miss); | 2817 __ bind(&miss); |
| 2818 __ IncrementCounter(counters->call_global_inline_miss(), 1, a1, a3); | 2818 __ IncrementCounter(counters->call_global_inline_miss(), 1, a1, a3); |
| 2819 MaybeObject* maybe_result = TryGenerateMissBranch(); | 2819 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 2820 if (maybe_result->IsFailure()) return maybe_result; | 2820 if (maybe_result->IsFailure()) return maybe_result; |
| 2821 | 2821 |
| 2822 // Return the generated code. | 2822 // Return the generated code. |
| 2823 return TryGetCode(NORMAL, name); | 2823 return TryGetCode(NORMAL, name); |
| 2824 } | 2824 } |
| 2825 | 2825 |
| 2826 | 2826 |
| 2827 MaybeObject* StoreStubCompiler::CompileStoreField(JSObject* object, | 2827 Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object, |
| 2828 int index, | 2828 int index, |
| 2829 Map* transition, | 2829 Handle<Map> transition, |
| 2830 String* name) { | 2830 Handle<String> name) { |
| 2831 // ----------- S t a t e ------------- | 2831 // ----------- S t a t e ------------- |
| 2832 // -- a0 : value | 2832 // -- a0 : value |
| 2833 // -- a1 : receiver | 2833 // -- a1 : receiver |
| 2834 // -- a2 : name | 2834 // -- a2 : name |
| 2835 // -- ra : return address | 2835 // -- ra : return address |
| 2836 // ----------------------------------- | 2836 // ----------------------------------- |
| 2837 Label miss; | 2837 Label miss; |
| 2838 | 2838 |
| 2839 // Name register might be clobbered. | 2839 // Name register might be clobbered. |
| 2840 GenerateStoreField(masm(), | 2840 GenerateStoreField(masm(), object, index, transition, a1, a2, a3, &miss); |
| 2841 object, | |
| 2842 index, | |
| 2843 transition, | |
| 2844 a1, a2, a3, | |
| 2845 &miss); | |
| 2846 __ bind(&miss); | 2841 __ bind(&miss); |
| 2847 __ li(a2, Operand(Handle<String>(name))); // Restore name. | 2842 __ li(a2, Operand(Handle<String>(name))); // Restore name. |
| 2848 Handle<Code> ic = masm()->isolate()->builtins()->Builtins::StoreIC_Miss(); | 2843 Handle<Code> ic = masm()->isolate()->builtins()->Builtins::StoreIC_Miss(); |
| 2849 __ Jump(ic, RelocInfo::CODE_TARGET); | 2844 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 2850 | 2845 |
| 2851 // Return the generated code. | 2846 // Return the generated code. |
| 2852 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); | 2847 return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name); |
| 2853 } | 2848 } |
| 2854 | 2849 |
| 2855 | 2850 |
| 2856 MaybeObject* StoreStubCompiler::CompileStoreCallback(JSObject* object, | 2851 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
| 2857 AccessorInfo* callback, | 2852 Handle<JSObject> object, |
| 2858 String* name) { | 2853 Handle<AccessorInfo> callback, |
| 2854 Handle<String> name) { |
| 2859 // ----------- S t a t e ------------- | 2855 // ----------- S t a t e ------------- |
| 2860 // -- a0 : value | 2856 // -- a0 : value |
| 2861 // -- a1 : receiver | 2857 // -- a1 : receiver |
| 2862 // -- a2 : name | 2858 // -- a2 : name |
| 2863 // -- ra : return address | 2859 // -- ra : return address |
| 2864 // ----------------------------------- | 2860 // ----------------------------------- |
| 2865 Label miss; | 2861 Label miss; |
| 2866 | 2862 |
| 2867 // Check that the object isn't a smi. | 2863 // Check that the object isn't a smi. |
| 2868 __ JumpIfSmi(a1, &miss); | 2864 __ JumpIfSmi(a1, &miss); |
| 2869 | 2865 |
| 2870 // Check that the map of the object hasn't changed. | 2866 // Check that the map of the object hasn't changed. |
| 2871 __ lw(a3, FieldMemOperand(a1, HeapObject::kMapOffset)); | 2867 __ lw(a3, FieldMemOperand(a1, HeapObject::kMapOffset)); |
| 2872 __ Branch(&miss, ne, a3, Operand(Handle<Map>(object->map()))); | 2868 __ Branch(&miss, ne, a3, Operand(Handle<Map>(object->map()))); |
| 2873 | 2869 |
| 2874 // Perform global security token check if needed. | 2870 // Perform global security token check if needed. |
| 2875 if (object->IsJSGlobalProxy()) { | 2871 if (object->IsJSGlobalProxy()) { |
| 2876 __ CheckAccessGlobalProxy(a1, a3, &miss); | 2872 __ CheckAccessGlobalProxy(a1, a3, &miss); |
| 2877 } | 2873 } |
| 2878 | 2874 |
| 2879 // Stub never generated for non-global objects that require access | 2875 // Stub never generated for non-global objects that require access |
| 2880 // checks. | 2876 // checks. |
| 2881 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 2877 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
| 2882 | 2878 |
| 2883 __ push(a1); // Receiver. | 2879 __ push(a1); // Receiver. |
| 2884 __ li(a3, Operand(Handle<AccessorInfo>(callback))); // Callback info. | 2880 __ li(a3, Operand(callback)); // Callback info. |
| 2885 __ Push(a3, a2, a0); | 2881 __ Push(a3, a2, a0); |
| 2886 | 2882 |
| 2887 // Do tail-call to the runtime system. | 2883 // Do tail-call to the runtime system. |
| 2888 ExternalReference store_callback_property = | 2884 ExternalReference store_callback_property = |
| 2889 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), | 2885 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), |
| 2890 masm()->isolate()); | 2886 masm()->isolate()); |
| 2891 __ TailCallExternalReference(store_callback_property, 4, 1); | 2887 __ TailCallExternalReference(store_callback_property, 4, 1); |
| 2892 | 2888 |
| 2893 // Handle store cache miss. | 2889 // Handle store cache miss. |
| 2894 __ bind(&miss); | 2890 __ bind(&miss); |
| 2895 Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss(); | 2891 Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss(); |
| 2896 __ Jump(ic, RelocInfo::CODE_TARGET); | 2892 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 2897 | 2893 |
| 2898 // Return the generated code. | 2894 // Return the generated code. |
| 2899 return GetCode(CALLBACKS, name); | 2895 return GetCode(CALLBACKS, name); |
| 2900 } | 2896 } |
| 2901 | 2897 |
| 2902 | 2898 |
| 2903 MaybeObject* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, | 2899 Handle<Code> StoreStubCompiler::CompileStoreInterceptor( |
| 2904 String* name) { | 2900 Handle<JSObject> receiver, |
| 2901 Handle<String> name) { |
| 2905 // ----------- S t a t e ------------- | 2902 // ----------- S t a t e ------------- |
| 2906 // -- a0 : value | 2903 // -- a0 : value |
| 2907 // -- a1 : receiver | 2904 // -- a1 : receiver |
| 2908 // -- a2 : name | 2905 // -- a2 : name |
| 2909 // -- ra : return address | 2906 // -- ra : return address |
| 2910 // ----------------------------------- | 2907 // ----------------------------------- |
| 2911 Label miss; | 2908 Label miss; |
| 2912 | 2909 |
| 2913 // Check that the object isn't a smi. | 2910 // Check that the object isn't a smi. |
| 2914 __ JumpIfSmi(a1, &miss); | 2911 __ JumpIfSmi(a1, &miss); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2940 // Handle store cache miss. | 2937 // Handle store cache miss. |
| 2941 __ bind(&miss); | 2938 __ bind(&miss); |
| 2942 Handle<Code> ic = masm()->isolate()->builtins()->Builtins::StoreIC_Miss(); | 2939 Handle<Code> ic = masm()->isolate()->builtins()->Builtins::StoreIC_Miss(); |
| 2943 __ Jump(ic, RelocInfo::CODE_TARGET); | 2940 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 2944 | 2941 |
| 2945 // Return the generated code. | 2942 // Return the generated code. |
| 2946 return GetCode(INTERCEPTOR, name); | 2943 return GetCode(INTERCEPTOR, name); |
| 2947 } | 2944 } |
| 2948 | 2945 |
| 2949 | 2946 |
| 2950 MaybeObject* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, | 2947 Handle<Code> StoreStubCompiler::CompileStoreGlobal( |
| 2951 JSGlobalPropertyCell* cell, | 2948 Handle<GlobalObject> object, |
| 2952 String* name) { | 2949 Handle<JSGlobalPropertyCell> cell, |
| 2950 Handle<String> name) { |
| 2953 // ----------- S t a t e ------------- | 2951 // ----------- S t a t e ------------- |
| 2954 // -- a0 : value | 2952 // -- a0 : value |
| 2955 // -- a1 : receiver | 2953 // -- a1 : receiver |
| 2956 // -- a2 : name | 2954 // -- a2 : name |
| 2957 // -- ra : return address | 2955 // -- ra : return address |
| 2958 // ----------------------------------- | 2956 // ----------------------------------- |
| 2959 Label miss; | 2957 Label miss; |
| 2960 | 2958 |
| 2961 // Check that the map of the global has not changed. | 2959 // Check that the map of the global has not changed. |
| 2962 __ lw(a3, FieldMemOperand(a1, HeapObject::kMapOffset)); | 2960 __ lw(a3, FieldMemOperand(a1, HeapObject::kMapOffset)); |
| 2963 __ Branch(&miss, ne, a3, Operand(Handle<Map>(object->map()))); | 2961 __ Branch(&miss, ne, a3, Operand(Handle<Map>(object->map()))); |
| 2964 | 2962 |
| 2965 // Check that the value in the cell is not the hole. If it is, this | 2963 // Check that the value in the cell is not the hole. If it is, this |
| 2966 // cell could have been deleted and reintroducing the global needs | 2964 // cell could have been deleted and reintroducing the global needs |
| 2967 // to update the property details in the property dictionary of the | 2965 // to update the property details in the property dictionary of the |
| 2968 // global object. We bail out to the runtime system to do that. | 2966 // global object. We bail out to the runtime system to do that. |
| 2969 __ li(t0, Operand(Handle<JSGlobalPropertyCell>(cell))); | 2967 __ li(t0, Operand(cell)); |
| 2970 __ LoadRoot(t1, Heap::kTheHoleValueRootIndex); | 2968 __ LoadRoot(t1, Heap::kTheHoleValueRootIndex); |
| 2971 __ lw(t2, FieldMemOperand(t0, JSGlobalPropertyCell::kValueOffset)); | 2969 __ lw(t2, FieldMemOperand(t0, JSGlobalPropertyCell::kValueOffset)); |
| 2972 __ Branch(&miss, eq, t1, Operand(t2)); | 2970 __ Branch(&miss, eq, t1, Operand(t2)); |
| 2973 | 2971 |
| 2974 // Store the value in the cell. | 2972 // Store the value in the cell. |
| 2975 __ sw(a0, FieldMemOperand(t0, JSGlobalPropertyCell::kValueOffset)); | 2973 __ sw(a0, FieldMemOperand(t0, JSGlobalPropertyCell::kValueOffset)); |
| 2976 __ mov(v0, a0); // Stored value must be returned in v0. | 2974 __ mov(v0, a0); // Stored value must be returned in v0. |
| 2977 | 2975 |
| 2978 // This trashes a0 but the value is returned in v0 anyway. | 2976 // This trashes a0 but the value is returned in v0 anyway. |
| 2979 __ RecordWriteField(t0, | 2977 __ RecordWriteField(t0, |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3125 name, | 3123 name, |
| 3126 &miss); | 3124 &miss); |
| 3127 __ bind(&miss); | 3125 __ bind(&miss); |
| 3128 GenerateLoadMiss(masm(), Code::LOAD_IC); | 3126 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 3129 | 3127 |
| 3130 // Return the generated code. | 3128 // Return the generated code. |
| 3131 return TryGetCode(INTERCEPTOR, name); | 3129 return TryGetCode(INTERCEPTOR, name); |
| 3132 } | 3130 } |
| 3133 | 3131 |
| 3134 | 3132 |
| 3135 MaybeObject* LoadStubCompiler::CompileLoadGlobal(JSObject* object, | 3133 Handle<Code> LoadStubCompiler::CompileLoadGlobal( |
| 3136 GlobalObject* holder, | 3134 Handle<JSObject> object, |
| 3137 JSGlobalPropertyCell* cell, | 3135 Handle<GlobalObject> holder, |
| 3138 String* name, | 3136 Handle<JSGlobalPropertyCell> cell, |
| 3139 bool is_dont_delete) { | 3137 Handle<String> name, |
| 3138 bool is_dont_delete) { |
| 3140 // ----------- S t a t e ------------- | 3139 // ----------- S t a t e ------------- |
| 3141 // -- a0 : receiver | 3140 // -- a0 : receiver |
| 3142 // -- a2 : name | 3141 // -- a2 : name |
| 3143 // -- ra : return address | 3142 // -- ra : return address |
| 3144 // ----------------------------------- | 3143 // ----------------------------------- |
| 3145 Label miss; | 3144 Label miss; |
| 3146 | 3145 |
| 3147 // If the object is the holder then we know that it's a global | 3146 // If the object is the holder then we know that it's a global |
| 3148 // object which can only happen for contextual calls. In this case, | 3147 // object which can only happen for contextual calls. In this case, |
| 3149 // the receiver cannot be a smi. | 3148 // the receiver cannot be a smi. |
| 3150 if (object != holder) { | 3149 if (!object.is_identical_to(holder)) { |
| 3151 __ And(t0, a0, Operand(kSmiTagMask)); | 3150 __ And(t0, a0, Operand(kSmiTagMask)); |
| 3152 __ Branch(&miss, eq, t0, Operand(zero_reg)); | 3151 __ Branch(&miss, eq, t0, Operand(zero_reg)); |
| 3153 } | 3152 } |
| 3154 | 3153 |
| 3155 // Check that the map of the global has not changed. | 3154 // Check that the map of the global has not changed. |
| 3156 CheckPrototypes(object, a0, holder, a3, t0, a1, name, &miss); | 3155 CheckPrototypes(object, a0, holder, a3, t0, a1, name, &miss); |
| 3157 | 3156 |
| 3158 // Get the value from the cell. | 3157 // Get the value from the cell. |
| 3159 __ li(a3, Operand(Handle<JSGlobalPropertyCell>(cell))); | 3158 __ li(a3, Operand(cell)); |
| 3160 __ lw(t0, FieldMemOperand(a3, JSGlobalPropertyCell::kValueOffset)); | 3159 __ lw(t0, FieldMemOperand(a3, JSGlobalPropertyCell::kValueOffset)); |
| 3161 | 3160 |
| 3162 // Check for deleted property if property can actually be deleted. | 3161 // Check for deleted property if property can actually be deleted. |
| 3163 if (!is_dont_delete) { | 3162 if (!is_dont_delete) { |
| 3164 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 3163 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 3165 __ Branch(&miss, eq, t0, Operand(at)); | 3164 __ Branch(&miss, eq, t0, Operand(at)); |
| 3166 } | 3165 } |
| 3167 | 3166 |
| 3168 __ mov(v0, t0); | 3167 __ mov(v0, t0); |
| 3169 Counters* counters = masm()->isolate()->counters(); | 3168 Counters* counters = masm()->isolate()->counters(); |
| 3170 __ IncrementCounter(counters->named_load_global_stub(), 1, a1, a3); | 3169 __ IncrementCounter(counters->named_load_global_stub(), 1, a1, a3); |
| 3171 __ Ret(); | 3170 __ Ret(); |
| 3172 | 3171 |
| 3173 __ bind(&miss); | 3172 __ bind(&miss); |
| 3174 __ IncrementCounter(counters->named_load_global_stub_miss(), 1, a1, a3); | 3173 __ IncrementCounter(counters->named_load_global_stub_miss(), 1, a1, a3); |
| 3175 GenerateLoadMiss(masm(), Code::LOAD_IC); | 3174 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 3176 | 3175 |
| 3177 // Return the generated code. | 3176 // Return the generated code. |
| 3178 return TryGetCode(NORMAL, name); | 3177 return GetCode(NORMAL, name); |
| 3179 } | 3178 } |
| 3180 | 3179 |
| 3181 | 3180 |
| 3182 Handle<Code> KeyedLoadStubCompiler::CompileLoadField(Handle<String> name, | 3181 Handle<Code> KeyedLoadStubCompiler::CompileLoadField(Handle<String> name, |
| 3183 Handle<JSObject> receiver, | 3182 Handle<JSObject> receiver, |
| 3184 Handle<JSObject> holder, | 3183 Handle<JSObject> holder, |
| 3185 int index) { | 3184 int index) { |
| 3186 // ----------- S t a t e ------------- | 3185 // ----------- S t a t e ------------- |
| 3187 // -- ra : return address | 3186 // -- ra : return address |
| 3188 // -- a0 : key | 3187 // -- a0 : key |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3348 | 3347 |
| 3349 GenerateLoadFunctionPrototype(masm(), a1, a2, a3, &miss); | 3348 GenerateLoadFunctionPrototype(masm(), a1, a2, a3, &miss); |
| 3350 __ bind(&miss); | 3349 __ bind(&miss); |
| 3351 __ DecrementCounter(counters->keyed_load_function_prototype(), 1, a2, a3); | 3350 __ DecrementCounter(counters->keyed_load_function_prototype(), 1, a2, a3); |
| 3352 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3351 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3353 | 3352 |
| 3354 return GetCode(CALLBACKS, name); | 3353 return GetCode(CALLBACKS, name); |
| 3355 } | 3354 } |
| 3356 | 3355 |
| 3357 | 3356 |
| 3358 MaybeObject* KeyedLoadStubCompiler::CompileLoadElement(Map* receiver_map) { | 3357 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( |
| 3358 Handle<Map> receiver_map) { |
| 3359 // ----------- S t a t e ------------- | 3359 // ----------- S t a t e ------------- |
| 3360 // -- ra : return address | 3360 // -- ra : return address |
| 3361 // -- a0 : key | 3361 // -- a0 : key |
| 3362 // -- a1 : receiver | 3362 // -- a1 : receiver |
| 3363 // ----------------------------------- | 3363 // ----------------------------------- |
| 3364 Code* stub; | |
| 3365 ElementsKind elements_kind = receiver_map->elements_kind(); | 3364 ElementsKind elements_kind = receiver_map->elements_kind(); |
| 3366 MaybeObject* maybe_stub = KeyedLoadElementStub(elements_kind).TryGetCode(); | 3365 Handle<Code> stub = KeyedLoadElementStub(elements_kind).GetCode(); |
| 3367 if (!maybe_stub->To(&stub)) return maybe_stub; | 3366 |
| 3368 __ DispatchMap(a1, | 3367 __ DispatchMap(a1, a2, receiver_map, stub, DO_SMI_CHECK); |
| 3369 a2, | |
| 3370 Handle<Map>(receiver_map), | |
| 3371 Handle<Code>(stub), | |
| 3372 DO_SMI_CHECK); | |
| 3373 | 3368 |
| 3374 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss(); | 3369 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss(); |
| 3375 __ Jump(ic, RelocInfo::CODE_TARGET); | 3370 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 3376 | 3371 |
| 3377 // Return the generated code. | 3372 // Return the generated code. |
| 3378 return TryGetCode(NORMAL, NULL); | 3373 return GetCode(NORMAL, factory()->empty_string()); |
| 3379 } | 3374 } |
| 3380 | 3375 |
| 3381 | 3376 |
| 3382 MaybeObject* KeyedLoadStubCompiler::CompileLoadPolymorphic( | 3377 Handle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic( |
| 3383 MapList* receiver_maps, | 3378 MapHandleList* receiver_maps, |
| 3384 CodeList* handler_ics) { | 3379 CodeHandleList* handler_ics) { |
| 3385 // ----------- S t a t e ------------- | 3380 // ----------- S t a t e ------------- |
| 3386 // -- ra : return address | 3381 // -- ra : return address |
| 3387 // -- a0 : key | 3382 // -- a0 : key |
| 3388 // -- a1 : receiver | 3383 // -- a1 : receiver |
| 3389 // ----------------------------------- | 3384 // ----------------------------------- |
| 3390 Label miss; | 3385 Label miss; |
| 3391 __ JumpIfSmi(a1, &miss); | 3386 __ JumpIfSmi(a1, &miss); |
| 3392 | 3387 |
| 3393 int receiver_count = receiver_maps->length(); | 3388 int receiver_count = receiver_maps->length(); |
| 3394 __ lw(a2, FieldMemOperand(a1, HeapObject::kMapOffset)); | 3389 __ lw(a2, FieldMemOperand(a1, HeapObject::kMapOffset)); |
| 3395 for (int current = 0; current < receiver_count; ++current) { | 3390 for (int current = 0; current < receiver_count; ++current) { |
| 3396 Handle<Map> map(receiver_maps->at(current)); | 3391 __ Jump(handler_ics->at(current), RelocInfo::CODE_TARGET, |
| 3397 Handle<Code> code(handler_ics->at(current)); | 3392 eq, a2, Operand(receiver_maps->at(current))); |
| 3398 __ Jump(code, RelocInfo::CODE_TARGET, eq, a2, Operand(map)); | |
| 3399 } | 3393 } |
| 3400 | 3394 |
| 3401 __ bind(&miss); | 3395 __ bind(&miss); |
| 3402 Handle<Code> miss_ic = isolate()->builtins()->KeyedLoadIC_Miss(); | 3396 Handle<Code> miss_ic = isolate()->builtins()->KeyedLoadIC_Miss(); |
| 3403 __ Jump(miss_ic, RelocInfo::CODE_TARGET); | 3397 __ Jump(miss_ic, RelocInfo::CODE_TARGET); |
| 3404 | 3398 |
| 3405 // Return the generated code. | 3399 // Return the generated code. |
| 3406 return TryGetCode(NORMAL, NULL, MEGAMORPHIC); | 3400 return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC); |
| 3407 } | 3401 } |
| 3408 | 3402 |
| 3409 | 3403 |
| 3410 MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, | 3404 Handle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object, |
| 3411 int index, | 3405 int index, |
| 3412 Map* transition, | 3406 Handle<Map> transition, |
| 3413 String* name) { | 3407 Handle<String> name) { |
| 3414 // ----------- S t a t e ------------- | 3408 // ----------- S t a t e ------------- |
| 3415 // -- a0 : value | 3409 // -- a0 : value |
| 3416 // -- a1 : key | 3410 // -- a1 : key |
| 3417 // -- a2 : receiver | 3411 // -- a2 : receiver |
| 3418 // -- ra : return address | 3412 // -- ra : return address |
| 3419 // ----------------------------------- | 3413 // ----------------------------------- |
| 3420 | 3414 |
| 3421 Label miss; | 3415 Label miss; |
| 3422 | 3416 |
| 3423 Counters* counters = masm()->isolate()->counters(); | 3417 Counters* counters = masm()->isolate()->counters(); |
| 3424 __ IncrementCounter(counters->keyed_store_field(), 1, a3, t0); | 3418 __ IncrementCounter(counters->keyed_store_field(), 1, a3, t0); |
| 3425 | 3419 |
| 3426 // Check that the name has not changed. | 3420 // Check that the name has not changed. |
| 3427 __ Branch(&miss, ne, a1, Operand(Handle<String>(name))); | 3421 __ Branch(&miss, ne, a1, Operand(name)); |
| 3428 | 3422 |
| 3429 // a3 is used as scratch register. a1 and a2 keep their values if a jump to | 3423 // a3 is used as scratch register. a1 and a2 keep their values if a jump to |
| 3430 // the miss label is generated. | 3424 // the miss label is generated. |
| 3431 GenerateStoreField(masm(), | 3425 GenerateStoreField(masm(), object, index, transition, a2, a1, a3, &miss); |
| 3432 object, | |
| 3433 index, | |
| 3434 transition, | |
| 3435 a2, a1, a3, | |
| 3436 &miss); | |
| 3437 __ bind(&miss); | 3426 __ bind(&miss); |
| 3438 | 3427 |
| 3439 __ DecrementCounter(counters->keyed_store_field(), 1, a3, t0); | 3428 __ DecrementCounter(counters->keyed_store_field(), 1, a3, t0); |
| 3440 Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss(); | 3429 Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss(); |
| 3441 __ Jump(ic, RelocInfo::CODE_TARGET); | 3430 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 3442 | 3431 |
| 3443 // Return the generated code. | 3432 // Return the generated code. |
| 3444 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); | 3433 return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name); |
| 3445 } | 3434 } |
| 3446 | 3435 |
| 3447 | 3436 |
| 3448 MaybeObject* KeyedStoreStubCompiler::CompileStoreElement(Map* receiver_map) { | 3437 Handle<Code> KeyedStoreStubCompiler::CompileStoreElement( |
| 3438 Handle<Map> receiver_map) { |
| 3449 // ----------- S t a t e ------------- | 3439 // ----------- S t a t e ------------- |
| 3450 // -- a0 : value | 3440 // -- a0 : value |
| 3451 // -- a1 : key | 3441 // -- a1 : key |
| 3452 // -- a2 : receiver | 3442 // -- a2 : receiver |
| 3453 // -- ra : return address | 3443 // -- ra : return address |
| 3454 // -- a3 : scratch | 3444 // -- a3 : scratch |
| 3455 // ----------------------------------- | 3445 // ----------------------------------- |
| 3456 Code* stub; | |
| 3457 ElementsKind elements_kind = receiver_map->elements_kind(); | 3446 ElementsKind elements_kind = receiver_map->elements_kind(); |
| 3458 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; | 3447 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; |
| 3459 MaybeObject* maybe_stub = | 3448 Handle<Code> stub = |
| 3460 KeyedStoreElementStub(is_js_array, elements_kind).TryGetCode(); | 3449 KeyedStoreElementStub(is_js_array, elements_kind).GetCode(); |
| 3461 if (!maybe_stub->To(&stub)) return maybe_stub; | 3450 |
| 3462 __ DispatchMap(a2, | 3451 __ DispatchMap(a2, a3, receiver_map, stub, DO_SMI_CHECK); |
| 3463 a3, | |
| 3464 Handle<Map>(receiver_map), | |
| 3465 Handle<Code>(stub), | |
| 3466 DO_SMI_CHECK); | |
| 3467 | 3452 |
| 3468 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); | 3453 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
| 3469 __ Jump(ic, RelocInfo::CODE_TARGET); | 3454 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 3470 | 3455 |
| 3471 // Return the generated code. | 3456 // Return the generated code. |
| 3472 return GetCode(NORMAL, NULL); | 3457 return GetCode(NORMAL, factory()->empty_string()); |
| 3473 } | 3458 } |
| 3474 | 3459 |
| 3475 | 3460 |
| 3476 MaybeObject* KeyedStoreStubCompiler::CompileStorePolymorphic( | 3461 Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( |
| 3477 MapList* receiver_maps, | 3462 MapHandleList* receiver_maps, |
| 3478 CodeList* handler_stubs, | 3463 CodeHandleList* handler_stubs, |
| 3479 MapList* transitioned_maps) { | 3464 MapHandleList* transitioned_maps) { |
| 3480 // ----------- S t a t e ------------- | 3465 // ----------- S t a t e ------------- |
| 3481 // -- a0 : value | 3466 // -- a0 : value |
| 3482 // -- a1 : key | 3467 // -- a1 : key |
| 3483 // -- a2 : receiver | 3468 // -- a2 : receiver |
| 3484 // -- ra : return address | 3469 // -- ra : return address |
| 3485 // -- a3 : scratch | 3470 // -- a3 : scratch |
| 3486 // ----------------------------------- | 3471 // ----------------------------------- |
| 3487 Label miss; | 3472 Label miss; |
| 3488 __ JumpIfSmi(a2, &miss); | 3473 __ JumpIfSmi(a2, &miss); |
| 3489 | 3474 |
| 3490 int receiver_count = receiver_maps->length(); | 3475 int receiver_count = receiver_maps->length(); |
| 3491 __ lw(a3, FieldMemOperand(a2, HeapObject::kMapOffset)); | 3476 __ lw(a3, FieldMemOperand(a2, HeapObject::kMapOffset)); |
| 3492 for (int i = 0; i < receiver_count; ++i) { | 3477 for (int i = 0; i < receiver_count; ++i) { |
| 3493 Handle<Map> map(receiver_maps->at(i)); | 3478 if (transitioned_maps->at(i).is_null()) { |
| 3494 Handle<Code> code(handler_stubs->at(i)); | 3479 __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET, eq, |
| 3495 if (transitioned_maps->at(i) == NULL) { | 3480 a3, Operand(receiver_maps->at(i))); |
| 3496 __ Jump(code, RelocInfo::CODE_TARGET, eq, a3, Operand(map)); | |
| 3497 } else { | 3481 } else { |
| 3498 Label next_map; | 3482 Label next_map; |
| 3499 __ Branch(&next_map, ne, a3, Operand(map)); | 3483 __ Branch(&next_map, ne, a3, Operand(receiver_maps->at(i))); |
| 3500 __ li(a3, Operand(Handle<Map>(transitioned_maps->at(i)))); | 3484 __ li(a3, Operand(transitioned_maps->at(i))); |
| 3501 __ Jump(code, RelocInfo::CODE_TARGET); | 3485 __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET); |
| 3502 __ bind(&next_map); | 3486 __ bind(&next_map); |
| 3503 } | 3487 } |
| 3504 } | 3488 } |
| 3505 | 3489 |
| 3506 __ bind(&miss); | 3490 __ bind(&miss); |
| 3507 Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss(); | 3491 Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
| 3508 __ Jump(miss_ic, RelocInfo::CODE_TARGET); | 3492 __ Jump(miss_ic, RelocInfo::CODE_TARGET); |
| 3509 | 3493 |
| 3510 // Return the generated code. | 3494 // Return the generated code. |
| 3511 return GetCode(NORMAL, NULL, MEGAMORPHIC); | 3495 return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC); |
| 3512 } | 3496 } |
| 3513 | 3497 |
| 3514 | 3498 |
| 3515 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { | 3499 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { |
| 3516 // a0 : argc | 3500 // a0 : argc |
| 3517 // a1 : constructor | 3501 // a1 : constructor |
| 3518 // ra : return address | 3502 // ra : return address |
| 3519 // [sp] : last argument | 3503 // [sp] : last argument |
| 3520 Label generic_stub_call; | 3504 Label generic_stub_call; |
| 3521 | 3505 |
| (...skipping 1205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4727 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); | 4711 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); |
| 4728 __ Jump(ic_miss, RelocInfo::CODE_TARGET); | 4712 __ Jump(ic_miss, RelocInfo::CODE_TARGET); |
| 4729 } | 4713 } |
| 4730 | 4714 |
| 4731 | 4715 |
| 4732 #undef __ | 4716 #undef __ |
| 4733 | 4717 |
| 4734 } } // namespace v8::internal | 4718 } } // namespace v8::internal |
| 4735 | 4719 |
| 4736 #endif // V8_TARGET_ARCH_MIPS | 4720 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |