| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_MIPS | 7 #if V8_TARGET_ARCH_MIPS |
| 8 | 8 |
| 9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
| 10 #include "src/ic-inl.h" | 10 #include "src/ic-inl.h" |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 290 GenerateDictionaryNegativeLookup( | 290 GenerateDictionaryNegativeLookup( |
| 291 masm, miss, holder_reg, name, scratch1(), scratch2()); | 291 masm, miss, holder_reg, name, scratch1(), scratch2()); |
| 292 } | 292 } |
| 293 } | 293 } |
| 294 | 294 |
| 295 | 295 |
| 296 // Generate StoreTransition code, value is passed in a0 register. | 296 // Generate StoreTransition code, value is passed in a0 register. |
| 297 // After executing generated code, the receiver_reg and name_reg | 297 // After executing generated code, the receiver_reg and name_reg |
| 298 // may be clobbered. | 298 // may be clobbered. |
| 299 void NamedStoreHandlerCompiler::GenerateStoreTransition( | 299 void NamedStoreHandlerCompiler::GenerateStoreTransition( |
| 300 MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup, | 300 MacroAssembler* masm, LookupResult* lookup, Handle<Map> transition, |
| 301 Handle<Map> transition, Handle<Name> name, Register receiver_reg, | 301 Handle<Name> name, Register receiver_reg, Register storage_reg, |
| 302 Register storage_reg, Register value_reg, Register scratch1, | 302 Register value_reg, Register scratch1, Register scratch2, Register scratch3, |
| 303 Register scratch2, Register scratch3, Label* miss_label, Label* slow) { | 303 Label* miss_label, Label* slow) { |
| 304 // a0 : value. | 304 // a0 : value. |
| 305 Label exit; | 305 Label exit; |
| 306 | 306 |
| 307 int descriptor = transition->LastAdded(); | 307 int descriptor = transition->LastAdded(); |
| 308 DescriptorArray* descriptors = transition->instance_descriptors(); | 308 DescriptorArray* descriptors = transition->instance_descriptors(); |
| 309 PropertyDetails details = descriptors->GetDetails(descriptor); | 309 PropertyDetails details = descriptors->GetDetails(descriptor); |
| 310 Representation representation = details.representation(); | 310 Representation representation = details.representation(); |
| 311 ASSERT(!representation.IsNone()); | 311 ASSERT(!representation.IsNone()); |
| 312 | 312 |
| 313 if (details.type() == CONSTANT) { | 313 if (details.type() == CONSTANT) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 350 | 350 |
| 351 __ bind(&heap_number); | 351 __ bind(&heap_number); |
| 352 __ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex, | 352 __ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex, |
| 353 miss_label, DONT_DO_SMI_CHECK); | 353 miss_label, DONT_DO_SMI_CHECK); |
| 354 __ ldc1(f4, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); | 354 __ ldc1(f4, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); |
| 355 | 355 |
| 356 __ bind(&do_store); | 356 __ bind(&do_store); |
| 357 __ sdc1(f4, FieldMemOperand(storage_reg, HeapNumber::kValueOffset)); | 357 __ sdc1(f4, FieldMemOperand(storage_reg, HeapNumber::kValueOffset)); |
| 358 } | 358 } |
| 359 | 359 |
| 360 // Stub never generated for non-global objects that require access | 360 // Stub never generated for objects that require access checks. |
| 361 // checks. | 361 ASSERT(!transition->is_access_check_needed()); |
| 362 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | |
| 363 | 362 |
| 364 // Perform map transition for the receiver if necessary. | 363 // Perform map transition for the receiver if necessary. |
| 365 if (details.type() == FIELD && | 364 if (details.type() == FIELD && |
| 366 object->map()->unused_property_fields() == 0) { | 365 Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { |
| 367 // The properties must be extended before we can store the value. | 366 // The properties must be extended before we can store the value. |
| 368 // We jump to a runtime call that extends the properties array. | 367 // We jump to a runtime call that extends the properties array. |
| 369 __ push(receiver_reg); | 368 __ push(receiver_reg); |
| 370 __ li(a2, Operand(transition)); | 369 __ li(a2, Operand(transition)); |
| 371 __ Push(a2, a0); | 370 __ Push(a2, a0); |
| 372 __ TailCallExternalReference( | 371 __ TailCallExternalReference( |
| 373 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), | 372 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), |
| 374 masm->isolate()), | 373 masm->isolate()), |
| 375 3, 1); | 374 3, 1); |
| 376 return; | 375 return; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 396 __ mov(v0, a0); | 395 __ mov(v0, a0); |
| 397 return; | 396 return; |
| 398 } | 397 } |
| 399 | 398 |
| 400 int index = transition->instance_descriptors()->GetFieldIndex( | 399 int index = transition->instance_descriptors()->GetFieldIndex( |
| 401 transition->LastAdded()); | 400 transition->LastAdded()); |
| 402 | 401 |
| 403 // Adjust for the number of properties stored in the object. Even in the | 402 // Adjust for the number of properties stored in the object. Even in the |
| 404 // face of a transition we can use the old map here because the size of the | 403 // face of a transition we can use the old map here because the size of the |
| 405 // object and the number of in-object properties is not going to change. | 404 // object and the number of in-object properties is not going to change. |
| 406 index -= object->map()->inobject_properties(); | 405 index -= transition->inobject_properties(); |
| 407 | 406 |
| 408 // TODO(verwaest): Share this code as a code stub. | 407 // TODO(verwaest): Share this code as a code stub. |
| 409 SmiCheck smi_check = representation.IsTagged() | 408 SmiCheck smi_check = representation.IsTagged() |
| 410 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; | 409 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; |
| 411 if (index < 0) { | 410 if (index < 0) { |
| 412 // Set the property straight into the object. | 411 // Set the property straight into the object. |
| 413 int offset = object->map()->instance_size() + (index * kPointerSize); | 412 int offset = transition->instance_size() + (index * kPointerSize); |
| 414 if (representation.IsDouble()) { | 413 if (representation.IsDouble()) { |
| 415 __ sw(storage_reg, FieldMemOperand(receiver_reg, offset)); | 414 __ sw(storage_reg, FieldMemOperand(receiver_reg, offset)); |
| 416 } else { | 415 } else { |
| 417 __ sw(value_reg, FieldMemOperand(receiver_reg, offset)); | 416 __ sw(value_reg, FieldMemOperand(receiver_reg, offset)); |
| 418 } | 417 } |
| 419 | 418 |
| 420 if (!representation.IsSmi()) { | 419 if (!representation.IsSmi()) { |
| 421 // Update the write barrier for the array address. | 420 // Update the write barrier for the array address. |
| 422 if (!representation.IsDouble()) { | 421 if (!representation.IsDouble()) { |
| 423 __ mov(storage_reg, value_reg); | 422 __ mov(storage_reg, value_reg); |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 718 Handle<Code> code) { | 717 Handle<Code> code) { |
| 719 __ Jump(code, RelocInfo::CODE_TARGET); | 718 __ Jump(code, RelocInfo::CODE_TARGET); |
| 720 } | 719 } |
| 721 | 720 |
| 722 | 721 |
| 723 #undef __ | 722 #undef __ |
| 724 #define __ ACCESS_MASM(masm()) | 723 #define __ ACCESS_MASM(masm()) |
| 725 | 724 |
| 726 | 725 |
| 727 Register PropertyHandlerCompiler::CheckPrototypes( | 726 Register PropertyHandlerCompiler::CheckPrototypes( |
| 728 Handle<HeapType> type, Register object_reg, Handle<JSObject> holder, | 727 Register object_reg, Register holder_reg, Register scratch1, |
| 729 Register holder_reg, Register scratch1, Register scratch2, | 728 Register scratch2, Handle<Name> name, Label* miss, |
| 730 Handle<Name> name, Label* miss, PrototypeCheckType check) { | 729 PrototypeCheckType check) { |
| 731 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); | 730 Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); |
| 732 | 731 |
| 733 // Make sure there's no overlap between holder and object registers. | 732 // Make sure there's no overlap between holder and object registers. |
| 734 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 733 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
| 735 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 734 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
| 736 && !scratch2.is(scratch1)); | 735 && !scratch2.is(scratch1)); |
| 737 | 736 |
| 738 // Keep track of the current object in register reg. | 737 // Keep track of the current object in register reg. |
| 739 Register reg = object_reg; | 738 Register reg = object_reg; |
| 740 int depth = 0; | 739 int depth = 0; |
| 741 | 740 |
| 742 Handle<JSObject> current = Handle<JSObject>::null(); | 741 Handle<JSObject> current = Handle<JSObject>::null(); |
| 743 if (type->IsConstant()) { | 742 if (type()->IsConstant()) { |
| 744 current = Handle<JSObject>::cast(type->AsConstant()->Value()); | 743 current = Handle<JSObject>::cast(type()->AsConstant()->Value()); |
| 745 } | 744 } |
| 746 Handle<JSObject> prototype = Handle<JSObject>::null(); | 745 Handle<JSObject> prototype = Handle<JSObject>::null(); |
| 747 Handle<Map> current_map = receiver_map; | 746 Handle<Map> current_map = receiver_map; |
| 748 Handle<Map> holder_map(holder->map()); | 747 Handle<Map> holder_map(holder()->map()); |
| 749 // Traverse the prototype chain and check the maps in the prototype chain for | 748 // Traverse the prototype chain and check the maps in the prototype chain for |
| 750 // fast and global objects or do negative lookup for normal objects. | 749 // fast and global objects or do negative lookup for normal objects. |
| 751 while (!current_map.is_identical_to(holder_map)) { | 750 while (!current_map.is_identical_to(holder_map)) { |
| 752 ++depth; | 751 ++depth; |
| 753 | 752 |
| 754 // Only global objects and objects that do not require access | 753 // Only global objects and objects that do not require access |
| 755 // checks are allowed in stubs. | 754 // checks are allowed in stubs. |
| 756 ASSERT(current_map->IsJSGlobalProxyMap() || | 755 ASSERT(current_map->IsJSGlobalProxyMap() || |
| 757 !current_map->is_access_check_needed()); | 756 !current_map->is_access_check_needed()); |
| 758 | 757 |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 849 if (!miss->is_unused()) { | 848 if (!miss->is_unused()) { |
| 850 Label success; | 849 Label success; |
| 851 __ Branch(&success); | 850 __ Branch(&success); |
| 852 GenerateRestoreName(masm(), miss, name); | 851 GenerateRestoreName(masm(), miss, name); |
| 853 TailCallBuiltin(masm(), MissBuiltin(kind())); | 852 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 854 __ bind(&success); | 853 __ bind(&success); |
| 855 } | 854 } |
| 856 } | 855 } |
| 857 | 856 |
| 858 | 857 |
| 859 Register NamedLoadHandlerCompiler::CallbackFrontend(Handle<HeapType> type, | 858 Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, |
| 860 Register object_reg, | |
| 861 Handle<JSObject> holder, | |
| 862 Handle<Name> name, | 859 Handle<Name> name, |
| 863 Handle<Object> callback) { | 860 Handle<Object> callback) { |
| 864 Label miss; | 861 Label miss; |
| 865 | 862 |
| 866 Register reg = FrontendHeader(type, object_reg, holder, name, &miss); | 863 Register reg = FrontendHeader(object_reg, name, &miss); |
| 867 | 864 |
| 868 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { | 865 if (!holder()->HasFastProperties()) { |
| 866 ASSERT(!holder()->IsGlobalObject()); |
| 869 ASSERT(!reg.is(scratch2())); | 867 ASSERT(!reg.is(scratch2())); |
| 870 ASSERT(!reg.is(scratch3())); | 868 ASSERT(!reg.is(scratch3())); |
| 871 ASSERT(!reg.is(scratch4())); | 869 ASSERT(!reg.is(scratch4())); |
| 872 | 870 |
| 873 // Load the properties dictionary. | 871 // Load the properties dictionary. |
| 874 Register dictionary = scratch4(); | 872 Register dictionary = scratch4(); |
| 875 __ lw(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); | 873 __ lw(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); |
| 876 | 874 |
| 877 // Probe the dictionary. | 875 // Probe the dictionary. |
| 878 Label probe_done; | 876 Label probe_done; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 894 __ lw(scratch2(), FieldMemOperand(pointer, kValueOffset)); | 892 __ lw(scratch2(), FieldMemOperand(pointer, kValueOffset)); |
| 895 __ Branch(&miss, ne, scratch2(), Operand(callback)); | 893 __ Branch(&miss, ne, scratch2(), Operand(callback)); |
| 896 } | 894 } |
| 897 | 895 |
| 898 FrontendFooter(name, &miss); | 896 FrontendFooter(name, &miss); |
| 899 return reg; | 897 return reg; |
| 900 } | 898 } |
| 901 | 899 |
| 902 | 900 |
| 903 void NamedLoadHandlerCompiler::GenerateLoadField( | 901 void NamedLoadHandlerCompiler::GenerateLoadField( |
| 904 Register reg, Handle<JSObject> holder, FieldIndex field, | 902 Register reg, FieldIndex field, Representation representation) { |
| 905 Representation representation) { | |
| 906 if (!reg.is(receiver())) __ mov(receiver(), reg); | 903 if (!reg.is(receiver())) __ mov(receiver(), reg); |
| 907 LoadFieldStub stub(isolate(), field); | 904 LoadFieldStub stub(isolate(), field); |
| 908 GenerateTailCall(masm(), stub.GetCode()); | 905 GenerateTailCall(masm(), stub.GetCode()); |
| 909 } | 906 } |
| 910 | 907 |
| 911 | 908 |
| 912 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { | 909 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { |
| 913 // Return the constant value. | 910 // Return the constant value. |
| 914 __ li(v0, value); | 911 __ li(v0, value); |
| 915 __ Ret(); | 912 __ Ret(); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 958 ApiFunction fun(getter_address); | 955 ApiFunction fun(getter_address); |
| 959 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; | 956 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; |
| 960 ExternalReference ref = ExternalReference(&fun, type, isolate()); | 957 ExternalReference ref = ExternalReference(&fun, type, isolate()); |
| 961 __ li(getter_address_reg, Operand(ref)); | 958 __ li(getter_address_reg, Operand(ref)); |
| 962 | 959 |
| 963 CallApiGetterStub stub(isolate()); | 960 CallApiGetterStub stub(isolate()); |
| 964 __ TailCallStub(&stub); | 961 __ TailCallStub(&stub); |
| 965 } | 962 } |
| 966 | 963 |
| 967 | 964 |
| 968 void NamedLoadHandlerCompiler::GenerateLoadInterceptor( | 965 void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg, |
| 969 Register holder_reg, Handle<Object> object, | 966 LookupResult* lookup, |
| 970 Handle<JSObject> interceptor_holder, LookupResult* lookup, | 967 Handle<Name> name) { |
| 971 Handle<Name> name) { | 968 ASSERT(holder()->HasNamedInterceptor()); |
| 972 ASSERT(interceptor_holder->HasNamedInterceptor()); | 969 ASSERT(!holder()->GetNamedInterceptor()->getter()->IsUndefined()); |
| 973 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | |
| 974 | 970 |
| 975 // So far the most popular follow ups for interceptor loads are FIELD | 971 // So far the most popular follow ups for interceptor loads are FIELD |
| 976 // and CALLBACKS, so inline only them, other cases may be added | 972 // and CALLBACKS, so inline only them, other cases may be added |
| 977 // later. | 973 // later. |
| 978 bool compile_followup_inline = false; | 974 bool compile_followup_inline = false; |
| 979 if (lookup->IsFound() && lookup->IsCacheable()) { | 975 if (lookup->IsFound() && lookup->IsCacheable()) { |
| 980 if (lookup->IsField()) { | 976 if (lookup->IsField()) { |
| 981 compile_followup_inline = true; | 977 compile_followup_inline = true; |
| 982 } else if (lookup->type() == CALLBACKS && | 978 } else if (lookup->type() == CALLBACKS && |
| 983 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { | 979 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { |
| 984 ExecutableAccessorInfo* callback = | 980 Handle<ExecutableAccessorInfo> callback( |
| 985 ExecutableAccessorInfo::cast(lookup->GetCallbackObject()); | 981 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); |
| 986 compile_followup_inline = callback->getter() != NULL && | 982 compile_followup_inline = |
| 987 callback->IsCompatibleReceiver(*object); | 983 callback->getter() != NULL && |
| 984 ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback, |
| 985 type()); |
| 988 } | 986 } |
| 989 } | 987 } |
| 990 | 988 |
| 991 if (compile_followup_inline) { | 989 if (compile_followup_inline) { |
| 992 // Compile the interceptor call, followed by inline code to load the | 990 // Compile the interceptor call, followed by inline code to load the |
| 993 // property from further up the prototype chain if the call fails. | 991 // property from further up the prototype chain if the call fails. |
| 994 // Check that the maps haven't changed. | 992 // Check that the maps haven't changed. |
| 995 ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1())); | 993 ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1())); |
| 996 | 994 |
| 997 // Preserve the receiver register explicitly whenever it is different from | 995 // Preserve the receiver register explicitly whenever it is different from |
| 998 // the holder and it is needed should the interceptor return without any | 996 // the holder and it is needed should the interceptor return without any |
| 999 // result. The CALLBACKS case needs the receiver to be passed into C++ code, | 997 // result. The CALLBACKS case needs the receiver to be passed into C++ code, |
| 1000 // the FIELD case might cause a miss during the prototype check. | 998 // the FIELD case might cause a miss during the prototype check. |
| 1001 bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder(); | 999 bool must_perfrom_prototype_check = *holder() != lookup->holder(); |
| 1002 bool must_preserve_receiver_reg = !receiver().is(holder_reg) && | 1000 bool must_preserve_receiver_reg = !receiver().is(holder_reg) && |
| 1003 (lookup->type() == CALLBACKS || must_perfrom_prototype_check); | 1001 (lookup->type() == CALLBACKS || must_perfrom_prototype_check); |
| 1004 | 1002 |
| 1005 // Save necessary data before invoking an interceptor. | 1003 // Save necessary data before invoking an interceptor. |
| 1006 // Requires a frame to make GC aware of pushed pointers. | 1004 // Requires a frame to make GC aware of pushed pointers. |
| 1007 { | 1005 { |
| 1008 FrameScope frame_scope(masm(), StackFrame::INTERNAL); | 1006 FrameScope frame_scope(masm(), StackFrame::INTERNAL); |
| 1009 if (must_preserve_receiver_reg) { | 1007 if (must_preserve_receiver_reg) { |
| 1010 __ Push(receiver(), holder_reg, this->name()); | 1008 __ Push(receiver(), holder_reg, this->name()); |
| 1011 } else { | 1009 } else { |
| 1012 __ Push(holder_reg, this->name()); | 1010 __ Push(holder_reg, this->name()); |
| 1013 } | 1011 } |
| 1014 // Invoke an interceptor. Note: map checks from receiver to | 1012 // Invoke an interceptor. Note: map checks from receiver to |
| 1015 // interceptor's holder has been compiled before (see a caller | 1013 // interceptor's holder has been compiled before (see a caller |
| 1016 // of this method). | 1014 // of this method). |
| 1017 CompileCallLoadPropertyWithInterceptor( | 1015 CompileCallLoadPropertyWithInterceptor( |
| 1018 masm(), receiver(), holder_reg, this->name(), interceptor_holder, | 1016 masm(), receiver(), holder_reg, this->name(), holder(), |
| 1019 IC::kLoadPropertyWithInterceptorOnly); | 1017 IC::kLoadPropertyWithInterceptorOnly); |
| 1020 | 1018 |
| 1021 // Check if interceptor provided a value for property. If it's | 1019 // Check if interceptor provided a value for property. If it's |
| 1022 // the case, return immediately. | 1020 // the case, return immediately. |
| 1023 Label interceptor_failed; | 1021 Label interceptor_failed; |
| 1024 __ LoadRoot(scratch1(), Heap::kNoInterceptorResultSentinelRootIndex); | 1022 __ LoadRoot(scratch1(), Heap::kNoInterceptorResultSentinelRootIndex); |
| 1025 __ Branch(&interceptor_failed, eq, v0, Operand(scratch1())); | 1023 __ Branch(&interceptor_failed, eq, v0, Operand(scratch1())); |
| 1026 frame_scope.GenerateLeaveFrame(); | 1024 frame_scope.GenerateLeaveFrame(); |
| 1027 __ Ret(); | 1025 __ Ret(); |
| 1028 | 1026 |
| 1029 __ bind(&interceptor_failed); | 1027 __ bind(&interceptor_failed); |
| 1030 __ pop(this->name()); | 1028 __ pop(this->name()); |
| 1031 __ pop(holder_reg); | 1029 __ pop(holder_reg); |
| 1032 if (must_preserve_receiver_reg) { | 1030 if (must_preserve_receiver_reg) { |
| 1033 __ pop(receiver()); | 1031 __ pop(receiver()); |
| 1034 } | 1032 } |
| 1035 // Leave the internal frame. | 1033 // Leave the internal frame. |
| 1036 } | 1034 } |
| 1037 GenerateLoadPostInterceptor(holder_reg, interceptor_holder, name, lookup); | 1035 GenerateLoadPostInterceptor(holder_reg, name, lookup); |
| 1038 } else { // !compile_followup_inline | 1036 } else { // !compile_followup_inline |
| 1039 // Call the runtime system to load the interceptor. | 1037 // Call the runtime system to load the interceptor. |
| 1040 // Check that the maps haven't changed. | 1038 // Check that the maps haven't changed. |
| 1041 PushInterceptorArguments(masm(), receiver(), holder_reg, | 1039 PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(), |
| 1042 this->name(), interceptor_holder); | 1040 holder()); |
| 1043 | 1041 |
| 1044 ExternalReference ref = ExternalReference( | 1042 ExternalReference ref = ExternalReference( |
| 1045 IC_Utility(IC::kLoadPropertyWithInterceptor), isolate()); | 1043 IC_Utility(IC::kLoadPropertyWithInterceptor), isolate()); |
| 1046 __ TailCallExternalReference( | 1044 __ TailCallExternalReference( |
| 1047 ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1); | 1045 ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1); |
| 1048 } | 1046 } |
| 1049 } | 1047 } |
| 1050 | 1048 |
| 1051 | 1049 |
| 1052 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( | 1050 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( |
| 1053 Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name, | 1051 Handle<JSObject> object, Handle<Name> name, |
| 1054 Handle<ExecutableAccessorInfo> callback) { | 1052 Handle<ExecutableAccessorInfo> callback) { |
| 1055 Register holder_reg = | 1053 Register holder_reg = Frontend(receiver(), name); |
| 1056 Frontend(IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); | |
| 1057 | |
| 1058 // Stub never generated for non-global objects that require access | |
| 1059 // checks. | |
| 1060 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | |
| 1061 | 1054 |
| 1062 __ Push(receiver(), holder_reg); // Receiver. | 1055 __ Push(receiver(), holder_reg); // Receiver. |
| 1063 __ li(at, Operand(callback)); // Callback info. | 1056 __ li(at, Operand(callback)); // Callback info. |
| 1064 __ push(at); | 1057 __ push(at); |
| 1065 __ li(at, Operand(name)); | 1058 __ li(at, Operand(name)); |
| 1066 __ Push(at, value()); | 1059 __ Push(at, value()); |
| 1067 | 1060 |
| 1068 // Do tail-call to the runtime system. | 1061 // Do tail-call to the runtime system. |
| 1069 ExternalReference store_callback_property = | 1062 ExternalReference store_callback_property = |
| 1070 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); | 1063 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1117 } | 1110 } |
| 1118 __ Ret(); | 1111 __ Ret(); |
| 1119 } | 1112 } |
| 1120 | 1113 |
| 1121 | 1114 |
| 1122 #undef __ | 1115 #undef __ |
| 1123 #define __ ACCESS_MASM(masm()) | 1116 #define __ ACCESS_MASM(masm()) |
| 1124 | 1117 |
| 1125 | 1118 |
| 1126 Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( | 1119 Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( |
| 1127 Handle<JSObject> object, Handle<Name> name) { | 1120 Handle<Name> name) { |
| 1128 __ Push(receiver(), this->name(), value()); | 1121 __ Push(receiver(), this->name(), value()); |
| 1129 | 1122 |
| 1130 // Do tail-call to the runtime system. | 1123 // Do tail-call to the runtime system. |
| 1131 ExternalReference store_ic_property = ExternalReference( | 1124 ExternalReference store_ic_property = ExternalReference( |
| 1132 IC_Utility(IC::kStorePropertyWithInterceptor), isolate()); | 1125 IC_Utility(IC::kStorePropertyWithInterceptor), isolate()); |
| 1133 __ TailCallExternalReference(store_ic_property, 3, 1); | 1126 __ TailCallExternalReference(store_ic_property, 3, 1); |
| 1134 | 1127 |
| 1135 // Return the generated code. | 1128 // Return the generated code. |
| 1136 return GetCode(kind(), Code::FAST, name); | 1129 return GetCode(kind(), Code::FAST, name); |
| 1137 } | 1130 } |
| 1138 | 1131 |
| 1139 | 1132 |
| 1140 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( | 1133 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( |
| 1141 Handle<HeapType> type, Handle<JSObject> last, Handle<Name> name) { | 1134 Handle<Name> name) { |
| 1142 NonexistentFrontend(type, last, name); | 1135 NonexistentFrontend(name); |
| 1143 | 1136 |
| 1144 // Return undefined if maps of the full prototype chain is still the same. | 1137 // Return undefined if maps of the full prototype chain is still the same. |
| 1145 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); | 1138 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); |
| 1146 __ Ret(); | 1139 __ Ret(); |
| 1147 | 1140 |
| 1148 // Return the generated code. | 1141 // Return the generated code. |
| 1149 return GetCode(kind(), Code::FAST, name); | 1142 return GetCode(kind(), Code::FAST, name); |
| 1150 } | 1143 } |
| 1151 | 1144 |
| 1152 | 1145 |
| 1153 Register* PropertyAccessCompiler::load_calling_convention() { | 1146 Register* PropertyAccessCompiler::load_calling_convention() { |
| 1154 // receiver, name, scratch1, scratch2, scratch3, scratch4. | 1147 // receiver, name, scratch1, scratch2, scratch3, scratch4. |
| 1155 Register receiver = LoadIC::ReceiverRegister(); | 1148 Register receiver = LoadIC::ReceiverRegister(); |
| 1156 Register name = LoadIC::NameRegister(); | 1149 Register name = LoadIC::NameRegister(); |
| 1157 static Register registers[] = { receiver, name, a3, a0, t0, t1 }; | 1150 static Register registers[] = { receiver, name, a3, a0, t0, t1 }; |
| 1158 return registers; | 1151 return registers; |
| 1159 } | 1152 } |
| 1160 | 1153 |
| 1161 | 1154 |
| 1162 Register* PropertyAccessCompiler::store_calling_convention() { | 1155 Register* PropertyAccessCompiler::store_calling_convention() { |
| 1163 // receiver, name, scratch1, scratch2, scratch3. | 1156 // receiver, name, scratch1, scratch2, scratch3. |
| 1164 Register receiver = StoreIC::ReceiverRegister(); | 1157 Register receiver = StoreIC::ReceiverRegister(); |
| 1165 Register name = StoreIC::NameRegister(); | 1158 Register name = StoreIC::NameRegister(); |
| 1159 ASSERT(a3.is(KeyedStoreIC::MapRegister())); |
| 1166 static Register registers[] = { receiver, name, a3, t0, t1 }; | 1160 static Register registers[] = { receiver, name, a3, t0, t1 }; |
| 1167 return registers; | 1161 return registers; |
| 1168 } | 1162 } |
| 1169 | 1163 |
| 1170 | 1164 |
| 1171 Register* PropertyAccessCompiler::keyed_store_calling_convention() { | |
| 1172 // receiver, name, scratch1/map, scratch2, scratch3. | |
| 1173 Register receiver = KeyedStoreIC::ReceiverRegister(); | |
| 1174 Register name = KeyedStoreIC::NameRegister(); | |
| 1175 Register map = KeyedStoreIC::MapRegister(); | |
| 1176 static Register registers[] = { receiver, name, map, t0, t1 }; | |
| 1177 return registers; | |
| 1178 } | |
| 1179 | |
| 1180 | |
| 1181 Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); } | 1165 Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); } |
| 1182 | 1166 |
| 1183 | 1167 |
| 1184 #undef __ | 1168 #undef __ |
| 1185 #define __ ACCESS_MASM(masm) | 1169 #define __ ACCESS_MASM(masm) |
| 1186 | 1170 |
| 1187 | 1171 |
| 1188 void NamedLoadHandlerCompiler::GenerateLoadViaGetter( | 1172 void NamedLoadHandlerCompiler::GenerateLoadViaGetter( |
| 1189 MacroAssembler* masm, Handle<HeapType> type, Register receiver, | 1173 MacroAssembler* masm, Handle<HeapType> type, Register receiver, |
| 1190 Handle<JSFunction> getter) { | 1174 Handle<JSFunction> getter) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1219 } | 1203 } |
| 1220 __ Ret(); | 1204 __ Ret(); |
| 1221 } | 1205 } |
| 1222 | 1206 |
| 1223 | 1207 |
| 1224 #undef __ | 1208 #undef __ |
| 1225 #define __ ACCESS_MASM(masm()) | 1209 #define __ ACCESS_MASM(masm()) |
| 1226 | 1210 |
| 1227 | 1211 |
| 1228 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( | 1212 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( |
| 1229 Handle<HeapType> type, Handle<GlobalObject> global, | |
| 1230 Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) { | 1213 Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) { |
| 1231 Label miss; | 1214 Label miss; |
| 1232 | 1215 |
| 1233 FrontendHeader(type, receiver(), global, name, &miss); | 1216 FrontendHeader(receiver(), name, &miss); |
| 1234 | 1217 |
| 1235 // Get the value from the cell. | 1218 // Get the value from the cell. |
| 1236 __ li(a3, Operand(cell)); | 1219 Register result = StoreIC::ValueRegister(); |
| 1237 __ lw(t0, FieldMemOperand(a3, Cell::kValueOffset)); | 1220 __ li(result, Operand(cell)); |
| 1221 __ lw(result, FieldMemOperand(result, Cell::kValueOffset)); |
| 1238 | 1222 |
| 1239 // Check for deleted property if property can actually be deleted. | 1223 // Check for deleted property if property can actually be deleted. |
| 1240 if (!is_dont_delete) { | 1224 if (!is_dont_delete) { |
| 1241 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 1225 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 1242 __ Branch(&miss, eq, t0, Operand(at)); | 1226 __ Branch(&miss, eq, result, Operand(at)); |
| 1243 } | 1227 } |
| 1244 | 1228 |
| 1245 Counters* counters = isolate()->counters(); | 1229 Counters* counters = isolate()->counters(); |
| 1246 __ IncrementCounter(counters->named_load_global_stub(), 1, a1, a3); | 1230 __ IncrementCounter(counters->named_load_global_stub(), 1, a1, a3); |
| 1247 __ Ret(USE_DELAY_SLOT); | 1231 __ Ret(USE_DELAY_SLOT); |
| 1248 __ mov(v0, t0); | 1232 __ mov(v0, result); |
| 1249 | 1233 |
| 1250 FrontendFooter(name, &miss); | 1234 FrontendFooter(name, &miss); |
| 1251 | 1235 |
| 1252 // Return the generated code. | 1236 // Return the generated code. |
| 1253 return GetCode(kind(), Code::NORMAL, name); | 1237 return GetCode(kind(), Code::NORMAL, name); |
| 1254 } | 1238 } |
| 1255 | 1239 |
| 1256 | 1240 |
| 1257 Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types, | 1241 Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types, |
| 1258 CodeHandleList* handlers, | 1242 CodeHandleList* handlers, |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1385 | 1369 |
| 1386 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 1370 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
| 1387 } | 1371 } |
| 1388 | 1372 |
| 1389 | 1373 |
| 1390 #undef __ | 1374 #undef __ |
| 1391 | 1375 |
| 1392 } } // namespace v8::internal | 1376 } } // namespace v8::internal |
| 1393 | 1377 |
| 1394 #endif // V8_TARGET_ARCH_MIPS | 1378 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |