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 static void PushInterceptorArguments(MacroAssembler* masm, | |
156 Register receiver, | |
157 Register holder, | |
158 Register name, | |
159 JSObject* holder_obj) { | |
160 __ push(receiver); | |
161 __ push(holder); | |
162 __ push(name); | |
163 InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor(); | |
164 ASSERT(!Heap::InNewSpace(interceptor)); | |
165 __ mov(receiver, Immediate(Handle<Object>(interceptor))); | |
166 __ push(receiver); | |
167 __ push(FieldOperand(receiver, InterceptorInfo::kDataOffset)); | |
168 } | |
169 | |
170 | |
171 void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm, | 155 void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm, |
172 int index, | 156 int index, |
173 Register prototype) { | 157 Register prototype) { |
174 // Load the global or builtins object from the current context. | 158 // Load the global or builtins object from the current context. |
175 __ mov(prototype, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); | 159 __ mov(prototype, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); |
176 // Load the global context from the global or builtins object. | 160 // Load the global context from the global or builtins object. |
177 __ mov(prototype, | 161 __ mov(prototype, |
178 FieldOperand(prototype, GlobalObject::kGlobalContextOffset)); | 162 FieldOperand(prototype, GlobalObject::kGlobalContextOffset)); |
179 // Load the function from the global context. | 163 // Load the function from the global context. |
180 __ mov(prototype, Operand(prototype, Context::SlotOffset(index))); | 164 __ mov(prototype, Operand(prototype, Context::SlotOffset(index))); |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
280 __ mov(dst, FieldOperand(src, offset)); | 264 __ mov(dst, FieldOperand(src, offset)); |
281 } else { | 265 } else { |
282 // Calculate the offset into the properties array. | 266 // Calculate the offset into the properties array. |
283 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 267 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
284 __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset)); | 268 __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset)); |
285 __ mov(dst, FieldOperand(dst, offset)); | 269 __ mov(dst, FieldOperand(dst, offset)); |
286 } | 270 } |
287 } | 271 } |
288 | 272 |
289 | 273 |
| 274 static void PushInterceptorArguments(MacroAssembler* masm, |
| 275 Register receiver, |
| 276 Register holder, |
| 277 Register name, |
| 278 JSObject* holder_obj) { |
| 279 __ push(receiver); |
| 280 __ push(holder); |
| 281 __ push(name); |
| 282 InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor(); |
| 283 ASSERT(!Heap::InNewSpace(interceptor)); |
| 284 __ mov(receiver, Immediate(Handle<Object>(interceptor))); |
| 285 __ push(receiver); |
| 286 __ push(FieldOperand(receiver, InterceptorInfo::kDataOffset)); |
| 287 } |
| 288 |
| 289 |
290 static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm, | 290 static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm, |
291 Register receiver, | 291 Register receiver, |
292 Register holder, | 292 Register holder, |
293 Register name, | 293 Register name, |
294 JSObject* holder_obj) { | 294 JSObject* holder_obj) { |
295 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | 295 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); |
296 | 296 __ CallExternalReference( |
297 ExternalReference ref = | 297 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly)), |
298 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly)); | 298 5); |
299 __ mov(eax, Immediate(5)); | |
300 __ mov(ebx, Immediate(ref)); | |
301 | |
302 CEntryStub stub(1); | |
303 __ CallStub(&stub); | |
304 } | 299 } |
305 | 300 |
306 | 301 |
307 template <class Compiler> | 302 template <class Compiler> |
308 static void CompileLoadInterceptor(Compiler* compiler, | 303 static void CompileLoadInterceptor(Compiler* compiler, |
309 StubCompiler* stub_compiler, | 304 StubCompiler* stub_compiler, |
310 MacroAssembler* masm, | 305 MacroAssembler* masm, |
311 JSObject* object, | 306 JSObject* object, |
312 JSObject* holder, | 307 JSObject* holder, |
313 String* name, | 308 String* name, |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
357 void CompileCacheable(MacroAssembler* masm, | 352 void CompileCacheable(MacroAssembler* masm, |
358 StubCompiler* stub_compiler, | 353 StubCompiler* stub_compiler, |
359 Register receiver, | 354 Register receiver, |
360 Register holder, | 355 Register holder, |
361 Register scratch1, | 356 Register scratch1, |
362 Register scratch2, | 357 Register scratch2, |
363 JSObject* holder_obj, | 358 JSObject* holder_obj, |
364 LookupResult* lookup, | 359 LookupResult* lookup, |
365 String* name, | 360 String* name, |
366 Label* miss_label) { | 361 Label* miss_label) { |
367 AccessorInfo* callback = 0; | 362 AccessorInfo* callback = NULL; |
368 bool optimize = false; | 363 bool optimize = false; |
369 // So far the most popular follow ups for interceptor loads are FIELD | 364 // So far the most popular follow ups for interceptor loads are FIELD |
370 // and CALLBACKS, so inline only them, other cases may be added | 365 // and CALLBACKS, so inline only them, other cases may be added |
371 // later. | 366 // later. |
372 if (lookup->type() == FIELD) { | 367 if (lookup->type() == FIELD) { |
373 optimize = true; | 368 optimize = true; |
374 } else if (lookup->type() == CALLBACKS) { | 369 } else if (lookup->type() == CALLBACKS) { |
375 Object* callback_object = lookup->GetCallbackObject(); | 370 Object* callback_object = lookup->GetCallbackObject(); |
376 if (callback_object->IsAccessorInfo()) { | 371 if (callback_object->IsAccessorInfo()) { |
377 callback = AccessorInfo::cast(callback_object); | 372 callback = AccessorInfo::cast(callback_object); |
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
676 } | 671 } |
677 | 672 |
678 | 673 |
679 class CallInterceptorCompiler BASE_EMBEDDED { | 674 class CallInterceptorCompiler BASE_EMBEDDED { |
680 public: | 675 public: |
681 CallInterceptorCompiler(StubCompiler* stub_compiler, | 676 CallInterceptorCompiler(StubCompiler* stub_compiler, |
682 const ParameterCount& arguments, | 677 const ParameterCount& arguments, |
683 Register name) | 678 Register name) |
684 : stub_compiler_(stub_compiler), | 679 : stub_compiler_(stub_compiler), |
685 arguments_(arguments), | 680 arguments_(arguments), |
686 argc_(arguments.immediate()), | |
687 name_(name) {} | 681 name_(name) {} |
688 | 682 |
689 void Compile(MacroAssembler* masm, | 683 void Compile(MacroAssembler* masm, |
690 JSObject* object, | 684 JSObject* object, |
691 JSObject* holder, | 685 JSObject* holder, |
692 String* name, | 686 String* name, |
693 LookupResult* lookup, | 687 LookupResult* lookup, |
694 Register receiver, | 688 Register receiver, |
695 Register scratch1, | 689 Register scratch1, |
696 Register scratch2, | 690 Register scratch2, |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
733 JSObject* object, | 727 JSObject* object, |
734 Register receiver, | 728 Register receiver, |
735 Register scratch1, | 729 Register scratch1, |
736 Register scratch2, | 730 Register scratch2, |
737 JSObject* holder_obj, | 731 JSObject* holder_obj, |
738 LookupResult* lookup, | 732 LookupResult* lookup, |
739 String* name, | 733 String* name, |
740 const CallOptimization& optimization, | 734 const CallOptimization& optimization, |
741 Label* miss_label) { | 735 Label* miss_label) { |
742 ASSERT(optimization.is_constant_call()); | 736 ASSERT(optimization.is_constant_call()); |
| 737 ASSERT(!lookup->holder()->IsGlobalObject()); |
743 | 738 |
744 int depth1 = kInvalidProtoDepth; | 739 int depth1 = kInvalidProtoDepth; |
745 int depth2 = kInvalidProtoDepth; | 740 int depth2 = kInvalidProtoDepth; |
746 bool can_do_fast_api_call = false; | 741 bool can_do_fast_api_call = false; |
747 if (optimization.is_simple_api_call() && | 742 if (optimization.is_simple_api_call() && |
748 !lookup->holder()->IsGlobalObject()) { | 743 !lookup->holder()->IsGlobalObject()) { |
749 depth1 = optimization.GetPrototypeDepthOfExpectedType(object, holder_obj); | 744 depth1 = optimization.GetPrototypeDepthOfExpectedType(object, holder_obj); |
750 if (depth1 == kInvalidProtoDepth) { | 745 if (depth1 == kInvalidProtoDepth) { |
751 depth2 = optimization.GetPrototypeDepthOfExpectedType(holder_obj, | 746 depth2 = optimization.GetPrototypeDepthOfExpectedType(holder_obj, |
752 lookup->holder()); | 747 lookup->holder()); |
(...skipping 20 matching lines...) Expand all Loading... |
773 LoadWithInterceptor(masm, receiver, holder, holder_obj, ®ular_invoke); | 768 LoadWithInterceptor(masm, receiver, holder, holder_obj, ®ular_invoke); |
774 | 769 |
775 // Generate code for the failed interceptor case. | 770 // Generate code for the failed interceptor case. |
776 | 771 |
777 // Check the lookup is still valid. | 772 // Check the lookup is still valid. |
778 stub_compiler_->CheckPrototypes(holder_obj, receiver, | 773 stub_compiler_->CheckPrototypes(holder_obj, receiver, |
779 lookup->holder(), | 774 lookup->holder(), |
780 scratch1, scratch2, name, | 775 scratch1, scratch2, name, |
781 depth2, miss); | 776 depth2, miss); |
782 | 777 |
783 if (lookup->holder()->IsGlobalObject()) { | 778 if (can_do_fast_api_call) { |
784 ASSERT(!can_do_fast_api_call); | 779 GenerateFastApiCall(masm, optimization, arguments_.immediate()); |
785 __ mov(edx, Operand(esp, (argc_ + 1) * kPointerSize)); | 780 } else { |
786 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 781 // Jump to the cached code (tail call). |
787 __ mov(Operand(esp, (argc_ + 1) * kPointerSize), edx); | 782 __ InvokeFunction(optimization.constant_function(), arguments_); |
788 } | 783 } |
789 | 784 |
790 if (can_do_fast_api_call) { | 785 if (can_do_fast_api_call) { |
791 GenerateFastApiCall(masm, optimization, argc_); | |
792 } else { | |
793 // Get the function and setup the context. | |
794 JSFunction* function = optimization.constant_function(); | |
795 __ mov(edi, Immediate(Handle<JSFunction>(function))); | |
796 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | |
797 | |
798 // Jump to the cached code (tail call). | |
799 ASSERT(function->is_compiled()); | |
800 Handle<Code> code(function->code()); | |
801 ParameterCount expected(function->shared()->formal_parameter_count()); | |
802 __ InvokeCode(code, expected, arguments_, | |
803 RelocInfo::CODE_TARGET, JUMP_FUNCTION); | |
804 } | |
805 | |
806 if (can_do_fast_api_call) { | |
807 __ bind(&miss_cleanup); | 786 __ bind(&miss_cleanup); |
808 FreeSpaceForFastApiCall(masm, scratch1); | 787 FreeSpaceForFastApiCall(masm, scratch1); |
809 __ jmp(miss_label); | 788 __ jmp(miss_label); |
810 } | 789 } |
811 | 790 |
812 __ bind(®ular_invoke); | 791 __ bind(®ular_invoke); |
813 if (can_do_fast_api_call) { | 792 if (can_do_fast_api_call) { |
814 FreeSpaceForFastApiCall(masm, scratch1); | 793 FreeSpaceForFastApiCall(masm, scratch1); |
815 } | 794 } |
816 } | 795 } |
(...skipping 14 matching lines...) Expand all Loading... |
831 __ EnterInternalFrame(); | 810 __ EnterInternalFrame(); |
832 // Save the name_ register across the call. | 811 // Save the name_ register across the call. |
833 __ push(name_); | 812 __ push(name_); |
834 | 813 |
835 PushInterceptorArguments(masm, | 814 PushInterceptorArguments(masm, |
836 receiver, | 815 receiver, |
837 holder, | 816 holder, |
838 name_, | 817 name_, |
839 holder_obj); | 818 holder_obj); |
840 | 819 |
841 ExternalReference ref = ExternalReference( | 820 __ CallExternalReference( |
842 IC_Utility(IC::kLoadPropertyWithInterceptorForCall)); | 821 ExternalReference( |
843 __ mov(eax, Immediate(5)); | 822 IC_Utility(IC::kLoadPropertyWithInterceptorForCall)), |
844 __ mov(ebx, Immediate(ref)); | 823 5); |
845 | |
846 CEntryStub stub(1); | |
847 __ CallStub(&stub); | |
848 | 824 |
849 // Restore the name_ register. | 825 // Restore the name_ register. |
850 __ pop(name_); | 826 __ pop(name_); |
851 __ LeaveInternalFrame(); | 827 __ LeaveInternalFrame(); |
852 } | 828 } |
853 | 829 |
854 void LoadWithInterceptor(MacroAssembler* masm, | 830 void LoadWithInterceptor(MacroAssembler* masm, |
855 Register receiver, | 831 Register receiver, |
856 Register holder, | 832 Register holder, |
857 JSObject* holder_obj, | 833 JSObject* holder_obj, |
(...skipping 11 matching lines...) Expand all Loading... |
869 __ pop(name_); // Restore the name. | 845 __ pop(name_); // Restore the name. |
870 __ pop(receiver); // Restore the holder. | 846 __ pop(receiver); // Restore the holder. |
871 __ LeaveInternalFrame(); | 847 __ LeaveInternalFrame(); |
872 | 848 |
873 __ cmp(eax, Factory::no_interceptor_result_sentinel()); | 849 __ cmp(eax, Factory::no_interceptor_result_sentinel()); |
874 __ j(not_equal, interceptor_succeeded); | 850 __ j(not_equal, interceptor_succeeded); |
875 } | 851 } |
876 | 852 |
877 StubCompiler* stub_compiler_; | 853 StubCompiler* stub_compiler_; |
878 const ParameterCount& arguments_; | 854 const ParameterCount& arguments_; |
879 const int argc_; | |
880 Register name_; | 855 Register name_; |
881 }; | 856 }; |
882 | 857 |
883 | 858 |
884 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { | 859 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { |
885 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); | 860 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); |
886 Code* code = NULL; | 861 Code* code = NULL; |
887 if (kind == Code::LOAD_IC) { | 862 if (kind == Code::LOAD_IC) { |
888 code = Builtins::builtin(Builtins::LoadIC_Miss); | 863 code = Builtins::builtin(Builtins::LoadIC_Miss); |
889 } else { | 864 } else { |
(...skipping 481 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1371 __ j(not_equal, &miss, not_taken); | 1346 __ j(not_equal, &miss, not_taken); |
1372 break; | 1347 break; |
1373 | 1348 |
1374 default: | 1349 default: |
1375 UNREACHABLE(); | 1350 UNREACHABLE(); |
1376 } | 1351 } |
1377 | 1352 |
1378 if (depth != kInvalidProtoDepth) { | 1353 if (depth != kInvalidProtoDepth) { |
1379 GenerateFastApiCall(masm(), optimization, argc); | 1354 GenerateFastApiCall(masm(), optimization, argc); |
1380 } else { | 1355 } else { |
1381 // Get the function and setup the context. | 1356 __ InvokeFunction(function, arguments()); |
1382 __ mov(edi, Immediate(Handle<JSFunction>(function))); | |
1383 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | |
1384 | |
1385 // Jump to the cached code (tail call). | |
1386 ASSERT(function->is_compiled()); | |
1387 Handle<Code> code(function->code()); | |
1388 ParameterCount expected(function->shared()->formal_parameter_count()); | |
1389 __ InvokeCode(code, expected, arguments(), | |
1390 RelocInfo::CODE_TARGET, JUMP_FUNCTION); | |
1391 } | 1357 } |
1392 | 1358 |
1393 // Handle call cache miss. | 1359 // Handle call cache miss. |
1394 __ bind(&miss); | 1360 __ bind(&miss); |
1395 if (depth != kInvalidProtoDepth) { | 1361 if (depth != kInvalidProtoDepth) { |
1396 FreeSpaceForFastApiCall(masm(), eax); | 1362 FreeSpaceForFastApiCall(masm(), eax); |
1397 } | 1363 } |
1398 Handle<Code> ic = ComputeCallMiss(arguments().immediate()); | 1364 Handle<Code> ic = ComputeCallMiss(arguments().immediate()); |
1399 __ jmp(ic, RelocInfo::CODE_TARGET); | 1365 __ jmp(ic, RelocInfo::CODE_TARGET); |
1400 | 1366 |
(...skipping 851 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2252 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); | 2218 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); |
2253 | 2219 |
2254 // Return the generated code. | 2220 // Return the generated code. |
2255 return GetCode(); | 2221 return GetCode(); |
2256 } | 2222 } |
2257 | 2223 |
2258 | 2224 |
2259 #undef __ | 2225 #undef __ |
2260 | 2226 |
2261 } } // namespace v8::internal | 2227 } } // namespace v8::internal |
OLD | NEW |