| 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_X64 | 7 #if V8_TARGET_ARCH_X64 |
| 8 | 8 |
| 9 #include "src/arguments.h" | 9 #include "src/arguments.h" |
| 10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
| (...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 367 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { | 367 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { |
| 368 GenerateDictionaryNegativeLookup( | 368 GenerateDictionaryNegativeLookup( |
| 369 masm, miss, holder_reg, name, scratch1(), scratch2()); | 369 masm, miss, holder_reg, name, scratch1(), scratch2()); |
| 370 } | 370 } |
| 371 } | 371 } |
| 372 | 372 |
| 373 | 373 |
| 374 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if | 374 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if |
| 375 // store is successful. | 375 // store is successful. |
| 376 void NamedStoreHandlerCompiler::GenerateStoreTransition( | 376 void NamedStoreHandlerCompiler::GenerateStoreTransition( |
| 377 MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup, | 377 MacroAssembler* masm, LookupResult* lookup, Handle<Map> transition, |
| 378 Handle<Map> transition, Handle<Name> name, Register receiver_reg, | 378 Handle<Name> name, Register receiver_reg, Register storage_reg, |
| 379 Register storage_reg, Register value_reg, Register scratch1, | 379 Register value_reg, Register scratch1, Register scratch2, Register unused, |
| 380 Register scratch2, Register unused, Label* miss_label, Label* slow) { | 380 Label* miss_label, Label* slow) { |
| 381 int descriptor = transition->LastAdded(); | 381 int descriptor = transition->LastAdded(); |
| 382 DescriptorArray* descriptors = transition->instance_descriptors(); | 382 DescriptorArray* descriptors = transition->instance_descriptors(); |
| 383 PropertyDetails details = descriptors->GetDetails(descriptor); | 383 PropertyDetails details = descriptors->GetDetails(descriptor); |
| 384 Representation representation = details.representation(); | 384 Representation representation = details.representation(); |
| 385 ASSERT(!representation.IsNone()); | 385 ASSERT(!representation.IsNone()); |
| 386 | 386 |
| 387 if (details.type() == CONSTANT) { | 387 if (details.type() == CONSTANT) { |
| 388 Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate()); | 388 Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate()); |
| 389 __ Cmp(value_reg, constant); | 389 __ Cmp(value_reg, constant); |
| 390 __ j(not_equal, miss_label); | 390 __ j(not_equal, miss_label); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 418 | 418 |
| 419 __ bind(&heap_number); | 419 __ bind(&heap_number); |
| 420 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), | 420 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), |
| 421 miss_label, DONT_DO_SMI_CHECK); | 421 miss_label, DONT_DO_SMI_CHECK); |
| 422 __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); | 422 __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); |
| 423 | 423 |
| 424 __ bind(&do_store); | 424 __ bind(&do_store); |
| 425 __ movsd(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0); | 425 __ movsd(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0); |
| 426 } | 426 } |
| 427 | 427 |
| 428 // Stub never generated for non-global objects that require access | 428 // Stub never generated for objects that require access checks. |
| 429 // checks. | 429 ASSERT(!transition->is_access_check_needed()); |
| 430 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | |
| 431 | 430 |
| 432 // Perform map transition for the receiver if necessary. | 431 // Perform map transition for the receiver if necessary. |
| 433 if (details.type() == FIELD && | 432 if (details.type() == FIELD && |
| 434 object->map()->unused_property_fields() == 0) { | 433 Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { |
| 435 // The properties must be extended before we can store the value. | 434 // The properties must be extended before we can store the value. |
| 436 // We jump to a runtime call that extends the properties array. | 435 // We jump to a runtime call that extends the properties array. |
| 437 __ PopReturnAddressTo(scratch1); | 436 __ PopReturnAddressTo(scratch1); |
| 438 __ Push(receiver_reg); | 437 __ Push(receiver_reg); |
| 439 __ Push(transition); | 438 __ Push(transition); |
| 440 __ Push(value_reg); | 439 __ Push(value_reg); |
| 441 __ PushReturnAddressFrom(scratch1); | 440 __ PushReturnAddressFrom(scratch1); |
| 442 __ TailCallExternalReference( | 441 __ TailCallExternalReference( |
| 443 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), | 442 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), |
| 444 masm->isolate()), | 443 masm->isolate()), |
| (...skipping 20 matching lines...) Expand all Loading... |
| 465 __ ret(0); | 464 __ ret(0); |
| 466 return; | 465 return; |
| 467 } | 466 } |
| 468 | 467 |
| 469 int index = transition->instance_descriptors()->GetFieldIndex( | 468 int index = transition->instance_descriptors()->GetFieldIndex( |
| 470 transition->LastAdded()); | 469 transition->LastAdded()); |
| 471 | 470 |
| 472 // Adjust for the number of properties stored in the object. Even in the | 471 // Adjust for the number of properties stored in the object. Even in the |
| 473 // face of a transition we can use the old map here because the size of the | 472 // face of a transition we can use the old map here because the size of the |
| 474 // object and the number of in-object properties is not going to change. | 473 // object and the number of in-object properties is not going to change. |
| 475 index -= object->map()->inobject_properties(); | 474 index -= transition->inobject_properties(); |
| 476 | 475 |
| 477 // TODO(verwaest): Share this code as a code stub. | 476 // TODO(verwaest): Share this code as a code stub. |
| 478 SmiCheck smi_check = representation.IsTagged() | 477 SmiCheck smi_check = representation.IsTagged() |
| 479 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; | 478 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; |
| 480 if (index < 0) { | 479 if (index < 0) { |
| 481 // Set the property straight into the object. | 480 // Set the property straight into the object. |
| 482 int offset = object->map()->instance_size() + (index * kPointerSize); | 481 int offset = transition->instance_size() + (index * kPointerSize); |
| 483 if (representation.IsDouble()) { | 482 if (representation.IsDouble()) { |
| 484 __ movp(FieldOperand(receiver_reg, offset), storage_reg); | 483 __ movp(FieldOperand(receiver_reg, offset), storage_reg); |
| 485 } else { | 484 } else { |
| 486 __ movp(FieldOperand(receiver_reg, offset), value_reg); | 485 __ movp(FieldOperand(receiver_reg, offset), value_reg); |
| 487 } | 486 } |
| 488 | 487 |
| 489 if (!representation.IsSmi()) { | 488 if (!representation.IsSmi()) { |
| 490 // Update the write barrier for the array address. | 489 // Update the write barrier for the array address. |
| 491 if (!representation.IsDouble()) { | 490 if (!representation.IsDouble()) { |
| 492 __ movp(storage_reg, value_reg); | 491 __ movp(storage_reg, value_reg); |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 626 Handle<Code> code) { | 625 Handle<Code> code) { |
| 627 __ jmp(code, RelocInfo::CODE_TARGET); | 626 __ jmp(code, RelocInfo::CODE_TARGET); |
| 628 } | 627 } |
| 629 | 628 |
| 630 | 629 |
| 631 #undef __ | 630 #undef __ |
| 632 #define __ ACCESS_MASM((masm())) | 631 #define __ ACCESS_MASM((masm())) |
| 633 | 632 |
| 634 | 633 |
| 635 Register PropertyHandlerCompiler::CheckPrototypes( | 634 Register PropertyHandlerCompiler::CheckPrototypes( |
| 636 Register object_reg, Handle<JSObject> holder, Register holder_reg, | 635 Register object_reg, Register holder_reg, Register scratch1, |
| 637 Register scratch1, Register scratch2, Handle<Name> name, Label* miss, | 636 Register scratch2, Handle<Name> name, Label* miss, |
| 638 PrototypeCheckType check) { | 637 PrototypeCheckType check) { |
| 639 Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); | 638 Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); |
| 640 | 639 |
| 641 // Make sure there's no overlap between holder and object registers. | 640 // Make sure there's no overlap between holder and object registers. |
| 642 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 641 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
| 643 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 642 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
| 644 && !scratch2.is(scratch1)); | 643 && !scratch2.is(scratch1)); |
| 645 | 644 |
| 646 // Keep track of the current object in register reg. On the first | 645 // Keep track of the current object in register reg. On the first |
| 647 // iteration, reg is an alias for object_reg, on later iterations, | 646 // iteration, reg is an alias for object_reg, on later iterations, |
| 648 // it is an alias for holder_reg. | 647 // it is an alias for holder_reg. |
| 649 Register reg = object_reg; | 648 Register reg = object_reg; |
| 650 int depth = 0; | 649 int depth = 0; |
| 651 | 650 |
| 652 Handle<JSObject> current = Handle<JSObject>::null(); | 651 Handle<JSObject> current = Handle<JSObject>::null(); |
| 653 if (type()->IsConstant()) { | 652 if (type()->IsConstant()) { |
| 654 current = Handle<JSObject>::cast(type()->AsConstant()->Value()); | 653 current = Handle<JSObject>::cast(type()->AsConstant()->Value()); |
| 655 } | 654 } |
| 656 Handle<JSObject> prototype = Handle<JSObject>::null(); | 655 Handle<JSObject> prototype = Handle<JSObject>::null(); |
| 657 Handle<Map> current_map = receiver_map; | 656 Handle<Map> current_map = receiver_map; |
| 658 Handle<Map> holder_map(holder->map()); | 657 Handle<Map> holder_map(holder()->map()); |
| 659 // Traverse the prototype chain and check the maps in the prototype chain for | 658 // Traverse the prototype chain and check the maps in the prototype chain for |
| 660 // fast and global objects or do negative lookup for normal objects. | 659 // fast and global objects or do negative lookup for normal objects. |
| 661 while (!current_map.is_identical_to(holder_map)) { | 660 while (!current_map.is_identical_to(holder_map)) { |
| 662 ++depth; | 661 ++depth; |
| 663 | 662 |
| 664 // Only global objects and objects that do not require access | 663 // Only global objects and objects that do not require access |
| 665 // checks are allowed in stubs. | 664 // checks are allowed in stubs. |
| 666 ASSERT(current_map->IsJSGlobalProxyMap() || | 665 ASSERT(current_map->IsJSGlobalProxyMap() || |
| 667 !current_map->is_access_check_needed()); | 666 !current_map->is_access_check_needed()); |
| 668 | 667 |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 759 Label success; | 758 Label success; |
| 760 __ jmp(&success); | 759 __ jmp(&success); |
| 761 GenerateRestoreName(masm(), miss, name); | 760 GenerateRestoreName(masm(), miss, name); |
| 762 TailCallBuiltin(masm(), MissBuiltin(kind())); | 761 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 763 __ bind(&success); | 762 __ bind(&success); |
| 764 } | 763 } |
| 765 } | 764 } |
| 766 | 765 |
| 767 | 766 |
| 768 Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, | 767 Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, |
| 769 Handle<JSObject> holder, | |
| 770 Handle<Name> name, | 768 Handle<Name> name, |
| 771 Handle<Object> callback) { | 769 Handle<Object> callback) { |
| 772 Label miss; | 770 Label miss; |
| 773 | 771 |
| 774 Register reg = FrontendHeader(object_reg, holder, name, &miss); | 772 Register reg = FrontendHeader(object_reg, name, &miss); |
| 775 | 773 |
| 776 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { | 774 if (!holder()->HasFastProperties()) { |
| 775 ASSERT(!holder()->IsGlobalObject()); |
| 777 ASSERT(!reg.is(scratch2())); | 776 ASSERT(!reg.is(scratch2())); |
| 778 ASSERT(!reg.is(scratch3())); | 777 ASSERT(!reg.is(scratch3())); |
| 779 ASSERT(!reg.is(scratch4())); | 778 ASSERT(!reg.is(scratch4())); |
| 780 | 779 |
| 781 // Load the properties dictionary. | 780 // Load the properties dictionary. |
| 782 Register dictionary = scratch4(); | 781 Register dictionary = scratch4(); |
| 783 __ movp(dictionary, FieldOperand(reg, JSObject::kPropertiesOffset)); | 782 __ movp(dictionary, FieldOperand(reg, JSObject::kPropertiesOffset)); |
| 784 | 783 |
| 785 // Probe the dictionary. | 784 // Probe the dictionary. |
| 786 Label probe_done; | 785 Label probe_done; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 807 __ cmpp(scratch2(), scratch3()); | 806 __ cmpp(scratch2(), scratch3()); |
| 808 __ j(not_equal, &miss); | 807 __ j(not_equal, &miss); |
| 809 } | 808 } |
| 810 | 809 |
| 811 FrontendFooter(name, &miss); | 810 FrontendFooter(name, &miss); |
| 812 return reg; | 811 return reg; |
| 813 } | 812 } |
| 814 | 813 |
| 815 | 814 |
| 816 void NamedLoadHandlerCompiler::GenerateLoadField( | 815 void NamedLoadHandlerCompiler::GenerateLoadField( |
| 817 Register reg, Handle<JSObject> holder, FieldIndex field, | 816 Register reg, FieldIndex field, Representation representation) { |
| 818 Representation representation) { | |
| 819 if (!reg.is(receiver())) __ movp(receiver(), reg); | 817 if (!reg.is(receiver())) __ movp(receiver(), reg); |
| 820 LoadFieldStub stub(isolate(), field); | 818 LoadFieldStub stub(isolate(), field); |
| 821 GenerateTailCall(masm(), stub.GetCode()); | 819 GenerateTailCall(masm(), stub.GetCode()); |
| 822 } | 820 } |
| 823 | 821 |
| 824 | 822 |
| 825 void NamedLoadHandlerCompiler::GenerateLoadCallback( | 823 void NamedLoadHandlerCompiler::GenerateLoadCallback( |
| 826 Register reg, Handle<ExecutableAccessorInfo> callback) { | 824 Register reg, Handle<ExecutableAccessorInfo> callback) { |
| 827 // Insert additional parameters into the stack frame above return address. | 825 // Insert additional parameters into the stack frame above return address. |
| 828 ASSERT(!scratch4().is(reg)); | 826 ASSERT(!scratch4().is(reg)); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 866 } | 864 } |
| 867 | 865 |
| 868 | 866 |
| 869 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { | 867 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { |
| 870 // Return the constant value. | 868 // Return the constant value. |
| 871 __ Move(rax, value); | 869 __ Move(rax, value); |
| 872 __ ret(0); | 870 __ ret(0); |
| 873 } | 871 } |
| 874 | 872 |
| 875 | 873 |
| 876 void NamedLoadHandlerCompiler::GenerateLoadInterceptor( | 874 void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg, |
| 877 Register holder_reg, Handle<JSObject> interceptor_holder, | 875 LookupResult* lookup, |
| 878 LookupResult* lookup, Handle<Name> name) { | 876 Handle<Name> name) { |
| 879 ASSERT(interceptor_holder->HasNamedInterceptor()); | 877 ASSERT(holder()->HasNamedInterceptor()); |
| 880 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 878 ASSERT(!holder()->GetNamedInterceptor()->getter()->IsUndefined()); |
| 881 | 879 |
| 882 // So far the most popular follow ups for interceptor loads are FIELD | 880 // So far the most popular follow ups for interceptor loads are FIELD |
| 883 // and CALLBACKS, so inline only them, other cases may be added | 881 // and CALLBACKS, so inline only them, other cases may be added |
| 884 // later. | 882 // later. |
| 885 bool compile_followup_inline = false; | 883 bool compile_followup_inline = false; |
| 886 if (lookup->IsFound() && lookup->IsCacheable()) { | 884 if (lookup->IsFound() && lookup->IsCacheable()) { |
| 887 if (lookup->IsField()) { | 885 if (lookup->IsField()) { |
| 888 compile_followup_inline = true; | 886 compile_followup_inline = true; |
| 889 } else if (lookup->type() == CALLBACKS && | 887 } else if (lookup->type() == CALLBACKS && |
| 890 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { | 888 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { |
| 891 Handle<ExecutableAccessorInfo> callback( | 889 Handle<ExecutableAccessorInfo> callback( |
| 892 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); | 890 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); |
| 893 compile_followup_inline = | 891 compile_followup_inline = |
| 894 callback->getter() != NULL && | 892 callback->getter() != NULL && |
| 895 ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback, | 893 ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback, |
| 896 type()); | 894 type()); |
| 897 } | 895 } |
| 898 } | 896 } |
| 899 | 897 |
| 900 if (compile_followup_inline) { | 898 if (compile_followup_inline) { |
| 901 // Compile the interceptor call, followed by inline code to load the | 899 // Compile the interceptor call, followed by inline code to load the |
| 902 // property from further up the prototype chain if the call fails. | 900 // property from further up the prototype chain if the call fails. |
| 903 // Check that the maps haven't changed. | 901 // Check that the maps haven't changed. |
| 904 ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1())); | 902 ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1())); |
| 905 | 903 |
| 906 // Preserve the receiver register explicitly whenever it is different from | 904 // Preserve the receiver register explicitly whenever it is different from |
| 907 // the holder and it is needed should the interceptor return without any | 905 // the holder and it is needed should the interceptor return without any |
| 908 // result. The CALLBACKS case needs the receiver to be passed into C++ code, | 906 // result. The CALLBACKS case needs the receiver to be passed into C++ code, |
| 909 // the FIELD case might cause a miss during the prototype check. | 907 // the FIELD case might cause a miss during the prototype check. |
| 910 bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder(); | 908 bool must_perfrom_prototype_check = *holder() != lookup->holder(); |
| 911 bool must_preserve_receiver_reg = !receiver().is(holder_reg) && | 909 bool must_preserve_receiver_reg = !receiver().is(holder_reg) && |
| 912 (lookup->type() == CALLBACKS || must_perfrom_prototype_check); | 910 (lookup->type() == CALLBACKS || must_perfrom_prototype_check); |
| 913 | 911 |
| 914 // Save necessary data before invoking an interceptor. | 912 // Save necessary data before invoking an interceptor. |
| 915 // Requires a frame to make GC aware of pushed pointers. | 913 // Requires a frame to make GC aware of pushed pointers. |
| 916 { | 914 { |
| 917 FrameScope frame_scope(masm(), StackFrame::INTERNAL); | 915 FrameScope frame_scope(masm(), StackFrame::INTERNAL); |
| 918 | 916 |
| 919 if (must_preserve_receiver_reg) { | 917 if (must_preserve_receiver_reg) { |
| 920 __ Push(receiver()); | 918 __ Push(receiver()); |
| 921 } | 919 } |
| 922 __ Push(holder_reg); | 920 __ Push(holder_reg); |
| 923 __ Push(this->name()); | 921 __ Push(this->name()); |
| 924 | 922 |
| 925 // Invoke an interceptor. Note: map checks from receiver to | 923 // Invoke an interceptor. Note: map checks from receiver to |
| 926 // interceptor's holder has been compiled before (see a caller | 924 // interceptor's holder has been compiled before (see a caller |
| 927 // of this method.) | 925 // of this method.) |
| 928 CompileCallLoadPropertyWithInterceptor( | 926 CompileCallLoadPropertyWithInterceptor( |
| 929 masm(), receiver(), holder_reg, this->name(), interceptor_holder, | 927 masm(), receiver(), holder_reg, this->name(), holder(), |
| 930 IC::kLoadPropertyWithInterceptorOnly); | 928 IC::kLoadPropertyWithInterceptorOnly); |
| 931 | 929 |
| 932 // Check if interceptor provided a value for property. If it's | 930 // Check if interceptor provided a value for property. If it's |
| 933 // the case, return immediately. | 931 // the case, return immediately. |
| 934 Label interceptor_failed; | 932 Label interceptor_failed; |
| 935 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex); | 933 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex); |
| 936 __ j(equal, &interceptor_failed); | 934 __ j(equal, &interceptor_failed); |
| 937 frame_scope.GenerateLeaveFrame(); | 935 frame_scope.GenerateLeaveFrame(); |
| 938 __ ret(0); | 936 __ ret(0); |
| 939 | 937 |
| 940 __ bind(&interceptor_failed); | 938 __ bind(&interceptor_failed); |
| 941 __ Pop(this->name()); | 939 __ Pop(this->name()); |
| 942 __ Pop(holder_reg); | 940 __ Pop(holder_reg); |
| 943 if (must_preserve_receiver_reg) { | 941 if (must_preserve_receiver_reg) { |
| 944 __ Pop(receiver()); | 942 __ Pop(receiver()); |
| 945 } | 943 } |
| 946 | 944 |
| 947 // Leave the internal frame. | 945 // Leave the internal frame. |
| 948 } | 946 } |
| 949 | 947 |
| 950 GenerateLoadPostInterceptor(holder_reg, interceptor_holder, name, lookup); | 948 GenerateLoadPostInterceptor(holder_reg, name, lookup); |
| 951 } else { // !compile_followup_inline | 949 } else { // !compile_followup_inline |
| 952 // Call the runtime system to load the interceptor. | 950 // Call the runtime system to load the interceptor. |
| 953 // Check that the maps haven't changed. | 951 // Check that the maps haven't changed. |
| 954 __ PopReturnAddressTo(scratch2()); | 952 __ PopReturnAddressTo(scratch2()); |
| 955 PushInterceptorArguments(masm(), receiver(), holder_reg, | 953 PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(), |
| 956 this->name(), interceptor_holder); | 954 holder()); |
| 957 __ PushReturnAddressFrom(scratch2()); | 955 __ PushReturnAddressFrom(scratch2()); |
| 958 | 956 |
| 959 ExternalReference ref = ExternalReference( | 957 ExternalReference ref = ExternalReference( |
| 960 IC_Utility(IC::kLoadPropertyWithInterceptor), isolate()); | 958 IC_Utility(IC::kLoadPropertyWithInterceptor), isolate()); |
| 961 __ TailCallExternalReference( | 959 __ TailCallExternalReference( |
| 962 ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1); | 960 ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1); |
| 963 } | 961 } |
| 964 } | 962 } |
| 965 | 963 |
| 966 | 964 |
| 967 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( | 965 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( |
| 968 Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name, | 966 Handle<JSObject> object, Handle<Name> name, |
| 969 Handle<ExecutableAccessorInfo> callback) { | 967 Handle<ExecutableAccessorInfo> callback) { |
| 970 Register holder_reg = Frontend(receiver(), holder, name); | 968 Register holder_reg = Frontend(receiver(), name); |
| 971 | 969 |
| 972 __ PopReturnAddressTo(scratch1()); | 970 __ PopReturnAddressTo(scratch1()); |
| 973 __ Push(receiver()); | 971 __ Push(receiver()); |
| 974 __ Push(holder_reg); | 972 __ Push(holder_reg); |
| 975 __ Push(callback); // callback info | 973 __ Push(callback); // callback info |
| 976 __ Push(name); | 974 __ Push(name); |
| 977 __ Push(value()); | 975 __ Push(value()); |
| 978 __ PushReturnAddressFrom(scratch1()); | 976 __ PushReturnAddressFrom(scratch1()); |
| 979 | 977 |
| 980 // Do tail-call to the runtime system. | 978 // Do tail-call to the runtime system. |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1030 } | 1028 } |
| 1031 __ ret(0); | 1029 __ ret(0); |
| 1032 } | 1030 } |
| 1033 | 1031 |
| 1034 | 1032 |
| 1035 #undef __ | 1033 #undef __ |
| 1036 #define __ ACCESS_MASM(masm()) | 1034 #define __ ACCESS_MASM(masm()) |
| 1037 | 1035 |
| 1038 | 1036 |
| 1039 Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( | 1037 Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( |
| 1040 Handle<JSObject> object, Handle<Name> name) { | 1038 Handle<Name> name) { |
| 1041 __ PopReturnAddressTo(scratch1()); | 1039 __ PopReturnAddressTo(scratch1()); |
| 1042 __ Push(receiver()); | 1040 __ Push(receiver()); |
| 1043 __ Push(this->name()); | 1041 __ Push(this->name()); |
| 1044 __ Push(value()); | 1042 __ Push(value()); |
| 1045 __ PushReturnAddressFrom(scratch1()); | 1043 __ PushReturnAddressFrom(scratch1()); |
| 1046 | 1044 |
| 1047 // Do tail-call to the runtime system. | 1045 // Do tail-call to the runtime system. |
| 1048 ExternalReference store_ic_property = ExternalReference( | 1046 ExternalReference store_ic_property = ExternalReference( |
| 1049 IC_Utility(IC::kStorePropertyWithInterceptor), isolate()); | 1047 IC_Utility(IC::kStorePropertyWithInterceptor), isolate()); |
| 1050 __ TailCallExternalReference(store_ic_property, 3, 1); | 1048 __ TailCallExternalReference(store_ic_property, 3, 1); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1095 __ bind(&miss); | 1093 __ bind(&miss); |
| 1096 | 1094 |
| 1097 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1095 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1098 | 1096 |
| 1099 // Return the generated code. | 1097 // Return the generated code. |
| 1100 return GetCode(kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); | 1098 return GetCode(kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); |
| 1101 } | 1099 } |
| 1102 | 1100 |
| 1103 | 1101 |
| 1104 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( | 1102 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( |
| 1105 Handle<JSObject> last, Handle<Name> name) { | 1103 Handle<Name> name) { |
| 1106 NonexistentFrontend(last, name); | 1104 NonexistentFrontend(name); |
| 1107 | 1105 |
| 1108 // Return undefined if maps of the full prototype chain are still the | 1106 // Return undefined if maps of the full prototype chain are still the |
| 1109 // same and no global property with this name contains a value. | 1107 // same and no global property with this name contains a value. |
| 1110 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 1108 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); |
| 1111 __ ret(0); | 1109 __ ret(0); |
| 1112 | 1110 |
| 1113 // Return the generated code. | 1111 // Return the generated code. |
| 1114 return GetCode(kind(), Code::FAST, name); | 1112 return GetCode(kind(), Code::FAST, name); |
| 1115 } | 1113 } |
| 1116 | 1114 |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1184 } | 1182 } |
| 1185 __ ret(0); | 1183 __ ret(0); |
| 1186 } | 1184 } |
| 1187 | 1185 |
| 1188 | 1186 |
| 1189 #undef __ | 1187 #undef __ |
| 1190 #define __ ACCESS_MASM(masm()) | 1188 #define __ ACCESS_MASM(masm()) |
| 1191 | 1189 |
| 1192 | 1190 |
| 1193 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( | 1191 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( |
| 1194 Handle<GlobalObject> global, Handle<PropertyCell> cell, Handle<Name> name, | 1192 Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) { |
| 1195 bool is_dont_delete) { | |
| 1196 Label miss; | 1193 Label miss; |
| 1197 FrontendHeader(receiver(), global, name, &miss); | 1194 FrontendHeader(receiver(), name, &miss); |
| 1198 | 1195 |
| 1199 // Get the value from the cell. | 1196 // Get the value from the cell. |
| 1200 Register result = StoreIC::ValueRegister(); | 1197 Register result = StoreIC::ValueRegister(); |
| 1201 __ Move(result, cell); | 1198 __ Move(result, cell); |
| 1202 __ movp(result, FieldOperand(result, PropertyCell::kValueOffset)); | 1199 __ movp(result, FieldOperand(result, PropertyCell::kValueOffset)); |
| 1203 | 1200 |
| 1204 // Check for deleted property if property can actually be deleted. | 1201 // Check for deleted property if property can actually be deleted. |
| 1205 if (!is_dont_delete) { | 1202 if (!is_dont_delete) { |
| 1206 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); | 1203 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); |
| 1207 __ j(equal, &miss); | 1204 __ j(equal, &miss); |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1323 // ----------------------------------- | 1320 // ----------------------------------- |
| 1324 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 1321 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
| 1325 } | 1322 } |
| 1326 | 1323 |
| 1327 | 1324 |
| 1328 #undef __ | 1325 #undef __ |
| 1329 | 1326 |
| 1330 } } // namespace v8::internal | 1327 } } // namespace v8::internal |
| 1331 | 1328 |
| 1332 #endif // V8_TARGET_ARCH_X64 | 1329 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |