OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 | 145 |
146 // Probe the secondary table. | 146 // Probe the secondary table. |
147 ProbeTable(masm, flags, kSecondary, name, scratch, extra); | 147 ProbeTable(masm, flags, kSecondary, name, scratch, extra); |
148 | 148 |
149 // Cache miss: Fall-through and let caller handle the miss by | 149 // Cache miss: Fall-through and let caller handle the miss by |
150 // entering the runtime system. | 150 // entering the runtime system. |
151 __ bind(&miss); | 151 __ bind(&miss); |
152 } | 152 } |
153 | 153 |
154 | 154 |
155 template <typename Pushable> | |
156 static void PushInterceptorArguments(MacroAssembler* masm, | 155 static void PushInterceptorArguments(MacroAssembler* masm, |
157 Register receiver, | 156 Register receiver, |
158 Register holder, | 157 Register holder, |
159 Pushable name, | 158 Register name, |
160 JSObject* holder_obj) { | 159 JSObject* holder_obj) { |
161 __ push(receiver); | 160 __ push(receiver); |
162 __ push(holder); | 161 __ push(holder); |
163 __ push(name); | 162 __ push(name); |
164 InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor(); | 163 InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor(); |
165 __ mov(receiver, Immediate(Handle<Object>(interceptor))); | 164 __ mov(receiver, Immediate(Handle<Object>(interceptor))); |
166 __ push(receiver); | 165 __ push(receiver); |
167 __ push(FieldOperand(receiver, InterceptorInfo::kDataOffset)); | 166 __ push(FieldOperand(receiver, InterceptorInfo::kDataOffset)); |
168 } | 167 } |
169 | 168 |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
278 __ mov(dst, FieldOperand(src, offset)); | 277 __ mov(dst, FieldOperand(src, offset)); |
279 } else { | 278 } else { |
280 // Calculate the offset into the properties array. | 279 // Calculate the offset into the properties array. |
281 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 280 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
282 __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset)); | 281 __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset)); |
283 __ mov(dst, FieldOperand(dst, offset)); | 282 __ mov(dst, FieldOperand(dst, offset)); |
284 } | 283 } |
285 } | 284 } |
286 | 285 |
287 | 286 |
288 template <class Pushable> | |
289 static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm, | 287 static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm, |
290 Register receiver, | 288 Register receiver, |
291 Register holder, | 289 Register holder, |
292 Pushable name, | 290 Register name, |
293 JSObject* holder_obj) { | 291 JSObject* holder_obj) { |
294 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | 292 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); |
295 | 293 |
296 ExternalReference ref = | 294 ExternalReference ref = |
297 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly)); | 295 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly)); |
298 __ mov(eax, Immediate(5)); | 296 __ mov(eax, Immediate(5)); |
299 __ mov(ebx, Immediate(ref)); | 297 __ mov(ebx, Immediate(ref)); |
300 | 298 |
301 CEntryStub stub(1); | 299 CEntryStub stub(1); |
302 __ CallStub(&stub); | 300 __ CallStub(&stub); |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
488 __ TailCallRuntime(ref, 5, 1); | 486 __ TailCallRuntime(ref, 5, 1); |
489 } | 487 } |
490 | 488 |
491 private: | 489 private: |
492 Register name_; | 490 Register name_; |
493 }; | 491 }; |
494 | 492 |
495 | 493 |
496 class CallInterceptorCompiler BASE_EMBEDDED { | 494 class CallInterceptorCompiler BASE_EMBEDDED { |
497 public: | 495 public: |
498 explicit CallInterceptorCompiler(const ParameterCount& arguments) | 496 CallInterceptorCompiler(const ParameterCount& arguments, Register name) |
499 : arguments_(arguments), argc_(arguments.immediate()) {} | 497 : arguments_(arguments), argc_(arguments.immediate()), name_(name) {} |
500 | 498 |
501 void CompileCacheable(MacroAssembler* masm, | 499 void CompileCacheable(MacroAssembler* masm, |
502 StubCompiler* stub_compiler, | 500 StubCompiler* stub_compiler, |
503 Register receiver, | 501 Register receiver, |
504 Register holder, | 502 Register holder, |
505 Register scratch1, | 503 Register scratch1, |
506 Register scratch2, | 504 Register scratch2, |
507 JSObject* holder_obj, | 505 JSObject* holder_obj, |
508 LookupResult* lookup, | 506 LookupResult* lookup, |
509 String* name, | 507 String* name, |
(...skipping 10 matching lines...) Expand all Loading... |
520 optimize = true; | 518 optimize = true; |
521 } | 519 } |
522 } | 520 } |
523 | 521 |
524 if (!optimize) { | 522 if (!optimize) { |
525 CompileRegular(masm, receiver, holder, scratch2, holder_obj, miss_label); | 523 CompileRegular(masm, receiver, holder, scratch2, holder_obj, miss_label); |
526 return; | 524 return; |
527 } | 525 } |
528 | 526 |
529 __ EnterInternalFrame(); | 527 __ EnterInternalFrame(); |
530 __ push(holder); // save the holder | 528 __ push(holder); // Save the holder. |
| 529 __ push(name_); // Save the name. |
531 | 530 |
532 CompileCallLoadPropertyWithInterceptor( | 531 CompileCallLoadPropertyWithInterceptor(masm, |
533 masm, | 532 receiver, |
534 receiver, | 533 holder, |
535 holder, | 534 name_, |
536 // Under EnterInternalFrame this refers to name. | 535 holder_obj); |
537 Operand(ebp, (argc_ + 3) * kPointerSize), | |
538 holder_obj); | |
539 | 536 |
540 __ pop(receiver); // restore holder | 537 __ pop(name_); // Restore the name. |
| 538 __ pop(receiver); // Restore the holder. |
541 __ LeaveInternalFrame(); | 539 __ LeaveInternalFrame(); |
542 | 540 |
543 __ cmp(eax, Factory::no_interceptor_result_sentinel()); | 541 __ cmp(eax, Factory::no_interceptor_result_sentinel()); |
544 Label invoke; | 542 Label invoke; |
545 __ j(not_equal, &invoke); | 543 __ j(not_equal, &invoke); |
546 | 544 |
547 stub_compiler->CheckPrototypes(holder_obj, receiver, | 545 stub_compiler->CheckPrototypes(holder_obj, receiver, |
548 lookup->holder(), scratch1, | 546 lookup->holder(), scratch1, |
549 scratch2, | 547 scratch2, |
550 name, | 548 name, |
(...skipping 19 matching lines...) Expand all Loading... |
570 __ bind(&invoke); | 568 __ bind(&invoke); |
571 } | 569 } |
572 | 570 |
573 void CompileRegular(MacroAssembler* masm, | 571 void CompileRegular(MacroAssembler* masm, |
574 Register receiver, | 572 Register receiver, |
575 Register holder, | 573 Register holder, |
576 Register scratch, | 574 Register scratch, |
577 JSObject* holder_obj, | 575 JSObject* holder_obj, |
578 Label* miss_label) { | 576 Label* miss_label) { |
579 __ EnterInternalFrame(); | 577 __ EnterInternalFrame(); |
| 578 // Save the name_ register across the call. |
| 579 __ push(name_); |
580 | 580 |
581 PushInterceptorArguments(masm, | 581 PushInterceptorArguments(masm, |
582 receiver, | 582 receiver, |
583 holder, | 583 holder, |
584 Operand(ebp, (argc_ + 3) * kPointerSize), | 584 name_, |
585 holder_obj); | 585 holder_obj); |
586 | 586 |
587 ExternalReference ref = ExternalReference( | 587 ExternalReference ref = ExternalReference( |
588 IC_Utility(IC::kLoadPropertyWithInterceptorForCall)); | 588 IC_Utility(IC::kLoadPropertyWithInterceptorForCall)); |
589 __ mov(eax, Immediate(5)); | 589 __ mov(eax, Immediate(5)); |
590 __ mov(ebx, Immediate(ref)); | 590 __ mov(ebx, Immediate(ref)); |
591 | 591 |
592 CEntryStub stub(1); | 592 CEntryStub stub(1); |
593 __ CallStub(&stub); | 593 __ CallStub(&stub); |
594 | 594 |
| 595 // Restore the name_ register. |
| 596 __ pop(name_); |
595 __ LeaveInternalFrame(); | 597 __ LeaveInternalFrame(); |
596 } | 598 } |
597 | 599 |
598 private: | 600 private: |
599 const ParameterCount& arguments_; | 601 const ParameterCount& arguments_; |
600 int argc_; | 602 int argc_; |
| 603 Register name_; |
601 }; | 604 }; |
602 | 605 |
603 | 606 |
604 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { | 607 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { |
605 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); | 608 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); |
606 Code* code = NULL; | 609 Code* code = NULL; |
607 if (kind == Code::LOAD_IC) { | 610 if (kind == Code::LOAD_IC) { |
608 code = Builtins::builtin(Builtins::LoadIC_Miss); | 611 code = Builtins::builtin(Builtins::LoadIC_Miss); |
609 } else { | 612 } else { |
610 code = Builtins::builtin(Builtins::KeyedLoadIC_Miss); | 613 code = Builtins::builtin(Builtins::KeyedLoadIC_Miss); |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
887 | 890 |
888 return GetCodeWithFlags(flags, "LazyCompileStub"); | 891 return GetCodeWithFlags(flags, "LazyCompileStub"); |
889 } | 892 } |
890 | 893 |
891 | 894 |
892 Object* CallStubCompiler::CompileCallField(Object* object, | 895 Object* CallStubCompiler::CompileCallField(Object* object, |
893 JSObject* holder, | 896 JSObject* holder, |
894 int index, | 897 int index, |
895 String* name) { | 898 String* name) { |
896 // ----------- S t a t e ------------- | 899 // ----------- S t a t e ------------- |
| 900 // -- ecx : name |
| 901 // -- esp[0] : return address |
| 902 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 903 // -- ... |
| 904 // -- esp[(argc + 1) * 4] : receiver |
897 // ----------------------------------- | 905 // ----------------------------------- |
898 Label miss; | 906 Label miss; |
899 | 907 |
900 // Get the receiver from the stack. | 908 // Get the receiver from the stack. |
901 const int argc = arguments().immediate(); | 909 const int argc = arguments().immediate(); |
902 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 910 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
903 | 911 |
904 // Check that the receiver isn't a smi. | 912 // Check that the receiver isn't a smi. |
905 __ test(edx, Immediate(kSmiTagMask)); | 913 __ test(edx, Immediate(kSmiTagMask)); |
906 __ j(zero, &miss, not_taken); | 914 __ j(zero, &miss, not_taken); |
907 | 915 |
908 // Do the right check and compute the holder register. | 916 // Do the right check and compute the holder register. |
909 Register reg = | 917 Register reg = |
910 CheckPrototypes(JSObject::cast(object), edx, holder, | 918 CheckPrototypes(JSObject::cast(object), edx, holder, |
911 ebx, ecx, name, &miss); | 919 ebx, eax, name, &miss); |
912 | 920 |
913 GenerateFastPropertyLoad(masm(), edi, reg, holder, index); | 921 GenerateFastPropertyLoad(masm(), edi, reg, holder, index); |
914 | 922 |
915 // Check that the function really is a function. | 923 // Check that the function really is a function. |
916 __ test(edi, Immediate(kSmiTagMask)); | 924 __ test(edi, Immediate(kSmiTagMask)); |
917 __ j(zero, &miss, not_taken); | 925 __ j(zero, &miss, not_taken); |
918 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); | 926 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); |
919 __ j(not_equal, &miss, not_taken); | 927 __ j(not_equal, &miss, not_taken); |
920 | 928 |
921 // Patch the receiver on the stack with the global proxy if | 929 // Patch the receiver on the stack with the global proxy if |
(...skipping 15 matching lines...) Expand all Loading... |
937 return GetCode(FIELD, name); | 945 return GetCode(FIELD, name); |
938 } | 946 } |
939 | 947 |
940 | 948 |
941 Object* CallStubCompiler::CompileCallConstant(Object* object, | 949 Object* CallStubCompiler::CompileCallConstant(Object* object, |
942 JSObject* holder, | 950 JSObject* holder, |
943 JSFunction* function, | 951 JSFunction* function, |
944 String* name, | 952 String* name, |
945 CheckType check) { | 953 CheckType check) { |
946 // ----------- S t a t e ------------- | 954 // ----------- S t a t e ------------- |
| 955 // -- ecx : name |
| 956 // -- esp[0] : return address |
| 957 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 958 // -- ... |
| 959 // -- esp[(argc + 1) * 4] : receiver |
947 // ----------------------------------- | 960 // ----------------------------------- |
948 Label miss; | 961 Label miss; |
949 | 962 |
950 // Get the receiver from the stack. | 963 // Get the receiver from the stack. |
951 const int argc = arguments().immediate(); | 964 const int argc = arguments().immediate(); |
952 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 965 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
953 | 966 |
954 // Check that the receiver isn't a smi. | 967 // Check that the receiver isn't a smi. |
955 if (check != NUMBER_CHECK) { | 968 if (check != NUMBER_CHECK) { |
956 __ test(edx, Immediate(kSmiTagMask)); | 969 __ test(edx, Immediate(kSmiTagMask)); |
957 __ j(zero, &miss, not_taken); | 970 __ j(zero, &miss, not_taken); |
958 } | 971 } |
959 | 972 |
960 // Make sure that it's okay not to patch the on stack receiver | 973 // Make sure that it's okay not to patch the on stack receiver |
961 // unless we're doing a receiver map check. | 974 // unless we're doing a receiver map check. |
962 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 975 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
963 | 976 |
964 switch (check) { | 977 switch (check) { |
965 case RECEIVER_MAP_CHECK: | 978 case RECEIVER_MAP_CHECK: |
966 // Check that the maps haven't changed. | 979 // Check that the maps haven't changed. |
967 CheckPrototypes(JSObject::cast(object), edx, holder, | 980 CheckPrototypes(JSObject::cast(object), edx, holder, |
968 ebx, ecx, name, &miss); | 981 ebx, eax, name, &miss); |
969 | 982 |
970 // Patch the receiver on the stack with the global proxy if | 983 // Patch the receiver on the stack with the global proxy if |
971 // necessary. | 984 // necessary. |
972 if (object->IsGlobalObject()) { | 985 if (object->IsGlobalObject()) { |
973 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 986 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
974 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 987 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
975 } | 988 } |
976 break; | 989 break; |
977 | 990 |
978 case STRING_CHECK: | 991 case STRING_CHECK: |
979 // Check that the object is a two-byte string or a symbol. | 992 // Check that the object is a two-byte string or a symbol. |
980 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); | 993 __ mov(eax, FieldOperand(edx, HeapObject::kMapOffset)); |
981 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); | 994 __ movzx_b(eax, FieldOperand(ecx, Map::kInstanceTypeOffset)); |
982 __ cmp(ecx, FIRST_NONSTRING_TYPE); | 995 __ cmp(eax, FIRST_NONSTRING_TYPE); |
983 __ j(above_equal, &miss, not_taken); | 996 __ j(above_equal, &miss, not_taken); |
984 // Check that the maps starting from the prototype haven't changed. | 997 // Check that the maps starting from the prototype haven't changed. |
985 GenerateLoadGlobalFunctionPrototype(masm(), | 998 GenerateLoadGlobalFunctionPrototype(masm(), |
986 Context::STRING_FUNCTION_INDEX, | 999 Context::STRING_FUNCTION_INDEX, |
987 ecx); | 1000 eax); |
988 CheckPrototypes(JSObject::cast(object->GetPrototype()), ecx, holder, | 1001 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
989 ebx, edx, name, &miss); | 1002 ebx, edx, name, &miss); |
990 break; | 1003 break; |
991 | 1004 |
992 case NUMBER_CHECK: { | 1005 case NUMBER_CHECK: { |
993 Label fast; | 1006 Label fast; |
994 // Check that the object is a smi or a heap number. | 1007 // Check that the object is a smi or a heap number. |
995 __ test(edx, Immediate(kSmiTagMask)); | 1008 __ test(edx, Immediate(kSmiTagMask)); |
996 __ j(zero, &fast, taken); | 1009 __ j(zero, &fast, taken); |
997 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx); | 1010 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax); |
998 __ j(not_equal, &miss, not_taken); | 1011 __ j(not_equal, &miss, not_taken); |
999 __ bind(&fast); | 1012 __ bind(&fast); |
1000 // Check that the maps starting from the prototype haven't changed. | 1013 // Check that the maps starting from the prototype haven't changed. |
1001 GenerateLoadGlobalFunctionPrototype(masm(), | 1014 GenerateLoadGlobalFunctionPrototype(masm(), |
1002 Context::NUMBER_FUNCTION_INDEX, | 1015 Context::NUMBER_FUNCTION_INDEX, |
1003 ecx); | 1016 eax); |
1004 CheckPrototypes(JSObject::cast(object->GetPrototype()), ecx, holder, | 1017 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
1005 ebx, edx, name, &miss); | 1018 ebx, edx, name, &miss); |
1006 break; | 1019 break; |
1007 } | 1020 } |
1008 | 1021 |
1009 case BOOLEAN_CHECK: { | 1022 case BOOLEAN_CHECK: { |
1010 Label fast; | 1023 Label fast; |
1011 // Check that the object is a boolean. | 1024 // Check that the object is a boolean. |
1012 __ cmp(edx, Factory::true_value()); | 1025 __ cmp(edx, Factory::true_value()); |
1013 __ j(equal, &fast, taken); | 1026 __ j(equal, &fast, taken); |
1014 __ cmp(edx, Factory::false_value()); | 1027 __ cmp(edx, Factory::false_value()); |
1015 __ j(not_equal, &miss, not_taken); | 1028 __ j(not_equal, &miss, not_taken); |
1016 __ bind(&fast); | 1029 __ bind(&fast); |
1017 // Check that the maps starting from the prototype haven't changed. | 1030 // Check that the maps starting from the prototype haven't changed. |
1018 GenerateLoadGlobalFunctionPrototype(masm(), | 1031 GenerateLoadGlobalFunctionPrototype(masm(), |
1019 Context::BOOLEAN_FUNCTION_INDEX, | 1032 Context::BOOLEAN_FUNCTION_INDEX, |
1020 ecx); | 1033 eax); |
1021 CheckPrototypes(JSObject::cast(object->GetPrototype()), ecx, holder, | 1034 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
1022 ebx, edx, name, &miss); | 1035 ebx, edx, name, &miss); |
1023 break; | 1036 break; |
1024 } | 1037 } |
1025 | 1038 |
1026 case JSARRAY_HAS_FAST_ELEMENTS_CHECK: | 1039 case JSARRAY_HAS_FAST_ELEMENTS_CHECK: |
1027 CheckPrototypes(JSObject::cast(object), edx, holder, | 1040 CheckPrototypes(JSObject::cast(object), edx, holder, |
1028 ebx, ecx, name, &miss); | 1041 ebx, eax, name, &miss); |
1029 // Make sure object->HasFastElements(). | 1042 // Make sure object->HasFastElements(). |
1030 // Get the elements array of the object. | 1043 // Get the elements array of the object. |
1031 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); | 1044 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); |
1032 // Check that the object is in fast mode (not dictionary). | 1045 // Check that the object is in fast mode (not dictionary). |
1033 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), | 1046 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), |
1034 Immediate(Factory::fixed_array_map())); | 1047 Immediate(Factory::fixed_array_map())); |
1035 __ j(not_equal, &miss, not_taken); | 1048 __ j(not_equal, &miss, not_taken); |
1036 break; | 1049 break; |
1037 | 1050 |
1038 default: | 1051 default: |
(...skipping 22 matching lines...) Expand all Loading... |
1061 function_name = String::cast(function->shared()->name()); | 1074 function_name = String::cast(function->shared()->name()); |
1062 } | 1075 } |
1063 return GetCode(CONSTANT_FUNCTION, function_name); | 1076 return GetCode(CONSTANT_FUNCTION, function_name); |
1064 } | 1077 } |
1065 | 1078 |
1066 | 1079 |
1067 Object* CallStubCompiler::CompileCallInterceptor(Object* object, | 1080 Object* CallStubCompiler::CompileCallInterceptor(Object* object, |
1068 JSObject* holder, | 1081 JSObject* holder, |
1069 String* name) { | 1082 String* name) { |
1070 // ----------- S t a t e ------------- | 1083 // ----------- S t a t e ------------- |
| 1084 // -- ecx : name |
| 1085 // -- esp[0] : return address |
| 1086 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 1087 // -- ... |
| 1088 // -- esp[(argc + 1) * 4] : receiver |
1071 // ----------------------------------- | 1089 // ----------------------------------- |
1072 Label miss; | 1090 Label miss; |
1073 | 1091 |
1074 // Get the number of arguments. | 1092 // Get the number of arguments. |
1075 const int argc = arguments().immediate(); | 1093 const int argc = arguments().immediate(); |
1076 | 1094 |
1077 LookupResult lookup; | 1095 LookupResult lookup; |
1078 LookupPostInterceptor(holder, name, &lookup); | 1096 LookupPostInterceptor(holder, name, &lookup); |
1079 | 1097 |
1080 // Get the receiver from the stack. | 1098 // Get the receiver from the stack. |
1081 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1099 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
1082 | 1100 |
1083 CallInterceptorCompiler compiler(arguments()); | 1101 CallInterceptorCompiler compiler(arguments(), ecx); |
1084 CompileLoadInterceptor(&compiler, | 1102 CompileLoadInterceptor(&compiler, |
1085 this, | 1103 this, |
1086 masm(), | 1104 masm(), |
1087 JSObject::cast(object), | 1105 JSObject::cast(object), |
1088 holder, | 1106 holder, |
1089 name, | 1107 name, |
1090 &lookup, | 1108 &lookup, |
1091 edx, | 1109 edx, |
1092 ebx, | 1110 ebx, |
1093 ecx, | 1111 edi, |
1094 &miss); | 1112 &miss); |
1095 | 1113 |
1096 // Restore receiver. | 1114 // Restore receiver. |
1097 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1115 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
1098 | 1116 |
1099 // Check that the function really is a function. | 1117 // Check that the function really is a function. |
1100 __ test(eax, Immediate(kSmiTagMask)); | 1118 __ test(eax, Immediate(kSmiTagMask)); |
1101 __ j(zero, &miss, not_taken); | 1119 __ j(zero, &miss, not_taken); |
1102 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); | 1120 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); |
1103 __ j(not_equal, &miss, not_taken); | 1121 __ j(not_equal, &miss, not_taken); |
(...skipping 18 matching lines...) Expand all Loading... |
1122 return GetCode(INTERCEPTOR, name); | 1140 return GetCode(INTERCEPTOR, name); |
1123 } | 1141 } |
1124 | 1142 |
1125 | 1143 |
1126 Object* CallStubCompiler::CompileCallGlobal(JSObject* object, | 1144 Object* CallStubCompiler::CompileCallGlobal(JSObject* object, |
1127 GlobalObject* holder, | 1145 GlobalObject* holder, |
1128 JSGlobalPropertyCell* cell, | 1146 JSGlobalPropertyCell* cell, |
1129 JSFunction* function, | 1147 JSFunction* function, |
1130 String* name) { | 1148 String* name) { |
1131 // ----------- S t a t e ------------- | 1149 // ----------- S t a t e ------------- |
| 1150 // -- ecx : name |
| 1151 // -- esp[0] : return address |
| 1152 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 1153 // -- ... |
| 1154 // -- esp[(argc + 1) * 4] : receiver |
1132 // ----------------------------------- | 1155 // ----------------------------------- |
1133 Label miss; | 1156 Label miss; |
1134 | 1157 |
1135 // Get the number of arguments. | 1158 // Get the number of arguments. |
1136 const int argc = arguments().immediate(); | 1159 const int argc = arguments().immediate(); |
1137 | 1160 |
1138 // Get the receiver from the stack. | 1161 // Get the receiver from the stack. |
1139 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1162 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
1140 | 1163 |
1141 // If the object is the holder then we know that it's a global | 1164 // If the object is the holder then we know that it's a global |
1142 // object which can only happen for contextual calls. In this case, | 1165 // object which can only happen for contextual calls. In this case, |
1143 // the receiver cannot be a smi. | 1166 // the receiver cannot be a smi. |
1144 if (object != holder) { | 1167 if (object != holder) { |
1145 __ test(edx, Immediate(kSmiTagMask)); | 1168 __ test(edx, Immediate(kSmiTagMask)); |
1146 __ j(zero, &miss, not_taken); | 1169 __ j(zero, &miss, not_taken); |
1147 } | 1170 } |
1148 | 1171 |
1149 // Check that the maps haven't changed. | 1172 // Check that the maps haven't changed. |
1150 CheckPrototypes(object, edx, holder, ebx, ecx, name, &miss); | 1173 CheckPrototypes(object, edx, holder, ebx, eax, name, &miss); |
1151 | 1174 |
1152 // Get the value from the cell. | 1175 // Get the value from the cell. |
1153 __ mov(edi, Immediate(Handle<JSGlobalPropertyCell>(cell))); | 1176 __ mov(edi, Immediate(Handle<JSGlobalPropertyCell>(cell))); |
1154 __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset)); | 1177 __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset)); |
1155 | 1178 |
1156 // Check that the cell contains the same function. | 1179 // Check that the cell contains the same function. |
1157 __ cmp(Operand(edi), Immediate(Handle<JSFunction>(function))); | 1180 __ cmp(Operand(edi), Immediate(Handle<JSFunction>(function))); |
1158 __ j(not_equal, &miss, not_taken); | 1181 __ j(not_equal, &miss, not_taken); |
1159 | 1182 |
1160 // Patch the receiver on the stack with the global proxy. | 1183 // Patch the receiver on the stack with the global proxy. |
(...skipping 737 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1898 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); | 1921 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); |
1899 | 1922 |
1900 // Return the generated code. | 1923 // Return the generated code. |
1901 return GetCode(); | 1924 return GetCode(); |
1902 } | 1925 } |
1903 | 1926 |
1904 | 1927 |
1905 #undef __ | 1928 #undef __ |
1906 | 1929 |
1907 } } // namespace v8::internal | 1930 } } // namespace v8::internal |
OLD | NEW |