| 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 |