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 Register object_reg, Handle<JSObject> holder, Register holder_reg, | 727 Register object_reg, Register holder_reg, Register scratch1, |
729 Register scratch1, Register scratch2, Handle<Name> name, Label* miss, | 728 Register scratch2, Handle<Name> name, Label* miss, |
730 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 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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(Register object_reg, | 858 Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, |
860 Handle<JSObject> holder, | |
861 Handle<Name> name, | 859 Handle<Name> name, |
862 Handle<Object> callback) { | 860 Handle<Object> callback) { |
863 Label miss; | 861 Label miss; |
864 | 862 |
865 Register reg = FrontendHeader(object_reg, holder, name, &miss); | 863 Register reg = FrontendHeader(object_reg, name, &miss); |
866 | 864 |
867 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { | 865 if (!holder()->HasFastProperties()) { |
| 866 ASSERT(!holder()->IsGlobalObject()); |
868 ASSERT(!reg.is(scratch2())); | 867 ASSERT(!reg.is(scratch2())); |
869 ASSERT(!reg.is(scratch3())); | 868 ASSERT(!reg.is(scratch3())); |
870 ASSERT(!reg.is(scratch4())); | 869 ASSERT(!reg.is(scratch4())); |
871 | 870 |
872 // Load the properties dictionary. | 871 // Load the properties dictionary. |
873 Register dictionary = scratch4(); | 872 Register dictionary = scratch4(); |
874 __ lw(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); | 873 __ lw(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); |
875 | 874 |
876 // Probe the dictionary. | 875 // Probe the dictionary. |
877 Label probe_done; | 876 Label probe_done; |
(...skipping 15 matching lines...) Expand all Loading... |
893 __ lw(scratch2(), FieldMemOperand(pointer, kValueOffset)); | 892 __ lw(scratch2(), FieldMemOperand(pointer, kValueOffset)); |
894 __ Branch(&miss, ne, scratch2(), Operand(callback)); | 893 __ Branch(&miss, ne, scratch2(), Operand(callback)); |
895 } | 894 } |
896 | 895 |
897 FrontendFooter(name, &miss); | 896 FrontendFooter(name, &miss); |
898 return reg; | 897 return reg; |
899 } | 898 } |
900 | 899 |
901 | 900 |
902 void NamedLoadHandlerCompiler::GenerateLoadField( | 901 void NamedLoadHandlerCompiler::GenerateLoadField( |
903 Register reg, Handle<JSObject> holder, FieldIndex field, | 902 Register reg, FieldIndex field, Representation representation) { |
904 Representation representation) { | |
905 if (!reg.is(receiver())) __ mov(receiver(), reg); | 903 if (!reg.is(receiver())) __ mov(receiver(), reg); |
906 LoadFieldStub stub(isolate(), field); | 904 LoadFieldStub stub(isolate(), field); |
907 GenerateTailCall(masm(), stub.GetCode()); | 905 GenerateTailCall(masm(), stub.GetCode()); |
908 } | 906 } |
909 | 907 |
910 | 908 |
911 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { | 909 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { |
912 // Return the constant value. | 910 // Return the constant value. |
913 __ li(v0, value); | 911 __ li(v0, value); |
914 __ Ret(); | 912 __ Ret(); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
957 ApiFunction fun(getter_address); | 955 ApiFunction fun(getter_address); |
958 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; | 956 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; |
959 ExternalReference ref = ExternalReference(&fun, type, isolate()); | 957 ExternalReference ref = ExternalReference(&fun, type, isolate()); |
960 __ li(getter_address_reg, Operand(ref)); | 958 __ li(getter_address_reg, Operand(ref)); |
961 | 959 |
962 CallApiGetterStub stub(isolate()); | 960 CallApiGetterStub stub(isolate()); |
963 __ TailCallStub(&stub); | 961 __ TailCallStub(&stub); |
964 } | 962 } |
965 | 963 |
966 | 964 |
967 void NamedLoadHandlerCompiler::GenerateLoadInterceptor( | 965 void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg, |
968 Register holder_reg, Handle<JSObject> interceptor_holder, | 966 LookupResult* lookup, |
969 LookupResult* lookup, Handle<Name> name) { | 967 Handle<Name> name) { |
970 ASSERT(interceptor_holder->HasNamedInterceptor()); | 968 ASSERT(holder()->HasNamedInterceptor()); |
971 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 969 ASSERT(!holder()->GetNamedInterceptor()->getter()->IsUndefined()); |
972 | 970 |
973 // 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 |
974 // and CALLBACKS, so inline only them, other cases may be added | 972 // and CALLBACKS, so inline only them, other cases may be added |
975 // later. | 973 // later. |
976 bool compile_followup_inline = false; | 974 bool compile_followup_inline = false; |
977 if (lookup->IsFound() && lookup->IsCacheable()) { | 975 if (lookup->IsFound() && lookup->IsCacheable()) { |
978 if (lookup->IsField()) { | 976 if (lookup->IsField()) { |
979 compile_followup_inline = true; | 977 compile_followup_inline = true; |
980 } else if (lookup->type() == CALLBACKS && | 978 } else if (lookup->type() == CALLBACKS && |
981 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { | 979 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { |
982 Handle<ExecutableAccessorInfo> callback( | 980 Handle<ExecutableAccessorInfo> callback( |
983 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); | 981 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); |
984 compile_followup_inline = | 982 compile_followup_inline = |
985 callback->getter() != NULL && | 983 callback->getter() != NULL && |
986 ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback, | 984 ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback, |
987 type()); | 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 = Frontend(receiver(), holder, name); | 1053 Register holder_reg = Frontend(receiver(), name); |
1056 | |
1057 // Stub never generated for non-global objects that require access | |
1058 // checks. | |
1059 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | |
1060 | 1054 |
1061 __ Push(receiver(), holder_reg); // Receiver. | 1055 __ Push(receiver(), holder_reg); // Receiver. |
1062 __ li(at, Operand(callback)); // Callback info. | 1056 __ li(at, Operand(callback)); // Callback info. |
1063 __ push(at); | 1057 __ push(at); |
1064 __ li(at, Operand(name)); | 1058 __ li(at, Operand(name)); |
1065 __ Push(at, value()); | 1059 __ Push(at, value()); |
1066 | 1060 |
1067 // Do tail-call to the runtime system. | 1061 // Do tail-call to the runtime system. |
1068 ExternalReference store_callback_property = | 1062 ExternalReference store_callback_property = |
1069 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... |
1116 } | 1110 } |
1117 __ Ret(); | 1111 __ Ret(); |
1118 } | 1112 } |
1119 | 1113 |
1120 | 1114 |
1121 #undef __ | 1115 #undef __ |
1122 #define __ ACCESS_MASM(masm()) | 1116 #define __ ACCESS_MASM(masm()) |
1123 | 1117 |
1124 | 1118 |
1125 Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( | 1119 Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( |
1126 Handle<JSObject> object, Handle<Name> name) { | 1120 Handle<Name> name) { |
1127 __ Push(receiver(), this->name(), value()); | 1121 __ Push(receiver(), this->name(), value()); |
1128 | 1122 |
1129 // Do tail-call to the runtime system. | 1123 // Do tail-call to the runtime system. |
1130 ExternalReference store_ic_property = ExternalReference( | 1124 ExternalReference store_ic_property = ExternalReference( |
1131 IC_Utility(IC::kStorePropertyWithInterceptor), isolate()); | 1125 IC_Utility(IC::kStorePropertyWithInterceptor), isolate()); |
1132 __ TailCallExternalReference(store_ic_property, 3, 1); | 1126 __ TailCallExternalReference(store_ic_property, 3, 1); |
1133 | 1127 |
1134 // Return the generated code. | 1128 // Return the generated code. |
1135 return GetCode(kind(), Code::FAST, name); | 1129 return GetCode(kind(), Code::FAST, name); |
1136 } | 1130 } |
1137 | 1131 |
1138 | 1132 |
1139 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( | 1133 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( |
1140 Handle<JSObject> last, Handle<Name> name) { | 1134 Handle<Name> name) { |
1141 NonexistentFrontend(last, name); | 1135 NonexistentFrontend(name); |
1142 | 1136 |
1143 // 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. |
1144 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); | 1138 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); |
1145 __ Ret(); | 1139 __ Ret(); |
1146 | 1140 |
1147 // Return the generated code. | 1141 // Return the generated code. |
1148 return GetCode(kind(), Code::FAST, name); | 1142 return GetCode(kind(), Code::FAST, name); |
1149 } | 1143 } |
1150 | 1144 |
1151 | 1145 |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1218 } | 1212 } |
1219 __ Ret(); | 1213 __ Ret(); |
1220 } | 1214 } |
1221 | 1215 |
1222 | 1216 |
1223 #undef __ | 1217 #undef __ |
1224 #define __ ACCESS_MASM(masm()) | 1218 #define __ ACCESS_MASM(masm()) |
1225 | 1219 |
1226 | 1220 |
1227 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( | 1221 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( |
1228 Handle<GlobalObject> global, Handle<PropertyCell> cell, Handle<Name> name, | 1222 Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) { |
1229 bool is_dont_delete) { | |
1230 Label miss; | 1223 Label miss; |
1231 | 1224 |
1232 FrontendHeader(receiver(), global, name, &miss); | 1225 FrontendHeader(receiver(), name, &miss); |
1233 | 1226 |
1234 // Get the value from the cell. | 1227 // Get the value from the cell. |
1235 Register result = StoreIC::ValueRegister(); | 1228 Register result = StoreIC::ValueRegister(); |
1236 __ li(result, Operand(cell)); | 1229 __ li(result, Operand(cell)); |
1237 __ lw(result, FieldMemOperand(result, Cell::kValueOffset)); | 1230 __ lw(result, FieldMemOperand(result, Cell::kValueOffset)); |
1238 | 1231 |
1239 // Check for deleted property if property can actually be deleted. | 1232 // Check for deleted property if property can actually be deleted. |
1240 if (!is_dont_delete) { | 1233 if (!is_dont_delete) { |
1241 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 1234 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
1242 __ Branch(&miss, eq, result, Operand(at)); | 1235 __ Branch(&miss, eq, result, Operand(at)); |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1385 | 1378 |
1386 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 1379 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
1387 } | 1380 } |
1388 | 1381 |
1389 | 1382 |
1390 #undef __ | 1383 #undef __ |
1391 | 1384 |
1392 } } // namespace v8::internal | 1385 } } // namespace v8::internal |
1393 | 1386 |
1394 #endif // V8_TARGET_ARCH_MIPS | 1387 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |